[Telepathy-commits] [telepathy-glib/master] TpContact: track presence and avatars
Simon McVittie
simon.mcvittie at collabora.co.uk
Fri Oct 17 08:03:15 PDT 2008
Currently, this only works if the CM has SimplePresence and GetKnownAvatarTokens.
---
telepathy-glib/connection-internal.h | 3 +
telepathy-glib/contact.c | 211 ++++++++++++++++++++++++++++++++++
2 files changed, 214 insertions(+), 0 deletions(-)
diff --git a/telepathy-glib/connection-internal.h b/telepathy-glib/connection-internal.h
index 62730c4..e51b8b1 100644
--- a/telepathy-glib/connection-internal.h
+++ b/telepathy-glib/connection-internal.h
@@ -46,6 +46,9 @@ struct _TpConnectionPrivate {
unsigned ready:1;
unsigned tracking_aliases_changed:1;
+ unsigned tracking_avatar_updated:1;
+ unsigned tracking_presences_changed:1;
+ unsigned tracking_presence_update:1;
};
void _tp_connection_init_handle_refs (TpConnection *self);
diff --git a/telepathy-glib/contact.c b/telepathy-glib/contact.c
index 06fdfaf..82c5ccc 100644
--- a/telepathy-glib/contact.c
+++ b/telepathy-glib/contact.c
@@ -1211,6 +1211,192 @@ contacts_get_aliases (ContactsContext *c)
}
+static void
+contacts_presences_changed (TpConnection *connection,
+ GHashTable *presences,
+ gpointer user_data G_GNUC_UNUSED,
+ GObject *weak_object G_GNUC_UNUSED)
+{
+ GHashTableIter iter;
+ gpointer key, value;
+
+ g_hash_table_iter_init (&iter, presences);
+
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ TpContact *contact = _tp_connection_lookup_contact (connection,
+ GPOINTER_TO_UINT (key));
+ GValueArray *presence = value;
+
+ if (contact == NULL)
+ continue;
+
+ contact->priv->has_features |= CONTACT_FEATURE_FLAG_PRESENCE;
+ contact->priv->presence_type = g_value_get_uint (presence->values + 0);
+ g_free (contact->priv->presence_status);
+ contact->priv->presence_status = g_value_dup_string (
+ presence->values + 1);
+ g_free (contact->priv->presence_message);
+ contact->priv->presence_message = g_value_dup_string (
+ presence->values + 2);
+
+ g_object_notify ((GObject *) contact, "presence-type");
+ g_object_notify ((GObject *) contact, "presence-status");
+ g_object_notify ((GObject *) contact, "presence-message");
+ }
+}
+
+
+static void
+contacts_got_simple_presence (TpConnection *connection,
+ GHashTable *presences,
+ const GError *error,
+ gpointer user_data,
+ GObject *weak_object)
+{
+ ContactsContext *c = user_data;
+
+ if (error == NULL)
+ {
+ contacts_presences_changed (connection, presences, NULL, NULL);
+ }
+ else
+ {
+ /* never mind, we can live without presences */
+ DEBUG ("GetPresences failed with %s %u: %s",
+ g_quark_to_string (error->domain), error->code, error->message);
+ }
+
+ contacts_context_continue (c);
+}
+
+
+static void
+contacts_get_simple_presence (ContactsContext *c)
+{
+ guint i;
+
+ g_assert (c->handles->len == c->contacts->len);
+
+ if (!c->connection->priv->tracking_presences_changed)
+ {
+ c->connection->priv->tracking_presences_changed = TRUE;
+
+ tp_cli_connection_interface_simple_presence_connect_to_presences_changed
+ (c->connection, contacts_presences_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_PRESENCE) == 0)
+ {
+ c->refcount++;
+ tp_cli_connection_interface_simple_presence_call_get_presences (
+ c->connection, -1,
+ c->handles, contacts_got_simple_presence,
+ c, contacts_context_unref, c->weak_object);
+ return;
+ }
+ }
+
+ contacts_context_continue (c);
+}
+
+
+static void
+contacts_avatar_updated (TpConnection *connection,
+ TpHandle handle,
+ const gchar *new_token,
+ gpointer user_data G_GNUC_UNUSED,
+ GObject *weak_object G_GNUC_UNUSED)
+{
+ TpContact *contact = _tp_connection_lookup_contact (connection, handle);
+
+ DEBUG ("contact#%u token is %s", handle, new_token);
+
+ if (contact == NULL)
+ return;
+
+ contact->priv->has_features |= CONTACT_FEATURE_FLAG_AVATAR_TOKEN;
+ g_free (contact->priv->avatar_token);
+ contact->priv->avatar_token = g_strdup (new_token);
+ g_object_notify ((GObject *) contact, "avatar-token");
+}
+
+
+static void
+contacts_got_known_avatar_tokens (TpConnection *connection,
+ GHashTable *handle_to_token,
+ const GError *error,
+ gpointer user_data,
+ GObject *weak_object)
+{
+ ContactsContext *c = user_data;
+ GHashTableIter iter;
+ gpointer key, value;
+
+ if (error == NULL)
+ {
+ g_hash_table_iter_init (&iter, handle_to_token);
+
+ while (g_hash_table_iter_next (&iter, &key, &value))
+ {
+ contacts_avatar_updated (connection, GPOINTER_TO_UINT (key), value,
+ NULL, NULL);
+ }
+
+ }
+ /* FIXME: perhaps we could fall back to GetAvatarTokens (which should have
+ * been called RequestAvatarTokens, because it blocks on network traffic)
+ * if GetKnownAvatarTokens doesn't work? */
+ else
+ {
+ /* never mind, we can live without avatar tokens */
+ DEBUG ("GetKnownAvatarTokens failed with %s %u: %s",
+ g_quark_to_string (error->domain), error->code, error->message);
+ }
+
+ contacts_context_continue (c);
+}
+
+
+static void
+contacts_get_avatar_tokens (ContactsContext *c)
+{
+ guint i;
+
+ g_assert (c->handles->len == c->contacts->len);
+
+ if (!c->connection->priv->tracking_avatar_updated)
+ {
+ c->connection->priv->tracking_avatar_updated = TRUE;
+
+ tp_cli_connection_interface_avatars_connect_to_avatar_updated
+ (c->connection, contacts_avatar_updated, 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_AVATAR_TOKEN)
+ == 0)
+ {
+ c->refcount++;
+ tp_cli_connection_interface_avatars_call_get_known_avatar_tokens (
+ c->connection, -1,
+ c->handles, contacts_got_known_avatar_tokens,
+ c, contacts_context_unref, c->weak_object);
+ return;
+ }
+ }
+
+ contacts_context_continue (c);
+}
+
+
/**
* tp_connection_get_contacts_by_handle:
* @self: A connection, which must be ready (#TpConnection:connection-ready
@@ -1280,6 +1466,31 @@ tp_connection_get_contacts_by_handle (TpConnection *self,
g_queue_push_tail (&context->todo, contacts_get_aliases);
}
+ if ((feature_flags & CONTACT_FEATURE_FLAG_PRESENCE) != 0)
+ {
+ if (tp_proxy_has_interface_by_id (self,
+ TP_IFACE_QUARK_CONNECTION_INTERFACE_SIMPLE_PRESENCE))
+ {
+ g_queue_push_tail (&context->todo, contacts_get_simple_presence);
+ }
+#if 0
+ /* FIXME: Before doing this for the first time, we'd need to download
+ * from the CM the definition of what each status actually *means* */
+ else if (tp_proxy_has_interface_by_id (self,
+ TP_IFACE_QUARK_CONNECTION_INTERFACE_PRESENCE))
+ {
+ g_queue_push_tail (&context->todo, contacts_get_complex_presence);
+ }
+#endif
+ }
+
+ if ((feature_flags & CONTACT_FEATURE_FLAG_AVATAR_TOKEN) != 0 &&
+ tp_proxy_has_interface_by_id (self,
+ TP_IFACE_QUARK_CONNECTION_INTERFACE_AVATARS))
+ {
+ g_queue_push_tail (&context->todo, contacts_get_avatar_tokens);
+ }
+
/* 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