~noskcaj/ubuntu/vivid/gthumb/flickr-https

« back to all changes in this revision

Viewing changes to gthumb/gth-image-preloader.c

  • Committer: Package Import Robot
  • Author(s): Jackson Doak
  • Date: 2014-04-08 06:31:09 UTC
  • mfrom: (1.3.20)
  • Revision ID: package-import@ubuntu.com-20140408063109-tk845map8ji6uxvd
Tags: 3:3.3.1.is.3.2.7-0ubuntu1
* Revert to newest upstream stable release. LP: #1290691
  - Refresh patches

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
#include <config.h>
24
24
#include <string.h>
25
25
#include <glib.h>
26
 
#include "cairo-scale.h"
27
 
#include "cairo-utils.h"
28
26
#include "glib-utils.h"
29
27
#include "gth-image-preloader.h"
30
 
#include "gth-image-utils.h"
31
28
#include "gth-marshal.h"
32
29
 
33
30
 
34
31
#undef DEBUG_PRELOADER
35
 
#undef RESIZE_TO_REQUESTED_SIZE
36
32
#define GTH_IMAGE_PRELOADER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTH_TYPE_IMAGE_PRELOADER, GthImagePreloaderPrivate))
37
 
#define LOAD_NEXT_FILE_DELAY 100
38
 
#define CACHE_MAX_SIZE 10
 
33
#define REQUESTED_INTERVAL 100
 
34
#define SECOND_STEP_INTERVAL 100
 
35
#define NOT_REQUESTED_INTERVAL 400
39
36
 
40
37
 
41
38
enum {
46
43
 
47
44
 
48
45
typedef struct {
49
 
        int                      ref;
50
 
        GthFileData             *file_data;
51
 
        GthImage                *image;
52
 
        int                      original_width;
53
 
        int                      original_height;
54
 
        int                      requested_size;
55
 
        gboolean                 loaded_original;
56
 
        GError                  *error;
57
 
} CacheData;
 
46
        int                 ref;
 
47
        GthImagePreloader  *self;
 
48
        GthFileData        *file_data;
 
49
        int                 requested_size;
 
50
        gboolean            loaded;
 
51
        gboolean            error;
 
52
        gboolean            finalized;
 
53
        GthImageLoader     *loader;
 
54
        GthImage           *image;
 
55
        int                 original_width;
 
56
        int                 original_height;
 
57
        guint               token;
 
58
} Preloader;
58
59
 
59
60
 
60
61
typedef struct {
61
 
        int                      ref;
62
 
        gboolean                 finalized;
63
 
        GthImagePreloader       *preloader;
64
 
        GList                   *files;                 /* List of GthFileData */
65
 
        GList                   *current_file;
66
 
        GList                   *requested_file;
67
 
        int                      requested_size;
68
 
        GSimpleAsyncResult      *result;
69
 
        GCancellable            *cancellable;
70
 
} LoadRequest;
 
62
        GthImagePreloader  *self;
 
63
        GthFileData        *requested;
 
64
        int                 requested_size;
 
65
        GthFileData       **files;
 
66
        int                 n_files;
 
67
        guint               token;
 
68
} LoadData;
71
69
 
72
70
 
73
71
struct _GthImagePreloaderPrivate {
74
 
        GList                   *requests;              /* List of LoadRequest */
75
 
        LoadRequest             *current_request;
76
 
        LoadRequest             *last_request;
77
 
        GthImageLoader          *loader;
78
 
        GQueue                  *cache;
79
 
        guint                    load_next_id;
 
72
        GthLoadPolicy load_policy;
 
73
        int           n_preloaders;
 
74
        Preloader   **loader;                  /* Array of loaders, each loader
 
75
                                                * will load an image. */
 
76
        int           requested;               /* This is the loader with the
 
77
                                                * requested image.  The
 
78
                                                * requested image is the image
 
79
                                                * the user has expressly
 
80
                                                * requested to view, when this
 
81
                                                * image is loaded a
 
82
                                                * requested_ready signal is
 
83
                                                * emitted.
 
84
                                                * Other images do not trigger
 
85
                                                * any signal. */
 
86
        GFile        *requested_file;
 
87
        int           requested_size;
 
88
        int           current;                 /* This is the loader that has
 
89
                                                * a loading underway. */
 
90
        guint         load_id;
 
91
        GCancellable *cancellable;
 
92
        guint         token;
 
93
        LoadData     *next_load_data;
80
94
};
81
95
 
82
96
 
 
97
static guint gth_image_preloader_signals[LAST_SIGNAL] = { 0 };
 
98
 
 
99
 
83
100
G_DEFINE_TYPE (GthImagePreloader, gth_image_preloader, G_TYPE_OBJECT)
84
101
 
85
102
 
86
 
/* -- CacheData -- */
87
 
 
88
 
 
89
 
static CacheData *
90
 
cache_data_new (void)
91
 
{
92
 
        CacheData *cache_data;
93
 
 
94
 
        cache_data = g_new0 (CacheData, 1);
95
 
        cache_data->ref = 1;
96
 
        cache_data->file_data = NULL;
97
 
        cache_data->image = NULL;
98
 
        cache_data->original_width = -1;
99
 
        cache_data->original_height = -1;
100
 
        cache_data->requested_size = -1;
101
 
        cache_data->error = NULL;
102
 
        cache_data->loaded_original = FALSE;
103
 
 
104
 
        return cache_data;
105
 
}
106
 
 
107
 
 
108
 
static CacheData *
109
 
cache_data_ref (CacheData *cache_data)
110
 
{
111
 
        cache_data->ref++;
112
 
        return cache_data;
113
 
}
114
 
 
115
 
 
116
 
static void
117
 
cache_data_unref (CacheData *cache_data)
118
 
{
119
 
        if (cache_data == NULL)
120
 
                return;
121
 
        if (--cache_data->ref > 0)
122
 
                return;
123
 
 
124
 
        g_clear_error (&cache_data->error);
125
 
        _g_object_unref (cache_data->image);
126
 
        _g_object_unref (cache_data->file_data);
127
 
        g_free (cache_data);
128
 
}
129
 
 
130
 
 
131
 
static inline gboolean
132
 
cache_data_file_matches (CacheData   *cache_data,
133
 
                         GthFileData *file_data)
134
 
{
135
 
        if ((file_data == GTH_MODIFIED_IMAGE) && (cache_data->file_data == GTH_MODIFIED_IMAGE))
136
 
                return TRUE;
137
 
 
138
 
        if ((file_data == GTH_MODIFIED_IMAGE) || (cache_data->file_data == GTH_MODIFIED_IMAGE))
139
 
                return FALSE;
140
 
 
141
 
        if (g_file_equal (cache_data->file_data->file, file_data->file)
142
 
            && (_g_time_val_cmp (gth_file_data_get_modification_time (file_data),
143
 
                                 gth_file_data_get_modification_time (cache_data->file_data)) == 0))
144
 
        {
145
 
                return TRUE;
146
 
        }
147
 
 
148
 
        return FALSE;
149
 
}
150
 
 
151
 
 
152
 
static gboolean
153
 
cache_data_is_valid_for_request (CacheData   *cache_data,
154
 
                                 GthFileData *file_data,
155
 
                                 int          requested_size)
156
 
{
157
 
        if (! cache_data_file_matches (cache_data, file_data))
158
 
                return FALSE;
159
 
 
160
 
        return cache_data->requested_size == requested_size;
161
 
}
162
 
 
163
 
 
164
 
