/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2018 Carl Hetherington <cth@carlh.net>
- This program is free software; you can redistribute it and/or modify
+ This file is part of DCP-o-matic.
+
+ DCP-o-matic is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
- This program is distributed in the hope that it will be useful,
+ DCP-o-matic is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ along with DCP-o-matic. If not, see <http://www.gnu.org/licenses/>.
*/
JobManager::JobManager ()
: _terminate (false)
+ , _paused (false)
, _scheduler (0)
{
JobManager::start ()
{
_scheduler = new boost::thread (boost::bind (&JobManager::scheduler, this));
+#ifdef DCPOMATIC_LINUX
+ pthread_setname_np (_scheduler->native_handle(), "job-scheduler");
+#endif
}
JobManager::~JobManager ()
}
if (_scheduler) {
- DCPOMATIC_ASSERT (_scheduler->joinable ());
- _scheduler->join ();
+ /* Ideally this would be a DCPOMATIC_ASSERT(_scheduler->joinable()) but we
+ can't throw exceptions from a destructor.
+ */
+ if (_scheduler->joinable ()) {
+ _scheduler->join ();
+ }
}
delete _scheduler;
return j;
}
+shared_ptr<Job>
+JobManager::add_after (shared_ptr<Job> after, shared_ptr<Job> j)
+{
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+ list<shared_ptr<Job> >::iterator i = find (_jobs.begin(), _jobs.end(), after);
+ DCPOMATIC_ASSERT (i != _jobs.end());
+ _jobs.insert (i, j);
+ }
+
+ emit (boost::bind (boost::ref (JobAdded), weak_ptr<Job> (j)));
+
+ return j;
+}
+
list<shared_ptr<Job> >
JobManager::get () const
{
return;
}
- BOOST_FOREACH (shared_ptr<Job> i, _jobs) {
+ if (!_paused) {
+ BOOST_FOREACH (shared_ptr<Job> i, _jobs) {
- if (!i->finished ()) {
- active_job = i->json_name ();
- }
+ if (!i->finished ()) {
+ active_job = i->json_name ();
+ }
- if (i->running ()) {
- /* Something is already happening */
- break;
- }
+ if (i->running ()) {
+ /* Something is already happening */
+ break;
+ }
- if (i->is_new()) {
- i->start ();
- /* Only start one job at once */
- break;
+ if (i->is_new()) {
+ i->start ();
+ /* Only start one job at once */
+ break;
+ }
}
}
}
JobManager::analyse_audio (
shared_ptr<const Film> film,
shared_ptr<const Playlist> playlist,
+ bool from_zero,
boost::signals2::connection& connection,
function<void()> ready
)
{
boost::mutex::scoped_lock lm (_mutex);
- job.reset (new AnalyseAudioJob (film, playlist));
+ job.reset (new AnalyseAudioJob (film, playlist, from_zero));
connection = job->Finished.connect (ready);
_jobs.push_back (job);
}
emit (boost::bind (boost::ref (JobAdded), weak_ptr<Job> (job)));
}
+
+void
+JobManager::increase_priority (shared_ptr<Job> job)
+{
+ bool changed = false;
+
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+ list<shared_ptr<Job> >::iterator last = _jobs.end ();
+ for (list<shared_ptr<Job> >::iterator i = _jobs.begin(); i != _jobs.end(); ++i) {
+ if (*i == job && last != _jobs.end()) {
+ swap (*i, *last);
+ changed = true;
+ break;
+ }
+ last = i;
+ }
+ }
+
+ if (changed) {
+ priority_changed ();
+ }
+}
+
+void
+JobManager::priority_changed ()
+{
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+
+ bool first = true;
+ BOOST_FOREACH (shared_ptr<Job> i, _jobs) {
+ if (first) {
+ if (i->is_new ()) {
+ i->start ();
+ } else if (i->paused_by_priority ()) {
+ i->resume ();
+ }
+ first = false;
+ } else {
+ if (i->running ()) {
+ i->pause_by_priority ();
+ }
+ }
+ }
+ }
+
+ emit (boost::bind (boost::ref (JobsReordered)));
+}
+
+void
+JobManager::decrease_priority (shared_ptr<Job> job)
+{
+ bool changed = false;
+
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+ for (list<shared_ptr<Job> >::iterator i = _jobs.begin(); i != _jobs.end(); ++i) {
+ list<shared_ptr<Job> >::iterator next = i;
+ ++next;
+ if (*i == job && next != _jobs.end()) {
+ swap (*i, *next);
+ changed = true;
+ break;
+ }
+ }
+ }
+
+ if (changed) {
+ priority_changed ();
+ }
+}
+
+void
+JobManager::pause ()
+{
+ boost::mutex::scoped_lock lm (_mutex);
+
+ if (_paused) {
+ return;
+ }
+
+ BOOST_FOREACH (shared_ptr<Job> i, _jobs) {
+ if (i->pause_by_user()) {
+ _paused_job = i;
+ }
+ }
+
+ _paused = true;
+}
+
+void
+JobManager::resume ()
+{
+ boost::mutex::scoped_lock lm (_mutex);
+ if (!_paused) {
+ return;
+ }
+
+ if (_paused_job) {
+ _paused_job->resume ();
+ }
+
+ _paused_job.reset ();
+ _paused = false;
+}