diff options
Diffstat (limited to 'input/ipc.c')
-rw-r--r-- | input/ipc.c | 205 |
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; } |