static gboolean
165
 
cache_data_has_better_quality_for_request (CacheData   *cache_data,
166
 
                                           GthFileData *file_data,
167
 
                                           int          requested_size)
168
 
{
169
 
        if (! cache_data_file_matches (cache_data, file_data))
170
 
                return FALSE;
171
 
 
172
 
        if (requested_size == GTH_ORIGINAL_SIZE)
173
 
                return FALSE;
174
 
 
175
 
        return (cache_data->requested_size > requested_size) || (cache_data->requested_size == GTH_ORIGINAL_SIZE);
176
 
}
177
 
 
178
 
 
179
 
/* -- LoadRequest -- */
180
 
 
181
 
 
182
 
static LoadRequest *
183
 
load_request_new (GthImagePreloader *preloader)
184
 
{
185
 
        LoadRequest *request;
186
 
 
187
 
        request = g_new0 (LoadRequest, 1);
188
 
        request->ref = 1;
189
 
        request->finalized = FALSE;
190
 
        request->preloader = preloader;
191
 
        request->files = NULL;
192
 
        request->current_file = NULL;
193
 
        request->requested_size = GTH_ORIGINAL_SIZE;
194
 
        request->result = NULL;
195
 
        request->cancellable = NULL;
196
 
 
197
 
        return request;
198
 
}
199
 
 
200
 
 
201
 
static LoadRequest *
202
 
load_request_ref (LoadRequest *request)
203
 
{
204
 
        request->ref++;
205
 
        return request;
206
 
}
207
 
 
208
 
 
209
 
static void
210
 
load_request_unref (LoadRequest *request)
211
 
{
212
 
        if (request == NULL)
213
 
                return;
214
 
        if (--request->ref > 0)
215
 
                return;
216
 
 
217
 
        _g_object_unref (request->cancellable);
218
 
        _g_object_unref (request->result);
219
 
        _g_object_list_unref (request->files);
220
 
        g_free (request);
 
103
/* -- Preloader -- */
 
104
 
 
105
 
 
106
static Preloader *
 
107
preloader_new (GthImagePreloader *self)
 
108
{
 
109
        Preloader *preloader;
 
110
 
 
111
        preloader = g_new0 (Preloader, 1);
 
112
        preloader->ref = 1;
 
113
        preloader->self = self;
 
114
        preloader->file_data = NULL;
 
115
        preloader->loaded = FALSE;
 
116
        preloader->error = FALSE;
 
117
        preloader->finalized = FALSE;
 
118
        preloader->loader = gth_image_loader_new (NULL, NULL);
 
119
        gth_image_loader_set_preferred_format (preloader->loader, GTH_IMAGE_FORMAT_CAIRO_SURFACE);
 
120
        preloader->image = NULL;
 
121
        preloader->original_width = -1;
 
122
        preloader->original_height = -1;
 
123
 
 
124
        return preloader;
 
125
}
 
126
 
 
127
 
 
128
static Preloader *
 
129
preloader_ref (Preloader *preloader)
 
130
{
 
131
        preloader->ref++;
 
132
        return preloader;
 
133
}
 
134
 
 
135
 
 
136
static void
 
137
preloader_unref (Preloader *preloader)
 
138
{
 
139
        if (preloader == NULL)
 
140
                return;
 
141
        if (--preloader->ref > 0)
 
142
                return;
 
143
        _g_object_unref (preloader->image);
 
144
        _g_object_unref (preloader->loader);
 
145
        _g_object_unref (preloader->file_data);
 
146
        g_free (preloader);
 
147
}
 
148
 
 
149
 
 
150
static void
 
151
preloader_set_file_data (Preloader    *preloader,
 
152
                         GthFileData  *file_data)
 
153
{
 
154
        g_return_if_fail (preloader != NULL);
 
155
 
 
156
        if (preloader->file_data != file_data) {
 
157
                _g_object_unref (preloader->file_data);
 
158
                preloader->file_data = NULL;
 
159
        }
 
160
 
 
161
        if (file_data != NULL)
 
162
                preloader->file_data = g_object_ref (file_data);
 
163
 
 
164
        preloader->loaded = FALSE;
 
165
        preloader->error = FALSE;
 
166
}
 
167
 
 
168
 
 
169
static gboolean
 
170
preloader_has_valid_content_for_file (Preloader   *preloader,
 
171
                                      GthFileData *file_data)
 
172
{
 
173
        return ((preloader->file_data != NULL)
 
174
                && preloader->loaded
 
175
                && ! preloader->error
 
176
                && (preloader->image != NULL)
 
177
                && g_file_equal (preloader->file_data->file, file_data->file)
 
178
                && (_g_time_val_cmp (gth_file_data_get_modification_time (file_data),
 
179
                                     gth_file_data_get_modification_time (preloader->file_data)) == 0));
 
180
}
 
181
 
 
182
 
 
183
static gboolean
 
184
preloader_needs_to_load (Preloader *preloader)
 
185
{
 
186
        return ((preloader->token == preloader->self->priv->token)
 
187
                 && (preloader->file_data != NULL)
 
188
                 && ! preloader->error
 
189
                 && ! preloader->loaded);
 
190
}
 
191
 
 
192
 
 
193
static gboolean
 
194
preloader_needs_second_step (Preloader *preloader)
 
195
{
 
196
        return ((preloader->token == preloader->self->priv->token)
 
197
                && ! preloader->error
 
198
                && (preloader->requested_size != -1)
 
199
                && ((preloader->original_width > preloader->requested_size) || (preloader->original_height > preloader->requested_size))
 
200
                && (preloader->image != NULL)
 
201
                && ! gth_image_is_animation (preloader->image));
 
202
}
 
203
 
 
204
 
 
205
static int
 
206
preloader_signal_to_emit (Preloader *preloader)
 
207
{
 
208
        int signal = -1;
 
209
 
 
210
        switch (preloader->self->priv->load_policy) {
 
211
        case GTH_LOAD_POLICY_ONE_STEP:
 
212
                signal = REQUESTED_READY;
 
213
                break;
 
214
 
 
215
        case GTH_LOAD_POLICY_TWO_STEPS:
 
216
                if (preloader->self->priv->requested_size == -1)
 
217
                        signal = ORIGINAL_SIZE_READY;
 
218
                else
 
219
                        signal = REQUESTED_READY;
 
220
                break;
 
221
        }
 
222
 
 
223
        g_assert (signal != -1);
 
224
 
 
225
        return signal;
221
226
}
222
227
 
223
228
 
224
229
/* -- GthImagePreloader -- */
225
230
 
226
231
 
 
232
static void load_data_free (LoadData *load_data);
 
233
 
 
234
 
227
235
static void
228
236
gth_image_preloader_finalize (GObject *object)
229
237
{
230
238
        GthImagePreloader *self;
231
 
        GList             *scan;
 
239
        int                i;
232
240
 
233
241
        g_return_if_fail (object != NULL);
234
242
        g_return_if_fail (GTH_IS_IMAGE_PRELOADER (object));
235
243
 
236
244
        self = GTH_IMAGE_PRELOADER (object);
237
245
 
238
 
        if (self->priv->load_next_id != 0)
239
 
                g_source_remove (self->priv->load_next_id);
240
 
        load_request_unref (self->priv->last_request);
241
 
        load_request_unref (self->priv->current_request);
242
 
 
243
 
        for (scan = self->priv->requests; scan; scan = scan->next) {
244
 
                LoadRequest *request = scan->data;
245
 
 
246
 
                request->finalized = TRUE;
247
 
                load_request_unref (request);
248
 
        }
249
 
        g_list_free (self->priv->requests);
250
 
 
251
 
        g_object_unref (self->priv->loader);
252
 
        g_queue_free_full (self->priv->cache, (GDestroyNotify) cache_data_unref);
 
246
        if (self->priv->load_id != 0) {
 
247
                g_source_remove (self->priv->load_id);
 
248
                self->priv->load_id = 0;
 
249
        }
 
250
 
 
251
        if (self->priv->next_load_data != NULL) {
 
252
                load_data_free (self->priv->next_load_data);
 
253
                self->priv->next_load_data = NULL;
 
254
        }
 
255
 
 
256
        for (i = 0; i < self->priv->n_preloaders; i++) {
 
257
                self->priv->loader[i]->finalized = TRUE;
 
258
                preloader_unref (self->priv->loader[i]);
 
259
                self->priv->loader[i] = NULL;
 
260
        }
 
261
        g_free (self->priv->loader);
 
262
        _g_object_unref (self->priv->requested_file);
 
263
        g_object_unref (self->priv->cancellable);
253
264
 
254
265
        G_OBJECT_CLASS (gth_image_preloader_parent_class)->finalize (object);
255
266
}
262
273
 
263
274
        g_type_class_add_private (class, sizeof (GthImagePreloaderPrivate));
264
275
 
 
276
        gth_image_preloader_signals[REQUESTED_READY] =
 
277
                g_signal_new ("requested_ready",
 
278
                              G_TYPE_FROM_CLASS (class),
 
279
                              G_SIGNAL_RUN_LAST,
 
280
                              G_STRUCT_OFFSET (GthImagePreloaderClass, requested_ready),
 
281
                              NULL, NULL,
 
282
                              gth_marshal_VOID__OBJECT_OBJECT_INT_INT_POINTER,
 
283
                              G_TYPE_NONE,
 
284
                              5,
 
285
                              G_TYPE_OBJECT,
 
286
                              G_TYPE_OBJECT,
 
287
                              G_TYPE_INT,
 
288
                              G_TYPE_INT,
 
289
                              G_TYPE_POINTER);
 
290
        gth_image_preloader_signals[ORIGINAL_SIZE_READY] =
 
291
                g_signal_new ("original_size_ready",
 
292
                              G_TYPE_FROM_CLASS (class),
 
293
                              G_SIGNAL_RUN_LAST,
 
294
                              G_STRUCT_OFFSET (GthImagePreloaderClass, original_size_ready),
 
295
                              NULL, NULL,
 
296
                              gth_marshal_VOID__OBJECT_OBJECT_INT_INT_POINTER,
 
297
                              G_TYPE_NONE,
 
298
                              5,
 
299
                              G_TYPE_OBJECT,
 
300
                              G_TYPE_OBJECT,
 
301
                              G_TYPE_INT,
 
302
                              G_TYPE_INT,
 
303
                              G_TYPE_POINTER);
 
304
 
265
305
        object_class = G_OBJECT_CLASS (class);
266
306
        object_class->finalize = gth_image_preloader_finalize;
267
307
}
271
311
gth_image_preloader_init (GthImagePreloader *self)
272
312
{
273
313
        self->priv = GTH_IMAGE_PRELOADER_GET_PRIVATE (self);
274
 
        self->priv->requests = NULL;
275
 
        self->priv->current_request = NULL;
276
 
        self->priv->last_request = NULL;
277
 
        self->priv->loader = gth_image_loader_new (NULL, NULL);
278
 
        self->priv->cache = g_queue_new ();
279
 
        self->priv->load_next_id = 0;
 
314
        self->priv->loader = NULL;
 
315
        self->priv->requested = -1;
 
316
        self->priv->requested_file = NULL;
 
317
        self->priv->current = -1;
 
318
        self->priv->load_policy = GTH_LOAD_POLICY_ONE_STEP;
 
319
        self->priv->cancellable = g_cancellable_new ();
 
320
        self->priv->token = 0;
280
321
}
281
322
 
