[empathy] Bug 655212 — Update for libfolks API changes to AvatarDetails



commit 3a9a3210bbf8e927ef64510d066c035aa60a8a50
Author: Philip Withnall <philip tecnocode co uk>
Date:   Sun Jul 24 17:05:15 2011 +0100

    Bug 655212 â Update for libfolks API changes to AvatarDetails
    
    Folks' AvatarDetails.avatar is now a GLoadableIcon rather than a GFile.
    Closes: bgo#655212
    
    https://bugzilla.gnome.org/show_bug.cgi?id=655212

 configure.ac                      |    2 +-
 libempathy-gtk/empathy-ui-utils.c |  140 ++++++++++++++++++++++++++----------
 2 files changed, 102 insertions(+), 40 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 8646a1a..e536613 100644
--- a/configure.ac
+++ b/configure.ac
@@ -31,7 +31,7 @@ AC_COPYRIGHT([
 # Minimal version required
 
 # Hardp deps
-FOLKS_REQUIRED=0.5.1
+FOLKS_REQUIRED=0.6.0
 GLIB_REQUIRED=2.28.0
 GNUTLS_REQUIRED=2.8.5
 GTK_REQUIRED=3.0.2
diff --git a/libempathy-gtk/empathy-ui-utils.c b/libempathy-gtk/empathy-ui-utils.c
index 8ad7dfb..060e0aa 100644
--- a/libempathy-gtk/empathy-ui-utils.c
+++ b/libempathy-gtk/empathy-ui-utils.c
@@ -526,13 +526,18 @@ typedef struct {
 	GSimpleAsyncResult *result;
 	guint width;
 	guint height;
+	struct SizeData size_data;
+	GdkPixbufLoader *loader;
+	GCancellable *cancellable;
+	guint8 data[512];
 } PixbufAvatarFromIndividualClosure;
 
 static PixbufAvatarFromIndividualClosure *
 pixbuf_avatar_from_individual_closure_new (FolksIndividual    *individual,
 					   GSimpleAsyncResult *result,
 					   gint                width,
-					   gint                height)
+					   gint                height,
+					   GCancellable       *cancellable)
 {
 	PixbufAvatarFromIndividualClosure *closure;
 
@@ -544,6 +549,7 @@ pixbuf_avatar_from_individual_closure_new (FolksIndividual    *individual,
 	closure->result = g_object_ref (result);
 	closure->width = width;
 	closure->height = height;
+	closure->cancellable = g_object_ref (cancellable);
 
 	return closure;
 }
@@ -552,65 +558,120 @@ static void
 pixbuf_avatar_from_individual_closure_free (
 		PixbufAvatarFromIndividualClosure *closure)
 {
+	g_object_unref (closure->cancellable);
+	tp_clear_object (&closure->loader);
 	g_object_unref (closure->individual);
 	g_object_unref (closure->result);
 	g_free (closure);
 }
 
 static void
-avatar_file_load_contents_cb (GObject      *object,
-			      GAsyncResult *result,
-			      gpointer      user_data)
+avatar_icon_load_read_cb (GObject      *object,
+                          GAsyncResult *result,
+                          gpointer      user_data)
 {
-	GFile *file = G_FILE (object);
+	GInputStream *stream = G_INPUT_STREAM (object);
 	PixbufAvatarFromIndividualClosure *closure = user_data;
-	char *data = NULL;
-	gsize data_size;
-	struct SizeData size_data;
+	gssize n_read;
 	GError *error = NULL;
-	GdkPixbufLoader *loader = NULL;
 
-	if (!g_file_load_contents_finish (file, result, &data, &data_size,
-				NULL, &error)) {
-		DEBUG ("failed to load avatar from file: %s",
-				error->message);
+	/* Finish reading this chunk from the stream */
+	n_read = g_input_stream_read_finish (stream, result, &error);
+	if (error != NULL) {
+		DEBUG ("Failed to finish read from pixbuf stream: %s",
+			error->message);
 		g_simple_async_result_set_from_error (closure->result, error);
-		goto out;
+		goto out_close;
 	}
 
-	size_data.width = closure->width;
-	size_data.height = closure->height;
-	size_data.preserve_aspect_ratio = TRUE;
-
-	loader = gdk_pixbuf_loader_new ();
-
-	g_signal_connect (loader, "size-prepared",
-			  G_CALLBACK (pixbuf_from_avatar_size_prepared_cb),
-			  &size_data);
-
-	if (!gdk_pixbuf_loader_write (loader, (guchar *) data, data_size,
-				&error)) {
+	/* Write the chunk to the pixbuf loader */
+	if (!gdk_pixbuf_loader_write (closure->loader, (guchar *) closure->data,
+			n_read, &error)) {
 		DEBUG ("Failed to write to pixbuf loader: %s",
 			error ? error->message : "No error given");
 		g_simple_async_result_set_from_error (closure->result, error);
+		goto out_close;
+	}
+
+	if (n_read == 0) {
+		/* EOF? */
+		if (!gdk_pixbuf_loader_close (closure->loader, &error)) {
+			DEBUG ("Failed to close pixbuf loader: %s",
+				error ? error->message : "No error given");
+			g_simple_async_result_set_from_error (closure->result, error);
+			goto out;
+		}
+
+		/* We're done. */
+		g_simple_async_result_set_op_res_gpointer (closure->result,
+			avatar_pixbuf_from_loader (closure->loader),
+			g_object_unref);
+
 		goto out;
+	} else {
+		/* Loop round and read another chunk. */
+		g_input_stream_read_async (stream, closure->data,
+			G_N_ELEMENTS (closure->data),
+			G_PRIORITY_DEFAULT, closure->cancellable,
+			avatar_icon_load_read_cb, closure);
+
+		return;
 	}
-	if (!gdk_pixbuf_loader_close (loader, &error)) {
-		DEBUG ("Failed to close pixbuf loader: %s",
-			error ? error->message : "No error given");
+
+out_close:
+	/* We must close the pixbuf loader before unreffing it. */
+	gdk_pixbuf_loader_close (closure->loader, NULL);
+
+out:
+	g_simple_async_result_complete (closure->result);
+
+	g_clear_error (&error);
+	pixbuf_avatar_from_individual_closure_free (closure);
+}
+
+static void
+avatar_icon_load_cb (GObject      *object,
+                     GAsyncResult *result,
+                     gpointer      user_data)
+{
+	GLoadableIcon *icon = G_LOADABLE_ICON (object);
+	PixbufAvatarFromIndividualClosure *closure = user_data;
+	GInputStream *stream;
+	GError *error = NULL;
+
+	stream = g_loadable_icon_load_finish (icon, result, NULL, &error);
+	if (error != NULL) {
+		DEBUG ("Failed to open avatar stream: %s", error->message);
 		g_simple_async_result_set_from_error (closure->result, error);
 		goto out;
 	}
 
-	g_simple_async_result_set_op_res_gpointer (closure->result,
-			avatar_pixbuf_from_loader (loader), g_object_unref);
+	closure->size_data.width = closure->width;
+	closure->size_data.height = closure->height;
+	closure->size_data.preserve_aspect_ratio = TRUE;
+
+	/* Load the data into a pixbuf loader in chunks. */
+	closure->loader = gdk_pixbuf_loader_new ();
+
+	g_signal_connect (closure->loader, "size-prepared",
+			  G_CALLBACK (pixbuf_from_avatar_size_prepared_cb),
+	                  &(closure->size_data));
+
+	/* Begin to read the first chunk. */
+	g_input_stream_read_async (stream, closure->data,
+			G_N_ELEMENTS (closure->data),
+			G_PRIORITY_DEFAULT, closure->cancellable,
+			avatar_icon_load_read_cb, closure);
+
+	g_object_unref (stream);
+
+	return;
 
 out:
 	g_simple_async_result_complete (closure->result);
 
 	g_clear_error (&error);
-	g_free (data);
-	tp_clear_object (&loader);
+	tp_clear_object (&stream);
 	pixbuf_avatar_from_individual_closure_free (closure);
 }
 
@@ -623,7 +684,7 @@ empathy_pixbuf_avatar_from_individual_scaled_async (
 		GAsyncReadyCallback  callback,
 		gpointer             user_data)
 {
-	GFile *avatar_file;
+	GLoadableIcon *avatar_icon;
 	GSimpleAsyncResult *result;
 	PixbufAvatarFromIndividualClosure *closure;
 
@@ -631,18 +692,19 @@ empathy_pixbuf_avatar_from_individual_scaled_async (
 			callback, user_data,
 			empathy_pixbuf_avatar_from_individual_scaled_async);
 
-	avatar_file =
+	avatar_icon =
 		folks_avatar_details_get_avatar (FOLKS_AVATAR_DETAILS (individual));
-	if (avatar_file == NULL)
+	if (avatar_icon == NULL)
 		goto out;
 
 	closure = pixbuf_avatar_from_individual_closure_new (individual, result,
-							     width, height);
+							     width, height,
+							     cancellable);
 	if (closure == NULL)
 		goto out;
 
-	g_file_load_contents_async (avatar_file, cancellable,
-			avatar_file_load_contents_cb, closure);
+	g_loadable_icon_load_async (avatar_icon, width, cancellable,
+			avatar_icon_load_cb, closure);
 
 	g_object_unref (result);
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]