1
0
mirror of https://github.com/mpv-player/mpv synced 2025-02-17 13:17:13 +00:00

command: add better runtime filter toggling method

Basically, see the example in input.rst.

This is better than the "old" vf-toggle method, because it doesn't
require the user to duplicate the filter string in mpv.conf and
input.conf.

Some aspects of this changes are untested, so enjoy your alpha testing.
This commit is contained in:
wm4 2017-03-25 17:07:40 +01:00
parent 29f9e44723
commit 7d424b4ce4
8 changed files with 100 additions and 32 deletions

View File

@ -4,8 +4,8 @@ AUDIO FILTERS
Audio filters allow you to modify the audio stream and its properties. The
syntax is:
``--af=<filter1[=parameter1:parameter2:...],filter2,...>``
Setup a chain of audio filters.
``--af=...``
Setup a chain of audio filters. See ``--vf`` for the syntax.
.. note::
@ -15,27 +15,8 @@ syntax is:
wrapper, which gives you access to most of libavfilter's filters. This
includes all filters that have been ported from MPlayer to libavfilter.
You can also set defaults for each filter. The defaults are applied before the
normal filter parameters.
``--af-defaults=<filter1[=parameter1:parameter2:...],filter2,...>``
Set defaults for each filter.
Audio filters are managed in lists. There are a few commands to manage the
filter list:
``--af-add=<filter1[,filter2,...]>``
Appends the filters given as arguments to the filter list.
``--af-pre=<filter1[,filter2,...]>``
Prepends the filters given as arguments to the filter list.
``--af-del=<index1[,index2,...]>``
Deletes the filters at the given indexes. Index numbers start at 0,
negative numbers address the end of the list (-1 is the last).
``--af-clr``
Completely empties the filter list.
See ``--vf`` group of options for info on how ``--af-defaults``, ``--af-add``,
``--af-pre``, ``--af-del``, ``--af-clr``, and possibly others work.
Available filters are:

View File

@ -452,6 +452,9 @@ Input Commands that are Possibly Subject to Change
(If several filters are passed to the command, this is done for
each filter.)
A special variant is combining this with labels, and using ``@name:!``
as filter entry. This toggles the enable/disable flag.
del
Remove the given filters from the video chain. Unlike in the other
cases, the second parameter is a comma separated list of filter names
@ -487,6 +490,16 @@ Input Commands that are Possibly Subject to Change
- ``b vf set ""`` remove all video filters on ``b``
- ``c vf toggle lavfi=gradfun`` toggle debanding on ``c``
.. admonition:: Example how to toggle disabled filters at runtime
- Add something ``vf-add=@deband:!lavfi=[gradfun]`` to ``mpv.conf``. The
``@deband:`` is the label, and ``deband`` is an arbitrary, user-given
name for this filter entry. The ``!`` before the filter name disables
the filter by default. Everything after this is the normal filter name
and the filter parameters.
- Add ``a vf toggle @deband:!`` to ``input.conf``. This toggles the
"disabled" flag for the filter identified with ``deband``.
``cycle-values ["!reverse"] <property> "<value1>" "<value2>" ...``
Cycle through a list of values. Each invocation of the command will set the
given property to the next value in the list. The command maintains an

View File

@ -5,7 +5,37 @@ Video filters allow you to modify the video stream and its properties. The
syntax is:
``--vf=<filter1[=parameter1:parameter2:...],filter2,...>``
Setup a chain of video filters.
Setup a chain of video filters. This consists on the filter name, and an
option list of parameters after ``=``. The parameters are separated by
``:`` (not ``,``, as that starts a new filter entry).
Before the filter name, a label can be specified with ``@name:``, where
name is an arbitrary user-given name, which identifies the filter. This
is only needed if you want to toggle the filter at runtime.
A ``!`` before the filter name means the filter is enabled by default. It
will be skipped on filter creation. This is also useful for runtime filter
toggling.
See the ``vf`` command (and ``toggle`` sub-command) for further explanations
and examples.
The general filter entry syntax is:
``["@"<label-name>":"] ["!"] <filter-name> [ "=" <filter-parameter-list> ]``
and the ``filter-parameter-list``:
``<filter-parameter> | <filter-parameter> "," <filter-parameter-list>``
and ``filter-parameter``:
``( <param-name> "=" <param-value> ) | <param-value>``
``param-value`` can further be quoted in ``[`` / ``]`` in case the value
contains characters like ``,`` or ``=``. This is used in particular with
the ``lavfi`` filter, which uses a very similar syntax as mpv (MPlayer
historically) to specify filters and their parameters.
You can also set defaults for each filter. The defaults are applied before the
normal filter parameters.

