cpw.gillux.detachablepurple: b5cd4d96: Updated the code that propagates object ...

gillux at soc.pidgin.im gillux at soc.pidgin.im
Thu May 26 22:40:42 EDT 2011


----------------------------------------------------------------------
Revision: b5cd4d96e89d8b29bbbf29186651f77f6df59489
Parent:   46010b7adbcbe82ca21875208647e41747af2915
Author:   gillux at soc.pidgin.im
Date:     05/26/11 22:07:10
Branch:   im.pidgin.cpw.gillux.detachablepurple
URL: http://d.pidgin.im/viewmtn/revision/info/b5cd4d96e89d8b29bbbf29186651f77f6df59489

Changelog: 

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.

Changes against parent 46010b7adbcbe82ca21875208647e41747af2915

  patched  libpurple/dbus/account.c
  patched  libpurple/pobject.c
  patched  libpurple/pobject.h

-------------- next part --------------
============================================================
--- libpurple/pobject.c	c2cbab2af6956d41806b11b0fa87bac34dc38228
+++ libpurple/pobject.c	f60b53eaef7fba2435bd1a45b7380ca229fa6854
@@ -425,13 +425,48 @@ purple_object_notify_cb(DBusGProxy *prox
 	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 @@ purple_object_forward_notify_cb(GObject 
 	 * 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 @@ purple_object_forward_notify_cb(GObject 
 	/* 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
 }
 
 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)
============================================================
--- libpurple/pobject.h	24c4843b1462207bb851e2e9fe078db137d99422
+++ libpurple/pobject.h	71f1962d0d117982b283bf7385b563ed7b567c6b
@@ -204,6 +204,17 @@ void purple_object_bind_dbus_method(Purp
                                     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.
  *
============================================================
--- libpurple/dbus/account.c	c9b9d945437f34ebb901ba8796c94cd7eac3e3cf
+++ libpurple/dbus/account.c	4ab02c910d51b65df459e5a688b5c013c6360ac7
@@ -227,6 +227,8 @@ purple_account_dbus_init(PurpleAccount *
 	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));


More information about the Commits mailing list