summaryrefslogtreecommitdiffstats
path: root/player
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2020-03-21 19:31:58 +0100
committerwm4 <wm4@nowhere>2020-03-21 19:33:48 +0100
commit218d6643e940dde2a01260cf8def70efc100cd43 (patch)
treef7ce9e059456eeaa3e33b08d8fa96512573c6a99 /player
parent7e885a3bc3af4df93681b6e760a34e59e2f47ef7 (diff)
downloadmpv-218d6643e940dde2a01260cf8def70efc100cd43.tar.bz2
mpv-218d6643e940dde2a01260cf8def70efc100cd43.tar.xz
client API, lua, ipc: unify event struct return
Both Lua and the JSON IPC code need to convert the mpv_event struct (and everything it points to) to Lua tables or JSON. I was getting sick of having to make the same changes to Lua and IPC. Do what has been done everywhere else, and let the core handle this by going through mpv_node (which is supposed to serve both Lua tables and JSON, and potentially other scripting language backends). Expose it as new libmpv API function. The new API is still a bit "rough" and support for other event types might be added in the future. This silently adds support for the playlist_entry_id fields to both Lua and JSON IPC. There is a small API change for Lua; I don't think this matters, so I didn't care about compatibility. The new code in client.c is mashed up from the Lua and the IPC code. The manpage additions are moved from the Lua docs, and made slightly more "general". Some danger for unintended regressions both in Lua and IPC. Also damn these node functions suck, expect crashes due to UB. Not sure why this became more code instead of less compared to before (according to the diff stat), even though some code duplication across Lua and IPC was removed. Software development sucks.
Diffstat (limited to 'player')
-rw-r--r--player/client.c100
-rw-r--r--player/lua.c61
2 files changed, 111 insertions, 50 deletions
diff --git a/player/client.c b/player/client.c
index f9f8cd48f6..396c623cea 100644
--- a/player/client.c
+++ b/player/client.c
@@ -676,6 +676,9 @@ static void dup_event_data(struct mpv_event *ev)
ev->data = msg;
break;
}
+ case MPV_EVENT_START_FILE:
+ ev->data = talloc_memdup(NULL, ev->data, sizeof(mpv_event_start_file));
+ break;
case MPV_EVENT_END_FILE:
ev->data = talloc_memdup(NULL, ev->data, sizeof(mpv_event_end_file));
break;
@@ -1910,6 +1913,103 @@ unsigned long mpv_client_api_version(void)
return MPV_CLIENT_API_VERSION;
}
+int mpv_event_to_node(mpv_node *dst, mpv_event *event)
+{
+ *dst = (mpv_node){0};
+
+ node_init(dst, MPV_FORMAT_NODE_MAP, NULL);
+ node_map_add_string(dst, "event", mpv_event_name(event->event_id));
+
+ if (event->error < 0)
+ node_map_add_string(dst, "error", mpv_error_string(event->error));
+
+ switch (event->event_id) {
+
+ case MPV_EVENT_START_FILE: {
+ mpv_event_start_file *esf = event->data;
+
+ node_map_add_int64(dst, "playlist_entry_id", esf->playlist_entry_id);
+ break;
+ }
+
+ case MPV_EVENT_END_FILE: {
+ mpv_event_end_file *eef = event->data;
+
+ const char *reason;
+ switch (eef->reason) {
+ case MPV_END_FILE_REASON_EOF: reason = "eof"; break;
+ case MPV_END_FILE_REASON_STOP: reason = "stop"; break;
+ case MPV_END_FILE_REASON_QUIT: reason = "quit"; break;
+ case MPV_END_FILE_REASON_ERROR: reason = "error"; break;
+ case MPV_END_FILE_REASON_REDIRECT: reason = "redirect"; break;
+ default:
+ reason = "unknown";
+ }
+ node_map_add_string(dst, "reason", reason);
+
+ node_map_add_int64(dst, "playlist_entry_id", eef->playlist_entry_id);
+
+ if (eef->reason == MPV_END_FILE_REASON_ERROR)
+ node_map_add_string(dst, "file_error", mpv_error_string(eef->error));
+ break;
+ }
+
+ case MPV_EVENT_LOG_MESSAGE: {
+ mpv_event_log_message *msg = event->data;
+
+ node_map_add_string(dst, "prefix", msg->prefix);
+ node_map_add_string(dst, "level", msg->level);
+ node_map_add_string(dst, "text", msg->text);
+ break;
+ }
+
+ case MPV_EVENT_CLIENT_MESSAGE: {
+ mpv_event_client_message *msg = event->data;
+
+ struct mpv_node *args = node_map_add(dst, "args", MPV_FORMAT_NODE_ARRAY);
+ for (int n = 0; n < msg->num_args; n++) {
+ struct mpv_node *sn = node_array_add(args, MPV_FORMAT_NONE);
+ sn->format = MPV_FORMAT_STRING;
+ sn->u.string = (char *)msg->args[n];
+ }
+ break;
+ }
+
+ case MPV_EVENT_PROPERTY_CHANGE: {
+ mpv_event_property *prop = event->data;
+
+ node_map_add_string(dst, "name", prop->name);
+
+ switch (prop->format) {
+ case MPV_FORMAT_NODE:
+ *node_map_add(dst, "data", MPV_FORMAT_NONE) =
+ *(struct mpv_node *)prop->data;
+ break;
+ case MPV_FORMAT_DOUBLE:
+ node_map_add_double(dst, "data", *(double *)prop->data);
+ break;
+ case MPV_FORMAT_FLAG:
+ node_map_add_flag(dst, "data", *(int *)prop->data);
+ break;
+ case MPV_FORMAT_STRING:
+ node_map_add_string(dst, "data", *(char **)prop->data);
+ break;
+ default: ;
+ }
+ break;
+ }
+
+ case MPV_EVENT_HOOK: {
+ mpv_event_hook *hook = event->data;
+
+ node_map_add_int64(dst, "hook_id", hook->id);
+ break;
+ }
+
+ }
+ return 0;
+}
+
static const char *const err_table[] = {
[-MPV_ERROR_SUCCESS] = "success",
[-MPV_ERROR_EVENT_QUEUE_FULL] = "event queue full",
diff --git a/player/lua.c b/player/lua.c
index 13a368f7c5..aa0b071eb5 100644
--- a/player/lua.c
+++ b/player/lua.c
@@ -519,50 +519,6 @@ static int script_wait_event(lua_State *L)
}
switch (event->event_id) {
- case MPV_EVENT_LOG_MESSAGE: {
- mpv_event_log_message *msg = event->data;
-
- lua_pushstring(L, msg->prefix); // event s
- lua_setfield(L, -2, "prefix"); // event
- lua_pushstring(L, msg->level); // event s
- lua_setfield(L, -2, "level"); // event
- lua_pushstring(L, msg->text); // event s
- lua_setfield(L, -2, "text"); // event
- break;
- }
- case MPV_EVENT_CLIENT_MESSAGE: {
- mpv_event_client_message *msg = event->data;
-
- lua_newtable(L); // event args
- for (int n = 0; n < msg->num_args; n++) {
- lua_pushinteger(L, n + 1); // event args N
- lua_pushstring(L, msg->args[n]); // event args N val
- lua_settable(L, -3); // event args
- }
- lua_setfield(L, -2, "args"); // event
- break;
- }
- case MPV_EVENT_END_FILE: {
- mpv_event_end_file *eef = event->data;
- const char *reason;
- switch (eef->reason) {
- case MPV_END_FILE_REASON_EOF: reason = "eof"; break;
- case MPV_END_FILE_REASON_STOP: reason = "stop"; break;
- case MPV_END_FILE_REASON_QUIT: reason = "quit"; break;
- case MPV_END_FILE_REASON_ERROR: reason = "error"; break;
- case MPV_END_FILE_REASON_REDIRECT: reason = "redirect"; break;
- default:
- reason = "unknown";
- }
- lua_pushstring(L, reason); // event reason
- lua_setfield(L, -2, "reason"); // event
-
- if (eef->reason == MPV_END_FILE_REASON_ERROR) {
- lua_pushstring(L, mpv_error_string(eef->error)); // event error
- lua_setfield(L, -2, "error"); // event
- }
- break;
- }
case MPV_EVENT_PROPERTY_CHANGE: {
mpv_event_property *prop = event->data;
lua_pushstring(L, prop->name);
@@ -586,12 +542,6 @@ static int script_wait_event(lua_State *L)
lua_setfield(L, -2, "data");
break;
}
- case MPV_EVENT_HOOK: {
- mpv_event_hook *hook = event->data;
- lua_pushinteger(L, hook->id);
- lua_setfield(L, -2, "hook_id");
- break;
- }
case MPV_EVENT_COMMAND_REPLY: {
mpv_event_command *cmd = event->data;
pushnode(L, &cmd->result);
@@ -599,6 +549,17 @@ static int script_wait_event(lua_State *L)
break;
}
default: ;
+ struct mpv_node rn;
+ mpv_event_to_node(&rn, event);
+
+ assert(rn.format == MPV_FORMAT_NODE_MAP);
+ mpv_node_list *list = rn.u.list;
+ for (int n = 0; n < list->num; n++) {
+ pushnode(L, &list->values[n]);
+ lua_setfield(L, -2, list->keys[n]);
+ }
+
+ mpv_free_node_contents(&rn);
}
// return event