View File

@ -78,6 +78,7 @@ static bool get_desc(struct m_obj_desc *dst, int index)
const struct m_obj_list af_obj_list = {
.get_desc = get_desc,
.description = "audio filters",
.allow_disable_entries = true,
.aliases = {
{"force", "format"},
{0}
@ -545,6 +546,8 @@ int af_init(struct af_stream *s)
// Add all filters in the list (if there are any)
struct m_obj_settings *list = s->opts->af_settings;
for (int i = 0; list && list[i].name; i++) {
if (!list[i].enabled)
continue;
struct af_instance *af =
af_prepend(s, s->last, list[i].name, list[i].attribs);
if (!af) {

View File

@ -2590,6 +2590,7 @@ static void copy_obj_settings_list(const m_option_t *opt, void *dst,
for (n = 0; s[n].name; n++) {
d[n].name = talloc_strdup(NULL, s[n].name);
d[n].label = talloc_strdup(NULL, s[n].label);
d[n].enabled = s[n].enabled;
d[n].attribs = NULL;
copy_str_list(NULL, &(d[n].attribs), &(s[n].attribs));
}
@ -2754,7 +2755,7 @@ exit:
#define NAMECH "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_-"
// Parse one item, e.g. -vf a=b:c:d,e=f:g => parse a=b:c:d into "a" and "b:c:d"
static int parse_obj_settings(struct mp_log *log, struct bstr opt,
static int parse_obj_settings(struct mp_log *log, struct bstr opt, int op,
struct bstr *pstr, const struct m_obj_list *list,
m_obj_settings_t **_ret)
{
@ -2763,6 +2764,7 @@ static int parse_obj_settings(struct mp_log *log, struct bstr opt,
struct m_obj_desc desc;
bstr label = {0};
bool nopos = list->disallow_positional_parameters;
bool enabled = true;
if (bstr_eatstart0(pstr, "@")) {
if (!bstr_split_tok(*pstr, ":", &label, pstr)) {
@ -2771,9 +2773,14 @@ static int parse_obj_settings(struct mp_log *log, struct bstr opt,
}
}
if (list->allow_disable_entries && bstr_eatstart0(pstr, "!"))
enabled = false;
bool has_param = false;
int idx = bstrspn(*pstr, NAMECH);
bstr str = bstr_splice(*pstr, 0, idx);
if (str.len == 0 && !enabled && label.len && op == OP_TOGGLE)
goto done; // "@labelname:!" is the special enable/disable toggle syntax
*pstr = bstr_cut(*pstr, idx);
// video filters use "=", VOs use ":"
if (bstr_eatstart0(pstr, "=") || bstr_eatstart0(pstr, ":"))
@ -2817,9 +2824,11 @@ static int parse_obj_settings(struct mp_log *log, struct bstr opt,
if (!_ret)
return 1;
done: ;
m_obj_settings_t item = {
.name = bstrto0(NULL, str),
.label = bstrdup0(NULL, label),
.enabled = enabled,
.attribs = plist,
};
obj_settings_list_insert_at(_ret, -1, &item);
@ -2964,7 +2973,7 @@ static int parse_obj_settings_list(struct mp_log *log, const m_option_t *opt,
if (op == OP_DEL)
r = parse_obj_settings_del(log, name, &param, dst, mark_del);
if (r == 0) {
r = parse_obj_settings(log, name, &param, ol, dst ? &res : NULL);
r = parse_obj_settings(log, name, op, &param, ol, dst ? &res : NULL);
}
if (r < 0)
return r;
@ -3017,12 +3026,25 @@ static int parse_obj_settings_list(struct mp_log *log, const m_option_t *opt,
talloc_free(res);
} else if (op == OP_TOGGLE) {
for (int n = 0; res && res[n].name; n++) {
int found = obj_settings_find_by_content(list, &res[n]);
if (found < 0) {
obj_settings_list_insert_at(&list, -1, &res[n]);
} else {
obj_settings_list_del_at(&list, found);
if (!res[n].enabled && !res[n].name[0]) {
// Toggle enable/disable special case.
int found =
obj_settings_list_find_by_label0(list, res[n].label);
if (found < 0) {
mp_warn(log, "Option %.*s: Label %s not found\n",
BSTR_P(name), res[n].label);
} else {
list[found].enabled = !list[found].enabled;
}
obj_setting_free(&res[n]);
} else {
int found = obj_settings_find_by_content(list, &res[n]);
if (found < 0) {
obj_settings_list_insert_at(&list, -1, &res[n]);
} else {
obj_settings_list_del_at(&list, found);
obj_setting_free(&res[n]);
}
}
}
talloc_free(res);
@ -3073,6 +3095,8 @@ static char *print_obj_settings_list(const m_option_t *opt, const void *val)
// Assume labels and names don't need escaping
if (entry->label && entry->label[0])
res = talloc_asprintf_append(res, "@%s:", entry->label);
if (!entry->enabled)
res = talloc_strdup_append(res, "!");
res = talloc_strdup_append(res, entry->name);
if (entry->attribs && entry->attribs[0]) {
res = talloc_strdup_append(res, "=");
@ -3111,6 +3135,10 @@ static int set_obj_settings_list(const m_option_t *opt, void *dst,
if (val->format != MPV_FORMAT_STRING)
goto error;
entry->label = talloc_strdup(NULL, val->u.string);
} else if (strcmp(key, "enabled") == 0) {
if (val->format != MPV_FORMAT_FLAG)
goto error;
entry->enabled = val->u.flag;
} else if (strcmp(key, "params") == 0) {
if (val->format != MPV_FORMAT_NODE_MAP)
goto error;
@ -3176,6 +3204,9 @@ static int get_obj_settings_list(const m_option_t *opt, void *ta_parent,
add_map_string(nentry, "name", entry->name);
if (entry->label && entry->label[0])
add_map_string(nentry, "label", entry->label);
struct mpv_node *enabled = add_map_entry(nentry, "enabled");
enabled->format = MPV_FORMAT_FLAG;
enabled->u.flag = entry->enabled;
struct mpv_node *params = add_map_entry(nentry, "params");
params->format = MPV_FORMAT_NODE_MAP;
params->u.list = talloc_zero(ta_parent, struct mpv_node_list);

View File

@ -146,6 +146,8 @@ struct m_obj_list {
// Allow unknown entries, for which a dummy entry is inserted, and whose
// options are skipped and ignored.
bool allow_unknown_entries;
// Allow syntax for disabling entries.
bool allow_disable_entries;
// This helps with confusing error messages if unknown flag options are used.
bool disallow_positional_parameters;
// Each sub-item is backed by global options (for AOs and VOs).
@ -162,6 +164,8 @@ typedef struct m_obj_settings {
char *name;
// Optional user-defined name.
char *label;
// User enable flag.
bool enabled;
// NULL terminated array of parameter/value pairs.
char **attribs;
} m_obj_settings_t;

View File

@ -3449,7 +3449,10 @@ static char *print_obj_osd_list(struct m_obj_settings *list)
list[n].attribs[i],
list[n].attribs[i + 1]);
}
res = talloc_asprintf_append(res, "]\n");
res = talloc_asprintf_append(res, "]");
if (!list[n].enabled)
res = talloc_strdup_append(res, " (disabled)");
res = talloc_strdup_append(res, "\n");
}
if (!res)
res = talloc_strdup(NULL, "(empty)");

View File

@ -128,6 +128,7 @@ static bool get_desc(struct m_obj_desc *dst, int index)
const struct m_obj_list vf_obj_list = {
.get_desc = get_desc,
.description = "video filters",
.allow_disable_entries = true,
};
// Try the cmd on each filter (starting with the first), and stop at the first
@ -322,6 +323,8 @@ struct vf_instance *vf_append_filter(struct vf_chain *c, const char *name,
int vf_append_filter_list(struct vf_chain *c, struct m_obj_settings *list)
{
for (int n = 0; list && list[n].name; n++) {
if (!list[n].enabled)
continue;
struct vf_instance *vf =
vf_append_filter(c, list[n].name, list[n].attribs);
if (vf) {