From 71d8cf20889a3c419c9a3e485f461236e5317423 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Wed, 21 May 2014 16:44:06 +0100 Subject: [PATCH] Tidy up logging a bit. Make it configurable from the GUI. --- ChangeLog | 6 ++ src/lib/config.cc | 4 ++ src/lib/config.h | 10 +++ src/lib/cross.cc | 13 ++-- src/lib/dcp_video_frame.cc | 12 ++-- src/lib/encoder.cc | 46 ++++++------- src/lib/ffmpeg_content.cc | 4 +- src/lib/ffmpeg_decoder.cc | 26 ++++--- src/lib/film.cc | 29 ++++---- src/lib/image_decoder.cc | 5 +- src/lib/image_proxy.cc | 33 ++++++--- src/lib/image_proxy.h | 16 +++-- src/lib/log.cc | 70 ++++++++++++++----- src/lib/log.h | 22 +++--- src/lib/player.cc | 10 +-- src/lib/player_video_frame.cc | 4 +- src/lib/player_video_frame.h | 3 +- src/lib/scp_dcp_job.cc | 4 +- src/lib/server.cc | 17 +++-- src/lib/transcode_job.cc | 9 ++- src/lib/util.h | 6 -- src/lib/writer.cc | 41 +++++------ src/tools/dcpomatic.cc | 12 ++-- src/tools/dcpomatic_cli.cc | 8 +-- src/wx/config_dialog.cc | 125 +++++++++++++++++++++++++++------- test/client_server_test.cc | 6 +- 26 files changed, 360 insertions(+), 181 deletions(-) diff --git a/ChangeLog b/ChangeLog index da42e7ba1..0b6a24f8a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2014-05-21 Carl Hetherington + + * Tidy up logging a bit and make it configurable from the GUI + (moving a few things into an Advanced preferences tab at + the same time). + 2014-05-19 Carl Hetherington * Version 1.69.9 released. diff --git a/src/lib/config.cc b/src/lib/config.cc index 40ae3971b..6d029dd1f 100644 --- a/src/lib/config.cc +++ b/src/lib/config.cc @@ -73,6 +73,7 @@ Config::Config () , _check_for_updates (false) , _check_for_test_updates (false) , _maximum_j2k_bandwidth (250000000) + , _log_types (Log::GENERAL | Log::WARNING | Log::ERROR) { _allowed_dcp_frame_rates.push_back (24); _allowed_dcp_frame_rates.push_back (25); @@ -189,6 +190,8 @@ Config::read () _maximum_j2k_bandwidth = f.optional_number_child ("MaximumJ2KBandwidth").get_value_or (250000000); _allow_any_dcp_frame_rate = f.optional_bool_child ("AllowAnyDCPFrameRate"); + + _log_types = f.optional_number_child ("LogTypes").get_value_or (Log::GENERAL | Log::WARNING | Log::ERROR); } void @@ -366,6 +369,7 @@ Config::write () const root->add_child("MaximumJ2KBandwidth")->add_child_text (raw_convert (_maximum_j2k_bandwidth)); root->add_child("AllowAnyDCPFrameRate")->add_child_text (_allow_any_dcp_frame_rate ? "1" : "0"); + root->add_child("LogTypes")->add_child_text (raw_convert (_log_types)); doc.write_to_file_formatted (file(false).string ()); } diff --git a/src/lib/config.h b/src/lib/config.h index 87b7038de..bd8cfe297 100644 --- a/src/lib/config.h +++ b/src/lib/config.h @@ -188,6 +188,10 @@ public: int maximum_j2k_bandwidth () const { return _maximum_j2k_bandwidth; } + + int log_types () const { + return _log_types; + } /** @param n New number of local encoding threads */ void set_num_local_encoding_threads (int n) { @@ -339,6 +343,11 @@ public: _maximum_j2k_bandwidth = b; changed (); } + + void set_log_types (int t) { + _log_types = t; + changed (); + } boost::filesystem::path signer_chain_directory () const; @@ -401,6 +410,7 @@ private: bool _check_for_test_updates; /** maximum allowed J2K bandwidth in bits per second */ int _maximum_j2k_bandwidth; + int _log_types; /** Singleton instance, or 0 */ static Config* _instance; diff --git a/src/lib/cross.cc b/src/lib/cross.cc index 8785553cb..9247baa97 100644 --- a/src/lib/cross.cc +++ b/src/lib/cross.cc @@ -44,6 +44,11 @@ #endif #include "exceptions.h" +#include "i18n.h" + +#define LOG_GENERAL(...) log->log (String::compose (__VA_ARGS__), Log::GENERAL); +#define LOG_ERROR(...) log->log (String::compose (__VA_ARGS__), Log::ERROR); + using std::pair; using std::list; using std::ifstream; @@ -184,13 +189,13 @@ run_ffprobe (boost::filesystem::path content, boost::filesystem::path out, share PROCESS_INFORMATION process_info; ZeroMemory (&process_info, sizeof (process_info)); if (!CreateProcess (0, command, 0, 0, TRUE, CREATE_NO_WINDOW, 0, 0, &startup_info, &process_info)) { - log->log ("ffprobe call failed (could not CreateProcess)"); + LOG_ERROR (N_("ffprobe call failed (could not CreateProcess)")); return; } FILE* o = fopen_boost (out, "w"); if (!o) { - log->log ("ffprobe call failed (could not create output file)"); + LOG_ERROR (N_("ffprobe call failed (could not create output file)")); return; } @@ -215,7 +220,7 @@ run_ffprobe (boost::filesystem::path content, boost::filesystem::path out, share #ifdef DCPOMATIC_LINUX string ffprobe = "ffprobe \"" + content.string() + "\" 2> \"" + out.string() + "\""; - log->log (String::compose ("Probing with %1", ffprobe)); + LOG_GENERAL (N_("Probing with %1"), ffprobe); system (ffprobe.c_str ()); #endif @@ -225,7 +230,7 @@ run_ffprobe (boost::filesystem::path content, boost::filesystem::path out, share path /= "ffprobe"; string ffprobe = path.string() + " \"" + content.string() + "\" 2> \"" + out.string() + "\""; - log->log (String::compose ("Probing with %1", ffprobe)); + LOG_GENERAL (N_("Probing with %1"), ffprobe); system (ffprobe.c_str ()); #endif } diff --git a/src/lib/dcp_video_frame.cc b/src/lib/dcp_video_frame.cc index 5cd6a118e..265cbaae8 100644 --- a/src/lib/dcp_video_frame.cc +++ b/src/lib/dcp_video_frame.cc @@ -63,6 +63,8 @@ #include "cross.h" #include "player_video_frame.h" +#define LOG_GENERAL(...) _log->log (String::compose (__VA_ARGS__), Log::GENERAL); + #include "i18n.h" using std::string; @@ -250,13 +252,13 @@ DCPVideoFrame::encode_locally () switch (_frame->eyes()) { case EYES_BOTH: - _log->log (String::compose (N_("Finished locally-encoded frame %1 for mono"), _index)); + LOG_GENERAL (N_("Finished locally-encoded frame %1 for mono"), _index); break; case EYES_LEFT: - _log->log (String::compose (N_("Finished locally-encoded frame %1 for L"), _index)); + LOG_GENERAL (N_("Finished locally-encoded frame %1 for L"), _index); break; case EYES_RIGHT: - _log->log (String::compose (N_("Finished locally-encoded frame %1 for R"), _index)); + LOG_GENERAL (N_("Finished locally-encoded frame %1 for R"), _index); break; default: break; @@ -293,7 +295,7 @@ DCPVideoFrame::encode_remotely (ServerDescription serv) root->add_child("Version")->add_child_text (raw_convert (SERVER_LINK_VERSION)); add_metadata (root); - _log->log (String::compose (N_("Sending frame %1 to remote"), _index)); + LOG_GENERAL (N_("Sending frame %1 to remote"), _index); /* Send XML metadata */ stringstream xml; @@ -310,7 +312,7 @@ DCPVideoFrame::encode_remotely (ServerDescription serv) shared_ptr e (new RemotelyEncodedData (socket->read_uint32 ())); socket->read (e->data(), e->size()); - _log->log (String::compose (N_("Finished remotely-encoded frame %1"), _index)); + LOG_GENERAL (N_("Finished remotely-encoded frame %1"), _index); return e; } diff --git a/src/lib/encoder.cc b/src/lib/encoder.cc index 4fc2d7f81..05da6bbdf 100644 --- a/src/lib/encoder.cc +++ b/src/lib/encoder.cc @@ -39,6 +39,10 @@ #include "i18n.h" +#define LOG_GENERAL(...) _film->log()->log (String::compose (__VA_ARGS__), Log::GENERAL); +#define LOG_ERROR(...) _film->log()->log (String::compose (__VA_ARGS__), Log::ERROR); +#define LOG_TIMING(...) _film->log()->log (String::compose (__VA_ARGS__), Log::TIMING); + using std::pair; using std::string; using std::stringstream; @@ -78,7 +82,7 @@ Encoder::~Encoder () void Encoder::add_worker_threads (ServerDescription d) { - _film->log()->log (String::compose (N_("Adding %1 worker threads for remote %2"), d.host_name ())); + LOG_GENERAL (N_("Adding %1 worker threads for remote %2"), d.host_name ()); for (int i = 0; i < d.threads(); ++i) { _threads.push_back (new boost::thread (boost::bind (&Encoder::encoder_thread, this, d))); } @@ -100,11 +104,10 @@ Encoder::process_end () { boost::mutex::scoped_lock lock (_mutex); - _film->log()->log (String::compose (N_("Clearing queue of %1"), _queue.size ())); + LOG_GENERAL (N_("Clearing queue of %1"), _queue.size ()); /* Keep waking workers until the queue is empty */ while (!_queue.empty ()) { - _film->log()->log (String::compose (N_("Waking with %1"), _queue.size ()), Log::VERBOSE); _condition.notify_all (); _condition.wait (lock); } @@ -113,7 +116,7 @@ Encoder::process_end () terminate_threads (); - _film->log()->log (String::compose (N_("Mopping up %1"), _queue.size())); + LOG_GENERAL (N_("Mopping up %1"), _queue.size()); /* The following sequence of events can occur in the above code: 1. a remote worker takes the last image off the queue @@ -125,12 +128,12 @@ Encoder::process_end () */ for (list >::iterator i = _queue.begin(); i != _queue.end(); ++i) { - _film->log()->log (String::compose (N_("Encode left-over frame %1"), (*i)->index ())); + LOG_GENERAL (N_("Encode left-over frame %1"), (*i)->index ()); try { _writer->write ((*i)->encode_locally(), (*i)->index (), (*i)->eyes ()); frame_done (); } catch (std::exception& e) { - _film->log()->log (String::compose (N_("Local encode failed (%1)"), e.what ())); + LOG_ERROR (N_("Local encode failed (%1)"), e.what ()); } } @@ -190,9 +193,9 @@ Encoder::process_video (shared_ptr pvf, bool same) /* Wait until the queue has gone down a bit */ while (_queue.size() >= _threads.size() * 2 && !_terminate) { - TIMING ("decoder sleeps with queue of %1", _queue.size()); + LOG_TIMING ("decoder sleeps with queue of %1", _queue.size()); _condition.wait (lock); - TIMING ("decoder wakes with queue of %1", _queue.size()); + LOG_TIMING ("decoder wakes with queue of %1", _queue.size()); } if (_terminate) { @@ -216,7 +219,7 @@ Encoder::process_video (shared_ptr pvf, bool same) frame_done (); } else { /* Queue this new frame for encoding */ - TIMING ("adding to queue of %1", _queue.size ()); + LOG_TIMING ("adding to queue of %1", _queue.size ()); _queue.push_back (shared_ptr ( new DCPVideoFrame ( pvf, _video_frames_out, _film->video_frame_rate(), @@ -270,7 +273,7 @@ try while (1) { - TIMING ("encoder thread %1 sleeps", boost::this_thread::get_id()); + LOG_TIMING ("encoder thread %1 sleeps", boost::this_thread::get_id()); boost::mutex::scoped_lock lock (_mutex); while (_queue.empty () && !_terminate) { _condition.wait (lock); @@ -280,9 +283,9 @@ try return; } - TIMING ("encoder thread %1 wakes with queue of %2", boost::this_thread::get_id(), _queue.size()); + LOG_TIMING ("encoder thread %1 wakes with queue of %2", boost::this_thread::get_id(), _queue.size()); shared_ptr vf = _queue.front (); - TIMING ("encoder thread %1 pops frame %2 (%3) from queue", boost::this_thread::get_id(), vf->index(), vf->eyes ()); + LOG_TIMING ("encoder thread %1 pops frame %2 (%3) from queue", boost::this_thread::get_id(), vf->index(), vf->eyes ()); _queue.pop_front (); lock.unlock (); @@ -294,7 +297,7 @@ try encoded = vf->encode_remotely (server.get ()); if (remote_backoff > 0) { - _film->log()->log (String::compose (N_("%1 was lost, but now she is found; removing backoff"), server->host_name ())); + LOG_GENERAL ("%1 was lost, but now she is found; removing backoff", server->host_name ()); } /* This job succeeded, so remove any backoff */ @@ -305,20 +308,19 @@ try /* back off more */ remote_backoff += 10; } - _film->log()->log ( - String::compose ( - N_("Remote encode of %1 on %2 failed (%3); thread sleeping for %4s"), - vf->index(), server->host_name(), e.what(), remote_backoff) + LOG_ERROR ( + N_("Remote encode of %1 on %2 failed (%3); thread sleeping for %4s"), + vf->index(), server->host_name(), e.what(), remote_backoff ); } } else { try { - TIMING ("encoder thread %1 begins local encode of %2", boost::this_thread::get_id(), vf->index()); + LOG_TIMING ("encoder thread %1 begins local encode of %2", boost::this_thread::get_id(), vf->index()); encoded = vf->encode_locally (); - TIMING ("encoder thread %1 finishes local encode of %2", boost::this_thread::get_id(), vf->index()); + LOG_TIMING ("encoder thread %1 finishes local encode of %2", boost::this_thread::get_id(), vf->index()); } catch (std::exception& e) { - _film->log()->log (String::compose (N_("Local encode failed (%1)"), e.what ())); + LOG_ERROR (N_("Local encode failed (%1)"), e.what ()); } } @@ -327,9 +329,7 @@ try frame_done (); } else { lock.lock (); - _film->log()->log ( - String::compose (N_("Encoder thread %1 pushes frame %2 back onto queue after failure"), boost::this_thread::get_id(), vf->index()) - ); + LOG_GENERAL (N_("Encoder thread %1 pushes frame %2 back onto queue after failure"), boost::this_thread::get_id(), vf->index()); _queue.push_front (vf); lock.unlock (); } diff --git a/src/lib/ffmpeg_content.cc b/src/lib/ffmpeg_content.cc index f810d53be..5d0a6a309 100644 --- a/src/lib/ffmpeg_content.cc +++ b/src/lib/ffmpeg_content.cc @@ -34,6 +34,8 @@ extern "C" { #include "i18n.h" +#define LOG_GENERAL(...) film->log()->log (String::compose (__VA_ARGS__), Log::GENERAL); + using std::string; using std::stringstream; using std::vector; @@ -171,7 +173,7 @@ FFmpegContent::examine (shared_ptr job) VideoContent::Frame video_length = 0; video_length = examiner->video_length (); - film->log()->log (String::compose ("Video length obtained from header as %1 frames", video_length)); + LOG_GENERAL ("Video length obtained from header as %1 frames", video_length); { boost::mutex::scoped_lock lm (_mutex); diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index 7a5bf8ba8..6351c7e22 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012 Carl Hetherington + Copyright (C) 2012-2014 Carl Hetherington This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -46,6 +46,10 @@ extern "C" { #include "i18n.h" +#define LOG_GENERAL(...) film->log()->log (String::compose (__VA_ARGS__), Log::GENERAL); +#define LOG_ERROR(...) film->log()->log (String::compose (__VA_ARGS__), Log::ERROR); +#define LOG_WARNING(...) film->log()->log (__VA_ARGS__, Log::WARNING); + using std::cout; using std::string; using std::vector; @@ -158,7 +162,7 @@ FFmpegDecoder::pass () av_strerror (r, buf, sizeof(buf)); shared_ptr film = _film.lock (); assert (film); - film->log()->log (String::compose (N_("error on av_read_frame (%1) (%2)"), buf, r)); + LOG_ERROR (N_("error on av_read_frame (%1) (%2)"), buf, r); } flush (); @@ -400,7 +404,7 @@ FFmpegDecoder::decode_audio_packet () if (decode_result < 0) { shared_ptr film = _film.lock (); assert (film); - film->log()->log (String::compose ("avcodec_decode_audio4 failed (%1)", decode_result)); + LOG_ERROR ("avcodec_decode_audio4 failed (%1)", decode_result); return; } @@ -461,13 +465,16 @@ FFmpegDecoder::decode_video_packet () graph.reset (new FilterGraph (_ffmpeg_content, libdcp::Size (_frame->width, _frame->height), (AVPixelFormat) _frame->format)); _filter_graphs.push_back (graph); - film->log()->log (String::compose (N_("New graph for %1x%2, pixel format %3"), _frame->width, _frame->height, _frame->format)); + LOG_GENERAL (N_("New graph for %1x%2, pixel format %3"), _frame->width, _frame->height, _frame->format); } else { graph = *i; } list, int64_t> > images = graph->process (_frame); + shared_ptr film = _film.lock (); + assert (film); + for (list, int64_t> >::iterator i = images.begin(); i != images.end(); ++i) { shared_ptr image = i->first; @@ -502,20 +509,21 @@ FFmpegDecoder::decode_video_packet () ) ); + shared_ptr film = _film.lock (); + assert (film); + black->make_black (); - video (shared_ptr (new RawImageProxy (image)), false, _video_position); + video (shared_ptr (new RawImageProxy (image, film->log())), false, _video_position); delta -= one_frame; } if (delta > -one_frame) { /* This PTS is within a frame of being right; emit this (otherwise it will be dropped) */ - video (shared_ptr (new RawImageProxy (image)), false, _video_position); + video (shared_ptr (new RawImageProxy (image, film->log())), false, _video_position); } } else { - shared_ptr film = _film.lock (); - assert (film); - film->log()->log ("Dropping frame without PTS"); + LOG_WARNING ("Dropping frame without PTS"); } } diff --git a/src/lib/film.cc b/src/lib/film.cc index 12a57753f..206400da2 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -81,6 +81,9 @@ using libdcp::Size; using libdcp::Signer; using libdcp::raw_convert; +#define LOG_GENERAL(...) log()->log (String::compose (__VA_ARGS__), Log::GENERAL); +#define LOG_GENERAL_NC(...) log()->log (__VA_ARGS__, Log::GENERAL); + /* 5 -> 6 * AudioMapping XML changed. * 6 -> 7 @@ -253,43 +256,43 @@ Film::make_dcp () */ write_metadata (); - log()->log (String::compose ("DCP-o-matic %1 git %2 using %3", dcpomatic_version, dcpomatic_git_commit, dependency_version_summary())); + LOG_GENERAL ("DCP-o-matic %1 git %2 using %3", dcpomatic_version, dcpomatic_git_commit, dependency_version_summary()); { char buffer[128]; gethostname (buffer, sizeof (buffer)); - log()->log (String::compose ("Starting to make DCP on %1", buffer)); + LOG_GENERAL ("Starting to make DCP on %1", buffer); } ContentList cl = content (); for (ContentList::const_iterator i = cl.begin(); i != cl.end(); ++i) { - log()->log (String::compose ("Content: %1", (*i)->technical_summary())); + LOG_GENERAL ("Content: %1", (*i)->technical_summary()); } - log()->log (String::compose ("DCP video rate %1 fps", video_frame_rate())); - log()->log (String::compose ("%1 threads", Config::instance()->num_local_encoding_threads())); - log()->log (String::compose ("J2K bandwidth %1", j2k_bandwidth())); + LOG_GENERAL ("DCP video rate %1 fps", video_frame_rate()); + LOG_GENERAL ("%1 threads", Config::instance()->num_local_encoding_threads()); + LOG_GENERAL ("J2K bandwidth %1", j2k_bandwidth()); #ifdef DCPOMATIC_DEBUG - log()->log ("DCP-o-matic built in debug mode."); + LOG_GENERAL_NC ("DCP-o-matic built in debug mode."); #else - log()->log ("DCP-o-matic built in optimised mode."); + LOG_GENERAL_NC ("DCP-o-matic built in optimised mode."); #endif #ifdef LIBDCP_DEBUG - log()->log ("libdcp built in debug mode."); + LOG_GENERAL_NC ("libdcp built in debug mode."); #else - log()->log ("libdcp built in optimised mode."); + LOG_GENERAL_NC ("libdcp built in optimised mode."); #endif #ifdef DCPOMATIC_WINDOWS OSVERSIONINFO info; info.dwOSVersionInfoSize = sizeof (info); GetVersionEx (&info); - log()->log (String::compose ("Windows version %1.%2.%3 SP %4", info.dwMajorVersion, info.dwMinorVersion, info.dwBuildNumber, info.szCSDVersion)); + LOG_GENERAL ("Windows version %1.%2.%3 SP %4", info.dwMajorVersion, info.dwMinorVersion, info.dwBuildNumber, info.szCSDVersion); #endif - log()->log (String::compose ("CPU: %1, %2 processors", cpu_info(), boost::thread::hardware_concurrency ())); + LOG_GENERAL ("CPU: %1, %2 processors", cpu_info(), boost::thread::hardware_concurrency ()); list > const m = mount_info (); for (list >::const_iterator i = m.begin(); i != m.end(); ++i) { - log()->log (String::compose ("Mount: %1 %2", i->first, i->second)); + LOG_GENERAL ("Mount: %1 %2", i->first, i->second); } if (container() == 0) { diff --git a/src/lib/image_decoder.cc b/src/lib/image_decoder.cc index d33b64cd4..7a9acd9e4 100644 --- a/src/lib/image_decoder.cc +++ b/src/lib/image_decoder.cc @@ -53,7 +53,10 @@ ImageDecoder::pass () return; } - _image.reset (new MagickImageProxy (_image_content->path (_image_content->still() ? 0 : _video_position))); + shared_ptr film = _film.lock (); + assert (film); + + _image.reset (new MagickImageProxy (_image_content->path (_image_content->still() ? 0 : _video_position), film->log ())); video (_image, false, _video_position); } diff --git a/src/lib/image_proxy.cc b/src/lib/image_proxy.cc index 0806b4ccc..c0e75c77c 100644 --- a/src/lib/image_proxy.cc +++ b/src/lib/image_proxy.cc @@ -24,21 +24,32 @@ #include "image.h" #include "exceptions.h" #include "cross.h" +#include "log.h" #include "i18n.h" +#define LOG_TIMING(...) _log->microsecond_log (String::compose (__VA_ARGS__), Log::TIMING); + using std::cout; using std::string; using std::stringstream; using boost::shared_ptr; -RawImageProxy::RawImageProxy (shared_ptr image) - : _image (image) +ImageProxy::ImageProxy (shared_ptr log) + : _log (log) +{ + +} + +RawImageProxy::RawImageProxy (shared_ptr image, shared_ptr log) + : ImageProxy (log) + , _image (image) { } -RawImageProxy::RawImageProxy (shared_ptr xml, shared_ptr socket) +RawImageProxy::RawImageProxy (shared_ptr xml, shared_ptr socket, shared_ptr log) + : ImageProxy (log) { libdcp::Size size ( xml->number_child ("Width"), xml->number_child ("Height") @@ -68,7 +79,8 @@ RawImageProxy::send_binary (shared_ptr socket) const _image->write_to_socket (socket); } -MagickImageProxy::MagickImageProxy (boost::filesystem::path path) +MagickImageProxy::MagickImageProxy (boost::filesystem::path path, shared_ptr log) + : ImageProxy (log) { /* Read the file into a Blob */ @@ -89,7 +101,8 @@ MagickImageProxy::MagickImageProxy (boost::filesystem::path path) delete[] data; } -MagickImageProxy::MagickImageProxy (shared_ptr, shared_ptr socket) +MagickImageProxy::MagickImageProxy (shared_ptr, shared_ptr socket, shared_ptr log) + : ImageProxy (log) { uint32_t const size = socket->read_uint32 (); uint8_t* data = new uint8_t[size]; @@ -105,7 +118,7 @@ MagickImageProxy::image () const return _image; } - TIMING("MagickImageProxy begins read and decode of %1 bytes", _blob.length()); + LOG_TIMING ("MagickImageProxy begins read and decode of %1 bytes", _blob.length()); Magick::Image* magick_image = 0; try { @@ -134,7 +147,7 @@ MagickImageProxy::image () const delete magick_image; - TIMING("MagickImageProxy completes read and decode of %1 bytes", _blob.length()); + LOG_TIMING ("MagickImageProxy completes read and decode of %1 bytes", _blob.length()); return _image; } @@ -153,12 +166,12 @@ MagickImageProxy::send_binary (shared_ptr socket) const } shared_ptr -image_proxy_factory (shared_ptr xml, shared_ptr socket) +image_proxy_factory (shared_ptr xml, shared_ptr socket, shared_ptr log) { if (xml->string_child("Type") == N_("Raw")) { - return shared_ptr (new RawImageProxy (xml, socket)); + return shared_ptr (new RawImageProxy (xml, socket, log)); } else if (xml->string_child("Type") == N_("Magick")) { - return shared_ptr (new MagickImageProxy (xml, socket)); + return shared_ptr (new MagickImageProxy (xml, socket, log)); } throw NetworkError (_("Unexpected image type received by server")); diff --git a/src/lib/image_proxy.h b/src/lib/image_proxy.h index 792fa004a..fcbda7dd1 100644 --- a/src/lib/image_proxy.h +++ b/src/lib/image_proxy.h @@ -28,6 +28,7 @@ class Image; class Socket; +class Log; namespace cxml { class Node; @@ -47,16 +48,21 @@ namespace cxml { class ImageProxy { public: + ImageProxy (boost::shared_ptr log); + virtual boost::shared_ptr image () const = 0; virtual void add_metadata (xmlpp::Node *) const = 0; virtual void send_binary (boost::shared_ptr) const = 0; + +protected: + boost::shared_ptr _log; }; class RawImageProxy : public ImageProxy { public: - RawImageProxy (boost::shared_ptr); - RawImageProxy (boost::shared_ptr xml, boost::shared_ptr socket); + RawImageProxy (boost::shared_ptr, boost::shared_ptr log); + RawImageProxy (boost::shared_ptr xml, boost::shared_ptr socket, boost::shared_ptr log); boost::shared_ptr image () const; void add_metadata (xmlpp::Node *) const; @@ -69,8 +75,8 @@ private: class MagickImageProxy : public ImageProxy { public: - MagickImageProxy (boost::filesystem::path); - MagickImageProxy (boost::shared_ptr xml, boost::shared_ptr socket); + MagickImageProxy (boost::filesystem::path, boost::shared_ptr log); + MagickImageProxy (boost::shared_ptr xml, boost::shared_ptr socket, boost::shared_ptr log); boost::shared_ptr image () const; void add_metadata (xmlpp::Node *) const; @@ -81,4 +87,4 @@ private: mutable boost::shared_ptr _image; }; -boost::shared_ptr image_proxy_factory (boost::shared_ptr xml, boost::shared_ptr socket); +boost::shared_ptr image_proxy_factory (boost::shared_ptr xml, boost::shared_ptr socket, boost::shared_ptr log); diff --git a/src/lib/log.cc b/src/lib/log.cc index a0b031589..be32315d1 100644 --- a/src/lib/log.cc +++ b/src/lib/log.cc @@ -23,26 +23,42 @@ #include #include +#include #include "log.h" #include "cross.h" +#include "config.h" #include "i18n.h" using namespace std; +using boost::algorithm::is_any_of; +using boost::algorithm::split; + +int const Log::GENERAL = 0x1; +int const Log::WARNING = 0x2; +int const Log::ERROR = 0x4; +int const Log::TIMING = 0x8; Log::Log () - : _level (STANDARD) + : _types (0) { + Config::instance()->Changed.connect (boost::bind (&Log::config_changed, this)); + config_changed (); +} +void +Log::config_changed () +{ + set_types (Config::instance()->log_types ()); } /** @param n String to log */ void -Log::log (string m, Level l) +Log::log (string message, int type) { boost::mutex::scoped_lock lm (_mutex); - if (l > _level) { + if ((_types & type) == 0) { return; } @@ -51,16 +67,26 @@ Log::log (string m, Level l) string a = ctime (&t); stringstream s; - s << a.substr (0, a.length() - 1) << N_(": ") << m; + s << a.substr (0, a.length() - 1) << N_(": "); + + if (type & ERROR) { + s << "ERROR: "; + } + + if (type & WARNING) { + s << "WARNING: "; + } + + s << message; do_log (s.str ()); } void -Log::microsecond_log (string m, Level l) +Log::microsecond_log (string m, int t) { boost::mutex::scoped_lock lm (_mutex); - if (l > _level) { + if ((_types & t) == 0) { return; } @@ -73,24 +99,34 @@ Log::microsecond_log (string m, Level l) } void -Log::set_level (Level l) +Log::set_types (int t) { boost::mutex::scoped_lock lm (_mutex); - _level = l; + _types = t; } +/** @param A comma-separate list of debug types to enable */ void -Log::set_level (string l) +Log::set_types (string t) { - if (l == N_("verbose")) { - set_level (VERBOSE); - return; - } else if (l == N_("timing")) { - set_level (TIMING); - return; - } + boost::mutex::scoped_lock lm (_mutex); - set_level (STANDARD); + vector types; + split (types, t, is_any_of (",")); + + _types = 0; + + for (vector::const_iterator i = types.begin(); i != types.end(); ++i) { + if (*i == N_("general")) { + _types |= GENERAL; + } else if (*i == N_("warning")) { + _types |= WARNING; + } else if (*i == N_("error")) { + _types |= ERROR; + } else if (*i == N_("timing")) { + _types |= TIMING; + } + } } /** @param file Filename to write log to */ diff --git a/src/lib/log.h b/src/lib/log.h index 991532404..641ce186d 100644 --- a/src/lib/log.h +++ b/src/lib/log.h @@ -37,17 +37,16 @@ public: Log (); virtual ~Log () {} - enum Level { - STANDARD = 0, - VERBOSE = 1, - TIMING = 2 - }; + static const int GENERAL; + static const int WARNING; + static const int ERROR; + static const int TIMING; - void log (std::string m, Level l = STANDARD); - void microsecond_log (std::string m, Level l = STANDARD); + void log (std::string message, int type); + void microsecond_log (std::string message, int type); - void set_level (Level l); - void set_level (std::string l); + void set_types (int types); + void set_types (std::string types); protected: /** mutex to protect the log */ @@ -55,9 +54,10 @@ protected: private: virtual void do_log (std::string m) = 0; + void config_changed (); - /** level above which to ignore log messages */ - Level _level; + /** bit-field of log types which should be put into the log (others are ignored) */ + int _types; }; class FileLog : public Log diff --git a/src/lib/player.cc b/src/lib/player.cc index 9f0f380e3..a90350922 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -37,6 +37,8 @@ #include "scaler.h" #include "player_video_frame.h" +#define LOG_GENERAL(...) _film->log()->log (String::compose (__VA_ARGS__), Log::GENERAL); + using std::list; using std::cout; using std::min; @@ -526,7 +528,7 @@ Player::set_video_container_size (libdcp::Size s) _black_frame.reset ( new PlayerVideoFrame ( - shared_ptr (new RawImageProxy (im)), + shared_ptr (new RawImageProxy (im, _film->log ())), Crop(), _video_container_size, _video_container_size, @@ -550,10 +552,8 @@ Player::resampler (shared_ptr c, bool create) return shared_ptr (); } - _film->log()->log ( - String::compose ( - "Creating new resampler for %1 to %2 with %3 channels", c->content_audio_frame_rate(), c->output_audio_frame_rate(), c->audio_channels() - ) + LOG_GENERAL ( + "Creating new resampler for %1 to %2 with %3 channels", c->content_audio_frame_rate(), c->output_audio_frame_rate(), c->audio_channels() ); shared_ptr r (new Resampler (c->content_audio_frame_rate(), c->output_audio_frame_rate(), c->audio_channels())); diff --git a/src/lib/player_video_frame.cc b/src/lib/player_video_frame.cc index c96ed3a33..94760e495 100644 --- a/src/lib/player_video_frame.cc +++ b/src/lib/player_video_frame.cc @@ -50,7 +50,7 @@ PlayerVideoFrame::PlayerVideoFrame ( } -PlayerVideoFrame::PlayerVideoFrame (shared_ptr node, shared_ptr socket) +PlayerVideoFrame::PlayerVideoFrame (shared_ptr node, shared_ptr socket, shared_ptr log) { _crop = Crop (node); @@ -61,7 +61,7 @@ PlayerVideoFrame::PlayerVideoFrame (shared_ptr node, shared_ptrnumber_child ("Part"); _colour_conversion = ColourConversion (node); - _in = image_proxy_factory (node->node_child ("In"), socket); + _in = image_proxy_factory (node->node_child ("In"), socket, log); if (node->optional_number_child ("SubtitleX")) { diff --git a/src/lib/player_video_frame.h b/src/lib/player_video_frame.h index 6461134a9..b085cb609 100644 --- a/src/lib/player_video_frame.h +++ b/src/lib/player_video_frame.h @@ -26,6 +26,7 @@ class Image; class ImageProxy; class Scaler; class Socket; +class Log; /** Everything needed to describe a video frame coming out of the player, but with the * bits still their raw form. We may want to combine the bits on a remote machine, @@ -35,7 +36,7 @@ class PlayerVideoFrame { public: PlayerVideoFrame (boost::shared_ptr, Crop, libdcp::Size, libdcp::Size, Scaler const *, Eyes, Part, ColourConversion); - PlayerVideoFrame (boost::shared_ptr, boost::shared_ptr); + PlayerVideoFrame (boost::shared_ptr, boost::shared_ptr, boost::shared_ptr); void set_subtitle (boost::shared_ptr, Position); diff --git a/src/lib/scp_dcp_job.cc b/src/lib/scp_dcp_job.cc index 0b713b042..30bfc3441 100644 --- a/src/lib/scp_dcp_job.cc +++ b/src/lib/scp_dcp_job.cc @@ -37,6 +37,8 @@ #include "i18n.h" +#define LOG_GENERAL_NC(...) _film->log()->microsecond_log (__VA_ARGS__, Log::GENERAL); + using std::string; using std::stringstream; using std::min; @@ -119,7 +121,7 @@ SCPDCPJob::json_name () const void SCPDCPJob::run () { - _film->log()->log (N_("SCP DCP job starting")); + LOG_GENERAL_NC (N_("SCP DCP job starting")); SSHSession ss; diff --git a/src/lib/server.cc b/src/lib/server.cc index b9bb825ee..c4c98a4c9 100644 --- a/src/lib/server.cc +++ b/src/lib/server.cc @@ -41,6 +41,11 @@ #include "i18n.h" +#define LOG_GENERAL(...) _log->microsecond_log (String::compose (__VA_ARGS__), Log::GENERAL); +#define LOG_GENERAL_NC(...) _log->microsecond_log (__VA_ARGS__, Log::GENERAL); +#define LOG_ERROR(...) _log->microsecond_log (String::compose (__VA_ARGS__), Log::ERROR); +#define LOG_ERROR_NC(...) _log->microsecond_log (__VA_ARGS__, Log::ERROR); + using std::string; using std::stringstream; using std::multimap; @@ -82,11 +87,11 @@ Server::process (shared_ptr socket, struct timeval& after_read, struct t xml->read_stream (s); if (xml->number_child ("Version") != SERVER_LINK_VERSION) { cerr << "Mismatched server/client versions\n"; - _log->log ("Mismatched server/client versions"); + LOG_ERROR_NC ("Mismatched server/client versions"); return -1; } - shared_ptr pvf (new PlayerVideoFrame (xml, socket)); + shared_ptr pvf (new PlayerVideoFrame (xml, socket, _log)); DCPVideoFrame dcp_video_frame (pvf, xml, _log); @@ -99,7 +104,7 @@ Server::process (shared_ptr socket, struct timeval& after_read, struct t try { encoded->send (socket); } catch (std::exception& e) { - _log->log (String::compose ("Send failed; frame %1", dcp_video_frame.index())); + LOG_ERROR ("Send failed; frame %1", dcp_video_frame.index()); throw; } @@ -134,7 +139,7 @@ Server::worker_thread () frame = process (socket, after_read, after_encode); ip = socket->socket().remote_endpoint().address().to_string(); } catch (std::exception& e) { - _log->log (String::compose ("Error: %1", e.what())); + LOG_ERROR ("Error: %1", e.what()); } gettimeofday (&end, 0); @@ -159,7 +164,7 @@ Server::worker_thread () cout << message.str() << "\n"; } - _log->log (message.str ()); + LOG_GENERAL_NC (message.str ()); } _worker_condition.notify_all (); @@ -169,7 +174,7 @@ Server::worker_thread () void Server::run (int num_threads) { - _log->log (String::compose ("Server starting with %1 threads", num_threads)); + LOG_GENERAL ("Server starting with %1 threads", num_threads); if (_verbose) { cout << "DCP-o-matic server starting with " << num_threads << " threads.\n"; } diff --git a/src/lib/transcode_job.cc b/src/lib/transcode_job.cc index 7b304cb35..fb9a59179 100644 --- a/src/lib/transcode_job.cc +++ b/src/lib/transcode_job.cc @@ -30,6 +30,9 @@ #include "i18n.h" +#define LOG_GENERAL_NC(...) _film->log()->microsecond_log (__VA_ARGS__, Log::GENERAL); +#define LOG_ERROR_NC(...) _film->log()->microsecond_log (__VA_ARGS__, Log::ERROR); + using std::string; using std::stringstream; using std::fixed; @@ -61,20 +64,20 @@ TranscodeJob::run () { try { - _film->log()->log (N_("Transcode job starting")); + LOG_GENERAL_NC (N_("Transcode job starting")); _transcoder.reset (new Transcoder (_film, shared_from_this ())); _transcoder->go (); set_progress (1); set_state (FINISHED_OK); - _film->log()->log (N_("Transcode job completed successfully")); + LOG_GENERAL_NC (N_("Transcode job completed successfully")); _transcoder.reset (); } catch (...) { set_progress (1); set_state (FINISHED_ERROR); - _film->log()->log (N_("Transcode job failed or cancelled")); + LOG_ERROR_NC (N_("Transcode job failed or cancelled")); _transcoder.reset (); throw; } diff --git a/src/lib/util.h b/src/lib/util.h index e85abf402..5ca9f74c8 100644 --- a/src/lib/util.h +++ b/src/lib/util.h @@ -40,12 +40,6 @@ extern "C" { #include "types.h" #include "video_content.h" -#ifdef DCPOMATIC_DEBUG -#define TIMING(...) _film->log()->microsecond_log (String::compose (__VA_ARGS__), Log::TIMING); -#else -#define TIMING(...) -#endif - #undef check /** The maximum number of audio channels that we can have in a DCP */ diff --git a/src/lib/writer.cc b/src/lib/writer.cc index 639685149..b058c2801 100644 --- a/src/lib/writer.cc +++ b/src/lib/writer.cc @@ -40,6 +40,10 @@ #include "i18n.h" +#define LOG_GENERAL(...) _film->log()->log (String::compose (__VA_ARGS__), Log::GENERAL); +#define LOG_TIMING(...) _film->log()->microsecond_log (String::compose (__VA_ARGS__), Log::TIMING); +#define LOG_WARNING_NC(...) _film->log()->log (__VA_ARGS__, Log::WARNING); + /* OS X strikes again */ #undef set_key @@ -239,9 +243,9 @@ try break; } - TIMING (N_("writer sleeps with a queue of %1"), _queue.size()); + LOG_TIMING (N_("writer sleeps with a queue of %1"), _queue.size()); _empty_condition.wait (lock); - TIMING (N_("writer wakes with a queue of %1"), _queue.size()); + LOG_TIMING (N_("writer wakes with a queue of %1"), _queue.size()); } if (_finish && _queue.empty()) { @@ -260,7 +264,7 @@ try switch (qi.type) { case QueueItem::FULL: { - _film->log()->log (String::compose (N_("Writer FULL-writes %1 to MXF"), qi.frame)); + LOG_GENERAL (N_("Writer FULL-writes %1 to MXF"), qi.frame); if (!qi.encoded) { qi.encoded.reset (new EncodedData (_film->j2c_path (qi.frame, qi.eyes, false))); } @@ -272,14 +276,14 @@ try break; } case QueueItem::FAKE: - _film->log()->log (String::compose (N_("Writer FAKE-writes %1 to MXF"), qi.frame)); + LOG_GENERAL (N_("Writer FAKE-writes %1 to MXF"), qi.frame); _picture_asset_writer->fake_write (qi.size); _last_written[qi.eyes].reset (); ++_fake_written; break; case QueueItem::REPEAT: { - _film->log()->log (String::compose (N_("Writer REPEAT-writes %1 to MXF"), qi.frame)); + LOG_GENERAL (N_("Writer REPEAT-writes %1 to MXF"), qi.frame); libdcp::FrameInfo fin = _picture_asset_writer->write ( _last_written[qi.eyes]->data(), _last_written[qi.eyes]->size() @@ -328,11 +332,10 @@ try lock.unlock (); - _film->log()->log ( - String::compose ( - "Writer full (awaiting %1 [last eye was %2]); pushes %3 to disk", - _last_written_frame + 1, - _last_written_eyes, qi.frame) + LOG_GENERAL ( + "Writer full (awaiting %1 [last eye was %2]); pushes %3 to disk", + _last_written_frame + 1, + _last_written_eyes, qi.frame ); qi.encoded->write (_film, qi.frame, qi.eyes); @@ -403,7 +406,7 @@ Writer::finish () if (ec) { /* hard link failed; copy instead */ boost::filesystem::copy_file (video_from, video_to); - _film->log()->log ("Hard-link failed; fell back to copying"); + LOG_WARNING_NC ("Hard-link failed; fell back to copying"); } /* And update the asset */ @@ -465,8 +468,8 @@ Writer::finish () meta.set_issue_date_now (); dcp.write_xml (_film->interop (), meta, _film->is_signed() ? make_signer () : shared_ptr ()); - _film->log()->log ( - String::compose (N_("Wrote %1 FULL, %2 FAKE, %3 REPEAT; %4 pushed to disk"), _full_written, _fake_written, _repeat_written, _pushed_to_disk) + LOG_GENERAL ( + N_("Wrote %1 FULL, %2 FAKE, %3 REPEAT; %4 pushed to disk"), _full_written, _fake_written, _repeat_written, _pushed_to_disk ); } @@ -502,14 +505,14 @@ Writer::check_existing_picture_mxf_frame (FILE* mxf, int f, Eyes eyes) /* Read the frame info as written */ FILE* ifi = fopen_boost (_film->info_path (f, eyes), "r"); if (!ifi) { - _film->log()->log (String::compose ("Existing frame %1 has no info file", f)); + LOG_GENERAL ("Existing frame %1 has no info file", f); return false; } libdcp::FrameInfo info (ifi); fclose (ifi); if (info.size == 0) { - _film->log()->log (String::compose ("Existing frame %1 has no info file", f)); + LOG_GENERAL ("Existing frame %1 has no info file", f); return false; } @@ -518,13 +521,13 @@ Writer::check_existing_picture_mxf_frame (FILE* mxf, int f, Eyes eyes) EncodedData data (info.size); size_t const read = fread (data.data(), 1, data.size(), mxf); if (read != static_cast (data.size ())) { - _film->log()->log (String::compose ("Existing frame %1 is incomplete", f)); + LOG_GENERAL ("Existing frame %1 is incomplete", f); return false; } string const existing_hash = md5_digest (data.data(), data.size()); if (existing_hash != info.hash) { - _film->log()->log (String::compose ("Existing frame %1 failed hash check", f)); + LOG_GENERAL ("Existing frame %1 failed hash check", f); return false; } @@ -540,7 +543,7 @@ Writer::check_existing_picture_mxf () p /= _film->internal_video_mxf_filename (); FILE* mxf = fopen_boost (p, "rb"); if (!mxf) { - _film->log()->log (String::compose ("Could not open existing MXF at %1 (errno=%2)", p.string(), errno)); + LOG_GENERAL ("Could not open existing MXF at %1 (errno=%2)", p.string(), errno); return; } @@ -571,7 +574,7 @@ Writer::check_existing_picture_mxf () } } - _film->log()->log (String::compose ("Have existing frame %1", _first_nonexistant_frame)); + LOG_GENERAL ("Have existing frame %1", _first_nonexistant_frame); ++_first_nonexistant_frame; } diff --git a/src/tools/dcpomatic.cc b/src/tools/dcpomatic.cc index 28074a4ba..d092992a1 100644 --- a/src/tools/dcpomatic.cc +++ b/src/tools/dcpomatic.cc @@ -74,7 +74,7 @@ using boost::dynamic_pointer_cast; static FilmEditor* film_editor = 0; static FilmViewer* film_viewer = 0; static shared_ptr film; -static std::string log_level; +static std::string log_types = "general,log,warning"; static std::string film_to_load; static std::string film_to_create; static std::string content_to_add; @@ -157,7 +157,7 @@ load_film (boost::filesystem::path file) for (list::const_iterator i = notes.begin(); i != notes.end(); ++i) { error_dialog (0, std_to_wx (*i)); } - film->log()->set_level (log_level); + film->log()->set_types (log_types); } #define ALWAYS 0x0 @@ -401,7 +401,7 @@ private: maybe_save_then_delete_film (); film.reset (new Film (d->get_path ())); film->write_metadata (); - film->log()->set_level (log_level); + film->log()->set_types (log_types); film->set_name (boost::filesystem::path (d->get_path()).filename().generic_string()); set_film (); } @@ -609,7 +609,7 @@ private: }; static const wxCmdLineEntryDesc command_line_description[] = { - { wxCMD_LINE_OPTION, "l", "log", "set log level (silent, verbose or timing)", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, + { wxCMD_LINE_OPTION, "l", "log", "set message types to log (general,warning,error,timing)", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, { wxCMD_LINE_SWITCH, "n", "new", "create new film", wxCMD_LINE_VAL_NONE, wxCMD_LINE_PARAM_OPTIONAL }, { wxCMD_LINE_OPTION, "c", "content", "add content file", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, { wxCMD_LINE_PARAM, 0, 0, "film to load or create", wxCMD_LINE_VAL_STRING, wxCMD_LINE_PARAM_OPTIONAL }, @@ -668,7 +668,7 @@ class App : public wxApp if (!film_to_create.empty ()) { film.reset (new Film (film_to_create)); film->write_metadata (); - film->log()->set_level (log_level); + film->log()->set_types (log_types); film->set_name (boost::filesystem::path (film_to_create).filename().generic_string ()); } @@ -728,7 +728,7 @@ class App : public wxApp wxString log; if (parser.Found (wxT ("log"), &log)) { - log_level = wx_to_std (log); + log_types = wx_to_std (log); } return true; diff --git a/src/tools/dcpomatic_cli.cc b/src/tools/dcpomatic_cli.cc index a74ece149..73067f406 100644 --- a/src/tools/dcpomatic_cli.cc +++ b/src/tools/dcpomatic_cli.cc @@ -65,7 +65,7 @@ main (int argc, char* argv[]) string film_dir; bool progress = true; bool no_remote = false; - int log_level = 0; + string log_types = "general,warning,error"; int json_port = 0; bool keep_going = false; @@ -78,7 +78,7 @@ main (int argc, char* argv[]) { "flags", no_argument, 0, 'f'}, { "no-progress", no_argument, 0, 'n'}, { "no-remote", no_argument, 0, 'r'}, - { "log-level", required_argument, 0, 'l' }, + { "log-types", required_argument, 0, 'l' }, { "json", required_argument, 0, 'j' }, { "keep-going", no_argument, 0, 'k' }, { 0, 0, 0, 0 } @@ -110,7 +110,7 @@ main (int argc, char* argv[]) no_remote = true; break; case 'l': - log_level = atoi (optarg); + log_types = optarg; break; case 'j': json_port = atoi (optarg); @@ -155,7 +155,7 @@ main (int argc, char* argv[]) exit (EXIT_FAILURE); } - film->log()->set_level ((Log::Level) log_level); + film->log()->set_types (log_types); cout << "\nMaking DCP for " << film->name() << "\n"; // cout << "Content: " << film->content() << "\n"; diff --git a/src/wx/config_dialog.cc b/src/wx/config_dialog.cc index e27b79172..109ff9f87 100644 --- a/src/wx/config_dialog.cc +++ b/src/wx/config_dialog.cc @@ -106,14 +106,6 @@ public: _num_local_encoding_threads = new wxSpinCtrl (panel); table->Add (_num_local_encoding_threads, 1); - add_label_to_sizer (table, panel, _("Maximum JPEG2000 bandwidth"), true); - _maximum_j2k_bandwidth = new wxSpinCtrl (panel); - table->Add (_maximum_j2k_bandwidth, 1); - - _allow_any_dcp_frame_rate = new wxCheckBox (panel, wxID_ANY, _("Allow any DCP frame rate")); - table->Add (_allow_any_dcp_frame_rate, 1, wxEXPAND | wxALL); - table->AddSpacer (0); - add_label_to_sizer (table, panel, _("Outgoing mail server"), true); _mail_server = new wxTextCtrl (panel, wxID_ANY); table->Add (_mail_server, 1, wxEXPAND | wxALL); @@ -171,10 +163,6 @@ public: _num_local_encoding_threads->SetValue (config->num_local_encoding_threads ()); _num_local_encoding_threads->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&GeneralPage::num_local_encoding_threads_changed, this)); - _maximum_j2k_bandwidth->SetRange (1, 500); - _maximum_j2k_bandwidth->SetValue (config->maximum_j2k_bandwidth() / 1000000); - _maximum_j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&GeneralPage::maximum_j2k_bandwidth_changed, this)); - _mail_server->SetValue (std_to_wx (config->mail_server ())); _mail_server->Bind (wxEVT_COMMAND_TEXT_UPDATED, boost::bind (&GeneralPage::mail_server_changed, this)); _mail_user->SetValue (std_to_wx (config->mail_user ())); @@ -187,8 +175,6 @@ public: _check_for_updates->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::check_for_updates_changed, this)); _check_for_test_updates->SetValue (config->check_for_test_updates ()); _check_for_test_updates->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::check_for_test_updates_changed, this)); - _allow_any_dcp_frame_rate->SetValue (config->allow_any_dcp_frame_rate ()); - _allow_any_dcp_frame_rate->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&GeneralPage::allow_any_dcp_frame_rate_changed, this)); return panel; } @@ -271,21 +257,9 @@ private: Config::instance()->set_num_local_encoding_threads (_num_local_encoding_threads->GetValue ()); } - void maximum_j2k_bandwidth_changed () - { - Config::instance()->set_maximum_j2k_bandwidth (_maximum_j2k_bandwidth->GetValue() * 1000000); - } - - void allow_any_dcp_frame_rate_changed () - { - Config::instance()->set_allow_any_dcp_frame_rate (_allow_any_dcp_frame_rate->GetValue ()); - } - wxCheckBox* _set_language; wxChoice* _language; wxSpinCtrl* _num_local_encoding_threads; - wxSpinCtrl* _maximum_j2k_bandwidth; - wxCheckBox* _allow_any_dcp_frame_rate; wxTextCtrl* _mail_server; wxTextCtrl* _mail_user; wxTextCtrl* _mail_password; @@ -742,6 +716,104 @@ private: wxTextCtrl* _kdm_email; }; +class AdvancedPage : public wxStockPreferencesPage, public Page +{ +public: + + AdvancedPage (wxSize panel_size, int border) + : wxStockPreferencesPage (Kind_Advanced) + , Page (panel_size, border) + {} + + wxWindow* CreateWindow (wxWindow* parent) + { + wxPanel* panel = new wxPanel (parent); + + wxBoxSizer* s = new wxBoxSizer (wxVERTICAL); + panel->SetSizer (s); + + wxFlexGridSizer* table = new wxFlexGridSizer (2, DCPOMATIC_SIZER_X_GAP, DCPOMATIC_SIZER_Y_GAP); + table->AddGrowableCol (1, 1); + s->Add (table, 1, wxALL | wxEXPAND, _border); + + add_label_to_sizer (table, panel, _("Maximum JPEG2000 bandwidth"), true); + _maximum_j2k_bandwidth = new wxSpinCtrl (panel); + table->Add (_maximum_j2k_bandwidth, 1); + + _allow_any_dcp_frame_rate = new wxCheckBox (panel, wxID_ANY, _("Allow any DCP frame rate")); + table->Add (_allow_any_dcp_frame_rate, 1, wxEXPAND | wxALL); + table->AddSpacer (0); + + add_label_to_sizer (table, panel, _("Log"), true); + _log_general = new wxCheckBox (panel, wxID_ANY, _("General")); + table->Add (_log_general, 1, wxEXPAND | wxALL); + _log_warning = new wxCheckBox (panel, wxID_ANY, _("Warnings")); + table->AddSpacer (0); + table->Add (_log_warning, 1, wxEXPAND | wxALL); + _log_error = new wxCheckBox (panel, wxID_ANY, _("Errors")); + table->AddSpacer (0); + table->Add (_log_error, 1, wxEXPAND | wxALL); + _log_timing = new wxCheckBox (panel, wxID_ANY, _("Timing")); + table->AddSpacer (0); + table->Add (_log_timing, 1, wxEXPAND | wxALL); + + Config* config = Config::instance (); + + _maximum_j2k_bandwidth->SetRange (1, 500); + _maximum_j2k_bandwidth->SetValue (config->maximum_j2k_bandwidth() / 1000000); + _maximum_j2k_bandwidth->Bind (wxEVT_COMMAND_SPINCTRL_UPDATED, boost::bind (&AdvancedPage::maximum_j2k_bandwidth_changed, this)); + _allow_any_dcp_frame_rate->SetValue (config->allow_any_dcp_frame_rate ()); + _allow_any_dcp_frame_rate->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::allow_any_dcp_frame_rate_changed, this)); + _log_general->SetValue (config->log_types() & Log::GENERAL); + _log_general->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this)); + _log_warning->SetValue (config->log_types() & Log::WARNING); + _log_warning->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this)); + _log_error->SetValue (config->log_types() & Log::ERROR); + _log_error->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this)); + _log_timing->SetValue (config->log_types() & Log::TIMING); + _log_timing->Bind (wxEVT_COMMAND_CHECKBOX_CLICKED, boost::bind (&AdvancedPage::log_changed, this)); + + return panel; + } + +private: + + void maximum_j2k_bandwidth_changed () + { + Config::instance()->set_maximum_j2k_bandwidth (_maximum_j2k_bandwidth->GetValue() * 1000000); + } + + void allow_any_dcp_frame_rate_changed () + { + Config::instance()->set_allow_any_dcp_frame_rate (_allow_any_dcp_frame_rate->GetValue ()); + } + + void log_changed () + { + int types = 0; + if (_log_general->GetValue ()) { + types |= Log::GENERAL; + } + if (_log_warning->GetValue ()) { + types |= Log::WARNING; + } + if (_log_error->GetValue ()) { + types |= Log::ERROR; + } + if (_log_timing->GetValue ()) { + types |= Log::TIMING; + } + Config::instance()->set_log_types (types); + } + + wxSpinCtrl* _maximum_j2k_bandwidth; + wxCheckBox* _allow_any_dcp_frame_rate; + wxCheckBox* _log_general; + wxCheckBox* _log_warning; + wxCheckBox* _log_error; + wxCheckBox* _log_timing; +}; + wxPreferencesEditor* create_config_dialog () { @@ -768,5 +840,6 @@ create_config_dialog () e->AddPage (new ColourConversionsPage (ps, border)); e->AddPage (new TMSPage (ps, border)); e->AddPage (new KDMEmailPage (ps, border)); + e->AddPage (new AdvancedPage (ps, border)); return e; } diff --git a/test/client_server_test.cc b/test/client_server_test.cc index c8a2b49ef..98993cc5b 100644 --- a/test/client_server_test.cc +++ b/test/client_server_test.cc @@ -70,9 +70,11 @@ BOOST_AUTO_TEST_CASE (client_server_test) p += sub_image->stride()[0]; } + shared_ptr log (new FileLog ("build/test/client_server_test.log")); + shared_ptr pvf ( new PlayerVideoFrame ( - shared_ptr (new RawImageProxy (image)), + shared_ptr (new RawImageProxy (image, log)), Crop (), libdcp::Size (1998, 1080), libdcp::Size (1998, 1080), @@ -85,8 +87,6 @@ BOOST_AUTO_TEST_CASE (client_server_test) pvf->set_subtitle (sub_image, Position (50, 60)); - shared_ptr log (new FileLog ("build/test/client_server_test.log")); - shared_ptr frame ( new DCPVideoFrame ( pvf, -- 2.30.2