282
323
 
283
324
GthImagePreloader *
284
 
gth_image_preloader_new (void)
285
 
{
286
 
        return (GthImagePreloader *) g_object_new (GTH_TYPE_IMAGE_PRELOADER, NULL);
 
325
gth_image_preloader_new (GthLoadPolicy load_policy,
 
326
                         int           n_preloaders)
 
327
{
 
328
        GthImagePreloader *self;
 
329
        int                i;
 
330
 
 
331
        g_return_val_if_fail (n_preloaders > 0, NULL);
 
332
 
 
333
        self = g_object_new (GTH_TYPE_IMAGE_PRELOADER, NULL);
 
334
 
 
335
        self->priv->n_preloaders = n_preloaders;
 
336
        self->priv->load_policy = load_policy;
 
337
        self->priv->loader = g_new0 (Preloader *, self->priv->n_preloaders);
 
338
        for (i = 0; i < self->priv->n_preloaders; i++)
 
339
                self->priv->loader[i] = preloader_new (self);
 
340
 
 
341
        return self;
 
342
}
 
343
 
 
344
 
 
345
void
 
346
gth_image_prelaoder_set_load_policy (GthImagePreloader *self,
 
347
                                     GthLoadPolicy      policy)
 
348
{
 
349
        self->priv->load_policy = policy;
 
350
}
 
351
 
 
352
 
 
353
GthLoadPolicy
 
354
gth_image_prelaoder_get_load_policy  (GthImagePreloader *self)
 
355
{
 
356
        return self->priv->load_policy;
287
357
}
288
358
 
289
359
 
290
360
/* -- gth_image_preloader_load -- */
291
361
 
292
362
 
293
 
static CacheData *
294
 
_gth_image_preloader_lookup_same_size (GthImagePreloader        *self,
295
 
                                       GthFileData              *requested_file,
296
 
                                       int                       requested_size)
297
 
{
298
 
        GList *scan;
299
 
 
300
 
        for (scan = self->priv->cache->head; scan; scan = scan->next) {
301
 
                CacheData *cache_data = scan->data;
302
 
                if (cache_data_is_valid_for_request (cache_data, requested_file, requested_size))
303
 
                        return cache_data;
304
 
        }
305
 
 
306
 
        return NULL;
307
 
}
308
 
 
309
 
 
310
 
static CacheData *
311
 
_gth_image_preloader_lookup_bigger_size (GthImagePreloader      *self,
312
 
                                         GthFileData            *requested_file,
313
 
                                         int                     requested_size)
314
 
{
315
 
        GList *scan;
316
 
 
317
 
        if (requested_file != GTH_MODIFIED_IMAGE)
318
 
                return NULL;
319
 
 
320
 
        if (requested_size == GTH_ORIGINAL_SIZE)
321
 
                return NULL;
322
 
 
323
 
        for (scan = self->priv->cache->head; scan; scan = scan->next) {
324
 
                CacheData *cache_data = scan->data;
325
 
                if (cache_data_has_better_quality_for_request (cache_data, requested_file, requested_size))
326
 
                        return cache_data;
327
 
        }
328
 
 
329
 
        return NULL;
330
 
}
331
 
 
332
 
 
333
 
static void
334
 
_gth_image_preloader_request_finished (GthImagePreloader *self,
335
 
                                       LoadRequest       *load_request)
336
 
{
337
 
        if (self->priv->last_request == load_request)
338
 
                self->priv->last_request = NULL;
339
 
        load_request_unref (self->priv->current_request);
340
 
        self->priv->current_request = NULL;
341
 
        load_request_unref (load_request);
342
 
}
343
 
 
344
 
 
345
 
static void
346
 
_gth_image_preloader_load_current_file (GthImagePreloader *self,
347
 
                                        LoadRequest       *request);
 
363
static void start_next_loader (GthImagePreloader *self);
348
364
 
349
365
 
350
366
static gboolean
351
 
load_current_file (gpointer user_data)
 
367
load_next (gpointer data)
352
368
{
353
 
        LoadRequest       *request = user_data;
354
 
        GthImagePreloader *self = request->preloader;
355
 
 
356
 
        g_return_val_if_fail (request->current_file != NULL, FALSE);
357
 
 
358
 
        if (self->priv->load_next_id > 0) {
359
 
                g_source_remove (self->priv->load_next_id);
360
 
                self->priv->load_next_id = 0;
 
369
        GthImagePreloader *self = data;
 
370
 
 
371
        if (self->priv->load_id != 0) {
 
372
                g_source_remove (self->priv->load_id);
 
373
                self->priv->load_id = 0;
361
374
        }
362
 
        _gth_image_preloader_load_current_file (self, request);
 
375
        start_next_loader (self);
363
376
 
364
377
        return FALSE;
365
378
}
366
379
 
367
380
 
368
 
static void
369
 
_gth_image_preloader_request_completed (GthImagePreloader *self,
370
 
                                        LoadRequest       *request,
371
 
                                        CacheData         *cache_data)
372
 
{
373
 
        if (request->current_file == request->requested_file) {
374
 
                if (cache_data != NULL) {
375
 
#ifdef DEBUG_PRELOADER
376
 
                        {
377
 
                                cairo_surface_t *image;
378
 
                                int              w, h;
379
 
 
380
 
                                image = NULL;
381
 
                                if (cache_data->image != NULL)
382
 
                                        image = gth_image_get_cairo_surface (cache_data->image);
383
 
                                if (image != NULL) {
384
 
                                        w = cairo_image_surface_get_width (image);
385
 
                                        h = cairo_image_surface_get_height (image);
386
 
                                }
387
 
                                else {
388
 
                                        w = 0;
389
 
                                        h = 0;
390
 
                                }
391
 
 
392
 
                                g_print (" --> done @%d [%dx%d]\n",
393
 
                                                cache_data->requested_size,
394
 
                                                w,
395
 
                                                h);
396
 
                        }
397
 
#endif
398
 
 
399
 
                        g_simple_async_result_set_op_res_gpointer (request->result,
400
 
                                                                   cache_data_ref (cache_data),
401
 
                                                                   (GDestroyNotify) cache_data_unref);
402
 
                        g_simple_async_result_complete_in_idle (request->result);
403
 
                }
404
 
                else {
405
 
                        GError *error;
406
 
 
407
 
                        error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_NOT_FOUND, "");
408
 
                        g_simple_async_result_set_from_error (request->result, error);
409
 
 
410
 
                        g_error_free (error);
411
 
                }
412
 
        }
413
 
 
414
 
        /* queue the next file */
415
 
 
416
 
        g_return_if_fail (request->current_file != NULL);
417
 
 
418
 
        cache_data = NULL;
419
 
        do {
420
 
                GthFileData *requested_file;
421
 
 
422
 
                request->current_file = request->current_file->next;
423
 
                if (request->current_file == NULL) {
424
 
                        _gth_image_preloader_request_finished (self, request);
425
 
                        return;
426
 
                }
427
 
 
428
 
                requested_file = (GthFileData *) request->current_file->data;
429
 
                cache_data = _gth_image_preloader_lookup_same_size (self,
430
 
                                                                    requested_file,
431
 
                                                                    request->requested_size);
432
 
        }
433
 
        while (cache_data != NULL);
434
 
 
435
 
        if (self->priv->load_next_id > 0)
436
 
                g_source_remove (self->priv->load_next_id);
437
 
        self->priv->load_next_id = g_timeout_add (LOAD_NEXT_FILE_DELAY,
438
 
                                                  load_current_file,
439
 
                                                  request);
440
 
}
441
 
 
442
 
 
443
 
static void
444
 
_gth_image_preloader_start_request (GthImagePreloader *self,
445
 
                                    LoadRequest       *request);
446
 
 
447
 
 
448
 
static void
449
 
_gth_image_preloader_add_to_cache (GthImagePreloader *self,
450
 
                                   CacheData         *cache_data)
451
 
{
452
 
        if (g_queue_get_length (self->priv->cache) > CACHE_MAX_SIZE) {
453
 
                CacheData *oldest = g_queue_pop_tail (self->priv->cache);
454
 
                cache_data_unref (oldest);
455
 
        }
456
 
        g_queue_push_head (self->priv->cache, cache_data);
457
 
}
458
 
 
459
 
 
460
381
typedef struct {
461
 
        LoadRequest *request;
462
 
        gboolean     resize_to_requested_size;
463
 
} LoadData;
464
 
 
465
 
 
466
 
static LoadData *
467
 
load_data_new (LoadRequest *request,
468
 
               gboolean     resize_image)
469
 
{
470
 
        LoadData *load_data;
471
 
 
472
 
        load_data = g_new0 (LoadData, 1);
473
 
        load_data->request = load_request_ref (request);
474
 
        load_data->resize_to_requested_size = resize_image;
475
 
 
476
 
        return load_data;
477
 
}
478
 
 
479
 
 
480
 
static void
481
 
load_data_free (LoadData *load_data)
482
 
{
483
 
        load_request_unref (load_data->request);
484
 
        g_free (load_data);
485
 
}
486
 
 
487
 
 
488
 
#ifdef RESIZE_TO_REQUESTED_SIZE
489
 
 
490
 
static void
491
 
image_scale_ready_cb (GObject      *source_object,
492
 
                      GAsyncResult *result,
493
 
                      gpointer      user_data)
494
 
{
495
 
        LoadData          *load_data = user_data;
496
 
        LoadRequest       *request = load_data->request;
497
 
        GthImagePreloader *self = request->preloader;
498
 
        cairo_surface_t   *surface;
499
 
        GError            *error = NULL;
500
 
        int                original_width;
501
 
        int                original_height;
502
 
        CacheData         *cache_data;
503
 
 
504
 
        if (request->finalized) {
505
 
                load_data_free (load_data);
506
 
                return;
507
 
        }
508
 
 
509
 
        surface = _cairo_image_surface_scale_finish (result, &error);
510
 
 
511
 
        if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)
512
 
            || (self->priv->last_request != request))
