Check consistency of refer-to-DCP settings after adding content (#1456).
[dcpomatic.git] / src / lib / film.cc
index cbf08aa498075986b7670bf03081888c2b0cf00e..e7861a032c12ce1a3688454b0febe533e827b4cb 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    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.
 
@@ -156,6 +156,7 @@ Film::Film (optional<boost::filesystem::path> 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)
 {
@@ -288,6 +289,8 @@ Film::audio_analysis_path (shared_ptr<const Playlist> playlist) const
                digester.add (audio_processor()->id ());
        }
 
+       digester.add (audio_channels());
+
        p /= digester.get ();
        return p;
 }
@@ -398,6 +401,7 @@ Film::metadata (bool with_content_paths) const
        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;
@@ -513,6 +517,7 @@ Film::read_metadata (optional<boost::filesystem::path> path)
        _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) */
@@ -881,11 +886,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<Film> ch (this, VIDEO_FRAME_RATE);
        _video_frame_rate = f;
+       if (user_explicit) {
+               _user_explicit_video_frame_rate = true;
+       }
 }
 
 void
@@ -964,7 +976,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));
@@ -1171,7 +1185,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
@@ -1201,6 +1220,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<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
@@ -1213,12 +1257,9 @@ Film::playlist_order_changed ()
 int
 Film::audio_frame_rate () const
 {
-       BOOST_FOREACH (shared_ptr<Content> i, content ()) {
-               if (i->audio && i->audio->has_rate_above_48k ()) {
-                       return 96000;
-               }
-       }
-
+       /* It seems that nobody makes 96kHz DCPs at the moment, so let's avoid them.
+          See #1436.
+       */
        return 48000;
 }
 
@@ -1383,7 +1424,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.
  */