Make batch converter basically work.
[dcpomatic.git] / src / lib / job.cc
index 77d3671369481b0728cac6b369827a6291fab1fb..9a5812fa7426dfb451fb619951b606769be16e06 100644 (file)
@@ -26,6 +26,7 @@
 #include <libdcp/exceptions.h>
 #include "job.h"
 #include "util.h"
+#include "cross.h"
 
 #include "i18n.h"
 
@@ -38,6 +39,7 @@ using boost::shared_ptr;
  */
 Job::Job (shared_ptr<Film> f)
        : _film (f)
+       , _thread (0)
        , _state (NEW)
        , _start_time (0)
        , _progress_unknown (false)
@@ -52,7 +54,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 */
@@ -69,14 +71,22 @@ Job::run_wrapper ()
                set_state (FINISHED_ERROR);
                
                string m = String::compose (_("An error occurred whilst handling the file %1."), boost::filesystem::path (e.filename()).leaf());
-               
-               boost::filesystem::space_info const s = boost::filesystem::space (e.filename());
-               if (s.available < pow (1024, 3)) {
-                       m += N_("\n\n");
-                       m += _("The drive that the film is stored on is low in disc space.  Free some more space and try again.");
+
+               try {
+                       boost::filesystem::space_info const s = boost::filesystem::space (e.filename());
+                       if (s.available < pow (1024, 3)) {
+                               m += N_("\n\n");
+                               m += _("The drive that the film is stored on is low in disc space.  Free some more space and try again.");
+                       }
+               } catch (...) {
+
                }
 
                set_error (e.what(), m);
+
+       } catch (boost::thread_interrupted &) {
+
+               set_state (FINISHED_CANCELLED);
                
        } catch (std::exception& e) {
 
@@ -120,7 +130,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 */
@@ -139,6 +149,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.
  */
@@ -150,7 +174,6 @@ Job::set_state (State s)
 
        if (_state == FINISHED_OK || _state == FINISHED_ERROR) {
                _ran_for = elapsed_time ();
-               Finished ();
        }
 }
 
@@ -174,6 +197,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 ()) {
+               dvdomatic_sleep (1);
+       }
 }
 
 /** @return fractional overall progress, or -1 if not known */
@@ -286,6 +314,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 ();
@@ -297,3 +327,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);
+       }
+}