summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-11-30 00:18:24 +0100
committerwm4 <wm4@nowhere>2013-11-30 01:08:23 +0100
commitf388f14c01eeec551a3cdd705c9fa680048cb758 (patch)
tree44df7f883194a703dea3c3274a15166456795eb7
parente61e6e6fd9676ce3ff3971851755cdb7cf63dbf1 (diff)
downloadmpv-f388f14c01eeec551a3cdd705c9fa680048cb758.tar.bz2
mpv-f388f14c01eeec551a3cdd705c9fa680048cb758.tar.xz
command: add a cycle_values input command
-rw-r--r--DOCS/man/en/input.rst18
-rw-r--r--mpvcore/input/input.c5
-rw-r--r--mpvcore/input/input.h1
-rw-r--r--mpvcore/player/command.c79
4 files changed, 102 insertions, 1 deletions
diff --git a/DOCS/man/en/input.rst b/DOCS/man/en/input.rst
index 0e05be2745..0763b1d1e1 100644
--- a/DOCS/man/en/input.rst
+++ b/DOCS/man/en/input.rst
@@ -326,6 +326,24 @@ Input Commands that are Possibly Subject to Change
- ``b vf set ""`` remove all video filters on ``b``
- ``c vf toggle lavfi=gradfun`` toggle debanding on ``c``
+``cycle_values ["!reverse"] <property> "<value1>" "<value2>" ...``
+ Cycle through a list of values. Each invocation of the command will set the
+ given property to the next value in the list. The command maintains an
+ internal counter which value to pick next, and which is initially 0. It is
+ reset to 0 once the last value is reached.
+
+ The internal counter is associated using the property name and the value
+ list. If multiple commands (bound to different keys) use the same name
+ and value list, they will share the internal counter.
+
+ The special argument ``!reverse`` can be used to cycle the value list in
+ reverse. Compared with a command that just lists the value in reverse, this
+ command will actually share the internal counter with the forward-cycling
+ key binding.
+
+ Note that there is a static limit of (as of this writing) 10 arguments
+ (this limit could be raised on demand).
+
``enable_section "<section>" [default|exclusive]``
Enable all key bindings in the named input section.
diff --git a/mpvcore/input/input.c b/mpvcore/input/input.c
index 5d096fcd58..3e0313976a 100644
--- a/mpvcore/input/input.c
+++ b/mpvcore/input/input.c
@@ -228,7 +228,10 @@ static const struct mp_cmd_def mp_cmds[] = {
.allow_auto_repeat = true
},
{ MP_CMD_MULTIPLY, "multiply", { ARG_STRING, ARG_DOUBLE },
- .allow_auto_repeat = true},
+ .allow_auto_repeat = true},
+
+ { MP_CMD_CYCLE_VALUES, "cycle_values", { ARG_STRING, ARG_STRING, ARG_STRING },
+ .vararg = true, .allow_auto_repeat = true},
{ MP_CMD_ENABLE_INPUT_SECTION, "enable_section", {
ARG_STRING,
diff --git a/mpvcore/input/input.h b/mpvcore/input/input.h
index a7ddaa7db1..27db11705e 100644
--- a/mpvcore/input/input.h
+++ b/mpvcore/input/input.h
@@ -65,6 +65,7 @@ enum mp_command_type {
MP_CMD_ADD,
MP_CMD_CYCLE,
MP_CMD_MULTIPLY,
+ MP_CMD_CYCLE_VALUES,
MP_CMD_RADIO_STEP_FREQ,
MP_CMD_TV_STEP_FREQ,
MP_CMD_TV_START_SCAN,
diff --git a/mpvcore/player/command.c b/mpvcore/player/command.c
index 3bd618da8e..d8a317413f 100644
--- a/mpvcore/player/command.c
+++ b/mpvcore/player/command.c
@@ -71,6 +71,9 @@
struct command_ctx {
int events;
+ struct cycle_counter *cycle_counters;
+ int num_cycle_counters;
+
#define OVERLAY_MAX_ID 64
void *overlay_map[OVERLAY_MAX_ID];
};
@@ -2388,6 +2391,47 @@ static void overlay_uninit(struct MPContext *mpctx){}
#endif
+struct cycle_counter {
+ char **args;
+ int counter;
+};
+
+static bool stringlist_equals(char **l1, char **l2)
+{
+ assert(l1 && l2);
+ for (int i = 0; ; i++) {
+ if (!l1[i] && !l2[i])
+ return true;
+ if (!l1[i] || !l2[i])
+ return false;
+ if (strcmp(l1[i], l2[i]) != 0)
+ return false;
+ }
+}
+
+static char **stringlist_dup(void *talloc_ctx, char **list)
+{
+ int num = 0;
+ char **res = NULL;
+ for (int i = 0; list && list[i]; i++)
+ MP_TARRAY_APPEND(talloc_ctx, res, num, talloc_strdup(talloc_ctx, list[i]));
+ MP_TARRAY_APPEND(talloc_ctx, res, num, NULL);
+ return res;
+}
+
+static int *get_cmd_cycle_counter(struct MPContext *mpctx, char **args)
+{
+ struct command_ctx *cmd = mpctx->command_ctx;
+ for (int n = 0; n < cmd->num_cycle_counters; n++) {
+ struct cycle_counter *ctr = &cmd->cycle_counters[n];
+ if (stringlist_equals(ctr->args, args))
+ return &ctr->counter;
+ }
+ struct cycle_counter ctr = {stringlist_dup(cmd, args), 0};
+ MP_TARRAY_APPEND(cmd, cmd->cycle_counters, cmd->num_cycle_counters, ctr);
+ return &cmd->cycle_counters[cmd->num_cycle_counters - 1].counter;
+}
+
static int mp_property_multiply(char *property, double f, struct MPContext *mpctx)
{
union m_option_value val = {0};
@@ -2533,6 +2577,41 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd)
break;
}
+ case MP_CMD_CYCLE_VALUES: {
+ char *args[MP_CMD_MAX_ARGS + 1] = {0};
+ for (int n = 0; n < cmd->nargs; n++)
+ args[n] = cmd->args[n].v.s;
+ int first = 1, dir = 1;
+ if (strcmp(args[0], "!reverse") == 0) {
+ first += 1;
+ dir = -1;
+ }
+ int *ptr = get_cmd_cycle_counter(mpctx, &args[first - 1]);
+ int count = cmd->nargs - first;
+ if (ptr && count > 0) {
+ int next = *ptr;
+ *ptr += dir;
+ if (*ptr >= count)
+ *ptr = 0;
+ if (*ptr < 0)
+ *ptr = count - 1;
+ char *property = args[first - 1];
+ char *value = args[first + next];
+ int r = mp_property_do(property, M_PROPERTY_SET_STRING, value, mpctx);
+ if (r == M_PROPERTY_OK || r == M_PROPERTY_UNAVAILABLE) {
+ show_property_osd(mpctx, property, cmd->on_osd);
+ } else if (r == M_PROPERTY_UNKNOWN) {
+ set_osd_msg(mpctx, OSD_MSG_TEXT, osdl, osd_duration,
+ "Unknown property: '%s'", property);
+ } else if (r <= 0) {
+ set_osd_msg(mpctx, OSD_MSG_TEXT, osdl, osd_duration,
+ "Failed to set property '%s' to '%s'",
+ property, value);
+ }
+ }
+ break;
+ }
+
case MP_CMD_GET_PROPERTY: {
char *tmp;
int r = mp_property_do(cmd->args[0].v.s, M_PROPERTY_GET_STRING,