From cf627fd3de180f0cb0173e016f160de8399cd692 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sun, 19 Oct 2014 21:38:43 +0200 Subject: ipc: accept both JSON and "old" commands Minimizes the differences between --input-file and --input-unix-socket. --- DOCS/man/ipc.rst | 4 ++++ DOCS/man/options.rst | 8 +++++++- input/ipc.c | 57 +++++++++++++++++++++++++--------------------------- 3 files changed, 38 insertions(+), 31 deletions(-) diff --git a/DOCS/man/ipc.rst b/DOCS/man/ipc.rst index 83aa018b03..f0c6004006 100644 --- a/DOCS/man/ipc.rst +++ b/DOCS/man/ipc.rst @@ -47,6 +47,10 @@ mpv will also send events to clients with JSON messages of the following form: where ``event_name`` is the name of the event. Additional event-specific fields can also be present. See `List of events`_ for a list of all supported events. +If the first character (after skipping whitespace) is not ``{``, the command +will be interpreted as non-JSON text command, as they are used in input.conf +(or ``mpv_command_string()`` in the client API). + Commands -------- diff --git a/DOCS/man/options.rst b/DOCS/man/options.rst index aceca84d65..be00c1844a 100644 --- a/DOCS/man/options.rst +++ b/DOCS/man/options.rst @@ -2162,7 +2162,11 @@ Input like any other binding). See `INPUT.CONF`_. ``--input-file=`` - Read commands from the given file. Mostly useful with a FIFO. + Read commands from the given file. Mostly useful with a FIFO. Since + mpv 0.7.0 also understands JSON commands (see `JSON IPC`_), but you can't + get replies or events. Use ``--input-unix-socket`` for something + bi-directional. + See also ``--slave-broken``. .. note:: @@ -2182,6 +2186,8 @@ Input ``--input-unix-socket=`` Enable the IPC support and create the listening socket at the given path. + See `JSON IPC`_ for details. + ``--input-appleremote=`` (OS X only) Enable/disable Apple Remote support. Enabled by default (except for libmpv). diff --git a/input/ipc.c b/input/ipc.c index 872b7718ba..64c4bac87b 100644 --- a/input/ipc.c +++ b/input/ipc.c @@ -58,8 +58,7 @@ struct client_arg { char *client_name; int client_fd; - char *(*encode_event)(mpv_event *event); - char *(*execute_command)(struct client_arg *arg, bstr msg); + bool writable; }; static mpv_node *mpv_node_map_get(mpv_node *src, const char *key) @@ -239,7 +238,9 @@ static char *json_encode_event(mpv_event *event) return output; } -static char *json_execute_command(struct client_arg *arg, bstr msg) +// Function is allowed to modify src[n]. +static char *json_execute_command(struct client_arg *arg, void *ta_parent, + char *src) { int rc; const char *cmd = NULL; @@ -247,9 +248,6 @@ static char *json_execute_command(struct client_arg *arg, bstr msg) mpv_node msg_node; mpv_node reply_node = {.format = MPV_FORMAT_NODE_MAP, .u.list = NULL}; - void *ta_parent = talloc_new(NULL); - - char *src = bstrdup0(ta_parent, msg); rc = json_parse(ta_parent, &msg_node, &src, 3); if (rc < 0) { rc = MPV_ERROR_INVALID_PARAMETER; @@ -426,20 +424,16 @@ static char *json_execute_command(struct client_arg *arg, bstr msg) error: mpv_node_map_add_string(ta_parent, &reply_node, "error", mpv_error_string(rc)); - char *output = talloc_strdup(NULL, ""); + char *output = talloc_strdup(ta_parent, ""); json_write(&output, &reply_node); output = ta_talloc_strdup_append(output, "\n"); - talloc_free(ta_parent); - return output; } -static char *text_execute_command(struct client_arg *arg, bstr msg) +static char *text_execute_command(struct client_arg *arg, void *tmp, char *src) { - char *cmd_str = bstrdup0(NULL, msg); - mpv_command_string(arg->client, cmd_str); - talloc_free(cmd_str); + mpv_command_string(arg->client, src); return NULL; } @@ -512,10 +506,10 @@ static void *client_thread(void *p) if (event->event_id == MPV_EVENT_SHUTDOWN) goto done; - if (!arg->encode_event) + if (!arg->writable) continue; - char *event_msg = arg->encode_event(event); + char *event_msg = json_encode_event(event); if (!event_msg) { MP_ERR(arg, "Encoding error\n"); goto done; @@ -554,28 +548,33 @@ static void *client_thread(void *p) bstr_xappend(NULL, &client_msg, append); while (bstrchr(client_msg, '\n') != -1) { - bstr rest, tmp; + void *tmp = talloc_new(NULL); + bstr rest; bstr line = bstr_getline(client_msg, &rest); + char *line0 = bstrto0(tmp, line); + talloc_steal(tmp, client_msg.start); + client_msg = bstrdup(NULL, rest); + + json_skip_whitespace(&line0); - if (arg->execute_command) { - char *reply_msg = arg->execute_command(arg, line); - if (!reply_msg) - goto command_done; + char *reply_msg; + if (line0[0] == '{') { + reply_msg = json_execute_command(arg, tmp, line0); + } else { + reply_msg = text_execute_command(arg, tmp, line0); + } + if (reply_msg && arg->writable) { rc = ipc_write(arg->client_fd, reply_msg, strlen(reply_msg)); - talloc_free(reply_msg); if (rc < 0) { MP_ERR(arg, "Write error\n"); - talloc_free(client_msg.start); + talloc_free(tmp); goto done; } } -command_done: - tmp = bstrdup(NULL, rest); - talloc_free(client_msg.start); - client_msg = tmp; + talloc_free(tmp); } } } @@ -609,8 +608,7 @@ static void ipc_start_client_json(struct mp_ipc_ctx *ctx, int id, int fd) .client_name = talloc_asprintf(client, "ipc-%d", id), .client_fd = fd, - .encode_event = json_encode_event, - .execute_command = json_execute_command, + .writable = true, }; ipc_start_client(ctx, client); @@ -634,8 +632,7 @@ static void ipc_start_client_text(struct mp_ipc_ctx *ctx, const char *path) .client_name = "input-file", .client_fd = client_fd, - .encode_event = NULL, - .execute_command = text_execute_command, + .writable = false, }; ipc_start_client(ctx, client); -- cgit v1.2.3