From: Carl Hetherington Date: Thu, 26 Jul 2018 16:58:06 +0000 (+0100) Subject: Background-threaded hints including line length of CCAPs. X-Git-Tag: v2.13.41~13^2~2 X-Git-Url: https://git.carlh.net/gitweb/?p=dcpomatic.git;a=commitdiff_plain;h=c8b10d5eac6006b62d2a7add9da0c6206b72899b Background-threaded hints including line length of CCAPs. --- diff --git a/src/lib/hints.cc b/src/lib/hints.cc index 31b2ad849..77b10da15 100644 --- a/src/lib/hints.cc +++ b/src/lib/hints.cc @@ -30,6 +30,8 @@ #include "audio_analysis.h" #include "compose.hpp" #include "util.h" +#include "cross.h" +#include "player.h" #include #include #include @@ -44,12 +46,54 @@ using std::min; using std::max; using std::cout; using boost::shared_ptr; +using boost::weak_ptr; using boost::optional; +using boost::bind; -vector -get_hints (shared_ptr film) +Hints::Hints (weak_ptr film) + : _film (film) + , _thread (0) + , _long_ccap (false) { - vector hints; + +} + +void +Hints::stop_thread () +{ + if (_thread) { + try { + _thread->interrupt (); + _thread->join (); + } catch (...) { + + } + + delete _thread; + _thread = 0; + } +} + +Hints::~Hints () +{ + stop_thread (); +} + +void +Hints::start () +{ + stop_thread (); + _long_ccap = false; + _thread = new boost::thread (bind(&Hints::thread, this)); +} + +void +Hints::thread () +{ + shared_ptr film = _film.lock (); + if (!film) { + return; + } ContentList content = film->content (); @@ -70,16 +114,16 @@ get_hints (shared_ptr film) } if (big_font_files) { - hints.push_back (_("You have specified a font file which is larger than 640kB. This is very likely to cause problems on playback.")); + hint (_("You have specified a font file which is larger than 640kB. This is very likely to cause problems on playback.")); } if (film->audio_channels() < 6) { - hints.push_back (_("Your DCP has fewer than 6 audio channels. This may cause problems on some projectors.")); + hint (_("Your DCP has fewer than 6 audio channels. This may cause problems on some projectors.")); } AudioProcessor const * ap = film->audio_processor(); if (ap && (ap->id() == "stereo-5.1-upmix-a" || ap->id() == "stereo-5.1-upmix-b")) { - hints.push_back (_("You are using DCP-o-matic's stereo-to-5.1 upmixer. This is experimental and may result in poor-quality audio. If you continue, you should listen to the resulting DCP in a cinema to make sure that it sounds good.")); + hint (_("You are using DCP-o-matic's stereo-to-5.1 upmixer. This is experimental and may result in poor-quality audio. If you continue, you should listen to the resulting DCP in a cinema to make sure that it sounds good.")); } int flat_or_narrower = 0; @@ -98,19 +142,19 @@ get_hints (shared_ptr film) string const film_container = film->container()->id(); if (scope && !flat_or_narrower && film_container == "185") { - hints.push_back (_("All of your content is in Scope (2.39:1) but your DCP's container is Flat (1.85:1). This will letter-box your content inside a Flat (1.85:1) frame. You may prefer to set your DCP's container to Scope (2.39:1) in the \"DCP\" tab.")); + hint (_("All of your content is in Scope (2.39:1) but your DCP's container is Flat (1.85:1). This will letter-box your content inside a Flat (1.85:1) frame. You may prefer to set your DCP's container to Scope (2.39:1) in the \"DCP\" tab.")); } if (!scope && flat_or_narrower && film_container == "239") { - hints.push_back (_("All of your content is at 1.85:1 or narrower but your DCP's container is Scope (2.39:1). This will pillar-box your content inside a Flat (1.85:1) frame. You may prefer to set your DCP's container to Flat (1.85:1) in the \"DCP\" tab.")); + hint (_("All of your content is at 1.85:1 or narrower but your DCP's container is Scope (2.39:1). This will pillar-box your content inside a Flat (1.85:1) frame. You may prefer to set your DCP's container to Flat (1.85:1) in the \"DCP\" tab.")); } if (film_container != "185" && film_container != "239" && film_container != "190") { - hints.push_back (_("Your DCP uses an unusual container ratio. This may cause problems on some projectors. If possible, use Flat or Scope for the DCP container ratio")); + hint (_("Your DCP uses an unusual container ratio. This may cause problems on some projectors. If possible, use Flat or Scope for the DCP container ratio")); } if (film->j2k_bandwidth() >= 245000000) { - hints.push_back (_("A few projectors have problems playing back very high bit-rate DCPs. It is a good idea to drop the JPEG2000 bandwidth down to about 200Mbit/s; this is unlikely to have any visible effect on the image.")); + hint (_("A few projectors have problems playing back very high bit-rate DCPs. It is a good idea to drop the JPEG2000 bandwidth down to about 200Mbit/s; this is unlikely to have any visible effect on the image.")); } if (film->interop() && film->video_frame_rate() != 24 && film->video_frame_rate() != 48) { @@ -130,7 +174,7 @@ get_hints (shared_ptr film) h = _("You are set up for an Interop DCP at a frame rate which is not officially supported. You are advised either to change the frame rate of your DCP or to make a SMPTE DCP instead (although SMPTE DCPs are not supported by all projectors)."); } - hints.push_back (h); + hint (h); } optional lowest_speed_up; @@ -154,7 +198,7 @@ get_hints (shared_ptr film) } if (worst_speed_up > 25.5/24.0) { - hints.push_back (_("There is a large difference between the frame rate of your DCP and that of some of your content. This will cause your audio to play back at a much lower or higher pitch than it should. You are advised to set your DCP frame rate to one closer to your content, provided that your target projection systems support your chosen DCP rate.")); + hint (_("There is a large difference between the frame rate of your DCP and that of some of your content. This will cause your audio to play back at a much lower or higher pitch than it should. You are advised to set your DCP frame rate to one closer to your content, provided that your target projection systems support your chosen DCP rate.")); } int vob = 0; @@ -165,7 +209,7 @@ get_hints (shared_ptr film) } if (vob > 1) { - hints.push_back (String::compose (_("You have %1 files that look like they are VOB files from DVD. You should join them to ensure smooth joins between the files."), vob)); + hint (String::compose (_("You have %1 files that look like they are VOB files from DVD. You should join them to ensure smooth joins between the files."), vob)); } int three_d = 0; @@ -176,7 +220,7 @@ get_hints (shared_ptr film) } if (three_d > 0 && !film->three_d()) { - hints.push_back (_("You are using 3D content but your DCP is set to 2D. Set the DCP to 3D if you want to play it back on a 3D system (e.g. Real-D, MasterImage etc.)")); + hint (_("You are using 3D content but your DCP is set to 2D. Set the DCP to 3D if you want to play it back on a 3D system (e.g. Real-D, MasterImage etc.)")); } boost::filesystem::path path = film->audio_analysis_path (film->playlist ()); @@ -200,11 +244,10 @@ get_hints (shared_ptr film) ch = ch.substr (0, ch.length() - 2); if (!ch.empty ()) { - hints.push_back ( - String::compose ( - _("Your audio level is very high (on %1). You should reduce the gain of your audio content."), - ch - ) + hint (String::compose ( + _("Your audio level is very high (on %1). You should reduce the gain of your audio content."), + ch + ) ); } } catch (OldFormatError& e) { @@ -214,5 +257,36 @@ get_hints (shared_ptr film) } } - return hints; + emit (bind(boost::ref(Progress), _("Examining closed captions"))); + + shared_ptr player (new Player (film, film->playlist ())); + player->set_ignore_video (); + player->set_ignore_audio (); + player->Text.connect (bind(&Hints::text, this, _1, _2, _3)); + while (!player->pass ()) { + bind (boost::ref(Pulse)); + } + + emit (bind(boost::ref(Finished))); +} + +void +Hints::hint (string h) +{ + emit(bind(boost::ref(Hint), h)); +} + +void +Hints::text (PlayerText text, TextType type, DCPTimePeriod period) +{ + if (type != TEXT_CLOSED_CAPTION) { + return; + } + + BOOST_FOREACH (StringText i, text.text) { + if (!_long_ccap && i.text().length() > 30) { + _long_ccap = true; + hint (_("Some of your closed captions have lines longer than 30 characters, so they will probably be word-wrapped.")); + } + } } diff --git a/src/lib/hints.h b/src/lib/hints.h index 3a6850860..ad66fb472 100644 --- a/src/lib/hints.h +++ b/src/lib/hints.h @@ -18,10 +18,38 @@ */ -#include +#include "signaller.h" +#include "player_text.h" +#include "types.h" +#include "dcpomatic_time.h" +#include +#include #include #include class Film; -std::vector get_hints (boost::shared_ptr film); +class Hints : public Signaller +{ +public: + Hints (boost::weak_ptr film); + ~Hints (); + + void start (); + + boost::signals2::signal Hint; + boost::signals2::signal Progress; + boost::signals2::signal Pulse; + boost::signals2::signal Finished; + +private: + void thread (); + void stop_thread (); + void hint (std::string h); + void text (PlayerText text, TextType type, DCPTimePeriod period); + + boost::weak_ptr _film; + boost::thread* _thread; + + bool _long_ccap; +}; diff --git a/src/tools/dcpomatic.cc b/src/tools/dcpomatic.cc index a97e12b69..6972b35c4 100644 --- a/src/tools/dcpomatic.cc +++ b/src/tools/dcpomatic.cc @@ -636,7 +636,7 @@ private: } } - if (!get_hints(_film).empty() && Config::instance()->show_hints_before_make_dcp()) { + if (Config::instance()->show_hints_before_make_dcp()) { HintsDialog* hints = new HintsDialog (this, _film, false); int const r = hints->ShowModal(); hints->Destroy (); @@ -735,7 +735,7 @@ private: return; } - if (!get_hints(_film).empty() && Config::instance()->show_hints_before_make_dcp()) { + if (Config::instance()->show_hints_before_make_dcp()) { HintsDialog* hints = new HintsDialog (this, _film, false); int const r = hints->ShowModal(); hints->Destroy (); diff --git a/src/wx/hints_dialog.cc b/src/wx/hints_dialog.cc index 86a160213..1938e7cc4 100644 --- a/src/wx/hints_dialog.cc +++ b/src/wx/hints_dialog.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2016 Carl Hetherington + Copyright (C) 2012-2018 Carl Hetherington This file is part of DCP-o-matic. @@ -29,15 +29,24 @@ using std::max; using std::vector; using std::string; +using std::cout; using boost::shared_ptr; using boost::optional; +using boost::bind; using boost::dynamic_pointer_cast; HintsDialog::HintsDialog (wxWindow* parent, boost::weak_ptr film, bool ok) : wxDialog (parent, wxID_ANY, _("Hints")) , _film (film) + , _hints (new Hints (film)) { wxBoxSizer* sizer = new wxBoxSizer (wxVERTICAL); + + _gauge = new wxGauge (this, wxID_ANY, 100); + sizer->Add (_gauge, 0, wxALL | wxEXPAND, DCPOMATIC_SIZER_GAP); + _gauge_message = new wxStaticText (this, wxID_ANY, wxT("")); + sizer->Add (_gauge_message, 0, wxALL | wxEXPAND, DCPOMATIC_SIZER_GAP); + _text = new wxRichTextCtrl (this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize (400, 300), wxRE_READONLY); sizer->Add (_text, 1, wxEXPAND | wxALL, 6); @@ -70,6 +79,11 @@ HintsDialog::HintsDialog (wxWindow* parent, boost::weak_ptr film, bool ok) _film_content_changed_connection = locked_film->ContentChanged.connect (boost::bind (&HintsDialog::film_changed, this)); } + _hints->Hint.connect (bind (&HintsDialog::hint, this, _1)); + _hints->Progress.connect (bind (&HintsDialog::progress, this, _1)); + _hints->Pulse.connect (bind (&HintsDialog::pulse, this)); + _hints->Finished.connect (bind (&HintsDialog::finished, this)); + film_changed (); } @@ -77,19 +91,30 @@ void HintsDialog::film_changed () { _text->Clear (); + _current.clear (); boost::shared_ptr film = _film.lock (); if (!film) { return; } - vector hints = get_hints (film); + _gauge->Show (); + _gauge_message->Show (); + Layout (); + _gauge->SetValue (0); + update (); + _hints->start (); +} - if (hints.empty ()) { +void +HintsDialog::update () +{ + _text->Clear (); + if (_current.empty ()) { _text->WriteText (_("There are no hints: everything looks good!")); } else { _text->BeginStandardBullet (N_("standard/circle"), 1, 50); - BOOST_FOREACH (string i, hints) { + BOOST_FOREACH (string i, _current) { _text->WriteText (std_to_wx (i)); _text->Newline (); } @@ -97,8 +122,35 @@ HintsDialog::film_changed () } } +void +HintsDialog::hint (string text) +{ + _current.push_back (text); + update (); +} + void HintsDialog::shut_up (wxCommandEvent& ev) { Config::instance()->set_show_hints_before_make_dcp (!ev.IsChecked()); } + +void +HintsDialog::pulse () +{ + _gauge->Pulse (); +} + +void +HintsDialog::finished () +{ + _gauge->Hide (); + _gauge_message->Hide (); + Layout (); +} + +void +HintsDialog::progress (string m) +{ + _gauge_message->SetLabel (std_to_wx(m)); +} diff --git a/src/wx/hints_dialog.h b/src/wx/hints_dialog.h index c02cc8c85..06f979a74 100644 --- a/src/wx/hints_dialog.h +++ b/src/wx/hints_dialog.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2015 Carl Hetherington + Copyright (C) 2012-2018 Carl Hetherington This file is part of DCP-o-matic. @@ -24,6 +24,7 @@ class wxRichTextCtrl; class Film; +class Hints; class HintsDialog : public wxDialog { @@ -33,9 +34,18 @@ public: private: void film_changed (); void shut_up (wxCommandEvent& ev); + void update (); + void hint (std::string text); + void pulse (); + void finished (); + void progress (std::string m); boost::weak_ptr _film; + wxGauge* _gauge; + wxStaticText* _gauge_message; wxRichTextCtrl* _text; + boost::shared_ptr _hints; + std::list _current; boost::signals2::scoped_connection _film_changed_connection; boost::signals2::scoped_connection _film_content_changed_connection;