mirror of
https://gitlab.freedesktop.org/pipewire/wireplumber.git
synced 2026-02-04 15:30:30 +01:00
m-audio-endpoint: remove target property
Links between endpoints and device nodes are done externally in LUA
This commit is contained in:
parent
b93f84897a
commit
5c781db216
6 changed files with 210 additions and 358 deletions
|
|
@ -23,13 +23,10 @@ struct _WpSiAudioEndpoint
|
|||
WpDirection direction;
|
||||
gchar role[32];
|
||||
guint priority;
|
||||
WpSessionItem *target;
|
||||
WpSession *session;
|
||||
|
||||
/* activation */
|
||||
WpNode *node;
|
||||
WpObjectManager *links_om;
|
||||
WpSessionItem *target_link;
|
||||
|
||||
/* export */
|
||||
WpImplEndpoint *impl_endpoint;
|
||||
|
|
@ -65,7 +62,6 @@ si_audio_endpoint_reset (WpSessionItem * item)
|
|||
self->direction = WP_DIRECTION_INPUT;
|
||||
self->role[0] = '\0';
|
||||
self->priority = 0;
|
||||
g_clear_object (&self->target);
|
||||
g_clear_object (&self->session);
|
||||
|
||||
WP_SESSION_ITEM_CLASS (si_audio_endpoint_parent_class)->reset (item);
|
||||
|
|
@ -76,7 +72,6 @@ si_audio_endpoint_configure (WpSessionItem * item, WpProperties *p)
|
|||
{
|
||||
WpSiAudioEndpoint *self = WP_SI_AUDIO_ENDPOINT (item);
|
||||
g_autoptr (WpProperties) si_props = wp_properties_ensure_unique_owner (p);
|
||||
WpSessionItem *target = NULL;
|
||||
WpSession *session = NULL;
|
||||
const gchar *str;
|
||||
|
||||
|
|
@ -112,16 +107,6 @@ si_audio_endpoint_configure (WpSessionItem * item, WpProperties *p)
|
|||
if (!str)
|
||||
wp_properties_setf (si_props, "priority", "%u", self->priority);
|
||||
|
||||
/* target is optional (endpoint won't do anything if not set) */
|
||||
str = wp_properties_get (si_props, "target");
|
||||
if (str && (sscanf(str, "%p", &target) != 1 || !WP_IS_SI_PORT_INFO (target)))
|
||||
return FALSE;
|
||||
if (target) {
|
||||
wp_properties_setf (si_props, "target", "%p", target);
|
||||
wp_properties_setf (si_props, "target.id", "%u",
|
||||
wp_session_item_get_id (target));
|
||||
}
|
||||
|
||||
/* session is optional (only needed if we want to export) */
|
||||
str = wp_properties_get (si_props, "session");
|
||||
if (str && (sscanf(str, "%p", &session) != 1 || !WP_IS_SESSION (session)))
|
||||
|
|
@ -129,8 +114,6 @@ si_audio_endpoint_configure (WpSessionItem * item, WpProperties *p)
|
|||
if (!str)
|
||||
wp_properties_setf (si_props, "session", "%p", session);
|
||||
|
||||
if (target)
|
||||
self->target = g_object_ref (target);
|
||||
if (session)
|
||||
self->session = g_object_ref (session);
|
||||
|
||||
|
|
@ -163,8 +146,6 @@ si_audio_endpoint_disable_active (WpSessionItem *si)
|
|||
if (self->node)
|
||||
wp_object_deactivate (WP_OBJECT (self->node), WP_OBJECT_FEATURES_ALL);
|
||||
g_clear_object (&self->node);
|
||||
g_clear_object (&self->links_om);
|
||||
g_clear_object (&self->target_link);
|
||||
wp_object_update_features (WP_OBJECT (self), 0,
|
||||
WP_SESSION_ITEM_FEATURE_ACTIVE);
|
||||
}
|
||||
|
|
@ -179,110 +160,6 @@ si_audio_endpoint_disable_exported (WpSessionItem *si)
|
|||
WP_SESSION_ITEM_FEATURE_EXPORTED);
|
||||
}
|
||||
|
||||
static void
|
||||
on_target_link_activated (WpSessionItem * item, GAsyncResult * res,
|
||||
WpSiAudioEndpoint * self)
|
||||
{
|
||||
g_autoptr (GError) error = NULL;
|
||||
if (!wp_object_activate_finish (WP_OBJECT (item), res, &error))
|
||||
wp_warning_object (item, "failed to activate target link: %s",
|
||||
error->message);
|
||||
}
|
||||
|
||||
static void
|
||||
link_to_target (WpSiAudioEndpoint * self)
|
||||
{
|
||||
g_autoptr (WpCore) core = NULL;
|
||||
WpProperties *props = NULL;
|
||||
g_autoptr (WpSessionItem) link = NULL;
|
||||
|
||||
g_return_if_fail (self->target);
|
||||
core = wp_object_get_core (WP_OBJECT (self->node));
|
||||
|
||||
link = wp_session_item_make (core, "si-standard-link");
|
||||
if (G_UNLIKELY (!link)) {
|
||||
wp_warning_object (self, "could not create link; is the module loaded?");
|
||||
return;
|
||||
}
|
||||
|
||||
props = wp_properties_new_empty ();
|
||||
if (self->direction == WP_DIRECTION_INPUT) {
|
||||
/* Playback */
|
||||
wp_properties_setf (props, "out.item", "%p", self);
|
||||
wp_properties_setf (props, "in.item", "%p", self->target);
|
||||
wp_properties_set (props, "out.item.port.context", "reverse");
|
||||
} else {
|
||||
/* Capture */
|
||||
wp_properties_setf (props, "out.item", "%p", self->target);
|
||||
wp_properties_setf (props, "in.item", "%p", self);
|
||||
wp_properties_set (props, "in.item.port.context", "reverse");
|
||||
}
|
||||
|
||||
/* always create passive links; that means that they won't hold the graph
|
||||
running if they are the only links left around */
|
||||
wp_properties_setf (props, "passive", "%u", TRUE);
|
||||
|
||||
wp_session_item_configure (link, props);
|
||||
wp_object_activate (WP_OBJECT (link), WP_SESSION_ITEM_FEATURE_ACTIVE, NULL,
|
||||
(GAsyncReadyCallback) on_target_link_activated, self);
|
||||
self->target_link = g_steal_pointer (&link);
|
||||
}
|
||||
|
||||
static void
|
||||
on_links_changed (WpObjectManager * om, WpSiAudioEndpoint * self)
|
||||
{
|
||||
if (wp_object_manager_get_n_objects (om) == 0)
|
||||
g_clear_object (&self->target_link);
|
||||
else if (!self->target_link && self->target)
|
||||
link_to_target (self);
|
||||
}
|
||||
|
||||
static void
|
||||
si_audio_endpoint_setup_links_om (WpSiAudioEndpoint *self,
|
||||
WpTransition *transition)
|
||||
{
|
||||
g_autoptr (WpCore) core = wp_object_get_core (WP_OBJECT (self));
|
||||
g_auto (GVariantBuilder) b = G_VARIANT_BUILDER_INIT (G_VARIANT_TYPE_TUPLE);
|
||||
g_autoptr (WpIterator) it = NULL;
|
||||
g_auto (GValue) val = G_VALUE_INIT;
|
||||
GVariant *ports_v = NULL;
|
||||
|
||||
/* get a list of our external ports */
|
||||
for (it = wp_node_new_ports_iterator (self->node);
|
||||
wp_iterator_next (it, &val);
|
||||
g_value_unset (&val)) {
|
||||
WpPort *port = g_value_get_object (&val);
|
||||
if (wp_port_get_direction (port) != self->direction)
|
||||
continue;
|
||||
g_variant_builder_add (&b, "u", wp_proxy_get_bound_id (WP_PROXY (port)));
|
||||
}
|
||||
ports_v = g_variant_builder_end (&b);
|
||||
|
||||
/* create the links object manager */
|
||||
self->links_om = wp_object_manager_new ();
|
||||
wp_object_manager_request_object_features (self->links_om,
|
||||
WP_TYPE_LINK, WP_PROXY_FEATURE_BOUND);
|
||||
|
||||
/* interested in links that have one of our external ports */
|
||||
wp_object_manager_add_interest_full (self->links_om, ({
|
||||
WpObjectInterest *interest = wp_object_interest_new_type (WP_TYPE_LINK);
|
||||
wp_object_interest_add_constraint (interest,
|
||||
WP_CONSTRAINT_TYPE_PW_GLOBAL_PROPERTY,
|
||||
self->direction == WP_DIRECTION_INPUT ?
|
||||
PW_KEY_LINK_INPUT_PORT : PW_KEY_LINK_OUTPUT_PORT,
|
||||
WP_CONSTRAINT_VERB_IN_LIST,
|
||||
ports_v);
|
||||
interest;
|
||||
}));
|
||||
|
||||
g_signal_connect_object (self->links_om, "objects-changed",
|
||||
G_CALLBACK (on_links_changed), self, 0);
|
||||
wp_core_install_object_manager (core, self->links_om);
|
||||
|
||||
wp_object_update_features (WP_OBJECT (self),
|
||||
WP_SESSION_ITEM_FEATURE_ACTIVE, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
on_node_activate_done (WpObject * node, GAsyncResult * res,
|
||||
WpTransition * transition)
|
||||
|
|
@ -296,7 +173,8 @@ on_node_activate_done (WpObject * node, GAsyncResult * res,
|
|||
return;
|
||||
}
|
||||
|
||||
si_audio_endpoint_setup_links_om (self, transition);
|
||||
wp_object_update_features (WP_OBJECT (self),
|
||||
WP_SESSION_ITEM_FEATURE_ACTIVE, 0);
|
||||
}
|
||||
|
||||
static WpSpaPod *
|
||||
|
|
|
|||
|
|
@ -57,6 +57,9 @@ function default_policy.enable()
|
|||
-- Link nodes to each other to make media flow in the graph
|
||||
load_script("policy-node.lua", default_policy.policy)
|
||||
|
||||
-- Link endpoints with other items to make media flow in the graph
|
||||
-- Link client nodes with endpoints to make media flow in the graph
|
||||
load_script("policy-endpoint.lua", default_policy.policy)
|
||||
|
||||
-- Link endpoints with device nodes to make media flow in the graph
|
||||
load_script("policy-endpoint-device.lua", default_policy.policy)
|
||||
end
|
||||
|
|
|
|||
195
src/scripts/policy-endpoint-device.lua
Normal file
195
src/scripts/policy-endpoint-device.lua
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
-- WirePlumber
|
||||
--
|
||||
-- Copyright © 2021 Collabora Ltd.
|
||||
-- @author Julian Bouzas <julian.bouzas@collabora.com>
|
||||
--
|
||||
-- SPDX-License-Identifier: MIT
|
||||
|
||||
target_class_assoc = {
|
||||
["Audio/Source"] = "Audio/Source",
|
||||
["Audio/Sink"] = "Audio/Sink",
|
||||
["Video/Source"] = "Video/Source",
|
||||
}
|
||||
|
||||
-- Receive script arguments from config.lua
|
||||
local config = ...
|
||||
|
||||
-- ensure config.move and config.follow are not nil
|
||||
config.move = config.move or false
|
||||
config.follow = config.follow or false
|
||||
|
||||
function getSessionItemById (si_id, om)
|
||||
return om:lookup {
|
||||
Constraint { "id", "=", tonumber(si_id), type = "gobject" }
|
||||
}
|
||||
end
|
||||
|
||||
function findTargetByDefaultNode (target_media_class, om)
|
||||
local def_id = default_nodes:call("get-default-node", target_media_class)
|
||||
if def_id ~= Id.INVALID then
|
||||
for si_target in om:iterate() do
|
||||
local target_node = si_target:get_associated_proxy ("node")
|
||||
if target_node["bound-id"] == def_id then
|
||||
return si_target
|
||||
end
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function findTargetByFirstAvailable (target_media_class, om)
|
||||
for si_target in om:iterate() do
|
||||
local target_node = si_target:get_associated_proxy ("node")
|
||||
if target_node.properties["media.class"] == target_media_class then
|
||||
return si_target
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function findUndefinedTarget (target_media_class, om)
|
||||
local si_target = findTargetByDefaultNode (target_media_class, om)
|
||||
if not si_target then
|
||||
si_target = findTargetByFirstAvailable (target_media_class, om)
|
||||
end
|
||||
return si_target
|
||||
end
|
||||
|
||||
function createLink (si_ep, si_target)
|
||||
local target_node = si_target:get_associated_proxy ("node")
|
||||
local target_media_class = target_node.properties["media.class"]
|
||||
local out_item = nil
|
||||
local out_context = nil
|
||||
local in_item = nil
|
||||
local in_context = nil
|
||||
|
||||
if string.find (target_media_class, "Input") or
|
||||
string.find (target_media_class, "Sink") then
|
||||
-- capture
|
||||
in_item = si_target
|
||||
out_item = si_ep
|
||||
out_context = "reverse"
|
||||
else
|
||||
-- playback
|
||||
in_item = si_ep
|
||||
out_item = si_target
|
||||
in_context = "reverse"
|
||||
end
|
||||
|
||||
Log.info (string.format("link %s <-> %s",
|
||||
si_ep.properties["name"],
|
||||
target_node.properties["node.name"]))
|
||||
|
||||
-- create and configure link
|
||||
local si_link = SessionItem ( "si-standard-link" )
|
||||
if not si_link:configure {
|
||||
["out.item"] = out_item,
|
||||
["in.item"] = in_item,
|
||||
["out.item.port.context"] = out_context,
|
||||
["in.item.port.context"] = in_context,
|
||||
["manage.lifetime"] = false,
|
||||
["passive"] = true,
|
||||
["is.policy.endpoint.device.link"] = true,
|
||||
} then
|
||||
Log.warning (si_link, "failed to configure si-standard-link")
|
||||
return
|
||||
end
|
||||
|
||||
-- activate and register
|
||||
si_link:activate (Feature.SessionItem.ACTIVE, function (link)
|
||||
Log.info (link, "link activated")
|
||||
link:register ()
|
||||
end)
|
||||
end
|
||||
|
||||
function getSiLinkAndSiPeer (si_ep)
|
||||
for silink in silinks_om:iterate() do
|
||||
local out_id = tonumber(silink.properties["out.item.id"])
|
||||
local in_id = tonumber(silink.properties["in.item.id"])
|
||||
if out_id == si_ep.id then
|
||||
return silink, getSessionItemById (in_id, siportinfos_om)
|
||||
elseif in_id == si_ep.id then
|
||||
return silink, getSessionItemById (out_id, siportinfos_om)
|
||||
end
|
||||
end
|
||||
return nil, nil
|
||||
end
|
||||
|
||||
function handleSiEndpoint (si_ep)
|
||||
-- only handle endpoints that have a valid target media class
|
||||
local media_class = si_ep.properties["media.class"]
|
||||
local target_media_class = target_class_assoc[media_class]
|
||||
if not target_media_class then
|
||||
return
|
||||
end
|
||||
|
||||
Log.info (si_ep, "handling endpoint " .. si_ep.properties["name"])
|
||||
|
||||
-- find proper target item
|
||||
local si_target = findUndefinedTarget (target_media_class, siportinfos_om)
|
||||
if not si_target then
|
||||
Log.info (si_ep, "target item not found")
|
||||
return
|
||||
end
|
||||
|
||||
-- Check if item is linked to proper target endpoint, otherwise re-link
|
||||
local si_link, si_peer = getSiLinkAndSiPeer (si_ep)
|
||||
if si_link then
|
||||
if si_peer and si_peer.id == si_target.id then
|
||||
Log.info (si_ep, "already linked to proper target")
|
||||
return
|
||||
end
|
||||
|
||||
si_link:remove ()
|
||||
Log.info (si_ep, "moving to new target")
|
||||
end
|
||||
|
||||
-- create new link
|
||||
createLink (si_ep, si_target)
|
||||
end
|
||||
|
||||
function reevaluateLinks ()
|
||||
-- check endpoints and register new links
|
||||
for si_ep in siendpoints_om:iterate() do
|
||||
handleSiEndpoint (si_ep)
|
||||
end
|
||||
|
||||
-- check link session items and unregister them if not used
|
||||
for silink in silinks_om:iterate() do
|
||||
local out_id = tonumber (silink.properties["out.item.id"])
|
||||
local in_id = tonumber (silink.properties["in.item.id"])
|
||||
if (getSessionItemById (out_id, siendpoints_om) and not getSessionItemById (in_id, siportinfos_om)) or
|
||||
(getSessionItemById (in_id, siendpoints_om) and not getSessionItemById (out_id, siportinfos_om)) then
|
||||
silink:remove ()
|
||||
Log.info (silink, "link removed")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
default_nodes = Plugin("default-nodes-api")
|
||||
siendpoints_om = ObjectManager { Interest { type = "SiEndpoint" }}
|
||||
siportinfos_om = ObjectManager { Interest { type = "SiPortInfo",
|
||||
-- only handle si-audio-adapter and si-node
|
||||
Constraint {
|
||||
"si.factory.name", "c", "si-audio-adapter", "si-node", type = "pw-global" },
|
||||
}
|
||||
}
|
||||
silinks_om = ObjectManager { Interest { type = "SiLink",
|
||||
-- only handle links created by this policy
|
||||
Constraint { "is.policy.endpoint.device.link", "=", true, type = "pw-global" },
|
||||
} }
|
||||
|
||||
-- listen for default node changes if config.follow is enabled
|
||||
if config.follow then
|
||||
default_nodes:connect("changed", function (p)
|
||||
reevaluateLinks ()
|
||||
end)
|
||||
end
|
||||
|
||||
siportinfos_om:connect("objects-changed", function (om)
|
||||
reevaluateLinks ()
|
||||
end)
|
||||
|
||||
siendpoints_om:activate()
|
||||
siportinfos_om:activate()
|
||||
silinks_om:activate()
|
||||
|
|
@ -62,37 +62,6 @@ function findDefinedTarget (node, om)
|
|||
return si_target
|
||||
end
|
||||
|
||||
function findTargetByDefaultNode (target_media_class, om)
|
||||
local def_id = default_nodes:call("get-default-node", target_media_class)
|
||||
if def_id ~= Id.INVALID then
|
||||
for si_target in om:iterate() do
|
||||
local target_node = si_target:get_associated_proxy ("node")
|
||||
if target_node["bound-id"] == def_id then
|
||||
return si_target
|
||||
end
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function findTargetByFirstAvailable (target_media_class, om)
|
||||
for si_target in om:iterate() do
|
||||
local target_node = si_target:get_associated_proxy ("node")
|
||||
if target_node.properties["media.class"] == target_media_class then
|
||||
return si_target
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
function findUndefinedTarget (target_media_class, om)
|
||||
local si_target = findTargetByDefaultNode (target_media_class, om)
|
||||
if not si_target then
|
||||
si_target = findTargetByFirstAvailable (target_media_class, om)
|
||||
end
|
||||
return si_target
|
||||
end
|
||||
|
||||
function findTargetEndpoint (node, target_media_class)
|
||||
local media_role = node.properties["media.role"]
|
||||
local highest_priority = -1
|
||||
|
|
@ -131,63 +100,6 @@ function findTargetEndpoint (node, target_media_class)
|
|||
return target
|
||||
end
|
||||
|
||||
function reconfigureEndpoint (si_ep)
|
||||
Log.info (si_ep, "handling endpoint " .. si_ep.properties["name"])
|
||||
|
||||
-- get media class
|
||||
local ep_media_class = si_ep.properties["media.class"]
|
||||
|
||||
-- find a target with matching media class
|
||||
local si_target = findUndefinedTarget (ep_media_class, siportinfos_om)
|
||||
if not si_target then
|
||||
Log.info (si_ep, "Could not find target for endpoint")
|
||||
return falsed
|
||||
end
|
||||
|
||||
-- skip already configured endpoints matching target
|
||||
local target_id_str = si_ep.properties["target.id"]
|
||||
if target_id_str and tonumber(target_id_str) == si_target.id then
|
||||
Log.info (si_ep, "endpoint already configured with correct target")
|
||||
return false
|
||||
end
|
||||
|
||||
-- find the session
|
||||
local session_name = si_ep.properties["session.name"]
|
||||
local session = sessions_om:lookup {
|
||||
Constraint { "session.name", "=", session_name }
|
||||
}
|
||||
if not session then
|
||||
Log.warning(si_ep, "could not find session for endpoint");
|
||||
return false
|
||||
end
|
||||
|
||||
-- unlink all streams
|
||||
for silink in silinks_om:iterate() do
|
||||
local out_id = tonumber (silink.properties["out.item.id"])
|
||||
local in_id = tonumber (silink.properties["in.item.id"])
|
||||
if si_ep.id == out_id or si_ep.id == in_id then
|
||||
silink:remove ()
|
||||
Log.info (silink, "link removed")
|
||||
end
|
||||
end
|
||||
|
||||
-- add target and session properties
|
||||
local ep_props = si_ep.properties
|
||||
ep_props["target"] = si_target
|
||||
ep_props["session"] = session
|
||||
|
||||
-- reconfigure endpoint
|
||||
si_ep:reset ()
|
||||
si_ep:configure (ep_props)
|
||||
si_ep:activate (Features.ALL, function (item)
|
||||
Log.info (item, "configured endpoint '" .. ep_props.name ..
|
||||
"' for session '" .. session_name .. "' and target " .. si_target.id)
|
||||
reevaluateEndpointLinks ()
|
||||
end)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function createLink (si, si_target_ep)
|
||||
local node = si:get_associated_proxy ("node")
|
||||
local media_class = node.properties["media.class"]
|
||||
|
|
@ -226,7 +138,7 @@ function createLink (si, si_target_ep)
|
|||
["out.item.port.context"] = out_context,
|
||||
["in.item.port.context"] = in_context,
|
||||
["manage.lifetime"] = false,
|
||||
["is.policy.endpoint.link"] = true,
|
||||
["is.policy.endpoint.client.link"] = true,
|
||||
} then
|
||||
Log.warning (si_link, "failed to configure si-standard-link")
|
||||
return
|
||||
|
|
@ -299,18 +211,7 @@ function handleSiPortInfo (si)
|
|||
createLink (si, si_target_ep)
|
||||
end
|
||||
|
||||
function reevaluateEndpoints ()
|
||||
local res = false
|
||||
-- reconfigure endpoints
|
||||
for si_ep in siendpoints_om:iterate() do
|
||||
if reconfigureEndpoint (si_ep) then
|
||||
res = true
|
||||
end
|
||||
end
|
||||
return res
|
||||
end
|
||||
|
||||
function reevaluateEndpointLinks ()
|
||||
function reevaluateLinks ()
|
||||
-- check port info session items and register new links
|
||||
for si in siportinfos_om:iterate() do
|
||||
handleSiPortInfo (si)
|
||||
|
|
@ -328,15 +229,8 @@ function reevaluateEndpointLinks ()
|
|||
end
|
||||
end
|
||||
|
||||
function reevaluateItems ()
|
||||
if not reevaluateEndpoints () then
|
||||
reevaluateEndpointLinks ()
|
||||
end
|
||||
end
|
||||
|
||||
default_nodes = Plugin("default-nodes-api")
|
||||
metadatas_om = ObjectManager { Interest { type = "metadata" } }
|
||||
sessions_om = ObjectManager { Interest { type = "session" } }
|
||||
siendpoints_om = ObjectManager { Interest { type = "SiEndpoint" }}
|
||||
siportinfos_om = ObjectManager { Interest { type = "SiPortInfo",
|
||||
-- only handle si-audio-adapter and si-node
|
||||
|
|
@ -346,13 +240,13 @@ siportinfos_om = ObjectManager { Interest { type = "SiPortInfo",
|
|||
}
|
||||
silinks_om = ObjectManager { Interest { type = "SiLink",
|
||||
-- only handle links created by this policy
|
||||
Constraint { "is.policy.endpoint.link", "=", true, type = "pw-global" },
|
||||
Constraint { "is.policy.endpoint.client.link", "=", true, type = "pw-global" },
|
||||
} }
|
||||
|
||||
-- listen for default node changes if config.follow is enabled
|
||||
if config.follow then
|
||||
default_nodes:connect("changed", function (p)
|
||||
reevaluateItems ()
|
||||
reevaluateLinks ()
|
||||
end)
|
||||
end
|
||||
|
||||
|
|
@ -361,18 +255,17 @@ if config.move then
|
|||
metadatas_om:connect("object-added", function (om, metadata)
|
||||
metadata:connect("changed", function (m, subject, key, t, value)
|
||||
if key == "target.node" then
|
||||
reevaluateItems ()
|
||||
reevaluateLinks ()
|
||||
end
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
siportinfos_om:connect("objects-changed", function (om)
|
||||
reevaluateItems ()
|
||||
reevaluateLinks ()
|
||||
end)
|
||||
|
||||
metadatas_om:activate()
|
||||
sessions_om:activate()
|
||||
siendpoints_om:activate()
|
||||
siportinfos_om:activate()
|
||||
silinks_om:activate()
|
||||
|
|
|
|||
|
|
@ -26,19 +26,11 @@ test_si_audio_endpoint_setup (TestFixture * f, gconstpointer user_data)
|
|||
"fake*", "test/libspa-test"), ==, 0);
|
||||
g_assert_cmpint (pw_context_add_spa_lib (f->base.server.context,
|
||||
"audiotestsrc", "audiotestsrc/libspa-audiotestsrc"), ==, 0);
|
||||
g_assert_cmpint (pw_context_add_spa_lib (f->base.server.context,
|
||||
"audio.convert", "audioconvert/libspa-audioconvert"), ==, 0);
|
||||
g_assert_nonnull (pw_context_load_module (f->base.server.context,
|
||||
"libpipewire-module-spa-node-factory", NULL, NULL));
|
||||
g_assert_nonnull (pw_context_load_module (f->base.server.context,
|
||||
"libpipewire-module-adapter", NULL, NULL));
|
||||
}
|
||||
{
|
||||
g_autoptr (GError) error = NULL;
|
||||
wp_core_load_component (f->base.core,
|
||||
"libwireplumber-module-si-audio-adapter", "module", NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
}
|
||||
{
|
||||
g_autoptr (GError) error = NULL;
|
||||
wp_core_load_component (f->base.core,
|
||||
|
|
@ -57,46 +49,15 @@ static void
|
|||
test_si_audio_endpoint_configure_activate (TestFixture * f,
|
||||
gconstpointer user_data)
|
||||
{
|
||||
g_autoptr (WpNode) target_node = NULL;
|
||||
g_autoptr (WpSessionItem) target = NULL;
|
||||
g_autoptr (WpSessionItem) endpoint = NULL;
|
||||
|
||||
/* create target node */
|
||||
|
||||
target_node = wp_node_new_from_factory (f->base.core,
|
||||
"adapter",
|
||||
wp_properties_new (
|
||||
"factory.name", "audiotestsrc",
|
||||
"node.name", "audiotestsrc.adapter",
|
||||
NULL));
|
||||
g_assert_nonnull (target_node);
|
||||
wp_object_activate (WP_OBJECT (target_node),
|
||||
WP_PIPEWIRE_OBJECT_FEATURES_MINIMAL, NULL,
|
||||
(GAsyncReadyCallback) test_object_activate_finish_cb, f);
|
||||
g_main_loop_run (f->base.loop);
|
||||
|
||||
/* create target */
|
||||
|
||||
target = wp_session_item_make (f->base.core, "si-audio-adapter");
|
||||
g_assert_nonnull (target);
|
||||
g_assert_true (WP_IS_SI_PORT_INFO (target));
|
||||
|
||||
/* configure target */
|
||||
|
||||
{
|
||||
WpProperties *props = wp_properties_new_empty ();
|
||||
wp_properties_setf (props, "node", "%p", target_node);
|
||||
g_assert_true (wp_session_item_configure (target, props));
|
||||
g_assert_true (wp_session_item_is_configured (target));
|
||||
}
|
||||
|
||||
/* create endpoint */
|
||||
|
||||
endpoint = wp_session_item_make (f->base.core, "si-audio-endpoint");
|
||||
g_assert_nonnull (endpoint);
|
||||
g_assert_true (WP_IS_SI_ENDPOINT (endpoint));
|
||||
|
||||
/* configure endpoint without target */
|
||||
/* configure endpoint */
|
||||
|
||||
{
|
||||
WpProperties *props = wp_properties_new_empty ();
|
||||
|
|
@ -106,17 +67,6 @@ test_si_audio_endpoint_configure_activate (TestFixture * f,
|
|||
g_assert_true (wp_session_item_is_configured (endpoint));
|
||||
}
|
||||
|
||||
/* re-configure endpoint with target */
|
||||
|
||||
{
|
||||
WpProperties *props = wp_properties_new_empty ();
|
||||
wp_properties_set (props, "name", "endpoint");
|
||||
wp_properties_set (props, "media.class", "Audio/Source");
|
||||
wp_properties_setf (props, "target", "%p", target);
|
||||
g_assert_true (wp_session_item_configure (endpoint, props));
|
||||
g_assert_true (wp_session_item_is_configured (endpoint));
|
||||
}
|
||||
|
||||
{
|
||||
const gchar *str = NULL;
|
||||
g_autoptr (WpProperties) props = wp_session_item_get_properties (endpoint);
|
||||
|
|
@ -148,8 +98,6 @@ test_si_audio_endpoint_configure_activate (TestFixture * f,
|
|||
static void
|
||||
test_si_audio_endpoint_export (TestFixture * f, gconstpointer user_data)
|
||||
{
|
||||
g_autoptr (WpNode) target_node = NULL;
|
||||
g_autoptr (WpSessionItem) target = NULL;
|
||||
g_autoptr (WpSessionItem) endpoint = NULL;
|
||||
g_autoptr (WpSession) session = NULL;
|
||||
g_autoptr (WpObjectManager) clients_om = NULL;
|
||||
|
|
@ -177,35 +125,6 @@ test_si_audio_endpoint_export (TestFixture * f, gconstpointer user_data)
|
|||
(GAsyncReadyCallback) test_object_activate_finish_cb, f);
|
||||
g_main_loop_run (f->base.loop);
|
||||
|
||||
/* create target node */
|
||||
|
||||
target_node = wp_node_new_from_factory (f->base.core,
|
||||
"adapter",
|
||||
wp_properties_new (
|
||||
"factory.name", "audiotestsrc",
|
||||
"node.name", "audiotestsrc.adapter",
|
||||
NULL));
|
||||
g_assert_nonnull (target_node);
|
||||
wp_object_activate (WP_OBJECT (target_node),
|
||||
WP_PIPEWIRE_OBJECT_FEATURES_MINIMAL, NULL,
|
||||
(GAsyncReadyCallback) test_object_activate_finish_cb, f);
|
||||
g_main_loop_run (f->base.loop);
|
||||
|
||||
/* create target */
|
||||
|
||||
target = wp_session_item_make (f->base.core, "si-audio-adapter");
|
||||
g_assert_nonnull (target);
|
||||
g_assert_true (WP_IS_SI_PORT_INFO (target));
|
||||
|
||||
/* configure target */
|
||||
|
||||
{
|
||||
WpProperties *props = wp_properties_new_empty ();
|
||||
wp_properties_setf (props, "node", "%p", target_node);
|
||||
g_assert_true (wp_session_item_configure (target, props));
|
||||
g_assert_true (wp_session_item_is_configured (target));
|
||||
}
|
||||
|
||||
/* create endpoint */
|
||||
|
||||
endpoint = wp_session_item_make (f->base.core, "si-audio-endpoint");
|
||||
|
|
@ -216,7 +135,6 @@ test_si_audio_endpoint_export (TestFixture * f, gconstpointer user_data)
|
|||
WpProperties *props = wp_properties_new_empty ();
|
||||
wp_properties_set (props, "name", "endpoint");
|
||||
wp_properties_set (props, "media.class", "Audio/Source");
|
||||
wp_properties_setf (props, "target", "%p", target);
|
||||
wp_properties_setf (props, "session", "%p", session);
|
||||
g_assert_true (wp_session_item_configure (endpoint, props));
|
||||
g_assert_true (wp_session_item_is_configured (endpoint));
|
||||
|
|
|
|||
|
|
@ -21,38 +21,8 @@ typedef struct {
|
|||
static WpSessionItem *
|
||||
load_endpoint (TestFixture * f, const gchar * factory, const gchar * media_class)
|
||||
{
|
||||
g_autoptr (WpNode) target_node = NULL;
|
||||
g_autoptr (WpSessionItem) target = NULL;
|
||||
g_autoptr (WpSessionItem) endpoint = NULL;
|
||||
|
||||
/* create target node */
|
||||
|
||||
target_node = wp_node_new_from_factory (f->base.core,
|
||||
"adapter",
|
||||
wp_properties_new (
|
||||
"factory.name", factory,
|
||||
"node.name", factory,
|
||||
NULL));
|
||||
g_assert_nonnull (target_node);
|
||||
|
||||
/* create target */
|
||||
|
||||
target = wp_session_item_make (f->base.core, "si-audio-adapter");
|
||||
g_assert_nonnull (target);
|
||||
g_assert_true (WP_IS_SI_PORT_INFO (target));
|
||||
|
||||
/* configure target */
|
||||
|
||||
{
|
||||
WpProperties *props = wp_properties_new_empty ();
|
||||
wp_properties_setf (props, "node", "%p", target_node);
|
||||
wp_properties_set (props, "name", factory);
|
||||
wp_properties_set (props, "media.class", media_class);
|
||||
wp_properties_set (props, "role", "role");
|
||||
g_assert_true (wp_session_item_configure (target, props));
|
||||
g_assert_true (wp_session_item_is_configured (target));
|
||||
}
|
||||
|
||||
/* create endpoint */
|
||||
|
||||
endpoint = wp_session_item_make (f->base.core, "si-audio-endpoint");
|
||||
|
|
@ -64,7 +34,6 @@ load_endpoint (TestFixture * f, const gchar * factory, const gchar * media_class
|
|||
WpProperties *props = wp_properties_new_empty ();
|
||||
wp_properties_set (props, "name", factory);
|
||||
wp_properties_set (props, "media.class", media_class);
|
||||
wp_properties_setf (props, "target", "%p", target);
|
||||
wp_properties_setf (props, "session", "%p", f->session);
|
||||
g_assert_true (wp_session_item_configure (endpoint, props));
|
||||
g_assert_true (wp_session_item_is_configured (endpoint));
|
||||
|
|
@ -103,10 +72,6 @@ test_si_standard_link_setup (TestFixture * f, gconstpointer user_data)
|
|||
}
|
||||
{
|
||||
g_autoptr (GError) error = NULL;
|
||||
wp_core_load_component (f->base.core,
|
||||
"libwireplumber-module-si-audio-adapter", "module", NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
|
||||
wp_core_load_component (f->base.core,
|
||||
"libwireplumber-module-si-audio-endpoint", "module", NULL, &error);
|
||||
g_assert_no_error (error);
|
||||
|
|
@ -286,7 +251,7 @@ test_si_standard_link_main (TestFixture * f, gconstpointer user_data)
|
|||
g_assert_nonnull (in_node = wp_object_manager_lookup (om, WP_TYPE_NODE,
|
||||
WP_CONSTRAINT_TYPE_PW_PROPERTY, "node.name", "=s", "control.fakesink",
|
||||
NULL));
|
||||
g_assert_cmpuint (wp_object_manager_get_n_objects (om), ==, 13);
|
||||
g_assert_cmpuint (wp_object_manager_get_n_objects (om), ==, 12);
|
||||
|
||||
it = wp_object_manager_new_filtered_iterator (om, WP_TYPE_LINK, NULL);
|
||||
for (; wp_iterator_next (it, &val); g_value_unset (&val)) {
|
||||
|
|
@ -354,7 +319,7 @@ test_si_standard_link_main (TestFixture * f, gconstpointer user_data)
|
|||
WP_CONSTRAINT_TYPE_PW_PROPERTY, "port.direction", "=s", "in",
|
||||
NULL));
|
||||
g_assert_null (link = wp_object_manager_lookup (om, WP_TYPE_LINK, NULL));
|
||||
g_assert_cmpuint (wp_object_manager_get_n_objects (om), ==, 11);
|
||||
g_assert_cmpuint (wp_object_manager_get_n_objects (om), ==, 10);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue