Skip to content
Snippets Groups Projects
Commit 9db4a545 authored by George Kiagiadakis's avatar George Kiagiadakis
Browse files

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
parent ded2e34e
No related branches found
No related tags found
No related merge requests found
......@@ -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 ();
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment