Basic support for trusted device lists in KDMs (#750).
[dcpomatic.git] / src / lib / film.cc
index 8cf46815020d82eb14e6b419ea3100d1e62e94f5..6c0b4d5a541a2deb32fabd851f85fcf8fc60d0f7 100644 (file)
@@ -80,6 +80,7 @@ using std::make_pair;
 using std::cout;
 using std::list;
 using std::set;
+using std::runtime_error;
 using boost::shared_ptr;
 using boost::weak_ptr;
 using boost::dynamic_pointer_cast;
@@ -291,7 +292,7 @@ Film::make_dcp ()
        }
 
        if (content().empty()) {
-               throw StringError (_("You must add some content to the DCP before creating it"));
+               throw runtime_error (_("You must add some content to the DCP before creating it"));
        }
 
        if (dcp_content_type() == 0) {
@@ -370,7 +371,7 @@ list<string>
 Film::read_metadata ()
 {
        if (boost::filesystem::exists (file ("metadata")) && !boost::filesystem::exists (file ("metadata.xml"))) {
-               throw StringError (_("This film was created with an older version of DCP-o-matic, and unfortunately it cannot be loaded into this version.  You will need to create a new Film, re-add your content and set it up again.  Sorry!"));
+               throw runtime_error (_("This film was created with an older version of DCP-o-matic, and unfortunately it cannot be loaded into this version.  You will need to create a new Film, re-add your content and set it up again.  Sorry!"));
        }
 
        cxml::Document f ("Metadata");
@@ -378,7 +379,7 @@ Film::read_metadata ()
 
        _state_version = f.number_child<int> ("Version");
        if (_state_version > current_state_version) {
-               throw StringError (_("This film was created with a newer version of DCP-o-matic, and it cannot be loaded into this version.  Sorry!"));
+               throw runtime_error (_("This film was created with a newer version of DCP-o-matic, and it cannot be loaded into this version.  Sorry!"));
        }
 
        _name = f.string_child ("Name");
@@ -864,7 +865,7 @@ Film::set_isdcf_date_today ()
 }
 
 boost::filesystem::path
-Film::j2c_path (int f, Eyes e, bool t) const
+Film::j2c_path (int reel, Frame frame, Eyes eyes, bool tmp) const
 {
        boost::filesystem::path p;
        p /= "j2c";
@@ -872,17 +873,17 @@ Film::j2c_path (int f, Eyes e, bool t) const
 
        SafeStringStream s;
        s.width (8);
-       s << setfill('0') << f;
+       s << setfill('0') << reel << "_" << frame;
 
-       if (e == EYES_LEFT) {
+       if (eyes == EYES_LEFT) {
                s << ".L";
-       } else if (e == EYES_RIGHT) {
+       } else if (eyes == EYES_RIGHT) {
                s << ".R";
        }
 
        s << ".j2c";
 
-       if (t) {
+       if (tmp) {
                s << ".tmp";
        }
 
@@ -1112,7 +1113,8 @@ Film::frame_size () const
 
 dcp::EncryptedKDM
 Film::make_kdm (
-       dcp::Certificate target,
+       dcp::Certificate recipient,
+       vector<dcp::Certificate> trusted_devices,
        boost::filesystem::path cpl_file,
        dcp::LocalTime from,
        dcp::LocalTime until,
@@ -1127,7 +1129,7 @@ Film::make_kdm (
 
        return dcp::DecryptedKDM (
                cpl, key(), from, until, "DCP-o-matic", cpl->content_title_text(), dcp::LocalTime().as_string()
-               ).encrypt (signer, target, formulation);
+               ).encrypt (signer, recipient, trusted_devices, formulation);
 }
 
 list<ScreenKDM>
@@ -1142,8 +1144,8 @@ Film::make_kdms (
        list<ScreenKDM> kdms;
 
        BOOST_FOREACH (shared_ptr<Screen> i, screens) {
-               if (i->certificate) {
-                       kdms.push_back (ScreenKDM (i, make_kdm (i->certificate.get(), dcp, from, until, formulation)));
+               if (i->recipient) {
+                       kdms.push_back (ScreenKDM (i, make_kdm (i->recipient.get(), i->trusted_devices, dcp, from, until, formulation)));
                }
        }
 
@@ -1252,6 +1254,8 @@ Film::audio_output_names () const
                return audio_processor()->input_names ();
        }
 
+       DCPOMATIC_ASSERT (MAX_DCP_AUDIO_CHANNELS == 16);
+
        vector<string> n;
        n.push_back (_("L"));
        n.push_back (_("R"));
@@ -1265,6 +1269,10 @@ Film::audio_output_names () const
        n.push_back (_("Rc"));
        n.push_back (_("BsL"));
        n.push_back (_("BsR"));
+       n.push_back (_("DBP"));
+       n.push_back (_("DBS"));
+       n.push_back (_("NC"));
+       n.push_back (_("NC"));
 
        return vector<string> (n.begin(), n.begin() + audio_channels ());
 }
@@ -1291,26 +1299,39 @@ list<DCPTimePeriod>
 Film::reels () const
 {
        list<DCPTimePeriod> p;
-       DCPTime const len = length ();
+       DCPTime const len = length().round_up (video_frame_rate ());
 
        switch (reel_type ()) {
        case REELTYPE_SINGLE:
                p.push_back (DCPTimePeriod (DCPTime (), len));
                break;
-       case REELTYPE_ONE_PER_VIDEO:
+       case REELTYPE_BY_VIDEO_CONTENT:
        {
-               optional<DCPTime> last;
+               optional<DCPTime> last_split;
+               shared_ptr<VideoContent> last_video;
+               ContentList cl = content ();
                BOOST_FOREACH (shared_ptr<Content> c, content ()) {
                        shared_ptr<VideoContent> v = dynamic_pointer_cast<VideoContent> (c);
                        if (v) {
-                               if (last) {
-                                       p.push_back (DCPTimePeriod (last.get(), v->position ()));
+                               BOOST_FOREACH (DCPTime t, v->reel_split_points()) {
+                                       if (last_split) {
+                                               p.push_back (DCPTimePeriod (last_split.get(), t));
+                                       }
+                                       last_split = t;
                                }
-                               last = v->position ();
+                               last_video = v;
                        }
                }
-               if (last) {
-                       p.push_back (DCPTimePeriod (last.get(), len));
+
+               DCPTime video_end = last_video ? last_video->end() : 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));
+               }
+
+               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));
                }
                break;
        }
@@ -1330,4 +1351,3 @@ Film::reels () const
 
        return p;
 }
-