mirror of
https://gitlab.freedesktop.org/pipewire/wireplumber.git
synced 2026-05-05 22:58:02 +02:00
policy-node: forward filter stream's format to filter device
Currently, when using filter nodes such as echo-cancel or filer-chain, the ports format of the virtual stream node might not always match the format of its associated virtual device node. This can happen if the virtual stream node is linked with a real device node configured with many channels, such as surround profile. In that case, the channel configuration is not forwarded to the virtual device node, making the application not being aware of a surround setup. This change listens for port format changes in the virtual stream nodes, and reconfigures the virtual device node ports everytime the virtual stream node's port format changes. This behavior is experimental and optional, so it is disabled by default.
This commit is contained in:
parent
07179452e2
commit
7080e9961c
2 changed files with 105 additions and 5 deletions
|
|
@ -6,6 +6,11 @@ default_policy.policy = {
|
|||
["move"] = true, -- moves session items when metadata target.node changes
|
||||
["follow"] = true, -- moves session items to the default device when it has changed
|
||||
|
||||
-- Whether to forward the ports format of filter stream nodes to their
|
||||
-- associated filter device nodes. This is needed for application to stream
|
||||
-- surround audio if echo-cancel is enabled.
|
||||
["filter.forward-format"] = false,
|
||||
|
||||
-- Set to 'true' to disable channel splitting & merging on nodes and enable
|
||||
-- passthrough of audio in the same format as the format of the device.
|
||||
-- Note that this breaks JACK support; it is generally not recommended
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ local config = ... or {}
|
|||
-- ensure config.move and config.follow are not nil
|
||||
config.move = config.move or false
|
||||
config.follow = config.follow or false
|
||||
config.filter_forward_format = config["filter.forward-format"] or false
|
||||
|
||||
local self = {}
|
||||
self.scanning = false
|
||||
|
|
@ -648,10 +649,7 @@ function handleLinkable (si)
|
|||
Log.info (si, string.format("handling item: %s (%s)",
|
||||
tostring(si_props["node.name"]), tostring(si_props["node.id"])))
|
||||
|
||||
-- prepare flags table
|
||||
if not si_flags[si.id] then
|
||||
si_flags[si.id] = {}
|
||||
end
|
||||
ensureSiFlags(si)
|
||||
|
||||
-- get other important node properties
|
||||
local reconnect = not parseBool(si_props["node.dont-reconnect"])
|
||||
|
|
@ -857,8 +855,105 @@ if config.move then
|
|||
end)
|
||||
end
|
||||
|
||||
function findAssociatedLinkGroupNode (si)
|
||||
local si_props = si.properties
|
||||
local node = si:get_associated_proxy ("node")
|
||||
local link_group = node.properties["node.link-group"]
|
||||
if link_group == nil then
|
||||
return nil
|
||||
end
|
||||
|
||||
-- get the associated media class
|
||||
local assoc_direction = getTargetDirection(si_props)
|
||||
local assoc_media_class =
|
||||
si_props["media.type"] ..
|
||||
(assoc_direction == "input" and "/Sink" or "/Source")
|
||||
|
||||
-- find the linkable with same link group and matching assoc media class
|
||||
for assoc_si in linkables_om:iterate() do
|
||||
local assoc_node = assoc_si:get_associated_proxy ("node")
|
||||
local assoc_link_group = assoc_node.properties["node.link-group"]
|
||||
if assoc_link_group == link_group and
|
||||
assoc_media_class == assoc_node.properties["media.class"] then
|
||||
return assoc_si
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
function onLinkGroupPortsStateChanged (si, old_state, new_state)
|
||||
local new_str = tostring(new_state)
|
||||
local si_props = si.properties
|
||||
|
||||
-- only handle items with configured ports state
|
||||
if new_str ~= "configured" then
|
||||
return
|
||||
end
|
||||
|
||||
Log.info (si, "ports format changed on " .. si_props["node.name"])
|
||||
|
||||
-- find associated device
|
||||
local si_device = findAssociatedLinkGroupNode (si)
|
||||
if si_device ~= nil then
|
||||
local device_node_name = si_device.properties["node.name"]
|
||||
|
||||
-- get the stream format
|
||||
local f, m = si:get_ports_format()
|
||||
|
||||
-- unregister the device
|
||||
Log.info (si_device, "unregistering " .. device_node_name)
|
||||
si_device:remove()
|
||||
|
||||
-- set new format in the device
|
||||
Log.info (si_device, "setting new format in " .. device_node_name)
|
||||
si_device:set_ports_format(f, m, function (item, e)
|
||||
if e ~= nil then
|
||||
Log.warning (item, "failed to configure ports in " ..
|
||||
device_node_name .. ": " .. e)
|
||||
end
|
||||
|
||||
-- register back the device
|
||||
Log.info (item, "registering " .. device_node_name)
|
||||
item:register()
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function ensureSiFlags (si)
|
||||
-- prepare flags table
|
||||
if not si_flags[si.id] then
|
||||
si_flags[si.id] = {}
|
||||
end
|
||||
end
|
||||
|
||||
function checkFiltersPortsState (si)
|
||||
local si_props = si.properties
|
||||
local node = si:get_associated_proxy ("node")
|
||||
local link_group = node.properties["node.link-group"]
|
||||
|
||||
ensureSiFlags(si)
|
||||
|
||||
-- only listen for ports state changed on audio filter streams
|
||||
if si_flags[si.id].ports_state_signal ~= true and
|
||||
si_props["item.factory.name"] == "si-audio-adapter" and
|
||||
si_props["item.node.type"] == "stream" and
|
||||
link_group ~= nil then
|
||||
si:connect("adapter-ports-state-changed", onLinkGroupPortsStateChanged)
|
||||
si_flags[si.id].ports_state_signal = true
|
||||
Log.info (si, "listening ports state changed on " .. si_props["node.name"])
|
||||
end
|
||||
end
|
||||
|
||||
linkables_om:connect("object-added", function (om, si)
|
||||
if si.properties["item.node.type"] ~= "stream" then
|
||||
local si_props = si.properties
|
||||
|
||||
-- Forward filters ports format to associated virtual devices if enabled
|
||||
if config.filter_forward_format then
|
||||
checkFiltersPortsState (si)
|
||||
end
|
||||
|
||||
if si_props["item.node.type"] ~= "stream" then
|
||||
scheduleRescan ()
|
||||
else
|
||||
handleLinkable (si)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue