create-item.lua: Handle nodes that are collected into collections

This change makes sure the session items are always updated even after nodes
are collected or dropped from a collection. We also set a 'collection.name'
property so we can easily filter nodes by collection.
This commit is contained in:
Julian Bouzas 2025-12-17 12:10:08 -05:00
parent cfce278ec5
commit b2c4278213

View file

@ -17,6 +17,7 @@ function configProperties (node)
local properties = node.properties
local media_class = properties ["media.class"] or ""
local factory_name = properties ["factory.name"] or ""
local collection = CollectionManager.get_global_collection (node)
-- ensure a media.type is set
if not properties ["media.type"] then
@ -44,6 +45,7 @@ function configProperties (node)
(factory_name == "api.alsa.pcm.sink" or factory_name == "api.bluez5.a2dp.sink") and
Settings.get_boolean ("node.features.audio.mono")
properties ["node.id"] = node ["bound-id"]
properties ["collection.name"] = collection and collection:get_name () or nil
-- set the default media.role, if configured
-- avoid Settings.get_string(), as it will parse the default "null" value
@ -61,69 +63,76 @@ AsyncEventHook {
name = "node/create-item",
interests = {
EventInterest {
Constraint { "event.type", "=", "node-added" },
Constraint { "event.type", "c", "node-added", "node-collected", "node-dropped" },
Constraint { "media.class", "#", "Stream/*", type = "pw-global" },
},
EventInterest {
Constraint { "event.type", "=", "node-added" },
Constraint { "event.type", "c", "node-added", "node-collected", "node-dropped" },
Constraint { "media.class", "#", "Video/*", type = "pw-global" },
},
EventInterest {
Constraint { "event.type", "=", "node-added" },
Constraint { "event.type", "c", "node-added", "node-collected", "node-dropped" },
Constraint { "media.class", "#", "Audio/*", type = "pw-global" },
Constraint { "wireplumber.is-virtual", "-", type = "pw" },
},
},
steps = {
start = {
next = "register",
next = "none",
execute = function (event, transition)
local node = event:get_subject ()
local id = node.id
local item
local item_type
local media_class = node.properties ['media.class']
local node_name = node.properties ['node.name']
local collection = CollectionManager.get_global_collection (node)
local collection_name = collection and collection:get_name () or nil
-- Just return if the item already exists with the same collection name
if items [id] and
items [id]:get_property ("collection.name") == collection_name then
transition:advance ()
return
end
-- Destroy the old item if any
if items [id] then
log:info (items [id], "destroying item for node " .. tostring (id))
items [id]:remove ()
items [id] = nil
end
-- get the item type
local item_type = nil
if string.find (media_class, "Audio") then
item_type = "si-audio-adapter"
else
item_type = "si-node"
end
log:info (node, "creating item for node -> " .. item_type)
-- create item
item = SessionItem (item_type)
local item = SessionItem (item_type)
items [id] = item
log:info (item, "created item for node " .. tostring (id) .. ": " .. node_name)
-- configure item
if not item:configure (configProperties (node)) then
transition:return_error ("failed to configure item for node "
.. tostring (id))
transition:return_error ("failed to configure item for node " .. tostring (id))
return
end
-- activate item
item:activate (Features.ALL, function (_, e)
if e then
transition:return_error ("failed to activate item: "
.. tostring (e));
else
transition:advance ()
transition:return_error ("failed to activate item for node " .. tostring (id) ..
": " .. tostring (e));
return
end
end)
end,
},
register = {
next = "none",
execute = function (event, transition)
local node = event:get_subject ()
local bound_id = node ["bound-id"]
local item = items [node.id]
log:info (item, "activated item for node " .. tostring (bound_id))
item:register ()
transition:advance ()
-- register item
log:info (item, "activated item for node " .. tostring (id) .. ": " .. node_name)
item:register ()
transition:advance ()
end)
end,
},
},