X-Git-Url: https://main.carlh.net/gitweb/?p=dcpomatic.git;a=blobdiff_plain;f=src%2Flib%2Ffilm.cc;h=90b18ea707eb3e20c043160e482b18a8704c9688;hp=4eed5e3f0d0bd412dd554850bbbec8788eff49f1;hb=386e25f3b9d3fa59cbdeed458d9b3e0d21e338b8;hpb=95ddf2cc72b800967b9917f75917cfdde325d2e5 diff --git a/src/lib/film.cc b/src/lib/film.cc index 4eed5e3f0..90b18ea70 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -93,6 +93,7 @@ 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; @@ -161,12 +162,14 @@ Film::Film (optional dir) , _user_explicit_video_frame_rate (false) , _state_version (current_state_version) , _dirty (false) + , _tolerant (false) { set_isdcf_date_today (); _playlist_change_connection = _playlist->Change.connect (bind (&Film::playlist_change, this, _1)); - _playlist_order_changed_connection = _playlist->OrderChanged.connect (bind (&Film::playlist_order_changed, this)); + _playlist_order_changed_connection = _playlist->OrderChange.connect (bind (&Film::playlist_order_changed, this)); _playlist_content_change_connection = _playlist->ContentChange.connect (bind (&Film::playlist_content_change, this, _1, _2, _3, _4)); + _playlist_length_change_connection = _playlist->LengthChange.connect (bind(&Film::playlist_length_change, this)); if (dir) { /* Make state.directory a complete path without ..s (where possible) @@ -178,7 +181,8 @@ Film::Film (optional dir) boost::filesystem::path result; for (boost::filesystem::path::iterator i = p.begin(); i != p.end(); ++i) { if (*i == "..") { - if (boost::filesystem::is_symlink (result) || result.filename() == "..") { + boost::system::error_code ec; + if (boost::filesystem::is_symlink(result, ec) || result.filename() == "..") { result /= *i; } else { result = result.parent_path (); @@ -223,7 +227,8 @@ Film::video_identifier () const + "_" + raw_convert(j2k_bandwidth()); if (encrypted ()) { - s += "_E"; + /* This is insecure but hey, the key is in plaintext in metadata.xml */ + s += "_E" + _key.hex(); } else { s += "_P"; } @@ -316,6 +321,10 @@ Film::make_dcp (bool gui, bool check) throw runtime_error (_("You must add some content to the DCP before creating it")); } + if (length() == DCPTime()) { + throw runtime_error (_("The DCP is empty, perhaps because all the content has zero length.")); + } + if (dcp_content_type() == 0) { throw MissingSettingError (_("content type")); } @@ -419,6 +428,7 @@ Film::metadata (bool with_content_paths) const BOOST_FOREACH (dcp::Rating i, _ratings) { i.as_xml (root->add_child("Rating")); } + root->add_child("ContentVersion")->add_child_text(_content_version); _playlist->as_xml (root->add_child ("Playlist"), with_content_paths); return doc; @@ -541,6 +551,13 @@ 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); @@ -555,6 +572,8 @@ Film::read_metadata (optional path) _ratings.push_back (dcp::Rating(i)); } + _content_version = f.optional_string_child("ContentVersion").get_value_or(""); + list notes; _playlist->set_from_xml (shared_from_this(), f.node_child ("Playlist"), _state_version, notes); @@ -804,14 +823,21 @@ Film::isdcf_name (bool if_created_now) const /* Count mapped audio channels */ - pair ch = audio_channel_types (mapped_audio_channels(), audio_channels()); + list mapped = mapped_audio_channels (); + + pair ch = audio_channel_types (mapped, audio_channels()); if (!ch.first && !ch.second) { d += "_MOS"; } else if (ch.first) { d += String::compose("_%1%2", ch.first, ch.second); } - /* XXX: HI/VI */ + if (audio_channels() > static_cast(dcp::HI) && find(mapped.begin(), mapped.end(), dcp::HI) != mapped.end()) { + d += "-HI"; + } + if (audio_channels() > static_cast(dcp::VI) && find(mapped.begin(), mapped.end(), dcp::VI) != mapped.end()) { + d += "-VI"; + } d += "_" + resolution_to_string (_resolution); @@ -1259,11 +1285,20 @@ Film::playlist_content_change (ChangeType type, weak_ptr c, int p, bool if (type == CHANGE_TYPE_DONE) { emit (boost::bind (boost::ref (ContentChange), type, c, p, frequent)); + if (!frequent) { + check_settings_consistency (); + } } else { ContentChange (type, c, p, frequent); } } +void +Film::playlist_length_change () +{ + LengthChange (); +} + void Film::playlist_change (ChangeType type) { @@ -1271,28 +1306,36 @@ Film::playlist_change (ChangeType type) signal_change (type, NAME); if (type == CHANGE_TYPE_DONE) { - /* Check that this change hasn't made our settings inconsistent */ - bool change_made = false; - BOOST_FOREACH (shared_ptr i, content()) { - shared_ptr d = dynamic_pointer_cast(i); - if (!d) { - continue; - } + check_settings_consistency (); + } +} - string why_not; - if (d->reference_video() && !d->can_reference_video(shared_from_this(), why_not)) { - d->set_reference_video(false); - change_made = true; - } - if (d->reference_audio() && !d->can_reference_audio(shared_from_this(), why_not)) { - d->set_reference_audio(false); - change_made = true; - } +/** Check for (and if necessary fix) impossible settings combinations, like + * video set to being referenced when it can't be. + */ +void +Film::check_settings_consistency () +{ + bool change_made = false; + BOOST_FOREACH (shared_ptr i, content()) { + shared_ptr d = dynamic_pointer_cast(i); + if (!d) { + continue; } - if (change_made) { - Message (_("DCP-o-matic had to change your settings for referring to DCPs as OV. Please review those settings to make sure they are what you want.")); + string why_not; + if (d->reference_video() && !d->can_reference_video(shared_from_this(), why_not)) { + d->set_reference_video(false); + change_made = true; } + if (d->reference_audio() && !d->can_reference_audio(shared_from_this(), why_not)) { + d->set_reference_audio(false); + change_made = true; + } + } + + if (change_made) { + Message (_("DCP-o-matic had to change your settings for referring to DCPs as OV. Please review those settings to make sure they are what you want.")); } } @@ -1578,29 +1621,29 @@ Film::reels () const break; case REELTYPE_BY_VIDEO_CONTENT: { - optional last_split; - shared_ptr last_video; - BOOST_FOREACH (shared_ptr c, content ()) { + /* Collect all reel boundaries */ + list split_points; + split_points.push_back (DCPTime()); + split_points.push_back (len); + BOOST_FOREACH (shared_ptr c, content()) { if (c->video) { BOOST_FOREACH (DCPTime t, c->reel_split_points(shared_from_this())) { - if (last_split) { - p.push_back (DCPTimePeriod (last_split.get(), t)); - } - last_split = t; + split_points.push_back (t); } - last_video = c; + split_points.push_back (c->end(shared_from_this())); } } - DCPTime video_end = last_video ? last_video->end(shared_from_this()) : DCPTime(0); - if (last_split) { - /* Definitely go from the last split to the end of the video content */ - p.push_back (DCPTimePeriod (last_split.get(), video_end)); - } + split_points.sort (); + split_points.unique (); - if (video_end < len) { - /* And maybe go after that as well if there is any non-video hanging over the end */ - p.push_back (DCPTimePeriod (video_end, len)); + /* Make them into periods */ + optional last; + BOOST_FOREACH (DCPTime t, split_points) { + if (last) { + p.push_back (DCPTimePeriod(*last, t)); + } + last = t; } break; } @@ -1730,6 +1773,13 @@ Film::set_ratings (vector r) _ratings = r; } +void +Film::set_content_version (string v) +{ + ChangeSignaller ch (this, CONTENT_VERSION); + _content_version = v; +} + optional Film::marker (dcp::Marker type) const { @@ -1739,3 +1789,37 @@ Film::marker (dcp::Marker type) const } 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); +}