A script can use this to easily get runtime updates. (Even if script-opts is sort of clunky.)
Unified · Split
| @@ -566,14 +566,21 @@ command-line. All you have to do is to supply a table with default options to · 565 unmodified lines | ||
| 566 | 566 | the read_options function. The function will overwrite the default values |
| 567 | 567 | with values found in the config-file and the command-line (in that order). |
| 568 | 568 | |
| 569 | −``options.read_options(table [, identifier])`` | |
| 569 | +``options.read_options(table [, identifier [, on_update]])`` | |
| 570 | 570 | A ``table`` with key-value pairs. The type of the default values is |
| 571 | 571 | important for converting the values read from the config file or |
| 572 | 572 | command-line back. Do not use ``nil`` as a default value! |
| 573 | 573 | |
| 574 | 574 | The ``identifier`` is used to identify the config-file and the command-line |
| 575 | 575 | options. These needs to unique to avoid collisions with other scripts. |
| 576 | − Defaults to ``mp.get_script_name()``. | |
| 576 | + Defaults to ``mp.get_script_name()`` if the parameter is ``nil`` or missing. | |
| 577 | + | |
| 578 | + The ``on_update`` parameter enables run-time updates of all matching option | |
| 579 | + values via the ``script-opts`` option/property. If any of the matching | |
| 580 | + options changes, the values in the ``table`` (which was originally passed to | |
| 581 | + the function) are changed, and ``on_update(list)`` is called. ``list`` is | |
| 582 | + a table where each updated option has a ``list[option_name] = true`` entry. | |
| 583 | + There is no initial ``on_update()`` call. This never re-reads the config file. | |
| 577 | 584 | |
| 578 | 585 | |
| 579 | 586 | Example implementation:: |
| @@ -29,8 +29,17 @@ local function typeconv(desttypeval, val) · 28 unmodified lines | ||
| 29 | 29 | return val |
| 30 | 30 | end |
| 31 | 31 | |
| 32 | +-- performs a deep-copy of the given option value | |
| 33 | +local function opt_copy(val) | |
| 34 | + return val -- no tables currently | |
| 35 | +end | |
| 36 | + | |
| 37 | +-- compares the given option values for equality | |
| 38 | +local function opt_equal(val1, val2) | |
| 39 | + return val1 == val2 | |
| 40 | +end | |
| 32 | 41 | |
| 33 | −local function read_options(options, identifier) | |
| 42 | +local function read_options(options, identifier, on_update) | |
| 34 | 43 | if identifier == nil then |
| 35 | 44 | identifier = mp.get_script_name() |
| 36 | 45 | end |
| @@ -88,24 +97,62 @@ local function read_options(options, identifier) · 51 unmodified lines | ||
| 88 | 97 | end |
| 89 | 98 | |
| 90 | 99 | --parse command-line options |
| 91 | − for key, val in pairs(mp.get_property_native("options/script-opts")) do | |
| 92 | − local prefix = identifier.."-" | |
| 93 | − if not (string.find(key, prefix, 1, true) == nil) then | |
| 94 | − key = string.sub(key, string.len(prefix)+1) | |
| 95 | − | |
| 96 | − -- match found values with defaults | |
| 97 | − if options[key] == nil then | |
| 98 | − msg.warn("script-opts: unknown key " .. key .. ", ignoring") | |
| 99 | − else | |
| 100 | − local convval = typeconv(options[key], val) | |
| 101 | − if convval == nil then | |
| 102 | − msg.error("script-opts: error converting value '" .. val .. | |
| 103 | − "' for key '" .. key .. "'") | |
| 100 | + local prefix = identifier.."-" | |
| 101 | + | |
| 102 | + local option_types = {} | |
| 103 | + for key, value in pairs(options) do | |
| 104 | + option_types[key] = opt_copy(value) | |
| 105 | + end | |
| 106 | + | |
| 107 | + local function parse_opts(full, options) | |
| 108 | + local changelist = {} | |
| 109 | + for key, val in pairs(full) do | |
| 110 | + if not (string.find(key, prefix, 1, true) == nil) then | |
| 111 | + key = string.sub(key, string.len(prefix)+1) | |
| 112 | + | |
| 113 | + -- match found values with defaults | |
| 114 | + if option_types[key] == nil then | |
| 115 | + msg.warn("script-opts: unknown key " .. key .. ", ignoring") | |
| 104 | 116 | else |
| 105 | − options[key] = convval | |
| 117 | + local convval = typeconv(option_types[key], val) | |
| 118 | + if convval == nil then | |
| 119 | + msg.error("script-opts: error converting value '" .. val .. | |
| 120 | + "' for key '" .. key .. "'") | |
| 121 | + else | |
| 122 | + if not opt_equal(options[key], convval) then | |
| 123 | + changelist[key] = true | |
| 124 | + options[key] = convval | |
| 125 | + end | |
| 126 | + end | |
| 106 | 127 | end |
| 107 | 128 | end |
| 108 | 129 | end |
| 130 | + return changelist | |
| 131 | + end | |
| 132 | + | |
| 133 | + --initial | |
| 134 | + parse_opts(mp.get_property_native("options/script-opts"), options) | |
| 135 | + | |
| 136 | + --runtime updates | |
| 137 | + if on_update then | |
| 138 | + -- Current option state, so that we can detect changes, even if the | |
| 139 | + -- caller messes with the options table. | |
| 140 | + local cur_opts = {} | |
| 141 | + | |
| 142 | + for key, value in pairs(options) do | |
| 143 | + cur_opts[key] = opt_copy(value) | |
| 144 | + end | |
| 145 | + | |
| 146 | + mp.observe_property("options/script-opts", "native", function(name, val) | |
| 147 | + local changelist = parse_opts(val, cur_opts) | |
| 148 | + for key, _ in pairs(changelist) do | |
| 149 | + -- copy to user | |
| 150 | + options[key] = opt_copy(cur_opts[key]) | |
| 151 | + end | |
| 152 | + if #changelist then | |
| 153 | + on_update(changelist) | |
| 154 | + end | |
| 155 | + end) | |
| 109 | 156 | end |
| 110 | 157 | |
| 111 | 158 | end |