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.
This commit is contained in:
wm4
2020-02-19 22:18:15 +01:00
parent d06ebe2251
commit e2ab6b7f35
8 changed files with 177 additions and 21 deletions

View File

@@ -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.

View File

@@ -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)
{
}

View File

@@ -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);
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,
};
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)

View File

@@ -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