513
 
        {
514
 
                load_data_free (load_data);
515
 
                if (error != NULL)
516
 
                        g_error_free (error);
517
 
                cairo_surface_destroy (surface);
518
 
                _gth_image_preloader_request_finished (self, request);
519
 
 
520
 
                if (self->priv->last_request != NULL)
521
 
                        _gth_image_preloader_start_request (self, self->priv->last_request);
522
 
 
523
 
                return;
524
 
        }
525
 
 
526
 
        if (! _cairo_image_surface_get_original_size (surface, &original_width, &original_height)) {
527
 
                original_width = cairo_image_surface_get_width (surface);
528
 
                original_height = cairo_image_surface_get_height (surface);
529
 
        }
530
 
        cache_data = cache_data_new ();
531
 
        cache_data->file_data = _g_object_ref (request->current_file->data);
532
 
        cache_data->image = (surface != NULL) ? gth_image_new_for_surface (surface) : NULL;
533
 
        cache_data->original_width = (surface != NULL) ? original_width : -1;
534
 
        cache_data->original_height = (surface != NULL) ? original_height : -1;
535
 
        cache_data->requested_size = request->requested_size;
536
 
        cache_data->error = error;
537
 
        _gth_image_preloader_add_to_cache (self, cache_data);
538
 
        _gth_image_preloader_request_completed (self, request, cache_data);
