policy-device-defaults.lua: Adjust style

This commit is contained in:
Ashok Sidipotu 2022-07-07 11:01:19 +05:30 committed by Julian Bouzas
parent 6e31b47c28
commit 5ebef4be6e

View file

@ -20,41 +20,41 @@ default_input_volume = tonumber (Settings.get_float ("default-input-volume") or
dev_infos = {}
-- the state storage
state = use_persistent_storage and State("default-routes") or nil
state_table = state and state:load() or {}
state = use_persistent_storage and State ("default-routes") or nil
state_table = state and state:load () or {}
-- simple serializer {"foo", "bar"} -> "foo;bar;"
function serializeArray(a)
function serializeArray (a)
local str = ""
for _, v in ipairs(a) do
str = str .. tostring(v):gsub(";", "\\;") .. ";"
for _, v in ipairs (a) do
str = str .. tostring (v):gsub (";", "\\;") .. ";"
end
return str
end
-- simple deserializer "foo;bar;" -> {"foo", "bar"}
function parseArray(str, convert_value)
function parseArray (str, convert_value)
local array = {}
local val = ""
local escaped = false
for i = 1, #str do
local c = str:sub(i,i)
local c = str:sub (i,i)
if c == '\\' then
escaped = true
elseif c == ';' and not escaped then
val = convert_value and convert_value(val) or val
table.insert(array, val)
val = convert_value and convert_value (val) or val
table.insert (array, val)
val = ""
else
val = val .. tostring(c)
val = val .. tostring (c)
escaped = false
end
end
return array
end
function arrayContains(a, value)
for _, v in ipairs(a) do
function arrayContains (a, value)
for _, v in ipairs (a) do
if v == value then
return true
end
@ -62,8 +62,8 @@ function arrayContains(a, value)
return false
end
function parseParam(param, id)
local route = param:parse()
function parseParam (param, id)
local route = param:parse ()
if route.pod_type == "Object" and route.object_id == id then
return route.properties
else
@ -71,65 +71,65 @@ function parseParam(param, id)
end
end
function storeAfterTimeout()
function storeAfterTimeout ()
if timeout_source then
timeout_source:destroy()
timeout_source:destroy ()
end
timeout_source = Core.timeout_add(1000, function ()
local saved, err = state:save(state_table)
timeout_source = Core.timeout_add (1000, function ()
local saved, err = state:save (state_table)
if not saved then
Log.warning(err)
Log.warning (err)
end
timeout_source = nil
end)
end
function saveProfile(dev_info, profile_name)
function saveProfile (dev_info, profile_name)
if not use_persistent_storage then
return
end
local routes = {}
for idx, ri in pairs(dev_info.route_infos) do
for idx, ri in pairs (dev_info.route_infos) do
if ri.save then
table.insert(routes, ri.name)
table.insert (routes, ri.name)
end
end
if #routes > 0 then
local key = dev_info.name .. ":profile:" .. profile_name
state_table[key] = serializeArray(routes)
storeAfterTimeout()
state_table [key] = serializeArray (routes)
storeAfterTimeout ()
end
end
function saveRouteProps(dev_info, route)
function saveRouteProps (dev_info, route)
if not use_persistent_storage or not route.props then
return
end
local props = route.props.properties
local key_base = dev_info.name .. ":" ..
route.direction:lower() .. ":" ..
route.direction:lower () .. ":" ..
route.name .. ":"
state_table[key_base .. "volume"] =
props.volume and tostring(props.volume) or nil
state_table[key_base .. "mute"] =
props.mute and tostring(props.mute) or nil
state_table[key_base .. "channelVolumes"] =
props.channelVolumes and serializeArray(props.channelVolumes) or nil
state_table[key_base .. "channelMap"] =
props.channelMap and serializeArray(props.channelMap) or nil
state_table[key_base .. "latencyOffsetNsec"] =
props.latencyOffsetNsec and tostring(props.latencyOffsetNsec) or nil
state_table[key_base .. "iec958Codecs"] =
props.iec958Codecs and serializeArray(props.iec958Codecs) or nil
state_table [key_base .. "volume"] =
props.volume and tostring (props.volume) or nil
state_table [key_base .. "mute"] =
props.mute and tostring (props.mute) or nil
state_table [key_base .. "channelVolumes"] =
props.channelVolumes and serializeArray (props.channelVolumes) or nil
state_table [key_base .. "channelMap"] =
props.channelMap and serializeArray (props.channelMap) or nil
state_table [key_base .. "latencyOffsetNsec"] =
props.latencyOffsetNsec and tostring (props.latencyOffsetNsec) or nil
state_table [key_base .. "iec958Codecs"] =
props.iec958Codecs and serializeArray (props.iec958Codecs) or nil
storeAfterTimeout()
storeAfterTimeout ()
end
function restoreRoute(device, dev_info, device_id, route)
function restoreRoute (device, dev_info, device_id, route)
-- default props
local props = {
"Spa:Pod:Object:Param:Props", "Route",
@ -145,40 +145,40 @@ function restoreRoute(device, dev_info, device_id, route)
-- restore props from persistent storage
if use_persistent_storage then
local key_base = dev_info.name .. ":" ..
route.direction:lower() .. ":" ..
route.direction:lower () .. ":" ..
route.name .. ":"
local str = state_table[key_base .. "volume"]
props.volume = str and tonumber(str) or props.volume
local str = state_table [key_base .. "volume"]
props.volume = str and tonumber (str) or props.volume
local str = state_table[key_base .. "mute"]
local str = state_table [key_base .. "mute"]
props.mute = str and (str == "true") or false
local str = state_table[key_base .. "channelVolumes"]
props.channelVolumes = str and parseArray(str, tonumber) or props.channelVolumes
local str = state_table [key_base .. "channelVolumes"]
props.channelVolumes = str and parseArray (str, tonumber) or props.channelVolumes
local str = state_table[key_base .. "channelMap"]
props.channelMap = str and parseArray(str) or props.channelMap
local str = state_table [key_base .. "channelMap"]
props.channelMap = str and parseArray (str) or props.channelMap
local str = state_table[key_base .. "latencyOffsetNsec"]
props.latencyOffsetNsec = str and math.tointeger(str) or props.latencyOffsetNsec
local str = state_table [key_base .. "latencyOffsetNsec"]
props.latencyOffsetNsec = str and math.tointeger (str) or props.latencyOffsetNsec
local str = state_table[key_base .. "iec958Codecs"]
props.iec958Codecs = str and parseArray(str) or props.iec958Codecs
local str = state_table [key_base .. "iec958Codecs"]
props.iec958Codecs = str and parseArray (str) or props.iec958Codecs
end
-- convert arrays to Spa Pod
if props.channelVolumes then
table.insert(props.channelVolumes, 1, "Spa:Float")
props.channelVolumes = Pod.Array(props.channelVolumes)
table.insert (props.channelVolumes, 1, "Spa:Float")
props.channelVolumes = Pod.Array (props.channelVolumes)
end
if props.channelMap then
table.insert(props.channelMap, 1, "Spa:Enum:AudioChannel")
props.channelMap = Pod.Array(props.channelMap)
table.insert (props.channelMap, 1, "Spa:Enum:AudioChannel")
props.channelMap = Pod.Array (props.channelMap)
end
if props.iec958Codecs then
table.insert(props.iec958Codecs, 1, "Spa:Enum:AudioIEC958Codec")
props.iec958Codecs = Pod.Array(props.iec958Codecs)
table.insert (props.iec958Codecs, 1, "Spa:Enum:AudioIEC958Codec")
props.iec958Codecs = Pod.Array (props.iec958Codecs)
end
-- construct Route param
@ -186,18 +186,18 @@ function restoreRoute(device, dev_info, device_id, route)
"Spa:Pod:Object:Param:Route", "Route",
index = route.index,
device = device_id,
props = Pod.Object(props),
props = Pod.Object (props),
save = route.save,
}
Log.debug(param, "setting route on " .. tostring(device))
device:set_param("Route", param)
Log.debug (param, "setting route on " .. tostring (device))
device:set_param ("Route", param)
route.prev_active = true
route.active = true
end
function findActiveDeviceIDs(profile)
function findActiveDeviceIDs (profile)
-- parses the classes from the profile and returns the device IDs
----- sample structure, should return { 0, 8 } -----
-- classes:
@ -222,20 +222,20 @@ function findActiveDeviceIDs(profile)
-- pod_type: Struct
-- pod_type: Struct
local active_ids = {}
if type(profile.classes) == "table" and profile.classes.pod_type == "Struct" then
for _, p in ipairs(profile.classes) do
if type(p) == "table" and p.pod_type == "Struct" then
if type (profile.classes) == "table" and profile.classes.pod_type == "Struct" then
for _, p in ipairs (profile.classes) do
if type (p) == "table" and p.pod_type == "Struct" then
local i = 1
while true do
local k, v = p[i], p[i+1]
local k, v = p [i], p [i+1]
i = i + 2
if not k or not v then
break
end
if k == "card.profile.devices" and
type(v) == "table" and v.pod_type == "Array" then
for _, dev_id in ipairs(v) do
table.insert(active_ids, dev_id)
type (v) == "table" and v.pod_type == "Array" then
for _, dev_id in ipairs (v) do
table.insert (active_ids, dev_id)
end
end
end
@ -247,10 +247,10 @@ end
-- returns an array of the route names that were previously selected
-- for the given device and profile
function getStoredProfileRoutes(dev_name, profile_name)
function getStoredProfileRoutes (dev_name, profile_name)
local key = dev_name .. ":profile:" .. profile_name
local str = state_table[key]
return str and parseArray(str) or {}
local str = state_table [key]
return str and parseArray (str) or {}
end
-- find a route that was previously stored for a device_id
@ -267,7 +267,7 @@ function findSavedRoute(dev_info, device_id, spr)
end
-- find the best route for a given device_id, based on availability and priority
function findBestRoute(dev_info, device_id)
function findBestRoute (dev_info, device_id)
local best_avail = nil
local best_unk = nil
for idx, ri in pairs(dev_info.route_infos) do
@ -291,29 +291,29 @@ function findBestRoute(dev_info, device_id)
return best_avail or best_unk
end
function restoreProfileRoutes(device, dev_info, profile, profile_changed)
Log.info(device, "restore routes for profile " .. profile.name)
function restoreProfileRoutes (device, dev_info, profile, profile_changed)
Log.info (device, "restore routes for profile " .. profile.name)
local active_ids = findActiveDeviceIDs(profile)
local spr = getStoredProfileRoutes(dev_info.name, profile.name)
local active_ids = findActiveDeviceIDs (profile)
local spr = getStoredProfileRoutes (dev_info.name, profile.name)
for _, device_id in ipairs(active_ids) do
Log.info(device, "restoring device " .. device_id);
for _, device_id in ipairs (active_ids) do
Log.info (device, "restoring device " .. device_id);
local route = nil
-- restore routes selection for the newly selected profile
-- don't bother if spr is empty, there is no point
if profile_changed and #spr > 0 then
route = findSavedRoute(dev_info, device_id, spr)
route = findSavedRoute (dev_info, device_id, spr)
if route then
-- we found a saved route
if route.available == "no" then
Log.info(device, "saved route '" .. route.name .. "' not available")
Log.info (device, "saved route '" .. route.name .. "' not available")
-- not available, try to find next best
route = nil
else
Log.info(device, "found saved route: " .. route.name)
Log.info (device, "found saved route: " .. route.name)
-- make sure we save it again
route.save = true
end
@ -322,23 +322,23 @@ function restoreProfileRoutes(device, dev_info, profile, profile_changed)
-- we could not find a saved route, try to find a new best
if not route then
route = findBestRoute(dev_info, device_id)
route = findBestRoute (dev_info, device_id)
if not route then
Log.info(device, "can't find best route")
Log.info (device, "can't find best route")
else
Log.info(device, "found best route: " .. route.name)
Log.info (device, "found best route: " .. route.name)
end
end
-- restore route
if route then
restoreRoute(device, dev_info, device_id, route)
restoreRoute (device, dev_info, device_id, route)
end
end
end
function findRouteInfo(dev_info, route, return_new)
local ri = dev_info.route_infos[route.index]
function findRouteInfo (dev_info, route, return_new)
local ri = dev_info.route_infos [route.index]
if not ri and return_new then
ri = {
index = route.index,
@ -357,35 +357,35 @@ function findRouteInfo(dev_info, route, return_new)
return ri
end
function handleDevice(device)
local dev_info = dev_infos[device["bound-id"]]
function handleDevice (device)
local dev_info = dev_infos [device ["bound-id"]]
local new_route_infos = {}
local avail_routes_changed = false
local profile = nil
-- get current profile
for p in device:iterate_params("Profile") do
profile = parseParam(p, "Profile")
for p in device:iterate_params ("Profile") do
profile = parseParam (p, "Profile")
end
-- look at all the routes and update/reset cached information
for p in device:iterate_params("EnumRoute") do
for p in device:iterate_params ("EnumRoute") do
-- parse pod
local route = parseParam(p, "EnumRoute")
local route = parseParam (p, "EnumRoute")
if not route then
goto skip_enum_route
end
-- find cached route information
local route_info = findRouteInfo(dev_info, route, true)
local route_info = findRouteInfo (dev_info, route, true)
-- update properties
route_info.prev_available = route_info.available
if route_info.available ~= route.available then
Log.info(device, "route " .. route.name .. " available changed " ..
Log.info (device, "route " .. route.name .. " available changed " ..
route_info.available .. " -> " .. route.available)
route_info.available = route.available
if profile and arrayContains(route.profiles, profile.index) then
if profile and arrayContains (route.profiles, profile.index) then
avail_routes_changed = true
end
end
@ -394,7 +394,7 @@ function handleDevice(device)
route_info.save = false
-- store
new_route_infos[route.index] = route_info
new_route_infos [route.index] = route_info
::skip_enum_route::
end
@ -405,15 +405,15 @@ function handleDevice(device)
new_route_infos = nil
-- check for changes in the active routes
for p in device:iterate_params("Route") do
local route = parseParam(p, "Route")
for p in device:iterate_params ("Route") do
local route = parseParam (p, "Route")
if not route then
goto skip_route
end
-- get cached route info and at the same time
-- ensure that the route is also in EnumRoute
local route_info = findRouteInfo(dev_info, route, false)
local route_info = findRouteInfo (dev_info, route, false)
if not route_info then
goto skip_route
end
@ -425,12 +425,12 @@ function handleDevice(device)
if not route_info.prev_active then
-- a new route is now active, restore the volume and
-- make sure we save this as a preferred route
Log.info(device, "new active route found " .. route.name)
restoreRoute(device, dev_info, route.device, route_info)
Log.info (device, "new active route found " .. route.name)
restoreRoute (device, dev_info, route.device, route_info)
elseif route.save then
-- just save route properties
Log.info(device, "storing route props for " .. route.name)
saveRouteProps(dev_info, route)
Log.info (device, "storing route props for " .. route.name)
saveRouteProps (dev_info, route)
end
::skip_route::
@ -446,10 +446,10 @@ function handleDevice(device)
-- what was stored
if profile_changed or avail_routes_changed then
dev_info.active_profile = profile.index
restoreProfileRoutes(device, dev_info, profile, profile_changed)
restoreProfileRoutes (device, dev_info, profile, profile_changed)
end
saveProfile(dev_info, profile.name)
saveProfile (dev_info, profile.name)
end
end
@ -460,27 +460,27 @@ om = ObjectManager {
}
}
om:connect("objects-changed", function (om)
om:connect ("objects-changed", function (om)
local new_dev_infos = {}
for device in om:iterate() do
local dev_info = dev_infos[device["bound-id"]]
for device in om:iterate () do
local dev_info = dev_infos [device ["bound-id"]]
-- new device appeared
if not dev_info then
dev_info = {
name = device.properties["device.name"],
name = device.properties ["device.name"],
active_profile = -1,
route_infos = {},
}
dev_infos[device["bound-id"]] = dev_info
dev_infos [device ["bound-id"]] = dev_info
device:connect("params-changed", handleDevice)
handleDevice(device)
device:connect ("params-changed", handleDevice)
handleDevice (device)
end
new_dev_infos[device["bound-id"]] = dev_info
new_dev_infos [device ["bound-id"]] = dev_info
end
-- replace list to get rid of dev_info for devices that no longer exist
dev_infos = new_dev_infos
end)
om:activate()
om:activate ()