Various fixes to make audio analysis sort-of work.
[dcpomatic.git] / src / lib / job.cc
index bfad65a0a61f18d6566fa937b528232b91fe38f2..4969c4099c8aae60a4e7c22db6618ded9c8a1c93 100644 (file)
 #include <libdcp/exceptions.h>
 #include "job.h"
 #include "util.h"
+#include "cross.h"
+
+#include "i18n.h"
 
 using std::string;
 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)
@@ -50,7 +52,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 */
@@ -66,14 +68,23 @@ Job::run_wrapper ()
                set_progress (1);
                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\nThe drive that the film is stored on is low in disc space.  Free some more space and try again.";
+               string m = String::compose (_("An error occurred whilst handling the file %1."), boost::filesystem::path (e.filename()).leaf());
+
+               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) {
 
@@ -81,7 +92,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 (...) {
@@ -89,8 +100,8 @@ Job::run_wrapper ()
                set_progress (1);
                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)"
+                       _("Unknown error"),
+                       _("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)")
                        );
 
        }
@@ -117,7 +128,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 */
@@ -136,6 +147,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.
  */
@@ -147,7 +172,6 @@ Job::set_state (State s)
 
        if (_state == FINISHED_OK || _state == FINISHED_ERROR) {
                _ran_for = elapsed_time ();
-               Finished ();
        }
 }
 
@@ -171,6 +195,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 */
@@ -273,14 +302,18 @@ Job::status () const
 
        stringstream s;
        if (!finished ()) {
-               s << pc << "%";
+               s << pc << N_("%");
                if (p >= 0 && t > 10 && r > 0) {
-                       s << "; " << seconds_to_approximate_hms (r) << " remaining";
+                       /// TRANSLATORS: remaining here follows an amount of time that is remaining
+                       /// on an operation.
+                       s << "; " << seconds_to_approximate_hms (r) << " " << _("remaining");
                }
        } else if (finished_ok ()) {
-               s << "OK (ran for " << seconds_to_hms (_ran_for) << ")";
+               s << String::compose (_("OK (ran for %1)"), seconds_to_hms (_ran_for));
        } else if (finished_in_error ()) {
-               s << "Error (" << error_summary() << ")";
+               s << String::compose (_("Error (%1)"), error_summary());
+       } else if (finished_cancelled ()) {
+               s << _("Cancelled");
        }
 
        return s.str ();
@@ -292,3 +325,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);
+       }
+}