Merge 1.0 in.
authorCarl Hetherington <cth@carlh.net>
Tue, 17 Sep 2013 22:39:05 +0000 (23:39 +0100)
committerCarl Hetherington <cth@carlh.net>
Tue, 17 Sep 2013 22:39:05 +0000 (23:39 +0100)
18 files changed:
src/lib/cinema.h [new file with mode: 0644]
src/lib/config.cc
src/lib/config.h
src/lib/exceptions.h
src/lib/film.cc
src/lib/film.h
src/lib/make_dcp_job.cc [new file with mode: 0644]
src/lib/util.cc
src/tools/dcpomatic.cc
src/wx/cinema_dialog.cc [new file with mode: 0644]
src/wx/cinema_dialog.h [new file with mode: 0644]
src/wx/film_editor.cc
src/wx/film_editor.h
src/wx/kdm_dialog.cc [new file with mode: 0644]
src/wx/kdm_dialog.h [new file with mode: 0644]
src/wx/screen_dialog.cc [new file with mode: 0644]
src/wx/screen_dialog.h [new file with mode: 0644]
src/wx/wscript

diff --git a/src/lib/cinema.h b/src/lib/cinema.h
new file mode 100644 (file)
index 0000000..6f426ae
--- /dev/null
@@ -0,0 +1,26 @@
+#include <libdcp/certificates.h>
+
+class Screen
+{
+public:
+       Screen (std::string const & n, boost::shared_ptr<libdcp::Certificate> cert)
+               : name (n)
+               , certificate (cert)
+       {}
+       
+       std::string name;
+       boost::shared_ptr<libdcp::Certificate> certificate;
+};
+
+class Cinema
+{
+public:
+       Cinema (std::string const & n, std::string const & e)
+               : name (n)
+               , email (e)
+       {}
+       
+       std::string name;
+       std::string email;
+       std::list<boost::shared_ptr<Screen> > screens;
+};
index 9f981c61918b111874858a1af5847a8b8c8c174b..5b96d108ccdfdd51a9d08595eb1e6c0c9b9d710b 100644 (file)
@@ -135,6 +135,7 @@ Config::read_old_metadata ()
 {
        ifstream f (file(true).c_str ());
        string line;
+
        while (getline (f, line)) {
                if (line.empty ()) {
                        continue;
@@ -207,6 +208,17 @@ Config::file (bool old) const
        return p.string ();
 }
 
+string
+Config::crypt_chain_directory () const
+{
+       boost::filesystem::path p;
+       p /= g_get_user_config_dir ();
+       p /= "dvdomatic";
+       p /= "crypt";
+       boost::filesystem::create_directories (p);
+       return p.string ();
+}
+
 /** @return Singleton instance */
 Config *
 Config::instance ()
index bce6bfd7e2707ecbd7a196ee60ac69f4d1df5426..48eabd54ca3dc33b6f395f34c8981256413ce9f0 100644 (file)
@@ -38,6 +38,7 @@ class Filter;
 class SoundProcessor;
 class DCPContentType;
 class Ratio;
+class Cinema;
 
 /** @class Config
  *  @brief A singleton class holding configuration.
@@ -92,6 +93,10 @@ public:
                return _sound_processor;
        }
 
+       std::list<boost::shared_ptr<Cinema> > cinemas () const {
+               return _cinemas;
+       }
+       
        std::list<int> allowed_dcp_frame_rates () const {
                return _allowed_dcp_frame_rates;
        }
@@ -175,6 +180,14 @@ public:
                _tms_password = p;
        }
 
+       void add_cinema (boost::shared_ptr<Cinema> c) {
+               _cinemas.push_back (c);
+       }
+
+       void remove_cinema (boost::shared_ptr<Cinema> c) {
+               _cinemas.remove (c);
+       }
+
        void set_allowed_dcp_frame_rates (std::list<int> const & r) {
                _allowed_dcp_frame_rates = r;
        }
@@ -217,6 +230,8 @@ public:
        
        void write () const;
 
+       std::string crypt_chain_directory () const;
+
        static Config* instance ();
        static void drop ();
 
@@ -260,6 +275,8 @@ private:
        int _default_j2k_bandwidth;
        std::vector<PresetColourConversion> _colour_conversions;
 
+       std::list<boost::shared_ptr<Cinema> > _cinemas;
+
        /** Singleton instance, or 0 */
        static Config* _instance;
 };
index f587f055fde8fa87fffc5e6f66f69ce9ac8b4365..b04d973dc7a62197571ce7d6697917f2023b23e0 100644 (file)
@@ -209,6 +209,14 @@ public:
        {}
 };
 
+class KDMError : public StringError
+{
+public:
+       KDMError (std::string s)
+               : StringError (s)
+       {}
+};
+
 class PixelFormatError : public StringError
 {
 public:
index 940e94fa7631053ffe1ac3070fbed1f0e7e855aa..e885fe5fd350f804fb8e0e8ec489005da6b4501d 100644 (file)
@@ -31,6 +31,8 @@
 #include <boost/date_time.hpp>
 #include <libxml++/libxml++.h>
 #include <libcxml/cxml.h>
+#include <libdcp/crypt_chain.h>
+#include <libdcp/cpl.h>
 #include "film.h"
 #include "job.h"
 #include "util.h"
@@ -49,6 +51,7 @@
 #include "dcp_content_type.h"
 #include "ratio.h"
 #include "cross.h"
+#include "cinema.h"
 
 #include "i18n.h"
 
@@ -91,6 +94,7 @@ 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)
@@ -339,6 +343,7 @@ Film::write_metadata () const
        root->add_child("ThreeD")->add_child_text (_three_d ? "1" : "0");
        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");
        _playlist->as_xml (root->add_child ("Playlist"));
 
        doc.write_to_file_formatted (file ("metadata.xml"));
