summaryrefslogtreecommitdiff
path: root/community/shotwell/regenerate-video-thumbnails.patch
blob: 8a399355ee98cf11bece72f7f2ae83b9ead5edf5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
From 05c10b9c6107dc785808732216498ef5f3f6b87d Mon Sep 17 00:00:00 2001
From: Clint Rogers <clinton@yorba.org>
Date: Wed, 16 Jan 2013 00:09:42 +0000
Subject: Causes video thumbnails to get regenerated if lost; closes #6152.

Also moves some code around so regeneration for both stills and videos happens in the same spot, improving code navigability.
---
diff --git a/src/PhotoMonitor.vala b/src/PhotoMonitor.vala
index 40416d1..3dcc481 100644
--- a/src/PhotoMonitor.vala
+++ b/src/PhotoMonitor.vala
@@ -287,16 +287,7 @@ private class PhotoMonitor : MediaMonitor {
             
             return MediaMonitor.DiscoveredFile.UNKNOWN;
         }
-        
-        if (!ThumbnailCache.exists(photo)) {
-            try {
-                ThumbnailCache.import_from_source(photo, true);
-                photo.notify_altered(new Alteration("image","thumbnail"));
-            } catch (Error e) {
-                // thumbnail for this object was already broken, so nothing got worse.
-            }
-        }
-        
+
         switch (state) {
             case LibraryPhotoSourceCollection.State.ONLINE:
             case LibraryPhotoSourceCollection.State.OFFLINE:
diff --git a/src/ThumbnailCache.vala b/src/ThumbnailCache.vala
index be97183..2a2c716 100644
--- a/src/ThumbnailCache.vala
+++ b/src/ThumbnailCache.vala
@@ -1,7 +1,7 @@
-/* Copyright 2009-2012 Yorba Foundation
+/* Copyright 2009-2013 Yorba Foundation
  *
  * This software is licensed under the GNU LGPL (version 2.1 or later).
- * See the COPYING file in this distribution. 
+ * See the COPYING file in this distribution.
  */
 
 public class Thumbnails {
@@ -74,6 +74,7 @@ public class ThumbnailCache : Object {
     private class AsyncFetchJob : BackgroundJob {
         public ThumbnailCache cache;
         public string thumbnail_name;
+        public ThumbnailSource source;
         public PhotoFileFormat source_format;
         public Dimensions dim;
         public Gdk.InterpType interp;
@@ -84,13 +85,14 @@ public class ThumbnailCache : Object {
         public bool fetched = false;
         
         public AsyncFetchJob(ThumbnailCache cache, string thumbnail_name,
-            PhotoFileFormat source_format, Gdk.Pixbuf? prefetched, Dimensions dim,
+            ThumbnailSource source, Gdk.Pixbuf? prefetched, Dimensions dim,
             Gdk.InterpType interp, AsyncFetchCallback callback, Cancellable? cancellable) {
             base(cache, async_fetch_completion_callback, cancellable);
             
             this.cache = cache;
             this.thumbnail_name = thumbnail_name;
-            this.source_format = source_format;
+            this.source = source;
+            this.source_format = source.get_preferred_thumbnail_format();
             this.unscaled = prefetched;
             this.dim = dim;
             this.interp = interp;
@@ -126,11 +128,42 @@ public class ThumbnailCache : Object {
                 // scale if specified
                 scaled = dim.has_area() ? resize_pixbuf(unscaled, dim, interp) : unscaled;
             } catch (Error err) {
+                // Is the problem that the thumbnail couldn't be read? If so, it's recoverable;
+                // we'll just create it and leave this.err as null if creation works.
+                if (err is FileError) {
+                    try {
+                        Photo photo = source as Photo;
+                        Video video = source as Video;
+
+                        if (photo != null) {
+                            unscaled = photo.get_pixbuf(Scaling.for_best_fit(dim.width, true));
+                            photo.notify_altered(new Alteration("image","thumbnail"));
+                            return;
+                        }
+
+                        if (video != null) {
+                            unscaled = video.create_thumbnail(dim.width);
+                            scaled = resize_pixbuf(unscaled, dim, interp);
+                            cache.save_thumbnail(cache.get_source_cached_file(source),
+                                unscaled, source);
+                            replace(source, cache.size, unscaled);
+                            return;
+                        }
+
+                    } catch (Error e) {
+                        // Creating the thumbnail failed; tell the rest of the app.
+                        this.err = e;
+                        return;
+                    }
+                }
+
+                // ...the original error wasn't from reading the file, but something else;
+                // tell the rest of the app.
                 this.err = err;
             }
         }
     }
-        
+
     private static Workers fetch_workers = null;
     
     public const ulong MAX_BIG_CACHED_BYTES = 40 * 1024 * 1024;
@@ -230,13 +263,13 @@ public class ThumbnailCache : Object {
     
     public static void fetch_async(ThumbnailSource source, int scale, AsyncFetchCallback callback,
         Cancellable? cancellable = null) {
-        get_best_cache(scale)._fetch_async(source.get_source_id(), source.get_preferred_thumbnail_format(),
+        get_best_cache(scale)._fetch_async(source, source.get_preferred_thumbnail_format(),
             Dimensions(), DEFAULT_INTERP, callback, cancellable);
     }
     
-    public static void fetch_async_scaled(ThumbnailSource source, int scale, Dimensions dim, 
+    public static void fetch_async_scaled(ThumbnailSource source, int scale, Dimensions dim,
         Gdk.InterpType interp, AsyncFetchCallback callback, Cancellable? cancellable = null) {
-        get_best_cache(scale)._fetch_async(source.get_source_id(),
+        get_best_cache(scale)._fetch_async(source,
             source.get_preferred_thumbnail_format(), dim, interp, callback, cancellable);
     }
     
@@ -343,9 +376,10 @@ public class ThumbnailCache : Object {
         return pixbuf;
     }
     
-    private void _fetch_async(string thumbnail_name, PhotoFileFormat format, Dimensions dim, 
+    private void _fetch_async(ThumbnailSource source, PhotoFileFormat format, Dimensions dim,
         Gdk.InterpType interp, AsyncFetchCallback callback, Cancellable? cancellable) {
         // check if the pixbuf is already in memory
+        string thumbnail_name = source.get_source_id();
         Gdk.Pixbuf pixbuf = fetch_from_memory(thumbnail_name);
         if (pixbuf != null && (!dim.has_area() || Dimensions.for_pixbuf(pixbuf).equals(dim))) {
             // if no scaling operation required, callback in this context and done (otherwise,
@@ -365,8 +399,8 @@ public class ThumbnailCache : Object {
         // situation.  This may change in the future, and the caching situation will need to be 
         // handled.
         
-        fetch_workers.enqueue(new AsyncFetchJob(this, thumbnail_name, format, pixbuf, dim, interp, 
-            callback, cancellable));
+        fetch_workers.enqueue(new AsyncFetchJob(this, thumbnail_name, source, pixbuf, dim,
+            interp, callback, cancellable));
     }
     
     // Called within Gtk.main's thread context
--
cgit v0.9