summaryrefslogtreecommitdiffstats
path: root/player/command.c
diff options
context:
space:
mode:
Diffstat (limited to 'player/command.c')
-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,