summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--DOCS/man/en/lua.rst100
-rw-r--r--player/lua.c13
-rw-r--r--player/lua/defaults.lua78
3 files changed, 188 insertions, 3 deletions
diff --git a/DOCS/man/en/lua.rst b/DOCS/man/en/lua.rst
index 0a03ebde5c..89abcb00b5 100644
--- a/DOCS/man/en/lua.rst
+++ b/DOCS/man/en/lua.rst
@@ -92,6 +92,97 @@ The ``mp`` module is preloaded, although it can be loaded manually with
Return the current mpv internal time in seconds as a number. This is
basically the system time, with an arbitrary offset.
+``mp.register_script_command(name, fn)``
+ Register a command named ``name``. If the script receives a message
+ with the given name as first argument, ``fn(...)`` is called with the
+ rest of the script commands.
+
+ If a command with the given name already exists, it's overwritten.
+
+ This is intended for allowing users to interact the script in some ways
+ using the ``script_message`` input command.
+
+ Example:
+
+ In a script, say ``fooscript.lua``:
+
+ ::
+
+ function something_handler(arg1, arg2)
+ print("arg1=" .. arg1)
+ print("arg2=" .. arg2)
+ end
+ mp.register_script_command("something", something_handler)
+
+ input.conf:
+
+ ::
+
+ x script_message lua/fooscript something "hello" "you"
+
+ This will print the lines ``arg1=hello`` and ``arg2=something`` when the
+ key ``x`` is pressed.
+
+ Also see ``mp.add_key_binding`` how to add key bindings by default.
+
+``mp.unregister_script_command(name)``
+ Undo a previous registration with ``mp.register_script_command``. Does
+ nothing if the ``name`` wasn't registered.
+
+``mp.add_key_binding(key, name|fn [,fn])``
+ Register a key binding. The binding will be mapped to the given ``key``,
+ which is a string describing the physical key. This uses the same key
+ names as in input.conf, and also allows combinations (e.g. ``ctrl+a``).
+
+ Key bindings are dispatched as script commands. The ``name`` argument is
+ the name used to invoke command handlers as registered by
+ ``mp.register_script_command``. The name can also be used by users to remap
+ the bindings provided by your script (see below).
+
+ If a key binding or a command with the given name already exists, it's
+ overwritten.
+
+ The ``fn`` parameter is optional. If provided, it must be a function, and
+ will be called when the key is pressed. Actually, this just for
+ convenience, and literally calls ``mp.register_script_command(name, fn)``.
+
+ You can also omit the name and only provide a function ``fn`` instead. Then
+ a random name is generated internally.
+
+ Example:
+
+ ::
+
+ function something_handler()
+ print("the key was pressed")
+ end
+ mp.add_key_binding("x", "something", something_handler)
+
+ This will print the message ``the key was pressed`` when ``x`` was pressed.
+
+ The user can remap these key bindings. Assume the above script was using
+ the filename ``fooscript.lua``, then the user has to put the following
+ into his input.conf to remap the command to the ``y`` key:
+
+ ::
+
+ y script_message lua/fooscript something
+
+ This will print the message when the key ``y`` is pressed. (``x`` will
+ still work, unless the user overmaps it.)
+
+``mp.add_forced_key_binding(...)``
+ This works almost the same as ``mp.add_key_binding``, but registers the
+ key binding in a way that will overwrite the user's custom bindings in his
+ input.conf. (``mp.add_key_binding`` overwrites default key bindings only,
+ but not those by the user's input.conf.)
+
+``mp.remove_key_binding(name)``
+ Remove a key binding added with ``mp.add_key_binding`` or
+ ``mp.add_forced_key_binding``. Use the same name as you used when adding
+ the bindings. It's not possible to remove bindings for which you omitted
+ the name.
+
``mp.register_event(name, fn)``
Call a specific function when an event happens. The event name is a string,
and the function fn is a Lua function value.
@@ -136,7 +227,14 @@ The ``mp`` module is preloaded, although it can be loaded manually with
this equally, so you should be careful about collisions.
``mp.get_script_name()``
- Return the name of the current script.
+ Return the name of the current script. The name is usually made of the
+ filename of the script, with directory and file extension removed, and
+ prefixed with ``lua/``. If there are several script which would have the
+ same name, it's made unique by appending a number.
+
+ .. admonition:: Example
+
+ The script ``/path/to/fooscript.lua`` becomes ``lua/fooscript``.
``mp.suspend()``
Suspend the mpv main loop. There is a long-winded explanation of this in
diff --git a/player/lua.c b/player/lua.c
index dbe97cc278..e813d84bce 100644
--- a/player/lua.c
+++ b/player/lua.c
@@ -666,7 +666,18 @@ static int script_input_define_section(lua_State *L)
struct MPContext *mpctx = get_mpctx(L);
char *section = (char *)luaL_checkstring(L, 1);
char *contents = (char *)luaL_checkstring(L, 2);
- mp_input_define_section(mpctx->input, section, "<script>", contents, true);
+ char *flags = (char *)luaL_optstring(L, 3, "");
+ bool builtin = true;
+ if (strcmp(flags, "builtin") == 0) {
+ builtin = true;
+ } else if (strcmp(flags, "default") == 0) {
+ builtin = false;
+ } else if (strcmp(flags, "") == 0) {
+ //pass
+ } else {
+ luaL_error(L, "invalid flags: '%*'", flags);
+ }
+ mp_input_define_section(mpctx->input, section, "<script>", contents, builtin);
return 0;
}
diff --git a/player/lua/defaults.lua b/player/lua/defaults.lua
index 037529940f..f6dff96c3d 100644
--- a/player/lua/defaults.lua
+++ b/player/lua/defaults.lua
@@ -4,7 +4,7 @@ end
local callbacks = {}
-- each script has its own section, so that they don't conflict
-local default_section = "input_" .. mp.script_name
+local default_section = "input_dispatch_" .. mp.script_name
-- Set the list of key bindings. These will override the user's bindings, so
-- you should use this sparingly.
@@ -66,6 +66,64 @@ local function script_dispatch(event)
end
end
+-- "Newer" and more convenient API
+
+local key_bindings = {}
+local command_id = 1
+
+local function update_key_bindings()
+ for i = 1, 2 do
+ local section, flags
+ local def = i == 1
+ if def then
+ section = "input_" .. mp.script_name
+ flags = "builtin"
+ else
+ section = "input_forced_" .. mp.script_name
+ flags = "default"
+ end
+ local cfg = ""
+ for k, v in pairs(key_bindings) do
+ if v.forced ~= def then
+ cfg = cfg .. v.key .. " script_message " .. mp.script_name
+ .. " " .. v.name .. "\n"
+ end
+ end
+ mp.input_define_section(section, cfg, flags)
+ -- TODO: remove the section if the script is stopped
+ mp.input_enable_section(section)
+ end
+end
+
+local function add_binding(attrs, key, name, fn)
+ if (type(name) ~= "string") and (not fn) then
+ fn = name
+ name = "command" .. tostring(command_id)
+ command_id = command_id + 1
+ end
+ attrs.key = key
+ attrs.name = name
+ key_bindings[name] = attrs
+ update_key_bindings()
+ if fn then
+ mp.register_script_command(name, fn)
+ end
+end
+
+function mp.add_key_binding(...)
+ add_binding({forced=false}, ...)
+end
+
+function mp.add_forced_key_binding(...)
+ add_binding({forced=true}, ...)
+end
+
+function mp.remove_key_binding(name)
+ key_bindings[name] = nil
+ update_key_bindings()
+ mp.unregister_script_command(name)
+end
+
local timers = {}
function mp.add_timeout(seconds, cb)
@@ -125,6 +183,23 @@ local function process_timers()
end
end
+local commands = {}
+
+function mp.register_script_command(name, fn)
+ commands[name] = fn
+end
+
+function mp.unregister_script_command(name)
+ commands[name] = nil
+end
+
+local function command_dispatch(ev)
+ if #ev.args > 0 then
+ local handler = commands[ev.args[1]]
+ handler(unpack(ev.args, 2))
+ end
+end
+
-- used by default event loop (mp_event_loop()) to decide when to quit
mp.keep_running = true
@@ -143,6 +218,7 @@ end
-- default handlers
mp.register_event("shutdown", function() mp.keep_running = false end)
mp.register_event("script-input-dispatch", script_dispatch)
+mp.register_event("client-message", command_dispatch)
mp.msg = {
log = mp.log,