diff options
Diffstat (limited to 'player/lua/options.lua')
-rw-r--r-- | player/lua/options.lua | 164 |
1 files changed, 164 insertions, 0 deletions
diff --git a/player/lua/options.lua b/player/lua/options.lua new file mode 100644 index 0000000..b05b734 --- /dev/null +++ b/player/lua/options.lua @@ -0,0 +1,164 @@ +local msg = require 'mp.msg' + +-- converts val to type of desttypeval +local function typeconv(desttypeval, val) + if type(desttypeval) == "boolean" then + if val == "yes" then + val = true + elseif val == "no" then + val = false + else + msg.error("Error: Can't convert '" .. val .. "' to boolean!") + val = nil + end + elseif type(desttypeval) == "number" then + if tonumber(val) ~= nil then + val = tonumber(val) + else + msg.error("Error: Can't convert '" .. val .. "' to number!") + val = nil + end + end + 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 + +-- performs a deep-copy of an entire option table +local function opt_table_copy(opts) + local copy = {} + for key, value in pairs(opts) do + copy[key] = opt_copy(value) + end + return copy +end + + +local function read_options(options, identifier, on_update) + local option_types = opt_table_copy(options) + if identifier == nil then + identifier = mp.get_script_name() + end + msg.debug("reading options for " .. identifier) + + -- read config file + local conffilename = "script-opts/" .. identifier .. ".conf" + local conffile = mp.find_config_file(conffilename) + if conffile == nil then + msg.debug(conffilename .. " not found.") + conffilename = "lua-settings/" .. identifier .. ".conf" + conffile = mp.find_config_file(conffilename) + if conffile then + msg.warn("lua-settings/ is deprecated, use directory script-opts/") + end + end + local f = conffile and io.open(conffile,"r") + if f == nil then + -- config not found + msg.debug(conffilename .. " not found.") + else + -- config exists, read values + msg.verbose("Opened config file " .. conffilename .. ".") + local linecounter = 1 + for line in f:lines() do + if line:sub(#line) == "\r" then + line = line:sub(1, #line - 1) + end + if string.find(line, "#") == 1 then + + else + local eqpos = string.find(line, "=") + if eqpos == nil then + + else + local key = string.sub(line, 1, eqpos-1) + local val = string.sub(line, eqpos+1) + + -- match found values with defaults + if option_types[key] == nil then + msg.warn(conffilename..":"..linecounter.. + " unknown key '" .. key .. "', ignoring") + else + local convval = typeconv(option_types[key], val) + if convval == nil then + msg.error(conffilename..":"..linecounter.. + " error converting value '" .. val .. + "' for key '" .. key .. "'") + else + options[key] = convval + end + end + end + end + linecounter = linecounter + 1 + end + io.close(f) + end + + --parse command-line options + local prefix = identifier.."-" + -- command line options are always applied on top of these + local conf_and_default_opts = opt_table_copy(options) + + local function parse_opts(full, options) + for key, val in pairs(full) do + if string.find(key, prefix, 1, true) == 1 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 + local convval = typeconv(option_types[key], val) + if convval == nil then + msg.error("script-opts: error converting value '" .. val .. + "' for key '" .. key .. "'") + else + options[key] = convval + end + end + end + end + end + + --initial + parse_opts(mp.get_property_native("options/script-opts"), options) + + --runtime updates + if on_update then + local last_opts = opt_table_copy(options) + + mp.observe_property("options/script-opts", "native", function(name, val) + local new_opts = opt_table_copy(conf_and_default_opts) + parse_opts(val, new_opts) + local changelist = {} + for key, val in pairs(new_opts) do + if not opt_equal(last_opts[key], val) then + -- copy to user + options[key] = opt_copy(val) + changelist[key] = true + end + end + last_opts = new_opts + if next(changelist) ~= nil then + on_update(changelist) + end + end) + end + +end + +-- backwards compatibility with broken read_options export +_G.read_options = read_options + +return { + read_options = read_options, +} |