From 3af1ee89ded5209697eec4e2ecb77cf1f3f19803 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 6 Mar 2013 00:03:52 -0800 Subject: Wed Mar 6 00:03:52 PST 2013 --- .../shotwell/0001-Port-to-GStreamer-1.0.patch | 150 ++++++++++++++------ community/shotwell/PKGBUILD | 17 ++- .../shotwell/regenerate-video-thumbnails.patch | 154 +++++++++++++++++++++ 3 files changed, 271 insertions(+), 50 deletions(-) create mode 100644 community/shotwell/regenerate-video-thumbnails.patch (limited to 'community/shotwell') diff --git a/community/shotwell/0001-Port-to-GStreamer-1.0.patch b/community/shotwell/0001-Port-to-GStreamer-1.0.patch index 7d7ac742d..a7a2cbf4c 100644 --- a/community/shotwell/0001-Port-to-GStreamer-1.0.patch +++ b/community/shotwell/0001-Port-to-GStreamer-1.0.patch @@ -1,17 +1,11 @@ -From 9cb0726dd0873e3664f3589aabadea8bb7c8ff37 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= -Date: Tue, 25 Sep 2012 18:15:02 -0400 -Subject: [PATCH] Port to GStreamer 1.0 +From 4db67e385c9c2d89947077f1520aa31af2538d65 Mon Sep 17 00:00:00 2001 +From: Alban Browaeys +Date: Wed, 09 Jan 2013 01:11:27 +0000 +Subject: Ports Shotwell to GStreamer 1.0. Closes #6055. --- - Makefile | 21 +++++++++++---------- - src/VideoSupport.vala | 8 ++++---- - src/libshotwell.deps | 5 +++-- - thumbnailer/shotwell-video-thumbnailer.vala | 18 ++++++++---------- - 4 files changed, 26 insertions(+), 26 deletions(-) - diff --git a/Makefile b/Makefile -index 1bd09e0..06059e3 100644 +index 2488f82..5a7e262 100644 --- a/Makefile +++ b/Makefile @@ -37,7 +37,7 @@ EXTRAS_SUPPORTED_LANGUAGES=fr de it es pl et sv sk lv pt bg bn nl da zh_CN el ru @@ -19,7 +13,7 @@ index 1bd09e0..06059e3 100644 SYSTEM_LANG_DIR := $(DESTDIR)$(PREFIX)/share/locale -VALAFLAGS := -g --enable-checking --thread --fatal-warnings --enable-deprecated $(USER_VALAFLAGS) -+VALAFLAGS := -g --enable-checking --thread --enable-deprecated $(USER_VALAFLAGS) ++VALAFLAGS := -g --enable-checking --thread --fatal-warnings --enable-deprecated --enable-experimental $(USER_VALAFLAGS) ifdef UNITY_SUPPORT VALAFLAGS := $(VALAFLAGS) --define UNITY_SUPPORT endif @@ -36,19 +30,18 @@ index 1bd09e0..06059e3 100644 gtk+-3.0 \ gudev-1.0 \ libexif \ -@@ -314,8 +314,9 @@ endif +@@ -314,8 +314,8 @@ endif THUMBNAILER_PKGS = \ gtk+-3.0 \ gee-1.0 \ - gstreamer-0.10 \ - gstreamer-base-0.10 + gstreamer-1.0 \ -+ gstreamer-base-1.0 \ -+ gstreamer-app-1.0 \ ++ gstreamer-base-1.0 DIRECT_LIBS = -@@ -325,10 +326,10 @@ EXT_PKG_VERSIONS = \ +@@ -325,10 +325,10 @@ EXT_PKG_VERSIONS = \ gio-unix-2.0 >= 2.20 \ glib-2.0 >= $(MIN_GLIB_VERSION) \ gmodule-2.0 >= 2.24.0 \ @@ -63,6 +56,15 @@ index 1bd09e0..06059e3 100644 gtk+-3.0 >= 3.0.11 \ gudev-1.0 >= 145 \ libexif >= 0.6.16 \ +@@ -683,7 +683,7 @@ $(VALA_STAMP): $(EXPANDED_SRC_FILES) $(EXPANDED_VAPI_FILES) $(GPHOTO_VAPI_FILE) + $(call check_valac_version) + @echo Compiling Vala code... + @mkdir -p $(BUILD_DIR) +- @$(VALAC) --ccode --directory=$(BUILD_DIR) --basedir=src \ ++ $(VALAC) --ccode --directory=$(BUILD_DIR) --basedir=src \ + $(foreach pkg,$(VALA_PKGS),--pkg=$(pkg)) \ + $(foreach vapidir,$(VAPI_DIRS),--vapidir=$(vapidir)) \ + $(foreach def,$(DEFINES),-X -D$(def)) \ diff --git a/src/VideoSupport.vala b/src/VideoSupport.vala index deb45e2..f679bd0 100644 --- a/src/VideoSupport.vala @@ -97,10 +99,10 @@ index deb45e2..f679bd0 100644 message("interpreter state cookie not found; assuming all video thumbnails are out of date"); interpreter_state_changed = true; diff --git a/thumbnailer/shotwell-video-thumbnailer.vala b/thumbnailer/shotwell-video-thumbnailer.vala -index a4d7dc2..c12784e 100644 +index 79a2d7e..ae1e537 100644 --- a/thumbnailer/shotwell-video-thumbnailer.vala +++ b/thumbnailer/shotwell-video-thumbnailer.vala -@@ -10,11 +10,7 @@ +@@ -10,22 +10,15 @@ // Shotwell Thumbnailer takes in a video file and returns a thumbnail to stdout. This is // a replacement for totem-video-thumbnailer class ShotwellThumbnailer { @@ -109,51 +111,109 @@ index a4d7dc2..c12784e 100644 - red_mask = (int) 0xFF000000, - green_mask = (int) 0x00FF0000, - blue_mask = (int) 0x0000FF00, -+ const string caps_string = """video/x-raw, format=RGBA, - width = (int) [ 1, max ], - height = (int) [ 1, max ], - framerate = (fraction) [ 0, max ]"""; -@@ -36,7 +32,7 @@ class ShotwellThumbnailer { +- width = (int) [ 1, max ], +- height = (int) [ 1, max ], +- framerate = (fraction) [ 0, max ]"""; ++ const string caps_string = """video/x-raw,format=RGB,bpp=32,depth=32,pixel-aspect-ratio=1/1"""; + + public static int main(string[] args) { + Gst.Element pipeline, sink; + int width, height; +- Gst.Buffer buffer; ++ Gst.Sample sample; + string descr; + Gdk.Pixbuf pixbuf; +- int64 position; ++ int64 duration, position; + Gst.StateChangeReturn ret; + bool res; + +@@ -36,7 +29,7 @@ class ShotwellThumbnailer { return 1; } - descr = "filesrc location=\"%s\" ! decodebin2 ! ffmpegcolorspace ! ".printf(args[1]) + -+ descr = "filesrc location=\"%s\" ! decodebin ! videoconvert ! ".printf(args[1]) + ++ descr = "filesrc location=\"%s\" ! decodebin ! videoconvert ! videoscale ! ".printf(args[1]) + "appsink name=sink caps=\"%s\"".printf(caps_string); try { -@@ -69,7 +65,7 @@ class ShotwellThumbnailer { - // by seeking to somewhere else we have a bigger chance of getting something - // more interesting. An optimization would be to detect black images and then - // seek a little more. +@@ -64,29 +57,41 @@ class ShotwellThumbnailer { + stderr.printf("Failed to play the file: couldn't get state.\n"); + return 3; + } +- +- // Seek to the a position in the file. Most files have a black first frame so +- // by seeking to somewhere else we have a bigger chance of getting something +- // more interesting. An optimization would be to detect black images and then +- // seek a little more. - position = (int64) (Gst.Format.PERCENT_MAX * 0.05); -+ position = (int64) (Gst.FORMAT_PERCENT_MAX * 0.05); - pipeline.seek_simple(Gst.Format.PERCENT, Gst.SeekFlags.KEY_UNIT | Gst.SeekFlags.FLUSH , position); - - // Get the preroll buffer from appsink, this block untils appsink really -@@ -86,7 +82,7 @@ class ShotwellThumbnailer { +- pipeline.seek_simple(Gst.Format.PERCENT, Gst.SeekFlags.KEY_UNIT | Gst.SeekFlags.FLUSH , position); +- +- // Get the preroll buffer from appsink, this block untils appsink really +- // prerolls. +- GLib.Signal.emit_by_name(sink, "pull-preroll", out buffer, null); +- ++ ++ /* get the duration */ ++ pipeline.query_duration (Gst.Format.TIME, out duration); ++ ++ if (duration != -1) { ++ /* we have a duration, seek to 5% */ ++ position = duration * 5 / 100; ++ } else { ++ /* no duration, seek to 1 second, this could EOS */ ++ position = 1 * Gst.SECOND; ++ } ++ ++ /* seek to the a position in the file. Most files have a black first frame so ++ * by seeking to somewhere else we have a bigger chance of getting something ++ * more interesting. An optimisation would be to detect black images and then ++ * seek a little more */ ++ pipeline.seek_simple (Gst.Format.TIME, Gst.SeekFlags.KEY_UNIT | Gst.SeekFlags.FLUSH, position); ++ ++ /* get the preroll buffer from appsink, this block untils appsink really ++ * prerolls */ ++ GLib.Signal.emit_by_name (sink, "pull-preroll", out sample, null); ++ + // if we have a buffer now, convert it to a pixbuf. It's possible that we + // don't have a buffer because we went EOS right away or had an error. +- if (buffer != null) { ++ if (sample != null) { ++ Gst.Buffer buffer; + Gst.Caps caps; + Gst.Structure s; ++ Gst.MapInfo mapinfo; + + // Get the snapshot buffer format now. We set the caps on the appsink so // that it can only be an rgb buffer. The only thing we have not specified // on the caps is the height, which is dependant on the pixel-aspect-ratio // of the source material. - caps = buffer.get_caps(); -+ caps = (sink as Gst.App.Sink).caps; ++ caps = sample.get_caps(); if (caps == null) { stderr.printf("could not get snapshot format\n"); return 5; -@@ -104,9 +100,11 @@ class ShotwellThumbnailer { - +@@ -101,14 +106,18 @@ class ShotwellThumbnailer { + stderr.printf("Could not get snapshot dimension\n"); + return 6; + } +- ++ ++ buffer = sample.get_buffer(); ++ buffer.map(out mapinfo, Gst.MapFlags.READ); ++ // Create pixmap from buffer and save, gstreamer video buffers have a stride // that is rounded up to the nearest multiple of 4. - pixbuf = new Gdk.Pixbuf.from_data(buffer.data, Gdk.Colorspace.RGB, true, 8, -+ Gst.MapInfo info; -+ buffer.map(out info, Gst.MapFlags.READ); -+ pixbuf = new Gdk.Pixbuf.from_data(info.data, Gdk.Colorspace.RGB, true, 8, - width, height, width * 4, null); -- -+ buffer.unmap(info); +- width, height, width * 4, null); ++ pixbuf = new Gdk.Pixbuf.from_data(mapinfo.data, Gdk.Colorspace.RGB, false, 8, ++ width, height, (((width * 3)+3)&~3), null); + // Save the pixbuf. pixbuf.save("/dev/stdout", "png"); ++ buffer.unmap(mapinfo); } else { --- -1.7.11.4 - + stderr.printf("Could not make snapshot\n"); + return 10; +-- +cgit v0.9 diff --git a/community/shotwell/PKGBUILD b/community/shotwell/PKGBUILD index 578cc10f5..8ff178ab2 100644 --- a/community/shotwell/PKGBUILD +++ b/community/shotwell/PKGBUILD @@ -1,11 +1,11 @@ -# $Id: PKGBUILD 81068 2012-12-11 14:37:24Z allan $ +# $Id: PKGBUILD 85690 2013-03-05 07:36:48Z bgyorgy $ # Maintainer: Sergej Pupykin # Maintainer : Ionut Biru # Contributor: Joeny Ang pkgname=shotwell pkgver=0.13.1 -pkgrel=5 +pkgrel=6 pkgdesc="A digital photo organizer designed for the GNOME desktop environment" arch=('i686' 'x86_64') url="http://yorba.org/shotwell/" @@ -17,19 +17,26 @@ makedepends=('intltool' 'vala>=0.17.2' 'libunique3') install=shotwell.install source=("http://yorba.org/download/shotwell/0.13/shotwell-${pkgver}.tar.xz" "no-libexec.patch" - "0001-Port-to-GStreamer-1.0.patch") + "0001-Port-to-GStreamer-1.0.patch" + "regenerate-video-thumbnails.patch") md5sums=('71eb1346093705ca2b37c12a21994d14' 'b4124e022c98b4382530e6fbcef965e2' - '86e47eade2b5a49bd6503294751d95f0') + '666d28c2a1b78632df8ab5f24c3aa3cd' + '4b70442c6d9c04f3be23426ef92adb43') build() { cd "${srcdir}/${pkgname}-${pkgver}" patch -p1 <$srcdir/no-libexec.patch - # http://redmine.yorba.org/issues/5548 + # Port to GSreamer 1.0 (video thumbnailer) + # http://redmine.yorba.org/issues/6055 patch -p1 <$srcdir/0001-Port-to-GStreamer-1.0.patch + # Regenerate video thumbnails on lost + # http://redmine.yorba.org/issues/6152 + patch -p1 <$srcdir/regenerate-video-thumbnails.patch + ./configure --prefix=/usr \ --disable-schemas-compile \ --disable-desktop-update \ diff --git a/community/shotwell/regenerate-video-thumbnails.patch b/community/shotwell/regenerate-video-thumbnails.patch new file mode 100644 index 000000000..8a399355e --- /dev/null +++ b/community/shotwell/regenerate-video-thumbnails.patch @@ -0,0 +1,154 @@ +From 05c10b9c6107dc785808732216498ef5f3f6b87d Mon Sep 17 00:00:00 2001 +From: Clint Rogers +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 -- cgit v1.2.3-54-g00ecf