From 999dad454f6db2c3d52e9594778bccc03156d299 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 21 Jul 2013 21:17:25 +0200 Subject: options: add some features to video filter parser This is in preparation of making VOs and AOs use the parser which originally was for video filters only. The --vo and --ao options have several very annoying features, which are added here: - They can skip unknown video outputs (might be useful if a config file is supposed to work on several systems, where not all VOs/AOs are available everywhere) - The trailing "," in "-vo a,b," was significant, and meant that if "a" and "b" don't work, try the normal autoprobe order as fallback - There were deprecated VO names (like "gl3" and "gl"), which have to be handled with the option parser - Separating VO/VF names and options is different ("-vf foo=opts" vs. "-vo foo:opts") - vo_opengl.c provides opengl-hq as opengl + preset options --- core/m_option.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++------- core/m_option.h | 11 ++++++++ 2 files changed, 80 insertions(+), 9 deletions(-) diff --git a/core/m_option.c b/core/m_option.c index 59864d93ad..3a14564830 100644 --- a/core/m_option.c +++ b/core/m_option.c @@ -1790,6 +1790,27 @@ bool m_obj_list_find(struct m_obj_desc *dst, const struct m_obj_list *l, if (bstr_equals0(name, dst->name)) return true; } + if (l->aliases) { + for (int i = 0; l->aliases[i][0]; i++) { + const char *aname = l->aliases[i][0]; + const char *alias = l->aliases[i][1]; + const char *opts = l->aliases[i][2]; + if (bstr_equals0(name, aname) && + m_obj_list_find(dst, l, bstr0(alias))) + { + if (opts) { + dst->init_options = opts; + } else { + // Assume it's deprecated in this case. + // Also, it's used by the VO code only, so whatever. + mp_msg(MSGT_CFGPARSER, MSGL_WARN, + "VO driver '%s' has been replaced with '%s'!\n", + aname, alias); + } + return true; + } + } + } return false; } @@ -1947,6 +1968,9 @@ static int get_obj_param(bstr opt_name, bstr obj_name, struct m_config *config, { int r; + if (!config) + return 0; // skip + // va.start != NULL => of the form name=val (not positional) // If it's just "name", and the associated option exists and is a flag, // don't accept it as positional argument. @@ -2010,6 +2034,12 @@ static int get_obj_params(struct bstr opt_name, struct bstr name, int num_args = 0; int r = 1; + if (ret) { + args = *ret; + while (args && args[num_args]) + num_args++; + } + struct m_config *config = m_config_from_obj_desc(NULL, desc); while (pstr->len > 0) { @@ -2048,7 +2078,12 @@ static int get_obj_params(struct bstr opt_name, struct bstr name, goto exit; print_help: ; - m_config_print_option_list(config); + if (config) { + m_config_print_option_list(config); + } else { + mp_msg(MSGT_CFGPARSER, MSGL_WARN, "Option %.*s doesn't exist.\n", + BSTR_P(opt_name)); + } r = M_OPT_EXIT - 1; exit: @@ -2082,13 +2117,26 @@ static int parse_obj_settings(struct bstr opt, struct bstr *pstr, int idx = bstrspn(*pstr, NAMECH); bstr str = bstr_splice(*pstr, 0, idx); *pstr = bstr_cut(*pstr, idx); - if (bstr_eatstart0(pstr, "=")) + // video filters use "=", VOs use ":" + if (bstr_eatstart0(pstr, "=") || bstr_eatstart0(pstr, ":")) has_param = true; if (!m_obj_list_find(&desc, list, str)) { - mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %.*s: %.*s doesn't exist.\n", - BSTR_P(opt), BSTR_P(str)); - return M_OPT_INVALID; + if (!list->allow_unknown_entries) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %.*s: %.*s doesn't exist.\n", + BSTR_P(opt), BSTR_P(str)); + return M_OPT_INVALID; + } + desc = (struct m_obj_desc){0}; + } + + if (desc.init_options && desc.options && _ret) { + bstr s = bstr0(desc.init_options); + r = get_obj_params(opt, str, &s, &desc, &plist); + if (r < 0 || s.len > 0) { + mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Internal error: preset broken\n"); + return r; + } } if (has_param) { @@ -2099,7 +2147,7 @@ static int parse_obj_settings(struct bstr opt, struct bstr *pstr, bstr param = bstr_splice(*pstr, 0, next); *pstr = bstr_cut(*pstr, next); if (!bstrcmp0(param, "help")) { - mp_msg(MSGT_CFGPARSER, MSGL_INFO, + mp_msg(MSGT_CFGPARSER, MSGL_WARN, "Option %.*s: %.*s has no option description.\n", BSTR_P(opt), BSTR_P(str)); return M_OPT_EXIT - 1; @@ -2262,9 +2310,21 @@ static int parse_obj_settings_list(const m_option_t *opt, struct bstr name, } if (r < 0) return r; - const char sep[2] = {OPTION_LIST_SEPARATOR, 0}; - if (param.len > 0 && !bstr_eatstart0(¶m, sep)) - return M_OPT_INVALID; + if (param.len > 0) { + const char sep[2] = {OPTION_LIST_SEPARATOR, 0}; + if (!bstr_eatstart0(¶m, sep)) + return M_OPT_INVALID; + if (param.len == 0) { + if (!ol->allow_trailer) + return M_OPT_INVALID; + if (dst) { + m_obj_settings_t item = { + .name = talloc_strdup(NULL, ""), + }; + obj_settings_list_insert_at(&res, -1, &item); + } + } + } } if (dst) { diff --git a/core/m_option.h b/core/m_option.h index 5f95232076..7fd1ffd04c 100644 --- a/core/m_option.h +++ b/core/m_option.h @@ -106,12 +106,23 @@ struct m_obj_desc { const struct m_option *options; // For free use by the implementer of m_obj_list.get_desc const void *p; + // If not NULL, options which should be set before applying other options. + // This member is usually set my m_obj_list_find() only. + // Only works if options is not NULL. + const char *init_options; }; // Extra definition needed for \ref m_option_type_obj_settings_list options. struct m_obj_list { bool (*get_desc)(struct m_obj_desc *dst, int index); const char *description; + // Can be set to a NULL terminated array of aliases + const char *aliases[4][5]; + // Allow a trailing ",", which adds an entry with name="" + bool allow_trailer; + // Allow unknown entries, for which a dummy entry is inserted, and whose + // options are skipped and ignored. + bool allow_unknown_entries; }; // Find entry by name -- cgit v1.2.3