/srv/mercurial-server/detachablepurple: b2166962d9f9: Updated th...

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


Changeset: b2166962d9f9b3e93309acde1be476b7bc96ad16
Author:	 Gilles Bedel <gillux at cpw.pidgin.im>
Date:	 2011-05-27 02:07 +0000
Branch:	 cpw.gillux.detachablepurple
URL: http://hg.pidgin.im/srv/mercurial-server/detachablepurple/rev/b2166962d9f9

Description:

Updated the code that propagates object property changes,
to match the new gdbus library. Still only used by
PurpleAccounts and only from daemon to clients.

diffstat:

 libpurple/dbus/account.c |   2 +
 libpurple/pobject.c      |  72 ++++++++++++++++++++++++++++++++++++++++++++---
 libpurple/pobject.h      |  11 +++++++
 3 files changed, 80 insertions(+), 5 deletions(-)

diffs (144 lines):

diff --git a/libpurple/dbus/account.c b/libpurple/dbus/account.c
--- a/libpurple/dbus/account.c
+++ b/libpurple/dbus/account.c
@@ -227,6 +227,8 @@
 	purple_object_set_dbus_path(PURPLE_OBJECT(account), dbus_path);
 	g_free(dbus_path);	
 
+	purple_object_dbus_bind_notify(PURPLE_OBJECT(account));
+
 	if (purple_core_is_remote_mode() || purple_core_is_mirror_mode()) {
 		/* For clients connect our wrapper sighandlers */
 		proxy = purple_object_get_dbus_obj_proxy(PURPLE_OBJECT(account));
diff --git a/libpurple/pobject.c b/libpurple/pobject.c
--- a/libpurple/pobject.c
+++ b/libpurple/pobject.c
@@ -425,13 +425,48 @@
 	g_value_unset(&prop_val2);
 }
 
+/* Helps purple_object_forward_notify_cb() below.
+   This should be handled by glib somehow, but for the moment
+   it lacks type-independant gvalue/gvariant conversion tools. */
+typedef struct {
+	GType gtype;
+	const GVariantType *gvariant;
+} gtype_gvariant;
+const GVariantType*
+_g_variant_type_from_gvalue(GValue *value)
+{
+	static gtype_gvariant conversion_table[] =
+	  { { G_TYPE_BOOLEAN, G_VARIANT_TYPE_BOOLEAN },
+	    { G_TYPE_CHAR,    G_VARIANT_TYPE_BYTE    },
+	    { G_TYPE_UCHAR,   G_VARIANT_TYPE_BYTE    },
+	    { G_TYPE_INT,     G_VARIANT_TYPE_INT32   },
+	    { G_TYPE_UINT,    G_VARIANT_TYPE_UINT32  },
+	    { G_TYPE_INT64,   G_VARIANT_TYPE_INT64   },
+	    { G_TYPE_UINT64,  G_VARIANT_TYPE_UINT64  },
+	    { G_TYPE_DOUBLE,  G_VARIANT_TYPE_DOUBLE  },
+	    { G_TYPE_STRING,  G_VARIANT_TYPE_STRING  },
+	    { G_TYPE_VARIANT, G_VARIANT_TYPE_VARIANT },
+	    { 0, NULL } };
+	gtype_gvariant *iter = conversion_table;
+	while (iter) {
+		if (G_VALUE_TYPE(value) == iter->gtype)
+			return iter->gvariant;
+		iter++;
+	}
+	return NULL;
+}
+
 static void
 purple_object_forward_notify_cb(GObject *gobj, GParamSpec *pspec, gpointer user_data)
 {
 	gchar *prop_name;
 	GValue prop_val = {0, };
 	GValue prop_val2 = {0, };
-	gchar *interface;
+	GVariant *prop;
+	GVariant *signal_params;
+	char *object_path;
+	GDBusInterfaceInfo *ifaceinfo;
+	GDBusConnection *connection;
 
 	/* Note that this "notify" signal may occur even if the property havn't
 	 * changed (when one sets it to its previous value). This can constitute
@@ -439,11 +474,18 @@
 	 * avoid it.
 	 */
 
+	/* Check if we are on DBus. Not having a connection can happen
+	   during purple initialization, when object properties are
+	   modified whereas the bus name is not acquired yet.
+	   Not a problem at all. */
+	connection = purple_gdbus_get_connection();
+	if (!connection)
+		return;
+
 	/* Check if we want to tell clients about this property change */
-	interface = purple_object_get_dbus_obj_interface(PURPLE_OBJECT(gobj));
 	prop_name = g_param_spec_get_name(pspec);
-	if (!purple_object_have_dbus_property(PURPLE_OBJECT(gobj), interface,
-					prop_name))
+	ifaceinfo = PURPLE_OBJECT_GET_CLASS(gobj)->dbus_ifaceinfo;
+	if (!g_dbus_interface_info_lookup_property(ifaceinfo, prop_name))
 		return;
 
 	/* Get the property. */
@@ -464,7 +506,16 @@
 	/* Forward this property change to the clients */
 	purple_debug_info("dbus", "Sending notify about property '%s' of a %s\n",
 			prop_name, G_OBJECT_TYPE_NAME(gobj));
-	g_signal_emit(gobj, signals[SIG_DBUS_NOTIFY], 0, prop_name, &prop_val2);
+	prop = g_dbus_gvalue_to_gvariant(&prop_val2,
+	                                 _g_variant_type_from_gvalue(&prop_val2));
+
+	signal_params = g_variant_new("(sv)", prop_name, prop);
+	object_path = purple_object_get_dbus_path(PURPLE_OBJECT(gobj));
+	g_dbus_connection_emit_signal(connection, NULL,
+	                              object_path, ifaceinfo->name,
+	                              "PropertyChanged", signal_params, NULL);
+	g_variant_unref(prop);
+	g_variant_unref(signal_params);
 	g_value_unset(&prop_val2);
 }
 
@@ -534,6 +585,17 @@
 }
 
 void
+purple_object_dbus_bind_notify(PurpleObject *pobj)
+{
+	if (purple_core_is_remote_mode() || purple_core_is_mirror_mode()) {
+		/* TODO */	
+	} else if (purple_core_is_daemon_mode())
+		g_signal_connect(pobj, "notify",
+		                 G_CALLBACK(purple_object_forward_notify_cb),
+		                 NULL);
+}
+
+void
 purple_object_bind_dbus_method(PurpleObjectClass *klass,
                                const char *method_name,
                                GCallback func)
diff --git a/libpurple/pobject.h b/libpurple/pobject.h
--- a/libpurple/pobject.h
+++ b/libpurple/pobject.h
@@ -204,6 +204,17 @@
                                     GCallback          func);
 
 /**
+ * Makes the relevant object properties changes to be transmitted over DBus.
+ * "Relevant" properties are the one listed in the matching XML file of the
+ * PurpleObject subclass, e.g. account.xml. In client context, it binds a
+ * DBus signal handler that receives properties changes. In daemon context,
+ * it propagates the properties changes with a DBus signal.
+ *
+ * @param pobj The PurpleObject we want to bind notifications for.
+ */
+void purple_object_dbus_bind_notify(PurpleObject *pobj);
+
+/**
  * Gets the GClosure created to handle the call of the DBus method
  * named method_name.
  *



More information about the Commits mailing list