539
 
 
540
 
        cairo_surface_destroy (surface);
541
 
        load_data_free (load_data);
542
 
}
543
 
 
544
 
 
545
 
static gboolean
546
 
_gth_image_preloader_resize_at_requested_size (GthImagePreloader *self,
547
 
                                               LoadRequest       *request,
548
 
                                               GthImage          *image)
549
 
{
550
 
        cairo_surface_t *surface;
551
 
        int              new_width;
552
 
        int              new_height;
553
 
        gboolean         scaled;
554
 
 
555
 
        surface = gth_image_get_cairo_surface (image);
556
 
        new_width = cairo_image_surface_get_width (surface);
557
 
        new_height = cairo_image_surface_get_height (surface);
558
 
        scaled = scale_keeping_ratio (&new_width,
559
 
                                      &new_height,
560
 
                                      request->requested_size,
561
 
                                      request->requested_size,
562
 
                                      FALSE);
563
 
 
564
 
        if (scaled)
565
 
                _cairo_image_surface_scale_async (surface,
566
 
                                                  new_width,
567
 
                                                  new_height,
568
 
                                                  SCALE_FILTER_GOOD,
569
 
                                                  request->cancellable,
570
 
                                                  image_scale_ready_cb,
571
 
                                                  load_data_new (request, FALSE));
572
 
 
573
 
        cairo_surface_destroy (surface);
574
 
 
575
 
        return scaled;
576
 
}
577
 
 
578
 
#endif
 
382
        Preloader   *preloader;
 
383
        GthFileData *file_data;
 
384
        int          requested_size;
 
385
} LoadRequest;
 
386
 
 
387
 
 
388
static void
 
389
load_request_free (LoadRequest *load_request)
 
390
{
 
391
        preloader_unref (load_request->preloader);
 
392
        g_object_unref (load_request->file_data);
 
393
        g_free (load_request);
 
394
}
 
395
 
 
396
 
 
397
static void assign_loaders (LoadData *load_data);
579
398
 
580
399
 
581
400
static void
583
402
                       GAsyncResult *result,
584
403
                       gpointer      user_data)
585
404
{
586
 
        LoadData          *load_data = user_data;
587
 
        LoadRequest       *request = load_data->request;
588
 
        GthImagePreloader *self = request->preloader;
589
 
        GthImage          *image = NULL;
590
 
        int                original_width;
591
 
        int                original_height;
592
 
        gboolean           loaded_original;
593
 
        GError            *error = NULL;
594
 
        gboolean           success;
595
 
        CacheData         *cache_data;
596
 
        gboolean           resized;
 
405
        LoadRequest        *load_request = user_data;
 
406
        Preloader          *preloader = load_request->preloader;
 
407
        GthImagePreloader  *self = preloader->self;
 
408
        GthImage           *image = NULL;
 
409
        int                 original_width;
 
410
        int                 original_height;
 
411
        GError             *error = NULL;
 
412
        gboolean            success;
 
413
        int                 interval;
597
414
 
598
 
        if (request->finalized) {
599
 
#ifdef DEBUG_PRELOADER
600
 
                g_print (" --> cancelled\n");
601
 
#endif
602
 
                load_data_free (load_data);
 
415
        if (preloader->finalized) {
 
416
                load_request_free (load_request);
603
417
                return;
604
418
        }
605
419
 
 
420
        self->priv->current = -1;
 
421
 
606
422
        success = gth_image_loader_load_finish  (GTH_IMAGE_LOADER (source_object),
607
423
                                                 result,
608
424
                                                 &image,
609
425
                                                 &original_width,
610
426
                                                 &original_height,
611
 
                                                 &loaded_original,
612
427
                                                 &error);
613
428
 
614
429
        if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)
615
 
            || (self->priv->last_request != request))
 
430
            || ! g_file_equal (load_request->file_data->file, preloader->file_data->file)
 
431
            || (preloader->token != self->priv->token))
616
432
        {
617
 
#ifdef DEBUG_PRELOADER
618
 
                g_print (" --> cancelled\n");
619
 
#endif
620
 
                load_data_free (load_data);
 
433
                load_request_free (load_request);
621
434
                if (error != NULL)
622
435
                        g_error_free (error);
623
436
                _g_object_unref (image);
624
 
                _gth_image_preloader_request_finished (self, request);
625
 
 
626
 
                if (self->priv->last_request != NULL)
627
 
                        _gth_image_preloader_start_request (self, self->priv->last_request);
 
437
 
 
438
                if (self->priv->next_load_data != NULL) {
 
439
                        assign_loaders (self->priv->next_load_data);
 
440
                        start_next_loader (self);
 
441
 
 
442
                        load_data_free (self->priv->next_load_data);
 
443
                        self->priv->next_load_data = NULL;
 
444
                }
628
445
 
629
446
                return;
630
447
        }
631
448
 
632
 
        cache_data = cache_data_new ();
633
 
        cache_data->file_data = g_object_ref (request->current_file->data);
634
 
        cache_data->image = success ? _g_object_ref (image) : NULL;
635
 
        cache_data->original_width = success ? original_width : -1;
636
 
        cache_data->original_height = success ? original_height : -1;
637
 
        cache_data->requested_size = request->requested_size;
638
 
        cache_data->loaded_original = loaded_original;
639
 
        cache_data->error = error;
640
 
        _gth_image_preloader_add_to_cache (self, cache_data);
641
 
 
642
 
        if ((request->requested_size > 0) && loaded_original)
643
 
                load_data->resize_to_requested_size = TRUE;
644
 
 
645
 
        if ((image != NULL) && (gth_image_get_is_zoomable (image) || gth_image_get_is_animation (image)))
646
 
                load_data->resize_to_requested_size = FALSE;
647
 
 
648
 
        resized = FALSE;
649
 
#ifdef RESIZE_TO_REQUESTED_SIZE
650
 
        if (load_data->resize_to_requested_size)
651
 
                resized = _gth_image_preloader_resize_at_requested_size (self, request, cache_data->image);
652
 
#endif
653
 
 
654
 
        if (! resized)
655
 
                _gth_image_preloader_request_completed (self, request, cache_data);
656
 
 
 
449
        interval = NOT_REQUESTED_INTERVAL;
 
450
 
 
451
        _g_object_unref (preloader->image);
 
452
        preloader->image = _g_object_ref (image);
 
453
        preloader->original_width = original_width;
 
454
        preloader->original_height = original_height;
 
455
        preloader->loaded = success;
 
456
        preloader->error  = ! success;
 
457
        preloader->requested_size = load_request->requested_size;
 