@@ -737,6 +742,13 @@ Film::make_player () const
        return shared_ptr<Player> (new Player (shared_from_this (), _playlist));
 }
 
+void
+Film::set_encrypted (bool e)
+{
+       _encrypted = e;
+       signal_changed (ENCRYPTED);
+}
+
 shared_ptr<Playlist>
 Film::playlist () const
 {
@@ -876,3 +888,71 @@ Film::full_frame () const
        assert (false);
        return libdcp::Size ();
 }
+
+void
+Film::make_kdms (
+       list<shared_ptr<Screen> > screens,
+       boost::posix_time::ptime from,
+       boost::posix_time::ptime until,
+       string directory
+       ) const
+{
+       string const cd = Config::instance()->crypt_chain_directory ();
+       if (boost::filesystem::is_empty (cd)) {
+               libdcp::make_crypt_chain (cd);
+       }
+
+       libdcp::CertificateChain chain;
+
+       {
+               boost::filesystem::path p (cd);
+               p /= "ca.self-signed.pem";
+               chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate (p.string ())));
+       }
+
+       {
+               boost::filesystem::path p (cd);
+               p /= "intermediate.signed.pem";
+               chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate (p.string ())));
+       }
+
+       {
+               boost::filesystem::path p (cd);
+               p /= "leaf.signed.pem";
+               chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate (p.string ())));
+       }
+
+       boost::filesystem::path signer_key (cd);
+       signer_key /= "leaf.key";
+
+       /* Find the DCP to make the KDM for */
+       string const dir = this->directory ();
+       list<string> dcps;
+       for (boost::filesystem::directory_iterator i = boost::filesystem::directory_iterator(dir); i != boost::filesystem::directory_iterator(); ++i) {
+               if (boost::filesystem::is_directory (*i) && i->path().leaf() != "j2c" && i->path().leaf() != "wavs") {
+                       dcps.push_back (i->path().string());
+               }
+       }
+
+       if (dcps.empty()) {
+               throw KDMError ("Could not find DCP to make KDM for");
+       } else if (dcps.size() > 1) {
+               throw KDMError ("More than one possible DCP to make KDM for");
+       }
+
+       for (list<shared_ptr<Screen> >::iterator i = screens.begin(); i != screens.end(); ++i) {
+
+               libdcp::DCP dcp (dcps.front ());
+               dcp.read ();
+               
+               /* XXX: single CPL only */
+               shared_ptr<xmlpp::Document> kdm = dcp.cpls().front()->make_kdm (
+                       chain, signer_key.string(), (*i)->certificate, from, until, _interop, libdcp::MXFMetadata (), Config::instance()->dcp_metadata ()
+                       );
+
+               boost::filesystem::path out = directory;
+               out /= "kdm.xml";
+               kdm->write_to_file_formatted (out.string());
+       }
+}
+       
index f5b29466afe44574d033ae504d605f43bd6d49ba..809eabdaa9a1257cae980be9ce68a2c0b78e8452 100644 (file)
@@ -42,6 +42,7 @@ class Player;
 class Playlist;
 class AudioContent;
 class Scaler;
+class Screen;
 
 /** @class Film
  *
@@ -113,6 +114,13 @@ public:
        bool has_subtitles () const;
        OutputVideoFrame best_video_frame_rate () const;
 
+       void make_kdms (
+               std::list<boost::shared_ptr<Screen> >,
+               boost::posix_time::ptime from,
+               boost::posix_time::ptime until,
+               std::string directory
+               ) const;
+
        /** Identifiers for the parts of our state;
            used for signalling changes.
        */
@@ -127,6 +135,7 @@ public:
                RESOLUTION,
                SCALER,
                WITH_SUBTITLES,
+               ENCRYPTED,
                J2K_BANDWIDTH,
                DCI_METADATA,
                VIDEO_FRAME_RATE,
@@ -172,6 +181,10 @@ public:
                return _with_subtitles;
        }
 
+       bool encrypted () const {
+               return _encrypted;
+       }
+
        int j2k_bandwidth () const {
                return _j2k_bandwidth;
        }
@@ -215,6 +228,7 @@ public:
        void set_resolution (Resolution);
        void set_scaler (Scaler const *);
        void set_with_subtitles (bool);
+       void set_encrypted (bool);
        void set_j2k_bandwidth (int);
        void set_dci_metadata (DCIMetadata);
        void set_video_frame_rate (int);
@@ -265,6 +279,7 @@ private:
        Scaler const * _scaler;
        /** True if subtitles should be shown for this film */
        bool _with_subtitles;
+       bool _encrypted;
        /** bandwidth for J2K files in bits per second */
        int _j2k_bandwidth;
        /** DCI naming stuff */
