/* Copyright 2016 Software Freedom Conservancy Inc. * * This software is licensed under the GNU Lesser General Public License * (version 2.1 or later). See the COPYING file in this distribution. */ private class VideoUpdates : MonitorableUpdates { public Video video; private bool check_interpretable = false; public VideoUpdates(Video video) { base (video); this.video = video; } public virtual void set_check_interpretable(bool check) { check_interpretable = check; } public override void mark_online() { base.mark_online(); set_check_interpretable(true); } public bool is_check_interpretable() { return check_interpretable; } public override bool is_all_updated() { return (check_interpretable == false) && base.is_all_updated(); } } private class VideoMonitor : MediaMonitor { private const int MAX_INTERPRETABLE_CHECKS_PER_CYCLE = 5; // Performs interpretable check on video. In a background job because // this will create a new thumbnail for the video. private class VideoInterpretableCheckJob : BackgroundJob { // IN public Video video; // OUT public Video.InterpretableResults? results = null; public VideoInterpretableCheckJob(Video video, CompletionCallback? callback = null) { base (video, callback); this.video = video; } public override void execute() { results = video.check_is_interpretable(); } } // Work queue for video thumbnailing. // Note: only using 1 thread. If we want to change this to use multiple // threads, we need to put a lock around background_jobs wherever it's modified. private Workers workers = new Workers(1, false); private uint64 background_jobs = 0; public VideoMonitor(Cancellable cancellable) { base (Video.global, cancellable); foreach (DataObject obj in Video.global.get_all()) { Video video = obj as Video; assert (video != null); if (!video.get_is_interpretable()) set_check_interpretable(video, true); } } protected override MonitorableUpdates create_updates(Monitorable monitorable) { assert(monitorable is Video); return new VideoUpdates((Video) monitorable); } public override MediaSourceCollection get_media_source_collection() { return Video.global; } public override bool is_file_represented(File file) { VideoSourceCollection.State state; return get_state(file, out state) != null; } public override MediaMonitor.DiscoveredFile notify_file_discovered(File file, FileInfo info, out Monitorable monitorable) { VideoSourceCollection.State state; Video? video = get_state(file, out state); if (video == null) { monitorable = null; return MediaMonitor.DiscoveredFile.UNKNOWN; } switch (state) { case VideoSourceCollection.State.ONLINE: case VideoSourceCollection.State.OFFLINE: monitorable = video; return MediaMonitor.DiscoveredFile.REPRESENTED; case VideoSourceCollection.State.TRASH: default: // ignored ... trash always stays in trash monitorable = null; return MediaMonitor.DiscoveredFile.IGNORE; } } public override Gee.Collection? candidates_for_unknown_file(File file, FileInfo info, out MediaMonitor.DiscoveredFile result) { Gee.Collection