X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Ffilm.cc;h=f61d5106f14e42c5a60e71d015ed1221d015c152;hb=74873babf8ed3ffb3dd79858328d5b3f142479a3;hp=8080b9921ee4e0a32b44fd3797fa925230fcb7b8;hpb=bd68f5a27795cb9151633bac810c53bae4ec4bf4;p=dcpomatic.git diff --git a/src/lib/film.cc b/src/lib/film.cc index 8080b9921..f61d5106f 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2018 Carl Hetherington + Copyright (C) 2012-2019 Carl Hetherington This file is part of DCP-o-matic. @@ -92,6 +92,7 @@ using std::runtime_error; using std::copy; using std::back_inserter; using std::map; +using std::exception; using boost::shared_ptr; using boost::weak_ptr; using boost::dynamic_pointer_cast; @@ -156,6 +157,7 @@ Film::Film (optional dir) , _reel_length (2000000000) , _upload_after_make_dcp (Config::instance()->default_upload_after_make_dcp()) , _reencode_j2k (false) + , _user_explicit_video_frame_rate (false) , _state_version (current_state_version) , _dirty (false) { @@ -400,6 +402,7 @@ Film::metadata (bool with_content_paths) const root->add_child("ReelLength")->add_child_text (raw_convert (_reel_length)); 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"); _playlist->as_xml (root->add_child ("Playlist"), with_content_paths); return doc; @@ -452,6 +455,16 @@ Film::read_metadata (optional path) _state_version = f.number_child ("Version"); if (_state_version > current_state_version) { throw runtime_error (_("This film was created with a newer version of DCP-o-matic, and it cannot be loaded into this version. Sorry!")); + } else if (_state_version < current_state_version) { + /* This is an older version; save a copy (if we haven't already) */ + boost::filesystem::path const older = path->parent_path() / String::compose("metadata.%1.xml", _state_version); + if (!boost::filesystem::is_regular_file(older)) { + try { + boost::filesystem::copy_file(*path, older); + } catch (...) { + /* Never mind; at least we tried */ + } + } } _name = f.string_child ("Name"); @@ -515,6 +528,7 @@ Film::read_metadata (optional path) _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); list notes; /* This method is the only one that can return notes (so far) */ @@ -883,11 +897,18 @@ Film::set_isdcf_metadata (ISDCFMetadata m) _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. + */ void -Film::set_video_frame_rate (int f) +Film::set_video_frame_rate (int f, bool user_explicit) { ChangeSignaller ch (this, VIDEO_FRAME_RATE); _video_frame_rate = f; + if (user_explicit) { + _user_explicit_video_frame_rate = true; + } } void @@ -966,7 +987,9 @@ Film::signal_change (ChangeType type, Property p) _dirty = true; if (p == Film::CONTENT) { - set_video_frame_rate (_playlist->best_video_frame_rate ()); + if (!_user_explicit_video_frame_rate) { + set_video_frame_rate (best_video_frame_rate()); + } } emit (boost::bind (boost::ref (Change), type, p)); @@ -1015,7 +1038,16 @@ Film::j2c_path (int reel, Frame frame, Eyes eyes, bool tmp) const return file (p); } -/** Find all the DCPs in our directory that can be dcp::DCP::read() and return details of their CPLs */ +static +bool +cpl_summary_compare (CPLSummary const & a, CPLSummary const & b) +{ + return a.last_write_time > b.last_write_time; +} + +/** Find all the DCPs in our directory that can be dcp::DCP::read() and return details of their CPLs. + * The list will be returned in reverse order of timestamp (i.e. most recent first). + */ vector Film::cpls () const { @@ -1033,23 +1065,15 @@ Film::cpls () const ) { try { - dcp::DCP dcp (*i); - dcp.read (); - DCPOMATIC_ASSERT (dcp.cpls().front()->file()); - out.push_back ( - CPLSummary ( - i->path().leaf().string(), - dcp.cpls().front()->id(), - dcp.cpls().front()->annotation_text(), - dcp.cpls().front()->file().get() - ) - ); + out.push_back (CPLSummary(*i)); } catch (...) { } } } + sort (out.begin(), out.end(), cpl_summary_compare); + return out; } @@ -1173,7 +1197,12 @@ Film::length () const int Film::best_video_frame_rate () const { - return _playlist->best_video_frame_rate (); + /* Don't default to anything above 30fps (make the user select that explicitly) */ + int best = _playlist->best_video_frame_rate (); + if (best > 30) { + best /= 2; + } + return best; } FrameRateChange @@ -1203,6 +1232,31 @@ Film::playlist_change (ChangeType type) { signal_change (type, CONTENT); 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; + } + + 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.")); + } + } } void @@ -1382,7 +1436,7 @@ Film::required_disk_space () const /** This method checks the disk that the Film is on and tries to decide whether or not * there will be enough space to make a DCP for it. If so, true is returned; if not, * false is returned and required and available are filled in with the amount of disk space - * required and available respectively (in Gb). + * required and available respectively (in GB). * * Note: the decision made by this method isn't, of course, 100% reliable. */