soc.2010.detachablepurple: 729a8d40: Added a new dbus method to grab all the ...

gillux at soc.pidgin.im gillux at soc.pidgin.im
Thu Jul 15 17:35:48 EDT 2010


----------------------------------------------------------------------
Revision: 729a8d40bc3b49c16ae374cb02294364e7b71aa4
Parent:   a254ef1c2e90cb2fb355cc506748177983700148
Author:   gillux at soc.pidgin.im
Date:     07/15/10 15:37:18
Branch:   im.pidgin.soc.2010.detachablepurple
URL: http://d.pidgin.im/viewmtn/revision/info/729a8d40bc3b49c16ae374cb02294364e7b71aa4

Changelog: 

Added a new dbus method to grab all the accounts from the daemon (daemon
part). It aims to be called remotely, packs everything that will be needed
to create an account in a single argument, and returns it.
Updated the dbus-constructor.c comments accordingly.
Fixed the PurpleConstructor parent type (was GObject, now PurpleObject).
Added #ifdef HAVE_DBUS around dbus-constructor.h code, so that it should be
able to be included without dbus support.

Changes against parent a254ef1c2e90cb2fb355cc506748177983700148

  patched  libpurple/dbus-constructor.c
  patched  libpurple/dbus-constructor.h
  patched  libpurple/dbus-prototypes/constructor.xml

-------------- next part --------------
============================================================
--- libpurple/dbus-constructor.c	09aa1f02691374dcb4b31fabc39de2fef2ee1c02
+++ libpurple/dbus-constructor.c	cb39a2c74a5c78982ef679844a67a1bc0a66e35e
@@ -21,22 +21,26 @@
 
 #include <dbus/dbus-glib-bindings.h>
 
+#include "internal.h"
+#include "account.h"
+#include "accountlist.h"
 #include "dbus-constructor.h"
 #include "dbus-constructor-server.h"
+#include "dbus-maybe.h"
 
-#include "account.h"
 
 /**
- * PurpleConstructor, a dummy class to remotely create gobjects over DBus.
+ * PurpleConstructor, a dummy class to remotely create and load gobjects over DBus.
  *
  * The DBus glib bindings allows to publish your gobjects on DBus. You can then
  * call their methods and get/set their properties. But this only works for
  * instantiated gobjects. So when you want to instantiate an object remotely,
- * using an RPC, you also need to do this on some instantiated object.
+ * or to copy an existing remote object locally, using an RPC, you also need
+ * to do this on some instantiated object.
  *
  * This is what this PurpleConstructor class is intended to do. It allows
- * you to remotely create gobjects over dbus. Therefore, there is only one
- * PurpleConstructor created for the whole program - the one held by
+ * you to remotely create and load gobjects over dbus. Therefore, there is
+ * only one PurpleConstructor created for the whole program - the one held by
  * purple_constructor_get_instance(). Over dbus this object is named
  * /im/pidgin/purple/constructor.
  *
@@ -48,7 +52,7 @@
  * dbus-prototypes/constructor.xml.
  */
 
-G_DEFINE_TYPE(PurpleConstructor, purple_constructor, G_TYPE_OBJECT)
+G_DEFINE_TYPE(PurpleConstructor, purple_constructor, PURPLE_TYPE_OBJECT)
 
 static void purple_constructor_init(PurpleConstructor* obj) {
 
@@ -86,3 +90,136 @@ DBUS_purple_constructor_new_account(Purp
 	}
 }
 
