cpw.gillux.detachablepurple: 3e65e884: Introduced the switch from dbus-glib to ...

gillux at soc.pidgin.im gillux at soc.pidgin.im
Thu May 19 16:21:15 EDT 2011


----------------------------------------------------------------------
Revision: 3e65e88487d511bac639b768dd5a4d68b11f8027
Parent:   a82660ab5e31dbe1d7e86014eaafa25264b0d438
Author:   gillux at soc.pidgin.im
Date:     05/19/11 15:45:55
Branch:   im.pidgin.cpw.gillux.detachablepurple
URL: http://d.pidgin.im/viewmtn/revision/info/3e65e88487d511bac639b768dd5a4d68b11f8027

Changelog: 

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.

Changes against parent a82660ab5e31dbe1d7e86014eaafa25264b0d438

  patched  configure.ac
  patched  libpurple/dbus/account.c
  patched  libpurple/dbus-bindings.h
  patched  libpurple/dbus-server.c
  patched  libpurple/dbus-server.h
  patched  libpurple/pobject.c
  patched  libpurple/pobject.h

-------------- next part --------------
============================================================
--- configure.ac	e04a5fae688b0ff25e902a3ffa611b0d820372e3
+++ configure.ac	1b779d19c273f81ffc2340729ce4e24450bc8e1b
@@ -328,7 +328,7 @@ dnl ####################################
 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([
 
============================================================
--- libpurple/dbus-server.c	d24f9f54bd9dd42ff4d6c1589232a460d8bc0137
+++ libpurple/dbus-server.c	e0bf81855f0987841f234719a7474ba1f17a32bb
@@ -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_type;
 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 @@ purple_dbus_get_gobject_by_path(const gc
 /* 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 @@ purple_dbus_dispatch_init(void)
 	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_dispatch_init(void)
 	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 @@ purple_dbus_init(void)
 	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 @@ purple_dbus_uninit(void)
 	g_free(init_error);
 	init_error = NULL;
 
-	purple_dbus_g_uninit();
+	purple_gdbus_uninit();
 }
============================================================
--- libpurple/dbus-server.h	0acd9de4c5ab4abeb23e019ae0d2b11de7a3fa41
+++ libpurple/dbus-server.h	fdc85e47a83c0d3688979bee43480d04f33c2e9b
@@ -179,6 +179,15 @@ gboolean purple_dbus_is_owner(void);
 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.
  */
============================================================
--- libpurple/dbus-bindings.h	cf9bc137c80c8a1d14cd0a38d74fc9d6ef839238
+++ libpurple/dbus-bindings.h	16b39a8348552a1490a0fa8815261ab92ec89e1f
@@ -107,7 +107,7 @@ DBusConnection *purple_dbus_get_connecti
 
 DBusConnection *purple_dbus_get_connection(void);
 
-DBusGConnection *purple_dbus_get_g_connection(void);
+GDBusConnection *purple_gdbus_get_connection(void);
 
 #ifdef __cplusplus
 }
============================================================
--- libpurple/pobject.c	38302660f3991b981d0a1a0475af2d9fa688f8c7
+++ libpurple/pobject.c	f4b3c3a9683bd5f1cc581fabcb0900b5715b6319
@@ -459,14 +459,14 @@ purple_object_install_dbus_infos(PurpleO
 	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 @@ purple_object_install_dbus_infos(PurpleO
 	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 */
============================================================
--- libpurple/pobject.h	fac160f0d1097e0f16383286a3e36118290499b3
+++ libpurple/pobject.h	18476ab80af15bff6acdd5cc7232c60c63ab01e4
@@ -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
 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 @@ void purple_object_set_dbus_path(PurpleO
  * @param path The path name.
  */
 void purple_object_set_dbus_path(PurpleObject *pobj, char* path);
+/**
+ * Calls the dbus_register function pointer on the class of object, and keeps
+ * the registration id.
+ *
+ * @param object An object derived from PurpleObject.
+ * @param dbus_conn The GDBus handle.
+ */
+void purple_object_register_on_dbus(gpointer object, GDBusConnection *dbus_conn);
+
+
 #endif /* HAVE_DBUS */
 
 int purple_object_get_int(PurpleObject *pobj, const char *prop);
============================================================
--- libpurple/dbus/account.c	4090faba625cb3299307578a53cb1ddf4e4093d5
+++ libpurple/dbus/account.c	767afc902247a45b355a5f64435e00d0b002447c
@@ -245,7 +245,7 @@ purple_account_new_RPC(const char *usern
 	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);


More information about the Commits mailing list