scripts: remove settings-manager and use the Settings API

The settings manager is not needed anymore because the WpSettings Lua API
returns now the default value from the schema if the setting is not found.
This commit is contained in:
Julian Bouzas
2024-02-26 12:20:12 -05:00
parent f18a8c5a35
commit 8935837cda
20 changed files with 172 additions and 259 deletions

View File

@@ -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"))

View File

@@ -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")

View File

@@ -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

View File

@@ -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"))

View File

@@ -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"))

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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)

View File

@@ -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

View File

@@ -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)

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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"))

View File

@@ -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"],

View File

@@ -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)

View File

@@ -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"))

View File

@@ -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);

View File

@@ -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
}
}