diff --git a/lib/wp/endpoint.c b/lib/wp/endpoint.c index df00742e1e49d35a9b5cac298e43d9383985a89c..bb30d41cf5bb8605c9432635dc04b80c2551fdb8 100644 --- a/lib/wp/endpoint.c +++ b/lib/wp/endpoint.c @@ -676,30 +676,6 @@ impl_set_param (void *object, uint32_t id, uint32_t flags, return 0; } -static void -on_stream_flags_changed (WpSessionItem * stream, WpSiFlags flags, - WpSessionItem * link) -{ - /* 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); - } -} - static void on_si_link_exported (WpSessionItem * link, GAsyncResult * res, gpointer data) { @@ -859,18 +835,13 @@ impl_create_link (void *object, const struct spa_dict *props) g_variant_new_uint64 (out_stream_i)); g_variant_builder_add (&b, "{sv}", "in-stream", g_variant_new_uint64 (in_stream_i)); + g_variant_builder_add (&b, "{sv}", "manage-lifetime", + g_variant_new_boolean (TRUE)); if (G_UNLIKELY (!wp_session_item_configure (link, g_variant_builder_end (&b)))) { g_critical ("si-standard-link configuration failed"); return -ENAVAIL; } - g_signal_connect_object (self_si_stream, "flags-changed", - 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); link = NULL; diff --git a/modules/module-si-standard-link.c b/modules/module-si-standard-link.c index e50d0afd23bf0b525615cfbe499ec38549a2b826..f972332fa4a4ae8ac5768a31ab5a7b48b3a57b51 100644 --- a/modules/module-si-standard-link.c +++ b/modules/module-si-standard-link.c @@ -22,6 +22,7 @@ struct _WpSiStandardLink WpSiStream *out_stream; WpSiStream *in_stream; + gboolean manage_lifetime; GPtrArray *node_links; guint n_async_ops_wait; @@ -33,6 +34,30 @@ G_DECLARE_FINAL_TYPE (WpSiStandardLink, si_standard_link, WP, SI_STANDARD_LINK, G_DEFINE_TYPE_WITH_CODE (WpSiStandardLink, si_standard_link, WP_TYPE_SESSION_ITEM, G_IMPLEMENT_INTERFACE (WP_TYPE_SI_LINK, si_standard_link_link_init)) +static void +on_stream_flags_changed (WpSessionItem * stream, WpSiFlags flags, + WpSessionItem * link) +{ + /* 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); + } +} + static void si_standard_link_init (WpSiStandardLink * self) { @@ -45,6 +70,15 @@ si_standard_link_reset (WpSessionItem * item) WP_SESSION_ITEM_CLASS (si_standard_link_parent_class)->reset (item); + if (self->manage_lifetime) { + g_signal_handlers_disconnect_by_func (self->out_stream, + G_CALLBACK (on_stream_flags_changed), self); + g_signal_handlers_disconnect_by_func (self->in_stream, + G_CALLBACK (on_stream_flags_changed), self); + g_signal_handlers_disconnect_by_func (self, + G_CALLBACK (on_link_flags_changed), NULL); + } + self->manage_lifetime = FALSE; self->out_stream = NULL; self->in_stream = NULL; @@ -63,6 +97,8 @@ si_standard_link_get_configuration (WpSessionItem * item) "out-stream", g_variant_new_uint64 ((guint64) self->out_stream)); g_variant_builder_add (&b, "{sv}", "in-stream", g_variant_new_uint64 ((guint64) self->in_stream)); + g_variant_builder_add (&b, "{sv}", + "manage-lifetime", g_variant_new_boolean (self->manage_lifetime)); return g_variant_builder_end (&b); } @@ -91,9 +127,29 @@ si_standard_link_configure (WpSessionItem * item, GVariant * args) !(wp_session_item_get_flags (in_stream) & WP_SI_FLAG_ACTIVE)) return FALSE; + /* clear previous configuration; we are not active or exported, + so this doesn't have any other side-effects */ + wp_session_item_reset (item); + self->out_stream = WP_SI_STREAM (out_stream); self->in_stream = WP_SI_STREAM (in_stream); + /* manage-lifetime == TRUE means that this si-standard-link item is + * responsible for self-destructing if either + * - one of the streams is deactivated + * - if the WpImplEndpointLink is destroyed upon request + * (wp_proxy_request_destroy()) + */ + if (g_variant_lookup (args, "manage-lifetime", "b", &self->manage_lifetime) + && self->manage_lifetime) { + g_signal_connect_object (self->out_stream, "flags-changed", + G_CALLBACK (on_stream_flags_changed), self, 0); + g_signal_connect_object (self->in_stream, "flags-changed", + G_CALLBACK (on_stream_flags_changed), self, 0); + g_signal_connect (self, "flags-changed", + G_CALLBACK (on_link_flags_changed), NULL); + } + wp_session_item_set_flag (item, WP_SI_FLAG_CONFIGURED); return TRUE; @@ -417,6 +473,8 @@ wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args) WP_SI_CONFIG_OPTION_WRITEABLE | WP_SI_CONFIG_OPTION_REQUIRED, NULL); g_variant_builder_add (&b, "(ssymv)", "in-stream", "t", WP_SI_CONFIG_OPTION_WRITEABLE | WP_SI_CONFIG_OPTION_REQUIRED, NULL); + g_variant_builder_add (&b, "(ssymv)", "manage-lifetime", "b", + WP_SI_CONFIG_OPTION_WRITEABLE, NULL); wp_si_factory_register (core, wp_si_factory_new_simple ( "si-standard-link",