458
 
 
459
        if (_g_file_equal (load_request->file_data->file, self->priv->requested_file)) {
 
460
#if DEBUG_PRELOADER
 
461
                debug (DEBUG_INFO, "loaded [requested] %s => %s [size: %d]", (error == NULL) ? "ready" : "error", g_file_get_uri (preloader->file_data->file), preloader->requested_size);
 
462
#endif
 
463
 
 
464
                g_signal_emit (G_OBJECT (self),
 
465
                               gth_image_preloader_signals[preloader_signal_to_emit (preloader)],
 
466
                               0,
 
467
                               preloader->file_data,
 
468
                               preloader->image,
 
469
                               preloader->original_width,
 
470
                               preloader->original_height,
 
471
                               error);
 
472
 
 
473
                /* Reload only if the original size is bigger then the
 
474
                 * requested size, and if the image is not an animation. */
 
475
 
 
476
                if (preloader_needs_second_step (preloader)) {
 
477
                        /* Reload the image at the original size */
 
478
                        preloader->loaded = FALSE;
 
479
                        preloader->requested_size = -1;
 
480
                        interval = SECOND_STEP_INTERVAL;
 
481
                }
 
482
                else
 
483
                        interval = REQUESTED_INTERVAL;
 
484
        }
 
485
#if DEBUG_PRELOADER
 
486
        else
 
487
                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);
 
488
#endif
 
489
 
 
490
        if (self->priv->load_id == 0)
 
491
                self->priv->load_id = g_timeout_add (interval, load_next, self);
 
492
 
 
493
        load_request_free (load_request);
657
494
        _g_object_unref (image);
658
 
        load_data_free (load_data);
659
 
}
660
 
 
661
 
 
662
 
static void
663
 
_gth_image_preloader_load_current_file (GthImagePreloader *self,
664
 
                                        LoadRequest       *request)
665
 
{
666
 
        GthFileData *requested_file;
667
 
        CacheData   *cache_data;
668
 
        gboolean     ignore_requested_size;
669
 
 
670
 
        g_return_if_fail (request->current_file != NULL);
671
 
        requested_file = (GthFileData *) request->current_file->data;
672
 
 
673
 
        /* search the file at the requested size */
674
 
 
675
 
        cache_data = _gth_image_preloader_lookup_same_size (self,
676
 
                                                            requested_file,
677
 
                                                            request->requested_size);
678
 
        if (cache_data != NULL) {
679
 
                _gth_image_preloader_request_completed (self, request, cache_data);
680
 
                return;
681
 
        }
682
 
 
683
 
        /* search the file at a bigger size */
684
 
 
685
 
        cache_data = _gth_image_preloader_lookup_bigger_size (self,
686
 
                                                              requested_file,
687
 
                                                              request->requested_size);
688
 
        if (cache_data != NULL) {
689
 
#ifdef RESIZE_TO_REQUESTED_SIZE
690
 
                if (! _gth_image_preloader_resize_at_requested_size (self, request, cache_data->image))
691
 
#endif
692
 
                _gth_image_preloader_request_completed (self, request, cache_data);
693
 
                return;
694
 
        }
695
 
 
696
 
        /* load the file at the requested size */
697
 
 
698
 
        if (requested_file == GTH_MODIFIED_IMAGE) {
699
 
                /* not found */
700
 
                _gth_image_preloader_request_completed (self, request, NULL);
701
 
                return;
702
 
        }
703
 
 
704
 
        ignore_requested_size = (request->requested_size > 0) && ! g_file_is_native (requested_file->file);
705
 
 
706
 
#ifdef DEBUG_PRELOADER
707
 
        g_print ("load %s @%d\n", g_file_get_uri (requested_file->file), ignore_requested_size ? -1 : request->requested_size);
708
 
#endif
709
 
 
710
 
        gth_image_loader_load (self->priv->loader,
711
 
                               requested_file,
712
 
                               ignore_requested_size ? -1 : request->requested_size,
713
 
                               (request->current_file == request->files) ? G_PRIORITY_HIGH : G_PRIORITY_DEFAULT,
714
 
                               request->cancellable,
715
 
                               image_loader_ready_cb,
716
 
                               load_data_new (request, ignore_requested_size));
717
 
}
718
 
 
719
 
 
720
 
static void
721
 
_gth_image_preloader_start_request (GthImagePreloader *self,
722
 
                                    LoadRequest       *request)
723
 
{
724
 
        load_request_unref (self->priv->current_request);
725
 
        self->priv->current_request = load_request_ref (request);
726
 
 
727
 
        request->current_file = request->files;
728
 
        _gth_image_preloader_load_current_file (self, request);
729
 
}
730
 
 
731
 
 
732
 
static void
733
 
_gth_image_preloader_cancel_current_request (GthImagePreloader *self)
734
 
{
735
 
        if (self->priv->current_request == NULL)
736
 
                return;
737
 
 
738
 
        if (self->priv->load_next_id > 0) {
739
 
                g_source_remove (self->priv->load_next_id);
740
 
                self->priv->load_next_id = 0;
741
 
 
742
 
                _gth_image_preloader_request_finished (self, self->priv->current_request);
743
 
                _gth_image_preloader_start_request (self, self->priv->last_request);
744
 
        }
 
495
}
 
496
 
 
497
 
 
498
static Preloader *
 
499
current_preloader (GthImagePreloader *self)
 
500
{
 
501
        return (self->priv->current == -1) ? NULL : self->priv->loader[self->priv->current];
 
502
}
 
503
 
 
504
 
 
505
static Preloader *
 
506
requested_preloader (GthImagePreloader *self)
 
507
{
 
508
        return (self->priv->requested == -1) ? NULL : self->priv->loader[self->priv->requested];
 
509
}
 
510
 
 
511
 
 
512
static void
 
513
start_next_loader (GthImagePreloader *self)
 
514
{
 
515
        int        i;
 
516
        Preloader *preloader;
 
517
 
 
518
        i = -1;
 
519
 
 
520
        if (preloader_needs_to_load (requested_preloader (self))) {
 
521
                i = self->priv->requested;
 
522
        }
 
523
        else {
 
524
                int n = 0;
 
525
 
 
526
                if  (self->priv->current == -1)
 
527
                        i = 0;
 
528
                else
 
529
                        i = (self->priv->current + 1) % self->priv->n_preloaders;
 
530
 
 
531
                for (i = 0; n < self->priv->n_preloaders; i = (i + 1) % self->priv->n_preloaders) {
 
532
                        if (preloader_needs_to_load (self->priv->loader[i]))
 
533
                                break;
 
534
                        n++;
 
535
                }
 
536
 
 
537
                if (n >= self->priv->n_preloaders)
 
538
                        i = -1;
 
539
        }
 
540
 
 
541
        self->priv->current = i;
 
542
        preloader = current_preloader (self);
 
543
 
 
544
        if (preloader != NULL) {
 
545
                LoadRequest *load_request;
 
546
 
 
547
#if DEBUG_PRELOADER
 
548
                {
 
549
                        char *uri;
 
550
 
 
551
                        uri = g_file_get_uri (preloader->file_data->file);
 
552
                        debug (DEBUG_INFO, "load %s [size: %d]", uri, preloader->requested_size);
 
553
                        g_free (uri);
 
554
                }
 
555
#endif
 
556
 
 
557
                _g_object_unref (preloader->image);
 
558
                preloader->image = NULL;
 
559
 
 
560
                load_request = g_new0 (LoadRequest, 1);
 
561
                load_request->preloader = preloader_ref (preloader);
 
562
                load_request->file_data = g_object_ref (preloader->file_data);
 
563
                load_request->requested_size = preloader->requested_size;
 
564
 
 
565
                g_cancellable_reset (preloader->self->priv->cancellable);
 
566
                gth_image_loader_load (preloader->loader,
 
567
                                       preloader->file_data,
 
568
                                       preloader->requested_size,
 
569
                                       (i == self->priv->requested) ? G_PRIORITY_HIGH : G_PRIORITY_DEFAULT,
 
570
                                       preloader->self->priv->cancellable,
 
571
                                       image_loader_ready_cb,
 
572
                                       load_request);
 
573
        }
 
574
#if DEBUG_PRELOADER
745
575
        else
746
 
                g_cancellable_cancel (self->priv->current_request->cancellable);
 
576
                debug (DEBUG_INFO, "done");
 
577
#endif
 
578
}
 
