diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/ab_transcode_job.cc | 4 | ||||
| -rw-r--r-- | src/lib/check_hashes_job.cc | 4 | ||||
| -rw-r--r-- | src/lib/compose.hpp | 393 | ||||
| -rw-r--r-- | src/lib/dcp_video_frame.cc | 12 | ||||
| -rw-r--r-- | src/lib/decoder.cc | 2 | ||||
| -rw-r--r-- | src/lib/examine_content_job.cc | 4 | ||||
| -rw-r--r-- | src/lib/film.cc | 10 | ||||
| -rw-r--r-- | src/lib/j2k_wav_encoder.cc | 32 | ||||
| -rw-r--r-- | src/lib/job.cc | 11 | ||||
| -rw-r--r-- | src/lib/job.h | 2 | ||||
| -rw-r--r-- | src/lib/log.cc | 19 | ||||
| -rw-r--r-- | src/lib/log.h | 4 | ||||
| -rw-r--r-- | src/lib/make_dcp_job.cc | 4 | ||||
| -rw-r--r-- | src/lib/scp_dcp_job.cc | 36 | ||||
| -rw-r--r-- | src/lib/server.cc | 8 | ||||
| -rw-r--r-- | src/lib/thumbs_job.cc | 4 | ||||
| -rw-r--r-- | src/lib/transcode_job.cc | 9 | ||||
| -rw-r--r-- | src/lib/util.h | 7 | ||||
| -rw-r--r-- | src/tools/dvdomatic.cc | 3 | ||||
| -rw-r--r-- | src/tools/makedcp.cc | 10 | ||||
| -rw-r--r-- | src/wx/film_editor.cc | 4 | ||||
| -rw-r--r-- | src/wx/film_viewer.cc | 6 | ||||
| -rw-r--r-- | src/wx/job_manager_view.cc | 4 | ||||
| -rw-r--r-- | src/wx/job_wrapper.cc | 8 |
24 files changed, 491 insertions, 109 deletions
diff --git a/src/lib/ab_transcode_job.cc b/src/lib/ab_transcode_job.cc index 1a6104251..d94f56d0a 100644 --- a/src/lib/ab_transcode_job.cc +++ b/src/lib/ab_transcode_job.cc @@ -46,9 +46,7 @@ ABTranscodeJob::ABTranscodeJob (shared_ptr<const FilmState> s, shared_ptr<const string ABTranscodeJob::name () const { - stringstream s; - s << "A/B transcode " << _fs->name; - return s.str (); + return String::compose ("A/B transcode %1", _fs->name); } void diff --git a/src/lib/check_hashes_job.cc b/src/lib/check_hashes_job.cc index 5a927f752..cf269564a 100644 --- a/src/lib/check_hashes_job.cc +++ b/src/lib/check_hashes_job.cc @@ -41,9 +41,7 @@ CheckHashesJob::CheckHashesJob (shared_ptr<const FilmState> s, shared_ptr<const string CheckHashesJob::name () const { - stringstream s; - s << "Check hashes of " << _fs->name; - return s.str (); + return String::compose ("Check hashes of %1", _fs->name); } void diff --git a/src/lib/compose.hpp b/src/lib/compose.hpp new file mode 100644 index 000000000..b3f410c8e --- /dev/null +++ b/src/lib/compose.hpp @@ -0,0 +1,393 @@ +/* Defines String::compose(fmt, arg...) for easy, i18n-friendly + * composition of strings. + * + * Version 1.0. + * + * Copyright (c) 2002 Ole Laursen <olau@hardworking.dk>. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This program 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA. + */ + +// +// Basic usage is like +// +// std::cout << String::compose("This is a %1x%2 matrix.", rows, cols); +// +// See http://www.cs.aau.dk/~olau/compose/ or the included README.compose for +// more details. +// + +#ifndef STRING_COMPOSE_H +#define STRING_COMPOSE_H + +#include <sstream> +#include <string> +#include <list> +#include <map> // for multimap + +namespace StringPrivate +{ + // the actual composition class - using string::compose is cleaner, so we + // hide it here + class Composition + { + public: + // initialize and prepare format string on the form "text %1 text %2 etc." + explicit Composition(std::string fmt); + + // supply an replacement argument starting from %1 + template <typename T> + Composition &arg(const T &obj); + + // compose and return string + std::string str() const; + + private: + std::ostringstream os; + int arg_no; + + // we store the output as a list - when the output string is requested, the + // list is concatenated to a string; this way we can keep iterators into + // the list instead of into a string where they're possibly invalidated on + // inserting a specification string + typedef std::list<std::string> output_list; + output_list output; + + // the initial parse of the format string fills in the specification map + // with positions for each of the various %?s + typedef std::multimap<int, output_list::iterator> specification_map; + specification_map specs; + }; + + // helper for converting spec string numbers + inline int char_to_int(char c) + { + switch (c) { + case '0': return 0; + case '1': return 1; + case '2': return 2; + case '3': return 3; + case '4': return 4; + case '5': return 5; + case '6': return 6; + case '7': return 7; + case '8': return 8; + case '9': return 9; + default: return -1000; + } + } + + inline bool is_number(int n) + { + switch (n) { + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + return true; + + default: + return false; + } + } + + + // implementation of class Composition + template <typename T> + inline Composition &Composition::arg(const T &obj) + { + os << obj; + + std::string rep = os.str(); + + if (!rep.empty()) { // manipulators don't produce output + for (specification_map::const_iterator i = specs.lower_bound(arg_no), + end = specs.upper_bound(arg_no); i != end; ++i) { + output_list::iterator pos = i->second; + ++pos; + + output.insert(pos, rep); + } + + os.str(std::string()); + //os.clear(); + ++arg_no; + } + + return *this; + } + + inline Composition::Composition(std::string fmt) + : arg_no(1) + { + std::string::size_type b = 0, i = 0; + + // fill in output with the strings between the %1 %2 %3 etc. and + // fill in specs with the positions + while (i < fmt.length()) { + if (fmt[i] == '%' && i + 1 < fmt.length()) { + if (fmt[i + 1] == '%') { // catch %% + fmt.replace(i, 2, "%"); + ++i; + } + else if (is_number(fmt[i + 1])) { // aha! a spec! + // save string + output.push_back(fmt.substr(b, i - b)); + + int n = 1; // number of digits + int spec_no = 0; + + do { + spec_no += char_to_int(fmt[i + n]); + spec_no *= 10; + ++n; + } while (i + n < fmt.length() && is_number(fmt[i + n])); + + spec_no /= 10; + output_list::iterator pos = output.end(); + --pos; // safe since we have just inserted a string> + + specs.insert(specification_map::value_type(spec_no, pos)); + + // jump over spec string + i += n; + b = i; + } + else + ++i; + } + else + ++i; + } + + if (i - b > 0) // add the rest of the string + output.push_back(fmt.substr(b, i - b)); + } + + inline std::string Composition::str() const + { + // assemble string + std::string str; + + for (output_list::const_iterator i = output.begin(), end = output.end(); + i != end; ++i) + str += *i; + + return str; + } +} + +// now for the real thing(s) +namespace String +{ + // a series of functions which accept a format string on the form "text %1 + // more %2 less %3" and a number of templated parameters and spits out the + // composited string + template <typename T1> + inline std::string compose(const std::string &fmt, const T1 &o1) + { + StringPrivate::Composition c(fmt); + c.arg(o1); + return c.str(); + } + + template <typename T1, typename T2> + inline std::string compose(const std::string &fmt, + const T1 &o1, const T2 &o2) + { + StringPrivate::Composition c(fmt); + c.arg(o1).arg(o2); + return c.str(); + } + + template <typename T1, typename T2, typename T3> + inline std::string compose(const std::string &fmt, + const T1 &o1, const T2 &o2, const T3 &o3) + { + StringPrivate::Composition c(fmt); + c.arg(o1).arg(o2).arg(o3); + return c.str(); + } + + template <typename T1, typename T2, typename T3, typename T4> + inline std::string compose(const std::string &fmt, + const T1 &o1, const T2 &o2, const T3 &o3, + const T4 &o4) + { + StringPrivate::Composition c(fmt); + c.arg(o1).arg(o2).arg(o3).arg(o4); + return c.str(); + } + + template <typename T1, typename T2, typename T3, typename T4, typename T5> + inline std::string compose(const std::string &fmt, + const T1 &o1, const T2 &o2, const T3 &o3, + const T4 &o4, const T5 &o5) + { + StringPrivate::Composition c(fmt); + c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5); + return c.str(); + } + + template <typename T1, typename T2, typename T3, typename T4, typename T5, + typename T6> + inline std::string compose(const std::string &fmt, + const T1 &o1, const T2 &o2, const T3 &o3, + const T4 &o4, const T5 &o5, const T6 &o6) + { + StringPrivate::Composition c(fmt); + c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6); + return c.str(); + } + + template <typename T1, typename T2, typename T3, typename T4, typename T5, + typename T6, typename T7> + inline std::string compose(const std::string &fmt, + const T1 &o1, const T2 &o2, const T3 &o3, + const T4 &o4, const T5 &o5, const T6 &o6, + const T7 &o7) + { + StringPrivate::Composition c(fmt); + c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7); + return c.str(); + } + + template <typename T1, typename T2, typename T3, typename T4, typename T5, + typename T6, typename T7, typename T8> + inline std::string compose(const std::string &fmt, + const T1 &o1, const T2 &o2, const T3 &o3, + const T4 &o4, const T5 &o5, const T6 &o6, + const T7 &o7, const T8 &o8) + { + StringPrivate::Composition c(fmt); + c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8); + return c.str(); + } + + template <typename T1, typename T2, typename T3, typename T4, typename T5, + typename T6, typename T7, typename T8, typename T9> + inline std::string compose(const std::string &fmt, + const T1 &o1, const T2 &o2, const T3 &o3, + const T4 &o4, const T5 &o5, const T6 &o6, + const T7 &o7, const T8 &o8, const T9 &o9) + { + StringPrivate::Composition c(fmt); + c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9); + return c.str(); + } + + template <typename T1, typename T2, typename T3, typename T4, typename T5, + typename T6, typename T7, typename T8, typename T9, typename T10> + inline std::string compose(const std::string &fmt, + const T1 &o1, const T2 &o2, const T3 &o3, + const T4 &o4, const T5 &o5, const T6 &o6, + const T7 &o7, const T8 &o8, const T9 &o9, + const T10 &o10) + { + StringPrivate::Composition c(fmt); + c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9) + .arg(o10); + return c.str(); + } + + template <typename T1, typename T2, typename T3, typename T4, typename T5, + typename T6, typename T7, typename T8, typename T9, typename T10, + typename T11> + inline std::string compose(const std::string &fmt, + const T1 &o1, const T2 &o2, const T3 &o3, + const T4 &o4, const T5 &o5, const T6 &o6, + const T7 &o7, const T8 &o8, const T9 &o9, + const T10 &o10, const T11 &o11) + { + StringPrivate::Composition c(fmt); + c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9) + .arg(o10).arg(o11); + return c.str(); + } + + template <typename T1, typename T2, typename T3, typename T4, typename T5, + typename T6, typename T7, typename T8, typename T9, typename T10, + typename T11, typename T12> + inline std::string compose(const std::string &fmt, + const T1 &o1, const T2 &o2, const T3 &o3, + const T4 &o4, const T5 &o5, const T6 &o6, + const T7 &o7, const T8 &o8, const T9 &o9, + const T10 &o10, const T11 &o11, const T12 &o12) + { + StringPrivate::Composition c(fmt); + c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9) + .arg(o10).arg(o11).arg(o12); + return c.str(); + } + + template <typename T1, typename T2, typename T3, typename T4, typename T5, + typename T6, typename T7, typename T8, typename T9, typename T10, + typename T11, typename T12, typename T13> + inline std::string compose(const std::string &fmt, + const T1 &o1, const T2 &o2, const T3 &o3, + const T4 &o4, const T5 &o5, const T6 &o6, + const T7 &o7, const T8 &o8, const T9 &o9, + const T10 &o10, const T11 &o11, const T12 &o12, + const T13 &o13) + { + StringPrivate::Composition c(fmt); + c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9) + .arg(o10).arg(o11).arg(o12).arg(o13); + return c.str(); + } + + template <typename T1, typename T2, typename T3, typename T4, typename T5, + typename T6, typename T7, typename T8, typename T9, typename T10, + typename T11, typename T12, typename T13, typename T14> + inline std::string compose(const std::string &fmt, + const T1 &o1, const T2 &o2, const T3 &o3, + const T4 &o4, const T5 &o5, const T6 &o6, + const T7 &o7, const T8 &o8, const T9 &o9, + const T10 &o10, const T11 &o11, const T12 &o12, + const T13 &o13, const T14 &o14) + { + StringPrivate::Composition c(fmt); + c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9) + .arg(o10).arg(o11).arg(o12).arg(o13).arg(o14); + return c.str(); + } + + template <typename T1, typename T2, typename T3, typename T4, typename T5, + typename T6, typename T7, typename T8, typename T9, typename T10, + typename T11, typename T12, typename T13, typename T14, + typename T15> + inline std::string compose(const std::string &fmt, + const T1 &o1, const T2 &o2, const T3 &o3, + const T4 &o4, const T5 &o5, const T6 &o6, + const T7 &o7, const T8 &o8, const T9 &o9, + const T10 &o10, const T11 &o11, const T12 &o12, + const T13 &o13, const T14 &o14, const T15 &o15) + { + StringPrivate::Composition c(fmt); + c.arg(o1).arg(o2).arg(o3).arg(o4).arg(o5).arg(o6).arg(o7).arg(o8).arg(o9) + .arg(o10).arg(o11).arg(o12).arg(o13).arg(o14).arg(o15); + return c.str(); + } +} + + +#endif // STRING_COMPOSE_H diff --git a/src/lib/dcp_video_frame.cc b/src/lib/dcp_video_frame.cc index da7133c4b..90826a99f 100644 --- a/src/lib/dcp_video_frame.cc +++ b/src/lib/dcp_video_frame.cc @@ -262,11 +262,7 @@ DCPVideoFrame::encode_locally () throw EncodeError ("jpeg2000 encoding failed"); } - { - stringstream s; - s << "Finished locally-encoded frame " << _frame; - _log->log (s.str ()); - } + _log->log (String::compose ("Finished locally-encoded frame %1", _frame)); return shared_ptr<EncodedData> (new LocallyEncodedData (_cio->buffer, cio_tell (_cio))); } @@ -318,11 +314,7 @@ DCPVideoFrame::encode_remotely (ServerDescription const * serv) /* now read the rest */ socket.read_definite_and_consume (e->data(), e->size(), 30); - { - stringstream s; - s << "Finished remotely-encoded frame " << _frame; - _log->log (s.str ()); - } + _log->log (String::compose ("Finished remotely-encoded frame %1", _frame)); return e; } diff --git a/src/lib/decoder.cc b/src/lib/decoder.cc index 213ff9dd4..8aa5f77c6 100644 --- a/src/lib/decoder.cc +++ b/src/lib/decoder.cc @@ -23,6 +23,7 @@ #include <iostream> #include <stdint.h> +#include <boost/lexical_cast.hpp> extern "C" { #include <libavfilter/avfiltergraph.h> #include <libavfilter/buffersrc.h> @@ -313,6 +314,7 @@ Decoder::process_video (AVFrame* frame) image->make_black (); } + TIMING ("Decoder emits %1", _video_frame); Video (image, _video_frame); ++_video_frame; } diff --git a/src/lib/examine_content_job.cc b/src/lib/examine_content_job.cc index 6927715bd..d77ede2f9 100644 --- a/src/lib/examine_content_job.cc +++ b/src/lib/examine_content_job.cc @@ -43,9 +43,7 @@ ExamineContentJob::~ExamineContentJob () string ExamineContentJob::name () const { - stringstream s; - s << "Examine content of " << _fs->name; - return s.str (); + return String::compose ("Examine content of %1", _fs->name); } void diff --git a/src/lib/film.cc b/src/lib/film.cc index 583a15e19..90c410546 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -483,18 +483,12 @@ Film::make_dcp (bool transcode, int freq) throw BadSettingError ("name", "cannot contain slashes"); } - { - stringstream s; - s << "DVD-o-matic " << DVDOMATIC_VERSION << " using " << dependency_version_summary (); - log()->log (s.str ()); - } + log()->log (String::compose ("DVD-o-matic %1 using %2", DVDOMATIC_VERSION, dependency_version_summary())); { char buffer[128]; gethostname (buffer, sizeof (buffer)); - stringstream s; - s << "Starting to make a DCP on " << buffer; - log()->log (s.str ()); + log()->log (String::compose ("Starting to make DCP on %1", buffer)); } if (format() == 0) { diff --git a/src/lib/j2k_wav_encoder.cc b/src/lib/j2k_wav_encoder.cc index 9b25717ef..87514bf14 100644 --- a/src/lib/j2k_wav_encoder.cc +++ b/src/lib/j2k_wav_encoder.cc @@ -111,7 +111,9 @@ J2KWAVEncoder::process_video (shared_ptr<Image> yuv, int frame) /* Wait until the queue has gone down a bit */ while (_queue.size() >= _worker_threads.size() * 2 && !_process_end) { + TIMING ("decoder sleeps with queue of %1", _queue.size()); _worker_condition.wait (lock); + TIMING ("decoder wakes with queue of %1", _queue.size()); } if (_process_end) { @@ -121,6 +123,7 @@ J2KWAVEncoder::process_video (shared_ptr<Image> yuv, int frame) /* Only do the processing if we don't already have a file for this frame */ if (!boost::filesystem::exists (_opt->frame_out_path (frame, false))) { pair<string, string> const s = Filter::ffmpeg_strings (_fs->filters); + TIMING ("adding to queue of %1", _queue.size ()); _queue.push_back (boost::shared_ptr<DCPVideoFrame> ( new DCPVideoFrame ( yuv, _opt->out_size, _opt->padding, _fs->scaler, frame, _fs->frames_per_second, s.second, @@ -145,6 +148,8 @@ J2KWAVEncoder::encoder_thread (ServerDescription* server) int remote_backoff = 0; while (1) { + + TIMING ("encoder thread %1 sleeps", pthread_self ()); boost::mutex::scoped_lock lock (_worker_mutex); while (_queue.empty () && !_process_end) { _worker_condition.wait (lock); @@ -154,6 +159,7 @@ J2KWAVEncoder::encoder_thread (ServerDescription* server) return; } + TIMING ("encoder thread %1 wakes with queue of %2", pthread_self(), _queue.size()); boost::shared_ptr<DCPVideoFrame> vf = _queue.front (); _queue.pop_front (); @@ -166,9 +172,7 @@ J2KWAVEncoder::encoder_thread (ServerDescription* server) encoded = vf->encode_remotely (server); if (remote_backoff > 0) { - stringstream s; - s << server->host_name() << " was lost, but now she is found; removing backoff"; - _log->log (s.str ()); + _log->log (String::compose ("%1 was lost, but now she is found; removing backoff", server->host_name ())); } /* This job succeeded, so remove any backoff */ @@ -179,18 +183,20 @@ J2KWAVEncoder::encoder_thread (ServerDescription* server) /* back off more */ remote_backoff += 10; } - stringstream s; - s << "Remote encode of " << vf->frame() << " on " << server->host_name() << " failed (" << e.what() << "); thread sleeping for " << remote_backoff << "s."; - _log->log (s.str ()); + _log->log ( + String::compose ( + "Remote encode of %1 on %2 failed (%3); thread sleeping for %4s", + vf->frame(), server->host_name(), e.what(), remote_backoff) + ); } } else { try { + TIMING ("encoder thread %1 begins local encode of %2", pthread_self(), vf->frame()); encoded = vf->encode_locally (); + TIMING ("encoder thread %1 finishes local encode of %2", pthread_self(), vf->frame()); } catch (std::exception& e) { - stringstream s; - s << "Local encode failed " << e.what() << "."; - _log->log (s.str ()); + _log->log (String::compose ("Local encode failed (%1)", e.what ())); } } @@ -286,17 +292,13 @@ J2KWAVEncoder::process_end () */ for (list<shared_ptr<DCPVideoFrame> >::iterator i = _queue.begin(); i != _queue.end(); ++i) { - stringstream s; - s << "Encode left-over frame " << (*i)->frame(); - _log->log (s.str ()); + _log->log (String::compose ("Encode left-over frame %1", (*i)->frame ())); try { shared_ptr<EncodedData> e = (*i)->encode_locally (); e->write (_opt, (*i)->frame ()); frame_done ((*i)->frame ()); } catch (std::exception& e) { - stringstream s; - s << "Local encode failed " << e.what() << "."; - _log->log (s.str ()); + _log->log (String::compose ("Local encode failed (%1)", e.what ())); } } diff --git a/src/lib/job.cc b/src/lib/job.cc index 22754eb90..39ce4173a 100644 --- a/src/lib/job.cc +++ b/src/lib/job.cc @@ -41,6 +41,7 @@ Job::Job (shared_ptr<const FilmState> s, shared_ptr<const Options> o, Log* l) , _state (NEW) , _start_time (0) , _progress_unknown (false) + , _ran_for (0) { assert (_log); @@ -68,9 +69,7 @@ Job::run_wrapper () set_progress (1); set_state (FINISHED_ERROR); - stringstream s; - s << e.what() << "(" << filesystem::path (e.filename()).leaf() << ")"; - set_error (s.str ()); + set_error (String::compose ("%1 (%2)", e.what(), filesystem::path (e.filename()).leaf())); } catch (std::exception& e) { @@ -121,6 +120,10 @@ Job::set_state (State s) { boost::mutex::scoped_lock lm (_state_mutex); _state = s; + + if (_state == FINISHED_OK || _state == FINISHED_ERROR) { + _ran_for = elapsed_time (); + } } /** A hack to work around our lack of cross-thread @@ -245,7 +248,7 @@ Job::status () const } else if (!finished () && (t <= 10 || r == 0)) { s << rint (p * 100) << "%"; } else if (finished_ok ()) { - s << "OK (ran for " << seconds_to_hms (t) << ")"; + s << "OK (ran for " << seconds_to_hms (_ran_for) << ")"; } else if (finished_in_error ()) { s << "Error (" << error() << ")"; } diff --git a/src/lib/job.h b/src/lib/job.h index b39130479..802bf468d 100644 --- a/src/lib/job.h +++ b/src/lib/job.h @@ -119,6 +119,8 @@ private: /** true if this job's progress will always be unknown */ bool _progress_unknown; + + int _ran_for; }; #endif diff --git a/src/lib/log.cc b/src/lib/log.cc index 7f1eea206..650384bc7 100644 --- a/src/lib/log.cc +++ b/src/lib/log.cc @@ -42,7 +42,7 @@ Log::log (string m, Level l) if (l > _level) { return; } - + time_t t; time (&t); string a = ctime (&t); @@ -53,6 +53,23 @@ Log::log (string m, Level l) } void +Log::microsecond_log (string m, Level l) +{ + boost::mutex::scoped_lock lm (_mutex); + + if (l > _level) { + return; + } + + struct timeval tv; + gettimeofday (&tv, 0); + + stringstream s; + s << tv.tv_sec << ":" << tv.tv_usec << " " << m; + do_log (s.str ()); +} + +void Log::set_level (Level l) { boost::mutex::scoped_lock lm (_mutex); diff --git a/src/lib/log.h b/src/lib/log.h index 2a242e24c..2e5d69a08 100644 --- a/src/lib/log.h +++ b/src/lib/log.h @@ -37,10 +37,12 @@ public: enum Level { STANDARD = 0, - VERBOSE = 1 + VERBOSE = 1, + TIMING = 2 }; void log (std::string m, Level l = STANDARD); + void microsecond_log (std::string m, Level l = STANDARD); void set_level (Level l); diff --git a/src/lib/make_dcp_job.cc b/src/lib/make_dcp_job.cc index 8d3547cae..ae4bb4fbe 100644 --- a/src/lib/make_dcp_job.cc +++ b/src/lib/make_dcp_job.cc @@ -52,9 +52,7 @@ MakeDCPJob::MakeDCPJob (shared_ptr<const FilmState> s, shared_ptr<const Options> string MakeDCPJob::name () const { - stringstream s; - s << "Make DCP for " << _fs->name; - return s.str (); + return String::compose ("Make DCP for %1", _fs->name); } string diff --git a/src/lib/scp_dcp_job.cc b/src/lib/scp_dcp_job.cc index f62d2db8d..dac4a602c 100644 --- a/src/lib/scp_dcp_job.cc +++ b/src/lib/scp_dcp_job.cc @@ -78,9 +78,7 @@ public: { scp = ssh_scp_new (s, SSH_SCP_WRITE | SSH_SCP_RECURSIVE, Config::instance()->tms_path().c_str ()); if (!scp) { - stringstream s; - s << "Could not start SCP session (" << ssh_get_error (s) << ")"; - throw NetworkError (s.str ()); + throw NetworkError (String::compose ("Could not start SCP session (%1)", ssh_get_error (s))); } } @@ -103,9 +101,7 @@ SCPDCPJob::SCPDCPJob (shared_ptr<const FilmState> s, Log* l) string SCPDCPJob::name () const { - stringstream s; - s << "Copy DCP to TMS"; - return s.str (); + return "Copy DCP to TMS"; } void @@ -124,39 +120,29 @@ SCPDCPJob::run () int r = ss.connect (); if (r != SSH_OK) { - stringstream s; - s << "Could not connect to server " << Config::instance()->tms_ip() << " (" << ssh_get_error (ss.session) << ")"; - throw NetworkError (s.str ()); + throw NetworkError (String::compose ("Could not connect to server %1 (%2)", Config::instance()->tms_ip(), ssh_get_error (ss.session))); } int const state = ssh_is_server_known (ss.session); if (state == SSH_SERVER_ERROR) { - stringstream s; - s << "SSH error (" << ssh_get_error (ss.session) << ")"; - throw NetworkError (s.str ()); + throw NetworkError (String::compose ("SSH error (%1)", ssh_get_error (ss.session))); } r = ssh_userauth_password (ss.session, 0, Config::instance()->tms_password().c_str ()); if (r != SSH_AUTH_SUCCESS) { - stringstream s; - s << "Failed to authenticate with server (" << ssh_get_error (ss.session) << ")"; - throw NetworkError (s.str ()); + throw NetworkError (String::compose ("Failed to authenticate with server (%1)", ssh_get_error (ss.session))); } SSHSCP sc (ss.session); r = ssh_scp_init (sc.scp); if (r != SSH_OK) { - stringstream s; - s << "Could not start SCP session (" << ssh_get_error (ss.session) << ")"; - throw NetworkError (s.str ()); + throw NetworkError (String::compose ("Could not start SCP session (%1)", ssh_get_error (ss.session))); } r = ssh_scp_push_directory (sc.scp, _fs->name.c_str(), S_IRWXU); if (r != SSH_OK) { - stringstream s; - s << "Could not create remote directory " << _fs->name << "(" << ssh_get_error (ss.session) << ")"; - throw NetworkError (s.str ()); + throw NetworkError (String::compose ("Could not create remote directory %1 (%2)", _fs->name, ssh_get_error (ss.session))); } string const dcp_dir = _fs->dir (_fs->name); @@ -186,9 +172,7 @@ SCPDCPJob::run () FILE* f = fopen (filesystem::path (*i).string().c_str(), "rb"); if (f == 0) { - stringstream s; - s << "Could not open " << *i << " to send"; - throw NetworkError (s.str ()); + throw NetworkError (String::compose ("Could not open %1 to send", *i)); } while (to_do > 0) { @@ -200,9 +184,7 @@ SCPDCPJob::run () r = ssh_scp_write (sc.scp, buffer, t); if (r != SSH_OK) { - stringstream s; - s << "Could not write to remote file (" << ssh_get_error (ss.session) << ")"; - throw NetworkError (s.str ()); + throw NetworkError (String::compose ("Could not write to remote file (%1)", ssh_get_error (ss.session))); } to_do -= t; bytes_transferred += t; diff --git a/src/lib/server.cc b/src/lib/server.cc index f8c4425d9..28236e3e0 100644 --- a/src/lib/server.cc +++ b/src/lib/server.cc @@ -163,9 +163,7 @@ Server::worker_thread () if (frame >= 0) { struct timeval end; gettimeofday (&end, 0); - stringstream s; - s << "Encoded frame " << frame << " in " << (seconds (end) - seconds (start)); - _log->log (s.str ()); + _log->log (String::compose ("Encoded frame %1 in %2", frame, seconds (end) - seconds (start))); } _worker_condition.notify_all (); @@ -175,9 +173,7 @@ Server::worker_thread () void Server::run (int num_threads) { - stringstream s; - s << "Server starting with " << num_threads << " threads."; - _log->log (s.str ()); + _log->log (String::compose ("Server starting with %1 threads", num_threads)); for (int i = 0; i < num_threads; ++i) { _worker_threads.push_back (new thread (bind (&Server::worker_thread, this))); diff --git a/src/lib/thumbs_job.cc b/src/lib/thumbs_job.cc index 0eb116fd1..f6ed75ff7 100644 --- a/src/lib/thumbs_job.cc +++ b/src/lib/thumbs_job.cc @@ -44,9 +44,7 @@ ThumbsJob::ThumbsJob (shared_ptr<const FilmState> s, shared_ptr<const Options> o string ThumbsJob::name () const { - stringstream s; - s << "Update thumbs for " << _fs->name; - return s.str (); + return String::compose ("Update thumbs for %1", _fs->name); } void diff --git a/src/lib/transcode_job.cc b/src/lib/transcode_job.cc index 9113593f0..e79be09fe 100644 --- a/src/lib/transcode_job.cc +++ b/src/lib/transcode_job.cc @@ -48,9 +48,7 @@ TranscodeJob::TranscodeJob (shared_ptr<const FilmState> s, shared_ptr<const Opti string TranscodeJob::name () const { - stringstream s; - s << "Transcode " << _fs->name; - return s.str (); + return String::compose ("Transcode %1", _fs->name); } void @@ -70,12 +68,9 @@ TranscodeJob::run () } catch (std::exception& e) { - stringstream s; set_progress (1); set_state (FINISHED_ERROR); - - s << "Transcode job failed (" << e.what() << ")"; - _log->log (s.str ()); + _log->log (String::compose ("Transcode job failed (%1)", e.what())); throw; } diff --git a/src/lib/util.h b/src/lib/util.h index bc5a00fc4..8d98437af 100644 --- a/src/lib/util.h +++ b/src/lib/util.h @@ -34,6 +34,13 @@ extern "C" { #include <libavfilter/avfilter.h> } +#ifdef DVDOMATIC_DEBUG +#include "compose.hpp" +#define TIMING(...) _log->microsecond_log (String::compose (__VA_ARGS__), Log::TIMING); +#else +#define TIMING(...) +#endif + class Scaler; extern std::string seconds_to_hms (int); diff --git a/src/tools/dvdomatic.cc b/src/tools/dvdomatic.cc index c42321300..9ff2c1ddc 100644 --- a/src/tools/dvdomatic.cc +++ b/src/tools/dvdomatic.cc @@ -352,11 +352,12 @@ public: info.SetName (_("DVD-o-matic")); info.SetVersion (wxT (DVDOMATIC_VERSION)); info.SetDescription (_("Free, open-source DCP generation from almost anything.")); - info.SetCopyright (_("(C) Carl Hetherington, Terrence Meiczinger, Paul Davis")); + info.SetCopyright (_("(C) Carl Hetherington, Terrence Meiczinger, Paul Davis, Ole Laursen")); wxArrayString authors; authors.Add (wxT ("Carl Hetherington")); authors.Add (wxT ("Terrence Meiczinger")); authors.Add (wxT ("Paul Davis")); + authors.Add (wxT ("Ole Laursen")); info.SetDevelopers (authors); info.SetWebSite (wxT ("http://carlh.net/software/dvdomatic")); wxAboutBox (info); diff --git a/src/tools/makedcp.cc b/src/tools/makedcp.cc index c6cb1ba14..d3608059c 100644 --- a/src/tools/makedcp.cc +++ b/src/tools/makedcp.cc @@ -34,6 +34,7 @@ #include "version.h" #include "cross.h" #include "config.h" +#include "log.h" using namespace std; using namespace boost; @@ -58,6 +59,7 @@ main (int argc, char* argv[]) string film_dir; bool test_mode = false; bool progress = true; + int log_level = 1; int option_index = 0; while (1) { @@ -68,10 +70,11 @@ main (int argc, char* argv[]) { "config", no_argument, 0, 'c'}, { "test", no_argument, 0, 't'}, { "no-progress", no_argument, 0, 'n'}, + { "log-level", required_argument, 0, 'l' }, { 0, 0, 0, 0 } }; - int c = getopt_long (argc, argv, "vhdctn", long_options, &option_index); + int c = getopt_long (argc, argv, "vhdctnl:", long_options, &option_index); if (c == -1) { break; @@ -102,6 +105,9 @@ main (int argc, char* argv[]) cout << "built in optimised mode\n"; #endif exit (EXIT_SUCCESS); + case 'l': + log_level = atoi (optarg); + break; } } @@ -134,6 +140,8 @@ main (int argc, char* argv[]) exit (EXIT_FAILURE); } + film->log()->set_level ((Log::Level) log_level); + cout << "\nMaking "; if (film->dcp_ab ()) { cout << "A/B "; diff --git a/src/wx/film_editor.cc b/src/wx/film_editor.cc index 6de3af9e7..9171daa5c 100644 --- a/src/wx/film_editor.cc +++ b/src/wx/film_editor.cc @@ -289,9 +289,7 @@ FilmEditor::content_changed (wxCommandEvent &) _film->set_content (wx_to_std (_content->GetPath ())); } catch (std::exception& e) { _content->SetPath (std_to_wx (_film->directory ())); - stringstream m; - m << "Could not set content: " << e.what() << "."; - error_dialog (this, m.str ()); + error_dialog (this, String::compose ("Could not set content: %1", e.what ())); } _ignore_changes = Film::NONE; diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index 0d17baf83..e647a5886 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -171,7 +171,7 @@ END_EVENT_TABLE () FilmViewer::FilmViewer (Film* f, wxWindow* p) : wxPanel (p) - , _film (f) + , _film (0) { _sizer = new wxBoxSizer (wxVERTICAL); SetSizer (_sizer); @@ -232,6 +232,10 @@ FilmViewer::film_changed (Film::Property p) void FilmViewer::set_film (Film* f) { + if (_film == f) { + return; + } + _film = f; _thumb_panel->set_film (_film); diff --git a/src/wx/job_manager_view.cc b/src/wx/job_manager_view.cc index 1d5c855ea..97da3936f 100644 --- a/src/wx/job_manager_view.cc +++ b/src/wx/job_manager_view.cc @@ -111,9 +111,7 @@ JobManagerView::update () try { (*i)->emit_finished (); } catch (OpenFileError& e) { - stringstream s; - s << "Error: " << e.what(); - error_dialog (this, s.str ()); + error_dialog (this, String::compose ("Error: %1", e.what ())); } _job_records[*i].informed_of_finish = true; diff --git a/src/wx/job_wrapper.cc b/src/wx/job_wrapper.cc index ad83aa271..cc7507547 100644 --- a/src/wx/job_wrapper.cc +++ b/src/wx/job_wrapper.cc @@ -35,12 +35,8 @@ JobWrapper::make_dcp (wxWindow* parent, Film* film, bool transcode) try { film->make_dcp (transcode); } catch (BadSettingError& e) { - stringstream s; - s << "Bad setting for " << e.setting() << "(" << e.what() << ")"; - error_dialog (parent, s.str ()); + error_dialog (parent, String::compose ("Bad setting for %1 (%2)", e.setting(), e.what ())); } catch (std::exception& e) { - stringstream s; - s << "Could not make DCP: " << e.what () << "."; - error_dialog (parent, s.str ()); + error_dialog (parent, String::compose ("Could not make DCP: %1", e.what ())); } } |
