From eb39dec68bc6dd3cba8ebd193b332d76ea553dfb Mon Sep 17 00:00:00 2001 From: Julian Bouzas Date: Wed, 10 Jun 2020 12:27:39 -0400 Subject: [PATCH] core: add wp_core_clone API --- lib/wp/core.c | 51 ++++++++++++++++++++++++++++++++++++++++++++----- lib/wp/core.h | 3 +++ tests/wp/core.c | 33 ++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 5 deletions(-) diff --git a/lib/wp/core.c b/lib/wp/core.c index 425e1ea4..a9397685 100644 --- a/lib/wp/core.c +++ b/lib/wp/core.c @@ -222,15 +222,29 @@ wp_core_constructed (GObject *object) { WpCore *self = WP_CORE (object); g_autoptr (GSource) source = NULL; - struct pw_properties *p = NULL; /* loop */ source = wp_loop_source_new (); g_source_attach (source, self->context); /* context */ - p = self->properties ? wp_properties_to_pw_properties (self->properties) : NULL; - self->pw_context = pw_context_new (WP_LOOP_SOURCE(source)->loop, p, 0); + if (!self->pw_context) { + struct pw_properties *p = NULL; + p = self->properties ? wp_properties_to_pw_properties (self->properties) : NULL; + self->pw_context = pw_context_new (WP_LOOP_SOURCE(source)->loop, p, + sizeof (grefcount)); + g_return_if_fail (self->pw_context); + + /* Init refcount */ + grefcount *rc = pw_context_get_user_data (self->pw_context); + g_return_if_fail (rc); + g_ref_count_init (rc); + } else { + /* Increase refcount */ + grefcount *rc = pw_context_get_user_data (self->pw_context); + g_return_if_fail (rc); + g_ref_count_inc (rc); + } G_OBJECT_CLASS (wp_core_parent_class)->constructed (object); } @@ -249,9 +263,14 @@ static void wp_core_finalize (GObject * obj) { WpCore *self = WP_CORE (obj); + grefcount *rc = pw_context_get_user_data (self->pw_context); + g_return_if_fail (rc); wp_core_disconnect (self); - g_clear_pointer (&self->pw_context, pw_context_destroy); + + /* Clear pw-context if refcount reaches 0 */ + if (g_ref_count_dec (rc)) + g_clear_pointer (&self->pw_context, pw_context_destroy); g_clear_pointer (&self->properties, wp_properties_unref); g_clear_pointer (&self->context, g_main_context_unref); @@ -300,6 +319,9 @@ wp_core_set_property (GObject * object, guint property_id, case PROP_PROPERTIES: self->properties = g_value_dup_boxed (value); break; + case PROP_PW_CONTEXT: + self->pw_context = g_value_get_pointer (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -329,7 +351,7 @@ wp_core_class_init (WpCoreClass * klass) g_object_class_install_property (object_class, PROP_PW_CONTEXT, g_param_spec_pointer ("pw-context", "pw-context", "The pipewire context", - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (object_class, PROP_PW_CORE, g_param_spec_pointer ("pw-core", "pw-core", "The pipewire core", @@ -371,6 +393,25 @@ wp_core_new (GMainContext *context, WpProperties * properties) return g_object_new (WP_TYPE_CORE, "context", context, "properties", properties, + "pw-context", NULL, + NULL); +} + +/** + * wp_core_clone: + * @self: the core + * + * Clones a core with the same context as @self + * + * Returns: (transfer full): the clone #WpCore + */ +WpCore * +wp_core_clone (WpCore * self) +{ + return g_object_new (WP_TYPE_CORE, + "context", self->context, + "properties", self->properties, + "pw-context", self->pw_context, NULL); } diff --git a/lib/wp/core.h b/lib/wp/core.h index 9bafbc37..fe290bd9 100644 --- a/lib/wp/core.h +++ b/lib/wp/core.h @@ -27,6 +27,9 @@ G_DECLARE_FINAL_TYPE (WpCore, wp_core, WP, CORE, GObject) WP_API WpCore * wp_core_new (GMainContext *context, WpProperties * properties); +WP_API +WpCore * wp_core_clone (WpCore * self); + WP_API GMainContext * wp_core_get_context (WpCore * self); diff --git a/tests/wp/core.c b/tests/wp/core.c index 000390f7..3f408d50 100644 --- a/tests/wp/core.c +++ b/tests/wp/core.c @@ -101,6 +101,37 @@ test_core_client_disconnected (TestFixture *f, gconstpointer data) g_assert_cmpuint (wp_object_manager_get_n_objects (f->om), ==, 0); } +static void +test_core_clone (TestFixture *f, gconstpointer data) +{ + g_assert_false (wp_core_is_connected (f->base.core)); + + /* clone */ + g_autoptr (WpCore) clone = wp_core_clone (f->base.core); + g_assert_nonnull (clone); + g_assert_false (wp_core_is_connected (clone)); + + /* connect clone */ + g_assert_true (wp_core_connect (clone)); + g_assert_true (wp_core_is_connected (clone)); + g_assert_false (wp_core_is_connected (f->base.core)); + + /* connect core */ + g_assert_true (wp_core_connect (f->base.core)); + g_assert_true (wp_core_is_connected (clone)); + g_assert_true (wp_core_is_connected (f->base.core)); + + /* disconnect clone */ + wp_core_disconnect (clone); + g_assert_false (wp_core_is_connected (clone)); + g_assert_true (wp_core_is_connected (f->base.core)); + + /* disconnect core */ + wp_core_disconnect (f->base.core); + g_assert_false (wp_core_is_connected (f->base.core)); + g_assert_false (wp_core_is_connected (clone)); +} + gint main (gint argc, gchar *argv[]) { @@ -111,6 +142,8 @@ main (gint argc, gchar *argv[]) test_core_setup, test_core_server_disconnected, test_core_teardown); g_test_add ("/wp/core/client-disconnected", TestFixture, NULL, test_core_setup, test_core_client_disconnected, test_core_teardown); + g_test_add ("/wp/core/cline", TestFixture, NULL, + test_core_setup, test_core_clone, test_core_teardown); return g_test_run (); }