diff options
Diffstat (limited to 'core/m_option.c')
-rw-r--r-- | core/m_option.c | 132 |
1 files 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 = 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 = head; + res = list; } VAL(dst) = res; } |