From e2ab6b7f3567542a2a1b5aab053d513737e72878 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 19 Feb 2020 22:18:15 +0100 Subject: scripting: add a way to run sub processes as "scripts" This is just a more convenient way to start IPC client scripts per mpv instance. Does not work on Windows, although it could if the subprocess and IPC parts are implemented (and I guess .exe/.bat suffixes are required). Also untested whether it builds on Windows. A lot of other things are untested too, so don't complain. --- input/input.h | 10 ++++++++++ input/ipc-dummy.c | 6 ++++++ input/ipc-unix.c | 51 +++++++++++++++++++++++++++++++++++++++++---------- input/ipc-win.c | 6 ++++++ 4 files changed, 63 insertions(+), 10 deletions(-) (limited to 'input') diff --git a/input/input.h b/input/input.h index df51cb7ed4..1a90a47d42 100644 --- a/input/input.h +++ b/input/input.h @@ -213,10 +213,20 @@ void mp_input_sdl_gamepad_add(struct input_ctx *ictx); struct mp_ipc_ctx; struct mp_client_api; +struct mpv_handle; // Platform specific implementation, provided by ipc-*.c. struct mp_ipc_ctx *mp_init_ipc(struct mp_client_api *client_api, struct mpv_global *global); +// Start a thread for the given handle and return a socket in out_fd[0] that +// is served by this thread. If the FD is not full-duplex, then out_fd[0] is +// the user's read-end, and out_fd[1] the write-end, otherwise out_fd[1] is set +// to -1. +// returns: +// true: out_fd[0] and out_fd[1] are set, ownership of h is transferred +// false: out_fd are not touched, caller retains ownership of h +bool mp_ipc_start_anon_client(struct mp_ipc_ctx *ctx, struct mpv_handle *h, + int out_fd[2]); void mp_uninit_ipc(struct mp_ipc_ctx *ctx); // Serialize the given mpv_event structure to JSON. Returns an allocated string. diff --git a/input/ipc-dummy.c b/input/ipc-dummy.c index d9c31c046c..f0232b2f6e 100644 --- a/input/ipc-dummy.c +++ b/input/ipc-dummy.c @@ -8,6 +8,12 @@ struct mp_ipc_ctx *mp_init_ipc(struct mp_client_api *client_api, return NULL; } +bool mp_ipc_start_anon_client(struct mp_ipc_ctx *ctx, struct mpv_handle *h, + int out_fd[2]) +{ + return false; +} + void mp_uninit_ipc(struct mp_ipc_ctx *ctx) { } diff --git a/input/ipc-unix.c b/input/ipc-unix.c index ef478ba35e..0a7f2a5838 100644 --- a/input/ipc-unix.c +++ b/input/ipc-unix.c @@ -58,7 +58,7 @@ struct client_arg { struct mp_log *log; struct mpv_handle *client; - char *client_name; + const char *client_name; int client_fd; bool close_client_fd; @@ -215,9 +215,11 @@ done: return NULL; } -static void ipc_start_client(struct mp_ipc_ctx *ctx, struct client_arg *client) +static bool ipc_start_client(struct mp_ipc_ctx *ctx, struct client_arg *client, + bool free_on_init_fail) { - client->client = mp_new_client(ctx->client_api, client->client_name); + if (!client->client) + client->client = mp_new_client(ctx->client_api, client->client_name); if (!client->client) goto err; @@ -227,16 +229,19 @@ static void ipc_start_client(struct mp_ipc_ctx *ctx, struct client_arg *client) if (pthread_create(&client_thr, NULL, client_thread, client)) goto err; - return; + return true; err: - if (client->client) - mpv_destroy(client->client); + if (free_on_init_fail) { + if (client->client) + mpv_destroy(client->client); - if (client->close_client_fd) - close(client->client_fd); + if (client->close_client_fd) + close(client->client_fd); + } talloc_free(client); + return false; } static void ipc_start_client_json(struct mp_ipc_ctx *ctx, int id, int fd) @@ -246,11 +251,37 @@ 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, .close_client_fd = true, + .writable = true, + }; + ipc_start_client(ctx, client, true); +} + +bool mp_ipc_start_anon_client(struct mp_ipc_ctx *ctx, struct mpv_handle *h, + int out_fd[2]) +{ + int pair[2]; + if (socketpair(AF_UNIX, SOCK_STREAM, 0, pair)) + return false; + + struct client_arg *client = talloc_ptrtype(NULL, client); + *client = (struct client_arg){ + .client = h, + .client_name = mpv_client_name(h), + .client_fd = pair[1], + .close_client_fd = true, .writable = true, }; - ipc_start_client(ctx, client); + if (!ipc_start_client(ctx, client, false)) { + close(pair[0]); + close(pair[1]); + return false; + } + + out_fd[0] = pair[0]; + out_fd[1] = -1; + return true; } static void ipc_start_client_text(struct mp_ipc_ctx *ctx, const char *path) @@ -292,7 +323,7 @@ static void ipc_start_client_text(struct mp_ipc_ctx *ctx, const char *path) .writable = writable, }; - ipc_start_client(ctx, client); + ipc_start_client(ctx, client, true); } static void *ipc_thread(void *p) diff --git a/input/ipc-win.c b/input/ipc-win.c index 727a8cca73..9672ec85fe 100644 --- a/input/ipc-win.c +++ b/input/ipc-win.c @@ -335,6 +335,12 @@ static void ipc_start_client_json(struct mp_ipc_ctx *ctx, int id, HANDLE h) ipc_start_client(ctx, client); } +bool mp_ipc_start_anon_client(struct mp_ipc_ctx *ctx, struct mpv_handle *h, + int out_fd[2]) +{ + return false; +} + static void *ipc_thread(void *p) { // Use PIPE_TYPE_MESSAGE | PIPE_READMODE_BYTE so message framing is -- cgit v1.2.3