From 7eba27c125f6e4813ecc6cff567dc29e17d10fc5 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 21 Jul 2013 21:33:17 +0200 Subject: options: use new option code for --ao This requires completely refactoring the AO creation code too. --- audio/out/ao.c | 166 +++++++++++++++++++++++++++------------------------------ audio/out/ao.h | 14 +++-- core/mplayer.c | 17 ++---- core/options.c | 3 +- core/options.h | 2 +- 5 files changed, 96 insertions(+), 106 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); diff --git a/core/mplayer.c b/core/mplayer.c index 07f54b142f..e54b55444f 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -1618,14 +1618,10 @@ void reinit_audio_chain(struct MPContext *mpctx) mpctx->initialized_flags |= INITIALIZED_AO; mp_chmap_remove_useless_channels(&ao_channels, &opts->audio_output_channels); - mpctx->ao = ao_create(opts, mpctx->input); + mpctx->ao = ao_init_best(opts, mpctx->input, mpctx->encode_lavc_ctx, + ao_srate, ao_format, ao_channels); struct ao *ao = mpctx->ao; - ao->samplerate = ao_srate; - ao->format = ao_format; - ao->channels = ao_channels; - ao->encode_lavc_ctx = mpctx->encode_lavc_ctx; - ao_init(ao, opts->audio_driver_list); - if (!ao->initialized) { + if (!ao) { mp_tmsg(MSGT_CPLAYER, MSGL_ERR, "Could not open/initialize audio device -> no sound.\n"); goto init_error; @@ -4117,7 +4113,7 @@ static void play_current_file(struct MPContext *mpctx) opts->vo.video_driver_list[0].name); if (opts->audio_driver_list) load_per_output_config(mpctx->mconfig, PROFILE_CFG_AO, - opts->audio_driver_list[0]); + opts->audio_driver_list[0].name); if (opts->position_resume) load_playback_resume(mpctx->mconfig, mpctx->filename); @@ -4504,11 +4500,6 @@ static bool handle_help_options(struct MPContext *mpctx) { struct MPOpts *opts = &mpctx->opts; int opt_exit = 0; - if (opts->audio_driver_list && - strcmp(opts->audio_driver_list[0], "help") == 0) { - list_audio_out(); - opt_exit = 1; - } if (opts->audio_decoders && strcmp(opts->audio_decoders, "help") == 0) { struct mp_decoder_list *list = mp_audio_decoder_list(); mp_print_decoders(MSGT_CPLAYER, MSGL_INFO, "Audio decoders:", list); diff --git a/core/options.c b/core/options.c index 3c0bf213a1..eceb1f259f 100644 --- a/core/options.c +++ b/core/options.c @@ -183,6 +183,7 @@ extern double mf_fps; extern char * mf_type; extern const struct m_obj_list vf_obj_list; extern const struct m_obj_list vo_obj_list; +extern const struct m_obj_list ao_obj_list; static const m_option_t mfopts_conf[]={ {"fps", &mf_fps, CONF_TYPE_DOUBLE, 0, 0, 0, NULL}, @@ -520,7 +521,7 @@ const m_option_t mp_opts[] = { //---------------------- libao/libvo options ------------------------ OPT_SETTINGSLIST("vo", vo.video_driver_list, 0, &vo_obj_list), - OPT_STRINGLIST("ao", audio_driver_list, 0), + OPT_SETTINGSLIST("ao", audio_driver_list, 0, &ao_obj_list), OPT_FLAG("fixed-vo", fixed_vo, CONF_GLOBAL), OPT_FLAG("ontop", vo.ontop, 0), OPT_FLAG("border", vo.border, 0), diff --git a/core/options.h b/core/options.h index f70f7f8553..44ca1148b9 100644 --- a/core/options.h +++ b/core/options.h @@ -47,7 +47,7 @@ typedef struct mp_vo_opts { typedef struct MPOpts { char **reset_options; - char **audio_driver_list; + struct m_obj_settings *audio_driver_list; int fixed_vo; char *mixer_device; char *mixer_channel; -- cgit v1.2.3