/srv/mercurial-server/detachablepurple: be7eafffa0b9: Introduced...

Gilles Bedel gillux at cpw.pidgin.im
Fri Jun 15 22:01:29 EDT 2012


Changeset: be7eafffa0b91f943ac2b023c688cbef8c8acc99
Author:	 Gilles Bedel <gillux at cpw.pidgin.im>
Date:	 2011-05-19 19:45 +0000
Branch:	 cpw.gillux.detachablepurple
URL: http://hg.pidgin.im/srv/mercurial-server/detachablepurple/rev/be7eafffa0b9

Description:

Introduced the switch from dbus-glib to gdbus, with:
- the code needed to acquire the bus
- a "virtual function", (*dbus_register), aimed to be set by
  all the PurpleObjects to register themselves on DBus.

diffstat:

 configure.ac              |    2 +-
 libpurple/dbus-bindings.h |    2 +-
 libpurple/dbus-server.c   |  115 ++++++++++++++++++++++++++++++----------------
 libpurple/dbus-server.h   |    9 +++
 libpurple/dbus/account.c  |    2 +-
 libpurple/pobject.c       |    6 +-
 libpurple/pobject.h       |   18 ++++++-
 7 files changed, 107 insertions(+), 47 deletions(-)

diffs (truncated from 316 to 300 lines):

diff --git a/configure.ac b/configure.ac
--- a/configure.ac
+++ b/configure.ac
@@ -328,7 +328,7 @@
 dnl #######################################################################
 dnl # Check for GLib 2.16 (required)
 dnl #######################################################################
-PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.16.0 gobject-2.0 gmodule-2.0 gthread-2.0], , [
+PKG_CHECK_MODULES(GLIB, [glib-2.0 >= 2.16.0 gobject-2.0 gmodule-2.0 gthread-2.0 gio-2.0], , [
 	AC_MSG_RESULT(no)
 	AC_MSG_ERROR([
 
diff --git a/libpurple/dbus-bindings.h b/libpurple/dbus-bindings.h
--- a/libpurple/dbus-bindings.h
+++ b/libpurple/dbus-bindings.h
@@ -107,7 +107,7 @@
 
 DBusConnection *purple_dbus_get_connection(void);
 
-DBusGConnection *purple_dbus_get_g_connection(void);
+GDBusConnection *purple_gdbus_get_connection(void);
 
 #ifdef __cplusplus
 }
diff --git a/libpurple/dbus-server.c b/libpurple/dbus-server.c
--- a/libpurple/dbus-server.c
+++ b/libpurple/dbus-server.c
@@ -35,6 +35,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <dbus/dbus-glib-bindings.h>
+#include <gio/gio.h>
 
 #include "account.h"
 #include "accountlist.h"
@@ -87,6 +88,14 @@
 static GHashTable *map_id_node;
 static GHashTable *map_id_type;
 
+/* The bus acquiring process is asynchronous. We first ask to get it,
+ * then the other parts of purple are initialized, and then when we
+ * reach the program main loop, the on_bus_acquired callback is called.
+ * Therefore we need something to remember the objects created during
+ * the initialization that we will need to register on DBus when we get
+ * the bus. We temporary hold a reference to such objects in this list. */
+static GSList *dbus_obj_to_register = NULL;
+
 static gchar *init_error;
 static int dbus_request_name_reply = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;
 
@@ -524,14 +533,14 @@
 /* DBus bindings ...                                          */
 /**************************************************************/
 
-static DBusGConnection *purple_dbus_g_connection;
+static GDBusConnection *purple_gdbus_connection;
 
 static DBusConnection *purple_dbus_connection;
 
-DBusGConnection *
-purple_dbus_get_g_connection(void)
+GDBusConnection *
+purple_gdbus_get_connection(void)
 {
-	return purple_dbus_g_connection;
+	return purple_gdbus_connection;
 }
 
 DBusConnection *
@@ -721,8 +730,8 @@
 	GError *gerror = NULL;
 
 	dbus_error_init(&error);
-	purple_dbus_g_connection = dbus_g_bus_get(DBUS_BUS_STARTER, &gerror);
-	purple_dbus_connection = dbus_g_connection_get_connection(purple_dbus_g_connection);
+	//purple_gdbus_connection = g_bus_get_sync(G_BUS_TYPE_STARTER, NULL, &gerror);
+	purple_dbus_connection = dbus_bus_get(DBUS_BUS_STARTER, &error);
 
 	if (purple_dbus_connection == NULL)
 	{
@@ -772,54 +781,80 @@
 	PURPLE_DBUS_REGISTER_BINDINGS(purple_dbus_get_handle());
 }
 
+void
+purple_dbus_register_object(gpointer object)
+{
+	if (purple_gdbus_connection)
+		purple_object_register_on_dbus(object, purple_gdbus_connection);
+	else
+		dbus_obj_to_register = g_slist_append(dbus_obj_to_register,
+		                                      g_object_ref(object));
+}
+
+/* Note that this callback will not be called until we reach the event loop,
+ * after everything is initialized. That’s why we need to put our objects
+ * in the dbus_obj_to_register GSList, to register them later, when we have
+ * acquired the bus.
+ */
 static void
-purple_dbus_g_init(void)
+on_bus_acquired(GDBusConnection *connection, const gchar *name,
+                gpointer user_data)
 {
-	DBusGProxy* dbus_proxy;
+	GObject *obj;
+	GSList* obj_list;
+
+	purple_gdbus_connection = connection;
+	for (obj_list = dbus_obj_to_register; obj_list; obj_list = obj_list->next) {
+		obj = G_OBJECT(obj_list->data);
+		/* If we are owning the last a reference, it means we are going
+		 * to destroy it, so don’t bother registering it on DBus. */
+		if (obj->ref_count > 1)
+			purple_object_register_on_dbus(obj_list->data, connection);
+		g_object_unref(obj);
+	}
+
+	g_slist_free(dbus_obj_to_register);
+}
+
+static void
+on_name_lost(GDBusConnection *connection, const gchar *name, gpointer user_data)
+{
+	/* TODO: Handle this properly. */
+	purple_debug_error("dbus", "Name %s lost!", name);
+}
+
+static void
+purple_gdbus_init(void)
+{
+	guint owner_id;
 	GError *error = NULL;
-	guint request_ret;
 
-	/* In remote mode we need to register the marshallers
-	 * we will use to receive the signals sent by the daemon */
 	if (purple_core_is_remote_mode()) {
 		/* Initialize the "dbus path name -> gobject" hash table */
 		dbus_path_gobjects = g_hash_table_new_full(g_str_hash, g_str_equal,
 							g_free, NULL);
 	}
 
-	/* In daemon mode create a proxy for the purple service, so we can
-	 * publish our gobjects on DBus.
+	/* In daemon mode we need to own our name on the bus,
+	 * so we can publish our gobjects on DBus.
 	 */
 	if (purple_core_is_daemon_mode()) {
-		dbus_proxy = dbus_g_proxy_new_for_name(purple_dbus_get_g_connection(),
-					DBUS_SERVICE_DBUS, DBUS_PATH_DBUS,
-					DBUS_INTERFACE_DBUS);
-		if (!dbus_proxy) {
-			purple_debug_error("dbus", "Unable to create proxy\n");
-			return;
-		}
-
-		if (!org_freedesktop_DBus_request_name(dbus_proxy,
-						DBUS_PURPLE_SERVICE, 0,
-						&request_ret, &error)) {
-			purple_debug_error("dbus",
-					"Unable to request the name of service "
-					DBUS_PURPLE_SERVICE ": %s\n",
-					error->message);
-			g_object_unref(dbus_proxy);
-			g_error_free(error);
-			return;
-		}
-		g_object_unref(dbus_proxy);
-		/* We should also care about request_ret */
+		owner_id = g_bus_own_name (G_BUS_TYPE_SESSION, DBUS_PURPLE_SERVICE,
+		                           G_BUS_NAME_OWNER_FLAGS_NONE,
+		                           on_bus_acquired,
+								   NULL, /* on_name_acquired */
+		                           on_name_lost, /* on_name_lost */
+		                           NULL, NULL);
+		/* TODO: handle fail of owning the name. */
 	}
 
 	/* In remote and daemon mode, we create our singleton objects */
+
+	/* Instantiate the PurpleConstructor */
+	purple_constructor_do_init();
+
 	/* Instantiate the PurpleDBusCallback. */
 	purple_dbus_callback_do_init();
-
-	/* Instantiate and publish the PurpleConstructor */
-	purple_constructor_do_init();
 }
 
 
@@ -1007,11 +1042,11 @@
 	if (init_error != NULL)
 		purple_debug_error("dbus", "%s\n", init_error);
 
-	purple_dbus_g_init();
+	purple_gdbus_init();
 }
 
 static void
-purple_dbus_g_uninit(void)
+purple_gdbus_uninit(void)
 {
 	if (purple_core_is_remote_mode())
 		g_hash_table_destroy(dbus_path_gobjects);
@@ -1038,5 +1073,5 @@
 	g_free(init_error);
 	init_error = NULL;
 
-	purple_dbus_g_uninit();
+	purple_gdbus_uninit();
 }
diff --git a/libpurple/dbus-server.h b/libpurple/dbus-server.h
--- a/libpurple/dbus-server.h
+++ b/libpurple/dbus-server.h
@@ -179,6 +179,15 @@
 gboolean purple_dbus_is_owner(void);
 
 /**
+ * "Busless" function to register a PurpleObject on DBus.
+ * If the bus is acquired, it calls the ->dbus_register() operation.
+ * Otherwise, it will do it when the bus is acquired.
+ *
+ * @param obj The object to register. Must be a subclass of PurpleObject.
+ */
+void purple_dbus_register_object(gpointer object);
+
+/**
  * Starts Purple's D-BUS server.  It is responsible for handling DBUS
  * requests from other applications.
  */
diff --git a/libpurple/dbus/account.c b/libpurple/dbus/account.c
--- a/libpurple/dbus/account.c
+++ b/libpurple/dbus/account.c
@@ -245,7 +245,7 @@
 	PurpleRunningMode mode;
 
 	/* First, remotely create a new account */
-	dbus_proxy = dbus_g_proxy_new_for_name(purple_dbus_get_g_connection(),
+	dbus_proxy = dbus_g_proxy_new_for_name(purple_gdbus_get_connection(),
 	                                       DBUS_PURPLE_SERVICE,
 	                                       DBUS_CONSTRUCTOR_PATH,
 	                                       DBUS_CONSTRUCTOR_INTERFACE);
diff --git a/libpurple/pobject.c b/libpurple/pobject.c
--- a/libpurple/pobject.c
+++ b/libpurple/pobject.c
@@ -459,14 +459,14 @@
 	if (purple_core_is_remote_mode() || purple_core_is_mirror_mode()) {
 		/* One for the org.freedesktop.DBus.Properties interface */
 		dbus_proxy = dbus_g_proxy_new_for_name(
-					purple_dbus_get_g_connection(),
+					purple_gdbus_get_connection(),
 					DBUS_PURPLE_SERVICE, dbus_path,
 					DBUS_INTERFACE_PROPERTIES);
 		priv->dbus_props_proxy = dbus_proxy;
 
 		/* One for the provided interface */
 		dbus_proxy = dbus_g_proxy_new_for_name(
-					purple_dbus_get_g_connection(),
+					purple_gdbus_get_connection(),
 					DBUS_PURPLE_SERVICE, dbus_path,
 					dbus_interface);
 		priv->dbus_obj_proxy = dbus_proxy;
@@ -487,7 +487,7 @@
 	else if (purple_core_is_daemon_mode()) {
 		/* Register our object as at dbus_path */
 		dbus_g_connection_register_g_object(
-					purple_dbus_get_g_connection(),
+					purple_gdbus_get_connection(),
 					dbus_path, G_OBJECT(pobj));
 
 		/* Remember the purple interface */
diff --git a/libpurple/pobject.h b/libpurple/pobject.h
--- a/libpurple/pobject.h
+++ b/libpurple/pobject.h
@@ -26,6 +26,7 @@
 
 #ifdef HAVE_DBUS
 #  include <dbus/dbus-glib-bindings.h>
+#  include <gio/gio.h>
 #endif
 
 #define PURPLE_TYPE_OBJECT              (purple_object_get_type())
@@ -47,8 +48,13 @@
 struct _PurpleObjectClass
 {
 	GObjectClass gparent;
-
+#ifdef HAVE_DBUS
+	/* A function that should register the object on DBus. */
+	guint (*dbus_register)(gpointer object, GDBusConnection *connection);
+	void (*_purple_reserved[3])(void);
+#else
 	void (*_purple_reserved[4])(void);
+#endif
 };
 
 G_BEGIN_DECLS
@@ -155,6 +161,16 @@



More information about the Commits mailing list