[Spice-commits] 3 commits - gtk/display gtk/glib-compat.h gtk/Makefile.am gtk/smartcard-manager.c gtk/spice-pulse.c gtk/spice-util.c gtk/spice-util-priv.h gtk/usb-device-manager.c

Marc-André Lureau elmarco at kemper.freedesktop.org
Fri Sep 23 07:26:56 PDT 2011


 gtk/Makefile.am          |    2 
 gtk/display/gnome-rr.c   |   46 --------------------
 gtk/glib-compat.h        |   65 ++++++++++++++++++++++++++++
 gtk/smartcard-manager.c  |    2 
 gtk/spice-pulse.c        |   74 ++++++++++++++------------------
 gtk/spice-util-priv.h    |    5 ++
 gtk/spice-util.c         |  106 +++++++++++++++++++++++++++++++++++++++++++++++
 gtk/usb-device-manager.c |    2 
 8 files changed, 217 insertions(+), 85 deletions(-)

New commits:
commit 386773537d2a6f5798e435483232ab7189a7f6be
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Fri Sep 23 00:41:20 2011 +0200

    build: move G_DEFINE_BOXED in glib-compat.h and fix build with old glib

diff --git a/gtk/Makefile.am b/gtk/Makefile.am
index 40fd327..154e39c 100644
--- a/gtk/Makefile.am
+++ b/gtk/Makefile.am
@@ -186,6 +186,7 @@ GUSB_SRCS =
 endif
 
 libspice_client_glib_2_0_la_SOURCES =	\
+	glib-compat.h			\
 	spice-audio.c			\
 	spice-common.h			\
 	spice-util.c			\
@@ -317,6 +318,7 @@ libspice_client_glib_2_0_la_LIBADD += $(GTHREAD_LIBS)
 endif
 
 displaysrc = \
+	glib-compat.h				\
 	display/edid.h				\
 	display/edid-parse.c			\
 	display/display-name.c			\
diff --git a/gtk/display/gnome-rr.c b/gtk/display/gnome-rr.c
index 71902bd..5de86dd 100644
--- a/gtk/display/gnome-rr.c
+++ b/gtk/display/gnome-rr.c
@@ -30,6 +30,8 @@
 
 #include <gtk/gtk.h>
 
+#include "../glib-compat.h"
+
 #if defined(HAVE_X11)
 #include <X11/Xlib.h>
 #include <gdk/gdkx.h>
@@ -77,50 +79,6 @@ static void gnome_rr_screen_initable_iface_init (GInitableIface *iface);
 G_DEFINE_TYPE_WITH_CODE (GnomeRRScreen, gnome_rr_screen, G_TYPE_OBJECT,
         G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, gnome_rr_screen_initable_iface_init))
 
-#if !GLIB_CHECK_VERSION(2,26,0)
-#define G_DEFINE_BOXED_TYPE(TypeName, type_name, copy_func, free_func) G_DEFINE_BOXED_TYPE_WITH_CODE (TypeName, type_name, copy_func, free_func, {})
-#define G_DEFINE_BOXED_TYPE_WITH_CODE(TypeName, type_name, copy_func, free_func, _C_) _G_DEFINE_BOXED_TYPE_BEGIN (TypeName, type_name, copy_func, free_func) {_C_;} _G_DEFINE_TYPE_EXTENDED_END()
-#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
-#define _G_DEFINE_BOXED_TYPE_BEGIN(TypeName, type_name, copy_func, free_func) \
-GType \
-type_name##_get_type (void) \
-{ \
-  static volatile gsize g_define_type_id__volatile = 0; \
-  if (g_once_init_enter (&g_define_type_id__volatile))  \
-    { \
-      GType (* _g_register_boxed) \
-        (const gchar *, \
-         union \
-           { \
-             TypeName * (*do_copy_type) (TypeName *); \
-             TypeName * (*do_const_copy_type) (const TypeName *); \
-             GBoxedCopyFunc do_copy_boxed; \
-           } __attribute__((__transparent_union__)), \
-         union \
-           { \
-             void (* do_free_type) (TypeName *); \
-             GBoxedFreeFunc do_free_boxed; \
-           } __attribute__((__transparent_union__)) \
-        ) = g_boxed_type_register_static; \
-      GType g_define_type_id = \
-        _g_register_boxed (g_intern_static_string (#TypeName), copy_func, free_func); \
-      { /* custom code follows */
-#else
-#define _G_DEFINE_BOXED_TYPE_BEGIN(TypeName, type_name, copy_func, free_func) \
-GType \
-type_name##_get_type (void) \
-{ \
-  static volatile gsize g_define_type_id__volatile = 0; \
-  if (g_once_init_enter (&g_define_type_id__volatile))  \
-    { \
-      GType g_define_type_id = \
-        g_boxed_type_register_static (g_intern_static_string (#TypeName), \
-                                      (GBoxedCopyFunc) copy_func, \
-                                      (GBoxedFreeFunc) free_func); \
-      { /* custom code follows */
-#endif /* __GNUC__ */
-#endif /* glib 2.26 */
-
 G_DEFINE_BOXED_TYPE (GnomeRRCrtc, gnome_rr_crtc, crtc_copy, crtc_free)
 G_DEFINE_BOXED_TYPE (GnomeRROutput, gnome_rr_output, output_copy, output_free)
 G_DEFINE_BOXED_TYPE (GnomeRRMode, gnome_rr_mode, mode_copy, mode_free)
diff --git a/gtk/glib-compat.h b/gtk/glib-compat.h
new file mode 100644
index 0000000..b111c91
--- /dev/null
+++ b/gtk/glib-compat.h
@@ -0,0 +1,65 @@
+/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/*
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, see <http://www.gnu.org/licenses/>.
+*/
+#ifndef GLIB_COMPAT_H
+#define GLIB_COMPAT_H
+
+#include <glib-object.h>
+
+#if !GLIB_CHECK_VERSION(2,26,0)
+#define G_DEFINE_BOXED_TYPE(TypeName, type_name, copy_func, free_func) G_DEFINE_BOXED_TYPE_WITH_CODE (TypeName, type_name, copy_func, free_func, {})
+#define G_DEFINE_BOXED_TYPE_WITH_CODE(TypeName, type_name, copy_func, free_func, _C_) _G_DEFINE_BOXED_TYPE_BEGIN (TypeName, type_name, copy_func, free_func) {_C_;} _G_DEFINE_TYPE_EXTENDED_END()
+#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7)
+#define _G_DEFINE_BOXED_TYPE_BEGIN(TypeName, type_name, copy_func, free_func) \
+GType \
+type_name##_get_type (void) \
+{ \
+  static volatile gsize g_define_type_id__volatile = 0; \
+  if (g_once_init_enter (&g_define_type_id__volatile))  \
+    { \
+      GType (* _g_register_boxed) \
+        (const gchar *, \
+         union \
+           { \
+             TypeName * (*do_copy_type) (TypeName *); \
+             TypeName * (*do_const_copy_type) (const TypeName *); \
+             GBoxedCopyFunc do_copy_boxed; \
+           } __attribute__((__transparent_union__)), \
+         union \
+           { \
+             void (* do_free_type) (TypeName *); \
+             GBoxedFreeFunc do_free_boxed; \
+           } __attribute__((__transparent_union__)) \
+        ) = g_boxed_type_register_static; \
+      GType g_define_type_id = \
+        _g_register_boxed (g_intern_static_string (#TypeName), copy_func, free_func); \
+      { /* custom code follows */
+#else
+#define _G_DEFINE_BOXED_TYPE_BEGIN(TypeName, type_name, copy_func, free_func) \
+GType \
+type_name##_get_type (void) \
+{ \
+  static volatile gsize g_define_type_id__volatile = 0; \
+  if (g_once_init_enter (&g_define_type_id__volatile))  \
+    { \
+      GType g_define_type_id = \
+        g_boxed_type_register_static (g_intern_static_string (#TypeName), \
+                                      (GBoxedCopyFunc) copy_func, \
+                                      (GBoxedFreeFunc) free_func); \
+      { /* custom code follows */
+#endif /* __GNUC__ */
+#endif /* glib 2.26 */
+
+#endif /* GLIB_COMPAT_H */
diff --git a/gtk/smartcard-manager.c b/gtk/smartcard-manager.c
index 806aee5..df29088 100644
--- a/gtk/smartcard-manager.c
+++ b/gtk/smartcard-manager.c
@@ -20,6 +20,8 @@
 #include <glib-object.h>
 #include <string.h>
 
+#include "glib-compat.h"
+
 #ifdef USE_SMARTCARD
 #include <vcard_emul.h>
 #include <vevent.h>
diff --git a/gtk/usb-device-manager.c b/gtk/usb-device-manager.c
index b14369a..f2dbf90 100644
--- a/gtk/usb-device-manager.c
+++ b/gtk/usb-device-manager.c
@@ -24,6 +24,8 @@
 #include <glib-object.h>
 #include <gio/gio.h> /* For GInitable */
 
+#include "glib-compat.h"
+
 #ifdef USE_USBREDIR
 #include <gusb/gusb-source.h>
 #include <gusb/gusb-device-list.h>
commit eaed66b848868e763c8ad2e101e5109fa2ff7806
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Thu Sep 22 23:08:11 2011 +0200

    pulse: use spice_g_signal_connect_object
    
    Disconnect all handlers when either emitter or observer is gone.
    That should help https://bugzilla.redhat.com/show_bug.cgi?id=737202

diff --git a/gtk/spice-pulse.c b/gtk/spice-pulse.c
index dce4e9c..7231251 100644
--- a/gtk/spice-pulse.c
+++ b/gtk/spice-pulse.c
@@ -19,6 +19,7 @@
 #include "spice-common.h"
 #include "spice-session-priv.h"
 #include "spice-channel-priv.h"
+#include "spice-util-priv.h"
 
 #include <pulse/glib-mainloop.h>
 #include <pulse/pulseaudio.h>
@@ -113,26 +114,17 @@ static void spice_pulse_dispose(GObject *obj)
         pa_operation_unref(p->record.cork_op);
     p->record.cork_op = NULL;
 
-    if (p->pchannel != NULL) {
-        g_signal_handlers_disconnect_by_func(p->pchannel,
-                                             channel_event, obj);
+    if (p->pchannel)
         g_object_unref(p->pchannel);
-        p->pchannel = NULL;
-    }
+    p->pchannel = NULL;
 
-    if (p->rchannel != NULL) {
-        g_signal_handlers_disconnect_by_func(p->rchannel,
-                                             channel_event, obj);
+    if (p->rchannel)
         g_object_unref(p->rchannel);
-        p->rchannel = NULL;
-    }
+    p->rchannel = NULL;
 
-    if (p->session != NULL) {
-        g_signal_handlers_disconnect_by_func(p->session,
-                                             channel_new, obj);
+    if (p->session)
         g_object_unref(p->session);
-        p->session = NULL;
-    }
+    p->session = NULL;
 
     G_OBJECT_CLASS(spice_pulse_parent_class)->dispose(obj);
 }
@@ -720,36 +712,36 @@ static void channel_new(SpiceSession *s, SpiceChannel *channel, gpointer data)
     if (SPICE_IS_PLAYBACK_CHANNEL(channel)) {
         g_return_if_fail(p->pchannel == NULL);
         p->pchannel = g_object_ref(channel);
-        g_signal_connect(channel, "playback-start",
-                         G_CALLBACK(playback_start), pulse);
-        g_signal_connect(channel, "playback-get-delay",
-                         G_CALLBACK(playback_get_delay), pulse);
-        g_signal_connect(channel, "playback-data",
-                         G_CALLBACK(playback_data), pulse);
-        g_signal_connect(channel, "playback-stop",
-                         G_CALLBACK(playback_stop), pulse);
-        g_signal_connect(channel, "channel-event",
-                         G_CALLBACK(channel_event), pulse);
-        g_signal_connect(channel, "notify::volume",
-                         G_CALLBACK(playback_volume_changed), pulse);
-        g_signal_connect(channel, "notify::mute",
-                         G_CALLBACK(playback_mute_changed), pulse);
+        spice_g_signal_connect_object(channel, "playback-start",
+                                      G_CALLBACK(playback_start), pulse, 0);
+        spice_g_signal_connect_object(channel, "playback-get-delay",
+                                      G_CALLBACK(playback_get_delay), pulse, 0);
+        spice_g_signal_connect_object(channel, "playback-data",
+                                      G_CALLBACK(playback_data), pulse, 0);
+        spice_g_signal_connect_object(channel, "playback-stop",
+                                      G_CALLBACK(playback_stop), pulse, 0);
+        spice_g_signal_connect_object(channel, "channel-event",
+                                      G_CALLBACK(channel_event), pulse, 0);
+        spice_g_signal_connect_object(channel, "notify::volume",
+                                      G_CALLBACK(playback_volume_changed), pulse, 0);
+        spice_g_signal_connect_object(channel, "notify::mute",
+                                      G_CALLBACK(playback_mute_changed), pulse, 0);
         spice_channel_connect(channel);
     }
 
     if (SPICE_IS_RECORD_CHANNEL(channel)) {
         g_return_if_fail(p->rchannel == NULL);
         p->rchannel = g_object_ref(channel);
-        g_signal_connect(channel, "record-start",
-                         G_CALLBACK(record_start), pulse);
-        g_signal_connect(channel, "record-stop",
-                         G_CALLBACK(record_stop), pulse);
-        g_signal_connect(channel, "channel-event",
-                         G_CALLBACK(channel_event), pulse);
-        g_signal_connect(channel, "notify::volume",
-                         G_CALLBACK(record_volume_changed), pulse);
-        g_signal_connect(channel, "notify::mute",
-                         G_CALLBACK(record_mute_changed), pulse);
+        spice_g_signal_connect_object(channel, "record-start",
+                                      G_CALLBACK(record_start), pulse, 0);
+        spice_g_signal_connect_object(channel, "record-stop",
+                                      G_CALLBACK(record_stop), pulse, 0);
+        spice_g_signal_connect_object(channel, "channel-event",
+                                      G_CALLBACK(channel_event), pulse, 0);
+        spice_g_signal_connect_object(channel, "notify::volume",
+                                      G_CALLBACK(record_volume_changed), pulse, 0);
+        spice_g_signal_connect_object(channel, "notify::mute",
+                                      G_CALLBACK(record_mute_changed), pulse, 0);
         spice_channel_connect(channel);
     }
 }
@@ -800,8 +792,8 @@ SpicePulse *spice_pulse_new(SpiceSession *session, GMainContext *context,
     p = SPICE_PULSE_GET_PRIVATE(pulse);
     p->session = g_object_ref(session);
 
-    g_signal_connect(session, "channel-new",
-                     G_CALLBACK(channel_new), pulse);
+    spice_g_signal_connect_object(session, "channel-new",
+                                  G_CALLBACK(channel_new), pulse, 0);
     list = spice_session_get_channels(session);
     for (tmp = g_list_first(list); tmp != NULL; tmp = g_list_next(tmp)) {
         channel_new(session, tmp->data, (gpointer)pulse);
commit f01c59ade68473e3b6ebb58c41d9d82e633af080
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Thu Sep 22 23:06:48 2011 +0200

    util: add spice_g_signal_connect_object
    
    This is a copy of telepathy-glib tp_g_signal_connect_object.
    
    That function allows to connect object's signals without
    having to worry much about emitter/observer lifetime.
    
    It handles automatic disconnection for us, no need to track
    all the handlers id. Nice!

diff --git a/gtk/spice-util-priv.h b/gtk/spice-util-priv.h
index 90b437c..1f9778c 100644
--- a/gtk/spice-util-priv.h
+++ b/gtk/spice-util-priv.h
@@ -23,6 +23,11 @@
 G_BEGIN_DECLS
 
 gboolean spice_strv_contains(const GStrv strv, const gchar *str);
+gulong spice_g_signal_connect_object(gpointer instance,
+                                     const gchar *detailed_signal,
+                                     GCallback c_handler,
+                                     gpointer gobject,
+                                     GConnectFlags connect_flags);
 
 G_END_DECLS
 
diff --git a/gtk/spice-util.c b/gtk/spice-util.c
index d3097ca..fb5767b 100644
--- a/gtk/spice-util.c
+++ b/gtk/spice-util.c
@@ -1,6 +1,7 @@
 /* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
 /*
    Copyright (C) 2010 Red Hat, Inc.
+   Copyright © 2006-2010 Collabora Ltd. <http://www.collabora.co.uk/>
 
    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
@@ -74,3 +75,108 @@ gboolean spice_strv_contains(const GStrv strv, const gchar *str)
 
     return FALSE;
 }
+
+typedef struct {
+    GObject *instance;
+    GObject *observer;
+    GClosure *closure;
+    gulong handler_id;
+} WeakHandlerCtx;
+
+static WeakHandlerCtx *
+whc_new (GObject *instance,
+         GObject *observer)
+{
+    WeakHandlerCtx *ctx = g_slice_new0 (WeakHandlerCtx);
+
+    ctx->instance = instance;
+    ctx->observer = observer;
+
+    return ctx;
+}
+
+static void
+whc_free (WeakHandlerCtx *ctx)
+{
+    g_slice_free (WeakHandlerCtx, ctx);
+}
+
+static void observer_destroyed_cb (gpointer, GObject *);
+static void closure_invalidated_cb (gpointer, GClosure *);
+
+/*
+ * If signal handlers are removed before the object is destroyed, this
+ * callback will never get triggered.
+ */
+static void
+instance_destroyed_cb (gpointer ctx_,
+                       GObject *where_the_instance_was)
+{
+    WeakHandlerCtx *ctx = ctx_;
+
+    /* No need to disconnect the signal here, the instance has gone away. */
+    g_object_weak_unref (ctx->observer, observer_destroyed_cb, ctx);
+    g_closure_remove_invalidate_notifier (ctx->closure, ctx,
+                                          closure_invalidated_cb);
+    whc_free (ctx);
+}
+
+/* Triggered when the observer is destroyed. */
+static void
+observer_destroyed_cb (gpointer ctx_,
+                       GObject *where_the_observer_was)
+{
+    WeakHandlerCtx *ctx = ctx_;
+
+    g_closure_remove_invalidate_notifier (ctx->closure, ctx,
+                                          closure_invalidated_cb);
+    g_signal_handler_disconnect (ctx->instance, ctx->handler_id);
+    g_object_weak_unref (ctx->instance, instance_destroyed_cb, ctx);
+    whc_free (ctx);
+}
+
+/* Triggered when either object is destroyed or the handler is disconnected. */
+static void
+closure_invalidated_cb (gpointer ctx_,
+                        GClosure *where_the_closure_was)
+{
+    WeakHandlerCtx *ctx = ctx_;
+
+    g_object_weak_unref (ctx->instance, instance_destroyed_cb, ctx);
+    g_object_weak_unref (ctx->observer, observer_destroyed_cb, ctx);
+    whc_free (ctx);
+}
+
+/* Copied from tp_g_signal_connect_object. See documentation. */
+G_GNUC_INTERNAL
+gulong spice_g_signal_connect_object (gpointer instance,
+                                      const gchar *detailed_signal,
+                                      GCallback c_handler,
+                                      gpointer gobject,
+                                      GConnectFlags connect_flags)
+{
+    GObject *instance_obj = G_OBJECT (instance);
+    WeakHandlerCtx *ctx = whc_new (instance_obj, gobject);
+
+    g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
+    g_return_val_if_fail (detailed_signal != NULL, 0);
+    g_return_val_if_fail (c_handler != NULL, 0);
+    g_return_val_if_fail (G_IS_OBJECT (gobject), 0);
+    g_return_val_if_fail (
+                          (connect_flags & ~(G_CONNECT_AFTER|G_CONNECT_SWAPPED)) == 0, 0);
+
+    if (connect_flags & G_CONNECT_SWAPPED)
+        ctx->closure = g_cclosure_new_object_swap (c_handler, gobject);
+    else
+        ctx->closure = g_cclosure_new_object (c_handler, gobject);
+
+    ctx->handler_id = g_signal_connect_closure (instance, detailed_signal,
+                                                ctx->closure, (connect_flags & G_CONNECT_AFTER) ? TRUE : FALSE);
+
+    g_object_weak_ref (instance_obj, instance_destroyed_cb, ctx);
+    g_object_weak_ref (gobject, observer_destroyed_cb, ctx);
+    g_closure_add_invalidate_notifier (ctx->closure, ctx,
+                                       closure_invalidated_cb);
+
+    return ctx->handler_id;
+}


More information about the Spice-commits mailing list