Files
wireplumber/src/scripts/linking/rescan.lua
Julian Bouzas 0b44d9cf84 scripts: change filter.enabled property to filter.disabled
Avoids confusion with default value if the property is not defined.
2023-10-02 10:44:38 -04:00

207 lines
5.7 KiB
Lua

-- WirePlumber
--
-- Copyright © 2020-2022 Collabora Ltd.
--
-- SPDX-License-Identifier: MIT
--
-- Handle new linkables and trigger rescanning of the graph.
-- Rescan the graph by pushing new select-target events for
-- all linkables that need to be linked
-- Cleanup links when the linkables they are associated with are removed.
-- Also, cleanup flags attached to linkables.
putils = require ("linking-utils")
cutils = require ("common-utils")
futils = require ("filter-utils")
log = Log.open_topic ("s-linking")
function checkFilter (si, om, handle_nonstreams)
-- always handle filters if handle_nonstreams is true, even if it is disabled
if handle_nonstreams then
return true
end
-- always return true if this is not a filter
local node = si:get_associated_proxy ("node")
local link_group = node.properties["node.link-group"]
if link_group == nil then
return true
end
local direction = cutils.getTargetDirection (si.properties)
return not futils.is_filter_disabled (direction, link_group)
end
function checkLinkable (si, om, handle_nonstreams)
local si_props = si.properties
-- Always handle si-audio-virtual session items
if si_props ["item.factory.name"] == "si-audio-virtual" then
return true, si_props
end
-- For the rest of them, only handle stream session items
if not si_props or (si_props ["item.node.type"] ~= "stream"
and not handle_nonstreams) then
return false, si_props
end
-- check filters
if not checkFilter (si, om, handle_nonstreams) then
return false, si_props
end
return true, si_props
end
function unhandleLinkable (si, om)
local si_id = si.id
local valid, si_props = checkLinkable (si, om, true)
if not valid then
return
end
log.info (si, string.format ("unhandling item: %s (%s)",
tostring (si_props ["node.name"]), tostring (si_props ["node.id"])))
-- iterate over all the links in the graph and
-- remove any links associated with this item
for silink in om:iterate { type = "SiLink" } do
local out_id = tonumber (silink.properties ["out.item.id"])
local in_id = tonumber (silink.properties ["in.item.id"])
if out_id == si_id or in_id == si_id then
local in_flags = putils:get_flags (in_id)
local out_flags = putils:get_flags (out_id)
if out_id == si_id and in_flags.peer_id == out_id then
in_flags.peer_id = nil
elseif in_id == si_id and out_flags.peer_id == in_id then
out_flags.peer_id = nil
end
silink:remove ()
log.info (silink, "... link removed")
end
end
putils:clear_flags (si_id)
end
SimpleEventHook {
name = "linking/linkable-removed",
interests = {
EventInterest {
Constraint { "event.type", "=", "session-item-removed" },
Constraint { "event.session-item.interface", "=", "linkable" },
},
},
execute = function (event)
local si = event:get_subject ()
local source = event:get_source ()
local om = source:call ("get-object-manager", "session-item")
unhandleLinkable (si, om)
end
}:register ()
function handleLinkables (source)
local om = source:call ("get-object-manager", "session-item")
for si in om:iterate { type = "SiLinkable" } do
local valid, si_props = checkLinkable (si, om)
if not valid then
goto skip_linkable
end
-- check if we need to link this node at all
local autoconnect = cutils.parseBool (si_props ["node.autoconnect"])
if not autoconnect then
log.debug (si, tostring (si_props ["node.name"]) .. " does not need to be autoconnected")
goto skip_linkable
end
-- push event to find target and link
source:call ("push-event", "select-target", si, nil)
::skip_linkable::
end
end
SimpleEventHook {
name = "linking/rescan",
interests = {
EventInterest {
Constraint { "event.type", "=", "rescan-for-linking" },
},
},
execute = function (event)
local source = event:get_source ()
log:info ("rescanning...")
handleLinkables (source)
end
}:register ()
SimpleEventHook {
name = "linking/rescan-trigger",
interests = {
-- on linkable added or removed, where linkable is adapter or plain node
EventInterest {
Constraint { "event.type", "c", "session-item-added", "session-item-removed" },
Constraint { "event.session-item.interface", "=", "linkable" },
},
-- on device Routes changed
EventInterest {
Constraint { "event.type", "=", "device-params-changed" },
Constraint { "event.subject.param-id", "=", "Route" },
},
},
execute = function (event)
local source = event:get_source ()
source:call ("schedule-rescan", "linking")
end
}:register ()
SimpleEventHook {
name = "linking/rescan-trigger-before-filters-metadata-changed",
before = "lib/filter-utils/rescan-metadata-changed",
interests = {
EventInterest {
Constraint { "event.type", "=", "metadata-changed" },
Constraint { "metadata.name", "=", "filters" },
},
},
execute = function (event)
local source = event:get_source ()
local om = source:call ("get-object-manager", "session-item")
-- unlink all filters
for si in om:iterate {
type = "SiLinkable",
Constraint { "node.link-group", "+" },
} do
unhandleLinkable (si, om)
end
end
}:register ()
SimpleEventHook {
name = "linking/rescan-trigger-after-filters-metadata-changed",
after = "lib/filter-utils/rescan-metadata-changed",
interests = {
EventInterest {
Constraint { "event.type", "=", "metadata-changed" },
Constraint { "metadata.name", "=", "filters" },
},
},
execute = function (event)
local source = event:get_source ()
local om = source:call ("get-object-manager", "session-item")
source:call ("schedule-rescan", "linking")
end
}:register ()