diff options
-rw-r--r-- | docs/reference/gdata-sections.txt | 2 | ||||
-rw-r--r-- | gdata/gdata.symbols | 2 | ||||
-rw-r--r-- | gdata/services/contacts/gdata-contacts-contact.c | 128 | ||||
-rw-r--r-- | gdata/services/contacts/gdata-contacts-contact.h | 6 | ||||
-rw-r--r-- | gdata/tests/contacts.c | 44 |
5 files changed, 180 insertions, 2 deletions
diff --git a/docs/reference/gdata-sections.txt b/docs/reference/gdata-sections.txt index fe656b31..c24d879e 100644 --- a/docs/reference/gdata-sections.txt +++ b/docs/reference/gdata-sections.txt @@ -426,6 +426,8 @@ gdata_contacts_contact_get_edited gdata_contacts_contact_is_deleted gdata_contacts_contact_has_photo gdata_contacts_contact_get_photo +gdata_contacts_contact_get_photo_async +gdata_contacts_contact_get_photo_finish gdata_contacts_contact_set_photo <SUBSECTION Standard> gdata_contacts_contact_get_type diff --git a/gdata/gdata.symbols b/gdata/gdata.symbols index 195c935a..6852ced4 100644 --- a/gdata/gdata.symbols +++ b/gdata/gdata.symbols @@ -856,3 +856,5 @@ gdata_youtube_service_upload_video gdata_youtube_service_finish_video_upload gdata_calendar_service_query_events_async gdata_calendar_service_insert_event_async +gdata_contacts_contact_get_photo_async +gdata_contacts_contact_get_photo_finish diff --git a/gdata/services/contacts/gdata-contacts-contact.c b/gdata/services/contacts/gdata-contacts-contact.c index a3c44909..85518727 100644 --- a/gdata/services/contacts/gdata-contacts-contact.c +++ b/gdata/services/contacts/gdata-contacts-contact.c @@ -2937,7 +2937,7 @@ gdata_contacts_contact_has_photo (GDataContactsContact *self) * * Return value: the image data, or %NULL; free with g_free() * - * Since: 0.4.0 + * Since: 0.8.0 **/ guint8 * gdata_contacts_contact_get_photo (GDataContactsContact *self, GDataContactsService *service, gsize *length, gchar **content_type, @@ -2998,6 +2998,130 @@ gdata_contacts_contact_get_photo (GDataContactsContact *self, GDataContactsServi return data; } +typedef struct { + guint8 *data; + gsize length; + gchar *content_type; +} PhotoData; + +static void +photo_data_free (PhotoData *data) +{ + g_free (data->data); + g_free (data->content_type); + g_slice_free (PhotoData, data); +} + +static void +get_photo_thread (GSimpleAsyncResult *result, GDataContactsContact *contact, GCancellable *cancellable) +{ + GDataContactsService *service; + PhotoData *data; + GError *error = NULL; + + /* Input and output */ + service = g_simple_async_result_get_op_res_gpointer (result); + data = g_slice_new0 (PhotoData); + + /* Get the photo */ + data->data = gdata_contacts_contact_get_photo (contact, service, &(data->length), &(data->content_type), cancellable, &error); + if (error != NULL) { + g_simple_async_result_set_from_error (result, error); + g_error_free (error); + return; + } + + /* Replace the service with the photo struct */ + g_simple_async_result_set_op_res_gpointer (result, data, (GDestroyNotify) photo_data_free); +} + +/** + * gdata_contacts_contact_get_photo_async: + * @self: a #GDataContactsContact + * @service: a #GDataContactsService + * @cancellable: optional #GCancellable object, or %NULL + * @callback: a #GAsyncReadyCallback to call when the photo has been retrieved, or %NULL + * @user_data: (closure): data to pass to the @callback function + * + * Downloads and returns the contact's photo, if they have one, asynchronously. @self and @service are both reffed when this function is called, so + * can safely be unreffed after this function returns. + * + * When the operation is finished, @callback will be called. You can then call gdata_contacts_contact_get_photo_finish() to get the results of the + * operation. + * + * For more details, see gdata_contacts_contact_get_photo(), which is the synchronous version of this function. + * + * If @cancellable is not %NULL, then the operation can be cancelled by triggering the @cancellable object from another thread. + * If the operation was cancelled, the error %G_IO_ERROR_CANCELLED will be returned by gdata_contacts_contact_get_photo_finish(). + * + * If there is an error getting the photo, a %GDATA_SERVICE_ERROR_PROTOCOL_ERROR error will be returned by gdata_contacts_contact_get_photo_finish(). + * + * Since: 0.8.0 + **/ +void +gdata_contacts_contact_get_photo_async (GDataContactsContact *self, GDataContactsService *service, GCancellable *cancellable, + GAsyncReadyCallback callback, gpointer user_data) +{ + GSimpleAsyncResult *result; + + g_return_if_fail (GDATA_IS_CONTACTS_CONTACT (self)); + g_return_if_fail (GDATA_IS_CONTACTS_SERVICE (service)); + g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); + g_return_if_fail (callback != NULL); + + result = g_simple_async_result_new (G_OBJECT (self), callback, user_data, gdata_contacts_contact_get_photo_async); + g_simple_async_result_set_op_res_gpointer (result, g_object_ref (service), (GDestroyNotify) g_object_unref); + g_simple_async_result_run_in_thread (result, (GSimpleAsyncThreadFunc) get_photo_thread, G_PRIORITY_DEFAULT, cancellable); + g_object_unref (result); +} + +/** + * gdata_contacts_contact_get_photo_finish: + * @self: a #GDataContactsContact + * @async_result: a #GAsyncResult + * @length: (out caller-allocates): return location for the image length, in bytes + * @content_type: (out callee-allocates) (transfer full) (allow-none): return location for the image's content type, or %NULL; free with g_free() + * @error: a #GError, or %NULL + * + * Finishes an asynchronous contact photo retrieval operation started with gdata_contacts_contact_get_photo_async(). If the contact doesn't have a + * photo (i.e. gdata_contacts_contact_has_photo() returns %FALSE), %NULL is returned, but no error is set in @error. + * + * If there is an error getting the photo, a %GDATA_SERVICE_ERROR_PROTOCOL_ERROR error will be returned. + * + * Return value: the image data, or %NULL; free with g_free() + * + * Since: 0.8.0 + **/ +guint8 * +gdata_contacts_contact_get_photo_finish (GDataContactsContact *self, GAsyncResult *async_result, gsize *length, gchar **content_type, GError **error) +{ + PhotoData *data; + guint8 *photo_data; + GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (async_result); + + g_return_val_if_fail (GDATA_IS_CONTACTS_CONTACT (self), NULL); + g_return_val_if_fail (G_IS_ASYNC_RESULT (async_result), NULL); + g_return_val_if_fail (length != NULL, NULL); + g_return_val_if_fail (error == NULL || *error == NULL, NULL); + + g_warn_if_fail (g_simple_async_result_get_source_tag (result) == gdata_contacts_contact_get_photo_async); + + if (g_simple_async_result_propagate_error (result, error) == TRUE) + return NULL; + + /* Return the photo (steal the data from the PhotoData struct so we don't have to copy it again) */ + data = g_simple_async_result_get_op_res_gpointer (result); + photo_data = data->data; + *length = data->length; + if (content_type != NULL) + *content_type = data->content_type; + + data->data = NULL; + data->content_type = NULL; + + return photo_data; +} + /** * gdata_contacts_contact_set_photo: * @self: a #GDataContactsContact @@ -3016,7 +3140,7 @@ gdata_contacts_contact_get_photo (GDataContactsContact *self, GDataContactsServi * * Return value: %TRUE on success, %FALSE otherwise * - * Since: 0.4.0 + * Since: 0.8.0 **/ gboolean gdata_contacts_contact_set_photo (GDataContactsContact *self, GDataService *service, const guint8 *data, gsize length, diff --git a/gdata/services/contacts/gdata-contacts-contact.h b/gdata/services/contacts/gdata-contacts-contact.h index 627819db..ad636795 100644 --- a/gdata/services/contacts/gdata-contacts-contact.h +++ b/gdata/services/contacts/gdata-contacts-contact.h @@ -278,8 +278,14 @@ GList *gdata_contacts_contact_get_groups (GDataContactsContact *self) G_GNUC_WAR #include <gdata/services/contacts/gdata-contacts-service.h> gboolean gdata_contacts_contact_has_photo (GDataContactsContact *self) G_GNUC_PURE; + guint8 *gdata_contacts_contact_get_photo (GDataContactsContact *self, GDataContactsService *service, gsize *length, gchar **content_type, GCancellable *cancellable, GError **error) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC; +void gdata_contacts_contact_get_photo_async (GDataContactsContact *self, GDataContactsService *service, GCancellable *cancellable, + GAsyncReadyCallback callback, gpointer user_data); +guint8 *gdata_contacts_contact_get_photo_finish (GDataContactsContact *self, GAsyncResult *async_result, gsize *length, gchar **content_type, + GError **error) G_GNUC_WARN_UNUSED_RESULT G_GNUC_MALLOC; + gboolean gdata_contacts_contact_set_photo (GDataContactsContact *self, GDataService *service, const guint8 *data, gsize length, GCancellable *cancellable, GError **error); diff --git a/gdata/tests/contacts.c b/gdata/tests/contacts.c index 76d9c0e4..960d0fee 100644 --- a/gdata/tests/contacts.c +++ b/gdata/tests/contacts.c @@ -1616,6 +1616,49 @@ test_photo_get (gconstpointer service) } static void +test_photo_get_async_cb (GDataContactsContact *contact, GAsyncResult *result, GMainLoop *main_loop) +{ + guint8 *data; + gsize length; + gchar *content_type; + GError *error = NULL; + + /* Finish getting the photo */ + data = gdata_contacts_contact_get_photo_finish (contact, result, &length, &content_type, &error); + g_assert_no_error (error); + g_assert (data != NULL); + g_assert (length != 0); + g_assert_cmpstr (content_type, ==, "image/jpeg"); + + g_assert (gdata_contacts_contact_has_photo (contact) == TRUE); + + g_main_loop_quit (main_loop); + + g_free (content_type); + g_free (data); +} + +static void +test_photo_get_async (gconstpointer service) +{ + GDataContactsContact *contact; + GMainLoop *main_loop; + + contact = get_contact (service); + g_assert (gdata_contacts_contact_has_photo (contact) == TRUE); + + main_loop = g_main_loop_new (NULL, TRUE); + + /* Get the photo from the network asynchronously */ + gdata_contacts_contact_get_photo_async (contact, GDATA_CONTACTS_SERVICE (service), NULL, (GAsyncReadyCallback) test_photo_get_async_cb, + main_loop); + g_main_loop_run (main_loop); + + g_main_loop_unref (main_loop); + g_object_unref (contact); +} + +static void test_photo_delete (gconstpointer service) { GDataContactsContact *contact; @@ -1910,6 +1953,7 @@ main (int argc, char *argv[]) g_test_add_data_func ("/contacts/photo/has_photo", service, test_photo_has_photo); g_test_add_data_func ("/contacts/photo/add", service, test_photo_add); g_test_add_data_func ("/contacts/photo/get", service, test_photo_get); + g_test_add_data_func ("/contacts/photo/get/async", service, test_photo_get_async); g_test_add_data_func ("/contacts/photo/delete", service, test_photo_delete); g_test_add_data_func ("/contacts/batch", service, test_batch); |