summaryrefslogtreecommitdiffstats
path: root/player
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2020-07-17 01:34:46 +0200
committerwm4 <wm4@nowhere>2020-07-20 21:02:17 +0200
commit0279a44d93a378fbdff393d6568a691817f83518 (patch)
treee81a2984f7d71cccb871f43c2c6e25c652548834 /player
parentc9742413ac5eeabfdd46503f67b7393c9bd99f49 (diff)
downloadmpv-0279a44d93a378fbdff393d6568a691817f83518.tar.bz2
mpv-0279a44d93a378fbdff393d6568a691817f83518.tar.xz
command: extend subprocess command
Add env and detach arguments. This means the command.c code must use the "new" mp_subprocess2(). So also take this as an opportunity to clean up. win32 support gets broken by it, because it never made the switch to the newer function. The new detach parameter makes the "run" command fully redundant, but I guess we'll keep it for simplicity. But change its implementation to use mp_subprocess2() (couldn't do this earlier, because win32). Privately, I'm going to use the "env" argument to add a key binding that starts a shell with a FILE environment variable set to the currently playing file, so this is very useful to me. Note: breaks windows, so for example youtube-dl on windows will not work anymore. mp_subprocess2() has to be implemented. The old functions are gone, and subprocess-win.c is not built anymore. It will probably work on Cygwin.
Diffstat (limited to 'player')
-rw-r--r--player/command.c118
1 files changed, 82 insertions, 36 deletions
diff --git a/player/command.c b/player/command.c
index 08c5caf1f7..dd6efbea86 100644
--- a/player/command.c
+++ b/player/command.c
@@ -5242,48 +5242,54 @@ static void cmd_run(void *p)
char **args = talloc_zero_array(NULL, char *, cmd->num_args + 1);
for (int n = 0; n < cmd->num_args; n++)
args[n] = cmd->args[n].v.s;
- mp_subprocess_detached(mpctx->log, args);
+ mp_msg_flush_status_line(mpctx->log);
+ struct mp_subprocess_opts opts = {
+ .exe = args[0],
+ .args = args,
+ .fds = { {0, .src_fd = 0}, {1, .src_fd = 1}, {2, .src_fd = 2} },
+ .num_fds = 3,
+ .detach = true,
+ };
+ struct mp_subprocess_result res;
+ mp_subprocess2(&opts, &res);
+ if (res.error < 0) {
+ mp_err(mpctx->log, "Starting subprocess failed: %s\n",
+ mp_subprocess_err_str(res.error));
+ }
talloc_free(args);
}
-struct subprocess_cb_ctx {
+struct subprocess_fd_ctx {
struct mp_log *log;
void* talloc_ctx;
int64_t max_size;
- bool capture[3];
- bstr output[3];
+ int msgl;
+ bool capture;
+ bstr output;
};
-static void subprocess_output(struct subprocess_cb_ctx *ctx, int fd,
- char *data, size_t size)
+static void subprocess_read(void *p, char *data, size_t size)
{
- if (ctx->capture[fd]) {
- if (ctx->output[fd].len < ctx->max_size)
- bstr_xappend(ctx->talloc_ctx, &ctx->output[fd], (bstr){data, size});
+ struct subprocess_fd_ctx *ctx = p;
+ if (ctx->capture) {
+ if (ctx->output.len < ctx->max_size)
+ bstr_xappend(ctx->talloc_ctx, &ctx->output, (bstr){data, size});
} else {
- int msgl = fd == 2 ? MSGL_ERR : MSGL_INFO;
- mp_msg(ctx->log, msgl, "%.*s", (int)size, data);
+ mp_msg(ctx->log, ctx->msgl, "%.*s", (int)size, data);
}
}
-static void subprocess_stdout(void *p, char *data, size_t size)
-{
- struct subprocess_cb_ctx *ctx = p;
- subprocess_output(ctx, 1, data, size);
-}
-
-static void subprocess_stderr(void *p, char *data, size_t size)
-{
- struct subprocess_cb_ctx *ctx = p;
- subprocess_output(ctx, 2, data, size);
-}
-
static void cmd_subprocess(void *p)
{
struct mp_cmd_ctx *cmd = p;
struct MPContext *mpctx = cmd->mpctx;
char **args = cmd->args[0].v.str_list;
bool playback_only = cmd->args[1].v.i;
+ bool detach = cmd->args[5].v.i;
+ char **env = cmd->args[6].v.str_list;
+
+ if (env && !env[0])
+ env = NULL; // do not actually set an empty environment
if (!args || !args[0]) {
MP_ERR(mpctx, "program name missing\n");
@@ -5292,12 +5298,19 @@ static void cmd_subprocess(void *p)
}
void *tmp = talloc_new(NULL);
- struct subprocess_cb_ctx ctx = {
- .log = mp_log_new(tmp, mpctx->log, cmd->cmd->sender),
- .talloc_ctx = tmp,
- .max_size = cmd->args[2].v.i,
- .capture = {0, cmd->args[3].v.i, cmd->args[4].v.i},
- };
+
+ struct mp_log *fdlog = mp_log_new(tmp, mpctx->log, cmd->cmd->sender);
+ struct subprocess_fd_ctx fdctx[3];
+ for (int fd = 0; fd < 3; fd++) {
+ fdctx[fd] = (struct subprocess_fd_ctx) {
+ .log = fdlog,
+ .talloc_ctx = tmp,
+ .max_size = cmd->args[2].v.i,
+ .msgl = fd == 2 ? MSGL_ERR : MSGL_INFO,
+ };
+ }
+ fdctx[1].capture = cmd->args[3].v.i;
+ fdctx[2].capture = cmd->args[4].v.i;
pthread_mutex_lock(&mpctx->abort_lock);
cmd->abort->coupled_to_playback = playback_only;
@@ -5306,9 +5319,40 @@ static void cmd_subprocess(void *p)
mp_core_unlock(mpctx);
+ struct mp_subprocess_opts opts = {
+ .exe = args[0],
+ .args = args,
+ .env = env,
+ .cancel = cmd->abort->cancel,
+ .detach = detach,
+ .fds = {
+ {
+ .fd = 0, // stdin
+ .src_fd = 0,
+ },
+ },
+ .num_fds = 1,
+ };
+
+ // stdout, stderr
+ for (int fd = 1; fd < 3; fd++) {
+ bool capture = fdctx[fd].capture || !detach;
+ opts.fds[opts.num_fds++] = (struct mp_subprocess_fd){
+ .fd = fd,
+ .src_fd = capture ? -1 : fd,
+ .on_read = capture ? subprocess_read : NULL,
+ .on_read_ctx = &fdctx[fd],
+ };
+ }
+
+ struct mp_subprocess_result sres;
+ mp_subprocess2(&opts, &sres);
+ int status = sres.exit_status;
char *error = NULL;
- int status = mp_subprocess(args, cmd->abort->cancel, &ctx,
- subprocess_stdout, subprocess_stderr, &error);
+ if (sres.error < 0) {
+ error = (char *)mp_subprocess_err_str(sres.error);
+ status = sres.error;
+ }
mp_core_lock(mpctx);
@@ -5318,14 +5362,14 @@ static void cmd_subprocess(void *p)
node_map_add_flag(res, "killed_by_us", status == MP_SUBPROCESS_EKILLED_BY_US);
node_map_add_string(res, "error_string", error ? error : "");
const char *sname[] = {NULL, "stdout", "stderr"};
- for (int n = 1; n < 3; n++) {
- if (!ctx.capture[n])
+ for (int fd = 1; fd < 3; fd++) {
+ if (!fdctx[fd].capture)
continue;
struct mpv_byte_array *ba =
- node_map_add(res, sname[n], MPV_FORMAT_BYTE_ARRAY)->u.ba;
+ node_map_add(res, sname[fd], MPV_FORMAT_BYTE_ARRAY)->u.ba;
*ba = (struct mpv_byte_array){
- .data = talloc_steal(ba, ctx.output[n].start),
- .size = ctx.output[n].len,
+ .data = talloc_steal(ba, fdctx[fd].output.start),
+ .size = fdctx[fd].output.len,
};
}
@@ -5963,6 +6007,8 @@ const struct mp_cmd_def mp_cmds[] = {
OPTDEF_INT64(64 * 1024 * 1024)},
{"capture_stdout", OPT_FLAG(v.i), .flags = MP_CMD_OPT_ARG},
{"capture_stderr", OPT_FLAG(v.i), .flags = MP_CMD_OPT_ARG},
+ {"detach", OPT_FLAG(v.i), .flags = MP_CMD_OPT_ARG},
+ {"env", OPT_STRINGLIST(v.str_list), .flags = MP_CMD_OPT_ARG},
},
.spawn_thread = true,
.can_abort = true,