diff options
| author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2017-11-12 17:19:32 +0100 | 
|---|---|---|
| committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2017-11-12 17:19:32 +0100 | 
| commit | 0b7ebb2f0f7d70d50054380ff5878104b72710e9 (patch) | |
| tree | 7dcb662c7fa4ea100bccfc3042b1785d305458e8 | |
| parent | 73542a3b4379319fc2d0a4d134f1f8a6d488dfc4 (diff) | |
Add missing .gitignore
| -rw-r--r-- | .gitignore | 4 | ||||
| -rw-r--r-- | .pc/.dpkg-source-unapply | 0 | ||||
| -rw-r--r-- | .pc/.quilt_patches | 1 | ||||
| -rw-r--r-- | .pc/.quilt_series | 1 | ||||
| -rw-r--r-- | .pc/.version | 1 | ||||
| -rw-r--r-- | .pc/0100-ios8.patch/src/camera/ImportPage.vala | 1811 | ||||
| -rw-r--r-- | .pc/applied-patches | 1 | ||||
| -rw-r--r-- | src/camera/ImportPage.vala | 47 | 
8 files changed, 17 insertions, 1849 deletions
| diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c6fbd72 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.bzr +.bzrignore +.pc +debian/files
\ No newline at end of file diff --git a/.pc/.dpkg-source-unapply b/.pc/.dpkg-source-unapply deleted file mode 100644 index e69de29..0000000 --- a/.pc/.dpkg-source-unapply +++ /dev/null diff --git a/.pc/.quilt_patches b/.pc/.quilt_patches deleted file mode 100644 index 6857a8d..0000000 --- a/.pc/.quilt_patches +++ /dev/null @@ -1 +0,0 @@ -debian/patches diff --git a/.pc/.quilt_series b/.pc/.quilt_series deleted file mode 100644 index c206706..0000000 --- a/.pc/.quilt_series +++ /dev/null @@ -1 +0,0 @@ -series diff --git a/.pc/.version b/.pc/.version deleted file mode 100644 index 0cfbf08..0000000 --- a/.pc/.version +++ /dev/null @@ -1 +0,0 @@ -2 diff --git a/.pc/0100-ios8.patch/src/camera/ImportPage.vala b/.pc/0100-ios8.patch/src/camera/ImportPage.vala deleted file mode 100644 index 4e055ec..0000000 --- a/.pc/0100-ios8.patch/src/camera/ImportPage.vala +++ /dev/null @@ -1,1811 +0,0 @@ -/* Copyright 2016 Software Freedom Conservancy Inc. - * - * This software is licensed under the GNU LGPL (version 2.1 or later). - * See the COPYING file in this distribution. - */ - -private class ImportSourceCollection : SourceCollection { -    public ImportSourceCollection(string name) { -        base (name); -    } -     -    public override bool holds_type_of_source(DataSource source) { -        return source is ImportSource; -    } -} - -abstract class ImportSource : ThumbnailSource, Indexable { -    private string camera_name; -    private GPhoto.Camera camera; -    private int fsid; -    private string folder; -    private string filename; -    private ulong file_size; -    private time_t modification_time; -    private Gdk.Pixbuf? preview = null; -    private string? indexable_keywords = null; -     -    public ImportSource(string camera_name, GPhoto.Camera camera, int fsid, string folder, -        string filename, ulong file_size, time_t modification_time) { -        this.camera_name = camera_name; -        this.camera = camera; -        this.fsid = fsid; -        this.folder = folder; -        this.filename = filename; -        this.file_size = file_size; -        this.modification_time = modification_time; -        indexable_keywords = prepare_indexable_string(filename); -    } -     -    protected void set_preview(Gdk.Pixbuf? preview) { -        this.preview = preview; -    } -     -    public string get_camera_name() { -        return camera_name; -    } -     -    public GPhoto.Camera get_camera() { -        return camera; -    } -     -    public int get_fsid() { -        return fsid; -    } -     -    public string get_folder() { -        return folder; -    } -     -    public string get_filename() { -        return filename; -    } -     -    public ulong get_filesize() { -        return file_size; -    } -     -    public time_t get_modification_time() { -        return modification_time; -    } -     -    public virtual Gdk.Pixbuf? get_preview() { -        return preview; -    } - -    public virtual time_t get_exposure_time() { -        return get_modification_time(); -    } - -    public string? get_fulldir() { -        return ImportPage.get_fulldir(get_camera(), get_camera_name(), get_fsid(), get_folder()); -    } - -    public override string to_string() { -        return "%s %s/%s".printf(get_camera_name(), get_folder(), get_filename()); -    } -     -    public override bool internal_delete_backing() throws Error { -        debug("Deleting %s from %s", to_string(), camera_name); -         -        string? fulldir = get_fulldir(); -        if (fulldir == null) { -            warning("Skipping deleting %s from %s: invalid folder name", to_string(), camera_name); -             -            return base.internal_delete_backing(); -        } -         -        GPhoto.Result result = get_camera().delete_file(fulldir, get_filename(), -            ImportPage.spin_idle_context.context); -        if (result != GPhoto.Result.OK) -            warning("Error deleting %s from %s: %s", to_string(), camera_name, result.to_full_string()); -         -        return base.internal_delete_backing() && (result == GPhoto.Result.OK); -    } -     -    public unowned string? get_indexable_keywords() { -        return indexable_keywords; -    } -} - -class VideoImportSource : ImportSource { -    public VideoImportSource(string camera_name, GPhoto.Camera camera, int fsid, string folder,  -        string filename, ulong file_size, time_t modification_time) { -        base(camera_name, camera, fsid, folder, filename, file_size, modification_time); -    } -     -    public override Gdk.Pixbuf? get_thumbnail(int scale) throws Error { -        return create_thumbnail(scale); -    } -     -    public override Gdk.Pixbuf? create_thumbnail(int scale) throws Error { -        if (get_preview() == null) -            return null; -         -        // this satifies the return-a-new-instance requirement of create_thumbnail( ) because -        // scale_pixbuf( ) allocates a new pixbuf -        return (scale > 0) ? scale_pixbuf(get_preview(), scale, Gdk.InterpType.BILINEAR, true) : -            get_preview(); -    } -     -    public override string get_typename() { -        return "videoimport"; -    } -     -    public override int64 get_instance_id() { -        return get_object_id(); -    } -     -    public override PhotoFileFormat get_preferred_thumbnail_format() { -        return PhotoFileFormat.get_system_default_format(); -    } - -    public override string get_name() { -        return get_filename(); -    } -     -    public void update(Gdk.Pixbuf? preview) { -        set_preview((preview != null) ? preview : Resources.get_noninterpretable_badge_pixbuf()); -    } -} - -class PhotoImportSource : ImportSource { -    public const Gdk.InterpType INTERP = Gdk.InterpType.BILINEAR; - -    private PhotoFileFormat file_format; -    private string? preview_md5 = null; -    private PhotoMetadata? metadata = null; -    private string? exif_md5 = null; -    private PhotoImportSource? associated = null; // JPEG source for RAW+JPEG -     -    public PhotoImportSource(string camera_name, GPhoto.Camera camera, int fsid, string folder,  -        string filename, ulong file_size, time_t modification_time, PhotoFileFormat file_format) { -        base(camera_name, camera, fsid, folder, filename, file_size, modification_time); -        this.file_format = file_format; -    } -     -    public override string get_name() { -        string? title = get_title(); -         -        return !is_string_empty(title) ? title : get_filename(); -    } -     -    public override string get_typename() { -        return "photoimport"; -    } -     -    public override int64 get_instance_id() { -        return get_object_id(); -    } -     -    public override PhotoFileFormat get_preferred_thumbnail_format() { -        return (file_format.can_write()) ? file_format : -            PhotoFileFormat.get_system_default_format(); -    } - -    public override Gdk.Pixbuf? create_thumbnail(int scale) throws Error { -        if (get_preview() == null) -            return null; -         -        // this satifies the return-a-new-instance requirement of create_thumbnail( ) because -        // scale_pixbuf( ) allocates a new pixbuf -        return (scale > 0) ? scale_pixbuf(get_preview(), scale, INTERP, true) : get_preview(); -    } - -    // Needed because previews and exif are loaded after other information has been gathered. -    public void update(Gdk.Pixbuf? preview, string? preview_md5, PhotoMetadata? metadata, string? exif_md5) { -        set_preview(preview); -        this.preview_md5 = preview_md5; -        this.metadata = metadata; -        this.exif_md5 = exif_md5; -    } - -    public override time_t get_exposure_time() { -        if (metadata == null) -            return get_modification_time(); -         -        MetadataDateTime? date_time = metadata.get_exposure_date_time(); -         -        return (date_time != null) ? date_time.get_timestamp() : get_modification_time(); -    } -     -    public string? get_title() { -        return (metadata != null) ? metadata.get_title() : null; -    } -     -    public PhotoMetadata? get_metadata() { -        if (associated != null) -            return associated.get_metadata(); -         -        return metadata; -    } -     -    public override Gdk.Pixbuf? get_preview() { -        if (associated != null) -            return associated.get_preview(); -             -        if (base.get_preview() != null)  -            return base.get_preview(); -         -        return null; -    } -     -    public override Gdk.Pixbuf? get_thumbnail(int scale) throws Error { -        if (get_preview() == null) -            return null; -         -        return (scale > 0) ? scale_pixbuf(get_preview(), scale, INTERP, true) : get_preview(); -    } -     -    public PhotoFileFormat get_file_format() { -        return file_format; -    } -     -    public string? get_preview_md5() { -        return preview_md5; -    } -     -    public void set_associated(PhotoImportSource? associated) { -        this.associated = associated; -    } -     -    public PhotoImportSource? get_associated() { -        return associated; -    } -     -    public override bool internal_delete_backing() throws Error { -        bool ret = base.internal_delete_backing(); -        if (associated != null) -            ret &= associated.internal_delete_backing(); -        return ret; -    } -} - -class ImportPreview : MediaSourceItem { -    public const int MAX_SCALE = 128; -     -    private static Gdk.Pixbuf placeholder_preview = null; -     -    private DuplicatedFile? duplicated_file; -     -    public ImportPreview(ImportSource source) { -        base(source, Dimensions(), source.get_name(), null); -         -        this.duplicated_file = null; -         -        // draw sprocket holes as visual indications on video previews -        if (source is VideoImportSource) -            set_enable_sprockets(true); -         -        // scale down pixbuf if necessary -        Gdk.Pixbuf pixbuf = null; -        try { -            pixbuf = source.get_thumbnail(0); -        } catch (Error err) { -            warning("Unable to fetch loaded import preview for %s: %s", to_string(), err.message); -        } -         -        // use placeholder if no preview available -        bool using_placeholder = (pixbuf == null); -        if (pixbuf == null) { -            if (placeholder_preview == null) { -                placeholder_preview = get_placeholder_pixbuf(); -                placeholder_preview = scale_pixbuf(placeholder_preview, MAX_SCALE, -                    Gdk.InterpType.BILINEAR, true); -            } -             -            pixbuf = placeholder_preview; -        } -         -        // scale down if too large -        if (pixbuf.get_width() > MAX_SCALE || pixbuf.get_height() > MAX_SCALE) -            pixbuf = scale_pixbuf(pixbuf, MAX_SCALE, PhotoImportSource.INTERP, false); -         -        if (source is PhotoImportSource) { -            // honor rotation for photos -- we don't care about videos since they can't be rotated -            PhotoImportSource photo_import_source = source as PhotoImportSource; -            if (!using_placeholder && photo_import_source.get_metadata() != null) -                pixbuf = photo_import_source.get_metadata().get_orientation().rotate_pixbuf(pixbuf); -             -            if (photo_import_source.get_associated() != null) { -                set_subtitle("<small>%s</small>".printf(_("RAW+JPEG")), true); -            } -        } -         -        set_image(pixbuf); -    } -     -    public bool is_already_imported() { -        PhotoImportSource photo_import_source = get_import_source() as PhotoImportSource; -        if (photo_import_source != null) { -            string? preview_md5 = photo_import_source.get_preview_md5(); -            PhotoFileFormat file_format = photo_import_source.get_file_format(); -             -            // ignore trashed duplicates -            if (!is_string_empty(preview_md5) -                && LibraryPhoto.has_nontrash_duplicate(null, preview_md5, null, file_format)) { -                 -                duplicated_file = DuplicatedFile.create_from_photo_id( -                    LibraryPhoto.get_nontrash_duplicate(null, preview_md5, null, file_format)); -                 -                return true; -            } -             -            // Because gPhoto doesn't reliably return thumbnails for RAW files, and because we want -            // to avoid downloading huge RAW files during an "import all" only to determine they're -            // duplicates, use the image's basename and filesize to do duplicate detection -            if (file_format == PhotoFileFormat.RAW) { -                uint64 filesize = get_import_source().get_filesize(); -                // unlikely to be a problem, but what the hay -                if (filesize <= int64.MAX) { -                    PhotoID duplicated_photo_id = LibraryPhoto.global.get_basename_filesize_duplicate( -                                get_import_source().get_filename(), (int64) filesize); - -                    if (duplicated_photo_id.is_valid()) { -                        // Check exposure timestamp -                        LibraryPhoto duplicated_photo = LibraryPhoto.global.fetch(duplicated_photo_id); -                        time_t photo_exposure_time = photo_import_source.get_exposure_time(); -                        time_t duplicated_photo_exposure_time = duplicated_photo.get_exposure_time(); -                         -                        if (photo_exposure_time == duplicated_photo_exposure_time) { -                            duplicated_file = DuplicatedFile.create_from_photo_id( -                                LibraryPhoto.global.get_basename_filesize_duplicate( -                                get_import_source().get_filename(), (int64) filesize)); - -                            return true; -                        } -                    } -                } -            } -             -            return false; -        } -         -        VideoImportSource video_import_source = get_import_source() as VideoImportSource; -        if (video_import_source != null) { -            // Unlike photos, if a video does have a thumbnail (i.e. gphoto2 can retrieve one from -            // a sidecar file), it will be unavailable to Shotwell during the import process, so -            // no comparison is available.  Instead, like RAW files, use name and filesize to -            // do a less-reliable but better-than-nothing comparison -            if (Video.global.has_basename_filesize_duplicate(video_import_source.get_filename(), -                video_import_source.get_filesize())) { -                 -                duplicated_file = DuplicatedFile.create_from_video_id( -                    Video.global.get_basename_filesize_duplicate( -                    video_import_source.get_filename(), -                    video_import_source.get_filesize())); -                 -                return true; -            } -             -            return false; -        } -         -        return false; -    } -     -    public DuplicatedFile? get_duplicated_file() { -        if (!is_already_imported()) -            return null; -         -        return duplicated_file; -    } -     -    public ImportSource get_import_source() { -        return (ImportSource) get_source(); -    } -} - -public class CameraViewTracker : Core.ViewTracker { -    public CameraAccumulator all = new CameraAccumulator(); -    public CameraAccumulator visible = new CameraAccumulator(); -    public CameraAccumulator selected = new CameraAccumulator(); -     -    public CameraViewTracker(ViewCollection collection) { -        base (collection); -         -        start(all, visible, selected); -    } -} - -public class CameraAccumulator : Object, Core.TrackerAccumulator { -    public int total { get; private set; default = 0; } -    public int photos { get; private set; default = 0; } -    public int videos { get; private set; default = 0; } -    public int raw { get; private set; default = 0; } -     -    public bool include(DataObject object) { -        ImportSource source = (ImportSource) ((DataView) object).get_source(); -         -        total++; -         -        PhotoImportSource? photo = source as PhotoImportSource; -        if (photo != null && photo.get_file_format() != PhotoFileFormat.RAW) -            photos++; -        else if (photo != null && photo.get_file_format() == PhotoFileFormat.RAW) -            raw++; -        else if (source is VideoImportSource) -            videos++; -         -        // because of total, always fire "updated" -        return true; -    } -     -    public bool uninclude(DataObject object) { -        ImportSource source = (ImportSource) ((DataView) object).get_source(); -         -        total++; -         -        PhotoImportSource? photo = source as PhotoImportSource; -        if (photo != null && photo.get_file_format() != PhotoFileFormat.RAW) { -            assert(photos > 0); -            photos--; -        } else if (photo != null && photo.get_file_format() == PhotoFileFormat.RAW) { -            assert(raw > 0); -            raw--; -        } else if (source is VideoImportSource) { -            assert(videos > 0); -            videos--; -        } -         -        // because of total, always fire "updated" -        return true; -    } -     -    public bool altered(DataObject object, Alteration alteration) { -        // no alteration affects accumulated data -        return false; -    } -     -    public string to_string() { -        return "%d total/%d photos/%d videos/%d raw".printf(total, photos, videos, raw); -    } -} - -public class ImportPage : CheckerboardPage { -    private const string UNMOUNT_FAILED_MSG = _("Unable to unmount camera. Try unmounting the camera from the file manager."); -     -    private class ImportViewManager : ViewManager { -        private ImportPage owner; -         -        public ImportViewManager(ImportPage owner) { -            this.owner = owner; -        } -         -        public override DataView create_view(DataSource source) { -            return new ImportPreview((ImportSource) source); -        } -    } -     -    private class CameraImportJob : BatchImportJob { -        private GPhoto.ContextWrapper context; -        private ImportSource import_file; -        private GPhoto.Camera camera; -        private string fulldir; -        private string filename; -        private uint64 filesize; -        private PhotoMetadata metadata; -        private time_t exposure_time; -        private CameraImportJob? associated = null; -        private BackingPhotoRow? associated_file = null; -        private DuplicatedFile? duplicated_file; -         -        public CameraImportJob(GPhoto.ContextWrapper context, ImportSource import_file, -            DuplicatedFile? duplicated_file = null) { -            this.context = context; -            this.import_file = import_file; -            this.duplicated_file = duplicated_file; -             -            // stash everything called in prepare(), as it may/will be called from a separate thread -            camera = import_file.get_camera(); -            fulldir = import_file.get_fulldir(); -            // this should've been caught long ago when the files were first enumerated -            assert(fulldir != null); -            filename = import_file.get_filename(); -            filesize = import_file.get_filesize(); -            metadata = (import_file is PhotoImportSource) ? -                (import_file as PhotoImportSource).get_metadata() : null; -            exposure_time = import_file.get_exposure_time(); -        } -         -        public time_t get_exposure_time() { -            return exposure_time; -        } -         -        public override DuplicatedFile? get_duplicated_file() { -            return duplicated_file; -        } - -        public override time_t get_exposure_time_override() { -            return (import_file is VideoImportSource) ? get_exposure_time() : 0; -        } -         -        public override string get_dest_identifier() { -            return filename; -        } -         -        public override string get_source_identifier() { -            return import_file.get_filename(); -        } -         -        public override string get_basename() { -            return filename; -        } -     -        public override string get_path() { -            return fulldir; -        } -         -        public override void set_associated(BatchImportJob associated) { -            this.associated = associated as CameraImportJob; -        } -         -        public ImportSource get_source() { -            return import_file; -        } -         -        public override bool is_directory() { -            return false; -        } -         -        public override bool determine_file_size(out uint64 filesize, out File file) { -            file = null; -            filesize = this.filesize; -             -            return true; -        } -         -        public override bool prepare(out File file_to_import, out bool copy_to_library) throws Error { -            file_to_import = null; -            copy_to_library = false; -             -            File dest_file = null; -            try { -                bool collision; -                dest_file = LibraryFiles.generate_unique_file(filename, metadata, exposure_time, -                    out collision); -            } catch (Error err) { -                warning("Unable to generate local file for %s: %s", import_file.get_filename(), -                    err.message); -            } -             -            if (dest_file == null) { -                message("Unable to generate local file for %s", import_file.get_filename()); -                 -                return false; -            } -             -            // always blacklist the copied images from the LibraryMonitor, otherwise it'll think -            // they should be auto-imported -            LibraryMonitor.blacklist_file(dest_file, "CameraImportJob.prepare"); -            try { -                GPhoto.save_image(context.context, camera, fulldir, filename, dest_file); -            } finally { -                LibraryMonitor.unblacklist_file(dest_file); -            } -             -            // Copy over associated file, if it exists. -            if (associated != null) { -                try { -                    associated_file =  -                        RawDeveloper.CAMERA.create_backing_row_for_development(dest_file.get_path(), -                            associated.get_basename()); -                } catch (Error err) { -                    warning("Unable to generate backing associated file for %s: %s", associated.filename, -                        err.message); -                } -                 -                if (associated_file == null) { -                    message("Unable to generate backing associated file for %s", associated.filename); -                    return false; -                } -                 -                File assoc_dest = File.new_for_path(associated_file.filepath); -                LibraryMonitor.blacklist_file(assoc_dest, "CameraImportJob.prepare"); -                try { -                    GPhoto.save_image(context.context, camera, associated.fulldir, associated.filename,  -                        assoc_dest); -                } finally { -                    LibraryMonitor.unblacklist_file(assoc_dest); -                } -            } -             -            file_to_import = dest_file; -            copy_to_library = false; -             -            return true; -        } -         -        public override bool complete(MediaSource source, BatchImportRoll import_roll) throws Error { -            bool ret = false; -            if (source is Photo) { -                Photo photo = source as Photo; -                 -                // Associate paired JPEG with RAW photo. -                if (associated_file != null) { -                    photo.add_backing_photo_for_development(RawDeveloper.CAMERA, associated_file); -                    ret = true; -                    photo.set_raw_developer(Config.Facade.get_instance().get_default_raw_developer()); -                } -            } -            return ret; -        } -    } -     -    private class ImportPageSearchViewFilter : SearchViewFilter { -        public override uint get_criteria() { -            return SearchFilterCriteria.TEXT | SearchFilterCriteria.MEDIA; -        } -         -        public override bool predicate(DataView view) { -            ImportSource source = ((ImportPreview) view).get_import_source(); -             -            // Media type. -            if ((bool) (SearchFilterCriteria.MEDIA & get_criteria()) && filter_by_media_type()) { -                if (source is VideoImportSource) { -                    if (!show_media_video) -                        return false; -                } else if (source is PhotoImportSource) { -                    PhotoImportSource photo = source as PhotoImportSource; -                    if (photo.get_file_format() == PhotoFileFormat.RAW) { -                        if (photo.get_associated() != null) { -                            if (!show_media_photos && !show_media_raw) -                                return false; -                        } else if (!show_media_raw) { -                            return false; -                        } -                    } else if (!show_media_photos) -                        return false; -                } -            } -             -            if ((bool) (SearchFilterCriteria.TEXT & get_criteria())) { -                unowned string? keywords = source.get_indexable_keywords(); -                if (is_string_empty(keywords)) -                    return false; -                 -                // Return false if the word isn't found, true otherwise. -                foreach (unowned string word in get_search_filter_words()) { -                    if (!keywords.contains(word)) -                        return false; -                } -            } -             -            return true; -        } -    } -     -    // View filter for already imported filter. -    private class HideImportedViewFilter : ViewFilter { -        public override bool predicate(DataView view) { -            return !((ImportPreview) view).is_already_imported(); -        } -    } -     -    public static GPhoto.ContextWrapper null_context = null; -    public static GPhoto.SpinIdleWrapper spin_idle_context = null; - -    private SourceCollection import_sources = null; -    private Gtk.Label camera_label = new Gtk.Label(null); -    private Gtk.CheckButton hide_imported; -    private Gtk.ProgressBar progress_bar = new Gtk.ProgressBar(); -    private GPhoto.Camera camera; -    private string uri; -    private bool busy = false; -    private bool refreshed = false; -    private GPhoto.Result refresh_result = GPhoto.Result.OK; -    private string refresh_error = null; -    private string camera_name; -    private VolumeMonitor volume_monitor = null; -    private ImportPage? local_ref = null; -    private string? icon; -    private ImportPageSearchViewFilter search_filter = new ImportPageSearchViewFilter(); -    private HideImportedViewFilter hide_imported_filter = new HideImportedViewFilter(); -    private CameraViewTracker tracker; - -#if UNITY_SUPPORT -    UnityProgressBar uniprobar = UnityProgressBar.get_instance(); -#endif -     -    public enum RefreshResult { -        OK, -        BUSY, -        LOCKED, -        LIBRARY_ERROR -    } -     -    public ImportPage(GPhoto.Camera camera, string uri, string? display_name = null, string? icon = null) { -        base(_("Camera")); -        this.camera = camera; -        this.uri = uri; -        this.import_sources = new ImportSourceCollection("ImportSources for %s".printf(uri)); -        this.icon = icon; -         -        tracker = new CameraViewTracker(get_view()); -         -        // Get camera name. -        if (null != display_name) { -            camera_name = display_name; -        } else { -            GPhoto.CameraAbilities abilities; -            GPhoto.Result res = camera.get_abilities(out abilities); -            if (res != GPhoto.Result.OK) { -                debug("Unable to get camera abilities: %s", res.to_full_string()); -                camera_name = _("Camera"); -            } -        } -        camera_label.set_text(camera_name); -        set_page_name(camera_name); -         -        // Mount.unmounted signal is *only* fired when a VolumeMonitor has been instantiated. -        this.volume_monitor = VolumeMonitor.get(); -         -        // set up the global null context when needed -        if (null_context == null) -            null_context = new GPhoto.ContextWrapper(); -         -        // same with idle-loop wrapper -        if (spin_idle_context == null) -            spin_idle_context = new GPhoto.SpinIdleWrapper(); -         -        // monitor source collection to add/remove views -        get_view().monitor_source_collection(import_sources, new ImportViewManager(this), null); -         -        // sort by exposure time -        get_view().set_comparator(preview_comparator, preview_comparator_predicate); -         -        // monitor selection for UI -        get_view().items_state_changed.connect(on_view_changed); -        get_view().contents_altered.connect(on_view_changed); -        get_view().items_visibility_changed.connect(on_view_changed); -         -        // Show subtitles. -        get_view().set_property(CheckerboardItem.PROP_SHOW_SUBTITLES, true); -         -        // monitor Photos for removals, as that will change the result of the ViewFilter -        LibraryPhoto.global.contents_altered.connect(on_media_added_removed); -        Video.global.contents_altered.connect(on_media_added_removed); -         -        init_item_context_menu("ImportContextMenu"); -        init_page_context_menu("ImportContextMenu"); -    } -     -    ~ImportPage() { -        LibraryPhoto.global.contents_altered.disconnect(on_media_added_removed); -        Video.global.contents_altered.disconnect(on_media_added_removed); -    } -     -    public override Gtk.Toolbar get_toolbar() { -        if (toolbar == null) { -            base.get_toolbar(); - -            // hide duplicates checkbox -            hide_imported = new Gtk.CheckButton.with_label(_("Hide photos already imported")); -            hide_imported.set_tooltip_text(_("Only display photos that have not been imported")); -            hide_imported.clicked.connect(on_hide_imported); -            hide_imported.sensitive = false; -            hide_imported.active = Config.Facade.get_instance().get_hide_photos_already_imported(); -            Gtk.ToolItem hide_item = new Gtk.ToolItem(); -            hide_item.is_important = true; -            hide_item.add(hide_imported); -             -            toolbar.insert(hide_item, -1); -             -            // separator to force buttons to right side of toolbar -            Gtk.SeparatorToolItem separator = new Gtk.SeparatorToolItem(); -            separator.set_draw(false); -             -            toolbar.insert(separator, -1); -             -            // progress bar in center of toolbar -            progress_bar.set_orientation(Gtk.Orientation.HORIZONTAL); -            progress_bar.visible = false; -            Gtk.ToolItem progress_item = new Gtk.ToolItem(); -            progress_item.set_expand(true); -            progress_item.add(progress_bar); -            progress_bar.set_show_text(true); -             -            toolbar.insert(progress_item, -1); -             -            // Find button -            Gtk.ToggleToolButton find_button = new Gtk.ToggleToolButton(); -            find_button.set_icon_name("edit-find"); -            find_button.set_action_name ("win.CommonDisplaySearchbar"); -             -            toolbar.insert(find_button, -1); -             -            // Separator -            toolbar.insert(new Gtk.SeparatorToolItem(), -1); -             -            // Import selected -            Gtk.ToolButton import_selected_button = new Gtk.ToolButton(null, null); -            import_selected_button.set_icon_name("import"); -            import_selected_button.set_label(_("Import _Selected")); -            import_selected_button.is_important = true; -            import_selected_button.use_underline = true; -            import_selected_button.set_action_name ("win.ImportSelected"); -             -            toolbar.insert(import_selected_button, -1); -             -            // Import all -            Gtk.ToolButton import_all_button = new Gtk.ToolButton(null, null); -            import_all_button.set_icon_name("import-all"); -            import_all_button.set_label(_("Import _All")); -            import_all_button.is_important = true; -            import_all_button.use_underline = true; -            import_all_button.set_action_name ("win.ImportAll"); -             -            toolbar.insert(import_all_button, -1); - -            // restrain the recalcitrant rascal!  prevents the progress bar from being added to the -            // show_all queue so we have more control over its visibility -            progress_bar.set_no_show_all(true); -             -            update_toolbar_state(); -             -            show_all(); -        } -         -        return toolbar; -    } -     -    public override Core.ViewTracker? get_view_tracker() { -        return tracker; -    } - -    protected override string get_view_empty_message() { -        return _("The camera seems to be empty. No photos/videos found to import"); -    } - -    protected override string get_filter_no_match_message () { -        return _("No new photos/videos found on camera"); -    } - -    private static int64 preview_comparator(void *a, void *b) { -        return ((ImportPreview *) a)->get_import_source().get_exposure_time() -            - ((ImportPreview *) b)->get_import_source().get_exposure_time(); -    } -     -    private static bool preview_comparator_predicate(DataObject object, Alteration alteration) { -        return alteration.has_detail("metadata", "exposure-time"); -    } -     -    private int64 import_job_comparator(void *a, void *b) { -        return ((CameraImportJob *) a)->get_exposure_time() - ((CameraImportJob *) b)->get_exposure_time(); -    } -     -    protected override void init_collect_ui_filenames(Gee.List<string> ui_filenames) { -        base.init_collect_ui_filenames(ui_filenames); -         -        ui_filenames.add("import.ui"); -    } - -    private const GLib.ActionEntry[] entries = { -        { "ImportSelected", on_import_selected }, -        { "ImportAll", on_import_all }, -        // Toggle actions -        { "ViewTitle", on_action_toggle, null, "false", on_display_titles }, -    }; - -    protected override void add_actions (GLib.ActionMap map) { -        base.add_actions (map); - -        map.add_action_entries (entries, this); - -        get_action ("ViewTitle").change_state (Config.Facade.get_instance ().get_display_photo_titles ()); -    } - -    protected override void remove_actions(GLib.ActionMap map) { -        base.remove_actions(map); -        foreach (var entry in entries) { -            map.remove_action(entry.name); -        } -    } - -    public GPhoto.Camera get_camera() { -        return camera; -    } -     -    public string get_uri() { -        return uri; -    } -     -    public bool is_busy() { -        return busy; -    } -     -    protected override void init_actions(int selected_count, int count) { -        on_view_changed(); -         -        set_action_important("ImportSelected", true); -        set_action_important("ImportAll", true); -         -        base.init_actions(selected_count, count); -    } -     -    public bool is_refreshed() { -        return refreshed && !busy; -    } -     -    public string? get_refresh_message() { -        string msg = null; -        if (refresh_error != null) { -            msg = refresh_error; -        } else if (refresh_result == GPhoto.Result.OK) { -            // all went well -        } else { -            msg = refresh_result.to_full_string(); -        } -         -        return msg; -    } -     -    private void update_status(bool busy, bool refreshed) { -        this.busy = busy; -        this.refreshed = refreshed; -         -        on_view_changed(); -    } - -    private void update_toolbar_state() { -        if (hide_imported != null) -            hide_imported.sensitive = !busy && refreshed && (get_view().get_unfiltered_count() > 0); -    } -     -    private void on_view_changed() { -        set_action_sensitive("ImportSelected", !busy && refreshed && get_view().get_selected_count() > 0); -        set_action_sensitive("ImportAll", !busy && refreshed && get_view().get_count() > 0); -        set_action_sensitive("CommonSelectAll", !busy && (get_view().get_count() > 0)); - -        update_toolbar_state(); -    } -     -    private void on_media_added_removed() { -        search_filter.refresh(); -    } - -    private void on_display_titles(GLib.SimpleAction action, Variant? value) { -        bool display = value.get_boolean (); - -        set_display_titles(display); - -        Config.Facade.get_instance().set_display_photo_titles(display); -        action.set_state (value); -    } - -    public override void switched_to() { -        set_display_titles(Config.Facade.get_instance().get_display_photo_titles()); -         -        base.switched_to(); -    } - -    public override void ready() { -        try_refreshing_camera(false); -        hide_imported_filter.refresh(); -    } - -    private void try_refreshing_camera(bool fail_on_locked) { -        // if camera has been refreshed or is in the process of refreshing, go no further -        if (refreshed || busy) -            return; -         -        RefreshResult res = refresh_camera(); -        switch (res) { -            case ImportPage.RefreshResult.OK: -            case ImportPage.RefreshResult.BUSY: -                // nothing to report; if busy, let it continue doing its thing -                // (although earlier check should've caught this) -            break; -             -            case ImportPage.RefreshResult.LOCKED: -                if (fail_on_locked) { -                    AppWindow.error_message(UNMOUNT_FAILED_MSG); -                     -                    break; -                } -                 -                // if locked because it's mounted, offer to unmount -                debug("Checking if %s is mounted…", uri); - -                File uri = File.new_for_uri(uri); - -                Mount mount = null; -                try { -                    mount = uri.find_enclosing_mount(null); -                } catch (Error err) { -                    // error means not mounted -                } -                 -                if (mount != null) { -                    // it's mounted, offer to unmount for the user -                    string mounted_message = _("Shotwell needs to unmount the camera from the filesystem in order to access it. Continue?"); - -                    Gtk.MessageDialog dialog = new Gtk.MessageDialog(AppWindow.get_instance(),  -                        Gtk.DialogFlags.MODAL, Gtk.MessageType.QUESTION, -                        Gtk.ButtonsType.CANCEL, "%s", mounted_message); -                    dialog.title = Resources.APP_TITLE; -                    dialog.add_button(_("_Unmount"), Gtk.ResponseType.YES); -                    int dialog_res = dialog.run(); -                    dialog.destroy(); -                     -                    if (dialog_res != Gtk.ResponseType.YES) { -                        set_page_message(_("Please unmount the camera.")); -                    } else { -                        unmount_camera(mount); -                    } -                } else { -                    string locked_message = _("The camera is locked by another application. Shotwell can only access the camera when it’s unlocked. Please close any other application using the camera and try again."); - -                    // it's not mounted, so another application must have it locked -                    Gtk.MessageDialog dialog = new Gtk.MessageDialog(AppWindow.get_instance(), -                        Gtk.DialogFlags.MODAL, Gtk.MessageType.WARNING, -                        Gtk.ButtonsType.OK, "%s", locked_message); -                    dialog.title = Resources.APP_TITLE; -                    dialog.run(); -                    dialog.destroy(); -                     -                    set_page_message(_("Please close any other application using the camera.")); -                } -            break; -             -            case ImportPage.RefreshResult.LIBRARY_ERROR: -                AppWindow.error_message(_("Unable to fetch previews from the camera:\n%s").printf( -                    get_refresh_message())); -            break; -             -            default: -                error("Unknown result type %d", (int) res); -        } -    } -     -    public bool unmount_camera(Mount mount) { -        if (busy) -            return false; -         -        update_status(true, false); -        progress_bar.visible = true; -        progress_bar.set_fraction(0.0); -        progress_bar.set_ellipsize(Pango.EllipsizeMode.NONE); -        progress_bar.set_text(_("Unmounting…")); -         -        // unmount_with_operation() can/will complete with the volume still mounted (probably meaning -        // it's been *scheduled* for unmounting).  However, this signal is fired when the mount -        // really is unmounted -- *if* a VolumeMonitor has been instantiated. -        mount.unmounted.connect(on_unmounted); -         -        debug("Unmounting camera…"); -        mount.unmount_with_operation.begin(MountUnmountFlags.NONE,  -            new Gtk.MountOperation(AppWindow.get_instance()), null, on_unmount_finished); -         -        return true; -    } -     -    private void on_unmount_finished(Object? source, AsyncResult aresult) { -        debug("Async unmount finished"); -         -        Mount mount = (Mount) source; -        try { -            mount.unmount_with_operation.end(aresult); -        } catch (Error err) { -            AppWindow.error_message(UNMOUNT_FAILED_MSG); -             -            // don't trap this signal, even if it does come in, we've backed off -            mount.unmounted.disconnect(on_unmounted); -             -            update_status(false, refreshed); -            progress_bar.set_ellipsize(Pango.EllipsizeMode.NONE); -            progress_bar.set_text(""); -            progress_bar.visible = false; -        } -    } -     -    private void on_unmounted(Mount mount) { -        debug("on_unmounted"); -         -        update_status(false, refreshed); -        progress_bar.set_ellipsize(Pango.EllipsizeMode.NONE); -        progress_bar.set_text(""); -        progress_bar.visible = false; -         -        try_refreshing_camera(true); -    } -     -    private void clear_all_import_sources() { -        Marker marker = import_sources.start_marking(); -        marker.mark_all(); -        import_sources.destroy_marked(marker, false); -    } - -    /** -     * @brief Returns whether the current device has a given directory or not. -     * -     * @param fsid The file system id of the camera or other device to search. -     * @param dir The path to start searching from. -     * @param search_target The name of the directory to look for. -     */ -    private bool check_directory_exists(int fsid, string dir, string search_target) { -        string? fulldir = get_fulldir(camera, camera_name, fsid, dir); -        GPhoto.Result result; -        GPhoto.CameraList folders; - -        result = GPhoto.CameraList.create(out folders); -        if (result != GPhoto.Result.OK) { -            // couldn't create a list - can't determine whether specified dir is present -            return false; -        } - -        result = camera.list_folders(fulldir, folders, spin_idle_context.context); -        if (result != GPhoto.Result.OK) { -            // fetching the list failed - can't determine whether specified dir is present -            return false; -        } - -        int list_len = folders.count(); - -        for(int list_index = 0; list_index < list_len; list_index++) { -            string tmp; - -            folders.get_name(list_index, out tmp); -            if (tmp == search_target) { -                return true; -            } -        } -        return false; -    } - -    private RefreshResult refresh_camera() { -        if (busy) -            return RefreshResult.BUSY; -             -        this.set_page_message (_("Starting import, please wait…")); - -        update_status(busy, false); -         -        refresh_error = null; -        refresh_result = camera.init(spin_idle_context.context); -        if (refresh_result != GPhoto.Result.OK) { -            warning("Unable to initialize camera: %s", refresh_result.to_full_string()); -             -            return (refresh_result == GPhoto.Result.IO_LOCK) ? RefreshResult.LOCKED : RefreshResult.LIBRARY_ERROR; -        } - -        update_status(true, refreshed); -         -        on_view_changed(); - -        progress_bar.set_ellipsize(Pango.EllipsizeMode.NONE); -        progress_bar.set_text(_("Fetching photo information")); -        progress_bar.set_fraction(0.0); -        progress_bar.set_pulse_step(0.01); -        progress_bar.visible = true; -         -        Gee.ArrayList<ImportSource> import_list = new Gee.ArrayList<ImportSource>(); -         -        GPhoto.CameraStorageInformation *sifs = null; -        int count = 0; -        refresh_result = camera.get_storageinfo(&sifs, out count, spin_idle_context.context); -        if (refresh_result == GPhoto.Result.OK) { -            for (int fsid = 0; fsid < count; fsid++) { -                // Check well-known video and image paths first to prevent accidental -                // scanning of undesired directories (which can cause user annoyance with -                // some smartphones or camera-equipped media players) -                bool got_well_known_dir = false; - -                // Check common paths for most primarily-still cameras, many (most?) smartphones -                if (check_directory_exists(fsid, "/", "DCIM")) { -                    enumerate_files(fsid, "/DCIM", import_list); -                    got_well_known_dir = true; -                } -                if (check_directory_exists(fsid, "/", "dcim")) { -                    enumerate_files(fsid, "/dcim", import_list); -                    got_well_known_dir = true; -                } - -                // Check common paths for AVCHD camcorders, primarily-still -                // cameras that shoot .mts video files -                if (check_directory_exists(fsid, "/PRIVATE/", "AVCHD")) { -                    enumerate_files(fsid, "/PRIVATE/AVCHD", import_list); -                    got_well_known_dir = true; -                } -                if (check_directory_exists(fsid, "/private/", "avchd")) { -                    enumerate_files(fsid, "/private/avchd", import_list); -                    got_well_known_dir = true; -                } -                if (check_directory_exists(fsid, "/", "AVCHD")) { -                    enumerate_files(fsid, "/AVCHD", import_list); -                    got_well_known_dir = true; -                } -                if (check_directory_exists(fsid, "/", "avchd")) { -                    enumerate_files(fsid, "/avchd", import_list); -                    got_well_known_dir = true; -                } - -                // Check common video paths for some Sony primarily-still -                // cameras -                if (check_directory_exists(fsid, "/PRIVATE/", "SONY")) { -                    enumerate_files(fsid, "/PRIVATE/SONY", import_list); -                    got_well_known_dir = true; -                } -                if (check_directory_exists(fsid, "/private/", "sony")) { -                    enumerate_files(fsid, "/private/sony", import_list); -                    got_well_known_dir = true; -                } - -                // Check common video paths for Sony NEX3, PSP addon camera  -                if (check_directory_exists(fsid, "/", "MP_ROOT")) { -                    enumerate_files(fsid, "/MP_ROOT", import_list); -                    got_well_known_dir = true; -                } -                if (check_directory_exists(fsid, "/", "mp_root")) { -                    enumerate_files(fsid, "/mp_root", import_list); -                    got_well_known_dir = true; -                } -                 -                // Didn't find any of the common directories we know about -                // already - try scanning from device root. -                if (!got_well_known_dir) { -                    if (!enumerate_files(fsid, "/", import_list)) -                        break; -                } -            } -        } - -        clear_all_import_sources(); - -        // Associate files (for RAW+JPEG) -        auto_match_raw_jpeg(import_list); -         -#if UNITY_SUPPORT -        //UnityProgressBar: try to draw progress bar -        uniprobar.set_visible(true); -#endif -         -        load_previews_and_metadata(import_list); -         -#if UNITY_SUPPORT -        //UnityProgressBar: reset -        uniprobar.reset(); -#endif -         -        progress_bar.visible = false; -        progress_bar.set_ellipsize(Pango.EllipsizeMode.NONE); -        progress_bar.set_text(""); -        progress_bar.set_fraction(0.0); -         -        GPhoto.Result res = camera.exit(spin_idle_context.context); -        if (res != GPhoto.Result.OK) { -            // log but don't fail -            warning("Unable to unlock camera: %s", res.to_full_string()); -        } -         -        if (refresh_result == GPhoto.Result.OK) { -            if (import_sources.get_count () == 0) { -                this.set_page_message (this.get_view_empty_message ()); -            } -            update_status(false, true); -        } else { -            update_status(false, false); -             -            // show 'em all or show none -            clear_all_import_sources(); -        } -         -        on_view_changed(); - -        switch (refresh_result) { -            case GPhoto.Result.OK: -                return RefreshResult.OK; -             -            case GPhoto.Result.IO_LOCK: -                return RefreshResult.LOCKED; -             -            default: -                return RefreshResult.LIBRARY_ERROR; -        } -    } -     -    private static string chomp_ch(string str, char ch) { -        long offset = str.length; -        while (--offset >= 0) { -            if (str[offset] != ch) -                return str.slice(0, offset); -        } -         -        return ""; -    } -     -    public static string append_path(string basepath, string addition) { -        if (!basepath.has_suffix("/") && !addition.has_prefix("/")) -            return basepath + "/" + addition; -        else if (basepath.has_suffix("/") && addition.has_prefix("/")) -            return chomp_ch(basepath, '/') + addition; -        else -            return basepath + addition; -    } -     -    // Need to do this because some phones (iPhone, in particular) changes the name of their filesystem -    // between each mount -    public static string? get_fs_basedir(GPhoto.Camera camera, int fsid) { -        GPhoto.CameraStorageInformation *sifs = null; -        int count = 0; -        GPhoto.Result res = camera.get_storageinfo(&sifs, out count, null_context.context); -        if (res != GPhoto.Result.OK) -            return null; -         -        if (fsid >= count) -            return null; -         -        GPhoto.CameraStorageInformation *ifs = sifs + fsid; -         -        return (ifs->fields & GPhoto.CameraStorageInfoFields.BASE) != 0 ? ifs->basedir : "/"; -    } -     -    public static string? get_fulldir(GPhoto.Camera camera, string camera_name, int fsid, string folder) { -        if (folder.length > GPhoto.MAX_BASEDIR_LENGTH) -            return null; -         -        string basedir = get_fs_basedir(camera, fsid); -        if (basedir == null) { -            debug("Unable to find base directory for %s fsid %d", camera_name, fsid); -             -            return folder; -        } -         -        return append_path(basedir, folder); -    } - -    private bool enumerate_files(int fsid, string dir, Gee.ArrayList<ImportSource> import_list) { -        string? fulldir = get_fulldir(camera, camera_name, fsid, dir); -        if (fulldir == null) { -            warning("Skipping enumerating %s: invalid folder name", dir); -             -            return true; -        } -         -        GPhoto.CameraList files; -        refresh_result = GPhoto.CameraList.create(out files); -        if (refresh_result != GPhoto.Result.OK) { -            warning("Unable to create file list: %s", refresh_result.to_full_string()); -             -            return false; -        } -         -        refresh_result = camera.list_files(fulldir, files, spin_idle_context.context); -        if (refresh_result != GPhoto.Result.OK) { -            warning("Unable to list files in %s: %s", fulldir, refresh_result.to_full_string()); -             -            // Although an error, don't abort the import because of this -            refresh_result = GPhoto.Result.OK; -             -            return true; -        } - -        for (int ctr = 0; ctr < files.count(); ctr++) { -            string filename; -            refresh_result = files.get_name(ctr, out filename); -            if (refresh_result != GPhoto.Result.OK) { -                warning("Unable to get the name of file %d in %s: %s", ctr, fulldir, -                    refresh_result.to_full_string()); -                 -                return false; -            } -             -            try { -                GPhoto.CameraFileInfo info; -                if (!GPhoto.get_info(spin_idle_context.context, camera, fulldir, filename, out info)) { -                    warning("Skipping import of %s/%s: name too long", fulldir, filename); -                     -                    continue; -                } -                 -                if ((info.file.fields & GPhoto.CameraFileInfoFields.TYPE) == 0) { -                    message("Skipping %s/%s: No file (file=%02Xh)", fulldir, filename, -                        info.file.fields); -                         -                    continue; -                } -                 -                if (VideoReader.is_supported_video_filename(filename)) { -                    VideoImportSource video_source = new VideoImportSource(camera_name, camera, -                        fsid, dir, filename, info.file.size, info.file.mtime); -                    import_list.add(video_source); -                } else { -                    // determine file format from type, and then from file extension -                    PhotoFileFormat file_format = PhotoFileFormat.from_gphoto_type(info.file.type);                -                    if (file_format == PhotoFileFormat.UNKNOWN) { -                        file_format = PhotoFileFormat.get_by_basename_extension(filename); -                        if (file_format == PhotoFileFormat.UNKNOWN) { -                            message("Skipping %s/%s: Not a supported file extension (%s)", fulldir, -                                filename, info.file.type); -                             -                            continue; -                        } -                    } -                    import_list.add(new PhotoImportSource(camera_name, camera, fsid, dir, filename, -                        info.file.size, info.file.mtime, file_format)); -                } -                 -                progress_bar.pulse(); -                 -                // spin the event loop so the UI doesn't freeze -                spin_event_loop(); -            } catch (Error err) { -                warning("Error while enumerating files in %s: %s", fulldir, err.message); -                 -                refresh_error = err.message; -                 -                return false; -            } -        } -         -        GPhoto.CameraList folders; -        refresh_result = GPhoto.CameraList.create(out folders); -        if (refresh_result != GPhoto.Result.OK) { -            warning("Unable to create folder list: %s", refresh_result.to_full_string()); -             -            return false; -        } -         -        refresh_result = camera.list_folders(fulldir, folders, spin_idle_context.context); -        if (refresh_result != GPhoto.Result.OK) { -            warning("Unable to list folders in %s: %s", fulldir, refresh_result.to_full_string()); -             -            // Although an error, don't abort the import because of this -            refresh_result = GPhoto.Result.OK; -             -            return true; -        } -         -        for (int ctr = 0; ctr < folders.count(); ctr++) { -            string subdir; -            refresh_result = folders.get_name(ctr, out subdir); -            if (refresh_result != GPhoto.Result.OK) { -                warning("Unable to get name of folder %d: %s", ctr, refresh_result.to_full_string()); -                 -                return false; -            } -             -            if (!enumerate_files(fsid, append_path(dir, subdir), import_list)) -                return false; -        } -         -        return true; -    } -     -    // Try to match RAW+JPEG pairs. -    private void auto_match_raw_jpeg(Gee.ArrayList<ImportSource> import_list) { -        for (int i = 0; i < import_list.size; i++) { -            PhotoImportSource? current = import_list.get(i) as PhotoImportSource; -            PhotoImportSource? next = (i + 1 < import_list.size) ?  -                import_list.get(i + 1) as PhotoImportSource : null; -            PhotoImportSource? prev = (i > 0) ?  -                import_list.get(i - 1) as PhotoImportSource : null; -            if (current != null && current.get_file_format() == PhotoFileFormat.RAW) { -                string current_name; -                string ext; -                disassemble_filename(current.get_filename(), out current_name, out ext); -                 -                // Try to find a matching pair. -                PhotoImportSource? associated = null; -                if (next != null && next.get_file_format() == PhotoFileFormat.JFIF) { -                    string next_name; -                    disassemble_filename(next.get_filename(), out next_name, out ext); -                    if (next_name == current_name) -                        associated = next; -                } -                if (prev != null && prev.get_file_format() == PhotoFileFormat.JFIF) { -                    string prev_name; -                    disassemble_filename(prev.get_filename(), out prev_name, out ext); -                    if (prev_name == current_name) -                        associated = prev; -                } -                 -                // Associate! -                if (associated != null) { -                    debug("Found RAW+JPEG pair: %s and %s", current.get_filename(), associated.get_filename()); -                    current.set_associated(associated); -                    if (!import_list.remove(associated)) { -                        debug("Unable to associate files"); -                        current.set_associated(null); -                    } -                } -            } -        } -    } -     -    private void load_previews_and_metadata(Gee.List<ImportSource> import_list) { -        int loaded_photos = 0; -        foreach (ImportSource import_source in import_list) { -            string filename = import_source.get_filename(); -            string? fulldir = import_source.get_fulldir(); -            if (fulldir == null) { -                warning("Skipping loading preview of %s: invalid folder name", import_source.to_string()); -                 -                continue; -            } -             -            // Get JPEG pair, if available. -            PhotoImportSource? associated = null; -            if (import_source is PhotoImportSource &&  -                ((PhotoImportSource) import_source).get_associated() != null) { -                associated = ((PhotoImportSource) import_source).get_associated(); -            } -             -            progress_bar.set_ellipsize(Pango.EllipsizeMode.MIDDLE); -            progress_bar.set_text(_("Fetching preview for %s").printf(import_source.get_name())); -             -            // Ask GPhoto to read the current file's metadata, but only if the file is not a -            // video. Across every memory card and camera type I've tested (lucas, as of 10/27/2010) -            // GPhoto always loads null metadata for videos. So without the is-not-video guard, -            // this code segment just needlessly and annoyingly prints a warning message to the -            // console. -            PhotoMetadata? metadata = null; -            if (!VideoReader.is_supported_video_filename(filename)) { -                try { -                    metadata = GPhoto.load_metadata(spin_idle_context.context, camera, fulldir, -                        filename); -                } catch (Error err) { -                    warning("Unable to fetch metadata for %s/%s: %s", fulldir, filename, -                        err.message); -                } -            } -             -            // calculate EXIF's fingerprint -            string? exif_only_md5 = null; -            if (metadata != null) { -                uint8[]? flattened_sans_thumbnail = metadata.flatten_exif(false); -                if (flattened_sans_thumbnail != null && flattened_sans_thumbnail.length > 0) -                    exif_only_md5 = md5_binary(flattened_sans_thumbnail, flattened_sans_thumbnail.length); -            } -             -            // XXX: Cannot use the metadata for the thumbnail preview because libgphoto2 -            // 2.4.6 has a bug where the returned EXIF data object is complete garbage.  This -            // is fixed in 2.4.7, but need to work around this as best we can.  In particular, -            // this means the preview orientation will be wrong and the MD5 is not generated -            // if the EXIF did not parse properly (see above) -             -            uint8[] preview_raw = null; -            size_t preview_raw_length = 0; -            Gdk.Pixbuf preview = null; -            try { -                string preview_fulldir = fulldir; -                string preview_filename = filename; -                if (associated != null) { -                    preview_fulldir = associated.get_fulldir(); -                    preview_filename = associated.get_filename(); -                } -                preview = GPhoto.load_preview(spin_idle_context.context, camera, preview_fulldir, -                    preview_filename, out preview_raw, out preview_raw_length); -            } catch (Error err) { -                // only issue the warning message if we're not reading a video. GPhoto is capable -                // of reading video previews about 50% of the time, so we don't want to put a guard -                // around this entire code segment like we did with the metadata-read segment above, -                // however video previews being absent is so common that there's no reason -                // we should generate a warning for one. -                if (!VideoReader.is_supported_video_filename(filename)) { -                    warning("Unable to fetch preview for %s/%s: %s", fulldir, filename, err.message); -                } -            } -             -            // calculate thumbnail fingerprint -            string? preview_md5 = null; -            if (preview != null && preview_raw != null && preview_raw_length > 0) -                preview_md5 = md5_binary(preview_raw, preview_raw_length); -             -#if TRACE_MD5 -            debug("camera MD5 %s: exif=%s preview=%s", filename, exif_only_md5, preview_md5); -#endif - -            if (import_source is VideoImportSource) -                (import_source as VideoImportSource).update(preview); - -            if (import_source is PhotoImportSource) -                (import_source as PhotoImportSource).update(preview, preview_md5, metadata, -                    exif_only_md5); -             -            if (associated != null) { -                try { -                    PhotoMetadata? associated_metadata = GPhoto.load_metadata(spin_idle_context.context,  -                        camera, associated.get_fulldir(), associated.get_filename()); -                    associated.update(preview, preview_md5, associated_metadata, null); -                } catch (Error err) { -                    warning("Unable to fetch metadata for %s/%s: %s",  associated.get_fulldir(), -                        associated.get_filename(), err.message); -                } -            } -             -            // *now* add to the SourceCollection, now that it is completed -            import_sources.add(import_source); -             -            progress_bar.set_fraction((double) (++loaded_photos) / (double) import_list.size); -#if UNITY_SUPPORT -            //UnityProgressBar: set progress -            uniprobar.set_progress((double) (loaded_photos) / (double) import_list.size); -#endif -             -            // spin the event loop so the UI doesn't freeze -            spin_event_loop(); -        } -    } -     -    private void on_hide_imported() { -        if (hide_imported.get_active()) -            get_view().install_view_filter(hide_imported_filter); -        else -            get_view().remove_view_filter(hide_imported_filter); -         -        Config.Facade.get_instance().set_hide_photos_already_imported(hide_imported.get_active()); -    } -     -    private void on_import_selected() { -        import(get_view().get_selected()); -    } -     -    private void on_import_all() { -        import(get_view().get_all()); -    } -     -    private void import(Gee.Iterable<DataObject> items) { -        GPhoto.Result res = camera.init(spin_idle_context.context); -        if (res != GPhoto.Result.OK) { -            AppWindow.error_message(_("Unable to lock camera: %s").printf(res.to_full_string())); -             -            return; -        } - -        update_status(true, refreshed); -         -        on_view_changed(); -        progress_bar.visible = false; - -        SortedList<CameraImportJob> jobs = new SortedList<CameraImportJob>(import_job_comparator); -        Gee.ArrayList<CameraImportJob> already_imported = new Gee.ArrayList<CameraImportJob>(); -         -        foreach (DataObject object in items) { -            ImportPreview preview = (ImportPreview) object; -            ImportSource import_file = (ImportSource) preview.get_source(); -             -            if (preview.is_already_imported()) { -                message("Skipping import of %s: checksum detected in library",  -                    import_file.get_filename()); -                 -                already_imported.add(new CameraImportJob(null_context, import_file, -                    preview.get_duplicated_file())); -                 -                continue; -            } -             -            CameraImportJob import_job = new CameraImportJob(null_context, import_file); -             -            // Maintain RAW+JPEG association. -            if (import_file is PhotoImportSource &&  -                ((PhotoImportSource) import_file).get_associated() != null) { -                import_job.set_associated(new CameraImportJob(null_context,  -                    ((PhotoImportSource) import_file).get_associated())); -            } -             -            jobs.add(import_job); -        } -         -        debug("Importing %d files from %s", jobs.size, camera_name); -         -        if (jobs.size > 0) { -            // see import_reporter() to see why this is held during the duration of the import -            assert(local_ref == null); -            local_ref = this; -             -            BatchImport batch_import = new BatchImport(jobs, camera_name, import_reporter, -                null, already_imported); -            batch_import.import_job_failed.connect(on_import_job_failed); -            batch_import.import_complete.connect(close_import); -             -            LibraryWindow.get_app().enqueue_batch_import(batch_import, true); -            LibraryWindow.get_app().switch_to_import_queue_page(); -            // camera.exit() and busy flag will be handled when the batch import completes -        } else { -            // since failed up-front, build a fake (faux?) ImportManifest and report it here -            if (already_imported.size > 0) -                import_reporter(new ImportManifest(null, already_imported)); -             -            close_import(); -        } -    } -     -    private void on_import_job_failed(BatchImportResult result) { -        if (result.file == null || result.result == ImportResult.SUCCESS) -            return; -             -        // delete the copied file -        try { -            result.file.delete(null); -        } catch (Error err) { -            message("Unable to delete downloaded file %s: %s", result.file.get_path(), err.message); -        } -    } -     -    private void import_reporter(ImportManifest manifest) { -        // TODO: Need to keep the ImportPage around until the BatchImport is completed, but the -        // page controller (i.e. LibraryWindow) needs to know (a) if ImportPage is busy before -        // removing and (b) if it is, to be notified when it ain't.  Until that's in place, need -        // to hold the ref so the page isn't destroyed ... this switcheroo keeps the ref alive -        // until this function returns (at any time) -        ImportPage? local_ref = this.local_ref; -        this.local_ref = null; -         -        if (manifest.success.size > 0) { -            string photos_string = (ngettext("Delete this photo from camera?", -                "Delete these %d photos from camera?",  -                manifest.success.size)).printf(manifest.success.size); -            string videos_string = (ngettext("Delete this video from camera?", -                "Delete these %d videos from camera?",  -                manifest.success.size)).printf(manifest.success.size); -            string both_string = (ngettext("Delete this photo/video from camera?", -                "Delete these %d photos/videos from camera?",  -                manifest.success.size)).printf(manifest.success.size); -            string neither_string = (ngettext("Delete these files from camera?", -                "Delete these %d files from camera?",  -                manifest.success.size)).printf(manifest.success.size); - -            string question_string = ImportUI.get_media_specific_string(manifest.success, -                photos_string, videos_string, both_string, neither_string); - -            ImportUI.QuestionParams question = new ImportUI.QuestionParams( -                question_string, Resources.DELETE_LABEL, _("_Keep")); -         -            if (!ImportUI.report_manifest(manifest, false, question)) -                return; -        } else { -            ImportUI.report_manifest(manifest, false, null); -            return; -        } -         -        // delete the photos from the camera and the SourceCollection... for now, this is an  -        // all-or-nothing deal -        Marker marker = import_sources.start_marking(); -        foreach (BatchImportResult batch_result in manifest.success) { -            CameraImportJob job = batch_result.job as CameraImportJob; -             -            marker.mark(job.get_source()); -        } -         -        ProgressDialog progress = new ProgressDialog(AppWindow.get_instance(),  -            _("Removing photos/videos from camera"), new Cancellable()); -        int error_count = import_sources.destroy_marked(marker, true, progress.monitor); -        if (error_count > 0) { -            string error_string = -                (ngettext("Unable to delete %d photo/video from the camera due to errors.", -                "Unable to delete %d photos/videos from the camera due to errors.", error_count)).printf( -                error_count); -            AppWindow.error_message(error_string); -        } -         -        progress.close(); -         -        // to stop build warnings -        local_ref = null; -    } - -    private void close_import() { -        GPhoto.Result res = camera.exit(spin_idle_context.context); -        if (res != GPhoto.Result.OK) { -            // log but don't fail -            message("Unable to unlock camera: %s", res.to_full_string()); -        } -         -        update_status(false, refreshed); -         -        on_view_changed(); -    } - -    public override void set_display_titles(bool display) { -        base.set_display_titles(display); - -        set_action_active ("ViewTitle", display); -    } -     -    // Gets the search view filter for this page. -    public override SearchViewFilter get_search_view_filter() { -        return search_filter; -    } -} - diff --git a/.pc/applied-patches b/.pc/applied-patches deleted file mode 100644 index 1f5bb0c..0000000 --- a/.pc/applied-patches +++ /dev/null @@ -1 +0,0 @@ -0100-ios8.patch diff --git a/src/camera/ImportPage.vala b/src/camera/ImportPage.vala index 67a298a..4e055ec 100644 --- a/src/camera/ImportPage.vala +++ b/src/camera/ImportPage.vala @@ -773,15 +773,6 @@ public class ImportPage : CheckerboardPage {      ~ImportPage() {          LibraryPhoto.global.contents_altered.disconnect(on_media_added_removed);          Video.global.contents_altered.disconnect(on_media_added_removed); - -        // iOS 8 issue. Release the camera here -        if (camera != null) { -          GPhoto.Result res = camera.exit(spin_idle_context.context); -          if (res != GPhoto.Result.OK) { -              // log but don't fail -              warning("ImportPage destructor: Unable to unlock camera: %s", res.to_full_string()); -          } -        }      }      public override Gtk.Toolbar get_toolbar() { @@ -1171,14 +1162,11 @@ public class ImportPage : CheckerboardPage {          update_status(busy, false);          refresh_error = null; -        // iOS 8 issue -        if (camera == null) { -          refresh_result = camera.init(spin_idle_context.context); -          if (refresh_result != GPhoto.Result.OK) { -              warning("Unable to initialize camera: %s", refresh_result.to_full_string()); - -              return (refresh_result == GPhoto.Result.IO_LOCK) ? RefreshResult.LOCKED : RefreshResult.LIBRARY_ERROR; -          } +        refresh_result = camera.init(spin_idle_context.context); +        if (refresh_result != GPhoto.Result.OK) { +            warning("Unable to initialize camera: %s", refresh_result.to_full_string()); +             +            return (refresh_result == GPhoto.Result.IO_LOCK) ? RefreshResult.LOCKED : RefreshResult.LIBRARY_ERROR;          }          update_status(true, refreshed); @@ -1283,15 +1271,13 @@ public class ImportPage : CheckerboardPage {          progress_bar.set_ellipsize(Pango.EllipsizeMode.NONE);          progress_bar.set_text("");          progress_bar.set_fraction(0.0); - -#if 0 +                  GPhoto.Result res = camera.exit(spin_idle_context.context);          if (res != GPhoto.Result.OK) {              // log but don't fail              warning("Unable to unlock camera: %s", res.to_full_string());          } -#endif - +                  if (refresh_result == GPhoto.Result.OK) {              if (import_sources.get_count () == 0) {                  this.set_page_message (this.get_view_empty_message ()); @@ -1660,15 +1646,11 @@ public class ImportPage : CheckerboardPage {      }      private void import(Gee.Iterable<DataObject> items) { -        // We now keep the camera open as long as we can to -        // work around the iOS 8 directory name shuffling issue. -        if (camera == null) { -          GPhoto.Result res = camera.init(spin_idle_context.context); -          if (res != GPhoto.Result.OK) { -              AppWindow.error_message(_("Unable to lock camera: %s").printf(res.to_full_string())); - -              return; -          } +        GPhoto.Result res = camera.init(spin_idle_context.context); +        if (res != GPhoto.Result.OK) { +            AppWindow.error_message(_("Unable to lock camera: %s").printf(res.to_full_string())); +             +            return;          }          update_status(true, refreshed); @@ -1804,15 +1786,12 @@ public class ImportPage : CheckerboardPage {      }      private void close_import() { -// iOS 8 issue -#if 0          GPhoto.Result res = camera.exit(spin_idle_context.context);          if (res != GPhoto.Result.OK) {              // log but don't fail              message("Unable to unlock camera: %s", res.to_full_string());          } -#endif - +                  update_status(false, refreshed);          on_view_changed(); | 