+/**
+ * A callback used in pack_accounts_cb().
+ * Packs the given prop_name named property into a
+ * { prop_name, prop_gvalue } dbus structure and append it in props_pack.
+ */
+static void
+pack_account_prop_cb(char *prop_name, PurpleAccount *acc, GPtrArray *props_pack)
+{
+	GValue prop = {0, };
+	GValue prop_val = {0, };
+	GParamSpec *prop_spec;
+	gboolean ok;
+
+	/* Each property consists of a DBUS_STRUCT_PROPERTY */
+	g_value_init(&prop, DBUS_STRUCT_PROPERTY);
+	g_value_take_boxed(&prop, dbus_g_type_specialized_construct(
+			DBUS_STRUCT_PROPERTY));
+
+	/* First find out the property GType */
+	prop_spec = g_object_class_find_property(G_OBJECT_GET_CLASS(acc),
+						prop_name);
+	g_return_if_fail(prop_spec != NULL);
+	g_value_init(&prop_val, G_PARAM_SPEC_VALUE_TYPE(prop_spec));
+	/* Then get it */
+	g_object_get_property(G_OBJECT(acc), prop_name,	&prop_val);
+
+	/* Setup the DBus struct, with our extracted data */
+	ok = dbus_g_type_struct_set(&prop,
+				0, prop_name,
+				1, &prop_val,
+				G_MAXUINT);
+	g_value_unset(&prop_val);
+	g_return_if_fail(ok == TRUE);
+
+	/* Finally append this fresh struct to the array */
+	g_ptr_array_add(props_pack, g_value_get_boxed(&prop));
+}
+
+/* We can't include dbus-account-server.h twice in libpurple or it produces an
+ * error when linking. For here we use an extern definition instead.
+ */
+extern const DBusGObjectInfo dbus_glib_DBUS_purple_account_object_info;
+
+/**
+ * A callback used in DBUS_purple_constructor_get_all_accounts().
+ * Packs the given acc account into a { protocol_id, account_struct } dbus
+ * structure and append it in accounts_pack.
+ */
+static void
+pack_accounts_cb(PurpleAccount *acc, GPtrArray *accounts_pack, GPtrArray *exported_props)
+{
+	GValue acc_props = {0, };
+	char *prop_name;
+	GPtrArray* props_pack = g_ptr_array_new();
+	int i;
+	gboolean ok;
+
+	g_return_if_fail(props_pack != NULL);
+
+	/* Each account consists of a DBUS_STRUCT_ACCOUNT */
+	g_value_init(&acc_props, DBUS_STRUCT_ACCOUNT);
+	g_value_set_boxed(&acc_props,
+			dbus_g_type_specialized_construct(DBUS_STRUCT_ACCOUNT));
+
+	/* Fill props_pack with every property of acc */
+	for (i = 0; i < exported_props->len; i++) {
+		prop_name = exported_props->pdata[i];
+		pack_account_prop_cb(prop_name, acc, props_pack);
+	}
+
+	/* Setup the DBus struct, with our extracted data */
+	ok = dbus_g_type_struct_set(&acc_props,
+				0, purple_account_get_protocol_id(acc),
+				1, props_pack,
+				G_MAXUINT);
+	g_ptr_array_foreach(props_pack, (GFunc)g_value_array_free, NULL);
+	g_ptr_array_free(props_pack, TRUE);
+	g_return_if_fail(ok == TRUE);
+
+	/* Finally append this fresh struct to the array */
+	g_ptr_array_add(accounts_pack, g_value_get_boxed(&acc_props));
+}
+
+/**
+ * This is what is actually called when someone calls the dbus method
+ * GetAllAccounts. It packs the accounts and their properties in the
+ * glib-dbus data format.
+ */
+gboolean
+DBUS_purple_constructor_get_all_accounts(PurpleConstructor* con, GPtrArray** accounts, GError** error)
+{
+	PurpleAccount *acc;
+	GPtrArray *exported_props = NULL;
+	GList *glist_accs;
+	char *interface;
+
+	/* We send an array of accounts. The complete data format, as
+	 * defined in dbus-constructor.h, is something like :
+	 * GPtrArray *account = [
+	 *     struct {
+	 *         char      *protocol_id; // Needed to properly g_object_new()
+	 *         GPtrArray *properties [
+	 *             struct {
+	 *                char   *property_name;
+	 *                GValue *property_value; 
+	 *             }
+	 *         ];
+	 *     }
+	 * ]
+	 */
+	*accounts = g_ptr_array_new();
+	g_return_val_if_fail(*accounts != NULL, FALSE);
+
+	/* Fill *accounts with every account */
+	glist_accs = purple_accounts_all();
+	for (; glist_accs; glist_accs = glist_accs->next) {
+		acc = glist_accs->data;
+
+		if (!exported_props) {
+			/* Grab all the properties names */
+			interface = purple_object_get_dbus_obj_interface(PURPLE_OBJECT(acc));
+			exported_props = purple_dbus_get_gobj_props(interface,
+				&dbus_glib_DBUS_purple_account_object_info);
+
+		}
+		pack_accounts_cb(acc, *accounts, exported_props);
+	}
+	g_ptr_array_foreach(exported_props, (GFunc)g_free, NULL);
+	g_ptr_array_free(exported_props, TRUE);
+
+	return TRUE;
+}
+
============================================================
--- libpurple/dbus-constructor.h	41553047ac0137c9975de1950b967621d257525e
+++ libpurple/dbus-constructor.h	bd334697ba1cec9544763dc50d06b422d203a47a
@@ -23,6 +23,8 @@
 
 #include "pobject.h"
 
+#ifdef HAVE_DBUS
+
 /* GObject definitions */
 
 #define PURPLE_TYPE_CONSTRUCTOR         (purple_constructor_get_type())
@@ -37,6 +39,25 @@ typedef struct {
 	PurpleObject parent;
 } PurpleConstructor;
 
+/* DBus transfered data formats */
+
+#define DBUS_STRUCT_PROPERTY \
+( \
+	dbus_g_type_get_struct("GValueArray", \
+		G_TYPE_STRING, G_TYPE_VALUE, G_TYPE_INVALID) \
+)
+#define DBUS_COLLECTION_PROPS \
+( \
+	dbus_g_type_get_collection("GPtrArray", \
+		DBUS_STRUCT_PROPERTY) \
+)
+#define DBUS_STRUCT_ACCOUNT \
+( \
+	dbus_g_type_get_struct("GValueArray", \
+		G_TYPE_STRING, DBUS_COLLECTION_PROPS, \
+		G_TYPE_INVALID) \
+)
+
 G_BEGIN_DECLS
 
 PurpleConstructor* purple_constructor_get_instance(void);
@@ -46,7 +67,14 @@ gboolean DBUS_purple_constructor_new_acc
  */
 gboolean DBUS_purple_constructor_new_account(PurpleConstructor *con, gchar* username, gchar* protocol_id, gchar **account_path, GError** error);
 
+/**
+ * What gets actually called when you call GetAllAccounts over dbus.
+ */
+gboolean DBUS_purple_constructor_get_all_accounts(PurpleConstructor* con, GPtrArray** accounts, GError** error);
+
 G_END_DECLS
 
+#endif /* HAVE_DBUS */
+
 #endif /* _DBUS_CONSTRUCTOR_H_ */
 
============================================================
--- libpurple/dbus-prototypes/constructor.xml	0bf4b150a76e65b7a96d7bfbf741931a18ae2b05
+++ libpurple/dbus-prototypes/constructor.xml	43bccf4ca2b3a020e5ef8041bb43d3b1ad3b9ee6
@@ -7,5 +7,8 @@
 			<arg type="s" name="username"    direction="in" />
 			<arg type="s" name="protocol_id" direction="in" />
 		</method>
+		<method name="GetAllAccounts">
+			<arg type="a(sa(sv))" name="accounts" direction="out" />
+		</method>
 	</interface>
 </node>


More information about the Commits mailing list