mirror of
https://github.com/mpv-player/mpv
synced 2024-12-27 01:22:30 +00:00
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:
parent
f2e3a49810
commit
999dad454f
@ -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))
|
if (bstr_equals0(name, dst->name))
|
||||||
return true;
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1947,6 +1968,9 @@ static int get_obj_param(bstr opt_name, bstr obj_name, struct m_config *config,
|
|||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
if (!config)
|
||||||
|
return 0; // skip
|
||||||
|
|
||||||
// va.start != NULL => of the form name=val (not positional)
|
// va.start != NULL => of the form name=val (not positional)
|
||||||
// If it's just "name", and the associated option exists and is a flag,
|
// If it's just "name", and the associated option exists and is a flag,
|
||||||
// don't accept it as positional argument.
|
// 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 num_args = 0;
|
||||||
int r = 1;
|
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);
|
struct m_config *config = m_config_from_obj_desc(NULL, desc);
|
||||||
|
|
||||||
while (pstr->len > 0) {
|
while (pstr->len > 0) {
|
||||||
@ -2048,7 +2078,12 @@ static int get_obj_params(struct bstr opt_name, struct bstr name,
|
|||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
print_help: ;
|
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;
|
r = M_OPT_EXIT - 1;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
@ -2082,13 +2117,26 @@ static int parse_obj_settings(struct bstr opt, struct bstr *pstr,
|
|||||||
int idx = bstrspn(*pstr, NAMECH);
|
int idx = bstrspn(*pstr, NAMECH);
|
||||||
bstr str = bstr_splice(*pstr, 0, idx);
|
bstr str = bstr_splice(*pstr, 0, idx);
|
||||||
*pstr = bstr_cut(*pstr, 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;
|
has_param = true;
|
||||||
|
|
||||||
if (!m_obj_list_find(&desc, list, str)) {
|
if (!m_obj_list_find(&desc, list, str)) {
|
||||||
mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %.*s: %.*s doesn't exist.\n",
|
if (!list->allow_unknown_entries) {
|
||||||
BSTR_P(opt), BSTR_P(str));
|
mp_msg(MSGT_CFGPARSER, MSGL_ERR, "Option %.*s: %.*s doesn't exist.\n",
|
||||||
return M_OPT_INVALID;
|
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) {
|
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);
|
bstr param = bstr_splice(*pstr, 0, next);
|
||||||
*pstr = bstr_cut(*pstr, next);
|
*pstr = bstr_cut(*pstr, next);
|
||||||
if (!bstrcmp0(param, "help")) {
|
if (!bstrcmp0(param, "help")) {
|
||||||
mp_msg(MSGT_CFGPARSER, MSGL_INFO,
|
mp_msg(MSGT_CFGPARSER, MSGL_WARN,
|
||||||
"Option %.*s: %.*s has no option description.\n",
|
"Option %.*s: %.*s has no option description.\n",
|
||||||
BSTR_P(opt), BSTR_P(str));
|
BSTR_P(opt), BSTR_P(str));
|
||||||
return M_OPT_EXIT - 1;
|
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)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
const char sep[2] = {OPTION_LIST_SEPARATOR, 0};
|
if (param.len > 0) {
|
||||||
if (param.len > 0 && !bstr_eatstart0(¶m, sep))
|
const char sep[2] = {OPTION_LIST_SEPARATOR, 0};
|
||||||
return M_OPT_INVALID;
|
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) {
|
if (dst) {
|
||||||
|
@ -106,12 +106,23 @@ struct m_obj_desc {
|
|||||||
const struct m_option *options;
|
const struct m_option *options;
|
||||||
// For free use by the implementer of m_obj_list.get_desc
|
// For free use by the implementer of m_obj_list.get_desc
|
||||||
const void *p;
|
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.
|
// Extra definition needed for \ref m_option_type_obj_settings_list options.
|
||||||
struct m_obj_list {
|
struct m_obj_list {
|
||||||
bool (*get_desc)(struct m_obj_desc *dst, int index);
|
bool (*get_desc)(struct m_obj_desc *dst, int index);
|
||||||
const char *description;
|
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
|
// Find entry by name
|
||||||
|
Loading…
Reference in New Issue
Block a user