[gthumb] Simplified the image preloader
- From: Paolo Bacchilega <paobac src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gthumb] Simplified the image preloader
- Date: Sat, 9 Nov 2013 19:55:50 +0000 (UTC)
commit af1f8caf1bfb5aedc365e3ac3a94c37db6e0d5f5
Author: Paolo Bacchilega <paobac src gnome org>
Date: Sat Sep 14 18:07:18 2013 +0200
Simplified the image preloader
Removed the two steps policy that loaded the image at the original
size after loading it at the requested size. Now it only loads the
image at the requested size without the second step.
gthumb/gth-image-preloader.c | 904 +++++++++++++++---------------------------
gthumb/gth-image-preloader.h | 52 +--
gthumb/gth-marshal.list | 1 -
3 files changed, 342 insertions(+), 615 deletions(-)
---
diff --git a/gthumb/gth-image-preloader.c b/gthumb/gth-image-preloader.c
index d1c4d7d..5765c7b 100644
--- a/gthumb/gth-image-preloader.c
+++ b/gthumb/gth-image-preloader.c
@@ -28,11 +28,9 @@
#include "gth-marshal.h"
-#undef DEBUG_PRELOADER
#define GTH_IMAGE_PRELOADER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTH_TYPE_IMAGE_PRELOADER,
GthImagePreloaderPrivate))
-#define REQUESTED_INTERVAL 100
-#define SECOND_STEP_INTERVAL 100
-#define NOT_REQUESTED_INTERVAL 400
+#define LOAD_NEXT_FILE_DELAY 200
+#define CACHE_MAX_SIZE 10
enum {
@@ -43,224 +41,172 @@ enum {
typedef struct {
- int ref;
- GthImagePreloader *self;
- GthFileData *file_data;
- int requested_size;
- gboolean loaded;
- gboolean error;
- gboolean finalized;
- GthImageLoader *loader;
- GthImage *image;
- int original_width;
- int original_height;
- guint token;
-} Preloader;
+ int ref;
+ GthFileData *file_data;
+ GthImage *image;
+ int original_width;
+ int original_height;
+ int requested_size;
+ GError *error;
+} CacheData;
typedef struct {
- GthImagePreloader *self;
- GthFileData *requested;
- int requested_size;
- GthFileData **files;
- int n_files;
- guint token;
-} LoadData;
+ int ref;
+ gboolean finalized;
+ GthImagePreloader *preloader;
+ GList *files; /* List of GthFileData */
+ GList *current_file;
+ GList *requested_file;
+ int requested_size;
+ GSimpleAsyncResult *result;
+ GCancellable *cancellable;
+} LoadRequest;
struct _GthImagePreloaderPrivate {
- GthLoadPolicy load_policy;
- int n_preloaders;
- Preloader **loader; /* Array of loaders, each loader
- * will load an image. */
- int requested; /* This is the loader with the
- * requested image. The
- * requested image is the image
- * the user has expressly
- * requested to view, when this
- * image is loaded a
- * requested_ready signal is
- * emitted.
- * Other images do not trigger
- * any signal. */
- GFile *requested_file;
- int requested_size;
- int current; /* This is the loader that has
- * a loading underway. */
- guint load_id;
- GCancellable *cancellable;
- guint token;
- LoadData *next_load_data;
+ GList *requests; /* List of LoadRequest */
+ LoadRequest *current_request;
+ LoadRequest *last_request;
+ GthImageLoader *loader;
+ GQueue *cache;
+ guint load_next_id;
};
-static guint gth_image_preloader_signals[LAST_SIGNAL] = { 0 };
-
-
G_DEFINE_TYPE (GthImagePreloader, gth_image_preloader, G_TYPE_OBJECT)
-/* -- Preloader -- */
+/* -- CacheData -- */
-static Preloader *
-preloader_new (GthImagePreloader *self)
+static CacheData *
+cache_data_new (void)
{
- Preloader *preloader;
-
- preloader = g_new0 (Preloader, 1);
- preloader->ref = 1;
- preloader->self = self;
- preloader->file_data = NULL;
- preloader->loaded = FALSE;
- preloader->error = FALSE;
- preloader->finalized = FALSE;
- preloader->loader = gth_image_loader_new (NULL, NULL);
- gth_image_loader_set_preferred_format (preloader->loader, GTH_IMAGE_FORMAT_CAIRO_SURFACE);
- preloader->image = NULL;
- preloader->original_width = -1;
- preloader->original_height = -1;
-
- return preloader;
+ CacheData *cache_data;
+
+ cache_data = g_new0 (CacheData, 1);
+ cache_data->ref = 1;
+ cache_data->file_data = NULL;
+ cache_data->image = NULL;
+ cache_data->original_width = -1;
+ cache_data->original_height = -1;
+ cache_data->requested_size = -1;
+ cache_data->error = NULL;
+
+ return cache_data;
}
-static Preloader *
-preloader_ref (Preloader *preloader)
+static CacheData *
+cache_data_ref (CacheData *cache_data)
{
- preloader->ref++;
- return preloader;
+ cache_data->ref++;
+ return cache_data;
}
static void
-preloader_unref (Preloader *preloader)
+cache_data_unref (CacheData *cache_data)
{
- if (preloader == NULL)
+ if (cache_data == NULL)
return;
- if (--preloader->ref > 0)
+ if (--cache_data->ref > 0)
return;
- _g_object_unref (preloader->image);
- _g_object_unref (preloader->loader);
- _g_object_unref (preloader->file_data);
- g_free (preloader);
-}
-
-
-static void
-preloader_set_file_data (Preloader *preloader,
- GthFileData *file_data)
-{
- g_return_if_fail (preloader != NULL);
-
- if (preloader->file_data != file_data) {
- _g_object_unref (preloader->file_data);
- preloader->file_data = NULL;
- }
-
- if (file_data != NULL)
- preloader->file_data = g_object_ref (file_data);
- preloader->loaded = FALSE;
- preloader->error = FALSE;
+ g_clear_error (&cache_data->error);
+ _g_object_unref (cache_data->image);
+ _g_object_unref (cache_data->file_data);
+ g_free (cache_data);
}
static gboolean
-preloader_has_valid_content_for_file (Preloader *preloader,
- GthFileData *file_data)
+cache_data_is_valid_for_request (CacheData *cache_data,
+ GthFileData *file_data,
+ int requested_size)
{
- return ((preloader->file_data != NULL)
- && preloader->loaded
- && ! preloader->error
- && (preloader->image != NULL)
- && g_file_equal (preloader->file_data->file, file_data->file)
+ return (((cache_data->requested_size == requested_size) || ((requested_size > 0) &&
(cache_data->requested_size > requested_size)))
+ && g_file_equal (cache_data->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));
+ gth_file_data_get_modification_time (cache_data->file_data)) == 0));
}
-static gboolean
-preloader_needs_to_load (Preloader *preloader)
+/* -- LoadRequest -- */
+
+
+static LoadRequest *
+load_request_new (GthImagePreloader *preloader)
{
- return ((preloader->token == preloader->self->priv->token)
- && (preloader->file_data != NULL)
- && ! preloader->error
- && ! preloader->loaded);
+ LoadRequest *request;
+
+ request = g_new0 (LoadRequest, 1);
+ request->ref = 1;
+ request->finalized = FALSE;
+ request->preloader = preloader;
+ request->files = NULL;
+ request->current_file = NULL;
+ request->requested_size = -1;
+ request->result = NULL;
+ request->cancellable = NULL;
+
+ return request;
}
-static gboolean
-preloader_needs_second_step (Preloader *preloader)
+static LoadRequest *
+load_request_ref (LoadRequest *request)
{
- 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->image != NULL)
- && ! gth_image_is_animation (preloader->image));
+ request->ref++;
+ return request;
}
-static int
-preloader_signal_to_emit (Preloader *preloader)
+static void
+load_request_unref (LoadRequest *request)
{
- int signal = -1;
-
- switch (preloader->self->priv->load_policy) {
- case GTH_LOAD_POLICY_ONE_STEP:
- signal = REQUESTED_READY;
- break;
-
- case GTH_LOAD_POLICY_TWO_STEPS:
- if (preloader->self->priv->requested_size == -1)
- signal = ORIGINAL_SIZE_READY;
- else
- signal = REQUESTED_READY;
- break;
- }
-
- g_assert (signal != -1);
+ if (request == NULL)
+ return;
+ if (--request->ref > 0)
+ return;
- return signal;
+ _g_object_unref (request->cancellable);
+ _g_object_unref (request->result);
+ _g_object_list_unref (request->files);
+ g_free (request);
}
/* -- GthImagePreloader -- */
-static void load_data_free (LoadData *load_data);
-
-
static void
gth_image_preloader_finalize (GObject *object)
{
GthImagePreloader *self;
- int i;
+ GList *scan;
g_return_if_fail (object != NULL);
g_return_if_fail (GTH_IS_IMAGE_PRELOADER (object));
self = GTH_IMAGE_PRELOADER (object);
- if (self->priv->load_id != 0) {
- g_source_remove (self->priv->load_id);
- self->priv->load_id = 0;
- }
+ if (self->priv->load_next_id == 0)
+ g_source_remove (self->priv->load_next_id);
+ load_request_unref (self->priv->last_request);
+ load_request_unref (self->priv->current_request);
- if (self->priv->next_load_data != NULL) {
- load_data_free (self->priv->next_load_data);
- self->priv->next_load_data = NULL;
- }
+ for (scan = self->priv->requests; scan; scan = scan->next) {
+ LoadRequest *request = scan->data;
- for (i = 0; i < self->priv->n_preloaders; i++) {
- self->priv->loader[i]->finalized = TRUE;
- preloader_unref (self->priv->loader[i]);
- self->priv->loader[i] = NULL;
+ request->finalized = TRUE;
+ load_request_unref (request);
}
- g_free (self->priv->loader);
- _g_object_unref (self->priv->requested_file);
- g_object_unref (self->priv->cancellable);
+ g_list_free (self->priv->requests);
+
+ g_object_unref (self->priv->loader);
+ g_queue_free_full (self->priv->cache, (GDestroyNotify) cache_data_unref);
G_OBJECT_CLASS (gth_image_preloader_parent_class)->finalize (object);
}
@@ -273,35 +219,6 @@ gth_image_preloader_class_init (GthImagePreloaderClass *class)
g_type_class_add_private (class, sizeof (GthImagePreloaderPrivate));
- gth_image_preloader_signals[REQUESTED_READY] =
- g_signal_new ("requested_ready",
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GthImagePreloaderClass, requested_ready),
- NULL, NULL,
- gth_marshal_VOID__OBJECT_OBJECT_INT_INT_POINTER,
- G_TYPE_NONE,
- 5,
- G_TYPE_OBJECT,
- G_TYPE_OBJECT,
- G_TYPE_INT,
- G_TYPE_INT,
- G_TYPE_POINTER);
- gth_image_preloader_signals[ORIGINAL_SIZE_READY] =
- g_signal_new ("original_size_ready",
- G_TYPE_FROM_CLASS (class),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (GthImagePreloaderClass, original_size_ready),
- NULL, NULL,
- gth_marshal_VOID__OBJECT_OBJECT_INT_INT_POINTER,
- G_TYPE_NONE,
- 5,
- G_TYPE_OBJECT,
- G_TYPE_OBJECT,
- G_TYPE_INT,
- G_TYPE_INT,
- G_TYPE_POINTER);
-
object_class = G_OBJECT_CLASS (class);
object_class->finalize = gth_image_preloader_finalize;
}
@@ -311,90 +228,126 @@ static void
gth_image_preloader_init (GthImagePreloader *self)
{
self->priv = GTH_IMAGE_PRELOADER_GET_PRIVATE (self);
- self->priv->loader = NULL;
- self->priv->requested = -1;
- self->priv->requested_file = NULL;
- self->priv->current = -1;
- self->priv->load_policy = GTH_LOAD_POLICY_ONE_STEP;
- self->priv->cancellable = g_cancellable_new ();
- self->priv->token = 0;
+ self->priv->requests = NULL;
+ self->priv->current_request = NULL;
+ self->priv->last_request = NULL;
+ self->priv->loader = gth_image_loader_new (NULL, NULL);
+ self->priv->cache = g_queue_new ();
+ self->priv->load_next_id = 0;
}
GthImagePreloader *
-gth_image_preloader_new (GthLoadPolicy load_policy,
- int n_preloaders)
+gth_image_preloader_new (void)
{
- GthImagePreloader *self;
- int i;
+ return (GthImagePreloader *) g_object_new (GTH_TYPE_IMAGE_PRELOADER, NULL);
+}
- g_return_val_if_fail (n_preloaders > 0, NULL);
- self = g_object_new (GTH_TYPE_IMAGE_PRELOADER, NULL);
+/* -- gth_image_preloader_load -- */
- self->priv->n_preloaders = n_preloaders;
- self->priv->load_policy = 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);
- return self;
-}
+static CacheData *
+_gth_image_preloader_lookup_request (GthImagePreloader *self,
+ GthFileData *requested_file,
+ int requested_size)
+{
+ GList *scan;
+ for (scan = self->priv->cache->head; scan; scan = scan->next) {
+ CacheData *cache_data = scan->data;
+ if (cache_data_is_valid_for_request (cache_data, requested_file, requested_size)) {
+ g_print ("cached\n");
+ return cache_data;
+ }
+ }
-void
-gth_image_prelaoder_set_load_policy (GthImagePreloader *self,
- GthLoadPolicy policy)
-{
- self->priv->load_policy = policy;
+ return NULL;
}
-GthLoadPolicy
-gth_image_prelaoder_get_load_policy (GthImagePreloader *self)
+static void
+_gth_image_preloader_request_finished (GthImagePreloader *self,
+ LoadRequest *load_request)
{
- return self->priv->load_policy;
+ if (self->priv->last_request == load_request)
+ self->priv->last_request = NULL;
+ load_request_unref (self->priv->current_request);
+ self->priv->current_request = NULL;
+ load_request_unref (load_request);
}
-/* -- gth_image_preloader_load -- */
-
-
-static void start_next_loader (GthImagePreloader *self);
+static void
+_gth_image_preloader_load_current_file (GthImagePreloader *self,
+ LoadRequest *request);
static gboolean
-load_next (gpointer data)
+load_current_file (gpointer user_data)
{
- GthImagePreloader *self = data;
+ LoadRequest *request = user_data;
+ GthImagePreloader *self = request->preloader;
- if (self->priv->load_id != 0) {
- g_source_remove (self->priv->load_id);
- self->priv->load_id = 0;
+ g_return_val_if_fail (request->current_file != NULL, FALSE);
+
+ if (self->priv->load_next_id > 0) {
+ g_source_remove (self->priv->load_next_id);
+ self->priv->load_next_id = 0;
}
- start_next_loader (self);
+ _gth_image_preloader_load_current_file (self, request);
return FALSE;
}
-typedef struct {
- Preloader *preloader;
- GthFileData *file_data;
- int requested_size;
-} LoadRequest;
-
-
static void
-load_request_free (LoadRequest *load_request)
+queue_load_next_file (GthImagePreloader *self,
+ LoadRequest *request)
{
- preloader_unref (load_request->preloader);
- g_object_unref (load_request->file_data);
- g_free (load_request);
+ CacheData *cache_data;
+
+ g_return_if_fail (request->current_file != NULL);
+
+ do {
+ GthFileData *requested_file;
+
+ request->current_file = request->current_file->next;
+ if (request->current_file == NULL) {
+ _gth_image_preloader_request_finished (self, request);
+ return;
+ }
+
+ requested_file = (GthFileData *) request->current_file->data;
+ cache_data = _gth_image_preloader_lookup_request (self,
+ requested_file,
+ request->requested_size);
+ }
+ while (cache_data != NULL);
+
+ if (self->priv->load_next_id > 0)
+ g_source_remove (self->priv->load_next_id);
+ self->priv->load_next_id = g_timeout_add (LOAD_NEXT_FILE_DELAY,
+ load_current_file,
+ request);
}
-static void assign_loaders (LoadData *load_data);
+static void
+_gth_image_preloader_start_request (GthImagePreloader *self,
+ LoadRequest *request);
+
+
+static void
+_gth_image_preloader_add_to_cache (GthImagePreloader *self,
+ CacheData *cache_data)
+{
+ if (g_queue_get_length (self->priv->cache) > CACHE_MAX_SIZE) {
+ CacheData *oldest = g_queue_pop_tail (self->priv->cache);
+ cache_data_unref (oldest);
+ }
+ g_queue_push_head (self->priv->cache, cache_data);
+}
static void
@@ -402,23 +355,20 @@ image_loader_ready_cb (GObject *source_object,
GAsyncResult *result,
gpointer user_data)
{
- LoadRequest *load_request = user_data;
- Preloader *preloader = load_request->preloader;
- GthImagePreloader *self = preloader->self;
- GthImage *image = NULL;
- int original_width;
- int original_height;
- GError *error = NULL;
- gboolean success;
- int interval;
-
- if (preloader->finalized) {
- load_request_free (load_request);
+ LoadRequest *request = user_data;
+ GthImagePreloader *self = request->preloader;
+ GthImage *image = NULL;
+ int original_width;
+ int original_height;
+ GError *error = NULL;
+ gboolean success;
+ CacheData *cache_data;
+
+ if (request->finalized) {
+ load_request_unref (request);
return;
}
- self->priv->current = -1;
-
success = gth_image_loader_load_finish (GTH_IMAGE_LOADER (source_object),
result,
&image,
@@ -427,306 +377,108 @@ image_loader_ready_cb (GObject *source_object,
&error);
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)
- || ! g_file_equal (load_request->file_data->file, preloader->file_data->file)
- || (preloader->token != self->priv->token))
+ || (self->priv->last_request != request))
{
- load_request_free (load_request);
+ load_request_unref (request);
if (error != NULL)
g_error_free (error);
_g_object_unref (image);
+ _gth_image_preloader_request_finished (self, request);
- if (self->priv->next_load_data != NULL) {
- assign_loaders (self->priv->next_load_data);
- start_next_loader (self);
-
- load_data_free (self->priv->next_load_data);
- self->priv->next_load_data = NULL;
- }
+ if (self->priv->last_request != NULL)
+ _gth_image_preloader_start_request (self, self->priv->last_request);
return;
}
- interval = NOT_REQUESTED_INTERVAL;
-
- _g_object_unref (preloader->image);
- preloader->image = _g_object_ref (image);
- preloader->original_width = original_width;
- preloader->original_height = original_height;
- preloader->loaded = success;
- preloader->error = ! success;
- preloader->requested_size = load_request->requested_size;
-
- if (_g_file_equal (load_request->file_data->file, self->priv->requested_file)) {
-#if DEBUG_PRELOADER
- debug (DEBUG_INFO, "loaded [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[preloader_signal_to_emit (preloader)],
- 0,
- preloader->file_data,
- preloader->image,
- 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 = SECOND_STEP_INTERVAL;
- }
- else
- interval = REQUESTED_INTERVAL;
+ cache_data = cache_data_new ();
+ cache_data->file_data = g_object_ref (request->current_file->data);
+ cache_data->image = success ? _g_object_ref (image) : NULL;
+ cache_data->original_width = success ? original_width : -1;
+ cache_data->original_height = success ? original_height : -1;
+ cache_data->requested_size = request->requested_size;
+ cache_data->error = error;
+ _gth_image_preloader_add_to_cache (self, cache_data);
+
+ if (request->current_file == request->requested_file) {
+ g_simple_async_result_set_op_res_gpointer (request->result,
+ cache_data_ref (cache_data),
+ (GDestroyNotify) cache_data_unref);
+ g_simple_async_result_complete_in_idle (request->result);
}
-#if DEBUG_PRELOADER
- else
- debug (DEBUG_INFO, "loaded [non-requested] %s => %s [size: %d]", (error == NULL) ? "ready" :
"error", g_file_get_uri (preloader->file_data->file), preloader->requested_size);
-#endif
- if (self->priv->load_id == 0)
- self->priv->load_id = g_timeout_add (interval, load_next, self);
+ queue_load_next_file (self, request);
- load_request_free (load_request);
_g_object_unref (image);
-}
-
-
-static Preloader *
-current_preloader (GthImagePreloader *self)
-{
- return (self->priv->current == -1) ? NULL : self->priv->loader[self->priv->current];
-}
-
-
-static Preloader *
-requested_preloader (GthImagePreloader *self)
-{
- return (self->priv->requested == -1) ? NULL : self->priv->loader[self->priv->requested];
+ load_request_unref (request);
}
static void
-start_next_loader (GthImagePreloader *self)
+_gth_image_preloader_load_current_file (GthImagePreloader *self,
+ LoadRequest *request)
{
- 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++;
+ GthFileData *requested_file;
+ CacheData *cache_data;
+
+ g_return_if_fail (request->current_file != NULL);
+
+ requested_file = (GthFileData *) request->current_file->data;
+ cache_data = _gth_image_preloader_lookup_request (self,
+ requested_file,
+ request->requested_size);
+ if (cache_data != NULL) {
+ if (request->current_file == request->requested_file) {
+ g_simple_async_result_set_op_res_gpointer (request->result,
+ cache_data_ref (cache_data),
+ (GDestroyNotify) cache_data_unref);
+ g_simple_async_result_complete_in_idle (request->result);
}
+ queue_load_next_file (self, request);
- if (n >= self->priv->n_preloaders)
- i = -1;
+ return;
}
- self->priv->current = i;
- preloader = current_preloader (self);
-
- if (preloader != NULL) {
- LoadRequest *load_request;
-
-#if DEBUG_PRELOADER
- {
- char *uri;
+ g_print ("load @ %d\n", request->requested_size);
- 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->image);
- preloader->image = NULL;
-
- load_request = g_new0 (LoadRequest, 1);
- load_request->preloader = preloader_ref (preloader);
- load_request->file_data = g_object_ref (preloader->file_data);
- load_request->requested_size = preloader->requested_size;
-
- g_cancellable_reset (preloader->self->priv->cancellable);
- gth_image_loader_load (preloader->loader,
- preloader->file_data,
- preloader->requested_size,
- (i == self->priv->requested) ? G_PRIORITY_HIGH : G_PRIORITY_DEFAULT,
- preloader->self->priv->cancellable,
- image_loader_ready_cb,
- load_request);
- }
-#if DEBUG_PRELOADER
- else
- debug (DEBUG_INFO, "done");
-#endif
+ load_request_ref (request);
+ gth_image_loader_load (self->priv->loader,
+ requested_file,
+ request->requested_size,
+ (request->current_file == request->files) ? G_PRIORITY_HIGH :
G_PRIORITY_DEFAULT,
+ request->cancellable,
+ image_loader_ready_cb,
+ request);
}
static void
-load_data_free (LoadData *load_data)
+_gth_image_preloader_start_request (GthImagePreloader *self,
+ LoadRequest *request)
{
- int i;
-
- if (load_data == NULL)
- return;
+ load_request_unref (self->priv->current_request);
+ self->priv->current_request = load_request_ref (request);
- 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);
+ request->current_file = request->files;
+ _gth_image_preloader_load_current_file (self, request);
}
static void
-assign_loaders (LoadData *load_data)
+_gth_image_preloader_cancel_current_request (GthImagePreloader *self)
{
- GthImagePreloader *self = load_data->self;
- gboolean *file_assigned;
- gboolean *loader_assigned;
- int i, j;
-
- if (load_data->token != self->priv->token)
+ if (self->priv->current_request == NULL)
return;
- 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 < load_data->n_files; j++) {
- GthFileData *file_data = load_data->files[j];
-
- if (file_data == NULL)
- continue;
-
- /* check whether the image has already been loaded. */
-
- for (i = 0; i < self->priv->n_preloaders; i++) {
- Preloader *preloader = self->priv->loader[i];
-
- if (preloader_has_valid_content_for_file (preloader, file_data)) {
- loader_assigned[i] = TRUE;
- file_assigned[j] = TRUE;
-
- if (_g_file_equal (file_data->file, load_data->requested->file)) {
- self->priv->requested = i;
-
- g_signal_emit (G_OBJECT (self),
- gth_image_preloader_signals[preloader_signal_to_emit
(preloader)],
- 0,
- preloader->file_data,
- preloader->image,
- preloader->original_width,
- preloader->original_height,
- NULL);
-
-#if DEBUG_PRELOADER
- debug (DEBUG_INFO, "[requested] preloaded %s [size: %d]",
g_file_get_uri (preloader->file_data->file), preloader->requested_size);
-#endif
-
- if (preloader_needs_second_step (preloader)) {
- /* Reload the image at the original size */
- preloader->loaded = FALSE;
- preloader->requested_size = -1;
- }
- }
-
-#if DEBUG_PRELOADER
- {
- char *uri;
-
- uri = g_file_get_uri (file_data->file);
- debug (DEBUG_INFO, "[=] [%d] <- %s", i, uri);
- g_free (uri);
- }
-#endif
-
- break;
- }
- }
- }
-
- /* assign the remaining files */
-
- for (j = 0; j < load_data->n_files; j++) {
- GthFileData *file_data = load_data->files[j];
- Preloader *preloader;
- int k;
+ if (self->priv->load_next_id > 0) {
+ g_source_remove (self->priv->load_next_id);
+ self->priv->load_next_id = 0;
- if (file_data == NULL)
- continue;
-
- if (file_assigned[j])
- continue;
-
- /* find the first non-assigned loader */
- for (k = 0; (k < self->priv->n_preloaders) && loader_assigned[k]; k++)
- /* void */;
-
- g_return_if_fail (k < self->priv->n_preloaders);
-
- loader_assigned[k] = TRUE;
-
- preloader = self->priv->loader[k];
- preloader_set_file_data (preloader, file_data);
- preloader->requested_size = _g_file_equal (file_data->file, load_data->requested->file) ?
load_data->requested_size : -1;
- /* force the use of the single step policy if the file is not local, in order to speed-up
loading. */
- if (! g_file_is_native (file_data->file))
- preloader->requested_size = -1;
- preloader->token = load_data->token;
-
- if (_g_file_equal (file_data->file, load_data->requested->file)) {
- self->priv->requested = k;
-
-#if DEBUG_PRELOADER
- {
- char *uri;
-
- uri = g_file_get_uri (file_data->file);
- debug (DEBUG_INFO, "[requested] %s", uri);
- g_free (uri);
- }
-#endif
- }
-
-#if DEBUG_PRELOADER
- {
- char *uri;
-
- uri = g_file_get_uri (file_data->file);
- debug (DEBUG_INFO, "[+] [%d] <- %s", k, uri);
- g_free (uri);
- }
-#endif
+ _gth_image_preloader_request_finished (self, self->priv->current_request);
+ _gth_image_preloader_start_request (self, self->priv->last_request);
}
-
- g_free (loader_assigned);
- g_free (file_assigned);
+ else
+ g_cancellable_cancel (self->priv->current_request->cancellable);
}
@@ -747,89 +499,81 @@ check_file (GthFileData *file_data)
void
-gth_image_preloader_load (GthImagePreloader *self,
- GthFileData *requested,
- int requested_size,
+gth_image_preloader_load (GthImagePreloader *self,
+ GthFileData *requested,
+ int requested_size,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ int n_files,
...)
{
- LoadData *load_data;
- int n;
+ LoadRequest *request;
va_list args;
- GthFileData *file_data;
- self->priv->token++;
+ request = load_request_new (self);
+ request->requested_size = requested_size;
+ request->files = g_list_prepend (request->files, gth_file_data_dup (requested));
+ va_start (args, n_files);
+ while (n_files-- > 0) {
+ GthFileData *file_data;
+ GthFileData *checked_file_data;
- _g_object_unref (self->priv->requested_file);
- self->priv->requested_file = g_file_dup (requested->file);
-
- if (self->priv->next_load_data != NULL) {
- load_data_free (self->priv->next_load_data);
- self->priv->next_load_data = NULL;
- }
-
- 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);
-
- 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);
+ file_data = va_arg (args, GthFileData *);
+ checked_file_data = check_file (file_data);
if (checked_file_data != NULL)
- load_data->files[n++] = checked_file_data;
+ request->files = g_list_prepend (request->files, checked_file_data);
}
va_end (args);
- load_data->n_files = n;
-
- if (self->priv->current != -1) {
- Preloader *preloader;
-
- preloader = current_preloader (self);
- if (preloader != NULL) {
- self->priv->next_load_data = load_data;
- g_cancellable_cancel (preloader->self->priv->cancellable);
- return;
- }
- }
-
- assign_loaders (load_data);
- start_next_loader (self);
-
- load_data_free (load_data);
+ request->files = g_list_reverse (request->files);
+ request->requested_file = request->files;
+ request->result = g_simple_async_result_new (G_OBJECT (self),
+ callback,
+ user_data,
+ gth_image_preloader_load);
+ request->cancellable = (cancellable != NULL) ? g_object_ref (cancellable) : g_cancellable_new ();
+
+ self->priv->last_request = request;
+ if (self->priv->current_request != NULL)
+ _gth_image_preloader_cancel_current_request (self);
+ else
+ _gth_image_preloader_start_request (self, self->priv->last_request);
}
-GthImageLoader *
-gth_image_preloader_get_loader (GthImagePreloader *self,
- GthFileData *file_data)
+gboolean
+gth_image_preloader_load_finish (GthImagePreloader *self,
+ GAsyncResult *result,
+ GthFileData **requested,
+ GthImage **image,
+ int *requested_size,
+ int *original_width,
+ int *original_height,
+ GError **error)
{
- int i;
+ CacheData *cache_data;
- g_return_val_if_fail (self != NULL, NULL);
+ g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self),
gth_image_preloader_load), FALSE);
- if (file_data == NULL)
- return NULL;
+ cache_data = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
+ g_return_val_if_fail (cache_data != NULL, FALSE);
- for (i = 0; i < self->priv->n_preloaders; i++) {
- Preloader *preloader = self->priv->loader[i];
-
- if (preloader_has_valid_content_for_file (preloader, file_data))
- return preloader->loader;
+ if (cache_data->error != NULL) {
+ if (error != NULL)
+ *error = g_error_copy (cache_data->error);
+ return FALSE;
}
- return NULL;
-}
-
-
-GthFileData *
-gth_image_preloader_get_requested (GthImagePreloader *self)
-{
- Preloader *preloader;
-
- preloader = requested_preloader (self);
- return (preloader != NULL) ? preloader->file_data : NULL;
+ if (requested != NULL)
+ *requested = _g_object_ref (cache_data->file_data);
+ if (image != NULL)
+ *image = _g_object_ref (cache_data->image);
+ if (requested_size != NULL)
+ *requested_size = cache_data->requested_size;
+ if (original_width != NULL)
+ *original_width = cache_data->original_width;
+ if (original_height != NULL)
+ *original_height = cache_data->original_height;
+
+ return TRUE;
}
diff --git a/gthumb/gth-image-preloader.h b/gthumb/gth-image-preloader.h
index 0278654..0077213 100644
--- a/gthumb/gth-image-preloader.h
+++ b/gthumb/gth-image-preloader.h
@@ -25,10 +25,8 @@
#include "gth-image-loader.h"
#include "gth-file-data.h"
-typedef enum {
- GTH_LOAD_POLICY_ONE_STEP,
- GTH_LOAD_POLICY_TWO_STEPS,
-} GthLoadPolicy;
+#define GTH_ORIGINAL_SIZE -1
+#define GTH_NO_PRELOADERS 0
#define GTH_TYPE_IMAGE_PRELOADER (gth_image_preloader_get_type ())
#define GTH_IMAGE_PRELOADER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTH_TYPE_IMAGE_PRELOADER,
GthImagePreloader))
@@ -37,50 +35,36 @@ typedef enum {
#define GTH_IS_IMAGE_PRELOADER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTH_TYPE_IMAGE_PRELOADER))
#define GTH_IMAGE_PRELOADER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), GTH_TYPE_IMAGE_PRELOADER,
GthImagePreloaderClass))
-
typedef struct _GthImagePreloader GthImagePreloader;
typedef struct _GthImagePreloaderClass GthImagePreloaderClass;
typedef struct _GthImagePreloaderPrivate GthImagePreloaderPrivate;
-
struct _GthImagePreloader {
GObject __parent;
GthImagePreloaderPrivate *priv;
};
-
struct _GthImagePreloaderClass {
GObjectClass __parent_class;
-
- /*< signals >*/
-
- void (* requested_ready) (GthImagePreloader *preloader,
- GthFileData *requested,
- GthImage *image,
- int original_width,
- int original_height,
- GError *error);
- void (* original_size_ready) (GthImagePreloader *preloader,
- GthFileData *requested,
- GthImage *image,
- 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);
-GthLoadPolicy gth_image_prelaoder_get_load_policy (GthImagePreloader *self);
-void gth_image_preloader_load (GthImagePreloader *self,
- GthFileData *requested,
- int requested_size,
+GthImagePreloader * gth_image_preloader_new (void);
+void gth_image_preloader_load (GthImagePreloader *self,
+ GthFileData *requested,
+ int requested_size,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data,
+ int n_files,
...);
-GthImageLoader * gth_image_preloader_get_loader (GthImagePreloader *self,
- GthFileData *file_data);
-GthFileData * gth_image_preloader_get_requested (GthImagePreloader *self);
+gboolean gth_image_preloader_load_finish (GthImagePreloader *self,
+ GAsyncResult *result,
+ GthFileData **requested,
+ GthImage **image,
+ int *requested_size,
+ int *original_width,
+ int *original_height,
+ GError **error);
#endif /* GTH_IMAGE_PRELOADER_H */
diff --git a/gthumb/gth-marshal.list b/gthumb/gth-marshal.list
index 3f16292..602db29 100644
--- a/gthumb/gth-marshal.list
+++ b/gthumb/gth-marshal.list
@@ -8,7 +8,6 @@ VOID:OBJECT, BOOLEAN
VOID:OBJECT, BOXED, ENUM
VOID:OBJECT, BOXED, INT, ENUM
VOID:OBJECT, OBJECT
-VOID:OBJECT, OBJECT, INT, INT, POINTER
VOID:OBJECT, POINTER
VOID:OBJECT, STRING
VOID:OBJECT, UINT
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]