diff --git a/src/lib/make_dcp_job.cc b/src/lib/make_dcp_job.cc
new file mode 100644 (file)
index 0000000..37c9ca6
--- /dev/null
@@ -0,0 +1,188 @@
+/*
+    Copyright (C) 2012 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.
+
+*/
+
+/** @file src/make_dcp_job.cc
+ *  @brief A job to create DCPs.
+ */
+
+#include <iostream>
+#include <boost/filesystem.hpp>
+#include <libdcp/dcp.h>
+#include <libdcp/picture_asset.h>
+#include <libdcp/sound_asset.h>
+#include <libdcp/reel.h>
+extern "C" {
+#include <libavutil/pixdesc.h>
+}
+#include "make_dcp_job.h"
+#include "dcp_content_type.h"
+#include "exceptions.h"
+#include "options.h"
+#include "imagemagick_decoder.h"
+#include "film.h"
+
+using std::string;
+using std::cout;
+using boost::shared_ptr;
+
+/** @param f Film we are making the DCP for.
+ *  @param o Options.
+ */
+MakeDCPJob::MakeDCPJob (shared_ptr<Film> f, shared_ptr<const EncodeOptions> o, shared_ptr<Job> req)
+       : Job (f, req)
+       , _opt (o)
+{
+       
+}
+
+string
+MakeDCPJob::name () const
+{
+       return String::compose ("Make DCP for %1", _film->name());
+}
+
+/** @param f DCP frame index */
+string
+MakeDCPJob::j2c_path (int f, int offset) const
+{
+       SourceFrame const s = ((f + offset) * dcp_frame_rate(_film->frames_per_second()).skip) + _film->dcp_trim_start();
+       return _opt->frame_out_path (s, false);
+}
+
+string
+MakeDCPJob::wav_path (libdcp::Channel c) const
+{
+       return _opt->multichannel_audio_out_path (int (c), false);
+}
+
+void
+MakeDCPJob::run ()
+{
+       if (!_film->dcp_length()) {
+               throw EncodeError ("cannot make a DCP when the source length is not known");
+       }
+
+       descend (0.9);
+       
+       string const dcp_path = _film->dir (_film->dcp_name());
+
+       /* Remove any old DCP */
+       boost::filesystem::remove_all (dcp_path);
+
+       DCPFrameRate const dfr = dcp_frame_rate (_film->frames_per_second ());
+
+       int frames = 0;
+       switch (_film->content_type ()) {
+       case VIDEO:
+               /* Source frames -> DCP frames */
+               frames = _film->dcp_length().get() / dfr.skip;
+               break;
+       case STILL:
+               frames = _film->still_duration() * 24;
+               break;
+       }
+
+       libdcp::DCP dcp (_film->dir (_film->dcp_name()));
+       dcp.Progress.connect (boost::bind (&MakeDCPJob::dcp_progress, this, _1));
+
+       shared_ptr<libdcp::CPL> cpl (
+               new libdcp::CPL (_film->dir (_film->dcp_name()), _film->dcp_name(), _film->dcp_content_type()->libdcp_kind (), frames, dfr.frames_per_second)
+               );
+       
+       dcp.add_cpl (cpl);
+
+       int frames_per_reel = 0;
+       if (_film->reel_size()) {
+               frames_per_reel = (_film->reel_size().get() / (_film->j2k_bandwidth() / 8)) * dfr.frames_per_second;
+       } else {
+               frames_per_reel = frames;
+       }
+
+       int frames_done = 0;
+       int reel = 0;
+
+       while (frames_done < frames) {
+
+               descend (float (frames_per_reel) / frames);
+
+               int this_time = std::min (frames_per_reel, (frames - frames_done));
+
+               descend (0.8);
+
+               shared_ptr<libdcp::MonoPictureAsset> pa (
+                       new libdcp::MonoPictureAsset (
+                               boost::bind (&MakeDCPJob::j2c_path, this, _1, frames_done),
+                               _film->dir (_film->dcp_name()),
+                               String::compose ("video_%1.mxf", reel),
+                               &dcp.Progress,
+                               dfr.frames_per_second,
+                               this_time,
+                               _opt->out_size.width,
+                               _opt->out_size.height,
+                               _film->encrypted()
+                               )
+                       );
+       
+               ascend ();
+               
+               shared_ptr<libdcp::SoundAsset> sa;
+               
+               if (_film->audio_channels() > 0) {
+                       descend (0.1);
+                       sa.reset (
+                               new libdcp::SoundAsset (
+                                       boost::bind (&MakeDCPJob::wav_path, this, _1),
+                                       _film->dir (_film->dcp_name()),
+                                       String::compose ("audio_%1.mxf", reel),
+                                       &dcp.Progress,
+                                       dfr.frames_per_second,
+                                       this_time,
+                                       frames_done,
+                                       dcp_audio_channels (_film->audio_channels()),
+                                       _film->encrypted()
+                                       )
+                               );
+                       ascend ();
+               }
+
+               descend (0.1);
+               cpl->add_reel (shared_ptr<libdcp::Reel> (new libdcp::Reel (pa, sa, shared_ptr<libdcp::SubtitleAsset> ())));
+               ascend ();
+               
+               frames_done += frames_per_reel;
+               ++reel;
+
+               ascend ();
+       }
+
+       ascend ();
+
+       descend (0.1);
+       dcp.write_xml ();
+       ascend ();
+               
+       set_progress (1);
+       set_state (FINISHED_OK);
+}
+
+void
+MakeDCPJob::dcp_progress (float p)
+{
+       set_progress (p);
+}
index 4180bbfd7e5dc50dd22a4d986e8fe9c0e92b37ac..b8bc1fc9e467680646f924c2ab3385d195911efb 100644 (file)
@@ -45,6 +45,7 @@
 #include <magick/MagickCore.h>
 #include <magick/version.h>
 #include <libdcp/version.h>
