summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2018-05-12 15:36:43 +0200
committerwm4 <wm4@nowhere>2018-05-24 19:56:34 +0200
commit548ef07864f3e1a40f731b2643f037435ceae46d (patch)
treee40245dc8f8b323b00632fc9c4bad9d8f5f131d9
parentd9bc97bda6e4750af2fbbfcb51ddb6b2c04c277b (diff)
downloadmpv-548ef07864f3e1a40f731b2643f037435ceae46d.tar.bz2
mpv-548ef07864f3e1a40f731b2643f037435ceae46d.tar.xz
lua: reimplement mp.subprocess() by invoking the new subprocess command
We keep mp.subprocess() with roughly the same semantics for compatibility with scripts (including the internal ytdl script). Seems to work with rhe ytdl wrapper. Not tested further.
-rw-r--r--DOCS/man/lua.rst56
-rw-r--r--player/command.c2
-rw-r--r--player/lua.c78
-rw-r--r--player/lua/defaults.lua23
4 files changed, 41 insertions, 118 deletions
diff --git a/DOCS/man/lua.rst b/DOCS/man/lua.rst
index dab185a284..ba09164d3b 100644
--- a/DOCS/man/lua.rst
+++ b/DOCS/man/lua.rst
@@ -653,45 +653,23 @@ strictly part of the guaranteed API.
``utils.subprocess(t)``
Runs an external process and waits until it exits. Returns process status
- and the captured output.
-
- The parameter ``t`` is a table. The function reads the following entries:
-
- ``args``
- Array of strings. The first array entry is the executable. This
- can be either an absolute path, or a filename with no path
- components, in which case the ``PATH`` environment variable is
- used to resolve the executable. The other array elements are
- passed as command line arguments.
-
- ``cancellable``
- Optional. If set to ``true`` (default), then if the user stops
- playback or goes to the next file while the process is running,
- the process will be killed.
-
- ``max_size``
- Optional. The maximum size in bytes of the data that can be captured
- from stdout. (Default: 16 MB.)
-
- The function returns a table as result with the following entries:
-
- ``status``
- The raw exit status of the process. It will be negative on error.
-
- ``stdout``
- Captured output stream as string, limited to ``max_size``.
-
- ``error``
- ``nil`` on success. The string ``killed`` if the process was
- terminated in an unusual way. The string ``init`` if the process
- could not be started.
-
- On Windows, ``killed`` is only returned when the process has been
- killed by mpv as a result of ``cancellable`` being set to ``true``.
-
- ``killed_by_us``
- Set to ``true`` if the process has been killed by mpv as a result
- of ``cancellable`` being set to ``true``.
+ and the captured output. This is a legacy wrapper around calling the
+ ``subprocess`` command with ``mp.command_native``. It does the following
+ things:
+
+ - copy the table ``t``
+ - rename ``cancellable`` field to ``playback_only``
+ - rename ``max_size`` to ``capture_size``
+ - set ``capture_stdout`` field to ``true`` if unset
+ - set ``name`` field to ``subprocess``
+ - call ``mp.command_native(copied_t)``
+ - if the command failed, create a dummy result table
+ - copy ``error_string`` to ``error`` field if the string is non-empty
+ - return the result table
+
+ It is recommended to use ``mp.command_native`` or ``mp.command_native_async``
+ directly, instead of calling this legacy wrapper. It is for compatibility
+ only.
``utils.subprocess_detached(t)``
Runs an external process and detaches it from mpv's control.
diff --git a/player/command.c b/player/command.c
index fe6c3fd2ca..f2d7eedd5f 100644
--- a/player/command.c
+++ b/player/command.c
@@ -5680,7 +5680,7 @@ static void cmd_subprocess(void *p)
void *tmp = talloc_new(NULL);
struct subprocess_cb_ctx ctx = {
- .log = mpctx->log,
+ .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},
diff --git a/player/lua.c b/player/lua.c
index 8d4e794a52..f3bc3e699b 100644
--- a/player/lua.c
+++ b/player/lua.c
@@ -1187,83 +1187,6 @@ static int script_join_path(lua_State *L)
return 1;
}
-struct subprocess_cb_ctx {
- struct mp_log *log;
- void* talloc_ctx;
- int64_t max_size;
- bstr output;
-};
-
-static void subprocess_stdout(void *p, char *data, size_t size)
-{
- struct subprocess_cb_ctx *ctx = p;
- if (ctx->output.len < ctx->max_size)
- bstr_xappend(ctx->talloc_ctx, &ctx->output, (bstr){data, size});
-}
-
-static void subprocess_stderr(void *p, char *data, size_t size)
-{
- struct subprocess_cb_ctx *ctx = p;
- MP_INFO(ctx, "%.*s", (int)size, data);
-}
-
-static int script_subprocess(lua_State *L)
-{
- struct script_ctx *ctx = get_ctx(L);
- luaL_checktype(L, 1, LUA_TTABLE);
- void *tmp = mp_lua_PITA(L);
-
- lua_getfield(L, 1, "args"); // args
- int num_args = mp_lua_len(L, -1);
- char *args[256];
- if (num_args > MP_ARRAY_SIZE(args) - 1) // last needs to be NULL
- luaL_error(L, "too many arguments");
- if (num_args < 1)
- luaL_error(L, "program name missing");
- for (int n = 0; n < num_args; n++) {
- lua_pushinteger(L, n + 1); // args n
- lua_gettable(L, -2); // args arg
- args[n] = talloc_strdup(tmp, lua_tostring(L, -1));
- if (!args[n])
- luaL_error(L, "program arguments must be strings");
- lua_pop(L, 1); // args
- }
- args[num_args] = NULL;
- lua_pop(L, 1); // -
-
- lua_getfield(L, 1, "cancellable"); // c
- struct mp_cancel *cancel = NULL;
- if (lua_isnil(L, -1) ? true : lua_toboolean(L, -1))
- cancel = ctx->mpctx->playback_abort;
- lua_pop(L, 1); // -
-
- lua_getfield(L, 1, "max_size"); // m
- int64_t max_size = lua_isnil(L, -1) ? 64 * 1024 * 1024 : lua_tointeger(L, -1);
-
- struct subprocess_cb_ctx cb_ctx = {
- .log = ctx->log,
- .talloc_ctx = tmp,
- .max_size = max_size,
- };
-
- char *error = NULL;
- int status = mp_subprocess(args, cancel, &cb_ctx, subprocess_stdout,
- subprocess_stderr, &error);
-
- lua_newtable(L); // res
- if (error) {
- lua_pushstring(L, error); // res e
- lua_setfield(L, -2, "error"); // res
- }
- lua_pushinteger(L, status); // res s
- lua_setfield(L, -2, "status"); // res
- lua_pushlstring(L, cb_ctx.output.start, cb_ctx.output.len); // res d
- lua_setfield(L, -2, "stdout"); // res
- lua_pushboolean(L, status == MP_SUBPROCESS_EKILLED_BY_US); // res b
- lua_setfield(L, -2, "killed_by_us"); // res
- return 1;
-}
-
static int script_subprocess_detached(lua_State *L)
{
struct script_ctx *ctx = get_ctx(L);
@@ -1386,7 +1309,6 @@ static const struct fn_entry utils_fns[] = {
FN_ENTRY(file_info),
FN_ENTRY(split_path),
FN_ENTRY(join_path),
- FN_ENTRY(subprocess),
FN_ENTRY(subprocess_detached),
FN_ENTRY(getpid),
FN_ENTRY(parse_json),
diff --git a/player/lua/defaults.lua b/player/lua/defaults.lua
index 6f5a9c4b6c..feb400111a 100644
--- a/player/lua/defaults.lua
+++ b/player/lua/defaults.lua
@@ -617,4 +617,27 @@ function mp_utils.format_bytes_humanized(b)
return string.format("%0.2f %s", b, d[i] and d[i] or "*1024^" .. (i-1))
end
+function mp_utils.subprocess(t)
+ local cmd = {}
+ cmd.name = "subprocess"
+ cmd.capture_stdout = true
+ for k, v in pairs(t) do
+ if k == "cancellable" then
+ k = "playback_only"
+ elseif k == "max_size" then
+ k = "capture_size"
+ end
+ cmd[k] = v
+ end
+ local res, err = mp.command_native(cmd)
+ if res == nil then
+ -- an error usually happens only if parsing failed (or no args passed)
+ res = {error_string = err, status = -1}
+ end
+ if res.error_string ~= "" then
+ res.error = res.error_string
+ end
+ return res
+end
+
return {}