link-target.lua: change into a async hook

link setup is a asynchronous action, async hook serves the purpose well
here.

The code dependent on links will be less error prone with this design.
This commit is contained in:
Ashok Sidipotu
2023-01-05 16:08:53 +05:30
committed by Julian Bouzas
parent a8aeb1010e
commit 4b153ec553

View File

@@ -10,7 +10,7 @@
local putils = require ("policy-utils") local putils = require ("policy-utils")
local cutils = require ("common-utils") local cutils = require ("common-utils")
SimpleEventHook { AsyncEventHook {
name = "linking/link-target", name = "linking/link-target",
after = "linking/prepare-link", after = "linking/prepare-link",
interests = { interests = {
@@ -18,124 +18,146 @@ SimpleEventHook {
Constraint { "event.type", "=", "select-target" }, Constraint { "event.type", "=", "select-target" },
}, },
}, },
execute = function (event) steps = {
local source, om, si, si_props, si_flags, target = start = {
putils:unwrap_find_target_event (event) next = "link_activated",
execute = function (event, transition)
local source, om, si, si_props, si_flags, target =
putils:unwrap_find_target_event (event)
-- bypass the hook, nothing to link to if not target then
if not target then -- bypass the hook, nothing to link to.
return transition:advance ()
end return
end
local target_props = target.properties local target_props = target.properties
local out_item = nil local out_item = nil
local in_item = nil local in_item = nil
local si_link = nil local si_link = nil
local passthrough = si_flags.can_passthrough local passthrough = si_flags.can_passthrough
Log.info (si, string.format ("handling item: %s (%s)", Log.info (si, string.format ("handling item: %s (%s)",
tostring (si_props ["node.name"]), tostring (si_props ["node.id"]))) tostring (si_props ["node.name"]), tostring (si_props ["node.id"])))
local exclusive = cutils.parseBool (si_props ["node.exclusive"]) local exclusive = cutils.parseBool (si_props ["node.exclusive"])
local passive = cutils.parseBool (si_props ["node.passive"]) or local passive = cutils.parseBool (si_props ["node.passive"]) or
cutils.parseBool (target_props ["node.passive"]) cutils.parseBool (target_props ["node.passive"])
-- break rescan if tried more than 5 times with same target -- break rescan if tried more than 5 times with same target
if si_flags.failed_peer_id ~= nil and if si_flags.failed_peer_id ~= nil and
si_flags.failed_peer_id == target.id and si_flags.failed_peer_id == target.id and
si_flags.failed_count ~= nil and si_flags.failed_count ~= nil and
si_flags.failed_count > 5 then si_flags.failed_count > 5 then
Log.warning (si, "tried to link on last rescan, not retrying") transition:return_error ("tried to link on last rescan, not retrying "
goto done .. tostring (si_link))
end end
if si_props ["item.node.direction"] == "output" then if si_props ["item.node.direction"] == "output" then
-- playback -- playback
out_item = si out_item = si
in_item = target in_item = target
else else
-- capture -- capture
in_item = si in_item = si
out_item = target out_item = target
end end
Log.info (si, Log.info (si,
string.format ("link %s <-> %s passive:%s, passthrough:%s, exclusive:%s", string.format ("link %s <-> %s passive:%s, passthrough:%s, exclusive:%s",
tostring (si_props ["node.name"]), tostring (si_props ["node.name"]),
tostring (target_props ["node.name"]), tostring (target_props ["node.name"]),
tostring (passive), tostring (passthrough), tostring (exclusive))) tostring (passive), tostring (passthrough), tostring (exclusive)))
-- create and configure link -- create and configure link
si_link = SessionItem ("si-standard-link") si_link = SessionItem ("si-standard-link")
if not si_link:configure { if not si_link:configure {
["out.item"] = out_item, ["out.item"] = out_item,
["in.item"] = in_item, ["in.item"] = in_item,
["passive"] = passive, ["passive"] = passive,
["passthrough"] = passthrough, ["passthrough"] = passthrough,
["exclusive"] = exclusive, ["exclusive"] = exclusive,
["out.item.port.context"] = "output", ["out.item.port.context"] = "output",
["in.item.port.context"] = "input", ["in.item.port.context"] = "input",
["is.policy.item.link"] = true, ["is.policy.item.link"] = true,
} then } then
Log.warning (si_link, "failed to configure si-standard-link") transition:return_error ("failed to configure si-standard-link "
goto done .. tostring (si_link))
end return
end
si_link:connect("link-error", function (_, error_msg) si_link:connect("link-error", function (_, error_msg)
local ids = {si.id, si_flags.peer_id} local ids = {si.id, si_flags.peer_id}
for _, id in ipairs (ids) do for _, id in ipairs (ids) do
local si = om:lookup { local si = om:lookup {
Constraint { "id", "=", id, type = "gobject" }, Constraint { "id", "=", id, type = "gobject" },
}
if si then
local node = si:get_associated_proxy ("node")
local client_id = node.properties["client.id"]
if client_id then
local client = om:lookup {
Constraint { "bound-id", "=", client_id, type = "gobject" }
} }
if client then if si then
Log.info (node, "sending client error: " .. error_msg) local node = si:get_associated_proxy ("node")
client:send_error (node["bound-id"], -32, error_msg) local client_id = node.properties["client.id"]
if client_id then
local client = om:lookup {
Constraint { "bound-id", "=", client_id, type = "gobject" }
}
if client then
Log.info (node, "sending client error: " .. error_msg)
client:send_error (node["bound-id"], -32, error_msg)
end
end
end end
end end
end end)
end
end)
-- register -- register
si_flags.peer_id = target.id si_flags.peer_id = target.id
si_flags.failed_peer_id = target.id si_flags.failed_peer_id = target.id
if si_flags.failed_count ~= nil then if si_flags.failed_count ~= nil then
si_flags.failed_count = si_flags.failed_count + 1 si_flags.failed_count = si_flags.failed_count + 1
else else
si_flags.failed_count = 1 si_flags.failed_count = 1
end
si_link:register ()
-- activate
si_link:activate (Feature.SessionItem.ACTIVE, function (l, e)
if e then
Log.info (l, "failed to activate si-standard-link: " .. tostring (si) .. " error:" .. tostring (e))
if si_flags ~= nil then
si_flags.peer_id = nil
end end
l:remove () si_link:register ()
else
-- activate
si_link:activate (Feature.SessionItem.ACTIVE, function (l, e)
if e then
transition:return_error ("failed to activate si-standard-link: "
.. tostring (si) .. " error:" .. tostring (e))
if si_flags ~= nil then
si_flags.peer_id = nil
end
l:remove ()
else
si_flags.si_link = si_link
transition:advance ()
end
end)
end,
},
link_activated = {
next = "none",
execute = function (event, transition)
local source, om, si, si_props, si_flags, target =
putils:unwrap_find_target_event (event)
if not target then
-- bypass the hook, nothing to link to.
transition:advance ()
return
end
if si_flags ~= nil then if si_flags ~= nil then
si_flags.failed_peer_id = nil si_flags.failed_peer_id = nil
if si_flags.peer_id == nil then if si_flags.peer_id == nil then
si_flags.peer_id = target.id si_flags.peer_id = si_target.id
end end
si_flags.failed_count = 0 si_flags.failed_count = 0
end end
Log.info (l, "activated si-standard-link " .. tostring (si)) Log.info (si_flags.si_link, "activated si-standard-link between "
end .. tostring (si).." and "..tostring(si_target))
end)
::done:: transition:advance ()
si_flags.was_handled = true end,
putils.checkFollowDefault (si, target, si_flags.has_node_defined_target) },
end },
}:register () }:register ()