+#include <libdcp/util.h>
 extern "C" {
 #include <libavcodec/avcodec.h>
 #include <libavformat/avformat.h>
index 98501d3bb13d9e4f178a42d2defd02fe803e97ab..f61ef19e2408478e30a1174e00c6cf7d95ef6db4 100644 (file)
@@ -39,6 +39,7 @@
 #include "wx/properties_dialog.h"
 #include "wx/wx_ui_signaller.h"
 #include "wx/about_dialog.h"
+#include "wx/kdm_dialog.h"
 #include "lib/film.h"
 #include "lib/config.h"
 #include "lib/util.h"
@@ -47,6 +48,7 @@
 #include "lib/log.h"
 #include "lib/job_manager.h"
 #include "lib/transcode_job.h"
+#include "lib/exceptions.h"
 
 using std::cout;
 using std::string;
@@ -167,6 +169,7 @@ enum {
        ID_file_save,
        ID_file_properties,
        ID_jobs_make_dcp,
+       ID_jobs_make_kdms,
        ID_jobs_send_dcp_to_tms,
        ID_jobs_show_dcp,
 };
@@ -201,6 +204,7 @@ setup_menu (wxMenuBar* m)
 
        jobs_menu = new wxMenu;
        add_item (jobs_menu, _("&Make DCP"), ID_jobs_make_dcp, NEEDS_FILM | NOT_DURING_DCP_CREATION);
+       add_item (jobs_menu, _("Make &KDMs..."), ID_jobs_make_kdms, NEEDS_FILM);
        add_item (jobs_menu, _("&Send DCP to TMS"), ID_jobs_send_dcp_to_tms, NEEDS_FILM | NOT_DURING_DCP_CREATION);
        add_item (jobs_menu, _("S&how DCP"), ID_jobs_show_dcp, NEEDS_FILM | NOT_DURING_DCP_CREATION);
 
@@ -236,6 +240,7 @@ public:
                Bind (wxEVT_COMMAND_MENU_SELECTED, boost::bind (&Frame::file_exit, this),            wxID_EXIT);
                Bind (wxEVT_COMMAND_MENU_SELECTED, boost::bind (&Frame::edit_preferences, this),     wxID_PREFERENCES);
                Bind (wxEVT_COMMAND_MENU_SELECTED, boost::bind (&Frame::jobs_make_dcp, this),        ID_jobs_make_dcp);
+               Bind (wxEVT_COMMAND_MENU_SELECTED, boost::bind (&Frame::jobs_make_kdms, this),       ID_jobs_make_kdms);
                Bind (wxEVT_COMMAND_MENU_SELECTED, boost::bind (&Frame::jobs_send_dcp_to_tms, this), ID_jobs_send_dcp_to_tms);
                Bind (wxEVT_COMMAND_MENU_SELECTED, boost::bind (&Frame::jobs_show_dcp, this),        ID_jobs_show_dcp);
                Bind (wxEVT_COMMAND_MENU_SELECTED, boost::bind (&Frame::help_about, this),           wxID_ABOUT);
@@ -283,7 +288,7 @@ private:
                        return;
                }
 
-               bool const have_dcp = film && film->have_dcp();
+               bool const have_dcp = false;//film && film->have_dcp();
                jobs_menu->Enable (ID_jobs_send_dcp_to_tms, have_dcp);
                jobs_menu->Enable (ID_jobs_show_dcp, have_dcp);
        }
@@ -407,6 +412,29 @@ private:
        {
                JobWrapper::make_dcp (this, film);
        }
+
+       void jobs_make_kdms ()
+       {
+               if (!film) {
+                       return;
+               }
+               
+               KDMDialog* d = new KDMDialog (this);
+               if (d->ShowModal () == wxID_OK) {
+                       try {
+                               film->make_kdms (
+                                       d->screens (),
+                                       d->from (),
+                                       d->until (),
+                                       d->directory ()
+                                       );
+                       } catch (KDMError& e) {
+                               error_dialog (this, e.what ());
+                       }
+               }
+               
+               d->Destroy ();
+       }
        
        void jobs_send_dcp_to_tms ()
        {
diff --git a/src/wx/cinema_dialog.cc b/src/wx/cinema_dialog.cc
new file mode 100644 (file)
index 0000000..2c0b0b4
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+    Copyright (C) 2012 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 "cinema_dialog.h"
+#include "wx_util.h"
+
+using std::string;
+
+CinemaDialog::CinemaDialog (wxWindow* parent, string title, string name, string email)
+       : wxDialog (parent, wxID_ANY, std_to_wx (title))
+{
+       wxFlexGridSizer* table = new wxFlexGridSizer (2, 6, 6);
+       table->AddGrowableCol (1, 1);
+
+       add_label_to_sizer (table, this, "Name", true);
+       _name = new wxTextCtrl (this, wxID_ANY, std_to_wx (name), wxDefaultPosition, wxSize (256, -1));
+       table->Add (_name, 1, wxEXPAND);
+
+       add_label_to_sizer (table, this, "Email address for KDM delivery", true);
+       _email = new wxTextCtrl (this, wxID_ANY, std_to_wx (email), wxDefaultPosition, wxSize (256, -1));
+       table->Add (_email, 1, wxEXPAND);
+
+       wxBoxSizer* overall_sizer = new wxBoxSizer (wxVERTICAL);
+       overall_sizer->Add (table, 1, wxEXPAND | wxALL, 6);
+       
+       wxSizer* buttons = CreateSeparatedButtonSizer (wxOK | wxCANCEL);
+       if (buttons) {
+               overall_sizer->Add (buttons, wxSizerFlags().Expand().DoubleBorder());
+       }
+
+       SetSizer (overall_sizer);
+       overall_sizer->Layout ();
+       overall_sizer->SetSizeHints (this);
+}
+
+string
+CinemaDialog::name () const
+{
+       return wx_to_std (_name->GetValue());
+}
+
+string
+CinemaDialog::email () const
+{
+       return wx_to_std (_email->GetValue());
+}
diff --git a/src/wx/cinema_dialog.h b/src/wx/cinema_dialog.h
new file mode 100644 (file)
index 0000000..02520ee
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+    Copyright (C) 2012 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 <wx/wx.h>
+
+class CinemaDialog : public wxDialog
+{
+public:
+       CinemaDialog (wxWindow *, std::string, std::string name = "", std::string email = "");
+
+       std::string name () const;
+       std::string email () const;
+       
+private:
+       wxTextCtrl* _name;
+       wxTextCtrl* _email;
+};
index bcc63c735be79e4f217a5743da6007ca4bc60031..56b6973757e0f7be59a52f892060a4223b4123a9 100644 (file)
@@ -148,6 +148,10 @@ FilmEditor::make_dcp_panel ()
        }
        ++r;
 
+       _encrypted = new wxCheckBox (_dcp_panel, wxID_ANY, wxT ("Encrypted"));
+       grid->Add (_encrypted, wxGBPosition (r, 0), wxGBSpan (1, 2));
+       ++r;
+
        add_label_to_grid_bag_sizer (grid, _dcp_panel, _("Audio channels"), true, wxGBPosition (r, 0));
        _audio_channels = new wxSpinCtrl (_dcp_panel, wxID_ANY);
        grid->Add (_audio_channels, wxGBPosition (r, 1));
@@ -306,6 +310,17 @@ FilmEditor::j2k_bandwidth_changed ()
        _film->set_j2k_bandwidth (_j2k_bandwidth->GetValue() * 1e6);
 }
 
+void
+FilmEditor::encrypted_toggled ()
+{
+       if (!_film) {
+               return;
+       }
+
+       _film->set_encrypted (_encrypted->GetValue ());
+}
+                              
+/** Called when the name widget has been changed */
 void
 FilmEditor::frame_rate_changed ()
 {
@@ -392,6 +407,9 @@ FilmEditor::film_changed (Film::Property p)
        case Film::SCALER:
                checked_set (_scaler, Scaler::as_index (_film->scaler ()));
                break;
+       case Film::ENCRYPTED:
+               checked_set (_encrypted, _film->encrypted ());
+               break;
        case Film::RESOLUTION:
                checked_set (_resolution, _film->resolution() == RESOLUTION_2K ? 0 : 1);
                setup_dcp_name ();
@@ -548,6 +566,7 @@ FilmEditor::set_film (shared_ptr<Film> f)
        film_changed (Film::RESOLUTION);
        film_changed (Film::SCALER);
        film_changed (Film::WITH_SUBTITLES);
+       film_changed (Film::ENCRYPTED);
        film_changed (Film::J2K_BANDWIDTH);
        film_changed (Film::DCI_METADATA);
        film_changed (Film::VIDEO_FRAME_RATE);
@@ -578,6 +597,7 @@ FilmEditor::set_general_sensitivity (bool s)
        _content_remove->Enable (s);
        _content_timeline->Enable (s);
        _dcp_content_type->Enable (s);
+       _encrypted->Enable (s);
        _frame_rate->Enable (s);
        _audio_channels->Enable (s);
        _j2k_bandwidth->Enable (s);
index 8ecec3ec76801b6612d1a196a6a9465bde774a91..bb217211ca7719c0e58ba4a8cb22854726ec8961 100644 (file)
@@ -93,6 +93,7 @@ private:
        void content_right_click (wxListEvent &);
        void three_d_changed ();
        void standard_changed ();
+       void encrypted_toggled ();
 
        /* Handle changes to the model */
        void film_changed (Film::Property);
@@ -143,6 +144,7 @@ private:
        wxCheckBox* _three_d;
        wxChoice* _resolution;
        wxChoice* _standard;
+       wxCheckBox* _encrypted;
 
        ContentMenu _menu;
 
diff --git a/src/wx/kdm_dialog.cc b/src/wx/kdm_dialog.cc
new file mode 100644 (file)
index 0000000..a9f63cf
--- /dev/null
@@ -0,0 +1,373 @@
+/*
+    Copyright (C) 2012 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 <wx/treectrl.h>
+#include <wx/datectrl.h>
+#include <wx/timectrl.h>
+#include "lib/cinema.h"
+#include "lib/config.h"
+#include "kdm_dialog.h"
+#include "cinema_dialog.h"
+#include "screen_dialog.h"
+#include "wx_util.h"
+#ifdef __WXMSW__
+#include "dir_picker_ctrl.h"
+#else
+#include <wx/filepicker.h>
+#endif
+
+using std::string;
+using std::map;
+using std::list;
+using std::pair;
+using std::make_pair;
+using boost::shared_ptr;
+
+KDMDialog::KDMDialog (wxWindow* parent)
+       : wxDialog (parent, wxID_ANY, _("Make KDMs"))
+{
+       wxBoxSizer* vertical = new wxBoxSizer (wxVERTICAL);
+       wxBoxSizer* targets = new wxBoxSizer (wxHORIZONTAL);
+       
+       _targets = new wxTreeCtrl (this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTR_HIDE_ROOT | wxTR_MULTIPLE | wxTR_HAS_BUTTONS);
+       targets->Add (_targets, 1, wxEXPAND | wxALL, 6);
+
+       _root = _targets->AddRoot ("Foo");
+
+       list<shared_ptr<Cinema> > c = Config::instance()->cinemas ();
+       for (list<shared_ptr<Cinema> >::iterator i = c.begin(); i != c.end(); ++i) {
+               add_cinema (*i);
+       }
+
+       _targets->ExpandAll ();
+
+       wxBoxSizer* target_buttons = new wxBoxSizer (wxVERTICAL);
+
+       _add_cinema = new wxButton (this, wxID_ANY, _("Add Cinema..."));
+       target_buttons->Add (_add_cinema, 1, wxEXPAND, 6);
+       _edit_cinema = new wxButton (this, wxID_ANY, _("Edit Cinema..."));
+       target_buttons->Add (_edit_cinema, 1, wxEXPAND, 6);
+       _remove_cinema = new wxButton (this, wxID_ANY, _("Remove Cinema"));
+       target_buttons->Add (_remove_cinema, 1, wxEXPAND, 6);
+       
+       _add_screen = new wxButton (this, wxID_ANY, _("Add Screen..."));
+       target_buttons->Add (_add_screen, 1, wxEXPAND, 6);
+       _edit_screen = new wxButton (this, wxID_ANY, _("Edit Screen..."));
+       target_buttons->Add (_edit_screen, 1, wxEXPAND, 6);
+       _remove_screen = new wxButton (this, wxID_ANY, _("Remove Screen"));
+       target_buttons->Add (_remove_screen, 1, wxEXPAND, 6);
+
+       targets->Add (target_buttons, 0, 0, 6);
+
+       vertical->Add (targets, 1, wxEXPAND | wxALL, 6);
+
+       wxFlexGridSizer* table = new wxFlexGridSizer (3, 2, 6);
+       add_label_to_sizer (table, this, "From", true);
+       _from_date = new wxDatePickerCtrl (this, wxID_ANY);
+       table->Add (_from_date, 1, wxEXPAND);
+       _from_time = new wxTimePickerCtrl (this, wxID_ANY);
+       table->Add (_from_time, 1, wxEXPAND);
+       
+       add_label_to_sizer (table, this, "Until", true);
+       _until_date = new wxDatePickerCtrl (this, wxID_ANY);
+       table->Add (_until_date, 1, wxEXPAND);
+       _until_time = new wxTimePickerCtrl (this, wxID_ANY);
+       table->Add (_until_time, 1, wxEXPAND);
+
+       add_label_to_sizer (table, this, "Write to", true);
+
+#ifdef __WXMSW__
+       _folder = new DirPickerCtrl (this);
+#else  
+       _folder = new wxDirPickerCtrl (this, wxDD_DIR_MUST_EXIST);
+#endif
+
+       table->Add (_folder, 1, wxEXPAND);
+       
+       vertical->Add (table, 0, wxEXPAND | wxALL, 6);
+
+       wxSizer* buttons = CreateSeparatedButtonSizer (wxOK | wxCANCEL);
+       if (buttons) {
+               vertical->Add (buttons, wxSizerFlags().Expand().DoubleBorder());
+       }
+
+       _targets->Connect (wxID_ANY, wxEVT_COMMAND_TREE_SEL_CHANGED, wxCommandEventHandler (KDMDialog::targets_selection_changed), 0, this);
+
+       _add_cinema->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (KDMDialog::add_cinema_clicked), 0, this);
+       _edit_cinema->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (KDMDialog::edit_cinema_clicked), 0, this);
+       _remove_cinema->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (KDMDialog::remove_cinema_clicked), 0, this);
+
+       _add_screen->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (KDMDialog::add_screen_clicked), 0, this);
+       _edit_screen->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (KDMDialog::edit_screen_clicked), 0, this);
+       _remove_screen->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (KDMDialog::remove_screen_clicked), 0, this);
+
+       setup_sensitivity ();
+       
+       SetSizer (vertical);
+       vertical->Layout ();
+       vertical->SetSizeHints (this);
+}
+
+list<pair<wxTreeItemId, shared_ptr<Cinema> > >
+KDMDialog::selected_cinemas () const
+{
+       wxArrayTreeItemIds s;
+       _targets->GetSelections (s);
+
+       list<pair<wxTreeItemId, shared_ptr<Cinema> > > c;
+       for (size_t i = 0; i < s.GetCount(); ++i) {
+               map<wxTreeItemId, shared_ptr<Cinema> >::const_iterator j = _cinemas.find (s[i]);
+               if (j != _cinemas.end ()) {
+                       c.push_back (make_pair (j->first, j->second));
+               }
+       }
+
+       return c;
+}
+
+list<pair<wxTreeItemId, shared_ptr<Screen> > >
+KDMDialog::selected_screens () const
+{
+       wxArrayTreeItemIds s;
+       _targets->GetSelections (s);
+
+       list<pair<wxTreeItemId, shared_ptr<Screen> > > c;
+       for (size_t i = 0; i < s.GetCount(); ++i) {
+               map<wxTreeItemId, shared_ptr<Screen> >::const_iterator j = _screens.find (s[i]);
+               if (j != _screens.end ()) {
+                       c.push_back (make_pair (j->first, j->second));
+               }
+       }
+
+       return c;
+}
+
+void
+KDMDialog::targets_selection_changed (wxCommandEvent &)
+{
+       setup_sensitivity ();
+}
+
+void
+KDMDialog::setup_sensitivity ()
+{
+       bool const sc = selected_cinemas().size() == 1;
+       bool const ss = selected_screens().size() == 1;
+       
+       _edit_cinema->Enable (sc);
+       _remove_cinema->Enable (sc);
+       
+       _add_screen->Enable (sc);
+       _edit_screen->Enable (ss);
+       _remove_screen->Enable (ss);
+}
+
+void
+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) {
+               add_screen (c, *i);
+       }
+}
+
+void
+KDMDialog::add_screen (shared_ptr<Cinema> c, shared_ptr<Screen> s)
+{
+       map<wxTreeItemId, shared_ptr<Cinema> >::const_iterator i = _cinemas.begin();
+       while (i != _cinemas.end() && i->second != c) {
+               ++i;
+       }
+
+       if (i == _cinemas.end()) {
+               return;
+       }
+
+       _screens[_targets->AppendItem (i->first, std_to_wx (s->name))] = s;
+}
+
+void
+KDMDialog::add_cinema_clicked (wxCommandEvent &)
+{
+       CinemaDialog* d = new CinemaDialog (this, "Add Cinema");
+       d->ShowModal ();
+
+       shared_ptr<Cinema> c (new Cinema (d->name(), d->email()));
+       Config::instance()->add_cinema (c);
+       add_cinema (c);
+
+       Config::instance()->write ();
+       
+       d->Destroy ();
+}
+
+void
+KDMDialog::edit_cinema_clicked (wxCommandEvent &)
+{
+       if (selected_cinemas().size() != 1) {
+               return;
+       }
+
+       pair<wxTreeItemId, shared_ptr<Cinema> > c = selected_cinemas().front();
+       
+       CinemaDialog* d = new CinemaDialog (this, "Edit cinema", c.second->name, c.second->email);
+       d->ShowModal ();
+
+       c.second->name = d->name ();
+       c.second->email = d->email ();
+       _targets->SetItemText (c.first, std_to_wx (d->name()));
+
+       Config::instance()->write ();
+
+       d->Destroy ();  
+}
+
+void
+KDMDialog::remove_cinema_clicked (wxCommandEvent &)
+{
+       if (selected_cinemas().size() != 1) {
+               return;
+       }
+
+       pair<wxTreeItemId, shared_ptr<Cinema> > c = selected_cinemas().front();
+
+       Config::instance()->remove_cinema (c.second);
+       _targets->Delete (c.first);
+
+       Config::instance()->write ();   
+}
+
+void
+KDMDialog::add_screen_clicked (wxCommandEvent &)
+{
+       if (selected_cinemas().size() != 1) {
+               return;
+       }
+
+       shared_ptr<Cinema> c = selected_cinemas().front().second;
+       
+       ScreenDialog* d = new ScreenDialog (this, "Add Screen");
+       d->ShowModal ();
+
+       shared_ptr<Screen> s (new Screen (d->name(), d->certificate()));
+       c->screens.push_back (s);
+       add_screen (c, s);
+
+       Config::instance()->write ();
+
+       d->Destroy ();
+}
+
+void
+KDMDialog::edit_screen_clicked (wxCommandEvent &)
+{
+       if (selected_screens().size() != 1) {
+               return;
+       }
+
+       pair<wxTreeItemId, shared_ptr<Screen> > s = selected_screens().front();
+       
+       ScreenDialog* d = new ScreenDialog (this, "Edit screen", s.second->name, s.second->certificate);
+       d->ShowModal ();
+
+       s.second->name = d->name ();
+       s.second->certificate = d->certificate ();
+       _targets->SetItemText (s.first, std_to_wx (d->name()));
+
+       Config::instance()->write ();
+
+       d->Destroy ();
+}
+
+void
+KDMDialog::remove_screen_clicked (wxCommandEvent &)
+{
+       if (selected_screens().size() != 1) {
+               return;
+       }
+
+       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()) {
+               ++i;
+       }
+
+       if (i == _cinemas.end()) {
+               return;
+       }
+
+       i->second->screens.remove (s.second);
+       _targets->Delete (s.first);
+
+       Config::instance()->write ();
+}
+
+list<shared_ptr<Screen> >
+KDMDialog::screens () const
+{
+       list<shared_ptr<Screen> > s;
+
+       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) {
+                       s.push_back (*j);
+               }
+       }
+
+       list<pair<wxTreeItemId, shared_ptr<Screen> > > screens = selected_screens ();
+       for (list<pair<wxTreeItemId, shared_ptr<Screen> > >::iterator i = screens.begin(); i != screens.end(); ++i) {
+               s.push_back (i->second);
+       }
+
+       s.sort ();
+       s.unique ();
+
+       return s;
+}
+
+boost::posix_time::ptime
+KDMDialog::from () const
+{
+       return posix_time (_from_date, _from_time);
+}
+
+boost::posix_time::ptime
+KDMDialog::posix_time (wxDatePickerCtrl* date_picker, wxTimePickerCtrl* time_picker)
+{
+       wxDateTime const date = date_picker->GetValue ();
+       wxDateTime const time = time_picker->GetValue ();
+       return boost::posix_time::ptime (
+               boost::gregorian::date (date.GetYear(), date.GetMonth() + 1, date.GetDay()),
+               boost::posix_time::time_duration (time.GetHour(), time.GetMinute(), time.GetSecond())
+               );
+}
+
+boost::posix_time::ptime
+KDMDialog::until () const
+{
+       return posix_time (_until_date, _until_time);
+}
+
+string
+KDMDialog::directory () const
+{
+       return wx_to_std (_folder->GetPath ());
+}
diff --git a/src/wx/kdm_dialog.h b/src/wx/kdm_dialog.h
new file mode 100644 (file)
index 0000000..ac2db9b
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+    Copyright (C) 2012 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 <map>
+#include <boost/shared_ptr.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <wx/wx.h>
+#include <wx/treectrl.h>
+
+class wxTreeCtrl;
+class wxDatePickerCtrl;
+class wxTimePickerCtrl;
+class wxDirPickerCtrl;
+class DirPickerCtrl;
+
+class Cinema;
+class Screen;
+
+class KDMDialog : public wxDialog
+{
+public:
+       KDMDialog (wxWindow *);
+
+       std::list<boost::shared_ptr<Screen> > screens () const;
+       boost::posix_time::ptime from () const;
+       boost::posix_time::ptime until () const;
+       std::string directory () const;
+
+private:
+       void add_cinema (boost::shared_ptr<Cinema>);
+       void add_screen (boost::shared_ptr<Cinema>, boost::shared_ptr<Screen>);
+       void targets_selection_changed (wxCommandEvent &);
+       void add_cinema_clicked (wxCommandEvent &);
+       void edit_cinema_clicked (wxCommandEvent &);
+       void remove_cinema_clicked (wxCommandEvent &);
+       void add_screen_clicked (wxCommandEvent &);
+       void edit_screen_clicked (wxCommandEvent &);
+       void remove_screen_clicked (wxCommandEvent &);
+       std::list<std::pair<wxTreeItemId, boost::shared_ptr<Cinema> > > selected_cinemas () const;
+       std::list<std::pair<wxTreeItemId, boost::shared_ptr<Screen> > > selected_screens () const;
+       void setup_sensitivity ();
+
+       static boost::posix_time::ptime posix_time (wxDatePickerCtrl *, wxTimePickerCtrl *);
+       
+       wxTreeCtrl* _targets;
+       wxButton* _add_cinema;
+       wxButton* _edit_cinema;
+       wxButton* _remove_cinema;
+       wxButton* _add_screen;
+       wxButton* _edit_screen;
+       wxButton* _remove_screen;
+       wxDatePickerCtrl* _from_date;
+       wxDatePickerCtrl* _until_date;
+       wxTimePickerCtrl* _from_time;
+       wxTimePickerCtrl* _until_time;
+#ifdef __WXMSW__       
+       DirPickerCtrl* _folder;
+#else
+       wxDirPickerCtrl* _folder;
+#endif
+
+       wxTreeItemId _root;
+       std::map<wxTreeItemId, boost::shared_ptr<Cinema> > _cinemas;
+       std::map<wxTreeItemId, boost::shared_ptr<Screen> > _screens;
+};
diff --git a/src/wx/screen_dialog.cc b/src/wx/screen_dialog.cc
new file mode 100644 (file)
index 0000000..7ff5197
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+    Copyright (C) 2012 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 <wx/filepicker.h>
+#include <wx/validate.h>
+#include <libdcp/exceptions.h>
+#include "lib/compose.hpp"
+#include "screen_dialog.h"
+#include "wx_util.h"
+
+using std::string;
+using std::cout;
+using boost::shared_ptr;
+
+ScreenDialog::ScreenDialog (wxWindow* parent, string title, string name, shared_ptr<libdcp::Certificate> certificate)
+       : wxDialog (parent, wxID_ANY, std_to_wx (title))
+       , _certificate (certificate)
+{
+       wxFlexGridSizer* table = new wxFlexGridSizer (2, 6, 6);
+       table->AddGrowableCol (1, 1);
+
+       add_label_to_sizer (table, this, "Name", true);
+       _name = new wxTextCtrl (this, wxID_ANY, std_to_wx (name), wxDefaultPosition, wxSize (320, -1));
+       table->Add (_name, 1, wxEXPAND);
+
+       add_label_to_sizer (table, this, "Certificate", true);
+       _certificate_load = new wxButton (this, wxID_ANY, wxT ("Load from file..."));
+       table->Add (_certificate_load, 1, wxEXPAND);
+
+       table->AddSpacer (0);
+       _certificate_text = new wxTextCtrl (this, wxID_ANY, wxT (""), wxDefaultPosition, wxSize (320, 256), wxTE_MULTILINE | wxTE_READONLY);
+       if (certificate) {
+               _certificate_text->SetValue (certificate->certificate ());
+       }
+       wxFont font = wxSystemSettings::GetFont (wxSYS_ANSI_FIXED_FONT);
+       font.SetPointSize (font.GetPointSize() / 2);
+       _certificate_text->SetFont (font);
+       table->Add (_certificate_text, 1, wxEXPAND);
+
+       wxBoxSizer* overall_sizer = new wxBoxSizer (wxVERTICAL);
+       overall_sizer->Add (table, 1, wxEXPAND | wxALL, 6);
+       
+       wxSizer* buttons = CreateSeparatedButtonSizer (wxOK | wxCANCEL);
+       if (buttons) {
+               overall_sizer->Add (buttons, wxSizerFlags().Expand().DoubleBorder());
+       }
+
+       SetSizer (overall_sizer);
+       overall_sizer->Layout ();
+       overall_sizer->SetSizeHints (this);
+
+       _certificate_load->Connect (wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler (ScreenDialog::load_certificate), 0, this);
+}
+
+string
+ScreenDialog::name () const
+{
+       return wx_to_std (_name->GetValue());
+}
+
+shared_ptr<libdcp::Certificate>
+ScreenDialog::certificate () const
+{
+       return _certificate;
+}
+
+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()));
+       }
+
+       d->Destroy ();
+}
diff --git a/src/wx/screen_dialog.h b/src/wx/screen_dialog.h
new file mode 100644 (file)
index 0000000..1bd4a89
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+    Copyright (C) 2012 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 <wx/wx.h>
+#include <boost/shared_ptr.hpp>
+#include <libdcp/certificates.h>
+
+class ScreenDialog : public wxDialog
+{
+public:
+       ScreenDialog (wxWindow *, std::string, std::string name = "", boost::shared_ptr<libdcp::Certificate> c = boost::shared_ptr<libdcp::Certificate> ());
+
+       std::string name () const;
+       boost::shared_ptr<libdcp::Certificate> certificate () const;
+       
+private:
+       void load_certificate (wxCommandEvent &);
+       
+       wxTextCtrl* _name;
+       wxButton* _certificate_load;
+       wxTextCtrl* _certificate_text;
+
+       boost::shared_ptr<libdcp::Certificate> _certificate;
+};
index 9c3ecdd71eacf10f9cc682055cfe66bc7eb94e86..8f35e2facea49aa784b761ef4dbb3cc341f3b537 100644 (file)
@@ -9,6 +9,7 @@ sources = """
           audio_mapping_view.cc
           audio_panel.cc
           audio_plot.cc
+          cinema_dialog.cc
           colour_conversion_editor.cc
           config_dialog.cc
           content_colour_conversion_dialog.cc
@@ -23,10 +24,12 @@ sources = """
           gain_calculator_dialog.cc
           job_manager_view.cc
           job_wrapper.cc
+          kdm_dialog.cc
           new_film_dialog.cc
           preset_colour_conversion_dialog.cc
           properties_dialog.cc
           repeat_dialog.cc
+          screen_dialog.cc
           server_dialog.cc
           subtitle_panel.cc
           timecode.cc