/srv/mercurial-server/detachablepurple: 86c8068e3918: Going mult...

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


Changeset: 86c8068e391890ca0e36c9ec021a4f8d175e6360
Author:	 Gilles Bedel <gillux at cpw.pidgin.im>
Date:	 2012-05-20 13:17 +0000
Branch:	 cpw.gillux.detachablepurple
URL: http://hg.pidgin.im/srv/mercurial-server/detachablepurple/rev/86c8068e3918

Description:

Going multi-interface capable. Objects may now hold several D-Bus interfaces.
This is the first commit of a long series to get things multi-interface. We
are going to to have one interface per class, from the PurpleObject class to
its most derived child class. Therefore we store a set of interfaces for
each class, and register each one when registering an object.

diffstat:

 libpurple/pobject.c |  60 +++++++++++++++++++++++++++++++++++++---------------
 libpurple/pobject.h |  38 ++++++++++++++++++++++-----------
 2 files changed, 68 insertions(+), 30 deletions(-)

diffs (190 lines):

diff --git a/libpurple/pobject.c b/libpurple/pobject.c
--- a/libpurple/pobject.c
+++ b/libpurple/pobject.c
@@ -43,7 +43,7 @@
 	gpointer ui_data;
 	/* The gdbus id(s) used to unregister the registered object (in daemon
 	   context) or the registered sighandler (in client context). */
-	guint dbus_reg_id;
+	GSList *dbus_reg_id;
 	/* The dbus interface we use for purple related methods and signals,
 	 * e.g. im.pidgin.purple.account.
 	 */
@@ -293,8 +293,8 @@
 }
 
 #ifdef HAVE_DBUS
-guint
-purple_object_get_dbus_reg_id(PurpleObject *pobj)
+GSList *
+purple_object_get_dbus_reg_ids(PurpleObject *pobj)
 {
 	PurpleObjectPrivate *priv;
 
@@ -304,13 +304,15 @@
 }
 
 void
-purple_object_set_dbus_reg_id(PurpleObject *pobj, guint registration_id)
+purple_object_add_dbus_reg_id(PurpleObject *pobj, guint registration_id)
 {
 	PurpleObjectPrivate *priv;
 
 	g_return_if_fail(pobj);
 	priv = PURPLE_OBJECT_GET_PRIVATE(pobj);
-	priv->dbus_reg_id = registration_id;
+	/* TODO: unregister on exit. */
+	priv->dbus_reg_id = g_slist_append(priv->dbus_reg_id,
+	                                   GINT_TO_POINTER(registration_id));
 }
 
 char*
@@ -827,29 +829,45 @@
 	}
 }
 
-guint
+void
 purple_object_generic_dbus_register_object(gpointer object, GDBusConnection *dbus_conn)
 {
 	PurpleObject *pobj = PURPLE_OBJECT(object);
+	PurpleObjectClass *pobjclass = PURPLE_OBJECT_GET_CLASS(object);
 	GError *error = NULL;
 	guint reg_id;
+	GDBusInterfaceInfo *ifaceinfo;
+	GType type, child;
 	static const GDBusInterfaceVTable interface_vtable =
 	{ purple_object_generic_dbus_method_handler,
 	  purple_object_generic_dbus_get_property,
 	  purple_object_generic_dbus_set_property };
 
-	reg_id = g_dbus_connection_register_object
-	          (dbus_conn,
-	           purple_object_get_dbus_path(pobj),
-	           PURPLE_OBJECT_GET_CLASS(pobj)->dbus_ifaceinfo,
-	           &interface_vtable,
-	           object, NULL, &error);
-	if (reg_id == 0) {
-		purple_debug_error("dbus", "Failed to register a %s: %s\n",
-                           G_OBJECT_TYPE_NAME(object), error->message);
-		g_error_free(error);
+	/* Step from the most derived type to PurpleObject
+	 * type and retreive each associated D-Bus interface info. */
+	type = G_OBJECT_TYPE(pobj);
+	do {
+		ifaceinfo = g_datalist_id_get_data(&pobjclass->dbus_ifaceinfos,
+		                                   g_type_qname(type));
+		if (ifaceinfo) {
+			reg_id = g_dbus_connection_register_object
+			          (dbus_conn,
+			           purple_object_get_dbus_path(pobj),
+			           ifaceinfo,
+			           &interface_vtable,
+			           object, NULL, &error);
+			if (reg_id == 0) {
+				purple_debug_error("dbus",
+				  "Failed to register a %s for interface %s\n",
+				  G_OBJECT_TYPE_NAME(object), ifaceinfo->name);
+			} else {
+				purple_object_add_dbus_reg_id(pobj, reg_id);
+			}
+		}
+		child = type;
+		type = g_type_parent(type);
 	}
-	return reg_id;
+	while (child != PURPLE_TYPE_OBJECT && child != 0);
 }
 
 static void
@@ -907,6 +925,14 @@
 }
 
 void
