summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/cinema.cc75
-rw-r--r--src/lib/cinema.h69
-rw-r--r--src/lib/config.cc34
-rw-r--r--src/lib/config.h27
-rw-r--r--src/lib/exceptions.h8
-rw-r--r--src/lib/film.cc92
-rw-r--r--src/lib/film.h21
-rw-r--r--src/lib/make_dcp_job.cc188
-rw-r--r--src/lib/util.cc18
-rw-r--r--src/lib/util.h1
-rw-r--r--src/lib/writer.cc10
-rw-r--r--src/lib/wscript1
12 files changed, 531 insertions, 13 deletions
diff --git a/src/lib/cinema.cc b/src/lib/cinema.cc
new file mode 100644
index 000000000..7af4372f5
--- /dev/null
+++ b/src/lib/cinema.cc
@@ -0,0 +1,75 @@
+/*
+ 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 <libxml++/libxml++.h>
+#include <libcxml/cxml.h>
+#include "cinema.h"
+
+using std::list;
+using boost::shared_ptr;
+
+Cinema::Cinema (shared_ptr<const cxml::Node> node)
+{
+ name = node->string_child ("Name");
+ email = node->string_child ("Email");
+
+ list<shared_ptr<cxml::Node> > s = node->node_children ("Screen");
+ for (list<shared_ptr<cxml::Node> >::iterator i = s.begin(); i != s.end(); ++i) {
+ add_screen (shared_ptr<Screen> (new Screen (*i)));
+ }
+}
+
+void
+Cinema::as_xml (xmlpp::Element* parent) const
+{
+ parent->add_child("Name")->add_child_text (name);
+ parent->add_child("Email")->add_child_text (email);
+
+ for (list<shared_ptr<Screen> >::const_iterator i = _screens.begin(); i != _screens.end(); ++i) {
+ (*i)->as_xml (parent->add_child ("Screen"));
+ }
+}
+
+void
+Cinema::add_screen (shared_ptr<Screen> s)
+{
+ s->cinema = shared_from_this ();
+ _screens.push_back (s);
+}
+
+void
+Cinema::remove_screen (shared_ptr<Screen> s)
+{
+ _screens.remove (s);
+}
+
+Screen::Screen (shared_ptr<const cxml::Node> node)
+{
+ name = node->string_child ("Name");
+ certificate = shared_ptr<libdcp::Certificate> (new libdcp::Certificate (node->string_child ("Certificate")));
+}
+
+void
+Screen::as_xml (xmlpp::Element* parent) const
+{
+ parent->add_child("Name")->add_child_text (name);
+ parent->add_child("Certificate")->add_child_text (certificate->certificate (true));
+}
+
+
diff --git a/src/lib/cinema.h b/src/lib/cinema.h
new file mode 100644
index 000000000..251bb5d61
--- /dev/null
+++ b/src/lib/cinema.h
@@ -0,0 +1,69 @@
+/*
+ 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:
+ Screen (std::string const & n, boost::shared_ptr<libdcp::Certificate> cert)
+ : 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 : 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 () const {
+ return _screens;
+ }
+
+private:
+ std::list<boost::shared_ptr<Screen> > _screens;
+};
diff --git a/src/lib/config.cc b/src/lib/config.cc
index 9f981c619..a72e1a9e4 100644
--- a/src/lib/config.cc
+++ b/src/lib/config.cc
@@ -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
@@ -135,6 +141,7 @@ Config::read_old_metadata ()
{
ifstream f (file(true).c_str ());
string line;
+
while (getline (f, line)) {
if (line.empty ()) {
continue;
@@ -192,7 +199,7 @@ Config::read_old_metadata ()
}
/** @return Filename to write configuration to */
-string
+boost::filesystem::path
Config::file (bool old) const
{
boost::filesystem::path p;
@@ -204,7 +211,18 @@ Config::file (bool old) const
} else {
p /= "dcpomatic.xml";
}
- return p.string ();
+ return p;
+}
+
+boost::filesystem::path
+Config::signer_chain_directory () const
+{
+ boost::filesystem::path p;
+ p /= g_get_user_config_dir ();
+ p /= "dvdomatic";
+ p /= "crypt";
+ boost::filesystem::create_directories (p);
+ return p;
}
/** @return Singleton instance */
@@ -233,7 +251,7 @@ Config::write () const
xmlpp::Element* root = doc.create_root_node ("Config");
root->add_child("NumLocalEncodingThreads")->add_child_text (lexical_cast<string> (_num_local_encoding_threads));
- root->add_child("DefaultDirectory")->add_child_text (_default_directory);
+ root->add_child("DefaultDirectory")->add_child_text (_default_directory.string ());
root->add_child("ServerPort")->add_child_text (lexical_cast<string> (_server_port));
for (vector<ServerDescription>::const_iterator i = _servers.begin(); i != _servers.end(); ++i) {
@@ -268,11 +286,15 @@ Config::write () const
i->as_xml (root->add_child ("ColourConversion"));
}
- doc.write_to_file_formatted (file (false));
+ 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 ());
}
-string
-Config::default_directory_or (string a) const
+boost::filesystem::path
+Config::default_directory_or (boost::filesystem::path a) const
{
if (_default_directory.empty() || !boost::filesystem::exists (_default_directory)) {
return a;
diff --git a/src/lib/config.h b/src/lib/config.h
index bce6bfd7e..3e8a975d6 100644
--- a/src/lib/config.h
+++ b/src/lib/config.h
@@ -27,6 +27,7 @@
#include <vector>
#include <boost/shared_ptr.hpp>
#include <boost/signals2.hpp>
+#include <boost/filesystem.hpp>
#include <libdcp/metadata.h>
#include "dci_metadata.h"
#include "colour_conversion.h"
@@ -38,6 +39,7 @@ class Filter;
class SoundProcessor;
class DCPContentType;
class Ratio;
+class Cinema;
/** @class Config
* @brief A singleton class holding configuration.
@@ -51,11 +53,11 @@ public:
return _num_local_encoding_threads;
}
- std::string default_directory () const {
+ boost::filesystem::path default_directory () const {
return _default_directory;
}
- std::string default_directory_or (std::string a) const;
+ boost::filesystem::path default_directory_or (boost::filesystem::path a) const;
/** @return port to use for J2K encoding servers */
int server_port () const {
@@ -92,6 +94,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;
}
@@ -133,7 +139,7 @@ public:
_num_local_encoding_threads = n;
}
- void set_default_directory (std::string d) {
+ void set_default_directory (boost::filesystem::path d) {
_default_directory = d;
}
@@ -175,6 +181,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,19 +231,21 @@ public:
void write () const;
+ boost::filesystem::path signer_chain_directory () const;
+
static Config* instance ();
static void drop ();
private:
Config ();
- std::string file (bool) const;
+ boost::filesystem::path file (bool) const;
void read ();
void read_old_metadata ();
/** number of threads to use for J2K encoding on the local machine */
int _num_local_encoding_threads;
/** default directory to put new films in */
- std::string _default_directory;
+ boost::filesystem::path _default_directory;
/** port to use for J2K encoding servers */
int _server_port;
@@ -259,6 +275,7 @@ 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 */
static Config* _instance;
diff --git a/src/lib/exceptions.h b/src/lib/exceptions.h
index f587f055f..b04d973dc 100644
--- a/src/lib/exceptions.h
+++ b/src/lib/exceptions.h
@@ -209,6 +209,14 @@ public:
{}
};
+class KDMError : public StringError
+{
+public:
+ KDMError (std::string s)
+ : StringError (s)
+ {}
+};
+
class PixelFormatError : public StringError
{
public:
diff --git a/src/lib/film.cc b/src/lib/film.cc
index 940e94fa7..07af46d97 100644
--- a/src/lib/film.cc
+++ b/src/lib/film.cc
@@ -31,6 +31,9 @@
#include <boost/date_time.hpp>
#include <libxml++/libxml++.h>
#include <libcxml/cxml.h>
+#include <libdcp/signer_chain.h>
+#include <libdcp/cpl.h>
+#include <libdcp/signer.h>
#include "film.h"
#include "job.h"
#include "util.h"
@@ -49,6 +52,7 @@
#include "dcp_content_type.h"
#include "ratio.h"
#include "cross.h"
+#include "cinema.h"
#include "i18n.h"
@@ -75,6 +79,7 @@ using boost::ends_with;
using boost::starts_with;
using boost::optional;
using libdcp::Size;
+using libdcp::Signer;
int const Film::state_version = 4;
@@ -91,6 +96,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 +345,8 @@ 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");
+ root->add_child("Key")->add_child_text (_key.hex ());
_playlist->as_xml (root->add_child ("Playlist"));
doc.write_to_file_formatted (file ("metadata.xml"));
@@ -383,11 +391,12 @@ Film::read_metadata ()
_dci_metadata = DCIMetadata (f.node_child ("DCIMetadata"));
_video_frame_rate = f.number_child<int> ("VideoFrameRate");
_dci_date = boost::gregorian::from_undelimited_string (f.string_child ("DCIDate"));
+ _encrypted = f.bool_child ("Encrypted");
_audio_channels = f.number_child<int> ("AudioChannels");
_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;
@@ -737,6 +746,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 +892,77 @@ 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
+{
+ boost::filesystem::path const sd = Config::instance()->signer_chain_directory ();
+ if (boost::filesystem::is_empty (sd)) {
+ libdcp::make_signer_chain (sd);
+ }
+
+ libdcp::CertificateChain chain;
+
+ {
+ boost::filesystem::path p (sd);
+ p /= "ca.self-signed.pem";
+ 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)));
+ }
+
+ {
+ boost::filesystem::path p (sd);
+ p /= "leaf.signed.pem";
+ chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate (p)));
+ }
+
+ boost::filesystem::path signer_key (sd);
+ signer_key /= "leaf.key";
+
+ shared_ptr<const Signer> signer (new Signer (chain, signer_key));
+
+ /* Find the DCP to make the KDM for */
+ string const dir = this->directory ();
+ list<boost::filesystem::path> 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() != "video" && i->path().leaf() != "info") {
+ dcps.push_back (i->path());
+ }
+ }
+
+ 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 ());
+
+ try {
+ dcp.read ();
+ } catch (...) {
+ throw KDMError (_("Could not read DCP to make KDM for"));
+ }
+
+ shared_ptr<xmlpp::Document> kdm = dcp.cpls().front()->make_kdm (
+ signer, (*i)->certificate, key (), 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) + ".kdm.xml";
+ kdm->write_to_file_formatted (out.string());
+ }
+}
+
diff --git a/src/lib/film.h b/src/lib/film.h
index f5b29466a..26623e69e 100644
--- a/src/lib/film.h
+++ b/src/lib/film.h
@@ -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"
@@ -42,6 +43,7 @@ class Player;
class Playlist;
class AudioContent;
class Scaler;
+class Screen;
/** @class Film
*
@@ -113,6 +115,17 @@ 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;
+
+ libdcp::Key key () const {
+ return _key;
+ }
+
/** Identifiers for the parts of our state;
used for signalling changes.
*/
@@ -127,6 +140,7 @@ public:
RESOLUTION,
SCALER,
WITH_SUBTITLES,
+ ENCRYPTED,
J2K_BANDWIDTH,
DCI_METADATA,
VIDEO_FRAME_RATE,
@@ -172,6 +186,10 @@ public:
return _with_subtitles;
}
+ bool encrypted () const {
+ return _encrypted;
+ }
+
int j2k_bandwidth () const {
return _j2k_bandwidth;
}
@@ -215,6 +233,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 +284,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 */
@@ -281,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;
diff --git a/src/lib/make_dcp_job.cc b/src/lib/make_dcp_job.cc
new file mode 100644
index 000000000..37c9ca620
--- /dev/null
+++ b/src/lib/make_dcp_job.cc
@@ -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);
+}
diff --git a/src/lib/util.cc b/src/lib/util.cc
index 4180bbfd7..667ee8ce9 100644
--- a/src/lib/util.cc
+++ b/src/lib/util.cc
@@ -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>
@@ -274,6 +275,8 @@ dcpomatic_setup ()
#endif
avfilter_register_all ();
+
+ libdcp::init ();
Ratio::setup_ratios ();
DCPContentType::setup_dcp_content_types ();
@@ -799,3 +802,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;
+}
+
diff --git a/src/lib/util.h b/src/lib/util.h
index a83426206..b5c94d994 100644
--- a/src/lib/util.h
+++ b/src/lib/util.h
@@ -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
{
diff --git a/src/lib/writer.cc b/src/lib/writer.cc
index 5f94d5d6b..37376ca23 100644
--- a/src/lib/writer.cc
+++ b/src/lib/writer.cc
@@ -73,7 +73,7 @@ Writer::Writer (shared_ptr<const Film> f, shared_ptr<Job> j)
it into the DCP later.
*/
- if (f->three_d ()) {
+ if (_film->three_d ()) {
_picture_asset.reset (
new libdcp::StereoPictureAsset (
_film->internal_video_mxf_dir (),
@@ -95,6 +95,10 @@ Writer::Writer (shared_ptr<const Film> f, shared_ptr<Job> j)
}
+ 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 (
@@ -106,6 +110,10 @@ Writer::Writer (shared_ptr<const Film> f, shared_ptr<Job> j)
_film->audio_frame_rate ()
)
);
+
+ if (_film->encrypted ()) {
+ _sound_asset->set_key (_film->key ());
+ }
_sound_asset_writer = _sound_asset->start_write (_film->interop ());
diff --git a/src/lib/wscript b/src/lib/wscript
index 6c45d8b1e..e91666f7f 100644
--- a/src/lib/wscript
+++ b/src/lib/wscript
@@ -8,6 +8,7 @@ sources = """
audio_content.cc
audio_decoder.cc
audio_mapping.cc
+ cinema.cc
colour_conversion.cc
config.cc
content.cc