summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/en/changes.rst2
-rw-r--r--DOCS/man/en/input.rst22
-rw-r--r--audio/decode/dec_audio.c17
-rw-r--r--audio/decode/dec_audio.h2
-rw-r--r--audio/filter/af.c195
-rw-r--r--audio/filter/af.h44
-rw-r--r--audio/mixer.c4
-rw-r--r--core/command.c101
-rw-r--r--core/input/input.c6
-rw-r--r--core/input/input.h6
-rw-r--r--core/mp_core.h1
-rw-r--r--core/mplayer.c85
-rw-r--r--core/options.c4
-rw-r--r--core/options.h1
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)
}
}
- // first init to detect best values
+ // Determine what the filter chain outputs. build_afilter_chain() also
+ // needs this for testing whether playback speed is changed by resampling
+ // or using a special filter.
if (!init_audio_filters(mpctx->sh_audio, // preliminary init
// input:
mpctx->sh_audio->samplerate,
@@ -1638,25 +1678,9 @@ void reinit_audio_chain(struct MPContext *mpctx)
ao->driver->info->comment);
}
- // init audio filters:
- if (!build_afilter_chain(mpctx)) {
- mp_tmsg(MSGT_CPLAYER, MSGL_ERR,
- "Couldn't find matching filter/ao format!\n");
+ if (recreate_audio_filters(mpctx) < 0)
goto init_error;
- }
- 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;
- }
+
mpctx->syncing_audio = true;
return;
@@ -4512,11 +4536,6 @@ static bool handle_help_options(struct MPContext *mpctx)
talloc_free(list);
opt_exit = 1;
}
- if (af_cfg.list && strcmp(af_cfg.list[0], "help") == 0) {
- af_help();
- mp_msg(MSGT_CPLAYER, MSGL_INFO, "\n");
- opt_exit = 1;
- }
#ifdef CONFIG_X11
if (opts->vo.fstype_list && strcmp(opts->vo.fstype_list[0], "help") == 0) {
fstype_help();
diff --git a/core/options.c b/core/options.c
index cce36b90bb..03acdc570b 100644
--- a/core/options.c
+++ b/core/options.c
@@ -182,6 +182,7 @@ extern char *dvd_device, *cdrom_device;
extern double mf_fps;
extern char * mf_type;
extern const struct m_obj_list vf_obj_list;
+extern const struct m_obj_list af_obj_list;
extern const struct m_obj_list vo_obj_list;
extern const struct m_obj_list ao_obj_list;
@@ -436,8 +437,7 @@ const m_option_t mp_opts[] = {
// ------------------------- codec/vfilter options --------------------
- {"af*", &af_cfg.list, CONF_TYPE_STRING_LIST, 0, 0, 0, NULL},
-
+ OPT_SETTINGSLIST("af*", af_settings, 0, &af_obj_list),
OPT_SETTINGSLIST("vf*", vf_settings, 0, &vf_obj_list),
OPT_STRING("ad", audio_decoders, 0),
diff --git a/core/options.h b/core/options.h
index e7f04b548c..fcb8002a42 100644
--- a/core/options.h
+++ b/core/options.h
@@ -162,6 +162,7 @@ typedef struct MPOpts {
int dtshd;
float playback_speed;
struct m_obj_settings *vf_settings;
+ struct m_obj_settings *af_settings;
float movie_aspect;
int flip;
int field_dominance;