summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/m_option.c132
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, &param, opt->priv, dst ? &res : NULL, n);
+ int r = parse_obj_settings(name, &param, 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(&param, 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;
}