[Telepathy-commits] [telepathy-glib/master] TpContact: track aliases if supported and requested
Simon McVittie
simon.mcvittie at collabora.co.uk
Thu Oct 16 07:22:20 PDT 2008
---
telepathy-glib/connection-internal.h | 1 +
telepathy-glib/contact.c | 183 ++++++++++++++++++++++++++++++++++
2 files changed, 184 insertions(+), 0 deletions(-)
diff --git a/telepathy-glib/connection-internal.h b/telepathy-glib/connection-internal.h
index 5d4894c..62730c4 100644
--- a/telepathy-glib/connection-internal.h
+++ b/telepathy-glib/connection-internal.h
@@ -45,6 +45,7 @@ struct _TpConnectionPrivate {
GHashTable *contacts;
unsigned ready:1;
+ unsigned tracking_aliases_changed:1;
};
void _tp_connection_init_handle_refs (TpConnection *self);
diff --git a/telepathy-glib/contact.c b/telepathy-glib/contact.c
index 5aa4ff7..06fdfaf 100644
--- a/telepathy-glib/contact.c
+++ b/telepathy-glib/contact.c
@@ -20,9 +20,12 @@
#include <telepathy-glib/contact.h>
+#include <telepathy-glib/interfaces.h>
#include <telepathy-glib/util.h>
+#define DEBUG_FLAG TP_DEBUG_CONTACTS
#include "telepathy-glib/connection-internal.h"
+#include "telepathy-glib/debug-internal.h"
/**
@@ -1035,6 +1038,179 @@ contacts_inspect (ContactsContext *c)
}
+static void
+contacts_requested_aliases (TpConnection *connection,
+ const gchar **aliases,
+ const GError *error,
+ gpointer user_data,
+ GObject *weak_object)
+{
+ ContactsContext *c = user_data;
+
+ g_assert (c->handles->len == c->contacts->len);
+
+ if (error == NULL)
+ {
+ guint i;
+
+ if (G_UNLIKELY (g_strv_length ((GStrv) aliases) != c->contacts->len))
+ {
+ g_warning ("Connection manager %s is broken: we requested %u "
+ "handles' aliases but got %u strings back",
+ tp_proxy_get_bus_name (connection), c->contacts->len,
+ g_strv_length ((GStrv) aliases));
+
+ /* give up on the possibility of getting aliases, and just
+ * move on */
+ contacts_context_continue (c);
+ return;
+ }
+
+ for (i = 0; i < c->contacts->len; i++)
+ {
+ TpContact *contact = g_ptr_array_index (c->contacts, i);
+ const gchar *alias = aliases[i];
+
+ contact->priv->has_features |= CONTACT_FEATURE_FLAG_ALIAS;
+ g_free (contact->priv->alias);
+ contact->priv->alias = g_strdup (alias);
+ g_object_notify ((GObject *) contact, "alias");
+ }
+ }
+ else
+ {
+ /* never mind, we can live without aliases */
+ DEBUG ("GetAliases failed with %s %u: %s",
+ g_quark_to_string (error->domain), error->code, error->message);
+ }
+
+ contacts_context_continue (c);
+}
+
+
+static void
+contacts_got_aliases (TpConnection *connection,
+ GHashTable *handle_to_alias,
+ const GError *error,
+ gpointer user_data,
+ GObject *weak_object)
+{
+ ContactsContext *c = user_data;
+
+ if (error == NULL)
+ {
+ guint i;
+
+ for (i = 0; i < c->contacts->len; i++)
+ {
+ TpContact *contact = g_ptr_array_index (c->contacts, i);
+ const gchar *alias = g_hash_table_lookup (handle_to_alias,
+ GUINT_TO_POINTER (contact->priv->handle));
+
+ contact->priv->has_features |= CONTACT_FEATURE_FLAG_ALIAS;
+ g_free (contact->priv->alias);
+ contact->priv->alias = NULL;
+
+ if (alias != NULL)
+ {
+ contact->priv->alias = g_strdup (alias);
+ }
+ else
+ {
+ g_warning ("No alias returned for %u, will use ID instead",
+ contact->priv->handle);
+ }
+
+ g_object_notify ((GObject *) contact, "alias");
+ }
+ }
+ else if ((error->domain == TP_ERRORS &&
+ error->code == TP_ERROR_NOT_IMPLEMENTED) ||
+ (error->domain == DBUS_GERROR &&
+ error->code == DBUS_GERROR_UNKNOWN_METHOD))
+ {
+ /* GetAliases not implemented, fall back to (slow?) RequestAliases */
+ c->refcount++;
+ tp_cli_connection_interface_aliasing_call_request_aliases (connection,
+ -1, c->handles, contacts_requested_aliases,
+ c, contacts_context_unref, weak_object);
+ return;
+ }
+ else
+ {
+ /* never mind, we can live without aliases */
+ DEBUG ("GetAliases failed with %s %u: %s",
+ g_quark_to_string (error->domain), error->code, error->message);
+ }
+
+ contacts_context_continue (c);
+}
+
+
+static void
+contacts_aliases_changed (TpConnection *connection,
+ const GPtrArray *alias_structs,
+ gpointer user_data G_GNUC_UNUSED,
+ GObject *weak_object G_GNUC_UNUSED)
+{
+ guint i;
+
+ for (i = 0; i < alias_structs->len; i++)
+ {
+ GValueArray *pair = g_ptr_array_index (alias_structs, i);
+ TpHandle handle = g_value_get_uint (pair->values + 0);
+ const gchar *alias = g_value_get_string (pair->values + 1);
+ TpContact *contact = _tp_connection_lookup_contact (connection, handle);
+
+ if (contact != NULL)
+ {
+ contact->priv->has_features |= CONTACT_FEATURE_FLAG_ALIAS;
+ DEBUG ("Contact \"%s\" alias changed from \"%s\" to \"%s\"",
+ contact->priv->identifier, contact->priv->alias, alias);
+ g_free (contact->priv->alias);
+ contact->priv->alias = g_strdup (alias);
+ g_object_notify ((GObject *) contact, "alias");
+ }
+ }
+}
+
+
+static void
+contacts_get_aliases (ContactsContext *c)
+{
+ guint i;
+
+ g_assert (c->handles->len == c->contacts->len);
+
+ /* ensure we'll get told about alias changes */
+ if (!c->connection->priv->tracking_aliases_changed)
+ {
+ c->connection->priv->tracking_aliases_changed = TRUE;
+
+ tp_cli_connection_interface_aliasing_connect_to_aliases_changed (
+ c->connection, contacts_aliases_changed, NULL, NULL, NULL, NULL);
+ }
+
+ for (i = 0; i < c->contacts->len; i++)
+ {
+ TpContact *contact = g_ptr_array_index (c->contacts, i);
+
+ if ((contact->priv->has_features & CONTACT_FEATURE_FLAG_ALIAS) == 0)
+ {
+ c->refcount++;
+ tp_cli_connection_interface_aliasing_call_get_aliases (c->connection,
+ -1, c->handles, contacts_got_aliases, c, contacts_context_unref,
+ c->weak_object);
+ return;
+ }
+ }
+
+ /* else there's no need to get the contacts' aliases, because we already
+ * know them all */
+ contacts_context_continue (c);
+}
+
+
/**
* tp_connection_get_contacts_by_handle:
* @self: A connection, which must be ready (#TpConnection:connection-ready
@@ -1097,6 +1273,13 @@ tp_connection_get_contacts_by_handle (TpConnection *self,
/* Before we return anything we'll want to inspect the handles */
g_queue_push_head (&context->todo, contacts_inspect);
+ if ((feature_flags & CONTACT_FEATURE_FLAG_ALIAS) != 0 &&
+ tp_proxy_has_interface_by_id (self,
+ TP_IFACE_QUARK_CONNECTION_INTERFACE_ALIASING))
+ {
+ g_queue_push_tail (&context->todo, contacts_get_aliases);
+ }
+
/* but first, we need to hold onto them */
tp_connection_hold_handles (self, -1,
TP_HANDLE_TYPE_CONTACT, n_handles, handles,
--
1.5.6.5
More information about the Telepathy-commits
mailing list