From 90b13c26a97bc357164d958bce5b07285a63eff8 Mon Sep 17 00:00:00 2001 From: Xavier Claessens Date: Fri, 28 May 2010 16:42:33 +0200 Subject: [PATCH] Sync conn-contact.c from telepathy-glib This adds support for avatar data and avatar requirements on the test CM. --- tests/lib/glib/contacts-conn.c | 170 +++++++++++++++++++++++++++++++++++----- tests/lib/glib/contacts-conn.h | 7 ++ 2 files changed, 158 insertions(+), 19 deletions(-) diff --git a/tests/lib/glib/contacts-conn.c b/tests/lib/glib/contacts-conn.c index 79039f7..553aaa2 100644 --- a/tests/lib/glib/contacts-conn.c +++ b/tests/lib/glib/contacts-conn.c @@ -26,6 +26,8 @@ static void init_avatars (gpointer, gpointer); static void init_location (gpointer, gpointer); static void init_contact_caps (gpointer, gpointer); static void init_contact_info (gpointer, gpointer); +static void conn_avatars_properties_getter (GObject *object, GQuark interface, + GQuark name, GValue *value, gpointer getter_data); G_DEFINE_TYPE_WITH_CODE (ContactsConnection, contacts_connection, @@ -51,6 +53,20 @@ G_DEFINE_TYPE_WITH_CODE (ContactsConnection, /* type definition stuff */ +static const char *mime_types[] = { "image/png", NULL }; +static TpDBusPropertiesMixinPropImpl conn_avatars_properties[] = { + { "MinimumAvatarWidth", GUINT_TO_POINTER (1), NULL }, + { "MinimumAvatarHeight", GUINT_TO_POINTER (2), NULL }, + { "RecommendedAvatarWidth", GUINT_TO_POINTER (3), NULL }, + { "RecommendedAvatarHeight", GUINT_TO_POINTER (4), NULL }, + { "MaximumAvatarWidth", GUINT_TO_POINTER (5), NULL }, + { "MaximumAvatarHeight", GUINT_TO_POINTER (6), NULL }, + { "MaximumAvatarBytes", GUINT_TO_POINTER (7), NULL }, + /* special-cased - it's the only one with a non-guint value */ + { "SupportedAvatarMIMETypes", NULL, NULL }, + { NULL } +}; + enum { N_SIGNALS @@ -60,8 +76,8 @@ struct _ContactsConnectionPrivate { /* TpHandle => gchar * */ GHashTable *aliases; - /* TpHandle => gchar * */ - GHashTable *avatar_tokens; + /* TpHandle => AvatarData */ + GHashTable *avatars; /* TpHandle => ContactsConnectionPresenceStatusIndex */ GHashTable *presence_statuses; /* TpHandle => gchar * */ @@ -74,6 +90,41 @@ struct _ContactsConnectionPrivate GHashTable *infos; }; +typedef struct +{ + GArray *data; + gchar *mime_type; + gchar *token; +} AvatarData; + +static AvatarData * +avatar_data_new (GArray *data, const gchar *mime_type, const gchar *token) +{ + AvatarData *a; + + a = g_slice_new (AvatarData); + a->data = data ? g_array_ref (data) : NULL; + a->mime_type = g_strdup (mime_type); + a->token = g_strdup (token); + + return a; +} + +static void +avatar_data_free (gpointer data) +{ + AvatarData *a = data; + + if (a != NULL) + { + if (a->data != NULL) + g_array_unref (a->data); + g_free (a->mime_type); + g_free (a->token); + g_slice_free (AvatarData, a); + } +} + static void free_rcc_list (GPtrArray *rccs) { @@ -87,8 +138,8 @@ contacts_connection_init (ContactsConnection *self) ContactsConnectionPrivate); self->priv->aliases = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); - self->priv->avatar_tokens = g_hash_table_new_full (g_direct_hash, - g_direct_equal, NULL, g_free); + self->priv->avatars = g_hash_table_new_full (g_direct_hash, + g_direct_equal, NULL, avatar_data_free); self->priv->presence_statuses = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL); self->priv->presence_messages = g_hash_table_new_full (g_direct_hash, @@ -108,7 +159,7 @@ finalize (GObject *object) tp_contacts_mixin_finalize (object); g_hash_table_destroy (self->priv->aliases); - g_hash_table_destroy (self->priv->avatar_tokens); + g_hash_table_destroy (self->priv->avatars); g_hash_table_destroy (self->priv->presence_statuses); g_hash_table_destroy (self->priv->presence_messages); g_hash_table_destroy (self->priv->locations); @@ -157,14 +208,14 @@ avatars_fill_contact_attributes (GObject *object, for (i = 0; i < contacts->len; i++) { TpHandle handle = g_array_index (contacts, guint, i); - const gchar *token = g_hash_table_lookup (self->priv->avatar_tokens, + AvatarData *a = g_hash_table_lookup (self->priv->avatars, GUINT_TO_POINTER (handle)); - if (token != NULL) + if (a != NULL && a->token != NULL) { tp_contacts_mixin_set_contact_attribute (attributes, handle, TP_IFACE_CONNECTION_INTERFACE_AVATARS "/token", - tp_g_value_slice_new_string (token)); + tp_g_value_slice_new_string (a->token)); } } } @@ -381,6 +432,14 @@ contacts_connection_class_init (ContactsConnectionClass *klass) TP_IFACE_CONNECTION_INTERFACE_CONTACT_INFO, TP_IFACE_CONNECTION_INTERFACE_REQUESTS, NULL }; + static TpDBusPropertiesMixinIfaceImpl prop_interfaces[] = { + { TP_IFACE_CONNECTION_INTERFACE_AVATARS, + conn_avatars_properties_getter, + NULL, + conn_avatars_properties, + }, + { NULL } + }; object_class->constructed = constructed; object_class->finalize = finalize; @@ -397,6 +456,10 @@ contacts_connection_class_init (ContactsConnectionClass *klass) my_set_own_status, my_statuses); tp_presence_mixin_simple_presence_init_dbus_properties (object_class); + + klass->properties_class.interfaces = prop_interfaces; + tp_dbus_properties_mixin_class_init (object_class, + G_STRUCT_OFFSET (ContactsConnectionClass, properties_class)); } void @@ -488,13 +551,26 @@ contacts_connection_change_avatar_tokens (ContactsConnection *self, for (i = 0; i < n; i++) { DEBUG ("contact#%u -> %s", handles[i], tokens[i]); - g_hash_table_insert (self->priv->avatar_tokens, - GUINT_TO_POINTER (handles[i]), g_strdup (tokens[i])); + g_hash_table_insert (self->priv->avatars, + GUINT_TO_POINTER (handles[i]), avatar_data_new (NULL, NULL, tokens[i])); tp_svc_connection_interface_avatars_emit_avatar_updated (self, handles[i], tokens[i]); } } +void contacts_connection_change_avatar_data (ContactsConnection *self, + TpHandle handle, + GArray *data, + const gchar *mime_type, + const gchar *token) +{ + g_hash_table_insert (self->priv->avatars, + GUINT_TO_POINTER (handle), avatar_data_new (data, mime_type, token)); + + tp_svc_connection_interface_avatars_emit_avatar_updated (self, + handle, token); +} + void contacts_connection_change_locations (ContactsConnection *self, guint n, @@ -695,23 +771,23 @@ my_get_avatar_tokens (TpSvcConnectionInterfaceAvatars *avatars, for (i = 0; i < contacts->len; i++) { TpHandle handle = g_array_index (contacts, TpHandle, i); - const gchar *token = g_hash_table_lookup (self->priv->avatar_tokens, + AvatarData *a = g_hash_table_lookup (self->priv->avatars, GUINT_TO_POINTER (handle)); - if (token == NULL) + if (a == NULL || a->token == NULL) { /* we're expected to do a round-trip to the server to find out * their token, so we have to give some sort of result. Assume * no avatar, here */ - token = ""; - g_hash_table_insert (self->priv->avatar_tokens, - GUINT_TO_POINTER (handle), g_strdup (token)); + a = avatar_data_new (NULL, NULL, ""); + g_hash_table_insert (self->priv->avatars, + GUINT_TO_POINTER (handle), a); tp_svc_connection_interface_avatars_emit_avatar_updated (self, - handle, token); + handle, a->token); } g_hash_table_insert (result, GUINT_TO_POINTER (handle), - (gchar *) token); + a->token); } tp_svc_connection_interface_avatars_return_from_get_known_avatar_tokens ( @@ -746,8 +822,9 @@ my_get_known_avatar_tokens (TpSvcConnectionInterfaceAvatars *avatars, for (i = 0; i < contacts->len; i++) { TpHandle handle = g_array_index (contacts, TpHandle, i); - const gchar *token = g_hash_table_lookup (self->priv->avatar_tokens, + AvatarData *a = g_hash_table_lookup (self->priv->avatars, GUINT_TO_POINTER (handle)); + const gchar *token = a ? a->token : NULL; g_hash_table_insert (result, GUINT_TO_POINTER (handle), (gchar *) (token != NULL ? token : "")); @@ -759,6 +836,61 @@ my_get_known_avatar_tokens (TpSvcConnectionInterfaceAvatars *avatars, } static void +my_request_avatars (TpSvcConnectionInterfaceAvatars *avatars, + const GArray *contacts, + DBusGMethodInvocation *context) +{ + ContactsConnection *self = CONTACTS_CONNECTION (avatars); + TpBaseConnection *base = TP_BASE_CONNECTION (avatars); + TpHandleRepoIface *contact_repo = tp_base_connection_get_handles (base, + TP_HANDLE_TYPE_CONTACT); + GError *error = NULL; + guint i; + + TP_BASE_CONNECTION_ERROR_IF_NOT_CONNECTED (base, context); + + if (!tp_handles_are_valid (contact_repo, contacts, FALSE, &error)) + { + dbus_g_method_return_error (context, error); + g_error_free (error); + return; + } + + for (i = 0; i < contacts->len; i++) + { + TpHandle handle = g_array_index (contacts, TpHandle, i); + AvatarData *a = g_hash_table_lookup (self->priv->avatars, + GUINT_TO_POINTER (handle)); + + if (a != NULL) + tp_svc_connection_interface_avatars_emit_avatar_retrieved (self, handle, + a->token, a->data, a->mime_type); + } + + tp_svc_connection_interface_avatars_return_from_request_avatars (context); +} + +static void +conn_avatars_properties_getter (GObject *object, + GQuark interface, + GQuark name, + GValue *value, + gpointer getter_data) +{ + GQuark q_mime_types = g_quark_from_static_string ( + "SupportedAvatarMIMETypes"); + + if (name == q_mime_types) + { + g_value_set_static_boxed (value, mime_types); + } + else + { + g_value_set_uint (value, GPOINTER_TO_UINT (getter_data)); + } +} + +static void init_avatars (gpointer g_iface, gpointer iface_data) { @@ -770,7 +902,7 @@ init_avatars (gpointer g_iface, IMPLEMENT(get_avatar_tokens); IMPLEMENT(get_known_avatar_tokens); /* IMPLEMENT(request_avatar); */ - /* IMPLEMENT(request_avatars); */ + IMPLEMENT(request_avatars); /* IMPLEMENT(set_avatar); */ /* IMPLEMENT(clear_avatar); */ #undef IMPLEMENT diff --git a/tests/lib/glib/contacts-conn.h b/tests/lib/glib/contacts-conn.h index b72b030..2eaefd1 100644 --- a/tests/lib/glib/contacts-conn.h +++ b/tests/lib/glib/contacts-conn.h @@ -30,6 +30,7 @@ struct _ContactsConnectionClass { TpPresenceMixinClass presence_mixin; TpContactsMixinClass contacts_mixin; + TpDBusPropertiesMixinClass properties_class; }; struct _ContactsConnection { @@ -81,6 +82,12 @@ void contacts_connection_change_presences (ContactsConnection *self, guint n, void contacts_connection_change_avatar_tokens (ContactsConnection *self, guint n, const TpHandle *handles, const gchar * const *tokens); +void contacts_connection_change_avatar_data (ContactsConnection *self, + TpHandle handle, + GArray *data, + const gchar *mime_type, + const gchar *token); + void contacts_connection_change_locations (ContactsConnection *self, guint n, const TpHandle *handles, -- 1.7.0.4