soc.2010.detachablepurple: bc886588: Added the new GetBuddyList dbus method -...

gillux at soc.pidgin.im gillux at soc.pidgin.im
Mon Aug 9 23:58:42 EDT 2010


----------------------------------------------------------------------
Revision: bc886588a0be43d28804bf9bb9cc3259691f7aac
Parent:   e071748c3c086a743a68ced010f2c62758c0219d
Author:   gillux at soc.pidgin.im
Date:     08/08/10 12:40:04
Branch:   im.pidgin.soc.2010.detachablepurple
URL: http://d.pidgin.im/viewmtn/revision/info/bc886588a0be43d28804bf9bb9cc3259691f7aac

Changelog: 

Added the new GetBuddyList dbus method - server side only. It will be used by
clients to load their buddy list from the daemon.

Changes against parent e071748c3c086a743a68ced010f2c62758c0219d

  patched  libpurple/dbus/blist.c
  patched  libpurple/dbus/blist.xml

-------------- next part --------------
============================================================
--- libpurple/dbus/blist.c	9b375eb3b2dabe6cc0d5c2d05be24f1bd780ae9f
+++ libpurple/dbus/blist.c	17d1b295884f98ed97b75e8c79e13097e28a0728
@@ -23,9 +23,9 @@
 
 #include "internal.h"
 #include "blist.h"
+#include "blist-node.h"
 #include "core.h"
 #include "dbus/blist.h"
-#include "dbus/blist-server.h"
 #include "dbus-purple.h"
 
 /**
@@ -58,6 +58,51 @@ G_DEFINE_TYPE(PurpleBListDBus, purple_bl
 
 G_DEFINE_TYPE(PurpleBListDBus, purple_blist_dbus, PURPLE_TYPE_OBJECT)
 
+/* Server side dbus methods.
+ * Theses functions needs PurpleBListDBus declared, and must go before the
+ * inclusion of blist-server.h, in which they are defined. */
+gboolean DBUS_purple_blist_get_buddy_list(PurpleBListDBus *blist, GPtrArray **groups, GPtrArray **contacts, GPtrArray **buddies, GPtrArray **chats, GError** error);
+#include "dbus/blist-server.h"
+
+/* DBus transfered data formats */
+#define DBUS_PURPLE_BLIST_SETTING \
+( \
+	dbus_g_type_get_struct("GValueArray", \
+		G_TYPE_STRING, G_TYPE_VALUE, G_TYPE_INVALID) \
+)
+#define DBUS_PURPLE_BLIST_SETTINGS \
+( \
+	dbus_g_type_get_collection("GPtrArray", \
+		DBUS_PURPLE_BLIST_SETTING) \
+)
+#define DBUS_PURPLE_GROUP_PACK \
+( \
+	dbus_g_type_get_struct("GValueArray", \
+		G_TYPE_STRING, DBUS_PURPLE_BLIST_SETTINGS, G_TYPE_INVALID) \
+)
+#define DBUS_PURPLE_CONTACT_PACK \
+( \
+	dbus_g_type_get_struct("GValueArray", \
+		G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, \
+		DBUS_PURPLE_BLIST_SETTINGS, G_TYPE_INVALID) \
+)
+#define DBUS_PURPLE_BUDDY_PACK \
+( \
+	dbus_g_type_get_struct("GValueArray", \
+		G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, \
+		G_TYPE_STRING, DBUS_PURPLE_BLIST_SETTINGS, G_TYPE_INVALID) \
+)
+#define DBUS_PURPLE_CHAT_PACK \
+( \
+	dbus_g_type_get_struct("GValueArray", \
+		G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, \
+		DBUS_TYPE_G_STRING_STRING_HASHTABLE, G_TYPE_STRING, \
+		DBUS_PURPLE_BLIST_SETTINGS, G_TYPE_INVALID) \
+)
+
+/* A convenience macro. */
+#define parent_node_dbus_path(node) purple_object_get_dbus_path(PURPLE_OBJECT(purple_blist_node_parent(node)))
+
 static void
 purple_blist_dbus_init(PurpleBListDBus *self)
 {
@@ -110,3 +155,240 @@ purple_blist_uninit_dbus(void)
 	g_return_if_fail(klass->instance != NULL);
 	g_object_unref(klass->instance);
 }
