diff --git a/src/scripts/default-nodes/state-default-nodes.lua b/src/scripts/default-nodes/state-default-nodes.lua index 35f74a6b..c3980881 100644 --- a/src/scripts/default-nodes/state-default-nodes.lua +++ b/src/scripts/default-nodes/state-default-nodes.lua @@ -10,7 +10,6 @@ -- state file during the bootup, finally it has a hook which finds a default -- node out of the user preferences -settings = require ("settings-node") log = Log.open_topic ("s-default-nodes") -- the state storage @@ -193,5 +192,7 @@ function toggleState (enable) end end -settings:subscribe ("restore-default-targets", toggleState) -toggleState (settings ["restore-default-targets"]) +Settings.subscribe ("node.restore-default-targets", function () + toggleState (Settings.get_boolean ("node.restore-default-targets")) +end) +toggleState (Settings.get_boolean ("node.restore-default-targets")) diff --git a/src/scripts/device/apply-routes.lua b/src/scripts/device/apply-routes.lua index ad3e802a..bb933339 100644 --- a/src/scripts/device/apply-routes.lua +++ b/src/scripts/device/apply-routes.lua @@ -10,7 +10,6 @@ -- -- Set the Route param as part of the "select-routes" event run -settings = require ("settings-device") devinfo = require ("device-info-cache") log = Log.open_topic ("s-device") @@ -57,8 +56,8 @@ AsyncEventHook { local is_input = (route_info.direction == "Input") props.mute = props.mute or false props.channelVolumes = props.channelVolumes or - { is_input and settings ["routes.default-source-volume"] - or settings ["routes.default-sink-volume"] } + { is_input and Settings.get_float ("device.routes.default-source-volume") + or Settings.get_float ("device.routes.default-sink-volume") } -- prefix the props with correct IDs to create a Pod.Object table.insert (props, 1, "Spa:Pod:Object:Param:Props") diff --git a/src/scripts/device/autoswitch-bluetooth-profile.lua b/src/scripts/device/autoswitch-bluetooth-profile.lua index 8f859e30..2c767b25 100644 --- a/src/scripts/device/autoswitch-bluetooth-profile.lua +++ b/src/scripts/device/autoswitch-bluetooth-profile.lua @@ -27,7 +27,6 @@ lutils = require ("linking-utils") cutils = require ("common-utils") -settings = require ("settings-bluetooth") state = nil headset_profiles = nil @@ -47,7 +46,8 @@ local previous_streams = {} function handlePersistentSetting (enable) if enable and state == nil then -- the state storage - state = settings.autoswitch_to_headset_profile and State ("bluetooth-autoswitch") or nil + state = Settings.get_boolean ("bluetooth.autoswitch-to-headset-profile") + and State ("bluetooth-autoswitch") or nil headset_profiles = state and state:load () or {} else state = nil @@ -55,9 +55,10 @@ function handlePersistentSetting (enable) end end -handlePersistentSetting (settings.use_persistent_storage) - -settings:subscribe ("use-persistent-storage", handlePersistentSetting) +handlePersistentSetting (Settings.get_boolean ("bluetooth.use-persistent-storage")) +Settings.subscribe ("bluetooth.use-persistent-storage", function () + handlePersistentSetting (Settings.get_boolean ("bluetooth.use-persistent-storage")) +end) devices_om = ObjectManager { Interest { @@ -341,7 +342,7 @@ local function checkStreamStatus (stream) end local function handleStream (stream) - if not settings.autoswitch_to_headset_profile then + if not Settings.get_boolean ("bluetooth.autoswitch-to-headset-profile") then return end diff --git a/src/scripts/device/state-profile.lua b/src/scripts/device/state-profile.lua index eca69f3a..0ea7dbbc 100644 --- a/src/scripts/device/state-profile.lua +++ b/src/scripts/device/state-profile.lua @@ -12,7 +12,6 @@ -- selected device profile to state file cutils = require ("common-utils") -settings = require ("settings-device") log = Log.open_topic ("s-device") -- the state storage @@ -140,5 +139,7 @@ function toggleState (enable) end end -settings:subscribe ("restore-profile", toggleState) -toggleState (settings.restore_profile) +Settings.subscribe ("device.restore-profile", function () + toggleState (Settings.get_boolean ("device.restore-profile")) +end) +toggleState (Settings.get_boolean ("device.restore-profile")) diff --git a/src/scripts/device/state-routes.lua b/src/scripts/device/state-routes.lua index ddba0dc2..e6ccba10 100644 --- a/src/scripts/device/state-routes.lua +++ b/src/scripts/device/state-routes.lua @@ -14,7 +14,6 @@ -- cutils = require ("common-utils") -settings = require ("settings-device") devinfo = require ("device-info-cache") log = Log.open_topic ("s-device") @@ -329,5 +328,7 @@ function toggleState (enable) end end -settings:subscribe ("restore-routes", toggleState) -toggleState (settings.restore_routes) +Settings.subscribe ("device.restore-routes", function () + toggleState (Settings.get_boolean ("device.restore-routes")) +end) +toggleState (Settings.get_boolean ("device.restore-routes")) diff --git a/src/scripts/lib/monitor-utils.lua b/src/scripts/lib/monitor-utils.lua index 65c2f037..5c58cd68 100644 --- a/src/scripts/lib/monitor-utils.lua +++ b/src/scripts/lib/monitor-utils.lua @@ -7,7 +7,6 @@ -- Script is a Lua Module of monitor Lua utility functions -settings = require ("settings-monitor") log = Log.open_topic ("s-monitors-utils") local mutils = { @@ -103,7 +102,8 @@ function mutils.register_cam_node (self, parent, id, factory, properties) local other_api = api == "v4l2" and "libcamera" or "v4l2" if cam_api_data.enum_status and not cam_data[other_api].enum_status then log:trace (string.format ("\"%s\" armed a timer for %d", api, dev_num)) - cam_data.source = Core.timeout_add (settings["camera-discovery-timeout"], function() + cam_data.source = Core.timeout_add ( + Settings.get_int ("monitor.camera-discovery-timeout"), function() log:trace (string.format ("\"%s\" armed timer expired for %d", api, dev_num)) self:create_cam_node (dev_num) cam_data.source = nil diff --git a/src/scripts/lib/settings-bluetooth.lua b/src/scripts/lib/settings-bluetooth.lua deleted file mode 100644 index a2c1e120..00000000 --- a/src/scripts/lib/settings-bluetooth.lua +++ /dev/null @@ -1,16 +0,0 @@ --- WirePlumber --- --- Copyright © 2022 Collabora Ltd. --- --- SPDX-License-Identifier: MIT - --- Bluetooth settings manager - -local settings_manager = require ("settings-manager") - -local defaults = { - ["use-persistent-storage"] = true, - ["autoswitch-to-headset-profile"] = true -} - -return settings_manager.new ("bluetooth.", defaults) diff --git a/src/scripts/lib/settings-device.lua b/src/scripts/lib/settings-device.lua deleted file mode 100644 index 1bc0efb5..00000000 --- a/src/scripts/lib/settings-device.lua +++ /dev/null @@ -1,18 +0,0 @@ --- WirePlumber --- --- Copyright © 2022 Collabora Ltd. --- --- SPDX-License-Identifier: MIT - --- Device settings manager - -local settings_manager = require ("settings-manager") - -local defaults = { - ["restore-profile"] = true, - ["restore-routes"] = true, - ["routes.default-sink-volume"] = 0.4 ^ 3, - ["routes.default-source-volume"] = 1.0, -} - -return settings_manager.new ("device.", defaults) diff --git a/src/scripts/lib/settings-linking.lua b/src/scripts/lib/settings-linking.lua deleted file mode 100644 index bef0445d..00000000 --- a/src/scripts/lib/settings-linking.lua +++ /dev/null @@ -1,16 +0,0 @@ --- WirePlumber --- --- Copyright © 2022 Collabora Ltd. --- --- SPDX-License-Identifier: MIT - --- linking settings manager - -local settings_manager = require ("settings-manager") - -local defaults = { - ["allow-moving-streams"] = true, - ["follow-default-target"] = true, -} - -return settings_manager.new ("linking.", defaults) diff --git a/src/scripts/lib/settings-manager.lua b/src/scripts/lib/settings-manager.lua deleted file mode 100644 index 9bf42630..00000000 --- a/src/scripts/lib/settings-manager.lua +++ /dev/null @@ -1,124 +0,0 @@ --- WirePlumber --- --- Copyright © 2022 Collabora Ltd. --- --- SPDX-License-Identifier: MIT --- --- Settings manager helper --- --- This sets up a lua table that will automatically populate itself with --- values from the settings, falling back to the default values specified. --- Any changes in the settings will automatically change the values of this --- table. --- --- Usage: --- --- local settings_manager = require ("settings-manager") --- local defaults = { --- ["foo"] = true, --- ["foo-bar"] = 3, --- } --- local settings = settings_manager.new ("example.prefix.", defaults) --- --- The above "settings" table should now look like this internally: --- { --- foo = true, -- or the value specified in the Settings --- foo_bar = 3, -- or the value specified in the Settings --- } --- --- Additionally, a "subscribe" method is present in the "settings" table, which --- allows subscribing to changes of the values: --- --- settings:subscribe ("foo-bar", function (new_value) --- Log.info ("foo-bar value changed to " .. new_value) --- end) --- - -local settings_manager = {} -local private_api = {} - -function private_api.subscribe (self, key, closure) - if not self.subscribers[key] then - self.subscribers[key] = {} - end - table.insert (self.subscribers, closure) -end - -function private_api.call_subscribers (self, key, new_value) - if self.subscribers[key] then - for i, closure in ipairs (self.subscribers[key]) do - closure (new_value) - end - end -end - -function private_api.update_value (self, key, json_value, default) - local new_value = json_value and json_value:parse () or default - - -- only accept values that have the same type as the default value - if type (new_value) ~= type (default) then - new_value = default - end - - -- store only if the new value is not equal to the default - self.values[key] = (new_value ~= default) and new_value or nil - - return new_value -end - -function settings_manager.new (_prefix, _defaults) - -- private storage table - local private = { - prefix = _prefix, - prefix_len = string.len (_prefix), - defaults = _defaults, - values = {}, - subscribers = {}, - } - setmetatable (private, { __index = private_api }) - - -- initialize with the values found in Settings - for key, default in pairs (private.defaults) do - local json_value = Settings.get (private.prefix .. key) - private:update_value (key, json_value, default) - end - - -- subscribe for changes in Settings - Settings.subscribe (private.prefix .. "*", function (_, setting, json_value) - local key = string.sub (setting, private.prefix_len, -1) - local default = private.defaults[key] - - -- unknown key, ignore it - if default == nil then - return - end - - local new_value = private:update_value (key, json_value, default) - private:call_subscribers (key, new_value) - end) - - -- return an empty table with a metatable that will resolve - -- keys to the values stored in `private` or their default values - return setmetatable ({}, { - __private = private, - __index = function (self, key) - if key == "subscribe" then - -- special case, "subscribe" is a method - return function (self, key, closure) - local private = getmetatable (self) ["__private"] - private:subscribe (key, closure) - end - else - local private = getmetatable (self) ["__private"] - key = string.gsub (key, "_", "-") -- foo_bar_baz -> foo-bar-baz - local value = private.values[key] - return (value ~= nil) and value or private.defaults[key] - end - end, - __newindex = function(_, key, _) - error ('Not allowed to modify configuration value') - end - }) -end - -return settings_manager diff --git a/src/scripts/lib/settings-monitor.lua b/src/scripts/lib/settings-monitor.lua deleted file mode 100644 index a1b5f703..00000000 --- a/src/scripts/lib/settings-monitor.lua +++ /dev/null @@ -1,15 +0,0 @@ --- WirePlumber --- --- Copyright © 2023 Collabora Ltd. --- --- SPDX-License-Identifier: MIT - --- Monitors settings manager - -local settings_manager = require ("settings-manager") - -local defaults = { - ["camera-discovery-timeout"] = 100, -} - -return settings_manager.new ("monitor.", defaults) diff --git a/src/scripts/lib/settings-node.lua b/src/scripts/lib/settings-node.lua deleted file mode 100644 index fd2ecee2..00000000 --- a/src/scripts/lib/settings-node.lua +++ /dev/null @@ -1,26 +0,0 @@ --- WirePlumber --- --- Copyright © 2022 Collabora Ltd. --- --- SPDX-License-Identifier: MIT - --- Node settings manager - -local settings_manager = require ("settings-manager") - -local defaults = { - ["features.audio.no-dsp"] = false, - ["features.audio.monitor-ports"] = true, - ["features.audio.control-port"] = false, - - ["stream.restore-props"] = true, - ["stream.restore-target"] = true, - ["stream.default-playback-volume"] = 1.0, - ["stream.default-capture-volume"] = 1.0, - - ["filter.forward-format"] = false, - - ["restore-default-targets"] = true, -} - -return settings_manager.new ("node.", defaults) diff --git a/src/scripts/linking/find-defined-target.lua b/src/scripts/linking/find-defined-target.lua index 49cf9a3e..5028a3a9 100644 --- a/src/scripts/linking/find-defined-target.lua +++ b/src/scripts/linking/find-defined-target.lua @@ -11,7 +11,6 @@ lutils = require ("linking-utils") cutils = require ("common-utils") -settings = require ("settings-linking") log = Log.open_topic ("s-linking") SimpleEventHook { @@ -34,7 +33,8 @@ SimpleEventHook { log:info (si, string.format ("handling item %d: %s (%s)", si.id, tostring (si_props ["node.name"]), tostring (si_props ["node.id"]))) - local metadata = settings.allow_moving_streams and cutils.get_default_metadata_object () + local metadata = Settings.get_boolean ("linking.allow-moving-streams") and + cutils.get_default_metadata_object () local dont_fallback = cutils.parseBool (si_props ["node.dont-fallback"]) local dont_move = cutils.parseBool (si_props ["node.dont-move"]) local target_key diff --git a/src/scripts/linking/prepare-link.lua b/src/scripts/linking/prepare-link.lua index c1be2911..06b9a833 100644 --- a/src/scripts/linking/prepare-link.lua +++ b/src/scripts/linking/prepare-link.lua @@ -10,7 +10,6 @@ lutils = require ("linking-utils") cutils = require ("common-utils") -settings = require ("settings-linking") log = Log.open_topic ("s-linking") SimpleEventHook { @@ -39,7 +38,8 @@ SimpleEventHook { log:debug (si, "... already linked to proper target") -- Check this also here, in case in default targets changed - if settings.follow_default_target and si_flags.has_node_defined_target then + if Settings.get_boolean ("linking.follow-default-target") and + si_flags.has_node_defined_target then lutils.checkFollowDefault (si, target) end diff --git a/src/scripts/linking/rescan.lua b/src/scripts/linking/rescan.lua index 96e4b453..406f0573 100644 --- a/src/scripts/linking/rescan.lua +++ b/src/scripts/linking/rescan.lua @@ -13,7 +13,6 @@ lutils = require ("linking-utils") cutils = require ("common-utils") futils = require ("filter-utils") -settings = require ("settings-linking") log = Log.open_topic ("s-linking") handles = {} @@ -231,5 +230,7 @@ function handleMoveSetting (enable) end end -settings:subscribe ("allow-moving-streams", handleMoveSetting) -handleMoveSetting (settings.allow_moving_streams) +Settings.subscribe ("linking.allow-moving-streams", function () + handleMoveSetting (Settings.get_boolean ("linking.allow-moving-streams")) +end) +handleMoveSetting (Settings.get_boolean ("linking.allow-moving-streams")) diff --git a/src/scripts/node/create-item.lua b/src/scripts/node/create-item.lua index 52873612..2fb96c3f 100644 --- a/src/scripts/node/create-item.lua +++ b/src/scripts/node/create-item.lua @@ -9,7 +9,6 @@ -- linkable) objects out of them. cutils = require ("common-utils") -settings = require ("settings-node") log = Log.open_topic ("s-node") items = {} @@ -19,9 +18,9 @@ function configProperties (node) local properties = { ["item.node"] = node, ["item.plugged.usec"] = GLib.get_monotonic_time (), - ["item.features.no-dsp"] = settings ["features.audio.no-dsp"], - ["item.features.monitor"] = settings ["features.audio.monitor-ports"], - ["item.features.control-port"] = settings ["features.audio.control-port"], + ["item.features.no-dsp"] = Settings.get_boolean ("node.features.audio.no-dsp"), + ["item.features.monitor"] = Settings.get_boolean ("node.features.audio.monitor-ports"), + ["item.features.control-port"] = Settings.get_boolean ("node.features.audio.control-port"), ["node.id"] = node ["bound-id"], ["client.id"] = np ["client.id"], ["object.path"] = np ["object.path"], diff --git a/src/scripts/node/filter-forward-format.lua b/src/scripts/node/filter-forward-format.lua index 1ad33228..04b6198c 100644 --- a/src/scripts/node/filter-forward-format.lua +++ b/src/scripts/node/filter-forward-format.lua @@ -11,7 +11,6 @@ -- FIXME: this script can be further improved lutils = require ("linking-utils") -settings = require ("settings-node") log = Log.open_topic ("s-node") function findAssociatedLinkGroupNode (si) @@ -93,7 +92,7 @@ SimpleEventHook { local si = event:get_subject () -- Forward filters ports format to associated virtual devices if enabled - if settings["filter.forward-format"] then + if Settings.get_boolean ("node.filter.forward-format") then local si_props = si.properties local link_group = si_props ["node.link-group"] local si_flags = lutils:get_flags (si.id) diff --git a/src/scripts/node/state-stream.lua b/src/scripts/node/state-stream.lua index c690f420..a118bb10 100644 --- a/src/scripts/node/state-stream.lua +++ b/src/scripts/node/state-stream.lua @@ -9,7 +9,6 @@ -- SPDX-License-Identifier: MIT cutils = require ("common-utils") -settings = require ("settings-node") log = Log.open_topic ("s-node") -- the state storage @@ -56,7 +55,7 @@ restore_stream_hook = SimpleEventHook { end -- restore node Props (volumes, channelMap, etc...) - if settings ["stream.restore-props"] and stream_props ["state.restore-props"] ~= "false" + if Settings.get_boolean ("node.stream.restore-props") and stream_props ["state.restore-props"] ~= "false" then local props = { "Spa:Pod:Object:Param:Props", "Props", @@ -87,7 +86,7 @@ restore_stream_hook = SimpleEventHook { end -- restore the node's link target on metadata - if settings ["stream.restore-target"] and stream_props ["state.restore-target"] ~= "false" + if Settings.get_boolean ("node.stream.restore-target") and stream_props ["state.restore-target"] ~= "false" then if stored_values.target then -- check first if there is a defined target in the node's properties @@ -152,7 +151,7 @@ store_stream_props_hook = SimpleEventHook { local stream_props = node.properties cutils.evaluateRulesApplyProperties (stream_props, "stream.rules") - if settings ["stream.restore-props"] and stream_props ["state.restore-props"] ~= "false" + if Settings.get_boolean ("node.stream.restore-props") and stream_props ["state.restore-props"] ~= "false" then local key = formKey (stream_props) if not key then @@ -346,9 +345,9 @@ function buildDefaultChannelVolumes (node) if str ~= nil then def_vol = tonumber (str) elseif direction == "input" then - def_vol = settings ["stream.default-capture-volume"] + def_vol = Settings.get_float ("node.stream.default-capture-volume") elseif direction == "output" then - def_vol = settings ["stream.default-playback-volume"] + def_vol = Settings.get_float ("node.stream.default-playback-volume") end for pod in node:iterate_params("Format") do @@ -439,12 +438,15 @@ function toggleState (enable) end end -settings:subscribe ("restore-props", function (enable) - toggleState (enable or settings["stream.restore-target"]) +Settings.subscribe ("node.stream.restore-props", function () + toggleState (Settings.get_boolean ("node.stream.restore-props") or + Settings.get_boolean ("node.stream.restore-target")) end) -settings:subscribe ("restore-target", function (enable) - toggleState (enable or settings["stream.restore-props"]) +Settings.subscribe ("node.stream.restore-target", function () + toggleState (Settings.get_boolean ("node.stream.restore-props") or + Settings.get_boolean ("node.stream.restore-target")) end) -toggleState (settings["stream.restore-props"] or settings["stream.restore-target"]) +toggleState (Settings.get_boolean ("node.stream.restore-props") or + Settings.get_boolean ("node.stream.restore-target")) diff --git a/tests/script-tester.c b/tests/script-tester.c index 261bca6d..930dc354 100644 --- a/tests/script-tester.c +++ b/tests/script-tester.c @@ -280,6 +280,9 @@ base_tests_setup (ScriptRunnerFixture *f, gconstpointer data) static void script_tests_setup (ScriptRunnerFixture *f, gconstpointer data) { + f->base.conf_file = + g_strdup_printf ("%s/config/wireplumber.conf", g_getenv ("G_TEST_SRCDIR")); + wp_base_test_fixture_setup (&f->base, WP_BASE_TEST_FLAG_CLIENT_CORE); load_components (f, data); diff --git a/tests/scripts/config/wireplumber.conf b/tests/scripts/config/wireplumber.conf new file mode 100644 index 00000000..c8597e52 --- /dev/null +++ b/tests/scripts/config/wireplumber.conf @@ -0,0 +1,121 @@ +context.modules = [ + { name = libpipewire-module-protocol-native } + { name = libpipewire-module-metadata } + { name = libpipewire-module-spa-device-factory } + { name = libpipewire-module-spa-node-factory } + { name = libpipewire-module-client-node } + { name = libpipewire-module-client-device } + { name = libpipewire-module-adapter } +] + +wireplumber.settings.schema = { + ## Bluetooth + bluetooth.use-persistent-storage = { + description = "Whether to use persistent BT storage or not" + type = "bool" + default = true + } + bluetooth.autoswitch-to-headset-profile = { + description = "Whether to autoswitch to BT headset profile or not" + type = "bool" + default = true + } + + ## Device + device.restore-profile = { + description = "Whether to restore device profile or not" + type = "bool" + default = true + } + device.restore-routes = { + description = "Whether to restore device routes or not" + type = "bool" + default = true + } + device.routes.default-sink-volume = { + description = "The default volume for sink devices" + type = "float" + default = 0.064 + min = 0.0 + max = 1.0 + } + device.routes.default-source-volume = { + description = "The default volume for source devices" + type = "float" + default = 1.0 + min = 0.0 + max = 1.0 + } + + ## Linking + linking.allow-moving-streams = { + description = "Whether to allow metadata to move streams at runtime or not" + type = "bool" + default = true + } + linking.follow-default-target = { + description = "Whether to allow streams follow the default device or not" + type = "bool" + default = true + } + + ## Monitor + monitor.camera-discovery-timeout = { + description = "The camera discovery timeout in milliseconds" + type = "int" + default = 100 + min = 0 + max = 60000 + } + + ## Node + node.features.audio.no-dsp = { + description = "Whether to never convert audio to F32 format or not" + type = "bool" + default = false + } + node.eatures.audio.monitor-ports = { + description = "Whether to enable monitor ports on audio nodes or not" + type = "bool" + default = true + } + node.features.audio.control-port = { + description = "Whether to enable control ports on audio nodes or not" + type = "bool" + default = false + } + node.stream.restore-props = { + description = "Whether to restore properties on stream nodes or not" + type = "bool" + default = true + } + node.stream.restore-target = { + description = "Whether to restore target on stream nodes or not" + type = "bool" + default = true + } + node.default-playback-volume = { + description = "The default volume for playback nodes" + type = "float" + default = 1.0 + min = 0.0 + max = 1.0 + } + node.default-capture-volume = { + description = "The default volume for capture nodes" + type = "float" + default = 1.0 + min = 0.0 + max = 1.0 + } + node.filter.forward-format = { + description = "Whether to forward format on filter nodes or not" + type = "bool" + default = false + } + node.restore-default-targets = { + description = "Whether to restore default targets or not" + type = "bool" + default = true + } +}