1
0
mirror of https://github.com/mpv-player/mpv synced 2025-03-11 08:37:59 +00:00

command: add a cycle_values input command

This commit is contained in:
wm4 2013-11-30 00:18:24 +01:00
parent e61e6e6fd9
commit f388f14c01
4 changed files with 102 additions and 1 deletions

View File

@ -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.

View File

@ -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,

View File

@ -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,

View File

@ -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,