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:
parent
e61e6e6fd9
commit
f388f14c01
@ -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.
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user