mirror of
https://gitlab.freedesktop.org/pipewire/wireplumber.git
synced 2025-12-20 04:10:03 +01:00
role-based-policy: Allow to set target sink for media role loopbacks
There are streams that should go to a speaker rather than a headphone or earpiece by default. Examples are alarms and emergency alerts on phones. Allow to set a preference via `policy.role-based.preferred-target` which then looks up the target via `node.name` and `node.nick`. Signed-off-by: Guido Günther <agx@sigxcpu.org>
This commit is contained in:
parent
d2a49e8bc5
commit
c095ae5254
4 changed files with 90 additions and 2 deletions
|
|
@ -727,11 +727,16 @@ wireplumber.components = [
|
|||
provides = hooks.node.role-based.default-volume
|
||||
requires = [ hooks.linking.role-based.rescan ]
|
||||
}
|
||||
{
|
||||
name = linking/find-media-role-sink-target.lua, type = script/lua
|
||||
provides = hooks.linking.target.find-media-role-sink
|
||||
}
|
||||
{
|
||||
type = virtual, provides = policy.linking.role-based
|
||||
requires = [ policy.linking.standard,
|
||||
hooks.linking.role-based.rescan,
|
||||
hooks.node.role-based.default-volume ]
|
||||
hooks.node.role-based.default-volume,
|
||||
hooks.linking.target.find-media-role-sink ]
|
||||
}
|
||||
|
||||
## Standard policy definition
|
||||
|
|
|
|||
|
|
@ -150,6 +150,7 @@ wireplumber.components = [
|
|||
policy.role-based.priority = 100
|
||||
policy.role-based.action.same-priority = "mix"
|
||||
policy.role-based.action.lower-priority = "cork"
|
||||
policy.role-based.preferred-target = "Speaker"
|
||||
}
|
||||
}
|
||||
provides = loopback.sink.role.alert
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@ SimpleEventHook {
|
|||
name = "linking/find-default-target",
|
||||
after = { "linking/find-defined-target",
|
||||
"linking/find-filter-target",
|
||||
"linking/find-media-role-target" },
|
||||
"linking/find-media-role-target",
|
||||
"linking/find-media-role-sink-target" },
|
||||
before = "linking/prepare-link",
|
||||
interests = {
|
||||
EventInterest {
|
||||
|
|
|
|||
81
src/scripts/linking/find-media-role-sink-target.lua
Normal file
81
src/scripts/linking/find-media-role-sink-target.lua
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
-- WirePlumber
|
||||
--
|
||||
-- Copyright © 2025 Phosh.mobi e.V.
|
||||
--
|
||||
-- SPDX-License-Identifier: MIT
|
||||
--
|
||||
-- Pick up a preferred target node for the output stream of role-based loopbacks
|
||||
|
||||
lutils = require ("linking-utils")
|
||||
cutils = require ("common-utils")
|
||||
|
||||
log = Log.open_topic ("s-linking")
|
||||
|
||||
SimpleEventHook {
|
||||
name = "linking/find-media-role-sink-target",
|
||||
after = { "linking/find-defined-target",
|
||||
"linking/find-media-role-target" },
|
||||
before = "linking/prepare-link",
|
||||
interests = {
|
||||
EventInterest {
|
||||
Constraint { "event.type", "=", "select-target" },
|
||||
},
|
||||
},
|
||||
execute = function (event)
|
||||
local _, om, si, si_props, _, target =
|
||||
lutils:unwrap_select_target_event (event)
|
||||
|
||||
local node_name = si_props["node.name"]
|
||||
local target_direction = cutils.getTargetDirection (si_props)
|
||||
local media_class = si_props["media.class"]
|
||||
local link_group = si_props["node.link-group"]
|
||||
local is_virtual = si_props["node.virtual"]
|
||||
|
||||
log:info (si, string.format ("Lookup for '%s' (%s) / '%s' / '%s'",
|
||||
node_name, tostring (si_props ["node.id"]), media_class, link_group))
|
||||
|
||||
--- bypass the hook if the target is already set or there's no link group
|
||||
if target or media_class ~= "Stream/Output/Audio" or not is_virtual or link_group == nil then
|
||||
return
|
||||
end
|
||||
|
||||
--- We link the output node but the relevant properties are on the input node
|
||||
--- of the link group
|
||||
local input_node = om:lookup {
|
||||
type = "SiLinkable",
|
||||
Constraint { "media.class", "=", "Audio/Sink" },
|
||||
Constraint { "node.link-group", "=", link_group },
|
||||
}
|
||||
|
||||
if input_node == nil then
|
||||
log:warning (si, string.format("No input node for %s found", link_group))
|
||||
return
|
||||
end
|
||||
|
||||
local target_name = input_node.properties["policy.role-based.preferred-target"]
|
||||
--- no preferred target
|
||||
if target_name == nil then
|
||||
return
|
||||
end
|
||||
|
||||
local si_target = om:lookup {
|
||||
type = "SiLinkable",
|
||||
Constraint { "item.factory.name", "c", "si-audio-adapter", "si-node" },
|
||||
Constraint { "node.name", "=", target_name },
|
||||
}
|
||||
if si_target == nil then
|
||||
si_target = om:lookup {
|
||||
type = "SiLinkable",
|
||||
Constraint { "item.factory.name", "c", "si-audio-adapter", "si-node" },
|
||||
Constraint { "node.nick", "=", target_name },
|
||||
}
|
||||
end
|
||||
if si_target then
|
||||
log:info (si,
|
||||
string.format ("... role based sink target picked: %s (%s)",
|
||||
tostring (si_target.properties ["node.name"]),
|
||||
tostring (si_target.properties ["node.id"])))
|
||||
event:set_data ("target", si_target)
|
||||
end
|
||||
end
|
||||
}:register ()
|
||||
Loading…
Add table
Reference in a new issue