diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 20:36:56 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 20:36:56 +0000 |
commit | 51de1d8436100f725f3576aefa24a2bd2057bc28 (patch) | |
tree | c6d1d5264b6d40a8d7ca34129f36b7d61e188af3 /DOCS/man/lua.rst | |
parent | Initial commit. (diff) | |
download | mpv-51de1d8436100f725f3576aefa24a2bd2057bc28.tar.xz mpv-51de1d8436100f725f3576aefa24a2bd2057bc28.zip |
Adding upstream version 0.37.0.upstream/0.37.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'DOCS/man/lua.rst')
-rw-r--r-- | DOCS/man/lua.rst | 917 |
1 files changed, 917 insertions, 0 deletions
diff --git a/DOCS/man/lua.rst b/DOCS/man/lua.rst new file mode 100644 index 0000000..5708e19 --- /dev/null +++ b/DOCS/man/lua.rst @@ -0,0 +1,917 @@ +LUA SCRIPTING +============= + +mpv can load Lua scripts. (See `Script location`_.) + +mpv provides the built-in module ``mp``, which contains functions to send +commands to the mpv core and to retrieve information about playback state, user +settings, file information, and so on. + +These scripts can be used to control mpv in a similar way to slave mode. +Technically, the Lua code uses the client API internally. + +Example +------- + +A script which leaves fullscreen mode when the player is paused: + +:: + + function on_pause_change(name, value) + if value == true then + mp.set_property("fullscreen", "no") + end + end + mp.observe_property("pause", "bool", on_pause_change) + + +Script location +--------------- + +Scripts can be passed to the ``--script`` option, and are automatically loaded +from the ``scripts`` subdirectory of the mpv configuration directory (usually +``~/.config/mpv/scripts/``). + +A script can be a single file. The file extension is used to select the +scripting backend to use for it. For Lua, it is ``.lua``. If the extension is +not recognized, an error is printed. (If an error happens, the extension is +either mistyped, or the backend was not compiled into your mpv binary.) + +mpv internally loads the script's name by stripping the ``.lua`` extension and +replacing all nonalphanumeric characters with ``_``. E.g., ``my-tools.lua`` +becomes ``my_tools``. If there are several scripts with the same name, it is +made unique by appending a number. This is the name returned by +``mp.get_script_name()``. + +Entries with ``.disable`` extension are always ignored. + +If a script is a directory (either if a directory is passed to ``--script``, +or any sub-directories in the script directory, such as for example +``~/.config/mpv/scripts/something/``), then the directory represents a single +script. The player will try to load a file named ``main.x``, where ``x`` is +replaced with the file extension. For example, if ``main.lua`` exists, it is +loaded with the Lua scripting backend. + +You must not put any other files or directories that start with ``main.`` into +the script's top level directory. If the script directory contains for example +both ``main.lua`` and ``main.js``, only one of them will be loaded (and which +one depends on mpv internals that may change any time). Likewise, if there is +for example ``main.foo``, your script will break as soon as mpv adds a backend +that uses the ``.foo`` file extension. + +mpv also appends the top level directory of the script to the start of Lua's +package path so you can import scripts from there too. Be aware that this will +shadow Lua libraries that use the same package path. (Single file scripts do not +include mpv specific directories in the Lua package path. This was silently +changed in mpv 0.32.0.) + +Using a script directory is the recommended way to package a script that +consists of multiple source files, or requires other files (you can use +``mp.get_script_directory()`` to get the location and e.g. load data files). + +Making a script a git repository, basically a repository which contains a +``main.lua`` file in the root directory, makes scripts easily updateable +(without the dangers of auto-updates). Another suggestion is to use git +submodules to share common files or libraries. + +Details on the script initialization and lifecycle +-------------------------------------------------- + +Your script will be loaded by the player at program start from the ``scripts`` +configuration subdirectory, or from a path specified with the ``--script`` +option. Some scripts are loaded internally (like ``--osc``). Each script runs in +its own thread. Your script is first run "as is", and once that is done, the event loop +is entered. This event loop will dispatch events received by mpv and call your +own event handlers which you have registered with ``mp.register_event``, or +timers added with ``mp.add_timeout`` or similar. Note that since the +script starts execution concurrently with player initialization, some properties +may not be populated with meaningful values until the relevant subsystems have +initialized. + +When the player quits, all scripts will be asked to terminate. This happens via +a ``shutdown`` event, which by default will make the event loop return. If your +script got into an endless loop, mpv will probably behave fine during playback, +but it won't terminate when quitting, because it's waiting on your script. + +Internally, the C code will call the Lua function ``mp_event_loop`` after +loading a Lua script. This function is normally defined by the default prelude +loaded before your script (see ``player/lua/defaults.lua`` in the mpv sources). +The event loop will wait for events and dispatch events registered with +``mp.register_event``. It will also handle timers added with ``mp.add_timeout`` +and similar (by waiting with a timeout). + +Since mpv 0.6.0, the player will wait until the script is fully loaded before +continuing normal operation. The player considers a script as fully loaded as +soon as it starts waiting for mpv events (or it exits). In practice this means +the player will more or less hang until the script returns from the main chunk +(and ``mp_event_loop`` is called), or the script calls ``mp_event_loop`` or +``mp.dispatch_events`` directly. This is done to make it possible for a script +to fully setup event handlers etc. before playback actually starts. In older +mpv versions, this happened asynchronously. With mpv 0.29.0, this changes +slightly, and it merely waits for scripts to be loaded in this manner before +starting playback as part of the player initialization phase. Scripts run though +initialization in parallel. This might change again. + +mp functions +------------ + +The ``mp`` module is preloaded, although it can be loaded manually with +``require 'mp'``. It provides the core client API. + +``mp.command(string)`` + Run the given command. This is similar to the commands used in input.conf. + See `List of Input Commands`_. + + By default, this will show something on the OSD (depending on the command), + as if it was used in ``input.conf``. See `Input Command Prefixes`_ how + to influence OSD usage per command. + + Returns ``true`` on success, or ``nil, error`` on error. + +``mp.commandv(arg1, arg2, ...)`` + Similar to ``mp.command``, but pass each command argument as separate + parameter. This has the advantage that you don't have to care about + quoting and escaping in some cases. + + Example: + + :: + + mp.command("loadfile " .. filename .. " append") + mp.commandv("loadfile", filename, "append") + + These two commands are equivalent, except that the first version breaks + if the filename contains spaces or certain special characters. + + Note that properties are *not* expanded. You can use either ``mp.command``, + the ``expand-properties`` prefix, or the ``mp.get_property`` family of + functions. + + Unlike ``mp.command``, this will not use OSD by default either (except + for some OSD-specific commands). + +``mp.command_native(table [,def])`` + Similar to ``mp.commandv``, but pass the argument list as table. This has + the advantage that in at least some cases, arguments can be passed as + native types. It also allows you to use named argument. + + If the table is an array, each array item is like an argument in + ``mp.commandv()`` (but can be a native type instead of a string). + + If the table contains string keys, it's interpreted as command with named + arguments. This requires at least an entry with the key ``name`` to be + present, which must be a string, and contains the command name. The special + entry ``_flags`` is optional, and if present, must be an array of + `Input Command Prefixes`_ to apply. All other entries are interpreted as + arguments. + + Returns a result table on success (usually empty), or ``def, error`` on + error. ``def`` is the second parameter provided to the function, and is + nil if it's missing. + +``mp.command_native_async(table [,fn])`` + Like ``mp.command_native()``, but the command is ran asynchronously (as far + as possible), and upon completion, fn is called. fn has three arguments: + ``fn(success, result, error)``: + + ``success`` + Always a Boolean and is true if the command was successful, + otherwise false. + + ``result`` + The result value (can be nil) in case of success, nil otherwise (as + returned by ``mp.command_native()``). + + ``error`` + The error string in case of an error, nil otherwise. + + Returns a table with undefined contents, which can be used as argument for + ``mp.abort_async_command``. + + If starting the command failed for some reason, ``nil, error`` is returned, + and ``fn`` is called indicating failure, using the same error value. + + ``fn`` is always called asynchronously, even if the command failed to start. + +``mp.abort_async_command(t)`` + Abort a ``mp.command_native_async`` call. The argument is the return value + of that command (which starts asynchronous execution of the command). + Whether this works and how long it takes depends on the command and the + situation. The abort call itself is asynchronous. Does not return anything. + +``mp.del_property(name)`` + Delete the given property. See ``mp.get_property`` and `Properties`_ for more + information about properties. Most properties cannot be deleted. + + Returns true on success, or ``nil, error`` on error. + +``mp.get_property(name [,def])`` + Return the value of the given property as string. These are the same + properties as used in input.conf. See `Properties`_ for a list of + properties. The returned string is formatted similar to ``${=name}`` + (see `Property Expansion`_). + + Returns the string on success, or ``def, error`` on error. ``def`` is the + second parameter provided to the function, and is nil if it's missing. + +``mp.get_property_osd(name [,def])`` + Similar to ``mp.get_property``, but return the property value formatted for + OSD. This is the same string as printed with ``${name}`` when used in + input.conf. + + Returns the string on success, or ``def, error`` on error. ``def`` is the + second parameter provided to the function, and is an empty string if it's + missing. Unlike ``get_property()``, assigning the return value to a variable + will always result in a string. + +``mp.get_property_bool(name [,def])`` + Similar to ``mp.get_property``, but return the property value as Boolean. + + Returns a Boolean on success, or ``def, error`` on error. + +``mp.get_property_number(name [,def])`` + Similar to ``mp.get_property``, but return the property value as number. + + Note that while Lua does not distinguish between integers and floats, + mpv internals do. This function simply request a double float from mpv, + and mpv will usually convert integer property values to float. + + Returns a number on success, or ``def, error`` on error. + +``mp.get_property_native(name [,def])`` + Similar to ``mp.get_property``, but return the property value using the best + Lua type for the property. Most time, this will return a string, Boolean, + or number. Some properties (for example ``chapter-list``) are returned as + tables. + + Returns a value on success, or ``def, error`` on error. Note that ``nil`` + might be a possible, valid value too in some corner cases. + +``mp.set_property(name, value)`` + Set the given property to the given string value. See ``mp.get_property`` + and `Properties`_ for more information about properties. + + Returns true on success, or ``nil, error`` on error. + +``mp.set_property_bool(name, value)`` + Similar to ``mp.set_property``, but set the given property to the given + Boolean value. + +``mp.set_property_number(name, value)`` + Similar to ``mp.set_property``, but set the given property to the given + numeric value. + + Note that while Lua does not distinguish between integers and floats, + mpv internals do. This function will test whether the number can be + represented as integer, and if so, it will pass an integer value to mpv, + otherwise a double float. + +``mp.set_property_native(name, value)`` + Similar to ``mp.set_property``, but set the given property using its native + type. + + Since there are several data types which cannot represented natively in + Lua, this might not always work as expected. For example, while the Lua + wrapper can do some guesswork to decide whether a Lua table is an array + or a map, this would fail with empty tables. Also, there are not many + properties for which it makes sense to use this, instead of + ``set_property``, ``set_property_bool``, ``set_property_number``. + For these reasons, this function should probably be avoided for now, except + for properties that use tables natively. + +``mp.get_time()`` + Return the current mpv internal time in seconds as a number. This is + basically the system time, with an arbitrary offset. + +``mp.add_key_binding(key, name|fn [,fn [,flags]])`` + Register callback to be run on 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``). If the key is empty or ``nil``, no physical key is + registered, but the user still can create own bindings (see below). + + After calling this function, key presses will cause the function ``fn`` to + be called (unless the user remapped the key with another binding). + + The ``name`` argument should be a short symbolic string. It allows the user + to remap the key binding via input.conf using the ``script-message`` + command, and the name of the key binding (see below for + an example). The name should be unique across other bindings in the same + script - if not, the previous binding with the same name will be + overwritten. You can omit the name, in which case a random name is generated + internally. (Omitting works as follows: either pass ``nil`` for ``name``, + or pass the ``fn`` argument in place of the name. The latter is not + recommended and is handled for compatibility only.) + + The last argument is used for optional flags. This is a table, which can + have the following entries: + + ``repeatable`` + If set to ``true``, enables key repeat for this specific binding. + + ``complex`` + If set to ``true``, then ``fn`` is called on both key up and down + events (as well as key repeat, if enabled), with the first + argument being a table. This table has the following entries (and + may contain undocumented ones): + + ``event`` + Set to one of the strings ``down``, ``repeat``, ``up`` or + ``press`` (the latter if key up/down can't be tracked). + + ``is_mouse`` + Boolean Whether the event was caused by a mouse button. + + ``key_name`` + The name of they key that triggered this, or ``nil`` if + invoked artificially. If the key name is unknown, it's an + empty string. + + ``key_text`` + Text if triggered by a text key, otherwise ``nil``. See + description of ``script-binding`` command for details (this + field is equivalent to the 5th argument). + + Internally, key bindings are dispatched via the ``script-message-to`` or + ``script-binding`` input commands and ``mp.register_script_message``. + + Trying to map multiple commands to a key will essentially prefer a random + binding, while the other bindings are not called. It is guaranteed that + user defined bindings in the central input.conf are preferred over bindings + added with this function (but see ``mp.add_forced_key_binding``). + + 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. Then the user has to put the + following into their input.conf to remap the command to the ``y`` key: + + :: + + y script-binding something + + + This will print the message when the key ``y`` is pressed. (``x`` will + still work, unless the user remaps it.) + + You can also explicitly send a message to a named script only. Assume the + above script was using the filename ``fooscript.lua``: + + :: + + y script-binding fooscript/something + +``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 their + 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. + + Some events have associated data. This is put into a Lua table and passed + as argument to fn. The Lua table by default contains a ``name`` field, + which is a string containing the event name. If the event has an error + associated, the ``error`` field is set to a string describing the error, + on success it's not set. + + If multiple functions are registered for the same event, they are run in + registration order, which the first registered function running before all + the other ones. + + Returns true if such an event exists, false otherwise. + + See `Events`_ and `List of events`_ for details. + +``mp.unregister_event(fn)`` + Undo ``mp.register_event(..., fn)``. This removes all event handlers that + are equal to the ``fn`` parameter. This uses normal Lua ``==`` comparison, + so be careful when dealing with closures. + +``mp.observe_property(name, type, fn)`` + Watch a property for changes. If the property ``name`` is changed, then + the function ``fn(name)`` will be called. ``type`` can be ``nil``, or be + set to one of ``none``, ``native``, ``bool``, ``string``, or ``number``. + ``none`` is the same as ``nil``. For all other values, the new value of + the property will be passed as second argument to ``fn``, using + ``mp.get_property_<type>`` to retrieve it. This means if ``type`` is for + example ``string``, ``fn`` is roughly called as in + ``fn(name, mp.get_property_string(name))``. + + If possible, change events are coalesced. If a property is changed a bunch + of times in a row, only the last change triggers the change function. (The + exact behavior depends on timing and other things.) + + If a property is unavailable, or on error, the value argument to ``fn`` is + ``nil``. (The ``observe_property()`` call always succeeds, even if a + property does not exist.) + + In some cases the function is not called even if the property changes. + This depends on the property, and it's a valid feature request to ask for + better update handling of a specific property. + + If the ``type`` is ``none`` or ``nil``, sporadic property change events are + possible. This means the change function ``fn`` can be called even if the + property doesn't actually change. + + You always get an initial change notification. This is meant to initialize + the user's state to the current value of the property. + +``mp.unobserve_property(fn)`` + Undo ``mp.observe_property(..., fn)``. This removes all property handlers + that are equal to the ``fn`` parameter. This uses normal Lua ``==`` + comparison, so be careful when dealing with closures. + +``mp.add_timeout(seconds, fn [, disabled])`` + Call the given function fn when the given number of seconds has elapsed. + Note that the number of seconds can be fractional. For now, the timer's + resolution may be as low as 50 ms, although this will be improved in the + future. + + If the ``disabled`` argument is set to ``true`` or a truthy value, the + timer will wait to be manually started with a call to its ``resume()`` + method. + + This is a one-shot timer: it will be removed when it's fired. + + Returns a timer object. See ``mp.add_periodic_timer`` for details. + +``mp.add_periodic_timer(seconds, fn [, disabled])`` + Call the given function periodically. This is like ``mp.add_timeout``, but + the timer is re-added after the function fn is run. + + Returns a timer object. The timer object provides the following methods: + ``stop()`` + Disable the timer. Does nothing if the timer is already disabled. + This will remember the current elapsed time when stopping, so that + ``resume()`` essentially unpauses the timer. + + ``kill()`` + Disable the timer. Resets the elapsed time. ``resume()`` will + restart the timer. + + ``resume()`` + Restart the timer. If the timer was disabled with ``stop()``, this + will resume at the time it was stopped. If the timer was disabled + with ``kill()``, or if it's a previously fired one-shot timer (added + with ``add_timeout()``), this starts the timer from the beginning, + using the initially configured timeout. + + ``is_enabled()`` + Whether the timer is currently enabled or was previously disabled + (e.g. by ``stop()`` or ``kill()``). + + ``timeout`` (RW) + This field contains the current timeout period. This value is not + updated as time progresses. It's only used to calculate when the + timer should fire next when the timer expires. + + If you write this, you can call ``t:kill() ; t:resume()`` to reset + the current timeout to the new one. (``t:stop()`` won't use the + new timeout.) + + ``oneshot`` (RW) + Whether the timer is periodic (``false``) or fires just once + (``true``). This value is used when the timer expires (but before + the timer callback function fn is run). + + Note that these are methods, and you have to call them using ``:`` instead + of ``.`` (Refer to https://www.lua.org/manual/5.2/manual.html#3.4.9 .) + + Example: + + :: + + seconds = 0 + timer = mp.add_periodic_timer(1, function() + print("called every second") + # stop it after 10 seconds + seconds = seconds + 1 + if seconds >= 10 then + timer:kill() + end + end) + + +``mp.get_opt(key)`` + Return a setting from the ``--script-opts`` option. It's up to the user and + the script how this mechanism is used. Currently, all scripts can access + this equally, so you should be careful about collisions. + +``mp.get_script_name()`` + Return the name of the current script. The name is usually made of the + filename of the script, with directory and file extension removed. If + there are several scripts which would have the same name, it's made unique + by appending a number. Any nonalphanumeric characters are replaced with ``_``. + + .. admonition:: Example + + The script ``/path/to/foo-script.lua`` becomes ``foo_script``. + +``mp.get_script_directory()`` + Return the directory if this is a script packaged as directory (see + `Script location`_ for a description). Return nothing if this is a single + file script. + +``mp.osd_message(text [,duration])`` + Show an OSD message on the screen. ``duration`` is in seconds, and is + optional (uses ``--osd-duration`` by default). + +Advanced mp functions +--------------------- + +These also live in the ``mp`` module, but are documented separately as they +are useful only in special situations. + +``mp.get_wakeup_pipe()`` + Calls ``mpv_get_wakeup_pipe()`` and returns the read end of the wakeup + pipe. This is deprecated, but still works. (See ``client.h`` for details.) + +``mp.get_next_timeout()`` + Return the relative time in seconds when the next timer (``mp.add_timeout`` + and similar) expires. If there is no timer, return ``nil``. + +``mp.dispatch_events([allow_wait])`` + This can be used to run custom event loops. If you want to have direct + control what the Lua script does (instead of being called by the default + event loop), you can set the global variable ``mp_event_loop`` to your + own function running the event loop. From your event loop, you should call + ``mp.dispatch_events()`` to dequeue and dispatch mpv events. + + If the ``allow_wait`` parameter is set to ``true``, the function will block + until the next event is received or the next timer expires. Otherwise (and + this is the default behavior), it returns as soon as the event loop is + emptied. It's strongly recommended to use ``mp.get_next_timeout()`` and + ``mp.get_wakeup_pipe()`` if you're interested in properly working + notification of new events and working timers. + +``mp.register_idle(fn)`` + Register an event loop idle handler. Idle handlers are called before the + script goes to sleep after handling all new events. This can be used for + example to delay processing of property change events: if you're observing + multiple properties at once, you might not want to act on each property + change, but only when all change notifications have been received. + +``mp.unregister_idle(fn)`` + Undo ``mp.register_idle(fn)``. This removes all idle handlers that + are equal to the ``fn`` parameter. This uses normal Lua ``==`` comparison, + so be careful when dealing with closures. + +``mp.enable_messages(level)`` + Set the minimum log level of which mpv message output to receive. These + messages are normally printed to the terminal. By calling this function, + you can set the minimum log level of messages which should be received with + the ``log-message`` event. See the description of this event for details. + The level is a string, see ``msg.log`` for allowed log levels. + +``mp.register_script_message(name, fn)`` + This is a helper to dispatch ``script-message`` or ``script-message-to`` + invocations to Lua functions. ``fn`` is called if ``script-message`` or + ``script-message-to`` (with this script as destination) is run + with ``name`` as first parameter. The other parameters are passed to ``fn``. + If a message with the given name is already registered, it's overwritten. + + Used by ``mp.add_key_binding``, so be careful about name collisions. + +``mp.unregister_script_message(name)`` + Undo a previous registration with ``mp.register_script_message``. Does + nothing if the ``name`` wasn't registered. + +``mp.create_osd_overlay(format)`` + Create an OSD overlay. This is a very thin wrapper around the ``osd-overlay`` + command. The function returns a table, which mostly contains fields that + will be passed to ``osd-overlay``. The ``format`` parameter is used to + initialize the ``format`` field. The ``data`` field contains the text to + be used as overlay. For details, see the ``osd-overlay`` command. + + In addition, it provides the following methods: + + ``update()`` + Commit the OSD overlay to the screen, or in other words, run the + ``osd-overlay`` command with the current fields of the overlay table. + Returns the result of the ``osd-overlay`` command itself. + + ``remove()`` + Remove the overlay from the screen. A ``update()`` call will add it + again. + + Example: + + :: + + ov = mp.create_osd_overlay("ass-events") + ov.data = "{\\an5}{\\b1}hello world!" + ov:update() + + The advantage of using this wrapper (as opposed to running ``osd-overlay`` + directly) is that the ``id`` field is allocated automatically. + +``mp.get_osd_size()`` + Returns a tuple of ``osd_width, osd_height, osd_par``. The first two give + the size of the OSD in pixels (for video outputs like ``--vo=xv``, this may + be "scaled" pixels). The third is the display pixel aspect ratio. + + May return invalid/nonsense values if OSD is not initialized yet. + +mp.msg functions +---------------- + +This module allows outputting messages to the terminal, and can be loaded +with ``require 'mp.msg'``. + +``msg.log(level, ...)`` + The level parameter is the message priority. It's a string and one of + ``fatal``, ``error``, ``warn``, ``info``, ``v``, ``debug``, ``trace``. The + user's settings will determine which of these messages will be + visible. Normally, all messages are visible, except ``v``, ``debug`` and + ``trace``. + + The parameters after that are all converted to strings. Spaces are inserted + to separate multiple parameters. + + You don't need to add newlines. + +``msg.fatal(...)``, ``msg.error(...)``, ``msg.warn(...)``, ``msg.info(...)``, ``msg.verbose(...)``, ``msg.debug(...)``, ``msg.trace(...)`` + All of these are shortcuts and equivalent to the corresponding + ``msg.log(level, ...)`` call. + +mp.options functions +-------------------- + +mpv comes with a built-in module to manage options from config-files and the +command-line. All you have to do is to supply a table with default options to +the read_options function. The function will overwrite the default values +with values found in the config-file and the command-line (in that order). + +``options.read_options(table [, identifier [, on_update]])`` + A ``table`` with key-value pairs. The type of the default values is + important for converting the values read from the config file or + command-line back. Do not use ``nil`` as a default value! + + The ``identifier`` is used to identify the config-file and the command-line + options. These needs to unique to avoid collisions with other scripts. + Defaults to ``mp.get_script_name()`` if the parameter is ``nil`` or missing. + + The ``on_update`` parameter enables run-time updates of all matching option + values via the ``script-opts`` option/property. If any of the matching + options changes, the values in the ``table`` (which was originally passed to + the function) are changed, and ``on_update(list)`` is called. ``list`` is + a table where each updated option has a ``list[option_name] = true`` entry. + There is no initial ``on_update()`` call. This never re-reads the config file. + ``script-opts`` is always applied on the original config file, ignoring + previous ``script-opts`` values (for example, if an option is removed from + ``script-opts`` at runtime, the option will have the value in the config + file). ``table`` entries are only written for option values whose values + effectively change (this is important if the script changes ``table`` + entries independently). + + +Example implementation:: + + local options = { + optionA = "defaultvalueA", + optionB = -0.5, + optionC = true, + } + + require "mp.options".read_options(options, "myscript") + print(options.optionA) + + +The config file will be stored in ``script-opts/identifier.conf`` in mpv's user +folder. Comment lines can be started with # and stray spaces are not removed. +Boolean values will be represented with yes/no. + +Example config:: + + # comment + optionA=Hello World + optionB=9999 + optionC=no + + +Command-line options are read from the ``--script-opts`` parameter. To avoid +collisions, all keys have to be prefixed with ``identifier-``. + +Example command-line:: + + --script-opts=myscript-optionA=TEST,myscript-optionB=0,myscript-optionC=yes + + +mp.utils functions +------------------ + +This built-in module provides generic helper functions for Lua, and have +strictly speaking nothing to do with mpv or video/audio playback. They are +provided for convenience. Most compensate for Lua's scarce standard library. + +Be warned that any of these functions might disappear any time. They are not +strictly part of the guaranteed API. + +``utils.getcwd()`` + Returns the directory that mpv was launched from. On error, ``nil, error`` + is returned. + +``utils.readdir(path [, filter])`` + Enumerate all entries at the given path on the filesystem, and return them + as array. Each entry is a directory entry (without the path). + The list is unsorted (in whatever order the operating system returns it). + + If the ``filter`` argument is given, it must be one of the following + strings: + + ``files`` + List regular files only. This excludes directories, special files + (like UNIX device files or FIFOs), and dead symlinks. It includes + UNIX symlinks to regular files. + + ``dirs`` + List directories only, or symlinks to directories. ``.`` and ``..`` + are not included. + + ``normal`` + Include the results of both ``files`` and ``dirs``. (This is the + default.) + + ``all`` + List all entries, even device files, dead symlinks, FIFOs, and the + ``.`` and ``..`` entries. + + On error, ``nil, error`` is returned. + +``utils.file_info(path)`` + Stats the given path for information and returns a table with the + following entries: + + ``mode`` + protection bits (on Windows, always 755 (octal) for directories + and 644 (octal) for files) + ``size`` + size in bytes + ``atime`` + time of last access + ``mtime`` + time of last modification + ``ctime`` + time of last metadata change + ``is_file`` + Whether ``path`` is a regular file (boolean) + ``is_dir`` + Whether ``path`` is a directory (boolean) + + ``mode`` and ``size`` are integers. + Timestamps (``atime``, ``mtime`` and ``ctime``) are integer seconds since + the Unix epoch (Unix time). + The booleans ``is_file`` and ``is_dir`` are provided as a convenience; + they can be and are derived from ``mode``. + + On error (e.g. path does not exist), ``nil, error`` is returned. + +``utils.split_path(path)`` + Split a path into directory component and filename component, and return + them. The first return value is always the directory. The second return + value is the trailing part of the path, the directory entry. + +``utils.join_path(p1, p2)`` + Return the concatenation of the 2 paths. Tries to be clever. For example, + if ``p2`` is an absolute path, ``p2`` is returned without change. + +``utils.subprocess(t)`` + Runs an external process and waits until it exits. Returns process status + 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. + + See the ``subprocess`` documentation for semantics and further parameters. + +``utils.subprocess_detached(t)`` + Runs an external process and detaches it from mpv's control. + + The parameter ``t`` is a table. The function reads the following entries: + + ``args`` + Array of strings of the same semantics as the ``args`` used in the + ``subprocess`` function. + + The function returns ``nil``. + + This is a legacy wrapper around calling the ``run`` command with + ``mp.commandv`` and other functions. + +``utils.getpid()`` + Returns the process ID of the running mpv process. This can be used to identify + the calling mpv when launching (detached) subprocesses. + +``utils.get_env_list()`` + Returns the C environment as a list of strings. (Do not confuse this with + the Lua "environment", which is an unrelated concept.) + +``utils.parse_json(str [, trail])`` + Parses the given string argument as JSON, and returns it as a Lua table. On + error, returns ``nil, error``. (Currently, ``error`` is just a string + reading ``error``, because there is no fine-grained error reporting of any + kind.) + + The returned value uses similar conventions as ``mp.get_property_native()`` + to distinguish empty objects and arrays. + + If the ``trail`` parameter is ``true`` (or any value equal to ``true``), + then trailing non-whitespace text is tolerated by the function, and the + trailing text is returned as 3rd return value. (The 3rd return value is + always there, but with ``trail`` set, no error is raised.) + +``utils.format_json(v)`` + Format the given Lua table (or value) as a JSON string and return it. On + error, returns ``nil, error``. (Errors usually only happen on value types + incompatible with JSON.) + + The argument value uses similar conventions as ``mp.set_property_native()`` + to distinguish empty objects and arrays. + +``utils.to_string(v)`` + Turn the given value into a string. Formats tables and their contents. This + doesn't do anything special; it is only needed because Lua is terrible. + +Events +------ + +Events are notifications from player core to scripts. You can register an +event handler with ``mp.register_event``. + +Note that all scripts (and other parts of the player) receive events equally, +and there's no such thing as blocking other scripts from receiving events. + +Example: + +:: + + function my_fn(event) + print("start of playback!") + end + + mp.register_event("file-loaded", my_fn) + +For the existing event types, see `List of events`_. + +Extras +------ + +This documents experimental features, or features that are "too special" to +guarantee a stable interface. + +``mp.add_hook(type, priority, fn)`` + Add a hook callback for ``type`` (a string identifying a certain kind of + hook). These hooks allow the player to call script functions and wait for + their result (normally, the Lua scripting interface is asynchronous from + the point of view of the player core). ``priority`` is an arbitrary integer + that allows ordering among hooks of the same kind. Using the value 50 is + recommended as neutral default value. + + ``fn(hook)`` is the function that will be called during execution of the + hook. The parameter passed to it (``hook``) is a Lua object that can control + further aspects about the currently invoked hook. It provides the following + methods: + + ``defer()`` + Returning from the hook function should not automatically continue + the hook. Instead, the API user wants to call ``hook:cont()`` on its + own at a later point in time (before or after the function has + returned). + + ``cont()`` + Continue the hook. Doesn't need to be called unless ``defer()`` was + called. + + See `Hooks`_ for currently existing hooks and what they do - only the hook + list is interesting; handling hook execution is done by the Lua script + function automatically. |