X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Ffilm.cc;h=a9ac82b5a227224a1a01ea97c074f4028ac94a67;hb=8336cba4e6a8c594680696d2337ddc800d84c267;hp=321a932d17751f9fb6b75210195fcf73d35bca30;hpb=79e711cb33c182e48c1d33d3e9f1df1c41c122a6;p=dcpomatic.git diff --git a/src/lib/film.cc b/src/lib/film.cc index 321a932d1..a9ac82b5a 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -155,7 +155,6 @@ Film::Film (optional dir) , _encrypted (false) , _context_id (dcp::make_uuid ()) , _j2k_bandwidth (Config::instance()->default_j2k_bandwidth ()) - , _isdcf_metadata (Config::instance()->default_isdcf_metadata ()) , _video_frame_rate (24) , _audio_channels (Config::instance()->default_dcp_audio_channels ()) , _three_d (false) @@ -446,7 +445,6 @@ Film::metadata (bool with_content_paths) const root->add_child("Resolution")->add_child_text (resolution_to_string (_resolution)); root->add_child("J2KBandwidth")->add_child_text (raw_convert (_j2k_bandwidth)); - _isdcf_metadata.as_xml (root->add_child ("ISDCFMetadata")); root->add_child("VideoFrameRate")->add_child_text (raw_convert (_video_frame_rate)); root->add_child("ISDCFDate")->add_child_text (boost::gregorian::to_iso_string (_isdcf_date)); root->add_child("AudioChannels")->add_child_text (raw_convert (_audio_channels)); @@ -490,15 +488,19 @@ Film::metadata (bool with_content_paths) const if (_facility) { root->add_child("Facility")->add_child_text(*_facility); } + if (_studio) { + root->add_child("Studio")->add_child_text(*_studio); + } + root->add_child("TempVersion")->add_child_text(_temp_version ? "1" : "0"); + root->add_child("PreRelease")->add_child_text(_pre_release ? "1" : "0"); + root->add_child("RedBand")->add_child_text(_red_band ? "1" : "0"); + root->add_child("TwoDVersionOfThreeD")->add_child_text(_two_d_version_of_three_d ? "1" : "0"); if (_luminance) { root->add_child("LuminanceValue")->add_child_text(raw_convert(_luminance->value())); root->add_child("LuminanceUnit")->add_child_text(dcp::Luminance::unit_to_string(_luminance->unit())); } 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; @@ -568,11 +570,9 @@ Film::read_metadata (optional path) _name = f.string_child ("Name"); if (_state_version >= 9) { _use_isdcf_name = f.bool_child ("UseISDCFName"); - _isdcf_metadata = ISDCFMetadata (f.node_child ("ISDCFMetadata")); _isdcf_date = boost::gregorian::from_undelimited_string (f.string_child ("ISDCFDate")); } else { _use_isdcf_name = f.bool_child ("UseDCIName"); - _isdcf_metadata = ISDCFMetadata (f.node_child ("DCIMetadata")); _isdcf_date = boost::gregorian::from_undelimited_string (f.string_child ("DCIDate")); } @@ -669,6 +669,11 @@ Film::read_metadata (optional path) _chain = f.optional_string_child("Chain"); _distributor = f.optional_string_child("Distributor"); _facility = f.optional_string_child("Facility"); + _studio = f.optional_string_child("Studio"); + _temp_version = f.optional_bool_child("TempVersion").get_value_or(false); + _pre_release = f.optional_bool_child("PreRelease").get_value_or(false); + _red_band = f.optional_bool_child("RedBand").get_value_or(false); + _two_d_version_of_three_d = f.optional_bool_child("TwoDVersionOfThreeD").get_value_or(false); auto value = f.optional_number_child("LuminanceValue"); auto unit = f.optional_string_child("LuminanceUnit"); @@ -680,10 +685,6 @@ Film::read_metadata (optional 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 notes; _playlist->set_from_xml (shared_from_this(), f.node_child ("Playlist"), _state_version, notes); @@ -692,41 +693,6 @@ Film::read_metadata (optional 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 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 +759,50 @@ Film::mapped_audio_channels () const return mapped; } + +vector +Film::audio_languages () const +{ + vector result; + for (auto i: content()) { + if (i->audio && !i->audio->mapping().mapped_output_channels().empty() && i->audio->language()) { + result.push_back (i->audio->language().get()); + } + } + + std::sort (result.begin(), result.end()); + auto last = std::unique (result.begin(), result.end()); + result.erase (last, result.end()); + return result; +} + + +pair, vector> +Film::subtitle_languages () const +{ + pair, vector> 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(); + } + } + } + if (i->video && i->video->burnt_subtitle_language()) { + result.first = i->video->burnt_subtitle_language(); + } + } + + 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 @@ -844,37 +854,49 @@ Film::isdcf_name (bool if_created_now) const if (dcp_content_type()) { d += "_" + dcp_content_type()->isdcf_name(); - d += "-" + raw_convert(isdcf_metadata().content_version); + string version = "1"; + if (_interop) { + if (!_content_versions.empty()) { + auto cv = _content_versions[0]; + if (!cv.empty() && std::all_of(cv.begin(), cv.end(), isdigit)) { + version = cv; + } + } + } else { + version = dcp::raw_convert(_version_number); + } + d += "-" + version; } - auto const dm = isdcf_metadata (); - - if (dm.temp_version) { + if (_temp_version) { d += "-Temp"; } - if (dm.pre_release) { + if (_pre_release) { d += "-Pre"; } - if (dm.red_band) { + if (_red_band) { d += "-RedBand"; } - if (!dm.chain.empty ()) { - d += "-" + dm.chain; + if (_chain && !_chain->empty()) { + d += "-" + *_chain; } if (three_d ()) { d += "-3D"; } - if (dm.two_d_version_of_three_d) { + if (_two_d_version_of_three_d) { d += "-2D"; } - if (!dm.mastered_luminance.empty ()) { - d += "-" + dm.mastered_luminance; + if (_luminance) { + auto fl = _luminance->value_in_foot_lamberts(); + char buffer[64]; + snprintf (buffer, sizeof(buffer), "%.1f", fl); + d += String::compose("-%1fl", buffer); } if (video_frame_rate() != 24) { @@ -904,49 +926,52 @@ Film::isdcf_name (bool if_created_now) const } } - if (!dm.audio_language.empty ()) { - d += "_" + dm.audio_language; + auto audio_langs = audio_languages(); + auto audio_language = (audio_langs.empty() || !audio_langs.front().language()) ? "XX" : audio_langs.front().language()->subtag(); - /* I'm not clear on the precise details of the convention for CCAP labelling; - for now I'm just appending -CCAP if we have any closed captions. - */ + d += "_" + to_upper (audio_language); - auto burnt_in = true; - auto ccap = false; - for (auto i: content()) { - for (auto j: i->text) { - if (j->type() == TextType::OPEN_SUBTITLE && j->use() && !j->burn()) { - burnt_in = false; - } else if (j->type() == TextType::CLOSED_CAPTION && j->use()) { - ccap = true; - } - } - } + /* I'm not clear on the precise details of the convention for CCAP labelling; + for now I'm just appending -CCAP if we have any closed captions. + */ - if (!_subtitle_languages.empty()) { - auto lang = _subtitle_languages.front().language().get_value_or("en").subtag(); - if (burnt_in) { - transform (lang.begin(), lang.end(), lang.begin(), ::tolower); - } else { - transform (lang.begin(), lang.end(), lang.begin(), ::toupper); + auto burnt_in = true; + auto ccap = false; + for (auto i: content()) { + for (auto j: i->text) { + if (j->type() == TextType::OPEN_SUBTITLE && j->use() && !j->burn()) { + burnt_in = false; + } else if (j->type() == TextType::CLOSED_CAPTION && j->use()) { + ccap = true; } + } + } - d += "-" + lang; - if (ccap) { - d += "-CCAP"; - } + auto sub_langs = subtitle_languages(); + if (sub_langs.first && sub_langs.first->language()) { + auto lang = sub_langs.first->language()->subtag(); + if (burnt_in) { + transform (lang.begin(), lang.end(), lang.begin(), ::tolower); } else { - /* No subtitles */ - d += "-XX"; + lang = to_upper (lang); + } + + d += "-" + lang; + if (ccap) { + d += "-CCAP"; } + } else { + /* No subtitles */ + d += "-XX"; } - if (!dm.territory.empty ()) { - d += "_" + dm.territory; - if (dm.rating.empty ()) { + if (_release_territory) { + auto territory = _release_territory->subtag(); + d += "_" + to_upper (territory); + if (_ratings.empty ()) { d += "-NR"; } else { - d += "-" + dm.rating; + d += "-" + _ratings[0].label; } } @@ -970,8 +995,8 @@ Film::isdcf_name (bool if_created_now) const d += "_" + resolution_to_string (_resolution); - if (!dm.studio.empty ()) { - d += "_" + dm.studio; + if (_studio && _studio->length() >= 2) { + d += "_" + to_upper (_studio->substr(0, 4)); } if (if_created_now) { @@ -980,8 +1005,8 @@ Film::isdcf_name (bool if_created_now) const d += "_" + boost::gregorian::to_iso_string (_isdcf_date); } - if (!dm.facility.empty ()) { - d += "_" + dm.facility; + if (_facility && _facility->length() >= 3) { + d += "_" + to_upper(_facility->substr(0, 3)); } if (_interop) { @@ -1101,13 +1126,6 @@ Film::set_j2k_bandwidth (int b) _j2k_bandwidth = b; } -void -Film::set_isdcf_metadata (ISDCFMetadata m) -{ - FilmChangeSignaller ch (this, Property::ISDCF_METADATA); - _isdcf_metadata = m; -} - /** @param f New frame rate. * @param user_explicit true if this comes from a direct user instruction, false if it is from * DCP-o-matic being helpful. @@ -1135,9 +1153,8 @@ Film::set_three_d (bool t) FilmChangeSignaller ch (this, Property::THREE_D); _three_d = t; - if (_three_d && _isdcf_metadata.two_d_version_of_three_d) { - FilmChangeSignaller ch (this, Property::ISDCF_METADATA); - _isdcf_metadata.two_d_version_of_three_d = false; + if (_three_d && _two_d_version_of_three_d) { + set_two_d_version_of_three_d (false); } } @@ -1862,7 +1879,6 @@ Film::use_template (string name) _audio_processor = _template_film->_audio_processor; _reel_type = _template_film->_reel_type; _reel_length = _template_film->_reel_length; - _isdcf_metadata = _template_film->_isdcf_metadata; } pair @@ -2038,33 +2054,18 @@ Film::set_luminance (optional 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 languages) +Film::set_facility (optional f) { - FilmChangeSignaller ch (this, Property::SUBTITLE_LANGUAGES); - _subtitle_languages = languages; + FilmChangeSignaller ch (this, Property::FACILITY); + _facility = f; } void -Film::set_facility (optional f) +Film::set_studio (optional s) { - FilmChangeSignaller ch (this, Property::FACILITY); - _facility = f; + FilmChangeSignaller ch (this, Property::STUDIO); + _studio = s; } @@ -2125,3 +2126,36 @@ Film::add_ffoc_lfoc (Markers& markers) const markers[dcp::Marker::LFOC] = length() - DCPTime::from_frames(1, video_frame_rate()); } } + + +void +Film::set_temp_version (bool t) +{ + FilmChangeSignaller ch (this, Property::TEMP_VERSION); + _temp_version = t; +} + + +void +Film::set_pre_release (bool p) +{ + FilmChangeSignaller ch (this, Property::PRE_RELEASE); + _pre_release = p; +} + + +void +Film::set_red_band (bool r) +{ + FilmChangeSignaller ch (this, Property::RED_BAND); + _red_band = r; +} + + +void +Film::set_two_d_version_of_three_d (bool t) +{ + FilmChangeSignaller ch (this, Property::TWO_D_VERSION_OF_THREE_D); + _two_d_version_of_three_d = t; +} +