summaryrefslogtreecommitdiff
path: root/telepathy-glib/account-request.c
diff options
context:
space:
mode:
authorJonny Lamb <jonny.lamb@collabora.co.uk>2012-05-10 11:44:38 +0100
committerJonny Lamb <jonny.lamb@collabora.co.uk>2012-05-10 11:44:38 +0100
commit253b2ee2e1eb8ef631e7d0049907576e04acaa2e (patch)
tree5ad488d12ad03f79f763978f1ea8ce1db71b1ec0 /telepathy-glib/account-request.c
parentb79e36c1d65a59a44de20264224b5bc05a2934c1 (diff)
downloadtelepathy-glib-253b2ee2e1eb8ef631e7d0049907576e04acaa2e.tar.gz
future-account: rename to TpAccountRequest
Signed-off-by: Jonny Lamb <jonny.lamb@collabora.co.uk>
Diffstat (limited to 'telepathy-glib/account-request.c')
-rw-r--r--telepathy-glib/account-request.c1349
1 files changed, 1349 insertions, 0 deletions
diff --git a/telepathy-glib/account-request.c b/telepathy-glib/account-request.c
new file mode 100644
index 000000000..2f39c7f2f
--- /dev/null
+++ b/telepathy-glib/account-request.c
@@ -0,0 +1,1349 @@
+/*
+ * account-request.c - object for a currently non-existent account to create
+ *
+ * Copyright © 2012 Collabora Ltd. <http://www.collabora.co.uk/>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+
+#include "telepathy-glib/account-request.h"
+
+#include <telepathy-glib/gtypes.h>
+#include <telepathy-glib/interfaces.h>
+#include <telepathy-glib/util.h>
+#include <telepathy-glib/simple-client-factory.h>
+
+#define DEBUG_FLAG TP_DEBUG_ACCOUNTS
+#include "telepathy-glib/dbus-internal.h"
+#include "telepathy-glib/debug-internal.h"
+#include "telepathy-glib/util-internal.h"
+
+/**
+ * SECTION:account-request
+ * @title: TpAccountRequest
+ * @short_description: object for a currently non-existent account in
+ * order to create easily without speaking fluent D-Bus
+ * @see_also: #TpAccountManager
+ *
+ * This is a convenience object to aid in the creation of accounts on
+ * a #TpAccountManager without having to construct #GHashTables with
+ * well-known keys. For example:
+ *
+ * |[
+ * static void created_cb (GObject *object, GAsyncResult *res, gpointer user_data);
+ *
+ * static void
+ * create_acount (void)
+ * {
+ * TpAccountManager *am = tp_account_manager_dup ();
+ * TpAccountRequest *req;
+ *
+ * req = tp_account_request_new (am, "gabble", "jabber", "Work Jabber account");
+ *
+ * tp_account_request_set_parameter (req, "account", "walter.white@lospollos.lit");
+ *
+ * // ...
+ *
+ * tp_account_request_create_account_async (req, created_cb, NULL);
+ * g_object_unref (req);
+ * g_object_unref (am);
+ * }
+ *
+ * static void
+ * created_cb (GObject *object,
+ * GAsyncResult *result,
+ * gpointer user_data)
+ * {
+ * TpAccountRequest *req = TP_ACCOUNT_REQUEST (object);
+ * TpAccount *account;
+ * GError *error = NULL;
+ *
+ * account = tp_account_request_create_account_finish (req, result, &error);
+ *
+ * if (account == NULL)
+ * {
+ * g_error ("Failed to create account: %s\n", error->message);
+ * g_clear_error (&error);
+ * return;
+ * }
+ *
+ * // ...
+ *
+ * g_object_unref (account);
+ * }
+ * ]|
+ *
+ *
+ * Since: 0.UNRELEASED
+ */
+
+/**
+ * TpAccountRequest:
+ *
+ * An object for representing a currently non-existent account which
+ * is to be created on a #TpAccountManager.
+ *
+ * Since: 0.UNRELEASED
+ */
+
+/**
+ * TpAccountRequestClass:
+ *
+ * The class of a #TpAccountRequest.
+ */
+
+struct _TpAccountRequestPrivate {
+ TpAccountManager *account_manager;
+
+ GSimpleAsyncResult *result;
+ gboolean created;
+
+ gchar *cm_name;
+ gchar *proto_name;
+ gchar *display_name;
+
+ GHashTable *parameters;
+ GHashTable *properties;
+};
+
+G_DEFINE_TYPE (TpAccountRequest, tp_account_request, G_TYPE_OBJECT)
+
+/* properties */
+enum {
+ PROP_ACCOUNT_MANAGER = 1,
+ PROP_CONNECTION_MANAGER,
+ PROP_PROTOCOL,
+ PROP_DISPLAY_NAME,
+ PROP_PARAMETERS,
+ PROP_PROPERTIES,
+ PROP_ICON_NAME,
+ PROP_NICKNAME,
+ PROP_REQUESTED_PRESENCE_TYPE,
+ PROP_REQUESTED_STATUS,
+ PROP_REQUESTED_STATUS_MESSAGE,
+ PROP_AUTOMATIC_PRESENCE_TYPE,
+ PROP_AUTOMATIC_STATUS,
+ PROP_AUTOMATIC_STATUS_MESSAGE,
+ PROP_ENABLED,
+ PROP_CONNECT_AUTOMATICALLY,
+ PROP_SUPERSEDES,
+ PROP_AVATAR,
+ PROP_AVATAR_MIME_TYPE,
+ PROP_SERVICE,
+ N_PROPS
+};
+
+static void
+tp_account_request_init (TpAccountRequest *self)
+{
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, TP_TYPE_ACCOUNT_REQUEST,
+ TpAccountRequestPrivate);
+}
+
+static void
+tp_account_request_constructed (GObject *object)
+{
+ TpAccountRequest *self = TP_ACCOUNT_REQUEST (object);
+ TpAccountRequestPrivate *priv = self->priv;
+ void (*chain_up) (GObject *) =
+ ((GObjectClass *) tp_account_request_parent_class)->constructed;
+
+ if (chain_up != NULL)
+ chain_up (object);
+
+ g_assert (priv->account_manager != NULL);
+ g_assert (priv->cm_name != NULL);
+ g_assert (priv->proto_name != NULL);
+ g_assert (priv->display_name != NULL);
+
+ priv->parameters = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, (GDestroyNotify) tp_g_value_slice_free);
+
+ priv->properties = tp_asv_new (NULL, NULL);
+}
+
+#define GET_PRESENCE_VALUE(key, offset, type) \
+ G_STMT_START { \
+ GValueArray *_arr = tp_asv_get_boxed (self->priv->properties, \
+ key, TP_STRUCT_TYPE_SIMPLE_PRESENCE); \
+ if (_arr != NULL) \
+ g_value_set_##type (value, g_value_get_##type (_arr->values + offset)); \
+ } G_STMT_END
+
+static void
+tp_account_request_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ TpAccountRequest *self = TP_ACCOUNT_REQUEST (object);
+
+ switch (prop_id)
+ {
+ case PROP_ACCOUNT_MANAGER:
+ g_value_set_object (value, self->priv->account_manager);
+ break;
+ case PROP_CONNECTION_MANAGER:
+ g_value_set_string (value, self->priv->cm_name);
+ break;
+ case PROP_PROTOCOL:
+ g_value_set_string (value, self->priv->proto_name);
+ break;
+ case PROP_DISPLAY_NAME:
+ g_value_set_string (value, self->priv->display_name);
+ break;
+ case PROP_PARAMETERS:
+ g_value_take_variant (value, _tp_asv_to_vardict (self->priv->parameters));
+ break;
+ case PROP_PROPERTIES:
+ g_value_take_variant (value, _tp_asv_to_vardict (self->priv->properties));
+ break;
+ case PROP_ICON_NAME:
+ g_value_set_string (value,
+ tp_asv_get_string (self->priv->properties,
+ TP_PROP_ACCOUNT_ICON));
+ break;
+ case PROP_NICKNAME:
+ g_value_set_string (value,
+ tp_asv_get_string (self->priv->properties,
+ TP_PROP_ACCOUNT_NICKNAME));
+ break;
+ case PROP_REQUESTED_PRESENCE_TYPE:
+ GET_PRESENCE_VALUE (TP_PROP_ACCOUNT_REQUESTED_PRESENCE, 0, uint);
+ break;
+ case PROP_REQUESTED_STATUS:
+ GET_PRESENCE_VALUE (TP_PROP_ACCOUNT_REQUESTED_PRESENCE, 1, string);
+ break;
+ case PROP_REQUESTED_STATUS_MESSAGE:
+ GET_PRESENCE_VALUE (TP_PROP_ACCOUNT_REQUESTED_PRESENCE, 2, string);
+ break;
+ case PROP_AUTOMATIC_PRESENCE_TYPE:
+ GET_PRESENCE_VALUE (TP_PROP_ACCOUNT_AUTOMATIC_PRESENCE, 0, uint);
+ break;
+ case PROP_AUTOMATIC_STATUS:
+ GET_PRESENCE_VALUE (TP_PROP_ACCOUNT_AUTOMATIC_PRESENCE, 1, string);
+ break;
+ case PROP_AUTOMATIC_STATUS_MESSAGE:
+ GET_PRESENCE_VALUE (TP_PROP_ACCOUNT_AUTOMATIC_PRESENCE, 2, string);
+ break;
+ case PROP_ENABLED:
+ g_value_set_boolean (value,
+ tp_asv_get_boolean (self->priv->properties,
+ TP_PROP_ACCOUNT_ENABLED, NULL));
+ break;
+ case PROP_CONNECT_AUTOMATICALLY:
+ g_value_set_boolean (value,
+ tp_asv_get_boolean (self->priv->properties,
+ TP_PROP_ACCOUNT_CONNECT_AUTOMATICALLY,
+ NULL));
+ break;
+ case PROP_SUPERSEDES:
+ {
+ GPtrArray *array = tp_asv_get_boxed (self->priv->properties,
+ TP_PROP_ACCOUNT_SUPERSEDES,
+ TP_ARRAY_TYPE_OBJECT_PATH_LIST);
+
+ if (array != NULL)
+ {
+ /* add the NULL-termination to make it a real GStrv */
+ g_ptr_array_add (array, NULL);
+ g_value_set_boxed (value, array->pdata);
+ g_ptr_array_remove_index (array, (array->len - 1));
+ }
+ else
+ {
+ g_value_set_boxed (value, NULL);
+ }
+ }
+ break;
+ case PROP_AVATAR:
+ {
+ GValueArray *array = tp_asv_get_boxed (self->priv->properties,
+ TP_PROP_ACCOUNT_INTERFACE_AVATAR_AVATAR,
+ TP_STRUCT_TYPE_AVATAR);
+
+ if (array != NULL)
+ g_value_set_boxed (value, g_value_get_boxed (array->values));
+ }
+ break;
+ case PROP_AVATAR_MIME_TYPE:
+ {
+ GValueArray *array = tp_asv_get_boxed (self->priv->properties,
+ TP_PROP_ACCOUNT_INTERFACE_AVATAR_AVATAR,
+ TP_STRUCT_TYPE_AVATAR);
+
+ if (array != NULL)
+ g_value_set_string (value, g_value_get_string (array->values + 1));
+ }
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+#undef GET_PRESENCE_VALUE
+
+static void
+tp_account_request_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ TpAccountRequest *self = TP_ACCOUNT_REQUEST (object);
+ TpAccountRequestPrivate *priv = self->priv;
+
+ switch (property_id)
+ {
+ case PROP_ACCOUNT_MANAGER:
+ g_assert (priv->account_manager == NULL);
+ priv->account_manager = g_value_dup_object (value);
+ break;
+ case PROP_CONNECTION_MANAGER:
+ g_assert (priv->cm_name == NULL);
+ priv->cm_name = g_value_dup_string (value);
+ break;
+ case PROP_PROTOCOL:
+ g_assert (priv->proto_name == NULL);
+ priv->proto_name = g_value_dup_string (value);
+ break;
+ case PROP_DISPLAY_NAME:
+ g_assert (priv->display_name == NULL);
+ priv->display_name = g_value_dup_string (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+tp_account_request_dispose (GObject *object)
+{
+ TpAccountRequest *self = TP_ACCOUNT_REQUEST (object);
+ TpAccountRequestPrivate *priv = self->priv;
+
+ g_clear_object (&priv->account_manager);
+
+ tp_clear_pointer (&priv->parameters, g_hash_table_unref);
+ tp_clear_pointer (&priv->properties, g_hash_table_unref);
+
+ /* release any references held by the object here */
+
+ if (G_OBJECT_CLASS (tp_account_request_parent_class)->dispose != NULL)
+ G_OBJECT_CLASS (tp_account_request_parent_class)->dispose (object);
+}
+
+static void
+tp_account_request_finalize (GObject *object)
+{
+ TpAccountRequest *self = TP_ACCOUNT_REQUEST (object);
+ TpAccountRequestPrivate *priv = self->priv;
+
+ tp_clear_pointer (&priv->cm_name, g_free);
+ tp_clear_pointer (&priv->proto_name, g_free);
+ tp_clear_pointer (&priv->display_name, g_free);
+
+ /* free any data held directly by the object here */
+
+ if (G_OBJECT_CLASS (tp_account_request_parent_class)->finalize != NULL)
+ G_OBJECT_CLASS (tp_account_request_parent_class)->finalize (object);
+}
+
+static void
+tp_account_request_class_init (TpAccountRequestClass *klass)
+{
+ GObjectClass *object_class = (GObjectClass *) klass;
+
+ g_type_class_add_private (klass, sizeof (TpAccountRequestPrivate));
+
+ object_class->constructed = tp_account_request_constructed;
+ object_class->get_property = tp_account_request_get_property;
+ object_class->set_property = tp_account_request_set_property;
+ object_class->dispose = tp_account_request_dispose;
+ object_class->finalize = tp_account_request_finalize;
+
+ /**
+ * TpAccountRequest:account-manager:
+ *
+ * The #TpAccountManager to create the account on.
+ *
+ * Since: 0.UNRELEASED
+ */
+ g_object_class_install_property (object_class, PROP_ACCOUNT_MANAGER,
+ g_param_spec_object ("account-manager",
+ "Account manager",
+ "The account's account manager",
+ TP_TYPE_ACCOUNT_MANAGER,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ /**
+ * TpAccountRequest:connection-manager:
+ *
+ * The account's connection manager name.
+ *
+ * Since: 0.UNRELEASED
+ */
+ g_object_class_install_property (object_class, PROP_CONNECTION_MANAGER,
+ g_param_spec_string ("connection-manager",
+ "Connection manager",
+ "The account's connection manager name",
+ NULL,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ /**
+ * TpAccountRequest:protocol:
+ *
+ * The account's machine-readable protocol name, such as "jabber", "msn" or
+ * "local-xmpp". Recommended names for most protocols can be found in the
+ * Telepathy D-Bus Interface Specification.
+ *
+ * Since: 0.UNRELEASED
+ */
+ g_object_class_install_property (object_class, PROP_PROTOCOL,
+ g_param_spec_string ("protocol",
+ "Protocol",
+ "The account's protocol name",
+ NULL,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ /**
+ * TpAccountRequest:display-name:
+ *
+ * The account's display name. To change this property use
+ * tp_account_request_set_display_name().
+ *
+ * Since: 0.UNRELEASED
+ */
+ g_object_class_install_property (object_class, PROP_DISPLAY_NAME,
+ g_param_spec_string ("display-name",
+ "DisplayName",
+ "The account's display name",
+ NULL,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ /**
+ * TpAccountRequest:parameters:
+ *
+ * The account's connection parameters. To add a parameter, use
+ * tp_account_request_set_parameter() or another convience function.
+ *
+ * Since: 0.UNRELEASED
+ */
+ g_object_class_install_property (object_class, PROP_PARAMETERS,
+ g_param_spec_variant ("parameters",
+ "Parameters",
+ "Connection parameters of the account",
+ G_VARIANT_TYPE_VARDICT, NULL,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
+
+ /**
+ * TpAccountRequest:properties:
+ *
+ * The account's properties.
+ *
+ * Since: 0.UNRELEASED
+ */
+ g_object_class_install_property (object_class, PROP_PROPERTIES,
+ g_param_spec_variant ("properties",
+ "Properties",
+ "Account properties",
+ G_VARIANT_TYPE_VARDICT, NULL,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
+
+ /**
+ * TpAccountRequest:icon-name:
+ *
+ * The account's icon name. To change this propery, use
+ * tp_account_request_set_icon_name().
+ *
+ * Since: 0.UNRELEASED
+ */
+ g_object_class_install_property (object_class, PROP_ICON_NAME,
+ g_param_spec_string ("icon-name",
+ "Icon",
+ "The account's icon name",
+ NULL,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
+
+ /**
+ * TpAccountRequest:nickname:
+ *
+ * The account's nickname. To change this property use
+ * tp_account_request_set_nickname().
+ *
+ * Since: 0.UNRELEASED
+ */
+ g_object_class_install_property (object_class, PROP_NICKNAME,
+ g_param_spec_string ("nickname",
+ "Nickname",
+ "The account's nickname",
+ NULL,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
+
+ /**
+ * TpAccountRequest:requested-presence-type:
+ *
+ * The account's requested presence type (a
+ * #TpConnectionPresenceType). To change this property use
+ * tp_account_request_set_requested_presence().
+ *
+ * Since: 0.UNRELEASED
+ */
+ g_object_class_install_property (object_class, PROP_REQUESTED_PRESENCE_TYPE,
+ g_param_spec_uint ("requested-presence-type",
+ "RequestedPresence",
+ "The account's requested presence type",
+ 0,
+ TP_NUM_CONNECTION_PRESENCE_TYPES,
+ TP_CONNECTION_PRESENCE_TYPE_UNSET,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
+
+ /**
+ * TpAccountRequest:requested-status:
+ *
+ * The requested Status string of the account. To change this
+ * property use tp_account_request_set_requested_presence().
+ *
+ * Since: 0.UNRELEASED
+ */
+ g_object_class_install_property (object_class, PROP_REQUESTED_STATUS,
+ g_param_spec_string ("requested-status",
+ "RequestedStatus",
+ "The account's requested status string",
+ NULL,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
+
+ /**
+ * TpAccountRequest:requested-status-message:
+ *
+ * The requested status message message of the account. To change
+ * this property use tp_account_request_set_requested_presence().
+ *
+ * Since: 0.UNRELEASED
+ */
+ g_object_class_install_property (object_class, PROP_REQUESTED_STATUS_MESSAGE,
+ g_param_spec_string ("requested-status-message",
+ "RequestedStatusMessage",
+ "The requested Status message string of the account",
+ NULL,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
+
+ /**
+ * TpAccountRequest:automatic-presence-type:
+ *
+ * The account's automatic presence type (a
+ * #TpConnectionPresenceType). To change this property use
+ * tp_account_request_set_automatic_presence().
+ *
+ * When the account is put online automatically, for instance to
+ * make a channel request or because network connectivity becomes
+ * available, the automatic presence type, status and message will
+ * be copied to their "requested" counterparts.
+ *
+ * Since: 0.UNRELEASED
+ */
+ g_object_class_install_property (object_class, PROP_AUTOMATIC_PRESENCE_TYPE,
+ g_param_spec_uint ("automatic-presence-type",
+ "AutomaticPresence type",
+ "Presence type used to put the account online automatically",
+ 0,
+ TP_NUM_CONNECTION_PRESENCE_TYPES,
+ TP_CONNECTION_PRESENCE_TYPE_UNSET,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
+
+ /**
+ * TpAccountRequest:automatic-status:
+ *
+ * The string status name to use in conjunction with the
+ * #TpAccountRequest:automatic-presence-type. To change this property
+ * use tp_account_request_set_automatic_presence().
+ *
+ * Since: 0.UNRELEASED
+ */
+ g_object_class_install_property (object_class, PROP_AUTOMATIC_STATUS,
+ g_param_spec_string ("automatic-status",
+ "AutomaticPresence status",
+ "Presence status used to put the account online automatically",
+ NULL,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
+
+ /**
+ * TpAccountRequest:automatic-status-message:
+ *
+ * The user-defined message to use in conjunction with the
+ * #TpAccount:automatic-presence-type. To change this property use
+ * tp_account_request_set_automatic_presence().
+ *
+ * Since: 0.UNRELEASED
+ */
+ g_object_class_install_property (object_class, PROP_AUTOMATIC_STATUS_MESSAGE,
+ g_param_spec_string ("automatic-status-message",
+ "AutomaticPresence message",
+ "User-defined message used to put the account online automatically",
+ NULL,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
+
+ /**
+ * TpAccountRequest:enabled:
+ *
+ * Whether the account is enabled or not. To change this property
+ * use tp_account_request_set_enabled().
+ *
+ * Since: 0.UNRELEASED
+ */
+ g_object_class_install_property (object_class, PROP_ENABLED,
+ g_param_spec_boolean ("enabled",
+ "Enabled",
+ "Whether this account is enabled or not",
+ FALSE,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
+
+ /**
+ * TpAccountRequest:connect-automatically:
+ *
+ * Whether the account should connect automatically or not. To change this
+ * property, use tp_account_request_set_connect_automatically().
+ *
+ * Since: 0.UNRELEASED
+ */
+ g_object_class_install_property (object_class, PROP_CONNECT_AUTOMATICALLY,
+ g_param_spec_boolean ("connect-automatically",
+ "ConnectAutomatically",
+ "Whether this account should connect automatically or not",
+ FALSE,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
+
+ /**
+ * TpAccountRequest:supersedes:
+ *
+ * The object paths of previously-active accounts superseded by this one.
+ * For instance, this can be used in a logger to read old logs for an
+ * account that has been migrated from one connection manager to another.
+ *
+ * To add to this property use tp_account_request_add_supersedes().
+ *
+ * Since: 0.UNRELEASED
+ */
+ g_object_class_install_property (object_class, PROP_SUPERSEDES,
+ g_param_spec_boxed ("supersedes",
+ "Supersedes",
+ "Accounts superseded by this one",
+ G_TYPE_STRV,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
+
+ /**
+ * TpAccountRequest:avatar:
+ *
+ * The avatar set on the account. The avatar's mime type can be read
+ * in the #TpAccountRequest:avatar-mime-type property. To change this
+ * property, use tp_account_request_set_avatar().
+ *
+ * Since: 0.UNRELEASED
+ */
+ g_object_class_install_property (object_class, PROP_AVATAR,
+ g_param_spec_boxed ("avatar",
+ "Avatar",
+ "The account's avatar data",
+ G_TYPE_ARRAY,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
+
+ /**
+ * TpAccountRequest:avatar-mime-type:
+ *
+ * The mime type of the #TpAccountRequest:avatar property. To change
+ * this property, use tp_account_request_set_avatar().
+ *
+ * Since: 0.UNRELEASED
+ */
+ g_object_class_install_property (object_class, PROP_AVATAR_MIME_TYPE,
+ g_param_spec_string ("avatar-mime-type",
+ "Avatar mime type",
+ "The account's avatar's mime type",
+ NULL,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
+
+ /**
+ * TpAccountRequest:service:
+ *
+ * A string describing the service of the account, which must
+ * consist only of ASCII letters, numbers and hyphen/minus signs,
+ * and start with a letter (matching the requirements for
+ * Protocol). To change this property, use
+ * tp_account_request_set_service().
+ *
+ * Since: 0.UNRELEASED
+ */
+ g_object_class_install_property (object_class, PROP_SERVICE,
+ g_param_spec_string ("service",
+ "Service",
+ "The account's service",
+ NULL,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
+}
+
+/**
+ * tp_account_request_new:
+ * @account_manager: the #TpAccountManager to create the account on
+ * @manager: the name of the connection manager
+ * @protocol: the name of the protocol on @manager
+ * @display_name: the user-visible name of this account
+ *
+ * Convenience function to create a new account request object which
+ * will assist in the creation of a new account on @account_manager,
+ * using connection manager @manager, and protocol @protocol.
+ *
+ * Returns: (transfer full): a new reference to an account request
+ * object, or %NULL if any argument is incorrect
+ *
+ * Since: 0.UNRELEASED
+ */
+TpAccountRequest *
+tp_account_request_new (TpAccountManager *account_manager,
+ const gchar *manager,
+ const gchar *protocol,
+ const gchar *display_name)
+{
+ g_return_val_if_fail (TP_IS_ACCOUNT_MANAGER (account_manager), NULL);
+ g_return_val_if_fail (manager != NULL, NULL);
+ g_return_val_if_fail (protocol != NULL, NULL);
+
+ return g_object_new (TP_TYPE_ACCOUNT_REQUEST,
+ "account-manager", account_manager,
+ "connection-manager", manager,
+ "protocol", protocol,
+ "display-name", display_name,
+ NULL);
+}
+
+/**
+ * tp_account_request_new_from_protocol:
+ * @account_manager: the #TpAccountManager to create the account on
+ * @protocol: a #TpProtocol
+ * @display_name: the user-visible name of this account
+ *
+ * Convenience function to create a new #TpAccountRequest object using
+ * a #TpProtocol instance, instead of specifying connection manager
+ * and protocol name specifically. See tp_account_request_new() for
+ * more details.
+ *
+ * Returns: (transfer full): a new reference to an account request
+ * object, or %NULL if any argument is incorrect
+ *
+ * Since: 0.UNRELEASED
+ */
+TpAccountRequest *
+tp_account_request_new_from_protocol (TpAccountManager *account_manager,
+ TpProtocol *protocol,
+ const gchar *display_name)
+{
+ g_return_val_if_fail (TP_IS_ACCOUNT_MANAGER (account_manager), NULL);
+ g_return_val_if_fail (TP_IS_PROTOCOL (protocol), NULL);
+
+ return g_object_new (TP_TYPE_ACCOUNT_REQUEST,
+ "account-manager", account_manager,
+ "connection-manager", tp_protocol_get_cm_name (protocol),
+ "protocol", tp_protocol_get_name (protocol),
+ "display-name", display_name,
+ NULL);
+}
+
+/**
+ * tp_account_request_set_display_name:
+ * @self: a #TpAccountRequest
+ * @name: a display name for the account
+ *
+ * Set the display name for the new account, @self, to @name. Use the
+ * #TpAccountRequest:display-name property to read the current display
+ * name.
+ *
+ * Since: 0.UNRELEASED
+ */
+void
+tp_account_request_set_display_name (TpAccountRequest *self,
+ const gchar *name)
+{
+ TpAccountRequestPrivate *priv;
+
+ g_return_if_fail (TP_IS_ACCOUNT_REQUEST (self));
+ g_return_if_fail (name != NULL);
+
+ priv = self->priv;
+
+ g_return_if_fail (priv->result == NULL && !priv->created);
+
+ g_free (priv->display_name);
+ priv->display_name = g_strdup (name);
+}
+
+/**
+ * tp_account_request_set_icon_name:
+ * @self: a #TpAccountRequest
+ * @icon: an icon name for the account
+ *
+ * Set the icon name for the new account, @self, to @icon. Use the
+ * #TpAccountRequest:icon-name property to read the current icon name.
+ *
+ * Since: 0.UNRELEASED
+ */
+void
+tp_account_request_set_icon_name (TpAccountRequest *self,
+ const gchar *icon)
+{
+ TpAccountRequestPrivate *priv;
+
+ g_return_if_fail (TP_IS_ACCOUNT_REQUEST (self));
+ g_return_if_fail (icon != NULL);
+
+ priv = self->priv;
+
+ g_return_if_fail (priv->result == NULL && !priv->created);
+
+ tp_asv_set_string (priv->properties, TP_PROP_ACCOUNT_ICON, icon);
+}
+
+/**
+ * tp_account_request_set_nickname:
+ * @self: a #TpAccountRequest
+ * @nickname: a nickname for the account
+ *
+ * Set the nickname for the new account, @self, to @nickname. Use the
+ * #TpAccountRequest:nickname property to read the current nickname.
+ *
+ * Since: 0.UNRELEASED
+ */
+void
+tp_account_request_set_nickname (TpAccountRequest *self,
+ const gchar *nickname)
+{
+ TpAccountRequestPrivate *priv;
+
+ g_return_if_fail (TP_IS_ACCOUNT_REQUEST (self));
+ g_return_if_fail (nickname != NULL);
+
+ priv = self->priv;
+
+ g_return_if_fail (priv->result == NULL && !priv->created);
+
+ tp_asv_set_string (priv->properties, TP_PROP_ACCOUNT_NICKNAME, nickname);
+}
+
+/**
+ * tp_account_request_set_requested_presence:
+ * @self: a #TpAccountRequest
+ * @presence: the requested presence type
+ * @status: the requested presence status
+ * @message: the requested presence message
+ *
+ * Set the requested presence for the new account, @self, to the type
+ * (@presence, @status), with message @message. Use the
+ * #TpAccountRequest:requested-presence-type,
+ * #TpAccountRequest:requested-status, and
+ * #TpAccountRequest:requested-status-message properties to read the
+ * current requested presence.
+ *
+ * Since: 0.UNRELEASED
+ */
+void
+tp_account_request_set_requested_presence (TpAccountRequest *self,
+ TpConnectionPresenceType presence,
+ const gchar *status,
+ const gchar *message)
+{
+ TpAccountRequestPrivate *priv;
+ GValue *value;
+ GValueArray *arr;
+
+ g_return_if_fail (TP_IS_ACCOUNT_REQUEST (self));
+
+ priv = self->priv;
+
+ g_return_if_fail (priv->result == NULL && !priv->created);
+
+ value = tp_g_value_slice_new_take_boxed (TP_STRUCT_TYPE_SIMPLE_PRESENCE,
+ dbus_g_type_specialized_construct (TP_STRUCT_TYPE_SIMPLE_PRESENCE));
+ arr = (GValueArray *) g_value_get_boxed (value);
+
+ g_value_set_uint (arr->values, presence);
+ g_value_set_string (arr->values + 1, status);
+ g_value_set_string (arr->values + 2, message);
+
+ g_hash_table_insert (priv->properties,
+ TP_PROP_ACCOUNT_REQUESTED_PRESENCE, value);
+}
+
+/**
+ * tp_account_request_set_automatic_presence:
+ * @self: a #TpAccountRequest
+ * @presence: the automatic presence type
+ * @status: the automatic presence status
+ * @message: the automatic presence message
+ *
+ * Set the automatic presence for the new account, @self, to the type
+ * (@presence, @status), with message @message. Use the
+ * #TpAccountRequest:automatic-presence-type,
+ * #TpAccountRequest:automatic-status, and
+ * #TpAccountRequest:automatic-status-message properties to read the
+ * current automatic presence.
+ *
+ * Since: 0.UNRELEASED
+ */
+void
+tp_account_request_set_automatic_presence (TpAccountRequest *self,
+ TpConnectionPresenceType presence,
+ const gchar *status,
+ const gchar *message)
+{
+ TpAccountRequestPrivate *priv;
+ GValue *value;
+ GValueArray *arr;
+
+ g_return_if_fail (TP_IS_ACCOUNT_REQUEST (self));
+
+ priv = self->priv;
+
+ g_return_if_fail (priv->result == NULL && !priv->created);
+
+ value = tp_g_value_slice_new_take_boxed (TP_STRUCT_TYPE_SIMPLE_PRESENCE,
+ dbus_g_type_specialized_construct (TP_STRUCT_TYPE_SIMPLE_PRESENCE));
+ arr = (GValueArray *) g_value_get_boxed (value);
+
+ g_value_set_uint (arr->values, presence);
+ g_value_set_string (arr->values + 1, status);
+ g_value_set_string (arr->values + 2, message);
+
+ g_hash_table_insert (priv->properties,
+ TP_PROP_ACCOUNT_AUTOMATIC_PRESENCE, value);
+}
+
+/**
+ * tp_account_request_set_enabled:
+ * @self: a #TpAccountRequest
+ * @enabled: %TRUE if the account is to be enabled
+ *
+ * Set the enabled property of the account on creation to
+ * @enabled. Use the #TpAccountRequest:enabled property to read the
+ * current enabled value.
+ *
+ * Since: 0.UNRELEASED
+ */
+void
+tp_account_request_set_enabled (TpAccountRequest *self,
+ gboolean enabled)
+{
+ TpAccountRequestPrivate *priv;
+
+ g_return_if_fail (TP_IS_ACCOUNT_REQUEST (self));
+
+ priv = self->priv;
+
+ g_return_if_fail (priv->result == NULL && !priv->created);
+
+ tp_asv_set_boolean (priv->properties, TP_PROP_ACCOUNT_ENABLED, enabled);
+}
+
+/**
+ * tp_account_request_set_connect_automatically:
+ * @self: a #TpAccountRequest
+ * @connect_automatically: %TRUE if the account is to connect automatically
+ *
+ * Set the connect automatically property of the account on creation
+ * to @connect_automatically so that the account is brought online to
+ * the automatic presence. Use the
+ * #TpAccountRequest:connect-automatically property to read the current
+ * connect automatically value.
+ *
+ * Since: 0.UNRELEASED
+ */
+void
+tp_account_request_set_connect_automatically (TpAccountRequest *self,
+ gboolean connect_automatically)
+{
+ TpAccountRequestPrivate *priv;
+
+ g_return_if_fail (TP_IS_ACCOUNT_REQUEST (self));
+
+ priv = self->priv;
+
+ g_return_if_fail (priv->result == NULL && !priv->created);
+
+ tp_asv_set_boolean (priv->properties,
+ TP_PROP_ACCOUNT_CONNECT_AUTOMATICALLY,
+ connect_automatically);
+}
+
+/**
+ * tp_account_request_add_supersedes:
+ * @self: a #TpAccountRequest
+ * @superseded_path: an account object path to add to the supersedes
+ * list
+ *
+ * Add an account object path to the list of superseded accounts which
+ * this new account will supersede. Use the
+ * #TpAccountRequest:supersedes property to read the current list of
+ * superseded accounts.
+ *
+ * Since: 0.UNRELEASED
+ */
+void
+tp_account_request_add_supersedes (TpAccountRequest *self,
+ const gchar *superseded_path)
+{
+ TpAccountRequestPrivate *priv;
+ GPtrArray *array;
+
+ g_return_if_fail (TP_IS_ACCOUNT_REQUEST (self));
+ g_return_if_fail (g_variant_is_object_path (superseded_path));
+
+ priv = self->priv;
+
+ g_return_if_fail (priv->result == NULL && !priv->created);
+
+ array = tp_asv_get_boxed (priv->properties,
+ TP_PROP_ACCOUNT_SUPERSEDES,
+ TP_ARRAY_TYPE_OBJECT_PATH_LIST);
+
+ if (array == NULL)
+ {
+ array = g_ptr_array_new ();
+
+ tp_asv_take_boxed (priv->properties,
+ TP_PROP_ACCOUNT_SUPERSEDES,
+ TP_ARRAY_TYPE_OBJECT_PATH_LIST, array);
+ }
+
+ g_ptr_array_add (array, g_strdup (superseded_path));
+}
+
+/**
+ * tp_account_request_set_avatar:
+ * @self: a #TpAccountRequest
+ * @avatar: (allow-none) (array length=len) a new avatar to set; can
+ * be %NULL only if %len equals 0
+ * @len: the length of the new avatar
+ * @mime_type: (allow-none): the MIME type of the new avatar; can be %NULL
+ * only if @len equals 0
+ *
+ * Set the avatar of the account @self to @avatar. Use the
+ * #TpAccountRequest:avatar and #TpAccountRequest:avatar-mime-type
+ * properties to read the current avatar.
+ *
+ * Since: 0.UNRELEASED
+ */
+void
+tp_account_request_set_avatar (TpAccountRequest *self,
+ const guchar *avatar,
+ gsize len,
+ const gchar *mime_type)
+{
+ TpAccountRequestPrivate *priv;
+ GArray *tmp;
+ GValueArray *arr;
+
+ g_return_if_fail (TP_IS_ACCOUNT_REQUEST (self));
+ g_return_if_fail (avatar != NULL || len == 0);
+ g_return_if_fail (mime_type != NULL || len == 0);
+
+ priv = self->priv;
+
+ g_return_if_fail (priv->result == NULL && !priv->created);
+
+ tmp = g_array_new (FALSE, FALSE, sizeof (guchar));
+
+ if (len > 0)
+ g_array_append_vals (tmp, avatar, len);
+
+ arr = tp_value_array_build (2,
+ TP_TYPE_UCHAR_ARRAY, tmp,
+ G_TYPE_STRING, mime_type,
+ G_TYPE_INVALID);
+
+ g_array_unref (tmp);
+
+ tp_asv_take_boxed (priv->properties,
+ TP_PROP_ACCOUNT_INTERFACE_AVATAR_AVATAR,
+ TP_STRUCT_TYPE_AVATAR, arr);
+}
+
+/**
+ * tp_account_request_set_service:
+ * @self: a #TpAccountRequest
+ * @service: the service name for
+ *
+ * Set the service property of the account to @service. Use the
+ * #TpAccountRequest:service property to read the current value.
+ *
+ * Since: 0.UNRELEASED
+ */
+void
+tp_account_request_set_service (TpAccountRequest *self,
+ const gchar *service)
+{
+ TpAccountRequestPrivate *priv;
+
+ g_return_if_fail (TP_IS_ACCOUNT_REQUEST (self));
+ g_return_if_fail (service != NULL);
+
+ priv = self->priv;
+
+ g_return_if_fail (priv->result == NULL && !priv->created);
+
+ tp_asv_set_string (priv->properties,
+ TP_PROP_ACCOUNT_SERVICE, service);
+}
+
+/**
+ * tp_account_request_set_parameter:
+ * @self: a #TpAccountRequest
+ * @key: the parameter key
+ * @value: (transfer none): a variant containing the parameter value
+ *
+ * Set an account parameter, @key, to @value. Use the
+ * #TpAccountRequest:parameters property to read the current list of
+ * set parameters.
+ *
+ * Parameters can be unset using tp_account_request_unset_parameter().
+ *
+ * Since: 0.UNRELEASED
+ */
+void
+tp_account_request_set_parameter (TpAccountRequest *self,
+ const gchar *key,
+ GVariant *value)
+{
+ TpAccountRequestPrivate *priv;
+ GValue one = G_VALUE_INIT, *two;
+
+ g_return_if_fail (TP_IS_ACCOUNT_REQUEST (self));
+ g_return_if_fail (key != NULL);
+ g_return_if_fail (value != NULL);
+
+ priv = self->priv;
+
+ g_return_if_fail (priv->result == NULL && !priv->created);
+
+ dbus_g_value_parse_g_variant (value, &one);
+ two = tp_g_value_slice_dup (&one);
+
+ g_hash_table_insert (priv->parameters, g_strdup (key), two);
+
+ g_value_unset (&one);
+}
+
+/**
+ * tp_account_request_unset_parameter:
+ * @self: a #TpAccountRequest
+ * @key: the parameter key
+ *
+ * Unset the account parameter @key which has previously been set
+ * using tp_account_request_set_parameter() or another convenience
+ * function.
+ *
+ * Since: 0.UNRELEASED
+ */
+void
+tp_account_request_unset_parameter (TpAccountRequest *self,
+ const gchar *key)
+{
+ TpAccountRequestPrivate *priv;
+
+ g_return_if_fail (TP_IS_ACCOUNT_REQUEST (self));
+ g_return_if_fail (key != NULL);
+
+ priv = self->priv;
+
+ g_return_if_fail (priv->result == NULL && !priv->created);
+
+ g_hash_table_remove (priv->parameters, key);
+}
+
+/**
+ * tp_account_request_set_parameter_string: (skip)
+ * @self: a #TpAccountRequest
+ * @key: the parameter key
+ * @value: the parameter value
+ *
+ * Convenience function to set an account parameter string value. See
+ * tp_account_request_set_parameter() for more details.
+ *
+ * Since: 0.UNRELEASED
+ */
+void
+tp_account_request_set_parameter_string (TpAccountRequest *self,
+ const gchar *key,
+ const gchar *value)
+{
+ TpAccountRequestPrivate *priv;
+
+ g_return_if_fail (TP_IS_ACCOUNT_REQUEST (self));
+ g_return_if_fail (key != NULL);
+ g_return_if_fail (value != NULL);
+
+ priv = self->priv;
+
+ g_return_if_fail (priv->result == NULL && !priv->created);
+
+ g_hash_table_insert (priv->parameters, g_strdup (key),
+ tp_g_value_slice_new_string (value));
+}
+
+static void
+tp_account_request_account_prepared_cb (GObject *object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ TpAccountRequest *self = user_data;
+ TpAccountRequestPrivate *priv = self->priv;
+ GError *error = NULL;
+
+ if (!tp_proxy_prepare_finish (object, result, &error))
+ {
+ DEBUG ("Error preparing account: %s", error->message);
+ g_simple_async_result_take_error (priv->result, error);
+ }
+
+ g_simple_async_result_complete (priv->result);
+ g_clear_object (&priv->result);
+}
+
+static void
+tp_account_request_create_account_cb (TpAccountManager *proxy,
+ const gchar *account_path,
+ const GError *error,
+ gpointer user_data,
+ GObject *weak_object)
+{
+ TpAccountRequest *self = TP_ACCOUNT_REQUEST (weak_object);
+ TpAccountRequestPrivate *priv = self->priv;
+ GError *e = NULL;
+ TpAccount *account;
+ GArray *features;
+
+ if (error != NULL)
+ {
+ DEBUG ("failed to create account: %s", error->message);
+ g_simple_async_result_set_from_error (priv->result, error);
+ g_simple_async_result_complete (priv->result);
+ g_clear_object (&priv->result);
+ return;
+ }
+
+ priv->created = TRUE;
+
+ account = tp_simple_client_factory_ensure_account (
+ tp_proxy_get_factory (proxy), account_path, NULL, &e);
+
+ if (account == NULL)
+ {
+ g_simple_async_result_take_error (priv->result, e);
+ g_simple_async_result_complete (priv->result);
+ g_clear_object (&priv->result);
+ return;
+ }
+
+ /* Give account's ref to the result */
+ g_simple_async_result_set_op_res_gpointer (priv->result, account,
+ g_object_unref);
+
+ features = tp_simple_client_factory_dup_account_features (
+ tp_proxy_get_factory (proxy), account);
+
+ tp_proxy_prepare_async (account, (GQuark *) features->data,
+ tp_account_request_account_prepared_cb, self);
+
+ g_array_unref (features);
+}
+
+/**
+ * tp_account_request_create_account_async:
+ * @self: a #TpAccountRequest
+ * @callback: a function to call when the account has been created
+ * @user_data: user data to @callback
+ *
+ * Start an asynchronous operation to create the account @self on the
+ * account manager.
+ *
+ * @callback will only be called when the newly created #TpAccount has
+ * the %TP_ACCOUNT_FEATURE_CORE feature ready on it, so when calling
+ * tp_account_request_create_account_finish(), one can guarantee this
+ * feature.
+ *
+ * Since: 0.UNRELEASED
+ */
+void
+tp_account_request_create_account_async (TpAccountRequest *self,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ TpAccountRequestPrivate *priv = self->priv;
+
+ g_return_if_fail (TP_IS_ACCOUNT_REQUEST (self));
+
+ priv = self->priv;
+
+ if (priv->result != NULL)
+ {
+ g_simple_async_report_error_in_idle (G_OBJECT (self),
+ callback, user_data,
+ TP_ERROR, TP_ERROR_BUSY,
+ "An account creation operation has already been started on this "
+ "account request");
+ return;
+ }
+
+ if (priv->created)
+ {
+ g_simple_async_report_error_in_idle (G_OBJECT (self),
+ callback, user_data,
+ TP_ERROR, TP_ERROR_NOT_AVAILABLE,
+ "This account has already been created");
+ return;
+ }
+
+ priv->result = g_simple_async_result_new (G_OBJECT (self), callback, user_data,
+ tp_account_request_create_account_async);
+
+ tp_cli_account_manager_call_create_account (priv->account_manager,
+ -1, priv->cm_name, priv->proto_name, priv->display_name,
+ priv->parameters, priv->properties,
+ tp_account_request_create_account_cb, NULL, NULL, G_OBJECT (self));
+}
+
+/**
+ * tp_account_request_create_account_finish:
+ * @self: a #TpAccountRequest
+ * @result: a #GAsyncResult
+ * @error: something
+ *
+ * Finishes an asynchronous account creation operation and returns a
+ * new ref to a #TpAccount object. The returned account will have the
+ * features listed in tp_simple_client_factory_dup_account_features()
+ * (with the proxy factory from #TpAccountRequest:account-manager)
+ * prepared on it.
+ *
+ * Returns: (transfer full): a new ref to a #TpAccount, or %NULL
+ *
+ * Since: 0.UNRELEASED
+ */
+TpAccount *
+tp_account_request_create_account_finish (TpAccountRequest *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ _tp_implement_finish_return_copy_pointer (self,
+ tp_account_request_create_account_async, g_object_ref);
+}