summaryrefslogtreecommitdiffstats
path: root/input/ipc.c
diff options
context:
space:
mode:
Diffstat (limited to 'input/ipc.c')
-rw-r--r--input/ipc.c205
1 files changed, 82 insertions, 123 deletions
diff --git a/input/ipc.c b/input/ipc.c
index 6568feacfa..ea69fb7c24 100644
--- a/input/ipc.c
+++ b/input/ipc.c
@@ -15,8 +15,6 @@
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
-#include "config.h"
-
#include "common/msg.h"
#include "input/input.h"
#include "misc/json.h"
@@ -37,28 +35,6 @@ static mpv_node *mpv_node_array_get(mpv_node *src, int index)
return &src->u.list->values[index];
}
-static void mpv_node_array_add(void *ta_parent, mpv_node *src, mpv_node *val)
-{
- if (src->format != MPV_FORMAT_NODE_ARRAY)
- return;
-
- if (!src->u.list)
- src->u.list = talloc_zero(ta_parent, mpv_node_list);
-
- MP_TARRAY_GROW(src->u.list, src->u.list->values, src->u.list->num);
-
- static const struct m_option type = { .type = CONF_TYPE_NODE };
- m_option_get_node(&type, ta_parent, &src->u.list->values[src->u.list->num], val);
-
- src->u.list->num++;
-}
-
-static void mpv_node_array_add_string(void *ta_parent, mpv_node *src, const char *val)
-{
- mpv_node val_node = {.format = MPV_FORMAT_STRING, .u.string = (char *)val};
- mpv_node_array_add(ta_parent, src, &val_node);
-}
-
static void mpv_node_map_add(void *ta_parent, mpv_node *src, const char *key, mpv_node *val)
{
if (src->format != MPV_FORMAT_NODE_MAP)
@@ -84,94 +60,46 @@ static void mpv_node_map_add_null(void *ta_parent, mpv_node *src, const char *ke
mpv_node_map_add(ta_parent, src, key, &val_node);
}
-static void mpv_node_map_add_flag(void *ta_parent, mpv_node *src, const char *key, bool val)
-{
- mpv_node val_node = {.format = MPV_FORMAT_FLAG, .u.flag = val};
-
- mpv_node_map_add(ta_parent, src, key, &val_node);
-}
-
static void mpv_node_map_add_int64(void *ta_parent, mpv_node *src, const char *key, int64_t val)
{
mpv_node val_node = {.format = MPV_FORMAT_INT64, .u.int64 = val};
mpv_node_map_add(ta_parent, src, key, &val_node);
}
-static void mpv_node_map_add_double(void *ta_parent, mpv_node *src, const char *key, double val)
-{
- mpv_node val_node = {.format = MPV_FORMAT_DOUBLE, .u.double_ = val};
- mpv_node_map_add(ta_parent, src, key, &val_node);
-}
-
static void mpv_node_map_add_string(void *ta_parent, mpv_node *src, const char *key, const char *val)
{
mpv_node val_node = {.format = MPV_FORMAT_STRING, .u.string = (char*)val};
mpv_node_map_add(ta_parent, src, key, &val_node);
}
-static void mpv_event_to_node(void *ta_parent, mpv_event *event, mpv_node *dst)
+// This is supposed to write a reply that looks like "normal" command execution.
+static void mpv_format_command_reply(void *ta_parent, mpv_event *event,
+ mpv_node *dst)
{
- mpv_node_map_add_string(ta_parent, dst, "event", mpv_event_name(event->event_id));
-
- if (event->reply_userdata)
- mpv_node_map_add_int64(ta_parent, dst, "id", event->reply_userdata);
-
- if (event->error < 0)
- mpv_node_map_add_string(ta_parent, dst, "error", mpv_error_string(event->error));
-
- switch (event->event_id) {
- case MPV_EVENT_LOG_MESSAGE: {
- mpv_event_log_message *msg = event->data;
-
- mpv_node_map_add_string(ta_parent, dst, "prefix", msg->prefix);
- mpv_node_map_add_string(ta_parent, dst, "level", msg->level);
- mpv_node_map_add_string(ta_parent, dst, "text", msg->text);
-
- break;
- }
+ assert(event->event_id == MPV_EVENT_COMMAND_REPLY);
+ mpv_event_command *cmd = event->data;
- case MPV_EVENT_CLIENT_MESSAGE: {
- mpv_event_client_message *msg = event->data;
+ mpv_node_map_add_int64(ta_parent, dst, "request_id", event->reply_userdata);
- mpv_node args_node = {.format = MPV_FORMAT_NODE_ARRAY, .u.list = NULL};
- for (int n = 0; n < msg->num_args; n++)
- mpv_node_array_add_string(ta_parent, &args_node, msg->args[n]);
- mpv_node_map_add(ta_parent, dst, "args", &args_node);
- break;
- }
+ mpv_node_map_add_string(ta_parent, dst, "error",
+ mpv_error_string(event->error));
- case MPV_EVENT_PROPERTY_CHANGE: {
- mpv_event_property *prop = event->data;
-
- mpv_node_map_add_string(ta_parent, dst, "name", prop->name);
-
- switch (prop->format) {
- case MPV_FORMAT_NODE:
- mpv_node_map_add(ta_parent, dst, "data", prop->data);
- break;
- case MPV_FORMAT_DOUBLE:
- mpv_node_map_add_double(ta_parent, dst, "data", *(double *)prop->data);
- break;
- case MPV_FORMAT_FLAG:
- mpv_node_map_add_flag(ta_parent, dst, "data", *(int *)prop->data);
- break;
- case MPV_FORMAT_STRING:
- mpv_node_map_add_string(ta_parent, dst, "data", *(char **)prop->data);
- break;
- default:
- mpv_node_map_add_null(ta_parent, dst, "data");
- }
- break;
- }
- }
+ mpv_node_map_add(ta_parent, dst, "data", &cmd->result);
}
char *mp_json_encode_event(mpv_event *event)
{
void *ta_parent = talloc_new(NULL);
- mpv_node event_node = {.format = MPV_FORMAT_NODE_MAP, .u.list = NULL};
- mpv_event_to_node(ta_parent, event, &event_node);
+ struct mpv_node event_node;
+ if (event->event_id == MPV_EVENT_COMMAND_REPLY) {
+ event_node = (mpv_node){.format = MPV_FORMAT_NODE_MAP, .u.list = NULL};
+ mpv_format_command_reply(ta_parent, event, &event_node);
+ } else {
+ mpv_event_to_node(&event_node, event);
+ // Abuse mpv_event_to_node() internals.
+ talloc_steal(ta_parent, node_get_alloc(&event_node));
+ }
char *output = talloc_strdup(NULL, "");
json_write(&output, &event_node);
@@ -193,8 +121,12 @@ static char *json_execute_command(struct mpv_handle *client, void *ta_parent,
mpv_node msg_node;
mpv_node reply_node = {.format = MPV_FORMAT_NODE_MAP, .u.list = NULL};
mpv_node *reqid_node = NULL;
+ int64_t reqid = 0;
+ mpv_node *async_node = NULL;
+ bool async = false;
+ bool send_reply = true;
- rc = json_parse(ta_parent, &msg_node, &src, 50);
+ rc = json_parse(ta_parent, &msg_node, &src, MAX_JSON_DEPTH);
if (rc < 0) {
mp_err(log, "malformed JSON received: '%s'\n", src);
rc = MPV_ERROR_INVALID_PARAMETER;
@@ -206,42 +138,58 @@ static char *json_execute_command(struct mpv_handle *client, void *ta_parent,
goto error;
}
+ async_node = node_map_get(&msg_node, "async");
+ if (async_node) {
+ if (async_node->format != MPV_FORMAT_FLAG) {
+ rc = MPV_ERROR_INVALID_PARAMETER;
+ goto error;
+ }
+ async = async_node->u.flag;
+ }
+
reqid_node = node_map_get(&msg_node, "request_id");
- if (reqid_node && reqid_node->format != MPV_FORMAT_INT64) {
- mp_warn(log, "'request_id' must be an integer. Using other types is "
- "deprecated and will trigger an error in the future!\n");
+ if (reqid_node) {
+ if (reqid_node->format == MPV_FORMAT_INT64) {
+ reqid = reqid_node->u.int64;
+ } else if (async) {
+ mp_err(log, "'request_id' must be an integer for async commands.\n");
+ rc = MPV_ERROR_INVALID_PARAMETER;
+ goto error;
+ } else {
+ mp_warn(log, "'request_id' must be an integer. Using other types is "
+ "deprecated and will trigger an error in the future!\n");
+ }
}
mpv_node *cmd_node = node_map_get(&msg_node, "command");
- if (!cmd_node ||
- (cmd_node->format != MPV_FORMAT_NODE_ARRAY) ||
- !cmd_node->u.list->num)
- {
+ if (!cmd_node) {
rc = MPV_ERROR_INVALID_PARAMETER;
goto error;
}
- mpv_node *cmd_str_node = mpv_node_array_get(cmd_node, 0);
- if (!cmd_str_node || (cmd_str_node->format != MPV_FORMAT_STRING)) {
- rc = MPV_ERROR_INVALID_PARAMETER;
- goto error;
- }
+ if (cmd_node->format == MPV_FORMAT_NODE_ARRAY) {
+ mpv_node *cmd_str_node = mpv_node_array_get(cmd_node, 0);
+ if (!cmd_str_node || (cmd_str_node->format != MPV_FORMAT_STRING)) {
+ rc = MPV_ERROR_INVALID_PARAMETER;
+ goto error;
+ }
- cmd = cmd_str_node->u.string;
+ cmd = cmd_str_node->u.string;
+ }
- if (!strcmp("client_name", cmd)) {
+ if (cmd && !strcmp("client_name", cmd)) {
const char *client_name = mpv_client_name(client);
mpv_node_map_add_string(ta_parent, &reply_node, "data", client_name);
rc = MPV_ERROR_SUCCESS;
- } else if (!strcmp("get_time_us", cmd)) {
+ } else if (cmd && !strcmp("get_time_us", cmd)) {
int64_t time_us = mpv_get_time_us(client);
mpv_node_map_add_int64(ta_parent, &reply_node, "data", time_us);
rc = MPV_ERROR_SUCCESS;
- } else if (!strcmp("get_version", cmd)) {
+ } else if (cmd && !strcmp("get_version", cmd)) {
int64_t ver = mpv_client_api_version();
mpv_node_map_add_int64(ta_parent, &reply_node, "data", ver);
rc = MPV_ERROR_SUCCESS;
- } else if (!strcmp("get_property", cmd)) {
+ } else if (cmd && !strcmp("get_property", cmd)) {
mpv_node result_node;
if (cmd_node->u.list->num != 2) {
@@ -260,7 +208,7 @@ static char *json_execute_command(struct mpv_handle *client, void *ta_parent,
mpv_node_map_add(ta_parent, &reply_node, "data", &result_node);
mpv_free_node_contents(&result_node);
}
- } else if (!strcmp("get_property_string", cmd)) {
+ } else if (cmd && !strcmp("get_property_string", cmd)) {
if (cmd_node->u.list->num != 2) {
rc = MPV_ERROR_INVALID_PARAMETER;
goto error;
@@ -279,8 +227,8 @@ static char *json_execute_command(struct mpv_handle *client, void *ta_parent,
} else {
mpv_node_map_add_null(ta_parent, &reply_node, "data");
}
- } else if (!strcmp("set_property", cmd) ||
- !strcmp("set_property_string", cmd))
+ } else if (cmd && (!strcmp("set_property", cmd) ||
+ !strcmp("set_property_string", cmd)))
{
if (cmd_node->u.list->num != 3) {
rc = MPV_ERROR_INVALID_PARAMETER;
@@ -294,7 +242,7 @@ static char *json_execute_command(struct mpv_handle *client, void *ta_parent,
rc = mpv_set_property(client, cmd_node->u.list->values[1].u.string,
MPV_FORMAT_NODE, &cmd_node->u.list->values[2]);
- } else if (!strcmp("observe_property", cmd)) {
+ } else if (cmd && !strcmp("observe_property", cmd)) {
if (cmd_node->u.list->num != 3) {
rc = MPV_ERROR_INVALID_PARAMETER;
goto error;
@@ -314,7 +262,7 @@ static char *json_execute_command(struct mpv_handle *client, void *ta_parent,
cmd_node->u.list->values[1].u.int64,
cmd_node->u.list->values[2].u.string,
MPV_FORMAT_NODE);
- } else if (!strcmp("observe_property_string", cmd)) {
+ } else if (cmd && !strcmp("observe_property_string", cmd)) {
if (cmd_node->u.list->num != 3) {
rc = MPV_ERROR_INVALID_PARAMETER;
goto error;
@@ -334,7 +282,7 @@ static char *json_execute_command(struct mpv_handle *client, void *ta_parent,
cmd_node->u.list->values[1].u.int64,
cmd_node->u.list->values[2].u.string,
MPV_FORMAT_STRING);
- } else if (!strcmp("unobserve_property", cmd)) {
+ } else if (cmd && !strcmp("unobserve_property", cmd)) {
if (cmd_node->u.list->num != 2) {
rc = MPV_ERROR_INVALID_PARAMETER;
goto error;
@@ -347,7 +295,7 @@ static char *json_execute_command(struct mpv_handle *client, void *ta_parent,
rc = mpv_unobserve_property(client,
cmd_node->u.list->values[1].u.int64);
- } else if (!strcmp("request_log_messages", cmd)) {
+ } else if (cmd && !strcmp("request_log_messages", cmd)) {
if (cmd_node->u.list->num != 2) {
rc = MPV_ERROR_INVALID_PARAMETER;
goto error;
@@ -360,8 +308,8 @@ static char *json_execute_command(struct mpv_handle *client, void *ta_parent,
rc = mpv_request_log_messages(client,
cmd_node->u.list->values[1].u.string);
- } else if (!strcmp("enable_event", cmd) ||
- !strcmp("disable_event", cmd))
+ } else if (cmd && (!strcmp("enable_event", cmd) ||
+ !strcmp("disable_event", cmd)))
{
bool enable = !strcmp("enable_event", cmd);
@@ -394,11 +342,19 @@ static char *json_execute_command(struct mpv_handle *client, void *ta_parent,
rc = mpv_request_event(client, event, enable);
}
} else {
- mpv_node result_node;
+ mpv_node result_node = {0};
- rc = mpv_command_node(client, cmd_node, &result_node);
- if (rc >= 0)
- mpv_node_map_add(ta_parent, &reply_node, "data", &result_node);
+ if (async) {
+ rc = mpv_command_node_async(client, reqid, cmd_node);
+ if (rc >= 0)
+ send_reply = false;
+ } else {
+ rc = mpv_command_node(client, cmd_node, &result_node);
+ if (rc >= 0)
+ mpv_node_map_add(ta_parent, &reply_node, "data", &result_node);
+ }
+
+ mpv_free_node_contents(&result_node);
}
error:
@@ -415,8 +371,11 @@ error:
mpv_node_map_add_string(ta_parent, &reply_node, "error", mpv_error_string(rc));
char *output = talloc_strdup(ta_parent, "");
- json_write(&output, &reply_node);
- output = ta_talloc_strdup_append(output, "\n");
+
+ if (send_reply) {
+ json_write(&output, &reply_node);
+ output = ta_talloc_strdup_append(output, "\n");
+ }
return output;
}