}
_active_audio_channels = node->optional_number_child<int>("ActiveAudioChannels");
+
+ for (auto non_zero: node->node_children("HasNonZeroEntryPoint")) {
+ try {
+ auto type = string_to_text_type(non_zero->string_attribute("type"));
+ _has_non_zero_entry_point[type] = non_zero->content() == "1";
+ } catch (MetadataError&) {}
+ }
}
void
}
_ratings = examiner->ratings ();
_content_versions = examiner->content_versions ();
+ _has_non_zero_entry_point = examiner->has_non_zero_entry_point();
}
if (needed_assets == needs_assets()) {
return s;
}
+
void
-DCPContent::as_xml (xmlpp::Node* node, bool with_paths) const
+DCPContent::as_xml(xmlpp::Element* element, bool with_paths) const
{
- node->add_child("Type")->add_child_text ("DCP");
+ cxml::add_text_child(element, "Type", "DCP");
- Content::as_xml (node, with_paths);
+ Content::as_xml(element, with_paths);
if (video) {
- video->as_xml (node);
+ video->as_xml(element);
}
if (audio) {
- audio->as_xml (node);
- node->add_child("AudioFrameRate")->add_child_text (raw_convert<string> (audio->stream()->frame_rate()));
- node->add_child("AudioLength")->add_child_text (raw_convert<string> (audio->stream()->length()));
- audio->stream()->mapping().as_xml (node->add_child("AudioMapping"));
+ audio->as_xml(element);
+ cxml::add_text_child(element, "AudioFrameRate", raw_convert<string>(audio->stream()->frame_rate()));
+ cxml::add_text_child(element, "AudioLength", raw_convert<string>(audio->stream()->length()));
+ audio->stream()->mapping().as_xml(cxml::add_child(element, "AudioMapping"));
}
for (auto i: text) {
- i->as_xml (node);
+ i->as_xml(element);
}
if (atmos) {
- atmos->as_xml (node);
+ atmos->as_xml(element);
}
boost::mutex::scoped_lock lm (_mutex);
- node->add_child("Name")->add_child_text (_name);
- node->add_child("Encrypted")->add_child_text (_encrypted ? "1" : "0");
- node->add_child("NeedsAssets")->add_child_text (_needs_assets ? "1" : "0");
+ cxml::add_text_child(element, "Name", _name);
+ cxml::add_text_child(element, "Encrypted", _encrypted ? "1" : "0");
+ cxml::add_text_child(element, "NeedsAssets", _needs_assets ? "1" : "0");
if (_kdm) {
- node->add_child("KDM")->add_child_text (_kdm->as_xml ());
+ cxml::add_text_child(element, "KDM", _kdm->as_xml());
}
- node->add_child("KDMValid")->add_child_text (_kdm_valid ? "1" : "0");
- node->add_child("ReferenceVideo")->add_child_text (_reference_video ? "1" : "0");
- node->add_child("ReferenceAudio")->add_child_text (_reference_audio ? "1" : "0");
- node->add_child("ReferenceOpenSubtitle")->add_child_text(_reference_text[TextType::OPEN_SUBTITLE] ? "1" : "0");
- node->add_child("ReferenceClosedCaption")->add_child_text(_reference_text[TextType::CLOSED_CAPTION] ? "1" : "0");
+ cxml::add_text_child(element, "KDMValid", _kdm_valid ? "1" : "0");
+ cxml::add_text_child(element, "ReferenceVideo", _reference_video ? "1" : "0");
+ cxml::add_text_child(element, "ReferenceAudio", _reference_audio ? "1" : "0");
+ cxml::add_text_child(element, "ReferenceOpenSubtitle", _reference_text[TextType::OPEN_SUBTITLE] ? "1" : "0");
+ cxml::add_text_child(element, "ReferenceClosedCaption", _reference_text[TextType::CLOSED_CAPTION] ? "1" : "0");
if (_standard) {
switch (_standard.get ()) {
case dcp::Standard::INTEROP:
- node->add_child("Standard")->add_child_text ("Interop");
+ cxml::add_text_child(element, "Standard", "Interop");
break;
case dcp::Standard::SMPTE:
- node->add_child("Standard")->add_child_text ("SMPTE");
+ cxml::add_text_child(element, "Standard", "SMPTE");
break;
default:
DCPOMATIC_ASSERT (false);
}
}
- node->add_child("ThreeD")->add_child_text (_three_d ? "1" : "0");
+ cxml::add_text_child(element, "ThreeD", _three_d ? "1" : "0");
if (_content_kind) {
- node->add_child("ContentKind")->add_child_text(_content_kind->name());
+ cxml::add_text_child(element, "ContentKind", _content_kind->name());
}
if (_cpl) {
- node->add_child("CPL")->add_child_text (_cpl.get ());
+ cxml::add_text_child(element, "CPL", _cpl.get());
}
for (auto i: _reel_lengths) {
- node->add_child("ReelLength")->add_child_text (raw_convert<string> (i));
+ cxml::add_text_child(element, "ReelLength", raw_convert<string>(i));
}
for (auto const& i: _markers) {
- auto marker = node->add_child("Marker");
+ auto marker = cxml::add_child(element, "Marker");
marker->set_attribute("type", dcp::marker_to_string(i.first));
marker->add_child_text(raw_convert<string>(i.second.get()));
}
for (auto i: _ratings) {
- auto rating = node->add_child("Rating");
+ auto rating = cxml::add_child(element, "Rating");
i.as_xml (rating);
}
for (auto i: _content_versions) {
- node->add_child("ContentVersion")->add_child_text(i);
+ cxml::add_text_child(element, "ContentVersion", i);
}
if (_active_audio_channels) {
- node->add_child("ActiveAudioChannels")->add_child_text(raw_convert<string>(*_active_audio_channels));
+ cxml::add_text_child(element, "ActiveAudioChannels", raw_convert<string>(*_active_audio_channels));
+ }
+
+ for (auto i = 0; i < static_cast<int>(TextType::COUNT); ++i) {
+ if (_has_non_zero_entry_point[i]) {
+ auto has = cxml::add_child(element, "HasNonZeroEntryPoint");
+ has->add_child_text("1");
+ has->set_attribute("type", text_type_to_string(static_cast<TextType>(i)));
+ }
}
}
+
DCPTime
DCPContent::full_length (shared_ptr<const Film> film) const
{
}
bool
-DCPContent::can_reference (shared_ptr<const Film> film, function<bool (shared_ptr<const Content>)> part, string overlapping, string& why_not) const
+DCPContent::can_reference_anything(shared_ptr<const Film> film, string& why_not) const
{
/* We must be using the same standard as the film */
if (_standard) {
}
}
- auto a = overlaps (film, film->content(), part, position(), end(film));
- if (a.size() != 1 || a.front().get() != this) {
- why_not = overlapping;
- return false;
- }
-
return true;
}
+bool
+DCPContent::overlaps(shared_ptr<const Film> film, function<bool (shared_ptr<const Content>)> part) const
+{
+ auto const a = dcpomatic::overlaps(film, film->content(), part, position(), end(film));
+ return a.size() != 1 || a.front().get() != this;
+}
+
bool
DCPContent::can_reference_video (shared_ptr<const Film> film, string& why_not) const
return false;
}
- /// TRANSLATORS: this string will follow "Cannot reference this DCP: "
- return can_reference(
- film,
- [](shared_ptr<const Content> c) {
- return static_cast<bool>(c->video) && c->video->use();
- },
- _("it overlaps other video content; remove the other content."),
- why_not
- );
+ auto part = [](shared_ptr<const Content> c) {
+ return static_cast<bool>(c->video) && c->video->use();
+ };
+
+ if (overlaps(film, part)) {
+ /// TRANSLATORS: this string will follow "Cannot reference this DCP: "
+ why_not = _("it overlaps other video content.");
+ return false;
+ }
+
+ return can_reference_anything(film, why_not);
}
bool
DCPContent::can_reference_audio (shared_ptr<const Film> film, string& why_not) const
{
- shared_ptr<DCPDecoder> decoder;
- try {
- decoder = make_shared<DCPDecoder>(film, shared_from_this(), false, film->tolerant(), shared_ptr<DCPDecoder>());
- } catch (dcp::ReadError &) {
- /* We couldn't read the DCP, so it's probably missing */
- return false;
- } catch (DCPError &) {
- /* We couldn't read the DCP, so it's probably missing */
- return false;
- } catch (dcp::KDMDecryptionError &) {
- /* We have an incorrect KDM */
+ if (audio && audio->stream()) {
+ auto const channels = audio->stream()->channels();
+ if (channels != film->audio_channels()) {
+ why_not = String::compose(_("it has a different number of audio channels than the project; set the project to have %1 channels."), channels);
+ return false;
+ }
+ }
+
+ auto part = [](shared_ptr<const Content> c) {
+ return static_cast<bool>(c->audio) && !c->audio->mapping().mapped_output_channels().empty();
+ };
+
+ if (overlaps(film, part)) {
+ /// TRANSLATORS: this string will follow "Cannot reference this DCP: "
+ why_not = _("it overlaps other audio content.");
return false;
}
- /// TRANSLATORS: this string will follow "Cannot reference this DCP: "
- return can_reference(
- film, [](shared_ptr<const Content> c) {
- return static_cast<bool>(c->audio) && !c->audio->mapping().mapped_output_channels().empty();
- },
- _("it overlaps other audio content; remove the other content."),
- why_not
- );
+ return can_reference_anything(film, why_not);
}
bool
DCPContent::can_reference_text (shared_ptr<const Film> film, TextType type, string& why_not) const
{
- shared_ptr<DCPDecoder> decoder;
- try {
- decoder = make_shared<DCPDecoder>(film, shared_from_this(), false, film->tolerant(), shared_ptr<DCPDecoder>());
- } catch (dcp::ReadError &) {
- /* We couldn't read the DCP, so it's probably missing */
- return false;
- } catch (DCPError &) {
- /* We couldn't read the DCP, so it's probably missing */
- return false;
- } catch (dcp::KDMDecryptionError &) {
- /* We have an incorrect KDM */
+ if (_has_non_zero_entry_point[TextType::OPEN_SUBTITLE]) {
+ /// TRANSLATORS: this string will follow "Cannot reference this DCP: "
+ why_not = _("one of its subtitle reels has a non-zero entry point so it must be re-written.");
return false;
}
- for (auto i: decoder->reels()) {
- if (type == TextType::OPEN_SUBTITLE) {
- if (i->main_subtitle() && i->main_subtitle()->entry_point().get_value_or(0) != 0) {
- /// TRANSLATORS: this string will follow "Cannot reference this DCP: "
- why_not = _("one of its subtitle reels has a non-zero entry point so it must be re-written.");
- return false;
- }
- }
- if (type == TextType::CLOSED_CAPTION) {
- 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 of its closed caption has a non-zero entry point so it must be re-written.");
- return false;
- }
- }
- }
+ if (_has_non_zero_entry_point[TextType::CLOSED_CAPTION]) {
+ /// TRANSLATORS: this string will follow "Cannot reference this DCP: "
+ why_not = _("one of its closed caption has a non-zero entry point so it must be re-written.");
+ return false;
}
if (trim_start() != dcpomatic::ContentTime()) {
return false;
}
- /// TRANSLATORS: this string will follow "Cannot reference this DCP: "
- return can_reference(
- film,
- [type](shared_ptr<const Content> c) {
- return std::find_if(c->text.begin(), c->text.end(), [type](shared_ptr<const TextContent> t) { return t->type() == type; }) != c->text.end();
- },
- _("they overlap other text content; remove the other content."),
- why_not
- );
+ auto part = [type](shared_ptr<const Content> c) {
+ return std::find_if(c->text.begin(), c->text.end(), [type](shared_ptr<const TextContent> t) { return t->type() == type; }) != c->text.end();
+ };
+
+ if (overlaps(film, part)) {
+ /// TRANSLATORS: this string will follow "Cannot reference this DCP: "
+ why_not = _("it overlaps other text content.");
+ return false;
+ }
+
+ return can_reference_anything(film, why_not);
}
void