X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fdcp_content.cc;h=e43d88a3472b2050f139c784c742611ee94d7419;hb=a5d004b0773f633401528392fc28e66d70e13ac8;hp=d2c1df748ddc5d3dbf529a0f3ea4f7147f4d42a1;hpb=ca981c8cfa23111e92be329f1c2dfbe3a07b4247;p=dcpomatic.git diff --git a/src/lib/dcp_content.cc b/src/lib/dcp_content.cc index d2c1df748..e43d88a34 100644 --- a/src/lib/dcp_content.cc +++ b/src/lib/dcp_content.cc @@ -35,10 +35,11 @@ #include #include #include +#include #include +#include #include #include -#include #include #include @@ -51,11 +52,14 @@ using std::pair; using std::vector; using std::list; using std::map; -using boost::shared_ptr; +using std::shared_ptr; using boost::scoped_ptr; using boost::optional; using boost::function; -using boost::dynamic_pointer_cast; +using std::dynamic_pointer_cast; +#if BOOST_VERSION >= 106100 +using namespace boost::placeholders; +#endif using dcp::raw_convert; using namespace dcpomatic; @@ -92,6 +96,7 @@ DCPContent::DCPContent (cxml::ConstNodePtr node, int version) video = VideoContent::from_xml (this, node, version); audio = AudioContent::from_xml (this, node, version); text = TextContent::from_xml (this, node, version); + atmos = AtmosContent::from_xml (this, node); for (int i = 0; i < TEXT_COUNT; ++i) { _reference_text[i] = false; @@ -145,36 +150,51 @@ DCPContent::DCPContent (cxml::ConstNodePtr node, int version) _content_kind = dcp::content_kind_from_string (*ck); } _cpl = node->optional_string_child("CPL"); - BOOST_FOREACH (cxml::ConstNodePtr i, node->node_children("ReelLength")) { + for (auto i: node->node_children("ReelLength")) { _reel_lengths.push_back (raw_convert (i->content ())); } - BOOST_FOREACH (cxml::ConstNodePtr i, node->node_children("Marker")) { + for (auto i: node->node_children("Marker")) { _markers[dcp::marker_from_string(i->string_attribute("type"))] = ContentTime(raw_convert(i->content())); } - BOOST_FOREACH (cxml::ConstNodePtr i, node->node_children("Rating")) { + for (auto i: node->node_children("Rating")) { _ratings.push_back (dcp::Rating(i)); } - _content_version = node->optional_string_child("ContentVersion").get_value_or(""); + for (auto i: node->node_children("ContentVersion")) { + _content_versions.push_back (i->content()); + } } void DCPContent::read_directory (boost::filesystem::path p) { - read_sub_directory (p); + using namespace boost::filesystem; bool have_assetmap = false; - BOOST_FOREACH (boost::filesystem::path i, paths()) { - if (i.filename() == "ASSETMAP" || i.filename() == "ASSETMAP.xml") { + bool have_metadata = false; + + for (directory_iterator i(p); i != directory_iterator(); ++i) { + if (i->path().filename() == "ASSETMAP" || i->path().filename() == "ASSETMAP.xml") { have_assetmap = true; + } else if (i->path().filename() == "metadata.xml") { + have_metadata = true; } } if (!have_assetmap) { - throw DCPError ("No ASSETMAP or ASSETMAP.xml file found: is this a DCP?"); + if (!have_metadata) { + throw DCPError ("No ASSETMAP or ASSETMAP.xml file found: is this a DCP?"); + } else { + throw DCPError ( + "This looks like a DCP-o-matic project folder, which cannot be added to a different project. " + "Choose the DCP directory inside the DCP-o-matic project folder if that's what you want to import." + ); + } } + + read_sub_directory (p); } void @@ -199,7 +219,6 @@ DCPContent::examine (shared_ptr film, shared_ptr job) bool const needed_assets = needs_assets (); bool const needed_kdm = needs_kdm (); string const old_name = name (); - int const old_texts = text.size (); ChangeSignaller cc_texts (this, DCPContentProperty::TEXTS); ChangeSignaller cc_assets (this, DCPContentProperty::NEEDS_ASSETS); @@ -235,20 +254,32 @@ DCPContent::examine (shared_ptr film, shared_ptr job) } if (examiner->has_atmos()) { - boost::mutex::scoped_lock lm (_mutex); - atmos.reset (new AtmosContent(this)); + { + boost::mutex::scoped_lock lm (_mutex); + atmos.reset (new AtmosContent(this)); + } + /* Setting length will cause calculations to be made based on edit rate, so that must + * be set up first otherwise hard-to-spot exceptions will be thrown. + */ + atmos->set_edit_rate (examiner->atmos_edit_rate()); + atmos->set_length (examiner->atmos_length()); + } + + list > new_text; + for (int i = 0; i < TEXT_COUNT; ++i) { + for (int j = 0; j < examiner->text_count(static_cast(i)); ++j) { + shared_ptr c(new TextContent(this, static_cast(i), static_cast(i))); + if (i == TEXT_CLOSED_CAPTION) { + c->set_dcp_track (examiner->dcp_text_track(j)); + } + new_text.push_back (c); + } } - int texts = 0; { boost::mutex::scoped_lock lm (_mutex); + text = new_text; _name = examiner->name (); - for (int i = 0; i < TEXT_COUNT; ++i) { - for (int j = 0; j < examiner->text_count(static_cast(i)); ++j) { - text.push_back (shared_ptr(new TextContent(this, static_cast(i), static_cast(i)))); - } - } - texts = text.size (); _encrypted = examiner->encrypted (); _needs_assets = examiner->needs_assets (); _kdm_valid = examiner->kdm_valid (); @@ -262,11 +293,7 @@ DCPContent::examine (shared_ptr film, shared_ptr job) _markers[i->first] = ContentTime(i->second.as_editable_units(DCPTime::HZ)); } _ratings = examiner->ratings (); - _content_version = examiner->content_version (); - } - - if (old_texts == texts) { - cc_texts.abort (); + _content_versions = examiner->content_versions (); } if (needed_assets == needs_assets()) { @@ -324,10 +351,14 @@ DCPContent::as_xml (xmlpp::Node* node, bool with_paths) const audio->stream()->mapping().as_xml (node->add_child("AudioMapping")); } - BOOST_FOREACH (shared_ptr i, text) { + for (auto i: text) { i->as_xml (node); } + if (atmos) { + atmos->as_xml (node); + } + boost::mutex::scoped_lock lm (_mutex); node->add_child("Name")->add_child_text (_name); node->add_child("Encrypted")->add_child_text (_encrypted ? "1" : "0"); @@ -359,7 +390,7 @@ DCPContent::as_xml (xmlpp::Node* node, bool with_paths) const if (_cpl) { node->add_child("CPL")->add_child_text (_cpl.get ()); } - BOOST_FOREACH (int64_t i, _reel_lengths) { + for (auto i: _reel_lengths) { node->add_child("ReelLength")->add_child_text (raw_convert (i)); } @@ -369,12 +400,14 @@ DCPContent::as_xml (xmlpp::Node* node, bool with_paths) const marker->add_child_text(raw_convert(i->second.get())); } - BOOST_FOREACH (dcp::Rating i, _ratings) { + for (auto i: _ratings) { xmlpp::Element* rating = node->add_child("Rating"); i.as_xml (rating); } - node->add_child("ContentVersion")->add_child_text (_content_version); + for (auto i: _content_versions) { + node->add_child("ContentVersion")->add_child_text(i); + } } DCPTime @@ -405,7 +438,7 @@ DCPContent::identifier () const s += video->identifier() + "_"; } - BOOST_FOREACH (shared_ptr i, text) { + for (auto i: text) { s += i->identifier () + " "; } @@ -532,7 +565,7 @@ DCPContent::reels (shared_ptr film) const /* The starting point of this content on the timeline */ DCPTime pos = position() - DCPTime (trim_start().get()); - BOOST_FOREACH (int64_t i, reel_lengths) { + for (auto i: reel_lengths) { /* This reel runs from `pos' to `to' */ DCPTime const to = pos + DCPTime::from_frames (i, film->video_frame_rate()); if (to > position()) { @@ -551,7 +584,7 @@ list DCPContent::reel_split_points (shared_ptr film) const { list s; - BOOST_FOREACH (DCPTimePeriod i, reels(film)) { + for (auto i: reels(film)) { s.push_back (i.from); } return s; @@ -596,7 +629,7 @@ DCPContent::can_reference (shared_ptr film, function film, string& why_not) c return false; } - BOOST_FOREACH (shared_ptr i, decoder->reels()) { + for (auto i: decoder->reels()) { if (!i->main_sound()) { /// TRANSLATORS: this string will follow "Cannot reference this DCP: " why_not = _("it does not have sound in all its reels."); @@ -701,19 +734,40 @@ DCPContent::can_reference_text (shared_ptr film, TextType type, stri return false; } - BOOST_FOREACH (shared_ptr i, decoder->reels()) { - if (type == TEXT_OPEN_SUBTITLE && !i->main_subtitle()) { - /// TRANSLATORS: this string will follow "Cannot reference this DCP: " - why_not = _("it does not have open subtitles in all its reels."); - return false; + for (auto i: decoder->reels()) { + if (type == TEXT_OPEN_SUBTITLE) { + if (!i->main_subtitle()) { + /// TRANSLATORS: this string will follow "Cannot reference this DCP: " + why_not = _("it does not have open subtitles in all its reels."); + return false; + } else if (i->main_subtitle()->entry_point().get_value_or(0) != 0) { + /// TRANSLATORS: this string will follow "Cannot reference this DCP: " + why_not = _("one if its subtitle reels has a non-zero entry point so it must be re-written."); + return false; + } } - if (type == TEXT_CLOSED_CAPTION && i->closed_captions().empty()) { - /// TRANSLATORS: this string will follow "Cannot reference this DCP: " - why_not = _("it does not have closed captions in all its reels."); - return false; + if (type == TEXT_CLOSED_CAPTION) { + if (i->closed_captions().empty()) { + /// TRANSLATORS: this string will follow "Cannot reference this DCP: " + why_not = _("it does not have closed captions in all its reels."); + return false; + } + for (auto j: i->closed_captions()) { + if (j->entry_point().get_value_or(0) != 0) { + /// TRANSLATORS: this string will follow "Cannot reference this DCP: " + why_not = _("one if its closed caption has a non-zero entry point so it must be re-written."); + return false; + } + } } } + if (trim_start() != dcpomatic::ContentTime()) { + /// TRANSLATORS: this string will follow "Cannot reference this DCP: " + why_not = _("it has a start trim so its subtitles or closed captions must be re-written."); + return false; + } + /// TRANSLATORS: this string will follow "Cannot reference this DCP: " return can_reference (film, bind (&check_text, _1), _("it overlaps other text content; remove the other content."), why_not); }