diff options
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/content.h | 2 | ||||
| -rw-r--r-- | src/lib/film.cc | 94 | ||||
| -rw-r--r-- | src/lib/film.h | 9 | ||||
| -rw-r--r-- | src/lib/reel_writer.cc | 10 | ||||
| -rw-r--r-- | src/lib/subtitle_encoder.cc | 10 | ||||
| -rw-r--r-- | src/lib/text_content.cc | 49 | ||||
| -rw-r--r-- | src/lib/text_content.h | 25 | ||||
| -rw-r--r-- | src/lib/writer.cc | 12 |
8 files changed, 113 insertions, 98 deletions
diff --git a/src/lib/content.h b/src/lib/content.h index b8626e212..567cd5c1f 100644 --- a/src/lib/content.h +++ b/src/lib/content.h @@ -196,7 +196,7 @@ public: std::shared_ptr<VideoContent> video; std::shared_ptr<AudioContent> audio; - std::list<std::shared_ptr<TextContent> > text; + std::list<std::shared_ptr<TextContent>> text; std::shared_ptr<AtmosContent> atmos; std::shared_ptr<TextContent> only_text () const; diff --git a/src/lib/film.cc b/src/lib/film.cc index 46074e2ad..763af8f8a 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -496,9 +496,6 @@ Film::metadata (bool with_content_paths) const } root->add_child("UserExplicitContainer")->add_child_text(_user_explicit_container ? "1" : "0"); root->add_child("UserExplicitResolution")->add_child_text(_user_explicit_resolution ? "1" : "0"); - for (auto i: _subtitle_languages) { - root->add_child("SubtitleLanguage")->add_child_text(i.to_string()); - } _playlist->as_xml (root->add_child ("Playlist"), with_content_paths); return doc; @@ -680,10 +677,6 @@ Film::read_metadata (optional<boost::filesystem::path> path) _user_explicit_container = f.optional_bool_child("UserExplicitContainer").get_value_or(true); _user_explicit_resolution = f.optional_bool_child("UserExplicitResolution").get_value_or(true); - for (auto i: f.node_children("SubtitleLanguage")) { - _subtitle_languages.push_back (dcp::LanguageTag(i->content())); - } - list<string> notes; _playlist->set_from_xml (shared_from_this(), f.node_child ("Playlist"), _state_version, notes); @@ -692,41 +685,6 @@ Film::read_metadata (optional<boost::filesystem::path> path) set_backtrace_file (file ("backtrace.txt")); } - /* Around 2.15.108 we removed subtitle language state from the text content and the ISDCF - * metadata and put it into the Film instead. If we've loaded an old Film let's try and fish - * out the settings from where they were so that they don't get lost. - */ - - optional<dcp::LanguageTag> found_language; - - for (auto i: f.node_child("Playlist")->node_children("Content")) { - auto text = i->optional_node_child("Text"); - if (text && text->optional_string_child("Language") && !found_language) { - try { - found_language = dcp::LanguageTag(text->string_child("Language")); - } catch (...) {} - } - } - - if (_state_version >= 9) { - auto isdcf_language = f.node_child("ISDCFMetadata")->optional_string_child("SubtitleLanguage"); - if (isdcf_language && !found_language) { - try { - found_language = dcp::LanguageTag(*isdcf_language); - } catch (...) { - try { - found_language = dcp::LanguageTag(boost::algorithm::to_lower_copy(*isdcf_language)); - } catch (...) { - - } - } - } - } - - if (found_language) { - _subtitle_languages.push_back (*found_language); - } - _dirty = false; return notes; } @@ -793,6 +751,30 @@ Film::mapped_audio_channels () const return mapped; } + +pair<optional<dcp::LanguageTag>, vector<dcp::LanguageTag>> +Film::subtitle_languages () const +{ + pair<optional<dcp::LanguageTag>, vector<dcp::LanguageTag>> result; + for (auto i: content()) { + for (auto j: i->text) { + if (j->use() && j->type() == TextType::OPEN_SUBTITLE && j->language()) { + if (j->language_is_additional()) { + result.second.push_back (j->language().get()); + } else { + result.first = j->language().get(); + } + } + } + } + + std::sort (result.second.begin(), result.second.end()); + auto last = std::unique (result.second.begin(), result.second.end()); + result.second.erase (last, result.second.end()); + return result; +} + + /** @return a ISDCF-compliant name for a DCP of this film */ string Film::isdcf_name (bool if_created_now) const @@ -924,8 +906,9 @@ Film::isdcf_name (bool if_created_now) const } } - if (!_subtitle_languages.empty()) { - auto lang = _subtitle_languages.front().language().get_value_or("en").subtag(); + auto sublangs = subtitle_languages(); + if (sublangs.first && sublangs.first->language()) { + auto lang = sublangs.first->language()->subtag(); if (burnt_in) { transform (lang.begin(), lang.end(), lang.begin(), ::tolower); } else { @@ -2038,29 +2021,6 @@ Film::set_luminance (optional<dcp::Luminance> l) void -Film::set_subtitle_language (dcp::LanguageTag language) -{ - set_subtitle_languages ({language}); -} - - -void -Film::unset_subtitle_language () -{ - FilmChangeSignaller ch (this, Property::SUBTITLE_LANGUAGES); - _subtitle_languages.clear(); -} - - -void -Film::set_subtitle_languages (vector<dcp::LanguageTag> languages) -{ - FilmChangeSignaller ch (this, Property::SUBTITLE_LANGUAGES); - _subtitle_languages = languages; -} - - -void Film::set_facility (optional<string> f) { FilmChangeSignaller ch (this, Property::FACILITY); diff --git a/src/lib/film.h b/src/lib/film.h index 9b45fd073..9feb5d0d3 100644 --- a/src/lib/film.h +++ b/src/lib/film.h @@ -184,6 +184,7 @@ public: std::list<dcpomatic::DCPTimePeriod> reels () const; std::list<int> mapped_audio_channels () const; + std::pair<boost::optional<dcp::LanguageTag>, std::vector<dcp::LanguageTag>> subtitle_languages () const; std::string content_summary (dcpomatic::DCPTimePeriod period) const; @@ -376,10 +377,6 @@ public: return _luminance; } - std::vector<dcp::LanguageTag> subtitle_languages () const { - return _subtitle_languages; - } - /* SET */ void set_directory (boost::filesystem::path); @@ -421,9 +418,6 @@ public: void set_facility (boost::optional<std::string> f = boost::none); void set_distributor (boost::optional<std::string> d = boost::none); void set_luminance (boost::optional<dcp::Luminance> l = boost::none); - void set_subtitle_language (dcp::LanguageTag language); - void unset_subtitle_language (); - void set_subtitle_languages (std::vector<dcp::LanguageTag> languages); void add_ffoc_lfoc (Markers& markers) const; @@ -529,7 +523,6 @@ private: boost::optional<std::string> _distributor; boost::optional<std::string> _facility; boost::optional<dcp::Luminance> _luminance; - std::vector<dcp::LanguageTag> _subtitle_languages; int _state_version; diff --git a/src/lib/reel_writer.cc b/src/lib/reel_writer.cc index 366e6edc6..2c55f0f06 100644 --- a/src/lib/reel_writer.cc +++ b/src/lib/reel_writer.cc @@ -623,8 +623,8 @@ ReelWriter::create_reel_text ( if (subtitle) { /* We have a subtitle asset that we either made or are referencing */ - if (!film()->subtitle_languages().empty()) { - subtitle->set_language (film()->subtitle_languages().front()); + if (auto main_language = film()->subtitle_languages().first) { + subtitle->set_language (*main_language); } } else if (ensure_subtitles) { /* We had no subtitle asset, but we've been asked to make sure there is one */ @@ -776,7 +776,7 @@ ReelWriter::empty_text_asset (TextType type, optional<DCPTextTrack> track) const auto s = make_shared<dcp::InteropSubtitleAsset>(); s->set_movie_title (film()->name()); if (type == TextType::OPEN_SUBTITLE) { - s->set_language (lang.empty() ? "Unknown" : lang.front().to_string()); + s->set_language (lang.first ? lang.first->to_string() : "Unknown"); } else if (!track->language.empty()) { s->set_language (track->language); } @@ -786,8 +786,8 @@ ReelWriter::empty_text_asset (TextType type, optional<DCPTextTrack> track) const auto s = make_shared<dcp::SMPTESubtitleAsset>(); s->set_content_title_text (film()->name()); s->set_metadata (mxf_metadata()); - if (type == TextType::OPEN_SUBTITLE && !lang.empty()) { - s->set_language (lang.front()); + if (type == TextType::OPEN_SUBTITLE && lang.first) { + s->set_language (*lang.first); } else if (track && !track->language.empty()) { s->set_language (dcp::LanguageTag(track->language)); } diff --git a/src/lib/subtitle_encoder.cc b/src/lib/subtitle_encoder.cc index 3721ee02b..b61876ad6 100644 --- a/src/lib/subtitle_encoder.cc +++ b/src/lib/subtitle_encoder.cc @@ -135,20 +135,20 @@ SubtitleEncoder::text (PlayerText subs, TextType type, optional<DCPTextTrack> tr if (!_assets[_reel_index].first) { shared_ptr<dcp::SubtitleAsset> asset; - vector<dcp::LanguageTag> lang = _film->subtitle_languages (); + auto lang = _film->subtitle_languages (); if (_film->interop ()) { auto s = make_shared<dcp::InteropSubtitleAsset>(); s->set_movie_title (_film->name()); - if (!lang.empty()) { - s->set_language (lang.front().to_string()); + if (lang.first) { + s->set_language (lang.first->to_string()); } s->set_reel_number (raw_convert<string>(_reel_index + 1)); _assets[_reel_index].first = s; } else { auto s = make_shared<dcp::SMPTESubtitleAsset>(); s->set_content_title_text (_film->name()); - if (!lang.empty()) { - s->set_language (lang.front()); + if (lang.first) { + s->set_language (*lang.first); } else if (!track->language.empty()) { s->set_language (dcp::LanguageTag(track->language)); } diff --git a/src/lib/text_content.cc b/src/lib/text_content.cc index 0c25e5696..c86150881 100644 --- a/src/lib/text_content.cc +++ b/src/lib/text_content.cc @@ -18,6 +18,7 @@ */ + #include "text_content.h" #include "util.h" #include "exceptions.h" @@ -30,6 +31,7 @@ #include "i18n.h" + using std::string; using std::vector; using std::cout; @@ -41,6 +43,7 @@ using boost::optional; using dcp::raw_convert; using namespace dcpomatic; + int const TextContentProperty::X_OFFSET = 500; int const TextContentProperty::Y_OFFSET = 501; int const TextContentProperty::X_SCALE = 502; @@ -57,6 +60,9 @@ int const TextContentProperty::FADE_OUT = 512; int const TextContentProperty::OUTLINE_WIDTH = 513; int const TextContentProperty::TYPE = 514; int const TextContentProperty::DCP_TRACK = 515; +int const TextContentProperty::LANGUAGE = 516; +int const TextContentProperty::LANGUAGE_IS_ADDITIONAL = 517; + TextContent::TextContent (Content* parent, TextType type, TextType original_type) : ContentPart (parent) @@ -95,9 +101,7 @@ TextContent::from_xml (Content* parent, cxml::ConstNodePtr node, int version) if (!node->optional_number_child<double>("SubtitleXOffset") && !node->optional_number_child<double>("SubtitleOffset")) { return {}; } - list<shared_ptr<TextContent>> c; - c.push_back (make_shared<TextContent>(parent, node, version)); - return c; + return { make_shared<TextContent>(parent, node, version) }; } if (!node->optional_node_child("Text")) { @@ -124,6 +128,7 @@ TextContent::TextContent (Content* parent, cxml::ConstNodePtr node, int version) , _outline_width (node->optional_number_child<int>("OutlineWidth").get_value_or(4)) , _type (TextType::OPEN_SUBTITLE) , _original_type (TextType::OPEN_SUBTITLE) + , _language ("en-US") { if (version >= 37) { _use = node->bool_child ("Use"); @@ -231,6 +236,13 @@ TextContent::TextContent (Content* parent, cxml::ConstNodePtr node, int version) if (dt) { _dcp_track = DCPTextTrack (dt); } + + auto lang = node->optional_node_child("Language"); + if (lang) { + _language = dcp::LanguageTag(lang->content()); + auto add = lang->optional_bool_attribute("Additional"); + _language_is_additional = add && *add; + } } TextContent::TextContent (Content* parent, vector<shared_ptr<Content>> c) @@ -290,6 +302,14 @@ TextContent::TextContent (Content* parent, vector<shared_ptr<Content>> c) throw JoinError (_("Content to be joined must use the same DCP track.")); } + if (c[i]->only_text()->language() != ref->language()) { + throw JoinError (_("Content to be joined must use the same text language.")); + } + + if (c[i]->only_text()->language_is_additional() != ref->language_is_additional()) { + throw JoinError (_("Content to be joined must both be main subtitle languages or both additional.")); + } + auto j = ref_fonts.begin (); auto k = fonts.begin (); @@ -316,6 +336,8 @@ TextContent::TextContent (Content* parent, vector<shared_ptr<Content>> c) _type = ref->type (); _original_type = ref->original_type (); _dcp_track = ref->dcp_track (); + _language = ref->language (); + _language_is_additional = ref->language_is_additional (); connect_to_fonts (); } @@ -375,6 +397,11 @@ TextContent::as_xml (xmlpp::Node* root) const if (_dcp_track) { _dcp_track->as_xml(text->add_child("DCPTrack")); } + if (_language) { + auto lang = text->add_child("Language"); + lang->add_child_text (_language->to_string()); + lang->set_attribute ("Additional", _language_is_additional ? "1" : "0"); + } } string @@ -400,7 +427,7 @@ TextContent::identifier () const s += "_" + f->file().get_value_or("Default").string(); } - /* The DCP track is for metadata only, and doesn't affect how this content looks */ + /* The DCP track and language are for metadata only, and don't affect how this content looks */ return s; } @@ -560,6 +587,18 @@ TextContent::unset_dcp_track () } void +TextContent::set_language (optional<dcp::LanguageTag> language) +{ + maybe_set (_language, language, TextContentProperty::LANGUAGE); +} + +void +TextContent::set_language_is_additional (bool additional) +{ + maybe_set (_language_is_additional, additional, TextContentProperty::LANGUAGE_IS_ADDITIONAL); +} + +void TextContent::take_settings_from (shared_ptr<const TextContent> c) { set_use (c->_use); @@ -595,4 +634,6 @@ TextContent::take_settings_from (shared_ptr<const TextContent> c) } else { unset_dcp_track (); } + set_language (c->_language); + set_language_is_additional (c->_language_is_additional); } diff --git a/src/lib/text_content.h b/src/lib/text_content.h index e566d0552..4c6918a42 100644 --- a/src/lib/text_content.h +++ b/src/lib/text_content.h @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2020 Carl Hetherington <cth@carlh.net> + Copyright (C) 2013-2021 Carl Hetherington <cth@carlh.net> This file is part of DCP-o-matic. @@ -18,15 +18,19 @@ */ + #ifndef DCPOMATIC_CAPTION_CONTENT_H #define DCPOMATIC_CAPTION_CONTENT_H + #include "content_part.h" #include "dcp_text_track.h" #include <libcxml/cxml.h> +#include <dcp/language_tag.h> #include <dcp/types.h> #include <boost/signals2.hpp> + namespace dcpomatic { class Font; } @@ -50,8 +54,11 @@ public: static int const OUTLINE_WIDTH; static int const TYPE; static int const DCP_TRACK; + static int const LANGUAGE; + static int const LANGUAGE_IS_ADDITIONAL; }; + /** @class TextContent * @brief Description of how some text content should be presented. * @@ -92,6 +99,8 @@ public: void set_type (TextType type); void set_dcp_track (DCPTextTrack track); void unset_dcp_track (); + void set_language (boost::optional<dcp::LanguageTag> language = boost::none); + void set_language_is_additional (bool additional); bool use () const { boost::mutex::scoped_lock lm (_mutex); @@ -178,7 +187,17 @@ public: return _dcp_track; } - static std::list<std::shared_ptr<TextContent> > from_xml (Content* parent, cxml::ConstNodePtr, int version); + boost::optional<dcp::LanguageTag> language () const { + boost::mutex::scoped_lock lm (_mutex); + return _language; + } + + bool language_is_additional () const { + boost::mutex::scoped_lock lm (_mutex); + return _language_is_additional; + } + + static std::list<std::shared_ptr<TextContent>> from_xml (Content* parent, cxml::ConstNodePtr, int version); private: friend struct ffmpeg_pts_offset_test; @@ -219,6 +238,8 @@ private: TextType _original_type; /** the track of closed captions that this content should be put in, or empty to put in the default (only) track */ boost::optional<DCPTextTrack> _dcp_track; + boost::optional<dcp::LanguageTag> _language; + bool _language_is_additional = false; }; #endif diff --git a/src/lib/writer.cc b/src/lib/writer.cc index 839156d34..3448c5bca 100644 --- a/src/lib/writer.cc +++ b/src/lib/writer.cc @@ -663,9 +663,9 @@ Writer::finish (boost::filesystem::path output_dcp) cpl->set_main_picture_active_area (active_area); } - vector<dcp::LanguageTag> sl = film()->subtitle_languages(); - if (sl.size() > 1) { - cpl->set_additional_subtitle_languages(std::vector<dcp::LanguageTag>(sl.begin() + 1, sl.end())); + auto sl = film()->subtitle_languages().second; + if (!sl.empty()) { + cpl->set_additional_subtitle_languages(sl); } auto signer = Config::instance()->signer_chain(); @@ -709,10 +709,10 @@ Writer::write_cover_sheet (boost::filesystem::path output_dcp) boost::algorithm::replace_all (text, "$AUDIO_LANGUAGE", film()->isdcf_metadata().audio_language); auto subtitle_languages = film()->subtitle_languages(); - if (subtitle_languages.empty()) { - boost::algorithm::replace_all (text, "$SUBTITLE_LANGUAGE", "None"); + if (subtitle_languages.first) { + boost::algorithm::replace_all (text, "$SUBTITLE_LANGUAGE", subtitle_languages.first->description()); } else { - boost::algorithm::replace_all (text, "$SUBTITLE_LANGUAGE", subtitle_languages.front().description()); + boost::algorithm::replace_all (text, "$SUBTITLE_LANGUAGE", "None"); } boost::uintmax_t size = 0; |
