summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/interface-changes.rst2
-rw-r--r--DOCS/man/input.rst19
-rw-r--r--DOCS/man/options.rst2
-rw-r--r--player/command.c161
4 files changed, 97 insertions, 87 deletions
diff --git a/DOCS/interface-changes.rst b/DOCS/interface-changes.rst
index d9fa295fc4..a21f50e0fa 100644
--- a/DOCS/interface-changes.rst
+++ b/DOCS/interface-changes.rst
@@ -98,6 +98,8 @@ Interface changes
nobody wants to fix it. Automatic 3D down-conversion to 2D is also broken,
although you can just insert the stereo3d filter manually. The obscurity
of 3D content doesn't justify such an option anyway.
+ - change cycle-values command to use the current value, instead of an
+ internal counter that remembered the current position.
--- mpv 0.28.0 ---
- rename --hwdec=mediacodec option to mediacodec-copy, to reflect
conventions followed by other hardware video decoding APIs
diff --git a/DOCS/man/input.rst b/DOCS/man/input.rst
index 4a59a919f0..58e2b9c27d 100644
--- a/DOCS/man/input.rst
+++ b/DOCS/man/input.rst
@@ -514,21 +514,14 @@ Input Commands that are Possibly Subject to Change
``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.
+ given property to the next value in the list. The command will use the
+ current value of the property/option, and use it to determine the current
+ position in the list of values. Once it has found it, it will set the
+ next value in the list (wrapping around to the first item if needed).
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 (as long as the rest of the arguments are the same).
-
- Note that there is a static limit of (as of this writing) 10 arguments
- (this limit could be raised on demand).
+ reverse. The only advantage is that you don't need to reverse the value
+ list yourself when adding a second key binding for cycling backwards.
``enable-section "<section>" [flags]``
Enable all key bindings in the named input section.
diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst
index 069363dfd0..d147800ea3 100644
--- a/DOCS/man/options.rst
+++ b/DOCS/man/options.rst
@@ -2249,7 +2249,7 @@ Window
.. admonition:: Note (X11)
- This option does works properly only with window managers which
+ This option works properly only with window managers which
understand the EWMH ``_NET_WM_FULLSCREEN_MONITORS`` hint.
.. admonition:: Note (OS X)
diff --git a/player/command.c b/player/command.c
index fa0151c6b8..a21fc53abb 100644
--- a/player/command.c
+++ b/player/command.c
@@ -84,9 +84,6 @@ struct command_ctx {
char **warned_deprecated;
int num_warned_deprecated;
- struct cycle_counter *cycle_counters;
- int num_cycle_counters;
-
struct overlay *overlays;
int num_overlays;
// One of these is in use by the OSD; the other one exists so that the
@@ -4671,47 +4668,6 @@ static void overlay_uninit(struct MPContext *mpctx)
mp_image_unrefp(&cmd->overlay_osd[n].packed);
}
-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), -1};
- MP_TARRAY_APPEND(cmd, cmd->cycle_counters, cmd->num_cycle_counters, ctr);
- return &cmd->cycle_counters[cmd->num_cycle_counters - 1].counter;
-}
-
static struct track *find_track_with_url(struct MPContext *mpctx, int type,
const char *url)
{
@@ -4752,8 +4708,8 @@ static bool check_property_scalable(char *property, struct MPContext *mpctx)
prop.type == &m_option_type_aspect;
}
-static int change_property_cmd(struct MPContext *mpctx, struct mp_cmd *cmd,
- const char *name, int action, void *arg)
+static int show_property_status(struct MPContext *mpctx, struct mp_cmd *cmd,
+ const char *name, int r)
{
struct MPOpts *opts = mpctx->opts;
int osd_duration = opts->osd_duration;
@@ -4762,9 +4718,10 @@ static int change_property_cmd(struct MPContext *mpctx, struct mp_cmd *cmd,
bool msg_osd = auto_osd || (on_osd & MP_ON_OSD_MSG);
int osdl = msg_osd ? 1 : OSD_LEVEL_INVISIBLE;
- int r = mp_property_do(name, action, arg, mpctx);
if (r == M_PROPERTY_OK || r == M_PROPERTY_UNAVAILABLE) {
show_property_osd(mpctx, name, on_osd);
+ if (r == M_PROPERTY_UNAVAILABLE)
+ return -1;
} else if (r == M_PROPERTY_UNKNOWN) {
set_osd_msg(mpctx, osdl, osd_duration, "Unknown property: '%s'", name);
return -1;
@@ -4776,6 +4733,88 @@ static int change_property_cmd(struct MPContext *mpctx, struct mp_cmd *cmd,
return 0;
}
+static int change_property_cmd(struct MPContext *mpctx, struct mp_cmd *cmd,
+ const char *name, int action, void *arg)
+{
+ int r = mp_property_do(name, action, arg, mpctx);
+ return show_property_status(mpctx, cmd, name, r);
+}
+
+static bool compare_values(struct m_option *type, void *a, void *b)
+{
+ // Since there is no m_option_equals() or anything similar, we convert all
+ // values to a common, unambiguous representation - strings.
+ char *as = m_option_print(type, a);
+ char *bs = m_option_print(type, b);
+ bool res = bstr_equals(bstr0(as), bstr0(bs)); // treat as "" on failure
+ talloc_free(as);
+ talloc_free(bs);
+ return res;
+}
+
+static int cycle_values_cmd(struct MPContext *mpctx, struct mp_cmd *cmd)
+{
+ int first = 0, dir = 1;
+
+ if (strcmp(cmd->args[first].v.s, "!reverse") == 0) {
+ first += 1;
+ dir = -1;
+ }
+
+ const char *name = cmd->args[first].v.s;
+ first += 1;
+
+ if (first >= cmd->nargs) {
+ MP_ERR(mpctx, "cycle-values command does not have any value arguments.\n");
+ return -1;
+ }
+
+ struct m_option prop = {0};
+ int r = mp_property_do(name, M_PROPERTY_GET_TYPE, &prop, mpctx);
+ if (r <= 0)
+ return show_property_status(mpctx, cmd, name, r);
+
+ union m_option_value curval = {0};
+ r = mp_property_do(name, M_PROPERTY_GET, &curval, mpctx);
+ if (r <= 0)
+ return show_property_status(mpctx, cmd, name, r);
+
+ // Find the current value. Note that we even though compare_values() uses
+ // strings internally, we need to convert the cycle-values arguments to
+ // native anyway to "normalize" the value for comparison.
+ int current = -1;
+ for (int n = first; n < cmd->nargs; n++) {
+ union m_option_value val = {0};
+ if (m_option_parse(mpctx->log, &prop, bstr0(name),
+ bstr0(cmd->args[n].v.s), &val) <= 0)
+ continue;
+
+ if (compare_values(&prop, &curval, &val))
+ current = n;
+
+ m_option_free(&prop, &val);
+
+ if (current >= 0)
+ break;
+ }
+
+ m_option_free(&prop, &curval);
+
+ if (current >= 0) {
+ current += dir;
+ if (current < first)
+ current = cmd->nargs - 1;
+ if (current >= cmd->nargs)
+ current = first;
+ } else {
+ MP_VERBOSE(mpctx, "Current value not found. Picking default.\n");
+ current = dir > 0 ? first : cmd->nargs - 1;
+ }
+
+ return change_property_cmd(mpctx, cmd, name, M_PROPERTY_SET_STRING,
+ cmd->args[current].v.s);
+}
+
int run_command(struct MPContext *mpctx, struct mp_cmd *cmd, struct mpv_node *res)
{
struct command_ctx *cmdctx = mpctx->command_ctx;
@@ -4952,32 +4991,8 @@ int run_command(struct MPContext *mpctx, struct mp_cmd *cmd, struct mpv_node *re
M_PROPERTY_MULTIPLY, &cmd->args[1].v.d);
}
- case MP_CMD_CYCLE_VALUES: {
- char **args = talloc_zero_array(NULL, char *, cmd->nargs + 1);
- 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;
- int r = 0;
- if (ptr && count > 0) {
- *ptr = *ptr < 0 ? (dir > 0 ? 0 : -1) : *ptr + dir;
- if (*ptr >= count)
- *ptr = 0;
- if (*ptr < 0)
- *ptr = count - 1;
- char *property = args[first - 1];
- char *value = args[first + *ptr];
- r = change_property_cmd(mpctx, cmd, property, M_PROPERTY_SET_STRING,
- value);
- }
- talloc_free(args);
- return r;
- }
+ case MP_CMD_CYCLE_VALUES:
+ return cycle_values_cmd(mpctx, cmd);
case MP_CMD_FRAME_STEP:
if (!mpctx->playback_initialized)