Merge master.
[dcpomatic.git] / src / lib / job.cc
index 78a7a75776c8f9463c48b73cfd5b7eceb1be1804..080d1eaf6018a5588c9d9f0c31a63c894585a4a1 100644 (file)
@@ -26,6 +26,8 @@
 #include <libdcp/exceptions.h>
 #include "job.h"
 #include "util.h"
+#include "cross.h"
+#include "ui_signaller.h"
 
 #include "i18n.h"
 
@@ -34,10 +36,9 @@ using std::list;
 using std::stringstream;
 using boost::shared_ptr;
 
-/** @param s Film that we are operating on.
- */
-Job::Job (shared_ptr<Film> f)
+Job::Job (shared_ptr<const Film> f)
        : _film (f)
+       , _thread (0)
        , _state (NEW)
        , _start_time (0)
        , _progress_unknown (false)
@@ -52,7 +53,7 @@ Job::start ()
 {
        set_state (RUNNING);
        _start_time = time (0);
-       boost::thread (boost::bind (&Job::run_wrapper, this));
+       _thread = new boost::thread (boost::bind (&Job::run_wrapper, this));
 }
 
 /** A wrapper for the ::run() method to catch exceptions */
@@ -81,6 +82,10 @@ Job::run_wrapper ()
                }
 
                set_error (e.what(), m);
+
+       } catch (boost::thread_interrupted &) {
+
+               set_state (FINISHED_CANCELLED);
                
        } catch (std::exception& e) {
 
@@ -88,7 +93,7 @@ Job::run_wrapper ()
                set_state (FINISHED_ERROR);
                set_error (
                        e.what (),
-                       _("It is not known what caused this error.  The best idea is to report the problem to the DVD-o-matic mailing list (dvdomatic@carlh.net)")
+                       _("It is not known what caused this error.  The best idea is to report the problem to the DCP-o-matic mailing list (dcpomatic@carlh.net)")
                        );
 
        } catch (...) {
@@ -97,7 +102,7 @@ Job::run_wrapper ()
                set_state (FINISHED_ERROR);
                set_error (
                        _("Unknown error"),
-                       _("It is not known what caused this error.  The best idea is to report the problem to the DVD-o-matic mailing list (dvdomatic@carlh.net)")
+                       _("It is not known what caused this error.  The best idea is to report the problem to the DCP-o-matic mailing list (dcpomatic@carlh.net)")
                        );
 
        }
@@ -124,7 +129,7 @@ bool
 Job::finished () const
 {
        boost::mutex::scoped_lock lm (_state_mutex);
-       return _state == FINISHED_OK || _state == FINISHED_ERROR;
+       return _state == FINISHED_OK || _state == FINISHED_ERROR || _state == FINISHED_CANCELLED;
 }
 
 /** @return true if the job has finished successfully */
@@ -143,6 +148,20 @@ Job::finished_in_error () const
        return _state == FINISHED_ERROR;
 }
 
+bool
+Job::finished_cancelled () const
+{
+       boost::mutex::scoped_lock lm (_state_mutex);
+       return _state == FINISHED_CANCELLED;
+}
+
+bool
+Job::paused () const
+{
+       boost::mutex::scoped_lock lm (_state_mutex);
+       return _state == PAUSED;
+}
+       
 /** Set the state of this job.
  *  @param s New state.
  */
@@ -152,8 +171,11 @@ Job::set_state (State s)
        boost::mutex::scoped_lock lm (_state_mutex);
        _state = s;
 
-       if (_state == FINISHED_OK || _state == FINISHED_ERROR) {
+       if (_state == FINISHED_OK || _state == FINISHED_ERROR || _state == FINISHED_CANCELLED) {
                _ran_for = elapsed_time ();
+               if (ui_signaller) {
+                       ui_signaller->emit (boost::bind (boost::ref (Finished)));
+               }
        }
 }
 
@@ -177,6 +199,11 @@ Job::set_progress (float p)
        boost::mutex::scoped_lock lm (_progress_mutex);
        _progress_unknown = false;
        _stack.back().normalised = p;
+       boost::this_thread::interruption_point ();
+
+       if (paused ()) {
+               dcpomatic_sleep (1);
+       }
 }
 
 /** @return fractional overall progress, or -1 if not known */
@@ -289,6 +316,8 @@ Job::status () const
                s << String::compose (_("OK (ran for %1)"), seconds_to_hms (_ran_for));
        } else if (finished_in_error ()) {
                s << String::compose (_("Error (%1)"), error_summary());
+       } else if (finished_cancelled ()) {
+               s << _("Cancelled");
        }
 
        return s.str ();
@@ -300,3 +329,30 @@ Job::remaining_time () const
 {
        return elapsed_time() / overall_progress() - elapsed_time();
 }
+
+void
+Job::cancel ()
+{
+       if (!_thread) {
+               return;
+       }
+
+       _thread->interrupt ();
+       _thread->join ();
+}
+
+void
+Job::pause ()
+{
+       if (running ()) {
+               set_state (PAUSED);
+       }
+}
+
+void
+Job::resume ()
+{
+       if (paused ()) {
+               set_state (RUNNING);
+       }
+}