[gthumb: 16/40] gth-image-loader: use callbacks instead of signals
- From: Paolo Bacchilega <paobac src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gthumb: 16/40] gth-image-loader: use callbacks instead of signals
- Date: Fri, 10 Sep 2010 16:57:33 +0000 (UTC)
commit 69f25bc5f2a846f1bc74399b9431bb0497323bec
Author: Paolo Bacchilega <paobac src gnome org>
Date: Mon Sep 6 23:43:19 2010 +0200
gth-image-loader: use callbacks instead of signals
this new api allows to fix some loading errors when the user
quickly changes images.
extensions/file_viewer/gth-file-viewer-page.c | 58 +-
extensions/flicker/dlg-import-from-flickr.c | 4 +-
extensions/image_print/gth-load-image-info-task.c | 38 +-
extensions/image_viewer/gth-image-viewer-page.c | 10 +-
extensions/list_tools/gth-script.c | 33 +-
extensions/picasaweb/dlg-import-from-picasaweb.c | 4 +-
extensions/slideshow/gth-slideshow.c | 48 +-
extensions/webalbums/gth-web-exporter.c | 67 +-
gthumb/gth-file-list.c | 320 ++++----
gthumb/gth-file-properties.c | 10 +-
gthumb/gth-image-loader.c | 780 ++++-------------
gthumb/gth-image-loader.h | 62 +-
gthumb/gth-image-preloader.c | 570 +++++++------
gthumb/gth-image-preloader.h | 17 +-
gthumb/gth-main.c | 22 +-
gthumb/gth-main.h | 2 +-
gthumb/gth-marshal.list | 2 +-
gthumb/gth-overwrite-dialog.c | 59 +-
gthumb/gth-thumb-loader.c | 960 ++++++++++-----------
gthumb/gth-thumb-loader.h | 59 +-
20 files changed, 1385 insertions(+), 1740 deletions(-)
---
diff --git a/extensions/file_viewer/gth-file-viewer-page.c b/extensions/file_viewer/gth-file-viewer-page.c
index f2f3923..f2824d7 100644
--- a/extensions/file_viewer/gth-file-viewer-page.c
+++ b/extensions/file_viewer/gth-file-viewer-page.c
@@ -42,7 +42,6 @@ struct _GthFileViewerPagePrivate {
GthFileData *file_data;
guint merge_id;
GthThumbLoader *thumb_loader;
- gulong thumb_loader_ready_event;
};
@@ -86,17 +85,6 @@ viewer_popup_menu_cb (GtkWidget *widget,
static void
-thumb_loader_ready_cb (GthThumbLoader *il,
- GError *error,
- GthFileViewerPage *self)
-{
- if (error == NULL)
- gtk_image_set_from_pixbuf (GTK_IMAGE (self->priv->icon), gth_thumb_loader_get_pixbuf (self->priv->thumb_loader));
- gth_viewer_page_file_loaded (GTH_VIEWER_PAGE (self), self->priv->file_data, TRUE);
-}
-
-
-static void
gth_file_viewer_page_real_activate (GthViewerPage *base,
GthBrowser *browser)
{
@@ -107,13 +95,7 @@ gth_file_viewer_page_real_activate (GthViewerPage *base,
self = (GthFileViewerPage*) base;
self->priv->browser = browser;
-
self->priv->thumb_loader = gth_thumb_loader_new (128);
- self->priv->thumb_loader_ready_event =
- g_signal_connect (G_OBJECT (self->priv->thumb_loader),
- "ready",
- G_CALLBACK (thumb_loader_ready_cb),
- self);
self->priv->viewer = gtk_event_box_new ();
gtk_widget_show (self->priv->viewer);
@@ -162,10 +144,6 @@ gth_file_viewer_page_real_deactivate (GthViewerPage *base)
GthFileViewerPage *self;
self = (GthFileViewerPage*) base;
-
- g_signal_handler_disconnect (self->priv->thumb_loader, self->priv->thumb_loader_ready_event);
- self->priv->thumb_loader_ready_event = 0;
-
gth_browser_set_viewer_widget (self->priv->browser, NULL);
}
@@ -214,6 +192,34 @@ gth_file_viewer_page_real_can_view (GthViewerPage *base,
static void
+thumb_loader_ready_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GthFileViewerPage *self = user_data;
+ GthFileData *file_data;
+ GdkPixbuf *pixbuf;
+
+ if (! gth_thumb_loader_load_finish (GTH_THUMB_LOADER (source_object),
+ result,
+ &file_data,
+ &pixbuf,
+ NULL))
+ {
+ return;
+ }
+
+ if (g_file_equal (self->priv->file_data->file, file_data->file)) {
+ gtk_image_set_from_pixbuf (GTK_IMAGE (self->priv->icon), pixbuf);
+ gth_viewer_page_file_loaded (GTH_VIEWER_PAGE (self), self->priv->file_data, TRUE);
+ }
+
+ g_object_unref (pixbuf);
+ g_object_unref (file_data);
+}
+
+
+static void
gth_file_viewer_page_real_view (GthViewerPage *base,
GthFileData *file_data)
{
@@ -232,8 +238,12 @@ gth_file_viewer_page_real_view (GthViewerPage *base,
self->priv->file_data = g_object_ref (file_data);
gth_viewer_page_focus (GTH_VIEWER_PAGE (self));
- gth_thumb_loader_set_file (self->priv->thumb_loader, file_data);
- gth_thumb_loader_load (self->priv->thumb_loader);
+
+ gth_thumb_loader_load (self->priv->thumb_loader,
+ self->priv->file_data,
+ NULL,
+ thumb_loader_ready_cb,
+ self);
}
diff --git a/extensions/flicker/dlg-import-from-flickr.c b/extensions/flicker/dlg-import-from-flickr.c
index c6a1589..eee3443 100644
--- a/extensions/flicker/dlg-import-from-flickr.c
+++ b/extensions/flicker/dlg-import-from-flickr.c
@@ -560,8 +560,8 @@ dlg_import_from_flickr (FlickrServer *server,
data->file_list = gth_file_list_new (GTH_FILE_LIST_TYPE_NORMAL, FALSE);
thumb_loader = gth_file_list_get_thumb_loader (GTH_FILE_LIST (data->file_list));
- gth_thumb_loader_use_cache (thumb_loader, FALSE);
- gth_thumb_loader_set_loader (thumb_loader, flickr_thumbnail_loader);
+ gth_thumb_loader_set_use_cache (thumb_loader, FALSE);
+ gth_thumb_loader_set_loader_func (thumb_loader, flickr_thumbnail_loader);
gth_file_list_set_thumb_size (GTH_FILE_LIST (data->file_list), FLICKR_SIZE_THUMBNAIL);
gth_file_view_set_spacing (GTH_FILE_VIEW (gth_file_list_get_view (GTH_FILE_LIST (data->file_list))), 0);
gth_file_list_enable_thumbs (GTH_FILE_LIST (data->file_list), TRUE);
diff --git a/extensions/image_print/gth-load-image-info-task.c b/extensions/image_print/gth-load-image-info-task.c
index f7fd3f5..a6b84c3 100644
--- a/extensions/image_print/gth-load-image-info-task.c
+++ b/extensions/image_print/gth-load-image-info-task.c
@@ -103,13 +103,23 @@ continue_loading_image (GthLoadImageInfoTask *self)
static void
-image_loader_ready_cb (GthImageLoader *loader,
- GError *error,
- gpointer user_data)
+image_loader_ready_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
{
GthLoadImageInfoTask *self = user_data;
GthImageInfo *image_info;
GdkPixbuf *pixbuf;
+ GError *error = NULL;
+
+ gth_image_loader_load_image_finish (GTH_IMAGE_LOADER (source_object),
+ result,
+ NULL,
+ NULL,
+ &pixbuf,
+ NULL,
+ NULL,
+ &error);
if (error == NULL)
g_cancellable_set_error_if_cancelled (gth_task_get_cancellable (GTH_TASK (self)), &error);
@@ -120,9 +130,10 @@ image_loader_ready_cb (GthImageLoader *loader,
}
image_info = self->priv->images[self->priv->current];
- pixbuf = gth_image_loader_get_pixbuf (loader);
- if (pixbuf != NULL)
+ if (pixbuf != NULL) {
gth_image_info_set_pixbuf (image_info, pixbuf);
+ g_object_unref (pixbuf);
+ }
continue_loading_image (self);
}
@@ -149,10 +160,13 @@ load_current_image (GthLoadImageInfoTask *self)
FALSE,
((double) self->priv->current + 0.5) / self->priv->n_images);
- if (image_info->pixbuf == NULL) {
- gth_image_loader_set_file_data (self->priv->loader, image_info->file_data);
- gth_image_loader_load (self->priv->loader);
- }
+ if (image_info->pixbuf == NULL)
+ gth_image_loader_load (self->priv->loader,
+ image_info->file_data,
+ -1,
+ gth_task_get_cancellable (GTH_TASK (self)),
+ image_loader_ready_cb,
+ self);
else
call_when_idle ((DataFunc) continue_loading_image, self);
@@ -202,11 +216,7 @@ static void
gth_load_image_info_task_init (GthLoadImageInfoTask *self)
{
self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_LOAD_IMAGE_INFO_TASK, GthLoadImageInfoTaskPrivate);
- self->priv->loader = gth_image_loader_new (FALSE);
- g_signal_connect (self->priv->loader,
- "ready",
- G_CALLBACK (image_loader_ready_cb),
- self);
+ self->priv->loader = gth_image_loader_new (NULL, NULL);
}
diff --git a/extensions/image_viewer/gth-image-viewer-page.c b/extensions/image_viewer/gth-image-viewer-page.c
index b8cebc1..1c846f0 100644
--- a/extensions/image_viewer/gth-image-viewer-page.c
+++ b/extensions/image_viewer/gth-image-viewer-page.c
@@ -287,13 +287,12 @@ viewer_key_press_cb (GtkWidget *widget,
static void
image_preloader_requested_ready_cb (GthImagePreloader *preloader,
GthFileData *requested,
- GthImageLoader *image_loader,
+ GdkPixbufAnimation *animation,
+ int original_width,
+ int original_height,
GError *error,
GthImageViewerPage *self)
{
- int original_width;
- int original_height;
-
if (! _g_file_equal (requested->file, self->priv->file_data->file))
return;
@@ -304,9 +303,8 @@ image_preloader_requested_ready_cb (GthImagePreloader *preloader,
gth_viewer_page_focus (GTH_VIEWER_PAGE (self));
- gth_image_loader_get_original_size (image_loader, &original_width, &original_height);
gth_image_viewer_set_animation (GTH_IMAGE_VIEWER (self->priv->viewer),
- gth_image_loader_get_animation (image_loader),
+ animation,
original_width,
original_height);
diff --git a/extensions/list_tools/gth-script.c b/extensions/list_tools/gth-script.c
index 90b72f4..ec230ac 100644
--- a/extensions/list_tools/gth-script.c
+++ b/extensions/list_tools/gth-script.c
@@ -590,20 +590,25 @@ get_parent_func (GthFileData *file_data)
static void
-thumb_loader_ready_cb (GthThumbLoader *thumb_loader,
- GError *error,
- gpointer user_data)
+thumb_loader_ready_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
{
GtkBuilder *builder = user_data;
GdkPixbuf *pixbuf;
- pixbuf = gth_thumb_loader_get_pixbuf (thumb_loader);
- if (pixbuf != NULL) {
- GtkWidget *image;
+ if (! gth_thumb_loader_load_finish (GTH_THUMB_LOADER (source_object),
+ result,
+ NULL,
+ &pixbuf,
+ NULL))
+ {
+ return;
+ }
- image = _gtk_builder_get_widget (builder, "request_image");
- if (image != NULL)
- gtk_image_set_from_pixbuf (GTK_IMAGE (image), pixbuf);
+ if (pixbuf != NULL) {
+ gtk_image_set_from_pixbuf (GTK_IMAGE (_gtk_builder_get_widget (builder, "request_image")), pixbuf);
+ g_object_unref (pixbuf);
}
g_object_unref (builder);
@@ -650,14 +655,16 @@ ask_value (ReplaceData *replace_data,
gtk_window_set_title (GTK_WINDOW (dialog), "");
gtk_window_set_transient_for (GTK_WINDOW (dialog), replace_data->parent);
gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
- if (! gth_script_for_each_file(replace_data->script))
+ if (! gth_script_for_each_file (replace_data->script))
gtk_widget_hide (_gtk_builder_get_widget (builder, "skip_button"));
g_object_ref (builder);
thumb_loader = gth_thumb_loader_new (128);
- g_signal_connect (thumb_loader, "ready", G_CALLBACK (thumb_loader_ready_cb), builder);
- gth_thumb_loader_set_file (thumb_loader, file_data);
- gth_thumb_loader_load (thumb_loader);
+ gth_thumb_loader_load (thumb_loader,
+ file_data,
+ NULL,
+ thumb_loader_ready_cb,
+ builder);
result = gtk_dialog_run (GTK_DIALOG (dialog));
if (result == 2) {
diff --git a/extensions/picasaweb/dlg-import-from-picasaweb.c b/extensions/picasaweb/dlg-import-from-picasaweb.c
index 1723f7a..b60594d 100644
--- a/extensions/picasaweb/dlg-import-from-picasaweb.c
+++ b/extensions/picasaweb/dlg-import-from-picasaweb.c
@@ -975,8 +975,8 @@ dlg_import_from_picasaweb (GthBrowser *browser)
data->file_list = gth_file_list_new (GTH_FILE_LIST_TYPE_NORMAL, FALSE);
thumb_loader = gth_file_list_get_thumb_loader (GTH_FILE_LIST (data->file_list));
- gth_thumb_loader_use_cache (thumb_loader, FALSE);
- gth_thumb_loader_set_loader (thumb_loader, picasa_web_thumbnail_loader);
+ gth_thumb_loader_set_use_cache (thumb_loader, FALSE);
+ gth_thumb_loader_set_loader_func (thumb_loader, picasa_web_thumbnail_loader);
gth_file_list_set_thumb_size (GTH_FILE_LIST (data->file_list), PICASA_WEB_THUMB_SIZE_SMALL);
gth_file_view_set_spacing (GTH_FILE_VIEW (gth_file_list_get_view (GTH_FILE_LIST (data->file_list))), 0);
gth_file_list_enable_thumbs (GTH_FILE_LIST (data->file_list), TRUE);
diff --git a/extensions/slideshow/gth-slideshow.c b/extensions/slideshow/gth-slideshow.c
index 70c5d4f..8e75a9e 100644
--- a/extensions/slideshow/gth-slideshow.c
+++ b/extensions/slideshow/gth-slideshow.c
@@ -60,6 +60,7 @@ struct _GthSlideshowPrivate {
ClutterActor *image1;
ClutterActor *image2;
#endif
+ GdkPixbuf *current_pixbuf;
GtkWidget *viewer;
guint next_event;
guint delay;
@@ -224,14 +225,15 @@ view_next_image_automatically (GthSlideshow *self)
static void
-image_preloader_requested_ready_cb (GthImagePreloader *preloader,
- GthFileData *requested,
- GthImageLoader *image_loader,
- GError *error,
- gpointer user_data)
+image_preloader_requested_ready_cb (GthImagePreloader *preloader,
+ GthFileData *requested,
+ GdkPixbufAnimation *animation,
+ int original_width,
+ int original_height,
+ GError *error,
+ gpointer user_data)
{
- GthSlideshow *self = user_data;
- GdkPixbuf *pixbuf;
+ GthSlideshow *self = user_data;
if (error != NULL) {
g_clear_error (&error);
@@ -239,14 +241,15 @@ image_preloader_requested_ready_cb (GthImagePreloader *preloader,
return;
}
- pixbuf = gth_image_loader_get_pixbuf (image_loader);
- if (pixbuf == NULL) {
+ _g_object_unref (self->priv->current_pixbuf);
+ self->priv->current_pixbuf = gdk_pixbuf_animation_get_static_image (animation);
+ if (self->priv->current_pixbuf == NULL) {
_gth_slideshow_load_next_image (self);
return;
}
self->priv->one_loaded = TRUE;
- self->priv->projector->image_ready (self, pixbuf);
+ self->priv->projector->image_ready (self, self->priv->current_pixbuf);
}
@@ -268,6 +271,7 @@ gth_slideshow_init (GthSlideshow *self)
self->priv->animating = FALSE;
self->priv->direction = GTH_SLIDESHOW_DIRECTION_FORWARD;
self->priv->random_order = FALSE;
+ self->priv->current_pixbuf = NULL;
self->priv->preloader = gth_image_preloader_new (GTH_LOAD_POLICY_ONE_STEP, 3);
g_signal_connect (self->priv->preloader,
@@ -287,6 +291,7 @@ gth_slideshow_finalize (GObject *object)
if (self->priv->hide_cursor_event != 0)
g_source_remove (self->priv->hide_cursor_event);
+ _g_object_unref (self->priv->current_pixbuf);
_g_object_list_unref (self->priv->file_list);
_g_object_unref (self->priv->browser);
_g_object_unref (self->priv->preloader);
@@ -955,8 +960,6 @@ gth_slideshow_size_allocate_cb (GtkWidget *widget,
{
GthSlideshow *self = user_data;
gfloat stage_w, stage_h;
- GthImageLoader *image_loader;
- GdkPixbuf *pixbuf;
GdkPixbuf *image;
int pixbuf_w, pixbuf_h;
int pixbuf_x, pixbuf_y;
@@ -969,28 +972,23 @@ gth_slideshow_size_allocate_cb (GtkWidget *widget,
if ((stage_w == 0) || (stage_h == 0))
return;
- image_loader = gth_image_preloader_get_loader (self->priv->preloader, (GthFileData *) self->priv->current->data);
- if (image_loader == NULL)
- return;
-
- pixbuf = gth_image_loader_get_pixbuf (image_loader);
- if (pixbuf == NULL)
+ if (self->priv->current_pixbuf == NULL)
return;
- image = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (pixbuf),
+ image = gdk_pixbuf_new (gdk_pixbuf_get_colorspace (self->priv->current_pixbuf),
FALSE,
- gdk_pixbuf_get_bits_per_sample (pixbuf),
+ gdk_pixbuf_get_bits_per_sample (self->priv->current_pixbuf),
stage_w,
stage_h);
gdk_pixbuf_fill (image, 0x000000ff);
- pixbuf_w = gdk_pixbuf_get_width (pixbuf);
- pixbuf_h = gdk_pixbuf_get_height (pixbuf);
+ pixbuf_w = gdk_pixbuf_get_width (self->priv->current_pixbuf);
+ pixbuf_h = gdk_pixbuf_get_height (self->priv->current_pixbuf);
scale_keeping_ratio (&pixbuf_w, &pixbuf_h, (int) stage_w, (int) stage_h, TRUE);
pixbuf_x = (stage_w - pixbuf_w) / 2;
pixbuf_y = (stage_h - pixbuf_h) / 2;
- gdk_pixbuf_composite (pixbuf,
+ gdk_pixbuf_composite (self->priv->current_pixbuf,
image,
pixbuf_x,
pixbuf_y,
@@ -998,8 +996,8 @@ gth_slideshow_size_allocate_cb (GtkWidget *widget,
pixbuf_h,
pixbuf_x,
pixbuf_y,
- (double) pixbuf_w / gdk_pixbuf_get_width (pixbuf),
- (double) pixbuf_h / gdk_pixbuf_get_height (pixbuf),
+ (double) pixbuf_w / gdk_pixbuf_get_width (self->priv->current_pixbuf),
+ (double) pixbuf_h / gdk_pixbuf_get_height (self->priv->current_pixbuf),
GDK_INTERP_BILINEAR,
255);
diff --git a/extensions/webalbums/gth-web-exporter.c b/extensions/webalbums/gth-web-exporter.c
index 9a8978f..f9d6bec 100644
--- a/extensions/webalbums/gth-web-exporter.c
+++ b/extensions/webalbums/gth-web-exporter.c
@@ -2554,16 +2554,37 @@ create_squared_thumbnail (GdkPixbuf *p,
}
+static int
+image_data_cmp (gconstpointer a,
+ gconstpointer b,
+ gpointer user_data)
+{
+ GthWebExporter *self = user_data;
+ ImageData *idata_a = (ImageData *) a;
+ ImageData *idata_b = (ImageData *) b;
+
+ return self->priv->sort_type->cmp_func (idata_a->file_data, idata_b->file_data);
+}
+
+
static void
-image_loader_ready_cb (GthImageLoader *iloader,
- GError *error,
- gpointer data)
+image_loader_ready_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
{
- GthWebExporter *self = data;
+ GthWebExporter *self = user_data;
ImageData *idata;
GdkPixbuf *pixbuf;
- if (error != NULL) {
+ if (! gth_image_loader_load_image_finish (GTH_IMAGE_LOADER (source_object),
+ result,
+ NULL,
+ NULL,
+ &pixbuf,
+ NULL,
+ NULL,
+ NULL))
+ {
load_next_file (self);
return;
}
@@ -2572,7 +2593,7 @@ image_loader_ready_cb (GthImageLoader *iloader,
/* image */
- idata->image = pixbuf = g_object_ref (gth_image_loader_get_pixbuf (iloader));
+ idata->image = g_object_ref (pixbuf);
if (self->priv->copy_images && self->priv->resize_images) {
int w = gdk_pixbuf_get_width (pixbuf);
int h = gdk_pixbuf_get_height (pixbuf);
@@ -2594,7 +2615,7 @@ image_loader_ready_cb (GthImageLoader *iloader,
/* preview */
- idata->preview = pixbuf = g_object_ref (gth_image_loader_get_pixbuf (iloader));
+ idata->preview = g_object_ref (pixbuf);
if ((self->priv->preview_max_width > 0) && (self->priv->preview_max_height > 0)) {
int w = gdk_pixbuf_get_width (pixbuf);
int h = gdk_pixbuf_get_height (pixbuf);
@@ -2626,7 +2647,7 @@ image_loader_ready_cb (GthImageLoader *iloader,
/* thumbnail. */
- idata->thumb = pixbuf = gth_image_loader_get_pixbuf (iloader);
+ idata->thumb = g_object_ref (pixbuf);
g_object_ref (idata->thumb);
if ((self->priv->thumb_width > 0) && (self->priv->thumb_height > 0)) {
@@ -2691,19 +2712,8 @@ image_loader_ready_cb (GthImageLoader *iloader,
}
else
self->priv->saving_timeout = g_idle_add (save_image_preview, self);
-}
-
-
-static int
-image_data_cmp (gconstpointer a,
- gconstpointer b,
- gpointer user_data)
-{
- GthWebExporter *self = user_data;
- ImageData *idata_a = (ImageData *) a;
- ImageData *idata_b = (ImageData *) b;
- return self->priv->sort_type->cmp_func (idata_a->file_data, idata_b->file_data);
+ g_object_unref (pixbuf);
}
@@ -2727,8 +2737,13 @@ load_current_file (GthWebExporter *self)
g_file_info_get_display_name (file_data->info),
FALSE,
(double) (self->priv->image + 1) / (self->priv->n_images + 1));
- gth_image_loader_set_file_data (self->priv->iloader, file_data);
- gth_image_loader_load (self->priv->iloader);
+
+ gth_image_loader_load (self->priv->iloader,
+ file_data,
+ -1,
+ gth_task_get_cancellable (GTH_TASK (self)),
+ image_loader_ready_cb,
+ self);
}
@@ -3186,13 +3201,7 @@ gth_web_exporter_init (GthWebExporter *self)
self->priv->file_list = NULL;
self->priv->tmp_dir = NULL;
self->priv->interrupted = FALSE;
-
- self->priv->iloader = gth_image_loader_new (FALSE);
- g_signal_connect (G_OBJECT (self->priv->iloader),
- "ready",
- G_CALLBACK (image_loader_ready_cb),
- self);
-
+ self->priv->iloader = gth_image_loader_new (NULL, NULL);
self->priv->error = NULL;
}
diff --git a/gthumb/gth-file-list.c b/gthumb/gth-file-list.c
index b7341aa..5f34680 100644
--- a/gthumb/gth-file-list.c
+++ b/gthumb/gth-file-list.c
@@ -77,6 +77,7 @@ typedef struct {
* image. */
guint thumb_created : 1; /* Whether a thumb has been
* created for this image. */
+ GdkPixbuf *pixbuf;
} ThumbData;
@@ -122,6 +123,8 @@ struct _GthFileListPrivateData
char **caption_attributes_v;
+ gboolean can_cancel;
+ GCancellable *cancellable;
DataFunc done_func;
gpointer done_func_data;
};
@@ -248,10 +251,12 @@ gth_file_list_finalize (GObject *object)
file_list = GTH_FILE_LIST (object);
if (file_list->priv != NULL) {
+ g_object_unref (file_list->priv->cancellable);
g_hash_table_unref (file_list->priv->thumb_data);
if (file_list->priv->icon_cache != NULL)
gth_icon_cache_free (file_list->priv->icon_cache);
g_strfreev (file_list->priv->caption_attributes_v);
+
g_free (file_list->priv);
file_list->priv = NULL;
}
@@ -340,6 +345,7 @@ thumb_data_unref (ThumbData *data)
data->ref--;
if (data->ref > 0)
return;
+ _g_object_unref (data->pixbuf);
g_free (data);
}
@@ -354,6 +360,8 @@ gth_file_list_init (GthFileList *file_list)
file_list->priv->ignore_hidden_thumbs = FALSE;
file_list->priv->load_thumbs = TRUE;
file_list->priv->caption_attributes_v = g_strsplit ("none", ",", -1);
+ file_list->priv->cancellable = g_cancellable_new ();
+ file_list->priv->can_cancel = FALSE;
}
@@ -361,124 +369,6 @@ static void _gth_file_list_update_next_thumb (GthFileList *file_list);
static void
-flash_queue (GthFileList *file_list)
-{
- if (file_list->priv->dirty) {
- GthFileStore *file_store;
-
- file_store = (GthFileStore *) gth_file_view_get_model (GTH_FILE_VIEW (file_list->priv->view));
- gth_file_store_exec_set (file_store);
- file_list->priv->dirty = FALSE;
- }
-
- if (file_list->priv->dirty_event != 0) {
- g_source_remove (file_list->priv->dirty_event);
- file_list->priv->dirty_event = 0;
- }
-}
-
-
-static gboolean
-flash_queue_cb (gpointer data)
-{
- flash_queue ((GthFileList *) data);
- return FALSE;
-}
-
-
-static void
-queue_flash_updates (GthFileList *file_list)
-{
- file_list->priv->dirty = TRUE;
- if (file_list->priv->dirty_event == 0)
- file_list->priv->dirty_event = g_timeout_add (UPDATE_THUMBNAILS_TIMEOUT, flash_queue_cb, file_list);
-}
-
-
-static void
-update_thumb_in_file_view (GthFileList *file_list)
-{
- GthFileStore *file_store;
- GdkPixbuf *pixbuf;
-
- file_store = (GthFileStore *) gth_file_view_get_model (GTH_FILE_VIEW (file_list->priv->view));
-
- pixbuf = gth_thumb_loader_get_pixbuf (file_list->priv->thumb_loader);
- if (pixbuf != NULL) {
- GtkTreeIter iter;
-
- if (gth_file_store_get_nth_visible (file_store, file_list->priv->thumb_pos, &iter)) {
- gth_file_store_queue_set (file_store,
- &iter,
- GTH_FILE_STORE_THUMBNAIL_COLUMN, pixbuf,
- GTH_FILE_STORE_IS_ICON_COLUMN, FALSE,
- -1);
- queue_flash_updates (file_list);
- }
- }
-}
-
-
-static void
-set_mime_type_icon (GthFileList *file_list,
- GthFileData *file_data)
-{
- GthFileStore *file_store;
- GtkTreeIter iter;
- GIcon *icon;
- GdkPixbuf *pixbuf;
-
- file_store = (GthFileStore *) gth_file_view_get_model (GTH_FILE_VIEW (file_list->priv->view));
-
- if (! gth_file_store_find (file_store, file_data->file, &iter))
- return;
-
- icon = g_file_info_get_icon (file_data->info);
- pixbuf = gth_icon_cache_get_pixbuf (file_list->priv->icon_cache, icon);
- gth_file_store_queue_set (file_store,
- &iter,
- GTH_FILE_STORE_THUMBNAIL_COLUMN, pixbuf,
- GTH_FILE_STORE_IS_ICON_COLUMN, TRUE,
- -1);
- queue_flash_updates (file_list);
-
- _g_object_unref (pixbuf);
-}
-
-
-static void
-thumb_loader_ready_cb (GthThumbLoader *tloader,
- GError *error,
- gpointer data)
-{
- GthFileList *file_list = data;
-
- if (file_list->priv->thumb_fd != NULL) {
- ThumbData *thumb_data;
-
- thumb_data = g_hash_table_lookup (file_list->priv->thumb_data, file_list->priv->thumb_fd->file);
- if (error == NULL) {
- thumb_data->error = FALSE;
- thumb_data->thumb_created = TRUE;
- if (file_list->priv->update_thumb_in_view) {
- thumb_data->thumb_loaded = TRUE;
- update_thumb_in_file_view (file_list);
- }
- }
- else {
- thumb_data->error = TRUE;
- thumb_data->thumb_loaded = FALSE;
- thumb_data->thumb_created = FALSE;
- if (file_list->priv->update_thumb_in_view)
- set_mime_type_icon (file_list, file_list->priv->thumb_fd);
- }
- }
-
- _gth_file_list_update_next_thumb (file_list);
-}
-
-
-static void
start_update_next_thumb (GthFileList *file_list)
{
GthFileStore *file_store;
@@ -617,16 +507,7 @@ gth_file_list_construct (GthFileList *file_list,
GtkCellRenderer *renderer;
GthFileStore *model;
- /* thumbnail loader */
-
file_list->priv->thumb_loader = gth_thumb_loader_new (file_list->priv->thumb_size);
- g_signal_connect (G_OBJECT (file_list->priv->thumb_loader),
- "ready",
- G_CALLBACK (thumb_loader_ready_cb),
- file_list);
-
- /* other data */
-
file_list->priv->icon_cache = gth_icon_cache_new (gtk_icon_theme_get_for_screen (gtk_widget_get_screen (GTK_WIDGET (file_list))), file_list->priv->thumb_size / 2);
/* the main notebook */
@@ -831,18 +712,7 @@ _gth_file_list_done (GthFileList *file_list)
_gth_file_list_thumb_cleanup (file_list);
file_list->priv->loading_thumbs = FALSE;
file_list->priv->cancel = FALSE;
-}
-
-
-static void
-cancel_step2 (gpointer user_data)
-{
- GthFileList *file_list = user_data;
-
- _gth_file_list_done (file_list);
-
- if (file_list->priv->done_func)
- (file_list->priv->done_func) (file_list->priv->done_func_data);
+ g_cancellable_reset (file_list->priv->cancellable);
}
@@ -855,7 +725,13 @@ gth_file_list_cancel (GthFileList *file_list,
file_list->priv->done_func = done_func;
file_list->priv->done_func_data = user_data;
- gth_thumb_loader_cancel (file_list->priv->thumb_loader, cancel_step2, file_list);
+
+ if (file_list->priv->can_cancel) {
+ g_cancellable_cancel (file_list->priv->cancellable);
+ file_list->priv->can_cancel = FALSE;
+ }
+ else
+ call_when_idle (done_func, user_data);
}
@@ -1381,10 +1257,151 @@ gth_file_list_get_vadjustment (GthFileList *file_list)
static void
-_gth_file_list_thumbs_completed (GthFileList *file_list)
+flash_queue (GthFileList *file_list)
{
- flash_queue (file_list);
- _gth_file_list_done (file_list);
+ if (file_list->priv->dirty) {
+ GthFileStore *file_store;
+
+ file_store = (GthFileStore *) gth_file_view_get_model (GTH_FILE_VIEW (file_list->priv->view));
+ gth_file_store_exec_set (file_store);
+ file_list->priv->dirty = FALSE;
+ }
+
+ if (file_list->priv->dirty_event != 0) {
+ g_source_remove (file_list->priv->dirty_event);
+ file_list->priv->dirty_event = 0;
+ }
+}
+
+
+static gboolean
+flash_queue_cb (gpointer data)
+{
+ flash_queue ((GthFileList *) data);
+ return FALSE;
+}
+
+
+static void
+queue_flash_updates (GthFileList *file_list)
+{
+ file_list->priv->dirty = TRUE;
+ if (file_list->priv->dirty_event == 0)
+ file_list->priv->dirty_event = g_timeout_add (UPDATE_THUMBNAILS_TIMEOUT, flash_queue_cb, file_list);
+}
+
+
+static void
+update_thumb_in_file_view (GthFileList *file_list,
+ GthFileData *file_data)
+{
+ GthFileStore *file_store;
+ GtkTreeIter iter;
+ ThumbData *thumb_data;
+
+ file_store = (GthFileStore *) gth_file_view_get_model (GTH_FILE_VIEW (file_list->priv->view));
+ if (! gth_file_store_find (file_store, file_data->file, &iter))
+ return;
+
+ thumb_data = g_hash_table_lookup (file_list->priv->thumb_data, file_data->file);
+ if (thumb_data == NULL)
+ return;
+
+ if (thumb_data->pixbuf == NULL)
+ return;
+
+ gth_file_store_queue_set (file_store,
+ &iter,
+ GTH_FILE_STORE_THUMBNAIL_COLUMN, thumb_data->pixbuf,
+ GTH_FILE_STORE_IS_ICON_COLUMN, FALSE,
+ -1);
+ queue_flash_updates (file_list);
+}
+
+
+static void
+set_mime_type_icon (GthFileList *file_list,
+ GthFileData *file_data)
+{
+ GthFileStore *file_store;
+ GtkTreeIter iter;
+ GIcon *icon;
+ GdkPixbuf *pixbuf;
+
+ file_store = (GthFileStore *) gth_file_view_get_model (GTH_FILE_VIEW (file_list->priv->view));
+ if (! gth_file_store_find (file_store, file_data->file, &iter))
+ return;
+
+ icon = g_file_info_get_icon (file_data->info);
+ pixbuf = gth_icon_cache_get_pixbuf (file_list->priv->icon_cache, icon);
+ gth_file_store_queue_set (file_store,
+ &iter,
+ GTH_FILE_STORE_THUMBNAIL_COLUMN, pixbuf,
+ GTH_FILE_STORE_IS_ICON_COLUMN, TRUE,
+ -1);
+ queue_flash_updates (file_list);
+
+ _g_object_unref (pixbuf);
+}
+
+
+static void
+thumb_loader_ready_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GthFileList *file_list = user_data;
+ ThumbData *thumb_data;
+ GthFileData *file_data;
+ GdkPixbuf *pixbuf;
+ GError *error = NULL;
+
+ file_list->priv->can_cancel = FALSE;
+
+ if (file_list->priv->thumb_fd == NULL) {
+ _gth_file_list_update_next_thumb (file_list);
+ return;
+ }
+
+ thumb_data = g_hash_table_lookup (file_list->priv->thumb_data, file_list->priv->thumb_fd->file);
+ if (thumb_data == NULL) {
+ _gth_file_list_update_next_thumb (file_list);
+ return;
+ }
+
+ _g_object_unref (thumb_data->pixbuf);
+ thumb_data->pixbuf = NULL;
+
+ if (! gth_thumb_loader_load_finish (GTH_THUMB_LOADER (source_object),
+ result,
+ &file_data,
+ &pixbuf,
+ &error))
+ {
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ _gth_file_list_done (file_list);
+ if (file_list->priv->done_func)
+ (file_list->priv->done_func) (file_list->priv->done_func_data);
+ return;
+ }
+
+ thumb_data->error = TRUE;
+ thumb_data->thumb_loaded = FALSE;
+ thumb_data->thumb_created = FALSE;
+ if (file_list->priv->update_thumb_in_view)
+ set_mime_type_icon (file_list, file_list->priv->thumb_fd);
+ }
+ else {
+ thumb_data->error = FALSE;
+ thumb_data->thumb_created = TRUE;
+ thumb_data->pixbuf = pixbuf;
+ if (file_list->priv->update_thumb_in_view) {
+ thumb_data->thumb_loaded = TRUE;
+ update_thumb_in_file_view (file_list, file_list->priv->thumb_fd);
+ }
+ }
+
+ _gth_file_list_update_next_thumb (file_list);
}
@@ -1420,8 +1437,21 @@ static void
_gth_file_list_update_current_thumb (GthFileList *file_list)
{
set_loading_icon (file_list, file_list->priv->thumb_fd);
- gth_thumb_loader_set_file (file_list->priv->thumb_loader, file_list->priv->thumb_fd);
- gth_thumb_loader_load (file_list->priv->thumb_loader);
+
+ file_list->priv->can_cancel = TRUE;
+ gth_thumb_loader_load (file_list->priv->thumb_loader,
+ file_list->priv->thumb_fd,
+ file_list->priv->cancellable,
+ thumb_loader_ready_cb,
+ file_list);
+}
+
+
+static void
+_gth_file_list_thumbs_completed (GthFileList *file_list)
+{
+ flash_queue (file_list);
+ _gth_file_list_done (file_list);
}
diff --git a/gthumb/gth-file-properties.c b/gthumb/gth-file-properties.c
index f18d98a..ae03162 100644
--- a/gthumb/gth-file-properties.c
+++ b/gthumb/gth-file-properties.c
@@ -92,8 +92,8 @@ gth_file_properties_real_set_file (GthPropertyView *base,
{
GthFileProperties *self;
GHashTable *category_hash;
- GPtrArray *metadata_info;
- int i;
+ GList *metadata_info;
+ GList *scan;
GtkTextBuffer *text_buffer;
char *comment;
@@ -107,14 +107,13 @@ gth_file_properties_real_set_file (GthPropertyView *base,
category_hash = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, NULL);
metadata_info = gth_main_get_all_metadata_info ();
- for (i = 0; i < metadata_info->len; i++) {
- GthMetadataInfo *info;
+ for (scan = metadata_info; scan; scan = scan->next) {
+ GthMetadataInfo *info = scan->data;
char *value;
char *tooltip;
GthMetadataCategory *category;
GtkTreeIter iter;
- info = g_ptr_array_index (metadata_info, i);
if ((info->flags & GTH_METADATA_ALLOW_IN_PROPERTIES_VIEW) != GTH_METADATA_ALLOW_IN_PROPERTIES_VIEW)
continue;
@@ -163,6 +162,7 @@ gth_file_properties_real_set_file (GthPropertyView *base,
g_free (tooltip);
g_free (value);
}
+ g_list_free (metadata_info);
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (self->priv->tree_model), POS_COLUMN, GTK_SORT_ASCENDING);
gtk_tree_view_expand_all (GTK_TREE_VIEW (self->priv->tree_view));
diff --git a/gthumb/gth-image-loader.c b/gthumb/gth-image-loader.c
index 5ae3106..c047ddb 100644
--- a/gthumb/gth-image-loader.c
+++ b/gthumb/gth-image-loader.c
@@ -24,329 +24,49 @@
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gtk/gtk.h>
#include "gth-file-data.h"
-#include "glib-utils.h"
-#include "gth-error.h"
#include "gth-image-loader.h"
#include "gth-main.h"
-/*
-#include "file-utils.h"
-#include "glib-utils.h"
-#include "gconf-utils.h"
-#include "gth-exif-utils.h"
-#include "pixbuf-utils.h"
-#include "preferences.h"
-*/
-
-#define REFRESH_RATE 5
-#define GTH_IMAGE_LOADER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTH_TYPE_IMAGE_LOADER, GthImageLoaderPrivate))
-G_LOCK_DEFINE_STATIC (pixbuf_loader_lock);
-
struct _GthImageLoaderPrivate {
- GthFileData *file;
- int requested_size;
- GdkPixbuf *pixbuf;
- GdkPixbufAnimation *animation;
- int original_width;
- int original_height;
-
- gboolean as_animation; /* Whether to load the image in a
- * GdkPixbufAnimation structure. */
- gboolean ready;
- GError *error;
- gboolean loader_ready;
- gboolean cancelled;
- gboolean loading;
- gboolean emit_signal;
-
- DataFunc done_func;
- gpointer done_func_data;
-
- guint check_id;
- guint idle_id;
-
- GThread *thread;
-
- GMutex *data_mutex;
-
- gboolean exit_thread;
- GMutex *exit_thread_mutex;
-
- gboolean start_loading;
- GMutex *start_loading_mutex;
- GCond *start_loading_cond;
-
- PixbufLoader loader;
- gpointer loader_data;
- GCancellable *cancellable;
-};
-
-
-enum {
- READY,
- LAST_SIGNAL
+ gboolean as_animation; /* Whether to load the image in a
+ * GdkPixbufAnimation structure. */
+ PixbufLoader loader_func;
+ gpointer loader_data;
};
static gpointer parent_class = NULL;
-static guint gth_image_loader_signals[LAST_SIGNAL] = { 0 };
-
-
-static void
-gth_image_loader_finalize__step2 (GObject *object)
-{
- GthImageLoader *self;
-
- self = GTH_IMAGE_LOADER (object);
-
- g_mutex_lock (self->priv->data_mutex);
- if (self->priv->file != NULL) {
- g_object_unref (self->priv->file);
- self->priv->file = NULL;
- }
- if (self->priv->pixbuf != NULL) {
- g_object_unref (G_OBJECT (self->priv->pixbuf));
- self->priv->pixbuf = NULL;
- }
-
- if (self->priv->animation != NULL) {
- g_object_unref (G_OBJECT (self->priv->animation));
- self->priv->animation = NULL;
- }
- g_mutex_unlock (self->priv->data_mutex);
-
- g_mutex_lock (self->priv->exit_thread_mutex);
- self->priv->exit_thread = TRUE;
- g_mutex_unlock (self->priv->exit_thread_mutex);
-
- g_mutex_lock (self->priv->start_loading_mutex);
- self->priv->start_loading = TRUE;
- g_cond_signal (self->priv->start_loading_cond);
- g_mutex_unlock (self->priv->start_loading_mutex);
-
- g_thread_join (self->priv->thread);
-
- g_cond_free (self->priv->start_loading_cond);
- g_mutex_free (self->priv->data_mutex);
- g_mutex_free (self->priv->start_loading_mutex);
- g_mutex_free (self->priv->exit_thread_mutex);
-
- g_object_unref (self->priv->cancellable);
-
- /* Chain up */
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-
-static void _gth_image_loader_stop (GthImageLoader *self,
- DataFunc done_func,
- gpointer done_func_data,
- gboolean emit_sig,
- gboolean use_idle_cb);
static void
gth_image_loader_finalize (GObject *object)
{
- GthImageLoader *self;
-
- g_return_if_fail (object != NULL);
- g_return_if_fail (GTH_IS_IMAGE_LOADER (object));
-
- self = GTH_IMAGE_LOADER (object);
-
- if (self->priv->idle_id != 0) {
- g_source_remove (self->priv->idle_id);
- self->priv->idle_id = 0;
- }
-
- if (self->priv->check_id != 0) {
- g_source_remove (self->priv->check_id);
- self->priv->check_id = 0;
- }
-
- _gth_image_loader_stop (self,
- (DataFunc) gth_image_loader_finalize__step2,
- object,
- FALSE,
- FALSE);
+ G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
gth_image_loader_class_init (GthImageLoaderClass *class)
{
- GObjectClass *object_class = G_OBJECT_CLASS (class);
+ GObjectClass *object_class;
parent_class = g_type_class_peek_parent (class);
g_type_class_add_private (class, sizeof (GthImageLoaderPrivate));
+ object_class = G_OBJECT_CLASS (class);
object_class->finalize = gth_image_loader_finalize;
- gth_image_loader_signals[READY] =
- g_signal_new ("ready",
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GthImageLoaderClass, ready),
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE,
- 1,
- G_TYPE_POINTER);
-}
-
-
-static void *
-load_image_thread (void *thread_data)
-{
- GthImageLoader *self = thread_data;
- GdkPixbufAnimation *animation;
- GError *error;
-
- for (;;) {
- GthFileData *file;
- gboolean exit_thread;
- int requested_size;
- int original_width;
- int original_height;
-
- g_mutex_lock (self->priv->start_loading_mutex);
- while (! self->priv->start_loading)
- g_cond_wait (self->priv->start_loading_cond, self->priv->start_loading_mutex);
- self->priv->start_loading = FALSE;
- g_mutex_unlock (self->priv->start_loading_mutex);
-
- g_mutex_lock (self->priv->exit_thread_mutex);
- exit_thread = self->priv->exit_thread;
- requested_size = self->priv->requested_size;
- g_mutex_unlock (self->priv->exit_thread_mutex);
-
- if (exit_thread)
- break;
-
- file = gth_image_loader_get_file (self);
-
- G_LOCK (pixbuf_loader_lock);
-
- original_width = -1;
- original_height = -1;
- animation = NULL;
- if (file != NULL) {
- error = NULL;
- if (self->priv->loader != NULL) {
- animation = (*self->priv->loader) (file,
- requested_size,
- &original_width,
- &original_height,
- self->priv->loader_data,
- self->priv->cancellable,
- &error);
- }
- else {
- PixbufLoader loader;
-
- loader = gth_main_get_pixbuf_loader (gth_file_data_get_mime_type (file));
- if (loader != NULL)
- animation = loader (file,
- requested_size,
- &original_width,
- &original_height,
- NULL,
- self->priv->cancellable,
- &error);
- else
- error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("No suitable loader available for this file type"));
- }
- }
-
- G_UNLOCK (pixbuf_loader_lock);
-
- g_mutex_lock (self->priv->data_mutex);
-
- self->priv->loader_ready = TRUE;
-
- if ((animation == NULL) || (error != NULL)) {
- self->priv->error = error;
- self->priv->ready = FALSE;
- }
- else if ((self->priv->file != NULL)
- && _g_file_equal_uris (file->file, self->priv->file->file)
- && (requested_size == self->priv->requested_size))
- {
- _g_object_unref (self->priv->animation);
- self->priv->animation = g_object_ref (animation);
- self->priv->original_width = original_width;
- self->priv->original_height = original_height;
-
- self->priv->error = NULL;
- self->priv->ready = TRUE;
- }
-
- _g_object_unref (animation);
-
- g_mutex_unlock (self->priv->data_mutex);
-
- g_object_unref (file);
- }
-
- return NULL;
}
static void
gth_image_loader_init (GthImageLoader *self)
{
- self->priv = GTH_IMAGE_LOADER_GET_PRIVATE (self);
-
- self->priv->pixbuf = NULL;
- self->priv->animation = NULL;
- self->priv->file = NULL;
- self->priv->requested_size = -1;
-
- self->priv->ready = FALSE;
- self->priv->error = NULL;
- self->priv->loader_ready = FALSE;
- self->priv->cancelled = FALSE;
-
- self->priv->done_func = NULL;
- self->priv->done_func_data = NULL;
-
- self->priv->check_id = 0;
- self->priv->idle_id = 0;
-
- self->priv->data_mutex = g_mutex_new ();
-
- self->priv->exit_thread = FALSE;
- self->priv->exit_thread_mutex = g_mutex_new ();
-
- self->priv->start_loading = FALSE;
- self->priv->start_loading_mutex = g_mutex_new ();
- self->priv->start_loading_cond = g_cond_new ();
-
- self->priv->loader = NULL;
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_IMAGE_LOADER, GthImageLoaderPrivate);
+ self->priv->as_animation = FALSE;
+ self->priv->loader_func = NULL;
self->priv->loader_data = NULL;
-
- self->priv->cancellable = g_cancellable_new ();
-
- /*self->priv->thread = g_thread_create (load_image_thread, self, TRUE, NULL);*/
-
- /* The g_thread_create function assigns a very large default stacksize for each
- thread (10 MB on FC6), which is probably excessive. 16k seems to be
- sufficient. To be conversative, we'll try 32k. Use g_thread_create_full to
- manually specify a small stack size. See Bug 310749 - Memory usage.
- This reduces the virtual memory requirements, and the "writeable/private"
- figure reported by "pmap -d". */
-
- /* Update: 32k caused crashes with svg images. Boosting to 512k. Bug 410827. */
-
- self->priv->thread = g_thread_create_full (load_image_thread,
- self,
- (512 * 1024),
- TRUE,
- TRUE,
- G_THREAD_PRIORITY_NORMAL,
- NULL);
}
@@ -379,399 +99,219 @@ gth_image_loader_get_type (void)
GthImageLoader *
-gth_image_loader_new (gboolean as_animation)
+gth_image_loader_new (PixbufLoader loader_func,
+ gpointer loader_data)
{
GthImageLoader *self;
self = g_object_new (GTH_TYPE_IMAGE_LOADER, NULL);
- g_mutex_lock (self->priv->data_mutex);
- self->priv->as_animation = as_animation;
- g_mutex_unlock (self->priv->data_mutex);
+ gth_image_loader_set_loader_func (self, loader_func, loader_data);
return self;
}
void
-gth_image_loader_set_loader (GthImageLoader *self,
- PixbufLoader loader,
- gpointer loader_data)
+gth_image_loader_set_loader_func (GthImageLoader *self,
+ PixbufLoader loader_func,
+ gpointer loader_data)
{
g_return_if_fail (self != NULL);
- g_mutex_lock (self->priv->data_mutex);
- self->priv->loader = loader;
+ self->priv->loader_func = loader_func;
self->priv->loader_data = loader_data;
- g_mutex_unlock (self->priv->data_mutex);
}
-void
-gth_image_loader_set_file_data (GthImageLoader *self,
- GthFileData *file)
-{
- g_mutex_lock (self->priv->data_mutex);
- _g_object_unref (self->priv->file);
- self->priv->file = NULL;
- if (file != NULL)
- self->priv->file = gth_file_data_dup (file);
- g_mutex_unlock (self->priv->data_mutex);
-}
+typedef struct {
+ GthFileData *file_data;
+ int requested_size;
+} LoadData;
-GthFileData *
-gth_image_loader_get_file (GthImageLoader *self)
+static LoadData *
+load_data_new (GthFileData *file_data,
+ int requested_size)
{
- GthFileData *file = NULL;
+ LoadData *load_data;
- g_mutex_lock (self->priv->data_mutex);
- if (self->priv->file != NULL)
- file = gth_file_data_dup (self->priv->file);
- g_mutex_unlock (self->priv->data_mutex);
+ load_data = g_new0 (LoadData, 1);
+ load_data->file_data = g_object_ref (file_data);
+ load_data->requested_size = requested_size;
- return file;
-}
-
-
-void
-gth_image_loader_set_pixbuf (GthImageLoader *self,
- GdkPixbuf *pixbuf)
-{
- g_return_if_fail (self != NULL);
-
- g_mutex_lock (self->priv->data_mutex);
-
- if (self->priv->animation != NULL) {
- g_object_unref (self->priv->animation);
- self->priv->animation = NULL;
- }
-
- if (self->priv->pixbuf != NULL) {
- g_object_unref (self->priv->pixbuf);
- self->priv->pixbuf = NULL;
- }
-
- self->priv->pixbuf = pixbuf;
- if (pixbuf != NULL)
- g_object_ref (pixbuf);
-
- g_mutex_unlock (self->priv->data_mutex);
+ return load_data;
}
static void
-_gth_image_loader_sync_pixbuf (GthImageLoader *self)
+load_data_unref (LoadData *load_data)
{
- GdkPixbuf *pixbuf;
-
- g_mutex_lock (self->priv->data_mutex);
-
- if (self->priv->animation == NULL) {
- if (self->priv->pixbuf != NULL)
- g_object_unref (self->priv->pixbuf);
- self->priv->pixbuf = NULL;
- g_mutex_unlock (self->priv->data_mutex);
- return;
- }
-
- pixbuf = gdk_pixbuf_animation_get_static_image (self->priv->animation);
- g_object_ref (pixbuf);
-
- if (self->priv->pixbuf == pixbuf) {
- g_object_unref (pixbuf);
- g_mutex_unlock (self->priv->data_mutex);
- return;
- }
-
- if (self->priv->pixbuf != NULL) {
- g_object_unref (self->priv->pixbuf);
- self->priv->pixbuf = NULL;
- }
-
- if (pixbuf != NULL) {
- g_object_ref (pixbuf);
- self->priv->pixbuf = pixbuf;
- }
-
- g_object_unref (pixbuf);
-
- g_mutex_unlock (self->priv->data_mutex);
+ g_object_unref (load_data->file_data);
+ g_free (load_data);
}
-static void
-_gth_image_loader_cancelled (GthImageLoader *self)
-{
- g_mutex_lock (self->priv->data_mutex);
- self->priv->error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_CANCELLED, "");
- g_mutex_unlock (self->priv->data_mutex);
-
- _gth_image_loader_stop (self,
- self->priv->done_func,
- self->priv->done_func_data,
- TRUE,
- TRUE);
-}
+typedef struct {
+ GthFileData *file_data;
+ int requested_size;
+ GdkPixbufAnimation *animation;
+ int original_width;
+ int original_height;
+} LoadResult;
static void
-_gth_image_loader_ready (GthImageLoader *self)
+load_result_unref (LoadResult *load_result)
{
- g_mutex_lock (self->priv->data_mutex);
- self->priv->error = NULL;
- g_mutex_unlock (self->priv->data_mutex);
-
- _gth_image_loader_stop (self, NULL, NULL, TRUE, TRUE);
+ g_object_unref (load_result->file_data);
+ if (load_result->animation != NULL)
+ g_object_unref (load_result->animation);
+ g_free (load_result);
}
static void
-_gth_image_loader_error (GthImageLoader *self,
- GError *error)
+load_pixbuf_thread (GSimpleAsyncResult *result,
+ GObject *object,
+ GCancellable *cancellable)
{
- g_mutex_lock (self->priv->data_mutex);
-
- if (self->priv->error != error) {
- if (self->priv->error != NULL) {
- g_error_free (self->priv->error);
- self->priv->error = NULL;
- }
- self->priv->error = error;
- }
-
- g_mutex_unlock (self->priv->data_mutex);
-
- _gth_image_loader_stop (self, NULL, NULL, TRUE, TRUE);
-}
-
-
-static gboolean
-check_thread (gpointer data)
-{
- GthImageLoader *self = data;
- gboolean ready, loader_done;
- GError *error = NULL;
-
- /* Remove check. */
-
- g_source_remove (self->priv->check_id);
- self->priv->check_id = 0;
-
- /**/
-
- g_mutex_lock (self->priv->data_mutex);
-
- ready = self->priv->ready;
- if (self->priv->error != NULL)
- error = g_error_copy (self->priv->error);
- loader_done = self->priv->loader_ready;
-
- g_mutex_unlock (self->priv->data_mutex);
-
- /**/
-
- if (loader_done && self->priv->cancelled)
- _gth_image_loader_cancelled (self);
-
- else if (loader_done && ready)
- _gth_image_loader_ready (self);
-
- else if (loader_done && (error != NULL))
- _gth_image_loader_error (self, error);
-
- else /* Add the check again. */
- self->priv->check_id = g_timeout_add (REFRESH_RATE, check_thread, self);
-
- return FALSE;
-}
-
-
-static void
-_gth_image_loader_load__step2 (GthImageLoader *self)
-{
- g_mutex_lock (self->priv->data_mutex);
-
- self->priv->ready = FALSE;
- self->priv->error = NULL;
- self->priv->loader_ready = FALSE;
- self->priv->loading = TRUE;
- if (self->priv->pixbuf != NULL) {
- g_object_unref (self->priv->pixbuf);
- self->priv->pixbuf = NULL;
+ GthImageLoader *self = GTH_IMAGE_LOADER (object);
+ LoadData *load_data;
+ GdkPixbufAnimation *animation;
+ int original_width;
+ int original_height;
+ GError *error = NULL;
+ LoadResult *load_result;
+
+ load_data = g_simple_async_result_get_op_res_gpointer (result);
+ animation = NULL;
+ original_width = -1;
+ original_height = -1;
+
+ if (self->priv->loader_func != NULL) {
+ animation = (*self->priv->loader_func) (load_data->file_data,
+ load_data->requested_size,
+ &original_width,
+ &original_height,
+ self->priv->loader_data,
+ cancellable,
+ &error);
}
- if (self->priv->animation != NULL) {
- g_object_unref (self->priv->animation);
- self->priv->animation = NULL;
+ else {
+ PixbufLoader loader_func;
+
+ loader_func = gth_main_get_pixbuf_loader (gth_file_data_get_mime_type (load_data->file_data));
+ if (loader_func != NULL)
+ animation = loader_func (load_data->file_data,
+ load_data->requested_size,
+ &original_width,
+ &original_height,
+ NULL,
+ cancellable,
+ &error);
+ else
+ error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("No suitable loader available for this file type"));
}
- g_cancellable_reset (self->priv->cancellable);
-
- g_mutex_unlock (self->priv->data_mutex);
-
- /**/
-
- g_mutex_lock (self->priv->start_loading_mutex);
-
- self->priv->start_loading = TRUE;
- g_cond_signal (self->priv->start_loading_cond);
-
- g_mutex_unlock (self->priv->start_loading_mutex);
- /**/
+ load_result = g_new0 (LoadResult, 1);
+ load_result->file_data = g_object_ref (load_data->file_data);
+ load_result->requested_size = load_data->requested_size;
+ load_result->animation = animation;
+ load_result->original_width = original_width;
+ load_result->original_height = original_height;
- self->priv->check_id = g_timeout_add (REFRESH_RATE,
- check_thread,
- self);
+ if (error != NULL) {
+ g_simple_async_result_set_from_error (result, error);
+ g_error_free (error);
+ }
+ else
+ g_simple_async_result_set_op_res_gpointer (result, load_result, (GDestroyNotify) load_result_unref);
}
void
-gth_image_loader_load (GthImageLoader *self)
+gth_image_loader_load (GthImageLoader *loader,
+ GthFileData *file_data,
+ int requested_size,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- gth_image_loader_load_at_size (self, -1);
+ GSimpleAsyncResult *result;
+
+ result = g_simple_async_result_new (G_OBJECT (loader), callback, user_data, gth_image_loader_load);
+ g_simple_async_result_set_op_res_gpointer (result,
+ load_data_new (file_data, requested_size),
+ (GDestroyNotify) load_data_unref);
+ g_simple_async_result_run_in_thread (result,
+ load_pixbuf_thread,
+ G_PRIORITY_DEFAULT,
+ cancellable);
+ g_object_unref (result);
}
-void
-gth_image_loader_load_at_size (GthImageLoader *self,
- int requested_size)
+gboolean
+gth_image_loader_load_animation_finish (GthImageLoader *loader,
+ GAsyncResult *result,
+ GthFileData **file_data,
+ int *requested_size,
+ GdkPixbufAnimation **animation,
+ int *original_width,
+ int *original_height,
+ GError **error)
{
- gboolean no_file = FALSE;
-
- g_return_if_fail (self != NULL);
+ GSimpleAsyncResult *simple;
+ LoadResult *load_result;
- g_mutex_lock (self->priv->data_mutex);
- if (self->priv->file == NULL)
- no_file = TRUE;
- self->priv->requested_size = requested_size;
- g_mutex_unlock (self->priv->data_mutex);
-
- if (no_file)
- return;
-
- _gth_image_loader_stop (self,
- (DataFunc) _gth_image_loader_load__step2,
- self,
- FALSE,
- TRUE);
-}
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (loader), gth_image_loader_load), FALSE);
+ simple = G_SIMPLE_ASYNC_RESULT (result);
+ if (g_simple_async_result_propagate_error (simple, error))
+ return FALSE;
-/* -- gth_image_loader_stop -- */
+ load_result = g_simple_async_result_get_op_res_gpointer (simple);
+ if (file_data != NULL)
+ *file_data = g_object_ref (load_result->file_data);
+ if (requested_size != NULL)
+ *requested_size = load_result->requested_size;
+ if (animation != NULL)
+ *animation = g_object_ref (load_result->animation);
+ if (original_width != NULL)
+ *original_width = load_result->original_width;
+ if (original_height != NULL)
+ *original_height = load_result->original_height;
-
-static void
-_gth_image_loader_stop__step2 (GthImageLoader *self,
- gboolean use_idle_cb)
-{
- DataFunc done_func;
- GError *error;
-
- g_mutex_lock (self->priv->data_mutex);
- error = self->priv->error;
- self->priv->error = NULL;
- self->priv->ready = TRUE;
- g_mutex_unlock (self->priv->data_mutex);
-
- if ((error == NULL) && ! self->priv->cancelled && self->priv->loading)
- _gth_image_loader_sync_pixbuf (self);
- self->priv->loading = FALSE;
-
- done_func = self->priv->done_func;
- self->priv->done_func = NULL;
- if (done_func != NULL) {
- IdleCall *call;
-
- call = idle_call_new (done_func, self->priv->done_func_data);
- if (self->priv->idle_id != 0)
- g_source_remove (self->priv->idle_id);
- self->priv->idle_id = idle_call_exec (call, use_idle_cb);
- }
-
- if (! self->priv->emit_signal || self->priv->cancelled) {
- self->priv->cancelled = FALSE;
- return;
- }
- self->priv->cancelled = FALSE;
-
- g_signal_emit (G_OBJECT (self),
- gth_image_loader_signals[READY],
- 0,
- error);
+ return TRUE;
}
-static void
-_gth_image_loader_stop (GthImageLoader *self,
- DataFunc done_func,
- gpointer done_func_data,
- gboolean emit_signal,
- gboolean use_idle_cb)
-{
- self->priv->done_func = done_func;
- self->priv->done_func_data = done_func_data;
- self->priv->emit_signal = emit_signal;
-
- _gth_image_loader_stop__step2 (self, use_idle_cb);
-}
-
-
-void
-gth_image_loader_cancel (GthImageLoader *self,
- DataFunc done_func,
- gpointer done_func_data)
-{
- g_mutex_lock (self->priv->data_mutex);
- self->priv->error = FALSE;
- g_mutex_unlock (self->priv->data_mutex);
-
- if (self->priv->loading) {
- self->priv->emit_signal = TRUE;
- self->priv->cancelled = TRUE;
- self->priv->done_func = done_func;
- self->priv->done_func_data = done_func_data;
- g_cancellable_cancel (self->priv->cancellable);
- }
- else
- _gth_image_loader_stop (self,
- done_func,
- done_func_data,
- FALSE,
- TRUE);
-}
-
-
-GdkPixbuf *
-gth_image_loader_get_pixbuf (GthImageLoader *self)
-{
- return self->priv->pixbuf;
-}
-
-
-GdkPixbufAnimation *
-gth_image_loader_get_animation (GthImageLoader *self)
+gboolean
+gth_image_loader_load_image_finish (GthImageLoader *loader,
+ GAsyncResult *res,
+ GthFileData **file_data,
+ int *requested_size,
+ GdkPixbuf **pixbuf,
+ int *original_width,
+ int *original_height,
+ GError **error)
{
GdkPixbufAnimation *animation;
- g_mutex_lock (self->priv->data_mutex);
- animation = self->priv->animation;
- if (animation != NULL)
- g_object_ref (animation);
- g_mutex_unlock (self->priv->data_mutex);
-
- return animation;
-}
+ if (! gth_image_loader_load_animation_finish (loader,
+ res,
+ file_data,
+ requested_size,
+ &animation,
+ original_width,
+ original_height,
+ error))
+ {
+ return FALSE;
+ }
+ *pixbuf = gdk_pixbuf_animation_get_static_image (animation);
-void
-gth_image_loader_get_original_size (GthImageLoader *self,
- int *width,
- int *height)
-{
- g_mutex_lock (self->priv->data_mutex);
- if (width != NULL)
- *width = self->priv->original_width;
- if (height != NULL)
- *height = self->priv->original_height;
- g_mutex_unlock (self->priv->data_mutex);
+ return TRUE;
}
diff --git a/gthumb/gth-image-loader.h b/gthumb/gth-image-loader.h
index 36fff43..31d9c2b 100644
--- a/gthumb/gth-image-loader.h
+++ b/gthumb/gth-image-loader.h
@@ -3,7 +3,7 @@
/*
* GThumb
*
- * Copyright (C) 2001-2008 The Free Software Foundation, Inc.
+ * Copyright (C) 2001-2010 The Free Software Foundation, Inc.
*
* 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
@@ -41,43 +41,43 @@ typedef struct _GthImageLoader GthImageLoader;
typedef struct _GthImageLoaderClass GthImageLoaderClass;
typedef struct _GthImageLoaderPrivate GthImageLoaderPrivate;
-struct _GthImageLoader
-{
+struct _GthImageLoader {
GObject __parent;
GthImageLoaderPrivate *priv;
};
-struct _GthImageLoaderClass
-{
+struct _GthImageLoaderClass {
GObjectClass __parent_class;
-
- /* -- Signals -- */
-
- void (* ready) (GthImageLoader *iloader,
- GError *error);
};
-GType gth_image_loader_get_type (void);
-GthImageLoader * gth_image_loader_new (gboolean as_animation);
-void gth_image_loader_set_loader (GthImageLoader *iloader,
- PixbufLoader loader,
- gpointer data);
-void gth_image_loader_set_file_data (GthImageLoader *iloader,
- GthFileData *file);
-GthFileData * gth_image_loader_get_file (GthImageLoader *iloader);
-void gth_image_loader_set_pixbuf (GthImageLoader *iloader,
- GdkPixbuf *pixbuf);
-GdkPixbuf * gth_image_loader_get_pixbuf (GthImageLoader *iloader);
-GdkPixbufAnimation * gth_image_loader_get_animation (GthImageLoader *iloader);
-void gth_image_loader_get_original_size (GthImageLoader *iloader,
- int *width,
- int *height);
-void gth_image_loader_load (GthImageLoader *iloader);
-void gth_image_loader_load_at_size (GthImageLoader *iloader,
- int requested_size);
-void gth_image_loader_cancel (GthImageLoader *iloader,
- DataFunc done_func,
- gpointer done_func_data);
+GType gth_image_loader_get_type (void);
+GthImageLoader * gth_image_loader_new (PixbufLoader loader_func,
+ gpointer loader_data);
+void gth_image_loader_set_loader_func (GthImageLoader *loader,
+ PixbufLoader loader_func,
+ gpointer loader_data);
+void gth_image_loader_load (GthImageLoader *loader,
+ GthFileData *file_data,
+ int requested_size,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean gth_image_loader_load_animation_finish (GthImageLoader *loader,
+ GAsyncResult *res,
+ GthFileData **file_data,
+ int *requested_size,
+ GdkPixbufAnimation **animation,
+ int *original_width,
+ int *original_height,
+ GError **error);
+gboolean gth_image_loader_load_image_finish (GthImageLoader *loader,
+ GAsyncResult *res,
+ GthFileData **file_data,
+ int *requested_size,
+ GdkPixbuf **pixbuf,
+ int *original_width,
+ int *original_height,
+ GError **error);
G_END_DECLS
diff --git a/gthumb/gth-image-preloader.c b/gthumb/gth-image-preloader.c
index 184c37a..314e255 100644
--- a/gthumb/gth-image-preloader.c
+++ b/gthumb/gth-image-preloader.c
@@ -41,12 +41,16 @@ enum {
typedef struct {
+ GthImagePreloader *self;
GthFileData *file_data;
int requested_size;
- GthImageLoader *loader;
gboolean loaded;
gboolean error;
- GthImagePreloader *self;
+ GthImageLoader *loader;
+ GdkPixbufAnimation *animation;
+ int original_width;
+ int original_height;
+ guint token;
} Preloader;
@@ -67,10 +71,11 @@ struct _GthImagePreloaderPrivate {
* any signal. */
GFile *requested_file;
int requested_size;
- GthFileData **files;
int current; /* This is the loader that has
* a loading underway. */
guint load_id;
+ GCancellable *cancellable;
+ guint token;
};
@@ -80,89 +85,6 @@ static guint gth_image_preloader_signals[LAST_SIGNAL] = { 0 };
/* -- Preloader -- */
-static void start_next_loader (GthImagePreloader *self);
-static Preloader * current_preloader (GthImagePreloader *self);
-static Preloader * requested_preloader (GthImagePreloader *self);
-
-
-static gboolean
-load_next (gpointer data)
-{
- GthImagePreloader *self = data;
-
- if (self->priv->load_id != 0) {
- g_source_remove (self->priv->load_id);
- self->priv->load_id = 0;
- }
-
- start_next_loader (self);
-
- return FALSE;
-}
-
-
-static gboolean
-preloader_need_second_step (Preloader *preloader)
-{
- int original_width;
- int original_height;
- GdkPixbufAnimation *animation;
-
- gth_image_loader_get_original_size (preloader->loader, &original_width, &original_height);
- animation = gth_image_loader_get_animation (preloader->loader);
-
- return (! preloader->error
- && (preloader->requested_size != -1)
- && ((original_width > preloader->requested_size) || (original_height > preloader->requested_size))
- && (animation != NULL)
- && gdk_pixbuf_animation_is_static_image (animation));
-}
-
-
-static void
-image_loader_ready_cb (GthImageLoader *iloader,
- GError *error,
- Preloader *preloader)
-{
- GthImagePreloader *self = preloader->self;
- int interval = NEXT_LOAD_SMALL_TIMEOUT;
-
- preloader->loaded = (error == NULL);
- preloader->error = (error != NULL);
-
- g_object_ref (self);
-
- if (_g_file_equal (preloader->file_data->file, self->priv->requested_file)) {
-#if DEBUG_PRELOADER
- debug (DEBUG_INFO, "[requested] %s => %s [size: %d]", (error == NULL) ? "ready" : "error", g_file_get_uri (preloader->file_data->file), preloader->requested_size);
-#endif
-
- g_signal_emit (G_OBJECT (self),
- gth_image_preloader_signals[REQUESTED_READY],
- 0,
- preloader->file_data,
- preloader->loader,
- error);
-
- /* Reload only if the original size is bigger then the
- * requested size, and if the image is not an animation. */
-
- if ((self->priv->load_policy == GTH_LOAD_POLICY_TWO_STEPS)
- && preloader_need_second_step (preloader))
- {
- /* Reload the image at the original size */
- preloader->loaded = FALSE;
- preloader->requested_size = -1;
- }
-
- interval = NEXT_LOAD_BIG_TIMEOUT;
- }
-
- self->priv->load_id = g_timeout_add (interval, load_next, self);
-
- g_object_unref (self);
-}
-
static Preloader *
preloader_new (GthImagePreloader *self)
@@ -170,16 +92,14 @@ preloader_new (GthImagePreloader *self)
Preloader *preloader;
preloader = g_new0 (Preloader, 1);
+ preloader->self = self;
preloader->file_data = NULL;
preloader->loaded = FALSE;
preloader->error = FALSE;
- preloader->loader = GTH_IMAGE_LOADER (gth_image_loader_new (TRUE));
- preloader->self = self;
-
- g_signal_connect (G_OBJECT (preloader->loader),
- "ready",
- G_CALLBACK (image_loader_ready_cb),
- preloader);
+ preloader->loader = gth_image_loader_new (NULL, NULL);
+ preloader->animation = NULL;
+ preloader->original_width = -1;
+ preloader->original_height = -1;
return preloader;
}
@@ -190,6 +110,7 @@ preloader_free (Preloader *preloader)
{
if (preloader == NULL)
return;
+ _g_object_unref (preloader->animation);
_g_object_unref (preloader->loader);
_g_object_unref (preloader->file_data);
g_free (preloader);
@@ -207,16 +128,53 @@ preloader_set_file_data (Preloader *preloader,
preloader->file_data = NULL;
}
- if (file_data != NULL) {
+ if (file_data != NULL)
preloader->file_data = g_object_ref (file_data);
- gth_image_loader_set_file_data (preloader->loader, preloader->file_data);
- }
preloader->loaded = FALSE;
preloader->error = FALSE;
}
+static gboolean
+preloader_has_valid_content_for_file (Preloader *preloader,
+ GthFileData *file_data)
+{
+ return ((preloader->file_data != NULL)
+ && preloader->loaded
+ && ! preloader->error
+ && (preloader->animation != NULL)
+ && g_file_equal (preloader->file_data->file, file_data->file)
+ && (_g_time_val_cmp (gth_file_data_get_modification_time (file_data),
+ gth_file_data_get_modification_time (preloader->file_data)) == 0));
+}
+
+
+static gboolean
+preloader_needs_to_load (Preloader *preloader)
+{
+ return ((preloader->token == preloader->self->priv->token)
+ && (preloader->file_data != NULL)
+ && ! preloader->error
+ && ! preloader->loaded);
+}
+
+
+static gboolean
+preloader_needs_second_step (Preloader *preloader)
+{
+ if (preloader->self->priv->load_policy != GTH_LOAD_POLICY_TWO_STEPS)
+ return FALSE;
+
+ return ((preloader->token == preloader->self->priv->token)
+ && ! preloader->error
+ && (preloader->requested_size != -1)
+ && ((preloader->original_width > preloader->requested_size) || (preloader->original_height > preloader->requested_size))
+ && (preloader->animation != NULL)
+ && gdk_pixbuf_animation_is_static_image (preloader->animation));
+}
+
+
/* -- GthImagePreloader -- */
@@ -241,18 +199,9 @@ gth_image_preloader_finalize (GObject *object)
self->priv->loader[i] = NULL;
}
g_free (self->priv->loader);
- self->priv->loader = NULL;
-
_g_object_unref (self->priv->requested_file);
+ g_object_unref (self->priv->cancellable);
- for (i = 0; i < self->priv->n_preloaders; i++) {
- _g_object_unref (self->priv->files[i]);
- self->priv->files[i] = NULL;
- }
- g_free (self->priv->files);
- self->priv->files = NULL;
-
- /* Chain up */
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@@ -271,11 +220,13 @@ gth_image_preloader_class_init (GthImagePreloaderClass *class)
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GthImagePreloaderClass, requested_ready),
NULL, NULL,
- gth_marshal_VOID__OBJECT_OBJECT_POINTER,
+ gth_marshal_VOID__OBJECT_OBJECT_INT_INT_POINTER,
G_TYPE_NONE,
- 3,
+ 5,
G_TYPE_OBJECT,
G_TYPE_OBJECT,
+ G_TYPE_INT,
+ G_TYPE_INT,
G_TYPE_POINTER);
object_class = G_OBJECT_CLASS (class);
@@ -291,8 +242,9 @@ gth_image_preloader_init (GthImagePreloader *self)
self->priv->requested = -1;
self->priv->requested_file = NULL;
self->priv->current = -1;
- self->priv->files = NULL;
self->priv->load_policy = GTH_LOAD_POLICY_ONE_STEP;
+ self->priv->cancellable = g_cancellable_new ();
+ self->priv->token = 0;
}
@@ -340,82 +292,248 @@ gth_image_preloader_new (GthLoadPolicy load_policy,
self->priv->loader = g_new0 (Preloader *, self->priv->n_preloaders);
for (i = 0; i < self->priv->n_preloaders; i++)
self->priv->loader[i] = preloader_new (self);
- self->priv->files = g_new0 (GthFileData *, self->priv->n_preloaders);
return self;
}
+void
+gth_image_prelaoder_set_load_policy (GthImagePreloader *self,
+ GthLoadPolicy policy)
+{
+ self->priv->load_policy = policy;
+}
+
+
+/* -- gth_image_preloader_load -- */
+
+
+static void start_next_loader (GthImagePreloader *self);
+
+
+static gboolean
+load_next (gpointer data)
+{
+ GthImagePreloader *self = data;
+
+ if (self->priv->load_id != 0) {
+ g_source_remove (self->priv->load_id);
+ self->priv->load_id = 0;
+ }
+ start_next_loader (self);
+
+ return FALSE;
+}
+
+
+static void
+image_loader_ready_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ Preloader *preloader = user_data;
+ GthImagePreloader *self = preloader->self;
+ GthFileData *file_data;
+ int requested_size;
+ GdkPixbufAnimation *animation;
+ int original_width;
+ int original_height;
+ GError *error = NULL;
+ gboolean success;
+ int interval;
+
+ success = gth_image_loader_load_animation_finish (GTH_IMAGE_LOADER (source_object),
+ result,
+ &file_data,
+ &requested_size,
+ &animation,
+ &original_width,
+ &original_height,
+ &error);
+
+ if (! g_file_equal (file_data->file, preloader->file_data->file)
+ || (preloader->token != self->priv->token))
+ {
+ g_object_unref (file_data);
+ g_object_unref (animation);
+ if (error != NULL)
+ g_error_free (error);
+ return;
+ }
+
+ interval = NEXT_LOAD_SMALL_TIMEOUT;
+
+ _g_object_unref (preloader->animation);
+ preloader->animation = g_object_ref (animation);
+ preloader->original_width = original_width;
+ preloader->original_height = original_height;
+ preloader->loaded = success;
+ preloader->error = ! success;
+ preloader->requested_size = requested_size;
+
+ if (_g_file_equal (file_data->file, self->priv->requested_file)) {
+#if DEBUG_PRELOADER
+ debug (DEBUG_INFO, "[requested] %s => %s [size: %d]", (error == NULL) ? "ready" : "error", g_file_get_uri (preloader->file_data->file), preloader->requested_size);
+#endif
+
+ g_signal_emit (G_OBJECT (self),
+ gth_image_preloader_signals[REQUESTED_READY],
+ 0,
+ preloader->file_data,
+ preloader->animation,
+ preloader->original_width,
+ preloader->original_height,
+ error);
+
+ /* Reload only if the original size is bigger then the
+ * requested size, and if the image is not an animation. */
+
+ if (preloader_needs_second_step (preloader)) {
+ /* Reload the image at the original size */
+ preloader->loaded = FALSE;
+ preloader->requested_size = -1;
+ }
+
+ interval = NEXT_LOAD_BIG_TIMEOUT;
+ }
+
+ if (self->priv->load_id == 0)
+ self->priv->load_id = g_timeout_add (interval, load_next, self);
+
+ g_object_unref (file_data);
+ g_object_unref (animation);
+}
+
+
static Preloader *
current_preloader (GthImagePreloader *self)
{
- if (self->priv->current == -1)
- return NULL;
- else
- return self->priv->loader[self->priv->current];
+ return (self->priv->current == -1) ? NULL : self->priv->loader[self->priv->current];
}
static Preloader *
requested_preloader (GthImagePreloader *self)
{
- if (self->priv->requested == -1)
- return NULL;
- else
- return self->priv->loader[self->priv->requested];
+ return (self->priv->requested == -1) ? NULL : self->priv->loader[self->priv->requested];
}
-/* -- gth_image_preloader_load -- */
+static void
+start_next_loader (GthImagePreloader *self)
+{
+ int i;
+ Preloader *preloader;
+
+ i = -1;
+
+ if (preloader_needs_to_load (requested_preloader (self))) {
+ i = self->priv->requested;
+ }
+ else {
+ int n = 0;
+
+ if (self->priv->current == -1)
+ i = 0;
+ else
+ i = (self->priv->current + 1) % self->priv->n_preloaders;
+
+ for (i = 0; n < self->priv->n_preloaders; i = (i + 1) % self->priv->n_preloaders) {
+ if (preloader_needs_to_load (self->priv->loader[i]))
+ break;
+ n++;
+ }
+
+ if (n >= self->priv->n_preloaders)
+ i = -1;
+ }
+
+ self->priv->current = i;
+ preloader = current_preloader (self);
+
+ if (preloader != NULL) {
+#if DEBUG_PRELOADER
+ {
+ char *uri;
+
+ uri = g_file_get_uri (preloader->file_data->file);
+ debug (DEBUG_INFO, "load %s [size: %d]", uri, preloader->requested_size);
+ g_free (uri);
+ }
+#endif
+
+ _g_object_unref (preloader->animation);
+ preloader->animation = NULL;
+
+ g_cancellable_reset (preloader->self->priv->cancellable);
+ gth_image_loader_load (preloader->loader,
+ preloader->file_data,
+ preloader->requested_size,
+ preloader->self->priv->cancellable,
+ image_loader_ready_cb,
+ preloader);
+ }
+#if DEBUG_PRELOADER
+ else
+ debug (DEBUG_INFO, "done");
+#endif
+}
typedef struct {
- GthImagePreloader *self;
- GthFileData *requested;
- int requested_size;
+ GthImagePreloader *self;
+ GthFileData *requested;
+ int requested_size;
+ GthFileData **files;
+ int n_files;
+ guint token;
} LoadData;
static void
load_data_free (LoadData *load_data)
{
+ int i;
+
if (load_data == NULL)
return;
- _g_object_unref (load_data->requested);
+ for (i = 0; i < load_data->n_files; i++)
+ g_object_unref (load_data->files[i]);
+ g_free (load_data->files);
g_free (load_data);
}
-void
-gth_image_preloader_load__step2 (LoadData *load_data)
+static void
+assign_loaders (LoadData *load_data)
{
GthImagePreloader *self = load_data->self;
gboolean *file_assigned;
gboolean *loader_assigned;
- GthFileData *requested;
int i, j;
- if (! _g_file_equal (load_data->requested->file, self->priv->requested_file)
- || (load_data->requested_size != self->priv->requested_size))
- {
+ if (load_data->token != self->priv->token) {
load_data_free (load_data);
return;
}
- requested = load_data->requested;
-
file_assigned = g_new (gboolean, self->priv->n_preloaders);
loader_assigned = g_new (gboolean, self->priv->n_preloaders);
for (i = 0; i < self->priv->n_preloaders; i++) {
+ Preloader *preloader = self->priv->loader[i];
+
loader_assigned[i] = FALSE;
file_assigned[i] = FALSE;
+
+ if (preloader->loaded && ! preloader->error)
+ preloader->token = load_data->token;
}
self->priv->requested = -1;
- for (j = 0; j < self->priv->n_preloaders; j++) {
- GthFileData *file_data = self->priv->files[j];
+ for (j = 0; j < load_data->n_files; j++) {
+ GthFileData *file_data = load_data->files[j];
if (file_data == NULL)
continue;
@@ -425,29 +543,27 @@ gth_image_preloader_load__step2 (LoadData *load_data)
for (i = 0; i < self->priv->n_preloaders; i++) {
Preloader *preloader = self->priv->loader[i];
- if ((preloader->file_data != NULL)
- && g_file_equal (preloader->file_data->file, file_data->file)
- && (_g_time_val_cmp (gth_file_data_get_modification_time (file_data),
- gth_file_data_get_modification_time (preloader->file_data)) == 0)
- && preloader->loaded)
- {
+ if (preloader_has_valid_content_for_file (preloader, file_data)) {
loader_assigned[i] = TRUE;
file_assigned[j] = TRUE;
- if ((requested != NULL) && g_file_equal (file_data->file, requested->file)) {
+
+ if (file_data == load_data->requested) {
self->priv->requested = i;
+
g_signal_emit (G_OBJECT (self),
gth_image_preloader_signals[REQUESTED_READY],
0,
preloader->file_data,
- preloader->loader,
+ preloader->animation,
+ preloader->original_width,
+ preloader->original_height,
NULL);
+
#if DEBUG_PRELOADER
debug (DEBUG_INFO, "[requested] preloaded");
#endif
- if ((self->priv->load_policy == GTH_LOAD_POLICY_TWO_STEPS)
- && preloader_need_second_step (preloader))
- {
+ if (preloader_needs_second_step (preloader)) {
/* Reload the image at the original size */
preloader->loaded = FALSE;
preloader->requested_size = -1;
@@ -469,10 +585,10 @@ gth_image_preloader_load__step2 (LoadData *load_data)
}
}
- /* assign remaining files */
+ /* assign the remaining files */
- for (j = 0; j < self->priv->n_preloaders; j++) {
- GthFileData *file_data = self->priv->files[j];
+ for (j = 0; j < load_data->n_files; j++) {
+ GthFileData *file_data = load_data->files[j];
Preloader *preloader;
int k;
@@ -488,13 +604,16 @@ gth_image_preloader_load__step2 (LoadData *load_data)
g_return_if_fail (k < self->priv->n_preloaders);
- preloader = self->priv->loader[k];
loader_assigned[k] = TRUE;
+
+ preloader = self->priv->loader[k];
preloader_set_file_data (preloader, file_data);
preloader->requested_size = load_data->requested_size;
+ preloader->token = load_data->token;
- if ((requested != NULL) && g_file_equal (file_data->file, requested->file)) {
+ if (file_data == load_data->requested) {
self->priv->requested = k;
+
#if DEBUG_PRELOADER
{
char *uri;
@@ -507,17 +626,18 @@ gth_image_preloader_load__step2 (LoadData *load_data)
}
#if DEBUG_PRELOADER
- uri = g_file_get_uri (file_data->file);
- debug (DEBUG_INFO, "[+] [%d] <- %s", k, uri);
- g_free (uri);
+ {
+ char *uri;
+
+ uri = g_file_get_uri (file_data->file);
+ debug (DEBUG_INFO, "[+] [%d] <- %s", k, uri);
+ g_free (uri);
+ }
#endif
}
- load_data_free (load_data);
g_free (loader_assigned);
g_free (file_assigned);
-
- start_next_loader (self);
}
@@ -543,43 +663,38 @@ gth_image_preloader_load (GthImagePreloader *self,
int requested_size,
...)
{
- int i;
+ LoadData *load_data;
int n;
va_list args;
GthFileData *file_data;
- LoadData *load_data;
- _g_object_unref (self->priv->requested_file);
- self->priv->requested_file = g_object_ref (requested->file);
- self->priv->requested_size = requested_size;
- self->priv->requested = -1;
-
- for (i = 0; i < self->priv->n_preloaders; i++) {
- _g_object_unref (self->priv->files[i]);
- self->priv->files[i] = NULL;
- }
+ self->priv->token++;
- self->priv->files[0] = gth_file_data_dup (requested);
- n = 1;
- va_start (args, requested_size);
- while ((n < self->priv->n_preloaders) && (file_data = va_arg (args, GthFileData *)) != NULL)
- self->priv->files[n++] = check_file (file_data);
- va_end (args);
+ _g_object_unref (self->priv->requested_file);
+ self->priv->requested_file = g_file_dup (requested->file);
load_data = g_new0 (LoadData, 1);
load_data->self = self;
+ load_data->token = self->priv->token;
load_data->requested = gth_file_data_dup (requested);
load_data->requested_size = requested_size;
+ load_data->files = g_new0 (GthFileData *, self->priv->n_preloaders);
- gth_image_preloader_stop (self, (DataFunc) gth_image_preloader_load__step2, load_data);
-}
+ n = 0;
+ load_data->files[n++] = load_data->requested;
+ va_start (args, requested_size);
+ while ((n < self->priv->n_preloaders) && (file_data = va_arg (args, GthFileData *)) != NULL) {
+ GthFileData *checked_file_data = check_file (file_data);
+ if (checked_file_data != NULL)
+ load_data->files[n++] = checked_file_data;
+ }
+ va_end (args);
+ load_data->n_files = n;
+ assign_loaders (load_data);
+ start_next_loader (self);
-void
-gth_image_prelaoder_set_load_policy (GthImagePreloader *self,
- GthLoadPolicy policy)
-{
- self->priv->load_policy = policy;
+ load_data_free (load_data);
}
@@ -597,14 +712,8 @@ gth_image_preloader_get_loader (GthImagePreloader *self,
for (i = 0; i < self->priv->n_preloaders; i++) {
Preloader *preloader = self->priv->loader[i];
- if ((preloader->file_data != NULL)
- && g_file_equal (preloader->file_data->file, file_data->file)
- && (_g_time_val_cmp (gth_file_data_get_modification_time (file_data),
- gth_file_data_get_modification_time (preloader->file_data)) == 0)
- && preloader->loaded)
- {
+ if (preloader_has_valid_content_for_file (preloader, file_data))
return preloader->loader;
- }
}
return NULL;
@@ -617,92 +726,5 @@ gth_image_preloader_get_requested (GthImagePreloader *self)
Preloader *preloader;
preloader = requested_preloader (self);
- if (preloader == NULL)
- return NULL;
- else
- return preloader->file_data;
-}
-
-
-static void
-start_next_loader (GthImagePreloader *self)
-{
- Preloader *preloader;
- int i;
-
- preloader = requested_preloader (self);
- if ((preloader != NULL)
- && (preloader->file_data != NULL)
- && ! preloader->error
- && ! preloader->loaded)
- {
- i = self->priv->requested;
- }
- else {
- int n = 0;
-
- if (self->priv->current == -1)
- i = 0;
- else
- i = (self->priv->current + 1) % self->priv->n_preloaders;
-
- for (i = 0; n < self->priv->n_preloaders; i = (i + 1) % self->priv->n_preloaders) {
- preloader = self->priv->loader[i];
-
- if ((preloader != NULL)
- && (preloader->file_data != NULL)
- && ! preloader->error
- && ! preloader->loaded)
- {
- break;
- }
-
- n++;
- }
-
- if (n >= self->priv->n_preloaders) {
- self->priv->current = -1;
-#if DEBUG_PRELOADER
- debug (DEBUG_INFO, "done");
-#endif
- return;
- }
- }
-
- self->priv->current = i;
- preloader = current_preloader (self);
-
-#if DEBUG_PRELOADER
- {
- char *uri;
-
- uri = g_file_get_uri (preloader->file_data->file);
- debug (DEBUG_INFO, "load %s [size: %d]", uri, preloader->requested_size);
- g_free (uri);
- }
-#endif
-
- gth_image_loader_load_at_size (preloader->loader, preloader->requested_size);
-}
-
-
-void
-gth_image_preloader_stop (GthImagePreloader *self,
- DataFunc done_func,
- gpointer done_func_data)
-{
- Preloader *preloader;
-
- preloader = current_preloader (self);
-
- if (preloader == NULL) {
-#if DEBUG_PRELOADER
- debug (DEBUG_INFO, "stopped");
-#endif
- call_when_idle (done_func, done_func_data);
- return;
- }
-
- self->priv->current = -1;
- gth_image_loader_cancel (preloader->loader, done_func, done_func_data);
+ return (preloader != NULL) ? preloader->file_data : NULL;
}
diff --git a/gthumb/gth-image-preloader.h b/gthumb/gth-image-preloader.h
index a5dc3cf..46fdbff 100644
--- a/gthumb/gth-image-preloader.h
+++ b/gthumb/gth-image-preloader.h
@@ -54,25 +54,24 @@ struct _GthImagePreloaderClass {
/*< signals >*/
- void (* requested_ready) (GthImagePreloader *preloader,
- GthFileData *requested,
- GthImageLoader *image_loader,
- GError *error);
+ void (* requested_ready) (GthImagePreloader *preloader,
+ GthFileData *requested,
+ GdkPixbufAnimation *animation,
+ int original_width,
+ int original_height,
+ GError *error);
};
GType gth_image_preloader_get_type (void) G_GNUC_CONST;
GthImagePreloader * gth_image_preloader_new (GthLoadPolicy load_policy,
int max_preloaders);
+void gth_image_prelaoder_set_load_policy (GthImagePreloader *self,
+ GthLoadPolicy policy);
void gth_image_preloader_load (GthImagePreloader *self,
GthFileData *requested,
int requested_size,
...);
-void gth_image_prelaoder_set_load_policy (GthImagePreloader *self,
- GthLoadPolicy policy);
-void gth_image_preloader_stop (GthImagePreloader *self,
- DataFunc done_func,
- gpointer done_func_data);
GthImageLoader * gth_image_preloader_get_loader (GthImagePreloader *self,
GthFileData *file_data);
GthFileData * gth_image_preloader_get_requested (GthImagePreloader *self);
diff --git a/gthumb/gth-main.c b/gthumb/gth-main.c
index 7457c6c..e47aa8c 100644
--- a/gthumb/gth-main.c
+++ b/gthumb/gth-main.c
@@ -494,6 +494,8 @@ gth_main_get_metadata_attributes (const char *mask)
GList *scan;
char **values;
+ g_static_mutex_lock (&metadata_info_mutex);
+
if (! Main->priv->metadata_info_sorted) {
g_ptr_array_sort (Main->priv->metadata_info, metadata_info_sort_func);
Main->priv->metadata_info_sorted = TRUE;
@@ -510,6 +512,8 @@ gth_main_get_metadata_attributes (const char *mask)
}
list = g_list_reverse (list);
+ g_static_mutex_unlock (&metadata_info_mutex);
+
values = g_new (char *, n + 1);
for (i = 0, scan = list; scan; i++, scan = scan->next)
values[i] = g_strdup (scan->data);
@@ -598,10 +602,24 @@ gth_main_get_metadata_info (const char *id)
}
-GPtrArray *
+GList *
gth_main_get_all_metadata_info (void)
{
- return Main->priv->metadata_info;
+ GList *list = NULL;
+ int i;
+
+ g_static_mutex_lock (&metadata_info_mutex);
+
+ for (i = 0; i < Main->priv->metadata_info->len; i++) {
+ GthMetadataInfo *metadata_info = g_ptr_array_index (Main->priv->metadata_info, i);
+
+ list = g_list_prepend (list, metadata_info);
+ }
+ list = g_list_reverse (list);
+
+ g_static_mutex_unlock (&metadata_info_mutex);
+
+ return list;
}
diff --git a/gthumb/gth-main.h b/gthumb/gth-main.h
index 89c09d0..f428755 100644
--- a/gthumb/gth-main.h
+++ b/gthumb/gth-main.h
@@ -88,7 +88,7 @@ GthMetadataProvider * gth_main_get_metadata_writer (const char
const char *mime_type);
GthMetadataCategory * gth_main_get_metadata_category (const char *id);
GthMetadataInfo * gth_main_get_metadata_info (const char *id);
-GPtrArray * gth_main_get_all_metadata_info (void);
+GList * gth_main_get_all_metadata_info (void);
void gth_main_register_sort_type (GthFileDataSort *sort_type);
GthFileDataSort * gth_main_get_sort_type (const char *name);
GList * gth_main_get_all_sort_types (void);
diff --git a/gthumb/gth-marshal.list b/gthumb/gth-marshal.list
index b83cc20..3ab5c7d 100644
--- a/gthumb/gth-marshal.list
+++ b/gthumb/gth-marshal.list
@@ -4,7 +4,7 @@ VOID:INT, INT
VOID:OBJECT, BOOLEAN
VOID:OBJECT, BOXED, ENUM
VOID:OBJECT, OBJECT
-VOID:OBJECT, OBJECT, POINTER
+VOID:OBJECT, OBJECT, INT, INT, POINTER
VOID:OBJECT, POINTER
VOID:OBJECT, STRING
VOID:OBJECT, UINT
diff --git a/gthumb/gth-overwrite-dialog.c b/gthumb/gth-overwrite-dialog.c
index 4ed5f98..9160c82 100644
--- a/gthumb/gth-overwrite-dialog.c
+++ b/gthumb/gth-overwrite-dialog.c
@@ -118,22 +118,34 @@ gth_overwrite_dialog_get_type (void)
static void
-image_loader_ready_cb (GthImageLoader *image_loader,
- GError *error,
- gpointer user_data)
+image_loader_ready_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
{
GthOverwriteDialog *self = user_data;
- GtkWidget *viewer;
-
- if (error != NULL)
+ GError *error;
+ GdkPixbuf *pixbuf;
+ GtkWidget *viewer;
+
+ if (! gth_image_loader_load_image_finish (GTH_IMAGE_LOADER (source_object),
+ result,
+ NULL,
+ NULL,
+ &pixbuf,
+ NULL,
+ NULL,
+ &error))
+ {
return;
+ }
- if (image_loader == self->priv->old_image_loader)
+ if (GTH_IMAGE_LOADER (source_object) == self->priv->old_image_loader)
viewer = self->priv->old_image_viewer;
else
viewer = self->priv->new_image_viewer;
+ gth_image_viewer_set_pixbuf (GTH_IMAGE_VIEWER (viewer), pixbuf, -1, -1);
- gth_image_viewer_set_pixbuf (GTH_IMAGE_VIEWER (viewer), gth_image_loader_get_pixbuf (image_loader), -1, -1);
+ g_object_unref (pixbuf);
}
@@ -181,8 +193,13 @@ info_ready_cb (GList *files,
gtk_widget_show (_gtk_builder_get_widget (self->priv->builder, "new_filename_label"));
gtk_widget_show (_gtk_builder_get_widget (self->priv->builder, "new_size_label"));
gtk_widget_show (_gtk_builder_get_widget (self->priv->builder, "new_modified_label"));
- gth_image_loader_set_file_data (self->priv->new_image_loader, self->priv->source_data);
- gth_image_loader_load_at_size (GTH_IMAGE_LOADER (self->priv->new_image_loader), PREVIEW_SIZE);
+
+ gth_image_loader_load (GTH_IMAGE_LOADER (self->priv->new_image_loader),
+ self->priv->source_data,
+ PREVIEW_SIZE,
+ NULL, /* FIXME: make this cancellable */
+ image_loader_ready_cb,
+ self);
}
else if (self->priv->source_pixbuf != NULL) {
gtk_widget_hide (_gtk_builder_get_widget (self->priv->builder, "new_filename_label"));
@@ -219,8 +236,13 @@ info_ready_cb (GList *files,
gth_image_viewer_set_pixbuf (GTH_IMAGE_VIEWER (self->priv->old_image_viewer), pixbuf, -1, -1);
g_object_unref (pixbuf);
}
- gth_image_loader_set_file_data (self->priv->old_image_loader, self->priv->destination_data);
- gth_image_loader_load_at_size (GTH_IMAGE_LOADER (self->priv->old_image_loader), PREVIEW_SIZE);
+
+ gth_image_loader_load (GTH_IMAGE_LOADER (self->priv->old_image_loader),
+ self->priv->destination_data,
+ PREVIEW_SIZE,
+ NULL, /* FIXME: make this cancellable */
+ image_loader_ready_cb,
+ self);
}
@@ -311,17 +333,8 @@ gth_overwrite_dialog_construct (GthOverwriteDialog *self,
G_CALLBACK (overwrite_rename_radiobutton_toggled_cb),
self);
- self->priv->old_image_loader = gth_image_loader_new (FALSE);
- g_signal_connect (self->priv->old_image_loader,
- "ready",
- G_CALLBACK (image_loader_ready_cb),
- self);
-
- self->priv->new_image_loader = gth_image_loader_new (FALSE);
- g_signal_connect (self->priv->new_image_loader,
- "ready",
- G_CALLBACK (image_loader_ready_cb),
- self);
+ self->priv->old_image_loader = gth_image_loader_new (NULL, NULL);
+ self->priv->new_image_loader = gth_image_loader_new (NULL, NULL);
files = NULL;
if (self->priv->source != NULL)
diff --git a/gthumb/gth-thumb-loader.c b/gthumb/gth-thumb-loader.c
index b78fec4..1f2efb5 100644
--- a/gthumb/gth-thumb-loader.c
+++ b/gthumb/gth-thumb-loader.c
@@ -45,15 +45,11 @@
#define THUMBNAIL_DIR_PERMISSIONS 0700
#define MAX_THUMBNAILER_LIFETIME 2000 /* kill the thumbnailer after this amount of time*/
-struct _GthThumbLoaderPrivateData
+struct _GthThumbLoaderPrivate
{
- GthFileData *file_data;
GthImageLoader *iloader;
- GdkPixbuf *pixbuf; /* Contains the final (scaled
- * if necessary) image when
- * done. */
+ GthImageLoader *tloader;
guint use_cache : 1;
- guint loading_from_cache : 1;
guint save_thumbnails : 1;
int requested_size;
int cache_max_size;
@@ -65,10 +61,6 @@ struct _GthThumbLoaderPrivateData
thumb_size;
GnomeDesktopThumbnailFactory
*thumb_factory;
- char *thumbnailer_tmpfile;
- GPid thumbnailer_pid;
- guint thumbnailer_watch;
- guint thumbnailer_timeout;
};
@@ -79,7 +71,6 @@ enum {
static GObjectClass *parent_class = NULL;
-static guint gth_thumb_loader_signals[LAST_SIGNAL] = { 0 };
static void
@@ -87,21 +78,10 @@ gth_thumb_loader_finalize (GObject *object)
{
GthThumbLoader *self;
- g_return_if_fail (object != NULL);
- g_return_if_fail (GTH_IS_THUMB_LOADER (object));
-
self = GTH_THUMB_LOADER (object);
+ _g_object_unref (self->priv->iloader);
+ _g_object_unref (self->priv->tloader);
- 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);
- g_free (self->priv);
- self->priv = NULL;
- }
-
- /* Chain up */
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@@ -109,34 +89,22 @@ gth_thumb_loader_finalize (GObject *object)
static void
gth_thumb_loader_class_init (GthThumbLoaderClass *class)
{
- GObjectClass *object_class = G_OBJECT_CLASS (class);
+ GObjectClass *object_class;
parent_class = g_type_class_peek_parent (class);
+ g_type_class_add_private (class, sizeof (GthThumbLoaderPrivate));
+ object_class = G_OBJECT_CLASS (class);
object_class->finalize = gth_thumb_loader_finalize;
-
- gth_thumb_loader_signals[READY] =
- g_signal_new ("ready",
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GthThumbLoaderClass, ready),
- NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE,
- 1,
- G_TYPE_POINTER);
}
static void
gth_thumb_loader_init (GthThumbLoader *self)
{
- self->priv = g_new0 (GthThumbLoaderPrivateData, 1);
- self->priv->file_data = NULL;
- self->priv->pixbuf = NULL;
+ self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GTH_TYPE_THUMB_LOADER, GthThumbLoaderPrivate);
self->priv->use_cache = TRUE;
self->priv->save_thumbnails = TRUE;
- self->priv->loading_from_cache = FALSE;
self->priv->max_file_size = 0;
}
@@ -169,54 +137,281 @@ gth_thumb_loader_get_type (void)
}
-static int
-normalize_thumb (int *width,
- int *height,
- int max_size,
- int cache_max_size)
+static GdkPixbufAnimation *
+load_thumbnail (GthFileData *file_data,
+ int requested_size,
+ int *original_width,
+ int *original_height,
+ gpointer user_data,
+ GCancellable *cancellable,
+ GError **error)
{
- gboolean modified;
- float max_w = max_size;
- float max_h = max_size;
- float w = *width;
- float h = *height;
- float factor;
- int new_width, new_height;
+ GthThumbLoader *self = user_data;
+ GdkPixbuf *pixbuf = NULL;
+ GdkPixbufAnimation *animation;
+ char *uri;
- if (max_size > cache_max_size) {
- if ((*width < cache_max_size - 1) && (*height < cache_max_size - 1))
- return FALSE;
+ if (original_width != NULL)
+ *original_width = -1;
+
+ if (original_height != NULL)
+ *original_height = -1;
+
+ animation = NULL;
+ uri = g_file_get_uri (file_data->file);
+ pixbuf = gnome_desktop_thumbnail_factory_generate_no_script (self->priv->thumb_factory,
+ uri,
+ gth_file_data_get_mime_type (file_data));
+ if (pixbuf == NULL) {
+ PixbufLoader thumbnailer;
+
+ thumbnailer = gth_main_get_pixbuf_loader (gth_file_data_get_mime_type (file_data));
+ if (thumbnailer != NULL)
+ animation = thumbnailer (file_data,
+ self->priv->cache_max_size,
+ original_width,
+ original_height,
+ NULL,
+ cancellable,
+ error);
}
- else if ((*width < max_size - 1) && (*height < max_size - 1))
- return FALSE;
- factor = MIN (max_w / w, max_h / h);
- new_width = MAX ((int) (w * factor), 1);
- new_height = MAX ((int) (h * factor), 1);
+ if (pixbuf != NULL) {
+ g_clear_error (error);
+ animation = gdk_pixbuf_non_anim_new (pixbuf);
+ g_object_unref (pixbuf);
+ }
- modified = (new_width != *width) || (new_height != *height);
+ if (animation == NULL)
+ *error = g_error_new_literal (GTH_ERROR, 0, "Cannot generate the thumbnail");
- *width = new_width;
- *height = new_height;
+ g_free (uri);
- return modified;
+ return animation;
+}
+
+
+static void
+gth_thumb_loader_construct (GthThumbLoader *self,
+ int requested_size)
+{
+ gth_thumb_loader_set_requested_size (self, requested_size);
+ self->priv->tloader = gth_image_loader_new (load_thumbnail, self);
+ self->priv->iloader = gth_image_loader_new (NULL, NULL);
+}
+
+
+GthThumbLoader *
+gth_thumb_loader_new (int requested_size)
+{
+ GthThumbLoader *self;
+
+ self = g_object_new (GTH_TYPE_THUMB_LOADER, NULL);
+ gth_thumb_loader_construct (self, requested_size);
+
+ return self;
+}
+
+
+void
+gth_thumb_loader_set_loader_func (GthThumbLoader *self,
+ PixbufLoader loader_func)
+{
+ gth_image_loader_set_loader_func (self->priv->iloader,
+ (loader_func != NULL) ? loader_func : load_thumbnail,
+ self);
+}
+
+
+void
+gth_thumb_loader_set_requested_size (GthThumbLoader *self,
+ int size)
+{
+ if (self->priv->thumb_factory != NULL) {
+ g_object_unref (self->priv->thumb_factory);
+ self->priv->thumb_factory = NULL;
+ }
+
+ self->priv->requested_size = size;
+ if (self->priv->requested_size <= THUMBNAIL_NORMAL_SIZE) {
+ self->priv->cache_max_size = THUMBNAIL_NORMAL_SIZE;
+ self->priv->thumb_size = GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL;
+ }
+ else {
+ self->priv->cache_max_size = THUMBNAIL_LARGE_SIZE;
+ self->priv->thumb_size = GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE;
+ }
+ self->priv->thumb_factory = gnome_desktop_thumbnail_factory_new (self->priv->thumb_size);
+}
+
+
+int
+gth_thumb_loader_get_requested_size (GthThumbLoader *self)
+{
+ return self->priv->requested_size;
+}
+
+
+void
+gth_thumb_loader_use_cache (GthThumbLoader *self,
+ gboolean use)
+{
+ g_return_if_fail (self != NULL);
+ self->priv->use_cache = use;
+}
+
+
+void
+gth_thumb_loader_save_thumbnails (GthThumbLoader *self,
+ gboolean save)
+{
+ g_return_if_fail (self != NULL);
+ self->priv->save_thumbnails = save;
+}
+
+
+void
+gth_thumb_loader_set_max_file_size (GthThumbLoader *self,
+ goffset size)
+{
+ g_return_if_fail (self != NULL);
+ self->priv->max_file_size = size;
+}
+
+
+typedef struct {
+ GthThumbLoader *thumb_loader;
+ GthFileData *file_data;
+ int requested_size;
+ GSimpleAsyncResult *simple;
+ GCancellable *cancellable;
+ char *thumbnailer_tmpfile;
+ GPid thumbnailer_pid;
+ guint thumbnailer_watch;
+ guint thumbnailer_timeout;
+} LoadData;
+
+
+static LoadData *
+load_data_new (GthFileData *file_data,
+ int requested_size)
+{
+ LoadData *load_data;
+
+ load_data = g_new0 (LoadData, 1);
+ load_data->file_data = g_object_ref (file_data);
+ load_data->requested_size = requested_size;
+
+ return load_data;
+}
+
+
+static void
+load_data_unref (LoadData *load_data)
+{
+ g_object_unref (load_data->thumb_loader);
+ g_object_unref (load_data->file_data);
+ _g_object_unref (load_data->cancellable);
+ g_free (load_data);
+}
+
+
+typedef struct {
+ GthFileData *file_data;
+ GdkPixbuf *pixbuf;
+} LoadResult;
+
+
+static void
+load_result_unref (LoadResult *load_result)
+{
+ g_object_unref (load_result->file_data);
+ _g_object_unref (load_result->pixbuf);
+ g_free (load_result);
+}
+
+
+static void
+original_image_ready_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data);
+
+
+static void
+cache_image_ready_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ LoadData *load_data = user_data;
+ GthThumbLoader *self = load_data->thumb_loader;
+ GdkPixbuf *pixbuf;
+ int width;
+ int height;
+ gboolean modified;
+ LoadResult *load_result;
+
+ if (! gth_image_loader_load_image_finish (GTH_IMAGE_LOADER (source_object),
+ res,
+ NULL,
+ NULL,
+ &pixbuf,
+ NULL,
+ NULL,
+ NULL))
+ {
+ /* error loading the thumbnail from the cache, try to generate
+ * the thumbnail loading the original image. */
+
+ gth_image_loader_load (self->priv->tloader,
+ load_data->file_data,
+ load_data->requested_size,
+ load_data->cancellable,
+ original_image_ready_cb,
+ load_data);
+
+ return;
+ }
+
+ /* Thumbnail correctly loaded from the cache. Scale if the user wants
+ * a different size. */
+
+ width = gdk_pixbuf_get_width (pixbuf);
+ height = gdk_pixbuf_get_height (pixbuf);
+ modified = scale_keeping_ratio (&width,
+ &height,
+ self->priv->requested_size,
+ self->priv->requested_size,
+ FALSE);
+ if (modified) {
+ GdkPixbuf *tmp = pixbuf;
+ pixbuf = gdk_pixbuf_scale_simple (tmp, width, height, GDK_INTERP_BILINEAR);
+ g_object_unref (tmp);
+ }
+
+ load_result = g_new0 (LoadResult, 1);
+ load_result->file_data = g_object_ref (load_data->file_data);
+ load_result->pixbuf = pixbuf;
+ g_simple_async_result_set_op_res_gpointer (load_data->simple, load_result, (GDestroyNotify) load_result_unref);
+ g_simple_async_result_complete_in_idle (load_data->simple);
}
static gboolean
-_gth_thumb_loader_save_to_cache (GthThumbLoader *self)
+_gth_thumb_loader_save_to_cache (GthThumbLoader *self,
+ GthFileData *file_data,
+ GdkPixbuf *pixbuf)
{
char *uri;
char *cache_path;
GFile *cache_file;
GFile *cache_dir;
- if ((self == NULL) || (self->priv->pixbuf == NULL))
+ if ((self == NULL) || (pixbuf == NULL))
return FALSE;
- uri = g_file_get_uri (self->priv->file_data->file);
+ uri = g_file_get_uri (file_data->file);
- if (g_file_is_native (self->priv->file_data->file)) {
+ if (g_file_is_native (file_data->file)) {
char *cache_base_uri;
/* Do not save thumbnails from the user's thumbnail directory,
@@ -243,11 +438,11 @@ _gth_thumb_loader_save_to_cache (GthThumbLoader *self)
if (_g_directory_make (cache_dir, THUMBNAIL_DIR_PERMISSIONS, NULL)) {
char *uri;
- uri = g_file_get_uri (self->priv->file_data->file);
+ uri = g_file_get_uri (file_data->file);
gnome_desktop_thumbnail_factory_save_thumbnail (self->priv->thumb_factory,
- self->priv->pixbuf,
+ pixbuf,
uri,
- gth_file_data_get_mtime (self->priv->file_data));
+ gth_file_data_get_mtime (file_data));
g_free (uri);
}
@@ -260,44 +455,59 @@ _gth_thumb_loader_save_to_cache (GthThumbLoader *self)
}
-static void
-image_loader_loaded (GthImageLoader *iloader,
- GdkPixbuf *pixbuf,
- gpointer data)
+static int
+normalize_thumb (int *width,
+ int *height,
+ int max_size,
+ int cache_max_size)
{
- GthThumbLoader *self = data;
- int width, height;
- gboolean modified;
+ gboolean modified;
+ float max_w = max_size;
+ float max_h = max_size;
+ float w = *width;
+ float h = *height;
+ float factor;
+ int new_width, new_height;
- if (self->priv->pixbuf != NULL) {
- g_object_unref (self->priv->pixbuf);
- self->priv->pixbuf = NULL;
+ if (max_size > cache_max_size) {
+ if ((*width < cache_max_size - 1) && (*height < cache_max_size - 1))
+ return FALSE;
}
+ else if ((*width < max_size - 1) && (*height < max_size - 1))
+ return FALSE;
- if (pixbuf == NULL) {
- char *uri;
+ factor = MIN (max_w / w, max_h / h);
+ new_width = MAX ((int) (w * factor), 1);
+ new_height = MAX ((int) (h * factor), 1);
- uri = g_file_get_uri (self->priv->file_data->file);
- gnome_desktop_thumbnail_factory_create_failed_thumbnail (self->priv->thumb_factory,
- uri,
- gth_file_data_get_mtime (self->priv->file_data));
- g_signal_emit (G_OBJECT (self), gth_thumb_loader_signals[READY], 0, NULL);
- g_free (uri);
+ modified = (new_width != *width) || (new_height != *height);
+
+ *width = new_width;
+ *height = new_height;
+
+ return modified;
+}
- return;
- }
- g_object_ref (pixbuf);
- self->priv->pixbuf = pixbuf;
+static void
+original_image_loaded_correctly (GthThumbLoader *self,
+ LoadData *load_data,
+ GdkPixbuf *pixbuf)
+{
+ int width;
+ int height;
+ gboolean modified;
+ LoadResult *load_result;
width = gdk_pixbuf_get_width (pixbuf);
height = gdk_pixbuf_get_height (pixbuf);
- if (self->priv->use_cache) {
- /* Thumbnails are always saved with the same size, then
- * scaled if necessary. */
+ if (self->priv->save_thumbnails) {
+ gboolean modified;
- /* Check whether to scale. */
+ /* Thumbnails are always saved in the cache max size, then
+ * scaled a second time if the user requested a different
+ * size. */
modified = scale_keeping_ratio (&width,
&height,
@@ -305,91 +515,67 @@ image_loader_loaded (GthImageLoader *iloader,
self->priv->cache_max_size,
FALSE);
if (modified) {
- g_object_unref (self->priv->pixbuf);
- self->priv->pixbuf = gdk_pixbuf_scale_simple (pixbuf, width, height, GDK_INTERP_BILINEAR);
+ GdkPixbuf *tmp = pixbuf;
+ pixbuf = _gdk_pixbuf_scale_simple_safe (tmp, width, height, GDK_INTERP_BILINEAR);
+ g_object_unref (tmp);
}
- /* Save the thumbnail if necessary. */
-
- if (self->priv->save_thumbnails && ! self->priv->loading_from_cache)
- _gth_thumb_loader_save_to_cache (self);
+ _gth_thumb_loader_save_to_cache (self, load_data->file_data, pixbuf);
+ }
- /* Scale if the user wants a different size. */
+ /* Scale if the user wants a different size. */
- modified = normalize_thumb (&width,
- &height,
- self->priv->requested_size,
- self->priv->cache_max_size);
- if (modified) {
- pixbuf = self->priv->pixbuf;
- self->priv->pixbuf = gdk_pixbuf_scale_simple (pixbuf, width, height, GDK_INTERP_BILINEAR);
- g_object_unref (pixbuf);
- }
- }
- else {
- modified = scale_keeping_ratio (&width,
- &height,
- self->priv->requested_size,
- self->priv->requested_size,
- FALSE);
- if (modified) {
- g_object_unref (self->priv->pixbuf);
- self->priv->pixbuf = gdk_pixbuf_scale_simple (pixbuf, width, height, GDK_INTERP_BILINEAR);
- }
+ modified = normalize_thumb (&width,
+ &height,
+ self->priv->requested_size,
+ self->priv->cache_max_size);
+ if (modified) {
+ GdkPixbuf *tmp = pixbuf;
+ pixbuf = gdk_pixbuf_scale_simple (tmp, width, height, GDK_INTERP_BILINEAR);
+ g_object_unref (tmp);
}
- g_signal_emit (G_OBJECT (self), gth_thumb_loader_signals[READY], 0, NULL);
+ load_result = g_new0 (LoadResult, 1);
+ load_result->file_data = g_object_ref (load_data->file_data);
+ load_result->pixbuf = g_object_ref (pixbuf);
+ g_simple_async_result_set_op_res_gpointer (load_data->simple, load_result, (GDestroyNotify) load_result_unref);
+ g_simple_async_result_complete_in_idle (load_data->simple);
}
static void
-image_loader_error (GthImageLoader *iloader,
- GError *error,
- gpointer data)
+failed_to_load_original_image (GthThumbLoader *self,
+ LoadData *load_data)
{
- GthThumbLoader *self = data;
-
- g_return_if_fail (error != NULL);
+ char *uri;
+ GError *error = NULL;
- if (! self->priv->loading_from_cache) {
- char *uri;
+ uri = g_file_get_uri (load_data->file_data->file);
+ gnome_desktop_thumbnail_factory_create_failed_thumbnail (self->priv->thumb_factory,
+ uri,
+ gth_file_data_get_mtime (load_data->file_data));
- if (self->priv->pixbuf != NULL) {
- g_object_unref (self->priv->pixbuf);
- self->priv->pixbuf = NULL;
- }
+ error = g_error_new_literal (GTH_ERROR, 0, "failed to generate the thumbnail");
+ g_simple_async_result_set_from_error (load_data->simple, error);
+ g_simple_async_result_complete_in_idle (load_data->simple);
- uri = g_file_get_uri (self->priv->file_data->file);
- gnome_desktop_thumbnail_factory_create_failed_thumbnail (self->priv->thumb_factory,
- uri,
- gth_file_data_get_mtime (self->priv->file_data));
- g_free (uri);
- g_signal_emit (G_OBJECT (self), gth_thumb_loader_signals[READY], 0, error);
- }
- else {
- /* ! loading_from_cache : try to load the original image if
- * the cache version failed. */
-
- g_error_free (error);
- self->priv->loading_from_cache = FALSE;
- gth_image_loader_set_file_data (self->priv->iloader, self->priv->file_data);
- gth_image_loader_load (self->priv->iloader);
- }
+ g_error_free (error);
+ g_free (uri);
}
static gboolean
-kill_thumbnailer_cb (gpointer data)
+kill_thumbnailer_cb (gpointer user_data)
{
- GthThumbLoader *self = data;
+ LoadData *load_data = user_data;
- if (self->priv->thumbnailer_timeout != 0) {
- g_source_remove (self->priv->thumbnailer_timeout);
- self->priv->thumbnailer_timeout = 0;
+ if (load_data->thumbnailer_timeout != 0) {
+ g_source_remove (load_data->thumbnailer_timeout);
+ load_data->thumbnailer_timeout = 0;
}
- if (self->priv->thumbnailer_pid != 0)
- kill (self->priv->thumbnailer_pid, SIGTERM);
+ if (load_data->thumbnailer_pid != 0)
+ kill (load_data->thumbnailer_pid, SIGTERM);
return FALSE;
}
@@ -398,387 +584,197 @@ kill_thumbnailer_cb (gpointer data)
static void
watch_thumbnailer_cb (GPid pid,
int status,
- gpointer data)
+ gpointer user_data)
{
- GthThumbLoader *self = data;
- GdkPixbuf *pixbuf = NULL;
+ LoadData *load_data = user_data;
+ GthThumbLoader *self = load_data->thumb_loader;
+ GdkPixbuf *pixbuf;
- if (self->priv->thumbnailer_timeout != 0) {
- g_source_remove (self->priv->thumbnailer_timeout);
- self->priv->thumbnailer_timeout = 0;
+ if (load_data->thumbnailer_timeout != 0) {
+ g_source_remove (load_data->thumbnailer_timeout);
+ load_data->thumbnailer_timeout = 0;
}
g_spawn_close_pid (pid);
- self->priv->thumbnailer_pid = 0;
- self->priv->thumbnailer_watch = 0;
+ load_data->thumbnailer_pid = 0;
+ load_data->thumbnailer_watch = 0;
+ pixbuf = NULL;
if (status == 0)
pixbuf = gnome_desktop_thumbnail_factory_load_from_tempfile (self->priv->thumb_factory,
- &self->priv->thumbnailer_tmpfile);
+ &load_data->thumbnailer_tmpfile);
if (pixbuf != NULL) {
- image_loader_loaded (NULL, pixbuf, data);
+ original_image_loaded_correctly (self, load_data, pixbuf);
g_object_unref (pixbuf);
}
- else {
- GError *error;
-
- error = g_error_new_literal (GTH_ERROR, 0, "Cannot generate the thumbnail");
- image_loader_error (NULL, error, self);
- }
+ else
+ failed_to_load_original_image (self, load_data);
}
static void
-image_loader_ready_cb (GthImageLoader *iloader,
- GError *error,
- gpointer data)
+original_image_ready_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
{
- GthThumbLoader *self = data;
- char *uri;
-
- if (error == NULL) {
- image_loader_loaded (iloader, gth_image_loader_get_pixbuf (self->priv->iloader), data);
- return;
- }
-
- /* error != NULL */
-
- if (self->priv->loading_from_cache) {
- image_loader_error (iloader, error, data);
- return;
- }
-
- /* not loading from the cache: try with the system thumbnailer */
-
- g_clear_error (&error);
- 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,
- &error))
+ LoadData *load_data = user_data;
+ GthThumbLoader *self = load_data->thumb_loader;
+ GdkPixbuf *pixbuf;
+ GError *error = NULL;
+
+ if (! gth_image_loader_load_image_finish (GTH_IMAGE_LOADER (source_object),
+ res,
+ NULL,
+ NULL,
+ &pixbuf,
+ NULL,
+ NULL,
+ &error))
{
- 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
- image_loader_error (iloader, error, data);
-
- g_free (uri);
-}
-
-
-static GdkPixbufAnimation *
-thumb_loader (GthFileData *file_data,
- int requested_size,
- int *original_width,
- int *original_height,
- gpointer data,
- GCancellable *cancellable,
- GError **error)
-{
- GthThumbLoader *self = data;
- GdkPixbuf *pixbuf = NULL;
- GdkPixbufAnimation *animation;
-
- if (original_width != NULL)
- *original_width = -1;
+ /* error loading the original image, try with the system
+ * thumbnailer */
- if (original_height != NULL)
- *original_height = -1;
-
- animation = NULL;
- if (! self->priv->loading_from_cache) {
char *uri;
- uri = g_file_get_uri (file_data->file);
- pixbuf = gnome_desktop_thumbnail_factory_generate_no_script (self->priv->thumb_factory,
- uri,
- gth_file_data_get_mime_type (file_data));
- if (pixbuf == NULL) {
- PixbufLoader thumbnailer;
-
- thumbnailer = gth_main_get_pixbuf_loader (gth_file_data_get_mime_type (file_data));
- if (thumbnailer != NULL)
- animation = thumbnailer (file_data,
- self->priv->cache_max_size,
- original_width,
- original_height,
- NULL,
- cancellable,
- error);
+ g_clear_error (&error);
+
+ uri = g_file_get_uri (load_data->file_data->file);
+ if (gnome_desktop_thumbnail_factory_generate_from_script (self->priv->thumb_factory,
+ uri,
+ gth_file_data_get_mime_type (load_data->file_data),
+ &load_data->thumbnailer_pid,
+ &load_data->thumbnailer_tmpfile,
+ &error))
+ {
+ load_data->thumbnailer_watch = g_child_watch_add (load_data->thumbnailer_pid,
+ watch_thumbnailer_cb,
+ load_data);
+ load_data->thumbnailer_timeout = g_timeout_add (MAX_THUMBNAILER_LIFETIME,
+ kill_thumbnailer_cb,
+ load_data);
}
+ else
+ failed_to_load_original_image (self, load_data);
g_free (uri);
- }
- else
- pixbuf = gth_pixbuf_new_from_file (file_data,
- -1,
- original_width,
- original_height,
- FALSE,
- cancellable,
- error);
-
- if (pixbuf != NULL) {
- g_clear_error (error);
- animation = gdk_pixbuf_non_anim_new (pixbuf);
- g_object_unref (pixbuf);
- }
-
- if (animation == NULL)
- *error = g_error_new_literal (GTH_ERROR, 0, "Cannot generate the thumbnail");
-
- return animation;
-}
-
-
-static void
-gth_thumb_loader_construct (GthThumbLoader *self,
- int size)
-{
- gth_thumb_loader_set_requested_size (self, size);
-
- self->priv->iloader = gth_image_loader_new (FALSE);
- g_signal_connect (G_OBJECT (self->priv->iloader),
- "ready",
- G_CALLBACK (image_loader_ready_cb),
- self);
- gth_image_loader_set_loader (self->priv->iloader, thumb_loader, self);
-}
-
-
-GthThumbLoader *
-gth_thumb_loader_new (int size)
-{
- GthThumbLoader *self;
-
- self = g_object_new (GTH_TYPE_THUMB_LOADER, NULL);
- gth_thumb_loader_construct (self, size);
-
- return self;
-}
-
-void
-gth_thumb_loader_set_loader (GthThumbLoader *self,
- PixbufLoader loader)
-{
- if (loader != NULL)
- gth_image_loader_set_loader (self->priv->iloader, loader, self);
- else
- gth_image_loader_set_loader (self->priv->iloader, thumb_loader, self);
-}
-
-
-void
-gth_thumb_loader_set_requested_size (GthThumbLoader *self,
- int size)
-{
- if (self->priv->thumb_factory != NULL) {
- g_object_unref (self->priv->thumb_factory);
- self->priv->thumb_factory = NULL;
- }
-
- self->priv->requested_size = size;
- if (self->priv->requested_size <= THUMBNAIL_NORMAL_SIZE) {
- self->priv->cache_max_size = THUMBNAIL_NORMAL_SIZE;
- self->priv->thumb_size = GNOME_DESKTOP_THUMBNAIL_SIZE_NORMAL;
- }
- else {
- self->priv->cache_max_size = THUMBNAIL_LARGE_SIZE;
- self->priv->thumb_size = GNOME_DESKTOP_THUMBNAIL_SIZE_LARGE;
+ return;
}
- self->priv->thumb_factory = gnome_desktop_thumbnail_factory_new (self->priv->thumb_size);
-}
-
-
-int
-gth_thumb_loader_get_requested_size (GthThumbLoader *self)
-{
- return self->priv->requested_size;
-}
-
-
-void
-gth_thumb_loader_use_cache (GthThumbLoader *self,
- gboolean use)
-{
- g_return_if_fail (self != NULL);
- self->priv->use_cache = use;
-}
-
-
-void
-gth_thumb_loader_save_thumbnails (GthThumbLoader *self,
- gboolean save)
-{
- g_return_if_fail (self != NULL);
- self->priv->save_thumbnails = save;
-}
-
-
-void
-gth_thumb_loader_set_max_file_size (GthThumbLoader *self,
- goffset size)
-{
- g_return_if_fail (self != NULL);
- self->priv->max_file_size = size;
-}
-
-
-void
-gth_thumb_loader_set_file (GthThumbLoader *self,
- GthFileData *file_data)
-{
- g_return_if_fail (self != NULL);
-
- _g_object_unref (self->priv->file_data);
- self->priv->file_data = NULL;
- if (file_data != NULL) {
- GFile *real_file = NULL;
- GError *error = NULL;
+ original_image_loaded_correctly (self, load_data, pixbuf);
- self->priv->file_data = gth_file_data_dup (file_data);
-
- real_file = _g_file_resolve_all_symlinks (self->priv->file_data->file, &error);
- if (real_file == NULL) {
- g_warning ("%s", error->message);
- g_clear_error (&error);
- return;
- }
-
- gth_file_data_set_file (self->priv->file_data, real_file);
-
- g_object_unref (real_file);
- }
-
- gth_image_loader_set_file_data (self->priv->iloader, self->priv->file_data);
+ g_object_unref (pixbuf);
}
void
-gth_thumb_loader_set_uri (GthThumbLoader *self,
- const char *uri,
- const char *mime_type)
+gth_thumb_loader_load (GthThumbLoader *self,
+ GthFileData *file_data,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- GFile *file;
- GthFileData *file_data;
+ GSimpleAsyncResult *simple;
+ char *cache_path;
+ LoadData *load_data;
- g_return_if_fail (self != NULL);
- g_return_if_fail (uri != NULL);
-
- file = g_file_new_for_uri (uri);
- file_data = gth_file_data_new (file, NULL);
- gth_file_data_update_info (file_data, NULL);
- gth_file_data_set_mime_type (file_data, mime_type);
-
- gth_thumb_loader_set_file (self, file_data);
-
- g_object_unref (file);
-}
-
-
-GdkPixbuf *
-gth_thumb_loader_get_pixbuf (GthThumbLoader *self)
-{
- g_return_val_if_fail (self != NULL, NULL);
- return self->priv->pixbuf;
-}
-
-
-static void
-gth_thumb_loader_load__step2 (GthThumbLoader *self)
-{
- char *cache_path = NULL;
+ simple = g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ gth_thumb_loader_load);
+ cache_path = NULL;
if (self->priv->use_cache) {
char *uri;
time_t mtime;
- uri = g_file_get_uri (self->priv->file_data->file);
- mtime = gth_file_data_get_mtime (self->priv->file_data);
+ uri = g_file_get_uri (file_data->file);
+ mtime = gth_file_data_get_mtime (file_data);
cache_path = gnome_desktop_thumbnail_factory_lookup (self->priv->thumb_factory, uri, mtime);
- if ((cache_path == NULL)
- && gnome_desktop_thumbnail_factory_has_valid_failed_thumbnail (self->priv->thumb_factory, uri, mtime))
- {
- g_signal_emit (G_OBJECT (self),
- gth_thumb_loader_signals[READY],
- 0,
- g_error_new_literal (GTH_ERROR, 0, "failed thumbnail"));
+
+ if ((cache_path == NULL) && gnome_desktop_thumbnail_factory_has_valid_failed_thumbnail (self->priv->thumb_factory, uri, mtime)) {
+ GError *error;
+
+ error = g_error_new_literal (GTH_ERROR, 0, "failed thumbnail");
+ g_simple_async_result_set_from_error (simple, error);
+ g_simple_async_result_complete_in_idle (simple);
+
+ g_error_free (error);
g_free (uri);
+
return;
}
g_free (uri);
}
- if (cache_path != NULL) {
- GFile *file;
- GthFileData *file_data;
+ load_data = load_data_new (file_data, self->priv->requested_size);
+ load_data->thumb_loader = g_object_ref (self);
+ load_data->cancellable = _g_object_ref (cancellable);
+ load_data->simple = simple;
- self->priv->loading_from_cache = TRUE;
-
- file = g_file_new_for_path (cache_path);
- file_data = gth_file_data_new (file, NULL);
- gth_file_data_set_mime_type (file_data, "image/png");
- gth_image_loader_set_file_data (self->priv->iloader, file_data);
-
- g_object_unref (file_data);
- g_object_unref (file);
+ if (cache_path != NULL) {
+ GFile *cache_file;
+ GthFileData *cache_file_data;
+
+ cache_file = g_file_new_for_path (cache_path);
+ cache_file_data = gth_file_data_new (cache_file, NULL);
+ gth_file_data_set_mime_type (cache_file_data, "image/png");
+ gth_image_loader_load (self->priv->iloader,
+ cache_file_data,
+ -1,
+ cancellable,
+ cache_image_ready_cb,
+ load_data);
+
+ g_object_unref (cache_file_data);
+ g_object_unref (cache_file);
g_free (cache_path);
}
- else {
- self->priv->loading_from_cache = FALSE;
- gth_image_loader_set_file_data (self->priv->iloader, self->priv->file_data);
+ else if ((self->priv->max_file_size > 0) && (g_file_info_get_size (file_data->info) > self->priv->max_file_size)) {
+ GError *error;
- /* Check file dimensions. */
+ load_data_unref (load_data);
- if ((self->priv->max_file_size > 0)
- && (g_file_info_get_size (self->priv->file_data->info) > self->priv->max_file_size))
- {
- _g_clear_object (&self->priv->pixbuf);
- g_signal_emit (G_OBJECT (self),
- gth_thumb_loader_signals[READY],
- 0,
- NULL);
- return;
- }
- }
+ error = g_error_new_literal (GTH_ERROR, 0, "file too big to generate the thumbnail");
+ g_simple_async_result_set_from_error (simple, error);
+ g_simple_async_result_complete_in_idle (simple);
- gth_image_loader_load (self->priv->iloader);
+ g_error_free (error);
+ }
+ else
+ gth_image_loader_load (self->priv->tloader,
+ file_data,
+ self->priv->requested_size,
+ cancellable,
+ original_image_ready_cb,
+ load_data);
}
-void
-gth_thumb_loader_load (GthThumbLoader *self)
+gboolean
+gth_thumb_loader_load_finish (GthThumbLoader *self,
+ GAsyncResult *result,
+ GthFileData **file_data,
+ GdkPixbuf **pixbuf,
+ GError **error)
{
- gth_thumb_loader_cancel (self, (DataFunc) gth_thumb_loader_load__step2, self);
-}
+ GSimpleAsyncResult *simple;
+ LoadResult *load_result;
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self), gth_thumb_loader_load), FALSE);
-void
-gth_thumb_loader_cancel (GthThumbLoader *self,
- DataFunc done_func,
- gpointer done_func_data)
-{
- g_return_if_fail (self->priv->iloader != NULL);
+ simple = G_SIMPLE_ASYNC_RESULT (result);
- if (self->priv->thumbnailer_watch != 0) {
- /* kill the thumbnailer script */
- g_source_remove (self->priv->thumbnailer_watch);
- self->priv->thumbnailer_watch = 0;
- kill_thumbnailer_cb (self);
- }
+ if (g_simple_async_result_propagate_error (simple, error))
+ return FALSE;
+
+ load_result = g_simple_async_result_get_op_res_gpointer (simple);
+ if (file_data != NULL)
+ *file_data = g_object_ref (load_result->file_data);
+ if (pixbuf != NULL)
+ *pixbuf = g_object_ref (load_result->pixbuf);
- gth_image_loader_cancel (self->priv->iloader, done_func, done_func_data);
+ return TRUE;
}
diff --git a/gthumb/gth-thumb-loader.h b/gthumb/gth-thumb-loader.h
index e92feb5..855cac6 100644
--- a/gthumb/gth-thumb-loader.h
+++ b/gthumb/gth-thumb-loader.h
@@ -37,49 +37,44 @@ G_BEGIN_DECLS
#define GTH_IS_THUMB_LOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTH_TYPE_THUMB_LOADER))
#define GTH_THUMB_LOADER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTH_TYPE_THUMB_LOADER, GthThumbLoaderClass))
-typedef struct _GthThumbLoader GthThumbLoader;
-typedef struct _GthThumbLoaderClass GthThumbLoaderClass;
-typedef struct _GthThumbLoaderPrivateData GthThumbLoaderPrivateData;
+typedef struct _GthThumbLoader GthThumbLoader;
+typedef struct _GthThumbLoaderClass GthThumbLoaderClass;
+typedef struct _GthThumbLoaderPrivate GthThumbLoaderPrivate;
struct _GthThumbLoader
{
GObject __parent;
- GthThumbLoaderPrivateData *priv;
+ GthThumbLoaderPrivate *priv;
};
struct _GthThumbLoaderClass
{
GObjectClass __parent_class;
-
- /*< signals >*/
-
- void (* ready) (GthThumbLoader *tl,
- GError *error);
};
-GType gth_thumb_loader_get_type (void);
-GthThumbLoader * gth_thumb_loader_new (int size);
-void gth_thumb_loader_set_loader (GthThumbLoader *self,
- PixbufLoader loader);
-void gth_thumb_loader_set_requested_size (GthThumbLoader *self,
- int size);
-int gth_thumb_loader_get_requested_size (GthThumbLoader *self);
-void gth_thumb_loader_use_cache (GthThumbLoader *self,
- gboolean use);
-void gth_thumb_loader_save_thumbnails (GthThumbLoader *self,
- gboolean save);
-void gth_thumb_loader_set_max_file_size (GthThumbLoader *self,
- goffset size);
-void gth_thumb_loader_set_file (GthThumbLoader *self,
- GthFileData *file_data);
-void gth_thumb_loader_set_uri (GthThumbLoader *self,
- const char *uri,
- const char *mime_type);
-GdkPixbuf * gth_thumb_loader_get_pixbuf (GthThumbLoader *self);
-void gth_thumb_loader_load (GthThumbLoader *self);
-void gth_thumb_loader_cancel (GthThumbLoader *self,
- DataFunc func,
- gpointer data);
+GType gth_thumb_loader_get_type (void);
+GthThumbLoader * gth_thumb_loader_new (int requested_size);
+void gth_thumb_loader_set_loader_func (GthThumbLoader *self,
+ PixbufLoader loader_func);
+void gth_thumb_loader_set_requested_size (GthThumbLoader *self,
+ int size);
+int gth_thumb_loader_get_requested_size (GthThumbLoader *self);
+void gth_thumb_loader_set_use_cache (GthThumbLoader *self,
+ gboolean use);
+void gth_thumb_loader_set_save_thumbnails (GthThumbLoader *self,
+ gboolean save);
+void gth_thumb_loader_set_max_file_size (GthThumbLoader *self,
+ goffset size);
+void gth_thumb_loader_load (GthThumbLoader *self,
+ GthFileData *file_data,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean gth_thumb_loader_load_finish (GthThumbLoader *self,
+ GAsyncResult *res,
+ GthFileData **file_data,
+ GdkPixbuf **pixbuf,
+ GError **error);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]