X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Ffilm.cc;h=93459661be39463c8cd257ee3ac3611ea85e33f1;hb=a9dde34b8772ef8b985af067e2ff709be4e3cab6;hp=c70e82cdacb0c2890d993777779fb370d4c522ba;hpb=cd22846b748141261db1243588fe11d1a1504ce4;p=dcpomatic.git diff --git a/src/lib/film.cc b/src/lib/film.cc index c70e82cda..93459661b 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -93,12 +93,14 @@ using std::copy; using std::back_inserter; using std::map; using std::exception; +using std::find; using boost::shared_ptr; using boost::weak_ptr; using boost::dynamic_pointer_cast; using boost::optional; using boost::is_any_of; using dcp::raw_convert; +using namespace dcpomatic; string const Film::metadata_file = "metadata.xml"; @@ -160,6 +162,7 @@ Film::Film (optional dir) , _user_explicit_video_frame_rate (false) , _state_version (current_state_version) , _dirty (false) + , _tolerant (false) { set_isdcf_date_today (); @@ -296,9 +299,12 @@ Film::audio_analysis_path (shared_ptr playlist) const return p; } -/** Add suitable Jobs to the JobManager to create a DCP for this Film */ +/** Add suitable Jobs to the JobManager to create a DCP for this Film. + * @param gui true if this is being called from a GUI tool. + * @param check true to check the content in the project for changes before making the DCP. + */ void -Film::make_dcp () +Film::make_dcp (bool gui, bool check) { if (dcp_name().find ("/") != string::npos) { throw BadSettingError (_("name"), _("Cannot contain slashes")); @@ -352,8 +358,12 @@ Film::make_dcp () shared_ptr tj (new TranscodeJob (shared_from_this())); tj->set_encoder (shared_ptr (new DCPEncoder (shared_from_this(), tj))); - shared_ptr cc (new CheckContentChangeJob (shared_from_this(), tj)); - JobManager::instance()->add (cc); + if (check) { + shared_ptr cc (new CheckContentChangeJob(shared_from_this(), tj, gui)); + JobManager::instance()->add (cc); + } else { + JobManager::instance()->add (tj); + } } /** Start a job to send our DCP to the configured TMS */ @@ -403,6 +413,14 @@ Film::metadata (bool with_content_paths) const root->add_child("UploadAfterMakeDCP")->add_child_text (_upload_after_make_dcp ? "1" : "0"); root->add_child("ReencodeJ2K")->add_child_text (_reencode_j2k ? "1" : "0"); root->add_child("UserExplicitVideoFrameRate")->add_child_text(_user_explicit_video_frame_rate ? "1" : "0"); + for (map::const_iterator i = _markers.begin(); i != _markers.end(); ++i) { + xmlpp::Element* m = root->add_child("Marker"); + m->set_attribute("Type", dcp::marker_to_string(i->first)); + m->add_child_text(raw_convert(i->second.get())); + } + BOOST_FOREACH (dcp::Rating i, _ratings) { + i.as_xml (root->add_child("Rating")); + } _playlist->as_xml (root->add_child ("Playlist"), with_content_paths); return doc; @@ -478,12 +496,6 @@ Film::read_metadata (optional path) _isdcf_date = boost::gregorian::from_undelimited_string (f.string_child ("DCIDate")); } - list notes; - - if (_isdcf_metadata.has_subtitle_language) { - notes.push_back(_("This film had a subtitle language, configured within the ISDCF metadata dialogue, which will be ignored by this version of DCP-o-matic. " - "Please set the language for each piece of subtitle or closed-caption content in the film.")); - } { optional c = f.optional_string_child ("DCPContentType"); @@ -531,12 +543,28 @@ Film::read_metadata (optional path) _audio_processor = 0; } + if (_audio_processor && !Config::instance()->show_experimental_audio_processors()) { + list ap = AudioProcessor::visible(); + if (find(ap.begin(), ap.end(), _audio_processor) == ap.end()) { + Config::instance()->set_show_experimental_audio_processors(true); + } + } + _reel_type = static_cast (f.optional_number_child("ReelType").get_value_or (static_cast(REELTYPE_SINGLE))); _reel_length = f.optional_number_child("ReelLength").get_value_or (2000000000); _upload_after_make_dcp = f.optional_bool_child("UploadAfterMakeDCP").get_value_or (false); _reencode_j2k = f.optional_bool_child("ReencodeJ2K").get_value_or(false); _user_explicit_video_frame_rate = f.optional_bool_child("UserExplicitVideoFrameRate").get_value_or(false); + BOOST_FOREACH (cxml::ConstNodePtr i, f.node_children("Marker")) { + _markers[dcp::marker_from_string(i->string_attribute("Type"))] = DCPTime(dcp::raw_convert(i->content())); + } + + BOOST_FOREACH (cxml::ConstNodePtr i, f.node_children("Rating")) { + _ratings.push_back (dcp::Rating(i)); + } + + list notes; _playlist->set_from_xml (shared_from_this(), f.node_child ("Playlist"), _state_version, notes); /* Write backtraces to this film's directory, until another film is loaded */ @@ -748,7 +776,16 @@ Film::isdcf_name (bool if_created_now) const } } - if (subtitle_language) { + if (dm.subtitle_language) { + /* Subtitle language is overridden in ISDCF metadata, primarily to handle + content with pre-burnt subtitles. + */ + d += "-" + *dm.subtitle_language; + if (ccap) { + d += "-CCAP"; + } + } else if (subtitle_language) { + /* Language is worked out from the content */ if (burnt_in && *subtitle_language != "XX") { transform (subtitle_language->begin(), subtitle_language->end(), subtitle_language->begin(), ::tolower); } else { @@ -760,6 +797,7 @@ Film::isdcf_name (bool if_created_now) const d += "-CCAP"; } } else { + /* No subtitles */ d += "-XX"; } } @@ -1362,26 +1400,25 @@ Film::make_kdm ( map, dcp::Key> keys; - BOOST_FOREACH(shared_ptr i, cpl->reel_assets ()) { - shared_ptr mxf = boost::dynamic_pointer_cast (i); - if (!mxf || !mxf->key_id()) { + BOOST_FOREACH(shared_ptr i, cpl->reel_mxfs()) { + if (!i->key_id()) { continue; } /* Get any imported key for this ID */ bool done = false; BOOST_FOREACH (dcp::DecryptedKDMKey j, imported_keys) { - if (j.id() == mxf->key_id().get()) { - LOG_GENERAL ("Using imported key for %1", mxf->key_id().get()); - keys[mxf] = j.key(); + if (j.id() == i->key_id().get()) { + LOG_GENERAL ("Using imported key for %1", i->key_id().get()); + keys[i] = j.key(); done = true; } } if (!done) { /* No imported key; it must be an asset that we encrypted */ - LOG_GENERAL ("Using our own key for %1", mxf->key_id().get()); - keys[mxf] = key(); + LOG_GENERAL ("Using our own key for %1", i->key_id().get()); + keys[i] = key(); } } @@ -1399,7 +1436,7 @@ Film::make_kdm ( * @param disable_forensic_marking_audio if not set, don't disable forensic marking of audio. If set to 0, * disable all forensic marking; if set above 0, disable forensic marking above that channel. */ -list +list > Film::make_kdms ( list > screens, boost::filesystem::path cpl_file, @@ -1410,7 +1447,7 @@ Film::make_kdms ( optional disable_forensic_marking_audio ) const { - list kdms; + list > kdms; BOOST_FOREACH (shared_ptr i, screens) { if (i->recipient) { @@ -1425,7 +1462,7 @@ Film::make_kdms ( disable_forensic_marking_audio ); - kdms.push_back (ScreenKDM (i, kdm)); + kdms.push_back (shared_ptr(new DCPScreenKDM(i, kdm))); } } @@ -1680,3 +1717,68 @@ Film::closed_caption_tracks () const return tt; } + +void +Film::set_marker (dcp::Marker type, DCPTime time) +{ + ChangeSignaller ch (this, MARKERS); + _markers[type] = time; +} + +void +Film::unset_marker (dcp::Marker type) +{ + ChangeSignaller ch (this, MARKERS); + _markers.erase (type); +} + +void +Film::set_ratings (vector r) +{ + ChangeSignaller ch (this, RATINGS); + _ratings = r; +} + +optional +Film::marker (dcp::Marker type) const +{ + map::const_iterator i = _markers.find (type); + if (i == _markers.end()) { + return optional(); + } + return i->second; +} + +shared_ptr +Film::info_file_handle (DCPTimePeriod period, bool read) const +{ + return shared_ptr (new InfoFileHandle(_info_file_mutex, info_file(period), read)); +} + +InfoFileHandle::InfoFileHandle (boost::mutex& mutex, boost::filesystem::path file, bool read) + : _lock (mutex) + , _file (file) +{ + if (read) { + _handle = fopen_boost (file, "rb"); + if (!_handle) { + throw OpenFileError (file, errno, OpenFileError::READ); + } + } else { + bool const exists = boost::filesystem::exists (file); + if (exists) { + _handle = fopen_boost (file, "r+b"); + } else { + _handle = fopen_boost (file, "wb"); + } + + if (!_handle) { + throw OpenFileError (file, errno, exists ? OpenFileError::READ_WRITE : OpenFileError::WRITE); + } + } +} + +InfoFileHandle::~InfoFileHandle () +{ + fclose (_handle); +}