BOOST_FOREACH.
[dcpomatic.git] / src / lib / hints.cc
index 23d5a15fb128caaa086b4fc32523dd5b8ce2ac3b..ca697ad74a8fc8abbaebe3b17521463b4ab1f68c 100644 (file)
 #include "text_content.h"
 #include "audio_processor.h"
 #include "font.h"
+#include "font_data.h"
 #include "ratio.h"
 #include "audio_analysis.h"
 #include "compose.hpp"
 #include "util.h"
 #include "cross.h"
 #include "player.h"
+#include "writer.h"
+#include <dcp/cpl.h>
 #include <dcp/raw_convert.h>
-#include <boost/foreach.hpp>
+#include <dcp/reel.h>
+#include <dcp/reel_closed_caption_asset.h>
+#include <dcp/reel_subtitle_asset.h>
 #include <boost/algorithm/string.hpp>
 #include <iostream>
 
@@ -46,8 +51,8 @@ using std::pair;
 using std::min;
 using std::max;
 using std::cout;
-using boost::shared_ptr;
-using boost::weak_ptr;
+using std::shared_ptr;
+using std::weak_ptr;
 using boost::optional;
 using boost::bind;
 using namespace dcpomatic;
@@ -55,8 +60,16 @@ using namespace dcpomatic;
 using namespace boost::placeholders;
 #endif
 
+
+/* When checking to see if things are too big, we'll say they are if they
+ * are more than the target size minus this "slack."
+ */
+#define SIZE_SLACK 4096
+
+
 Hints::Hints (weak_ptr<const Film> film)
-       : _film (film)
+       : WeakConstFilm (film)
+       , _writer (new Writer(film, weak_ptr<Job>(), true))
        , _long_ccap (false)
        , _overlap_ccap (false)
        , _too_many_ccap_lines (false)
