summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-07-08 19:27:45 +0200
committerwm4 <wm4@nowhere>2013-07-08 19:28:52 +0200
commit15a5422dd2ba18d10c598f91b8cdae86269b2af1 (patch)
treed102504505a0a3ec2047946871e7c40bc02100b7
parent09250d9921304ae988de756fa9cb33d86758b519 (diff)
downloadmpv-15a5422dd2ba18d10c598f91b8cdae86269b2af1.tar.bz2
mpv-15a5422dd2ba18d10c598f91b8cdae86269b2af1.tar.xz
input: allow binding multiple commands to a key
Separate the commands with ';'.
-rw-r--r--DOCS/man/en/input.rst11
-rw-r--r--core/command.c6
-rw-r--r--core/input/input.c59
-rw-r--r--core/input/input.h4
4 files changed, 74 insertions, 6 deletions
diff --git a/DOCS/man/en/input.rst b/DOCS/man/en/input.rst
index 7dab3bb1b4..c9adc7a4ca 100644
--- a/DOCS/man/en/input.rst
+++ b/DOCS/man/en/input.rst
@@ -29,7 +29,7 @@ must kill **mpv** externally to make it exit.)
General Input Command Syntax
----------------------------
-``[Shift+][Ctrl+][Alt+][Meta+]<key> [{<section>}] [<prefixes>] <command> (<argument>)*``
+``[Shift+][Ctrl+][Alt+][Meta+]<key> [{<section>}] [<prefixes>] <command> (<argument>)* [; <command>]``
Newlines always start a new binding. ``#`` starts a comment (outside of quoted
string arguments). To bind commands to the ``#`` key, ``SHARP`` can be used.
@@ -46,6 +46,15 @@ C-style escaping can be used.
Optional arguments can be skipped with ``-``.
+You can bind multiple commands to one key. For example:
+
+| a show_text "command 1" ; show_text "command 2"
+
+Note that some magic is disabled for keys: seek commands inside lists are not
+coalesced (seeking will appear slower), and no check is done for abort commands
+(so these commands can't be used to abort playback if the network cache is
+stuck).
+
List of Input Commands
----------------------
diff --git a/core/command.c b/core/command.c
index 80f6f5d9d2..848ebb848f 100644
--- a/core/command.c
+++ b/core/command.c
@@ -2507,6 +2507,12 @@ void run_command(MPContext *mpctx, mp_cmd_t *cmd)
change_video_filters(mpctx, cmd->args[0].v.s, cmd->args[1].v.s);
break;
+ case MP_CMD_COMMAND_LIST: {
+ for (struct mp_cmd *sub = cmd->args[0].v.p; sub; sub = sub->queue_next)
+ run_command(mpctx, sub);
+ break;
+ }
+
default:
mp_msg(MSGT_CPLAYER, MSGL_V,
"Received unknown cmd %s\n", cmd->name);
diff --git a/core/input/input.c b/core/input/input.c
index 4a52b3f9c9..73ac5bc698 100644
--- a/core/input/input.c
+++ b/core/input/input.c
@@ -808,7 +808,7 @@ static bool read_token(bstr str, bstr *out_rest, bstr *out_token)
bstr t = bstr_lstrip(str);
int next = bstrcspn(t, WHITESPACE "#");
// Handle comments
- if (t.start[next] == '#')
+ if (t.len && t.start[next] == '#')
t = bstr_splice(t, 0, next);
if (!t.len)
return false;
@@ -852,13 +852,16 @@ error:
return false;
}
-mp_cmd_t *mp_input_parse_cmd(bstr str, const char *loc)
+// If dest is non-NULL when calling this function, append the command to the
+// list formed by dest->queue_next, otherwise just set *dest = new_cmd;
+static int parse_cmd(struct mp_cmd **dest, bstr str, const char *loc)
{
int pausing = 0;
int on_osd = MP_ON_OSD_AUTO;
bool raw_args = false;
struct mp_cmd *cmd = NULL;
bstr start = str;
+ bstr next = {0};
void *tmp = talloc_new(NULL);
str = bstr_lstrip(str);
@@ -929,8 +932,13 @@ mp_cmd_t *mp_input_parse_cmd(bstr str, const char *loc)
struct mp_cmd_arg *cmdarg = &cmd->args[i];
if (!cmdarg->type.type)
break;
- cmd->nargs++;
str = bstr_lstrip(str);
+ if (eat_token(&str, ";")) {
+ next = str;
+ str.len = 0;
+ break;
+ }
+ cmd->nargs++;
bstr arg = {0};
if (bstr_eatstart0(&str, "\"")) {
if (!read_escaped_string(tmp, &str, &arg)) {
@@ -962,6 +970,11 @@ mp_cmd_t *mp_input_parse_cmd(bstr str, const char *loc)
cmdarg->v.s = talloc_steal(cmd, cmdarg->v.s);
}
+ if (eat_token(&str, ";")) {
+ next = str;
+ str.len = 0;
+ }
+
bstr dummy;
if (read_token(str, &dummy, &dummy)) {
mp_tmsg(MSGT_INPUT, MSGL_ERR, "Command %s has trailing unused "
@@ -986,14 +999,50 @@ mp_cmd_t *mp_input_parse_cmd(bstr str, const char *loc)
bstr orig = (bstr) {start.start, str.start - start.start};
cmd->original = bstrdup(cmd, bstr_strip(orig));
+ while (*dest)
+ dest = &(*dest)->queue_next;
+ *dest = cmd;
+
+ next = bstr_strip(next);
+ if (next.len) {
+ if (parse_cmd(dest, next, loc) < 0) {
+ *dest = NULL;
+ goto error;
+ }
+ }
+
talloc_free(tmp);
- return cmd;
+ return 1;
error:
mp_tmsg(MSGT_INPUT, MSGL_ERR, "Command was defined at %s.\n", loc);
talloc_free(cmd);
talloc_free(tmp);
- return NULL;
+ return -1;
+}
+
+mp_cmd_t *mp_input_parse_cmd(bstr str, const char *loc)
+{
+ struct mp_cmd *cmd = NULL;
+ if (parse_cmd(&cmd, str, loc) < 0) {
+ assert(!cmd);
+ }
+ // Other input.c code uses queue_next for its own purposes, so explicitly
+ // wrap lists in a pseudo-command.
+ if (cmd && cmd->queue_next) {
+ struct mp_cmd *list = talloc_ptrtype(NULL, list);
+ *list = (struct mp_cmd) {
+ .id = MP_CMD_COMMAND_LIST,
+ .name = "list",
+ };
+ list->args[0].v.p = cmd;
+ while (cmd) {
+ talloc_steal(list, cmd);
+ cmd = cmd->queue_next;
+ }
+ cmd = list;
+ }
+ return cmd;
}
#define MP_CMD_MAX_SIZE 4096
diff --git a/core/input/input.h b/core/input/input.h
index 2a9b3832c1..f7d69a0de7 100644
--- a/core/input/input.h
+++ b/core/input/input.h
@@ -87,6 +87,9 @@ enum mp_command_type {
/// Video output commands
MP_CMD_VO_CMDLINE,
+
+ // Internal
+ MP_CMD_COMMAND_LIST, // list of sub-commands in args[0].v.p
};
#define MP_CMD_MAX_ARGS 10
@@ -128,6 +131,7 @@ struct mp_cmd_arg {
float f;
double d;
char *s;
+ void *p;
} v;
};