mirror of
https://gitlab.freedesktop.org/pipewire/wireplumber.git
synced 2026-05-09 02:48:05 +02:00
linking: Add ALSA loopback policy scripts
This policy script is in charge of linking all nodes from all ALSA loopback collections.
This commit is contained in:
parent
c81cd4cd96
commit
dfeb57934d
3 changed files with 209 additions and 0 deletions
|
|
@ -719,6 +719,14 @@ wireplumber.components = [
|
|||
provides = hooks.linking.default.target.get-filter-from
|
||||
requires = [ metadata.filters ]
|
||||
}
|
||||
{
|
||||
name = linking/alsa-loopback/find-filter-target.lua, type = script/lua
|
||||
provides = hooks.linking.alsa-loopback.target.find-filter
|
||||
}
|
||||
{
|
||||
name = linking/alsa-loopback/find-alsa-target.lua, type = script/lua
|
||||
provides = hooks.linking.alsa-loopback.target.find-alsa
|
||||
}
|
||||
{
|
||||
name = linking/prepare-link.lua, type = script/lua
|
||||
provides = hooks.linking.target.prepare-link
|
||||
|
|
@ -747,6 +755,8 @@ wireplumber.components = [
|
|||
hooks.linking.default.target.find-default,
|
||||
hooks.linking.default.target.find-best,
|
||||
hooks.linking.default.target.get-filter-from,
|
||||
hooks.linking.alsa-loopback.target.find-filter,
|
||||
hooks.linking.alsa-loopback.target.find-alsa,
|
||||
hooks.linking.pause-playback ]
|
||||
}
|
||||
|
||||
|
|
|
|||
102
src/scripts/linking/alsa-loopback/find-alsa-target.lua
Normal file
102
src/scripts/linking/alsa-loopback/find-alsa-target.lua
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
-- WirePlumber
|
||||
--
|
||||
-- Copyright © 2025 Collabora Ltd.
|
||||
--
|
||||
-- SPDX-License-Identifier: MIT
|
||||
--
|
||||
-- Finds the hardware target for a linkable in 'alsa_loopback.*' collection
|
||||
|
||||
lutils = require ("linking-utils")
|
||||
cutils = require ("common-utils")
|
||||
log = Log.open_topic ("s-linking")
|
||||
|
||||
SimpleEventHook {
|
||||
name = "linking/alsa-loopback/find-alsa-target",
|
||||
before = "linking/prepare-link",
|
||||
interests = {
|
||||
EventInterest {
|
||||
Constraint { "event.type", "=", "select-target" },
|
||||
Constraint { "collection.name", "#", "alsa_loopback.*" },
|
||||
},
|
||||
},
|
||||
execute = function (event)
|
||||
local source, om, si, si_props, si_flags, target =
|
||||
lutils:unwrap_select_target_event (event)
|
||||
|
||||
-- Bypass the hook if the target is already picked up
|
||||
if target then
|
||||
return
|
||||
end
|
||||
|
||||
-- Get the collection name
|
||||
local collection_name = si_props["collection.name"]
|
||||
assert (collection_name)
|
||||
|
||||
local target_direction = cutils.getTargetDirection (si_props)
|
||||
local target_picked = nil
|
||||
local target_can_passthrough = false
|
||||
local target_priority = 0
|
||||
|
||||
log:info (string.format ("handling item %d: %s (%s)", si.id,
|
||||
si_props ["node.name"], si_props ["node.id"]))
|
||||
|
||||
-- Find the hardware target (session items without node.link-group property)
|
||||
-- matching the collection name
|
||||
for target in om:iterate {
|
||||
type = "SiLinkable",
|
||||
Constraint { "item.node.type", "=", "device" },
|
||||
Constraint { "item.node.direction", "=", target_direction },
|
||||
Constraint { "media.type", "=", si_props ["media.type"] },
|
||||
Constraint { "collection.name", "=", collection_name },
|
||||
Constraint { "node.link-group", "-" },
|
||||
} do
|
||||
local target_props = target.properties
|
||||
local priority = tonumber (target_props ["priority.session"]) or 0
|
||||
|
||||
log:debug (string.format ("Looking at: %s (%s)",
|
||||
target_props ["node.name"], target_props ["node.id"]))
|
||||
|
||||
if not lutils.canLink (si_props, target) then
|
||||
log:debug ("... cannot link, skip linkable")
|
||||
goto skip_linkable
|
||||
end
|
||||
|
||||
local passthrough_compatible, can_passthrough =
|
||||
lutils.checkPassthroughCompatibility (si, target)
|
||||
if not passthrough_compatible then
|
||||
log:debug ("... passthrough is not compatible, skip linkable")
|
||||
goto skip_linkable
|
||||
end
|
||||
|
||||
if target_picked == nil or priority > target_priority then
|
||||
log:debug ("... picked")
|
||||
target_picked = target
|
||||
target_can_passthrough = can_passthrough
|
||||
target_priority = priority
|
||||
end
|
||||
|
||||
::skip_linkable::
|
||||
end
|
||||
|
||||
local can_passthrough, passthrough_compatible
|
||||
if target then
|
||||
passthrough_compatible, can_passthrough =
|
||||
lutils.checkPassthroughCompatibility (si, target)
|
||||
if lutils.canLink (si_props, target) and passthrough_compatible then
|
||||
target_picked = true
|
||||
end
|
||||
end
|
||||
|
||||
if target_picked then
|
||||
log:info (si,
|
||||
string.format ("... hardware target picked: %s (%s), can_passthrough:%s",
|
||||
target_picked.properties ["node.name"],
|
||||
target_picked.properties ["node.id"],
|
||||
tostring (target_can_passthrough)))
|
||||
si_flags.can_passthrough = target_can_passthrough
|
||||
event:set_data ("target", target_picked)
|
||||
else
|
||||
event:stop_processing ()
|
||||
end
|
||||
end
|
||||
}:register ()
|
||||
97
src/scripts/linking/alsa-loopback/find-filter-target.lua
Normal file
97
src/scripts/linking/alsa-loopback/find-filter-target.lua
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
-- WirePlumber
|
||||
--
|
||||
-- Copyright © 2026 Collabora Ltd.
|
||||
--
|
||||
-- SPDX-License-Identifier: MIT
|
||||
--
|
||||
-- Finds the filter target for a linkable in 'alsa_loopback.*' collection
|
||||
|
||||
lutils = require ("linking-utils")
|
||||
cutils = require ("common-utils")
|
||||
log = Log.open_topic ("s-linking")
|
||||
|
||||
SimpleEventHook {
|
||||
name = "linking/alsa-loopback/find-filter-target",
|
||||
before = "linking/alsa-loopback/find-alsa-target",
|
||||
interests = {
|
||||
EventInterest {
|
||||
Constraint { "event.type", "=", "select-target" },
|
||||
Constraint { "collection.name", "#", "alsa_loopback.*" },
|
||||
},
|
||||
},
|
||||
execute = function (event)
|
||||
local source, om, si, si_props, si_flags, target =
|
||||
lutils:unwrap_select_target_event (event)
|
||||
|
||||
-- Bypass the hook if the target is already picked up
|
||||
if target then
|
||||
return
|
||||
end
|
||||
|
||||
-- Get the collection name
|
||||
local collection_name = si_props["collection.name"]
|
||||
assert (collection_name)
|
||||
|
||||
local target_direction = cutils.getTargetDirection (si_props)
|
||||
local target_picked = nil
|
||||
local target_can_passthrough = false
|
||||
|
||||
log:info (string.format ("handling item %d: %s (%s)", si.id,
|
||||
si_props ["node.name"], si_props ["node.id"]))
|
||||
|
||||
-- Find the first filter target (session items with node.link-group property
|
||||
-- that is not an alsa loopback item) matching the collection name
|
||||
for target in om:iterate {
|
||||
type = "SiLinkable",
|
||||
Constraint { "item.node.type", "=", "device" },
|
||||
Constraint { "item.node.direction", "=", target_direction },
|
||||
Constraint { "media.type", "=", si_props ["media.type"] },
|
||||
Constraint { "collection.name", "=", collection_name },
|
||||
Constraint { "node.link-group", "+" },
|
||||
Constraint { "alsa.loopback.id", "-" },
|
||||
} do
|
||||
local target_props = target.properties
|
||||
|
||||
log:debug (string.format ("Looking at: %s (%s)",
|
||||
target_props ["node.name"], target_props ["node.id"]))
|
||||
|
||||
if not lutils.canLink (si_props, target) then
|
||||
log:debug ("... cannot link, skip linkable")
|
||||
goto skip_linkable
|
||||
end
|
||||
|
||||
local passthrough_compatible, can_passthrough =
|
||||
lutils.checkPassthroughCompatibility (si, target)
|
||||
if not passthrough_compatible then
|
||||
log:debug ("... passthrough is not compatible, skip linkable")
|
||||
goto skip_linkable
|
||||
end
|
||||
|
||||
log:debug ("... picked")
|
||||
target_picked = target
|
||||
target_can_passthrough = can_passthrough
|
||||
break
|
||||
|
||||
::skip_linkable::
|
||||
end
|
||||
|
||||
local can_passthrough, passthrough_compatible
|
||||
if target then
|
||||
passthrough_compatible, can_passthrough =
|
||||
lutils.checkPassthroughCompatibility (si, target)
|
||||
if lutils.canLink (si_props, target) and passthrough_compatible then
|
||||
target_picked = true
|
||||
end
|
||||
end
|
||||
|
||||
if target_picked then
|
||||
log:info (si,
|
||||
string.format ("... filter target picked: %s (%s), can_passthrough:%s",
|
||||
target_picked.properties ["node.name"],
|
||||
target_picked.properties ["node.id"],
|
||||
tostring (target_can_passthrough)))
|
||||
si_flags.can_passthrough = target_can_passthrough
|
||||
event:set_data ("target", target_picked)
|
||||
end
|
||||
end
|
||||
}:register ()
|
||||
Loading…
Add table
Reference in a new issue