1
0
mirror of https://github.com/mpv-player/mpv synced 2024-12-20 22:02:59 +00:00

options: change handling of "no-" options

Normally, all flag options can be negated by prepending a "no-", for
example "--no-opt" becomes "--opt=no". Some flag options can't actually
be negated, so add a CONF_TYPE_STORE option type to disallow the "no-"
fallback.

Do the same for choice options. Remove the explicit "no-" prefixed
options, add "no" as choice.

Move the handling of automatic "no-" options from parser-mpcmd.c to
m_config.c, and use it in m_config_set_option/m_config_parse_option.
This makes these options available in the config file. It also
simplifies sub-option parsing, because it doesn't need to handle "no-"
anymore.
This commit is contained in:
wm4 2012-09-20 03:32:01 +02:00
parent ae070a6f1e
commit 830560979c
7 changed files with 101 additions and 60 deletions

View File

@ -71,7 +71,7 @@ const m_option_t radioopts_conf[]={
#ifdef CONFIG_TV
const m_option_t tvopts_conf[]={
{"immediatemode", &stream_tv_defaults.immediate, CONF_TYPE_INT, CONF_RANGE, 0, 1, NULL},
{"no-audio", &stream_tv_defaults.noaudio, CONF_TYPE_FLAG, 0, 0, 1, NULL},
{"audio", &stream_tv_defaults.noaudio, CONF_TYPE_FLAG, 0, 1, 0, NULL},
{"audiorate", &stream_tv_defaults.audiorate, CONF_TYPE_INT, 0, 0, 0, NULL},
{"driver", &stream_tv_defaults.driver, CONF_TYPE_STRING, 0, 0, 0, NULL},
{"device", &stream_tv_defaults.device, CONF_TYPE_STRING, 0, 0, 0, NULL},
@ -288,9 +288,9 @@ extern const m_option_t lavc_decode_opts_conf[];
const m_option_t common_opts[] = {
// ------------------------- common options --------------------
OPT_MAKE_FLAGS("quiet", quiet, CONF_GLOBAL),
{"really-quiet", &verbose, CONF_TYPE_FLAG, CONF_GLOBAL|CONF_PRE_PARSE, 0, -10, NULL},
{"really-quiet", &verbose, CONF_TYPE_STORE, CONF_GLOBAL|CONF_PRE_PARSE, 0, -10, NULL},
// -v is handled in command line preparser
{"v", NULL, CONF_TYPE_FLAG, CONF_GLOBAL | CONF_NOCFG, 0, 0, NULL},
{"v", NULL, CONF_TYPE_STORE, CONF_GLOBAL | CONF_NOCFG, 0, 0, NULL},
{"msglevel", (void *) msgl_config, CONF_TYPE_SUBCONFIG, CONF_GLOBAL, 0, 0, NULL},
{"msgcolor", &mp_msg_color, CONF_TYPE_FLAG, CONF_GLOBAL | CONF_PRE_PARSE, 0, 1, NULL},
{"msgmodule", &mp_msg_module, CONF_TYPE_FLAG, CONF_GLOBAL, 0, 1, NULL},
@ -303,9 +303,9 @@ const m_option_t common_opts[] = {
// ------------------------- stream options --------------------
#ifdef CONFIG_STREAM_CACHE
OPT_INTRANGE("cache", stream_cache_size, 0, 32, 0x7fffffff, OPTDEF_INT(-1)),
OPT_FLAG_CONSTANTS("no-cache", stream_cache_size, 0, -1, 0),
OPT_CHOICE_OR_INT("cache", stream_cache_size, 0, 32, 0x7fffffff,
({"no", -1}),
OPTDEF_INT(-1)),
OPT_FLOATRANGE("cache-min", stream_cache_min_percent, 0, 0, 99),
OPT_FLOATRANGE("cache-seek-min", stream_cache_seek_min_percent, 0, 0, 99),
OPT_CHOICE_OR_INT("cache-pause", stream_cache_pause, 0,
@ -367,9 +367,9 @@ const m_option_t common_opts[] = {
OPT_TRACKCHOICE("aid", audio_id),
OPT_TRACKCHOICE("vid", video_id),
OPT_TRACKCHOICE("sid", sub_id),
OPT_FLAG_CONSTANTS("no-sub", sub_id, 0, -1, -2),
OPT_FLAG_CONSTANTS("no-video", video_id, 0, -1, -2),
OPT_FLAG_CONSTANTS("no-audio", audio_id, 0, -1, -2),
OPT_FLAG_STORE("no-sub", sub_id, 0, -2),
OPT_FLAG_STORE("no-video", video_id, 0, -2),
OPT_FLAG_STORE("no-audio", audio_id, 0, -2),
OPT_STRINGLIST("alang", audio_lang, 0),
OPT_STRINGLIST("slang", sub_lang, 0),
@ -462,7 +462,8 @@ const m_option_t common_opts[] = {
{"sws", &sws_flags, CONF_TYPE_INT, 0, 0, 2, NULL},
{"ssf", (void *) scaler_filter_conf, CONF_TYPE_SUBCONFIG, 0, 0, 0, NULL},
OPT_FLOATRANGE("aspect", movie_aspect, 0, 0.1, 10.0),
OPT_FLAG_CONSTANTS("no-aspect", movie_aspect, 0, 0, 0),
// xxx: this aliases int with float, which is very evil (but works in this case)
OPT_FLAG_STORE("no-aspect", movie_aspect, 0, 0),
OPT_FLAG_CONSTANTS("flip", flip, 0, 0, 1),
@ -579,7 +580,7 @@ const m_option_t mplayer_opts[]={
// set bpp (x11+vm)
OPT_INTRANGE("bpp", vo_dbpp, 0, 0, 32),
{"colorkey", &vo_colorkey, CONF_TYPE_INT, 0, 0, 0, NULL},
{"no-colorkey", &vo_colorkey, CONF_TYPE_FLAG, 0, 0, 0x1000000, NULL},
{"no-colorkey", &vo_colorkey, CONF_TYPE_STORE, 0, 0, 0x1000000, NULL},
// wait for v-sync (gl)
{"vsync", &vo_vsync, CONF_TYPE_FLAG, 0, 0, 1, NULL},
{"panscan", &vo_panscan, CONF_TYPE_FLOAT, CONF_RANGE, 0, 1.0, NULL},
@ -645,8 +646,7 @@ const m_option_t mplayer_opts[]={
{"leak-report", "", CONF_TYPE_PRINT, 0, 0, 0, (void*)1},
OPT_FLAG_CONSTANTS("no-loop", loop_times, 0, 0, -1),
OPT_CHOICE_OR_INT("loop", loop_times, CONF_GLOBAL, 1, 10000,
OPT_CHOICE_OR_INT("loop", loop_times, M_OPT_GLOBAL, 1, 10000,
({"no", -1}, {"0", -1},
{"inf", 0})),
@ -666,8 +666,8 @@ const m_option_t mplayer_opts[]={
OPT_CHOICE("hr-seek", hr_seek, 0,
({"no", -1}, {"absolute", 0}, {"always", 1}, {"yes", 1})),
OPT_FLOATRANGE("hr-seek-demuxer-offset", hr_seek_demuxer_offset, 0, -9, 99),
OPT_FLAG_CONSTANTS("no-autosync", autosync, 0, 0, -1),
OPT_INTRANGE("autosync", autosync, 0, 0, 10000),
OPT_CHOICE_OR_INT("autosync", autosync, 0, 0, 10000,
({"no", -1})),
OPT_FLAG_ON("softsleep", softsleep, 0),

View File

@ -392,6 +392,13 @@ static int m_config_parse_option(struct m_config *config, void *optstruct,
assert(config != NULL);
assert(name.len != 0);
if (m_config_map_option(config, &name, &param) == M_OPT_INVALID) {
mp_tmsg(MSGT_CFGPARSER, MSGL_ERR,
"A no-* option can't take parameters: --%.*s=%.*s\n",
BSTR_P(name), BSTR_P(param));
return M_OPT_INVALID;
}
struct m_config_option *co = m_config_get_co(config, name);
if (!co)
return M_OPT_UNKNOWN;
@ -446,32 +453,15 @@ static int parse_subopts(struct m_config *config, void *optstruct, char *name,
char n[110];
if (snprintf(n, 110, "%s%s", prefix, lst[2 * i]) > 100)
abort();
if (!m_config_get_option(config, bstr0(n))) {
if (strncmp(lst[2 * i], "no-", 3))
goto nosubopt;
snprintf(n, 110, "%s%s", prefix, lst[2 * i] + 3);
const struct m_option *o = m_config_get_option(config, bstr0(n));
if (!o || o->type != &m_option_type_flag) {
nosubopt:
int sr = m_config_parse_option(config, optstruct, bstr0(n),
bstr0(lst[2 * i + 1]), set);
if (sr < 0) {
if (sr == M_OPT_UNKNOWN) {
mp_tmsg(MSGT_CFGPARSER, MSGL_ERR,
"Error: option '%s' has no suboption '%s'.\n",
name, lst[2 * i]);
r = M_OPT_INVALID;
break;
}
if (lst[2 * i + 1]) {
mp_tmsg(MSGT_CFGPARSER, MSGL_ERR,
"A --no-* option can't take parameters: "
"%s=%s\n", lst[2 * i], lst[2 * i + 1]);
r = M_OPT_INVALID;
break;
}
lst[2 * i + 1] = "no";
}
int sr = m_config_parse_option(config, optstruct, bstr0(n),
bstr0(lst[2 * i + 1]), set);
if (sr < 0) {
if (sr == M_OPT_MISSING_PARAM) {
} else if (sr == M_OPT_MISSING_PARAM) {
mp_tmsg(MSGT_CFGPARSER, MSGL_ERR,
"Error: suboption '%s' of '%s' must have "
"a parameter!\n", lst[2 * i], name);
@ -532,6 +522,29 @@ const struct m_option *m_config_get_option(const struct m_config *config,
return NULL;
}
int m_config_map_option(struct m_config *config, bstr *name, bstr *param)
{
bstr s = *name;
if (m_config_get_option(config, s))
return 0;
if (!bstr_eatstart0(&s, "no-"))
return M_OPT_UNKNOWN;
const struct m_option *opt = m_config_get_option(config, s);
if (!opt || (opt->type != &m_option_type_flag
&& opt->type != &m_option_type_choice))
return M_OPT_UNKNOWN;
// Avoid allowing "--no-no-opt".
if (bstr_startswith(bstr0(opt->name), bstr0("no-")))
return M_OPT_UNKNOWN;
if (param->len)
return M_OPT_INVALID;
*name = s;
*param = bstr0("no");
return 0;
}
void m_config_print_option_list(const struct m_config *config)
{
char min[50], max[50];

View File

@ -155,6 +155,17 @@ const struct m_option *m_config_get_option(const struct m_config *config,
struct m_config_option *m_config_get_co(const struct m_config *config,
struct bstr name);
/* Map options like "no-opt=" to "opt=no".
* config The config object.
* \param name The option's name. May be set to a new name.
* \param param The option value. May be set to a new value.
* \return The following error codes:
* M_OPT_UNKNOWN: option not found
* M_OPT_INVALID: parameter non-empty in map case, prevents the mapping
* 0: success, *name and *param have been changed (or not)
*/
int m_config_map_option(struct m_config *config, bstr *name, bstr *param);
/* Print a list of all registered options.
* \param config The config object.
*/

View File

@ -152,6 +152,31 @@ const m_option_type_t m_option_type_flag = {
.clamp = clamp_flag,
};
// Single-value, write-only flag
static int parse_store(const m_option_t *opt, struct bstr name,
struct bstr param, void *dst)
{
if (param.len == 0 || bstrcasecmp0(param, "yes") == 0) {
if (dst)
VAL(dst) = opt->max;
return 0;
} else {
mp_msg(MSGT_CFGPARSER, MSGL_ERR,
"Invalid parameter for %.*s flag: %.*s\n",
BSTR_P(name), BSTR_P(param));
return M_OPT_INVALID;
}
}
const m_option_type_t m_option_type_store = {
// can only be activated
.name = "Flag",
.size = sizeof(int),
.flags = M_OPT_TYPE_OLD_SYNTAX_NO_PARAM,
.parse = parse_store,
};
// Integer
#undef VAL

View File

@ -36,6 +36,7 @@ struct m_struct_st;
// Simple types
extern const m_option_type_t m_option_type_flag;
extern const m_option_type_t m_option_type_store;
extern const m_option_type_t m_option_type_int;
extern const m_option_type_t m_option_type_int64;
extern const m_option_type_t m_option_type_intpair;
@ -180,6 +181,7 @@ struct m_sub_options {
// FIXME: backward compatibility
#define CONF_TYPE_FLAG (&m_option_type_flag)
#define CONF_TYPE_STORE (&m_option_type_store)
#define CONF_TYPE_INT (&m_option_type_int)
#define CONF_TYPE_INT64 (&m_option_type_int64)
#define CONF_TYPE_FLOAT (&m_option_type_float)
@ -205,6 +207,7 @@ struct m_sub_options {
// size/alignment requirements for option values in general.
union m_option_value {
int flag; // not the C type "bool"!
int store;
int int_;
int64_t int64;
float float_;
@ -513,6 +516,7 @@ static inline void m_option_free(const m_option_t *opt, void *dst)
#define OPT_MAKE_FLAGS OPT_FLAG_ON
#define OPT_FLAG_CONSTANTS(...) OPT_FLAG_CONSTANTS_(__VA_ARGS__, .type = &m_option_type_flag)
#define OPT_FLAG_CONSTANTS_(optname, varname, flags, offvalue, value, ...) OPT_GENERAL(optname, varname, flags, .min = offvalue, .max = value, __VA_ARGS__)
#define OPT_FLAG_STORE(optname, varname, flags, value) OPT_GENERAL(optname, varname, flags, .max = value, .type = &m_option_type_store)
#define OPT_STRINGLIST(...) OPT_GENERAL(__VA_ARGS__, .type = &m_option_type_string_list)
#define OPT_PATHLIST(...) OPT_GENERAL(__VA_ARGS__, .type = &m_option_type_string_list, .priv = (void *)&(const char){OPTION_PATH_SEPARATOR})
#define OPT_INT(...) OPT_GENERAL(__VA_ARGS__, .type = &m_option_type_int)

View File

@ -87,32 +87,21 @@ static int split_opt_silent(struct parse_state *p)
}
}
p->mp_opt = m_config_get_option(p->config, p->arg);
if (!p->mp_opt) {
// Automagic "no-" arguments: "--no-bla" turns into "--bla=no".
if (!bstr_startswith0(p->arg, "no-"))
return -1;
if (m_config_map_option(p->config, &p->arg, &p->param) == M_OPT_INVALID)
return -2;
struct bstr s = bstr_cut(p->arg, 3);
p->mp_opt = m_config_get_option(p->config, s);
if (!p->mp_opt || p->mp_opt->type != &m_option_type_flag)
return -1;
// Avoid allowing "--no-no-bla".
if (bstr_startswith(bstr0(p->mp_opt->name), bstr0("no-")))
return -1;
// Flag options never have parameters.
p->mp_opt = m_config_get_option(p->config, p->arg);
if (!p->mp_opt)
return -1;
if ((p->mp_opt->type->flags & M_OPT_TYPE_OLD_SYNTAX_NO_PARAM)
|| p->param.len
|| bstr_endswith0(p->arg, "-clr"))
{
old_syntax = false;
if (p->param.len)
return -2;
p->arg = s;
p->param = bstr0("no");
}
if (bstr_endswith0(p->arg, "-clr"))
old_syntax = false;
if (old_syntax && !(p->mp_opt->type->flags & M_OPT_TYPE_OLD_SYNTAX_NO_PARAM))
{
if (old_syntax) {
if (p->argc < 1)
return -3;
p->param = bstr0(p->argv[0]);

View File

@ -1643,7 +1643,6 @@ const struct vo_driver video_out_vdpau = {
.options = (const struct m_option []){
OPT_INTRANGE("deint", deint, 0, -4, 4),
OPT_FLAG_ON("chroma-deint", chroma_deint, 0, OPTDEF_INT(1)),
OPT_FLAG_OFF("nochroma-deint", chroma_deint, 0),
OPT_MAKE_FLAGS("pullup", pullup, 0),
OPT_FLOATRANGE("denoise", denoise, 0, 0, 1),
OPT_FLOATRANGE("sharpen", sharpen, 0, -1, 1),