/*
- Copyright (C) 2012-2018 Carl Hetherington <cth@carlh.net>
+ Copyright (C) 2012-2019 Carl Hetherington <cth@carlh.net>
This file is part of DCP-o-matic.
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;
, _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)
{
root->add_child("ReelLength")->add_child_text (raw_convert<string> (_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;
_state_version = f.number_child<int> ("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");
_reel_length = f.optional_number_child<int64_t>("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<string> notes;
/* This method is the only one that can return notes (so far) */
_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<Film> ch (this, VIDEO_FRAME_RATE);
_video_frame_rate = f;
+ if (user_explicit) {
+ _user_explicit_video_frame_rate = true;
+ }
}
void
_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));
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<CPLSummary>
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;
}
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
{
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<Content> i, content()) {
+ shared_ptr<DCPContent> d = dynamic_pointer_cast<DCPContent>(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
/** 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.
*/