Mercurial > geeqie
annotate src/thumb_standard.c @ 1672:994169573393
Complete commit @1747 (intltool usage)
With using intltool the localisation will fail cause of missing
desktop.in file. Also the old desktop files are obsoleted by this
commit.
Also it is not necessary any more to have a './' in front of the files
in POTFILES.in.
author | mow |
---|---|
date | Sat, 27 Jun 2009 22:57:56 +0000 |
parents | c776b1310ca6 |
children | 46284779a897 |
rev | line source |
---|---|
9 | 1 /* |
196 | 2 * Geeqie |
79
528e3432e0c0
Thu Oct 19 07:23:37 2006 John Ellis <johne@verizon.net>
gqview
parents:
66
diff
changeset
|
3 * (C) 2006 John Ellis |
1284 | 4 * Copyright (C) 2008 - 2009 The Geeqie Team |
9 | 5 * |
6 * Author: John Ellis | |
7 * | |
8 * This software is released under the GNU General Public License (GNU GPL). | |
9 * Please read the included file COPYING for more information. | |
10 * This software comes with no warranty of any kind, use at your own risk! | |
11 */ | |
12 | |
13 | |
281 | 14 #include "main.h" |
9 | 15 #include "thumb_standard.h" |
16 | |
17 #include "image-load.h" | |
18 #include "md5-util.h" | |
19 #include "pixbuf_util.h" | |
20 #include "ui_fileops.h" | |
838 | 21 #include "filedata.h" |
839 | 22 #include "exif.h" |
1288 | 23 #include "metadata.h" |
9 | 24 |
25 | |
26 /* | |
27 * This thumbnail caching implementation attempts to conform | |
28 * to the Thumbnail Managing Standard proposed on freedesktop.org | |
29 * The standard is documented here: | |
30 * http://triq.net/~jens/thumbnail-spec/index.html | |
31 * (why isn't it actually hosted on freedesktop.org?) | |
32 * | |
33 * This code attempts to conform to version 0.7.0 of the standard. | |
34 * | |
35 * Notes: | |
36 * > Validation of the thumb's embedded uri is a simple strcmp between our | |
37 * version of the escaped uri and the thumb's escaped uri. But not all uri | |
38 * escape functions escape the same set of chars, comparing the unescaped | |
39 * versions may be more accurate. | |
40 * > Only Thumb::URI and Thumb::MTime are stored in a thumb at this time. | |
41 * Storing the Size, Width, Height should probably be implemented. | |
42 */ | |
43 | |
44 | |
45 #define THUMB_SIZE_NORMAL 128 | |
46 #define THUMB_SIZE_LARGE 256 | |
47 | |
48 #define THUMB_MARKER_URI "tEXt::Thumb::URI" | |
49 #define THUMB_MARKER_MTIME "tEXt::Thumb::MTime" | |
50 #define THUMB_MARKER_SIZE "tEXt::Thumb::Size" | |
51 #define THUMB_MARKER_WIDTH "tEXt::Thumb::Image::Width" | |
52 #define THUMB_MARKER_HEIGHT "tEXt::Thumb::Image::Height" | |
53 #define THUMB_MARKER_APP "tEXt::Software" | |
54 | |
55 #define THUMB_PERMS_FOLDER 0700 | |
56 #define THUMB_PERMS_THUMB 0600 | |
57 | |
58 | |
59 | |
60 /* | |
61 *----------------------------------------------------------------------------- | |
62 * thumbnail loader | |
63 *----------------------------------------------------------------------------- | |
64 */ | |
65 | |
66 | |
67 static void thumb_loader_std_error_cb(ImageLoader *il, gpointer data); | |
1009
dd311dae857a
fixed thumbnail loader for the new raw preview interface
nadvornik
parents:
972
diff
changeset
|
68 static gint thumb_loader_std_setup(ThumbLoaderStd *tl, FileData *fd); |
dd311dae857a
fixed thumbnail loader for the new raw preview interface
nadvornik
parents:
972
diff
changeset
|
69 static gint thumb_loader_std_setup_path(ThumbLoaderStd *tl, const gchar *path); |
9 | 70 |
71 | |
72 ThumbLoaderStd *thumb_loader_std_new(gint width, gint height) | |
73 { | |
74 ThumbLoaderStd *tl; | |
75 | |
76 tl = g_new0(ThumbLoaderStd, 1); | |
77 | |
78 tl->standard_loader = TRUE; | |
79 tl->requested_width = width; | |
80 tl->requested_height = height; | |
333 | 81 tl->cache_enable = options->thumbnails.enable_caching; |
9 | 82 |
83 return tl; | |
84 } | |
85 | |
86 void thumb_loader_std_set_callbacks(ThumbLoaderStd *tl, | |
87 ThumbLoaderStdFunc func_done, | |
88 ThumbLoaderStdFunc func_error, | |
89 ThumbLoaderStdFunc func_progress, | |
90 gpointer data) | |
91 { | |
92 if (!tl) return; | |
93 | |
94 tl->func_done = func_done; | |
95 tl->func_error = func_error; | |
96 tl->func_progress = func_progress; | |
97 tl->data = data; | |
98 } | |
99 | |
100 static void thumb_loader_std_reset(ThumbLoaderStd *tl) | |
101 { | |
102 image_loader_free(tl->il); | |
103 tl->il = NULL; | |
104 | |
838 | 105 file_data_unref(tl->fd); |
106 tl->fd = NULL; | |
9 | 107 |
108 g_free(tl->thumb_path); | |
109 tl->thumb_path = NULL; | |
110 | |
111 g_free(tl->thumb_uri); | |
112 tl->thumb_uri = NULL; | |
113 tl->local_uri = NULL; | |
114 | |
115 tl->thumb_path_local = FALSE; | |
116 | |
117 tl->cache_hit = FALSE; | |
118 | |
119 tl->source_mtime = 0; | |
120 tl->source_size = 0; | |
121 tl->source_mode = 0; | |
122 | |
123 tl->progress = 0.0; | |
124 } | |
125 | |
1446 | 126 static gchar *thumb_std_cache_path(const gchar *path, const gchar *uri, gboolean local, |
9 | 127 const gchar *cache_subfolder) |
128 { | |
129 gchar *result = NULL; | |
130 gchar *md5_text; | |
131 guchar digest[16]; | |
716
c534b8cecc1f
thumb_std_cache_path(): use g_build_filename() and simplify.
zas_
parents:
671
diff
changeset
|
132 gchar *name; |
9 | 133 |
134 if (!path || !uri || !cache_subfolder) return NULL; | |
135 | |
716
c534b8cecc1f
thumb_std_cache_path(): use g_build_filename() and simplify.
zas_
parents:
671
diff
changeset
|
136 md5_get_digest((guchar *)uri, strlen(uri), digest); |
c534b8cecc1f
thumb_std_cache_path(): use g_build_filename() and simplify.
zas_
parents:
671
diff
changeset
|
137 md5_text = md5_digest_to_text(digest); |
c534b8cecc1f
thumb_std_cache_path(): use g_build_filename() and simplify.
zas_
parents:
671
diff
changeset
|
138 |
c534b8cecc1f
thumb_std_cache_path(): use g_build_filename() and simplify.
zas_
parents:
671
diff
changeset
|
139 if (!md5_text) return NULL; |
c534b8cecc1f
thumb_std_cache_path(): use g_build_filename() and simplify.
zas_
parents:
671
diff
changeset
|
140 |
c534b8cecc1f
thumb_std_cache_path(): use g_build_filename() and simplify.
zas_
parents:
671
diff
changeset
|
141 name = g_strconcat(md5_text, THUMB_NAME_EXTENSION, NULL); |
c534b8cecc1f
thumb_std_cache_path(): use g_build_filename() and simplify.
zas_
parents:
671
diff
changeset
|
142 |
9 | 143 if (local) |
144 { | |
716
c534b8cecc1f
thumb_std_cache_path(): use g_build_filename() and simplify.
zas_
parents:
671
diff
changeset
|
145 gchar *base = remove_level_from_path(path); |
9 | 146 |
716
c534b8cecc1f
thumb_std_cache_path(): use g_build_filename() and simplify.
zas_
parents:
671
diff
changeset
|
147 result = g_build_filename(base, THUMB_FOLDER_LOCAL, cache_subfolder, name, NULL); |
9 | 148 g_free(base); |
149 } | |
150 else | |
151 { | |
716
c534b8cecc1f
thumb_std_cache_path(): use g_build_filename() and simplify.
zas_
parents:
671
diff
changeset
|
152 result = g_build_filename(homedir(), THUMB_FOLDER_GLOBAL, cache_subfolder, name, NULL); |
9 | 153 } |
154 | |
716
c534b8cecc1f
thumb_std_cache_path(): use g_build_filename() and simplify.
zas_
parents:
671
diff
changeset
|
155 g_free(name); |
9 | 156 g_free(md5_text); |
157 | |
158 return result; | |
159 } | |
160 | |
1446 | 161 static gchar *thumb_loader_std_cache_path(ThumbLoaderStd *tl, gboolean local, GdkPixbuf *pixbuf, gboolean fail) |
9 | 162 { |
436 | 163 const gchar *folder; |
9 | 164 gint w, h; |
165 | |
838 | 166 if (!tl->fd || !tl->thumb_uri) return NULL; |
9 | 167 |
168 if (pixbuf) | |
169 { | |
170 w = gdk_pixbuf_get_width(pixbuf); | |
171 h = gdk_pixbuf_get_height(pixbuf); | |
172 } | |
173 else | |
174 { | |
175 w = tl->requested_width; | |
176 h = tl->requested_height; | |
177 } | |
178 | |
179 if (fail) | |
180 { | |
436 | 181 folder = THUMB_FOLDER_FAIL; |
9 | 182 } |
183 else if (w > THUMB_SIZE_NORMAL || h > THUMB_SIZE_NORMAL) | |
184 { | |
436 | 185 folder = THUMB_FOLDER_LARGE; |
9 | 186 } |
187 else | |
188 { | |
436 | 189 folder = THUMB_FOLDER_NORMAL; |
9 | 190 } |
191 | |
838 | 192 return thumb_std_cache_path(tl->fd->path, |
9 | 193 (local) ? tl->local_uri : tl->thumb_uri, |
436 | 194 local, folder); |
9 | 195 } |
196 | |
1446 | 197 static gboolean thumb_loader_std_fail_check(ThumbLoaderStd *tl) |
9 | 198 { |
199 gchar *fail_path; | |
1437 | 200 gboolean result = FALSE; |
9 | 201 |
202 fail_path = thumb_loader_std_cache_path(tl, FALSE, NULL, TRUE); | |
203 if (isfile(fail_path)) | |
204 { | |
205 GdkPixbuf *pixbuf; | |
206 | |
207 if (tl->cache_retry) | |
208 { | |
209 pixbuf = NULL; | |
210 } | |
211 else | |
212 { | |
213 gchar *pathl; | |
214 | |
215 pathl = path_from_utf8(fail_path); | |
216 pixbuf = gdk_pixbuf_new_from_file(pathl, NULL); | |
217 g_free(pathl); | |
218 } | |
219 | |
220 if (pixbuf) | |
221 { | |
222 const gchar *mtime_str; | |
223 | |
224 mtime_str = gdk_pixbuf_get_option(pixbuf, THUMB_MARKER_MTIME); | |
225 if (mtime_str && strtol(mtime_str, NULL, 10) == tl->source_mtime) | |
226 { | |
227 result = TRUE; | |
838 | 228 DEBUG_1("thumb fail valid: %s", tl->fd->path); |
506
fc9c8a3e1a8b
Handle the newline in DEBUG_N() macro instead of adding one
zas_
parents:
495
diff
changeset
|
229 DEBUG_1(" thumb: %s", fail_path); |
9 | 230 } |
231 | |
232 g_object_unref(G_OBJECT(pixbuf)); | |
233 } | |
234 | |
235 if (!result) unlink_file(fail_path); | |
236 } | |
237 g_free(fail_path); | |
238 | |
239 return result; | |
240 } | |
241 | |
1446 | 242 static gboolean thumb_loader_std_validate(ThumbLoaderStd *tl, GdkPixbuf *pixbuf) |
9 | 243 { |
244 const gchar *valid_uri; | |
245 const gchar *uri; | |
246 const gchar *mtime_str; | |
247 time_t mtime; | |
248 gint w, h; | |
249 | |
250 if (!pixbuf) return FALSE; | |
251 | |
252 w = gdk_pixbuf_get_width(pixbuf); | |
253 h = gdk_pixbuf_get_height(pixbuf); | |
254 | |
255 if (w != THUMB_SIZE_NORMAL && w != THUMB_SIZE_LARGE && | |
256 h != THUMB_SIZE_NORMAL && h != THUMB_SIZE_LARGE) return FALSE; | |
257 | |
258 valid_uri = (tl->thumb_path_local) ? tl->local_uri : tl->thumb_uri; | |
259 | |
260 uri = gdk_pixbuf_get_option(pixbuf, THUMB_MARKER_URI); | |
261 mtime_str = gdk_pixbuf_get_option(pixbuf, THUMB_MARKER_MTIME); | |
262 | |
263 if (!mtime_str || !uri || !valid_uri) return FALSE; | |
264 if (strcmp(uri, valid_uri) != 0) return FALSE; | |
265 | |
266 mtime = strtol(mtime_str, NULL, 10); | |
267 if (tl->source_mtime != mtime) return FALSE; | |
268 | |
269 return TRUE; | |
270 } | |
271 | |
272 static void thumb_loader_std_save(ThumbLoaderStd *tl, GdkPixbuf *pixbuf) | |
273 { | |
274 gchar *base_path; | |
275 gchar *tmp_path; | |
1446 | 276 gboolean fail; |
9 | 277 |
278 if (!tl->cache_enable || tl->cache_hit) return; | |
279 if (tl->thumb_path) return; | |
280 | |
281 if (!pixbuf) | |
282 { | |
283 /* local failures are not stored */ | |
284 if (tl->cache_local) return; | |
285 | |
436 | 286 pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, 1, 1); |
9 | 287 fail = TRUE; |
288 } | |
289 else | |
290 { | |
291 g_object_ref(G_OBJECT(pixbuf)); | |
292 fail = FALSE; | |
293 } | |
294 | |
295 tl->thumb_path = thumb_loader_std_cache_path(tl, tl->cache_local, pixbuf, fail); | |
296 if (!tl->thumb_path) | |
297 { | |
298 g_object_unref(G_OBJECT(pixbuf)); | |
299 return; | |
300 } | |
301 tl->thumb_path_local = tl->cache_local; | |
302 | |
303 /* create thumbnail dir if needed */ | |
304 base_path = remove_level_from_path(tl->thumb_path); | |
305 if (tl->cache_local) | |
306 { | |
307 if (!isdir(base_path)) | |
308 { | |
309 struct stat st; | |
310 gchar *source_base; | |
311 | |
838 | 312 source_base = remove_level_from_path(tl->fd->path); |
9 | 313 if (stat_utf8(source_base, &st)) |
314 { | |
1148
95860439070b
Replace cache_ensure_dir_exists() by new recursive_mkdir_if_not_exists().
zas_
parents:
1055
diff
changeset
|
315 recursive_mkdir_if_not_exists(base_path, st.st_mode); |
9 | 316 } |
317 g_free(source_base); | |
318 } | |
319 } | |
320 else | |
321 { | |
1148
95860439070b
Replace cache_ensure_dir_exists() by new recursive_mkdir_if_not_exists().
zas_
parents:
1055
diff
changeset
|
322 recursive_mkdir_if_not_exists(base_path, THUMB_PERMS_FOLDER); |
9 | 323 } |
324 g_free(base_path); | |
325 | |
838 | 326 DEBUG_1("thumb saving: %s", tl->fd->path); |
506
fc9c8a3e1a8b
Handle the newline in DEBUG_N() macro instead of adding one
zas_
parents:
495
diff
changeset
|
327 DEBUG_1(" saved: %s", tl->thumb_path); |
9 | 328 |
329 /* save thumb, using a temp file then renaming into place */ | |
330 tmp_path = unique_filename(tl->thumb_path, ".tmp", "_", 2); | |
331 if (tmp_path) | |
332 { | |
333 const gchar *mark_uri; | |
334 gchar *mark_app; | |
335 gchar *mark_mtime; | |
336 gchar *pathl; | |
1446 | 337 gboolean success; |
9 | 338 |
339 mark_uri = (tl->cache_local) ? tl->local_uri :tl->thumb_uri; | |
340 | |
288
d1f74154463e
Replace occurences of Geeqie / geeqie by constants defined in main.h.
zas_
parents:
281
diff
changeset
|
341 mark_app = g_strdup_printf("%s %s", GQ_APPNAME, VERSION); |
9 | 342 mark_mtime = g_strdup_printf("%lu", tl->source_mtime); |
343 | |
344 pathl = path_from_utf8(tmp_path); | |
345 success = gdk_pixbuf_save(pixbuf, pathl, "png", NULL, | |
346 THUMB_MARKER_URI, mark_uri, | |
347 THUMB_MARKER_MTIME, mark_mtime, | |
348 THUMB_MARKER_APP, mark_app, | |
349 NULL); | |
350 if (success) | |
351 { | |
352 chmod(pathl, (tl->cache_local) ? tl->source_mode : THUMB_PERMS_THUMB); | |
353 success = rename_file(tmp_path, tl->thumb_path); | |
354 } | |
355 | |
356 g_free(pathl); | |
357 | |
358 g_free(mark_mtime); | |
359 g_free(mark_app); | |
360 | |
361 g_free(tmp_path); | |
506
fc9c8a3e1a8b
Handle the newline in DEBUG_N() macro instead of adding one
zas_
parents:
495
diff
changeset
|
362 if (!success) |
9 | 363 { |
838 | 364 DEBUG_1("thumb save failed: %s", tl->fd->path); |
506
fc9c8a3e1a8b
Handle the newline in DEBUG_N() macro instead of adding one
zas_
parents:
495
diff
changeset
|
365 DEBUG_1(" thumb: %s", tl->thumb_path); |
9 | 366 } |
367 | |
368 } | |
369 | |
370 g_object_unref(G_OBJECT(pixbuf)); | |
371 } | |
372 | |
876
2d8705f33da5
set fallback thumbnail pixbuf only if the loading really fails
nadvornik
parents:
864
diff
changeset
|
373 static void thumb_loader_std_set_fallback(ThumbLoaderStd *tl) |
2d8705f33da5
set fallback thumbnail pixbuf only if the loading really fails
nadvornik
parents:
864
diff
changeset
|
374 { |
2d8705f33da5
set fallback thumbnail pixbuf only if the loading really fails
nadvornik
parents:
864
diff
changeset
|
375 if (tl->fd->thumb_pixbuf) g_object_unref(tl->fd->thumb_pixbuf); |
2d8705f33da5
set fallback thumbnail pixbuf only if the loading really fails
nadvornik
parents:
864
diff
changeset
|
376 tl->fd->thumb_pixbuf = pixbuf_fallback(tl->fd, tl->requested_width, tl->requested_height); |
2d8705f33da5
set fallback thumbnail pixbuf only if the loading really fails
nadvornik
parents:
864
diff
changeset
|
377 } |
2d8705f33da5
set fallback thumbnail pixbuf only if the loading really fails
nadvornik
parents:
864
diff
changeset
|
378 |
1446 | 379 static GdkPixbuf *thumb_loader_std_finish(ThumbLoaderStd *tl, GdkPixbuf *pixbuf, gboolean shrunk) |
9 | 380 { |
381 GdkPixbuf *pixbuf_thumb = NULL; | |
382 GdkPixbuf *result; | |
839 | 383 GdkPixbuf *rotated = NULL; |
9 | 384 gint sw, sh; |
385 | |
839 | 386 |
387 if (!tl->cache_hit && options->image.exif_rotate_enable) | |
388 { | |
389 if (!tl->fd->exif_orientation) | |
390 { | |
1567
c776b1310ca6
added an option to write image orientation to the metadata
nadvornik
parents:
1523
diff
changeset
|
391 tl->fd->exif_orientation = metadata_read_int(tl->fd, ORIENTATION_KEY, EXIF_ORIENTATION_TOP_LEFT); |
839 | 392 } |
393 | |
842
94048d7843ba
do not allocate new buffer for thumbnails with correct orientation
nadvornik
parents:
841
diff
changeset
|
394 if (tl->fd->exif_orientation != EXIF_ORIENTATION_TOP_LEFT) |
94048d7843ba
do not allocate new buffer for thumbnails with correct orientation
nadvornik
parents:
841
diff
changeset
|
395 { |
94048d7843ba
do not allocate new buffer for thumbnails with correct orientation
nadvornik
parents:
841
diff
changeset
|
396 rotated = pixbuf_apply_orientation(pixbuf, tl->fd->exif_orientation); |
94048d7843ba
do not allocate new buffer for thumbnails with correct orientation
nadvornik
parents:
841
diff
changeset
|
397 pixbuf = rotated; |
94048d7843ba
do not allocate new buffer for thumbnails with correct orientation
nadvornik
parents:
841
diff
changeset
|
398 } |
839 | 399 } |
400 | |
9 | 401 sw = gdk_pixbuf_get_width(pixbuf); |
402 sh = gdk_pixbuf_get_height(pixbuf); | |
403 | |
40
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
404 if (tl->cache_enable) |
9 | 405 { |
40
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
406 if (!tl->cache_hit) |
9 | 407 { |
40
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
408 gint cache_w, cache_h; |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
409 |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
410 if (tl->requested_width > THUMB_SIZE_NORMAL || tl->requested_height > THUMB_SIZE_NORMAL) |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
411 { |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
412 cache_w = cache_h = THUMB_SIZE_LARGE; |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
413 } |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
414 else |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
415 { |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
416 cache_w = cache_h = THUMB_SIZE_NORMAL; |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
417 } |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
418 |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
419 if (sw > cache_w || sh > cache_h || shrunk) |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
420 { |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
421 gint thumb_w, thumb_h; |
9 | 422 |
864 | 423 if (pixbuf_scale_aspect(cache_w, cache_h, sw, sh, |
40
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
424 &thumb_w, &thumb_h)) |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
425 { |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
426 pixbuf_thumb = gdk_pixbuf_scale_simple(pixbuf, thumb_w, thumb_h, |
333 | 427 (GdkInterpType)options->thumbnails.quality); |
40
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
428 } |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
429 else |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
430 { |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
431 pixbuf_thumb = pixbuf; |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
432 g_object_ref(G_OBJECT(pixbuf_thumb)); |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
433 } |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
434 |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
435 thumb_loader_std_save(tl, pixbuf_thumb); |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
436 } |
9 | 437 } |
40
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
438 else if (tl->cache_hit && |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
439 tl->cache_local && !tl->thumb_path_local) |
9 | 440 { |
40
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
441 /* A local cache save was requested, but a valid thumb is in $HOME, |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
442 * so specifically save as a local thumbnail. |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
443 */ |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
444 g_free(tl->thumb_path); |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
445 tl->thumb_path = NULL; |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
446 |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
447 tl->cache_hit = FALSE; |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
448 |
838 | 449 DEBUG_1("thumb copied: %s", tl->fd->path); |
40
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
450 |
dcc04a6a58bf
Sat Apr 16 12:29:42 2005 John Ellis <johne@verizon.net>
gqview
parents:
14
diff
changeset
|
451 thumb_loader_std_save(tl, pixbuf); |
9 | 452 } |
453 } | |
454 | |
455 if (sw <= tl->requested_width && sh <= tl->requested_height) | |
456 { | |
457 result = pixbuf; | |
458 g_object_ref(result); | |
459 } | |
460 else | |
461 { | |
462 gint thumb_w, thumb_h; | |
463 | |
464 if (pixbuf_thumb) | |
465 { | |
466 pixbuf = pixbuf_thumb; | |
467 sw = gdk_pixbuf_get_width(pixbuf); | |
468 sh = gdk_pixbuf_get_height(pixbuf); | |
469 } | |
470 | |
864 | 471 if (pixbuf_scale_aspect(tl->requested_width, tl->requested_height, sw, sh, |
9 | 472 &thumb_w, &thumb_h)) |
473 { | |
474 result = gdk_pixbuf_scale_simple(pixbuf, thumb_w, thumb_h, | |
333 | 475 (GdkInterpType)options->thumbnails.quality); |
9 | 476 } |
477 else | |
478 { | |
479 result = pixbuf; | |
480 g_object_ref(result); | |
481 } | |
482 } | |
483 | |
484 if (pixbuf_thumb) g_object_unref(pixbuf_thumb); | |
839 | 485 if (rotated) g_object_unref(rotated); |
9 | 486 |
487 return result; | |
488 } | |
489 | |
1446 | 490 static gboolean thumb_loader_std_next_source(ThumbLoaderStd *tl, gboolean remove_broken) |
9 | 491 { |
492 image_loader_free(tl->il); | |
493 tl->il = NULL; | |
494 | |
495 if (tl->thumb_path) | |
496 { | |
497 if (!tl->thumb_path_local && remove_broken) | |
498 { | |
506
fc9c8a3e1a8b
Handle the newline in DEBUG_N() macro instead of adding one
zas_
parents:
495
diff
changeset
|
499 DEBUG_1("thumb broken, unlinking: %s", tl->thumb_path); |
9 | 500 unlink_file(tl->thumb_path); |
501 } | |
502 | |
503 g_free(tl->thumb_path); | |
504 tl->thumb_path = NULL; | |
505 | |
506 if (!tl->thumb_path_local) | |
507 { | |
508 tl->thumb_path = thumb_loader_std_cache_path(tl, TRUE, NULL, FALSE); | |
1009
dd311dae857a
fixed thumbnail loader for the new raw preview interface
nadvornik
parents:
972
diff
changeset
|
509 if (isfile(tl->thumb_path) && thumb_loader_std_setup_path(tl, tl->thumb_path)) |
9 | 510 { |
511 tl->thumb_path_local = TRUE; | |
512 return TRUE; | |
513 } | |
514 | |
515 g_free(tl->thumb_path); | |
516 tl->thumb_path = NULL; | |
517 } | |
518 | |
1009
dd311dae857a
fixed thumbnail loader for the new raw preview interface
nadvornik
parents:
972
diff
changeset
|
519 if (thumb_loader_std_setup(tl, tl->fd)) return TRUE; |
9 | 520 } |
521 | |
522 thumb_loader_std_save(tl, NULL); | |
523 return FALSE; | |
524 } | |
525 | |
526 static void thumb_loader_std_done_cb(ImageLoader *il, gpointer data) | |
527 { | |
528 ThumbLoaderStd *tl = data; | |
529 GdkPixbuf *pixbuf; | |
530 | |
881
10d0bf784323
Prevent segfault in certain conditions when displaying debug message.
zas_
parents:
876
diff
changeset
|
531 DEBUG_1("thumb image done: %s", tl->fd ? tl->fd->path : "???"); |
1011 | 532 DEBUG_1(" from: %s", image_loader_get_fd(tl->il)->path); |
9 | 533 |
534 pixbuf = image_loader_get_pixbuf(tl->il); | |
535 if (!pixbuf) | |
536 { | |
506
fc9c8a3e1a8b
Handle the newline in DEBUG_N() macro instead of adding one
zas_
parents:
495
diff
changeset
|
537 DEBUG_1("...but no pixbuf"); |
9 | 538 thumb_loader_std_error_cb(il, data); |
539 return; | |
540 } | |
541 | |
542 if (tl->thumb_path && !thumb_loader_std_validate(tl, pixbuf)) | |
543 { | |
544 if (thumb_loader_std_next_source(tl, TRUE)) return; | |
545 | |
546 if (tl->func_error) tl->func_error(tl, tl->data); | |
547 return; | |
548 } | |
549 | |
550 tl->cache_hit = (tl->thumb_path != NULL); | |
551 | |
838 | 552 if (tl->fd) |
553 { | |
845 | 554 if (tl->fd->thumb_pixbuf) g_object_unref(tl->fd->thumb_pixbuf); |
1011 | 555 tl->fd->thumb_pixbuf = thumb_loader_std_finish(tl, pixbuf, image_loader_get_shrunk(il)); |
838 | 556 } |
9 | 557 |
558 if (tl->func_done) tl->func_done(tl, tl->data); | |
559 } | |
560 | |
561 static void thumb_loader_std_error_cb(ImageLoader *il, gpointer data) | |
562 { | |
563 ThumbLoaderStd *tl = data; | |
564 | |
565 /* if at least some of the image is available, go to done */ | |
566 if (image_loader_get_pixbuf(tl->il) != NULL) | |
567 { | |
568 thumb_loader_std_done_cb(il, data); | |
569 return; | |
570 } | |
495 | 571 |
838 | 572 DEBUG_1("thumb image error: %s", tl->fd->path); |
1011 | 573 DEBUG_1(" from: %s", image_loader_get_fd(tl->il)->path); |
9 | 574 |
575 if (thumb_loader_std_next_source(tl, TRUE)) return; | |
576 | |
876
2d8705f33da5
set fallback thumbnail pixbuf only if the loading really fails
nadvornik
parents:
864
diff
changeset
|
577 thumb_loader_std_set_fallback(tl); |
2d8705f33da5
set fallback thumbnail pixbuf only if the loading really fails
nadvornik
parents:
864
diff
changeset
|
578 |
9 | 579 if (tl->func_error) tl->func_error(tl, tl->data); |
580 } | |
581 | |
582 static void thumb_loader_std_progress_cb(ImageLoader *il, gdouble percent, gpointer data) | |
583 { | |
584 ThumbLoaderStd *tl = data; | |
585 | |
586 tl->progress = (gdouble)percent; | |
587 | |
588 if (tl->func_progress) tl->func_progress(tl, tl->data); | |
589 } | |
590 | |
1446 | 591 static gboolean thumb_loader_std_setup(ThumbLoaderStd *tl, FileData *fd) |
9 | 592 { |
1009
dd311dae857a
fixed thumbnail loader for the new raw preview interface
nadvornik
parents:
972
diff
changeset
|
593 tl->il = image_loader_new(fd); |
1036 | 594 image_loader_set_priority(tl->il, G_PRIORITY_LOW); |
9 | 595 |
1521 | 596 /* this will speed up jpegs by up to 3x in some cases */ |
597 if (tl->requested_width <= THUMB_SIZE_NORMAL && | |
598 tl->requested_height <= THUMB_SIZE_NORMAL) | |
9 | 599 { |
1521 | 600 image_loader_set_requested_size(tl->il, THUMB_SIZE_NORMAL, THUMB_SIZE_NORMAL); |
601 } | |
602 else | |
603 { | |
604 image_loader_set_requested_size(tl->il, THUMB_SIZE_LARGE, THUMB_SIZE_LARGE); | |
9 | 605 } |
606 | |
1346
c9949c19a6d0
No space between function name and first parenthesis, it eases greping (see CODING).
zas_
parents:
1288
diff
changeset
|
607 g_signal_connect(G_OBJECT(tl->il), "error", (GCallback)thumb_loader_std_error_cb, tl); |
9 | 608 if (tl->func_progress) |
609 { | |
1346
c9949c19a6d0
No space between function name and first parenthesis, it eases greping (see CODING).
zas_
parents:
1288
diff
changeset
|
610 g_signal_connect(G_OBJECT(tl->il), "percent", (GCallback)thumb_loader_std_progress_cb, tl); |
9 | 611 } |
1346
c9949c19a6d0
No space between function name and first parenthesis, it eases greping (see CODING).
zas_
parents:
1288
diff
changeset
|
612 g_signal_connect(G_OBJECT(tl->il), "done", (GCallback)thumb_loader_std_done_cb, tl); |
9 | 613 |
1012
fe82830ab8fd
converted image loader to a GObject and use signals for notification
nadvornik
parents:
1011
diff
changeset
|
614 if (image_loader_start(tl->il)) |
9 | 615 { |
616 return TRUE; | |
617 } | |
618 | |
619 image_loader_free(tl->il); | |
620 tl->il = NULL; | |
621 return FALSE; | |
622 } | |
623 | |
1446 | 624 static gboolean thumb_loader_std_setup_path(ThumbLoaderStd *tl, const gchar *path) |
1009
dd311dae857a
fixed thumbnail loader for the new raw preview interface
nadvornik
parents:
972
diff
changeset
|
625 { |
dd311dae857a
fixed thumbnail loader for the new raw preview interface
nadvornik
parents:
972
diff
changeset
|
626 FileData *fd = file_data_new_simple(path); |
1446 | 627 gboolean ret = thumb_loader_std_setup(tl, fd); |
1009
dd311dae857a
fixed thumbnail loader for the new raw preview interface
nadvornik
parents:
972
diff
changeset
|
628 file_data_unref(fd); |
dd311dae857a
fixed thumbnail loader for the new raw preview interface
nadvornik
parents:
972
diff
changeset
|
629 return ret; |
dd311dae857a
fixed thumbnail loader for the new raw preview interface
nadvornik
parents:
972
diff
changeset
|
630 } |
dd311dae857a
fixed thumbnail loader for the new raw preview interface
nadvornik
parents:
972
diff
changeset
|
631 |
9 | 632 /* |
633 * Note: Currently local_cache only specifies where to save a _new_ thumb, if | |
634 * a valid existing thumb is found anywhere the local thumb will not be created. | |
635 */ | |
1446 | 636 void thumb_loader_std_set_cache(ThumbLoaderStd *tl, gboolean enable_cache, gboolean local, gboolean retry_failed) |
9 | 637 { |
638 if (!tl) return; | |
639 | |
640 tl->cache_enable = enable_cache; | |
641 tl->cache_local = local; | |
642 tl->cache_retry = retry_failed; | |
643 } | |
644 | |
1446 | 645 gboolean thumb_loader_std_start(ThumbLoaderStd *tl, FileData *fd) |
9 | 646 { |
647 static gchar *thumb_cache = NULL; | |
648 struct stat st; | |
649 | |
838 | 650 if (!tl || !fd) return FALSE; |
9 | 651 |
652 thumb_loader_std_reset(tl); | |
653 | |
654 | |
838 | 655 tl->fd = file_data_ref(fd); |
972 | 656 if (!stat_utf8(fd->path, &st)) |
657 { | |
658 thumb_loader_std_set_fallback(tl); | |
659 return FALSE; | |
660 } | |
9 | 661 tl->source_mtime = st.st_mtime; |
662 tl->source_size = st.st_size; | |
663 tl->source_mode = st.st_mode; | |
664 | |
717 | 665 if (!thumb_cache) thumb_cache = g_build_filename(homedir(), THUMB_FOLDER_GLOBAL, NULL); |
838 | 666 if (strncmp(tl->fd->path, thumb_cache, strlen(thumb_cache)) != 0) |
9 | 667 { |
668 gchar *pathl; | |
669 | |
838 | 670 pathl = path_from_utf8(fd->path); |
9 | 671 tl->thumb_uri = g_filename_to_uri(pathl, NULL, NULL); |
672 tl->local_uri = filename_from_path(tl->thumb_uri); | |
673 g_free(pathl); | |
674 } | |
675 | |
676 if (tl->cache_enable) | |
677 { | |
678 gint found; | |
679 | |
680 tl->thumb_path = thumb_loader_std_cache_path(tl, FALSE, NULL, FALSE); | |
681 tl->thumb_path_local = FALSE; | |
682 | |
683 found = isfile(tl->thumb_path); | |
1009
dd311dae857a
fixed thumbnail loader for the new raw preview interface
nadvornik
parents:
972
diff
changeset
|
684 if (found && thumb_loader_std_setup_path(tl, tl->thumb_path)) return TRUE; |
9 | 685 |
876
2d8705f33da5
set fallback thumbnail pixbuf only if the loading really fails
nadvornik
parents:
864
diff
changeset
|
686 if (thumb_loader_std_fail_check(tl) || |
2d8705f33da5
set fallback thumbnail pixbuf only if the loading really fails
nadvornik
parents:
864
diff
changeset
|
687 !thumb_loader_std_next_source(tl, found)) |
2d8705f33da5
set fallback thumbnail pixbuf only if the loading really fails
nadvornik
parents:
864
diff
changeset
|
688 { |
2d8705f33da5
set fallback thumbnail pixbuf only if the loading really fails
nadvornik
parents:
864
diff
changeset
|
689 thumb_loader_std_set_fallback(tl); |
2d8705f33da5
set fallback thumbnail pixbuf only if the loading really fails
nadvornik
parents:
864
diff
changeset
|
690 return FALSE; |
2d8705f33da5
set fallback thumbnail pixbuf only if the loading really fails
nadvornik
parents:
864
diff
changeset
|
691 } |
2d8705f33da5
set fallback thumbnail pixbuf only if the loading really fails
nadvornik
parents:
864
diff
changeset
|
692 return TRUE; |
9 | 693 } |
694 | |
1009
dd311dae857a
fixed thumbnail loader for the new raw preview interface
nadvornik
parents:
972
diff
changeset
|
695 if (!thumb_loader_std_setup(tl, tl->fd)) |
9 | 696 { |
697 thumb_loader_std_save(tl, NULL); | |
876
2d8705f33da5
set fallback thumbnail pixbuf only if the loading really fails
nadvornik
parents:
864
diff
changeset
|
698 thumb_loader_std_set_fallback(tl); |
9 | 699 return FALSE; |
700 } | |
701 | |
702 return TRUE; | |
703 } | |
704 | |
705 void thumb_loader_std_free(ThumbLoaderStd *tl) | |
706 { | |
707 if (!tl) return; | |
708 | |
709 thumb_loader_std_reset(tl); | |
710 g_free(tl); | |
711 } | |
712 | |
864 | 713 GdkPixbuf *thumb_loader_std_get_pixbuf(ThumbLoaderStd *tl) |
9 | 714 { |
715 GdkPixbuf *pixbuf; | |
716 | |
845 | 717 if (tl && tl->fd && tl->fd->thumb_pixbuf) |
9 | 718 { |
845 | 719 pixbuf = tl->fd->thumb_pixbuf; |
9 | 720 g_object_ref(pixbuf); |
721 } | |
722 else | |
723 { | |
864 | 724 pixbuf = pixbuf_fallback(NULL, tl->requested_width, tl->requested_height); |
9 | 725 } |
726 | |
727 return pixbuf; | |
728 } | |
729 | |
730 | |
731 typedef struct _ThumbValidate ThumbValidate; | |
732 struct _ThumbValidate | |
733 { | |
734 ThumbLoaderStd *tl; | |
735 gchar *path; | |
736 gint days; | |
737 | |
1446 | 738 void (*func_valid)(const gchar *path, gboolean valid, gpointer data); |
9 | 739 gpointer data; |
740 | |
1523 | 741 guint idle_id; /* event source id */ |
9 | 742 }; |
743 | |
744 static void thumb_loader_std_thumb_file_validate_free(ThumbValidate *tv) | |
745 { | |
746 thumb_loader_std_free(tv->tl); | |
747 g_free(tv->path); | |
748 g_free(tv); | |
749 } | |
750 | |
751 void thumb_loader_std_thumb_file_validate_cancel(ThumbLoaderStd *tl) | |
752 { | |
753 ThumbValidate *tv; | |
754 | |
755 if (!tl) return; | |
756 | |
757 tv = tl->data; | |
758 | |
1523 | 759 if (tv->idle_id) |
760 { | |
761 g_source_remove(tv->idle_id); | |
762 tv->idle_id = 0; | |
763 } | |
9 | 764 |
765 thumb_loader_std_thumb_file_validate_free(tv); | |
766 } | |
767 | |
1446 | 768 static void thumb_loader_std_thumb_file_validate_finish(ThumbValidate *tv, gboolean valid) |
9 | 769 { |
770 if (tv->func_valid) tv->func_valid(tv->path, valid, tv->data); | |
771 | |
772 thumb_loader_std_thumb_file_validate_free(tv); | |
773 } | |
774 | |
775 static void thumb_loader_std_thumb_file_validate_done_cb(ThumbLoaderStd *tl, gpointer data) | |
776 { | |
777 ThumbValidate *tv = data; | |
778 GdkPixbuf *pixbuf; | |
1437 | 779 gboolean valid = FALSE; |
9 | 780 |
864 | 781 /* this function is called on success, so the pixbuf should not be a fallback*/ |
782 pixbuf = thumb_loader_std_get_pixbuf(tv->tl); | |
9 | 783 if (pixbuf) |
784 { | |
785 const gchar *uri; | |
786 const gchar *mtime_str; | |
787 | |
788 uri = gdk_pixbuf_get_option(pixbuf, THUMB_MARKER_URI); | |
789 mtime_str = gdk_pixbuf_get_option(pixbuf, THUMB_MARKER_MTIME); | |
790 if (uri && mtime_str) | |
791 { | |
792 if (strncmp(uri, "file:", strlen("file:")) == 0) | |
793 { | |
794 struct stat st; | |
795 gchar *target; | |
796 | |
797 target = g_filename_from_uri(uri, NULL, NULL); | |
798 if (stat(target, &st) == 0 && | |
799 st.st_mtime == strtol(mtime_str, NULL, 10)) | |
800 { | |
801 valid = TRUE; | |
802 } | |
803 g_free(target); | |
804 } | |
805 else | |
806 { | |
807 struct stat st; | |
808 | |
506
fc9c8a3e1a8b
Handle the newline in DEBUG_N() macro instead of adding one
zas_
parents:
495
diff
changeset
|
809 DEBUG_1("thumb uri foreign, doing day check: %s", uri); |
9 | 810 |
811 if (stat_utf8(tv->path, &st)) | |
812 { | |
813 time_t now; | |
814 | |
815 now = time(NULL); | |
816 if (st.st_atime >= now - (time_t)tv->days * 24 * 60 * 60) | |
817 { | |
818 valid = TRUE; | |
819 } | |
820 } | |
821 } | |
822 } | |
823 | |
824 g_object_unref(pixbuf); | |
825 } | |
826 | |
827 thumb_loader_std_thumb_file_validate_finish(tv, valid); | |
828 } | |
829 | |
830 static void thumb_loader_std_thumb_file_validate_error_cb(ThumbLoaderStd *tl, gpointer data) | |
831 { | |
832 ThumbValidate *tv = data; | |
833 | |
834 thumb_loader_std_thumb_file_validate_finish(tv, FALSE); | |
835 } | |
836 | |
1446 | 837 static gboolean thumb_loader_std_thumb_file_validate_idle_cb(gpointer data) |
9 | 838 { |
839 ThumbValidate *tv = data; | |
840 | |
1523 | 841 tv->idle_id = 0; |
9 | 842 thumb_loader_std_thumb_file_validate_finish(tv, FALSE); |
843 | |
844 return FALSE; | |
845 } | |
846 | |
847 ThumbLoaderStd *thumb_loader_std_thumb_file_validate(const gchar *thumb_path, gint allowed_days, | |
1446 | 848 void (*func_valid)(const gchar *path, gboolean valid, gpointer data), |
9 | 849 gpointer data) |
850 { | |
851 ThumbValidate *tv; | |
852 | |
853 tv = g_new0(ThumbValidate, 1); | |
854 | |
855 tv->tl = thumb_loader_std_new(THUMB_SIZE_LARGE, THUMB_SIZE_LARGE); | |
856 thumb_loader_std_set_callbacks(tv->tl, | |
857 thumb_loader_std_thumb_file_validate_done_cb, | |
858 thumb_loader_std_thumb_file_validate_error_cb, | |
859 NULL, | |
860 tv); | |
861 thumb_loader_std_reset(tv->tl); | |
862 | |
863 tv->path = g_strdup(thumb_path); | |
864 tv->days = allowed_days; | |
865 tv->func_valid = func_valid; | |
866 tv->data = data; | |
867 | |
1009
dd311dae857a
fixed thumbnail loader for the new raw preview interface
nadvornik
parents:
972
diff
changeset
|
868 if (!thumb_loader_std_setup_path(tv->tl, thumb_path)) |
9 | 869 { |
870 tv->idle_id = g_idle_add(thumb_loader_std_thumb_file_validate_idle_cb, tv); | |
871 } | |
872 else | |
873 { | |
1523 | 874 tv->idle_id = 0; |
9 | 875 } |
876 | |
877 return tv->tl; | |
878 } | |
879 | |
1446 | 880 static void thumb_std_maint_remove_one(const gchar *source, const gchar *uri, gboolean local, |
9 | 881 const gchar *subfolder) |
882 { | |
883 gchar *thumb_path; | |
884 | |
885 thumb_path = thumb_std_cache_path(source, | |
886 (local) ? filename_from_path(uri) : uri, | |
887 local, subfolder); | |
888 if (isfile(thumb_path)) | |
889 { | |
506
fc9c8a3e1a8b
Handle the newline in DEBUG_N() macro instead of adding one
zas_
parents:
495
diff
changeset
|
890 DEBUG_1("thumb removing: %s", thumb_path); |
9 | 891 unlink_file(thumb_path); |
892 } | |
893 g_free(thumb_path); | |
894 } | |
895 | |
896 /* this also removes local thumbnails (the source is gone so it makes sense) */ | |
897 void thumb_std_maint_removed(const gchar *source) | |
898 { | |
899 gchar *uri; | |
900 gchar *sourcel; | |
901 | |
902 sourcel = path_from_utf8(source); | |
903 uri = g_filename_to_uri(sourcel, NULL, NULL); | |
904 g_free(sourcel); | |
905 | |
906 /* all this to remove a thumbnail? */ | |
907 | |
908 thumb_std_maint_remove_one(source, uri, FALSE, THUMB_FOLDER_NORMAL); | |
909 thumb_std_maint_remove_one(source, uri, FALSE, THUMB_FOLDER_LARGE); | |
910 thumb_std_maint_remove_one(source, uri, FALSE, THUMB_FOLDER_FAIL); | |
911 thumb_std_maint_remove_one(source, uri, TRUE, THUMB_FOLDER_NORMAL); | |
912 thumb_std_maint_remove_one(source, uri, TRUE, THUMB_FOLDER_LARGE); | |
913 | |
914 g_free(uri); | |
915 } | |
916 | |
917 typedef struct _TMaintMove TMaintMove; | |
918 struct _TMaintMove | |
919 { | |
920 gchar *source; | |
921 gchar *dest; | |
922 | |
923 ThumbLoaderStd *tl; | |
924 gchar *source_uri; | |
925 gchar *thumb_path; | |
926 | |
927 gint pass; | |
928 }; | |
929 | |
930 static GList *thumb_std_maint_move_list = NULL; | |
931 static GList *thumb_std_maint_move_tail = NULL; | |
932 | |
933 | |
934 static void thumb_std_maint_move_step(TMaintMove *tm); | |
1446 | 935 static gboolean thumb_std_maint_move_idle(gpointer data); |
9 | 936 |
937 | |
1446 | 938 static void thumb_std_maint_move_validate_cb(const gchar *path, gboolean valid, gpointer data) |
9 | 939 { |
940 TMaintMove *tm = data; | |
941 GdkPixbuf *pixbuf; | |
942 | |
864 | 943 /* this function is called on success, so the pixbuf should not be a fallback*/ |
944 pixbuf = thumb_loader_std_get_pixbuf(tm->tl); | |
9 | 945 if (pixbuf) |
946 { | |
947 const gchar *uri; | |
948 const gchar *mtime_str; | |
949 | |
950 uri = gdk_pixbuf_get_option(pixbuf, THUMB_MARKER_URI); | |
951 mtime_str = gdk_pixbuf_get_option(pixbuf, THUMB_MARKER_MTIME); | |
952 | |
953 if (uri && mtime_str && strcmp(uri, tm->source_uri) == 0) | |
954 { | |
955 gchar *pathl; | |
956 | |
957 /* The validation utility abuses ThumbLoader, and we | |
958 * abuse the utility just to load the thumbnail, | |
959 * but the loader needs to look sane for the save to complete. | |
960 */ | |
961 | |
962 tm->tl->cache_enable = TRUE; | |
963 tm->tl->cache_hit = FALSE; | |
964 tm->tl->cache_local = FALSE; | |
965 | |
838 | 966 file_data_unref(tm->tl->fd); |
967 tm->tl->fd = file_data_new_simple(tm->dest); | |
9 | 968 tm->tl->source_mtime = strtol(mtime_str, NULL, 10); |
969 | |
838 | 970 pathl = path_from_utf8(tm->tl->fd->path); |
9 | 971 g_free(tm->tl->thumb_uri); |
972 tm->tl->thumb_uri = g_filename_to_uri(pathl, NULL, NULL); | |
973 tm->tl->local_uri = filename_from_path(tm->tl->thumb_uri); | |
974 g_free(pathl); | |
975 | |
976 g_free(tm->tl->thumb_path); | |
977 tm->tl->thumb_path = NULL; | |
978 tm->tl->thumb_path_local = FALSE; | |
979 | |
506
fc9c8a3e1a8b
Handle the newline in DEBUG_N() macro instead of adding one
zas_
parents:
495
diff
changeset
|
980 DEBUG_1("thumb move attempting save:"); |
9 | 981 |
982 thumb_loader_std_save(tm->tl, pixbuf); | |
983 } | |
984 | |
506
fc9c8a3e1a8b
Handle the newline in DEBUG_N() macro instead of adding one
zas_
parents:
495
diff
changeset
|
985 DEBUG_1("thumb move unlink: %s", tm->thumb_path); |
9 | 986 unlink_file(tm->thumb_path); |
864 | 987 g_object_unref(pixbuf); |
9 | 988 } |
989 | |
990 thumb_std_maint_move_step(tm); | |
991 } | |
992 | |
993 static void thumb_std_maint_move_step(TMaintMove *tm) | |
994 { | |
995 const gchar *folder; | |
996 | |
997 tm->pass++; | |
998 if (tm->pass > 2) | |
999 { | |
1000 g_free(tm->source); | |
1001 g_free(tm->dest); | |
1002 g_free(tm->source_uri); | |
1003 g_free(tm->thumb_path); | |
1004 g_free(tm); | |
1005 | |
1006 if (thumb_std_maint_move_list) | |
1007 { | |
1008 g_idle_add_full(G_PRIORITY_LOW, thumb_std_maint_move_idle, NULL, NULL); | |
1009 } | |
1010 | |
1011 return; | |
1012 } | |
1013 | |
1014 folder = (tm->pass == 1) ? THUMB_FOLDER_NORMAL : THUMB_FOLDER_LARGE; | |
442 | 1015 |
9 | 1016 g_free(tm->thumb_path); |
1017 tm->thumb_path = thumb_std_cache_path(tm->source, tm->source_uri, FALSE, folder); | |
1018 tm->tl = thumb_loader_std_thumb_file_validate(tm->thumb_path, 0, | |
1019 thumb_std_maint_move_validate_cb, tm); | |
1020 } | |
1021 | |
1446 | 1022 static gboolean thumb_std_maint_move_idle(gpointer data) |
9 | 1023 { |
1024 TMaintMove *tm; | |
1025 gchar *pathl; | |
1026 | |
1027 if (!thumb_std_maint_move_list) return FALSE; | |
1028 | |
1029 tm = thumb_std_maint_move_list->data; | |
1030 | |
1031 thumb_std_maint_move_list = g_list_remove(thumb_std_maint_move_list, tm); | |
1032 if (!thumb_std_maint_move_list) thumb_std_maint_move_tail = NULL; | |
1033 | |
1034 pathl = path_from_utf8(tm->source); | |
1035 tm->source_uri = g_filename_to_uri(pathl, NULL, NULL); | |
1036 g_free(pathl); | |
1037 | |
1038 tm->pass = 0; | |
1039 | |
1040 thumb_std_maint_move_step(tm); | |
1041 | |
1042 return FALSE; | |
1043 } | |
1044 | |
1045 /* This will schedule a move of the thumbnail for source image to dest when idle. | |
1046 * We do this so that file renaming or moving speed is not sacrificed by | |
1047 * moving the thumbnails at the same time because: | |
1048 * | |
1049 * This cache design requires the tedious task of loading the png thumbnails and saving them. | |
1050 * | |
1051 * The thumbnails are processed when the app is idle. If the app | |
1052 * exits early well too bad - they can simply be regenerated from scratch. | |
1053 * | |
1054 * This does not manage local thumbnails (fixme ?) | |
1055 */ | |
1056 void thumb_std_maint_moved(const gchar *source, const gchar *dest) | |
1057 { | |
1058 TMaintMove *tm; | |
1059 | |
1060 tm = g_new0(TMaintMove, 1); | |
1061 tm->source = g_strdup(source); | |
1062 tm->dest = g_strdup(dest); | |
1063 | |
1064 if (!thumb_std_maint_move_list) | |
1065 { | |
1066 g_idle_add_full(G_PRIORITY_LOW, thumb_std_maint_move_idle, NULL, NULL); | |
1067 } | |
1068 | |
827 | 1069 if (thumb_std_maint_move_tail) |
1070 { | |
1071 thumb_std_maint_move_tail = g_list_append(thumb_std_maint_move_tail, tm); | |
1072 thumb_std_maint_move_tail = thumb_std_maint_move_tail->next; | |
1073 } | |
1074 else | |
1075 { | |
1076 thumb_std_maint_move_list = g_list_append(thumb_std_maint_move_list, tm); | |
1077 thumb_std_maint_move_tail = thumb_std_maint_move_list; | |
1078 } | |
9 | 1079 } |
1055
1646720364cf
Adding a vim modeline to all files - patch by Klaus Ethgen
nadvornik
parents:
1036
diff
changeset
|
1080 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */ |