From 0110b738d5d37a0f7cafd522b89017436f7cfd73 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 29 Aug 2016 12:46:12 +0200 Subject: vd_lavc, ad_lavc: set pkt_timebase, not time_base These are different AVCodecContext fields. pkt_timebase is the correct one for identifying the unit of packet/frame timestamps when decoding, while time_base is for encoding. Some decoders also overwrite the time_base field with some unrelated codec metadata. pkt_timebase does not exist in Libav, so an #if is required. --- audio/decode/ad_lavc.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'audio') diff --git a/audio/decode/ad_lavc.c b/audio/decode/ad_lavc.c index 78d0cec807..e5c426e912 100644 --- a/audio/decode/ad_lavc.c +++ b/audio/decode/ad_lavc.c @@ -103,7 +103,10 @@ static int init(struct dec_audio *da, const char *decoder) lavc_context->refcounted_frames = 1; lavc_context->codec_type = AVMEDIA_TYPE_AUDIO; lavc_context->codec_id = lavc_codec->id; - lavc_context->time_base = ctx->codec_timebase; + +#if LIBAVCODEC_VERSION_MICRO >= 100 + lavc_context->pkt_timebase = ctx->codec_timebase; +#endif if (opts->downmix && mpopts->audio_output_channels.num_chmaps == 1) { lavc_context->request_channel_layout = -- cgit v1.2.3 From 6b4f560f3ccca0f7db345bd7a6ed65e9307b432d Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 1 Sep 2016 14:21:32 +0200 Subject: vo, ao: disable positional parameter suboptions Positional parameters cause problems because they can be ambiguous with flag options. If a flag option is removed or turned into a non-flag option, it'll usually be interpreted as value for the first sub-option (as positional parameter), resulting in very confusing error messages. This changes it into a simple "option not found" error. I don't expect that anyone really used positional parameters with --vo or --ao. Although the docs for --ao=pulse seem to encourage positional parameters for the host/sink options, which means it could possibly annoy some PulseAudio users. --vf and --af are still mostly used with positional parameters, so this must be a configurable option in the option parser. --- audio/out/ao.c | 1 + 1 file changed, 1 insertion(+) (limited to 'audio') diff --git a/audio/out/ao.c b/audio/out/ao.c index cf66e0c64b..fcbc44b139 100644 --- a/audio/out/ao.c +++ b/audio/out/ao.c @@ -121,6 +121,7 @@ const struct m_obj_list ao_obj_list = { .description = "audio outputs", .allow_unknown_entries = true, .allow_trailer = true, + .disallow_positional_parameters = true, }; static struct ao *ao_alloc(bool probing, struct mpv_global *global, -- cgit v1.2.3 From 4fa6bcbb902d500ca0a1b9d2feeab5a4e5a98345 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 2 Sep 2016 14:49:34 +0200 Subject: m_config: add helper function for initializing af/ao/vf/vo suboptions Normally I'd prefer a bunch of smaller functions with fewer parameters over a single function with a lot of parameters. But future changes will require messing with the parameters in a slightly more complex way, so a combined function will be needed anyway. The now-unused "global" parameter is required for later as well. --- audio/filter/af.c | 8 ++++---- audio/out/ao.c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'audio') diff --git a/audio/filter/af.c b/audio/filter/af.c index f380459747..e6f19b3e37 100644 --- a/audio/filter/af.c +++ b/audio/filter/af.c @@ -166,10 +166,10 @@ static struct af_instance *af_create(struct af_stream *s, char *name, .replaygain_data = s->replaygain_data, .out_pool = mp_audio_pool_create(af), }; - struct m_config *config = m_config_from_obj_desc(af, s->log, &desc); - if (m_config_apply_defaults(config, name, s->opts->af_defs) < 0) - goto error; - if (m_config_set_obj_params(config, args) < 0) + struct m_config *config = + m_config_from_obj_desc_and_args(af, s->log, NULL, &desc, + name, s->opts->af_defs, args); + if (!config) goto error; af->priv = config->optstruct; diff --git a/audio/out/ao.c b/audio/out/ao.c index fcbc44b139..189434cf0b 100644 --- a/audio/out/ao.c +++ b/audio/out/ao.c @@ -145,10 +145,10 @@ static struct ao *ao_alloc(bool probing, struct mpv_global *global, .def_buffer = opts->audio_buffer, .client_name = talloc_strdup(ao, opts->audio_client_name), }; - struct m_config *config = m_config_from_obj_desc(ao, ao->log, &desc); - if (m_config_apply_defaults(config, name, opts->ao_defs) < 0) - goto error; - if (m_config_set_obj_params(config, args) < 0) + struct m_config *config = + m_config_from_obj_desc_and_args(ao, ao->log, global, &desc, + name, opts->ao_defs, args); + if (!config) goto error; ao->priv = config->optstruct; return ao; -- cgit v1.2.3 From a85eecfe401ccaaa0b1981de71152bdc02184c66 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 2 Sep 2016 20:07:25 +0200 Subject: ao_alsa: change sub-options to global options Same deal as with vo_opengl. Also edit the outdated information about multichannel output a little. --- audio/out/ao.c | 1 + audio/out/ao_alsa.c | 82 ++++++++++++++++++++++++++++++++-------------------- audio/out/internal.h | 1 + 3 files changed, 53 insertions(+), 31 deletions(-) (limited to 'audio') diff --git a/audio/out/ao.c b/audio/out/ao.c index 189434cf0b..df2fdd5416 100644 --- a/audio/out/ao.c +++ b/audio/out/ao.c @@ -140,6 +140,7 @@ static struct ao *ao_alloc(bool probing, struct mpv_global *global, *ao = (struct ao) { .driver = desc.p, .probing = probing, + .global = global, .input_ctx = input_ctx, .log = mp_log_new(ao, log, name), .def_buffer = opts->audio_buffer, diff --git a/audio/out/ao_alsa.c b/audio/out/ao_alsa.c index c6248d302b..e780d349c2 100644 --- a/audio/out/ao_alsa.c +++ b/audio/out/ao_alsa.c @@ -35,6 +35,7 @@ #include "config.h" #include "options/options.h" +#include "options/m_config.h" #include "options/m_option.h" #include "common/msg.h" #include "osdep/endian.h" @@ -48,6 +49,37 @@ #include "internal.h" #include "audio/format.h" +struct ao_alsa_opts { + char *device; + char *mixer_device; + char *mixer_name; + int mixer_index; + int resample; + int ni; + int ignore_chmap; +}; + +#define OPT_BASE_STRUCT struct ao_alsa_opts +const struct m_sub_options ao_alsa_conf = { + .opts = (const struct m_option[]) { + OPT_STRING("alsa-device", device, 0), + OPT_FLAG("alsa-resample", resample, 0), + OPT_STRING("alsa-mixer-device", mixer_device, 0), + OPT_STRING("alsa-mixer-name", mixer_name, 0), + OPT_INTRANGE("alsa-mixer-index", mixer_index, 0, 0, 99), + OPT_FLAG("alsa-non-interleaved", ni, 0), + OPT_FLAG("alsa-ignore-chmap", ignore_chmap, 0), + {0} + }, + .defaults = &(const struct ao_alsa_opts) { + .mixer_device = "default", + .mixer_name = "Master", + .mixer_index = 0, + .ni = 0, + }, + .size = sizeof(struct ao_alsa_opts), +}; + struct priv { snd_pcm_t *alsa; bool device_lost; @@ -61,13 +93,7 @@ struct priv { snd_output_t *output; - char *cfg_device; - char *cfg_mixer_device; - char *cfg_mixer_name; - int cfg_mixer_index; - int cfg_resample; - int cfg_ni; - int cfg_ignore_chmap; + struct ao_alsa_opts *opts; }; #define BUFFER_TIME 250000 // 250ms @@ -125,13 +151,13 @@ static int control(struct ao *ao, enum aocontrol cmd, void *arg) snd_mixer_selem_id_alloca(&sid); - snd_mixer_selem_id_set_index(sid, p->cfg_mixer_index); - snd_mixer_selem_id_set_name(sid, p->cfg_mixer_name); + snd_mixer_selem_id_set_index(sid, p->opts->mixer_index); + snd_mixer_selem_id_set_name(sid, p->opts->mixer_name); err = snd_mixer_open(&handle, 0); CHECK_ALSA_ERROR("Mixer open error"); - err = snd_mixer_attach(handle, p->cfg_mixer_device); + err = snd_mixer_attach(handle, p->opts->mixer_device); CHECK_ALSA_ERROR("Mixer attach error"); err = snd_mixer_selem_register(handle, NULL, NULL); @@ -447,7 +473,7 @@ static int set_chmap(struct ao *ao, struct mp_chmap *dev_chmap, int num_channels MP_VERBOSE(ao, "which we understand as: %s\n", mp_chmap_to_str(&chmap)); - if (p->cfg_ignore_chmap) { + if (p->opts->ignore_chmap) { MP_VERBOSE(ao, "user set ignore-chmap; ignoring the channel map.\n"); } else if (af_fmt_is_spdif(ao->format)) { MP_VERBOSE(ao, "using spdif passthrough; ignoring the channel map.\n"); @@ -615,8 +641,8 @@ static int init_device(struct ao *ao, int mode) const char *device = "default"; if (ao->device) device = ao->device; - if (p->cfg_device && p->cfg_device[0]) - device = p->cfg_device; + if (p->opts->device && p->opts->device[0]) + device = p->opts->device; err = try_open_device(ao, device, mode); CHECK_ALSA_ERROR("Playback open error"); @@ -641,7 +667,7 @@ static int init_device(struct ao *ao, int mode) // Some ALSA drivers have broken delay reporting, so disable the ALSA // resampling plugin by default. - if (!p->cfg_resample) { + if (!p->opts->resample) { err = snd_pcm_hw_params_set_rate_resample(p->alsa, alsa_hwparams, 0); CHECK_ALSA_ERROR("Unable to disable resampling"); } @@ -684,7 +710,7 @@ static int init_device(struct ao *ao, int mode) dump_hw_params(ao, MSGL_DEBUG, "HW params after format:\n", alsa_hwparams); struct mp_chmap dev_chmap = ao->channels; - if (af_fmt_is_spdif(ao->format) || p->cfg_ignore_chmap) { + if (af_fmt_is_spdif(ao->format) || p->opts->ignore_chmap) { dev_chmap.num = 0; // disable chmap API } else if (dev_chmap.num == 1 && dev_chmap.speaker[0] == MP_SPEAKER_ID_FC) { // As yet another ALSA API inconsistency, mono is not reported correctly. @@ -806,7 +832,9 @@ alsa_error: static int init(struct ao *ao) { struct priv *p = ao->priv; - if (!p->cfg_ni) + p->opts = mp_get_config_group(ao, ao->global, &ao_alsa_conf); + + if (!p->opts->ni) ao->format = af_fmt_from_planar(ao->format); MP_VERBOSE(ao, "using ALSA version: %s\n", snd_asoundlib_version()); @@ -1125,8 +1153,6 @@ static void list_devs(struct ao *ao, struct ao_device_list *list) snd_device_name_free_hint(hints); } -#define OPT_BASE_STRUCT struct priv - const struct ao_driver audio_out_alsa = { .description = "ALSA audio output", .name = "alsa", @@ -1144,20 +1170,14 @@ const struct ao_driver audio_out_alsa = { .wakeup = ao_wakeup_poll, .list_devs = list_devs, .priv_size = sizeof(struct priv), - .priv_defaults = &(const struct priv) { - .cfg_mixer_device = "default", - .cfg_mixer_name = "Master", - .cfg_mixer_index = 0, - .cfg_ni = 0, - }, .options = (const struct m_option[]) { - OPT_STRING("device", cfg_device, 0), - OPT_FLAG("resample", cfg_resample, 0), - OPT_STRING("mixer-device", cfg_mixer_device, 0), - OPT_STRING("mixer-name", cfg_mixer_name, 0), - OPT_INTRANGE("mixer-index", cfg_mixer_index, 0, 0, 99), - OPT_FLAG("non-interleaved", cfg_ni, 0), - OPT_FLAG("ignore-chmap", cfg_ignore_chmap, 0), + OPT_SUBOPT_LEGACY("device", "alsa-device"), + OPT_SUBOPT_LEGACY("resample", "alsa-resample"), + OPT_SUBOPT_LEGACY("mixer-device", "alsa-mixer-device"), + OPT_SUBOPT_LEGACY("mixer-name", "alsa-mixer-name"), + OPT_SUBOPT_LEGACY("mixer-index", "alsa-mixer-index"), + OPT_SUBOPT_LEGACY("non-interleaved", "alsa-non-interleaved"), + OPT_SUBOPT_LEGACY("ignore-chmap", "alsa-ignore-chmap"), {0} }, }; diff --git a/audio/out/internal.h b/audio/out/internal.h index 518661c2bd..bd8816366e 100644 --- a/audio/out/internal.h +++ b/audio/out/internal.h @@ -40,6 +40,7 @@ struct ao { const struct ao_driver *api; // entrypoints to the wrapper (push.c/pull.c) const struct ao_driver *driver; void *priv; + struct mpv_global *global; struct encode_lavc_context *encode_lavc_ctx; struct input_ctx *input_ctx; struct mp_log *log; // Using e.g. "[ao/coreaudio]" as prefix -- cgit v1.2.3 From 4ab860cddc177047663bbe8940b0d34c621b6425 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 5 Sep 2016 21:04:17 +0200 Subject: options: add a mechanism to make sub-option replacement slightly easier Instead of requiring each VO or AO to manually add members to MPOpts and the global option table, make it possible to register them automatically via vo_driver/ao_driver.global_opts members. This avoids modifying options.c/options.h every time, including having to duplicate the exact ifdeffery used to enable a driver. --- audio/out/ao.c | 1 + audio/out/ao_alsa.c | 3 ++- audio/out/internal.h | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) (limited to 'audio') diff --git a/audio/out/ao.c b/audio/out/ao.c index df2fdd5416..3bfa481bc5 100644 --- a/audio/out/ao.c +++ b/audio/out/ao.c @@ -109,6 +109,7 @@ static bool get_desc(struct m_obj_desc *dst, int index) .priv_size = ao->priv_size, .priv_defaults = ao->priv_defaults, .options = ao->options, + .global_opts = ao->global_opts, .hidden = ao->encode, .p = ao, }; diff --git a/audio/out/ao_alsa.c b/audio/out/ao_alsa.c index e780d349c2..c542bee030 100644 --- a/audio/out/ao_alsa.c +++ b/audio/out/ao_alsa.c @@ -60,7 +60,7 @@ struct ao_alsa_opts { }; #define OPT_BASE_STRUCT struct ao_alsa_opts -const struct m_sub_options ao_alsa_conf = { +static const struct m_sub_options ao_alsa_conf = { .opts = (const struct m_option[]) { OPT_STRING("alsa-device", device, 0), OPT_FLAG("alsa-resample", resample, 0), @@ -1180,4 +1180,5 @@ const struct ao_driver audio_out_alsa = { OPT_SUBOPT_LEGACY("ignore-chmap", "alsa-ignore-chmap"), {0} }, + .global_opts = &ao_alsa_conf, }; diff --git a/audio/out/internal.h b/audio/out/internal.h index bd8816366e..f9dc073b4d 100644 --- a/audio/out/internal.h +++ b/audio/out/internal.h @@ -181,6 +181,7 @@ struct ao_driver { int priv_size; const void *priv_defaults; const struct m_option *options; + const struct m_sub_options *global_opts; }; // These functions can be called by AOs. -- cgit v1.2.3 From 726ef35aa83907308587dda822c0f0fcd68fc07f Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 5 Sep 2016 21:04:41 +0200 Subject: ao_jack: move to global options --- audio/out/ao_jack.c | 64 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 42 insertions(+), 22 deletions(-) (limited to 'audio') diff --git a/audio/out/ao_jack.c b/audio/out/ao_jack.c index 41ccfae614..56c7e28544 100644 --- a/audio/out/ao_jack.c +++ b/audio/out/ao_jack.c @@ -34,24 +34,48 @@ #include "internal.h" #include "audio/format.h" #include "osdep/timer.h" +#include "options/m_config.h" #include "options/m_option.h" #include -struct priv { - jack_client_t *client; - float jack_latency; - char *cfg_port; - char *cfg_client_name; +struct jack_opts { + char *port; + char *client_name; int connect; int autostart; int stdlayout; +}; + +#define OPT_BASE_STRUCT struct jack_opts +static const struct m_sub_options ao_jack_conf = { + .opts = (const struct m_option[]){ + OPT_STRING("jack-port", port, 0), + OPT_STRING("jack-name", client_name, 0), + OPT_FLAG("jack-autostart", autostart, 0), + OPT_FLAG("jack-connect", connect, 0), + OPT_CHOICE("jack-std-channel-layout", stdlayout, 0, + ({"waveext", 0}, {"any", 1})), + {0} + }, + .defaults = &(const struct jack_opts) { + .client_name = "mpv", + .connect = 1, + }, + .size = sizeof(struct jack_opts), +}; + +struct priv { + jack_client_t *client; + float jack_latency; int last_chunk; int num_ports; jack_port_t *ports[MP_NUM_CHANNELS]; int activated; + + struct jack_opts *opts; }; static int process(jack_nframes_t nframes, void *arg) @@ -77,7 +101,7 @@ connect_to_outports(struct ao *ao) { struct priv *p = ao->priv; - char *port_name = (p->cfg_port && p->cfg_port[0]) ? p->cfg_port : NULL; + char *port_name = (p->opts->port && p->opts->port[0]) ? p->opts->port : NULL; const char **matching_ports = NULL; int port_flags = JackPortIsInput; int i; @@ -144,7 +168,7 @@ static void resume(struct ao *ao) if (jack_activate(p->client)) MP_FATAL(ao, "activate failed\n"); - if (p->connect) + if (p->opts->connect) connect_to_outports(ao); } } @@ -155,9 +179,11 @@ static int init(struct ao *ao) struct mp_chmap_sel sel = {0}; jack_options_t open_options; + p->opts = mp_get_config_group(ao, ao->global, &ao_jack_conf); + ao->format = AF_FORMAT_FLOATP; - switch (p->stdlayout) { + switch (p->opts->stdlayout) { case 0: mp_chmap_sel_add_waveext(&sel); break; @@ -170,10 +196,10 @@ static int init(struct ao *ao) goto err_chmap; open_options = JackNullOption; - if (!p->autostart) + if (!p->opts->autostart) open_options |= JackNoStartServer; - p->client = jack_client_open(p->cfg_client_name, open_options, NULL); + p->client = jack_client_open(p->opts->client_name, open_options, NULL); if (!p->client) { MP_FATAL(ao, "cannot open server\n"); goto err_client_open; @@ -213,8 +239,6 @@ static void uninit(struct ao *ao) jack_client_close(p->client); } -#define OPT_BASE_STRUCT struct priv - const struct ao_driver audio_out_jack = { .description = "JACK audio output", .name = "jack", @@ -222,17 +246,13 @@ const struct ao_driver audio_out_jack = { .uninit = uninit, .resume = resume, .priv_size = sizeof(struct priv), - .priv_defaults = &(const struct priv) { - .cfg_client_name = "mpv", - .connect = 1, - }, .options = (const struct m_option[]) { - OPT_STRING("port", cfg_port, 0), - OPT_STRING("name", cfg_client_name, 0), - OPT_FLAG("autostart", autostart, 0), - OPT_FLAG("connect", connect, 0), - OPT_CHOICE("std-channel-layout", stdlayout, 0, - ({"waveext", 0}, {"any", 1})), + OPT_SUBOPT_LEGACY("port", "jack-port"), + OPT_SUBOPT_LEGACY("name", "jack-name"), + OPT_SUBOPT_LEGACY("autostart", "jack-autostart"), + OPT_SUBOPT_LEGACY("connect", "jack-connect"), + OPT_SUBOPT_LEGACY("std-channel-layout", "jack-std-channel-layout"), {0} }, + .global_opts = &ao_jack_conf, }; -- cgit v1.2.3 From 633eb30cbe0e52879443633760e9460fe5bdcdfa Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 5 Sep 2016 21:05:47 +0200 Subject: options: add automagic hack for handling sub-option deprecations I decided that it's too much work to convert all the VO/AOs to the new option system manually at once. So here's a shitty hack instead, which achieves almost the same thing. (The only user-visible difference is that e.g. --vo=name:help will list the sub-options normally, instead of showing them as deprecation placeholders. Also, the sub-option parser will verify each option normally, instead of deferring to the global option parser.) Another advantage is that once we drop the deprecated options, converting the remaining things will be easier, because we obviously don't need to add the compatibility hacks. Using this mechanism is separate in the next commit to keep the diff noise down. --- audio/out/ao.c | 1 + audio/out/internal.h | 1 + 2 files changed, 2 insertions(+) (limited to 'audio') diff --git a/audio/out/ao.c b/audio/out/ao.c index 3bfa481bc5..cd2b9e8089 100644 --- a/audio/out/ao.c +++ b/audio/out/ao.c @@ -110,6 +110,7 @@ static bool get_desc(struct m_obj_desc *dst, int index) .priv_defaults = ao->priv_defaults, .options = ao->options, .global_opts = ao->global_opts, + .legacy_prefix = ao->legacy_prefix, .hidden = ao->encode, .p = ao, }; diff --git a/audio/out/internal.h b/audio/out/internal.h index f9dc073b4d..3115fbfeb7 100644 --- a/audio/out/internal.h +++ b/audio/out/internal.h @@ -182,6 +182,7 @@ struct ao_driver { const void *priv_defaults; const struct m_option *options; const struct m_sub_options *global_opts; + const char *legacy_prefix; }; // These functions can be called by AOs. -- cgit v1.2.3 From 69283bc0f8905e7748343f2c5389791f858a5f4c Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 5 Sep 2016 21:07:03 +0200 Subject: options: deprecate suboptions for the remaining AO/VOs --- audio/out/ao_coreaudio.c | 1 + audio/out/ao_null.c | 1 + audio/out/ao_openal.c | 1 + audio/out/ao_opensles.c | 1 + audio/out/ao_oss.c | 1 + audio/out/ao_pcm.c | 1 + audio/out/ao_pulse.c | 1 + audio/out/ao_rsound.c | 1 + audio/out/ao_sdl.c | 1 + audio/out/ao_sndio.c | 1 + audio/out/ao_wasapi.c | 1 + 11 files changed, 11 insertions(+) (limited to 'audio') diff --git a/audio/out/ao_coreaudio.c b/audio/out/ao_coreaudio.c index fbbacde714..1300489084 100644 --- a/audio/out/ao_coreaudio.c +++ b/audio/out/ao_coreaudio.c @@ -430,4 +430,5 @@ const struct ao_driver audio_out_coreaudio = { OPT_FLAG("exclusive", exclusive, 0), {0} }, + .legacy_prefix = "coreaudio", }; diff --git a/audio/out/ao_null.c b/audio/out/ao_null.c index ac3f8348b5..7c0c745b12 100644 --- a/audio/out/ao_null.c +++ b/audio/out/ao_null.c @@ -241,4 +241,5 @@ const struct ao_driver audio_out_null = { OPT_CHANNELS("channel-layouts", channel_layouts, 0), {0} }, + .legacy_prefix = "ao-null", }; diff --git a/audio/out/ao_openal.c b/audio/out/ao_openal.c index 72e8799e00..41a1a03194 100644 --- a/audio/out/ao_openal.c +++ b/audio/out/ao_openal.c @@ -359,4 +359,5 @@ const struct ao_driver audio_out_openal = { OPT_STRING_VALIDATE("device", cfg_device, 0, validate_device_opt), {0} }, + .legacy_prefix = "ao-openal", }; diff --git a/audio/out/ao_opensles.c b/audio/out/ao_opensles.c index 2ce7b01552..dd20dbf1d0 100644 --- a/audio/out/ao_opensles.c +++ b/audio/out/ao_opensles.c @@ -246,4 +246,5 @@ const struct ao_driver audio_out_opensles = { OPT_INTRANGE("sample-rate", cfg_sample_rate, 0, 1000, 100000), {0} }, + .legacy_prefix = "opensles", }; diff --git a/audio/out/ao_oss.c b/audio/out/ao_oss.c index 90d3b3e5c5..cd08a046f7 100644 --- a/audio/out/ao_oss.c +++ b/audio/out/ao_oss.c @@ -653,4 +653,5 @@ const struct ao_driver audio_out_oss = { OPT_STRING("mixer-channel", cfg_oss_mixer_channel, 0), {0} }, + .legacy_prefix = "oss", }; diff --git a/audio/out/ao_pcm.c b/audio/out/ao_pcm.c index c26f614f2d..535b77642d 100644 --- a/audio/out/ao_pcm.c +++ b/audio/out/ao_pcm.c @@ -226,4 +226,5 @@ const struct ao_driver audio_out_pcm = { OPT_FLAG("append", append, 0), {0} }, + .legacy_prefix = "ao-pcm", }; diff --git a/audio/out/ao_pulse.c b/audio/out/ao_pulse.c index fc0dd0d008..6eedea2b07 100644 --- a/audio/out/ao_pulse.c +++ b/audio/out/ao_pulse.c @@ -841,4 +841,5 @@ const struct ao_driver audio_out_pulse = { OPT_FLAG("latency-hacks", cfg_latency_hacks, 0), {0} }, + .legacy_prefix = "pulse", }; diff --git a/audio/out/ao_rsound.c b/audio/out/ao_rsound.c index 5379e73a72..8b80ddf1da 100644 --- a/audio/out/ao_rsound.c +++ b/audio/out/ao_rsound.c @@ -160,5 +160,6 @@ const struct ao_driver audio_out_rsound = { OPT_STRING("port", port, 0), {0} }, + .legacy_prefix = "rsound", }; diff --git a/audio/out/ao_sdl.c b/audio/out/ao_sdl.c index 627a1098cf..d9d00628b6 100644 --- a/audio/out/ao_sdl.c +++ b/audio/out/ao_sdl.c @@ -212,4 +212,5 @@ const struct ao_driver audio_out_sdl = { OPT_FLOAT("buflen", buflen, 0), {0} }, + .legacy_prefix = "sdl", }; diff --git a/audio/out/ao_sndio.c b/audio/out/ao_sndio.c index e9df269f90..c53e01cb9e 100644 --- a/audio/out/ao_sndio.c +++ b/audio/out/ao_sndio.c @@ -323,4 +323,5 @@ const struct ao_driver audio_out_sndio = { OPT_STRING("device", dev, 0, OPTDEF_STR(SIO_DEVANY)), {0} }, + .legacy_prefix = "ao-sndio", }; diff --git a/audio/out/ao_wasapi.c b/audio/out/ao_wasapi.c index 325a7cf72b..7cdde49ce9 100644 --- a/audio/out/ao_wasapi.c +++ b/audio/out/ao_wasapi.c @@ -499,4 +499,5 @@ const struct ao_driver audio_out_wasapi = { OPT_STRING("device", opt_device, 0), {NULL}, }, + .legacy_prefix = "ao-wasapi", }; -- cgit v1.2.3 From 13786dc643fe250a9560792ef342751585ea15e9 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 5 Sep 2016 21:07:30 +0200 Subject: audio/out: deprecate device sub-options We have --audio-device, which can force the device. Also add something describing to this extent to the manpage. --- audio/out/ao_alsa.c | 2 +- audio/out/ao_openal.c | 3 ++- audio/out/ao_oss.c | 2 +- audio/out/ao_pulse.c | 2 +- audio/out/ao_rsound.c | 6 ++++-- audio/out/ao_sndio.c | 3 ++- audio/out/ao_wasapi.c | 2 +- audio/out/internal.h | 3 +++ 8 files changed, 15 insertions(+), 8 deletions(-) (limited to 'audio') diff --git a/audio/out/ao_alsa.c b/audio/out/ao_alsa.c index c542bee030..4d879b1565 100644 --- a/audio/out/ao_alsa.c +++ b/audio/out/ao_alsa.c @@ -62,7 +62,7 @@ struct ao_alsa_opts { #define OPT_BASE_STRUCT struct ao_alsa_opts static const struct m_sub_options ao_alsa_conf = { .opts = (const struct m_option[]) { - OPT_STRING("alsa-device", device, 0), + OPT_STRING("alsa-device", device, 0, DEVICE_OPT_DEPRECATION), OPT_FLAG("alsa-resample", resample, 0), OPT_STRING("alsa-mixer-device", mixer_device, 0), OPT_STRING("alsa-mixer-name", mixer_name, 0), diff --git a/audio/out/ao_openal.c b/audio/out/ao_openal.c index 41a1a03194..2c29b8923b 100644 --- a/audio/out/ao_openal.c +++ b/audio/out/ao_openal.c @@ -356,7 +356,8 @@ const struct ao_driver audio_out_openal = { .list_devs = list_devs, .priv_size = sizeof(struct priv), .options = (const struct m_option[]) { - OPT_STRING_VALIDATE("device", cfg_device, 0, validate_device_opt), + OPT_STRING_VALIDATE("device", cfg_device, 0, validate_device_opt, + DEVICE_OPT_DEPRECATION), {0} }, .legacy_prefix = "ao-openal", diff --git a/audio/out/ao_oss.c b/audio/out/ao_oss.c index cd08a046f7..5bf5fec29b 100644 --- a/audio/out/ao_oss.c +++ b/audio/out/ao_oss.c @@ -648,7 +648,7 @@ const struct ao_driver audio_out_oss = { .oss_mixer_device = PATH_DEV_MIXER, }, .options = (const struct m_option[]) { - OPT_STRING("device", dsp, 0), + OPT_STRING("device", dsp, 0, DEVICE_OPT_DEPRECATION), OPT_STRING("mixer-device", oss_mixer_device, 0), OPT_STRING("mixer-channel", cfg_oss_mixer_channel, 0), {0} diff --git a/audio/out/ao_pulse.c b/audio/out/ao_pulse.c index 6eedea2b07..5a68553e88 100644 --- a/audio/out/ao_pulse.c +++ b/audio/out/ao_pulse.c @@ -836,7 +836,7 @@ const struct ao_driver audio_out_pulse = { }, .options = (const struct m_option[]) { OPT_STRING("host", cfg_host, 0), - OPT_STRING("sink", cfg_sink, 0), + OPT_STRING("sink", cfg_sink, 0, DEVICE_OPT_DEPRECATION), OPT_CHOICE_OR_INT("buffer", cfg_buffer, 0, 1, 2000, ({"native", 0})), OPT_FLAG("latency-hacks", cfg_latency_hacks, 0), {0} diff --git a/audio/out/ao_rsound.c b/audio/out/ao_rsound.c index 8b80ddf1da..65196d0932 100644 --- a/audio/out/ao_rsound.c +++ b/audio/out/ao_rsound.c @@ -156,8 +156,10 @@ const struct ao_driver audio_out_rsound = { .resume = audio_resume, .priv_size = sizeof(struct priv), .options = (const struct m_option[]) { - OPT_STRING("host", host, 0), - OPT_STRING("port", port, 0), + OPT_STRING("host", host, 0, + .deprecation_message = "request --audio-device support on issue tracker"), + OPT_STRING("port", port, 0 + .deprecation_message = "request --audio-device support on issue tracker"), {0} }, .legacy_prefix = "rsound", diff --git a/audio/out/ao_sndio.c b/audio/out/ao_sndio.c index c53e01cb9e..f60fa303e5 100644 --- a/audio/out/ao_sndio.c +++ b/audio/out/ao_sndio.c @@ -320,7 +320,8 @@ const struct ao_driver audio_out_sndio = { .reset = reset, .priv_size = sizeof(struct priv), .options = (const struct m_option[]) { - OPT_STRING("device", dev, 0, OPTDEF_STR(SIO_DEVANY)), + OPT_STRING("device", dev, 0, OPTDEF_STR(SIO_DEVANY), + DEVICE_OPT_DEPRECATION), {0} }, .legacy_prefix = "ao-sndio", diff --git a/audio/out/ao_wasapi.c b/audio/out/ao_wasapi.c index 7cdde49ce9..23a958bb3b 100644 --- a/audio/out/ao_wasapi.c +++ b/audio/out/ao_wasapi.c @@ -496,7 +496,7 @@ const struct ao_driver audio_out_wasapi = { .priv_size = sizeof(wasapi_state), .options = (const struct m_option[]) { OPT_FLAG("exclusive", opt_exclusive, 0), - OPT_STRING("device", opt_device, 0), + OPT_STRING("device", opt_device, 0, DEVICE_OPT_DEPRECATION), {NULL}, }, .legacy_prefix = "ao-wasapi", diff --git a/audio/out/internal.h b/audio/out/internal.h index 3115fbfeb7..fdbb423f52 100644 --- a/audio/out/internal.h +++ b/audio/out/internal.h @@ -206,4 +206,7 @@ bool ao_chmap_sel_get_def(struct ao *ao, const struct mp_chmap_sel *s, void ao_device_list_add(struct ao_device_list *list, struct ao *ao, struct ao_device_desc *e); +#define DEVICE_OPT_DEPRECATION \ + .deprecation_message = "use --audio-device instead" + #endif -- cgit v1.2.3 From 1d9032f011a57a31f6a8ccc40a0aba08a8e74e0d Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 5 Sep 2016 21:07:34 +0200 Subject: audio/out: deprecate "exclusive" sub-options And introduce a global option which does this. Or more precisely, this deprecates the global wasapi and coreaudio options, and adds a new one that merges their functionality. (Due to the way the sub-option deprecation mechanism works, this is simpler.) --- audio/out/ao.h | 2 ++ audio/out/ao_coreaudio.c | 5 ++++- audio/out/ao_wasapi.c | 5 ++++- 3 files changed, 10 insertions(+), 2 deletions(-) (limited to 'audio') diff --git a/audio/out/ao.h b/audio/out/ao.h index 3b187e7355..fe09e2750a 100644 --- a/audio/out/ao.h +++ b/audio/out/ao.h @@ -58,6 +58,8 @@ enum { AO_INIT_SAFE_MULTICHANNEL_ONLY = 1 << 1, // Stream silence as long as no audio is playing. AO_INIT_STREAM_SILENCE = 1 << 2, + // Force exclusive mode, i.e. lock out the system mixer. + AO_INIT_EXCLUSIVE = 1 << 3, }; typedef struct ao_control_vol { diff --git a/audio/out/ao_coreaudio.c b/audio/out/ao_coreaudio.c index 1300489084..3a7aa2eac1 100644 --- a/audio/out/ao_coreaudio.c +++ b/audio/out/ao_coreaudio.c @@ -143,6 +143,8 @@ static int init(struct ao *ao) { struct priv *p = ao->priv; + p->exclusive |= ao->init_flags & AO_INIT_EXCLUSIVE; + if (!af_fmt_is_pcm(ao->format) || p->exclusive) { MP_VERBOSE(ao, "redirecting to coreaudio_exclusive\n"); ao->redirect = "coreaudio_exclusive"; @@ -427,7 +429,8 @@ const struct ao_driver audio_out_coreaudio = { .priv_size = sizeof(struct priv), .options = (const struct m_option[]){ OPT_FLAG("change-physical-format", change_physical_format, 0), - OPT_FLAG("exclusive", exclusive, 0), + OPT_FLAG("exclusive", exclusive, 0, + .deprecation_message = "use --audio-exclusive"), {0} }, .legacy_prefix = "coreaudio", diff --git a/audio/out/ao_wasapi.c b/audio/out/ao_wasapi.c index 23a958bb3b..17f3e98653 100644 --- a/audio/out/ao_wasapi.c +++ b/audio/out/ao_wasapi.c @@ -275,6 +275,8 @@ static int init(struct ao *ao) struct wasapi_state *state = ao->priv; state->log = ao->log; + state->opt_exclusive |= ao->init_flags & AO_INIT_EXCLUSIVE; + state->deviceID = wasapi_find_deviceID(ao); if (!state->deviceID) { uninit(ao); @@ -495,7 +497,8 @@ const struct ao_driver audio_out_wasapi = { .hotplug_uninit = hotplug_uninit, .priv_size = sizeof(wasapi_state), .options = (const struct m_option[]) { - OPT_FLAG("exclusive", opt_exclusive, 0), + OPT_FLAG("exclusive", opt_exclusive, 0, + .deprecation_message = "use --audio-exclusive"), OPT_STRING("device", opt_device, 0, DEVICE_OPT_DEPRECATION), {NULL}, }, -- cgit v1.2.3 From 591e21a2ebd105c33127d4a792d4d0e1a083fcfc Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 7 Sep 2016 11:26:25 +0200 Subject: osdep: rename atomics.h to atomic.h The standard header is stdatomic.h, so the extra "s" freaks me out every time I look at it. --- audio/out/ao_coreaudio_exclusive.c | 2 +- audio/out/ao_wasapi.h | 2 +- audio/out/internal.h | 2 +- audio/out/pull.c | 2 +- audio/out/push.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) (limited to 'audio') diff --git a/audio/out/ao_coreaudio_exclusive.c b/audio/out/ao_coreaudio_exclusive.c index 49f921cd4c..cc20fd9a51 100644 --- a/audio/out/ao_coreaudio_exclusive.c +++ b/audio/out/ao_coreaudio_exclusive.c @@ -41,7 +41,7 @@ #include "internal.h" #include "audio/format.h" #include "osdep/timer.h" -#include "osdep/atomics.h" +#include "osdep/atomic.h" #include "options/m_option.h" #include "common/msg.h" #include "audio/out/ao_coreaudio_chmap.h" diff --git a/audio/out/ao_wasapi.h b/audio/out/ao_wasapi.h index 3ae50159b3..6dd130b50f 100644 --- a/audio/out/ao_wasapi.h +++ b/audio/out/ao_wasapi.h @@ -29,7 +29,7 @@ #include #include "common/msg.h" -#include "osdep/atomics.h" +#include "osdep/atomic.h" #include "osdep/windows_utils.h" #include "internal.h" #include "ao.h" diff --git a/audio/out/internal.h b/audio/out/internal.h index fdbb423f52..319881b194 100644 --- a/audio/out/internal.h +++ b/audio/out/internal.h @@ -21,7 +21,7 @@ #include #include -#include "osdep/atomics.h" +#include "osdep/atomic.h" #include "audio/out/ao.h" /* global data used by ao.c and ao drivers */ diff --git a/audio/out/pull.c b/audio/out/pull.c index 2175a58db0..5dd6525fc8 100644 --- a/audio/out/pull.c +++ b/audio/out/pull.c @@ -30,7 +30,7 @@ #include "osdep/timer.h" #include "osdep/threads.h" -#include "osdep/atomics.h" +#include "osdep/atomic.h" #include "misc/ring.h" /* diff --git a/audio/out/push.c b/audio/out/push.c index bf5dde46b5..406b0da790 100644 --- a/audio/out/push.c +++ b/audio/out/push.c @@ -35,7 +35,7 @@ #include "osdep/threads.h" #include "osdep/timer.h" -#include "osdep/atomics.h" +#include "osdep/atomic.h" #include "audio/audio.h" #include "audio/audio_buffer.h" -- cgit v1.2.3 From 5a7b1ff4c0cb176ee94995646d310f6ffd60fe61 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 7 Sep 2016 12:54:33 +0200 Subject: ao_pcm: remove some useless messages The first one is printed even if the user disabled video (or there's no video), so just remove it. The second one uses deprecated sub-option syntax, so remove that as well. --- audio/out/ao_pcm.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'audio') diff --git a/audio/out/ao_pcm.c b/audio/out/ao_pcm.c index 535b77642d..169a1b94a1 100644 --- a/audio/out/ao_pcm.c +++ b/audio/out/ao_pcm.c @@ -152,8 +152,6 @@ static int init(struct ao *ao) priv->outputfilename, priv->waveheader ? "WAVE" : "RAW PCM", ao->samplerate, ao->channels.num, af_fmt_to_str(ao->format)); - MP_INFO(ao, "Info: Faster dumping is achieved with --no-video\n"); - MP_INFO(ao, "Info: To write WAVE files use --ao=pcm:waveheader (default).\n"); priv->fp = fopen(priv->outputfilename, priv->append ? "ab" : "wb"); if (!priv->fp) { -- cgit v1.2.3 From 062423381d0e29d0560d44560019b23dde913bec Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 7 Sep 2016 18:10:12 +0200 Subject: ao_rsound: fix compilation Probably fixes #3501. --- audio/out/ao_rsound.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'audio') diff --git a/audio/out/ao_rsound.c b/audio/out/ao_rsound.c index 65196d0932..5ecb39b9d3 100644 --- a/audio/out/ao_rsound.c +++ b/audio/out/ao_rsound.c @@ -158,7 +158,7 @@ const struct ao_driver audio_out_rsound = { .options = (const struct m_option[]) { OPT_STRING("host", host, 0, .deprecation_message = "request --audio-device support on issue tracker"), - OPT_STRING("port", port, 0 + OPT_STRING("port", port, 0, .deprecation_message = "request --audio-device support on issue tracker"), {0} }, -- cgit v1.2.3 From b8ade7c99b830ee9870040bcfc1f2c3d3a64d172 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 16 Sep 2016 14:23:54 +0200 Subject: player, ao, vo: don't call mp_input_wakeup() directly Currently, calling mp_input_wakeup() will wake up the core thread (also called the playloop). This seems odd, but currently the core indeed calls mp_input_wait() when it has nothing more to do. It's done this way because MPlayer used input_ctx as central "mainloop". This is probably going to change. Remove direct calls to this function, and replace it with mp_wakeup_core() calls. ao and vo are changed to use opaque callbacks and not use input_ctx for this purpose. Other code already uses opaque callbacks, or has legitimate reasons to use input_ctx directly (such as sending actual user input). --- audio/out/ao.c | 44 +++++++++++++++++++++++++++----------------- audio/out/ao.h | 5 +++-- audio/out/internal.h | 3 ++- audio/out/pull.c | 2 +- audio/out/push.c | 4 ++-- 5 files changed, 35 insertions(+), 23 deletions(-) (limited to 'audio') diff --git a/audio/out/ao.c b/audio/out/ao.c index cd2b9e8089..15c0f8139e 100644 --- a/audio/out/ao.c +++ b/audio/out/ao.c @@ -28,7 +28,6 @@ #include "audio/format.h" #include "audio/audio.h" -#include "input/input.h" #include "options/options.h" #include "options/m_config.h" #include "common/msg.h" @@ -127,8 +126,11 @@ const struct m_obj_list ao_obj_list = { }; static struct ao *ao_alloc(bool probing, struct mpv_global *global, - struct input_ctx *input_ctx, char *name, char **args) + void (*wakeup_cb)(void *ctx), void *wakeup_ctx, + char *name, char **args) { + assert(wakeup_cb); + struct MPOpts *opts = global->opts; struct mp_log *log = mp_log_new(NULL, global->log, "ao"); struct m_obj_desc desc; @@ -143,7 +145,8 @@ static struct ao *ao_alloc(bool probing, struct mpv_global *global, .driver = desc.p, .probing = probing, .global = global, - .input_ctx = input_ctx, + .wakeup_cb = wakeup_cb, + .wakeup_ctx = wakeup_ctx, .log = mp_log_new(ao, log, name), .def_buffer = opts->audio_buffer, .client_name = talloc_strdup(ao, opts->audio_client_name), @@ -161,12 +164,12 @@ error: } static struct ao *ao_init(bool probing, struct mpv_global *global, - struct input_ctx *input_ctx, + void (*wakeup_cb)(void *ctx), void *wakeup_ctx, struct encode_lavc_context *encode_lavc_ctx, int flags, int samplerate, int format, struct mp_chmap channels, char *dev, char *name, char **args) { - struct ao *ao = ao_alloc(probing, global, input_ctx, name, args); + struct ao *ao = ao_alloc(probing, global, wakeup_cb, wakeup_ctx, name, args); if (!ao) return NULL; ao->samplerate = samplerate; @@ -197,8 +200,9 @@ static struct ao *ao_init(bool probing, struct mpv_global *global, snprintf(redirect, sizeof(redirect), "%s", ao->redirect); snprintf(rdevice, sizeof(rdevice), "%s", ao->device ? ao->device : ""); talloc_free(ao); - return ao_init(probing, global, input_ctx, encode_lavc_ctx, flags, - samplerate, format, channels, rdevice, redirect, NULL); + return ao_init(probing, global, wakeup_cb, wakeup_ctx, + encode_lavc_ctx, flags, samplerate, format, channels, + rdevice, redirect, NULL); } goto fail; } @@ -248,7 +252,7 @@ static void split_ao_device(void *tmp, char *opt, char **out_ao, char **out_dev) struct ao *ao_init_best(struct mpv_global *global, int init_flags, - struct input_ctx *input_ctx, + void (*wakeup_cb)(void *ctx), void *wakeup_ctx, struct encode_lavc_context *encode_lavc_ctx, int samplerate, int format, struct mp_chmap channels) { @@ -304,8 +308,8 @@ struct ao *ao_init_best(struct mpv_global *global, dev = pref_dev; mp_verbose(log, "Using preferred device '%s'\n", dev); } - ao = ao_init(probing, global, input_ctx, encode_lavc_ctx, init_flags, - samplerate, format, channels, dev, + ao = ao_init(probing, global, wakeup_cb, wakeup_ctx, encode_lavc_ctx, + init_flags, samplerate, format, channels, dev, entry->name, entry->attribs); if (ao) break; @@ -409,8 +413,7 @@ int ao_query_and_reset_events(struct ao *ao, int events) static void ao_add_events(struct ao *ao, int events) { atomic_fetch_or(&ao->events_, events); - if (ao->input_ctx) - mp_input_wakeup(ao->input_ctx); + ao->wakeup_cb(ao->wakeup_ctx); } // Request that the player core destroys and recreates the AO. Fully thread-safe. @@ -494,7 +497,8 @@ bool ao_untimed(struct ao *ao) struct ao_hotplug { struct mpv_global *global; - struct input_ctx *input_ctx; + void (*wakeup_cb)(void *ctx); + void *wakeup_ctx; // A single AO instance is used to listen to hotplug events. It wouldn't // make much sense to allow multiple AO drivers; all sane platforms have // a single such audio API. @@ -506,12 +510,14 @@ struct ao_hotplug { }; struct ao_hotplug *ao_hotplug_create(struct mpv_global *global, - struct input_ctx *input_ctx) + void (*wakeup_cb)(void *ctx), + void *wakeup_ctx) { struct ao_hotplug *hp = talloc_ptrtype(NULL, hp); *hp = (struct ao_hotplug){ .global = global, - .input_ctx = input_ctx, + .wakeup_cb = wakeup_cb, + .wakeup_ctx = wakeup_ctx, .needs_update = true, }; return hp; @@ -564,7 +570,7 @@ struct ao_device_list *ao_hotplug_get_device_list(struct ao_hotplug *hp) if (d == &audio_out_null) break; // don't add unsafe/special entries - struct ao *ao = ao_alloc(true, hp->global, hp->input_ctx, + struct ao *ao = ao_alloc(true, hp->global, hp->wakeup_cb, hp->wakeup_ctx, (char *)d->name, NULL); if (!ao) continue; @@ -605,9 +611,13 @@ void ao_hotplug_destroy(struct ao_hotplug *hp) talloc_free(hp); } +static void dummy_wakeup(void *ctx) +{ +} + void ao_print_devices(struct mpv_global *global, struct mp_log *log) { - struct ao_hotplug *hp = ao_hotplug_create(global, NULL); + struct ao_hotplug *hp = ao_hotplug_create(global, dummy_wakeup, NULL); struct ao_device_list *list = ao_hotplug_get_device_list(hp); mp_info(log, "List of detected audio devices:\n"); for (int n = 0; n < list->num_devices; n++) { diff --git a/audio/out/ao.h b/audio/out/ao.h index fe09e2750a..4a4d433c2b 100644 --- a/audio/out/ao.h +++ b/audio/out/ao.h @@ -85,7 +85,7 @@ struct mp_audio; struct ao *ao_init_best(struct mpv_global *global, int init_flags, - struct input_ctx *input_ctx, + void (*wakeup_cb)(void *ctx), void *wakeup_ctx, struct encode_lavc_context *encode_lavc_ctx, int samplerate, int format, struct mp_chmap channels); void ao_uninit(struct ao *ao); @@ -108,7 +108,8 @@ void ao_hotplug_event(struct ao *ao); struct ao_hotplug; struct ao_hotplug *ao_hotplug_create(struct mpv_global *global, - struct input_ctx *input_ctx); + void (*wakeup_cb)(void *ctx), + void *wakeup_ctx); void ao_hotplug_destroy(struct ao_hotplug *hp); bool ao_hotplug_check_update(struct ao_hotplug *hp); const char *ao_hotplug_get_detected_device(struct ao_hotplug *hp); diff --git a/audio/out/internal.h b/audio/out/internal.h index 319881b194..3ddc1becb9 100644 --- a/audio/out/internal.h +++ b/audio/out/internal.h @@ -42,7 +42,8 @@ struct ao { void *priv; struct mpv_global *global; struct encode_lavc_context *encode_lavc_ctx; - struct input_ctx *input_ctx; + void (*wakeup_cb)(void *ctx); + void *wakeup_ctx; struct mp_log *log; // Using e.g. "[ao/coreaudio]" as prefix int init_flags; // AO_INIT_* flags bool stream_silence; // if audio inactive, just play silence diff --git a/audio/out/pull.c b/audio/out/pull.c index 5dd6525fc8..44f6ab3355 100644 --- a/audio/out/pull.c +++ b/audio/out/pull.c @@ -151,7 +151,7 @@ int ao_read_data(struct ao *ao, void **data, int samples, int64_t out_time_us) end: if (need_wakeup) - mp_input_wakeup_nolock(ao->input_ctx); + ao->wakeup_cb(ao->wakeup_ctx); // pad with silence (underflow/paused/eof) for (int n = 0; n < ao->num_planes; n++) diff --git a/audio/out/push.c b/audio/out/push.c index 406b0da790..623ee6827a 100644 --- a/audio/out/push.c +++ b/audio/out/push.c @@ -305,7 +305,7 @@ static void ao_play_data(struct ao *ao) bool more = needed >= (r == space ? ao->device_buffer / 4 : 1) && !stuck && !(flags & AOPLAY_FINAL_CHUNK); if (more) - mp_input_wakeup(ao->input_ctx); // request more data + ao->wakeup_cb(ao->wakeup_ctx); // request more data MP_TRACE(ao, "in=%d flags=%d space=%d r=%d wa/pl=%d/%d needed=%d more=%d\n", max, flags, space, r, p->wait_on_ao, p->still_playing, needed, more); } @@ -347,7 +347,7 @@ static void *playthread(void *arg) } if (was_playing && !p->still_playing) - mp_input_wakeup(ao->input_ctx); + ao->wakeup_cb(ao->wakeup_ctx); pthread_cond_signal(&p->wakeup); // for draining if (p->still_playing && timeout > 0) { -- cgit v1.2.3 From dc48893630d11829121a45137460afb45e24ef2d Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 17 Sep 2016 18:07:40 +0200 Subject: options: simplify M_OPT_EXIT There were multiple values under M_OPT_EXIT (M_OPT_EXIT-n for n>=0). Somehow M_OPT_EXIT-n either meant error code n (with n==0 no error?), or the number of option valus consumed (0 or 1). The latter is MPlayer legacy, which left it to the option type parsers to determine whether an option took a value or not. All of this was changed in mpv, by requiring the user to use explicit syntax ("--opt=val" instead of "-opt val"). In any case, the n value wasn't even used (anymore), so rip this all out. Now M_OPT_EXIT-1 doesn't mean anything, and could be used by a new error code. --- audio/out/ao_openal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'audio') diff --git a/audio/out/ao_openal.c b/audio/out/ao_openal.c index 2c29b8923b..237226e4a5 100644 --- a/audio/out/ao_openal.c +++ b/audio/out/ao_openal.c @@ -96,7 +96,7 @@ static int validate_device_opt(struct mp_log *log, const m_option_t *opt, mp_info(log, " '%s'\n", list); list = list + strlen(list) + 1; } - return M_OPT_EXIT - 1; + return M_OPT_EXIT; } return 0; } -- cgit v1.2.3 From 0525f5fa93f9d997fd3d0037be17c3350823704e Mon Sep 17 00:00:00 2001 From: Hector Martin Date: Mon, 19 Sep 2016 21:22:58 +0900 Subject: af_pan: coding style fixes --- audio/filter/af_pan.c | 207 +++++++++++++++++++++++++------------------------- 1 file changed, 104 insertions(+), 103 deletions(-) (limited to 'audio') diff --git a/audio/filter/af_pan.c b/audio/filter/af_pan.c index 900d10cc74..ad4d31df29 100644 --- a/audio/filter/af_pan.c +++ b/audio/filter/af_pan.c @@ -28,12 +28,11 @@ #include "af.h" // Data for specific instances of this filter -typedef struct af_pan_s -{ - int nch; // Number of output channels; zero means same as input - float level[AF_NCH][AF_NCH]; // Gain level for each channel - char *matrixstr; -}af_pan_t; +typedef struct af_pan_s { + int nch; // Number of output channels; zero means same as input + float level[AF_NCH][AF_NCH]; // Gain level for each channel + char *matrixstr; +} af_pan_t; static void set_channels(struct mp_audio *mpa, int num) { @@ -45,128 +44,130 @@ static void set_channels(struct mp_audio *mpa, int num) } // Initialization and runtime control -static int control(struct af_instance* af, int cmd, void* arg) +static int control(struct af_instance *af, int cmd, void *arg) { - af_pan_t* s = af->priv; - - switch(cmd){ - case AF_CONTROL_REINIT: - // Sanity check - if(!arg) return AF_ERROR; - - af->data->rate = ((struct mp_audio*)arg)->rate; - mp_audio_set_format(af->data, AF_FORMAT_FLOAT); - set_channels(af->data, s->nch ? s->nch: ((struct mp_audio*)arg)->nch); - - if((af->data->format != ((struct mp_audio*)arg)->format) || - (af->data->bps != ((struct mp_audio*)arg)->bps)){ - mp_audio_set_format((struct mp_audio*)arg, af->data->format); - return AF_FALSE; + af_pan_t* s = af->priv; + + switch(cmd){ + case AF_CONTROL_REINIT: + // Sanity check + if (!arg) + return AF_ERROR; + + af->data->rate = ((struct mp_audio*)arg)->rate; + mp_audio_set_format(af->data, AF_FORMAT_FLOAT); + set_channels(af->data, s->nch ? s->nch : ((struct mp_audio*)arg)->nch); + + if ((af->data->format != ((struct mp_audio*)arg)->format) || + (af->data->bps != ((struct mp_audio*)arg)->bps)) { + mp_audio_set_format((struct mp_audio*)arg, af->data->format); + return AF_FALSE; + } + return AF_OK; + case AF_CONTROL_SET_PAN_LEVEL: { + int i; + int ch = ((af_control_ext_t*)arg)->ch; + float *level = ((af_control_ext_t*)arg)->arg; + if (ch >= AF_NCH) + return AF_FALSE; + for (i = 0; i < AF_NCH; i++) + s->level[ch][i] = level[i]; + return AF_OK; } - return AF_OK; - case AF_CONTROL_SET_PAN_LEVEL:{ - int i; - int ch = ((af_control_ext_t*)arg)->ch; - float* level = ((af_control_ext_t*)arg)->arg; - if (ch >= AF_NCH) - return AF_FALSE; - for(i=0;ilevel[ch][i] = level[i]; - return AF_OK; - } - case AF_CONTROL_SET_PAN_NOUT: - // Reinit must be called after this function has been called - - // Sanity check - if(((int*)arg)[0] <= 0 || ((int*)arg)[0] > AF_NCH){ - MP_ERR(af, "The number of output channels must be" - " between 1 and %i. Current value is %i\n",AF_NCH,((int*)arg)[0]); - return AF_ERROR; + case AF_CONTROL_SET_PAN_NOUT: + // Reinit must be called after this function has been called + // Sanity check + if (((int*)arg)[0] <= 0 || ((int*)arg)[0] > AF_NCH) { + MP_ERR(af, "The number of output channels must be" + " between 1 and %i. Current value is %i\n", + AF_NCH, ((int*)arg)[0]); + return AF_ERROR; + } + s->nch = ((int*)arg)[0]; + return AF_OK; + case AF_CONTROL_SET_PAN_BALANCE: { + float val = *(float*)arg; + if (s->nch) + return AF_ERROR; + if (af->data->nch >= 2) { + s->level[0][0] = MPMIN(1.f, 1.f - val); + s->level[0][1] = MPMAX(0.f, val); + s->level[1][0] = MPMAX(0.f, -val); + s->level[1][1] = MPMIN(1.f, 1.f + val); + } + return AF_OK; } - s->nch=((int*)arg)[0]; - return AF_OK; - case AF_CONTROL_SET_PAN_BALANCE:{ - float val = *(float*)arg; - if (s->nch) - return AF_ERROR; - if (af->data->nch >= 2) { - s->level[0][0] = MPMIN(1.f, 1.f - val); - s->level[0][1] = MPMAX(0.f, val); - s->level[1][0] = MPMAX(0.f, -val); - s->level[1][1] = MPMIN(1.f, 1.f + val); + case AF_CONTROL_GET_PAN_BALANCE: + if (s->nch) + return AF_ERROR; + *(float*)arg = s->level[0][1] - s->level[1][0]; + return AF_OK; } - return AF_OK; - } - case AF_CONTROL_GET_PAN_BALANCE: - if (s->nch) - return AF_ERROR; - *(float*)arg = s->level[0][1] - s->level[1][0]; - return AF_OK; - } - return AF_UNKNOWN; + return AF_UNKNOWN; } static int filter_frame(struct af_instance *af, struct mp_audio *c) { - if (!c) - return 0; - struct mp_audio *l = mp_audio_pool_get(af->out_pool, &af->fmt_out, c->samples); - if (!l) { - talloc_free(c); - return -1; - } - mp_audio_copy_attributes(l, c); - - af_pan_t* s = af->priv; // Setup for this instance - float* in = c->planes[0]; // Input audio data - float* out = NULL; // Output audio data - float* end = in+c->samples*c->nch; // End of loop - int nchi = c->nch; // Number of input channels - int ncho = l->nch; // Number of output channels - register int j,k; - - out = l->planes[0]; - // Execute panning - // FIXME: Too slow - while(in < end){ - for(j=0;jlevel[j][k]; - out[j] = x; + if (!c) + return 0; + struct mp_audio *l = mp_audio_pool_get(af->out_pool, &af->fmt_out, c->samples); + if (!l) { + talloc_free(c); + return -1; + } + mp_audio_copy_attributes(l, c); + + af_pan_t* s = af->priv; // Setup for this instance + float *in = c->planes[0]; // Input audio data + float *out = NULL; // Output audio data + float *end = in+c->samples * c->nch; // End of loop + int nchi = c->nch; // Number of input channels + int ncho = l->nch; // Number of output channels + register int j, k; + + out = l->planes[0]; + // Execute panning + // FIXME: Too slow + while (in < end) { + for (j = 0; j < ncho; j++) { + register float x = 0.0; + register float *tin = in; + for (k = 0; k < nchi; k++) + x += tin[k] * s->level[j][k]; + out[j] = x; + } + out += ncho; + in += nchi; } - out+= ncho; - in+= nchi; - } - talloc_free(c); - af_add_output_frame(af, l); - return 0; + talloc_free(c); + af_add_output_frame(af, l); + return 0; } // Allocate memory and set function pointers -static int af_open(struct af_instance* af){ - af->control=control; +static int af_open(struct af_instance *af) +{ + af->control = control; af->filter_frame = filter_frame; af_pan_t *s = af->priv; - int n = 0; - int j,k; + int n = 0; + int j, k; int nch = s->nch; - if(nch && AF_OK != control(af,AF_CONTROL_SET_PAN_NOUT, &nch)) + if (nch && AF_OK != control(af, AF_CONTROL_SET_PAN_NOUT, &nch)) return AF_ERROR; // Read pan values char *cp = s->matrixstr; j = 0; k = 0; - while(cp && k < AF_NCH){ + while (cp && k < AF_NCH) { sscanf(cp, "%f%n" , &s->level[j][k], &n); MP_VERBOSE(af, "Pan level from channel %i to" - " channel %i = %f\n",k,j,s->level[j][k]); - cp =&cp[n]; + " channel %i = %f\n", k, j, s->level[j][k]); + cp = &cp[n]; j++; - if(j>=nch){ + if (j >= nch) { j = 0; k++; } -- cgit v1.2.3 From ed8540c38effa1713fb066bab2771e5efae53ba4 Mon Sep 17 00:00:00 2001 From: Hector Martin Date: Mon, 19 Sep 2016 21:22:58 +0900 Subject: af_pan: add af-command support to change the matrix This allows for seamless changes in the downmixing matrix without having to reinitialize the filter chain. --- audio/filter/af_pan.c | 50 +++++++++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 19 deletions(-) (limited to 'audio') diff --git a/audio/filter/af_pan.c b/audio/filter/af_pan.c index ad4d31df29..c27f4bd07c 100644 --- a/audio/filter/af_pan.c +++ b/audio/filter/af_pan.c @@ -43,6 +43,27 @@ static void set_channels(struct mp_audio *mpa, int num) mp_audio_set_channels(mpa, &map); } +static void parse_matrix(struct af_instance *af, const char *cp) +{ + af_pan_t *s = af->priv; + int j = 0, k = 0, n; + while (cp && k < AF_NCH) { + sscanf(cp, "%f%n" , &s->level[j][k], &n); + MP_VERBOSE(af, "Pan level from channel %i to" + " channel %i = %f\n", k, j, s->level[j][k]); + cp = &cp[n]; + j++; + if (j >= s->nch) { + j = 0; + k++; + } + if (*cp != ',') + break; + cp++; + } + +} + // Initialization and runtime control static int control(struct af_instance *af, int cmd, void *arg) { @@ -102,6 +123,15 @@ static int control(struct af_instance *af, int cmd, void *arg) return AF_ERROR; *(float*)arg = s->level[0][1] - s->level[1][0]; return AF_OK; + case AF_CONTROL_COMMAND: { + char **args = arg; + if (!strcmp(args[0], "set-matrix")) { + parse_matrix(af, args[1]); + return CONTROL_OK; + } else { + return CONTROL_ERROR; + } + } } return AF_UNKNOWN; } @@ -151,30 +181,12 @@ static int af_open(struct af_instance *af) af->control = control; af->filter_frame = filter_frame; af_pan_t *s = af->priv; - int n = 0; - int j, k; - int nch = s->nch; if (nch && AF_OK != control(af, AF_CONTROL_SET_PAN_NOUT, &nch)) return AF_ERROR; // Read pan values - char *cp = s->matrixstr; - j = 0; k = 0; - while (cp && k < AF_NCH) { - sscanf(cp, "%f%n" , &s->level[j][k], &n); - MP_VERBOSE(af, "Pan level from channel %i to" - " channel %i = %f\n", k, j, s->level[j][k]); - cp = &cp[n]; - j++; - if (j >= nch) { - j = 0; - k++; - } - if (*cp != ',') - break; - cp++; - } + parse_matrix(af, s->matrixstr); return AF_OK; } -- cgit v1.2.3 From 57eca14a4537429df498b3b76578ee87debf166c Mon Sep 17 00:00:00 2001 From: Hector Martin Date: Tue, 20 Sep 2016 00:56:10 +0900 Subject: af_rubberband: add af-command and option to change the pitch This allows both fixed and dynamic control over the audio pitch using librubberband, which was previously not exposed to the user. --- audio/filter/af_rubberband.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'audio') diff --git a/audio/filter/af_rubberband.c b/audio/filter/af_rubberband.c index 48bb510679..529c252a12 100644 --- a/audio/filter/af_rubberband.c +++ b/audio/filter/af_rubberband.c @@ -26,6 +26,7 @@ struct priv { RubberBandState rubber; double speed; + double pitch; struct mp_audio *pending; bool needs_reset; // Estimate how much librubberband has buffered internally. @@ -44,6 +45,14 @@ static void update_speed(struct af_instance *af, double new_speed) rubberband_set_time_ratio(p->rubber, 1.0 / p->speed); } +static void update_pitch(struct af_instance *af, double new_pitch) +{ + struct priv *p = af->priv; + + p->pitch = new_pitch; + rubberband_set_pitch_scale(p->rubber, p->pitch); +} + static int control(struct af_instance *af, int cmd, void *arg) { struct priv *p = af->priv; @@ -72,6 +81,7 @@ static int control(struct af_instance *af, int cmd, void *arg) } update_speed(af, p->speed); + update_pitch(af, p->pitch); control(af, AF_CONTROL_RESET, NULL); return mp_audio_config_equals(in, &orig_in) ? AF_OK : AF_FALSE; @@ -87,6 +97,19 @@ static int control(struct af_instance *af, int cmd, void *arg) p->pending = NULL; p->rubber_delay = 0; return AF_OK; + case AF_CONTROL_COMMAND: { + char **args = arg; + if (!strcmp(args[0], "set-pitch")) { + char *endptr; + double pitch = strtod(args[1], &endptr); + if (*endptr || pitch < 0.01 || pitch > 100.0) + return CONTROL_ERROR; + update_pitch(af, pitch); + return CONTROL_OK; + } else { + return CONTROL_ERROR; + } + } } return AF_UNKNOWN; } @@ -187,6 +210,7 @@ const struct af_info af_info_rubberband = { .priv_size = sizeof(struct priv), .priv_defaults = &(const struct priv) { .speed = 1.0, + .pitch = 1.0, .opt_pitch = RubberBandOptionPitchHighConsistency, .opt_transients = RubberBandOptionTransientsMixed, .opt_formant = RubberBandOptionFormantPreserved, @@ -220,6 +244,7 @@ const struct af_info af_info_rubberband = { OPT_CHOICE("channels", opt_channels, 0, ({"apart", RubberBandOptionChannelsApart}, {"together", RubberBandOptionChannelsTogether})), + OPT_DOUBLE("pitch-scale", pitch, M_OPT_RANGE, .min = 0.01, .max = 100), {0} }, }; -- cgit v1.2.3 From f504661852dbd7b8ff28013ffed069de75de1826 Mon Sep 17 00:00:00 2001 From: Hector Martin Date: Tue, 20 Sep 2016 01:28:05 +0900 Subject: af_rubberband: default to channels=together For stereo and typical L/R-first channel arrangements, this avoids undesirable phasing artifacts, especially obvious when speed is changed and then reset. Without this, there is a very audible change in the stereo field even when librubberband is no longer actually making any speed changes. --- audio/filter/af_rubberband.c | 1 + 1 file changed, 1 insertion(+) (limited to 'audio') diff --git a/audio/filter/af_rubberband.c b/audio/filter/af_rubberband.c index 529c252a12..a4deb3d48c 100644 --- a/audio/filter/af_rubberband.c +++ b/audio/filter/af_rubberband.c @@ -214,6 +214,7 @@ const struct af_info af_info_rubberband = { .opt_pitch = RubberBandOptionPitchHighConsistency, .opt_transients = RubberBandOptionTransientsMixed, .opt_formant = RubberBandOptionFormantPreserved, + .opt_channels = RubberBandOptionChannelsTogether, }, .options = (const struct m_option[]) { OPT_CHOICE("transients", opt_transients, 0, -- cgit v1.2.3 From 297f9f1bec3c0e3eca6fbfdd8a346b6c1a5b533e Mon Sep 17 00:00:00 2001 From: Hector Martin Date: Tue, 20 Sep 2016 01:30:55 +0900 Subject: af_pan: fix typo This was in the parser code all along. As far as I can tell, *cp was intended. There is no need to check cp for NULL (nor does it make any sense to do so every time around the loop) for AF_CONTROL_COMMAND. However, s->matrixstr can be NULL, so checking for that separately is in order. --- audio/filter/af_pan.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'audio') diff --git a/audio/filter/af_pan.c b/audio/filter/af_pan.c index c27f4bd07c..de2adf790c 100644 --- a/audio/filter/af_pan.c +++ b/audio/filter/af_pan.c @@ -47,7 +47,7 @@ static void parse_matrix(struct af_instance *af, const char *cp) { af_pan_t *s = af->priv; int j = 0, k = 0, n; - while (cp && k < AF_NCH) { + while (*cp && k < AF_NCH) { sscanf(cp, "%f%n" , &s->level[j][k], &n); MP_VERBOSE(af, "Pan level from channel %i to" " channel %i = %f\n", k, j, s->level[j][k]); @@ -186,7 +186,8 @@ static int af_open(struct af_instance *af) return AF_ERROR; // Read pan values - parse_matrix(af, s->matrixstr); + if