mirror of https://github.com/mpv-player/mpv
m_option: allow using -vf-del with a name
Until now, -vf-del required a list of indexes. This was a bit inconvenient, so add support for using filter names too. Also simplify the code a bit, doing the change would have been too painful otherwise.
This commit is contained in:
parent
41d38b3a2b
commit
1dad548640
125
core/m_option.c
125
core/m_option.c
|
@ -1987,76 +1987,96 @@ static int parse_obj_settings(struct bstr opt, struct bstr *pstr,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int obj_settings_list_num_items(m_obj_settings_t *obj_list)
|
||||||
|
{
|
||||||
|
int num = 0;
|
||||||
|
while (obj_list && obj_list[num].name)
|
||||||
|
num++;
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void obj_settings_free_item(m_obj_settings_t *item)
|
||||||
|
{
|
||||||
|
talloc_free(item->name);
|
||||||
|
free_str_list(&(item->attribs));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void del_obj_settings_list_at(m_obj_settings_t **p_obj_list, int idx)
|
||||||
|
{
|
||||||
|
m_obj_settings_t *obj_list = *p_obj_list;
|
||||||
|
int num = obj_settings_list_num_items(obj_list);
|
||||||
|
|
||||||
|
assert(idx >= 0 && idx < num);
|
||||||
|
|
||||||
|
obj_settings_free_item(&obj_list[idx]);
|
||||||
|
|
||||||
|
// Note: the NULL-terminating element is moved down as part of this
|
||||||
|
memmove(&obj_list[idx], &obj_list[idx + 1],
|
||||||
|
sizeof(m_obj_settings_t) * (num - idx));
|
||||||
|
|
||||||
|
*p_obj_list = talloc_realloc(NULL, obj_list, struct m_obj_settings, num);
|
||||||
|
}
|
||||||
|
|
||||||
static int obj_settings_list_del(struct bstr opt_name, struct bstr param,
|
static int obj_settings_list_del(struct bstr opt_name, struct bstr param,
|
||||||
void *dst)
|
void *dst)
|
||||||
{
|
{
|
||||||
char **str_list = NULL;
|
|
||||||
int r, i, idx_max = 0;
|
|
||||||
char *rem_id = "_removed_marker_";
|
|
||||||
char name[100];
|
|
||||||
assert(opt_name.len < 100);
|
|
||||||
memcpy(name, opt_name.start, opt_name.len);
|
|
||||||
name[opt_name.len] = 0;
|
|
||||||
const m_option_t list_opt = {
|
|
||||||
name, NULL, CONF_TYPE_STRING_LIST,
|
|
||||||
0, 0, 0, NULL
|
|
||||||
};
|
|
||||||
m_obj_settings_t *obj_list = dst ? VAL(dst) : NULL;
|
m_obj_settings_t *obj_list = dst ? VAL(dst) : NULL;
|
||||||
|
int r = 1;
|
||||||
|
|
||||||
if (dst && !obj_list) {
|
if (dst && !obj_list) {
|
||||||
mp_msg(MSGT_CFGPARSER, MSGL_WARN, "Option %.*s: the list is empty.\n",
|
mp_msg(MSGT_CFGPARSER, MSGL_WARN, "Option %.*s: the list is empty.\n",
|
||||||
BSTR_P(opt_name));
|
BSTR_P(opt_name));
|
||||||
return 1;
|
return 1;
|
||||||
} else if (obj_list) {
|
|
||||||
for (idx_max = 0; obj_list[idx_max].name != NULL; idx_max++)
|
|
||||||
/* NOP */;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
r = m_option_parse(&list_opt, opt_name, param, &str_list);
|
int idx_max = obj_settings_list_num_items(obj_list);
|
||||||
if (r < 0 || !str_list)
|
bool *mark_del = talloc_zero_array(NULL, bool, idx_max);
|
||||||
return r;
|
|
||||||
|
|
||||||
for (r = 0; str_list[r]; r++) {
|
while (param.len) {
|
||||||
int id;
|
bstr item;
|
||||||
char *endptr;
|
bstr_split_tok(param, ",", &item, ¶m);
|
||||||
id = strtol(str_list[r], &endptr, 0);
|
|
||||||
if (endptr == str_list[r]) {
|
for (int n = 0; n < idx_max; n++) {
|
||||||
mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %.*s: invalid parameter. We need a list of integers which are the indices of the elements to remove.\n", BSTR_P(opt_name));
|
if (!mark_del[n] && bstr_equals0(item, obj_list[n].name)) {
|
||||||
m_option_free(&list_opt, &str_list);
|
mark_del[n] = true;
|
||||||
return M_OPT_INVALID;
|
goto found;
|
||||||
}
|
}
|
||||||
if (!obj_list)
|
}
|
||||||
continue;
|
|
||||||
if (id >= idx_max || id < -idx_max) {
|
bstr rest;
|
||||||
|
long long id = bstrtoll(item, &rest, 0);
|
||||||
|
if (rest.len == item.len) {
|
||||||
mp_msg(MSGT_CFGPARSER, MSGL_WARN,
|
mp_msg(MSGT_CFGPARSER, MSGL_WARN,
|
||||||
"Option %.*s: Index %d is out of range.\n",
|
"Option %.*s: item %.*s not found.\n",
|
||||||
|
BSTR_P(opt_name), BSTR_P(item));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (id < 0)
|
||||||
|
id = idx_max + id;
|
||||||
|
|
||||||
|
if (id < 0 || id >= idx_max) {
|
||||||
|
mp_msg(MSGT_CFGPARSER, MSGL_WARN,
|
||||||
|
"Option %.*s: Index %lld is out of range.\n",
|
||||||
BSTR_P(opt_name), id);
|
BSTR_P(opt_name), id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (id < 0)
|
|
||||||
id = idx_max + id;
|
mark_del[id] = true;
|
||||||
talloc_free(obj_list[id].name);
|
|
||||||
free_str_list(&(obj_list[id].attribs));
|
found: ;
|
||||||
obj_list[id].name = rem_id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dst) {
|
if (dst) {
|
||||||
m_option_free(&list_opt, &str_list);
|
for (int n = idx_max - 1; n >= 0; n--) {
|
||||||
return 1;
|
if (mark_del[n])
|
||||||
|
del_obj_settings_list_at(&obj_list, n);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; obj_list[i].name; i++) {
|
|
||||||
while (obj_list[i].name == rem_id) {
|
|
||||||
memmove(&obj_list[i], &obj_list[i + 1],
|
|
||||||
sizeof(m_obj_settings_t) * (idx_max - i));
|
|
||||||
idx_max--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
obj_list = talloc_realloc(NULL, obj_list, struct m_obj_settings,
|
|
||||||
idx_max + 1);
|
|
||||||
VAL(dst) = obj_list;
|
VAL(dst) = obj_list;
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
talloc_free(mark_del);
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void free_obj_settings_list(void *dst)
|
static void free_obj_settings_list(void *dst)
|
||||||
|
@ -2068,10 +2088,8 @@ static void free_obj_settings_list(void *dst)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
d = VAL(dst);
|
d = VAL(dst);
|
||||||
for (n = 0; d[n].name; n++) {
|
for (n = 0; d[n].name; n++)
|
||||||
talloc_free(d[n].name);
|
obj_settings_free_item(&d[n]);
|
||||||
free_str_list(&(d[n].attribs));
|
|
||||||
}
|
|
||||||
talloc_free(d);
|
talloc_free(d);
|
||||||
VAL(dst) = NULL;
|
VAL(dst) = NULL;
|
||||||
}
|
}
|
||||||
|
@ -2110,7 +2128,8 @@ static int parse_obj_settings_list(const m_option_t *opt, struct bstr name,
|
||||||
" Prepend the given list to the current list\n\n"
|
" Prepend the given list to the current list\n\n"
|
||||||
" %s-del x,y,...\n"
|
" %s-del x,y,...\n"
|
||||||
" Remove the given elements. Take the list element index (starting from 0).\n"
|
" Remove the given elements. Take the list element index (starting from 0).\n"
|
||||||
" Negative index can be used (i.e. -1 is the last element)\n\n"
|
" Negative index can be used (i.e. -1 is the last element).\n"
|
||||||
|
" Filter names work as well.\n\n"
|
||||||
" %s-clr\n"
|
" %s-clr\n"
|
||||||
" Clear the current list.\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);
|
||||||
|
|
Loading…
Reference in New Issue