[Commits] [SCM] claws branch, master, updated. 3.14.0-115-ge62c01e

mones at claws-mail.org mones at claws-mail.org
Mon Oct 17 14:11:47 CEST 2016


The branch, master has been updated
       via  e62c01edd0c6bfc6c9c2e7b9645497603b8f8e83 (commit)
      from  abbf2f8a104fcb5e72226a2edf0ecd1cd5d29b93 (commit)

Summary of changes:
 src/plugins/libravatar/Makefile.am                 |    1 +
 src/plugins/libravatar/libravatar.c                |   88 +++-------
 src/plugins/libravatar/libravatar_image.c          |  168 ++++++++++++++++++++
 ...{libravatar_federation.h => libravatar_image.h} |   19 ++-
 4 files changed, 210 insertions(+), 66 deletions(-)
 create mode 100644 src/plugins/libravatar/libravatar_image.c
 copy src/plugins/libravatar/{libravatar_federation.h => libravatar_image.h} (68%)


- Log -----------------------------------------------------------------
commit e62c01edd0c6bfc6c9c2e7b9645497603b8f8e83
Author: Ricardo Mones <ricardo at mones.org>
Date:   Mon Oct 17 14:09:25 2016 +0200

    Libravatar: refactor image retrieval
    
    And use a synchronous thread for fetching, in preparation
    of a future asynchronous fetching. Thanks Andrej for the
    ideas.

diff --git a/src/plugins/libravatar/Makefile.am b/src/plugins/libravatar/Makefile.am
index 7edf1f5..4fcc57c 100644
--- a/src/plugins/libravatar/Makefile.am
+++ b/src/plugins/libravatar/Makefile.am
@@ -79,6 +79,7 @@ libravatar_la_SOURCES = \
 	libravatar.c libravatar.h \
 	libravatar_prefs.c libravatar_prefs.h \
 	libravatar_cache.c libravatar_cache.h \
+	libravatar_image.c libravatar_image.h \
 	libravatar_missing.c libravatar_missing.h \
 	libravatar_federation.c libravatar_federation.h
 
diff --git a/src/plugins/libravatar/libravatar.c b/src/plugins/libravatar/libravatar.c
index e36829e..7ce4341 100644
--- a/src/plugins/libravatar/libravatar.c
+++ b/src/plugins/libravatar/libravatar.c
@@ -30,6 +30,7 @@
 #include "libravatar.h"
 #include "libravatar_prefs.h"
 #include "libravatar_cache.h"
+#include "libravatar_image.h"
 #include "libravatar_missing.h"
 #include "libravatar_federation.h"
 #include "prefs_common.h"
@@ -96,9 +97,21 @@ default_url:
 	return g_strdup(libravatarprefs.base_url);
 }
 
-static GtkWidget *image_widget_from_filename(const gchar *filename)
+static GtkWidget *image_widget_from_pixbuf(GdkPixbuf *picture)
 {
 	GtkWidget *image = NULL;
+
+	if (picture) {
+		image = gtk_image_new_from_pixbuf(picture);
+		g_object_unref(picture);
+	} else
+		g_warning("null picture returns null widget");
+
+	return image;
+}
+
+static GtkWidget *image_widget_from_filename(const gchar *filename)
+{
 	GdkPixbuf *picture = NULL;
 	GError *error = NULL;
 	gint w, h;
@@ -115,15 +128,10 @@ static GtkWidget *image_widget_from_filename(const gchar *filename)
 	if (error != NULL) {
 		g_warning("failed to load image '%s': %s", filename, error->message);
 		g_error_free(error);
-	} else {
-		if (picture) {
-			image = gtk_image_new_from_pixbuf(picture);
-			g_object_unref(picture);
-		} else
-			g_warning("failed to load image '%s': no error returned!", filename);
+		return NULL;
 	}
 
-	return image;
+	return image_widget_from_pixbuf(picture);
 }
 
 static gchar *cache_name_for_md5(const gchar *md5)
