diff options
author | wm4 <wm4@nowhere> | 2012-09-05 02:17:13 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2012-09-18 21:07:29 +0200 |
commit | c955549204c433abd1a3c8783f1b988e29315337 (patch) | |
tree | 47da7a2a9f552a810713b788513683f694eeec0c /command.c | |
parent | d29d4df634a9d847a2b5ef7a04f32726cd03c1ef (diff) | |
download | mpv-c955549204c433abd1a3c8783f1b988e29315337.tar.bz2 mpv-c955549204c433abd1a3c8783f1b988e29315337.tar.xz |
options: change --loop option, and extend choice option type
The --loop option takes slightly different parameters now. --loop=0
used to mean looping forever. Now it means looping is disabled (this is
more logical: 2 means playing 2 more times, 1 means playing 1 more time,
and 0 should mean playing not again).
Now --loop=inf must be used to enable looping forever.
Extend choice types to allow an optional range of integers as values.
If CONF_RANGE is added to the flags of a m_option_type_choice option,
m_option.min/max specify a range of allowed integer values. This can be
used to remove "special" values from make integer range options. These
special values are unintuitive, and sometimes expose mplayer internals
to the user. The (internal) choice values can be freely mixed with the
specified integer value range. If there are overlaps, the choice values
are preferred for conversion to/from strings.
Also make sure the extension to choice options works with properties.
Add the ability to step choice properties downwards, instead of just
upwards.
Diffstat (limited to 'command.c')
-rw-r--r-- | command.c | 90 |
1 files changed, 67 insertions, 23 deletions
@@ -105,6 +105,66 @@ static void rescale_input_coordinates(struct MPContext *mpctx, int ix, int iy, vo->dheight, vo_fs); } +static void choice_get_min_max(const struct m_option *opt, int *min, int *max) +{ + assert(opt->type == &m_option_type_choice); + *min = INT_MAX; + *max = INT_MIN; + for (struct m_opt_choice_alternatives *alt = opt->priv; alt->name; alt++) { + *min = FFMIN(*min, alt->value); + *max = FFMAX(*max, alt->value); + } + if ((opt->flags & M_OPT_MIN) && (opt->flags & M_OPT_MAX)) { + *min = FFMIN(*min, opt->min); + *max = FFMAX(*max, opt->max); + } +} + +static void check_choice(int dir, int val, bool *found, int *best, int choice) +{ + if ((dir == -1 && (!(*found) || choice > (*best)) && choice < val) || + (dir == +1 && (!(*found) || choice < (*best)) && choice > val)) + { + *found = true; + *best = choice; + } +} + +static int step_choice(const struct m_option *opt, int val, int add, bool wrap) +{ + assert(opt->type == &m_option_type_choice); + int dir = add > 0 ? +1 : -1; + bool found = false; + int best = 0; // init. value unused + + if (add == 0) + return val; + + if ((opt->flags & M_OPT_MIN) && (opt->flags & M_OPT_MAX)) { + int newval = val + add; + if (val >= opt->min && val <= opt->max && + newval >= opt->min && newval <= opt->max) + { + found = true; + best = newval; + } else { + check_choice(dir, val, &found, &best, opt->min); + check_choice(dir, val, &found, &best, opt->max); + } + } + + for (struct m_opt_choice_alternatives *alt = opt->priv; alt->name; alt++) + check_choice(dir, val, &found, &best, alt->value); + + if (!found) { + int min, max; + choice_get_min_max(opt, &min, &max); + best = (dir == -1) ^ wrap ? min : max; + } + + return best; +} + static int mp_property_generic_option(struct m_option *prop, int action, void *arg, MPContext *mpctx) { @@ -125,13 +185,9 @@ static int mp_property_generic_option(struct m_option *prop, int action, return M_PROPERTY_OK; case M_PROPERTY_STEP_UP: if (opt->type == &m_option_type_choice) { + int add = arg ? (*(int *)arg) : +1; int v = *(int *) valptr; - int best = v; - struct m_opt_choice_alternatives *alt; - for (alt = opt->priv; alt->name; alt++) - if ((unsigned) alt->value - v - 1 < (unsigned) best - v - 1) - best = alt->value; - *(int *) valptr = best; + *(int *) valptr = step_choice(opt, v, add, true); return M_PROPERTY_OK; } break; @@ -150,20 +206,7 @@ static int mp_property_osdlevel(m_option_t *prop, int action, void *arg, static int mp_property_loop(m_option_t *prop, int action, void *arg, MPContext *mpctx) { - struct MPOpts *opts = &mpctx->opts; - switch (action) { - case M_PROPERTY_PRINT: - if (!arg) - return M_PROPERTY_ERROR; - if (opts->loop_times < 0) - *(char **)arg = talloc_strdup(NULL, "off"); - else if (opts->loop_times == 0) - *(char **)arg = talloc_strdup(NULL, "inf"); - else - break; - return M_PROPERTY_OK; - } - return m_property_int_range(prop, action, arg, &opts->loop_times); + return mp_property_generic_option(prop, action, arg, mpctx); } /// Playback speed (RW) @@ -1628,8 +1671,8 @@ static const m_option_t mp_properties[] = { // General { "osdlevel", mp_property_osdlevel, CONF_TYPE_INT, M_OPT_RANGE, 0, 3, NULL }, - { "loop", mp_property_loop, CONF_TYPE_INT, - M_OPT_MIN, -1, 0, NULL }, + { "loop", mp_property_loop, &m_option_type_choice, + 0, 0, 0, "loop" }, { "speed", mp_property_playback_speed, CONF_TYPE_FLOAT, M_OPT_RANGE, 0.01, 100.0, NULL }, { "filename", mp_property_filename, CONF_TYPE_STRING, @@ -2192,7 +2235,8 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd) &prop, mpctx)) <= 0) goto step_prop_err; if (prop->type == CONF_TYPE_INT || - prop->type == CONF_TYPE_FLAG) + prop->type == CONF_TYPE_FLAG || + prop->type == &m_option_type_choice) i = cmd->args[1].v.f, arg = &i; else if (prop->type == CONF_TYPE_FLOAT) arg = &cmd->args[1].v.f; |