+ _instance = nullptr;
+}
+
+
+void
+JobManager::analyse_audio (
+ shared_ptr<const Film> film,
+ shared_ptr<const Playlist> playlist,
+ bool from_zero,
+ boost::signals2::connection& connection,
+ function<void (Job::Result)> ready
+ )
+{
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+
+ for (auto i: _jobs) {
+ auto a = dynamic_pointer_cast<AnalyseAudioJob> (i);
+ if (a && a->path() == film->audio_analysis_path(playlist) && !i->finished_cancelled()) {
+ i->when_finished (connection, ready);
+ return;
+ }
+ }
+ }
+
+ shared_ptr<AnalyseAudioJob> job;
+
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+
+ job = make_shared<AnalyseAudioJob> (film, playlist, from_zero);
+ connection = job->Finished.connect (ready);
+ _jobs.push_back (job);
+ _schedule_condition.notify_all ();
+ }
+
+ emit (boost::bind (boost::ref (JobAdded), weak_ptr<Job> (job)));
+}
+
+
+void
+JobManager::analyse_subtitles (
+ shared_ptr<const Film> film,
+ shared_ptr<Content> content,
+ boost::signals2::connection& connection,
+ function<void (Job::Result)> ready
+ )
+{
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+
+ for (auto i: _jobs) {
+ auto a = dynamic_pointer_cast<AnalyseSubtitlesJob> (i);
+ if (a && a->path() == film->subtitle_analysis_path(content) && !i->finished_cancelled()) {
+ i->when_finished (connection, ready);
+ return;
+ }
+ }
+ }
+
+ shared_ptr<AnalyseSubtitlesJob> job;
+
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+
+ job = make_shared<AnalyseSubtitlesJob>(film, content);
+ connection = job->Finished.connect (ready);
+ _jobs.push_back (job);
+ _schedule_condition.notify_all ();
+ }
+
+ emit (boost::bind(boost::ref(JobAdded), weak_ptr<Job>(job)));
+}
+
+
+void
+JobManager::increase_priority (shared_ptr<Job> job)
+{
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+ auto iter = std::find(_jobs.begin(), _jobs.end(), job);
+ if (iter == _jobs.begin() || iter == _jobs.end()) {
+ return;
+ }
+ swap(*iter, *std::prev(iter));
+ }
+
+ _schedule_condition.notify_all();
+ emit(boost::bind(boost::ref(JobsReordered)));
+}
+
+
+void
+JobManager::decrease_priority (shared_ptr<Job> job)
+{
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+ auto iter = std::find(_jobs.begin(), _jobs.end(), job);
+ if (iter == _jobs.end() || std::next(iter) == _jobs.end()) {
+ return;
+ }
+ swap(*iter, *std::next(iter));
+ }
+
+ _schedule_condition.notify_all();
+ emit(boost::bind(boost::ref(JobsReordered)));
+}
+
+
+/** Pause all job processing */
+void
+JobManager::pause ()
+{
+ boost::mutex::scoped_lock lm (_mutex);
+ _paused = true;
+ _schedule_condition.notify_all();
+}
+
+
+/** Resume processing jobs after a previous pause() */
+void
+JobManager::resume ()
+{
+ boost::mutex::scoped_lock lm (_mutex);
+ _paused = false;
+ _schedule_condition.notify_all();