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
This commit is contained in:
wm4 2013-07-21 21:17:25 +02:00
parent f2e3a49810
commit 999dad454f
2 changed files with 80 additions and 9 deletions

View File

@ -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(&param, sep))
return M_OPT_INVALID;
if (param.len > 0) {
const char sep[2] = {OPTION_LIST_SEPARATOR, 0};
if (!bstr_eatstart0(&param, 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) {

View File

@ -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