@@ -112,7 +125,7 @@ Hints::check_incorrect_container ()
 {
        int narrower_than_scope = 0;
        int scope = 0;
-       BOOST_FOREACH (shared_ptr<const Content> i, film()->content()) {
+       for (auto i: film()->content()) {
                if (i->video) {
                        Ratio const * r = Ratio::nearest_from_ratio(i->video->scaled_size(film()->frame_size()).ratio());
                        if (r && r->id() == "239") {
@@ -192,7 +205,7 @@ Hints::check_speed_up ()
 {
        optional<double> lowest_speed_up;
        optional<double> highest_speed_up;
-       BOOST_FOREACH (shared_ptr<const Content> i, film()->content()) {
+       for (auto i: film()->content()) {
                double spu = film()->active_frame_rate_change(i->position()).speed_up;
                if (!lowest_speed_up || spu < *lowest_speed_up) {
                        lowest_speed_up = spu;
@@ -222,11 +235,11 @@ Hints::check_big_font_files ()
 {
        bool big_font_files = false;
        if (film()->interop ()) {
-               BOOST_FOREACH (shared_ptr<Content> i, film()->content()) {
-                       BOOST_FOREACH (shared_ptr<TextContent> j, i->text) {
-                               BOOST_FOREACH (shared_ptr<Font> k, j->fonts()) {
+               for (auto i: film()->content()) {
+                       for (auto j: i->text) {
+                               for (auto k: j->fonts()) {
                                        optional<boost::filesystem::path> const p = k->file ();
-                                       if (p && boost::filesystem::file_size(p.get()) >= (640 * 1024)) {
+                                       if (p && boost::filesystem::file_size(p.get()) >= (MAX_FONT_FILE_SIZE - SIZE_SLACK)) {
                                                big_font_files = true;
                                        }
                                }
@@ -244,7 +257,7 @@ void
 Hints::check_vob ()
 {
        int vob = 0;
-       BOOST_FOREACH (shared_ptr<const Content> i, film()->content()) {
+       for (auto i: film()->content()) {
                if (boost::algorithm::starts_with (i->path(0).filename().string(), "VTS_")) {
                        ++vob;
                }
@@ -260,7 +273,7 @@ void
 Hints::check_3d_in_2d ()
 {
        int three_d = 0;
-       BOOST_FOREACH (shared_ptr<const Content> i, film()->content()) {
+       for (auto i: film()->content()) {
                if (i->video && i->video->frame_type() != VIDEO_FRAME_TYPE_2D) {
                        ++three_d;
                }
@@ -311,6 +324,14 @@ Hints::check_loudness ()
 }
 
 
+static
+bool
+subtitle_mxf_too_big (shared_ptr<dcp::SubtitleAsset> asset)
+{
+       return asset && asset->file() && boost::filesystem::file_size(*asset->file()) >= (MAX_TEXT_MXF_SIZE - SIZE_SLACK);
+}
+
+
 void
 Hints::thread ()
 {
@@ -339,7 +360,7 @@ Hints::thread ()
        shared_ptr<Player> player (new Player(film));
        player->set_ignore_video ();
        player->set_ignore_audio ();
-       player->Text.connect (bind(&Hints::text, this, _1, _2, _4));
+       player->Text.connect (bind(&Hints::text, this, _1, _2, _3, _4));
 
        struct timeval last_pulse;
        gettimeofday (&last_pulse, 0);
@@ -361,6 +382,53 @@ Hints::thread ()
                store_current ();
        }
 
+       _writer->write (player->get_subtitle_fonts());
+
+       bool ccap_xml_too_big = false;
+       bool ccap_mxf_too_big = false;
+       bool subs_mxf_too_big = false;
+
+       boost::filesystem::path dcp_dir = film->dir("hints") / dcpomatic::get_process_id();
+       boost::filesystem::remove_all (dcp_dir);
+
+       try {
+               _writer->finish (film->dir("hints") / dcpomatic::get_process_id());
+       } catch (...) {
+               store_current ();
+               emit (bind(boost::ref(Finished)));
+               return;
+       }
+
+       dcp::DCP dcp (dcp_dir);
+       dcp.read ();
+       DCPOMATIC_ASSERT (dcp.cpls().size() == 1);
+       for (auto reel: dcp.cpls().front()->reels()) {
+               for (auto ccap: reel->closed_captions()) {
+                       if (ccap->asset() && ccap->asset()->xml_as_string().length() > static_cast<size_t>(MAX_CLOSED_CAPTION_XML_SIZE - SIZE_SLACK) && !ccap_xml_too_big) {
+                               hint (_(
+                                               "At least one of your closed caption files' XML part is larger than " MAX_CLOSED_CAPTION_XML_SIZE_TEXT
+                                               ".  You should divide the DCP into shorter reels."
+                                      ));
+                               ccap_xml_too_big = true;
+                       }
+                       if (subtitle_mxf_too_big(ccap->asset()) && !ccap_mxf_too_big) {
+                               hint (_(
+                                               "At least one of your closed caption files is larger than " MAX_TEXT_MXF_SIZE_TEXT
+                                               " in total.  You should divide the DCP into shorter reels."
+                                      ));
+                               ccap_mxf_too_big = true;
+                       }
+               }
+               if (reel->main_subtitle() && subtitle_mxf_too_big(reel->main_subtitle()->asset()) && !subs_mxf_too_big) {
+                       hint (_(
+                                       "At least one of your subtitle files is larger than " MAX_TEXT_MXF_SIZE_TEXT " in total.  "
+                                       "You should divide the DCP into shorter reels."
+                              ));
+                       subs_mxf_too_big = true;
+               }
+       }
+       boost::filesystem::remove_all (dcp_dir);
+
        emit (bind(boost::ref(Finished)));
 }
 
@@ -371,8 +439,10 @@ Hints::hint (string h)
 }
 
 void
-Hints::text (PlayerText text, TextType type, DCPTimePeriod period)
+Hints::text (PlayerText text, TextType type, optional<DCPTextTrack> track, DCPTimePeriod period)
 {
+       _writer->write (text, type, track, period);
+
        switch (type) {
        case TEXT_CLOSED_CAPTION:
                closed_caption (text, period);
@@ -390,7 +460,7 @@ void
 Hints::closed_caption (PlayerText text, DCPTimePeriod period)
 {
        int lines = text.string.size();
-       BOOST_FOREACH (StringText i, text.string) {
+       for (auto i: text.string) {
                if (utf8_strlen(i.text()) > MAX_CLOSED_CAPTION_LENGTH) {
                        ++lines;
                        if (!_long_ccap) {
@@ -447,7 +517,7 @@ Hints::open_subtitle (PlayerText text, DCPTimePeriod period)
        }
 
        size_t longest_line = 0;
-       BOOST_FOREACH (StringText const& i, text.string) {
+       for (auto const& i: text.string) {
                longest_line = max (longest_line, i.text().length());
        }
 
@@ -460,15 +530,6 @@ Hints::open_subtitle (PlayerText text, DCPTimePeriod period)
 }
 
 
-shared_ptr<const Film>
-Hints::film () const
-{
-       shared_ptr<const Film> film = _film.lock ();
-       DCPOMATIC_ASSERT (film);
-       return film;
-}
-
-
 void
 Hints::check_ffec_and_ffmc_in_smpte_feature ()
 {