/*
- Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
#include "log.h"
#include "compose.hpp"
#include <dcp/exceptions.h>
+#include <sub/exceptions.h>
#include <boost/thread.hpp>
#include <boost/filesystem.hpp>
+#include <boost/foreach.hpp>
#include <iostream>
#include "i18n.h"
, _thread (0)
, _state (NEW)
, _start_time (0)
+ , _sub_start_time (0)
, _progress (0)
, _ran_for (0)
{
{
if (_thread) {
_thread->interrupt ();
- DCPOMATIC_ASSERT (_thread->joinable ());
- _thread->join ();
+ /* We can't use DCPOMATIC_ASSERT here as it may throw an exception */
+ if (_thread->joinable ()) {
+ try {
+ _thread->join ();
+ } catch (...) {
+ /* Too late to do anything about this */
+ }
+ }
}
delete _thread;
{
set_state (RUNNING);
_start_time = time (0);
+ _sub_start_time = time (0);
_thread = new boost::thread (boost::bind (&Job::run_wrapper, this));
}
set_state (FINISHED_CANCELLED);
+ } catch (sub::SubripError& e) {
+
+ string extra = "Error is near:\n";
+ BOOST_FOREACH (string i, e.context()) {
+ extra += i + "\n";
+ }
+
+ set_error (e.what (), extra);
+ set_progress (1);
+ set_state (FINISHED_ERROR);
+
} catch (std::bad_alloc& e) {
set_error (_("Out of memory"), _("There was not enough memory to do this. If you are running a 32-bit operating system try reducing the number of encoding threads in the General tab of Preferences."));
_state = s;
if (_state == FINISHED_OK || _state == FINISHED_ERROR || _state == FINISHED_CANCELLED) {
- _ran_for = elapsed_time ();
+ _ran_for = time(0) - _start_time;
finished = true;
_sub_name.clear ();
}
/** @return DCPTime (in seconds) that this sub-job has been running */
int
-Job::elapsed_time () const
+Job::elapsed_sub_time () const
{
- if (_start_time == 0) {
+ if (_sub_start_time == 0) {
return 0;
}
- return time (0) - _start_time;
+ return time (0) - _sub_start_time;
}
/** Set the progress of the current part of the job.
void
Job::set_progress (float p, bool force)
{
- if (!force && fabs (p - progress().get_value_or(0)) < 0.01) {
- /* Calm excessive progress reporting */
- return;
+ if (!force) {
+ /* Check for excessively frequent progress reporting */
+ boost::mutex::scoped_lock lm (_progress_mutex);
+ struct timeval now;
+ gettimeofday (&now, 0);
+ if (_last_progress_update && _last_progress_update->tv_sec > 0) {
+ double const elapsed = (now.tv_sec + now.tv_usec / 1000000.0)
+ - (_last_progress_update->tv_sec + _last_progress_update->tv_usec / 1000000.0);
+ if (elapsed < 0.5) {
+ return;
+ }
+ }
+ _last_progress_update = now;
}
set_progress_common (p);
}
set_progress (0, true);
+ _sub_start_time = time (0);
}
string
Job::status () const
{
optional<float> p = progress ();
- int const t = elapsed_time ();
+ int const t = elapsed_sub_time ();
int const r = remaining_time ();
- SafeStringStream s;
+ string s;
if (!finished () && p) {
int pc = lrintf (p.get() * 100);
if (pc == 100) {
pc = 99;
}
- s << pc << N_("%");
+ char buffer[64];
+ snprintf (buffer, sizeof(buffer), "%d%%", pc);
+ s += buffer;
if (t > 10 && r > 0) {
/// TRANSLATORS: remaining here follows an amount of time that is remaining
/// on an operation.
- s << "; " << seconds_to_approximate_hms (r) << " " << _("remaining");
+ s += "; " + seconds_to_approximate_hms (r) + " " + _("remaining");
}
} else if (finished_ok ()) {
- s << String::compose (_("OK (ran for %1)"), seconds_to_hms (_ran_for));
+ s = String::compose (_("OK (ran for %1)"), seconds_to_hms (_ran_for));
} else if (finished_in_error ()) {
- s << String::compose (_("Error: %1"), error_summary ());
+ s = String::compose (_("Error: %1"), error_summary ());
} else if (finished_cancelled ()) {
- s << _("Cancelled");
+ s = _("Cancelled");
}
- return s.str ();
+ return s;
}
string
Job::remaining_time () const
{
if (progress().get_value_or(0) == 0) {
- return elapsed_time ();
+ return elapsed_sub_time ();
}
- return elapsed_time() / progress().get() - elapsed_time();
+ return elapsed_sub_time() / progress().get() - elapsed_sub_time();
}
void