diff options
Diffstat (limited to 'player')
-rw-r--r-- | player/command.c | 118 |
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, |