diff options
Diffstat (limited to 'options/m_option.c')
-rw-r--r-- | options/m_option.c | 422 |
1 files changed, 219 insertions, 203 deletions
diff --git a/options/m_option.c b/options/m_option.c index 4d222df500..3d9ae26669 100644 --- a/options/m_option.c +++ b/options/m_option.c @@ -61,6 +61,31 @@ const char m_option_path_separator = OPTION_PATH_SEPARATOR; #define OPT_INT_MAX(opt, T, Tm) ((opt)->min < (opt)->max \ ? ((opt)->max >= (double)(Tm) ? (Tm) : (T)((opt)->max)) : (Tm)) +int m_option_parse(struct mp_log *log, const m_option_t *opt, + struct bstr name, struct bstr param, void *dst) +{ + int r = M_OPT_INVALID; + if (bstr_equals0(param, "help") && opt->help) { + r = opt->help(log, opt, name); + if (r < 0) + return r; + } + + r = opt->type->parse(log, opt, name, param, dst); + if (r < 0) + return r; + + if (opt->validate) { + r = opt->validate(log, opt, name, dst); + if (r < 0) { + if (opt->type->free) + opt->type->free(dst); + return r; + } + } + return 1; +} + char *m_option_strerror(int code) { switch (code) { @@ -86,7 +111,7 @@ int m_option_required_params(const m_option_t *opt) if (opt->flags & M_OPT_OPTIONAL_PARAM) return 0; if (opt->type == &m_option_type_choice) { - struct m_opt_choice_alternatives *alt; + const struct m_opt_choice_alternatives *alt; for (alt = opt->priv; alt->name; alt++) { if (strcmp(alt->name, "yes") == 0) return 0; @@ -245,6 +270,7 @@ static bool flag_equal(const m_option_t *opt, void *a, void *b) return VAL(a) == VAL(b); } +// Only exists for libmpv interopability and should not be used anywhere. const m_option_type_t m_option_type_flag = { // need yes or no in config files .name = "Flag", @@ -595,7 +621,7 @@ const char *m_opt_choice_str(const struct m_opt_choice_alternatives *choices, static void print_choice_values(struct mp_log *log, const struct m_option *opt) { - struct m_opt_choice_alternatives *alt = opt->priv; + const struct m_opt_choice_alternatives *alt = opt->priv; for ( ; alt->name; alt++) mp_info(log, " %s\n", alt->name[0] ? alt->name : "(passing nothing)"); if (opt->min < opt->max) @@ -605,7 +631,7 @@ static void print_choice_values(struct mp_log *log, const struct m_option *opt) static int parse_choice(struct mp_log *log, const struct m_option *opt, struct bstr name, struct bstr param, void *dst) { - struct m_opt_choice_alternatives *alt = opt->priv; + const struct m_opt_choice_alternatives *alt = opt->priv; for ( ; alt->name; alt++) { if (!bstrcmp0(param, alt->name)) break; @@ -652,7 +678,7 @@ static void choice_get_min_max(const struct m_option *opt, int *min, int *max) assert(opt->type == &m_option_type_choice); *min = INT_MAX; *max = INT_MIN; - for (struct m_opt_choice_alternatives *alt = opt->priv; alt->name; alt++) { + for (const struct m_opt_choice_alternatives *alt = opt->priv; alt->name; alt++) { *min = MPMIN(*min, alt->value); *max = MPMAX(*max, alt->value); } @@ -696,7 +722,7 @@ static void add_choice(const m_option_t *opt, void *val, double add, bool wrap) } } - for (struct m_opt_choice_alternatives *alt = opt->priv; alt->name; alt++) + for (const struct m_opt_choice_alternatives *alt = opt->priv; alt->name; alt++) check_choice(dir, ival, &found, &best, alt->value); if (!found) { @@ -729,11 +755,12 @@ static int choice_set(const m_option_t *opt, void *dst, struct mpv_node *src) return r; } -static struct m_opt_choice_alternatives *get_choice(const m_option_t *opt, - const void *val, int *out_val) +static const struct m_opt_choice_alternatives *get_choice(const m_option_t *opt, + const void *val, + int *out_val) { int v = *(int *)val; - struct m_opt_choice_alternatives *alt; + const struct m_opt_choice_alternatives *alt; for (alt = opt->priv; alt->name; alt++) { if (alt->value == v) return alt; @@ -744,14 +771,14 @@ static struct m_opt_choice_alternatives *get_choice(const m_option_t *opt, return NULL; } } - abort(); + MP_ASSERT_UNREACHABLE(); } static int choice_get(const m_option_t *opt, void *ta_parent, struct mpv_node *dst, void *src) { int ival = 0; - struct m_opt_choice_alternatives *alt = get_choice(opt, src, &ival); + const struct m_opt_choice_alternatives *alt = get_choice(opt, src, &ival); // If a choice string looks like a number, return it as number if (alt) { char *end = NULL; @@ -783,7 +810,7 @@ static int choice_get(const m_option_t *opt, void *ta_parent, static char *print_choice(const m_option_t *opt, const void *val) { int ival = 0; - struct m_opt_choice_alternatives *alt = get_choice(opt, val, &ival); + const struct m_opt_choice_alternatives *alt = get_choice(opt, val, &ival); return alt ? talloc_strdup(NULL, alt->name) : talloc_asprintf(NULL, "%d", ival); } @@ -803,7 +830,7 @@ const struct m_option_type m_option_type_choice = { static int apply_flag(const struct m_option *opt, int *val, bstr flag) { - struct m_opt_choice_alternatives *alt; + const struct m_opt_choice_alternatives *alt; for (alt = opt->priv; alt->name; alt++) { if (bstr_equals0(flag, alt->name)) { if (*val & alt->value) @@ -817,8 +844,8 @@ static int apply_flag(const struct m_option *opt, int *val, bstr flag) static const char *find_next_flag(const struct m_option *opt, int *val) { - struct m_opt_choice_alternatives *best = NULL; - struct m_opt_choice_alternatives *alt; + const struct m_opt_choice_alternatives *best = NULL; + const struct m_opt_choice_alternatives *alt; for (alt = opt->priv; alt->name; alt++) { if (alt->value && (alt->value & (*val)) == alt->value) { if (!best || av_popcount64(alt->value) > av_popcount64(best->value)) @@ -845,7 +872,7 @@ static int parse_flags(struct mp_log *log, const struct m_option *opt, mp_fatal(log, "Invalid flag for option %.*s: %.*s\n", BSTR_P(name), BSTR_P(flag)); mp_info(log, "Valid flags are:\n"); - struct m_opt_choice_alternatives *alt; + const struct m_opt_choice_alternatives *alt; for (alt = opt->priv; alt->name; alt++) mp_info(log, " %s\n", alt->name); mp_info(log, "Flags can usually be combined with '+'.\n"); @@ -996,12 +1023,12 @@ static char *print_double(const m_option_t *opt, const void *val) return talloc_asprintf(NULL, "%f", f); } -static char *print_double_f3(const m_option_t *opt, const void *val) +static char *pretty_print_double(const m_option_t *opt, const void *val) { double f = VAL(val); if (isnan(f)) return print_double(opt, val); - return talloc_asprintf(NULL, "%.3f", f); + return mp_format_double(NULL, f, 4, false, false, !(opt->flags & M_OPT_FIXED_LEN_PRINT)); } static void add_double(const m_option_t *opt, void *val, double add, bool wrap) @@ -1073,7 +1100,33 @@ const m_option_type_t m_option_type_double = { .size = sizeof(double), .parse = parse_double, .print = print_double, - .pretty_print = print_double_f3, + .pretty_print = pretty_print_double, + .copy = copy_opt, + .add = add_double, + .multiply = multiply_double, + .set = double_set, + .get = double_get, + .equal = double_equal, +}; + +static int parse_double_aspect(struct mp_log *log, const m_option_t *opt, + struct bstr name, struct bstr param, void *dst) +{ + if (bstr_equals0(param, "no")) { + if (dst) + VAL(dst) = 0.0; + return 1; + } + return parse_double(log, opt, name, param, dst); +} + +const m_option_type_t m_option_type_aspect = { + .name = "Aspect", + .size = sizeof(double), + .flags = M_OPT_TYPE_CHOICE | M_OPT_TYPE_USES_RANGE, + .parse = parse_double_aspect, + .print = print_double, + .pretty_print = pretty_print_double, .copy = copy_opt, .add = add_double, .multiply = multiply_double, @@ -1101,10 +1154,10 @@ static char *print_float(const m_option_t *opt, const void *val) return print_double(opt, &tmp); } -static char *print_float_f3(const m_option_t *opt, const void *val) +static char *pretty_print_float(const m_option_t *opt, const void *val) { double tmp = VAL(val); - return print_double_f3(opt, &tmp); + return pretty_print_double(opt, &tmp); } static void add_float(const m_option_t *opt, void *val, double add, bool wrap) @@ -1149,33 +1202,7 @@ const m_option_type_t m_option_type_float = { .size = sizeof(float), .parse = parse_float, .print = print_float, - .pretty_print = print_float_f3, - .copy = copy_opt, - .add = add_float, - .multiply = multiply_float, - .set = float_set, - .get = float_get, - .equal = float_equal, -}; - -static int parse_float_aspect(struct mp_log *log, const m_option_t *opt, - struct bstr name, struct bstr param, void *dst) -{ - if (bstr_equals0(param, "no")) { - if (dst) - VAL(dst) = 0.0f; - return 1; - } - return parse_float(log, opt, name, param, dst); -} - -const m_option_type_t m_option_type_aspect = { - .name = "Aspect", - .size = sizeof(float), - .flags = M_OPT_TYPE_CHOICE | M_OPT_TYPE_USES_RANGE, - .parse = parse_float_aspect, - .print = print_float, - .pretty_print = print_float_f3, + .pretty_print = pretty_print_float, .copy = copy_opt, .add = add_float, .multiply = multiply_float, @@ -1192,13 +1219,6 @@ const m_option_type_t m_option_type_aspect = { static int parse_str(struct mp_log *log, const m_option_t *opt, struct bstr name, struct bstr param, void *dst) { - m_opt_string_validate_fn validate = opt->priv; - if (validate) { - int r = validate(log, opt, name, param); - if (r < 0) - return r; - } - if (dst) { talloc_free(VAL(dst)); VAL(dst) = bstrdup0(NULL, param); @@ -1272,11 +1292,10 @@ const m_option_type_t m_option_type_string = { #define OP_NONE 0 #define OP_ADD 1 #define OP_PRE 2 -#define OP_DEL 3 -#define OP_CLR 4 -#define OP_TOGGLE 5 -#define OP_APPEND 6 -#define OP_REMOVE 7 +#define OP_CLR 3 +#define OP_TOGGLE 4 +#define OP_APPEND 5 +#define OP_REMOVE 6 static void free_str_list(void *dst) { @@ -1318,55 +1337,6 @@ static int str_list_add(char **add, int n, void *dst, int pre) return 1; } -static int str_list_del(struct mp_log *log, char **del, int n, void *dst) -{ - char **lst, *ep; - int i, ln, s; - long idx; - - lst = VAL(dst); - - for (ln = 0; lst && lst[ln]; ln++) - /**/; - s = ln; - - for (i = 0; del[i] != NULL; i++) { - idx = strtol(del[i], &ep, 0); - if (*ep) { - mp_err(log, "Invalid index: %s\n", del[i]); - talloc_free(del[i]); - continue; - } - talloc_free(del[i]); - if (idx < 0 || idx >= ln) { - mp_err(log, "Index %ld is out of range.\n", idx); - continue; - } else if (!lst[idx]) - continue; - talloc_free(lst[idx]); - lst[idx] = NULL; - s--; - } - talloc_free(del); - - if (s == 0) { - talloc_free(lst); - VAL(dst) = NULL; - return 1; - } - - // Don't bother shrinking the list allocation - for (i = 0, n = 0; i < ln; i++) { - if (!lst[i]) - continue; - lst[n] = lst[i]; - n++; - } - lst[s] = NULL; - - return 1; -} - static struct bstr get_nextsep(struct bstr *ptr, char sep, bool modify) { struct bstr str = *ptr; @@ -1413,11 +1383,6 @@ static int parse_str_list_impl(struct mp_log *log, const m_option_t *opt, multi = false; } else if (bstr_endswith0(name, "-pre")) { op = OP_PRE; - } else if (bstr_endswith0(name, "-del")) { - op = OP_DEL; - mp_warn(log, "Option %.*s: -del is deprecated! " - "Use -remove (removes by content instead of by index).\n", - BSTR_P(name)); } else if (bstr_endswith0(name, "-clr")) { op = OP_CLR; } else if (bstr_endswith0(name, "-set")) { @@ -1431,14 +1396,20 @@ static int parse_str_list_impl(struct mp_log *log, const m_option_t *opt, if (op == OP_TOGGLE || op == OP_REMOVE) { if (dst) { char **list = VAL(dst); - int index = find_list_bstr(list, param); - if (index >= 0) { - char *old = list[index]; - for (int n = index; list[n]; n++) - list[n] = list[n + 1]; - talloc_free(old); + bool found = false; + int index = 0; + do { + index = find_list_bstr(list, param); + if (index >= 0) { + found = true; + char *old = list[index]; + for (int n = index; list[n]; n++) + list[n] = list[n + 1]; + talloc_free(old); + } + } while (index >= 0); + if (found) return 1; - } } if (op == OP_REMOVE) return 1; // ignore if not found @@ -1499,8 +1470,6 @@ static int parse_str_list_impl(struct mp_log *log, const m_option_t *opt, return str_list_add(res, n, dst, 0); case OP_PRE: return str_list_add(res, n, dst, 1); - case OP_DEL: - return str_list_del(log, res, n, dst); } if (VAL(dst)) @@ -1543,6 +1512,7 @@ static char *print_str_list(const m_option_t *opt, const void *src) { char **lst = NULL; char *ret = NULL; + const char sep = opt->priv ? *(char *)opt->priv : OPTION_LIST_SEPARATOR; if (!(src && VAL(src))) return talloc_strdup(NULL, ""); @@ -1550,7 +1520,7 @@ static char *print_str_list(const m_option_t *opt, const void *src) for (int i = 0; lst[i]; i++) { if (ret) - ret = talloc_strdup_append_buffer(ret, ","); + ret = talloc_strndup_append_buffer(ret, &sep, 1); ret = talloc_strdup_append_buffer(ret, lst[i]); } return ret; @@ -1630,7 +1600,6 @@ const m_option_type_t m_option_type_string_list = { {"add"}, {"append"}, {"clr", M_OPT_TYPE_OPTIONAL_PARAM}, - {"del"}, {"pre"}, {"set"}, {"toggle"}, @@ -1736,7 +1705,7 @@ static int parse_keyvalue_list(struct mp_log *log, const m_option_t *opt, } if (param.len) { - mp_err(log, "Unparseable garbage at end of option value: '%.*s'\n", + mp_err(log, "Unparsable garbage at end of option value: '%.*s'\n", BSTR_P(param)); r = M_OPT_INVALID; } @@ -1846,7 +1815,7 @@ static int parse_msglevels(struct mp_log *log, const m_option_t *opt, struct bstr name, struct bstr param, void *dst) { if (bstr_equals0(param, "help")) { - mp_info(log, "Syntax:\n\n --msglevel=module1=level,module2=level,...\n\n" + mp_info(log, "Syntax:\n\n --msg-level=module1=level,module2=level,...\n\n" "'module' is output prefix as shown with -v, or a prefix\n" "of it. level is one of:\n\n" " fatal error warn info status v debug trace\n\n" @@ -1928,7 +1897,7 @@ const m_option_type_t m_option_type_dummy_flag = { // Read s sub-option name, or a positional sub-opt value. // termset is a string containing the set of chars that terminate an option. -// Return 0 on succes, M_OPT_ error code otherwise. +// Return 0 on success, M_OPT_ error code otherwise. // optname is for error reporting. static int read_subparam(struct mp_log *log, bstr optname, char *termset, bstr *str, bstr *out_subparam) @@ -2254,7 +2223,7 @@ void m_geometry_apply(int *xpos, int *ypos, int *widw, int *widh, *widw = *widh * asp; } // Center window after resize. If valid x:y values are passed to - // geometry, then those values will be overriden. + // geometry, then those values will be overridden. *xpos += prew / 2 - *widw / 2; *ypos += preh / 2 - *widh / 2; } @@ -2361,6 +2330,64 @@ const m_option_type_t m_option_type_size_box = { .equal = geometry_equal, }; +void m_rect_apply(struct mp_rect *rc, int w, int h, struct m_geometry *gm) +{ + *rc = (struct mp_rect){0, 0, w, h}; + if (!w || !h) + return; + m_geometry_apply(&rc->x0, &rc->y0, &rc->x1, &rc->y1, w, h, gm); + if (!gm->xy_valid && gm->wh_valid && rc->x1 == 0 && rc->y1 == 0) + return; + if (!gm->wh_valid || rc->x1 == 0 || rc->x1 == INT_MIN) + rc->x1 = w - rc->x0; + if (!gm->wh_valid || rc->y1 == 0 || rc->y1 == INT_MIN) + rc->y1 = h - rc->y0; + if (gm->wh_valid && (gm->w || gm->h)) + rc->x1 += rc->x0; + if (gm->wh_valid && (gm->w || gm->h)) + rc->y1 += rc->y0; +} + +static int parse_rect(struct mp_log *log, const m_option_t *opt, + struct bstr name, struct bstr param, void *dst) +{ + bool is_help = bstr_equals0(param, "help"); + if (is_help) + goto exit; + + struct m_geometry gm; + if (!parse_geometry_str(&gm, param)) + goto exit; + + bool invalid = gm.x_sign || gm.y_sign || gm.ws; + invalid |= gm.wh_valid && (gm.w < 0 || gm.h < 0); + invalid |= gm.wh_valid && !gm.xy_valid && gm.w <= 0 && gm.h <= 0; + + if (invalid) + goto exit; + + if (dst) + *((struct m_geometry *)dst) = gm; + + return 1; + +exit: + if (!is_help) { + mp_err(log, "Option %.*s: invalid rect: '%.*s'\n", + BSTR_P(name), BSTR_P(param)); + } + mp_info(log, "Valid format: W[%%][xH[%%]][+x+y]\n"); + return is_help ? M_OPT_EXIT : M_OPT_INVALID; +} + +const m_option_type_t m_option_type_rect = { + .name = "Video rect", + .size = sizeof(struct m_geometry), + .parse = parse_rect, + .print = print_geometry, + .copy = copy_opt, + .equal = geometry_equal, +}; #include "video/img_format.h" @@ -2628,21 +2655,33 @@ const m_option_type_t m_option_type_channels = { static int parse_timestring(struct bstr str, double *time, char endchar) { - int a, b, len; - double d; + int h, m, len; + double s; *time = 0; /* ensure initialization for error cases */ - if (bstr_sscanf(str, "%d:%d:%lf%n", &a, &b, &d, &len) >= 3) - *time = 3600 * a + 60 * b + d; - else if (bstr_sscanf(str, "%d:%lf%n", &a, &d, &len) >= 2) - *time = 60 * a + d; - else if (bstr_sscanf(str, "%lf%n", &d, &len) >= 1) - *time = d; - else + bool neg = bstr_eatstart0(&str, "-"); + if (!neg) + bstr_eatstart0(&str, "+"); + if (bstrchr(str, '-') >= 0 || bstrchr(str, '+') >= 0) + return 0; /* the timestamp shouldn't contain anymore +/- after this point */ + if (bstr_sscanf(str, "%d:%d:%lf%n", &h, &m, &s, &len) >= 3) { + if (m >= 60 || s >= 60) + return 0; /* minutes or seconds are out of range */ + *time = 3600 * h + 60 * m + s; + } else if (bstr_sscanf(str, "%d:%lf%n", &m, &s, &len) >= 2) { + if (s >= 60) + return 0; /* seconds are out of range */ + *time = 60 * m + s; + } else if (bstr_sscanf(str, "%lf%n", &s, &len) >= 1) { + *time = s; + } else { return 0; /* unsupported time format */ + } if (len < str.len && str.start[len] != endchar) return 0; /* invalid extra characters at the end */ if (!isfinite(*time)) return 0; + if (neg) + *time = -*time; return len; } @@ -2783,8 +2822,7 @@ static char *print_rel_time(const m_option_t *opt, const void *val) case REL_TIME_ABSOLUTE: return talloc_asprintf(NULL, "%g", t->pos); case REL_TIME_RELATIVE: - return talloc_asprintf(NULL, "%s%g", - (t->pos >= 0) ? "+" : "-", fabs(t->pos)); + return talloc_asprintf(NULL, "%+g", t->pos); case REL_TIME_CHAPTER: return talloc_asprintf(NULL, "#%g", t->pos); case REL_TIME_PERCENT: @@ -3128,7 +3166,7 @@ print_help: ; } else if (list->print_unknown_entry_help) { list->print_unknown_entry_help(log, mp_tprintf(80, "%.*s", BSTR_P(name))); } else { - mp_warn(log, "Option %.*s: item %.*s doesn't exist.\n", + mp_warn(log, "Option %.*s: item '%.*s' isn't supported.\n", BSTR_P(opt_name), BSTR_P(name)); } r = M_OPT_EXIT; @@ -3183,7 +3221,7 @@ static int parse_obj_settings(struct mp_log *log, struct bstr opt, int op, int idx = bstrspn(*pstr, NAMECH); str = bstr_splice(*pstr, 0, idx); if (!str.len) { - mp_err(log, "Option %.*s: filter name expected.\n", BSTR_P(opt)); + mp_err(log, "Option %.*s: item name expected.\n", BSTR_P(opt)); return M_OPT_INVALID; } *pstr = bstr_cut(*pstr, idx); @@ -3199,10 +3237,8 @@ static int parse_obj_settings(struct mp_log *log, struct bstr opt, int op, } else { char name[80]; snprintf(name, sizeof(name), "%.*s", BSTR_P(str)); - if (!list->allow_unknown_entries || - (list->check_unknown_entry && !list->check_unknown_entry(name))) - { - mp_err(log, "Option %.*s: %.*s doesn't exist.\n", + if (list->check_unknown_entry && !list->check_unknown_entry(name)) { + mp_err(log, "Option %.*s: '%.*s' isn't supported.\n", BSTR_P(opt), BSTR_P(str)); return M_OPT_INVALID; } @@ -3235,11 +3271,10 @@ done: ; return 1; } -// Parse a single entry for -vf-del (return 0 if not applicable) +// Parse a single entry for -vf-remove (return 0 if not applicable) // mark_del is bounded by the number of items in dst static int parse_obj_settings_del(struct mp_log *log, struct bstr opt_name, - struct bstr *param, int op, - void *dst, bool *mark_del) + struct bstr *param, void *dst, bool *mark_del) { bstr s = *param; if (bstr_eatstart0(&s, "@")) { @@ -3251,7 +3286,8 @@ static int parse_obj_settings_del(struct mp_log *log, struct bstr opt_name, if (bstr_startswith0(s, ":")) return 0; if (dst) { - int label_index = obj_settings_list_find_by_label(VAL(dst), label); + int label_index = 0; + label_index = obj_settings_list_find_by_label(VAL(dst), label); if (label_index >= 0) { mark_del[label_index] = true; } else { @@ -3262,30 +3298,7 @@ static int parse_obj_settings_del(struct mp_log *log, struct bstr opt_name, *param = s; return 1; } - - if (op == OP_REMOVE) - return 0; - - bstr rest; - long long id = bstrtoll(s, &rest, 0); - if (rest.len == s.len) - return 0; - - if (dst) { - int num = obj_settings_list_num_items(VAL(dst)); - if (id < 0) - id = num + id; - - if (id >= 0 && id < num) { - mark_del[id] = true; - } else { - mp_warn(log, "Option %.*s: Index %lld is out of range.\n", - BSTR_P(opt_name), id); - } - } - - *param = rest; - return 1; + return 0; } static int parse_obj_settings_list(struct mp_log *log, const m_option_t *opt, @@ -3295,7 +3308,7 @@ static int parse_obj_settings_list(struct mp_log *log, const m_option_t *opt, int op = OP_NONE; bool *mark_del = NULL; int num_items = obj_settings_list_num_items(dst ? VAL(dst) : 0); - struct m_obj_list *ol = opt->priv; + const struct m_obj_list *ol = opt->priv; assert(opt->priv); @@ -3307,11 +3320,6 @@ static int parse_obj_settings_list(struct mp_log *log, const m_option_t *opt, op = OP_NONE; } else if (bstr_endswith0(name, "-pre")) { op = OP_PRE; - } else if (bstr_endswith0(name, "-del")) { - op = OP_DEL; - mp_warn(log, "Option %.*s: -del is deprecated! " - "Use -remove (removes by content instead of by index).\n", - BSTR_P(name)); } else if (bstr_endswith0(name, "-remove")) { op = OP_REMOVE; } else if (bstr_endswith0(name, "-clr")) { @@ -3324,23 +3332,19 @@ static int parse_obj_settings_list(struct mp_log *log, const m_option_t *opt, " %s-set\n" " Overwrite the old list with the given list\n\n" " %s-append\n" - " Append the given filter to the current list\n\n" + " Append the given item to the current list\n\n" " %s-add\n" " Append the given list to the current list\n\n" " %s-pre\n" " Prepend the given list to the current list\n\n" " %s-remove\n" - " Remove the given filter from the current list\n\n" - " %s-del x,y,...\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" - " Filter names work as well.\n\n" + " Remove the given item from the current list\n\n" " %s-toggle\n" - " Add the filter to the list, or remove it if it's already added.\n\n" + " Add the item to the list, or remove it if it's already added.\n\n" " %s-clr\n" " Clear the current list.\n\n", opt->name, opt->name, opt->name, opt->name, opt->name, - opt->name, opt->name, opt->name, opt->name); + opt->name, opt->name, opt->name); return M_OPT_EXIT; } @@ -3375,7 +3379,7 @@ static int parse_obj_settings_list(struct mp_log *log, const m_option_t *opt, if (dst) free_obj_settings_list(dst); return 0; - } else if (op == OP_DEL || op == OP_REMOVE) { + } else if (op == OP_REMOVE) { mark_del = talloc_zero_array(NULL, bool, num_items + 1); } @@ -3384,20 +3388,26 @@ static int parse_obj_settings_list(struct mp_log *log, const m_option_t *opt, while (param.len > 0) { int r = 0; - if (op == OP_DEL || op == OP_REMOVE) - r = parse_obj_settings_del(log, name, ¶m, op, dst, mark_del); + if (op == OP_REMOVE) + r = parse_obj_settings_del(log, name, ¶m, dst, mark_del); if (r == 0) { r = parse_obj_settings(log, name, op, ¶m, ol, dst ? &res : NULL); } - if (r < 0) + if (r < 0) { + free_obj_settings_list(&res); return r; + } if (param.len > 0) { const char sep[2] = {OPTION_LIST_SEPARATOR, 0}; - if (!bstr_eatstart0(¶m, sep)) + if (!bstr_eatstart0(¶m, sep)) { + free_obj_settings_list(&res); return M_OPT_INVALID; + } if (param.len == 0) { - if (!ol->allow_trailer) + if (!ol->allow_trailer) { + free_obj_settings_list(&res); return M_OPT_INVALID; + } if (dst) { m_obj_settings_t item = { .name = talloc_strdup(NULL, ""), @@ -3410,8 +3420,9 @@ static int parse_obj_settings_list(struct mp_log *log, const m_option_t *opt, if (op != OP_NONE && res && res[0].name && res[1].name) { if (op == OP_APPEND) { - mp_err(log, "Option %.*s: -append takes only 1 filter (no ',').\n", + mp_err(log, "Option %.*s: -append takes only 1 item (no ',').\n", BSTR_P(name)); + free_obj_settings_list(&res); return M_OPT_INVALID; } mp_warn(log, "Passing more than 1 argument to %.*s is deprecated!\n", @@ -3472,19 +3483,15 @@ static int parse_obj_settings_list(struct mp_log *log, const m_option_t *opt, } } talloc_free(res); - } else if (op == OP_DEL || op == OP_REMOVE) { + } else if (op == OP_REMOVE) { for (int n = num_items - 1; n >= 0; n--) { if (mark_del[n]) obj_settings_list_del_at(&list, n); } for (int n = 0; res && res[n].name; n++) { int found = obj_settings_find_by_content(list, &res[n]); - if (found < 0) { - if (op == OP_DEL) - mp_warn(log, "Option %.*s: Item not found\n", BSTR_P(name)); - } else { + if (found >= 0) obj_settings_list_del_at(&list, found); - } } free_obj_settings_list(&res); } else { @@ -3650,7 +3657,7 @@ static bool obj_settings_list_equal(const m_option_t *opt, void *pa, void *pb) struct m_obj_settings *b = VAL(pb); if (a == b || !a || !b) - return a == b; + return a == b || (!a && !b[0].name) || (!b && !a[0].name); for (int n = 0; a[n].name || b[n].name; n++) { if (!a[n].name || !b[n].name) @@ -3690,7 +3697,6 @@ const m_option_type_t m_option_type_obj_settings_list = { {"add"}, {"append"}, {"clr", M_OPT_TYPE_OPTIONAL_PARAM}, - {"del"}, {"help", M_OPT_TYPE_OPTIONAL_PARAM}, {"pre"}, {"set"}, @@ -3757,6 +3763,16 @@ static void dup_node(void *ta_parent, struct mpv_node *node) } break; } + case MPV_FORMAT_BYTE_ARRAY: { + struct mpv_byte_array *old = node->u.ba; + struct mpv_byte_array *new = talloc_zero(ta_parent, struct mpv_byte_array); + node->u.ba = new; + if (old->size > 0) { + *new = *old; + new->data = talloc_memdup(new, old->data, old->size); + } + break; + } case MPV_FORMAT_NONE: case MPV_FORMAT_FLAG: case MPV_FORMAT_INT64: @@ -3770,7 +3786,7 @@ static void dup_node(void *ta_parent, struct mpv_node *node) static void copy_node(const m_option_t *opt, void *dst, const void *src) { - assert(sizeof(struct mpv_node) <= sizeof(union m_option_value)); + static_assert(sizeof(struct mpv_node) <= sizeof(union m_option_value), ""); if (!(dst && src)) return; |