+purple_object_class_register_dbus_iface(PurpleObjectClass *pclass,
+                                        GType type,
+                                        GDBusInterfaceInfo *i)
+{
+	g_datalist_id_set_data(&pclass->dbus_ifaceinfos, g_type_qname(type),i);
+}
+
+void
 purple_object_dbus_connect(gpointer object, GDBusConnection *dbus_conn)
 {
 	PurpleObjectClass *pclass = PURPLE_OBJECT_GET_CLASS(object);
diff --git a/libpurple/pobject.h b/libpurple/pobject.h
--- a/libpurple/pobject.h
+++ b/libpurple/pobject.h
@@ -57,8 +57,10 @@
 	/* A data set of DBus methods (in daemon context) or signals (in client
 	   context) names as keys and GClosures as values. */
 	GData *dbus_callbacks;
-	/* The C structure based representation of the XML DBus interface. */
-	GDBusInterfaceInfo *dbus_ifaceinfo;
+	/* A data set with GType names as keys and GDBusInterfaceInfo as
+	 * values. A GDBusInterfaceInfo is a C struct-based representation
+	 * of the XML DBus interface. */
+	GData *dbus_ifaceinfos;
 	/* Build a unique dbus path name for the object. Only the deamon can
 	   garantee the uniqueness of a name, thus this function should only
 	   be set in daemon mode, or possibly in client mode for well-known
@@ -88,21 +90,21 @@
 
 #ifdef HAVE_DBUS
 /**
- * Gets the DBus registration id of the object pobj.
- * An id of zero means no registration, or a registration failed.
+ * Gets the DBus registration id list of the object pobj.
+ * There is one id per D-Bus interface.
  *
- * @param pobj The PurpleObject we want to get the registration id from.
- * @return The registration id of pobj.
+ * @param pobj The PurpleObject we want to get the registration ids from.
+ * @return The registration ids of pobj.
  */
-guint purple_object_get_dbus_reg_id(PurpleObject *pobj);
+GSList* purple_object_get_dbus_reg_ids(PurpleObject *pobj);
 
 /**
- * Sets the DBus registration id of the object pobj.
+ * Adds a D-Bus registration id of the object pobj to its list.
  *
- * @param pobj The PurpleObject we want to set the registration id in.
- * @param registration_id The registration id we want to set.
+ * @param pobj The PurpleObject we want to add a registration id in.
+ * @param registration_id The registration id we want to add.
  */
-void purple_object_set_dbus_reg_id(PurpleObject *pobj, guint registration_id);
+void purple_object_add_dbus_reg_id(PurpleObject *pobj, guint registration_id);
 
 /**
  * Gets the dbus proxy. This is used in detachable sessions context only.
@@ -373,9 +375,8 @@
  * 
  * @param object An object derived from PurpleObject.
  * @param dbus_conn The GDBus handle.
- * @return The registration id returned by g_dbus_connection_register_object().
  */
-guint purple_object_generic_dbus_register_object(gpointer object, GDBusConnection *dbus_conn);
+void purple_object_generic_dbus_register_object(gpointer object, GDBusConnection *dbus_conn);
 
 /**
  * Make the given object receive D-Bus signals, with the default signal
@@ -387,6 +388,17 @@
  * @return The registration id returned by g_dbus_connection_signal_subscribe().
  */
 guint purple_object_generic_dbus_signal_subscribe(gpointer object, GDBusConnection *dbus_conn);
+/**
+ * Adds an D-Bus interface definition to the pool of handled interfaces
+ * by the object class of the given type. This function should be ran by
+ * children class initialization functions.
+ *
+ * @param pclass The super-class of the class on which you add the
+ *        interface definition.
+ * @param type The type of the class the interface is for.
+ * @param ifaceinfo A D-Bus interface definition.
+ */
+void purple_object_class_register_dbus_iface(PurpleObjectClass *pclass, GType type, GDBusInterfaceInfo *ifaceinfo);
 
 /**
  * Calls the on_dbus_connected function pointer on the class of object,



More information about the Commits mailing list