diff options
-rw-r--r-- | DOCS/man/en/lua.rst | 100 | ||||
-rw-r--r-- | player/lua.c | 13 | ||||
-rw-r--r-- | player/lua/defaults.lua | 78 |
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, |