@@ -149,61 +157,17 @@ static size_t write_image_data_cb(void *ptr, size_t size, size_t nmemb, void *st
 static GtkWidget *image_widget_from_url(const gchar *url, const gchar *md5)
 {
 	GtkWidget *image = NULL;
-	gchar *filename;
-	FILE *file;
-	CURL *curl;
-
-	curl = curl_easy_init();
-	if (curl == NULL) {
-		g_warning("could not initialize curl to get image from URL");
-		return NULL;
+	AvatarImageFetch aif;
+
+	aif.url = url;
+	aif.md5 = md5;
+	aif.filename = cache_name_for_md5(md5);
+	libravatar_image_fetch(&aif);
+	if (aif.pixbuf) {
+		image = gtk_image_new_from_pixbuf(aif.pixbuf);
+		g_object_unref(aif.pixbuf);
 	}
-	curl_easy_setopt(curl, CURLOPT_URL, url);
-	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_image_data_cb);
-	/* make sure timeout is less than general IO timeout */
-	curl_easy_setopt(curl, CURLOPT_TIMEOUT,
-			(libravatarprefs.timeout == 0
-				|| libravatarprefs.timeout
-					> prefs_common_get_prefs()->io_timeout_secs)
-			? prefs_common_get_prefs()->io_timeout_secs
-			: libravatarprefs.timeout);
-	curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
-
-	filename = cache_name_for_md5(md5);
-	file = fopen(filename, "wb");
-	if (file != NULL) {
-		long filesize;
-
-		if (libravatarprefs.allow_redirects) {
-			long maxredirs = (libravatarprefs.default_mode == DEF_MODE_URL)? 3L
-				: ((libravatarprefs.default_mode == DEF_MODE_MM)? 2L: 1L);
-
-			curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
-			curl_easy_setopt(curl, CURLOPT_MAXREDIRS, maxredirs);
-		}
-		curl_easy_setopt(curl, CURLOPT_FILE, file);
-		debug_print("retrieving URL to file: %s -> %s\n", url, filename);
-		curl_easy_perform(curl);
-		filesize = ftell(file);
-    		fclose(file);
-
-		if (filesize < MIN_PNG_SIZE)
-			debug_print("not enough data for an avatar image: %ld bytes\n", filesize);
-		else
-			image = image_widget_from_filename(filename);
-
-		if (!libravatarprefs.cache_icons || filesize == 0) {
-			if (g_unlink(filename) < 0)
-				g_warning("failed to delete cache file '%s'", filename);
-		}
-
-		if (filesize == 0)
-			missing_add_md5(libravatarmisses, md5);
-	} else {
-		g_warning("could not open '%s' for writing", filename);
-	}
-	curl_easy_cleanup(curl);
-	g_free(filename);
+	g_free(aif.filename);
 
 	return image;
 }
diff --git a/src/plugins/libravatar/libravatar_image.c b/src/plugins/libravatar/libravatar_image.c
new file mode 100644
index 0000000..fa1f78a
--- /dev/null
+++ b/src/plugins/libravatar/libravatar_image.c
@@ -0,0 +1,168 @@
+/*
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 2016 Ricardo Mones and the Claws Mail Team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#include "claws-features.h"
+#endif
+
+#include <glib.h>
+#include <curl/curl.h>
+#include <pthread.h>
+
+#include <common/claws.h>
+#include <prefs_common.h>
+
+#include "libravatar.h"
+#include "libravatar_prefs.h"
+#include "libravatar_missing.h"
+#include "libravatar_image.h"
+
+static size_t write_image_data_cb(void *ptr, size_t size, size_t nmemb, void *stream)
+{
+	size_t written = fwrite(ptr, size, nmemb, (FILE *)stream);
+	debug_print("received %zu bytes from avatar server\n", written);
+
+	return written;
+}
+
+static GdkPixbuf *image_pixbuf_from_filename(const gchar *filename)
+{
+	GdkPixbuf *picture = NULL;
+	GError *error = NULL;
+	gint w, h;
+
+	gdk_pixbuf_get_file_info(filename, &w, &h);
+
+	if (w != AVATAR_SIZE || h != AVATAR_SIZE)
+		/* server can provide a different size from the requested in URL */
+		picture = gdk_pixbuf_new_from_file_at_scale(
+				filename, AVATAR_SIZE, AVATAR_SIZE, TRUE, &error);
+	else	/* exact size */
+		picture = gdk_pixbuf_new_from_file(filename, &error);
+
+	if (error != NULL) {
+		g_warning("failed to load image '%s': %s", filename, error->message);
+		g_error_free(error);
+	} else {
+		if (!picture)
+			g_warning("failed to load image '%s': no error returned!", filename);
+	}
+
+	return picture;
+}
+
+static GdkPixbuf *pixbuf_from_url(const gchar *url, const gchar *md5, const gchar *filename) {
+	GdkPixbuf *image = NULL;
+	FILE *file;
+	CURL *curl;
+	long filesize;
+
+	file = fopen(filename, "wb");
+	if (file == NULL) {
+		g_warning("could not open '%s' for writing", filename);
+		return NULL;
+	}
+	curl = curl_easy_init();
+	if (curl == NULL) {
+		g_warning("could not initialize curl to get image from URL");
+		return NULL;
+	}
+
+	curl_easy_setopt(curl, CURLOPT_URL, url);
+	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_image_data_cb);
+	/* make sure timeout is less than general IO timeout */
+	curl_easy_setopt(curl, CURLOPT_TIMEOUT,
+			(libravatarprefs.timeout == 0
+				|| libravatarprefs.timeout
+					> prefs_common_get_prefs()->io_timeout_secs)
+			? prefs_common_get_prefs()->io_timeout_secs
+			: libravatarprefs.timeout);
+	curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
+
+	if (libravatarprefs.allow_redirects) {
+		long maxredirs = (libravatarprefs.default_mode == DEF_MODE_URL)? 3L
+			: ((libravatarprefs.default_mode == DEF_MODE_MM)? 2L: 1L);
+		curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
+		curl_easy_setopt(curl, CURLOPT_MAXREDIRS, maxredirs);
+	}
+	curl_easy_setopt(curl, CURLOPT_FILE, file);
+	debug_print("retrieving URL to file: %s -> %s\n", url, filename);
+	curl_easy_perform(curl);
+	filesize = ftell(file);
+	fclose(file);
+	if (filesize < MIN_PNG_SIZE)
+		debug_print("not enough data for an avatar image: %ld bytes\n", filesize);
+	else
+		image = image_pixbuf_from_filename(filename);
+
+	if (!libravatarprefs.cache_icons || filesize == 0) {
+		if (g_unlink(filename) < 0)
+			g_warning("failed to delete cache file '%s'", filename);
+	}
+
+	if (filesize == 0)
+		missing_add_md5(libravatarmisses, md5);
+
+	curl_easy_cleanup(curl);
+
+	return image;
+}
+
+static void *get_image_thread(void *arg) {
+	AvatarImageFetch *ctx = (AvatarImageFetch *)arg;
+
+	/* get image */
+	ctx->pixbuf = pixbuf_from_url(ctx->url, ctx->md5, ctx->filename);
+	/* done here */
+	ctx->ready = TRUE;
+
+	return arg;
+}
+
+GdkPixbuf *libravatar_image_fetch(AvatarImageFetch *ctx)
+{
+#ifdef USE_PTHREAD
+	pthread_t pt;
+#endif
+
+	g_return_if_fail(ctx != NULL);
+
+#ifdef USE_PTHREAD
+	if (pthread_create(&pt, PTHREAD_CREATE_JOINABLE, get_image_thread, (void *)ctx) != 0) {
+		debug_print("synchronous image fetching (couldn't create thread)\n");
+		get_image_thread(ctx);
+	} else {
+		debug_print("waiting for thread completion\n");
+		/*
+		while (!ctx->ready ) {
+			claws_do_idle();
+		}
+		*/
+		pthread_join(pt, NULL);
+		debug_print("thread completed\n");
+	}
+#else
+	debug_print("synchronous image fetching (pthreads unavailable)\n");
+	get_image_thread(ctx);
+#endif
+	if (ctx->pixbuf == NULL) {
+		g_warning("could not get image");
+	}
+	return ctx->pixbuf;
+}
diff --git a/src/plugins/libravatar/libravatar_image.h b/src/plugins/libravatar/libravatar_image.h
new file mode 100644
index 0000000..dc298b7
--- /dev/null
+++ b/src/plugins/libravatar/libravatar_image.h
@@ -0,0 +1,37 @@
+/*
+ * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
+ * Copyright (C) 2016 Ricardo Mones and the Claws Mail Team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LIBRAVATAR_IMAGE_H
+#define __LIBRAVATAR_IMAGE_H
+
+#include <glib.h>
+
+typedef struct _AvatarImageFetch	AvatarImageFetch;
+
+GdkPixbuf *libravatar_image_fetch(AvatarImageFetch *ctx);
+
+struct _AvatarImageFetch
+{
+	const gchar	*url;
+	const gchar	*md5;
+	gchar		*filename;
+	GdkPixbuf	*pixbuf;
+	gboolean	ready;
+};
+
+#endif

-----------------------------------------------------------------------


hooks/post-receive
-- 
Claws Mail


More information about the Commits mailing list