579
 
 
580
 
 
581
static void
 
582
load_data_free (LoadData *load_data)
 
583
{
 
584
        int i;
 
585
 
 
586
        if (load_data == NULL)
 
587
                return;
 
588
 
 
589
        for (i = 0; i < load_data->n_files; i++)
 
590
                g_object_unref (load_data->files[i]);
 
591
        g_free (load_data->files);
 
592
        g_free (load_data);
 
593
}
 
594
 
 
595
 
 
596
static void
 
597
assign_loaders (LoadData *load_data)
 
598
{
 
599
        GthImagePreloader *self = load_data->self;
 
600
        gboolean          *file_assigned;
 
601
        gboolean          *loader_assigned;
 
602
        int                i, j;
 
603
 
 
604
        if (load_data->token != self->priv->token)
 
605
                return;
 
606
 
 
607
        file_assigned = g_new (gboolean, self->priv->n_preloaders);
 
608
        loader_assigned = g_new (gboolean, self->priv->n_preloaders);
 
609
        for (i = 0; i < self->priv->n_preloaders; i++) {
 
610
                Preloader *preloader = self->priv->loader[i];
 
611
 
 
612
                loader_assigned[i] = FALSE;
 
613
                file_assigned[i] = FALSE;
 
614
 
 
615
                if (preloader->loaded && ! preloader->error)
 
616
                        preloader->token = load_data->token;
 
617
        }
 
618
 
 
619
        self->priv->requested = -1;
 
620
 
 
621
        for (j = 0; j < load_data->n_files; j++) {
 
622
                GthFileData *file_data = load_data->files[j];
 
623
 
 
624
                if (file_data == NULL)
 
625
                        continue;
 
626
 
 
627
                /* check whether the image has already been loaded. */
 
628
 
 
629
                for (i = 0; i < self->priv->n_preloaders; i++) {
 
630
                        Preloader *preloader = self->priv->loader[i];
 
631
 
 
632
                        if (preloader_has_valid_content_for_file (preloader, file_data)) {
 
633
                                loader_assigned[i] = TRUE;
 
634
                                file_assigned[j] = TRUE;
 
635
 
 
636
                                if (_g_file_equal (file_data->file, load_data->requested->file)) {
 
637
                                        self->priv->requested = i;
 
638
 
 
639
                                        g_signal_emit (G_OBJECT (self),
 
640
                                                        gth_image_preloader_signals[preloader_signal_to_emit (preloader)],
 
641
                                                        0,
 
642
                                                        preloader->file_data,
 
643
                                                        preloader->image,
 
644
                                                        preloader->original_width,
 
645
                                                        preloader->original_height,
 
646
                                                        NULL);
 
647
 
 
648
#if DEBUG_PRELOADER
 
649
                                        debug (DEBUG_INFO, "[requested] preloaded %s [size: %d]", g_file_get_uri (preloader->file_data->file), preloader->requested_size);
 
650
#endif
 
651
 
 
652
                                        if (preloader_needs_second_step (preloader)) {
 
653
                                                /* Reload the image at the original size */
 
654
                                                preloader->loaded = FALSE;
 
655
                                                preloader->requested_size = -1;
 
656
                                        }
 
657
                                }
 
658
 
 
659
#if DEBUG_PRELOADER
 
660
                                {
 
661
                                        char *uri;
 
662
 
 
663
                                        uri = g_file_get_uri (file_data->file);
 
664
                                        debug (DEBUG_INFO, "[=] [%d] <- %s", i, uri);
 
665
                                        g_free (uri);
 
666
                                }
 
667
#endif
 
668
 
 
669
                                break;
 
670
                        }
 
671
                }
 
672
        }
 
673
 
 
674
        /* assign the remaining files */
 
675
 
 
676
        for (j = 0; j < load_data->n_files; j++) {
 
677
                GthFileData *file_data = load_data->files[j];
 
678
                Preloader   *preloader;
 
679
                int          k;
 
680
 
 
681
                if (file_data == NULL)
 
682
                        continue;
 
683
 
 
684
                if (file_assigned[j])
 
685
                        continue;
 
686
 
 
687
                /* find the first non-assigned loader */
 
688
                for (k = 0; (k < self->priv->n_preloaders) && loader_assigned[k]; k++)
 
689
                        /* void */;
 
690
 
 
691
                g_return_if_fail (k < self->priv->n_preloaders);
 
692
 
 
693
                loader_assigned[k] = TRUE;
 
694
 
 
695
                preloader = self->priv->loader[k];
 
696
                preloader_set_file_data (preloader, file_data);
 
697
                preloader->requested_size = _g_file_equal (file_data->file, load_data->requested->file) ? load_data->requested_size  : -1;
 
698
                /* force the use of the single step policy if the file is not local, in order to speed-up loading. */
 
699
                if (! g_file_is_native (file_data->file))
 
700
                        preloader->requested_size = -1;
 
701
                preloader->token = load_data->token;
 
702
 
 
703
                if (_g_file_equal (file_data->file, load_data->requested->file)) {
 
704
                        self->priv->requested = k;
 
705
 
 
706
#if DEBUG_PRELOADER
 
707
                        {
 
708
                                char *uri;
 
709
 
 
710
                                uri = g_file_get_uri (file_data->file);
 
711
                                debug (DEBUG_INFO, "[requested] %s", uri);
 
712
                                g_free (uri);
 
713
                        }
 
714
#endif
 
715
                }
 
716
 
 
717
#if DEBUG_PRELOADER
 
718
                {
 
719
                        char *uri;
 
720
 
 
721
                        uri = g_file_get_uri (file_data->file);
 
722
                        debug (DEBUG_INFO, "[+] [%d] <- %s", k, uri);
 
723
                        g_free (uri);
 
724
                }
 
725
#endif
 
726
        }
 
727
 
 
728
        g_free (loader_assigned);
 
729
        g_free (file_assigned);
747
730
}
748
731
 
749
732
 
764
747
 
765
748
 
766
749
void
767
 
