summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-05-22 23:19:57 +0200
committerwm4 <wm4@nowhere>2013-05-23 01:02:24 +0200
commit3d87ca6b5ef1a25438cf05c685817a9b2d8de19e (patch)
tree95b72f87a72037ff75d452396db695b84efd48f0 /core
parentb2c2fe7a3782c1c47ba3bee6481b0c2f8d41ef22 (diff)
downloadmpv-3d87ca6b5ef1a25438cf05c685817a9b2d8de19e.tar.bz2
mpv-3d87ca6b5ef1a25438cf05c685817a9b2d8de19e.tar.xz
m_option, vf: add label support
Can be used to refer to filters by name. Intended to be used when the filter chain is changed at runtime. A label can be assigned to a filter by prefixing it with '@name:', where 'name' is an user-chosen identifier. For example, a filter added with '-vf-add @label1:gradfun=123' can be removed with '-vf-del @label1'. If a filter with an already existing label is added, the existing filter is replaced with the new filter (this happens for both -vf-add and -vf-pre). If a filter is replaced, the new filter takes the position of the old filter, instead of being appended/prepended to the filter chain as usual. For -vf-toggle, labels are compared if at least one of the filters has a label; otherwise they are compared by filter name and arguments (like before). This means two filters are never considered equal if one has a label and the other one does not.
Diffstat (limited to 'core')
-rw-r--r--core/m_option.c106
-rw-r--r--core/m_option.h2
2 files changed, 83 insertions, 25 deletions
diff --git a/core/m_option.c b/core/m_option.c
index e9feef7db9..1f2ba1123e 100644
--- a/core/m_option.c
+++ b/core/m_option.c
@@ -1938,6 +1938,15 @@ static int parse_obj_settings(struct bstr opt, struct bstr *pstr,
char **plist = NULL;
const m_struct_t *desc;
m_obj_settings_t *ret = _ret ? *_ret : NULL;
+ bstr label = {0};
+
+ if (bstr_eatstart0(pstr, "@")) {
+ if (!bstr_split_tok(*pstr, ":", &label, pstr)) {
+ mp_msg(MSGT_CFGPARSER, MSGL_ERR,
+ "Option %.*s: ':' expected after label.\n", BSTR_P(opt));
+ return M_OPT_INVALID;
+ }
+ }
bool has_param = false;
int idx = bstrspn(*pstr, NAMECH);
@@ -1982,6 +1991,7 @@ static int parse_obj_settings(struct bstr opt, struct bstr *pstr,
ret = talloc_realloc(NULL, ret, struct m_obj_settings, ret_n + 2);
memset(&ret[ret_n], 0, 2 * sizeof(m_obj_settings_t));
ret[ret_n].name = bstrto0(NULL, str);
+ ret[ret_n].label = bstrdup0(NULL, label);
ret[ret_n].attribs = plist;
*_ret = ret;
@@ -1999,6 +2009,7 @@ static int obj_settings_list_num_items(m_obj_settings_t *obj_list)
static void obj_settings_free_item(m_obj_settings_t *item)
{
talloc_free(item->name);
+ talloc_free(item->label);
free_str_list(&(item->attribs));
}
@@ -2018,19 +2029,30 @@ static void del_obj_settings_list_at(m_obj_settings_t **p_obj_list, int idx)
*p_obj_list = talloc_realloc(NULL, obj_list, struct m_obj_settings, num);
}
-// memory referenced by *item is not copied
-static void append_obj_settings_list(m_obj_settings_t **p_obj_list,
- m_obj_settings_t *item)
+// Insert such that *p_obj_list[idx] is set to item.
+// If idx < 0, set idx = count + idx + 1 (i.e. -1 inserts it as last element).
+// Memory referenced by *item is not copied.
+static void insert_obj_settings_list_at(m_obj_settings_t **p_obj_list, int idx,
+ m_obj_settings_t *item)
{
int num = obj_settings_list_num_items(*p_obj_list);
+ if (idx < 0)
+ idx = num + idx + 1;
+ assert(idx >= 0 && idx <= num);
*p_obj_list = talloc_realloc(NULL, *p_obj_list, struct m_obj_settings,
num + 2);
- (*p_obj_list)[num] = *item;
+ memmove(*p_obj_list + idx + 1, *p_obj_list + idx,
+ (num - idx) * sizeof(m_obj_settings_t));
+ (*p_obj_list)[idx] = *item;
(*p_obj_list)[num + 1] = (m_obj_settings_t){0};
}
+// If at least one item has a label, compare labels only - otherwise ignore them.
static bool obj_setting_equals(m_obj_settings_t *a, m_obj_settings_t *b)
{
+ bstr la = bstr0(a->label), lb = bstr0(b->label);
+ if (la.len || lb.len)
+ return bstr_equals(la, lb);
if (strcmp(a->name, b->name) != 0)
return false;
@@ -2049,6 +2071,15 @@ static bool obj_setting_equals(m_obj_settings_t *a, m_obj_settings_t *b)
return true;
}
+static int obj_settings_find_by_label(m_obj_settings_t *obj_list, bstr label)
+{
+ for (int n = 0; obj_list && obj_list[n].name; n++) {
+ if (label.len && bstr_equals0(label, obj_list[n].label))
+ return n;
+ }
+ return -1;
+}
+
static int obj_settings_list_del(struct bstr opt_name, struct bstr param,
void *dst)
{
@@ -2069,6 +2100,19 @@ static int obj_settings_list_del(struct bstr opt_name, struct bstr param,
bstr item;
bstr_split_tok(param, ",", &item, &param);
+ if (bstr_eatstart0(&item, "@")) {
+ int label_index = obj_settings_find_by_label(obj_list, item);
+ if (label_index >= 0) {
+ mark_del[label_index] = true;
+ goto found;
+ } else {
+ mp_msg(MSGT_CFGPARSER, MSGL_WARN,
+ "Option %.*s: item label %.*s not found.\n",
+ BSTR_P(opt_name), BSTR_P(item));
+ continue;
+ }
+ }
+
for (int n = 0; n < idx_max; n++) {
if (!mark_del[n] && bstr_equals0(item, obj_list[n].name)) {
mark_del[n] = true;
@@ -2194,11 +2238,6 @@ static int parse_obj_settings_list(const m_option_t *opt, struct bstr name,
return M_OPT_EXIT - 1;
}
- if (op == OP_NONE) {
- if (dst && VAL(dst))
- free_obj_settings_list(dst);
- }
-
int num = 0;
while (param.len > 0) {
int r = parse_obj_settings(name, &param, opt->priv,
@@ -2217,19 +2256,33 @@ static int parse_obj_settings_list(const m_option_t *opt, struct bstr name,
if (dst) {
m_obj_settings_t *list = VAL(dst);
if (op == OP_PRE) {
- int qsize = obj_settings_list_num_items(list);
- res = talloc_realloc(NULL, res, struct m_obj_settings,
- qsize + num + 1);
- memcpy(&res[num], list, (qsize + 1) * sizeof(m_obj_settings_t));
- talloc_free(list);
+ int prepend_counter = 0;
+ for (int n = 0; res && res[n].name; n++) {
+ int label = obj_settings_find_by_label(list, bstr0(res[n].label));
+ if (label < 0) {
+ insert_obj_settings_list_at(&list, prepend_counter, &res[n]);
+ prepend_counter++;
+ } else {
+ // Prefer replacement semantics, instead of actually
+ // prepending.
+ obj_settings_free_item(&list[label]);
+ list[label] = res[n];
+ }
+ }
+ talloc_free(res);
} else if (op == OP_ADD) {
- m_obj_settings_t *list = VAL(dst);
- int hsize = obj_settings_list_num_items(list);
- list = talloc_realloc(NULL, list, struct m_obj_settings,
- hsize + num + 1);
- memcpy(&list[hsize], res, (num + 1) * sizeof(m_obj_settings_t));
+ for (int n = 0; res && res[n].name; n++) {
+ int label = obj_settings_find_by_label(list, bstr0(res[n].label));
+ if (label < 0) {
+ insert_obj_settings_list_at(&list, -1, &res[n]);
+ } else {
+ // Prefer replacement semantics, instead of actually
+ // appending.
+ obj_settings_free_item(&list[label]);
+ list[label] = res[n];
+ }
+ }
talloc_free(res);
- res = list;
} else if (op == OP_TOGGLE) {
for (int n = 0; res && res[n].name; n++) {
int found = -1;
@@ -2240,16 +2293,19 @@ static int parse_obj_settings_list(const m_option_t *opt, struct bstr name,
}
}
if (found < 0) {
- append_obj_settings_list(&list, &res[n]);
+ insert_obj_settings_list_at(&list, -1, &res[n]);
} else {
del_obj_settings_list_at(&list, found);
obj_settings_free_item(&res[n]);
}
}
talloc_free(res);
- res = list;
+ } else {
+ assert(op == OP_NONE);
+ free_obj_settings_list(&list);
+ list = res;
}
- VAL(dst) = res;
+ VAL(dst) = list;
}
return 1;
}
@@ -2270,17 +2326,17 @@ static void copy_obj_settings_list(const m_option_t *opt, void *dst,
if (!s)
return;
-
-
for (n = 0; s[n].name; n++)
/* NOP */;
d = talloc_array(NULL, struct m_obj_settings, n + 1);
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].attribs = NULL;
copy_str_list(NULL, &(d[n].attribs), &(s[n].attribs));
}
d[n].name = NULL;
+ d[n].label = NULL;
d[n].attribs = NULL;
VAL(dst) = d;
}
diff --git a/core/m_option.h b/core/m_option.h
index c94b170424..6a8bcfbf1a 100644
--- a/core/m_option.h
+++ b/core/m_option.h
@@ -110,6 +110,8 @@ typedef struct {
typedef struct m_obj_settings {
// Type of the object.
char *name;
+ // Optional user-defined name.
+ char *label;
// NULL terminated array of parameter/value pairs.
char **attribs;
} m_obj_settings_t;