[gthumb: 17/20] readded ability to stop the thumbnailer if it lasts too much
- From: Paolo Bacchilega <paobac src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gthumb: 17/20] readded ability to stop the thumbnailer if it lasts too much
- Date: Tue, 30 Mar 2010 19:33:33 +0000 (UTC)
commit a4f7392fb0d077d04989c9fac71e1cfcd3e6ac85
Author: Paolo Bacchilega <paobac src gnome org>
Date: Tue Mar 30 18:21:06 2010 +0200
readded ability to stop the thumbnailer if it lasts too much
gthumb/gnome-desktop-thumbnail.c | 170 ++++++++++++++++++++++++++++++++++++++
gthumb/gnome-desktop-thumbnail.h | 12 +++-
gthumb/gth-thumb-loader.c | 93 ++++++++++++++++++++-
3 files changed, 270 insertions(+), 5 deletions(-)
---
diff --git a/gthumb/gnome-desktop-thumbnail.c b/gthumb/gnome-desktop-thumbnail.c
index 4cf33da..0a333ee 100644
--- a/gthumb/gnome-desktop-thumbnail.c
+++ b/gthumb/gnome-desktop-thumbnail.c
@@ -933,6 +933,176 @@ gnome_desktop_thumbnail_factory_generate_thumbnail (GnomeDesktopThumbnailFactory
return pixbuf;
}
+
+GdkPixbuf *
+gnome_desktop_thumbnail_factory_generate_no_script (GnomeDesktopThumbnailFactory *factory,
+ const char *uri,
+ const char *mime_type)
+{
+ GdkPixbuf *pixbuf, *scaled, *tmp_pixbuf;
+ int width, height, size;
+ int original_width = 0;
+ int original_height = 0;
+ char dimension[12];
+ double scale;
+
+ g_return_val_if_fail (uri != NULL, NULL);
+ g_return_val_if_fail (mime_type != NULL, NULL);
+
+ /* Doesn't access any volatile fields in factory, so it's threadsafe */
+
+ size = 128;
+ if (factory->priv->size == GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE)
+ size = 256;
+
+ /* Use a registered thumbnail generator */
+ pixbuf = gth_hook_invoke_get ("generate-thumbnail", (char *) uri, mime_type, size);
+
+ /* Fall back to gdk-pixbuf */
+ if (pixbuf == NULL)
+ pixbuf = _gdk_pixbuf_new_from_uri_at_scale (uri, size, size, TRUE);
+
+ if (pixbuf == NULL)
+ return NULL;
+
+ if (pixbuf != NULL)
+ {
+ original_width = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (pixbuf),
+ "gnome-original-width"));
+ original_height = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (pixbuf),
+ "gnome-original-height"));
+ }
+
+ /* The pixbuf loader may attach an "orientation" option to the pixbuf,
+ if the tiff or exif jpeg file had an orientation tag. Rotate/flip
+ the pixbuf as specified by this tag, if present. */
+ tmp_pixbuf = gdk_pixbuf_apply_embedded_orientation (pixbuf);
+ g_object_unref (pixbuf);
+ pixbuf = tmp_pixbuf;
+
+ width = gdk_pixbuf_get_width (pixbuf);
+ height = gdk_pixbuf_get_height (pixbuf);
+
+ if (width > size || height > size)
+ {
+ const gchar *orig_width, *orig_height;
+ scale = (double)size / MAX (width, height);
+
+ /* if the scale factor is small, use bilinear interpolation for better quality */
+ if ((scale >= 0.5) && (scale <= 2))
+ scaled = _gdk_pixbuf_scale_simple_safe (pixbuf,
+ floor (width * scale + 0.5),
+ floor (height * scale + 0.5),
+ GDK_INTERP_BILINEAR);
+ else
+ scaled = gnome_desktop_thumbnail_scale_down_pixbuf (pixbuf,
+ floor (width * scale + 0.5),
+ floor (height * scale + 0.5));
+
+ orig_width = gdk_pixbuf_get_option (pixbuf, "tEXt::Thumb::Image::Width");
+ orig_height = gdk_pixbuf_get_option (pixbuf, "tEXt::Thumb::Image::Height");
+
+ if (orig_width != NULL) {
+ gdk_pixbuf_set_option (scaled, "tEXt::Thumb::Image::Width", orig_width);
+ }
+ if (orig_height != NULL) {
+ gdk_pixbuf_set_option (scaled, "tEXt::Thumb::Image::Height", orig_height);
+ }
+
+ g_object_unref (pixbuf);
+ pixbuf = scaled;
+ }
+
+ if (original_width > 0)
+ {
+ g_snprintf (dimension, sizeof (dimension), "%i", original_width);
+ gdk_pixbuf_set_option (pixbuf, "tEXt::Thumb::Image::Width", dimension);
+ }
+ if (original_height > 0)
+ {
+ g_snprintf (dimension, sizeof (dimension), "%i", original_height);
+ gdk_pixbuf_set_option (pixbuf, "tEXt::Thumb::Image::Height", dimension);
+ }
+
+ return pixbuf;
+}
+
+
+gboolean
+gnome_desktop_thumbnail_factory_generate_from_script (GnomeDesktopThumbnailFactory *factory,
+ const char *uri,
+ const char *mime_type,
+ GPid *pid,
+ char **tmpname,
+ GError **error)
+{
+ gboolean retval = FALSE;
+ int size;
+ char *script;
+ int fd;
+ char *expanded_script;
+ int argc;
+ char **argv;
+
+ g_return_val_if_fail (uri != NULL, FALSE);
+ g_return_val_if_fail (mime_type != NULL, FALSE);
+
+ size = 128;
+ if (factory->priv->size == GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE)
+ size = 256;
+
+ script = NULL;
+ g_mutex_lock (factory->priv->lock);
+ if (factory->priv->scripts_hash != NULL) {
+ script = g_hash_table_lookup (factory->priv->scripts_hash, mime_type);
+ if (script)
+ script = g_strdup (script);
+ }
+ g_mutex_unlock (factory->priv->lock);
+
+ if (script == NULL)
+ return FALSE;
+
+ fd = g_file_open_tmp (".gnome_desktop_thumbnail.XXXXXX", tmpname, error);
+ if (fd == -1)
+ return FALSE;
+ close (fd);
+
+ expanded_script = expand_thumbnailing_script (script, size, uri, *tmpname);
+ if (g_shell_parse_argv (expanded_script, &argc, &argv, error))
+ if (g_spawn_async (NULL, argv, NULL, G_SPAWN_DO_NOT_REAP_CHILD, NULL, NULL, pid, error))
+ retval = TRUE;
+
+ g_free (expanded_script);
+ g_free (script);
+
+ return retval;
+}
+
+
+GdkPixbuf *
+gnome_desktop_thumbnail_factory_load_from_tempfile (GnomeDesktopThumbnailFactory *factory,
+ char **tmpname)
+{
+ GdkPixbuf *pixbuf;
+ GdkPixbuf *tmp_pixbuf;
+
+ pixbuf = gdk_pixbuf_new_from_file (*tmpname, NULL);
+ g_unlink (*tmpname);
+ g_free (*tmpname);
+ *tmpname = NULL;
+
+ if (pixbuf == NULL)
+ return NULL;
+
+ tmp_pixbuf = gdk_pixbuf_apply_embedded_orientation (pixbuf);
+ g_object_unref (pixbuf);
+ pixbuf = tmp_pixbuf;
+
+ return pixbuf;
+}
+
+
static gboolean
make_thumbnail_dirs (GnomeDesktopThumbnailFactory *factory)
{
diff --git a/gthumb/gnome-desktop-thumbnail.h b/gthumb/gnome-desktop-thumbnail.h
index 5081d00..3d7a197 100644
--- a/gthumb/gnome-desktop-thumbnail.h
+++ b/gthumb/gnome-desktop-thumbnail.h
@@ -97,6 +97,17 @@ gboolean gnome_desktop_thumbnail_factory_can_thumbnail (GnomeDeskt
GdkPixbuf * gnome_desktop_thumbnail_factory_generate_thumbnail (GnomeDesktopThumbnailFactory *factory,
const char *uri,
const char *mime_type);
+GdkPixbuf * gnome_desktop_thumbnail_factory_generate_no_script (GnomeDesktopThumbnailFactory *factory,
+ const char *uri,
+ const char *mime_type);
+gboolean gnome_desktop_thumbnail_factory_generate_from_script (GnomeDesktopThumbnailFactory *factory,
+ const char *uri,
+ const char *mime_type,
+ GPid *pid,
+ char **tmpname,
+ GError **error);
+GdkPixbuf * gnome_desktop_thumbnail_factory_load_from_tempfile (GnomeDesktopThumbnailFactory *factory,
+ char **tmpname);
void gnome_desktop_thumbnail_factory_save_thumbnail (GnomeDesktopThumbnailFactory *factory,
GdkPixbuf *thumbnail,
const char *uri,
@@ -105,7 +116,6 @@ void gnome_desktop_thumbnail_factory_create_failed_thumbnail (
const char *uri,
time_t mtime);
-
/* Thumbnailing utils: */
gboolean gnome_desktop_thumbnail_has_uri (GdkPixbuf *pixbuf,
const char *uri);
diff --git a/gthumb/gth-thumb-loader.c b/gthumb/gth-thumb-loader.c
index 56df2fc..7058493 100644
--- a/gthumb/gth-thumb-loader.c
+++ b/gthumb/gth-thumb-loader.c
@@ -67,6 +67,10 @@ struct _GthThumbLoaderPrivateData
thumb_size;
GnomeDesktopThumbnailFactory
*thumb_factory;
+ char *thumbnailer_tmpfile;
+ GPid thumbnailer_pid;
+ guint thumbnailer_watch;
+ guint thumbnailer_timeout;
};
@@ -91,6 +95,7 @@ gth_thumb_loader_finalize (GObject *object)
self = GTH_THUMB_LOADER (object);
if (self->priv != NULL) {
+ g_free (self->priv->thumbnailer_tmpfile);
_g_object_unref (self->priv->pixbuf);
_g_object_unref (self->priv->iloader);
_g_object_unref (self->priv->file_data);
@@ -405,7 +410,7 @@ thumb_loader (GthFileData *file_data,
char *uri;
uri = g_file_get_uri (file_data->file);
- pixbuf = gnome_desktop_thumbnail_factory_generate_thumbnail (self->priv->thumb_factory,
+ pixbuf = gnome_desktop_thumbnail_factory_generate_no_script (self->priv->thumb_factory,
uri,
gth_file_data_get_mime_type (file_data));
if (pixbuf == NULL) {
@@ -589,16 +594,68 @@ gth_thumb_loader_get_pixbuf (GthThumbLoader *self)
}
+static gboolean
+kill_thumbnailer_cb (gpointer data)
+{
+ GthThumbLoader *self = data;
+
+ g_source_remove (self->priv->thumbnailer_timeout);
+ self->priv->thumbnailer_timeout = 0;
+
+ if (self->priv->thumbnailer_pid != 0) {
+ /*g_source_remove (self->priv->thumbnailer_watch);
+ self->priv->thumbnailer_watch = 0;*/
+ kill (self->priv->thumbnailer_pid, SIGTERM);
+ /*self->priv->thumbnailer_pid = 0;*/
+ }
+
+ return FALSE;
+}
+
+
+static void
+watch_thumbnailer_cb (GPid pid,
+ int status,
+ gpointer data)
+{
+ GthThumbLoader *self = data;
+ GdkPixbuf *pixbuf = NULL;
+
+ if (self->priv->thumbnailer_timeout != 0) {
+ g_source_remove (self->priv->thumbnailer_timeout);
+ self->priv->thumbnailer_timeout = 0;
+ }
+
+ g_spawn_close_pid (pid);
+ self->priv->thumbnailer_pid = 0;
+ self->priv->thumbnailer_watch = 0;
+
+ if (status == 0)
+ pixbuf = gnome_desktop_thumbnail_factory_load_from_tempfile (self->priv->thumb_factory,
+ &self->priv->thumbnailer_tmpfile);
+
+ if (pixbuf != NULL) {
+ image_loader_loaded (NULL, pixbuf, data);
+ g_object_unref (pixbuf);
+ }
+ else {
+ /* the system thumbnailer couldn't generate the thumbnail,
+ * try using the thumb_loader() function */
+ gth_image_loader_load (self->priv->iloader);
+ }
+}
+
+
static void
gth_thumb_loader_load__step2 (GthThumbLoader *self)
{
char *cache_path = NULL;
+ char *uri;
g_return_if_fail (self != NULL);
if (self->priv->use_cache) {
- char *uri;
- time_t mtime;
+ time_t mtime;
uri = g_file_get_uri (self->priv->file_data->file);
mtime = gth_file_data_get_mtime (self->priv->file_data);
@@ -644,7 +701,35 @@ gth_thumb_loader_load__step2 (GthThumbLoader *self)
}
}
- gth_image_loader_load (self->priv->iloader);
+ if (self->priv->loading_from_cache) {
+ gth_image_loader_load (self->priv->iloader);
+ return;
+ }
+
+ /* not loading from the cache: try with the system thumbnailer first */
+
+ g_free (self->priv->thumbnailer_tmpfile);
+ self->priv->thumbnailer_tmpfile = NULL;
+ uri = g_file_get_uri (self->priv->file_data->file);
+ if (gnome_desktop_thumbnail_factory_generate_from_script (self->priv->thumb_factory,
+ uri,
+ gth_file_data_get_mime_type (self->priv->file_data),
+ &self->priv->thumbnailer_pid,
+ &self->priv->thumbnailer_tmpfile,
+ NULL))
+ {
+ self->priv->thumbnailer_watch = g_child_watch_add (self->priv->thumbnailer_pid,
+ watch_thumbnailer_cb,
+ self);
+ self->priv->thumbnailer_timeout = g_timeout_add (MAX_THUMBNAILER_LIFETIME,
+ kill_thumbnailer_cb,
+ self);
+ }
+ else /* if the system thumbnailer cannot generate the thumbnail,
+ * try using the thumb_loader() function */
+ gth_image_loader_load (self->priv->iloader);
+
+ g_free (uri);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]