scripts: rewrite policy-device-profile and m-default-profile into a set of hooks
... excluding the persistent profile functionality for now (I am not convinced)
This commit is contained in:

committed by
Julian Bouzas

parent
e1a8c3459a
commit
f99c3005f2
@@ -132,7 +132,8 @@ get_object_type (gpointer obj, WpProperties **properties)
|
|||||||
static gint
|
static gint
|
||||||
get_default_event_priority (const gchar *event_type)
|
get_default_event_priority (const gchar *event_type)
|
||||||
{
|
{
|
||||||
if (!g_strcmp0 (event_type, "find-target-si-and-link"))
|
if (!g_strcmp0 (event_type, "find-target-si-and-link") ||
|
||||||
|
!g_strcmp0 (event_type, "select-profile"))
|
||||||
return 500;
|
return 500;
|
||||||
else if (!g_strcmp0 (event_type, "rescan-session"))
|
else if (!g_strcmp0 (event_type, "rescan-session"))
|
||||||
return -500;
|
return -500;
|
||||||
|
56
src/scripts/device/apply-profile.lua
Normal file
56
src/scripts/device/apply-profile.lua
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
-- WirePlumber
|
||||||
|
--
|
||||||
|
-- Copyright © 2022 Collabora Ltd.
|
||||||
|
--
|
||||||
|
-- SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
cutils = require ("common-utils")
|
||||||
|
|
||||||
|
AsyncEventHook {
|
||||||
|
name = "apply-profile@device",
|
||||||
|
after = { "find-stored-profile@device", "find-best-profile@device" },
|
||||||
|
interests = {
|
||||||
|
EventInterest {
|
||||||
|
Constraint { "event.type", "=", "select-profile" },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
steps = {
|
||||||
|
start = {
|
||||||
|
next = "none",
|
||||||
|
execute = function (event, transition)
|
||||||
|
local device = event:get_subject ()
|
||||||
|
local profile = event:get_data ("selected-profile")
|
||||||
|
local dev_name = device.properties ["device.name"]
|
||||||
|
|
||||||
|
if not profile then
|
||||||
|
Log.info (device, "No profile found to set on " .. dev_name)
|
||||||
|
transition:advance ()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
for p in device:iterate_params ("Profile") do
|
||||||
|
local active_profile = cutils.parseParam (p, "Profile")
|
||||||
|
if active_profile.index == profile.index then
|
||||||
|
Log.info (device, "Profile " .. profile.name .. " is already set on " .. dev_name)
|
||||||
|
transition:advance ()
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local param = Pod.Object {
|
||||||
|
"Spa:Pod:Object:Param:Profile", "Profile",
|
||||||
|
index = profile.index,
|
||||||
|
}
|
||||||
|
Log.info (device, "Setting profile " .. profile.name .. " on " .. dev_name)
|
||||||
|
device:set_param ("Profile", param)
|
||||||
|
|
||||||
|
-- FIXME: add cancellability
|
||||||
|
-- sync on the pipewire connection to ensure that the param
|
||||||
|
-- has been configured on the remote device object
|
||||||
|
Core.sync (function ()
|
||||||
|
transition:advance ()
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}:register()
|
65
src/scripts/device/find-best-profile.lua
Normal file
65
src/scripts/device/find-best-profile.lua
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
-- WirePlumber
|
||||||
|
--
|
||||||
|
-- Copyright © 2022 Collabora Ltd.
|
||||||
|
--
|
||||||
|
-- SPDX-License-Identifier: MIT
|
||||||
|
--
|
||||||
|
-- Find the best profile for a device based on profile priorities and
|
||||||
|
-- availability
|
||||||
|
|
||||||
|
cutils = require ("common-utils")
|
||||||
|
|
||||||
|
SimpleEventHook {
|
||||||
|
name = "find-best-profile@device",
|
||||||
|
after = "find-stored-profile@device",
|
||||||
|
interests = {
|
||||||
|
EventInterest {
|
||||||
|
Constraint { "event.type", "=", "select-profile" },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
execute = function (event)
|
||||||
|
local selected_profile = event:get_data ("selected-profile")
|
||||||
|
local device = event:get_subject ()
|
||||||
|
local dev_name = device.properties["device.name"]
|
||||||
|
local off_profile = nil
|
||||||
|
local best_profile = nil
|
||||||
|
local unk_profile = nil
|
||||||
|
|
||||||
|
-- skip hook if profile is already selected
|
||||||
|
if selected_profile then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
for p in device:iterate_params ("EnumProfile") do
|
||||||
|
profile = cutils.parseParam (p, "EnumProfile")
|
||||||
|
if profile and profile.name ~= "pro-audio" then
|
||||||
|
if profile.name == "off" then
|
||||||
|
off_profile = profile
|
||||||
|
elseif profile.available == "yes" then
|
||||||
|
if best_profile == nil or profile.priority > best_profile.priority then
|
||||||
|
best_profile = profile
|
||||||
|
end
|
||||||
|
elseif profile.available ~= "no" then
|
||||||
|
if unk_profile == nil or profile.priority > unk_profile.priority then
|
||||||
|
unk_profile = profile
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if best_profile ~= nil then
|
||||||
|
selected_profile = best_profile
|
||||||
|
elseif unk_profile ~= nil then
|
||||||
|
selected_profile = unk_profile
|
||||||
|
elseif off_profile ~= nil then
|
||||||
|
selected_profile = off_profile
|
||||||
|
end
|
||||||
|
|
||||||
|
if selected_profile then
|
||||||
|
Log.info (device, string.format (
|
||||||
|
"Found best profile '%s' (%d) for device '%s'",
|
||||||
|
selected_profile.name, selected_profile.index, dev_name))
|
||||||
|
event:set_data ("selected-profile", selected_profile)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}:register()
|
25
src/scripts/device/select-profile.lua
Normal file
25
src/scripts/device/select-profile.lua
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
-- WirePlumber
|
||||||
|
--
|
||||||
|
-- Copyright © 2022 Collabora Ltd.
|
||||||
|
--
|
||||||
|
-- SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
cutils = require ("common-utils")
|
||||||
|
|
||||||
|
SimpleEventHook {
|
||||||
|
name = "select-profile@device",
|
||||||
|
interests = {
|
||||||
|
EventInterest {
|
||||||
|
Constraint { "event.type", "=", "device-added" },
|
||||||
|
},
|
||||||
|
EventInterest {
|
||||||
|
Constraint { "event.type", "=", "device-params-changed" },
|
||||||
|
Constraint { "event.subject.param-id", "=", "EnumProfile" },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
execute = function (event)
|
||||||
|
local source = event:get_source ()
|
||||||
|
local device = event:get_subject ()
|
||||||
|
source:call ("push-event", "select-profile", device, nil)
|
||||||
|
end
|
||||||
|
}:register()
|
120
src/scripts/device/state-profile.lua
Normal file
120
src/scripts/device/state-profile.lua
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
-- WirePlumber
|
||||||
|
--
|
||||||
|
-- Copyright © 2022 Collabora Ltd.
|
||||||
|
--
|
||||||
|
-- SPDX-License-Identifier: MIT
|
||||||
|
--
|
||||||
|
-- This file contains all the logic related to saving device profiles
|
||||||
|
-- to a state file and restoring them later on.
|
||||||
|
|
||||||
|
cutils = require ("common-utils")
|
||||||
|
|
||||||
|
state = State ("default-profile")
|
||||||
|
state_table = state:load ()
|
||||||
|
|
||||||
|
SimpleEventHook {
|
||||||
|
name = "find-stored-profile@device",
|
||||||
|
interests = {
|
||||||
|
EventInterest {
|
||||||
|
Constraint { "event.type", "=", "select-profile" },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
execute = function (event)
|
||||||
|
local selected_profile = event:get_data ("selected-profile")
|
||||||
|
local device = event:get_subject ()
|
||||||
|
local dev_name = device.properties["device.name"]
|
||||||
|
|
||||||
|
-- skip hook if profile is already selected
|
||||||
|
if selected_profile then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if not dev_name then
|
||||||
|
Log.critical (device, "invalid device.name")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local profile_name = state_table[dev_name]
|
||||||
|
|
||||||
|
if profile_name then
|
||||||
|
for p in device:iterate_params ("EnumProfile") do
|
||||||
|
local profile = cutils.parseParam (p, "EnumProfile")
|
||||||
|
if profile.name == profile_name then
|
||||||
|
selected_profile = profile
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if selected_profile then
|
||||||
|
Log.info (device, string.format (
|
||||||
|
"Found stored profile '%s' (%d) for device '%s'",
|
||||||
|
selected_profile.name, selected_profile.index, dev_name))
|
||||||
|
event:set_data ("selected-profile", selected_profile)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}:register()
|
||||||
|
|
||||||
|
SimpleEventHook {
|
||||||
|
name = "store-user-selected-profile@device",
|
||||||
|
interests = {
|
||||||
|
EventInterest {
|
||||||
|
Constraint { "event.type", "=", "device-params-changed" },
|
||||||
|
Constraint { "event.subject.param-id", "=", "Profile" },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
execute = function (event)
|
||||||
|
local device = event:get_subject ()
|
||||||
|
|
||||||
|
for p in device:iterate_params ("Profile") do
|
||||||
|
local profile = cutils.parseParam (p, "Profile")
|
||||||
|
if profile.save then
|
||||||
|
-- store only if this was a user-generated action (save == true)
|
||||||
|
updateStoredProfile (device, profile)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
}:register()
|
||||||
|
|
||||||
|
function updateStoredProfile (device, profile)
|
||||||
|
local dev_name = device.properties["device.name"]
|
||||||
|
local index = nil
|
||||||
|
|
||||||
|
if not dev_name then
|
||||||
|
Log.critical (device, "invalid device.name")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
Log.debug (device, string.format (
|
||||||
|
"update stored profile to '%s' (%d) for device '%s'",
|
||||||
|
profile.name, profile.index, dev_name))
|
||||||
|
|
||||||
|
-- check if the new profile is the same as the current one
|
||||||
|
if state_table[dev_name] == profile.name then
|
||||||
|
Log.debug (device, " ... profile is already stored")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- find the full profile from EnumProfile, making also sure that the
|
||||||
|
-- user / client application has actually set an existing profile
|
||||||
|
for p in device:iterate_params ("EnumProfile") do
|
||||||
|
local enum_profile = cutils.parseParam (p, "EnumProfile")
|
||||||
|
if enum_profile.name == profile.name then
|
||||||
|
index = enum_profile.index
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not index then
|
||||||
|
Log.info (device, string.format (
|
||||||
|
"profile '%s' (%d) is not valid on device '%s'",
|
||||||
|
profile.name, profile.index, dev_name))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
state_table[dev_name] = profile.name
|
||||||
|
cutils.storeAfterTimeout (state, state_table)
|
||||||
|
|
||||||
|
Log.info (device, string.format (
|
||||||
|
"stored profile '%s' (%d) for device '%s'",
|
||||||
|
profile.name, index, dev_name))
|
||||||
|
end
|
Reference in New Issue
Block a user