diff --git a/DOCS/interface-changes/msg-prefix.txt b/DOCS/interface-changes/msg-prefix.txt new file mode 100644 index 0000000000000..5df0adb4eb024 --- /dev/null +++ b/DOCS/interface-changes/msg-prefix.txt @@ -0,0 +1 @@ +add `msg-prefix` command diff --git a/DOCS/interface-changes/msg.txt b/DOCS/interface-changes/msg.txt new file mode 100644 index 0000000000000..79d11f58e7538 --- /dev/null +++ b/DOCS/interface-changes/msg.txt @@ -0,0 +1 @@ +add `msg` command diff --git a/DOCS/man/input.rst b/DOCS/man/input.rst index a4307c81467a8..da21d9f31a1a5 100644 --- a/DOCS/man/input.rst +++ b/DOCS/man/input.rst @@ -814,6 +814,20 @@ Text Manipulation This line of Lua prints "foo \\{bar}" on the OSD. +``msg [...]`` + Write a log message. ``level`` must be one of the log levels accepted by the + ``mp.msg.log`` Lua function. The ``message`` arguments are separated from + each other with a space. A newline is added to the end of the message. + + This command has a variable number of arguments, and cannot be used with + named arguments. + + .. note:: Lua and JS code should use the provided ``mp.msg`` modules. + +``msg-prefix [...]`` + Same as ``msg``, but allows writing messages using ``prefix`` as the prefix + instead of the name of the client that sent the command. + Configuration Commands ~~~~~~~~~~~~~~~~~~~~~~ diff --git a/player/command.c b/player/command.c index 9a378f76dfdb2..70b20f1992698 100644 --- a/player/command.c +++ b/player/command.c @@ -7104,6 +7104,44 @@ static void cmd_notify_property(void *p) mp_notify_property(mpctx, cmd->args[0].v.s); } +static void cmd_msg(void *p) +{ + struct mp_cmd_ctx *cmd = p; + struct MPContext *mpctx = cmd->mpctx; + + if (cmd->num_args < 2) + return; + + int level = mp_msg_find_level(cmd->args[0].v.s); + if (level < 0) + return; + + struct mp_log *log = mp_log_new(NULL, mpctx->log, cmd->cmd->sender); + for (int i = 1; i < cmd->num_args; i++) + mp_msg(log, level, (i == 1 ? "%s" : " %s"), cmd->args[i].v.s); + mp_msg(log, level, "\n"); + talloc_free(log); +} + +static void cmd_msg_prefix(void *p) +{ + struct mp_cmd_ctx *cmd = p; + struct MPContext *mpctx = cmd->mpctx; + + if (cmd->num_args < 3) + return; + + int level = mp_msg_find_level(cmd->args[0].v.s); + if (level < 0) + return; + + struct mp_log *log = mp_log_new(NULL, mpctx->log, cmd->args[1].v.s); + for (int i = 2; i < cmd->num_args; i++) + mp_msg(log, level, (i == 2 ? "%s" : " %s"), cmd->args[i].v.s); + mp_msg(log, level, "\n"); + talloc_free(log); +} + /* This array defines all known commands. * The first field the command name used in libmpv and input.conf. * The second field is the handler function (see mp_cmd_def.handler and @@ -7623,6 +7661,13 @@ const struct mp_cmd_def mp_cmds[] = { { "notify-property", cmd_notify_property, { {"property", OPT_STRING(v.s)} } }, + { "msg", cmd_msg, { {"level", OPT_STRING(v.s)}, {"message", OPT_STRING(v.s)} }, + .is_noisy = true, .vararg = true }, + { "msg-prefix", cmd_msg_prefix, { {"level", OPT_STRING(v.s)}, + {"prefix", OPT_STRING(v.s)}, + {"message", OPT_STRING(v.s)} }, + .is_noisy = true, .vararg = true }, + {0} }; diff --git a/player/javascript.c b/player/javascript.c index b435c14882920..4921481bc87a2 100644 --- a/player/javascript.c +++ b/player/javascript.c @@ -29,7 +29,6 @@ #include "common/common.h" #include "options/m_property.h" #include "common/msg.h" -#include "common/msg_control.h" #include "common/stats.h" #include "options/m_option.h" #include "input/input.h" @@ -565,21 +564,6 @@ static int checkopt(js_State *J, int idx, const char *def, const char *opts[], js_error(J, "Invalid %s '%s'", desc, opt); } -// args: level as string and a variable numbers of args to print. adds final \n -static void script_log(js_State *J) -{ - const char *level = js_tostring(J, 1); - int msgl = mp_msg_find_level(level); - if (msgl < 0) - js_error(J, "Invalid log level '%s'", level); - - struct mp_log *log = jctx(J)->log; - for (int top = js_gettop(J), i = 2; i < top; i++) - mp_msg(log, msgl, (i == 2 ? "%s" : " %s"), js_tostring(J, i)); - mp_msg(log, msgl, "\n"); - push_success(J); -} - static void script_find_config_file(js_State *J, void *af) { const char *fname = js_tostring(J, 1); @@ -1155,7 +1139,6 @@ struct fn_entry { // Names starting with underscore are wrapped at @defaults.js // FN_ENTRY is a normal js C function, AF_ENTRY is an autofree js C function. static const struct fn_entry main_fns[] = { - FN_ENTRY(log, 1), AF_ENTRY(wait_event, 1), FN_ENTRY(_request_event, 2), AF_ENTRY(find_config_file, 1), diff --git a/player/javascript/defaults.js b/player/javascript/defaults.js index ae687febe1014..b421213d0a3d9 100644 --- a/player/javascript/defaults.js +++ b/player/javascript/defaults.js @@ -5,6 +5,13 @@ // - The names of function expressions are not required, but are used in stack // traces. We name them where useful to show up (fname:#line always shows). +mp.log = function(level) { + var cmd = ["msg", level]; + for (var i = 1; i < arguments.length; i++) + cmd.push(String(arguments[i])) + mp.command_native(cmd); +} + mp.msg = { log: mp.log }; mp.msg.verbose = mp.log.bind(null, "v"); var levels = ["fatal", "error", "warn", "info", "debug", "trace"]; diff --git a/player/lua.c b/player/lua.c index 83964daebbddb..e9f98291d5017 100644 --- a/player/lua.c +++ b/player/lua.c @@ -32,7 +32,6 @@ #include "common/common.h" #include "options/m_property.h" #include "common/msg.h" -#include "common/msg_control.h" #include "common/stats.h" #include "options/m_option.h" #include "input/input.h" @@ -499,39 +498,6 @@ static int load_lua(struct mp_script_args *args) return r; } -static int check_loglevel(lua_State *L, int arg) -{ - const char *level = luaL_checkstring(L, arg); - int n = mp_msg_find_level(level); - if (n >= 0) - return n; - luaL_error(L, "Invalid log level '%s'", level); - abort(); -} - -static int script_log(lua_State *L) -{ - struct script_ctx *ctx = get_ctx(L); - - int msgl = check_loglevel(L, 1); - - int last = lua_gettop(L); - lua_getglobal(L, "tostring"); // args... tostring - for (int i = 2; i <= last; i++) { - lua_pushvalue(L, -1); // args... tostring tostring - lua_pushvalue(L, i); // args... tostring tostring args[i] - lua_call(L, 1, 1); // args... tostring str - const char *s = lua_tostring(L, -1); - if (s == NULL) - return luaL_error(L, "Invalid argument"); - mp_msg(ctx->log, msgl, (i == 2 ? "%s" : " %s"), s); - lua_pop(L, 1); // args... tostring - } - mp_msg(ctx->log, msgl, "\n"); - - return 0; -} - static int script_find_config_file(lua_State *L) { struct MPContext *mpctx = get_mpctx(L); @@ -1226,7 +1192,6 @@ struct fn_entry { }; static const struct fn_entry main_fns[] = { - FN_ENTRY(log), AF_ENTRY(raw_wait_event), FN_ENTRY(request_event), FN_ENTRY(find_config_file), diff --git a/player/lua/defaults.lua b/player/lua/defaults.lua index 278f411ad4b8d..03bc56badec8f 100644 --- a/player/lua/defaults.lua +++ b/player/lua/defaults.lua @@ -486,6 +486,14 @@ end -- sent by "script-binding" mp.register_script_message("key-binding", dispatch_key_binding) +function mp.log(level, ...) + local cmd = {"msg", level} + for i = 1, select("#", ...) do + cmd[#cmd + 1] = tostring(select(i, ...)) + end + mp.command_native(cmd) +end + mp.msg = { log = mp.log, fatal = function(...) return mp.log("fatal", ...) end,