[telepathy-glib/master] account: add functions taken from Empathy, and rename them
Jonny Lamb
jonny.lamb at collabora.co.uk
Mon Sep 28 07:39:03 PDT 2009
Signed-off-by: Jonny Lamb <jonny.lamb at collabora.co.uk>
---
telepathy-glib/account.c | 1207 ++++++++++++++++++++++++++++++++++-
telepathy-glib/account.h | 76 +++
telepathy-glib/signals-marshal.list | 2 +
3 files changed, 1272 insertions(+), 13 deletions(-)
diff --git a/telepathy-glib/account.c b/telepathy-glib/account.c
index 3285c59..1c69086 100644
--- a/telepathy-glib/account.c
+++ b/telepathy-glib/account.c
@@ -19,17 +19,22 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <string.h>
+
#include "telepathy-glib/account.h"
#include <telepathy-glib/dbus.h>
#include <telepathy-glib/defs.h>
#include <telepathy-glib/errors.h>
+#include <telepathy-glib/gtypes.h>
#include <telepathy-glib/interfaces.h>
#include <telepathy-glib/proxy-subclass.h>
+#include <telepathy-glib/util.h>
#define DEBUG_FLAG TP_DEBUG_ACCOUNTS
#include "telepathy-glib/debug-internal.h"
+#include "telepathy-glib/_gen/signals-marshal.h"
#include "telepathy-glib/_gen/tp-cli-account-body.h"
/**
@@ -80,33 +85,412 @@
*/
struct _TpAccountPrivate {
- gpointer dummy;
+ gboolean dispose_has_run;
+
+ TpConnection *connection;
+ guint connection_invalidated_id;
+
+ TpConnectionStatus connection_status;
+ TpConnectionStatusReason reason;
+
+ TpConnectionPresenceType presence;
+ gchar *status;
+ gchar *message;
+
+ gboolean enabled;
+ gboolean valid;
+ gboolean ready;
+ gboolean removed;
+ /* Timestamp when the connection got connected in seconds since the epoch */
+ glong connect_time;
+
+ gchar *cm_name;
+ gchar *proto_name;
+ gchar *icon_name;
+
+ gchar *unique_name;
+ gchar *display_name;
+ TpDBusDaemon *dbus;
+
+ GHashTable *parameters;
};
G_DEFINE_TYPE (TpAccount, tp_account, TP_TYPE_PROXY);
+/* signals */
+enum {
+ STATUS_CHANGED,
+ PRESENCE_CHANGED,
+ REMOVED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL];
+
+/* properties */
+enum {
+ PROP_ENABLED = 1,
+ PROP_PRESENCE,
+ PROP_STATUS,
+ PROP_STATUS_MESSAGE,
+ PROP_READY,
+ PROP_CONNECTION_STATUS,
+ PROP_CONNECTION_STATUS_REASON,
+ PROP_CONNECTION,
+ PROP_UNIQUE_NAME,
+ PROP_DBUS_DAEMON,
+ PROP_DISPLAY_NAME
+};
+
static void
tp_account_init (TpAccount *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, TP_TYPE_ACCOUNT,
TpAccountPrivate);
+
+ self->priv->connection_status = TP_CONNECTION_STATUS_DISCONNECTED;
}
static void
-tp_account_removed_cb (TpAccount *self,
+_tp_account_removed_cb (TpAccount *self,
gpointer unused G_GNUC_UNUSED,
GObject *object G_GNUC_UNUSED)
{
GError e = { TP_DBUS_ERRORS, TP_DBUS_ERROR_OBJECT_REMOVED,
- "Account removed" };
+ "Account removed" };
+
+ if (self->priv->removed)
+ return;
+
+ self->priv->removed = TRUE;
tp_proxy_invalidate ((TpProxy *) self, &e);
+
+ g_signal_emit (self, signals[REMOVED], 0);
+}
+
+static gchar *
+_tp_account_unescape_protocol (const gchar *protocol,
+ gssize len)
+{
+ gchar *result, *escape;
+ /* Bad implementation might accidentally use tp_escape_as_identifier,
+ * which escapes - in the wrong way... */
+ if ((escape = g_strstr_len (protocol, len, "_2d")) != NULL)
+ {
+ GString *str;
+ const gchar *input;
+
+ str = g_string_new ("");
+ input = protocol;
+ do {
+ g_string_append_len (str, input, escape - input);
+ g_string_append_c (str, '-');
+
+ len -= escape - input + 3;
+ input = escape + 3;
+ } while ((escape = g_strstr_len (input, len, "_2d")) != NULL);
+
+ g_string_append_len (str, input, len);
+
+ result = g_string_free (str, FALSE);
+ }
+ else
+ {
+ result = g_strndup (protocol, len);
+ }
+
+ g_strdelimit (result, "_", '-');
+
+ return result;
+}
+
+static gboolean
+_tp_account_parse_unique_name (const gchar *bus_name,
+ gchar **protocol,
+ gchar **manager)
+{
+ const gchar *proto, *proto_end;
+ const gchar *cm, *cm_end;
+
+ g_return_val_if_fail (
+ g_str_has_prefix (bus_name, TP_ACCOUNT_OBJECT_PATH_BASE), FALSE);
+
+ cm = bus_name + strlen (TP_ACCOUNT_OBJECT_PATH_BASE);
+
+ for (cm_end = cm; *cm_end != '/' && *cm_end != '\0'; cm_end++)
+ /* pass */;
+
+ if (*cm_end == '\0')
+ return FALSE;
+
+ if (cm_end == '\0')
+ return FALSE;
+
+ proto = cm_end + 1;
+
+ for (proto_end = proto; *proto_end != '/' && *proto_end != '\0'; proto_end++)
+ /* pass */;
+
+ if (*proto_end == '\0')
+ return FALSE;
+
+ if (protocol != NULL)
+ *protocol = _tp_account_unescape_protocol (proto, proto_end - proto);
+
+ if (manager != NULL)
+ *manager = g_strndup (cm, cm_end - cm);
+
+ return TRUE;
+}
+
+static void
+_tp_account_free_connection (TpAccount *account)
+{
+ TpAccountPrivate *priv = account->priv;
+ TpConnection *conn;
+
+ if (priv->connection == NULL)
+ return;
+
+ conn = priv->connection;
+ priv->connection = NULL;
+
+ if (priv->connection_invalidated_id != 0)
+ g_signal_handler_disconnect (conn, priv->connection_invalidated_id);
+ priv->connection_invalidated_id = 0;
+
+ g_object_unref (conn);
}
static void
-tp_account_constructed (GObject *object)
+_tp_account_connection_invalidated_cb (TpProxy *self,
+ guint domain,
+ gint code,
+ gchar *message,
+ gpointer user_data)
+{
+ TpAccount *account = TP_ACCOUNT (user_data);
+ TpAccountPrivate *priv = account->priv;
+
+ if (priv->connection == NULL)
+ return;
+
+ DEBUG ("(%s) Connection invalidated",
+ tp_account_get_unique_name (account));
+
+ g_assert (priv->connection == TP_CONNECTION (self));
+
+ _tp_account_free_connection (account);
+
+ g_object_notify (G_OBJECT (account), "connection");
+}
+
+static void
+_tp_account_connection_ready_cb (TpConnection *connection,
+ const GError *error,
+ gpointer user_data)
+{
+ TpAccount *account = TP_ACCOUNT (user_data);
+
+ if (error != NULL)
+ {
+ DEBUG ("(%s) Connection failed to become ready: %s",
+ tp_account_get_unique_name (account), error->message);
+ _tp_account_free_connection (account);
+ }
+ else
+ {
+ DEBUG ("(%s) Connection ready",
+ tp_account_get_unique_name (account));
+ g_object_notify (G_OBJECT (account), "connection");
+ }
+}
+
+static void
+_tp_account_set_connection (TpAccount *account,
+ const gchar *path)
+{
+ TpAccountPrivate *priv = account->priv;
+
+ if (priv->connection != NULL)
+ {
+ const gchar *current;
+
+ current = tp_proxy_get_object_path (priv->connection);
+ if (!tp_strdiff (current, path))
+ return;
+ }
+
+ _tp_account_free_connection (account);
+
+ if (tp_strdiff ("/", path))
+ {
+ GError *error = NULL;
+ priv->connection = tp_connection_new (priv->dbus, NULL, path, &error);
+
+ if (priv->connection == NULL)
+ {
+ DEBUG ("Failed to create a new TpConnection: %s",
+ error->message);
+ g_error_free (error);
+ }
+ else
+ {
+ priv->connection_invalidated_id = g_signal_connect (priv->connection,
+ "invalidated",
+ G_CALLBACK (_tp_account_connection_invalidated_cb), account);
+
+ DEBUG ("Readying connection for %s", priv->unique_name);
+ /* notify a change in the connection property when it's ready */
+ tp_connection_call_when_ready (priv->connection,
+ _tp_account_connection_ready_cb, account);
+ }
+ }
+
+ g_object_notify (G_OBJECT (account), "connection");
+}
+
+static void
+_tp_account_update (TpAccount *account,
+ GHashTable *properties)
+{
+ TpAccountPrivate *priv = account->priv;
+ GValueArray *arr;
+ TpConnectionStatus old_s = priv->connection_status;
+ gboolean presence_changed = FALSE;
+
+ if (g_hash_table_lookup (properties, "ConnectionStatus") != NULL)
+ priv->connection_status =
+ tp_asv_get_int32 (properties, "ConnectionStatus", NULL);
+
+ if (g_hash_table_lookup (properties, "ConnectionStatusReason") != NULL)
+ priv->reason = tp_asv_get_int32 (properties,
+ "ConnectionStatusReason", NULL);
+
+ if (g_hash_table_lookup (properties, "CurrentPresence") != NULL)
+ {
+ presence_changed = TRUE;
+ arr = tp_asv_get_boxed (properties, "CurrentPresence",
+ TP_STRUCT_TYPE_SIMPLE_PRESENCE);
+ priv->presence = g_value_get_uint (g_value_array_get_nth (arr, 0));
+
+ g_free (priv->status);
+ priv->status = g_value_dup_string (g_value_array_get_nth (arr, 1));
+
+ g_free (priv->message);
+ priv->message = g_value_dup_string (g_value_array_get_nth (arr, 2));
+ }
+
+ if (g_hash_table_lookup (properties, "DisplayName") != NULL)
+ {
+ g_free (priv->display_name);
+ priv->display_name =
+ g_strdup (tp_asv_get_string (properties, "DisplayName"));
+ g_object_notify (G_OBJECT (account), "display-name");
+ }
+
+ if (g_hash_table_lookup (properties, "Icon") != NULL)
+ {
+ const gchar *icon_name;
+
+ icon_name = tp_asv_get_string (properties, "Icon");
+
+ g_free (priv->icon_name);
+
+ if (icon_name == NULL || icon_name[0] == '\0')
+ priv->icon_name = g_strdup_printf ("im-%s", priv->proto_name);
+ else
+ priv->icon_name = g_strdup (icon_name);
+ }
+
+ if (g_hash_table_lookup (properties, "Enabled") != NULL)
+ {
+ gboolean enabled = tp_asv_get_boolean (properties, "Enabled", NULL);
+ if (priv->enabled != enabled)
+ {
+ priv->enabled = enabled;
+ g_object_notify (G_OBJECT (account), "enabled");
+ }
+ }
+
+ if (g_hash_table_lookup (properties, "Valid") != NULL)
+ priv->valid = tp_asv_get_boolean (properties, "Valid", NULL);
+
+ if (g_hash_table_lookup (properties, "Parameters") != NULL)
+ {
+ GHashTable *parameters;
+
+ parameters = tp_asv_get_boxed (properties, "Parameters",
+ TP_HASH_TYPE_STRING_VARIANT_MAP);
+
+ if (priv->parameters != NULL)
+ g_hash_table_unref (priv->parameters);
+
+ priv->parameters = g_boxed_copy (TP_HASH_TYPE_STRING_VARIANT_MAP,
+ parameters);
+ }
+
+ if (!priv->ready)
+ {
+ priv->ready = TRUE;
+ g_object_notify (G_OBJECT (account), "ready");
+ }
+
+ if (priv->connection_status != old_s)
+ {
+ if (priv->connection_status == TP_CONNECTION_STATUS_CONNECTED)
+ {
+ GTimeVal val;
+ g_get_current_time (&val);
+
+ priv->connect_time = val.tv_sec;
+ }
+
+ g_signal_emit (account, signals[STATUS_CHANGED], 0,
+ old_s, priv->connection_status, priv->reason);
+
+ g_object_notify (G_OBJECT (account), "connection-status");
+ g_object_notify (G_OBJECT (account), "connection-status-reason");
+ }
+
+ if (presence_changed)
+ {
+ g_signal_emit (account, signals[PRESENCE_CHANGED], 0,
+ priv->presence, priv->status, priv->message);
+ g_object_notify (G_OBJECT (account), "presence");
+ g_object_notify (G_OBJECT (account), "status");
+ g_object_notify (G_OBJECT (account), "status-message");
+ }
+
+ if (g_hash_table_lookup (properties, "Connection") != NULL)
+ {
+ const gchar *conn_path =
+ tp_asv_get_object_path (properties, "Connection");
+
+ _tp_account_set_connection (account, conn_path);
+ }
+}
+
+static void
+_tp_account_properties_changed (TpAccount *proxy,
+ GHashTable *properties,
+ gpointer user_data,
+ GObject *weak_object)
+{
+ TpAccount *self = TP_ACCOUNT (weak_object);
+
+ if (!self->priv->ready)
+ return;
+
+ _tp_account_update (self, properties);
+}
+
+static void
+_tp_account_constructed (GObject *object)
{
TpAccount *self = TP_ACCOUNT (object);
+ TpAccountPrivate *priv = self->priv;
void (*chain_up) (GObject *) =
((GObjectClass *) tp_account_parent_class)->constructed;
GError *error = NULL;
@@ -117,16 +501,139 @@ tp_account_constructed (GObject *object)
g_return_if_fail (tp_proxy_get_dbus_daemon (self) != NULL);
- sc = tp_cli_account_connect_to_removed (self, tp_account_removed_cb,
+ sc = tp_cli_account_connect_to_removed (self, _tp_account_removed_cb,
NULL, NULL, NULL, &error);
if (sc == NULL)
{
g_critical ("Couldn't connect to Removed: %s", error->message);
g_error_free (error);
- g_assert_not_reached ();
- return;
}
+
+ _tp_account_parse_unique_name (priv->unique_name,
+ &(priv->proto_name), &(priv->cm_name));
+
+ priv->icon_name = g_strdup_printf ("im-%s", priv->proto_name);
+
+ tp_cli_account_connect_to_account_property_changed (self,
+ _tp_account_properties_changed, NULL, NULL, object, NULL);
+
+ tp_account_refresh_properties (self);
+}
+
+static void
+_tp_account_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ TpAccount *self = TP_ACCOUNT (object);
+
+ switch (prop_id)
+ {
+ case PROP_ENABLED:
+ tp_account_set_enabled_async (self,
+ g_value_get_boolean (value), NULL, NULL);
+ break;
+ case PROP_UNIQUE_NAME:
+ self->priv->unique_name = g_value_dup_string (value);
+ break;
+ case PROP_DBUS_DAEMON:
+ self->priv->dbus = g_value_get_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+_tp_account_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ TpAccount *self = TP_ACCOUNT (object);
+
+ switch (prop_id)
+ {
+ case PROP_ENABLED:
+ g_value_set_boolean (value, self->priv->enabled);
+ break;
+ case PROP_READY:
+ g_value_set_boolean (value, self->priv->ready);
+ break;
+ case PROP_PRESENCE:
+ g_value_set_uint (value, self->priv->presence);
+ break;
+ case PROP_STATUS:
+ g_value_set_string (value, self->priv->status);
+ break;
+ case PROP_STATUS_MESSAGE:
+ g_value_set_string (value, self->priv->message);
+ break;
+ case PROP_CONNECTION_STATUS:
+ g_value_set_uint (value, self->priv->connection_status);
+ break;
+ case PROP_CONNECTION_STATUS_REASON:
+ g_value_set_uint (value, self->priv->reason);
+ break;
+ case PROP_CONNECTION:
+ g_value_set_object (value,
+ tp_account_get_connection (self));
+ break;
+ case PROP_UNIQUE_NAME:
+ g_value_set_string (value,
+ tp_account_get_unique_name (self));
+ break;
+ case PROP_DISPLAY_NAME:
+ g_value_set_string (value,
+ tp_account_get_display_name (self));
+ break;
+ case PROP_DBUS_DAEMON:
+ g_value_set_object (value, self->priv->dbus);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+_tp_account_dispose (GObject *object)
+{
+ TpAccount *self = TP_ACCOUNT (object);
+ TpAccountPrivate *priv = self->priv;
+
+ if (priv->dispose_has_run)
+ return;
+
+ priv->dispose_has_run = TRUE;
+
+ _tp_account_free_connection (self);
+
+ /* release any references held by the object here */
+ if (G_OBJECT_CLASS (tp_account_parent_class)->dispose != NULL)
+ G_OBJECT_CLASS (tp_account_parent_class)->dispose (object);
+}
+
+static void
+_tp_account_finalize (GObject *object)
+{
+ TpAccount *self = TP_ACCOUNT (object);
+ TpAccountPrivate *priv = self->priv;
+
+ g_free (priv->status);
+ g_free (priv->message);
+
+ g_free (priv->cm_name);
+ g_free (priv->proto_name);
+ g_free (priv->icon_name);
+ g_free (priv->display_name);
+
+ /* free any data held directly by the object here */
+ if (G_OBJECT_CLASS (tp_account_parent_class)->finalize != NULL)
+ G_OBJECT_CLASS (tp_account_parent_class)->finalize (object);
}
static void
@@ -137,7 +644,115 @@ tp_account_class_init (TpAccountClass *klass)
g_type_class_add_private (klass, sizeof (TpAccountPrivate));
- object_class->constructed = tp_account_constructed;
+ object_class->constructed = _tp_account_constructed;
+ object_class->get_property = _tp_account_get_property;
+ object_class->set_property = _tp_account_set_property;
+ object_class->dispose = _tp_account_dispose;
+ object_class->finalize = _tp_account_finalize;
+
+ 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_READWRITE));
+
+ g_object_class_install_property (object_class, PROP_READY,
+ g_param_spec_boolean ("ready",
+ "Ready",
+ "Whether this account is ready to be used",
+ FALSE,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
+
+ g_object_class_install_property (object_class, PROP_PRESENCE,
+ g_param_spec_uint ("presence",
+ "Presence",
+ "The account connections presence type",
+ 0,
+ NUM_TP_CONNECTION_PRESENCE_TYPES,
+ TP_CONNECTION_PRESENCE_TYPE_UNSET,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
+
+ g_object_class_install_property (object_class, PROP_STATUS,
+ g_param_spec_string ("status",
+ "Status",
+ "The Status string of the account",
+ NULL,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
+
+ g_object_class_install_property (object_class, PROP_STATUS_MESSAGE,
+ g_param_spec_string ("status-message",
+ "status-message",
+ "The Status message string of the account",
+ NULL,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
+
+ g_object_class_install_property (object_class, PROP_CONNECTION_STATUS,
+ g_param_spec_uint ("connection-status",
+ "ConnectionStatus",
+ "The accounts connections status type",
+ 0,
+ NUM_TP_CONNECTION_STATUSES,
+ TP_CONNECTION_STATUS_DISCONNECTED,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
+
+ g_object_class_install_property (object_class, PROP_CONNECTION_STATUS_REASON,
+ g_param_spec_uint ("connection-status-reason",
+ "ConnectionStatusReason",
+ "The account connections status reason",
+ 0,
+ NUM_TP_CONNECTION_STATUS_REASONS,
+ TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
+
+ g_object_class_install_property (object_class, PROP_CONNECTION,
+ g_param_spec_object ("connection",
+ "Connection",
+ "The accounts connection",
+ TP_TYPE_CONNECTION,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
+
+ g_object_class_install_property (object_class, PROP_UNIQUE_NAME,
+ g_param_spec_string ("unique-name",
+ "UniqueName",
+ "The accounts unique name",
+ NULL,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class, PROP_DBUS_DAEMON,
+ g_param_spec_object ("dbus-daemon",
+ "dbus-daemon",
+ "The Tp Dbus daemon on which this account exists",
+ TP_TYPE_DBUS_DAEMON,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class, PROP_DISPLAY_NAME,
+ g_param_spec_string ("display-name",
+ "DisplayName",
+ "The accounts display name",
+ NULL,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READABLE));
+
+ signals[STATUS_CHANGED] = g_signal_new ("status-changed",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ _tp_marshal_VOID__UINT_UINT_UINT,
+ G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT);
+
+ signals[PRESENCE_CHANGED] = g_signal_new ("presence-changed",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ _tp_marshal_VOID__UINT_STRING_STRING,
+ G_TYPE_NONE, 3, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING);
+
+ signals[REMOVED] = g_signal_new ("removed",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0, NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
proxy_class->interface = TP_IFACE_QUARK_ACCOUNT;
tp_account_init_known_interfaces ();
@@ -208,11 +823,577 @@ tp_account_new (TpDBusDaemon *bus_daemon,
}
self = TP_ACCOUNT (g_object_new (TP_TYPE_ACCOUNT,
- "dbus-daemon", bus_daemon,
- "dbus-connection", ((TpProxy *) bus_daemon)->dbus_connection,
- "bus-name", TP_ACCOUNT_MANAGER_BUS_NAME,
- "object-path", object_path,
- NULL));
+ "dbus-daemon", bus_daemon,
+ "dbus-connection", ((TpProxy *) bus_daemon)->dbus_connection,
+ "bus-name", TP_ACCOUNT_MANAGER_BUS_NAME,
+ "object-path", object_path,
+ NULL));
return self;
}
+
+static void
+_tp_account_got_all_cb (TpProxy *proxy,
+ GHashTable *properties,
+ const GError *error,
+ gpointer user_data,
+ GObject *weak_object)
+{
+ TpAccount *self = TP_ACCOUNT (weak_object);
+
+ DEBUG ("Got whole set of properties for %s",
+ tp_account_get_unique_name (self));
+
+ if (error != NULL)
+ {
+ DEBUG ("Failed to get the initial set of account properties: %s",
+ error->message);
+ return;
+ }
+
+ _tp_account_update (self, properties);
+}
+
+gboolean
+tp_account_is_just_connected (TpAccount *account)
+{
+ TpAccountPrivate *priv = account->priv;
+ GTimeVal val;
+
+ if (priv->connection_status != TP_CONNECTION_STATUS_CONNECTED)
+ return FALSE;
+
+ g_get_current_time (&val);
+
+ return (val.tv_sec - priv->connect_time) < 10;
+}
+
+/**
+ * tp_account_get_connection:
+ * @account: a #TpAccount
+ *
+ * Get the connection of the account, or NULL if account is offline or the
+ * connection is not yet ready. This function does not return a new ref.
+ *
+ * Returns: the connection of the account.
+ **/
+TpConnection *
+tp_account_get_connection (TpAccount *account)
+{
+ TpAccountPrivate *priv = account->priv;
+
+ if (priv->connection != NULL &&
+ tp_connection_is_ready (priv->connection))
+ return priv->connection;
+
+ return NULL;
+}
+
+/**
+ * tp_account_get_connection_for_path:
+ * @account: a #TpAccount
+ * @patch: the path to connection object for #TpAccount
+ *
+ * Get the connection of the account on path. This function does not return a
+ * new ref. It is not guaranteed that the returned connection object is ready
+ *
+ * Returns: the connection of the account.
+ **/
+TpConnection *
+tp_account_get_connection_for_path (TpAccount *account,
+ const gchar *path)
+{
+ TpAccountPrivate *priv = account->priv;
+
+ /* double-check that the object path is valid */
+ if (!tp_dbus_check_valid_object_path (path, NULL))
+ return NULL;
+
+ /* Should be a full object path, not the special "/" value */
+ if (strlen (path) == 1)
+ return NULL;
+
+ _tp_account_set_connection (account, path);
+
+ return priv->connection;
+}
+
+/**
+ * tp_account_get_unique_name:
+ * @account: a #TpAccount
+ *
+ * Returns: the unique name of the account.
+ **/
+const gchar *
+tp_account_get_unique_name (TpAccount *account)
+{
+ TpAccountPrivate *priv = account->priv;
+
+ return priv->unique_name;
+}
+
+/**
+ * tp_account_get_display_name:
+ * @account: a #TpAccount
+ *
+ * Returns: the display name of the account.
+ **/
+const gchar *
+tp_account_get_display_name (TpAccount *account)
+{
+ TpAccountPrivate *priv = account->priv;
+
+ return priv->display_name;
+}
+
+gboolean
+tp_account_is_valid (TpAccount *account)
+{
+ TpAccountPrivate *priv = account->priv;
+
+ return priv->valid;
+}
+
+const gchar *
+tp_account_get_connection_manager (TpAccount *account)
+{
+ TpAccountPrivate *priv = account->priv;
+
+ return priv->cm_name;
+}
+
+const gchar *
+tp_account_get_protocol (TpAccount *account)
+{
+ TpAccountPrivate *priv = account->priv;
+
+ return priv->proto_name;
+}
+
+const gchar *
+tp_account_get_icon_name (TpAccount *account)
+{
+ TpAccountPrivate *priv = account->priv;
+
+ return priv->icon_name;
+}
+
+const GHashTable *
+tp_account_get_parameters (TpAccount *account)
+{
+ TpAccountPrivate *priv = account->priv;
+
+ return priv->parameters;
+}
+
+gboolean
+tp_account_is_enabled (TpAccount *account)
+{
+ TpAccountPrivate *priv = account->priv;
+
+ return priv->enabled;
+}
+
+gboolean
+tp_account_is_ready (TpAccount *account)
+{
+ TpAccountPrivate *priv = account->priv;
+
+ return priv->ready;
+}
+
+#if 0
+static void
+_tp_account_enabled_set_cb (TpProxy *proxy,
+ const GError *error,
+ gpointer user_data,
+ GObject *weak_object)
+{
+ GSimpleAsyncResult *result = user_data;
+
+ if (error != NULL)
+ g_simple_async_result_set_from_error (result, (GError *) error);
+
+ g_simple_async_result_complete (result);
+ g_object_unref (result);
+}
+#endif
+
+gboolean
+tp_account_set_enabled_finish (TpAccount *account,
+ GAsyncResult *result,
+ GError **error)
+{
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result),
+ error) ||
+ !g_simple_async_result_is_valid (result, G_OBJECT (account),
+ tp_account_set_enabled_finish))
+ return FALSE;
+
+ return TRUE;
+}
+
+void
+tp_account_set_enabled_async (TpAccount *account,
+ gboolean enabled,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ /* Disabled for now due to lack of account manager */
+
+#if 0
+ TpAccountPrivate *priv = account->priv;
+ TpAccountManager *acc_manager;
+ GValue value = {0, };
+ GSimpleAsyncResult *result;
+ char *status = NULL;
+ char *status_message = NULL;
+ TpConnectionPresenceType presence;
+
+ result = g_simple_async_result_new (G_OBJECT (account),
+ callback, user_data, tp_account_set_enabled_finish);
+
+ if (priv->enabled == enabled)
+ {
+ g_simple_async_result_complete_in_idle (result);
+ return;
+ }
+
+ if (enabled)
+ {
+ acc_manager = tp_account_manager_dup_singleton ();
+ presence = tp_account_manager_get_requested_global_presence (
+ acc_manager, &status, &status_message);
+
+ if (presence != TP_CONNECTION_PRESENCE_TYPE_UNSET)
+ tp_account_request_presence (account, presence, status,
+ status_message);
+
+ g_object_unref (acc_manager);
+ g_free (status);
+ g_free (status_message);
+ }
+
+ g_value_init (&value, G_TYPE_BOOLEAN);
+ g_value_set_boolean (&value, enabled);
+
+ tp_cli_dbus_properties_call_set (TP_PROXY (account),
+ -1, TP_IFACE_ACCOUNT, "Enabled", &value,
+ _tp_account_enabled_set_cb, result, NULL, G_OBJECT (account));
+#endif
+}
+
+static void
+_tp_account_reconnected_cb (TpAccount *proxy,
+ const GError *error,
+ gpointer user_data,
+ GObject *weak_object)
+{
+ GSimpleAsyncResult *result = user_data;
+
+ if (error != NULL)
+ g_simple_async_result_set_from_error (result, (GError *) error);
+
+ g_simple_async_result_complete (result);
+ g_object_unref (result);
+}
+
+gboolean
+tp_account_reconnect_finish (TpAccount *account,
+ GAsyncResult *result,
+ GError **error)
+{
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result),
+ error) ||
+ !g_simple_async_result_is_valid (result, G_OBJECT (account),
+ tp_account_reconnect_finish))
+ return FALSE;
+
+ return TRUE;
+}
+
+void
+tp_account_reconnect_async (TpAccount *account,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *result;
+
+ result = g_simple_async_result_new (G_OBJECT (account),
+ callback, user_data, tp_account_reconnect_finish);
+
+ tp_cli_account_call_reconnect (account, -1, _tp_account_reconnected_cb,
+ result, NULL, G_OBJECT (account));
+}
+
+static void
+_tp_account_requested_presence_cb (TpProxy *proxy,
+ const GError *error,
+ gpointer user_data,
+ GObject *weak_object)
+{
+ GSimpleAsyncResult *result = user_data;
+
+ if (error)
+ DEBUG ("Failed to set the requested presence: %s", error->message);
+
+ if (error != NULL)
+ g_simple_async_result_set_from_error (result, (GError *) error);
+
+ g_simple_async_result_complete (result);
+ g_object_unref (result);
+}
+
+gboolean
+tp_account_request_presence_finish (TpAccount *account,
+ GAsyncResult *result,
+ GError **error)
+{
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result),
+ error) ||
+ !g_simple_async_result_is_valid (result, G_OBJECT (account),
+ tp_account_request_presence_finish))
+ return FALSE;
+
+ return TRUE;
+}
+
+void
+tp_account_request_presence_async (TpAccount *account,
+ TpConnectionPresenceType type,
+ const gchar *status,
+ const gchar *message,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GValue value = {0, };
+ GValueArray *arr;
+ GSimpleAsyncResult *result;
+
+ result = g_simple_async_result_new (G_OBJECT (account),
+ callback, user_data, tp_account_request_presence_finish);
+
+ g_value_init (&value, TP_STRUCT_TYPE_SIMPLE_PRESENCE);
+ g_value_take_boxed (&value, dbus_g_type_specialized_construct (
+ TP_STRUCT_TYPE_SIMPLE_PRESENCE));
+ arr = (GValueArray *) g_value_get_boxed (&value);
+
+ g_value_set_uint (arr->values, type);
+ g_value_set_static_string (arr->values + 1, status);
+ g_value_set_static_string (arr->values + 2, message);
+
+ tp_cli_dbus_properties_call_set (TP_PROXY (account), -1,
+ TP_IFACE_ACCOUNT, "RequestedPresence", &value,
+ _tp_account_requested_presence_cb, result, NULL, G_OBJECT (account));
+
+ g_value_unset (&value);
+}
+
+static void
+_tp_account_updated_cb (TpAccount *proxy,
+ const gchar **reconnect_required,
+ const GError *error,
+ gpointer user_data,
+ GObject *weak_object)
+{
+ GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data);
+
+ if (error != NULL)
+ g_simple_async_result_set_from_error (result, (GError *) error);
+
+ g_simple_async_result_complete (result);
+ g_object_unref (G_OBJECT (result));
+}
+
+void
+tp_account_update_settings_async (TpAccount *account,
+ GHashTable *parameters,
+ const gchar **unset_parameters,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *result;
+
+ result = g_simple_async_result_new (G_OBJECT (account),
+ callback, user_data, tp_account_update_settings_finish);
+
+ tp_cli_account_call_update_parameters (account, -1, parameters,
+ unset_parameters, _tp_account_updated_cb, result,
+ NULL, G_OBJECT (account));
+}
+
+gboolean
+tp_account_update_settings_finish (TpAccount *account,
+ GAsyncResult *result,
+ GError **error)
+{
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result),
+ error))
+ return FALSE;
+
+ g_return_val_if_fail (g_simple_async_result_is_valid (result,
+ G_OBJECT (account), tp_account_update_settings_finish), FALSE);
+
+ return TRUE;
+}
+
+static void
+_tp_account_display_name_set_cb (TpProxy *proxy,
+ const GError *error,
+ gpointer user_data,
+ GObject *weak_object)
+{
+ GSimpleAsyncResult *result = user_data;
+
+ if (error != NULL)
+ g_simple_async_result_set_from_error (result, (GError *) error);
+
+ g_simple_async_result_complete (result);
+ g_object_unref (result);
+}
+
+void
+tp_account_set_display_name_async (TpAccount *account,
+ const char *display_name,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *result;
+ GValue value = {0, };
+
+ if (display_name == NULL)
+ {
+ g_simple_async_report_error_in_idle (G_OBJECT (account),
+ callback, user_data, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+ "Can't set an empty display name");
+ return;
+ }
+
+ result = g_simple_async_result_new (G_OBJECT (account), callback,
+ user_data, tp_account_set_display_name_finish);
+
+ g_value_init (&value, G_TYPE_STRING);
+ g_value_set_string (&value, display_name);
+
+ tp_cli_dbus_properties_call_set (account, -1, TP_IFACE_ACCOUNT,
+ "DisplayName", &value, _tp_account_display_name_set_cb, result, NULL,
+ G_OBJECT (account));
+}
+
+gboolean
+tp_account_set_display_name_finish (TpAccount *account,
+ GAsyncResult *result,
+ GError **error)
+{
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result),
+ error) ||
+ !g_simple_async_result_is_valid (result, G_OBJECT (account),
+ tp_account_set_display_name_finish))
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+_tp_account_icon_name_set_cb (TpProxy *proxy,
+ const GError *error,
+ gpointer user_data,
+ GObject *weak_object)
+{
+ GSimpleAsyncResult *result = user_data;
+
+ if (error != NULL)
+ g_simple_async_result_set_from_error (result, (GError *) error);
+
+ g_simple_async_result_complete (result);
+ g_object_unref (result);
+}
+
+void
+tp_account_set_icon_name_async (TpAccount *account,
+ const char *icon_name,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *result;
+ GValue value = {0, };
+ const char *icon_name_set;
+
+ if (icon_name == NULL)
+ /* settings an empty icon name is allowed */
+ icon_name_set = "";
+ else
+ icon_name_set = icon_name;
+
+ result = g_simple_async_result_new (G_OBJECT (account), callback,
+ user_data, tp_account_set_icon_name_finish);
+
+ g_value_init (&value, G_TYPE_STRING);
+ g_value_set_string (&value, icon_name_set);
+
+ tp_cli_dbus_properties_call_set (account, -1, TP_IFACE_ACCOUNT,
+ "Icon", &value, _tp_account_icon_name_set_cb, result, NULL,
+ G_OBJECT (account));
+}
+
+gboolean
+tp_account_set_icon_name_finish (TpAccount *account,
+ GAsyncResult *result, GError **error)
+{
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result),
+ error) ||
+ !g_simple_async_result_is_valid (result, G_OBJECT (account),
+ tp_account_set_icon_name_finish))
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+_tp_account_remove_cb (TpAccount *proxy,
+ const GError *error,
+ gpointer user_data,
+ GObject *weak_object)
+{
+ GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data);
+
+ if (error != NULL)
+ g_simple_async_result_set_from_error (result, (GError *) error);
+
+ g_simple_async_result_complete (result);
+ g_object_unref (G_OBJECT (result));
+}
+
+void
+tp_account_remove_async (TpAccount *account,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (account),
+ callback, user_data, tp_account_remove_finish);
+
+ tp_cli_account_call_remove (account, -1, _tp_account_remove_cb, result, NULL,
+ G_OBJECT (account));
+}
+
+gboolean
+tp_account_remove_finish (TpAccount *account,
+ GAsyncResult *result,
+ GError **error)
+{
+ if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result),
+ error))
+ return FALSE;
+
+ g_return_val_if_fail (g_simple_async_result_is_valid (result,
+ G_OBJECT (account), tp_account_remove_finish), FALSE);
+
+ return TRUE;
+}
+
+void
+tp_account_refresh_properties (TpAccount *account)
+{
+ tp_cli_dbus_properties_call_get_all (account, -1, TP_IFACE_ACCOUNT,
+ _tp_account_got_all_cb, NULL, NULL, G_OBJECT (account));
+}
diff --git a/telepathy-glib/account.h b/telepathy-glib/account.h
index 4072d75..c2e3432 100644
--- a/telepathy-glib/account.h
+++ b/telepathy-glib/account.h
@@ -22,6 +22,9 @@
#ifndef TP_ACCOUNT_H
#define TP_ACCOUNT_H
+#include <gio/gio.h>
+
+#include <telepathy-glib/connection.h>
#include <telepathy-glib/proxy.h>
#include <telepathy-glib/dbus.h>
@@ -68,6 +71,79 @@ TpAccount *tp_account_new (TpDBusDaemon *bus_daemon, const gchar *object_path,
void tp_account_init_known_interfaces (void);
+gboolean tp_account_is_just_connected (TpAccount *account);
+
+TpConnection *tp_account_get_connection (TpAccount *account);
+
+TpConnection *tp_account_get_connection_for_path (TpAccount *account,
+ const gchar *path);
+
+const gchar *tp_account_get_unique_name (TpAccount *account);
+
+const gchar *tp_account_get_display_name (TpAccount *account);
+
+const gchar *tp_account_get_connection_manager (TpAccount *account);
+
+const gchar *tp_account_get_protocol (TpAccount *account);
+
+const gchar *tp_account_get_icon_name (TpAccount *account);
+
+void tp_account_set_enabled_async (TpAccount *account,
+ gboolean enabled, GAsyncReadyCallback callback, gpointer user_data);
+
+gboolean tp_account_set_enabled_finish (TpAccount *account,
+ GAsyncResult *result, GError **error);
+
+void tp_account_reconnect_async (TpAccount *account,
+ GAsyncReadyCallback callback, gpointer user_data);
+
+gboolean tp_account_reconnect_finish (TpAccount *account,
+ GAsyncResult *result, GError **error);
+
+gboolean tp_account_is_enabled (TpAccount *account);
+
+gboolean tp_account_is_valid (TpAccount *account);
+
+gboolean tp_account_is_ready (TpAccount *account);
+
+void tp_account_update_settings_async (TpAccount *account,
+ GHashTable *parameters, const gchar **unset_parameters,
+ GAsyncReadyCallback callback, gpointer user_data);
+
+gboolean tp_account_update_settings_finish (TpAccount *account,
+ GAsyncResult *result, GError **error);
+
+void tp_account_remove_async (TpAccount *account,
+ GAsyncReadyCallback callback, gpointer user_data);
+
+gboolean tp_account_remove_finish (TpAccount *account,
+ GAsyncResult *result, GError **error);
+
+void tp_account_set_display_name_async (TpAccount *account,
+ const gchar *display_name, GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean tp_account_set_display_name_finish (TpAccount *account,
+ GAsyncResult *result, GError **error);
+
+void tp_account_set_icon_name_async (TpAccount *account,
+ const gchar *icon_name, GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean tp_account_set_icon_name_finish (TpAccount *account,
+ GAsyncResult *result, GError **error);
+
+void tp_account_request_presence_async (TpAccount *account,
+ TpConnectionPresenceType type, const gchar *status, const gchar *message,
+ GAsyncReadyCallback callback, gpointer user_data);
+
+gboolean tp_account_request_presence_finish (TpAccount *account,
+ GAsyncResult *result, GError **error);
+
+const GHashTable *tp_account_get_parameters (TpAccount *account);
+
+void tp_account_refresh_properties (TpAccount *account);
+
G_END_DECLS
#include <telepathy-glib/_gen/tp-cli-account.h>
diff --git a/telepathy-glib/signals-marshal.list b/telepathy-glib/signals-marshal.list
index 0d7a7ee..2a02689 100644
--- a/telepathy-glib/signals-marshal.list
+++ b/telepathy-glib/signals-marshal.list
@@ -4,4 +4,6 @@ VOID:POINTER,OBJECT
VOID:POINTER,UINT,INT,STRING
VOID:STRING,UINT,UINT,BOXED
VOID:UINT,INT,STRING
+VOID:UINT,UINT,UINT
VOID:UINT,OBJECT
+VOID:UINT,STRING,STRING
--
1.5.6.5
More information about the telepathy-commits
mailing list