1 /* vi:set et ai sw=2 sts=2 ts=2: */
2 /*-
3 * Copyright (c) 2011 Jannis Pohlmann <jannis@xfce.org>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public
16 * License along with this program; if not, write to the Free
17 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include <thunar/thunar-thumbnail-cache-proxy.h>
26
27 #include <glib.h>
28 #include <glib-object.h>
29 #include <gio/gio.h>
30
31 #include <thunar/thunar-private.h>
32 #include <thunar/thunar-thumbnail-cache.h>
33 #include <thunar/thunar-file.h>
34
35 #define _thumbnail_cache_lock(cache) g_mutex_lock (&((cache)->lock))
36 #define _thumbnail_cache_unlock(cache) g_mutex_unlock (&((cache)->lock))
37
38
39
40 static void thunar_thumbnail_cache_finalize (GObject *object);
41
42
43
44 enum
45 {
46 THUNAR_THUMBNAIL_CACHE_PROXY_AVAILABLE,
47 THUNAR_THUMBNAIL_CACHE_PROXY_WAITING,
48 THUNAR_THUMBNAIL_CACHE_PROXY_FAILED
49 };
50
51 struct _ThunarThumbnailCacheClass
52 {
53 GObjectClass __parent__;
54 };
55
56 struct _ThunarThumbnailCache
57 {
58 GObject __parent__;
59
60 ThunarThumbnailCacheDBus *cache_proxy;
61 int proxy_state;
62
63 GList *move_source_queue;
64 GList *move_target_queue;
65 guint move_queue_idle_id;
66
67 GList *copy_source_queue;
68 GList *copy_target_queue;
69 guint copy_queue_idle_id;
70
71 GList *delete_queue;
72 guint delete_queue_idle_id;
73
74 GList *cleanup_queue;
75 guint cleanup_queue_idle_id;
76
77 GMutex lock;
78 };
79
80
81
G_DEFINE_TYPE(ThunarThumbnailCache,thunar_thumbnail_cache,G_TYPE_OBJECT)82 G_DEFINE_TYPE (ThunarThumbnailCache, thunar_thumbnail_cache, G_TYPE_OBJECT)
83
84
85
86 static void
87 thunar_thumbnail_cache_class_init (ThunarThumbnailCacheClass *klass)
88 {
89 GObjectClass *gobject_class;
90
91 /* Determine the parent type class */
92 thunar_thumbnail_cache_parent_class = g_type_class_peek_parent (klass);
93
94 gobject_class = G_OBJECT_CLASS (klass);
95 gobject_class->finalize = thunar_thumbnail_cache_finalize;
96 }
97
98
99
100 static void
thunar_thumbnail_cache_finalize(GObject * object)101 thunar_thumbnail_cache_finalize (GObject *object)
102 {
103 ThunarThumbnailCache *cache = THUNAR_THUMBNAIL_CACHE (object);
104
105 /* acquire a cache lock */
106 _thumbnail_cache_lock (cache);
107
108 /* drop the move queue idle and all queued files */
109 if (cache->move_queue_idle_id > 0)
110 g_source_remove (cache->move_queue_idle_id);
111 g_list_free_full (cache->move_source_queue, g_object_unref);
112 g_list_free_full (cache->move_target_queue, g_object_unref);
113
114 /* drop the copy queue idle and all queued files */
115 if (cache->copy_queue_idle_id > 0)
116 g_source_remove (cache->copy_queue_idle_id);
117 g_list_free_full (cache->copy_source_queue, g_object_unref);
118 g_list_free_full (cache->copy_target_queue, g_object_unref);
119
120 /* drop the delete queue idle and all queued files */
121 if (cache->delete_queue_idle_id > 0)
122 g_source_remove (cache->delete_queue_idle_id);
123 g_list_free_full (cache->delete_queue, g_object_unref);
124
125 /* drop the cleanup queue idle and all queued files */
126 if (cache->cleanup_queue_idle_id > 0)
127 g_source_remove (cache->cleanup_queue_idle_id);
128 g_list_free_full (cache->cleanup_queue, g_object_unref);
129
130 /* check if we have a valid cache proxy */
131 if (cache->cache_proxy != NULL)
132 g_object_unref (cache->cache_proxy);
133
134 /* release the cache lock */
135 _thumbnail_cache_unlock (cache);
136
137 /* release the mutex itself */
138 g_mutex_clear (&cache->lock);
139
140 (*G_OBJECT_CLASS (thunar_thumbnail_cache_parent_class)->finalize) (object);
141 }
142
143
144
145 static void
thunar_thumbnail_cache_copy_async_reply(ThunarThumbnailCacheDBus * proxy,GAsyncResult * res,gpointer user_data)146 thunar_thumbnail_cache_copy_async_reply (ThunarThumbnailCacheDBus *proxy,
147 GAsyncResult *res,
148 gpointer user_data)
149 {
150 GList *li;
151 ThunarFile *file;
152 GError *error = NULL;
153
154 _thunar_return_if_fail (THUNAR_IS_THUMBNAIL_CACHE_DBUS (proxy));
155
156 if (!thunar_thumbnail_cache_dbus_call_copy_finish (proxy, res, &error))
157 {
158 g_printerr ("ThunarThumbnailCache: failed to call Copy(): %s\n", error->message);
159 }
160 g_clear_error (&error);
161
162 for (li = user_data; li != NULL; li = li->next)
163 {
164 file = thunar_file_cache_lookup (G_FILE (li->data));
165
166 if (G_LIKELY (file != NULL))
167 {
168 /* if visible, let the view know there might be a thumb */
169 thunar_file_changed (file);
170 g_object_unref (file);
171 }
172 }
173
174 g_list_free_full (user_data, g_object_unref);
175 }
176
177
178
179 static void
thunar_thumbnail_cache_move_async_reply(ThunarThumbnailCacheDBus * proxy,GAsyncResult * res,gpointer user_data)180 thunar_thumbnail_cache_move_async_reply (ThunarThumbnailCacheDBus *proxy,
181 GAsyncResult *res,
182 gpointer user_data)
183 {
184 GList *li;
185 ThunarFile *file;
186 GError *error = NULL;
187
188 _thunar_return_if_fail (THUNAR_IS_THUMBNAIL_CACHE_DBUS (proxy));
189
190 if (!thunar_thumbnail_cache_dbus_call_move_finish (proxy, res, &error))
191 {
192 g_printerr ("ThunarThumbnailCache: failed to call Move(): %s\n", error->message);
193 }
194 g_clear_error (&error);
195
196 for (li = user_data; li != NULL; li = li->next)
197 {
198 file = thunar_file_cache_lookup (G_FILE (li->data));
199
200 if (G_LIKELY (file != NULL))
201 {
202 /* if visible, let the view know there might be a thumb */
203 thunar_file_changed (file);
204 g_object_unref (file);
205 }
206 }
207
208 g_list_free_full (user_data, g_object_unref);
209 }
210
211
212
213 static void
thunar_thumbnail_cache_move_async(ThunarThumbnailCache * cache,const gchar ** source_uris,const gchar ** target_uris,gpointer user_data)214 thunar_thumbnail_cache_move_async (ThunarThumbnailCache *cache,
215 const gchar **source_uris,
216 const gchar **target_uris,
217 gpointer user_data)
218 {
219 _thunar_return_if_fail (THUNAR_IS_THUMBNAIL_CACHE (cache));
220 _thunar_return_if_fail (source_uris != NULL);
221 _thunar_return_if_fail (target_uris != NULL);
222
223 /* request a thumbnail cache update asynchronously */
224 thunar_thumbnail_cache_dbus_call_move (cache->cache_proxy,
225 source_uris, target_uris,
226 NULL,
227 (GAsyncReadyCallback)thunar_thumbnail_cache_move_async_reply,
228 user_data);
229 }
230
231
232
233 static void
thunar_thumbnail_cache_copy_async(ThunarThumbnailCache * cache,const gchar ** source_uris,const gchar ** target_uris,gpointer user_data)234 thunar_thumbnail_cache_copy_async (ThunarThumbnailCache *cache,
235 const gchar **source_uris,
236 const gchar **target_uris,
237 gpointer user_data)
238 {
239 _thunar_return_if_fail (THUNAR_IS_THUMBNAIL_CACHE (cache));
240 _thunar_return_if_fail (source_uris != NULL);
241 _thunar_return_if_fail (target_uris != NULL);
242
243 /* request a thumbnail cache update asynchronously */
244 thunar_thumbnail_cache_dbus_call_copy (cache->cache_proxy,
245 source_uris, target_uris,
246 NULL,
247 (GAsyncReadyCallback)thunar_thumbnail_cache_copy_async_reply,
248 user_data);
249 }
250
251
252
253 static void
thunar_thumbnail_cache_delete_async(ThunarThumbnailCache * cache,const gchar ** uris)254 thunar_thumbnail_cache_delete_async (ThunarThumbnailCache *cache,
255 const gchar **uris)
256 {
257 _thunar_return_if_fail (THUNAR_IS_THUMBNAIL_CACHE (cache));
258 _thunar_return_if_fail (uris != NULL);
259
260 /* request a thumbnail cache update asynchronously */
261 thunar_thumbnail_cache_dbus_call_delete (cache->cache_proxy, uris,
262 NULL, NULL, NULL);
263 }
264
265
266
267 static void
thunar_thumbnail_cache_cleanup_async(ThunarThumbnailCache * cache,const gchar * const * base_uris)268 thunar_thumbnail_cache_cleanup_async (ThunarThumbnailCache *cache,
269 const gchar *const *base_uris)
270 {
271 _thunar_return_if_fail (THUNAR_IS_THUMBNAIL_CACHE (cache));
272 _thunar_return_if_fail (base_uris != NULL);
273
274 /* request a thumbnail cache update asynchronously */
275 thunar_thumbnail_cache_dbus_call_cleanup (cache->cache_proxy,
276 (const gchar **)base_uris, 0,
277 NULL, NULL, NULL);
278 }
279
280
281
282 static gboolean
thunar_thumbnail_cache_process_queue(ThunarThumbnailCache * cache,gboolean copy_async)283 thunar_thumbnail_cache_process_queue (ThunarThumbnailCache *cache,
284 gboolean copy_async)
285 {
286 GList *sp;
287 GList *tp;
288 gchar **source_uris;
289 gchar **target_uris;
290 guint n_uris;
291 guint n;
292 GList *source_queue;
293 GList *target_queue;
294
295 _thunar_return_val_if_fail (THUNAR_IS_THUMBNAIL_CACHE (cache), FALSE);
296
297 /* acquire a cache lock */
298 _thumbnail_cache_lock (cache);
299
300 /* steal the lists */
301 if (copy_async)
302 {
303 source_queue = cache->copy_source_queue;
304 cache->copy_source_queue = NULL;
305 target_queue = cache->copy_target_queue;
306 cache->copy_target_queue = NULL;
307 }
308 else
309 {
310 source_queue = cache->move_source_queue;
311 cache->move_source_queue = NULL;
312 target_queue = cache->move_target_queue;
313 cache->move_target_queue = NULL;
314 }
315
316 /* compute how many URIs there are */
317 n_uris = g_list_length (source_queue);
318
319 /* allocate a string array for the URIs */
320 source_uris = g_new0 (gchar *, n_uris + 1);
321 target_uris = g_new0 (gchar *, n_uris + 1);
322
323 /* fill URI array with file URIs from the move queue */
324 for (n = 0,
325 sp = g_list_last (source_queue),
326 tp = g_list_last (target_queue);
327 sp != NULL && tp != NULL;
328 sp = sp->prev, tp = tp->prev, ++n)
329 {
330 source_uris[n] = g_file_get_uri (sp->data);
331 target_uris[n] = g_file_get_uri (tp->data);
332
333 /* release the source object */
334 g_object_unref (sp->data);
335 }
336
337 /* NULL-terminate the URI arrays */
338 source_uris[n] = NULL;
339 target_uris[n] = NULL;
340
341 if (copy_async)
342 {
343 /* asynchronously copy the thumbnails */
344 thunar_thumbnail_cache_copy_async (cache,
345 (const gchar **)source_uris,
346 (const gchar **)target_uris,
347 target_queue);
348 }
349 else
350 {
351 /* asynchronously move the thumbnails */
352 thunar_thumbnail_cache_move_async (cache,
353 (const gchar **)source_uris,
354 (const gchar **)target_uris,
355 target_queue);
356 }
357
358 /* free the URI arrays */
359 g_strfreev (source_uris);
360 g_strfreev (target_uris);
361
362 /* release the move queue lists */
363 g_list_free (source_queue);
364
365 /* release the cache lock */
366 _thumbnail_cache_unlock (cache);
367
368 return FALSE;
369 }
370
371
372
373 static gboolean
thunar_thumbnail_cache_process_move_queue(gpointer user_data)374 thunar_thumbnail_cache_process_move_queue (gpointer user_data)
375 {
376 return thunar_thumbnail_cache_process_queue (user_data, FALSE);
377 }
378
379
380
381 static void
thunar_thumbnail_cache_process_move_queue_destroy(gpointer user_data)382 thunar_thumbnail_cache_process_move_queue_destroy (gpointer user_data)
383 {
384 THUNAR_THUMBNAIL_CACHE (user_data)->move_queue_idle_id = 0;
385 }
386
387
388
389 static gboolean
thunar_thumbnail_cache_process_copy_queue(gpointer user_data)390 thunar_thumbnail_cache_process_copy_queue (gpointer user_data)
391 {
392 return thunar_thumbnail_cache_process_queue (user_data, TRUE);
393 }
394
395
396
397 static void
thunar_thumbnail_cache_process_copy_queue_destroy(gpointer user_data)398 thunar_thumbnail_cache_process_copy_queue_destroy (gpointer user_data)
399 {
400 THUNAR_THUMBNAIL_CACHE (user_data)->copy_queue_idle_id = 0;
401 }
402
403
404
405 static gboolean
thunar_thumbnail_cache_process_delete_queue(ThunarThumbnailCache * cache)406 thunar_thumbnail_cache_process_delete_queue (ThunarThumbnailCache *cache)
407 {
408 GList *lp;
409 gchar **uris;
410 guint n_uris;
411 guint n;
412
413 _thunar_return_val_if_fail (THUNAR_IS_THUMBNAIL_CACHE (cache), FALSE);
414
415 /* acquire a cache lock */
416 _thumbnail_cache_lock (cache);
417
418 /* compute how many URIs there are */
419 n_uris = g_list_length (cache->delete_queue);
420
421 /* allocate a string array for the URIs */
422 uris = g_new0 (gchar *, n_uris + 1);
423
424 /* fill URI array with file URIs from the delete queue */
425 for (lp = g_list_last (cache->delete_queue), n = 0; lp != NULL; lp = lp->prev, ++n)
426 {
427 uris[n] = g_file_get_uri (lp->data);
428
429 /* release the file object */
430 g_object_unref (lp->data);
431 }
432
433 /* NULL-terminate the URI array */
434 uris[n] = NULL;
435
436 /* asynchronously delete the thumbnails */
437 thunar_thumbnail_cache_delete_async (cache, (const gchar **)uris);
438
439 /* free the URI array */
440 g_strfreev (uris);
441
442 /* release the delete queue list */
443 g_list_free (cache->delete_queue);
444 cache->delete_queue = NULL;
445
446 /* reset the delete queue idle ID */
447 cache->delete_queue_idle_id = 0;
448
449 /* release the cache lock */
450 _thumbnail_cache_unlock (cache);
451
452 return FALSE;
453 }
454
455
456
457 static gboolean
thunar_thumbnail_cache_process_cleanup_queue(ThunarThumbnailCache * cache)458 thunar_thumbnail_cache_process_cleanup_queue (ThunarThumbnailCache *cache)
459 {
460 GList *lp;
461 gchar **uris;
462 guint n_uris;
463 guint n;
464
465 _thunar_return_val_if_fail (THUNAR_IS_THUMBNAIL_CACHE (cache), FALSE);
466
467 /* acquire a cache lock */
468 _thumbnail_cache_lock (cache);
469
470 /* compute how many URIs there are */
471 n_uris = g_list_length (cache->cleanup_queue);
472
473 /* allocate a string array for the URIs */
474 uris = g_new0 (gchar *, n_uris + 1);
475
476 #ifndef NDEBUG
477 g_debug ("cleanup:");
478 #endif
479
480 /* fill URI array with file URIs from the cleanup queue */
481 for (lp = g_list_last (cache->cleanup_queue), n = 0; lp != NULL; lp = lp->prev, ++n)
482 {
483 uris[n] = g_file_get_uri (lp->data);
484
485 #ifndef NDEBUG
486 g_debug (" %s", uris[n]);
487 #endif
488
489 /* release the file object */
490 g_object_unref (lp->data);
491 }
492
493 /* NULL-terminate the URI array */
494 uris[n] = NULL;
495
496 /* asynchronously cleanup the thumbnails */
497 thunar_thumbnail_cache_cleanup_async (cache, (const gchar *const *)uris);
498
499 /* free the URI array */
500 g_strfreev (uris);
501
502 /* release the cleanup queue list */
503 g_list_free (cache->cleanup_queue);
504 cache->cleanup_queue = NULL;
505
506 /* reset the cleanup queue idle ID */
507 cache->cleanup_queue_idle_id = 0;
508
509 /* release the cache lock */
510 _thumbnail_cache_unlock (cache);
511
512 return FALSE;
513 }
514
515
516
517 ThunarThumbnailCache *
thunar_thumbnail_cache_new(void)518 thunar_thumbnail_cache_new (void)
519 {
520 return g_object_new (THUNAR_TYPE_THUMBNAIL_CACHE, NULL);
521 }
522
523
524
525 void
thunar_thumbnail_cache_move_file(ThunarThumbnailCache * cache,GFile * source_file,GFile * target_file)526 thunar_thumbnail_cache_move_file (ThunarThumbnailCache *cache,
527 GFile *source_file,
528 GFile *target_file)
529 {
530 _thunar_return_if_fail (THUNAR_IS_THUMBNAIL_CACHE (cache));
531 _thunar_return_if_fail (G_IS_FILE (source_file));
532 _thunar_return_if_fail (G_IS_FILE (target_file));
533
534 /* acquire a cache lock */
535 _thumbnail_cache_lock (cache);
536
537 /* check if we have a valid proxy for the cache service */
538 if (cache->proxy_state != THUNAR_THUMBNAIL_CACHE_PROXY_FAILED)
539 {
540 /* add the files to the move queue */
541 cache->move_source_queue = g_list_prepend (cache->move_source_queue,
542 g_object_ref (source_file));
543 cache->move_target_queue = g_list_prepend (cache->move_target_queue,
544 g_object_ref (target_file));
545 }
546
547 if (cache->proxy_state == THUNAR_THUMBNAIL_CACHE_PROXY_AVAILABLE)
548 {
549 /* cancel any pending timeout to process the move queue */
550 if (cache->move_queue_idle_id > 0)
551 {
552 g_source_remove (cache->move_queue_idle_id);
553 cache->move_queue_idle_id = 0;
554 }
555
556 /* process the move queue in a 250ms timeout */
557 cache->move_queue_idle_id =
558 g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE, 250, thunar_thumbnail_cache_process_move_queue,
559 cache, thunar_thumbnail_cache_process_move_queue_destroy);
560 }
561
562 /* release the cache lock */
563 _thumbnail_cache_unlock (cache);
564 }
565
566
567
568 void
thunar_thumbnail_cache_copy_file(ThunarThumbnailCache * cache,GFile * source_file,GFile * target_file)569 thunar_thumbnail_cache_copy_file (ThunarThumbnailCache *cache,
570 GFile *source_file,
571 GFile *target_file)
572 {
573 _thunar_return_if_fail (THUNAR_IS_THUMBNAIL_CACHE (cache));
574 _thunar_return_if_fail (G_IS_FILE (source_file));
575 _thunar_return_if_fail (G_IS_FILE (target_file));
576
577 /* acquire a cache lock */
578 _thumbnail_cache_lock (cache);
579
580 /* check if we have a valid proxy for the cache service */
581 if (cache->proxy_state != THUNAR_THUMBNAIL_CACHE_PROXY_FAILED)
582 {
583 /* add the files to the copy queues */
584 cache->copy_source_queue = g_list_prepend (cache->copy_source_queue,
585 g_object_ref (source_file));
586 cache->copy_target_queue = g_list_prepend (cache->copy_target_queue,
587 g_object_ref (target_file));
588 }
589
590 if (cache->proxy_state == THUNAR_THUMBNAIL_CACHE_PROXY_AVAILABLE)
591 {
592 /* cancel any pending timeout to process the copy queue */
593 if (cache->copy_queue_idle_id > 0)
594 {
595 g_source_remove (cache->copy_queue_idle_id);
596 cache->copy_queue_idle_id = 0;
597 }
598
599 /* process the copy queue in a 250ms timeout */
600 cache->copy_queue_idle_id =
601 g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE, 500, thunar_thumbnail_cache_process_copy_queue,
602 cache, thunar_thumbnail_cache_process_copy_queue_destroy);
603 }
604
605 /* release the cache lock */
606 _thumbnail_cache_unlock (cache);
607 }
608
609
610
611 void
thunar_thumbnail_cache_delete_file(ThunarThumbnailCache * cache,GFile * file)612 thunar_thumbnail_cache_delete_file (ThunarThumbnailCache *cache,
613 GFile *file)
614 {
615 _thunar_return_if_fail (THUNAR_IS_THUMBNAIL_CACHE (cache));
616 _thunar_return_if_fail (G_IS_FILE (file));
617
618 /* acquire a cache lock */
619 _thumbnail_cache_lock (cache);
620
621 /* check if we have a valid proxy for the cache service */
622 if (cache->proxy_state != THUNAR_THUMBNAIL_CACHE_PROXY_FAILED)
623 {
624 /* add the file to the delete queue */
625 cache->delete_queue = g_list_prepend (cache->delete_queue, g_object_ref (file));
626 }
627
628 if (cache->proxy_state == THUNAR_THUMBNAIL_CACHE_PROXY_AVAILABLE)
629 {
630 /* cancel any pending timeout to process the delete queue */
631 if (cache->delete_queue_idle_id > 0)
632 {
633 g_source_remove (cache->delete_queue_idle_id);
634 cache->delete_queue_idle_id = 0;
635 }
636
637 /* process the delete queue in a 250ms timeout */
638 cache->delete_queue_idle_id =
639 g_timeout_add (500, (GSourceFunc) thunar_thumbnail_cache_process_delete_queue,
640 cache);
641 }
642
643 /* release the cache lock */
644 _thumbnail_cache_unlock (cache);
645 }
646
647
648
649 void
thunar_thumbnail_cache_cleanup_file(ThunarThumbnailCache * cache,GFile * file)650 thunar_thumbnail_cache_cleanup_file (ThunarThumbnailCache *cache,
651 GFile *file)
652 {
653 _thunar_return_if_fail (THUNAR_IS_THUMBNAIL_CACHE (cache));
654 _thunar_return_if_fail (G_IS_FILE (file));
655
656 /* acquire a cache lock */
657 _thumbnail_cache_lock (cache);
658
659 /* check if we have a valid proxy for the cache service */
660 if (cache->proxy_state != THUNAR_THUMBNAIL_CACHE_PROXY_FAILED)
661 {
662 /* add the file to the cleanup queue */
663 cache->cleanup_queue = g_list_prepend (cache->cleanup_queue, g_object_ref (file));
664 }
665
666 if (cache->proxy_state == THUNAR_THUMBNAIL_CACHE_PROXY_AVAILABLE)
667 {
668 /* cancel any pending timeout to process the cleanup queue */
669 if (cache->cleanup_queue_idle_id > 0)
670 {
671 g_source_remove (cache->cleanup_queue_idle_id);
672 cache->cleanup_queue_idle_id = 0;
673 }
674
675 /* process the cleanup queue in a 250ms timeout */
676 cache->cleanup_queue_idle_id =
677 g_timeout_add (1000, (GSourceFunc) thunar_thumbnail_cache_process_cleanup_queue,
678 cache);
679 }
680
681 /* release the cache lock */
682 _thumbnail_cache_unlock (cache);
683 }
684
685
686
687 static void
thunar_thumbnail_cache_proxy_created(GObject * source,GAsyncResult * res,gpointer userdata)688 thunar_thumbnail_cache_proxy_created (GObject *source,
689 GAsyncResult *res,
690 gpointer userdata)
691 {
692 ThunarThumbnailCache *cache = THUNAR_THUMBNAIL_CACHE (userdata);
693 ThunarThumbnailCacheDBus *proxy;
694 GError *error = NULL;
695
696 _thumbnail_cache_lock (cache);
697
698 if ((proxy = thunar_thumbnail_cache_dbus_proxy_new_for_bus_finish (res, &error)))
699 {
700 cache->cache_proxy = proxy;
701 cache->proxy_state = THUNAR_THUMBNAIL_CACHE_PROXY_AVAILABLE;
702 }
703 else
704 {
705 cache->proxy_state = THUNAR_THUMBNAIL_CACHE_PROXY_FAILED;
706
707 g_printerr ("ThunarThumbnailCache: Couldn't connect to bus service: %s\n", error->message);
708 }
709
710 g_clear_error (&error);
711
712 /* process the move queue in a 250ms timeout */
713 if (cache->move_source_queue)
714 cache->move_queue_idle_id =
715 g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE, 250, thunar_thumbnail_cache_process_move_queue,
716 cache, thunar_thumbnail_cache_process_move_queue_destroy);
717
718 /* process the copy queue in a 250ms timeout */
719 if (cache->copy_source_queue)
720 cache->copy_queue_idle_id =
721 g_timeout_add_full (G_PRIORITY_DEFAULT_IDLE, 500, thunar_thumbnail_cache_process_copy_queue,
722 cache, thunar_thumbnail_cache_process_copy_queue_destroy);
723
724 /* process the delete queue in a 250ms timeout */
725 if (cache->delete_queue)
726 cache->delete_queue_idle_id =
727 g_timeout_add (500, (GSourceFunc) thunar_thumbnail_cache_process_delete_queue,
728 cache);
729
730 /* process the cleanup queue in a 250ms timeout */
731 if (cache->cleanup_queue)
732 cache->cleanup_queue_idle_id =
733 g_timeout_add (1000, (GSourceFunc) thunar_thumbnail_cache_process_cleanup_queue,
734 cache);
735
736 _thumbnail_cache_unlock (cache);
737
738 /* drop additional reference */
739 g_object_unref (cache);
740 }
741
742
743
744 static void
thunar_thumbnail_cache_init(ThunarThumbnailCache * cache)745 thunar_thumbnail_cache_init (ThunarThumbnailCache *cache)
746 {
747 /* create a new mutex for accessing the cache from different threads */
748 g_mutex_init (&cache->lock);
749
750 /* add an additional reference to keep us alive while tre proxy initializes */
751 g_object_ref (cache);
752
753 /* try to connect to D-Bus */
754 cache->proxy_state = THUNAR_THUMBNAIL_CACHE_PROXY_WAITING;
755 thunar_thumbnail_cache_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
756 0,
757 "org.freedesktop.thumbnails.Cache1",
758 "/org/freedesktop/thumbnails/Cache1",
759 NULL,
760 thunar_thumbnail_cache_proxy_created,
761 cache);
762 }
763
764
765