From 6b4288179194d2d76534a48fb631f94c7f861619 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 18 May 2013 11:31:03 +0200 Subject: [PATCH] m_option: add -vf-toggle Works like -vf-add, except if a filter already exists and has the same parameters, it's removed instead of added. Not really useful on the command line itself, but will make sense for runtime filter changing in the following commit. --- core/m_option.c | 132 +++++++++++++++++++++++++++++------------------- 1 file changed, 80 insertions(+), 52 deletions(-) diff --git a/core/m_option.c b/core/m_option.c index 8935cf8944..6e02c537ad 100644 --- a/core/m_option.c +++ b/core/m_option.c @@ -843,6 +843,7 @@ const m_option_type_t m_option_type_string = { #define OP_PRE 2 #define OP_DEL 3 #define OP_CLR 4 +#define OP_TOGGLE 5 static void free_str_list(void *dst) { @@ -2017,6 +2018,32 @@ 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) +{ + int num = obj_settings_list_num_items(*p_obj_list); + *p_obj_list = talloc_realloc(NULL, *p_obj_list, struct m_obj_settings, + num + 2); + (*p_obj_list)[num] = *item; + (*p_obj_list)[num + 1] = (m_obj_settings_t){0}; +} + +static bool obj_setting_equals(m_obj_settings_t *a, m_obj_settings_t *b) +{ + if (strcmp(a->name, b->name) != 0) + return false; + for (int n = 0; ; n += 2) { + if (!a->attribs[n] && !b->attribs[n]) + return true; + if (!a->attribs[n] || !b->attribs[n]) + return false; + if (strcmp(a->attribs[n], b->attribs[n]) != 0) + return false; + } + abort(); +} + static int obj_settings_list_del(struct bstr opt_name, struct bstr param, void *dst) { @@ -2098,23 +2125,25 @@ static int parse_obj_settings_list(const m_option_t *opt, struct bstr name, struct bstr param, void *dst) { int len = strlen(opt->name); - m_obj_settings_t *res = NULL, *queue = NULL, *head = NULL; + m_obj_settings_t *res = NULL; int op = OP_NONE; - // We need the objects list - if (!opt->priv) - return M_OPT_INVALID; + assert(opt->priv); if (opt->name[len - 1] == '*' && (name.len > len - 1)) { struct bstr suffix = bstr_cut(name, len - 1); if (bstrcmp0(suffix, "-add") == 0) op = OP_ADD; + else if (bstrcmp0(suffix, "-set") == 0) + op = OP_NONE; else if (bstrcmp0(suffix, "-pre") == 0) op = OP_PRE; else if (bstrcmp0(suffix, "-del") == 0) op = OP_DEL; else if (bstrcmp0(suffix, "-clr") == 0) op = OP_CLR; + else if (bstrcmp0(suffix, "-toggle") == 0) + op = OP_TOGGLE; else { char prefix[len]; strncpy(prefix, opt->name, len - 1); @@ -2122,6 +2151,8 @@ static int parse_obj_settings_list(const m_option_t *opt, struct bstr name, mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %.*s: unknown postfix %.*s\n" "Supported postfixes are:\n" + " %s-set\n" + " Overwrite the old list with the given list\n\n" " %s-add\n" " Append the given list to the current list\n\n" " %s-pre\n" @@ -2132,42 +2163,23 @@ static int parse_obj_settings_list(const m_option_t *opt, struct bstr name, " Filter names work as well.\n\n" " %s-clr\n" " Clear the current list.\n", - BSTR_P(name), BSTR_P(suffix), prefix, prefix, prefix, prefix); + BSTR_P(name), BSTR_P(suffix), prefix, prefix, prefix, prefix, prefix); return M_OPT_UNKNOWN; } } - // Clear the list ?? 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 (param.len == 0) return M_OPT_MISSING_PARAM; - switch (op) { - case OP_ADD: - if (dst) - head = VAL(dst); - break; - case OP_PRE: - if (dst) - queue = VAL(dst); - break; - case OP_DEL: - return obj_settings_list_del(name, param, dst); - case OP_NONE: - if (dst && VAL(dst)) - free_obj_settings_list(dst); - break; - default: - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %.*s: FIXME\n", BSTR_P(name)); - return M_OPT_UNKNOWN; - } - if (!bstrcmp0(param, "help")) { m_obj_list_t *ol = opt->priv; mp_msg(MSGT_CFGPARSER, MSGL_INFO, "Available video filters:\n"); @@ -2179,43 +2191,59 @@ static int parse_obj_settings_list(const m_option_t *opt, struct bstr name, return M_OPT_EXIT - 1; } - int n = 0; + 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, ¶m, opt->priv, dst ? &res : NULL, n); + int r = parse_obj_settings(name, ¶m, opt->priv, + dst ? &res : NULL, num); if (r < 0) return r; - char sep[2] = {OPTION_LIST_SEPARATOR, 0}; + const char sep[2] = {OPTION_LIST_SEPARATOR, 0}; if (param.len > 0 && !bstr_eatstart0(¶m, sep)) return M_OPT_INVALID; - n++; + num++; } - if (n == 0) + if (num == 0) return M_OPT_INVALID; - if (((opt->flags & M_OPT_MIN) && (n < opt->min)) || - ((opt->flags & M_OPT_MAX) && (n > opt->max))) - return M_OPT_OUT_OF_RANGE; - if (dst) { - if (queue) { - int qsize; - for (qsize = 0; queue[qsize].name; qsize++) - /* NOP */; + 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 + n + 1); - memcpy(&res[n], queue, (qsize + 1) * sizeof(m_obj_settings_t)); - n += qsize; - talloc_free(queue); - } - if (head) { - int hsize; - for (hsize = 0; head[hsize].name; hsize++) - /* NOP */; - head = talloc_realloc(NULL, head, struct m_obj_settings, - hsize + n + 1); - memcpy(&head[hsize], res, (n + 1) * sizeof(m_obj_settings_t)); + qsize + num + 1); + memcpy(&res[num], list, (qsize + 1) * sizeof(m_obj_settings_t)); + talloc_free(list); + } 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)); talloc_free(res); - res = head; + res = list; + } 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; + } + } + if (found < 0) { + append_obj_settings_list(&list, &res[n]); + } else { + del_obj_settings_list_at(&list, found); + obj_settings_free_item(&res[n]); + } + } + talloc_free(res); + res = list; } VAL(dst) = res; }