summaryrefslogtreecommitdiffstats
path: root/audio/out
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-07-21 21:33:17 +0200
committerwm4 <wm4@nowhere>2013-07-21 23:27:31 +0200
commit7eba27c125f6e4813ecc6cff567dc29e17d10fc5 (patch)
treefaff2bdc8aa2fc490634eacbebccdfa19b5c7df9 /audio/out
parent9e1331f7afe8f1648424e45ea2c67ca5e95656ad (diff)
downloadmpv-7eba27c125f6e4813ecc6cff567dc29e17d10fc5.tar.bz2
mpv-7eba27c125f6e4813ecc6cff567dc29e17d10fc5.tar.xz
options: use new option code for --ao
This requires completely refactoring the AO creation code too.
Diffstat (limited to 'audio/out')
-rw-r--r--audio/out/ao.c166
-rw-r--r--audio/out/ao.h14
2 files changed, 89 insertions, 91 deletions
diff --git a/audio/out/ao.c b/audio/out/ao.c
index a95c9e8f51..522acc21c1 100644
--- a/audio/out/ao.c
+++ b/audio/out/ao.c
@@ -27,6 +27,8 @@
#include "ao.h"
#include "audio/format.h"
+#include "core/options.h"
+#include "core/m_config.h"
#include "core/mp_msg.h"
// there are some globals:
@@ -94,113 +96,105 @@ static const struct ao_driver * const audio_out_drivers[] = {
NULL
};
-void list_audio_out(void)
+static bool get_desc(struct m_obj_desc *dst, int index)
{
- mp_tmsg(MSGT_AO, MSGL_INFO, "Available audio output drivers:\n");
- mp_msg(MSGT_IDENTIFY, MSGL_INFO, "ID_AUDIO_OUTPUTS\n");
- for (int i = 0; audio_out_drivers[i]; i++) {
- const ao_info_t *info = audio_out_drivers[i]->info;
- if (!audio_out_drivers[i]->encode) {
- mp_msg(MSGT_GLOBAL, MSGL_INFO, "\t%s\t%s\n",
- info->short_name, info->name);
- }
- }
- mp_msg(MSGT_GLOBAL, MSGL_INFO,"\n");
+ if (index >= MP_ARRAY_SIZE(audio_out_drivers) - 1)
+ return false;
+ const struct ao_driver *ao = audio_out_drivers[index];
+ *dst = (struct m_obj_desc) {
+ .name = ao->info->short_name,
+ .description = ao->info->name,
+ .priv_size = ao->priv_size,
+ .priv_defaults = ao->priv_defaults,
+ .options = ao->options,
+ .p = ao,
+ };
+ return true;
}
-struct ao *ao_create(struct MPOpts *opts, struct input_ctx *input)
-{
- struct ao *r = talloc(NULL, struct ao);
- *r = (struct ao){.opts = opts, .input_ctx = input };
- return r;
-}
+// For the ao option
+const struct m_obj_list ao_obj_list = {
+ .get_desc = get_desc,
+ .description = "audio outputs",
+ .allow_unknown_entries = true,
+ .allow_trailer = true,
+};
-static bool ao_try_init(struct ao *ao, char *params)
+static struct ao *ao_create(bool probing, struct MPOpts *opts,
+ struct input_ctx *input_ctx,
+ struct encode_lavc_context *encode_lavc_ctx,
+ int samplerate, int format, struct mp_chmap channels,
+ char *name, char **args)
{
+ struct m_obj_desc desc;
+ if (!m_obj_list_find(&desc, &ao_obj_list, bstr0(name))) {
+ mp_tmsg(MSGT_CPLAYER, MSGL_ERR, "Audio output %s not found!\n", name);
+ return NULL;
+ };
+ struct ao *ao = talloc_ptrtype(NULL, ao);
+ *ao = (struct ao) {
+ .driver = desc.p,
+ .probing = probing,
+ .opts = opts,
+ .encode_lavc_ctx = encode_lavc_ctx,
+ .input_ctx = input_ctx,
+ .samplerate = samplerate,
+ .channels = channels,
+ .format = format,
+ };
if (ao->driver->encode != !!ao->encode_lavc_ctx)
- return false;
- if (ao->driver->init(ao, params) < 0)
- return false;
+ goto error;
+ struct m_config *config = m_config_from_obj_desc(ao, &desc);
+ if (m_config_initialize_obj(config, &desc, &ao->priv, &args) < 0)
+ goto error;
+ if (ao->driver->init(ao, (char *)args) < 0)
+ goto error;
ao->bps = ao->channels.num * ao->samplerate * af_fmt2bits(ao->format) / 8;
- ao->initialized = true;
- return true;
+ return ao;
+error:
+ talloc_free(ao);
+ return NULL;
}
-void ao_init(struct ao *ao, char **ao_list)
+struct ao *ao_init_best(struct MPOpts *opts,
+ struct input_ctx *input_ctx,
+ struct encode_lavc_context *encode_lavc_ctx,
+ int samplerate, int format, struct mp_chmap channels)
{
- /* Caller adding child blocks is not supported as we may call
- * talloc_free_children() to clean up after failed open attempts.
- */
- assert(talloc_total_blocks(ao) == 1);
- struct ao backup = *ao;
-
- if (!ao_list)
- goto try_defaults;
-
- // first try the preferred drivers, with their optional subdevice param:
- while (*ao_list) {
- char *ao_name = *ao_list;
- if (!*ao_name)
- goto try_defaults; // empty entry means try defaults
- int ao_len;
- char *params = strchr(ao_name, ':');
- if (params) {
- ao_len = params - ao_name;
- params++;
- } else
- ao_len = strlen(ao_name);
-
- mp_tmsg(MSGT_AO, MSGL_V,
- "Trying preferred audio driver '%.*s', options '%s'\n",
- ao_len, ao_name, params ? params : "[none]");
-
- const struct ao_driver *audio_out = NULL;
- for (int i = 0; audio_out_drivers[i]; i++) {
- audio_out = audio_out_drivers[i];
- if (!strncmp(audio_out->info->short_name, ao_name, ao_len))
- break;
- audio_out = NULL;
+ struct m_obj_settings *ao_list = opts->audio_driver_list;
+ if (ao_list && ao_list[0].name) {
+ for (int n = 0; ao_list[n].name; n++) {
+ if (strlen(ao_list[n].name) == 0)
+ goto autoprobe;
+ mp_tmsg(MSGT_AO, MSGL_V, "Trying preferred audio driver '%s'\n",
+ ao_list[n].name);
+ struct ao *ao = ao_create(false, opts, input_ctx, encode_lavc_ctx,
+ samplerate, format, channels,
+ ao_list[n].name, ao_list[n].attribs);
+ if (ao)
+ return ao;
+ mp_tmsg(MSGT_AO, MSGL_WARN, "Failed to initialize audio driver '%s'\n",
+ ao_list[n].name);
}
- if (audio_out) {
- // name matches, try it
- ao->driver = audio_out;
- if (ao_try_init(ao, params))
- return;
- mp_tmsg(MSGT_AO, MSGL_WARN,
- "Failed to initialize audio driver '%s'\n", ao_name);
- talloc_free_children(ao);
- *ao = backup;
- } else
- mp_tmsg(MSGT_AO, MSGL_WARN, "No such audio driver '%.*s'\n",
- ao_len, ao_name);
- ++ao_list;
+ return NULL;
}
- return;
-
- try_defaults:
- mp_tmsg(MSGT_AO, MSGL_V, "Trying every known audio driver...\n");
-
- ao->probing = false;
-
+autoprobe:
// now try the rest...
for (int i = 0; audio_out_drivers[i]; i++) {
- const struct ao_driver *audio_out = audio_out_drivers[i];
- ao->driver = audio_out;
- ao->probing = true;
- if (ao_try_init(ao, NULL))
- return;
- talloc_free_children(ao);
- *ao = backup;
+ struct ao *ao = ao_create(true, opts, input_ctx, encode_lavc_ctx,
+ samplerate, format, channels,
+ (char *)audio_out_drivers[i]->info->short_name, NULL);
+ if (ao)
+ return ao;
}
- return;
+ return NULL;
}
void ao_uninit(struct ao *ao, bool cut_audio)
{
assert(ao->buffer.len >= ao->buffer_playable_size);
ao->buffer.len = ao->buffer_playable_size;
- if (ao->initialized)
- ao->driver->uninit(ao, cut_audio);
+ ao->driver->uninit(ao, cut_audio);
if (!cut_audio && ao->buffer.len)
mp_msg(MSGT_AO, MSGL_WARN, "Audio output truncated at end.\n");
talloc_free(ao);
diff --git a/audio/out/ao.h b/audio/out/ao.h
index 146c35f823..4556958324 100644
--- a/audio/out/ao.h
+++ b/audio/out/ao.h
@@ -82,6 +82,11 @@ struct ao_driver {
float (*get_delay)(struct ao *ao);
void (*pause)(struct ao *ao);
void (*resume)(struct ao *ao);
+
+ // For option parsing (see vo.h)
+ int priv_size;
+ const void *priv_defaults;
+ const struct m_option *options;
};
/* global data used by mplayer and plugins */
@@ -94,7 +99,6 @@ struct ao {
struct bstr buffer;
int buffer_playable_size;
bool probing; // if true, don't fail loudly on init
- bool initialized;
bool untimed;
bool no_persistent_volume; // the AO does the equivalent of af_volume
bool per_application_mixer; // like above, but volume persists (per app)
@@ -107,10 +111,10 @@ struct ao {
extern char *ao_subdevice;
-void list_audio_out(void);
-
-struct ao *ao_create(struct MPOpts *opts, struct input_ctx *input);
-void ao_init(struct ao *ao, char **ao_list);
+struct ao *ao_init_best(struct MPOpts *opts,
+ struct input_ctx *input_ctx,
+ struct encode_lavc_context *encode_lavc_ctx,
+ int samplerate, int format, struct mp_chmap channels);
void ao_uninit(struct ao *ao, bool cut_audio);
int ao_play(struct ao *ao, void *data, int len, int flags);
int ao_control(struct ao *ao, enum aocontrol cmd, void *arg);