diff options
| author | Carl Hetherington <cth@carlh.net> | 2015-09-02 11:20:24 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2015-09-14 10:20:41 +0100 |
| commit | d2bd0c628fd0616fe3b7dd02bd955b2c07ab48d5 (patch) | |
| tree | e974870e7e4b6014520b461a19a7b336eb7617a3 /src/lib | |
| parent | c138f4050bffbdc97edca8a824297f155dc62da3 (diff) | |
Add option to analyse audio automatically when content is added (#673).
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/analyse_audio_job.h | 5 | ||||
| -rw-r--r-- | src/lib/config.cc | 3 | ||||
| -rw-r--r-- | src/lib/config.h | 9 | ||||
| -rw-r--r-- | src/lib/film.cc | 29 | ||||
| -rw-r--r-- | src/lib/film.h | 2 | ||||
| -rw-r--r-- | src/lib/job.cc | 13 | ||||
| -rw-r--r-- | src/lib/job.h | 2 | ||||
| -rw-r--r-- | src/lib/job_manager.cc | 63 | ||||
| -rw-r--r-- | src/lib/job_manager.h | 16 |
9 files changed, 120 insertions, 22 deletions
diff --git a/src/lib/analyse_audio_job.h b/src/lib/analyse_audio_job.h index d484bff2c..d9b90ec66 100644 --- a/src/lib/analyse_audio_job.h +++ b/src/lib/analyse_audio_job.h @@ -28,6 +28,7 @@ class AudioBuffers; class AudioAnalysis; class Playlist; +class AudioPoint; /** @class AnalyseAudioJob * @brief A job to analyse the audio of a film and make a note of its @@ -46,6 +47,10 @@ public: std::string json_name () const; void run (); + boost::shared_ptr<const Playlist> playlist () const { + return _playlist; + } + private: void analyse (boost::shared_ptr<const AudioBuffers>); diff --git a/src/lib/config.cc b/src/lib/config.cc index fc71a72f3..20386368e 100644 --- a/src/lib/config.cc +++ b/src/lib/config.cc @@ -97,6 +97,7 @@ Config::set_defaults () _check_for_test_updates = false; _maximum_j2k_bandwidth = 250000000; _log_types = Log::TYPE_GENERAL | Log::TYPE_WARNING | Log::TYPE_ERROR; + _automatic_audio_analysis = false; #ifdef DCPOMATIC_WINDOWS _win32_console = false; #endif @@ -231,6 +232,7 @@ Config::read () _allow_any_dcp_frame_rate = f.optional_bool_child ("AllowAnyDCPFrameRate"); _log_types = f.optional_number_child<int> ("LogTypes").get_value_or (Log::TYPE_GENERAL | Log::TYPE_WARNING | Log::TYPE_ERROR); + _automatic_audio_analysis = f.optional_bool_child ("AutomaticAudioAnalysis").get_value_or (false); #ifdef DCPOMATIC_WINDOWS _win32_console = f.optional_bool_child ("Win32Console").get_value_or (false); #endif @@ -375,6 +377,7 @@ Config::write () const root->add_child("MaximumJ2KBandwidth")->add_child_text (raw_convert<string> (_maximum_j2k_bandwidth)); root->add_child("AllowAnyDCPFrameRate")->add_child_text (_allow_any_dcp_frame_rate ? "1" : "0"); root->add_child("LogTypes")->add_child_text (raw_convert<string> (_log_types)); + root->add_child("AutomaticAudioAnalysis")->add_child_text (_automatic_audio_analysis ? "1" : "0"); #ifdef DCPOMATIC_WINDOWS root->add_child("Win32Console")->add_child_text (_win32_console ? "1" : "0"); #endif diff --git a/src/lib/config.h b/src/lib/config.h index fc63c518c..2f68ea31c 100644 --- a/src/lib/config.h +++ b/src/lib/config.h @@ -226,6 +226,10 @@ public: return _log_types; } + bool automatic_audio_analysis () const { + return _automatic_audio_analysis; + } + #ifdef DCPOMATIC_WINDOWS bool win32_console () const { return _win32_console; @@ -407,6 +411,10 @@ public: maybe_set (_log_types, t); } + void set_automatic_audio_analysis (bool a) { + maybe_set (_automatic_audio_analysis, a); + } + #ifdef DCPOMATIC_WINDOWS void set_win32_console (bool c) { maybe_set (_win32_console, c); @@ -505,6 +513,7 @@ private: /** maximum allowed J2K bandwidth in bits per second */ int _maximum_j2k_bandwidth; int _log_types; + bool _automatic_audio_analysis; #ifdef DCPOMATIC_WINDOWS bool _win32_console; #endif diff --git a/src/lib/film.cc b/src/lib/film.cc index 685fc7658..231ac92e1 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -162,8 +162,12 @@ Film::Film (boost::filesystem::path dir, bool log) Film::~Film () { - for (list<boost::signals2::connection>::const_iterator i = _job_connections.begin(); i != _job_connections.end(); ++i) { - i->disconnect (); + BOOST_FOREACH (boost::signals2::connection& i, _job_connections) { + i.disconnect (); + } + + BOOST_FOREACH (boost::signals2::connection& i, _audio_analysis_connections) { + i.disconnect (); } } @@ -947,8 +951,19 @@ Film::maybe_add_content (weak_ptr<Job> j, weak_ptr<Content> c) } shared_ptr<Content> content = c.lock (); - if (content) { - add_content (content); + if (!content) { + return; + } + + add_content (content); + if (Config::instance()->automatic_audio_analysis ()) { + shared_ptr<Playlist> playlist (new Playlist); + playlist->add (content); + boost::signals2::connection c; + JobManager::instance()->analyse_audio ( + shared_from_this (), playlist, c, bind (&Film::audio_analysis_finished, this) + ); + _audio_analysis_connections.push_back (c); } } @@ -1233,3 +1248,9 @@ Film::remove_content (ContentList c) { _playlist->remove (c); } + +void +Film::audio_analysis_finished () +{ + /* XXX */ +} diff --git a/src/lib/film.h b/src/lib/film.h index 2165eed23..aa7be939e 100644 --- a/src/lib/film.h +++ b/src/lib/film.h @@ -296,6 +296,7 @@ private: void playlist_changed (); void playlist_content_changed (boost::weak_ptr<Content>, int, bool frequent); void maybe_add_content (boost::weak_ptr<Job>, boost::weak_ptr<Content>); + void audio_analysis_finished (); /** Log to write to */ boost::shared_ptr<Log> _log; @@ -345,6 +346,7 @@ private: boost::signals2::scoped_connection _playlist_changed_connection; boost::signals2::scoped_connection _playlist_content_changed_connection; std::list<boost::signals2::connection> _job_connections; + std::list<boost::signals2::connection> _audio_analysis_connections; friend struct paths_test; friend struct film_metadata_test; diff --git a/src/lib/job.cc b/src/lib/job.cc index 784defc91..37bf462fc 100644 --- a/src/lib/job.cc +++ b/src/lib/job.cc @@ -39,6 +39,7 @@ using std::list; using std::cout; using boost::shared_ptr; using boost::optional; +using boost::function; #define LOG_ERROR_NC(...) _film->log()->log (__VA_ARGS__, Log::TYPE_ERROR); @@ -434,3 +435,15 @@ Job::resume () _pause_changed.notify_all (); } } + +void +Job::when_finished (boost::signals2::connection& connection, function<void()> finished) +{ + boost::mutex::scoped_lock lm (_state_mutex); + if (_state == FINISHED_OK || _state == FINISHED_ERROR || _state == FINISHED_CANCELLED) { + finished (); + } else { + connection = Finished.connect (finished); + } +} + diff --git a/src/lib/job.h b/src/lib/job.h index 1caa5a904..32e71d658 100644 --- a/src/lib/job.h +++ b/src/lib/job.h @@ -80,6 +80,8 @@ public: return _film; } + void when_finished (boost::signals2::connection& connection, boost::function<void()> finished); + boost::signals2::signal<void()> Progress; /** Emitted from the UI thread when the job is finished */ boost::signals2::signal<void()> Finished; diff --git a/src/lib/job_manager.cc b/src/lib/job_manager.cc index e3f91f4fc..3748fa353 100644 --- a/src/lib/job_manager.cc +++ b/src/lib/job_manager.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,23 +21,28 @@ * @brief A simple scheduler for jobs. */ -#include <iostream> -#include <boost/thread.hpp> #include "job_manager.h" #include "job.h" #include "cross.h" +#include "analyse_audio_job.h" +#include "film.h" +#include <boost/thread.hpp> +#include <boost/foreach.hpp> +#include <iostream> using std::string; using std::list; using std::cout; using boost::shared_ptr; using boost::weak_ptr; +using boost::function; +using boost::dynamic_pointer_cast; +using boost::optional; JobManager* JobManager::_instance = 0; JobManager::JobManager () : _terminate (false) - , _last_active_jobs (false) , _scheduler (0) { @@ -113,7 +118,7 @@ JobManager::scheduler () { while (true) { - bool active_jobs = false; + optional<string> active_job; { boost::mutex::scoped_lock lm (_mutex); @@ -121,29 +126,28 @@ JobManager::scheduler () return; } - for (list<shared_ptr<Job> >::iterator i = _jobs.begin(); i != _jobs.end(); ++i) { + BOOST_FOREACH (shared_ptr<Job> i, _jobs) { - if (!(*i)->finished ()) { - active_jobs = true; + if (!i->finished ()) { + active_job = i->json_name (); } - if ((*i)->running ()) { + if (i->running ()) { /* Something is already happening */ break; } - if ((*i)->is_new()) { - (*i)->start (); - + if (i->is_new()) { + i->start (); /* Only start one job at once */ break; } } } - if (active_jobs != _last_active_jobs) { - _last_active_jobs = active_jobs; - emit (boost::bind (boost::ref (ActiveJobsChanged), active_jobs)); + if (active_job != _last_active_job) { + _last_active_job = active_job; + emit (boost::bind (boost::ref (ActiveJobsChanged), active_job)); } dcpomatic_sleep (1); @@ -167,3 +171,32 @@ JobManager::drop () delete _instance; _instance = 0; } + +void +JobManager::analyse_audio ( + shared_ptr<const Film> film, + shared_ptr<const Playlist> playlist, + boost::signals2::connection& connection, + function<void()> ready + ) +{ + shared_ptr<AnalyseAudioJob> job; + + { + boost::mutex::scoped_lock lm (_mutex); + + BOOST_FOREACH (shared_ptr<Job> i, _jobs) { + shared_ptr<AnalyseAudioJob> a = dynamic_pointer_cast<AnalyseAudioJob> (i); + if (a && film->audio_analysis_path (a->playlist ()) == film->audio_analysis_path (playlist)) { + i->when_finished (connection, ready); + return; + } + } + + job.reset (new AnalyseAudioJob (film, playlist)); + connection = job->Finished.connect (ready); + _jobs.push_back (job); + } + + emit (boost::bind (boost::ref (JobAdded), weak_ptr<Job> (job))); +} diff --git a/src/lib/job_manager.h b/src/lib/job_manager.h index 3cd8be6d6..7de7862a1 100644 --- a/src/lib/job_manager.h +++ b/src/lib/job_manager.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Carl Hetherington <cth@carlh.net> + Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -28,6 +28,9 @@ #include <list> class Job; +class Film; +class Playlist; + extern void wait_for_jobs (); /** @class JobManager @@ -42,8 +45,15 @@ public: bool work_to_do () const; bool errors () const; + void analyse_audio ( + boost::shared_ptr<const Film> film, + boost::shared_ptr<const Playlist> playlist, + boost::signals2::connection& connection, + boost::function<void()> ready + ); + boost::signals2::signal<void (boost::weak_ptr<Job>)> JobAdded; - boost::signals2::signal<void (bool)> ActiveJobsChanged; + boost::signals2::signal<void (boost::optional<std::string>)> ActiveJobsChanged; static JobManager* instance (); static void drop (); @@ -61,7 +71,7 @@ private: std::list<boost::shared_ptr<Job> > _jobs; bool _terminate; - bool _last_active_jobs; + boost::optional<std::string> _last_active_job; boost::thread* _scheduler; static JobManager* _instance; |
