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.
This commit is contained in:
wm4 2013-05-18 11:31:03 +02:00
parent 1dad548640
commit 6b42881791
1 changed files with 80 additions and 52 deletions

View File

@ -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 = 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;
}