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