summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2012-10-13 21:10:20 +0200
committerwm4 <wm4@nowhere>2012-10-14 22:28:51 +0200
commit187cbd7aa7a74bf1596b3501c095920441f76dc0 (patch)
treeeee5f51458440a74076d81e5b908cfd858a92933
parentad5bc380e2605108398d3815ad10adcbebf3913b (diff)
downloadmpv-187cbd7aa7a74bf1596b3501c095920441f76dc0.tar.bz2
mpv-187cbd7aa7a74bf1596b3501c095920441f76dc0.tar.xz
input: add input test mode
In input test mode, key bindings won't be executed, but are shown on the OSD. The OSD includes various information, such as the name of the key, the command itself, whether it's builtin, and the config file location it was defined. The input test mode can be enabled with "--input=test". No effort is spent trying to react to key bindings that normally exit the player; they are treated just like any other binding.
-rw-r--r--DOCS/man/en/options.rst7
-rw-r--r--etc/input.conf7
-rw-r--r--input/input.c88
-rw-r--r--input/input.h1
-rw-r--r--options.h1
5 files changed, 90 insertions, 14 deletions
diff --git a/DOCS/man/en/options.rst b/DOCS/man/en/options.rst
index c825cd58d6..a8fe171601 100644
--- a/DOCS/man/en/options.rst
+++ b/DOCS/man/en/options.rst
@@ -935,6 +935,13 @@
can do several `echo "seek 10" > mp_pipe` and the pipe will stay
valid.
+ test
+ Input test mode. Instead of executing commands on key presses, mpv
+ will show the keys and the bound commands on the OSD. Has to be used
+ with a dummy video, and the normal ways to quit the player will not
+ work (key bindings that normally quit will be shown on OSD only, just
+ like any other binding).
+
--ipv4-only-proxy
Skip any HTTP proxy for IPv6 addresses. It will still be used for IPv4
connections.
diff --git a/etc/input.conf b/etc/input.conf
index f9906b23a4..67ce10f72f 100644
--- a/etc/input.conf
+++ b/etc/input.conf
@@ -2,10 +2,13 @@
#
# You are able to redefine default keyboard/joystick/mouse/LIRC bindings, or
# add new ones here.
-# See DOCS/tech/slave.txt for possible commands that can be bound.
-# Also see mpv -input cmdlist for other possible options.
+# See DOCS/man/en/input.rst for possible commands that can be bound.
+# Also see mpv --input=cmdlist for other possible options.
# The file should be placed in the $HOME/.mpv directory.
#
+# mpv --input=test --pause dummy.mkv can be used to test which commands keys are
+# bound to.
+#
# If you wish to unbind a key, use key ignore.
# e.g. ENTER ignore
#
diff --git a/input/input.c b/input/input.c
index 5b349b6c39..1ea5050031 100644
--- a/input/input.c
+++ b/input/input.c
@@ -485,6 +485,8 @@ struct input_ctx {
unsigned int num_key_down;
unsigned int last_key_down;
+ bool test;
+
bool default_bindings;
// List of command binding sections
struct cmd_bind_section *cmd_bind_sections;
@@ -526,6 +528,7 @@ static const m_option_t input_conf[] = {
OPT_STRING("ar-dev", input.ar_dev, CONF_GLOBAL),
OPT_STRING("file", input.in_file, CONF_GLOBAL),
OPT_MAKE_FLAGS("default-bindings", input.default_bindings, CONF_GLOBAL),
+ OPT_MAKE_FLAGS("test", input.test, CONF_GLOBAL),
{ NULL, NULL, 0, 0, 0, 0, NULL}
};
@@ -854,6 +857,7 @@ mp_cmd_t *mp_input_parse_cmd(bstr str, const char *loc)
int pausing = 0;
int on_osd = MP_ON_OSD_AUTO;
struct mp_cmd *cmd = NULL;
+ bstr start = str;
void *tmp = talloc_new(NULL);
if (eat_token(&str, "pausing")) {
@@ -877,6 +881,7 @@ mp_cmd_t *mp_input_parse_cmd(bstr str, const char *loc)
entry->old, entry->new, loc);
bstr s = bstr_cut(str, old_len);
str = bstr0(talloc_asprintf(tmp, "%s%.*s", entry->new, BSTR_P(s)));
+ start = str;
break;
}
}
@@ -971,6 +976,9 @@ mp_cmd_t *mp_input_parse_cmd(bstr str, const char *loc)
goto error;
}
+ bstr orig = (bstr) {start.start, str.start - start.start};
+ cmd->original = bstrdup(cmd, bstr_strip(orig));
+
talloc_free(tmp);
return cmd;
@@ -1090,6 +1098,67 @@ static int read_wakeup(void *ctx, int fd)
return MP_INPUT_NOTHING;
}
+static bool bind_matches_key(struct cmd_bind *bind, int n, int *keys);
+
+static void append_bind_info(char **pmsg, struct cmd_bind *bind)
+{
+ char *msg = *pmsg;
+ struct mp_cmd *cmd = mp_input_parse_cmd(bstr0(bind->cmd), bind->location);
+ bstr stripped = cmd ? cmd->original : bstr0(bind->cmd);
+ msg = talloc_asprintf_append(msg, " '%.*s'", BSTR_P(stripped));
+ if (!cmd)
+ msg = talloc_asprintf_append(msg, " (invalid)");
+ if (strcmp(bind->owner->section, "default") != 0)
+ msg = talloc_asprintf_append(msg, " in section {%s}",
+ bind->owner->section);
+ if (bind->owner->is_builtin) {
+ msg = talloc_asprintf_append(msg, " (default binding)");
+ } else {
+ msg = talloc_asprintf_append(msg, " in %s", bind->location);
+ }
+ *pmsg = msg;
+}
+
+static mp_cmd_t *handle_test(struct input_ctx *ictx, int n, int *keys)
+{
+ char *key_buf = get_key_combo_name(keys, n);
+ // "$>" to disable property substitution when invoking "show_text"
+ char *msg = talloc_asprintf(NULL, "$>Key %s is bound to:\n", key_buf);
+ talloc_free(key_buf);
+
+ int count = 0;
+ for (struct cmd_bind_section *bs = ictx->cmd_bind_sections;
+ bs; bs = bs->next)
+ {
+ for (struct cmd_bind *bind = bs->cmd_binds; bind->cmd; bind++) {
+ if (bind_matches_key(bind, n, keys)) {
+ count++;
+ msg = talloc_asprintf_append(msg, "%d. ", count);
+ append_bind_info(&msg, bind);
+ msg = talloc_asprintf_append(msg, "\n");
+ }
+ }
+ }
+
+ if (!count)
+ msg = talloc_asprintf_append(msg, "(nothing)");
+
+ mp_cmd_t *res = mp_input_parse_cmd(bstr0("show_text \"\""), "");
+ res->args[0].v.s = talloc_steal(res, msg);
+ return res;
+}
+
+static bool bind_matches_key(struct cmd_bind *bind, int n, int *keys)
+{
+ int found = 1, s;
+ for (s = 0; s < n && bind->input[s] != 0; s++) {
+ if (bind->input[s] != keys[s]) {
+ found = 0;
+ break;
+ }
+ }
+ return found && bind->input[s] == 0 && s == n;
+}
static struct cmd_bind *find_bind_for_key(struct cmd_bind *binds, int n,
int *keys)
@@ -1099,14 +1168,7 @@ static struct cmd_bind *find_bind_for_key(struct cmd_bind *binds, int n,
if (n <= 0)
return NULL;
for (j = 0; binds[j].cmd != NULL; j++) {
- int found = 1, s;
- for (s = 0; s < n && binds[j].input[s] != 0; s++) {
- if (binds[j].input[s] != keys[s]) {
- found = 0;
- break;
- }
- }
- if (found && binds[j].input[s] == 0 && s == n)
+ if (bind_matches_key(&binds[j], n, keys))
break;
}
return binds[j].cmd ? &binds[j] : NULL;
@@ -1152,10 +1214,11 @@ static struct cmd_bind *section_find_bind_for_key(struct input_ctx *ictx,
static mp_cmd_t *get_cmd_from_keys(struct input_ctx *ictx, int n, int *keys)
{
- struct cmd_bind *cmd = NULL;
- mp_cmd_t *ret;
+ if (ictx->test)
+ return handle_test(ictx, n, keys);
- cmd = section_find_bind_for_key(ictx, false, ictx->section, n, keys);
+ struct cmd_bind *cmd
+ = section_find_bind_for_key(ictx, false, ictx->section, n, keys);
if (ictx->default_bindings && cmd == NULL)
cmd = section_find_bind_for_key(ictx, true, ictx->section, n, keys);
if (!(ictx->section_flags & MP_INPUT_NO_DEFAULT_SECTION)) {
@@ -1172,7 +1235,7 @@ static mp_cmd_t *get_cmd_from_keys(struct input_ctx *ictx, int n, int *keys)
talloc_free(key_buf);
return NULL;
}
- ret = mp_input_parse_cmd(bstr0(cmd->cmd), cmd->location);
+ mp_cmd_t *ret = mp_input_parse_cmd(bstr0(cmd->cmd), cmd->location);
if (!ret) {
char *key_buf = get_key_combo_name(keys, n);
mp_tmsg(MSGT_INPUT, MSGL_ERR,
@@ -1697,6 +1760,7 @@ struct input_ctx *mp_input_init(struct input_conf *input_conf)
.ar_delay = input_conf->ar_delay,
.ar_rate = input_conf->ar_rate,
.default_bindings = input_conf->default_bindings,
+ .test = input_conf->test,
.wakeup_pipe = {-1, -1},
};
ictx->section = talloc_strdup(ictx, "default");
diff --git a/input/input.h b/input/input.h
index 4bd68cca48..59f2d031ff 100644
--- a/input/input.h
+++ b/input/input.h
@@ -130,6 +130,7 @@ typedef struct mp_cmd {
int nargs;
int pausing;
enum mp_on_osd on_osd;
+ bstr original;
struct mp_cmd *queue_next;
} mp_cmd_t;
diff --git a/options.h b/options.h
index 090ea50535..d2404bb85a 100644
--- a/options.h
+++ b/options.h
@@ -160,6 +160,7 @@ typedef struct MPOpts {
int use_lircc;
int use_ar; // apple remote
int default_bindings;
+ int test;
} input;
struct encode_output_conf {