summaryrefslogtreecommitdiffstats
path: root/command.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2012-09-05 02:17:13 +0200
committerwm4 <wm4@nowhere>2012-09-18 21:07:29 +0200
commitc955549204c433abd1a3c8783f1b988e29315337 (patch)
tree47da7a2a9f552a810713b788513683f694eeec0c /command.c
parentd29d4df634a9d847a2b5ef7a04f32726cd03c1ef (diff)
downloadmpv-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.c90
1 files changed, 67 insertions, 23 deletions
diff --git a/command.c b/command.c
index 7947f83d6a..8a7f17dfba 100644
--- a/command.c
+++ b/command.c
@@ -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;