mirror of
https://gitlab.freedesktop.org/pipewire/wireplumber.git
synced 2026-05-05 06:38:01 +02:00
session-item: handle destroyed endpoint links
We can now call wp_proxy_request_destroy() on endpoint links and the WpImplEndpointLink together with the session item that created it will be cleaned up
This commit is contained in:
parent
ded2e34eb6
commit
9db4a54591
3 changed files with 169 additions and 0 deletions
|
|
@ -682,6 +682,19 @@ on_stream_flags_changed (WpSessionItem * stream, WpSiFlags flags,
|
|||
{
|
||||
/* stream was deactivated; destroy the associated link */
|
||||
if (!(flags & WP_SI_FLAG_ACTIVE)) {
|
||||
wp_trace_object (link, "destroying because stream " WP_OBJECT_FORMAT
|
||||
" was deactivated", WP_OBJECT_ARGS (stream));
|
||||
wp_session_item_reset (link);
|
||||
g_object_unref (link);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_link_flags_changed (WpSessionItem * link, WpSiFlags flags, gpointer data)
|
||||
{
|
||||
const guint mask = (WP_SI_FLAG_EXPORTED | WP_SI_FLAG_EXPORT_ERROR);
|
||||
if ((flags & mask) == mask) {
|
||||
wp_trace_object (link, "destroying because impl proxy was destroyed");
|
||||
wp_session_item_reset (link);
|
||||
g_object_unref (link);
|
||||
}
|
||||
|
|
@ -855,6 +868,8 @@ impl_create_link (void *object, const struct spa_dict *props)
|
|||
G_CALLBACK (on_stream_flags_changed), link, 0);
|
||||
g_signal_connect_object (peer_si_stream, "flags-changed",
|
||||
G_CALLBACK (on_stream_flags_changed), link, 0);
|
||||
g_signal_connect (link, "flags-changed",
|
||||
G_CALLBACK (on_link_flags_changed), NULL);
|
||||
|
||||
wp_session_item_export (link, session,
|
||||
(GAsyncReadyCallback) on_si_link_exported, self);
|
||||
|
|
|
|||
|
|
@ -190,6 +190,7 @@ enum {
|
|||
EXPORT_STEP_ENDPOINT = WP_TRANSITION_STEP_CUSTOM_START,
|
||||
EXPORT_STEP_STREAMS,
|
||||
EXPORT_STEP_LINK,
|
||||
EXPORT_STEP_CONNECT_DESTROYED,
|
||||
};
|
||||
|
||||
static guint
|
||||
|
|
@ -229,6 +230,9 @@ wp_session_item_default_export_get_next_step (WpSessionItem * self,
|
|||
|
||||
case EXPORT_STEP_LINK:
|
||||
g_return_val_if_fail (WP_IS_SI_LINK (self), WP_TRANSITION_STEP_ERROR);
|
||||
return EXPORT_STEP_CONNECT_DESTROYED;
|
||||
|
||||
case EXPORT_STEP_CONNECT_DESTROYED:
|
||||
return WP_TRANSITION_STEP_NONE;
|
||||
|
||||
default:
|
||||
|
|
@ -261,6 +265,36 @@ on_export_proxy_augmented (WpProxy * proxy, GAsyncResult * res, gpointer data)
|
|||
wp_transition_advance (transition);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_export_proxy_destroyed_deferred (WpSessionItem * self)
|
||||
{
|
||||
WpSessionItemPrivate *priv = wp_session_item_get_instance_private (self);
|
||||
|
||||
g_return_val_if_fail (priv->impl_proxy, G_SOURCE_REMOVE);
|
||||
g_return_val_if_fail (WP_SESSION_ITEM_GET_CLASS (self)->export_rollback,
|
||||
G_SOURCE_REMOVE);
|
||||
|
||||
wp_info_object (self, "destroying " WP_OBJECT_FORMAT
|
||||
" upon request by the server", WP_OBJECT_ARGS (priv->impl_proxy));
|
||||
|
||||
WP_SESSION_ITEM_GET_CLASS (self)->export_rollback (self);
|
||||
|
||||
priv->flags |= WP_SI_FLAG_EXPORT_ERROR;
|
||||
g_signal_emit (self, signals[SIGNAL_FLAGS_CHANGED], 0, priv->flags);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
static void
|
||||
on_export_proxy_destroyed (WpProxy * proxy, gpointer data)
|
||||
{
|
||||
WpSessionItem *self = WP_SESSION_ITEM (data);
|
||||
g_autoptr (WpCore) core = wp_proxy_get_core (proxy);
|
||||
|
||||
wp_core_idle_add_closure (core, NULL, g_cclosure_new_object (
|
||||
G_CALLBACK (on_export_proxy_destroyed_deferred), G_OBJECT (self)));
|
||||
}
|
||||
|
||||
static void
|
||||
wp_session_item_default_export_execute_step (WpSessionItem * self,
|
||||
WpTransition * transition, guint step)
|
||||
|
|
@ -311,6 +345,12 @@ wp_session_item_default_export_execute_step (WpSessionItem * self,
|
|||
transition);
|
||||
break;
|
||||
|
||||
case EXPORT_STEP_CONNECT_DESTROYED:
|
||||
g_signal_connect_object (priv->impl_proxy, "pw-proxy-destroyed",
|
||||
G_CALLBACK (on_export_proxy_destroyed), self, 0);
|
||||
wp_transition_advance (transition);
|
||||
break;
|
||||
|
||||
default:
|
||||
g_return_if_reached ();
|
||||
}
|
||||
|
|
@ -320,6 +360,8 @@ static void
|
|||
wp_session_item_default_export_rollback (WpSessionItem * self)
|
||||
{
|
||||
WpSessionItemPrivate *priv = wp_session_item_get_instance_private (self);
|
||||
if (priv->impl_proxy)
|
||||
g_signal_handlers_disconnect_by_data (priv->impl_proxy, self);
|
||||
g_clear_pointer (&priv->impl_streams, g_hash_table_unref);
|
||||
g_clear_object (&priv->impl_proxy);
|
||||
g_weak_ref_set (&priv->session, NULL);
|
||||
|
|
|
|||
|
|
@ -235,6 +235,7 @@ test_si_standard_link_main (TestFixture * f, gconstpointer user_data)
|
|||
g_assert_cmpuint (wp_endpoint_link_get_state (ep_link, &error), ==,
|
||||
WP_ENDPOINT_LINK_STATE_ACTIVE);
|
||||
g_assert_null (error);
|
||||
g_assert_cmpint (f->activation_state, ==, 2);
|
||||
}
|
||||
|
||||
/* verify the graph state */
|
||||
|
|
@ -290,6 +291,7 @@ test_si_standard_link_main (TestFixture * f, gconstpointer user_data)
|
|||
g_assert_cmpuint (wp_endpoint_link_get_state (ep_link, &error), ==,
|
||||
WP_ENDPOINT_LINK_STATE_INACTIVE);
|
||||
g_assert_null (error);
|
||||
g_assert_cmpint (f->activation_state, ==, 3);
|
||||
}
|
||||
|
||||
/* verify the graph state */
|
||||
|
|
@ -328,6 +330,110 @@ test_si_standard_link_main (TestFixture * f, gconstpointer user_data)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
on_link_destroyed (WpEndpointLink * link, TestFixture * f)
|
||||
{
|
||||
f->activation_state = 10;
|
||||
}
|
||||
|
||||
static void
|
||||
test_si_standard_link_destroy (TestFixture * f, gconstpointer user_data)
|
||||
{
|
||||
g_autoptr (WpSession) session_proxy = NULL;
|
||||
g_autoptr (WpEndpoint) src_ep = NULL;
|
||||
g_autoptr (WpEndpoint) sink_ep = NULL;
|
||||
g_autoptr (WpEndpointLink) ep_link = NULL;
|
||||
|
||||
/* find the "audio" session from the client */
|
||||
{
|
||||
g_autoptr (WpObjectManager) om = wp_object_manager_new ();
|
||||
wp_object_manager_add_interest_1 (om, WP_TYPE_SESSION, NULL);
|
||||
wp_object_manager_request_proxy_features (om, WP_TYPE_SESSION,
|
||||
WP_SESSION_FEATURES_STANDARD);
|
||||
g_signal_connect_swapped (om, "installed",
|
||||
G_CALLBACK (g_main_loop_quit), f->base.loop);
|
||||
wp_core_install_object_manager (f->base.client_core, om);
|
||||
g_main_loop_run (f->base.loop);
|
||||
|
||||
g_assert_nonnull (session_proxy =
|
||||
wp_object_manager_lookup (om, WP_TYPE_SESSION,
|
||||
WP_CONSTRAINT_TYPE_PW_PROPERTY, "session.name", "=s", "audio", NULL));
|
||||
g_assert_cmpint (wp_proxy_get_bound_id (WP_PROXY (session_proxy)), ==,
|
||||
wp_proxy_get_bound_id (WP_PROXY (f->session)));
|
||||
}
|
||||
|
||||
/* find the endpoints */
|
||||
|
||||
g_assert_nonnull (src_ep = wp_session_lookup_endpoint (session_proxy,
|
||||
WP_CONSTRAINT_TYPE_PW_PROPERTY, "endpoint.name", "=s", "audiotestsrc",
|
||||
NULL));
|
||||
g_assert_nonnull (sink_ep = wp_session_lookup_endpoint (session_proxy,
|
||||
WP_CONSTRAINT_TYPE_PW_PROPERTY, "endpoint.name", "=s", "fakesink",
|
||||
NULL));
|
||||
g_assert_cmpuint (wp_endpoint_get_n_streams (src_ep), ==, 1);
|
||||
g_assert_cmpuint (wp_endpoint_get_n_streams (sink_ep), ==, 1);
|
||||
|
||||
/* create the link */
|
||||
{
|
||||
g_autoptr (WpProperties) props = NULL;
|
||||
g_autofree gchar * id =
|
||||
g_strdup_printf ("%u", wp_proxy_get_bound_id (WP_PROXY (sink_ep)));
|
||||
|
||||
/* only the peer endpoint id is required,
|
||||
everything else will be discovered */
|
||||
props = wp_properties_new ("endpoint-link.input.endpoint", id, NULL);
|
||||
wp_endpoint_create_link (src_ep, props);
|
||||
}
|
||||
|
||||
g_signal_connect_swapped (session_proxy, "links-changed",
|
||||
G_CALLBACK (g_main_loop_quit), f->base.loop);
|
||||
g_main_loop_run (f->base.loop);
|
||||
|
||||
/* verify */
|
||||
|
||||
g_assert_cmpuint (wp_session_get_n_links (session_proxy), ==, 1);
|
||||
g_assert_nonnull (ep_link = wp_session_lookup_link (session_proxy, NULL));
|
||||
g_assert_cmpuint (wp_endpoint_link_get_state (ep_link, NULL), ==,
|
||||
WP_ENDPOINT_LINK_STATE_INACTIVE);
|
||||
|
||||
/* activate */
|
||||
|
||||
g_signal_connect (ep_link, "state-changed",
|
||||
G_CALLBACK (on_link_state_changed), f);
|
||||
wp_endpoint_link_request_state (ep_link, WP_ENDPOINT_LINK_STATE_ACTIVE);
|
||||
g_main_loop_run (f->base.loop);
|
||||
g_assert_cmpuint (wp_endpoint_link_get_state (ep_link, NULL), ==,
|
||||
WP_ENDPOINT_LINK_STATE_ACTIVE);
|
||||
|
||||
/* destroy */
|
||||
|
||||
g_signal_connect (ep_link, "pw-proxy-destroyed",
|
||||
G_CALLBACK (on_link_destroyed), f);
|
||||
wp_proxy_request_destroy (WP_PROXY (ep_link));
|
||||
|
||||
/* loop will quit because the "links-changed" signal from the session
|
||||
is still connected to quit() from earlier */
|
||||
g_main_loop_run (f->base.loop);
|
||||
|
||||
g_assert_cmpint (f->activation_state, ==, 10);
|
||||
g_assert_cmpuint (wp_session_get_n_links (session_proxy), ==, 0);
|
||||
g_assert_cmpuint (wp_proxy_get_bound_id (WP_PROXY (ep_link)), ==, (guint) -1);
|
||||
|
||||
/* verify the link was also destroyed on the session manager core */
|
||||
{
|
||||
g_autoptr (WpObjectManager) om = wp_object_manager_new ();
|
||||
|
||||
wp_object_manager_add_interest_1 (om, WP_TYPE_ENDPOINT_LINK, NULL);
|
||||
g_signal_connect_swapped (om, "installed",
|
||||
G_CALLBACK (g_main_loop_quit), f->base.loop);
|
||||
wp_core_install_object_manager (f->base.core, om);
|
||||
if (!wp_object_manager_is_installed (om))
|
||||
g_main_loop_run (f->base.loop);
|
||||
|
||||
g_assert_cmpuint (wp_object_manager_get_n_objects (om), ==, 0);
|
||||
}
|
||||
}
|
||||
|
||||
gint
|
||||
main (gint argc, gchar *argv[])
|
||||
{
|
||||
|
|
@ -341,5 +447,11 @@ main (gint argc, gchar *argv[])
|
|||
test_si_standard_link_main,
|
||||
test_si_standard_link_teardown);
|
||||
|
||||
g_test_add ("/modules/si-standard-link/destroy",
|
||||
TestFixture, NULL,
|
||||
test_si_standard_link_setup,
|
||||
test_si_standard_link_destroy,
|
||||
test_si_standard_link_teardown);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue