static void
update_contact_capabilities (EmpathyTpContactFactory *self,
			     GHashTable *caps)
{
	GHashTableIter iter;
	gpointer key, value;

	g_hash_table_iter_init (&iter, caps);
	while (g_hash_table_iter_next (&iter, &key, &value)) {
		TpHandle handle = GPOINTER_TO_UINT (key);
		GPtrArray *classes = value;
		EmpathyContact *contact;
		EmpathyCapabilities  capabilities;

		contact = tp_contact_factory_find_by_handle (self, handle);
		if (contact == NULL)
			continue;

		capabilities = empathy_contact_get_capabilities (contact);
		capabilities &= ~EMPATHY_CAPABILITIES_UNKNOWN;

		capabilities |= channel_classes_to_capabilities (classes, TRUE);

		DEBUG ("Changing capabilities for contact %s (%d) to %d",
			empathy_contact_get_id (contact),
			empathy_contact_get_handle (contact),
			capabilities);

		empathy_contact_set_capabilities (contact, capabilities);
	}
}
static void
tp_contact_factory_avatar_retrieved_cb (TpConnection *connection,
					guint         handle,
					const gchar  *token,
					const GArray *avatar_data,
					const gchar  *mime_type,
					gpointer      user_data,
					GObject      *tp_factory)
{
	EmpathyContact *contact;

	contact = tp_contact_factory_find_by_handle (EMPATHY_TP_CONTACT_FACTORY (tp_factory),
						     handle);
	if (!contact) {
		return;
	}

	DEBUG ("Avatar retrieved for contact %s (%d)",
		empathy_contact_get_id (contact),
		handle);

	empathy_contact_load_avatar_data (contact,
					  (guchar *) avatar_data->data,
					  avatar_data->len,
					  mime_type,
					  token);
}
static gboolean
tp_contact_factory_avatar_maybe_update (EmpathyTpContactFactory *tp_factory,
					guint                    handle,
					const gchar             *token)
{
	EmpathyContact *contact;
	EmpathyAvatar  *avatar;

	contact = tp_contact_factory_find_by_handle (tp_factory, handle);
	if (!contact) {
		return TRUE;
	}

	/* Check if we have an avatar */
	if (EMP_STR_EMPTY (token)) {
		empathy_contact_set_avatar (contact, NULL);
		return TRUE;
	}

	/* Check if the avatar changed */
	avatar = empathy_contact_get_avatar (contact);
	if (avatar && !tp_strdiff (avatar->token, token)) {
		return TRUE;
	}

	/* The avatar changed, search the new one in the cache */
	if (empathy_contact_load_avatar_cache (contact, token)) {
		/* Got from cache, use it */
		return TRUE;
	}

	/* Avatar is not up-to-date, we have to request it. */
	return FALSE;
}
static void
tp_contact_factory_update_location (EmpathyTpContactFactory *tp_factory,
				    guint handle,
				    GHashTable *location)
{
	EmpathyContact *contact;
	GHashTable     *new_location;

	contact = tp_contact_factory_find_by_handle (tp_factory, handle);

	if (contact == NULL)
		return;

	new_location = g_hash_table_new_full (g_str_hash, g_str_equal,
		(GDestroyNotify) g_free, (GDestroyNotify) tp_g_value_slice_free);
	tp_g_hash_table_update (new_location, location, (GBoxedCopyFunc) g_strdup,
		(GBoxedCopyFunc) tp_g_value_slice_dup);
	empathy_contact_set_location (contact, new_location);
	g_hash_table_unref (new_location);

	tp_contact_factory_geocode (contact);
}
static void
tp_contact_factory_update_capabilities (EmpathyTpContactFactory *tp_factory,
					guint                    handle,
					const gchar             *channel_type,
					guint                    generic,
					guint                    specific)
{
	EmpathyContact      *contact;
	EmpathyCapabilities  capabilities;

	contact = tp_contact_factory_find_by_handle (tp_factory, handle);
	if (!contact) {
		return;
	}

	capabilities = empathy_contact_get_capabilities (contact);
	capabilities &= ~EMPATHY_CAPABILITIES_UNKNOWN;

	if (strcmp (channel_type, TP_IFACE_CHANNEL_TYPE_STREAMED_MEDIA) == 0) {
		capabilities &= ~EMPATHY_CAPABILITIES_AUDIO;
		capabilities &= ~EMPATHY_CAPABILITIES_VIDEO;
		if (specific & TP_CHANNEL_MEDIA_CAPABILITY_AUDIO) {
			capabilities |= EMPATHY_CAPABILITIES_AUDIO;
		}
		if (specific & TP_CHANNEL_MEDIA_CAPABILITY_VIDEO) {
			capabilities |= EMPATHY_CAPABILITIES_VIDEO;
		}
	}

	DEBUG ("Changing capabilities for contact %s (%d) to %d",
		empathy_contact_get_id (contact),
		empathy_contact_get_handle (contact),
		capabilities);

	empathy_contact_set_capabilities (contact, capabilities);
}