From 478a321dcc62345a09acfd34740dc6d0783ade88 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 20 Dec 2019 14:21:16 +0100 Subject: lua: add a helper for runtime script option changes A script can use this to easily get runtime updates. (Even if script-opts is sort of clunky.) --- DOCS/man/lua.rst | 11 ++++++-- player/lua/options.lua | 77 ++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 71 insertions(+), 17 deletions(-) diff --git a/DOCS/man/lua.rst b/DOCS/man/lua.rst index 45fbfd62d0..6c6904c8b3 100644 --- a/DOCS/man/lua.rst +++ b/DOCS/man/lua.rst @@ -566,14 +566,21 @@ 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])`` +``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()``. + 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. Example implementation:: diff --git a/player/lua/options.lua b/player/lua/options.lua index a23417ae7d..3a05c08ea8 100644 --- a/player/lua/options.lua +++ b/player/lua/options.lua @@ -29,8 +29,17 @@ local function typeconv(desttypeval, val) return val end +-- performs a deep-copy of the given option value +local function opt_copy(val) + return val -- no tables currently +end + +-- compares the given option values for equality +local function opt_equal(val1, val2) + return val1 == val2 +end -local function read_options(options, identifier) +local function read_options(options, identifier, on_update) if identifier == nil then identifier = mp.get_script_name() end @@ -88,24 +97,62 @@ local function read_options(options, identifier) end --parse command-line options - for key, val in pairs(mp.get_property_native("options/script-opts")) do - local prefix = identifier.."-" - if not (string.find(key, prefix, 1, true) == nil) then - key = string.sub(key, string.len(prefix)+1) - - -- match found values with defaults - if options[key] == nil then - msg.warn("script-opts: unknown key " .. key .. ", ignoring") - else - local convval = typeconv(options[key], val) - if convval == nil then - msg.error("script-opts: error converting value '" .. val .. - "' for key '" .. key .. "'") + local prefix = identifier.."-" + + local option_types = {} + for key, value in pairs(options) do + option_types[key] = opt_copy(value) + end + + local function parse_opts(full, options) + local changelist = {} + for key, val in pairs(full) do + if not (string.find(key, prefix, 1, true) == nil) then + key = string.sub(key, string.len(prefix)+1) + + -- match found values with defaults + if option_types[key] == nil then + msg.warn("script-opts: unknown key " .. key .. ", ignoring") else - options[key] = convval + local convval = typeconv(option_types[key], val) + if convval == nil then + msg.error("script-opts: error converting value '" .. val .. + "' for key '" .. key .. "'") + else + if not opt_equal(options[key], convval) then + changelist[key] = true + options[key] = convval + end + end end end end + return changelist + end + + --initial + parse_opts(mp.get_property_native("options/script-opts"), options) + + --runtime updates + if on_update then + -- Current option state, so that we can detect changes, even if the + -- caller messes with the options table. + local cur_opts = {} + + for key, value in pairs(options) do + cur_opts[key] = opt_copy(value) + end + + mp.observe_property("options/script-opts", "native", function(name, val) + local changelist = parse_opts(val, cur_opts) + for key, _ in pairs(changelist) do + -- copy to user + options[key] = opt_copy(cur_opts[key]) + end + if #changelist then + on_update(changelist) + end + end) end end -- cgit v1.2.3