cpw.gillux.detachablepurple: 024d1924: Rewritten the "GetBuddyList" D-Bus metho...
gillux at soc.pidgin.im
gillux at soc.pidgin.im
Sun May 20 13:20:53 EDT 2012
----------------------------------------------------------------------
Revision: 024d19242602fd188011bbb4d9849e65b8d4a10f
Parent: 1cceaeb7d3d76f2a6a6a424a65cef49fe8fb2cf9
Author: gillux at soc.pidgin.im
Date: 05/20/12 12:45:05
Branch: im.pidgin.cpw.gillux.detachablepurple
URL: http://d.pidgin.im/viewmtn/revision/info/024d19242602fd188011bbb4d9849e65b8d4a10f
Changelog:
Rewritten the "GetBuddyList" D-Bus method for the new gdbus-based API.
Much more simpler and cleaner. :)
Changes against parent 1cceaeb7d3d76f2a6a6a424a65cef49fe8fb2cf9
patched libpurple/blist.c
patched libpurple/dbus/blist.c
patched libpurple/dbus/blist.h
patched libpurple/dbus/blist.xml
patched libpurple/dbus/constructor.c
-------------- next part --------------
============================================================
--- libpurple/blist.c 5c60239af51f3caae935f756237bc680520cae71
+++ libpurple/blist.c 408e31c454e4cd726b961dac67e33bb005469af1
@@ -25,6 +25,7 @@
#include "internal.h"
#include "accountlist.h"
+#include "blist.h"
#include "dbus-maybe.h"
#include "dbus/blist.h"
#include "debug.h"
@@ -398,7 +399,7 @@ purple_blist_load()
/* In remote mode, get the buddy list from the daemon instead. */
if (purple_core_is_remote_mode())
- return purple_blist_load_RPC();
+ return purple_blist_load_RPC(PURPLE_OBJECT(PURPLE_BLIST));
purple = purple_util_read_xml_from_file("blist.xml", _("buddy list"));
============================================================
--- libpurple/dbus/constructor.c 541fbb8647299455e608f15334fa3c8a84b4a82c
+++ libpurple/dbus/constructor.c cc724c41d602cddceb2a3cd1e347e8c623912b37
@@ -351,14 +351,21 @@ purple_constructor_foreach_pobjects(GVar
GVariantIter iter;
GVariant *array, *pobject;
- g_variant_get(box, "(@a(oa(sv)))", &array);
+ /* Some callers may box the variant in a tuple, while others may not. */
+ if (g_variant_type_is_tuple(g_variant_get_type(box)))
+ g_variant_get(box, "(@a(oa(sv)))", &array);
+ else
+ array = box;
g_variant_iter_init(&iter, array);
while ((pobject = g_variant_iter_next_value(&iter)) != NULL) {
treatment(pobject, user_data);
g_variant_unref(pobject);
}
- g_variant_unref(array);
+
+ /* Only free the array if it has been unpacked. */
+ if (array != box)
+ g_variant_unref(array);
}
/**
============================================================
--- libpurple/dbus/blist.c 59804fdab8fca26208b4df3adf127547847e4921
+++ libpurple/dbus/blist.c 6176cc9fe81b5dc805f584063830973f792c87e2
@@ -26,55 +26,18 @@
#include "blist-node.h"
#include "core.h"
#include "dbus/blist.h"
-#include "dbus/blist-client.h"
#include "dbus/blist.xml.h"
+#include "dbus/constructor.h"
#include "dbus-maybe.h"
#include "dbus-purple.h"
+/* The type PurpleBuddyList is only defined in libpurple/blist.c. While we
+ * don't strictly need it, we use it here and there for the sake of
+ * consistency. Hence this dummy type definition: */
+typedef void PurpleBlist;
-/* 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"
+static GVariant * purple_blist_get_buddy_list(PurpleBlist *blist);
-/* 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, 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)))
@@ -105,222 +68,37 @@ purple_blist_class_dbus_init(PurpleObjec
pobjclass->build_dbus_path = purple_blist_build_dbus_path;
if (purple_core_is_daemon_mode()) {
+ /* D-Bus method handlers. */
+ purple_object_bind_dbus_callback
+ (pobjclass, purple_blist_interface_info.name,
+ "GetBuddyList", (GCallback)purple_blist_get_buddy_list);
}
}
/**
- * Callback used by settings_to_ptr_array().
- * Builds a DBUS_PURPLE_BLIST_SETTING struct, to export a setting on dbus.
+ * Recursive function. Goes through the buddy list and fills the
+ * GVariantBuilders from what it encounters.
*/
static void
-blist_setting_to_array(const char *name, GValue *value, GPtrArray *settings)
+pack_node(PurpleBlistNode *node,
+ GVariantBuilder *groups, GVariantBuilder *contacts,
+ GVariantBuilder *buddies, GVariantBuilder *chats)
{
- 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;
- char *group_path;
- 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_path = purple_object_get_dbus_path(PURPLE_OBJECT(group));
- 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_path,
- 1, group_name,
- 2, 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));
+ g_variant_builder_add_value
+ (groups, purple_constructor_pack_pobject(node));
} else if(PURPLE_IS_CONTACT(node)) {
- pack_contact(contacts, PURPLE_CONTACT(node));
+ g_variant_builder_add_value
+ (contacts, purple_constructor_pack_pobject(node));
} else if(PURPLE_IS_BUDDY(node)) {
- pack_buddy(buddies, PURPLE_BUDDY(node));
+ g_variant_builder_add_value
+ (buddies, purple_constructor_pack_pobject(node));
} else if(PURPLE_IS_CHAT(node)) {
- pack_chat(chats, PURPLE_CHAT(node));
+ g_variant_builder_add_value
+ (chats, purple_constructor_pack_pobject(node));
}
child = purple_blist_node_first_child(node);
@@ -331,279 +109,76 @@ pack_node(PurpleBlistNode *node, GPtrArr
}
}
-gboolean
-DBUS_purple_blist_get_buddy_list(PurpleBListDBus *blist, GPtrArray **groups,
- GPtrArray **contacts, GPtrArray **buddies,
- GPtrArray **chats, GError** error)
+static GVariant *
+purple_blist_get_buddy_list(PurpleBlist *blist)
{
- PurpleBlistNode *node;
+ GVariantBuilder groups, contacts, buddies, chats;
+ PurpleBlistNode *root = purple_blist_get_root();
+ const gchar *root_path = NULL;
- *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;
-}
+ g_variant_builder_init(&groups, (const GVariantType *) "a(oa(sv))");
+ g_variant_builder_init(&contacts, (const GVariantType *) "a(oa(sv))");
+ g_variant_builder_init(&buddies, (const GVariantType *) "a(oa(sv))");
+ g_variant_builder_init(&chats, (const GVariantType *) "a(oa(sv))");
-static void
-set_blist_setting(GValueArray* box, GHashTable *settings)
-{
- GValue val = {0, };
- gboolean ok;
- char *name = NULL;
- GValue *value;
+ pack_node(purple_blist_get_root(),
+ &groups, &contacts, &buddies, &chats);
+ if (root)
+ root_path = purple_object_get_dbus_path(PURPLE_OBJECT(root));
- g_value_init(&val, DBUS_PURPLE_BLIST_SETTING);
- g_value_set_boxed(&val, box);
- ok = dbus_g_type_struct_get(&val, 0, &name, 1, &value, G_MAXUINT);
- if (ok)
- g_hash_table_replace(settings, g_strdup(name),
- purple_g_value_slice_dup(value));
- g_free(name);
- g_value_unset(&val);
- g_value_unset(value);
+ return g_variant_new("(@a(oa(sv))" /* groups */
+ "@a(oa(sv))" /* contacts */
+ "@a(oa(sv))" /* buddies */
+ "@a(oa(sv))" /* chats */
+ "o)", /* root node */
+ g_variant_builder_end(&groups),
+ g_variant_builder_end(&contacts),
+ g_variant_builder_end(&buddies),
+ g_variant_builder_end(&chats),
+ root_path);
}
-static void
-set_blist_settings(PurpleBlistNode *node, GPtrArray *settings)
-{
- g_ptr_array_foreach(settings, (GFunc)set_blist_setting,
- purple_blist_node_get_settings(node));
-}
-
-static void
-unpack_groups_cb(GValueArray* box)
-{
- GValue val = {0, };
- PurpleGroup *group;
- PurpleRunningMode mode;
- gboolean ok;
- char *group_path = NULL;
- char *group_name = NULL;
- GPtrArray *settings = NULL;
-
- /* Each group consists of a DBUS_PURPLE_GROUP_PACK */
- g_value_init(&val, DBUS_PURPLE_GROUP_PACK);
- g_value_set_boxed(&val, box);
- ok = dbus_g_type_struct_get(&val,
- 0, &group_path,
- 1, &group_name,
- 2, &settings, G_MAXUINT);
-
- if (ok && group_path[0] && group_name[0]) {
- /* Temporarly go in mirror mode and create a local group. */
- mode = purple_core_get_running_mode();
- purple_core_set_running_mode(PURPLE_RUN_MIRROR_MODE);
- group = purple_group_new(group_name);
- purple_object_install_dbus_infos(PURPLE_OBJECT(group),
- DBUS_GROUP_INTERFACE, group_path);
- set_blist_settings(PURPLE_BLIST_NODE(group), settings);
- purple_core_set_running_mode(mode);
- } else {
- purple_debug_warning("dbus", "GetBuddyList: received an invalid group\n");
- }
-
- g_free(group_path);
- g_free(group_name);
- g_ptr_array_foreach(settings, (GFunc)g_value_array_free, NULL);
- g_ptr_array_free(settings, TRUE);
- g_value_unset(&val);
- g_value_array_free(box);
-}
-
-
-static void
-unpack_contacts_cb(GValueArray* box)
-{
- GValue val = {0, };
- PurpleContact *contact;
- PurpleRunningMode mode;
- gboolean ok;
- GObject *parent;
- char *contact_path = NULL;
- char *alias = NULL;
- char *parent_path = NULL;
- GPtrArray *settings = NULL;
-
- /* Each contact consists of a DBUS_PURPLE_CONTACT_PACK */
- g_value_init(&val, DBUS_PURPLE_CONTACT_PACK);
- g_value_set_boxed(&val, box);
- ok = dbus_g_type_struct_get(&val,
- 0, &contact_path,
- 1, &alias,
- 2, &parent_path,
- 3, &settings, G_MAXUINT);
-
- if (ok && contact_path[0]) {
- /* Temporarly go in mirror mode, and create a local contact. */
- mode = purple_core_get_running_mode();
- purple_core_set_running_mode(PURPLE_RUN_MIRROR_MODE);
- contact = purple_contact_new();
- purple_object_install_dbus_infos(PURPLE_OBJECT(contact),
- DBUS_CONTACT_INTERFACE, contact_path);
- parent = purple_dbus_get_gobject_by_path(parent_path);
- if (parent)
- purple_blist_node_add_child(PURPLE_BLIST_NODE(parent),
- PURPLE_BLIST_NODE(contact));
- if (alias[0])
- purple_blist_alias_contact(contact, alias);
- set_blist_settings(PURPLE_BLIST_NODE(contact), settings);
- purple_core_set_running_mode(mode);
- } else {
- purple_debug_warning("dbus", "GetBuddyList: received an invalid contact\n");
- }
-
- g_free(contact_path);
- g_free(alias);
- g_free(parent_path);
- g_ptr_array_foreach(settings, (GFunc)g_value_array_free, NULL);
- g_ptr_array_free(settings, TRUE);
- g_value_unset(&val);
- g_value_array_free(box);
-}
-
-static void
-unpack_buddies_cb(GValueArray* box)
-{
- GValue val = {0, };
- PurpleBuddy *buddy;
- PurpleRunningMode mode;
- gboolean ok;
- GObject *parent;
- GObject *account;
- char *buddy_path = NULL;
- char *account_path = NULL;
- char *name = NULL;
- char *alias = NULL;
- char *parent_path = NULL;
- GPtrArray *settings = NULL;
-
- /* Each buddy consists of a DBUS_PURPLE_BUDDY_PACK */
- g_value_init(&val, DBUS_PURPLE_BUDDY_PACK);
- g_value_set_boxed(&val, box);
- ok = dbus_g_type_struct_get(&val,
- 0, &buddy_path,
- 1, &account_path,
- 2, &name,
- 3, &alias,
- 4, &parent_path,
- 5, &settings, G_MAXUINT);
-
- if (ok && account_path[0])
- account = purple_dbus_get_gobject_by_path(account_path);
- if (ok && buddy_path[0] && PURPLE_IS_ACCOUNT(account)) {
- /* Temporarly go in mirror mode, and create a local buddy. */
- mode = purple_core_get_running_mode();
- purple_core_set_running_mode(PURPLE_RUN_MIRROR_MODE);
- parent = purple_dbus_get_gobject_by_path(parent_path);
- buddy = purple_buddy_new(PURPLE_ACCOUNT(account), name, alias,
- PURPLE_BLIST_NODE(parent));
- purple_object_install_dbus_infos(PURPLE_OBJECT(buddy),
- DBUS_BUDDY_INTERFACE, buddy_path);
- purple_core_set_running_mode(mode);
- set_blist_settings(PURPLE_BLIST_NODE(buddy), settings);
- } else {
- purple_debug_warning("dbus", "GetBuddyList: received an invalid buddy\n");
- }
-
- g_free(buddy_path);
- g_free(account_path);
- g_free(name);
- g_free(alias);
- g_free(parent_path);
- g_ptr_array_foreach(settings, (GFunc)g_value_array_free, NULL);
- g_ptr_array_free(settings, TRUE);
- g_value_unset(&val);
- g_value_array_free(box);
-}
-
-static void
-unpack_chats_cb(GValueArray* box)
-{
- GValue val = {0, };
- PurpleChat *chat;
- PurpleRunningMode mode;
- gboolean ok;
- GObject *parent;
- GObject *account;
- char *chat_path = NULL;
- char *account_path = NULL;
- char *alias = NULL;
- GHashTable *components = NULL;
- char *parent_path = NULL;
- GPtrArray *settings = NULL;
-
- /* Each chat consists of a DBUS_PURPLE_CHAT_PACK */
- g_value_init(&val, DBUS_PURPLE_CHAT_PACK);
- g_value_set_boxed(&val, box);
- ok = dbus_g_type_struct_get(&val,
- 0, &chat_path,
- 1, &account_path,
- 2, &alias,
- 3, &components,
- 4, &parent_path,
- 5, &settings, G_MAXUINT);
-
- if (ok && account_path[0])
- account = purple_dbus_get_gobject_by_path(account_path);
- if (ok && chat_path[0] && PURPLE_IS_ACCOUNT(account) && components) {
- /* Temporarly go in mirror mode, and create a local chat. */
- mode = purple_core_get_running_mode();
- purple_core_set_running_mode(PURPLE_RUN_MIRROR_MODE);
- parent = purple_dbus_get_gobject_by_path(parent_path);
- chat = purple_chat_new(PURPLE_ACCOUNT(account), alias,
- components);
- purple_object_install_dbus_infos(PURPLE_OBJECT(chat),
- DBUS_CHAT_INTERFACE, chat_path);
- if (parent)
- purple_blist_node_add_child(PURPLE_BLIST_NODE(parent),
- PURPLE_BLIST_NODE(chat));
- purple_core_set_running_mode(mode);
- set_blist_settings(PURPLE_BLIST_NODE(chat), settings);
- } else {
- purple_debug_warning("dbus", "GetChatList: received an invalid chat\n");
- }
-
- g_free(chat_path);
- g_free(account_path);
- g_free(alias);
- g_hash_table_destroy(components);
- g_free(parent_path);
- g_ptr_array_foreach(settings, (GFunc)g_value_array_free, NULL);
- g_ptr_array_free(settings, TRUE);
- g_value_unset(&val);
- g_value_array_free(box);
-}
-
void
-purple_blist_load_RPC(void)
+purple_blist_load_RPC(PurpleObject *blist)
{
- PurpleBListDBus *blist = purple_blist_dbus_get_instance();
- DBusGProxy *proxy = purple_object_get_dbus_obj_proxy(PURPLE_OBJECT(blist));
- GError *error = NULL;
- GPtrArray *groups;
- GPtrArray *contacts;
- GPtrArray *buddies;
- GPtrArray *chats;
+ GVariant *groups, *contacts, *buddies, *chats, *root, *ret;
/* In remote mode the buddy list is already loaded by the daemon.
* We need get it here.
*/
- if(!im_pidgin_purple_blist_get_buddy_list(proxy, &groups, &contacts,
- &buddies, &chats, &error)) {
- PURPLE_RPC_FAILED(purple_blist_load, error);
- return;
- }
+ ret = purple_object_dbus_call(blist, purple_blist_interface_info.name,
+ "GetBuddyList");
+ if (!ret)
+ return; /* Likely a connection problem. */
- g_ptr_array_foreach(groups, (GFunc)unpack_groups_cb, NULL);
- g_ptr_array_foreach(contacts, (GFunc)unpack_contacts_cb, NULL);
- g_ptr_array_foreach(buddies, (GFunc)unpack_buddies_cb, NULL);
- g_ptr_array_foreach(chats, (GFunc)unpack_chats_cb, NULL);
- g_ptr_array_free(groups, TRUE);
- g_ptr_array_free(contacts, TRUE);
- g_ptr_array_free(buddies, TRUE);
- g_ptr_array_free(chats, TRUE);
+ g_variant_get(ret, "(@a(oa(sv))" /* groups */
+ "@a(oa(sv))" /* contacts */
+ "@a(oa(sv))" /* buddies */
+ "@a(oa(sv))" /* chats */
+ "@o)", /* root node */
+ &groups, &contacts, &buddies, &chats, &root);
+ /* This one is a bit tricky because these classes are all child
+ * of the PurpleBlistNode class, which holds a bunch of
+ * cross-referenced properties: each blist node have a parent,
+ * a child, a next and a prev object reference property.
+ * These properties are converted to/from dbus path names when
+ * they are got/set. Therefore, during the creation of these
+ * objects, some of their links will not be resolved.
+ * To solve this problem, we first create the objects and
+ * then reload their object reference properties. */
+ purple_constructor_load_pobjs_unsync(groups, PURPLE_TYPE_GROUP);
+ purple_constructor_load_pobjs_unsync(contacts, PURPLE_TYPE_CONTACT);
+ purple_constructor_load_pobjs_unsync(buddies, PURPLE_TYPE_BUDDY);
+ purple_constructor_load_pobjs_unsync(chats, PURPLE_TYPE_CHAT);
+
+ purple_constructor_reload_pobjs_objpath_props(groups);
+ purple_constructor_reload_pobjs_objpath_props(contacts);
+ purple_constructor_reload_pobjs_objpath_props(buddies);
+ purple_constructor_reload_pobjs_objpath_props(chats);
+
+ /* Now we've got all the blist nodes, maybe we can reference
+ * one of them as the root node. */
+ purple_object_set_dbus_property(blist, "root", root);
+
+ g_variant_unref(ret);
}
============================================================
--- libpurple/dbus/blist.h deaab5b09e0ca6fa5bf600c25df96ad036e2e4af
+++ libpurple/dbus/blist.h 793372e20c51411bae373d2403355c410b2c4bcf
@@ -38,14 +38,14 @@ void purple_blist_class_dbus_init(Purple
* but since this type is only defined in libpurple/blist.c, we use the
* upper-class instead.
*/
-void purple_blist_load_RPC(void);
+void purple_blist_load_RPC(PurpleObject *blist);
G_END_DECLS
#else /* !HAVE_DBUS */
#define purple_blist_class_dbus_init(klass) ((void)0)
-#define purple_blist_load_RPC() ((void)0)
+#define purple_blist_load_RPC(blist) ((void)0)
#endif /* HAVE_DBUS */
#endif /* _PURPLE_DBUS_BLIST_H */
============================================================
--- libpurple/dbus/blist.xml 2010b7b838f6acea6ca8e18c21f872924ab40e7a
+++ libpurple/dbus/blist.xml 2897566e338f85d4acd0e80fe7f2d769f311e1e4
@@ -1,24 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<node>
<interface name="im.pidgin.purple.blist">
+ <property type="o" name="root" access="read" />
+
<method name="GetBuddyList">
- <!-- group: s = group path name; s = group name;
- a(sv) = settings -->
- <arg type="a(ssa(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" />
+ <!-- a( o a( s v))
+ objects^ dbus-path^ properties^ name^ value^ -->
+ <arg type="a(oa(sv))" name="groups" direction="out" />
+ <arg type="a(oa(sv))" name="contacts" direction="out" />
+ <arg type="a(oa(sv))" name="buddies" direction="out" />
+ <arg type="a(oa(sv))" name="chats" direction="out" />
+ <arg type="o" name="rootnode" direction="out" />
</method>
</interface>
</node>
More information about the Commits
mailing list