Various KDM and encryption fixes.
authorCarl Hetherington <cth@carlh.net>
Thu, 19 Sep 2013 20:39:01 +0000 (21:39 +0100)
committerCarl Hetherington <cth@carlh.net>
Thu, 19 Sep 2013 20:39:01 +0000 (21:39 +0100)
src/lib/cinema.h
src/lib/config.cc
src/lib/config.h
src/lib/film.cc
src/lib/film.h
src/lib/util.cc
src/lib/util.h
src/lib/writer.cc
src/lib/wscript
src/wx/kdm_dialog.cc
src/wx/screen_dialog.cc

index 6f426ae8d66630eab59f1788e71535a24dfaed39..251bb5d6131e3869d12f7cecfb5b92358a2d1db2 100644 (file)
@@ -1,5 +1,31 @@
+/*
+    Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include <boost/enable_shared_from_this.hpp>
 #include <libdcp/certificates.h>
 
+class Cinema;
+
+namespace cxml {
+       class Node;
+}
+
 class Screen
 {
 public:
@@ -7,20 +33,37 @@ public:
                : name (n)
                , certificate (cert)
        {}
+
+       Screen (boost::shared_ptr<const cxml::Node>);
+
+       void as_xml (xmlpp::Element *) const;
        
+       boost::shared_ptr<Cinema> cinema;
        std::string name;
        boost::shared_ptr<libdcp::Certificate> certificate;
 };
 
-class Cinema
+class Cinema : public boost::enable_shared_from_this<Cinema>
 {
 public:
        Cinema (std::string const & n, std::string const & e)
                : name (n)
                , email (e)
        {}
+
+       Cinema (boost::shared_ptr<const cxml::Node>);
+
+       void as_xml (xmlpp::Element *) const;
+
+       void add_screen (boost::shared_ptr<Screen>);
+       void remove_screen (boost::shared_ptr<Screen>);
        
        std::string name;
        std::string email;
-       std::list<boost::shared_ptr<Screen> > screens;
+       std::list<boost::shared_ptr<Screen> > screens () const {
+               return _screens;
+       }
+
+private:       
+       std::list<boost::shared_ptr<Screen> > _screens;
 };
index 7d945c8979e904a0db44953f8110fefd68645c6a..a72e1a9e43fa9c91bd9fb6919c542e357ca04450 100644 (file)
@@ -32,6 +32,7 @@
 #include "dcp_content_type.h"
 #include "sound_processor.h"
 #include "colour_conversion.h"
+#include "cinema.h"
 
 #include "i18n.h"
 
@@ -128,6 +129,11 @@ Config::read ()
        for (list<shared_ptr<cxml::Node> >::iterator i = cc.begin(); i != cc.end(); ++i) {
                _colour_conversions.push_back (PresetColourConversion (*i));
        }
+
+       list<shared_ptr<cxml::Node> > cin = f.node_children ("Cinema");
+       for (list<shared_ptr<cxml::Node> >::iterator i = cin.begin(); i != cin.end(); ++i) {
+               _cinemas.push_back (shared_ptr<Cinema> (new Cinema (*i)));
+       }
 }
 
 void
@@ -280,6 +286,10 @@ Config::write () const
                i->as_xml (root->add_child ("ColourConversion"));
        }
 
+       for (list<shared_ptr<Cinema> >::const_iterator i = _cinemas.begin(); i != _cinemas.end(); ++i) {
+               (*i)->as_xml (root->add_child ("Cinema"));
+       }
+
        doc.write_to_file_formatted (file(false).string ());
 }
 
index 8c80f96799a202d52a9b83e0e9d5fa83c3603439..3e8a975d6fcb4330c90edafda325168f8648717e 100644 (file)
@@ -275,7 +275,6 @@ private:
        libdcp::XMLMetadata _dcp_metadata;
        int _default_j2k_bandwidth;
        std::vector<PresetColourConversion> _colour_conversions;
-
        std::list<boost::shared_ptr<Cinema> > _cinemas;
 
        /** Singleton instance, or 0 */
index aacc5a4ccaa9ba241ba403a3ff9e246b6b016af8..1e76dac2cab8e8b900100ca1fb0b73fe82a6aec0 100644 (file)
@@ -96,10 +96,10 @@ Film::Film (boost::filesystem::path dir)
        , _resolution (RESOLUTION_2K)
        , _scaler (Scaler::from_id ("bicubic"))
        , _with_subtitles (false)
+       , _encrypted (false)
        , _j2k_bandwidth (Config::instance()->default_j2k_bandwidth ())
        , _dci_metadata (Config::instance()->default_dci_metadata ())
        , _video_frame_rate (24)
-       , _encrypted (false)
        , _audio_channels (MAX_AUDIO_CHANNELS)
        , _three_d (false)
        , _sequence_video (true)
@@ -346,6 +346,7 @@ Film::write_metadata () const
        root->add_child("SequenceVideo")->add_child_text (_sequence_video ? "1" : "0");
        root->add_child("Interop")->add_child_text (_interop ? "1" : "0");
        root->add_child("Encrypted")->add_child_text (_encrypted ? "1" : "0");
+       root->add_child("Key")->add_child_text (_key.hex ());
        _playlist->as_xml (root->add_child ("Playlist"));
 
        doc.write_to_file_formatted (file ("metadata.xml"));
@@ -395,7 +396,7 @@ Film::read_metadata ()
        _sequence_video = f.bool_child ("SequenceVideo");
        _three_d = f.bool_child ("ThreeD");
        _interop = f.bool_child ("Interop");
-
+       _key = libdcp::Key (f.string_child ("Key"));
        _playlist->set_from_xml (shared_from_this(), f.node_child ("Playlist"));
 
        _dirty = false;
@@ -910,19 +911,19 @@ Film::make_kdms (
        {
                boost::filesystem::path p (sd);
                p /= "ca.self-signed.pem";
-               chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate (p.string ())));
+               chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate (p)));
        }
 
        {
                boost::filesystem::path p (sd);
                p /= "intermediate.signed.pem";
-               chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate (p.string ())));
+               chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate (p)));
        }
 
        {
                boost::filesystem::path p (sd);
                p /= "leaf.signed.pem";
-               chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate (p.string ())));
+               chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate (p)));
        }
 
        boost::filesystem::path signer_key (sd);
@@ -950,12 +951,12 @@ Film::make_kdms (
                libdcp::DCP dcp (dcps.front ());
                dcp.read ();
                
-               /* XXX: single CPL only */
                shared_ptr<xmlpp::Document> kdm = dcp.cpls().front()->make_kdm (
                        signer, (*i)->certificate, from, until, _interop, libdcp::MXFMetadata (), Config::instance()->dcp_metadata ()
                        );
 
                boost::filesystem::path out = directory;
+               out /= tidy_for_filename ((*i)->cinema->name) + "_" + tidy_for_filename ((*i)->name);
                out /= "kdm.xml";
                kdm->write_to_file_formatted (out.string());
        }
index 809eabdaa9a1257cae980be9ce68a2c0b78e8452..26623e69eb401bff6ab5948980527ab07fda6566 100644 (file)
@@ -31,6 +31,7 @@
 #include <boost/signals2.hpp>
 #include <boost/enable_shared_from_this.hpp>
 #include <boost/filesystem.hpp>
+#include <libdcp/key.h>
 #include "util.h"
 #include "types.h"
 #include "dci_metadata.h"
@@ -121,6 +122,10 @@ public:
                std::string directory
                ) const;
 
+       libdcp::Key key () const {
+               return _key;
+       }
+
        /** Identifiers for the parts of our state;
            used for signalling changes.
        */
@@ -296,6 +301,7 @@ private:
        bool _three_d;
        bool _sequence_video;
        bool _interop;
+       libdcp::Key _key;
 
        /** true if our state has changed since we last saved it */
        mutable bool _dirty;
index b8bc1fc9e467680646f924c2ab3385d195911efb..4e4493ac785ba1edecb3bdd68a2df1f6c03af676 100644 (file)
@@ -800,3 +800,18 @@ valid_image_file (boost::filesystem::path f)
        return (ext == ".tif" || ext == ".tiff" || ext == ".jpg" || ext == ".jpeg" || ext == ".png" || ext == ".bmp" || ext == ".tga");
 }
 
+string
+tidy_for_filename (string f)
+{
+       string t;
+       for (size_t i = 0; i < f.length(); ++i) {
+               if (isalpha (f[i]) || f[i] == '_' || f[i] == '-') {
+                       t += f[i];
+               } else {
+                       t += '_';
+               }
+       }
+
+       return t;
+}
+       
index a83426206f88e7398423a152b408573cb31066cb..b5c94d994e3e5e81870a53722ead1b46743a3640 100644 (file)
@@ -70,6 +70,7 @@ extern bool valid_image_file (boost::filesystem::path);
 #ifdef DCPOMATIC_WINDOWS
 extern boost::filesystem::path mo_path ();
 #endif
+extern std::string tidy_for_filename (std::string);
 
 struct FrameRateConversion
 {
index 4f93373f7d6094659a75a0600c395a7154e9c689..37376ca2309d20c5dd6b5ad1bf1e53d507b25f5e 100644 (file)
@@ -79,8 +79,7 @@ Writer::Writer (shared_ptr<const Film> f, shared_ptr<Job> j)
                                _film->internal_video_mxf_dir (),
                                _film->internal_video_mxf_filename (),
                                _film->video_frame_rate (),
-                               _film->container()->size (_film->full_frame ()),
-                               _film->encrypted ()
+                               _film->container()->size (_film->full_frame ())
                                )
                        );
                
@@ -90,13 +89,16 @@ Writer::Writer (shared_ptr<const Film> f, shared_ptr<Job> j)
                                _film->internal_video_mxf_dir (),
                                _film->internal_video_mxf_filename (),
                                _film->video_frame_rate (),
-                               _film->container()->size (_film->full_frame ()),
-                               _film->encrypted ()
+                               _film->container()->size (_film->full_frame ())
                                )
                        );
 
        }
 
