diff options
-rw-r--r-- | DOCS/man/en/changes.rst | 2 | ||||
-rw-r--r-- | DOCS/man/en/input.rst | 22 | ||||
-rw-r--r-- | audio/decode/dec_audio.c | 17 | ||||
-rw-r--r-- | audio/decode/dec_audio.h | 2 | ||||
-rw-r--r-- | audio/filter/af.c | 195 | ||||
-rw-r--r-- | audio/filter/af.h | 44 | ||||
-rw-r--r-- | audio/mixer.c | 4 | ||||
-rw-r--r-- | core/command.c | 101 | ||||
-rw-r--r-- | core/input/input.c | 6 | ||||
-rw-r--r-- | core/input/input.h | 6 | ||||
-rw-r--r-- | core/mp_core.h | 1 | ||||
-rw-r--r-- | core/mplayer.c | 85 | ||||
-rw-r--r-- | core/options.c | 4 | ||||
-rw-r--r-- | core/options.h | 1 |
14 files changed, 210 insertions, 280 deletions
diff --git a/DOCS/man/en/changes.rst b/DOCS/man/en/changes.rst index 26c9e9d9d2..5ff532ddc9 100644 --- a/DOCS/man/en/changes.rst +++ b/DOCS/man/en/changes.rst @@ -186,6 +186,8 @@ input.conf and Slave Commands +--------------------------------+----------------------------------------+ | ``show_chapters`` | ``show_text ${chapter-list}`` | +--------------------------------+----------------------------------------+ + | ``af_switch``, ``af_add``, ... | ``af [set|add|...]`` | + +--------------------------------+----------------------------------------+ Other ~~~~~ diff --git a/DOCS/man/en/input.rst b/DOCS/man/en/input.rst index fd1aad9c58..804d37d976 100644 --- a/DOCS/man/en/input.rst +++ b/DOCS/man/en/input.rst @@ -253,20 +253,10 @@ List of Input Commands Input Commands that are Possibly Subject to Change -------------------------------------------------- -``af_switch "filter1=params,filter2,..."`` - Replace the current filter chain with the given list. +``af set|add|toggle|del|clr "filter1=params,filter2,..."`` + Change audio filter chain. See ``vf`` command. -``af_add "filter1=params,filter2,..."`` - Add the given list of audio filters to the audio filter chain. - -``af_del "filter1,filter2,..."`` - Remove the given list of audio filters. - -``af_clr`` - Remove all audio filters. (Conversion filters will be re-added - automatically if needed.) - -``vf set|add|toggle|del "filter1=params,filter2,..."`` +``vf set|add|toggle|del|clr "filter1=params,filter2,..."`` Change video filter chain. The first argument decides what happens: @@ -290,6 +280,10 @@ Input Commands that are Possibly Subject to Change indexes start from the last filter, and ``-1`` denotes the last filter. + clr + Remove all filters. Note that like the other sub-commands, this does + not control automatically inserted filters. + You can assign labels to filter by prefixing them with ``@name:`` (where ``name`` is a user-chosen arbitrary identifier). Labels can be used to refer to filters by name in all of the filter chain modification commands. @@ -322,7 +316,7 @@ Undocumented commands: ``tv_start_scan``, ``tv_step_channel``, ``tv_step_norm``, ``tv_step_freq``, ``tv_set_norm``, ``dvb_set_channel``, ``radio_step_channel``, ``radio_set_channel``, ``radio_set_freq``, ``radio_step_freq`` (all of these should be replaced by properties), ``stop`` (questionable use), ``get_property`` -(?), ``af_cmdline``, ``vo_cmdline`` (experimental). +(?), ``vo_cmdline`` (experimental). Input Command Prefixes ---------------------- diff --git a/audio/decode/dec_audio.c b/audio/decode/dec_audio.c index 48a3512ee6..a73027e224 100644 --- a/audio/decode/dec_audio.c +++ b/audio/decode/dec_audio.c @@ -54,8 +54,6 @@ static const struct ad_functions * const ad_drivers[] = { NULL }; -struct af_cfg af_cfg = {0}; // Configuration for audio filters - static int init_audio_codec(sh_audio_t *sh_audio, const char *decoder) { assert(!sh_audio->initialized); @@ -180,7 +178,6 @@ void uninit_audio(sh_audio_t *sh_audio) { if (sh_audio->afilter) { mp_msg(MSGT_DECAUDIO, MSGL_V, "Uninit audio filters...\n"); - af_uninit(sh_audio->afilter); af_destroy(sh_audio->afilter); sh_audio->afilter = NULL; } @@ -199,9 +196,10 @@ int init_audio_filters(sh_audio_t *sh_audio, int in_samplerate, int *out_samplerate, struct mp_chmap *out_channels, int *out_format) { + if (!sh_audio->afilter) + sh_audio->afilter = af_new(sh_audio->opts); struct af_stream *afs = sh_audio->afilter; - if (!afs) - afs = af_new(sh_audio->opts); + // input format: same as codec's output format: afs->input.rate = in_samplerate; mp_audio_set_channels(&afs->input, &sh_audio->channels); @@ -212,9 +210,6 @@ int init_audio_filters(sh_audio_t *sh_audio, int in_samplerate, mp_audio_set_channels(&afs->output, out_channels); mp_audio_set_format(&afs->output, *out_format); - // filter config: - memcpy(&afs->cfg, &af_cfg, sizeof(struct af_cfg)); - char *s_from = mp_audio_config_to_str(&afs->input); char *s_to = mp_audio_config_to_str(&afs->output); mp_tmsg(MSGT_DECAUDIO, MSGL_V, @@ -223,9 +218,9 @@ int init_audio_filters(sh_audio_t *sh_audio, int in_samplerate, talloc_free(s_to); // let's autoprobe it! - if (0 != af_init(afs)) { - sh_audio->afilter = NULL; + if (af_init(afs) != 0) { af_destroy(afs); + sh_audio->afilter = NULL; return 0; // failed :( } @@ -233,8 +228,6 @@ int init_audio_filters(sh_audio_t *sh_audio, int in_samplerate, *out_channels = afs->output.channels; *out_format = afs->output.format; - // ok! - sh_audio->afilter = (void *) afs; return 1; } diff --git a/audio/decode/dec_audio.h b/audio/decode/dec_audio.h index 7a044e2040..b46f4282fb 100644 --- a/audio/decode/dec_audio.h +++ b/audio/decode/dec_audio.h @@ -37,6 +37,4 @@ int init_audio_filters(sh_audio_t *sh_audio, int in_samplerate, int *out_samplerate, struct mp_chmap *out_channels, int *out_format); -extern struct af_cfg af_cfg; - #endif /* MPLAYER_DEC_AUDIO_H */ diff --git a/audio/filter/af.c b/audio/filter/af.c index 7e2bdb8c18..26ca78c24f 100644 --- a/audio/filter/af.c +++ b/audio/filter/af.c @@ -22,6 +22,9 @@ #include <string.h> #include <assert.h> +#include "core/m_option.h" +#include "core/m_config.h" + #include "af.h" // Static list of filters @@ -87,6 +90,27 @@ static struct af_info* filter_list[] = { NULL }; +static bool get_desc(struct m_obj_desc *dst, int index) +{ + if (index >= MP_ARRAY_SIZE(filter_list) - 1) + return false; + const struct af_info *af = filter_list[index]; + *dst = (struct m_obj_desc) { + .name = af->name, + .description = af->info, + .priv_size = af->priv_size, + .priv_defaults = af->priv_defaults, + .options = af->options, + .p = af, + }; + return true; +} + +const struct m_obj_list af_obj_list = { + .get_desc = get_desc, + .description = "audio filters", +}; + static bool af_config_equals(struct mp_audio *a, struct mp_audio *b) { return a->format == b->format @@ -139,90 +163,58 @@ static struct mp_audio *dummy_play(struct af_instance* af, struct mp_audio* data return data; } -/* Find a filter in the static list of filters using it's name. This - function is used internally */ -static struct af_info *af_find(char *name) -{ - int i = 0; - while (filter_list[i]) { - if (!strcmp(filter_list[i]->name, name)) - return filter_list[i]; - i++; - } - mp_msg(MSGT_AFILTER, MSGL_ERR, "Couldn't find audio filter '%s'\n", name); - return NULL; -} - -/* Find filter in the dynamic filter list using it's name This - function is used for finding already initialized filters */ -struct af_instance *af_get(struct af_stream *s, char *name) -{ - struct af_instance *af = s->first; - // Find the filter - while (af != NULL) { - if (!strcmp(af->info->name, name)) - return af; - af = af->next; - } - return NULL; -} - /* Function for creating a new filter of type name.The name may contain the commandline parameters for the filter */ -static struct af_instance *af_create(struct af_stream *s, - const char *name_with_cmd) +static struct af_instance *af_create(struct af_stream *s, char *name, + char **args) { - char *name = strdup(name_with_cmd); - char *cmdline = name; - - // Allocate space for the new filter and reset all pointers - struct af_instance *new = malloc(sizeof(struct af_instance)); - if (!name || !new) { - mp_msg(MSGT_AFILTER, MSGL_ERR, "[libaf] Could not allocate memory\n"); - goto err_out; - } - memset(new, 0, sizeof(struct af_instance)); - - // Check for commandline parameters - char *skip = strstr(cmdline, "="); - if (skip) { - *skip = '\0'; // for name - cmdline = skip + 1; - } else { - cmdline = NULL; + struct m_obj_desc desc; + if (!m_obj_list_find(&desc, &af_obj_list, bstr0(name))) { + mp_tmsg(MSGT_VFILTER, MSGL_ERR, + "Couldn't find audio filter '%s'.\n", name); + return NULL; } - - // Find filter from name - if (NULL == (new->info = af_find(name))) - goto err_out; - + const struct af_info *info = desc.p; /* Make sure that the filter is not already in the list if it is non-reentrant */ - if (new->info->flags & AF_FLAGS_NOT_REENTRANT) { - if (af_get(s, name)) { - mp_msg(MSGT_AFILTER, MSGL_ERR, "[libaf] There can only be one " - "instance of the filter '%s' in each stream\n", name); - goto err_out; + if (info->flags & AF_FLAGS_NOT_REENTRANT) { + for (struct af_instance *cur = s->first; cur; cur = cur->next) { + if (cur->info == info) { + mp_msg(MSGT_AFILTER, MSGL_ERR, "[libaf] There can only be one " + "instance of the filter '%s' in each stream\n", name); + return NULL; + } } } mp_msg(MSGT_AFILTER, MSGL_V, "[libaf] Adding filter %s \n", name); + struct af_instance *af = talloc_zero(NULL, struct af_instance); + *af = (struct af_instance) { + .info = info, + .mul = 1, + }; + struct m_config *config = m_config_from_obj_desc(af, &desc); + if (m_config_initialize_obj(config, &desc, &af->priv, &args) < 0) + goto error; + // Initialize the new filter - if (AF_OK == new->info->open(new)) { - if (cmdline) { - if (AF_ERROR >= new->control(new, AF_CONTROL_COMMAND_LINE, cmdline)) - goto err_out; - } - free(name); - return new; + if (af->info->open(af) != AF_OK) + goto error; + if (args && af->control) { + // Single option string for old filters + char *s = (char *)args; // m_config_initialize_obj did this + assert(!af->priv); + if (af->control(af, AF_CONTROL_COMMAND_LINE, s) <= AF_ERROR) + goto error; } -err_out: - free(new); + return af; + +error: mp_msg(MSGT_AFILTER, MSGL_ERR, "[libaf] Couldn't create or open audio filter '%s'\n", name); - free(name); + talloc_free(af); return NULL; } @@ -231,14 +223,14 @@ err_out: value is the new filter */ static struct af_instance *af_prepend(struct af_stream *s, struct af_instance *af, - const char *name) + char *name, char **args) { if (!af) af = s->last; if (af == s->first) af = s->first->next; // Create the new filter and make sure it is OK - struct af_instance *new = af_create(s, name); + struct af_instance *new = af_create(s, name, args); if (!new) return NULL; // Update pointers @@ -254,14 +246,14 @@ static struct af_instance *af_prepend(struct af_stream *s, value is the new filter */ static struct af_instance *af_append(struct af_stream *s, struct af_instance *af, - const char *name) + char *name, char **args) { if (!af) af = s->first; if (af == s->last) af = s->last->prev; // Create the new filter and make sure it is OK - struct af_instance *new = af_create(s, name); + struct af_instance *new = af_create(s, name, args); if (!new) return NULL; // Update pointers @@ -273,7 +265,7 @@ static struct af_instance *af_append(struct af_stream *s, } // Uninit and remove the filter "af" -void af_remove(struct af_stream *s, struct af_instance *af) +static void af_remove(struct af_stream *s, struct af_instance *af) { if (!af) return; @@ -293,7 +285,7 @@ void af_remove(struct af_stream *s, struct af_instance *af) af->next->prev = af->prev; af->uninit(af); - free(af); + talloc_free(af); } static void remove_auto_inserted_filters(struct af_stream *s) @@ -341,12 +333,12 @@ static int af_count_filters(struct af_stream *s) return count; } -static const char *af_find_conversion_filter(int srcfmt, int dstfmt) +static char *af_find_conversion_filter(int srcfmt, int dstfmt) { for (int n = 0; filter_list[n]; n++) { struct af_info *af = filter_list[n]; if (af->test_conversion && af->test_conversion(srcfmt, dstfmt)) - return af->name; + return (char *)af->name; } return NULL; } @@ -376,10 +368,10 @@ static int af_fix_format_conversion(struct af_stream *s, *p_af = prev; return AF_OK; } - const char *filter = af_find_conversion_filter(actual.format, in.format); + char *filter = af_find_conversion_filter(actual.format, in.format); if (!filter) return AF_ERROR; - struct af_instance *new = af_prepend(s, af, filter); + struct af_instance *new = af_prepend(s, af, filter, NULL); if (new == NULL) return AF_ERROR; new->auto_inserted = true; @@ -403,8 +395,8 @@ static int af_fix_channels(struct af_stream *s, struct af_instance **p_af, *p_af = prev; return AF_OK; } - const char *filter = "lavrresample"; - struct af_instance *new = af_prepend(s, af, filter); + char *filter = "lavrresample"; + struct af_instance *new = af_prepend(s, af, filter, NULL); if (new == NULL) return AF_ERROR; new->auto_inserted = true; @@ -427,8 +419,8 @@ static int af_fix_rate(struct af_stream *s, struct af_instance **p_af, *p_af = prev; return AF_OK; } - const char *filter = "lavrresample"; - struct af_instance *new = af_prepend(s, af, filter); + char *filter = "lavrresample"; + struct af_instance *new = af_prepend(s, af, filter, NULL); if (new == NULL) return AF_ERROR; new->auto_inserted = true; @@ -438,6 +430,7 @@ static int af_fix_rate(struct af_stream *s, struct af_instance **p_af, return AF_OK; } +// Return AF_OK on success or AF_ERROR on failure. // Warning: // A failed af_reinit() leaves the audio chain behind in a useless, broken // state (for example, format filters that were tentatively inserted stay @@ -445,7 +438,7 @@ static int af_fix_rate(struct af_stream *s, struct af_instance **p_af, // In that case, you should always rebuild the filter chain, or abort. // Also, note that for complete reinit, fixup_output_format() may have to be // called after this function. -int af_reinit(struct af_stream *s) +static int af_reinit(struct af_stream *s) { // Start with the second filter, as the first filter is the special input // filter which needs no initialization. @@ -543,6 +536,7 @@ struct af_stream *af_new(struct MPOpts *opts) }; s->first->next = s->last; s->last->prev = s->first; + s->opts = opts; return s; } @@ -578,8 +572,6 @@ static int fixup_output_format(struct af_stream *s) The return value is 0 if success and -1 if failure */ int af_init(struct af_stream *s) { - int i = 0; - // Sanity check if (!s) return -1; @@ -591,11 +583,10 @@ int af_init(struct af_stream *s) // Check if this is the first call if (s->first->next == s->last) { // Add all filters in the list (if there are any) - if (s->cfg.list) { - while (s->cfg.list[i]) { - if (!af_prepend(s, s->last, s->cfg.list[i++])) - return -1; - } + struct m_obj_settings *list = s->opts->af_settings; + for (int i = 0; list && list[i].name; i++) { + if (!af_prepend(s, s->last, list[i].name, list[i].attribs)) + return -1; } } @@ -621,7 +612,7 @@ int af_init(struct af_stream *s) to the stream s. The filter will be inserted somewhere nice in the list of filters. The return value is a pointer to the new filter, If the filter couldn't be added the return value is NULL. */ -struct af_instance *af_add(struct af_stream *s, char *name) +struct af_instance *af_add(struct af_stream *s, char *name, char **args) { struct af_instance *new; // Sanity check @@ -629,9 +620,9 @@ struct af_instance *af_add(struct af_stream *s, char *name) return NULL; // Insert the filter somewhere nice if (af_is_conversion_filter(s->first->next)) - new = af_append(s, s->first->next, name); + new = af_append(s, s->first->next, name, args); else - new = af_prepend(s, s->first->next, name); + new = af_prepend(s, s->first->next, name, args); if (!new) return NULL; @@ -729,21 +720,3 @@ struct af_instance *af_control_any_rev(struct af_stream *s, int cmd, void *arg) } return NULL; } - -void af_help(void) -{ - int i = 0; - mp_msg(MSGT_AFILTER, MSGL_INFO, "Available audio filters:\n"); - while (filter_list[i]) { - if (filter_list[i]->comment && filter_list[i]->comment[0]) { - mp_msg(MSGT_AFILTER, MSGL_INFO, " %-15s: %s (%s)\n", - filter_list[i]->name, filter_list[i]->info, - filter_list[i]->comment); - } else { - mp_msg(MSGT_AFILTER, MSGL_INFO, " %-15s: %s\n", - filter_list[i]->name, - filter_list[i]->info); - } - i++; - } -} diff --git a/audio/filter/af.h b/audio/filter/af.h index 4ccc70792f..df4e03b49a 100644 --- a/audio/filter/af.h +++ b/audio/filter/af.h @@ -50,15 +50,19 @@ struct af_info { const int flags; int (*open)(struct af_instance *vf); bool (*test_conversion)(int src_format, int dst_format); + int priv_size; + const void *priv_defaults; + const struct m_option *options; }; // Linked list of audio filters struct af_instance { - struct af_info *info; + const struct af_info *info; int (*control)(struct af_instance *af, int cmd, void *arg); void (*uninit)(struct af_instance *af); struct mp_audio * (*play)(struct af_instance *af, struct mp_audio *data); - void *setup; // setup data for this specific instance and filter + void *setup; // old field for priv structs + void *priv; struct mp_audio *data; // configuration for outgoing data stream struct af_instance *next; struct af_instance *prev; @@ -69,12 +73,6 @@ struct af_instance { bool auto_inserted; // inserted by af.c, such as conversion filters }; -// Configuration switches -struct af_cfg { - char **list; /* list of names of filters that are added to filter - list during first initialization of stream */ -}; - // Current audio stream struct af_stream { // The first and last filter in the list @@ -86,8 +84,7 @@ struct af_stream { struct mp_audio input; struct mp_audio output; struct mp_audio filter_output; - // Configuration for this stream - struct af_cfg cfg; + struct MPOpts *opts; }; @@ -139,13 +136,6 @@ int af_init(struct af_stream *s); void af_uninit(struct af_stream *s); /** - * \brief Reinit the filter list from the given filter on downwards - * See af.c. - * \return AF_OK on success or AF_ERROR on failure - */ -int af_reinit(struct af_stream *s); - -/** * \brief This function adds the filter "name" to the stream s. * \param name name of filter to add * \return pointer to the new filter, NULL if insert failed @@ -154,22 +144,7 @@ int af_reinit(struct af_stream *s); * list of filters (i.e. at the beginning unless the * first filter is the format filter (why??). */ -struct af_instance *af_add(struct af_stream *s, char *name); - -/** - * \brief Uninit and remove the filter "af" - * \param af filter to remove - */ -void af_remove(struct af_stream *s, struct af_instance *af); - -/** - * \brief find filter in chain by name - * \param name name of the filter to find - * \return first filter with right name or NULL if not found - * - * This function is used for finding already initialized filters - */ -struct af_instance *af_get(struct af_stream *s, char *name); +struct af_instance *af_add(struct af_stream *s, char *name, char **args); /** * \brief filter data chunk through the filters in the list @@ -282,9 +257,6 @@ float af_softclip(float a); /** \} */ // end of af_filter group, but more functions of this group below -/** Print a list of all available audio filters */ -void af_help(void); - /** Memory reallocation macro: if a local buffer is used (i.e. if the filter doesn't operate on the incoming buffer this macro must be called to ensure the buffer is big enough. diff --git a/audio/mixer.c b/audio/mixer.c index 0f1a7871d6..7ccfaa4639 100644 --- a/audio/mixer.c +++ b/audio/mixer.c @@ -113,7 +113,7 @@ static void setvolume_internal(mixer_t *mixer, float l, float r) { mp_tmsg(MSGT_GLOBAL, mixer->softvol ? MSGL_V : MSGL_WARN, "[Mixer] No hardware mixing, inserting volume filter.\n"); - if (!(af_add(mixer->afilter, "volume") + if (!(af_add(mixer->afilter, "volume", NULL) && af_control_any_rev(mixer->afilter, AF_CONTROL_VOLUME_LEVEL | AF_CONTROL_SET, db_vals))) @@ -220,7 +220,7 @@ void mixer_setbalance(mixer_t *mixer, float val) if (val == 0 || mixer->ao->channels.num < 2) return; - if (!(af_pan_balance = af_add(mixer->afilter, "pan"))) { + if (!(af_pan_balance = af_add(mixer->afilter, "pan", NULL))) { mp_tmsg(MSGT_GLOBAL, MSGL_ERR, "[Mixer] No balance control available.\n"); return; diff --git a/core/command.c b/core/command.c index 4cf508d5e7..32479784e9 100644 --- a/core/command.c +++ b/core/command.c @@ -1914,43 +1914,72 @@ static const char *property_error_string(int error_value) return "UNKNOWN"; } -static void change_video_filters(MPContext *mpctx, const char *cmd, - const char *arg) +static bool reinit_filters(MPContext *mpctx, enum stream_type mediatype) +{ + switch (mediatype) { + case STREAM_VIDEO: + return reinit_video_filters(mpctx) >= 0; + case STREAM_AUDIO: + return reinit_audio_filters(mpctx) >= 0; + } + return false; +} + +static void change_filters(MPContext *mpctx, enum stream_type mediatype, + const char *cmd, const char *arg) { struct MPOpts *opts = &mpctx->opts; struct m_config *conf = mpctx->mconfig; - struct m_obj_settings *old_vf_settings = NULL; + struct m_obj_settings *old_settings = NULL; bool success = false; bool need_refresh = false; + const char *option; + struct m_obj_settings **list; + + switch (mediatype) { + case STREAM_VIDEO: + option = "vf"; + list = &opts->vf_settings; + break; + case STREAM_AUDIO: + option = "af"; + list = &opts->af_settings; + break; + } // The option parser is used to modify the filter list itself. char optname[20]; - snprintf(optname, sizeof(optname), "vf-%s", cmd); + snprintf(optname, sizeof(optname), "%s-%s", option, cmd); const struct m_option *type = m_config_get_option(conf, bstr0(optname)); // Backup old settings, in case it fails - m_option_copy(type, &old_vf_settings, &opts->vf_settings); + m_option_copy(type, &old_settings, list); if (m_config_set_option0(conf, optname, arg) >= 0) { need_refresh = true; - success = reinit_video_filters(mpctx) >= 0; + success = reinit_filters(mpctx, mediatype); } if (!success) { - m_option_copy(type, &opts->vf_settings, &old_vf_settings); + m_option_copy(type, list, &old_settings); if (need_refresh) - reinit_video_filters(mpctx); + reinit_filters(mpctx, mediatype); } - m_option_free(type, &old_vf_settings); + m_option_free(type, &old_settings); - if (need_refresh) + if (need_refresh && mediatype == STREAM_VIDEO) mp_force_video_refresh(mpctx); } +static void change_video_filters(MPContext *mpctx, const char *cmd, + const char *arg) +{ + change_filters(mpctx, STREAM_VIDEO, cmd, arg); +} + void run_command(MPContext *mpctx, mp_cmd_t *cmd) { struct MPOpts *opts = &mpctx->opts; - sh_audio_t *const sh_audio = mpctx->sh_audio; sh_video_t *const sh_video = mpctx->sh_video; int osd_duration = opts->osd_duration; bool auto_osd = cmd->on_osd == MP_ON_OSD_AUTO; @@ -2467,54 +2496,10 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd) } break; - case MP_CMD_AF_SWITCH: - if (sh_audio) { - af_uninit(mpctx->mixer.afilter); - af_init(mpctx->mixer.afilter); - } - /* fallthrough */ - case MP_CMD_AF_ADD: - case MP_CMD_AF_DEL: { - if (!sh_audio) - break; - char *af_args = strdup(cmd->args[0].v.s); - bstr af_commands = bstr0(af_args); - struct af_instance *af; - while (af_commands.len) { - bstr af_command; - bstr_split_tok(af_commands, ",", &af_command, &af_commands); - char *af_command0 = bstrdup0(NULL, af_command); - if (cmd->id == MP_CMD_AF_DEL) { - af = af_get(mpctx->mixer.afilter, af_command0); - if (af != NULL) - af_remove(mpctx->mixer.afilter, af); - } else - af_add(mpctx->mixer.afilter, af_command0); - talloc_free(af_command0); - } - reinit_audio_chain(mpctx); - free(af_args); - break; - } - case MP_CMD_AF_CLR: - if (!sh_audio) - break; - af_uninit(mpctx->mixer.afilter); - af_init(mpctx->mixer.afilter); - reinit_audio_chain(mpctx); - break; - case MP_CMD_AF_CMDLINE: - if (sh_audio) { - struct af_instance *af = af_get(sh_audio->afilter, cmd->args[0].v.s); - if (!af) { - mp_msg(MSGT_CPLAYER, MSGL_WARN, - "Filter '%s' not found in chain.\n", cmd->args[0].v.s); - break; - } - af->control(af, AF_CONTROL_COMMAND_LINE, cmd->args[1].v.s); - af_reinit(sh_audio->afilter); - } + case MP_CMD_AF: + change_filters(mpctx, STREAM_AUDIO, cmd->args[0].v.s, cmd->args[1].v.s); break; + case MP_CMD_VF: change_video_filters(mpctx, cmd->args[0].v.s, cmd->args[1].v.s); break; diff --git a/core/input/input.c b/core/input/input.c index 66d78b48c6..467f6d6299 100644 --- a/core/input/input.c +++ b/core/input/input.c @@ -210,11 +210,7 @@ static const mp_cmd_t mp_cmds[] = { }}, { MP_CMD_DISABLE_INPUT_SECTION, "disable_section", { ARG_STRING } }, - { MP_CMD_AF_SWITCH, "af_switch", { ARG_STRING } }, - { MP_CMD_AF_ADD, "af_add", { ARG_STRING } }, - { MP_CMD_AF_DEL, "af_del", { ARG_STRING } }, - { MP_CMD_AF_CLR, "af_clr", }, - { MP_CMD_AF_CMDLINE, "af_cmdline", { ARG_STRING, ARG_STRING } }, + { MP_CMD_AF, "af", { ARG_STRING, ARG_STRING } }, { MP_CMD_VF, "vf", { ARG_STRING, ARG_STRING } }, diff --git a/core/input/input.h b/core/input/input.h index 1a0f2529ce..f4f5621e9f 100644 --- a/core/input/input.h +++ b/core/input/input.h @@ -77,11 +77,7 @@ enum mp_command_type { MP_CMD_DVB_SET_CHANNEL = 5101, /// Audio Filter commands - MP_CMD_AF_SWITCH, - MP_CMD_AF_ADD, - MP_CMD_AF_DEL, - MP_CMD_AF_CLR, - MP_CMD_AF_CMDLINE, + MP_CMD_AF, /// Video filter commands MP_CMD_VF, diff --git a/core/mp_core.h b/core/mp_core.h index f7e6786b60..6bbe18c71e 100644 --- a/core/mp_core.h +++ b/core/mp_core.h @@ -296,6 +296,7 @@ double playing_audio_pts(struct MPContext *mpctx); struct track *mp_add_subtitles(struct MPContext *mpctx, char *filename, int noerr); int reinit_video_chain(struct MPContext *mpctx); int reinit_video_filters(struct MPContext *mpctx); +int reinit_audio_filters(struct MPContext *mpctx); void pause_player(struct MPContext *mpctx); void unpause_player(struct MPContext *mpctx); void add_step_frame(struct MPContext *mpctx, int dir); diff --git a/core/mplayer.c b/core/mplayer.c index e54b55444f..d9c03dace5 100644 --- a/core/mplayer.c +++ b/core/mplayer.c @@ -1185,11 +1185,6 @@ static int build_afilter_chain(struct MPContext *mpctx) struct ao *ao = mpctx->ao; struct MPOpts *opts = &mpctx->opts; int new_srate; - int result; - if (!sh_audio) { - mpctx->mixer.afilter = NULL; - return 0; - } if (af_control_any_rev(sh_audio->afilter, AF_CONTROL_PLAYBACK_SPEED | AF_CONTROL_SET, &opts->playback_speed)) @@ -1205,10 +1200,8 @@ static int build_afilter_chain(struct MPContext *mpctx) opts->playback_speed = (float)new_srate / sh_audio->samplerate; } } - result = init_audio_filters(sh_audio, new_srate, - &ao->samplerate, &ao->channels, &ao->format); - mpctx->mixer.afilter = sh_audio->afilter; - return result; + return init_audio_filters(sh_audio, new_srate, + &ao->samplerate, &ao->channels, &ao->format); } @@ -1572,6 +1565,51 @@ static void update_osd_msg(struct MPContext *mpctx) } } +static int recreate_audio_filters(struct MPContext *mpctx) +{ + struct MPOpts *opts = &mpctx->opts; + assert(mpctx->sh_audio); + + // init audio filters: + if (!build_afilter_chain(mpctx)) { + mp_tmsg(MSGT_CPLAYER, MSGL_ERR, + "Couldn't find matching filter/ao format!\n"); + return -1; + } + + mpctx->mixer.afilter = mpctx->sh_audio->afilter; + mpctx->mixer.volstep = opts->volstep; + mpctx->mixer.softvol = opts->softvol; + mpctx->mixer.softvol_max = opts->softvol_max; + mixer_reinit(&mpctx->mixer, mpctx->ao); + if (!(mpctx->initialized_flags & INITIALIZED_VOL)) { + if (opts->mixer_init_volume >= 0) { + mixer_setvolume(&mpctx->mixer, opts->mixer_init_volume, + opts->mixer_init_volume); + } + if (opts->mixer_init_mute >= 0) + mixer_setmute(&mpctx->mixer, opts->mixer_init_mute); + mpctx->initialized_flags |= INITIALIZED_VOL; + } + + return 0; +} + +int reinit_audio_filters(struct MPContext *mpctx) +{ + struct sh_audio *sh_audio = mpctx->sh_audio; + if (!sh_audio) + return -2; + + af_uninit(mpctx->sh_audio->afilter); + if (af_init(mpctx->sh_audio->afilter) < 0) + return -1; + if (recreate_audio_filters(mpctx) < 0) + return -1; + + return 0; +} + void reinit_audio_chain(struct MPContext *mpctx) { struct MPOpts *opts = &mpctx->opts; @@ -1603,7 +1641,9 @@ void reinit_audio_chain(struct MPContext *mpctx) } |