From 862989c0113da276ee9795f88541288da03015a6 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 22 May 2013 23:30:53 +0200 Subject: m_option: allow removing filter entries by content with -vf-del If a complete filter description is passed to -vf-del, search for an existing filter with the same label or the same name/arguments, and delete it. The rules for filter entry equality are the same as with the -vf-toggle option. E.g. -vf-add gradfun=123:gradfun=456 -vf-del gradfun=456 does what you would expect. --- core/m_option.c | 177 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 88 insertions(+), 89 deletions(-) diff --git a/core/m_option.c b/core/m_option.c index 956acacb4f..931b498213 100644 --- a/core/m_option.c +++ b/core/m_option.c @@ -1875,6 +1875,16 @@ static int obj_settings_list_find_by_label0(m_obj_settings_t *obj_list, return obj_settings_list_find_by_label(obj_list, bstr0(label)); } +static int obj_settings_find_by_content(m_obj_settings_t *obj_list, + m_obj_settings_t *item) +{ + for (int n = 0; obj_list && obj_list[n].name; n++) { + if (obj_setting_equals(&obj_list[n], item)) + return n; + } + return -1; +} + static void free_obj_settings_list(void *dst) { int n; @@ -2067,12 +2077,11 @@ print_help: ; // 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 bstr opt, struct bstr *pstr, const m_obj_list_t *list, - m_obj_settings_t **_ret, int ret_n) + m_obj_settings_t **_ret) { int r; char **plist = NULL; const m_struct_t *desc; - m_obj_settings_t *ret = _ret ? *_ret : NULL; bstr label = {0}; if (bstr_eatstart0(pstr, "@")) { @@ -2123,89 +2132,63 @@ static int parse_obj_settings(struct bstr opt, struct bstr *pstr, if (!_ret) return 1; - 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; + m_obj_settings_t item = { + .name = bstrto0(NULL, str), + .label = bstrdup0(NULL, label), + .attribs = plist, + }; + obj_settings_list_insert_at(_ret, -1, &item); return 1; } -static int obj_settings_list_del(struct bstr opt_name, struct bstr param, - void *dst) +// Parse a single entry for -vf-del (return 0 if not applicable) +// mark_del is bounded by the number of items in dst +static int parse_obj_settings_del(struct bstr opt_name, struct bstr *param, + void *dst, bool *mark_del) { - if (!dst) - return 1; // for profiles; pretend all is ok - m_obj_settings_t *obj_list = VAL(dst); - - if (dst && !obj_list) { - mp_msg(MSGT_CFGPARSER, MSGL_WARN, "Option %.*s: the list is empty.\n", - BSTR_P(opt_name)); - return 1; - } - - int idx_max = obj_settings_list_num_items(obj_list); - bool *mark_del = talloc_zero_array(NULL, bool, idx_max); - - while (param.len) { - bstr item; - bstr_split_tok(param, ",", &item, ¶m); - - if (bstr_eatstart0(&item, "@")) { - int label_index = obj_settings_list_find_by_label(obj_list, item); + bstr s = *param; + if (bstr_eatstart0(&s, "@")) { + // '@name:' -> parse as normal filter entry + // '@name,' or '@name' -> parse here + int idx = bstrspn(s, NAMECH); + bstr label = bstr_splice(s, 0, idx); + s = bstr_cut(s, idx); + if (bstr_startswith0(s, ":")) + return 0; + if (dst) { + int label_index = obj_settings_list_find_by_label(VAL(dst), label); 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; - goto found; + "Option %.*s: item label @%.*s not found.\n", + BSTR_P(opt_name), BSTR_P(label)); } } + *param = s; + return 1; + } - bstr rest; - long long id = bstrtoll(item, &rest, 0); - if (rest.len == item.len) { - mp_msg(MSGT_CFGPARSER, MSGL_WARN, - "Option %.*s: item %.*s not found.\n", - BSTR_P(opt_name), BSTR_P(item)); - continue; - } + bstr rest; + long long id = bstrtoll(s, &rest, 0); + if (rest.len == s.len) + return 0; + if (dst) { + int num = obj_settings_list_num_items(VAL(dst)); if (id < 0) - id = idx_max + id; + id = num + id; - if (id < 0 || id >= idx_max) { + if (id >= 0 && id < num) { + mark_del[id] = true; + } else { mp_msg(MSGT_CFGPARSER, MSGL_WARN, - "Option %.*s: Index %lld is out of range.\n", - BSTR_P(opt_name), id); - continue; - } - - mark_del[id] = true; - - found: ; - } - - if (dst) { - for (int n = idx_max - 1; n >= 0; n--) { - if (mark_del[n]) - obj_settings_list_del_at(&obj_list, n); + "Option %.*s: Index %lld is out of range.\n", + BSTR_P(opt_name), id); } - VAL(dst) = obj_list; } - talloc_free(mark_del); + *param = rest; return 1; } @@ -2215,6 +2198,8 @@ static int parse_obj_settings_list(const m_option_t *opt, struct bstr name, int len = strlen(opt->name); m_obj_settings_t *res = NULL; int op = OP_NONE; + bool *mark_del = NULL; + int num_items = obj_settings_list_num_items(dst ? VAL(dst) : 0); assert(opt->priv); @@ -2257,14 +2242,6 @@ static int parse_obj_settings_list(const m_option_t *opt, struct bstr name, } } - if (op == OP_CLR) { - if (dst) - free_obj_settings_list(dst); - return 0; - } else if (op == OP_DEL) { - return obj_settings_list_del(name, param, dst); - } - if (!bstrcmp0(param, "help")) { m_obj_list_t *ol = opt->priv; mp_msg(MSGT_CFGPARSER, MSGL_INFO, "Available video filters:\n"); @@ -2276,21 +2253,32 @@ static int parse_obj_settings_list(const m_option_t *opt, struct bstr name, return M_OPT_EXIT - 1; } - int num = 0; + if (op == OP_CLR) { + if (dst) + free_obj_settings_list(dst); + return 0; + } else if (op == OP_DEL) { + mark_del = talloc_zero_array(NULL, bool, num_items + 1); + } + + if (op != OP_NONE && param.len == 0) + return M_OPT_MISSING_PARAM; + while (param.len > 0) { - int r = parse_obj_settings(name, ¶m, opt->priv, - dst ? &res : NULL, num); + int r = 0; + if (op == OP_DEL) + r = parse_obj_settings_del(name, ¶m, dst, mark_del); + if (r == 0) { + r = parse_obj_settings(name, ¶m, opt->priv, + dst ? &res : NULL); + } if (r < 0) return r; const char sep[2] = {OPTION_LIST_SEPARATOR, 0}; if (param.len > 0 && !bstr_eatstart0(¶m, sep)) return M_OPT_INVALID; - num++; } - if (op != OP_NONE && num == 0) - return M_OPT_MISSING_PARAM; - if (dst) { m_obj_settings_t *list = VAL(dst); if (op == OP_PRE) { @@ -2323,13 +2311,7 @@ static int parse_obj_settings_list(const m_option_t *opt, struct bstr name, talloc_free(res); } else if (op == OP_TOGGLE) { for (int n = 0; res && res[n].name; n++) { - int found = -1; - for (int i = 0; list && list[i].name; i++) { - if (obj_setting_equals(&list[i], &res[n])) { - found = i; - break; - } - } + int found = obj_settings_find_by_content(list, &res[n]); if (found < 0) { obj_settings_list_insert_at(&list, -1, &res[n]); } else { @@ -2338,6 +2320,21 @@ static int parse_obj_settings_list(const m_option_t *opt, struct bstr name, } } talloc_free(res); + } else if (op == OP_DEL) { + for (int n = num_items - 1; n >= 0; n--) { + if (mark_del[n]) + obj_settings_list_del_at(&list, n); + } + for (int n = 0; res && res[n].name; n++) { + int found = obj_settings_find_by_content(list, &res[n]); + if (found < 0) { + mp_msg(MSGT_CFGPARSER, MSGL_WARN, + "Option %.*s: Item bot found\n", BSTR_P(name)); + } else { + obj_settings_list_del_at(&list, found); + } + } + free_obj_settings_list(&res); } else { assert(op == OP_NONE); free_obj_settings_list(&list); @@ -2345,6 +2342,8 @@ static int parse_obj_settings_list(const m_option_t *opt, struct bstr name, } VAL(dst) = list; } + + talloc_free(mark_del); return 1; } -- cgit v1.2.3