+       if (_film->encrypted ()) {
+               _picture_asset->set_key (_film->key ());
+       }
+       
        _picture_asset_writer = _picture_asset->start_write (_first_nonexistant_frame > 0, _film->interop ());
        
        _sound_asset.reset (
@@ -105,10 +107,13 @@ Writer::Writer (shared_ptr<const Film> f, shared_ptr<Job> j)
                        _film->audio_mxf_filename (),
                        _film->video_frame_rate (),
                        _film->audio_channels (),
-                       _film->audio_frame_rate (),
-                       _film->encrypted ()
+                       _film->audio_frame_rate ()
                        )
                );
+
+       if (_film->encrypted ()) {
+               _sound_asset->set_key (_film->key ());
+       }
        
        _sound_asset_writer = _sound_asset->start_write (_film->interop ());
 
index 6c45d8b1ed3cdf5d4731f444385b9e6a8f733400..e91666f7f31929dcc3a2abe579531029f9410718 100644 (file)
@@ -8,6 +8,7 @@ sources = """
           audio_content.cc
           audio_decoder.cc
           audio_mapping.cc
+          cinema.cc
           colour_conversion.cc
           config.cc
           content.cc
index a9f63cffce971e06dd65a8d1c9d6d2f0cbab2a29..c8db016aa4badb582a6401ebffbef43afb033eb1 100644 (file)
@@ -183,7 +183,8 @@ KDMDialog::add_cinema (shared_ptr<Cinema> c)
 {
        _cinemas[_targets->AppendItem (_root, std_to_wx (c->name))] = c;
 
-       for (list<shared_ptr<Screen> >::iterator i = c->screens.begin(); i != c->screens.end(); ++i) {
+       list<shared_ptr<Screen> > sc = c->screens ();
+       for (list<shared_ptr<Screen> >::iterator i = sc.begin(); i != sc.end(); ++i) {
                add_screen (c, *i);
        }
 }
@@ -267,7 +268,7 @@ KDMDialog::add_screen_clicked (wxCommandEvent &)
        d->ShowModal ();
 
        shared_ptr<Screen> s (new Screen (d->name(), d->certificate()));
-       c->screens.push_back (s);
+       c->add_screen (s);
        add_screen (c, s);
 
        Config::instance()->write ();
@@ -306,7 +307,8 @@ KDMDialog::remove_screen_clicked (wxCommandEvent &)
        pair<wxTreeItemId, shared_ptr<Screen> > s = selected_screens().front();
 
        map<wxTreeItemId, shared_ptr<Cinema> >::iterator i = _cinemas.begin ();
-       while (i != _cinemas.end() && find (i->second->screens.begin(), i->second->screens.end(), s.second) == i->second->screens.end()) {
+       list<shared_ptr<Screen> > sc = i->second->screens ();
+       while (i != _cinemas.end() && find (sc.begin(), sc.end(), s.second) == sc.end()) {
                ++i;
        }
 
@@ -314,7 +316,7 @@ KDMDialog::remove_screen_clicked (wxCommandEvent &)
                return;
        }
 
-       i->second->screens.remove (s.second);
+       i->second->remove_screen (s.second);
        _targets->Delete (s.first);
 
        Config::instance()->write ();
@@ -327,7 +329,8 @@ KDMDialog::screens () const
 
        list<pair<wxTreeItemId, shared_ptr<Cinema> > > cinemas = selected_cinemas ();
        for (list<pair<wxTreeItemId, shared_ptr<Cinema> > >::iterator i = cinemas.begin(); i != cinemas.end(); ++i) {
-               for (list<shared_ptr<Screen> >::iterator j = i->second->screens.begin(); j != i->second->screens.end(); ++j) {
+               list<shared_ptr<Screen> > sc = i->second->screens ();
+               for (list<shared_ptr<Screen> >::const_iterator j = sc.begin(); j != sc.end(); ++j) {
                        s.push_back (*j);
                }
        }
index 7ff5197137cd27e6d06c25e3d0326fb684d34bf0..6584e1ad6e92ba1b8a04a34ab761efdfa332b03b 100644 (file)
@@ -84,14 +84,15 @@ void
 ScreenDialog::load_certificate (wxCommandEvent &)
 {
        wxFileDialog* d = new wxFileDialog (this, _("Select Certificate File"));
-       d->ShowModal ();
-       
-       try {
-               _certificate.reset (new libdcp::Certificate (wx_to_std (d->GetPath ())));
-               _certificate_text->SetValue (_certificate->certificate ());
-       } catch (libdcp::MiscError& e) {
-               error_dialog (this, String::compose ("Could not read certificate file (%1)", e.what()));
-       }
 
+       if (d->ShowModal () == wxID_OK) {
+               try {
+                       _certificate.reset (new libdcp::Certificate (boost::filesystem::path (wx_to_std (d->GetPath ()))));
+                       _certificate_text->SetValue (_certificate->certificate ());
+               } catch (libdcp::MiscError& e) {
+                       error_dialog (this, String::compose ("Could not read certificate file (%1)", e.what()));
+               }
+       }
+       
        d->Destroy ();
 }