From 1eb533afb379ac9addb9205bf25e32cdc9442e93 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 27 Feb 2015 18:31:24 +0100 Subject: options: handle choice -> flag fallback automatically In the past it happened quite often that flag options (yes/no) were changed to choice options (yes/no/some more). The problem with this was that while flag options don't need a parameter, this wasn't the case with choice options. A hack was introduced to compensate for this: setting M_OPT_OPTIONAL_PARAM on the option, and an empty string ("") was added as choice, so that the choice could be used like a flag. So, for example, "--mute" would set the choice "". Fix this by 1. not requiring a parameter if there's a "yes" choice, and 2. redirect an empty parameter to "yes". The effect is that a choice option with the choices ["yes", "no"] is pretty much equivalent to a flag option. --- options/m_option.c | 20 +++++++++++++++++--- options/m_option.h | 3 --- options/options.c | 26 +++++++++++++------------- 3 files changed, 30 insertions(+), 19 deletions(-) (limited to 'options') diff --git a/options/m_option.c b/options/m_option.c index 699ecb4539..b5f9930068 100644 --- a/options/m_option.c +++ b/options/m_option.c @@ -74,9 +74,15 @@ char *m_option_strerror(int code) int m_option_required_params(const m_option_t *opt) { - if (((opt->flags & M_OPT_OPTIONAL_PARAM) || - (opt->type->flags & M_OPT_TYPE_OPTIONAL_PARAM))) + if (opt->type->flags & M_OPT_TYPE_OPTIONAL_PARAM) return 0; + if (opt->type == &m_option_type_choice) { + struct m_opt_choice_alternatives *alt; + for (alt = opt->priv; alt->name; alt++) { + if (strcmp(alt->name, "yes") == 0) + return 0; + } + } return 1; } @@ -535,9 +541,17 @@ 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; - for ( ; alt->name; alt++) + for ( ; alt->name; alt++) { if (!bstrcmp0(param, alt->name)) break; + } + if (!alt->name && param.len == 0) { + // allow flag-style options, e.g. "--mute" implies "--mute=yes" + for (alt = opt->priv; alt->name; alt++) { + if (!strcmp("yes", alt->name)) + break; + } + } if (!alt->name) { if (param.len == 0) return M_OPT_MISSING_PARAM; diff --git a/options/m_option.h b/options/m_option.h index c05e2d760c..c26d1b3529 100644 --- a/options/m_option.h +++ b/options/m_option.h @@ -358,9 +358,6 @@ struct m_option { // The option should be set during command line pre-parsing #define M_OPT_PRE_PARSE (1 << 6) -// See M_OPT_TYPE_OPTIONAL_PARAM. -#define M_OPT_OPTIONAL_PARAM (1 << 10) - // The option expects a file name (or a list of file names) #define M_OPT_FILE (1 << 11) diff --git a/options/options.c b/options/options.c index cc79a2d941..13727849b5 100644 --- a/options/options.c +++ b/options/options.c @@ -189,9 +189,9 @@ const m_option_t mp_opts[] = { OPT_TIME("ab-loop-b", ab_loop[1], 0, .min = MP_NOPTS_VALUE), OPT_FLAG("pause", pause, M_OPT_FIXED), - OPT_CHOICE("keep-open", keep_open, M_OPT_OPTIONAL_PARAM, + OPT_CHOICE("keep-open", keep_open, 0, ({"no", 0}, - {"yes", 1}, {"", 1}, + {"yes", 1}, {"always", 2})), OPT_CHOICE("index", index_mode, 0, ({"default", 1}, {"recreate", 0})), @@ -274,10 +274,10 @@ const m_option_t mp_opts[] = { OPT_SETTINGSLIST("vf-defaults", vf_defs, 0, &vf_obj_list), OPT_SETTINGSLIST("vf*", vf_settings, 0, &vf_obj_list), - OPT_CHOICE("deinterlace", deinterlace, M_OPT_OPTIONAL_PARAM, + OPT_CHOICE("deinterlace", deinterlace, 0, ({"auto", -1}, {"no", 0}, - {"yes", 1}, {"", 1})), + {"yes", 1})), OPT_STRING("ad", audio_decoders, 0), OPT_STRING("vd", video_decoders, 0), @@ -386,14 +386,14 @@ const m_option_t mp_opts[] = { {"auto", SOFTVOL_AUTO})), OPT_FLOATRANGE("softvol-max", softvol_max, 0, 10, 10000), OPT_FLOATRANGE("volume", mixer_init_volume, 0, -1, 100), - OPT_CHOICE("mute", mixer_init_mute, M_OPT_OPTIONAL_PARAM, + OPT_CHOICE("mute", mixer_init_mute, 0, ({"auto", -1}, {"no", 0}, - {"yes", 1}, {"", 1})), + {"yes", 1})), OPT_STRING("volume-restore-data", mixer_restore_volume_data, 0), - OPT_CHOICE("gapless-audio", gapless_audio, M_OPT_OPTIONAL_PARAM, + OPT_CHOICE("gapless-audio", gapless_audio, 0, ({"no", 0}, - {"yes", 1}, {"", 1}, + {"yes", 1}, {"weak", -1})), OPT_DOUBLE("audio-buffer", audio_buffer, M_OPT_MIN | M_OPT_MAX, .min = 0, .max = 10), @@ -505,8 +505,9 @@ const m_option_t mp_opts[] = { ({"no", 1}, {"inf", -1}, {"force", -2})), - OPT_CHOICE_OR_INT("loop-file", loop_file, M_OPT_OPTIONAL_PARAM, 0, 10000, - ({"yes", -1}, {"", -1}, {"no", 0}, // compat + OPT_CHOICE_OR_INT("loop-file", loop_file, 0, 0, 10000, + ({"no", 0}, + {"yes", -1}, {"inf", -1})), OPT_FLAG("resume-playback", position_resume, 0), @@ -553,11 +554,10 @@ const m_option_t mp_opts[] = { OPT_STRING("osd-msg2", osd_msg[1], 0), OPT_STRING("osd-msg3", osd_msg[2], 0), - OPT_CHOICE("idle", player_idle_mode, M_OPT_OPTIONAL_PARAM, + OPT_CHOICE("idle", player_idle_mode, 0, ({"no", 0}, {"once", 1}, - {"yes", 2}, - {"", 2})), + {"yes", 2})), OPT_FLAG("input-terminal", consolecontrols, CONF_GLOBAL), -- cgit v1.2.3