Various Doxygen fixes.
[dcpomatic.git] / src / lib / film.cc
index b337c50deffd70894fea9c2b9da1cb21476213b3..82a40d5c4390eec070a47ba42b562793a60af8a6 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2017 Carl Hetherington <cth@carlh.net>
 
     This file is part of DCP-o-matic.
 
@@ -57,6 +57,8 @@
 #include <dcp/local_time.h>
 #include <dcp/decrypted_kdm.h>
 #include <dcp/raw_convert.h>
+#include <dcp/reel_mxf.h>
+#include <dcp/reel_asset.h>
 #include <libxml++/libxml++.h>
 #include <boost/filesystem.hpp>
 #include <boost/algorithm/string.hpp>
@@ -83,6 +85,9 @@ using std::cout;
 using std::list;
 using std::set;
 using std::runtime_error;
+using std::copy;
+using std::back_inserter;
+using std::map;
 using boost::shared_ptr;
 using boost::weak_ptr;
 using boost::dynamic_pointer_cast;
@@ -293,7 +298,7 @@ Film::make_dcp ()
        }
 
        if (content().empty()) {
-               throw runtime_error (_("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) {
@@ -306,14 +311,14 @@ Film::make_dcp ()
 
        BOOST_FOREACH (shared_ptr<const Content> i, content ()) {
                if (!i->paths_valid()) {
-                       throw runtime_error (_("some of your content is missing."));
+                       throw runtime_error (_("some of your content is missing"));
                }
                shared_ptr<const DCPContent> dcp = dynamic_pointer_cast<const DCPContent> (i);
                if (dcp && dcp->needs_kdm()) {
-                       throw runtime_error (_("some of your content needs a KDM."));
+                       throw runtime_error (_("some of your content needs a KDM"));
                }
                if (dcp && dcp->needs_assets()) {
-                       throw runtime_error (_("some of your content needs an OV."));
+                       throw runtime_error (_("some of your content needs an OV"));
                }
        }
 
@@ -504,10 +509,11 @@ Film::read_metadata (optional<boost::filesystem::path> path)
 }
 
 /** Given a directory name, return its full path within the Film's directory.
- *  The directory (and its parents) will be created if they do not exist.
+ *  @param d directory name within the Filn's directory.
+ *  @param create true to create the directory (and its parents) if they do not exist.
  */
 boost::filesystem::path
-Film::dir (boost::filesystem::path d) const
+Film::dir (boost::filesystem::path d, bool create) const
 {
        DCPOMATIC_ASSERT (_directory);
 
@@ -515,7 +521,9 @@ Film::dir (boost::filesystem::path d) const
        p /= _directory.get();
        p /= d;
 
-       boost::filesystem::create_directories (p);
+       if (create) {
+               boost::filesystem::create_directories (p);
+       }
 
        return p;
 }
@@ -786,24 +794,10 @@ Film::dcp_name (bool if_created_now) const
 {
        string unfiltered;
        if (use_isdcf_name()) {
-               unfiltered = isdcf_name (if_created_now);
-       } else {
-               unfiltered = name ();
-       }
-
-       /* Filter out `bad' characters which cause problems with some systems.
-          There's no apparent list of what really is allowed, so this is a guess.
-       */
-
-       string filtered;
-       string const allowed = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_";
-       for (size_t i = 0; i < unfiltered.size(); ++i) {
-               if (allowed.find (unfiltered[i]) != string::npos) {
-                       filtered += unfiltered[i];
-               }
+               return careful_string_filter (isdcf_name (if_created_now));
        }
 
-       return filtered;
+       return careful_string_filter (name ());
 }
 
 void
@@ -1213,8 +1207,12 @@ Film::frame_size () const
        return fit_ratio_within (container()->ratio(), full_frame ());
 }
 
-/** @param from KDM from time expressed as a local time with an offset from UTC
- *  @param to KDM to time expressed as a local time with an offset from UTC
+/** @param recipient KDM recipient certificate.
+ *  @param trusted_devices Certificates of other trusted devices (can be empty).
+ *  @param cpl_file CPL filename.
+ *  @param from KDM from time expressed as a local time with an offset from UTC.
+ *  @param until KDM to time expressed as a local time with an offset from UTC.
+ *  @param formulation KDM formulation to use.
  */
 dcp::EncryptedKDM
 Film::make_kdm (
@@ -1232,18 +1230,57 @@ Film::make_kdm (
                throw InvalidSignerError ();
        }
 
+       /* Find keys that have been added to imported, encrypted DCP content */
+       list<dcp::DecryptedKDMKey> imported_keys;
+       BOOST_FOREACH (shared_ptr<Content> i, content()) {
+               shared_ptr<DCPContent> d = dynamic_pointer_cast<DCPContent> (i);
+               if (d && d->kdm()) {
+                       dcp::DecryptedKDM kdm (d->kdm().get(), Config::instance()->decryption_chain()->key().get());
+                       list<dcp::DecryptedKDMKey> keys = kdm.keys ();
+                       copy (keys.begin(), keys.end(), back_inserter (imported_keys));
+               }
+       }
+
+       map<shared_ptr<const dcp::ReelMXF>, dcp::Key> keys;
+
+       BOOST_FOREACH(shared_ptr<const dcp::ReelAsset> i, cpl->reel_assets ()) {
+               shared_ptr<const dcp::ReelMXF> mxf = boost::dynamic_pointer_cast<const dcp::ReelMXF> (i);
+               if (!mxf || !mxf->key_id()) {
+                       continue;
+               }
+
+               /* Get any imported key for this ID */
+               bool done = false;
+               BOOST_FOREACH (dcp::DecryptedKDMKey j, imported_keys) {
+                       if (j.id() == mxf->key_id().get()) {
+                               LOG_GENERAL ("Using imported key for %1", mxf->key_id().get());
+                               keys[mxf] = j.key();
+                               done = true;
+                       }
+               }
+
+               if (!done) {
+                       /* No imported key; it must be an asset that we encrypted */
+                       LOG_GENERAL ("Using our own key for %1", mxf->key_id().get());
+                       keys[mxf] = key();
+               }
+       }
+
        return dcp::DecryptedKDM (
-               cpl, key(), from, until, cpl->content_title_text(), cpl->content_title_text(), dcp::LocalTime().as_string()
+               cpl->id(), keys, from, until, cpl->content_title_text(), cpl->content_title_text(), dcp::LocalTime().as_string()
                ).encrypt (signer, recipient, trusted_devices, formulation);
 }
 
-/** @param from KDM from time expressed as a local time in the time zone of the Screen's Cinema.
- *  @param to KDM to time expressed as a local time in the time zone of the Screen's Cinema.
+/** @param screens Screens to make KDMs for.
+ *  @param cpl_file Path to CPL to make KDMs for.
+ *  @param from KDM from time expressed as a local time in the time zone of the Screen's Cinema.
+ *  @param until KDM to time expressed as a local time in the time zone of the Screen's Cinema.
+ *  @param formulation KDM formulation to use.
  */
 list<ScreenKDM>
 Film::make_kdms (
        list<shared_ptr<Screen> > screens,
-       boost::filesystem::path dcp,
+       boost::filesystem::path cpl_file,
        boost::posix_time::ptime from,
        boost::posix_time::ptime until,
        dcp::Formulation formulation
@@ -1256,7 +1293,7 @@ Film::make_kdms (
                        dcp::EncryptedKDM const kdm = make_kdm (
                                i->recipient.get(),
                                i->trusted_devices,
-                               dcp,
+                               cpl_file,
                                dcp::LocalTime (from, i->cinema->utc_offset_hour(), i->cinema->utc_offset_minute()),
                                dcp::LocalTime (until, i->cinema->utc_offset_hour(), i->cinema->utc_offset_minute()),
                                formulation
@@ -1480,6 +1517,9 @@ Film::reels () const
        return p;
 }
 
+/** @param period A period within the DCP
+ *  @return Name of the content which most contributes to the given period.
+ */
 string
 Film::content_summary (DCPTimePeriod period) const
 {