gth_image_preloader_load (GthImagePreloader      *self,
768
 
                          GthFileData            *requested,
769
 
                          int                     requested_size,
770
 
                          GCancellable           *cancellable,
771
 
                          GAsyncReadyCallback     callback,
772
 
                          gpointer                user_data,
773
 
                          int                     n_files,
 
750
gth_image_preloader_load (GthImagePreloader *self,
 
751
                          GthFileData       *requested,
 
752
                          int                requested_size,
774
753
                          ...)
775
754
{
776
 
        LoadRequest *request;
 
755
        LoadData    *load_data;
 
756
        int          n;
777
757
        va_list      args;
778
 
 
779
 
#ifdef DEBUG_PRELOADER
780
 
        g_print ("request %s @%d\n", g_file_get_uri (requested->file), requested_size);
781
 
#endif
782
 
 
783
 
        request = load_request_new (self);
784
 
        request->requested_size = requested_size;
785
 
        request->files = g_list_prepend (request->files, gth_file_data_dup (requested));
786
 
        va_start (args, n_files);
787
 
        while (n_files-- > 0) {
788
 
                GthFileData *file_data;
789
 
                GthFileData *checked_file_data;
790
 
 
791
 
                file_data = va_arg (args, GthFileData *);
792
 
                checked_file_data = check_file (file_data);
 
758
        GthFileData *file_data;
 
759
 
 
760
        self->priv->token++;
 
761
 
 
762
        _g_object_unref (self->priv->requested_file);
 
763
        self->priv->requested_file = g_file_dup (requested->file);
 
764
 
 
765
        if (self->priv->next_load_data != NULL) {
 
766
                load_data_free (self->priv->next_load_data);
 
767
                self->priv->next_load_data = NULL;
 
768
        }
 
769
 
 
770
        load_data = g_new0 (LoadData, 1);
 
771
        load_data->self = self;
 
772
        load_data->token = self->priv->token;
 
773
        load_data->requested = gth_file_data_dup (requested);
 
774
        load_data->requested_size = requested_size;
 
775
        load_data->files = g_new0 (GthFileData *, self->priv->n_preloaders);
 
776
 
 
777
        n = 0;
 
778
        load_data->files[n++] = load_data->requested;
 
779
        va_start (args, requested_size);
 
780
        while ((n < self->priv->n_preloaders) && (file_data = va_arg (args, GthFileData *)) != NULL) {
 
781
                GthFileData *checked_file_data = check_file (file_data);
793
782
                if (checked_file_data != NULL)
794
 
                        request->files = g_list_prepend (request->files, checked_file_data);
 
783
                        load_data->files[n++] = checked_file_data;
795
784
        }
796
785
        va_end (args);
797
 
        request->files = g_list_reverse (request->files);
798
 
        request->requested_file = request->files;
799
 
        request->result = g_simple_async_result_new (G_OBJECT (self),
800
 
                                                     callback,
801
 
                                                     user_data,
802
 
                                                     gth_image_preloader_load);
803
 
        request->cancellable = (cancellable != NULL) ? g_object_ref (cancellable) : g_cancellable_new ();
804
 
 
805
 
        self->priv->last_request = request;
806
 
        if (self->priv->current_request != NULL)
807
 
                _gth_image_preloader_cancel_current_request (self);
808
 
        else
809
 
                _gth_image_preloader_start_request (self, self->priv->last_request);
810
 
}
811
 
 
812
 
 
813
 
gboolean
814
 
gth_image_preloader_load_finish (GthImagePreloader       *self,
815
 
                                 GAsyncResult            *result,
816
 
                                 GthFileData            **requested,
817
 
                                 GthImage               **image,
818
 
                                 int                     *requested_size,
819
 
                                 int                     *original_width,
820
 
                                 int                     *original_height,
821
 
                                 GError                 **error)
822
 
{
823
 
        CacheData *cache_data;
824
 
 
825
 
        g_return_val_if_fail (g_simple_async_result_is_valid (result, G_OBJECT (self), gth_image_preloader_load), FALSE);
826
 
 
827
 
        cache_data = g_simple_async_result_get_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result));
828
 
        g_return_val_if_fail (cache_data != NULL, FALSE);
829
 
 
830
 
        if (cache_data->error != NULL) {
831
 
                if (error != NULL)
832
 
                        *error = g_error_copy (cache_data->error);
833
 
                return FALSE;
834
 
        }
835
 
 
836
 
        if (requested != NULL)
837
 
                *requested = _g_object_ref (cache_data->file_data);
838
 
        if (image != NULL)
839
 
                *image = _g_object_ref (cache_data->image);
840
 
        if (requested_size != NULL)
841
 
                *requested_size = cache_data->requested_size;
842
 
        if (original_width != NULL)
843
 
                *original_width = cache_data->original_width;
844
 
        if (original_height != NULL)
845
 
                *original_height = cache_data->original_height;
846
 
 
847
 
        return TRUE;
848
 
}
849
 
 
850
 
 
851
 
void
852
 
gth_image_preloader_set_modified_image (GthImagePreloader *self,
853
 
                                        cairo_surface_t   *image)
854
 
{
855
 
        GList     *scan;
856
 
        CacheData *cache_data;
857
 
 
858
 
        /* delete the modified image from the cache */
859
 
 
860
 
        for (scan = self->priv->cache->head; scan; /* void */) {
861
 
                GList *next = scan->next;
862
 
 
863
 
                cache_data = scan->data;
864
 
                if (cache_data->file_data == GTH_MODIFIED_IMAGE)
865
 
                        g_queue_delete_link (self->priv->cache, scan);
866
 
                scan = next;
867
 
        }
868
 
 
869
 
        if (image == NULL)
870
 
                return;
871
 
 
872
 
        /* add the modified image to the cache */
873
 
 
874
 
        cache_data = cache_data_new ();
875
 
        cache_data->file_data = GTH_MODIFIED_IMAGE;
876
 
        cache_data->image = gth_image_new_for_surface (image);
877
 
        cache_data->original_width = -1;
878
 
        cache_data->original_height = -1;
879
 
        cache_data->requested_size = -1;
880
 
        cache_data->error = NULL;
881
 
        _gth_image_preloader_add_to_cache (self, cache_data);
882
 
}
883
 
 
884
 
 
885
 
cairo_surface_t *
886
 
gth_image_preloader_get_modified_image (GthImagePreloader *self)
887
 
{
888
 
        GList *scan;
889
 
 
890
 
        for (scan = self->priv->cache->head; scan; scan = scan->next) {
891
 
                CacheData *cache_data = scan->data;
892
 
 
893
 
                if ((cache_data->file_data == GTH_MODIFIED_IMAGE) && (cache_data->requested_size == -1))
894
 
                        return gth_image_get_cairo_surface (cache_data->image);
 
786
        load_data->n_files = n;
 
787
 
 
788
        if (self->priv->current != -1) {
 
789
                Preloader *preloader;
 
790
 
 
791
                preloader = current_preloader (self);
 
792
                if (preloader != NULL) {
 
793
                        self->priv->next_load_data = load_data;
 
794
                        g_cancellable_cancel (preloader->self->priv->cancellable);
 
795
                        return;
 
796
                }
 
797
        }
 
798
 
 
799
        assign_loaders (load_data);
 
800
        start_next_loader (self);
 
801
 
 
802
        load_data_free (load_data);
 
803
}
 
804
 
 
805
 
 
806
GthImageLoader *
 
807
gth_image_preloader_get_loader (GthImagePreloader *self,
 
808
                                GthFileData       *file_data)
 
809
{
 
810
        int i;
 
811
 
 
812
        g_return_val_if_fail (self != NULL, NULL);
 
813
 
 
814
        if (file_data == NULL)
 
815
                return NULL;
 
816
 
 
817
        for (i = 0; i < self->priv->n_preloaders; i++) {
 
818
                Preloader *preloader = self->priv->loader[i];
 
819
 
 
820
                if (preloader_has_valid_content_for_file (preloader, file_data))
 
821
                        return preloader->loader;
895
822
        }
896
823
 
897
824
        return NULL;
898
825
}
 
826
 
 
827
 
 
828
GthFileData *
 
829
gth_image_preloader_get_requested (GthImagePreloader *self)
 
830
{
 
831
        Preloader *preloader;
 
832
 
 
833
        preloader = requested_preloader (self);
 
834
        return (preloader != NULL) ? preloader->file_data : NULL;
 
835
}