+
+/**
+ * Callback used by settings_to_ptr_array().
+ * Builds a DBUS_PURPLE_BLIST_SETTING struct, to export a setting on dbus.
+ */
+static void
+blist_setting_to_array(const char *name, GValue *value, GPtrArray *settings)
+{
+	GValue setting = {0, };
+	gboolean ok;
+
+	g_value_init(&setting, DBUS_PURPLE_BLIST_SETTING);
+	g_value_take_boxed(&setting,
+	         dbus_g_type_specialized_construct(DBUS_PURPLE_BLIST_SETTING));
+	ok = dbus_g_type_struct_set(&setting, 0, name, 1, value, G_MAXUINT);
+
+	g_return_if_fail(ok == TRUE);
+	g_ptr_array_add(settings, g_value_get_boxed(&setting));
+}
+
+/**
+ * Converts the settings of the provided PurpleBlistNode into a
+ * DBUS_PURPLE_BLIST_SETTINGS GPtrArray (array of GValues), to export them on
+ * dbus. Caller is responsible for freeing the array and the GValues in it.
+ * Used to pack data in DBUS_purple_blist_get_buddy_list().
+ */
+static GPtrArray *
+settings_to_ptr_array(PurpleBlistNode *node)
+{
+	GPtrArray *array;
+	GHashTable *settings_hash;
+
+	array = g_ptr_array_new();
+	settings_hash = purple_blist_node_get_settings(PURPLE_BLIST_NODE(node));
+	g_hash_table_foreach(settings_hash,
+	                     (GHFunc)blist_setting_to_array, array);
+	return array;
+}
+
+/**
+ * Packs a PurpleGroup in a DBUS_PURPLE_GROUP_PACK struct,
+ * to export it on dbus, and append it in the provided groups array.
+ * Used to pack data in DBUS_purple_blist_get_buddy_list().
+ */
+static void
+pack_group(GPtrArray *groups, PurpleGroup *group)
+{
+	GValue group_pack = {0, };
+	gboolean ok;
+	const char *group_name;
+	GPtrArray *settings_pack;
+
+	g_value_init(&group_pack, DBUS_PURPLE_GROUP_PACK);
+	g_value_set_boxed(&group_pack,
+	            dbus_g_type_specialized_construct(DBUS_PURPLE_GROUP_PACK));
+
+	group_name = purple_group_get_name(group);
+	settings_pack = settings_to_ptr_array(PURPLE_BLIST_NODE(group));
+	ok = dbus_g_type_struct_set(&group_pack,
+	                            0, group_name,
+	                            1, settings_pack, G_MAXUINT);
+
+	g_ptr_array_foreach(settings_pack, (GFunc)g_value_array_free, NULL);
+	g_ptr_array_free(settings_pack, TRUE);
+
+	g_return_if_fail(ok == TRUE);
+	g_ptr_array_add(groups, g_value_get_boxed(&group_pack));
+}
+
+/**
+ * Packs a PurpleContact in a DBUS_PURPLE_CONTACT_PACK struct,
+ * to export it on dbus, and append it in the provided contacts array.
+ * Used to pack data in DBUS_purple_blist_get_buddy_list().
+ */
+static void
+pack_contact(GPtrArray *contacts, PurpleContact *contact)
+{
+	GValue contact_pack = {0, };
+	gboolean ok;
+	char* contact_path;
+	const char *alias;
+	char *parent_path;
+	GPtrArray *settings_pack;
+
+	g_value_init(&contact_pack, DBUS_PURPLE_CONTACT_PACK);
+	g_value_set_boxed(&contact_pack,
+	          dbus_g_type_specialized_construct(DBUS_PURPLE_CONTACT_PACK));
+
+	contact_path = purple_object_get_dbus_path(PURPLE_OBJECT(contact));
+	alias = purple_contact_get_alias(contact);
+	parent_path = parent_node_dbus_path(PURPLE_BLIST_NODE(contact));
+	settings_pack = settings_to_ptr_array(PURPLE_BLIST_NODE(contact));
+	ok = dbus_g_type_struct_set(&contact_pack,
+	                            0, contact_path,
+	                            1, alias,
+	                            2, parent_path,
+	                            3, settings_pack, G_MAXUINT);
+
+	g_ptr_array_foreach(settings_pack, (GFunc)g_value_array_free, NULL);
+	g_ptr_array_free(settings_pack, TRUE);
+
+	g_return_if_fail(ok == TRUE);
+	g_ptr_array_add(contacts, g_value_get_boxed(&contact_pack));
+}
+
+/**
+ * Packs a PurpleBuddy in a DBUS_PURPLE_BUDDY_PACK struct,
+ * to export it on dbus, and append it in the provided buddies array.
+ * Used to pack data in DBUS_purple_blist_get_buddy_list().
+ */
+static void
+pack_buddy(GPtrArray *buddies, PurpleBuddy *buddy)
+{
+	GValue buddy_pack = {0, };
+	gboolean ok;
+	char *buddy_path;
+	char *account_path;
+	const char *name;
+	const char *alias;
+	char *parent_path;
+	GPtrArray *settings_pack;
+
+	g_value_init(&buddy_pack, DBUS_PURPLE_BUDDY_PACK);
+	g_value_set_boxed(&buddy_pack,
+	          dbus_g_type_specialized_construct(DBUS_PURPLE_BUDDY_PACK));
+
+	buddy_path   = purple_object_get_dbus_path(PURPLE_OBJECT(buddy));
+	account_path = purple_object_get_dbus_path(
+	                      PURPLE_OBJECT(purple_buddy_get_account(buddy)));
+	name  = purple_buddy_get_name(buddy);
+	alias = purple_buddy_get_alias_only(buddy);
+	parent_path = parent_node_dbus_path(PURPLE_BLIST_NODE(buddy));
+	settings_pack = settings_to_ptr_array(PURPLE_BLIST_NODE(buddy));
+	ok = dbus_g_type_struct_set(&buddy_pack,
+	                            0, buddy_path,
+	                            1, account_path,
+	                            2, name,
+	                            3, alias,
+	                            4, parent_path,
+	                            5, settings_pack, G_MAXUINT);
+
+	g_ptr_array_foreach(settings_pack, (GFunc)g_value_array_free, NULL);
+	g_ptr_array_free(settings_pack, TRUE);
+
+	g_return_if_fail(ok == TRUE);
+	g_ptr_array_add(buddies, g_value_get_boxed(&buddy_pack));
+}
+
+/**
+ * Packs a PurpleChat in a DBUS_PURPLE_CHAT_PACK struct,
+ * to export it on dbus, and append it in the provided chats array.
+ * Used to pack data in DBUS_purple_blist_get_buddy_list().
+ */
+static void
+pack_chat(GPtrArray *chats, PurpleChat *chat)
+{
+	GValue chat_pack = {0, };
+	gboolean ok;
+	char *chat_path;
+	char *account_path;
+	const char *alias;
+	GHashTable *components;
+	char *parent_path;
+	GPtrArray *settings_pack;
+
+	g_value_init(&chat_pack, DBUS_PURPLE_CHAT_PACK);
+	g_value_set_boxed(&chat_pack,
+	          dbus_g_type_specialized_construct(DBUS_PURPLE_CHAT_PACK));
+
+	chat_path    = purple_object_get_dbus_path(PURPLE_OBJECT(chat));
+	account_path = purple_object_get_dbus_path(
+	                        PURPLE_OBJECT(purple_chat_get_account(chat)));
+	alias        = purple_chat_get_alias(chat);
+	components   = purple_chat_get_components(chat);
+	parent_path  = parent_node_dbus_path(PURPLE_BLIST_NODE(chat));
+	settings_pack = settings_to_ptr_array(PURPLE_BLIST_NODE(chat));
+	ok = dbus_g_type_struct_set(&chat_pack,
+	                            0, chat_path,
+	                            1, account_path,
+	                            2, alias,
+	                            3, components,
+	                            4, parent_path,
+	                            5, settings_pack, G_MAXUINT);
+
+	g_ptr_array_foreach(settings_pack, (GFunc)g_value_array_free, NULL);
+	g_ptr_array_free(settings_pack, TRUE);
+
+	g_return_if_fail(ok == TRUE);
+	g_ptr_array_add(chats, g_value_get_boxed(&chat_pack));
+}
+
+/**
+ * Recursive function. Goes through the buddy list and fills the GPtrArrays
+ * from what it encounter.
+ * Used to pack data in purple_blist_get_buddy_list_RPC().
+ */
+static void
+pack_node(PurpleBlistNode *node, GPtrArray *groups, GPtrArray *contacts,
+          GPtrArray *buddies, GPtrArray *chats)
+{
+	PurpleBlistNode *child;
+
+	while (node) {
+		if (PURPLE_IS_GROUP(node)) {
+			pack_group(groups, PURPLE_GROUP(node));
+		} else if(PURPLE_IS_CONTACT(node)) {
+			pack_contact(contacts, PURPLE_CONTACT(node));
+		} else if(PURPLE_IS_BUDDY(node)) {
+		    pack_buddy(buddies, PURPLE_BUDDY(node));
+		} else if(PURPLE_IS_CHAT(node)) {
+		    pack_chat(chats, PURPLE_CHAT(node));
+		}
+
+		child = purple_blist_node_first_child(node);
+		if (child)
+			pack_node(child, groups, contacts, buddies, chats);
+
+		node = purple_blist_node_next(node);
+	}
+}
+
+gboolean
+DBUS_purple_blist_get_buddy_list(PurpleBListDBus *blist, GPtrArray **groups,
+                                 GPtrArray **contacts, GPtrArray **buddies,
+                                 GPtrArray **chats, GError** error)
+{
+        PurpleBlistNode *node;
+
+	*groups   = g_ptr_array_new();
+	*contacts = g_ptr_array_new();
+	*buddies  = g_ptr_array_new();
+	*chats    = g_ptr_array_new();
+	node = purple_blist_get_root();
+	pack_node(purple_blist_get_root(),
+	          *groups, *contacts, *buddies, *chats);
+	return TRUE;
+}
============================================================
--- libpurple/dbus/blist.xml	56900a2b6fe7f5483ad9d40112b3e034bc82cbb4
+++ libpurple/dbus/blist.xml	0096598a98100c297b0759050c79abe190d03e18
@@ -1,5 +1,23 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <node name="/im/pidgin/purple/blist">
 	<interface name="im.pidgin.purple.blist">
+		<method name="GetBuddyList">
+			<!-- group: s = group name; a(sv) = settings -->
+			<arg type="a(sa(sv))" name="groups" direction="out" />
+			<!-- contact: s = contact path name; s = alias;
+			              s = parent path name; a(sv) = settings -->
+			<arg type="a(sssa(sv))" name="contacts"
+			     direction="out" />
+			<!-- buddy: s = buddy path name; s = account; s = name;
+			            s = alias; s = parent path name;
+			            a(sv) = settings -->
+			<arg type="a(sssssa(sv))" name="buddies"
+			     direction="out" />
+			<!-- chat: s = chat path name; s = account; s = alias;
+			           a{ss} = components; s = parent path name;
+			           a(sv) = settings -->
+			<arg type="a(sssa{ss}sa(sv))" name="chats"
+			     direction="out" />
+		</method>
 	</interface>
 </node>


More information about the Commits mailing list