It builds again.
authorCarl Hetherington <cth@carlh.net>
Sun, 26 Jan 2014 21:35:02 +0000 (21:35 +0000)
committerCarl Hetherington <cth@carlh.net>
Sun, 26 Jan 2014 21:35:02 +0000 (21:35 +0000)
101 files changed:
examples/make_dcp.cc
src/argb_frame.cc
src/argb_frame.h
src/asset.cc
src/asset.h
src/certificates.cc
src/certificates.h
src/content.cc
src/content.h
src/cpl.cc
src/cpl.h
src/dcp.cc
src/dcp.h
src/exceptions.cc
src/exceptions.h
src/file.cc [new file with mode: 0644]
src/file.h [new file with mode: 0644]
src/font.cc [new file with mode: 0644]
src/font.h [new file with mode: 0644]
src/gamma_lut.cc
src/gamma_lut.h
src/kdm.cc
src/key.h
src/load_font.cc [new file with mode: 0644]
src/load_font.h [new file with mode: 0644]
src/mono_picture_mxf.cc
src/mono_picture_mxf.h
src/mono_picture_mxf_writer.cc
src/mono_picture_mxf_writer.h
src/mxf.cc
src/mxf.h
src/mxf_writer.cc [new file with mode: 0644]
src/mxf_writer.h [new file with mode: 0644]
src/object.cc
src/object.h
src/parse/asset_map.cc [deleted file]
src/parse/asset_map.h [deleted file]
src/parse/cpl.cc [deleted file]
src/parse/cpl.h [deleted file]
src/parse/pkl.cc [deleted file]
src/parse/pkl.h [deleted file]
src/parse/subtitle.cc [deleted file]
src/parse/subtitle.h [deleted file]
src/picture_mxf.cc
src/picture_mxf.h
src/picture_mxf_writer.cc
src/picture_mxf_writer.h
src/picture_mxf_writer_common.cc
src/reel.cc
src/reel.h
src/reel_asset.cc [new file with mode: 0644]
src/reel_asset.h [new file with mode: 0644]
src/reel_mono_picture_asset.cc [new file with mode: 0644]
src/reel_mono_picture_asset.h [new file with mode: 0644]
src/reel_picture_asset.cc [new file with mode: 0644]
src/reel_picture_asset.h [new file with mode: 0644]
src/reel_sound_asset.cc [new file with mode: 0644]
src/reel_sound_asset.h [new file with mode: 0644]
src/reel_stereo_picture_asset.cc [new file with mode: 0644]
src/reel_stereo_picture_asset.h [new file with mode: 0644]
src/reel_subtitle_asset.cc [new file with mode: 0644]
src/reel_subtitle_asset.h [new file with mode: 0644]
src/ref.h [new file with mode: 0644]
src/signer.cc
src/signer.h
src/sound_mxf.cc
src/sound_mxf.h
src/sound_mxf_writer.cc [new file with mode: 0644]
src/sound_mxf_writer.h [new file with mode: 0644]
src/stereo_picture_frame.cc
src/stereo_picture_mxf.cc
src/stereo_picture_mxf.h
src/stereo_picture_mxf_writer.cc
src/stereo_picture_mxf_writer.h
src/subtitle.cc [new file with mode: 0644]
src/subtitle.h [new file with mode: 0644]
src/subtitle_asset.cc [deleted file]
src/subtitle_asset.h [deleted file]
src/subtitle_content.cc [new file with mode: 0644]
src/subtitle_content.h [new file with mode: 0644]
src/subtitle_string.cc [new file with mode: 0644]
src/subtitle_string.h [new file with mode: 0644]
src/text.cc [new file with mode: 0644]
src/text.h [new file with mode: 0644]
src/types.h
src/util.cc
src/util.h
src/wscript
test/cpl_sar.cc [deleted file]
test/cpl_sar_test.cc [new file with mode: 0644]
test/decryption_test.cc
test/read_dcp_test.cc
test/recovery_test.cc
test/rewrite_subs.cc
test/round_trip_test.cc
test/subs_in_out.cc
test/subtitle_tests.cc
test/test.cc
test/test.h
test/wscript
tools/dcpinfo.cc

index 8f6897b82e89bcb6f8c63c90d4867010105a574f..e3e83f8dde7b30da556e80d0efeb7746056b1169 100644 (file)
 #include "mono_picture_mxf.h"
 #include "mono_picture_mxf_writer.h"
 #include "sound_mxf.h"
+#include "sound_mxf_writer.h"
 #include "reel.h"
+#include "file.h"
+#include "reel_mono_picture_asset.h"
+#include "reel_sound_asset.h"
 
 int
 main ()
@@ -49,10 +53,10 @@ main ()
           per second.
        */
 
-       boost::shared_ptr<dcp::MonoPictureMXF> picture_mxf (new dcp::MonoPictureMXF (24));
+       boost::shared_ptr<dcp::MonoPictureMXF> picture_mxf (new dcp::MonoPictureMXF (dcp::Fraction (24, 1)));
 
        /* Start off a write to it */
-       boost::shared_ptr<dcp::MonoPictureMXFWriter> picture_writer = picture_mxf->start_write ("DCP/picture.mxf", false);
+       boost::shared_ptr<dcp::PictureMXFWriter> picture_writer = picture_mxf->start_write ("DCP/picture.mxf", dcp::SMPTE, false);
 
        /* Write 24 frames of the same JPEG2000 file */
        dcp::File picture ("examples/help.j2c");
@@ -66,8 +70,8 @@ main ()
        /* Now create a sound MXF.  As before, create an object and a writer.
           When creating the object we specify the sampling rate (48kHz) and the number of channels (2).
        */
-       boost::shared_ptr<dcp::SoundMXF> sound_mxf (new dcp::SoundMXF (48000, 2));
-       boost::shared_ptr<dcp::SoundMXFWriter> sound_writer = sound_mxf->start_write ("DCP/sound.mxf", false);
+       boost::shared_ptr<dcp::SoundMXF> sound_mxf (new dcp::SoundMXF (dcp::Fraction (24, 1), 48000, 2));
+       boost::shared_ptr<dcp::SoundMXFWriter> sound_writer = sound_mxf->start_write ("DCP/sound.mxf", dcp::SMPTE);
 
        /* Write some sine waves */
        float* audio[2];
@@ -85,24 +89,24 @@ main ()
        sound_writer->finalize ();
 
        /* Now create a reel */
-       shared_ptr<dcp::Reel> reel (new dcp::Reel ());
+       boost::shared_ptr<dcp::Reel> reel (new dcp::Reel ());
 
        /* Add picture and sound to it.  The zeros are the `entry points', i.e. the first
           (video) frame from the MXFs that the reel should play.
        */
-       reel->add (picture, 0);
-       reel->add (sound, 0);
+       reel->add (boost::shared_ptr<dcp::ReelPictureAsset> (new dcp::ReelMonoPictureAsset (picture_mxf, 0)));
+       reel->add (boost::shared_ptr<dcp::ReelSoundAsset> (new dcp::ReelSoundAsset (sound_mxf, 0)));
 
        /* Make a CPL with this reel */
-       shared_ptr<dcp::CPL> cpl (new dcp::CPL ("My film", dcp::FEATURE));
+       boost::shared_ptr<dcp::CPL> cpl (new dcp::CPL ("My film", dcp::FEATURE));
        cpl->add (reel);
 
        /* Write the DCP */
-       list<shared_ptr<dcp::Asset> > assets;
-       asset.push_back (cpl);
-       asset.push_back (picture);
-       asset.push_back (sound);
-       dcp::write ("DCP", assets);
+       dcp::DCP dcp ("DCP");
+       dcp.add (cpl);
+       dcp.add (picture_mxf);
+       dcp.add (sound_mxf);
+       dcp.write_xml (dcp::SMPTE);
        
        return 0;
 }
index 79637329e0a07fc0be665b8fb1d7806046145952..99d6c8145154a3efb0fa6caa5d76502cec42611a 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2014 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
 
 */
 
+/** @file  src/argb_frame.cc
+ *  @brief ARGBFrame class. 
+ */
+
 #include "argb_frame.h"
 
 using namespace dcp;
index 2ad6f69d2aa636e4dd70f9585c132f7e0de12a08..a1b3b4276da68c8ee290533c3ac76bc28486fcd3 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2014 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
 */
 
 /** @file  src/argb_frame.h
- *  @brief Container for a single image from a picture asset.
+ *  @brief ARGBFrame class. 
  */
 
-#include <stdint.h>
 #include "util.h"
+#include <stdint.h>
 
 namespace dcp
 {
@@ -42,7 +42,7 @@ namespace dcp
  *
  *  Lines are packed so that the second row directly follows the first.
  */
-class ARGBFrame
+class ARGBFrame : boost::noncopyable
 {
 public:
        ARGBFrame (Size size);
@@ -60,8 +60,8 @@ public:
        }
 
 private:
-       Size _size;
-       uint8_t* _data;
+       Size _size;     ///< frame size in pixels
+       uint8_t* _data; ///< pointer to image data
 };
 
 }
index 0147eba2cf30a3a8997974fe3d6e81f41b8c59f7..74e32cf06b6c18bd446b19e1b4cea7faf56fd1f3 100644 (file)
 
 */
 
+/** @file  src/asset.cc
+ *  @brief Asset class.
+ */
+
 #include "asset.h"
+#include "util.h"
+#include <libxml++/libxml++.h>
+#include <boost/lexical_cast.hpp>
 
 using std::string;
+using boost::lexical_cast;
+using boost::function;
 using namespace dcp;
 
+/** Create an Asset with a randomly-generated ID */
 Asset::Asset ()
 {
 
 }
 
+Asset::Asset (boost::filesystem::path file)
+       : _file (file)
+{
+
+}
+
+/** Create an Asset with a specified ID.
+ *  @param id ID to use.
+ */
 Asset::Asset (string id)
        : Object (id)
 {
 
 }
+
+void
+Asset::write_to_pkl (xmlpp::Node* node) const
+{
+       xmlpp::Node* asset = node->add_child ("Asset");
+       asset->add_child("Id")->add_child_text ("urn:uuid:" + _id);
+       asset->add_child("AnnotationText")->add_child_text (_id);
+       asset->add_child("Hash")->add_child_text (hash ());
+       asset->add_child("Size")->add_child_text (lexical_cast<string> (boost::filesystem::file_size (_file)));
+       asset->add_child("Type")->add_child_text (pkl_type ());
+}
+
+void
+Asset::write_to_assetmap (xmlpp::Node* node) const
+{
+       xmlpp::Node* asset = node->add_child ("Asset");
+       asset->add_child("Id")->add_child_text ("urn:uuid:" + _id);
+       xmlpp::Node* chunk_list = asset->add_child ("ChunkList");
+       xmlpp::Node* chunk = chunk_list->add_child ("Chunk");
+       chunk->add_child("Path")->add_child_text (_file.string ());
+       chunk->add_child("VolumeIndex")->add_child_text ("1");
+       chunk->add_child("Offset")->add_child_text ("0");
+       chunk->add_child("Length")->add_child_text (lexical_cast<string> (boost::filesystem::file_size (_file)));
+}
+
+string
+Asset::hash () const
+{
+       if (!_hash.empty ()) {
+               _hash = make_digest (_file, 0);
+       }
+
+       return _hash;
+}
+
+bool
+Asset::equals (boost::shared_ptr<const Asset> other, EqualityOptions, function<void (NoteType, string)> note) const
+{
+       if (_hash != other->_hash) {
+               note (ERROR, "Asset hashes differ");
+               return false;
+       }
+
+       return true;
+}
index f3546cd86318cb6bf88ab172ed1b10a1cc4f6248..e8867ae551f7aa65363b3e53a87b47c79a5792cc 100644 (file)
 
 */
 
+/** @file  src/asset.h
+ *  @brief Asset class.
+ */ 
+
 #ifndef LIBDCP_ASSET_H
 #define LIBDCP_ASSET_H
 
 #include "object.h"
+#include "types.h"
+#include <boost/filesystem.hpp>
+#include <boost/function.hpp>
+
+namespace xmlpp {
+       class Node;
+}
 
 namespace dcp {
 
 /** @class Asset
- *  @brief Parent class for DCP assets, i.e. picture/sound/subtitles, CPLs and PKLs.
+ *  @brief Parent class for DCP assets, i.e. picture/sound/subtitles and CPLs.
+ *
+ *  Note that this class is not used for ReelAssets; they are just for the metadata
+ *  that gets put into <Reel>s.
  */
-       
 class Asset : public Object
 {
 public:
        Asset ();
+       Asset (boost::filesystem::path file);
        Asset (std::string id);
 
+       virtual std::string pkl_type () const = 0;
+       virtual bool equals (boost::shared_ptr<const Asset> other, EqualityOptions opt, boost::function<void (NoteType, std::string)> note) const;
+       
+       /** Write details of the asset to a PKL AssetList node.
+        *  @param node Parent node.
+        */
+       void write_to_pkl (xmlpp::Node* node) const;
+       void write_to_assetmap (xmlpp::Node* node) const;
+
+       boost::filesystem::path file () const {
+               return _file;
+       }
+
+       void set_file (boost::filesystem::path file) {
+               _file = file;
+       }
+
+       std::string hash () const;
+
+protected:
+       friend class MXFWriter;
+       
+       boost::filesystem::path _file;
+       mutable std::string _hash;
 };
 
 }
index caa4c830279be07e979c9004cae47bb5075c9cad..222352f2e95b05bf461353c55a6823d000f51757 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2014 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
 
 */
 
-#include <sstream>
-#include <vector>
-#include <cerrno>
-#include <boost/algorithm/string.hpp>
-#include <openssl/x509.h>
-#include <openssl/ssl.h>
-#include <openssl/asn1.h>
-#include <openssl/err.h>
-#include <libxml++/nodes/element.h>
 #include "KM_util.h"
 #include "certificates.h"
 #include "compose.hpp"
 #include "exceptions.h"
 #include "util.h"
+#include <libxml++/nodes/element.h>
+#include <openssl/x509.h>
+#include <openssl/ssl.h>
+#include <openssl/asn1.h>
+#include <openssl/err.h>
+#include <boost/algorithm/string.hpp>
+#include <cerrno>
 
 using std::list;
 using std::string;
-using std::stringstream;
-using std::vector;
 using boost::shared_ptr;
 using namespace dcp;
 
@@ -47,6 +43,9 @@ Certificate::Certificate (X509* c)
        
 }
 
+/** Load an X509 certificate from a file.
+ *  @param filename File to load.
+ */
 Certificate::Certificate (boost::filesystem::path filename)
        : _certificate (0)
        , _public_key (0)
@@ -61,6 +60,9 @@ Certificate::Certificate (boost::filesystem::path filename)
        }
 }
 
+/** Load an X509 certificate from a string.
+ *  @param cert String to read from.
+ */
 Certificate::Certificate (string cert)
        : _certificate (0)
        , _public_key (0)
@@ -68,6 +70,9 @@ Certificate::Certificate (string cert)
        read_string (cert);
 }
 
+/** Copy constructor.
+ *  @param other Certificate to copy.
+ */
 Certificate::Certificate (Certificate const & other)
        : _certificate (0)
        , _public_key (0)
@@ -75,6 +80,9 @@ Certificate::Certificate (Certificate const & other)
        read_string (other.certificate (true));
 }
 
+/** Read a certificate from a string.
+ *  @param cert String to read.
+ */
 void
 Certificate::read_string (string cert)
 {
@@ -91,12 +99,16 @@ Certificate::read_string (string cert)
        BIO_free (bio);
 }
 
+/** Destructor */
 Certificate::~Certificate ()
 {
        X509_free (_certificate);
        RSA_free (_public_key);
 }
 
+/** operator= for Certificate.
+ *  @param other Certificate to read from.
+ */
 Certificate &
 Certificate::operator= (Certificate const & other)
 {
@@ -114,6 +126,10 @@ Certificate::operator= (Certificate const & other)
        return *this;
 }
 
+/** Return the certificate as a string.
+ *  @param with_begin_end true to include the -----BEGIN CERTIFICATE--- / -----END CERTIFICATE----- markers.
+ *  @return Certificate string.
+ */
 string
 Certificate::certificate (bool with_begin_end) const
 {
@@ -143,6 +159,10 @@ Certificate::certificate (bool with_begin_end) const
        return s;
 }
 
+/** @return Certificate's issuer, in the form
+ *  dnqualifier=<dnQualififer>,CN=<commonName>,OU=<organizationalUnitName>,O=organizationName
+ *  and with + signs escaped to \+
+ */
 string
 Certificate::issuer () const
 {
@@ -244,6 +264,7 @@ Certificate::thumbprint () const
        return Kumu::base64encode (digest, 20, digest_base64, 64);
 }
 
+/** @return RSA public key from this Certificate.  Caller must not free the returned value. */
 RSA *
 Certificate::public_key () const
 {
@@ -266,6 +287,7 @@ Certificate::public_key () const
        return _public_key;
 }
 
+/** @return Root certificate */
 shared_ptr<Certificate>
 CertificateChain::root () const
 {
@@ -273,6 +295,7 @@ CertificateChain::root () const
        return _certificates.front ();
 }
 
+/** @return Leaf certificate */
 shared_ptr<Certificate>
 CertificateChain::leaf () const
 {
@@ -280,6 +303,7 @@ CertificateChain::leaf () const
        return _certificates.back ();
 }
 
+/** @return Certificates in order from leaf to root */
 list<shared_ptr<Certificate> >
 CertificateChain::leaf_to_root () const
 {
@@ -288,6 +312,9 @@ CertificateChain::leaf_to_root () const
        return c;
 }
 
+/** Add a certificate to the end of the chain.
+ *  @param c Certificate to add.
+ */
 void
 CertificateChain::add (shared_ptr<Certificate> c)
 {
index c7d6698bd513852b3196cc234aff3b44a1c727df..8ec5ddd54be461f315f811b364b900f12a9aeef7 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2014 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
 
 */
 
+/** @file  src/certificates.h
+ *  @brief Certificate and CertificateChain classes.
+ */
+
 #ifndef LIBDCP_CERTIFICATES_H
 #define LIBDCP_CERTIFICATES_H
 
-#include <string>
-#include <list>
+#undef X509_NAME
+#include <openssl/x509.h>
 #include <boost/noncopyable.hpp>
 #include <boost/shared_ptr.hpp>
 #include <boost/filesystem.hpp>
-#undef X509_NAME
-#include <openssl/x509.h>
+#include <string>
+#include <list>
 
 class certificates;
 
@@ -36,6 +40,11 @@ namespace xmlpp {
 
 namespace dcp {
 
+/** @class Certificate
+ *  @brief A wrapper for an X509 certificate.
+ *
+ *  This class can take a Certificate from a file, a string or an OpenSSL X509 object.
+ */
 class Certificate
 {
 public:
@@ -51,16 +60,12 @@ public:
 
        Certificate& operator= (Certificate const &);
 
-       /** @param with_begin_end true to include BEGIN CERTIFICATE / END CERTIFICATE markers
-        *  @return the whole certificate as a string.
-        */
        std::string certificate (bool with_begin_end = false) const;
        std::string issuer () const;
        std::string serial () const;
        std::string subject () const;
        std::string common_name () const;
 
-       /** @return RSA public key from this Certificate.  Caller must not free the returned value. */
        RSA* public_key () const;
 
        std::string thumbprint () const;
@@ -76,6 +81,9 @@ private:
        mutable RSA* _public_key;
 };
 
+/** @class CertificateChain
+ *  @brief A chain of any number of certificates, from root to leaf.
+ */
 class CertificateChain
 {
 public:
index 9a035c8098ee716b9e90ed7d282d218e728b691d..06e2806dbeb269eb507e963eca32f50563c2f712 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2014 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
@@ -33,59 +33,36 @@ using namespace boost;
 using namespace dcp;
 
 Content::Content (boost::filesystem::path file)
-       : _file (file)
-       , _edit_rate (0)
+       : Asset (file)
+       , _edit_rate (24, 1)
        , _intrinsic_duration (0)
 {
 
 }
 
-Content::Content (int edit_rate)
+Content::Content (Fraction edit_rate)
        : _edit_rate (edit_rate)
        , _intrinsic_duration (0)
 {
 
 }
 
-void
-Content::write_to_pkl (xmlpp::Node* node) const
-{
-       xmlpp::Node* asset = node->add_child ("Asset");
-       asset->add_child("Id")->add_child_text ("urn:uuid:" + _id);
-       asset->add_child("AnnotationText")->add_child_text (_id);
-//XXX  asset->add_child("Hash")->add_child_text (digest ());
-       asset->add_child("Size")->add_child_text (lexical_cast<string> (filesystem::file_size (_file)));
-       asset->add_child("Type")->add_child_text ("application/mxf");
-}
-
-void
-Content::write_to_assetmap (xmlpp::Node* node) const
-{
-       xmlpp::Node* asset = node->add_child ("Asset");
-       asset->add_child("Id")->add_child_text ("urn:uuid:" + _id);
-       xmlpp::Node* chunk_list = asset->add_child ("ChunkList");
-       xmlpp::Node* chunk = chunk_list->add_child ("Chunk");
-       chunk->add_child("Path")->add_child_text (_file.string ());
-       chunk->add_child("VolumeIndex")->add_child_text ("1");
-       chunk->add_child("Offset")->add_child_text ("0");
-       chunk->add_child("Length")->add_child_text (lexical_cast<string> (filesystem::file_size (_file)));
-}
-
 bool
-Content::equals (shared_ptr<const Content> other, EqualityOptions, boost::function<void (NoteType, string)> note) const
+Content::equals (shared_ptr<const Content> other, EqualityOptions opt, boost::function<void (NoteType, string)> note) const
 {
-       // if (_edit_rate != other->_edit_rate) {
-       //      note (ERROR, "asset edit rates differ");
-       //      return false;
-       // }
+       if (!Asset::equals (other, opt, note)) {
+               return false;
+       }
        
-       // if (_intrinsic_duration != other->_intrinsic_duration) {
-       //      note (ERROR, "asset intrinsic durations differ");
-       // }
-
-       // if (_duration != other->_duration) {
-       //      note (ERROR, "asset durations differ");
-       // }
+       if (_edit_rate != other->_edit_rate) {
+               note (ERROR, "content edit rates differ");
+               return false;
+       }
+       
+       if (_intrinsic_duration != other->_intrinsic_duration) {
+               note (ERROR, "asset intrinsic durations differ");
+               return false;
+       }
 
-       // return true;
+       return true;
 }
index 75e39a010b92f65868cba970bf6e0bb5125dd8da..57aaa14c84aaebb6e548d31cc419298f17f40a1a 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2014 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
 
 */
 
+/** @file  src/content.h
+ *  @brief Content class.
+ */
+
 #ifndef LIBDCP_CONTENT_H
 #define LIBDCP_CONTENT_H
 
-#include <string>
-#include <list>
-#include <boost/filesystem.hpp>
-#include <boost/function.hpp>
-#include <libxml++/libxml++.h>
 #include "types.h"
 #include "asset.h"
+#include <libxml++/libxml++.h>
+#include <boost/filesystem.hpp>
+#include <boost/function.hpp>
+#include <string>
+#include <list>
 
 namespace ASDCP {
        class WriterInfo;
@@ -48,65 +52,25 @@ class Content : public Asset
 {
 public:
        Content (boost::filesystem::path file);
-       Content (int edit_rate);
+       Content (Fraction edit_rate);
 
        virtual ~Content () {}
 
-       /** Write details of the asset to a PKL AssetList node.
-        *  @param p Parent node.
-        */
-       void write_to_pkl (xmlpp::Node *) const;
-
-       /** Write details of the asset to a ASSETMAP stream.
-        *  @param s Stream.
-        */
-       void write_to_assetmap (xmlpp::Node *) const;
-
-       boost::filesystem::path file () const {
-               return _file;
-       }
-
-       void set_file (boost::filesystem::path file) {
-               _file = file;
-       }
-
-       int edit_rate () const {
+       Fraction edit_rate () const {
                return _edit_rate;
        }
 
-       void set_edit_rate (int r) {
-               _edit_rate = r;
-       }
-
-       void set_entry_point (int64_t p) {
-               _entry_point = p;
-       }
-
        int64_t intrinsic_duration () const {
                return _intrinsic_duration;
        }
 
-       void set_intrinsic_duration (int64_t d) {
-               _intrinsic_duration = d;
-       }
-
-       int64_t duration () const {
-               return _duration;
-       }
-
-       void set_duration (int64_t d) {
-               _duration = d;
-       }
-
        virtual bool equals (boost::shared_ptr<const Content> other, EqualityOptions opt, boost::function<void (NoteType, std::string)>) const;
 
 protected:
-       boost::filesystem::path _file;
-       /** The edit rate; this is normally equal to the number of video frames per second */
-       int _edit_rate;
-       int64_t _entry_point;
+       friend class MXFWriter;
+       
+       Fraction _edit_rate;
        int64_t _intrinsic_duration;
-       int64_t _duration;
 };
 
 }
index 9f7ef7b308b6d179cdc8ab508e6a1cb87bbe21ad..0cd1d6ce16e9d38ec93ef4bb76fede9a8f95ea75 100644 (file)
 
 */
 
-#include <libxml/parser.h>
 #include "cpl.h"
-#include "parse/cpl.h"
 #include "util.h"
 #include "mono_picture_mxf.h"
 #include "stereo_picture_mxf.h"
 #include "sound_mxf.h"
-#include "subtitle_asset.h"
-#include "parse/asset_map.h"
+#include "subtitle_content.h"
 #include "reel.h"
 #include "metadata.h"
 #include "signer.h"
 #include "exceptions.h"
+#include "xml.h"
 #include "compose.hpp"
+#include "reel_picture_asset.h"
+#include "reel_sound_asset.h"
+#include "reel_subtitle_asset.h"
+#include <libxml/parser.h>
 
 using std::string;
 using std::stringstream;
@@ -43,165 +45,56 @@ using boost::lexical_cast;
 using boost::optional;
 using namespace dcp;
 
-CPL::CPL (boost::filesystem::path directory, string name, ContentKind content_kind, int length, int frames_per_second)
-       : _directory (directory)
-       , _name (name)
+CPL::CPL (string annotation_text, ContentKind content_kind)
+       : _annotation_text (annotation_text)
        , _content_kind (content_kind)
-       , _length (length)
-       , _fps (frames_per_second)
+       , _length (0)
 {
 
 }
 
-/** Construct a CPL object from a XML file.
- *  @param directory The directory containing this CPL's DCP.
- *  @param file The CPL XML filename.
- *  @param asset_maps AssetMaps to look for assets in.
- *  @param require_mxfs true to throw an exception if a required MXF file does not exist.
- */
-CPL::CPL (boost::filesystem::path directory, string file, list<PathAssetMap> asset_maps, bool require_mxfs)
-       : _directory (directory)
-       , _content_kind (FEATURE)
+/** Construct a CPL object from a XML file */
+CPL::CPL (boost::filesystem::path file)
+       : _content_kind (FEATURE)
        , _length (0)
-       , _fps (0)
 {
-       /* Read the XML */
-       shared_ptr<parse::CPL> cpl;
-       try {
-               cpl.reset (new parse::CPL (file));
-       } catch (FileError& e) {
-               boost::throw_exception (FileError ("could not load CPL file", file, e.number ()));
-       }
-       
-       /* Now cherry-pick the required bits into our own data structure */
-       
-       _name = cpl->annotation_text;
-       _content_kind = cpl->content_kind;
-
-       /* Trim urn:uuid: off the front */
-       _id = cpl->id.substr (9);
-
-       for (list<shared_ptr<parse::Reel> >::iterator i = cpl->reels.begin(); i != cpl->reels.end(); ++i) {
-
-               shared_ptr<parse::Picture> p;
-
-               if ((*i)->asset_list->main_picture) {
-                       p = (*i)->asset_list->main_picture;
-               } else {
-                       p = (*i)->asset_list->main_stereoscopic_picture;
-               }
-               
-               _fps = p->edit_rate.numerator;
-               _length += p->duration;
-
-               shared_ptr<PictureMXF> picture;
-               shared_ptr<SoundMXF> sound;
-               shared_ptr<SubtitleAsset> subtitle;
-
-               /* Some rather twisted logic to decide if we are 3D or not;
-                  some DCPs give a MainStereoscopicPicture to indicate 3D, others
-                  just have a FrameRate twice the EditRate and apparently
-                  expect you to divine the fact that they are hence 3D.
-               */
-
-               if (!(*i)->asset_list->main_stereoscopic_picture && p->edit_rate == p->frame_rate) {
-
-                       try {
-                               pair<string, shared_ptr<const parse::AssetMapAsset> > asset = asset_from_id (asset_maps, p->id);
-
-//                             picture.reset (new MonoPictureMXF (asset.first, asset.second->chunks.front()->path));
-
-//                             picture->read ();
-//                             picture->set_edit_rate (_fps);
-//                             picture->set_entry_point (p->entry_point);
-//                             picture->set_duration (p->duration);
-                               if (p->key_id.length() > 9) {
-                                       /* Trim urn:uuid: */
-//                                     picture->set_key_id (p->key_id.substr (9));
-                               }
-                       } catch (MXFFileError) {
-                               if (require_mxfs) {
-                                       throw;
-                               }
-                       }
-                       
-               } else {
-                       try {
-                               pair<string, shared_ptr<const parse::AssetMapAsset> > asset = asset_from_id (asset_maps, p->id);
-
-//                             picture.reset (new StereoPictureMXF (asset.first, asset.second->chunks.front()->path));
-
-//                             picture->read ();
-//                             picture->set_edit_rate (_fps);
-//                             picture->set_entry_point (p->entry_point);
-//                             picture->set_duration (p->duration);
-                               if (p->key_id.length() > 9) {
-                                       /* Trim urn:uuid: */
-//                                     picture->set_key_id (p->key_id.substr (9));
-                               }
-                               
-                       } catch (MXFFileError) {
-                               if (require_mxfs) {
-                                       throw;
-                               }
-                       }
-                       
-               }
-               
-               if ((*i)->asset_list->main_sound) {
-                       
-                       try {
-                               pair<string, shared_ptr<const parse::AssetMapAsset> > asset = asset_from_id (asset_maps, (*i)->asset_list->main_sound->id);
-                       
-//                             sound.reset (new SoundMXF (asset.first, asset.second->chunks.front()->path));
-//                             shared_ptr<parse::MainSound> s = (*i)->asset_list->main_sound;
-
-//                             sound->read ();
-//                             sound->set_entry_point (s->entry_point);
-//                             sound->set_duration (s->duration);
-//                             if (s->key_id.length() > 9) {
-                                       /* Trim urn:uuid: */
-//                                     sound->set_key_id (s->key_id.substr (9));
-//                             }
-                       } catch (MXFFileError) {
-                               if (require_mxfs) {
-                                       throw;
-                               }
-                       }
-               }
-
-               if ((*i)->asset_list->main_subtitle) {
-                       
-//                     pair<string, shared_ptr<const parse::AssetMapAsset> > asset = asset_from_id (asset_maps, (*i)->asset_list->main_subtitle->id);
-
-//                     subtitle.reset (new SubtitleAsset (asset.first, asset.second->chunks.front()->path));
-
-//                     subtitle->set_entry_point ((*i)->asset_list->main_subtitle->entry_point);
-//                     subtitle->set_duration ((*i)->asset_list->main_subtitle->duration);
-               }
-                       
-//             _reels.push_back (shared_ptr<Reel> (new Reel (picture, sound, subtitle)));
-       }
+       cxml::Document f ("CompositionPlaylist");
+       f.read_file (file);
+
+       _id = f.string_child ("Id");
+       _annotation_text = f.optional_string_child ("AnnotationText").get_value_or ("");
+       _issue_date = f.string_child ("IssueDate");
+       _creator = f.optional_string_child ("Creator").get_value_or ("");
+       _content_title_text = f.string_child ("ContentTitleText");
+       _content_kind = content_kind_from_string (f.string_child ("ContentKind"));
+       shared_ptr<cxml::Node> content_version = f.node_child ("ContentVersion");
+       if (content_version) {
+               _content_version_id = content_version->optional_string_child ("Id").get_value_or ("");
+               _content_version_label_text = content_version->string_child ("LabelText");
+               content_version->done ();
+       }
+       f.ignore_child ("RatingList");
+       _reels = type_grand_children<Reel> (f, "ReelList", "Reel");
+
+       f.ignore_child ("Issuer");
+       f.ignore_child ("Signer");
+       f.ignore_child ("Signature");
+
+       f.done ();
 }
 
 void
-CPL::add_reel (shared_ptr<Reel> reel)
+CPL::add (shared_ptr<Reel> reel)
 {
        _reels.push_back (reel);
 }
 
 void
-CPL::write_xml (bool interop, XMLMetadata const & metadata, shared_ptr<const Signer> signer) const
+CPL::write_xml (boost::filesystem::path file, Standard standard, XMLMetadata metadata, shared_ptr<const Signer> signer) const
 {
-       boost::filesystem::path p;
-       p /= _directory;
-       stringstream s;
-       s << _id << "_cpl.xml";
-       p /= s.str();
-
        xmlpp::Document doc;
        xmlpp::Element* root;
-       if (interop) {
+       if (standard == INTEROP) {
                root = doc.create_root_node ("CompositionPlaylist", "http://www.digicine.com/PROTO-ASDCP-CPL-20040511#");
        } else {
                root = doc.create_root_node ("CompositionPlaylist", "http://www.smpte-ra.org/schemas/429-7/2006/CPL");
@@ -212,44 +105,34 @@ CPL::write_xml (bool interop, XMLMetadata const & metadata, shared_ptr<const Sig
        }
        
        root->add_child("Id")->add_child_text ("urn:uuid:" + _id);
-       root->add_child("AnnotationText")->add_child_text (_name);
+       root->add_child("AnnotationText")->add_child_text (_annotation_text);
        root->add_child("IssueDate")->add_child_text (metadata.issue_date);
        root->add_child("Issuer")->add_child_text (metadata.issuer);
        root->add_child("Creator")->add_child_text (metadata.creator);
-       root->add_child("ContentTitleText")->add_child_text (_name);
+       root->add_child("ContentTitleText")->add_child_text (_content_version_label_text);
        root->add_child("ContentKind")->add_child_text (content_kind_to_string (_content_kind));
        {
                xmlpp::Node* cv = root->add_child ("ContentVersion");
-               cv->add_child ("Id")->add_child_text ("urn:uri:" + _id + "_" + metadata.issue_date);
-               cv->add_child ("LabelText")->add_child_text (_id + "_" + metadata.issue_date);
+               cv->add_child ("Id")->add_child_text (_content_version_id);
+               cv->add_child ("LabelText")->add_child_text (_content_version_label_text);
        }
        root->add_child("RatingList");
 
        xmlpp::Element* reel_list = root->add_child ("ReelList");
        
        for (list<shared_ptr<Reel> >::const_iterator i = _reels.begin(); i != _reels.end(); ++i) {
-               (*i)->write_to_cpl (reel_list);
+               (*i)->write_to_cpl (reel_list, standard);
        }
 
        if (signer) {
-               signer->sign (root, interop);
+               signer->sign (root, standard);
        }
 
        /* This must not be the _formatted version otherwise signature digests will be wrong */
-       doc.write_to_file (p.string (), "UTF-8");
-
-       _digest = make_digest (p.string (), 0);
-       _length = boost::filesystem::file_size (p.string ());
-}
+       doc.write_to_file (file.string (), "UTF-8");
 
-void
-CPL::write_to_pkl (xmlpp::Node* node) const
-{
-       xmlpp::Node* asset = node->add_child ("Asset");
-       asset->add_child("Id")->add_child_text ("urn:uuid:" + _id);
-       asset->add_child("Hash")->add_child_text (_digest);
-       asset->add_child("Size")->add_child_text (lexical_cast<string> (_length));
-       asset->add_child("Type")->add_child_text ("text/xml");
+       _digest = make_digest (file.string (), 0);
+       _length = boost::filesystem::file_size (file.string ());
 }
 
 list<shared_ptr<const Content> >
@@ -258,13 +141,13 @@ CPL::assets () const
        list<shared_ptr<const Content> > a;
        for (list<shared_ptr<Reel> >::const_iterator i = _reels.begin(); i != _reels.end(); ++i) {
                if ((*i)->main_picture ()) {
-                       a.push_back ((*i)->main_picture ());
+                       a.push_back ((*i)->main_picture()->mxf ());
                }
                if ((*i)->main_sound ()) {
-                       a.push_back ((*i)->main_sound ());
+                       a.push_back ((*i)->main_sound()->mxf ());
                }
                if ((*i)->main_subtitle ()) {
-                       a.push_back ((*i)->main_subtitle ());
+                       a.push_back ((*i)->main_subtitle()->subtitle_content ());
                }
        }
 
@@ -284,14 +167,12 @@ CPL::write_to_assetmap (xmlpp::Node* node) const
        chunk->add_child("Length")->add_child_text(lexical_cast<string> (_length));
 }
        
-       
-       
 bool
 CPL::equals (CPL const & other, EqualityOptions opt, boost::function<void (NoteType, string)> note) const
 {
-       if (_name != other._name && !opt.cpl_names_can_differ) {
+       if (_annotation_text != other._annotation_text && !opt.cpl_annotation_texts_can_differ) {
                stringstream s;
-               s << "names differ: " << _name << " vs " << other._name << "\n";
+               s << "annotation texts differ: " << _annotation_text << " vs " << other._annotation_text << "\n";
                note (ERROR, s.str ());
                return false;
        }
@@ -301,16 +182,6 @@ CPL::equals (CPL const & other, EqualityOptions opt, boost::function<void (NoteT
                return false;
        }
 
-       if (_fps != other._fps) {
-               note (ERROR, String::compose ("frames per second differ (%1 vs %2)", _fps, other._fps));
-               return false;
-       }
-
-       if (_length != other._length) {
-               stringstream s;
-               note (ERROR, String::compose ("lengths differ (%1 vs %2)", _length, other._length));
-       }
-
        if (_reels.size() != other._reels.size()) {
                note (ERROR, String::compose ("reel counts differ (%1 vs %2)", _reels.size(), other._reels.size()));
                return false;
@@ -344,26 +215,13 @@ CPL::encrypted () const
 }
 
 void
-CPL::add_kdm (KDM const & kdm)
+CPL::add (KDM const & kdm)
 {
        for (list<shared_ptr<Reel> >::const_iterator i = _reels.begin(); i != _reels.end(); ++i) {
                (*i)->add_kdm (kdm);
        }
 }
 
-pair<string, shared_ptr<const parse::AssetMapAsset> >
-CPL::asset_from_id (list<PathAssetMap> asset_maps, string id) const
-{
-       for (list<PathAssetMap>::const_iterator i = asset_maps.begin(); i != asset_maps.end(); ++i) {
-               shared_ptr<parse::AssetMapAsset> a = i->second->asset_from_id (id);
-               if (a) {
-                       return make_pair (i->first, a);
-               }
-       }
-
-       return make_pair ("", shared_ptr<const parse::AssetMapAsset> ());
-}
-
 void
 CPL::set_mxf_keys (Key key)
 {
index abfb92f617fdf582a2df4710482b728b2bb4ce93..83fc4b9d552c63f528ebb6814492b29a2e586567 100644 (file)
--- a/src/cpl.h
+++ b/src/cpl.h
 #include "asset.h"
 
 namespace dcp {
-
-namespace parse {
-       class AssetMap;
-       class AssetMapAsset;
-}
        
 class Content;
 class Reel;
@@ -52,16 +47,23 @@ class KDM;
 class CPL : public Asset
 {
 public:
-       CPL (boost::filesystem::path directory, std::string name, ContentKind content_kind, int length, int frames_per_second);
-       CPL (boost::filesystem::path, std::string file, std::list<PathAssetMap> asset_maps, bool require_mxfs = true);
+       CPL (std::string annotation_text, ContentKind content_kind);
+       CPL (boost::filesystem::path file);
 
-       void add_reel (boost::shared_ptr<Reel> reel);
-       
-       /** @return the length in frames */
-       int length () const {
-               return _length;
+       std::string pkl_type () const {
+               return "text/xml";
        }
 
+       void add (boost::shared_ptr<Reel> reel);
+
+       std::string annotation_text () const {
+               return _annotation_text;
+       }
+       
+       std::string content_title_text () const {
+               return _content_title_text;
+       }
+       
        /** @return the type of the content, used by media servers
         *  to categorise things (e.g. feature, trailer, etc.)
         */
@@ -73,18 +75,6 @@ public:
                return _reels;
        }
 
-       /** @return the CPL's name, as will be presented on projector
-        *  media servers and theatre management systems.
-        */
-       std::string name () const {
-               return _name;
-       }
-
-       /** @return the number of frames per second */
-       int frames_per_second () const {
-               return _fps;
-       }
-
        std::list<boost::shared_ptr<const Content> > assets () const;
 
        bool encrypted () const;
@@ -93,29 +83,27 @@ public:
 
        bool equals (CPL const & other, EqualityOptions options, boost::function<void (NoteType, std::string)> note) const;
        
-       void write_xml (bool, XMLMetadata const &, boost::shared_ptr<const Signer>) const;
+       void write_xml (boost::filesystem::path file, Standard standard, XMLMetadata, boost::shared_ptr<const Signer>) const;
        void write_to_assetmap (xmlpp::Node *) const;
-       void write_to_pkl (xmlpp::Node *) const;
 
-       void add_kdm (KDM const &);
+       void add (KDM const &);
        
 private:
-       std::pair<std::string, boost::shared_ptr<const parse::AssetMapAsset> > asset_from_id (std::list<PathAssetMap>, std::string id) const;
        
-       boost::filesystem::path _directory;
-       /** the name of the DCP */
-       std::string _name;
-       /** the content kind of the CPL */
+       std::string _annotation_text;
+       std::string _issue_date;
+       std::string _creator;
+       std::string _content_title_text;
        ContentKind _content_kind;
-       /** length in frames */
-       mutable int _length;
-       /** frames per second */
-       int _fps;
+       std::string _content_version_id;
+       std::string _content_version_label_text;
        /** reels */
        std::list<boost::shared_ptr<Reel> > _reels;
 
        /** a SHA1 digest of our XML */
        mutable std::string _digest;
+       /** length in bytes of the XML that we last wrote to disk */
+       mutable int64_t _length;
 };
 
 }
index a5b0c6e43db811bd7434079f916da808ba9ef8b1..808c040e74307d1be87f234bbfb9b0744f974e6f 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2014 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
 */
 
 /** @file  src/dcp.cc
- *  @brief A class to create a DCP.
+ *  @brief DCP class.
  */
 
-#include <sstream>
-#include <iomanip>
-#include <cassert>
-#include <iostream>
-#include <boost/filesystem.hpp>
-#include <boost/lexical_cast.hpp>
-#include <boost/algorithm/string.hpp>
-#include <boost/lexical_cast.hpp>
-#include <libxml++/libxml++.h>
-#include <xmlsec/xmldsig.h>
-#include <xmlsec/app.h>
 #include "dcp.h"
 #include "sound_mxf.h"
 #include "picture_mxf.h"
-#include "subtitle_asset.h"
+#include "subtitle_content.h"
+#include "mono_picture_mxf.h"
+#include "stereo_picture_mxf.h"
 #include "util.h"
 #include "metadata.h"
 #include "exceptions.h"
-#include "parse/pkl.h"
-#include "parse/asset_map.h"
 #include "reel.h"
 #include "cpl.h"
 #include "signer.h"
 #include "kdm.h"
+#include "compose.hpp"
+#include "AS_DCP.h"
+#include <xmlsec/xmldsig.h>
+#include <xmlsec/app.h>
+#include <libxml++/libxml++.h>
+#include <boost/filesystem.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/algorithm/string.hpp>
+#include <boost/lexical_cast.hpp>
+#include <sstream>
+#include <iomanip>
+#include <cassert>
+#include <iostream>
 
 using std::string;
 using std::list;
@@ -53,8 +55,10 @@ using std::ostream;
 using std::copy;
 using std::back_inserter;
 using std::make_pair;
+using std::map;
 using boost::shared_ptr;
 using boost::lexical_cast;
+using boost::dynamic_pointer_cast;
 using namespace dcp;
 
 DCP::DCP (boost::filesystem::path directory)
@@ -64,33 +68,154 @@ DCP::DCP (boost::filesystem::path directory)
 }
 
 void
-DCP::write_xml (bool interop, XMLMetadata const & metadata, shared_ptr<const Signer> signer) const
+DCP::read ()
 {
-       for (list<shared_ptr<CPL> >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) {
-               (*i)->write_xml (interop, metadata, signer);
+       /* Read the ASSETMAP */
+       
+       boost::filesystem::path asset_map_file;
+       if (boost::filesystem::exists (_directory / "ASSETMAP")) {
+               asset_map_file = _directory / "ASSETMAP";
+       } else if (boost::filesystem::exists (_directory / "ASSETMAP.xml")) {
+               asset_map_file = _directory / "ASSETMAP.xml";
+       } else {
+               boost::throw_exception (DCPReadError ("could not find AssetMap file"));
+       }
+
+       cxml::Document asset_map ("AssetMap");
+       asset_map.read_file (asset_map_file);
+       list<shared_ptr<cxml::Node> > assets = asset_map.node_child("AssetList")->node_children ("Asset");
+       map<string, boost::filesystem::path> paths;
+       for (list<shared_ptr<cxml::Node> >::const_iterator i = assets.begin(); i != assets.end(); ++i) {
+               if ((*i)->node_child("ChunkList")->node_children("Chunk").size() != 1) {
+                       boost::throw_exception (XMLError ("unsupported asset chunk count"));
+               }
+               paths.insert (make_pair (
+                       (*i)->string_child ("Id"),
+                       (*i)->node_child("ChunkList")->node_child("Chunk")->string_child ("Path")
+                                     ));
        }
 
-       string pkl_uuid = make_uuid ();
-       string pkl_path = write_pkl (pkl_uuid, interop, metadata, signer);
+       /* Read all the assets from the asset map */
        
-       write_volindex (interop);
-       write_assetmap (pkl_uuid, boost::filesystem::file_size (pkl_path), interop, metadata);
+       for (map<string, boost::filesystem::path>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
+               if (boost::algorithm::ends_with (i->second.string(), ".xml")) {
+                       xmlpp::DomParser* p = new xmlpp::DomParser;
+                       try {
+                               p->parse_file (i->second.string());
+                       } catch (std::exception& e) {
+                               delete p;
+                               continue;
+                       }
+                       
+                       string const root = p->get_document()->get_root_node()->get_name ();
+                       delete p;
+                       
+                       if (root == "CompositionPlaylist") {
+                               _assets.push_back (shared_ptr<CPL> (new CPL (i->second)));
+                       } else if (root == "DCSubtitle") {
+                               _assets.push_back (shared_ptr<SubtitleContent> (new SubtitleContent (i->second)));
+                       }
+               } else if (boost::algorithm::ends_with (i->second.string(), ".mxf")) {
+                       ASDCP::EssenceType_t type;
+                       if (ASDCP::EssenceType (i->second.string().c_str(), type) != ASDCP::RESULT_OK) {
+                               throw DCPReadError ("Could not find essence type");
+                       }
+                       switch (type) {
+                               case ASDCP::ESS_UNKNOWN:
+                               case ASDCP::ESS_MPEG2_VES:
+                                       throw DCPReadError ("MPEG2 video essences are not supported");
+                               case ASDCP::ESS_JPEG_2000:
+                                       _assets.push_back (shared_ptr<MonoPictureMXF> (new MonoPictureMXF (i->second)));
+                                       break;
+                               case ASDCP::ESS_PCM_24b_48k:
+                               case ASDCP::ESS_PCM_24b_96k:
+                                       _assets.push_back (shared_ptr<SoundMXF> (new SoundMXF (i->second)));
+                                       break;
+                               case ASDCP::ESS_JPEG_2000_S:
+                                       _assets.push_back (shared_ptr<StereoPictureMXF> (new StereoPictureMXF (i->second)));
+                                       break;
+                               default:
+                                       throw DCPReadError ("Unknown MXF essence type");
+                               }
+               }
+       }
+}
+
+bool
+DCP::equals (DCP const & other, EqualityOptions opt, boost::function<void (NoteType, string)> note) const
+{
+       if (_assets.size() != other._assets.size()) {
+               note (ERROR, "Asset counts differ");
+               return false;
+       }
+
+       list<shared_ptr<Asset> >::const_iterator a = _assets.begin ();
+       list<shared_ptr<Asset> >::const_iterator b = other._assets.begin ();
+
+       while (a != _assets.end ()) {
+               if (!(*a)->equals (*b, opt, note)) {
+                       return false;
+               }
+               ++a;
+               ++b;
+       }
+
+       return true;
+}
+
+void
+DCP::add (shared_ptr<Asset> asset)
+{
+       _assets.push_back (asset);
 }
 
-std::string
-DCP::write_pkl (string pkl_uuid, bool interop, XMLMetadata const & metadata, shared_ptr<const Signer> signer) const
+class AssetComparator
 {
-       assert (!_cpls.empty ());
+public:
+       bool operator() (shared_ptr<const Content> a, shared_ptr<const Content> b) {
+               return a->id() < b->id();
+       }
+};
+
+bool
+DCP::encrypted () const
+{
+       list<shared_ptr<CPL> > cpl = cpls ();
+       for (list<shared_ptr<CPL> >::const_iterator i = cpl.begin(); i != cpl.end(); ++i) {
+               if ((*i)->encrypted ()) {
+                       return true;
+               }
+       }
+
+       return false;
+}
+
+void
+DCP::add (KDM const & kdm)
+{
+       list<KDMKey> keys = kdm.keys ();
+       list<shared_ptr<CPL> > cpl = cpls ();
        
-       boost::filesystem::path p;
-       p /= _directory;
+       for (list<shared_ptr<CPL> >::iterator i = cpl.begin(); i != cpl.end(); ++i) {
+               for (list<KDMKey>::iterator j = keys.begin(); j != keys.end(); ++j) {
+                       if (j->cpl_id() == (*i)->id()) {
+                               (*i)->add (kdm);
+                       }                               
+               }
+       }
+}
+
+boost::filesystem::path
+DCP::write_pkl (Standard standard, string pkl_uuid, XMLMetadata metadata, shared_ptr<const Signer> signer) const
+{
+       boost::filesystem::path p = _directory;
        stringstream s;
        s << pkl_uuid << "_pkl.xml";
        p /= s.str();
 
        xmlpp::Document doc;
        xmlpp::Element* pkl;
-       if (interop) {
+       if (standard == INTEROP) {
                pkl = doc.create_root_node("PackingList", "http://www.digicine.com/PROTO-ASDCP-PKL-20040311#");
        } else {
                pkl = doc.create_root_node("PackingList", "http://www.smpte-ra.org/schemas/429-8/2007/PKL");
@@ -101,36 +226,49 @@ DCP::write_pkl (string pkl_uuid, bool interop, XMLMetadata const & metadata, sha
        }
 
        pkl->add_child("Id")->add_child_text ("urn:uuid:" + pkl_uuid);
+
        /* XXX: this is a bit of a hack */
-       pkl->add_child("AnnotationText")->add_child_text(_cpls.front()->name());
+       list<shared_ptr<Asset> >::const_iterator i = _assets.begin();
+       shared_ptr<CPL> first_cpl;
+       while (i != _assets.end()) {
+               first_cpl = dynamic_pointer_cast<CPL> (*i);
+               if (first_cpl) {
+                       break;
+               }
+       }
+
+       assert (first_cpl);
+       pkl->add_child("AnnotationText")->add_child_text (first_cpl->annotation_text ());
+       
        pkl->add_child("IssueDate")->add_child_text (metadata.issue_date);
        pkl->add_child("Issuer")->add_child_text (metadata.issuer);
        pkl->add_child("Creator")->add_child_text (metadata.creator);
 
        xmlpp::Element* asset_list = pkl->add_child("AssetList");
-       list<shared_ptr<const Content> > a = assets ();
-       for (list<shared_ptr<const Content> >::const_iterator i = a.begin(); i != a.end(); ++i) {
-               (*i)->write_to_pkl (asset_list);
-       }
-       
-       for (list<shared_ptr<CPL> >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) {
-               (*i)->write_to_pkl (asset_list);
+
+       for (list<shared_ptr<Asset> >::const_iterator i = _assets.begin(); i != _assets.end(); ++i) {
+               shared_ptr<Content> c = dynamic_pointer_cast<Content> (*i);
+               if (c) {
+                       c->write_to_pkl (asset_list);
+               }
        }
 
        if (signer) {
-               signer->sign (pkl, interop);
+               signer->sign (pkl, standard);
        }
                
        doc.write_to_file (p.string (), "UTF-8");
        return p.string ();
 }
 
+/** Write the VOLINDEX file.
+ *  @param standard DCP standard to use (INTEROP or SMPTE)
+ */
 void
-DCP::write_volindex (bool interop) const
+DCP::write_volindex (Standard standard) const
 {
-       boost::filesystem::path p;
-       p /= _directory;
-       if (interop) {
+       boost::filesystem::path p = _directory;
+       if (standard == INTEROP) {
                p /= "VOLINDEX";
        } else {
                p /= "VOLINDEX.xml";
@@ -143,11 +281,10 @@ DCP::write_volindex (bool interop) const
 }
 
 void
-DCP::write_assetmap (string pkl_uuid, int pkl_length, bool interop, XMLMetadata const & metadata) const
+DCP::write_assetmap (Standard standard, string pkl_uuid, int pkl_length, XMLMetadata metadata) const
 {
-       boost::filesystem::path p;
-       p /= _directory;
-       if (interop) {
+       boost::filesystem::path p = _directory;
+       if (standard == INTEROP) {
                p /= "ASSETMAP";
        } else {
                p /= "ASSETMAP.xml";
@@ -155,7 +292,7 @@ DCP::write_assetmap (string pkl_uuid, int pkl_length, bool interop, XMLMetadata
 
        xmlpp::Document doc;
        xmlpp::Element* root;
-       if (interop) {
+       if (standard == INTEROP) {
                root = doc.create_root_node ("AssetMap", "http://www.digicine.com/PROTO-ASDCP-AM-20040311#");
        } else {
                root = doc.create_root_node ("AssetMap", "http://www.smpte-ra.org/schemas/429-9/2007/AM");
@@ -163,7 +300,7 @@ DCP::write_assetmap (string pkl_uuid, int pkl_length, bool interop, XMLMetadata
 
        root->add_child("Id")->add_child_text ("urn:uuid:" + make_uuid());
        root->add_child("AnnotationText")->add_child_text ("Created by " + metadata.creator);
-       if (interop) {
+       if (standard == INTEROP) {
                root->add_child("VolumeCount")->add_child_text ("1");
                root->add_child("IssueDate")->add_child_text (metadata.issue_date);
                root->add_child("Issuer")->add_child_text (metadata.issuer);
@@ -187,12 +324,7 @@ DCP::write_assetmap (string pkl_uuid, int pkl_length, bool interop, XMLMetadata
        chunk->add_child("Offset")->add_child_text ("0");
        chunk->add_child("Length")->add_child_text (lexical_cast<string> (pkl_length));
        
-       for (list<shared_ptr<CPL> >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) {
-               (*i)->write_to_assetmap (asset_list);
-       }
-
-       list<shared_ptr<const Content> > a = assets ();
-       for (list<shared_ptr<const Content> >::const_iterator i = a.begin(); i != a.end(); ++i) {
+       for (list<shared_ptr<Asset> >::const_iterator i = _assets.begin(); i != _assets.end(); ++i) {
                (*i)->write_to_assetmap (asset_list);
        }
 
@@ -201,173 +333,39 @@ DCP::write_assetmap (string pkl_uuid, int pkl_length, bool interop, XMLMetadata
 }
 
 void
-DCP::read (bool require_mxfs)
+DCP::write_xml (
+       Standard standard,
+       XMLMetadata metadata,
+       shared_ptr<const Signer> signer
+       )
 {
-       read_assets ();
-       read_cpls (require_mxfs);
-}
-
-void
-DCP::read_assets ()
-{
-       shared_ptr<parse::AssetMap> asset_map;
-       try {
-               boost::filesystem::path p = _directory;
-               p /= "ASSETMAP";
-               if (boost::filesystem::exists (p)) {
-                       asset_map.reset (new dcp::parse::AssetMap (p.string ()));
-               } else {
-                       p = _directory;
-                       p /= "ASSETMAP.xml";
-                       if (boost::filesystem::exists (p)) {
-                               asset_map.reset (new dcp::parse::AssetMap (p.string ()));
-                       } else {
-                               boost::throw_exception (DCPReadError ("could not find AssetMap file"));
-                       }
-               }
-               
-       } catch (FileError& e) {
-               boost::throw_exception (FileError ("could not load AssetMap file", _files.asset_map, e.number ()));
-       }
-
-       for (list<shared_ptr<dcp::parse::AssetMapAsset> >::const_iterator i = asset_map->assets.begin(); i != asset_map->assets.end(); ++i) {
-               if ((*i)->chunks.size() != 1) {
-                       boost::throw_exception (XMLError ("unsupported asset chunk count"));
-               }
-
-               boost::filesystem::path t = _directory;
-               t /= (*i)->chunks.front()->path;
-               
-               if (boost::algorithm::ends_with (t.string(), ".mxf") || boost::algorithm::ends_with (t.string(), ".ttf")) {
-                       continue;
-               }
-
-               xmlpp::DomParser* p = new xmlpp::DomParser;
-               try {
-                       p->parse_file (t.string());
-               } catch (std::exception& e) {
-                       delete p;
-                       continue;
-               }
-
-               string const root = p->get_document()->get_root_node()->get_name ();
-               delete p;
-
-               if (root == "CompositionPlaylist") {
-                       _files.cpls.push_back (t.string());
-               } else if (root == "PackingList") {
-                       if (_files.pkl.empty ()) {
-                               _files.pkl = t.string();
-                       } else {
-                               boost::throw_exception (DCPReadError ("duplicate PKLs found"));
-                       }
-               }
-       }
+       string const pkl_uuid = make_uuid ();
+       boost::filesystem::path const pkl_path = write_pkl (standard, pkl_uuid, metadata, signer);
        
-       if (_files.cpls.empty ()) {
-               boost::throw_exception (DCPReadError ("no CPL files found"));
-       }
-
-       if (_files.pkl.empty ()) {
-               boost::throw_exception (DCPReadError ("no PKL file found"));
-       }
-
-       shared_ptr<parse::PKL> pkl;
-       try {
-               pkl.reset (new parse::PKL (_files.pkl));
-       } catch (FileError& e) {
-               boost::throw_exception (FileError ("could not load PKL file", _files.pkl, e.number ()));
-       }
-
-       _asset_maps.push_back (make_pair (boost::filesystem::absolute (_directory).string(), asset_map));
-}
-
-void
-DCP::read_cpls (bool require_mxfs)
-{
-       for (list<string>::iterator i = _files.cpls.begin(); i != _files.cpls.end(); ++i) {
-               _cpls.push_back (shared_ptr<CPL> (new CPL (_directory, *i, _asset_maps, require_mxfs)));
-       }
-}
-
-bool
-DCP::equals (DCP const & other, EqualityOptions opt, boost::function<void (NoteType, string)> note) const
-{
-       if (_cpls.size() != other._cpls.size()) {
-               note (ERROR, "CPL counts differ");
-               return false;
-       }
-
-       list<shared_ptr<CPL> >::const_iterator a = _cpls.begin ();
-       list<shared_ptr<CPL> >::const_iterator b = other._cpls.begin ();
-
-       while (a != _cpls.end ()) {
-               if (!(*a)->equals (*b->get(), opt, note)) {
-                       return false;
+       write_volindex (standard);
+       write_assetmap (standard, pkl_uuid, boost::filesystem::file_size (pkl_path), metadata);
+
+       for (list<shared_ptr<Asset> >::const_iterator i = _assets.begin(); i != _assets.end(); ++i) {
+               shared_ptr<CPL> c = dynamic_pointer_cast<CPL> (*i);
+               if (c) {
+                       string const filename = c->id() + "_cpl.xml";
+                       c->write_xml (_directory / filename, standard, metadata, signer);
                }
-               ++a;
-               ++b;
-       }
-
-       return true;
-}
-
-void
-DCP::add_cpl (shared_ptr<CPL> cpl)
-{
-       _cpls.push_back (cpl);
-}
-
-class AssetComparator
-{
-public:
-       bool operator() (shared_ptr<const Content> a, shared_ptr<const Content> b) {
-               return a->id() < b->id();
-       }
-};
-
-list<shared_ptr<const Content> >
-DCP::assets () const
-{
-       list<shared_ptr<const Content> > a;
-       for (list<shared_ptr<CPL> >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) {
-               list<shared_ptr<const Content> > t = (*i)->assets ();
-               a.merge (t);
        }
-
-       a.sort (AssetComparator ());
-       a.unique ();
-       return a;
 }
 
-bool
-DCP::encrypted () const
+list<shared_ptr<CPL> >
+DCP::cpls () const
 {
-       for (list<shared_ptr<CPL> >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) {
-               if ((*i)->encrypted ()) {
-                       return true;
+       list<shared_ptr<CPL> > cpls;
+       for (list<shared_ptr<Asset> >::const_iterator i = _assets.begin(); i != _assets.end(); ++i) {
+               shared_ptr<CPL> c = dynamic_pointer_cast<CPL> (*i);
+               if (c) {
+                       cpls.push_back (c);
                }
        }
 
-       return false;
+       return cpls;
 }
 
-void
-DCP::add_kdm (KDM const & kdm)
-{
-       list<KDMKey> keys = kdm.keys ();
        
-       for (list<shared_ptr<CPL> >::iterator i = _cpls.begin(); i != _cpls.end(); ++i) {
-               for (list<KDMKey>::iterator j = keys.begin(); j != keys.end(); ++j) {
-                       if (j->cpl_id() == (*i)->id()) {
-                               (*i)->add_kdm (kdm);
-                       }                               
-               }
-       }
-}
-
-void
-DCP::add_assets_from (DCP const & ov)
-{
-       copy (ov._asset_maps.begin(), ov._asset_maps.end(), back_inserter (_asset_maps));
-}
index 19903d3f89807f5b2d42b1d191575c74d696cd08..9f6d60fd8896de80c2edcd437a0616dec89831f1 100644 (file)
--- a/src/dcp.h
+++ b/src/dcp.h
 #ifndef LIBDCP_DCP_H
 #define LIBDCP_DCP_H
 
-#include <string>
-#include <vector>
-#include <boost/shared_ptr.hpp>
-#include <boost/signals2.hpp>
 #include "types.h"
 #include "certificates.h"
+#include "metadata.h"
+#include <boost/shared_ptr.hpp>
+#include <boost/signals2.hpp>
+#include <string>
+#include <vector>
 
 namespace xmlpp {
        class Document;
@@ -41,14 +42,12 @@ namespace dcp
 {
 
 class Content; 
-class PictureAsset;
-class SoundAsset;
-class SubtitleAsset;
 class Reel;
 class CPL;
 class XMLMetadata;
 class Signer;
 class KDM;
+class Asset;
 
 namespace parse {
        class AssetMap;
@@ -69,21 +68,7 @@ public:
         */
        DCP (boost::filesystem::path directory);
 
-       void read (bool require_mxfs = true);
-
-       /** Read an existing DCP's assets.
-        *
-        *  The DCP's XML metadata will be examined, and you can then look at the contents
-        *  of the DCP.
-        */
-       void read_assets ();
-
-       void read_cpls (bool require_mxfs = true);
-
-       /** Write the required XML files to the directory that was
-        *  passed into the constructor.
-        */
-       void write_xml (bool interop, XMLMetadata const &, boost::shared_ptr<const Signer> signer = boost::shared_ptr<const Signer> ()) const;
+       void read ();
 
        /** Compare this DCP with another, according to various options.
         *  @param other DCP to compare this one to.
@@ -92,29 +77,19 @@ public:
         */
        bool equals (DCP const & other, EqualityOptions options, boost::function<void (NoteType, std::string)> note) const;
 
-       /** Add a CPL to this DCP.
-        *  @param cpl CPL to add.
-        */
-       void add_cpl (boost::shared_ptr<CPL> cpl);
-
-       /** @return The list of CPLs in this DCP */
-       std::list<boost::shared_ptr<CPL> > cpls () const {
-               return _cpls;
-       }
+       void add (boost::shared_ptr<Asset> asset);
 
-       /** Add another DCP as a source of assets for this DCP.  This should be called before
-        *  ::read() on the DCP that needs the extra assets.  For example
-        *
-        *  DCP original_version ("my_dcp_OV");
-        *  DCP supplemental ("my_dcp_VF");
-        *  supplemental.add_assets_from (original_version);
-        *  supplemental.read ();
-        */
-       void add_assets_from (DCP const &);
+       std::list<boost::shared_ptr<CPL> > cpls () const;
 
        bool encrypted () const;
 
-       void add_kdm (KDM const &);
+       void add (KDM const &);
+
+       void write_xml (
+               Standard standard,
+               XMLMetadata metadata = XMLMetadata (),
+               boost::shared_ptr<const Signer> signer = boost::shared_ptr<const Signer> ()
+       );
 
        /** Emitted with a parameter between 0 and 1 to indicate progress
         *  for long jobs.
@@ -126,34 +101,19 @@ private:
        /** Write the PKL file.
         *  @param pkl_uuid UUID to use.
         */
-       std::string write_pkl (std::string pkl_uuid, bool, XMLMetadata const &, boost::shared_ptr<const Signer>) const;
+       boost::filesystem::path write_pkl (Standard standard, std::string pkl_uuid, XMLMetadata metadata, boost::shared_ptr<const Signer> signer) const;
        
-       /** Write the VOLINDEX file */
-       void write_volindex (bool) const;
+       void write_volindex (Standard standard) const;
 
        /** Write the ASSETMAP file.
         *  @param pkl_uuid UUID of our PKL.
         *  @param pkl_length Length of our PKL in bytes.
         */
-       void write_assetmap (std::string pkl_uuid, int pkl_length, bool, XMLMetadata const &) const;
-
-       /** @return Assets in all the CPLs in this DCP */
-       std::list<boost::shared_ptr<const Content> > assets () const;
-
-       struct Files {
-               std::list<std::string> cpls;
-               std::string pkl;
-               std::string asset_map;
-       };
-
-       Files _files;
+       void write_assetmap (Standard standard, std::string pkl_uuid, int pkl_length, XMLMetadata metadata) const;
 
        /** the directory that we are writing to */
        boost::filesystem::path _directory;
-       /** our CPLs */
-       std::list<boost::shared_ptr<CPL> > _cpls;
-
-       std::list<PathAssetMap> _asset_maps;
+       std::list<boost::shared_ptr<Asset> > _assets;
 };
 
 }
index c3755a6017f3f233949fae6e7ef4f587fbde59ce..e5a46948ce504ef14f8164a3ab8ec585ec3586fa 100644 (file)
 
 */
 
+/** @file  src/exceptions.cc
+ *  @brief Exceptions thrown by libdcp.
+ */
+
 #include "exceptions.h"
 #include "compose.hpp"
 
 using std::string;
 using namespace dcp;
 
-FileError::FileError (std::string const & message, boost::filesystem::path filename, int number)
+FileError::FileError (string message, boost::filesystem::path filename, int number)
        : _message (String::compose ("%1 (error %2) (%3)", message, filename.string(), number))
        , _filename (filename)
        , _number (number)
@@ -31,3 +35,9 @@ FileError::FileError (std::string const & message, boost::filesystem::path filen
 
 }
 
+UnresolvedRefError::UnresolvedRefError (string id)
+       : _message (String::compose ("Unresolved reference to asset id %1", id))
+{
+
+}
+
index 2a7fbdda0deec42ed4fabd159f62dc5bb2759ee1..c1d47e51b6588ff04662eea9c08986073461280d 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2014 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
@@ -33,7 +33,7 @@ namespace dcp
 class FileError : public std::exception
 {
 public:
-       FileError (std::string const & message, boost::filesystem::path filename, int number);
+       FileError (std::string message, boost::filesystem::path filename, int number);
        ~FileError () throw () {}
 
        /** @return error message */
@@ -63,7 +63,7 @@ private:
 class MXFFileError : public FileError
 {
 public:
-       MXFFileError (std::string const & message, boost::filesystem::path filename, int number)
+       MXFFileError (std::string message, boost::filesystem::path filename, int number)
                : FileError (message, filename, number)
        {}
 };
@@ -72,7 +72,7 @@ public:
 class MiscError : public std::exception
 {
 public:
-       MiscError (std::string const & message) : _message (message) {}
+       MiscError (std::string message) : _message (message) {}
        ~MiscError () throw () {}
 
        /** @return error message */
@@ -89,7 +89,7 @@ private:
 class DCPReadError : public std::exception
 {
 public:
-       DCPReadError (std::string const & message) : _message (message) {}
+       DCPReadError (std::string message) : _message (message) {}
        ~DCPReadError () throw () {}
 
        /** @return error message */
@@ -106,7 +106,7 @@ private:
 class XMLError : public std::exception
 {
 public:
-       XMLError (std::string const & message) : _message (message) {}
+       XMLError (std::string message) : _message (message) {}
        ~XMLError () throw () {}
 
        /** @return error message */
@@ -118,6 +118,21 @@ private:
        /** error message */
        std::string _message;
 };
+
+class UnresolvedRefError : public std::exception
+{
+public:
+       UnresolvedRefError (std::string id);
+       ~UnresolvedRefError () throw () {}
+
+       /** @return error message */
+       char const * what () const throw () {
+               return _message.c_str ();
+       }
+
+private:
+       std::string _message;
+};
        
 }
 
diff --git a/src/file.cc b/src/file.cc
new file mode 100644 (file)
index 0000000..d39f93e
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+    Copyright (C) 2014 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 "file.h"
+#include "util.h"
+
+using namespace dcp;
+
+File::File (boost::filesystem::path file)
+{
+       _size = boost::filesystem::file_size (file);
+       _data = new uint8_t[_size];
+       FILE* f = dcp::fopen_boost (file, "r");
+       assert (f);
+       fread (_data, 1, _size, f);
+       fclose (f);
+}
+
+File::~File ()
+{
+       delete[] _data;
+}
diff --git a/src/file.h b/src/file.h
new file mode 100644 (file)
index 0000000..f2b9920
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+    Copyright (C) 2014 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/filesystem.hpp>
+
+namespace dcp {
+
+class File
+{
+public:
+       File (boost::filesystem::path file);
+       ~File ();
+       
+       uint8_t* data () const {
+               return _data;
+       }
+
+       int64_t size () const {
+               return _size;
+       }
+
+private:
+       uint8_t* _data;
+       int64_t _size;
+};
+
+}
diff --git a/src/font.cc b/src/font.cc
new file mode 100644 (file)
index 0000000..5a568a6
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+    Copyright (C) 2012-2014 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 "font.h"
+#include "xml.h"
+#include "text.h"
+#include <libcxml/cxml.h>
+
+using std::string;
+using std::list;
+using boost::shared_ptr;
+using boost::optional;
+using namespace dcp;
+
+Font::Font (shared_ptr<const cxml::Node> node)
+{
+       text = node->content ();
+       
+       id = node->optional_string_attribute ("Id").get_value_or ("");
+       size = node->optional_number_attribute<int64_t> ("Size").get_value_or (0);
+       italic = node->optional_bool_attribute ("Italic");
+       optional<string> c = node->optional_string_attribute ("Color");
+       if (c) {
+               color = Color (c.get ());
+       }
+       optional<string> const e = node->optional_string_attribute ("Effect");
+       if (e) {
+               effect = string_to_effect (e.get ());
+       }
+       c = node->optional_string_attribute ( "EffectColor");
+       if (c) {
+               effect_color = Color (c.get ());
+       }
+       subtitle_nodes = type_children<Subtitle> (node, "Subtitle");
+       font_nodes = type_children<Font> (node, "Font");
+       text_nodes = type_children<Text> (node, "Text");
+}
+
+Font::Font (list<shared_ptr<Font> > const & font_nodes)
+       : size (0)
+       , italic (false)
+       , color ("FFFFFFFF")
+       , effect_color ("FFFFFFFF")
+{
+       for (list<shared_ptr<Font> >::const_iterator i = font_nodes.begin(); i != font_nodes.end(); ++i) {
+               if (!(*i)->id.empty ()) {
+                       id = (*i)->id;
+               }
+               if ((*i)->size != 0) {
+                       size = (*i)->size;
+               }
+               if ((*i)->italic) {
+                       italic = (*i)->italic.get ();
+               }
+               if ((*i)->color) {
+                       color = (*i)->color.get ();
+               }
+               if ((*i)->effect) {
+                       effect = (*i)->effect.get ();
+               }
+               if ((*i)->effect_color) {
+                       effect_color = (*i)->effect_color.get ();
+               }
+       }
+}
diff --git a/src/font.h b/src/font.h
new file mode 100644 (file)
index 0000000..1b29e57
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+    Copyright (C) 2012-2014 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 "types.h"
+#include "subtitle.h"
+#include <boost/shared_ptr.hpp>
+#include <boost/optional.hpp>
+#include <list>
+
+namespace cxml {
+       class Node;
+}
+
+namespace dcp {
+       
+class Font 
+{
+public:
+       Font ()
+               : size (0)
+       {}
+       
+       Font (boost::shared_ptr<const cxml::Node> node);
+       Font (std::list<boost::shared_ptr<Font> > const & font_nodes);
+
+       std::string text;
+       std::string id;
+       int size;
+       boost::optional<bool> italic;
+       boost::optional<Color> color;
+       boost::optional<Effect> effect;
+       boost::optional<Color> effect_color;
+       
+       std::list<boost::shared_ptr<Subtitle> > subtitle_nodes;
+       std::list<boost::shared_ptr<Font> > font_nodes;
+       std::list<boost::shared_ptr<Text> > text_nodes;
+};
+
+}
index 0b8ad2fd6d9048887acfa1727de8e022f02b0b9e..1a954914616130e89df3486c90d2133bd9329c82 100644 (file)
 
 */
 
-#include <cmath>
 #include "gamma_lut.h"
 #include "lut_cache.h"
+#include <cmath>
 
 using namespace dcp;
 
 LUTCache<GammaLUT> GammaLUT::cache;
 
-GammaLUT::GammaLUT(int bits, float gamma)
+GammaLUT::GammaLUT (int bits, float gamma)
        : LUT (bits, gamma)
 {
-       int const bit_length = pow(2, bits);
+       int const bit_length = pow (2, bits);
        for (int i = 0; i < bit_length; ++i) {
                _lut[i] = pow(float(i) / (bit_length - 1), gamma);
        }
index 095ad882c0afeb20d81c54d9998152a7cc5e49c3..31615afd22f60d3fe5ba2b0ec48ec6ba1b5e033d 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2014 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
index bdfa1fec458b6f83026b8a21d08dcee829fe9679..92e9a756c4a6f622c79732eaff9f1253fa5b67a0 100644 (file)
@@ -108,7 +108,7 @@ KDM::KDM (
        apu.recipient.x509_subject_name = recipient_cert->subject ();
        apu.composition_playlist_id = "urn:uuid:" + cpl->id ();
 //     apu.content_authenticator = signer->certificates().leaf()->thumbprint ();
-       apu.content_title_text = cpl->name ();
+       apu.content_title_text = cpl->content_title_text ();
        apu.content_keys_not_valid_before = ptime_to_string (not_valid_before);
        apu.content_keys_not_valid_after = ptime_to_string (not_valid_after);
        apu.authorized_device_info.device_list_identifier = "urn:uuid:" + make_uuid ();
index be9f95f46355e6f49ac3b08e841650bda440ebb6..d6b2f2f27d683964fb3d26fe21eae417b36e6051 100644 (file)
--- a/src/key.h
+++ b/src/key.h
@@ -25,6 +25,7 @@
 #define LIBDCP_KEY_H
 
 #include <stdint.h>
+#include <string>
 
 namespace dcp {
 
diff --git a/src/load_font.cc b/src/load_font.cc
new file mode 100644 (file)
index 0000000..a337856
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+    Copyright (C) 2012-2014 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 "load_font.h"
+#include <libcxml/cxml.h>
+
+using boost::shared_ptr;
+using namespace dcp;
+
+LoadFont::LoadFont (shared_ptr<const cxml::Node> node)
+{
+       id = node->string_attribute ("Id");
+       uri = node->string_attribute ("URI");
+}
diff --git a/src/load_font.h b/src/load_font.h
new file mode 100644 (file)
index 0000000..6319b1d
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+    Copyright (C) 2012-2014 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/shared_ptr.hpp>
+
+namespace cxml {
+       class Node;
+}
+
+namespace dcp {
+       
+class LoadFont 
+{
+public:
+       LoadFont () {}
+       LoadFont (boost::shared_ptr<const cxml::Node> node);
+
+       std::string id;
+       std::string uri;
+};
+
+}
index cea21c158f93270baea8373b5fd04317f1903022..e33454dc0cdd5045d5caaca5a4ff6bfadc9e6fb0 100644 (file)
@@ -45,14 +45,10 @@ MonoPictureMXF::MonoPictureMXF (boost::filesystem::path file)
                boost::throw_exception (DCPReadError ("could not read video MXF information"));
        }
 
-       _size.width = desc.StoredWidth;
-       _size.height = desc.StoredHeight;
-       _edit_rate = desc.EditRate.Numerator;
-       assert (desc.EditRate.Denominator == 1);
-       _intrinsic_duration = desc.ContainerDuration;
+       read_picture_descriptor (desc);
 }
 
-MonoPictureMXF::MonoPictureMXF (int edit_rate)
+MonoPictureMXF::MonoPictureMXF (Fraction edit_rate)
        : PictureMXF (edit_rate)
 {
        
@@ -121,10 +117,10 @@ MonoPictureMXF::equals (shared_ptr<const Content> other, EqualityOptions opt, bo
 }
 
 shared_ptr<PictureMXFWriter>
-MonoPictureMXF::start_write (boost::filesystem::path file, bool overwrite)
+MonoPictureMXF::start_write (boost::filesystem::path file, Standard standard, bool overwrite)
 {
        /* XXX: can't we use shared_ptr here? */
-       return shared_ptr<MonoPictureMXFWriter> (new MonoPictureMXFWriter (this, file, overwrite));
+       return shared_ptr<MonoPictureMXFWriter> (new MonoPictureMXFWriter (this, file, standard, overwrite));
 }
 
 string
index 8c8ee53123c322df94fe5b7beee43db5c5ba25b8..9f0a2eead3f174a833c1418c3e26578e639ad2d3 100644 (file)
@@ -24,6 +24,8 @@
 
 namespace dcp {
 
+class MonoPictureMXFWriter;    
+
 /** @class MonoPictureMXF
  *  @brief A 2D (monoscopic) picture MXF.
  */
@@ -38,10 +40,10 @@ public:
        /** Create a MonoPictureMXF with a given edit rate.
         *  @param edit_rate Edit rate (i.e. frame rate) in frames per second.
         */
-       MonoPictureMXF (int edit_rate);
+       MonoPictureMXF (Fraction edit_rate);
 
        /** Start a progressive write to a MonoPictureMXF */
-       boost::shared_ptr<PictureMXFWriter> start_write (boost::filesystem::path, bool);
+       boost::shared_ptr<PictureMXFWriter> start_write (boost::filesystem::path, Standard standard, bool);
 
        boost::shared_ptr<const MonoPictureFrame> get_frame (int n) const;
        bool equals (boost::shared_ptr<const Content> other, EqualityOptions opt, boost::function<void (NoteType, std::string)> note) const;
index 590a3f7d1e54d77cb04cc62e2bcd7a2294525c23..619d298e26ef1db3bff596227f2b7462d4c86e32 100644 (file)
@@ -40,8 +40,8 @@ struct MonoPictureMXFWriter::ASDCPState : public ASDCPStateBase
 /** @param a Asset to write to.  `a' must not be deleted while
  *  this writer class still exists, or bad things will happen.
  */
-MonoPictureMXFWriter::MonoPictureMXFWriter (PictureMXF* asset, boost::filesystem::path file, bool overwrite)
-       : PictureMXFWriter (asset, file, overwrite)
+MonoPictureMXFWriter::MonoPictureMXFWriter (PictureMXF* asset, boost::filesystem::path file, Standard standard, bool overwrite)
+       : PictureMXFWriter (asset, file, standard, overwrite)
        , _state (new MonoPictureMXFWriter::ASDCPState)
 {
        _state->encryption_context = asset->encryption_context ();
@@ -50,7 +50,7 @@ MonoPictureMXFWriter::MonoPictureMXFWriter (PictureMXF* asset, boost::filesystem
 void
 MonoPictureMXFWriter::start (uint8_t* data, int size)
 {
-       dcp::start (this, _state, _mxf, data, size);
+       dcp::start (this, _state, _standard, _picture_mxf, data, size);
 }
 
 FrameInfo
@@ -95,15 +95,11 @@ MonoPictureMXFWriter::fake_write (int size)
 void
 MonoPictureMXFWriter::finalize ()
 {
-       assert (!_finalized);
-       
        Kumu::Result_t r = _state->mxf_writer.Finalize();
        if (ASDCP_FAILURE (r)) {
                boost::throw_exception (MXFFileError ("error in finalizing video MXF", _mxf->file().string(), r));
        }
 
-       _finalized = true;
-       _mxf->set_intrinsic_duration (_frames_written);
-       _mxf->set_duration (_frames_written);
+       PictureMXFWriter::finalize ();
 }
 
index c4d9b6ed672c374dbcca6ee0e7f25c59f1248cd2..7ff87a5ddb169c383092e0b0795f6b694292bd45 100644 (file)
@@ -45,7 +45,7 @@ public:
 private:
        friend class MonoPictureMXF;
 
-       MonoPictureMXFWriter (PictureMXF *, boost::filesystem::path file, bool);
+       MonoPictureMXFWriter (PictureMXF *, boost::filesystem::path file, Standard standard, bool);
        void start (uint8_t *, int);
 
        /* do this with an opaque pointer so we don't have to include
index fa3aed8b8bf55a414a1e1b106c5ef385503843c3..42d925368a35f633c9a2617fa8728a36e4c6437e 100644 (file)
  *  @brief Parent class for assets of DCPs made up of MXF files.
  */
 
-#include <iostream>
-#include <boost/filesystem.hpp>
-#include <boost/lexical_cast.hpp>
-#include <libxml++/nodes/element.h>
 #include "AS_DCP.h"
 #include "KM_prng.h"
 #include "KM_util.h"
 #include "metadata.h"
 #include "exceptions.h"
 #include "kdm.h"
+#include <libxml++/nodes/element.h>
+#include <boost/filesystem.hpp>
+#include <boost/lexical_cast.hpp>
+#include <iostream>
 
 using std::string;
 using std::list;
@@ -42,12 +42,20 @@ using boost::lexical_cast;
 using boost::dynamic_pointer_cast;
 using namespace dcp;
 
+MXF::MXF (Fraction edit_rate)
+       : Content (edit_rate)
+       , _progress (0)
+       , _encryption_context (0)
+       , _decryption_context (0)
+{
+
+}
+
 MXF::MXF (boost::filesystem::path file)
        : Content (file)
        , _progress (0)
        , _encryption_context (0)
        , _decryption_context (0)
-       , _interop (false)
 {
 
 }
@@ -59,13 +67,13 @@ MXF::~MXF ()
 }
 
 void
-MXF::fill_writer_info (ASDCP::WriterInfo* writer_info)
+MXF::fill_writer_info (ASDCP::WriterInfo* writer_info, Standard standard)
 {
        writer_info->ProductVersion = _metadata.product_version;
        writer_info->CompanyName = _metadata.company_name;
        writer_info->ProductName = _metadata.product_name.c_str();
 
-       if (_interop) {
+       if (standard == INTEROP) {
                writer_info->LabelSetType = ASDCP::LS_MXF_INTEROP;
        } else {
                writer_info->LabelSetType = ASDCP::LS_MXF_SMPTE;
@@ -107,25 +115,6 @@ MXF::equals (shared_ptr<const Content> other, EqualityOptions opt, boost::functi
        return true;
 }
 
-void
-MXF::write_to_cpl (xmlpp::Element* node) const
-{
-       pair<string, string> const attr = cpl_node_attribute ();
-       xmlpp::Element* a = node->add_child (cpl_node_name ());
-       if (!attr.first.empty ()) {
-               a->set_attribute (attr.first, attr.second);
-       }
-       a->add_child ("Id")->add_child_text ("urn:uuid:" + _id);
-       a->add_child ("AnnotationText")->add_child_text (_file.string ());
-       a->add_child ("EditRate")->add_child_text (lexical_cast<string> (_edit_rate) + " 1");
-       a->add_child ("IntrinsicDuration")->add_child_text (lexical_cast<string> (_intrinsic_duration));
-       a->add_child ("EntryPoint")->add_child_text (lexical_cast<string> (_entry_point));
-       a->add_child ("Duration")->add_child_text (lexical_cast<string> (_duration));
-       if (!_key_id.empty ()) {
-               a->add_child("KeyId")->add_child_text ("urn:uuid:" + _key_id);
-       }
-}
-
 void
 MXF::set_key (Key key)
 {
index a83d9fff72f6beebcd1a4ee1db32e36c5a37796c..3aaadfd78d0d09091969f92f28204b3532b226e3 100644 (file)
--- a/src/mxf.h
+++ b/src/mxf.h
 #ifndef LIBDCP_MXF_ASSET_H
 #define LIBDCP_MXF_ASSET_H
 
-#include <boost/signals2.hpp>
 #include "content.h"
 #include "key.h"
 #include "metadata.h"
+#include <boost/signals2.hpp>
 
 namespace ASDCP {
        class AESEncContext;
@@ -41,19 +41,23 @@ class MXFMetadata;
 class MXF : public Content
 {
 public:
+       MXF (Fraction edit_rate);
        MXF (boost::filesystem::path file);
-       MXF (int edit_rate);
        
        ~MXF ();
 
        virtual bool equals (boost::shared_ptr<const Content> other, EqualityOptions opt, boost::function<void (NoteType, std::string)> note) const;
-       virtual void write_to_cpl (xmlpp::Element *) const;
        virtual std::string key_type () const = 0;
+
+       std::string pkl_type () const {
+               return "application/x-smpte-mxf";
+       }
        
        /** Fill in a ADSCP::WriteInfo struct.
         *  @param w struct to fill in.
+        *  @param standard INTEROP or SMPTE.
         */
-       void fill_writer_info (ASDCP::WriterInfo* w);
+       void fill_writer_info (ASDCP::WriterInfo* w, Standard standard);
 
        void set_progress (boost::signals2::signal<void (float)>* progress) {
                _progress = progress;
@@ -89,23 +93,7 @@ public:
                return _metadata;
        }
 
-       /** Set whether or not the asset should be written in Interop mode.
-        *  @param i true to use interop.
-        */
-       void set_interop (bool i) {
-               _interop = i;
-       }
-
-       bool interop () const {
-               return _interop;
-       }
-
 protected:
-       virtual std::string cpl_node_name () const = 0;
-       virtual std::pair<std::string, std::string> cpl_node_attribute () const {
-               return std::make_pair ("", "");
-       }
-       
        /** Signal to emit to report progress, or 0 */
        boost::signals2::signal<void (float)>* _progress;
        ASDCP::AESEncContext* _encryption_context;
@@ -113,7 +101,6 @@ protected:
        std::string _key_id;
        boost::optional<Key> _key;
        MXFMetadata _metadata;
-       bool _interop;
 };
 
 }
diff --git a/src/mxf_writer.cc b/src/mxf_writer.cc
new file mode 100644 (file)
index 0000000..c5fca15
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+    Copyright (C) 2012-2014 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 "mxf_writer.h"
+#include "mxf.h"
+
+using namespace dcp;
+
+MXFWriter::MXFWriter (MXF* mxf, boost::filesystem::path file)
+       : _mxf (mxf)
+       , _file (file)
+       , _frames_written (0)
+       , _finalized (false)
+{
+       mxf->_file = file;
+       mxf->_hash.clear ();
+}
+
+MXFWriter::~MXFWriter ()
+{
+       assert (_finalized);
+}
+
+void
+MXFWriter::finalize ()
+{
+       assert (!_finalized);
+       _finalized = true;
+       _mxf->_intrinsic_duration = _frames_written;
+}
diff --git a/src/mxf_writer.h b/src/mxf_writer.h
new file mode 100644 (file)
index 0000000..1963213
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+    Copyright (C) 2012-2014 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.
+
+*/
+
+#ifndef LIBDCP_MXF_WRITER_H
+#define LIBDCP_MXF_WRITER_H
+
+#include <boost/filesystem.hpp>
+
+namespace dcp {
+
+class MXF;
+
+class MXFWriter : public boost::noncopyable
+{
+public:
+       virtual ~MXFWriter ();
+       virtual void finalize ();
+
+protected:
+       MXFWriter (MXF* mxf, boost::filesystem::path file);
+
+       MXF* _mxf;
+       boost::filesystem::path _file;
+       int64_t _frames_written;
+       bool _finalized;
+};
+
+}
+
+#endif
index e9a4f62b9a40e7c2c2f0c0d27a475bac9872e92b..e3849d792f6c114c39e6a12bc1f02259936ce354 100644 (file)
 using std::string;
 using namespace dcp;
 
+/** Create an Object with a random ID. */
 Object::Object ()
        : _id (make_uuid ())
 {
 
 }
 
+/** Create an Object with a given ID.
+ *  @param ID to use.
+ */
 Object::Object (string id)
        : _id (id)
 {
index 636c76a04ed3b233d3a253718ca870459716ca4b..e12888e8b337016a8b3def3febfa9a95896279d7 100644 (file)
@@ -24,7 +24,9 @@
 
 namespace dcp {
 
-/** Some part of a DCP that has a UUID */
+/** @class Object
+ *  @brief Some part of a DCP that has a UUID.
+ */
 class Object
 {
 public:
@@ -32,11 +34,13 @@ public:
        Object (std::string id);
        virtual ~Object () {}
 
+       /** @return ID */
        std::string id () const {
                return _id;
        }
 
 protected:
+       /** ID */
        std::string _id;
 };
        
diff --git a/src/parse/asset_map.cc b/src/parse/asset_map.cc
deleted file mode 100644 (file)
index 0b323fb..0000000
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
-    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/asset_map.cc
- *  @brief Classes used to parse a AssetMap.
- */
-
-#include <boost/algorithm/string.hpp>
-#include "asset_map.h"
-#include "../util.h"
-#include "../xml.h"
-
-using std::string;
-using std::list;
-using boost::shared_ptr;
-using namespace dcp::parse;
-
-AssetMap::AssetMap (string file)
-{
-       cxml::Document f ("AssetMap");
-       f.read_file (file);
-
-       id = f.string_child ("Id");
-       creator = f.string_child ("Creator");
-       volume_count = f.number_child<int64_t> ("VolumeCount");
-       issue_date = f.string_child ("IssueDate");
-       issuer = f.string_child ("Issuer");
-       assets = type_grand_children<AssetMapAsset> (f, "AssetList", "Asset");
-}
-
-AssetMapAsset::AssetMapAsset (shared_ptr<const cxml::Node> node)
-{
-       id = node->string_child ("Id");
-       packing_list = node->optional_string_child ("PackingList").get_value_or ("");
-       chunks = type_grand_children<Chunk> (node, "ChunkList", "Chunk");
-}
-
-Chunk::Chunk (shared_ptr<const cxml::Node> node)
-{
-       path = node->string_child ("Path");
-
-       string const prefix = "file://";
-
-       if (boost::algorithm::starts_with (path, prefix)) {
-               path = path.substr (prefix.length());
-       }
-       
-       volume_index = node->optional_number_child<int64_t> ("VolumeIndex").get_value_or (0);
-       offset = node->optional_number_child<int64_t> ("Offset").get_value_or (0);
-       length = node->optional_number_child<int64_t> ("Length").get_value_or (0);
-}
-
-shared_ptr<AssetMapAsset>
-AssetMap::asset_from_id (string id) const
-{
-       for (list<shared_ptr<AssetMapAsset> >::const_iterator i = assets.begin (); i != assets.end(); ++i) {
-               if ((*i)->id == id) {
-                       return *i;
-               }
-       }
-
-       return shared_ptr<AssetMapAsset> ();
-}
diff --git a/src/parse/asset_map.h b/src/parse/asset_map.h
deleted file mode 100644 (file)
index e303559..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
-    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/asset_map.h
- *  @brief Classes used to parse a AssetMap.
- */
-
-#include <stdint.h>
-#include <boost/shared_ptr.hpp>
-#include <libcxml/cxml.h>
-
-namespace dcp {
-
-namespace parse {
-
-/** @class Chunk
- *  @brief A simple parser for and representation of a \<Chunk\> node within an asset map.
- */
-class Chunk
-{
-public:
-       Chunk ();
-       Chunk (boost::shared_ptr<const cxml::Node> node);
-
-       std::string path;
-       int64_t volume_index;
-       int64_t offset;
-       int64_t length;
-};
-
-/** @class AssetMapAsset
- *  @brief A simple parser for and representation of an \<AssetMap\> node within an asset map.
- */
-class AssetMapAsset
-{
-public:
-       AssetMapAsset ();
-       AssetMapAsset (boost::shared_ptr<const cxml::Node> node);
-
-       std::string id;
-       std::string packing_list;
-       std::list<boost::shared_ptr<Chunk> > chunks;
-};
-
-/** @class AssetMap
- *  @brief A simple parser for and representation of an asset map file.
- */
-class AssetMap
-{
-public:
-       AssetMap (std::string file);
-
-       boost::shared_ptr<AssetMapAsset> asset_from_id (std::string id) const;
-       
-       std::string id;
-       std::string creator;
-       int64_t volume_count;
-       std::string issue_date;
-       std::string issuer;
-       std::list<boost::shared_ptr<AssetMapAsset> > assets;
-};
-
-}
-
-}
diff --git a/src/parse/cpl.cc b/src/parse/cpl.cc
deleted file mode 100644 (file)
index d94fb68..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
-    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/cpl_file.cc
- *  @brief Classes used to parse a CPL.
- */
-
-#include <iostream>
-#include "cpl.h"
-#include "../xml.h"
-#include "../util.h"
-
-using std::string;
-using std::bad_cast;
-using boost::shared_ptr;
-using namespace dcp::parse;
-
-CPL::CPL (string file)
-{
-       cxml::Document f ("CompositionPlaylist");
-       f.read_file (file);
-       
-       id = f.string_child ("Id");
-       annotation_text = f.optional_string_child ("AnnotationText").get_value_or ("");
-       issue_date = f.string_child ("IssueDate");
-       creator = f.optional_string_child ("Creator").get_value_or ("");
-       content_title_text = f.string_child ("ContentTitleText");
-       content_kind = content_kind_from_string (f.string_child ("ContentKind"));
-       content_version = optional_type_child<ContentVersion> (f, "ContentVersion");
-       f.ignore_child ("RatingList");
-       reels = type_grand_children<Reel> (f, "ReelList", "Reel");
-
-       f.ignore_child ("Issuer");
-       f.ignore_child ("Signer");
-       f.ignore_child ("Signature");
-
-       f.done ();
-}
-
-ContentVersion::ContentVersion (shared_ptr<const cxml::Node> node)
-{
-       id = node->optional_string_child ("Id").get_value_or ("");
-       label_text = node->string_child ("LabelText");
-       node->done ();
-}
-
-Reel::Reel (shared_ptr<const cxml::Node> node)
-{
-       id = node->string_child ("Id");
-       asset_list = type_child<CPLAssetList> (node, "AssetList");
-
-       node->ignore_child ("AnnotationText");
-       node->done ();
-}
-
-CPLAssetList::CPLAssetList (shared_ptr<const cxml::Node> node)
-{
-       main_picture = optional_type_child<MainPicture> (node, "MainPicture");
-       main_stereoscopic_picture = optional_type_child<MainStereoscopicPicture> (node, "MainStereoscopicPicture");
-       main_sound = optional_type_child<MainSound> (node, "MainSound");
-       main_subtitle = optional_type_child<MainSubtitle> (node, "MainSubtitle");
-
-       node->done ();
-}
-
-MainPicture::MainPicture (shared_ptr<const cxml::Node> node)
-       : Picture (node)
-{
-
-}
-
-MainStereoscopicPicture::MainStereoscopicPicture (shared_ptr<const cxml::Node> node)
-       : Picture (node)
-{
-
-}
-
-Picture::Picture (shared_ptr<const cxml::Node> node)
-{
-       id = node->string_child ("Id");
-       annotation_text = node->optional_string_child ("AnnotationText").get_value_or ("");
-       edit_rate = Fraction (node->string_child ("EditRate"));
-       intrinsic_duration = node->number_child<int64_t> ("IntrinsicDuration");
-       entry_point = node->number_child<int64_t> ("EntryPoint");
-       duration = node->number_child<int64_t> ("Duration");
-       frame_rate = Fraction (node->string_child ("FrameRate"));
-       try {
-               screen_aspect_ratio = Fraction (node->string_child ("ScreenAspectRatio"));
-       } catch (XMLError& e) {
-               /* Maybe it's not a fraction */
-       }
-       try {
-               float f = node->number_child<float> ("ScreenAspectRatio");
-               screen_aspect_ratio = Fraction (f * 1000, 1000);
-       } catch (bad_cast& e) {
-
-       }
-
-       key_id = node->optional_string_child ("KeyId").get_value_or ("");
-
-       node->ignore_child ("Hash");
-
-       node->done ();
-}
-
-MainSound::MainSound (shared_ptr<const cxml::Node> node)
-{
-       id = node->string_child ("Id");
-       annotation_text = node->optional_string_child ("AnnotationText").get_value_or ("");
-       edit_rate = Fraction (node->string_child ("EditRate"));
-       intrinsic_duration = node->number_child<int64_t> ("IntrinsicDuration");
-       entry_point = node->number_child<int64_t> ("EntryPoint");
-       duration = node->number_child<int64_t> ("Duration");
-       key_id = node->optional_string_child ("KeyId").get_value_or ("");
-       
-       node->ignore_child ("Hash");
-       node->ignore_child ("Language");
-       
-       node->done ();
-}
-
-MainSubtitle::MainSubtitle (shared_ptr<const cxml::Node> node)
-{
-       id = node->string_child ("Id");
-       annotation_text = node->optional_string_child ("AnnotationText").get_value_or ("");
-       edit_rate = Fraction (node->string_child ("EditRate"));
-       intrinsic_duration = node->number_child<int64_t> ("IntrinsicDuration");
-       entry_point = node->number_child<int64_t> ("EntryPoint");
-       duration = node->number_child<int64_t> ("Duration");
-
-       node->ignore_child ("Hash");
-       node->ignore_child ("Language");
-       
-       node->done ();
-}
diff --git a/src/parse/cpl.h b/src/parse/cpl.h
deleted file mode 100644 (file)
index 4889a1c..0000000
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
-    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/parse/cpl.h
- *  @brief Classes used to parse a CPL.
- */
-
-#include <stdint.h>
-#include <boost/shared_ptr.hpp>
-#include <libcxml/cxml.h>
-#include "../types.h"
-
-namespace dcp {
-
-namespace parse        {
-
-/** @brief A simple representation of a CPL \<Picture\> node */
-class Picture
-{
-public:
-       Picture () {}
-       Picture (boost::shared_ptr<const cxml::Node> node);
-
-       std::string id;
-       std::string annotation_text;
-       Fraction edit_rate;
-       /** Duration of the whole thing */
-       int64_t intrinsic_duration;
-       /** Start point in frames */
-       int64_t entry_point;
-       /** Duration that will actually play */
-       int64_t duration;
-       Fraction frame_rate;
-       Fraction screen_aspect_ratio;
-       std::string key_id;
-};
-
-
-/** @brief A simple parser for and representation of a CPL \<MainPicture\> node */
-class MainPicture : public Picture
-{
-public:
-       MainPicture () {}
-       MainPicture (boost::shared_ptr<const cxml::Node> node);
-};
-
-/** @brief A simple parser for and representation of a CPL \<MainStereoscopicPicture\> node */
-class MainStereoscopicPicture : public Picture
-{
-public:
-       MainStereoscopicPicture () {}
-       MainStereoscopicPicture (boost::shared_ptr<const cxml::Node> node);
-};
-
-/** @brief A simple parser for and representation of a CPL \<MainSound\> node */
-class MainSound
-{
-public:
-       MainSound () {}
-       MainSound (boost::shared_ptr<const cxml::Node> node);
-
-       std::string id;
-       std::string annotation_text;
-       Fraction edit_rate;
-       int64_t intrinsic_duration;
-       int64_t entry_point;
-       int64_t duration;
-       std::string key_id;
-};
-
-/** @brief A simple parser for and representation of a CPL \<MainSubtitle\> node */
-class MainSubtitle
-{
-public:
-       MainSubtitle () {}
-       MainSubtitle (boost::shared_ptr<const cxml::Node> node);
-
-       std::string id;
-       std::string annotation_text;
-       Fraction edit_rate;
-       int64_t intrinsic_duration;
-       int64_t entry_point;
-       int64_t duration;
-};
-
-/** @brief A simple parser for and representation of a CPL \<AssetList\> node */
-class CPLAssetList
-{
-public:
-       CPLAssetList () {}
-       CPLAssetList (boost::shared_ptr<const cxml::Node> node);
-
-       boost::shared_ptr<MainPicture> main_picture;
-       boost::shared_ptr<MainStereoscopicPicture> main_stereoscopic_picture;
-       boost::shared_ptr<MainSound> main_sound;
-       boost::shared_ptr<MainSubtitle> main_subtitle;
-};
-
-/** @brief A simple parser for and representation of a CPL \<Reel\> node */
-class Reel
-{
-public:
-       Reel () {}
-       Reel (boost::shared_ptr<const cxml::Node> node);
-
-       std::string id;
-       boost::shared_ptr<CPLAssetList> asset_list;
-};
-
-
-/** @brief A simple parser for and representation of a CPL \<ContentVersion\> node */
-class ContentVersion
-{
-public:
-       ContentVersion () {}
-       ContentVersion (boost::shared_ptr<const cxml::Node> node);
-
-       std::string id;
-       std::string label_text;
-};
-
-/** @class CPL
- *  @brief Class to parse a CPL
- *
- *  This class is used to parse XML CPL files.  It is rarely necessary
- *  for the caller to use it outside libdcp.
- */
-class CPL
-{
-public:
-       /** Parse a CPL XML file into our member variables */
-       CPL (std::string file);
-
-       std::string id;
-       std::string annotation_text;
-       std::string issue_date;
-       std::string creator;
-       std::string content_title_text;
-       ContentKind content_kind;
-       boost::shared_ptr<ContentVersion> content_version;
-       std::list<boost::shared_ptr<Reel> > reels;
-};
-
-}
-
-}
-
diff --git a/src/parse/pkl.cc b/src/parse/pkl.cc
deleted file mode 100644 (file)
index d0fa155..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
-    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/pkl_file.cc
- *  @brief Classes used to parse a PKL.
- */
-
-#include <iostream>
-#include "pkl.h"
-
-using namespace std;
-using namespace boost;
-using namespace dcp::parse;
-
-PKL::PKL (string file)
-{
-       cxml::Document f ("PackingList");
-       f.read_file (file);
-       
-       id = f.string_child ("Id");
-       annotation_text = f.optional_string_child ("AnnotationText").get_value_or ("");
-       issue_date = f.string_child ("IssueDate");
-       issuer = f.string_child ("Issuer");
-       creator = f.string_child ("Creator");
-       assets = type_grand_children<PKLAsset> (f, "AssetList", "Asset");
-}
-
-PKLAsset::PKLAsset (boost::shared_ptr<const cxml::Node> node)
-{
-       id = node->string_child ("Id");
-       annotation_text = node->optional_string_child ("AnnotationText").get_value_or ("");
-       hash = node->string_child ("Hash");
-       size = node->number_child<int64_t> ("Size");
-       type = node->string_child ("Type");
-       original_file_name = node->optional_string_child ("OriginalFileName").get_value_or ("");
-}
diff --git a/src/parse/pkl.h b/src/parse/pkl.h
deleted file mode 100644 (file)
index f31eef7..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
-    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/parse/pkl.h
- *  @brief Classes used to parse a PKL
- */
-
-#include <boost/shared_ptr.hpp>
-#include "../xml.h"
-
-namespace dcp {
-
-namespace parse {
-
-class PKLAsset
-{
-public:
-       PKLAsset () {}
-       PKLAsset (boost::shared_ptr<const cxml::Node>);
-
-       std::string id;
-       std::string annotation_text;
-       std::string hash;
-       int64_t size;
-       std::string type;
-       std::string original_file_name;
-};
-
-class PKL
-{
-public:
-       PKL (std::string file);
-
-       std::string id;
-       std::string annotation_text;
-       std::string issue_date;
-       std::string issuer;
-       std::string creator;
-       std::list<boost::shared_ptr<PKLAsset> > assets;
-};
-       
-}
-
-}
diff --git a/src/parse/subtitle.cc b/src/parse/subtitle.cc
deleted file mode 100644 (file)
index 3f9869b..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
-    Copyright (C) 2012-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/shared_ptr.hpp>
-#include <boost/optional.hpp>
-#include "subtitle.h"
-#include "../types.h"
-
-using std::string;
-using std::list;
-using boost::shared_ptr;
-using boost::optional;
-using boost::lexical_cast;
-using namespace dcp;
-using namespace dcp::parse;
-
-Font::Font (shared_ptr<const cxml::Node> node)
-{
-       text = node->content ();
-       
-       id = node->optional_string_attribute ("Id").get_value_or ("");
-       size = node->optional_number_attribute<int64_t> ("Size").get_value_or (0);
-       italic = node->optional_bool_attribute ("Italic");
-       optional<string> c = node->optional_string_attribute ("Color");
-       if (c) {
-               color = Color (c.get ());
-       }
-       optional<string> const e = node->optional_string_attribute ("Effect");
-       if (e) {
-               effect = string_to_effect (e.get ());
-       }
-       c = node->optional_string_attribute ( "EffectColor");
-       if (c) {
-               effect_color = Color (c.get ());
-       }
-       subtitle_nodes = type_children<Subtitle> (node, "Subtitle");
-       font_nodes = type_children<Font> (node, "Font");
-       text_nodes = type_children<Text> (node, "Text");
-}
-
-Font::Font (list<shared_ptr<Font> > const & font_nodes)
-       : size (0)
-       , italic (false)
-       , color ("FFFFFFFF")
-       , effect_color ("FFFFFFFF")
-{
-       for (list<shared_ptr<Font> >::const_iterator i = font_nodes.begin(); i != font_nodes.end(); ++i) {
-               if (!(*i)->id.empty ()) {
-                       id = (*i)->id;
-               }
-               if ((*i)->size != 0) {
-                       size = (*i)->size;
-               }
-               if ((*i)->italic) {
-                       italic = (*i)->italic.get ();
-               }
-               if ((*i)->color) {
-                       color = (*i)->color.get ();
-               }
-               if ((*i)->effect) {
-                       effect = (*i)->effect.get ();
-               }
-               if ((*i)->effect_color) {
-                       effect_color = (*i)->effect_color.get ();
-               }
-       }
-}
-
-LoadFont::LoadFont (shared_ptr<const cxml::Node> node)
-{
-       id = node->string_attribute ("Id");
-       uri = node->string_attribute ("URI");
-}
-       
-
-Subtitle::Subtitle (shared_ptr<const cxml::Node> node)
-{
-       in = Time (node->string_attribute ("TimeIn"));
-       out = Time (node->string_attribute ("TimeOut"));
-       font_nodes = type_children<Font> (node, "Font");
-       text_nodes = type_children<Text> (node, "Text");
-       fade_up_time = fade_time (node, "FadeUpTime");
-       fade_down_time = fade_time (node, "FadeDownTime");
-}
-
-Time
-Subtitle::fade_time (shared_ptr<const cxml::Node> node, string name)
-{
-       string const u = node->optional_string_attribute (name).get_value_or ("");
-       Time t;
-       
-       if (u.empty ()) {
-               t = Time (0, 0, 0, 20);
-       } else if (u.find (":") != string::npos) {
-               t = Time (u);
-       } else {
-               t = Time (0, 0, 0, lexical_cast<int> (u));
-       }
-
-       if (t > Time (0, 0, 8, 0)) {
-               t = Time (0, 0, 8, 0);
-       }
-
-       return t;
-}
-
-Text::Text (shared_ptr<const cxml::Node> node)
-       : v_align (CENTER)
-{
-       text = node->content ();
-       v_position = node->number_attribute<float> ("VPosition");
-       optional<string> v = node->optional_string_attribute ("VAlign");
-       if (v) {
-               v_align = string_to_valign (v.get ());
-       }
-
-       font_nodes = type_children<Font> (node, "Font");
-}
-
diff --git a/src/parse/subtitle.h b/src/parse/subtitle.h
deleted file mode 100644 (file)
index 50c2ebc..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
-    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 "../xml.h"
-#include "../dcp_time.h"
-#include "../types.h"
-
-namespace dcp
-{
-
-namespace parse
-{
-
-class Font;
-
-class Text
-{
-public:
-       Text ()
-               : v_position (0)
-               , v_align (TOP)
-       {}
-       
-       Text (boost::shared_ptr<const cxml::Node> node);
-
-       float v_position;
-       VAlign v_align;
-       std::string text;
-       std::list<boost::shared_ptr<Font> > font_nodes;
-};
-
-class Subtitle 
-{
-public:
-       Subtitle () {}
-       Subtitle (boost::shared_ptr<const cxml::Node> node);
-
-       Time in;
-       Time out;
-       Time fade_up_time;
-       Time fade_down_time;
-       std::list<boost::shared_ptr<Font> > font_nodes;
-       std::list<boost::shared_ptr<Text> > text_nodes;
-
-private:
-       Time fade_time (boost::shared_ptr<const cxml::Node>, std::string name);
-};
-
-class Font 
-{
-public:
-       Font ()
-               : size (0)
-       {}
-       
-       Font (boost::shared_ptr<const cxml::Node> node);
-       Font (std::list<boost::shared_ptr<Font> > const & font_nodes);
-
-       std::string text;
-       std::string id;
-       int size;
-       boost::optional<bool> italic;
-       boost::optional<Color> color;
-       boost::optional<Effect> effect;
-       boost::optional<Color> effect_color;
-       
-       std::list<boost::shared_ptr<Subtitle> > subtitle_nodes;
-       std::list<boost::shared_ptr<Font> > font_nodes;
-       std::list<boost::shared_ptr<Text> > text_nodes;
-};
-
-class LoadFont 
-{
-public:
-       LoadFont () {}
-       LoadFont (boost::shared_ptr<const cxml::Node> node);
-
-       std::string id;
-       std::string uri;
-};
-
-}
-
-}
index 8f0f85b9555007bcadb3f9a83cfcaf415dfee7b0..7634493d95f1414b718ab3d992263620d1e527dc 100644 (file)
 
 */
 
-/** @file  src/picture_asset.cc
- *  @brief An asset made up of JPEG2000 files
- */
-
 #include <list>
 #include <stdexcept>
 #include <iostream>
@@ -58,33 +54,21 @@ PictureMXF::PictureMXF (boost::filesystem::path file)
 
 }
 
-PictureMXF::PictureMXF (int edit_rate)
+PictureMXF::PictureMXF (Fraction edit_rate)
        : MXF (edit_rate)
 {
 
 }
 
 void
-PictureMXF::write_to_cpl (xmlpp::Element* node) const
+PictureMXF::read_picture_descriptor (ASDCP::JP2K::PictureDescriptor const & desc)
 {
-       MXF::write_to_cpl (node);
-       
-       xmlpp::Node::NodeList c = node->get_children ();
-       xmlpp::Node::NodeList::iterator i = c.begin();
-       while (i != c.end() && (*i)->get_name() != cpl_node_name ()) {
-               ++i;
-       }
-
-       assert (i != c.end ());
-
-       (*i)->add_child ("FrameRate")->add_child_text (lexical_cast<string> (_edit_rate * edit_rate_factor ()) + " 1");
-       if (_interop) {
-               stringstream s;
-               s << std::fixed << std::setprecision (2) << (float (_size.width) / _size.height);
-               (*i)->add_child ("ScreenAspectRatio")->add_child_text (s.str ());
-       } else {
-               (*i)->add_child ("ScreenAspectRatio")->add_child_text (lexical_cast<string> (_size.width) + " " + lexical_cast<string> (_size.height));
-       }
+       _size.width = desc.StoredWidth;
+       _size.height = desc.StoredHeight;
+       _edit_rate = Fraction (desc.EditRate.Numerator, desc.EditRate.Denominator);
+       _intrinsic_duration = desc.ContainerDuration;
+       _frame_rate = Fraction (desc.SampleRate.Numerator, desc.SampleRate.Denominator);
+       _screen_aspect_ratio = Fraction (desc.AspectRatio.Numerator, desc.AspectRatio.Denominator);
 }
 
 bool
@@ -212,6 +196,3 @@ PictureMXF::key_type () const
 {
        return "MDIK";
 }
-
-
-
index 3a587280b0e4a0c105f8b2e969c7811649dd9ff8..df75625cee9167b9186786f683c444c5ebecfc27 100644 (file)
@@ -47,19 +47,27 @@ class PictureMXF : public MXF
 {
 public:
        PictureMXF (boost::filesystem::path file);
-       PictureMXF (int edit_rate);
+       PictureMXF (Fraction edit_rate);
 
-       virtual boost::shared_ptr<PictureMXFWriter> start_write (boost::filesystem::path file, bool overwrite) = 0;
+       virtual boost::shared_ptr<PictureMXFWriter> start_write (boost::filesystem::path file, Standard standard, bool overwrite) = 0;
+
+       void write_to_pkl (xmlpp::Node* node) const;
 
        Size size () const {
                return _size;
        }
 
-       void set_size (Size s) {
-               _size = s;
+       Fraction frame_rate () const {
+               return _frame_rate;
        }
 
-       void write_to_cpl (xmlpp::Element *) const;
+       Fraction screen_aspect_ratio () const {
+               return _screen_aspect_ratio;
+       }
+
+       Fraction edit_rate () const {
+               return _edit_rate;
+       }
 
 protected:     
 
@@ -72,8 +80,12 @@ protected:
                ASDCP::JP2K::PictureDescriptor const & a, ASDCP::JP2K::PictureDescriptor const & b, boost::function<void (NoteType, std::string)>
                ) const;
 
+       void read_picture_descriptor (ASDCP::JP2K::PictureDescriptor const &);
+
        /** picture size in pixels */
        Size _size;
+       Fraction _frame_rate;
+       Fraction _screen_aspect_ratio;
 
 private:
        std::string key_type () const;
index 1a128b33acc50a08aaae0df5e5ef3ef3f2c01088..46426401b456761c085ce32e219cdfaf54a17ffa 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2014 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
 
 */
 
-#include <inttypes.h>
-#include <stdint.h>
-#include "AS_DCP.h"
 #include "KM_fileio.h"
 #include "picture_mxf_writer.h"
 #include "exceptions.h"
 #include "picture_mxf.h"
+#include "AS_DCP.h"
+#include <inttypes.h>
+#include <stdint.h>
 
 using std::istream;
 using std::ostream;
@@ -82,14 +82,12 @@ FrameInfo::write (FILE* f) const
 #endif 
 }
 
-
-PictureMXFWriter::PictureMXFWriter (PictureMXF* mxf, boost::filesystem::path file, bool overwrite)
-       : _mxf (mxf)
-       , _file (file)
-       , _frames_written (0)
+PictureMXFWriter::PictureMXFWriter (PictureMXF* mxf, boost::filesystem::path file, Standard standard, bool overwrite)
+       : MXFWriter (mxf, file)
+       , _picture_mxf (mxf)
        , _started (false)
-       , _finalized (false)
+       , _standard (standard)
        , _overwrite (overwrite)
 {
-
+       
 }
index bcd8873d660a31d6dbec203f13989063f987208b..f8c67ba9b33918f88d85105aab3b39d5116263f2 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2014 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
 
 */
 
+#include "metadata.h"
+#include "types.h"
+#include "mxf_writer.h"
+#include <boost/shared_ptr.hpp>
+#include <boost/utility.hpp>
 #include <stdint.h>
 #include <string>
 #include <fstream>
-#include <boost/shared_ptr.hpp>
-#include <boost/utility.hpp>
-#include "metadata.h"
-#include "types.h"
 
 namespace dcp {
 
@@ -49,31 +50,21 @@ struct FrameInfo
        std::string hash;
 };
 
-class PictureMXFWriter : public boost::noncopyable
+class PictureMXFWriter : public MXFWriter
 {
 public:
-       virtual ~PictureMXFWriter () {}
        virtual FrameInfo write (uint8_t *, int) = 0;
-       virtual void finalize () = 0;
        virtual void fake_write (int) = 0;
 
 protected:
        template <class P, class Q>
-       friend void start (PictureMXFWriter *, boost::shared_ptr<P>, Q *, uint8_t *, int);
-
-       PictureMXFWriter (PictureMXF *, boost::filesystem::path, bool);
+       friend void start (PictureMXFWriter *, boost::shared_ptr<P>, Standard, Q *, uint8_t *, int);
 
-       PictureMXF* _mxf;
+       PictureMXFWriter (PictureMXF *, boost::filesystem::path, Standard standard, bool);
 
-       boost::filesystem::path _file;
-       /** Number of picture frames written to the asset so far.  For stereo assets
-        *  this will be incremented for each eye (i.e. there will be twice the number
-        *  of frames as in a mono asset).
-        */
-       int _frames_written;
+       PictureMXF* _picture_mxf;
        bool _started;
-       /** true if finalize() has been called */
-       bool _finalized;
+       Standard _standard;
        bool _overwrite;
 };
 
index 6ac8ae35022ed8c93762a1aef5c93f5c27b887a5..9836f03e9116935df523018b1d4be7eb9b2d800f 100644 (file)
@@ -33,7 +33,7 @@ struct ASDCPStateBase
 };
 
 template <class P, class Q>
-void dcp::start (PictureMXFWriter* writer, shared_ptr<P> state, Q* mxf, uint8_t* data, int size)
+void dcp::start (PictureMXFWriter* writer, shared_ptr<P> state, Standard standard, Q* mxf, uint8_t* data, int size)
 {
        mxf->set_file (writer->_file);
        
@@ -42,9 +42,9 @@ void dcp::start (PictureMXFWriter* writer, shared_ptr<P> state, Q* mxf, uint8_t*
        }
 
        state->j2k_parser.FillPictureDescriptor (state->picture_descriptor);
-       state->picture_descriptor.EditRate = ASDCP::Rational (mxf->edit_rate(), 1);
+       state->picture_descriptor.EditRate = ASDCP::Rational (mxf->edit_rate().numerator, mxf->edit_rate().denominator);
        
-       mxf->fill_writer_info (&state->writer_info);
+       mxf->fill_writer_info (&state->writer_info, standard);
        
        Kumu::Result_t r = state->mxf_writer.OpenWrite (
                mxf->file().string().c_str(),
index 9f514d8888a4a9aa80dccdae01e3f9a7a9926064..27fc0329ab9601721d05bd96ce56738d32782244 100644 (file)
 
 */
 
-#include <libxml++/nodes/element.h>
 #include "reel.h"
 #include "util.h"
 #include "picture_mxf.h"
 #include "mono_picture_mxf.h"
 #include "stereo_picture_mxf.h"
 #include "sound_mxf.h"
-#include "subtitle_asset.h"
+#include "subtitle_content.h"
+#include "reel_mono_picture_asset.h"
+#include "reel_stereo_picture_asset.h"
+#include "reel_sound_asset.h"
+#include "reel_subtitle_asset.h"
 #include "kdm.h"
+#include <libxml++/nodes/element.h>
 
 using std::string;
 using std::list;
@@ -34,8 +38,37 @@ using boost::shared_ptr;
 using boost::dynamic_pointer_cast;
 using namespace dcp;
 
+Reel::Reel (shared_ptr<const cxml::Node> node)
+       : Object (node->string_child ("Id"))
+{
+       shared_ptr<cxml::Node> asset_list = node->node_child ("AssetList");
+
+       shared_ptr<cxml::Node> main_picture = asset_list->optional_node_child ("MainPicture");
+       if (main_picture) {
+               _main_picture.reset (new ReelMonoPictureAsset (main_picture));
+       }
+       
+       shared_ptr<cxml::Node> main_stereoscopic_picture = asset_list->optional_node_child ("MainStereoscopicPicture");
+       if (main_stereoscopic_picture) {
+               _main_picture.reset (new ReelStereoPictureAsset (main_stereoscopic_picture));
+       }
+       
+       shared_ptr<cxml::Node> main_sound = asset_list->optional_node_child ("MainSound");
+       if (main_sound) {
+               _main_sound.reset (new ReelSoundAsset (main_sound));
+       }
+       
+       shared_ptr<cxml::Node> main_subtitle = asset_list->optional_node_child ("MainSubtitle");
+       if (main_subtitle) {
+               _main_subtitle.reset (new ReelSubtitleAsset (main_subtitle));
+       }
+
+       node->ignore_child ("AnnotationText");
+       node->done ();
+}
+
 void
-Reel::write_to_cpl (xmlpp::Element* node) const
+Reel::write_to_cpl (xmlpp::Element* node, Standard standard) const
 {
        xmlpp::Element* reel = node->add_child ("Reel");
        reel->add_child("Id")->add_child_text ("urn:uuid:" + make_uuid());
@@ -43,20 +76,20 @@ Reel::write_to_cpl (xmlpp::Element* node) const
        
        if (_main_picture && dynamic_pointer_cast<MonoPictureMXF> (_main_picture)) {
                /* Mono pictures come before other stuff... */
-               _main_picture->write_to_cpl (asset_list);
+               _main_picture->write_to_cpl (asset_list, standard);
        }
 
        if (_main_sound) {
-               _main_sound->write_to_cpl (asset_list);
+               _main_sound->write_to_cpl (asset_list, standard);
        }
 
        if (_main_subtitle) {
-               _main_subtitle->write_to_cpl (asset_list);
+               _main_subtitle->write_to_cpl (asset_list, standard);
        }
 
        if (_main_picture && dynamic_pointer_cast<StereoPictureMXF> (_main_picture)) {
                /* ... but stereo pictures must come after */
-               _main_picture->write_to_cpl (asset_list);
+               _main_picture->write_to_cpl (asset_list, standard);
        }
 }
        
@@ -106,10 +139,10 @@ Reel::add_kdm (KDM const & kdm)
        
        for (list<KDMKey>::iterator i = keys.begin(); i != keys.end(); ++i) {
                if (i->key_id() == _main_picture->key_id()) {
-                       _main_picture->set_key (i->key ());
+                       _main_picture->mxf()->set_key (i->key ());
                }
                if (i->key_id() == _main_sound->key_id()) {
-                       _main_sound->set_key (i->key ());
+                       _main_sound->mxf()->set_key (i->key ());
                }
        }
 }
@@ -117,10 +150,25 @@ Reel::add_kdm (KDM const & kdm)
 void
 Reel::set_mxf_keys (Key key)
 {
-       _main_picture->set_key (key);
+       _main_picture->mxf()->set_key (key);
        if (_main_sound) {
-               _main_sound->set_key (key);
+               _main_sound->mxf()->set_key (key);
        }
 
        /* XXX: subtitle asset? */
 }
+
+void
+Reel::add (shared_ptr<ReelAsset> asset)
+{
+       shared_ptr<ReelPictureAsset> p = dynamic_pointer_cast<ReelPictureAsset> (asset);
+       shared_ptr<ReelSoundAsset> so = dynamic_pointer_cast<ReelSoundAsset> (asset);
+       shared_ptr<ReelSubtitleAsset> su = dynamic_pointer_cast<ReelSubtitleAsset> (asset);
+       if (p) {
+               _main_picture = p;
+       } else if (so) {
+               _main_sound = so;
+       } else if (su) {
+               _main_subtitle = su;
+       }
+}
index 41e811e44966d7b31500bce6a0bbeeaf9a924f94..8aaebf5135d42616f28546ebf30f93a7f89ae48c 100644 (file)
 #ifndef LIBDCP_REEL_H
 #define LIBDCP_REEL_H
 
-#include <list>
-#include <boost/shared_ptr.hpp>
-#include <boost/function.hpp>
-#include <libxml++/libxml++.h>
 #include "key.h"
 #include "types.h"
+#include "ref.h"
+#include <libxml++/libxml++.h>
+#include <boost/shared_ptr.hpp>
+#include <boost/function.hpp>
+#include <list>
 
-namespace xmlpp {
+namespace cxml {
        class Node;
 }
 
 namespace dcp {
 
-class PictureMXF;
-class SoundMXF;
-class SubtitleAsset;
-class KDM;     
+class KDM;
+class ReelAsset;
+class ReelPictureAsset;
+class ReelSoundAsset;
+class ReelSubtitleAsset;
 
 /** @brief A reel within a DCP; the part which actually contains picture, sound and subtitle data */   
-class Reel
+class Reel : public Object
 {
 public:
+       Reel () {}
+       
        Reel (
-               boost::shared_ptr<PictureMXF> picture,
-               boost::shared_ptr<SoundMXF> sound,
-               boost::shared_ptr<SubtitleAsset> subtitle
+               boost::shared_ptr<ReelPictureAsset> picture,
+               boost::shared_ptr<ReelSoundAsset> sound,
+               boost::shared_ptr<ReelSubtitleAsset> subtitle
                )
                : _main_picture (picture)
                , _main_sound (sound)
                , _main_subtitle (subtitle)
        {}
+
+       Reel (boost::shared_ptr<const cxml::Node>);
        
-       boost::shared_ptr<const PictureMXF> main_picture () const {
+       boost::shared_ptr<ReelPictureAsset> main_picture () const {
                return _main_picture;
        }
 
-       boost::shared_ptr<const SoundMXF> main_sound () const {
+       boost::shared_ptr<ReelSoundAsset> main_sound () const {
                return _main_sound;
        }
        
-       boost::shared_ptr<const SubtitleAsset> main_subtitle () const {
+       boost::shared_ptr<ReelSubtitleAsset> main_subtitle () const {
                return _main_subtitle;
        }
 
-       void write_to_cpl (xmlpp::Element *) const;
+       void add (boost::shared_ptr<ReelAsset> asset);
+
+       void write_to_cpl (xmlpp::Element* node, Standard standard) const;
 
        bool encrypted () const;
 
@@ -75,9 +83,9 @@ public:
        void add_kdm (KDM const &);
 
 private:
-       boost::shared_ptr<PictureMXF> _main_picture;
-       boost::shared_ptr<SoundMXF> _main_sound;
-       boost::shared_ptr<SubtitleAsset> _main_subtitle;
+       boost::shared_ptr<ReelPictureAsset> _main_picture;
+       boost::shared_ptr<ReelSoundAsset> _main_sound;
+       boost::shared_ptr<ReelSubtitleAsset> _main_subtitle;
 };
 
 }
diff --git a/src/reel_asset.cc b/src/reel_asset.cc
new file mode 100644 (file)
index 0000000..8e03b5c
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+    Copyright (C) 2014 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 "reel_asset.h"
+#include "content.h"
+#include "compose.hpp"
+#include <libcxml/cxml.h>
+
+using std::pair;
+using std::string;
+using std::make_pair;
+using boost::shared_ptr;
+using boost::lexical_cast;
+using namespace dcp;
+
+ReelAsset::ReelAsset ()
+       : Object (make_uuid ())
+       , _content (_id)
+       , _edit_rate (Fraction (24, 1))
+       , _intrinsic_duration (0)
+       , _entry_point (0)
+       , _duration (0)
+{
+
+}
+
+ReelAsset::ReelAsset (shared_ptr<Content> content, int64_t entry_point)
+       : Object (content->id ())
+       , _content (content)
+       , _edit_rate (content->edit_rate ())
+       , _intrinsic_duration (content->intrinsic_duration ())
+       , _entry_point (entry_point)
+       , _duration (_intrinsic_duration - _entry_point)
+       , _hash (make_digest (content->file (), 0))
+{
+
+}
+
+ReelAsset::ReelAsset (shared_ptr<const cxml::Node> node)
+       : Object (node->string_child ("Id"))
+       , _content (_id)
+       , _annotation_text (node->optional_string_child ("AnnotationText").get_value_or (""))
+       , _edit_rate (Fraction (node->string_child ("EditRate")))
+       , _intrinsic_duration (node->number_child<int64_t> ("IntrinsicDuration"))
+       , _entry_point (node->number_child<int64_t> ("EntryPoint"))
+       , _duration (node->number_child<int64_t> ("Duration"))
+       , _hash (node->string_child ("Hash"))
+       , _key_id (node->optional_string_child ("KeyId").get_value_or (""))
+{
+       if (_id.length() > 9) {
+               _id = _id.substr (9);
+               _content.set_id (_id);
+       }
+       
+       if (_key_id.length() > 9) {
+               _key_id = _key_id.substr (9);
+       }
+       
+       node->done ();
+}
+
+void
+ReelAsset::write_to_cpl (xmlpp::Node* node, Standard) const
+{
+        pair<string, string> const attr = cpl_node_attribute ();
+        xmlpp::Element* a = node->add_child (cpl_node_name ());
+        if (!attr.first.empty ()) {
+                a->set_attribute (attr.first, attr.second);
+        }
+        a->add_child("Id")->add_child_text ("urn:uuid:" + _id);
+        a->add_child("AnnotationText")->add_child_text (_annotation_text);
+        a->add_child("EditRate")->add_child_text (String::compose ("%1 %2", _edit_rate.numerator, _edit_rate.denominator));
+        a->add_child("IntrinsicDuration")->add_child_text (lexical_cast<string> (_intrinsic_duration));
+        a->add_child("EntryPoint")->add_child_text (lexical_cast<string> (_entry_point));
+        a->add_child("Duration")->add_child_text (lexical_cast<string> (_duration));
+        if (!_key_id.empty ()) {
+                a->add_child("KeyId")->add_child_text ("urn:uuid:" + _key_id);
+        }
+}
+
+pair<string, string>
+ReelAsset::cpl_node_attribute () const
+{
+       return make_pair ("", "");
+}
diff --git a/src/reel_asset.h b/src/reel_asset.h
new file mode 100644 (file)
index 0000000..5207166
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+    Copyright (C) 2014 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.
+
+*/
+
+#ifndef LIBDCP_REEL_ASSET_H
+#define LIBDCP_REEL_ASSET_H
+
+#include "object.h"
+#include "util.h"
+#include "ref.h"
+#include <boost/shared_ptr.hpp>
+
+namespace cxml {
+       class Node;
+}
+
+namespace xmlpp {
+       class Node;
+}
+
+namespace dcp {
+
+class Content;
+
+class ReelAsset : public Object
+{
+public:
+       ReelAsset ();
+       ReelAsset (boost::shared_ptr<Content> content, int64_t entry_point);
+       ReelAsset (boost::shared_ptr<const cxml::Node>);
+
+       Ref<Content> content () const {
+               return _content;
+       }
+
+       bool encrypted () const {
+               return !_key_id.empty ();
+       }
+
+       std::string key_id () const {
+               return _key_id;
+       }
+
+       virtual void write_to_cpl (xmlpp::Node* node, Standard standard) const;
+       virtual bool equals (boost::shared_ptr<const ReelAsset>, EqualityOptions, boost::function<void (NoteType, std::string)>) const {
+               return false;
+       }
+
+protected:
+       virtual std::string cpl_node_name () const = 0;
+       virtual std::pair<std::string, std::string> cpl_node_attribute () const;
+
+       Ref<Content> _content;
+
+private:
+       std::string _annotation_text;
+       Fraction _edit_rate;
+       int64_t _intrinsic_duration;
+       int64_t _entry_point;
+       int64_t _duration;
+       std::string _hash;
+       std::string _key_id;
+};
+
+}
+
+#endif
diff --git a/src/reel_mono_picture_asset.cc b/src/reel_mono_picture_asset.cc
new file mode 100644 (file)
index 0000000..892c9f4
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+    Copyright (C) 2014 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 "reel_mono_picture_asset.h"
+#include "mono_picture_mxf.h"
+
+using std::string;
+using boost::shared_ptr;
+using namespace dcp;
+
+ReelMonoPictureAsset::ReelMonoPictureAsset ()
+{
+
+}
+
+ReelMonoPictureAsset::ReelMonoPictureAsset (shared_ptr<MonoPictureMXF> mxf, int64_t entry_point)
+       : ReelPictureAsset (mxf, entry_point)
+{
+
+}
+
+ReelMonoPictureAsset::ReelMonoPictureAsset (shared_ptr<const cxml::Node> node)
+       : ReelPictureAsset (node)
+{
+
+}
+
+string
+ReelMonoPictureAsset::cpl_node_name () const
+{
+       return "MainPicture";
+}
+
diff --git a/src/reel_mono_picture_asset.h b/src/reel_mono_picture_asset.h
new file mode 100644 (file)
index 0000000..881bbec
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+    Copyright (C) 2014 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 "reel_picture_asset.h"
+
+namespace dcp {
+
+class MonoPictureMXF;  
+
+class ReelMonoPictureAsset : public ReelPictureAsset
+{
+public:
+       ReelMonoPictureAsset ();
+       ReelMonoPictureAsset (boost::shared_ptr<MonoPictureMXF> content, int64_t entry_point);
+       ReelMonoPictureAsset (boost::shared_ptr<const cxml::Node>);
+
+private:
+       std::string cpl_node_name () const;
+};
+
+}
+
+       
+               
diff --git a/src/reel_picture_asset.cc b/src/reel_picture_asset.cc
new file mode 100644 (file)
index 0000000..9fdc3b9
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+    Copyright (C) 2014 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 "content.h"
+#include "reel_picture_asset.h"
+#include "picture_mxf.h"
+#include "compose.hpp"
+#include <libcxml/cxml.h>
+
+using std::bad_cast;
+using std::string;
+using std::stringstream;
+using boost::shared_ptr;
+using boost::lexical_cast;
+using namespace dcp;
+
+ReelPictureAsset::ReelPictureAsset ()
+       : _frame_rate (Fraction (24, 1))
+       , _screen_aspect_ratio (Fraction (1998, 1080))
+{
+
+}
+
+ReelPictureAsset::ReelPictureAsset (shared_ptr<PictureMXF> content, int64_t entry_point)
+       : ReelAsset (content, entry_point)
+       , _frame_rate (content->frame_rate ())
+       , _screen_aspect_ratio (content->screen_aspect_ratio ())
+{
+       
+}
+
+ReelPictureAsset::ReelPictureAsset (shared_ptr<const cxml::Node> node)
+       : ReelAsset (node)
+{
+       _frame_rate = Fraction (node->string_child ("FrameRate"));
+       try {
+               _screen_aspect_ratio = Fraction (node->string_child ("ScreenAspectRatio"));
+       } catch (XMLError& e) {
+               /* Maybe it's not a fraction */
+       }
+       try {
+               float f = node->number_child<float> ("ScreenAspectRatio");
+               _screen_aspect_ratio = Fraction (f * 1000, 1000);
+       } catch (bad_cast& e) {
+
+       }
+}
+
+void
+ReelPictureAsset::write_to_cpl (xmlpp::Node* node, Standard standard) const
+{
+       ReelAsset::write_to_cpl (node, standard);
+
+       xmlpp::Node::NodeList c = node->get_children ();
+       xmlpp::Node::NodeList::iterator i = c.begin();
+       while (i != c.end() && (*i)->get_name() != cpl_node_name ()) {
+               ++i;
+       }
+
+       assert (i != c.end ());
+       
+       (*i)->add_child ("FrameRate")->add_child_text (String::compose ("%1 %2", _frame_rate.numerator, _frame_rate.denominator));
+       if (standard == INTEROP) {
+               stringstream s;
+               s << std::fixed << std::setprecision (2) << (float (_screen_aspect_ratio.numerator) / _screen_aspect_ratio.denominator);
+               (*i)->add_child ("ScreenAspectRatio")->add_child_text (s.str ());
+       } else {
+               (*i)->add_child ("ScreenAspectRatio")->add_child_text (
+                       String::compose ("%1 %2", _screen_aspect_ratio.numerator, _screen_aspect_ratio.denominator)
+                       );
+       }
+}
diff --git a/src/reel_picture_asset.h b/src/reel_picture_asset.h
new file mode 100644 (file)
index 0000000..c6eb2c7
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+    Copyright (C) 2014 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.
+
+*/
+
+#ifndef LIBDCP_REEL_PICTURE_ASSET_H
+#define LIBDCP_REEL_PICTURE_ASSET_H
+
+#include "reel_asset.h"
+#include "picture_mxf.h"
+
+namespace dcp {
+
+class ReelPictureAsset : public ReelAsset
+{
+public:
+       ReelPictureAsset ();
+       ReelPictureAsset (boost::shared_ptr<PictureMXF> content, int64_t entry_point);
+       ReelPictureAsset (boost::shared_ptr<const cxml::Node>);
+
+       boost::shared_ptr<PictureMXF> mxf () {
+               return boost::dynamic_pointer_cast<PictureMXF> (_content.object ());
+       }
+
+       void set_screen_aspect_ratio (Fraction a) {
+               _screen_aspect_ratio = a;
+       }
+
+       virtual void write_to_cpl (xmlpp::Node* node, Standard standard) const;
+
+private:
+       Fraction _frame_rate;
+       Fraction _screen_aspect_ratio;
+};
+
+}
+
+#endif
diff --git a/src/reel_sound_asset.cc b/src/reel_sound_asset.cc
new file mode 100644 (file)
index 0000000..6ef473f
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+    Copyright (C) 2014 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 "reel_sound_asset.h"
+#include <libcxml/cxml.h>
+
+using std::string;
+using boost::shared_ptr;
+using namespace dcp;
+
+ReelSoundAsset::ReelSoundAsset (shared_ptr<Content> content, int64_t entry_point)
+       : ReelAsset (content, entry_point)
+{
+
+}
+
+ReelSoundAsset::ReelSoundAsset (shared_ptr<const cxml::Node> node)
+       : ReelAsset (node)
+{
+       node->ignore_child ("Language");
+       node->done ();
+}
+
+string
+ReelSoundAsset::cpl_node_name () const
+{
+       return "MainSound";
+}
diff --git a/src/reel_sound_asset.h b/src/reel_sound_asset.h
new file mode 100644 (file)
index 0000000..27d2499
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+    Copyright (C) 2014 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 "reel_asset.h"
+#include "sound_mxf.h"
+#include <boost/shared_ptr.hpp>
+#include <string>
+
+namespace dcp {
+
+class ReelSoundAsset : public ReelAsset
+{
+public:
+       ReelSoundAsset (boost::shared_ptr<Content> content, int64_t entry_point);
+       ReelSoundAsset (boost::shared_ptr<const cxml::Node>);
+
+       boost::shared_ptr<SoundMXF> mxf () {
+               return boost::dynamic_pointer_cast<SoundMXF> (_content.object ());
+       }
+       
+private:
+       std::string cpl_node_name () const;
+};
+
+}
+
diff --git a/src/reel_stereo_picture_asset.cc b/src/reel_stereo_picture_asset.cc
new file mode 100644 (file)
index 0000000..2715eb3
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+    Copyright (C) 2014 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 "reel_stereo_picture_asset.h"
+
+using std::string;
+using std::pair;
+using std::make_pair;
+using boost::shared_ptr;
+using namespace dcp;
+
+ReelStereoPictureAsset::ReelStereoPictureAsset (shared_ptr<const cxml::Node> node)
+       : ReelPictureAsset (node)
+{
+
+}
+
+string
+ReelStereoPictureAsset::cpl_node_name () const
+{
+       return "msp-cpl:MainStereoscopicPicture";
+}
+
+pair<string, string>
+ReelStereoPictureAsset::cpl_node_attribute (Standard standard) const
+{
+       if (standard == INTEROP) {
+               return make_pair ("xmlns:msp-cpl", "http://www.digicine.com/schemas/437-Y/2007/Main-Stereo-Picture-CPL");
+       } else {
+               return make_pair ("xmlns:msp-cpl", "http://www.smpte-ra.org/schemas/429-10/2008/Main-Stereo-Picture-CPL");
+       }
+
+       return make_pair ("", "");
+}
diff --git a/src/reel_stereo_picture_asset.h b/src/reel_stereo_picture_asset.h
new file mode 100644 (file)
index 0000000..6ae6721
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+    Copyright (C) 2014 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 "reel_picture_asset.h"
+
+namespace dcp {
+
+class ReelStereoPictureAsset : public ReelPictureAsset
+{
+public:
+       ReelStereoPictureAsset (boost::shared_ptr<const cxml::Node>);
+
+private:
+       std::string cpl_node_name () const;
+       std::pair<std::string, std::string> cpl_node_attribute (Standard standard) const;
+};
+
+}
+
+       
+               
diff --git a/src/reel_subtitle_asset.cc b/src/reel_subtitle_asset.cc
new file mode 100644 (file)
index 0000000..326e343
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+    Copyright (C) 2012-2014 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 "subtitle_content.h"
+#include "reel_subtitle_asset.h"
+
+using std::string;
+using boost::shared_ptr;
+using namespace dcp;
+
+ReelSubtitleAsset::ReelSubtitleAsset (shared_ptr<SubtitleContent> content, int64_t entry_point)
+       : ReelAsset (content, entry_point)
+{
+
+}
+
+ReelSubtitleAsset::ReelSubtitleAsset (shared_ptr<const cxml::Node> node)
+       : ReelAsset (node)
+{
+       node->ignore_child ("Language");
+       node->done ();
+}
+
+string
+ReelSubtitleAsset::cpl_node_name () const
+{
+       return "MainSubtitle";
+}
diff --git a/src/reel_subtitle_asset.h b/src/reel_subtitle_asset.h
new file mode 100644 (file)
index 0000000..7b17b8a
--- /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 "reel_asset.h"
+
+namespace dcp {
+
+class SubtitleContent;
+
+class ReelSubtitleAsset : public ReelAsset
+{
+public:
+       ReelSubtitleAsset (boost::shared_ptr<SubtitleContent> content, int64_t entry_point);
+       ReelSubtitleAsset (boost::shared_ptr<const cxml::Node>);
+
+       boost::shared_ptr<SubtitleContent> subtitle_content () const {
+               return boost::dynamic_pointer_cast<SubtitleContent> (_content.object ());
+       }
+
+private:       
+       std::string cpl_node_name () const;
+};
+
+}
diff --git a/src/ref.h b/src/ref.h
new file mode 100644 (file)
index 0000000..db39bfb
--- /dev/null
+++ b/src/ref.h
@@ -0,0 +1,91 @@
+/*
+    Copyright (C) 2014 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.
+
+*/
+
+#ifndef LIBDCP_REF_H
+#define LIBDCP_REF_H
+
+#include "exceptions.h"
+#include "object.h"
+#include <boost/shared_ptr.hpp>
+#include <string>
+
+namespace dcp {
+
+template<class T>
+class Ref
+{
+public:
+       Ref (std::string id)
+               : _id (id)
+       {}
+
+       Ref (boost::shared_ptr<T> object)
+               : _id (object->id ())
+               , _object (object)
+       {}
+
+       void set_id (std::string id)
+       {
+               _id = id;
+       }
+
+       void resolve (std::list<boost::shared_ptr<Object> > objects)
+       {
+               typename std::list<boost::shared_ptr<Object> >::iterator i = objects.begin();
+               while (i != objects.end() && (*i)->id() != _id) {
+                       ++i;
+               }
+
+               if (i != objects.end ()) {
+                       _object = boost::dynamic_pointer_cast<T> (*i);
+               }
+       }
+
+       std::string id () const {
+               return _id;
+       }
+
+       boost::shared_ptr<T> object () const {
+               if (!_object) {
+                       throw UnresolvedRefError (_id);
+               }
+
+               return _object;
+       }
+
+       T * operator->() const {
+               if (!_object) {
+                       throw UnresolvedRefError (_id);
+               }
+
+               return _object.get ();
+       }
+
+       bool resolved () const {
+               return _object;
+       }
+
+private:
+       std::string _id;
+       boost::shared_ptr<T> _object;
+};
+
+}
+
+#endif
index ea13563f8719c154a568e184acc0b8351e0628f4..4c5d199a25514e4cc05df90dfaa03fd154d06f87 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2013-2014 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
 
 */
 
+/** @file  src/signer.cc
+ *  @brief Signer class.
+ */
+
+#include "signer.h"
+#include "exceptions.h"
+#include <libcxml/cxml.h>
 #include <libxml++/libxml++.h>
 #include <xmlsec/xmldsig.h>
 #include <xmlsec/dl.h>
 #include <xmlsec/app.h>
 #include <xmlsec/crypto.h>
-#include <libcxml/cxml.h>
-#include "signer.h"
-#include "exceptions.h"
 
 using std::string;
 using std::list;
@@ -32,18 +36,30 @@ using std::cout;
 using boost::shared_ptr;
 using namespace dcp;
 
-/** @param signer_key Filename of private key to sign with */
+/** Add a &lt;Signer&gt; and &lt;ds:Signature&gt; nodes to an XML node.
+ *  @param parent XML node to add to.
+ *  @param interop true to use Interop standards, false for SMPTE.
+ */
 void
-Signer::sign (xmlpp::Element* parent, bool interop) const
+Signer::sign (xmlpp::Element* parent, Standard standard) const
 {
-       add_signer (parent, "dsig");
+       /* <Signer> */
+       
+       xmlpp::Element* signer = parent->add_child("Signer");
+       xmlpp::Element* data = signer->add_child("X509Data", "dsig");
+       xmlpp::Element* serial_element = data->add_child("X509IssuerSerial", "dsig");
+       serial_element->add_child("X509IssuerName", "dsig")->add_child_text (_certificates.leaf()->issuer());
+       serial_element->add_child("X509SerialNumber", "dsig")->add_child_text (_certificates.leaf()->serial());
+       data->add_child("X509SubjectName", "dsig")->add_child_text (_certificates.leaf()->subject());
 
+       /* <Signature> */
+       
        xmlpp::Element* signature = parent->add_child("Signature", "dsig");
        
        xmlpp::Element* signed_info = signature->add_child ("SignedInfo", "dsig");
        signed_info->add_child("CanonicalizationMethod", "dsig")->set_attribute ("Algorithm", "http://www.w3.org/TR/2001/REC-xml-c14n-20010315");
        
-       if (interop) {
+       if (standard == INTEROP) {
                signed_info->add_child("SignatureMethod", "dsig")->set_attribute("Algorithm", "http://www.w3.org/2000/09/xmldsig#rsa-sha1");
        } else {
                signed_info->add_child("SignatureMethod", "dsig")->set_attribute("Algorithm", "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
@@ -113,21 +129,3 @@ Signer::add_signature_value (xmlpp::Node* parent, string ns) const
 
        xmlSecDSigCtxDestroy (signature_context);
 }
-
-void
-Signer::add_signer (xmlpp::Element* parent, string ns) const
-{
-       xmlpp::Element* signer = parent->add_child("Signer");
-
-       {
-               xmlpp::Element* data = signer->add_child("X509Data", ns);
-               
-               {
-                       xmlpp::Element* serial_element = data->add_child("X509IssuerSerial", ns);
-                       serial_element->add_child("X509IssuerName", ns)->add_child_text (_certificates.leaf()->issuer());
-                       serial_element->add_child("X509SerialNumber", ns)->add_child_text (_certificates.leaf()->serial());
-               }
-               
-               data->add_child("X509SubjectName", ns)->add_child_text (_certificates.leaf()->subject());
-       }
-}
index 7c2864fdada9886dbac2ff50eedff2ee53a772b7..c57c73cf64ef48f16c7f5c744e9b71d36351ceb1 100644 (file)
 
 */
 
-#include <boost/filesystem.hpp>
+/** @file  src/signer.h
+ *  @brief Signer class.
+ */
+
 #include "certificates.h"
+#include "types.h"
+#include <boost/filesystem.hpp>
 
 namespace xmlpp {
        class Element;
@@ -27,15 +32,21 @@ namespace xmlpp {
 
 namespace dcp {
 
+/** @class Signer
+ *  @brief A class which can sign XML files.
+ */
 class Signer
 {
 public:
+       /** @param c Certificate chain to sign with.
+        *  @param k Key to sign with.
+        */
        Signer (CertificateChain c, boost::filesystem::path k)
                : _certificates (c)
                , _key (k)
        {}
 
-       void sign (xmlpp::Element* parent, bool interop) const;
+       void sign (xmlpp::Element* parent, Standard standard) const;
        void add_signature_value (xmlpp::Node* parent, std::string ns) const;
 
        CertificateChain const & certificates () const {
@@ -44,8 +55,7 @@ public:
        
 private:       
 
-       void add_signer (xmlpp::Element* parent, std::string ns) const;
-       
+       /** Certificate chain to sign with */
        CertificateChain _certificates;
        /** Filename of signer key */
        boost::filesystem::path _key;
index 63f9ba051fce5aa01102b00b7ee8c9574098003c..82ab08234898a4c164dc7826f0c7857c0d39b572 100644 (file)
@@ -32,6 +32,7 @@
 #include "util.h"
 #include "exceptions.h"
 #include "sound_frame.h"
+#include "sound_mxf_writer.h"
 
 using std::string;
 using std::stringstream;
@@ -60,15 +61,17 @@ SoundMXF::SoundMXF (boost::filesystem::path file)
 
        _sampling_rate = desc.AudioSamplingRate.Numerator / desc.AudioSamplingRate.Denominator;
        _channels = desc.ChannelCount;
-       _edit_rate = desc.EditRate.Numerator;
-       assert (desc.EditRate.Denominator == 1);
+       _edit_rate = Fraction (desc.EditRate.Numerator, desc.EditRate.Denominator);
+
        _intrinsic_duration = desc.ContainerDuration;
 }
 
-string
-SoundMXF::cpl_node_name () const
+SoundMXF::SoundMXF (Fraction edit_rate, int sampling_rate, int channels)
+       : MXF (edit_rate)
+       , _channels (channels)
+       , _sampling_rate (sampling_rate)
 {
-       return "MainSound";
+
 }
 
 bool
@@ -155,105 +158,10 @@ SoundMXF::get_frame (int n) const
 }
 
 shared_ptr<SoundMXFWriter>
-SoundMXF::start_write ()
+SoundMXF::start_write (boost::filesystem::path file, Standard standard)
 {
        /* XXX: can't we use a shared_ptr here? */
-       return shared_ptr<SoundMXFWriter> (new SoundMXFWriter (this));
-}
-
-struct SoundMXFWriter::ASDCPState
-{
-       ASDCP::PCM::MXFWriter mxf_writer;
-       ASDCP::PCM::FrameBuffer frame_buffer;
-       ASDCP::WriterInfo writer_info;
-       ASDCP::PCM::AudioDescriptor audio_desc;
-       ASDCP::AESEncContext* encryption_context;
-};
-
-SoundMXFWriter::SoundMXFWriter (SoundMXF* a)
-       : _state (new SoundMXFWriter::ASDCPState)
-       , _asset (a)
-       , _finalized (false)
-       , _frames_written (0)
-       , _frame_buffer_offset (0)
-{
-       _state->encryption_context = a->encryption_context ();
-       
-       /* Derived from ASDCP::Wav::SimpleWaveHeader::FillADesc */
-       _state->audio_desc.EditRate = ASDCP::Rational (_asset->edit_rate(), 1);
-       _state->audio_desc.AudioSamplingRate = ASDCP::Rational (_asset->sampling_rate(), 1);
-       _state->audio_desc.Locked = 0;
-       _state->audio_desc.ChannelCount = _asset->channels ();
-       _state->audio_desc.QuantizationBits = 24;
-       _state->audio_desc.BlockAlign = 3 * _asset->channels();
-       _state->audio_desc.AvgBps = _asset->sampling_rate() * _state->audio_desc.BlockAlign;
-       _state->audio_desc.LinkedTrackID = 0;
-       _state->audio_desc.ChannelFormat = ASDCP::PCM::CF_NONE;
-       
-       _state->frame_buffer.Capacity (ASDCP::PCM::CalcFrameBufferSize (_state->audio_desc));
-       _state->frame_buffer.Size (ASDCP::PCM::CalcFrameBufferSize (_state->audio_desc));
-       memset (_state->frame_buffer.Data(), 0, _state->frame_buffer.Capacity());
-       
-       _asset->fill_writer_info (&_state->writer_info);
-       
-       Kumu::Result_t r = _state->mxf_writer.OpenWrite (_asset->file().string().c_str(), _state->writer_info, _state->audio_desc);
-       if (ASDCP_FAILURE (r)) {
-               boost::throw_exception (FileError ("could not open audio MXF for writing", _asset->file().string(), r));
-       }
-}
-
-void
-SoundMXFWriter::write (float const * const * data, int frames)
-{
-       for (int i = 0; i < frames; ++i) {
-
-               byte_t* out = _state->frame_buffer.Data() + _frame_buffer_offset;
-
-               /* Write one sample per channel */
-               for (int j = 0; j < _asset->channels(); ++j) {
-                       int32_t const s = data[j][i] * (1 << 23);
-                       *out++ = (s & 0xff);
-                       *out++ = (s & 0xff00) >> 8;
-                       *out++ = (s & 0xff0000) >> 16;
-               }
-               _frame_buffer_offset += 3 * _asset->channels();
-
-               assert (_frame_buffer_offset <= int (_state->frame_buffer.Capacity()));
-
-               /* Finish the MXF frame if required */
-               if (_frame_buffer_offset == int (_state->frame_buffer.Capacity())) {
-                       write_current_frame ();
-                       _frame_buffer_offset = 0;
-                       memset (_state->frame_buffer.Data(), 0, _state->frame_buffer.Capacity());
-               }
-       }
-}
-
-void
-SoundMXFWriter::write_current_frame ()
-{
-       ASDCP::Result_t const r = _state->mxf_writer.WriteFrame (_state->frame_buffer, _state->encryption_context, 0);
-       if (ASDCP_FAILURE (r)) {
-               boost::throw_exception (MiscError ("could not write audio MXF frame (" + lexical_cast<string> (int (r)) + ")"));
-       }
-
-       ++_frames_written;
-}
-
-void
-SoundMXFWriter::finalize ()
-{
-       if (_frame_buffer_offset > 0) {
-               write_current_frame ();
-       }
-       
-       if (ASDCP_FAILURE (_state->mxf_writer.Finalize())) {
-               boost::throw_exception (MiscError ("could not finalise audio MXF"));
-       }
-
-       _finalized = true;
-       _asset->set_intrinsic_duration (_frames_written);
-       _asset->set_duration (_frames_written);
+       return shared_ptr<SoundMXFWriter> (new SoundMXFWriter (this, file, standard));
 }
 
 string
index 4216accb5dc4063dfca03dd6f77b2168a453577f..098680acf9724cbea881368cf1f09f884a0bf651 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2014 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
 
 */
 
-#ifndef LIBDCP_SOUND_ASSET_H
-#define LIBDCP_SOUND_ASSET_H
-
-/** @file  src/sound_asset.h
- *  @brief An asset made up of PCM audio data files
- */
+#ifndef LIBDCP_SOUND_MXF_H
+#define LIBDCP_SOUND_MXF_H
 
 #include "mxf.h"
 #include "types.h"
@@ -32,45 +28,15 @@ namespace dcp
 {
 
 class SoundFrame;
-class SoundMXF;
-
-class SoundMXFWriter
-{
-public:
-       void write (float const * const *, int);
-       void finalize ();
-
-private:
-       friend class SoundMXF;
-
-       SoundMXFWriter (SoundMXF *);
-
-       /* no copy construction */
-       SoundMXFWriter (SoundMXFWriter const &);
-       SoundMXFWriter& operator= (SoundMXFWriter const &);
-       
-       void write_current_frame ();
-
-       /* do this with an opaque pointer so we don't have to include
-          ASDCP headers
-       */
-          
-       struct ASDCPState;
-       boost::shared_ptr<ASDCPState> _state;
-
-       SoundMXF* _asset;
-       bool _finalized;
-       int _frames_written;
-       int _frame_buffer_offset;
-};
+class SoundMXFWriter;
 
-/** @brief An asset made up of WAV files */
 class SoundMXF : public MXF
 {
 public:
        SoundMXF (boost::filesystem::path file);
+       SoundMXF (Fraction edit_rate, int sampling_rate, int channels);
 
-       boost::shared_ptr<SoundMXFWriter> start_write ();
+       boost::shared_ptr<SoundMXFWriter> start_write (boost::filesystem::path file, Standard standard);
        
        bool equals (boost::shared_ptr<const Content> other, EqualityOptions opt, boost::function<void (NoteType, std::string)> note) const;
 
@@ -94,7 +60,6 @@ public:
 
 private:
        std::string key_type () const;
-       std::string cpl_node_name () const;
 
        /** Number of channels in the asset */
        int _channels;
diff --git a/src/sound_mxf_writer.cc b/src/sound_mxf_writer.cc
new file mode 100644 (file)
index 0000000..5dcd679
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+    Copyright (C) 2012-2014 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 "sound_mxf_writer.h"
+#include "sound_mxf.h"
+#include "exceptions.h"
+#include "compose.hpp"
+#include "AS_DCP.h"
+#include <boost/lexical_cast.hpp>
+
+using boost::lexical_cast;
+using namespace dcp;
+
+struct SoundMXFWriter::ASDCPState
+{
+       ASDCP::PCM::MXFWriter mxf_writer;
+       ASDCP::PCM::FrameBuffer frame_buffer;
+       ASDCP::WriterInfo writer_info;
+       ASDCP::PCM::AudioDescriptor audio_desc;
+       ASDCP::AESEncContext* encryption_context;
+};
+
+SoundMXFWriter::SoundMXFWriter (SoundMXF* m, boost::filesystem::path file, Standard standard)
+       : MXFWriter (m, file)
+       , _state (new SoundMXFWriter::ASDCPState)
+       , _sound_mxf (m)
+       , _frame_buffer_offset (0)
+{
+       _state->encryption_context = m->encryption_context ();
+       
+       /* Derived from ASDCP::Wav::SimpleWaveHeader::FillADesc */
+       _state->audio_desc.EditRate = ASDCP::Rational (_sound_mxf->edit_rate().numerator, _sound_mxf->edit_rate().denominator);
+       _state->audio_desc.AudioSamplingRate = ASDCP::Rational (_sound_mxf->sampling_rate(), 1);
+       _state->audio_desc.Locked = 0;
+       _state->audio_desc.ChannelCount = _sound_mxf->channels ();
+       _state->audio_desc.QuantizationBits = 24;
+       _state->audio_desc.BlockAlign = 3 * _sound_mxf->channels();
+       _state->audio_desc.AvgBps = _sound_mxf->sampling_rate() * _state->audio_desc.BlockAlign;
+       _state->audio_desc.LinkedTrackID = 0;
+       _state->audio_desc.ChannelFormat = ASDCP::PCM::CF_NONE;
+       
+       _state->frame_buffer.Capacity (ASDCP::PCM::CalcFrameBufferSize (_state->audio_desc));
+       _state->frame_buffer.Size (ASDCP::PCM::CalcFrameBufferSize (_state->audio_desc));
+       memset (_state->frame_buffer.Data(), 0, _state->frame_buffer.Capacity());
+       
+       _sound_mxf->fill_writer_info (&_state->writer_info, standard);
+       
+       Kumu::Result_t r = _state->mxf_writer.OpenWrite (file.string().c_str(), _state->writer_info, _state->audio_desc);
+       if (ASDCP_FAILURE (r)) {
+               boost::throw_exception (FileError ("could not open audio MXF for writing", file.string(), r));
+       }
+}
+
+void
+SoundMXFWriter::write (float const * const * data, int frames)
+{
+       assert (!_finalized);
+       
+       for (int i = 0; i < frames; ++i) {
+
+               byte_t* out = _state->frame_buffer.Data() + _frame_buffer_offset;
+
+               /* Write one sample per channel */
+               for (int j = 0; j < _sound_mxf->channels(); ++j) {
+                       int32_t const s = data[j][i] * (1 << 23);
+                       *out++ = (s & 0xff);
+                       *out++ = (s & 0xff00) >> 8;
+                       *out++ = (s & 0xff0000) >> 16;
+               }
+               _frame_buffer_offset += 3 * _sound_mxf->channels();
+
+               assert (_frame_buffer_offset <= int (_state->frame_buffer.Capacity()));
+
+               /* Finish the MXF frame if required */
+               if (_frame_buffer_offset == int (_state->frame_buffer.Capacity())) {
+                       write_current_frame ();
+                       _frame_buffer_offset = 0;
+                       memset (_state->frame_buffer.Data(), 0, _state->frame_buffer.Capacity());
+               }
+       }
+}
+
+void
+SoundMXFWriter::write_current_frame ()
+{
+       ASDCP::Result_t const r = _state->mxf_writer.WriteFrame (_state->frame_buffer, _state->encryption_context, 0);
+       if (ASDCP_FAILURE (r)) {
+               boost::throw_exception (MiscError (String::compose ("could not write audio MXF frame (%1)", int (r))));
+       }
+
+       ++_frames_written;
+}
+
+void
+SoundMXFWriter::finalize ()
+{
+       if (_frame_buffer_offset > 0) {
+               write_current_frame ();
+       }
+       
+       if (ASDCP_FAILURE (_state->mxf_writer.Finalize())) {
+               boost::throw_exception (MiscError ("could not finalise audio MXF"));
+       }
+
+       MXFWriter::finalize ();
+}
diff --git a/src/sound_mxf_writer.h b/src/sound_mxf_writer.h
new file mode 100644 (file)
index 0000000..4f60074
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+    Copyright (C) 2012-2014 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 "mxf_writer.h"
+#include "types.h"
+#include <boost/shared_ptr.hpp>
+#include <boost/filesystem.hpp>
+
+namespace dcp {
+
+class SoundFrame;
+class SoundMXF;
+
+class SoundMXFWriter : public MXFWriter
+{
+public:
+       void write (float const * const *, int);
+       void finalize ();
+
+private:
+       friend class SoundMXF;
+
+       SoundMXFWriter (SoundMXF *, boost::filesystem::path, Standard standard);
+
+       void write_current_frame ();
+
+       /* do this with an opaque pointer so we don't have to include
+          ASDCP headers
+       */
+          
+       struct ASDCPState;
+       boost::shared_ptr<ASDCPState> _state;
+
+       SoundMXF* _sound_mxf;
+       int _frame_buffer_offset;
+};
+
+}
+
index 893a9f72fd2cc7d6e1f58dbb3fcea87f151d712f..790fcc1a2593f6a5ba510dc7951994c347e58d40 100644 (file)
@@ -63,6 +63,8 @@ StereoPictureFrame::~StereoPictureFrame ()
  *  @param reduce a factor by which to reduce the resolution
  *  of the image, expressed as a power of two (pass 0 for no
  *  reduction).
+ *  @param srgb_gamma Reciprocal of gamma to use when doing the
+ *  output gamma correction (after conversion from XYZ to RGB).
  *
  *  @return An ARGB representation of one of the eyes (left or right)
  *  of this frame.  This is ARGB in the Cairo sense, so that each
index 7e1126873082af3a9d43e9b14c0ad0d3e06e0f61..980c6ad52e110f045ad762dc5f08ddba50e9ce0f 100644 (file)
@@ -30,6 +30,48 @@ using boost::shared_ptr;
 using boost::dynamic_pointer_cast;
 using namespace dcp;
 
+StereoPictureMXF::StereoPictureMXF (boost::filesystem::path file)
+       : PictureMXF (file)
+{
+       ASDCP::JP2K::MXFSReader reader;
+       Kumu::Result_t r = reader.OpenRead (file.string().c_str());
+       if (ASDCP_FAILURE (r)) {
+               boost::throw_exception (MXFFileError ("could not open MXF file for reading", file.string(), r));
+       }
+       
+       ASDCP::JP2K::PictureDescriptor desc;
+       if (ASDCP_FAILURE (reader.FillPictureDescriptor (desc))) {
+               boost::throw_exception (DCPReadError ("could not read video MXF information"));
+       }
+
+       read_picture_descriptor (desc);
+}
+
+StereoPictureMXF::StereoPictureMXF (Fraction edit_rate)
+       : PictureMXF
+         (edit_rate)
+{
+
+}
+
+shared_ptr<const StereoPictureFrame>
+StereoPictureMXF::get_frame (int n) const
+{
+       return shared_ptr<const StereoPictureFrame> (new StereoPictureFrame (file().string(), n));
+}
+
+shared_ptr<PictureMXFWriter>
+StereoPictureMXF::start_write (boost::filesystem::path file, Standard standard, bool overwrite)
+{
+       return shared_ptr<StereoPictureMXFWriter> (new StereoPictureMXFWriter (this, file, standard, overwrite));
+}
+
+int
+StereoPictureMXF::edit_rate_factor () const
+{
+       return 2;
+}
+
 bool
 StereoPictureMXF::equals (shared_ptr<const Content> other, EqualityOptions opt, boost::function<void (NoteType, string)> note) const
 {
@@ -88,57 +130,3 @@ StereoPictureMXF::equals (shared_ptr<const Content> other, EqualityOptions opt,
 
        return true;
 }
-
-StereoPictureMXF::StereoPictureMXF (boost::filesystem::path file)
-       : PictureMXF (file)
-{
-       ASDCP::JP2K::MXFSReader reader;
-       Kumu::Result_t r = reader.OpenRead (file.string().c_str());
-       if (ASDCP_FAILURE (r)) {
-               boost::throw_exception (MXFFileError ("could not open MXF file for reading", file.string(), r));
-       }
-       
-       ASDCP::JP2K::PictureDescriptor desc;
-       if (ASDCP_FAILURE (reader.FillPictureDescriptor (desc))) {
-               boost::throw_exception (DCPReadError ("could not read video MXF information"));
-       }
-
-       _size.width = desc.StoredWidth;
-       _size.height = desc.StoredHeight;
-}
-
-shared_ptr<const StereoPictureFrame>
-StereoPictureMXF::get_frame (int n) const
-{
-       return shared_ptr<const StereoPictureFrame> (new StereoPictureFrame (file().string(), n));
-}
-
-shared_ptr<PictureMXFWriter>
-StereoPictureMXF::start_write (boost::filesystem::path file, bool overwrite)
-{
-       return shared_ptr<StereoPictureMXFWriter> (new StereoPictureMXFWriter (this, file, overwrite));
-}
-
-string
-StereoPictureMXF::cpl_node_name () const
-{
-       return "msp-cpl:MainStereoscopicPicture";
-}
-
-pair<string, string>
-StereoPictureMXF::cpl_node_attribute () const
-{
-       if (_interop) {
-               return make_pair ("xmlns:msp-cpl", "http://www.digicine.com/schemas/437-Y/2007/Main-Stereo-Picture-CPL");
-       } else {
-               return make_pair ("xmlns:msp-cpl", "http://www.smpte-ra.org/schemas/429-10/2008/Main-Stereo-Picture-CPL");
-       }
-
-       return make_pair ("", "");
-}
-
-int
-StereoPictureMXF::edit_rate_factor () const
-{
-       return 2;
-}
index 4af8a3273ee289a527f41026f4bb9730124b247d..eb527a1e1b78eca76f082d548770ddc008ceafcd 100644 (file)
@@ -29,16 +29,15 @@ class StereoPictureMXF : public PictureMXF
 {
 public:
        StereoPictureMXF (boost::filesystem::path file);
+       StereoPictureMXF (Fraction edit_rate);
 
        /** Start a progressive write to a StereoPictureMXF */
-       boost::shared_ptr<PictureMXFWriter> start_write (boost::filesystem::path file, bool);
+       boost::shared_ptr<PictureMXFWriter> start_write (boost::filesystem::path file, Standard, bool);
 
        boost::shared_ptr<const StereoPictureFrame> get_frame (int n) const;
        bool equals (boost::shared_ptr<const Content> other, EqualityOptions opt, boost::function<void (NoteType, std::string)> note) const;
 
 private:
-       std::string cpl_node_name () const;
-       std::pair<std::string, std::string> cpl_node_attribute () const;
        int edit_rate_factor () const;
 };
 
index ad029b573921adc00b8190b9c7cc39f14673fabb..4ea65e05931a930ce8ac36eacf8420b8aa5a02c6 100644 (file)
@@ -36,8 +36,8 @@ struct StereoPictureMXFWriter::ASDCPState : public ASDCPStateBase
        ASDCP::JP2K::MXFSWriter mxf_writer;
 };
 
-StereoPictureMXFWriter::StereoPictureMXFWriter (PictureMXF* mxf, boost::filesystem::path file, bool overwrite)
-       : PictureMXFWriter (mxf, file, overwrite)
+StereoPictureMXFWriter::StereoPictureMXFWriter (PictureMXF* mxf, boost::filesystem::path file, Standard standard, bool overwrite)
+       : PictureMXFWriter (mxf, file, standard, overwrite)
        , _state (new StereoPictureMXFWriter::ASDCPState)
        , _next_eye (EYE_LEFT)
 {
@@ -47,7 +47,7 @@ StereoPictureMXFWriter::StereoPictureMXFWriter (PictureMXF* mxf, boost::filesyst
 void
 StereoPictureMXFWriter::start (uint8_t* data, int size)
 {
-       dcp::start (this, _state, _mxf, data, size);
+       dcp::start (this, _state, _standard, _picture_mxf, data, size);
 }
 
 /** Write a frame for one eye.  Frames must be written left, then right, then left etc.
@@ -84,7 +84,10 @@ StereoPictureMXFWriter::write (uint8_t* data, int size)
 
        _next_eye = _next_eye == EYE_LEFT ? EYE_RIGHT : EYE_LEFT;
 
-       ++_frames_written;
+       if (_next_eye == EYE_LEFT) {
+               ++_frames_written;
+       }
+                       
        return FrameInfo (before_offset, _state->mxf_writer.Tell() - before_offset, hash);
 }
 
@@ -100,20 +103,18 @@ StereoPictureMXFWriter::fake_write (int size)
        }
 
        _next_eye = _next_eye == EYE_LEFT ? EYE_RIGHT : EYE_LEFT;
-       ++_frames_written;
+       if (_next_eye == EYE_LEFT) {
+               ++_frames_written;
+       }
 }
 
 void
 StereoPictureMXFWriter::finalize ()
 {
-       assert (!_finalized);
-       
        Kumu::Result_t r = _state->mxf_writer.Finalize();
        if (ASDCP_FAILURE (r)) {
                boost::throw_exception (MXFFileError ("error in finalizing video MXF", _mxf->file().string(), r));
        }
 
-       _finalized = true;
-       _mxf->set_intrinsic_duration (_frames_written / 2);
-       _mxf->set_duration (_frames_written / 2);
+       PictureMXFWriter::finalize ();
 }
index a34af069b44ad508e4f3266968a751b95131979d..8773eccd59b126a4d67e28191bd932e2a9d1b8a6 100644 (file)
 
 */
 
+#include "picture_mxf_writer.h"
+#include "types.h"
+#include <boost/shared_ptr.hpp>
+#include <boost/utility.hpp>
 #include <stdint.h>
 #include <string>
 #include <fstream>
-#include <boost/shared_ptr.hpp>
-#include <boost/utility.hpp>
-#include "picture_mxf_writer.h"
 
 namespace dcp {
 
@@ -46,7 +47,7 @@ public:
 private:
        friend class StereoPictureMXF;
 
-       StereoPictureMXFWriter (PictureMXF *, boost::filesystem::path file, bool);
+       StereoPictureMXFWriter (PictureMXF *, boost::filesystem::path file, Standard, bool);
        void start (uint8_t *, int);
 
        /* do this with an opaque pointer so we don't have to include
diff --git a/src/subtitle.cc b/src/subtitle.cc
new file mode 100644 (file)
index 0000000..dc7a6b2
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+    Copyright (C) 2012-2014 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 "subtitle.h"
+#include "xml.h"
+#include "font.h"
+#include "text.h"
+#include <libcxml/cxml.h>
+
+using std::string;
+using boost::shared_ptr;
+using boost::lexical_cast;
+using namespace dcp;
+
+Subtitle::Subtitle (shared_ptr<const cxml::Node> node)
+{
+       in = Time (node->string_attribute ("TimeIn"));
+       out = Time (node->string_attribute ("TimeOut"));
+       font_nodes = type_children<Font> (node, "Font");
+       text_nodes = type_children<Text> (node, "Text");
+       fade_up_time = fade_time (node, "FadeUpTime");
+       fade_down_time = fade_time (node, "FadeDownTime");
+}
+
+Time
+Subtitle::fade_time (shared_ptr<const cxml::Node> node, string name)
+{
+       string const u = node->optional_string_attribute (name).get_value_or ("");
+       Time t;
+       
+       if (u.empty ()) {
+               t = Time (0, 0, 0, 20);
+       } else if (u.find (":") != string::npos) {
+               t = Time (u);
+       } else {
+               t = Time (0, 0, 0, lexical_cast<int> (u));
+       }
+
+       if (t > Time (0, 0, 8, 0)) {
+               t = Time (0, 0, 8, 0);
+       }
+
+       return t;
+}
diff --git a/src/subtitle.h b/src/subtitle.h
new file mode 100644 (file)
index 0000000..073bfb0
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+    Copyright (C) 2012-2014 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.
+
+*/
+
+#ifndef LIBDCP_SUBTITLE_H
+#define LIBDCP_SUBTITLE_H
+
+#include "dcp_time.h"
+#include <boost/shared_ptr.hpp>
+#include <list>
+
+namespace cxml {
+       class Node;
+}
+
+namespace dcp {
+
+class Font;    
+class Text;
+
+class Subtitle 
+{
+public:
+       Subtitle () {}
+       Subtitle (boost::shared_ptr<const cxml::Node> node);
+
+       Time in;
+       Time out;
+       Time fade_up_time;
+       Time fade_down_time;
+       std::list<boost::shared_ptr<Font> > font_nodes;
+       std::list<boost::shared_ptr<Text> > text_nodes;
+
+private:
+       Time fade_time (boost::shared_ptr<const cxml::Node>, std::string name);
+};
+
+}
+
+#endif
diff --git a/src/subtitle_asset.cc b/src/subtitle_asset.cc
deleted file mode 100644 (file)
index 1c36fdf..0000000
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
-    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 <fstream>
-#include <boost/lexical_cast.hpp>
-#include <boost/algorithm/string.hpp>
-#include <libxml++/nodes/element.h>
-#include "subtitle_asset.h"
-#include "parse/subtitle.h"
-#include "util.h"
-#include "xml.h"
-
-using std::string;
-using std::list;
-using std::ostream;
-using std::ofstream;
-using std::stringstream;
-using boost::shared_ptr;
-using boost::lexical_cast;
-using boost::optional;
-using namespace dcp;
-
-SubtitleAsset::SubtitleAsset (boost::filesystem::path file)
-       : Content (file)
-       , _need_sort (false)
-{
-       shared_ptr<cxml::Document> xml (new cxml::Document ("DCSubtitle"));
-       xml->read_file (file);
-       
-       _id = xml->string_child ("SubtitleID");
-       _movie_title = xml->string_child ("MovieTitle");
-       _reel_number = xml->string_child ("ReelNumber");
-       _language = xml->string_child ("Language");
-
-       xml->ignore_child ("LoadFont");
-
-       list<shared_ptr<dcp::parse::Font> > font_nodes = type_children<dcp::parse::Font> (xml, "Font");
-       _load_font_nodes = type_children<dcp::parse::LoadFont> (xml, "LoadFont");
-
-       /* Now make Subtitle objects to represent the raw XML nodes
-          in a sane way.
-       */
-
-       ParseState parse_state;
-       examine_font_nodes (xml, font_nodes, parse_state);
-}
-
-SubtitleAsset::SubtitleAsset (string directory, string movie_title, string language)
-       : Content (directory)
-       , _movie_title (movie_title)
-       , _reel_number ("1")
-       , _language (language)
-       , _need_sort (false)
-{
-
-}
-
-void
-SubtitleAsset::examine_font_nodes (
-       shared_ptr<const cxml::Node> xml,
-       list<shared_ptr<dcp::parse::Font> > const & font_nodes,
-       ParseState& parse_state
-       )
-{
-       for (list<shared_ptr<dcp::parse::Font> >::const_iterator i = font_nodes.begin(); i != font_nodes.end(); ++i) {
-
-               parse_state.font_nodes.push_back (*i);
-               maybe_add_subtitle ((*i)->text, parse_state);
-
-               for (list<shared_ptr<dcp::parse::Subtitle> >::iterator j = (*i)->subtitle_nodes.begin(); j != (*i)->subtitle_nodes.end(); ++j) {
-                       parse_state.subtitle_nodes.push_back (*j);
-                       examine_text_nodes (xml, (*j)->text_nodes, parse_state);
-                       examine_font_nodes (xml, (*j)->font_nodes, parse_state);
-                       parse_state.subtitle_nodes.pop_back ();
-               }
-       
-               examine_font_nodes (xml, (*i)->font_nodes, parse_state);
-               examine_text_nodes (xml, (*i)->text_nodes, parse_state);
-               
-               parse_state.font_nodes.pop_back ();
-       }
-}
-
-void
-SubtitleAsset::examine_text_nodes (
-       shared_ptr<const cxml::Node> xml,
-       list<shared_ptr<dcp::parse::Text> > const & text_nodes,
-       ParseState& parse_state
-       )
-{
-       for (list<shared_ptr<dcp::parse::Text> >::const_iterator i = text_nodes.begin(); i != text_nodes.end(); ++i) {
-               parse_state.text_nodes.push_back (*i);
-               maybe_add_subtitle ((*i)->text, parse_state);
-               examine_font_nodes (xml, (*i)->font_nodes, parse_state);
-               parse_state.text_nodes.pop_back ();
-       }
-}
-
-void
-SubtitleAsset::maybe_add_subtitle (string text, ParseState const & parse_state)
-{
-       if (empty_or_white_space (text)) {
-               return;
-       }
-       
-       if (parse_state.text_nodes.empty() || parse_state.subtitle_nodes.empty ()) {
-               return;
-       }
-
-       assert (!parse_state.text_nodes.empty ());
-       assert (!parse_state.subtitle_nodes.empty ());
-       
-       dcp::parse::Font effective_font (parse_state.font_nodes);
-       dcp::parse::Text effective_text (*parse_state.text_nodes.back ());
-       dcp::parse::Subtitle effective_subtitle (*parse_state.subtitle_nodes.back ());
-
-       _subtitles.push_back (
-               shared_ptr<Subtitle> (
-                       new Subtitle (
-                               font_id_to_name (effective_font.id),
-                               effective_font.italic.get(),
-                               effective_font.color.get(),
-                               effective_font.size,
-                               effective_subtitle.in,
-                               effective_subtitle.out,
-                               effective_text.v_position,
-                               effective_text.v_align,
-                               text,
-                               effective_font.effect ? effective_font.effect.get() : NONE,
-                               effective_font.effect_color.get(),
-                               effective_subtitle.fade_up_time,
-                               effective_subtitle.fade_down_time
-                               )
-                       )
-               );
-}
-
-list<shared_ptr<Subtitle> >
-SubtitleAsset::subtitles_at (Time t) const
-{
-       list<shared_ptr<Subtitle> > s;
-       for (list<shared_ptr<Subtitle> >::const_iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) {
-               if ((*i)->in() <= t && t <= (*i)->out ()) {
-                       s.push_back (*i);
-               }
-       }
-
-       return s;
-}
-
-std::string
-SubtitleAsset::font_id_to_name (string id) const
-{
-       list<shared_ptr<dcp::parse::LoadFont> >::const_iterator i = _load_font_nodes.begin();
-       while (i != _load_font_nodes.end() && (*i)->id != id) {
-               ++i;
-       }
-
-       if (i == _load_font_nodes.end ()) {
-               return "";
-       }
-
-       if ((*i)->uri == "arial.ttf") {
-               return "Arial";
-       }
-
-       return "";
-}
-
-Subtitle::Subtitle (
-       string font,
-       bool italic,
-       Color color,
-       int size,
-       Time in,
-       Time out,
-       float v_position,
-       VAlign v_align,
-       string text,
-       Effect effect,
-       Color effect_color,
-       Time fade_up_time,
-       Time fade_down_time
-       )
-       : _font (font)
-       , _italic (italic)
-       , _color (color)
-       , _size (size)
-       , _in (in)
-       , _out (out)
-       , _v_position (v_position)
-       , _v_align (v_align)
-       , _text (text)
-       , _effect (effect)
-       , _effect_color (effect_color)
-       , _fade_up_time (fade_up_time)
-       , _fade_down_time (fade_down_time)
-{
-
-}
-
-int
-Subtitle::size_in_pixels (int screen_height) const
-{
-       /* Size in the subtitle file is given in points as if the screen
-          height is 11 inches, so a 72pt font would be 1/11th of the screen
-          height.
-       */
-       
-       return _size * screen_height / (11 * 72);
-}
-
-bool
-dcp::operator== (Subtitle const & a, Subtitle const & b)
-{
-       return (
-               a.font() == b.font() &&
-               a.italic() == b.italic() &&
-               a.color() == b.color() &&
-               a.size() == b.size() &&
-               a.in() == b.in() &&
-               a.out() == b.out() &&
-               a.v_position() == b.v_position() &&
-               a.v_align() == b.v_align() &&
-               a.text() == b.text() &&
-               a.effect() == b.effect() &&
-               a.effect_color() == b.effect_color() &&
-               a.fade_up_time() == b.fade_up_time() &&
-               a.fade_down_time() == b.fade_down_time()
-               );
-}
-
-ostream&
-dcp::operator<< (ostream& s, Subtitle const & sub)
-{
-       s << "\n`" << sub.text() << "' from " << sub.in() << " to " << sub.out() << ";\n"
-         << "fade up " << sub.fade_up_time() << ", fade down " << sub.fade_down_time() << ";\n"
-         << "font " << sub.font() << ", ";
-
-       if (sub.italic()) {
-               s << "italic";
-       } else {
-               s << "non-italic";
-       }
-       
-       s << ", size " << sub.size() << ", color " << sub.color() << ", vpos " << sub.v_position() << ", valign " << ((int) sub.v_align()) << ";\n"
-         << "effect " << ((int) sub.effect()) << ", effect color " << sub.effect_color();
-
-       return s;
-}
-
-void
-SubtitleAsset::add (shared_ptr<Subtitle> s)
-{
-       _subtitles.push_back (s);
-       _need_sort = true;
-}
-
-void
-SubtitleAsset::write_to_cpl (xmlpp::Element* node) const
-{
-       /* XXX: should EditRate, Duration and IntrinsicDuration be in here? */
-
-       xmlpp::Node* ms = node->add_child ("MainSubtitle");
-       ms->add_child("Id")->add_child_text("urn:uuid:" + _id);
-       ms->add_child("AnnotationText")->add_child_text (_file.string ());
-       /* XXX */
-       ms->add_child("EntryPoint")->add_child_text ("0");
-}
-
-struct SubtitleSorter {
-       bool operator() (shared_ptr<Subtitle> a, shared_ptr<Subtitle> b) {
-               if (a->in() != b->in()) {
-                       return a->in() < b->in();
-               }
-               return a->v_position() < b->v_position();
-       }
-};
-
-void
-SubtitleAsset::write_xml () const
-{
-       FILE* f = fopen_boost (file (), "r");
-       Glib::ustring const s = xml_as_string ();
-       fwrite (s.c_str(), 1, s.length(), f);
-       fclose (f);
-}
-
-Glib::ustring
-SubtitleAsset::xml_as_string () const
-{
-       xmlpp::Document doc;
-       xmlpp::Element* root = doc.create_root_node ("DCSubtitle");
-       root->set_attribute ("Version", "1.0");
-
-       root->add_child("SubtitleID")->add_child_text (_id);
-       root->add_child("MovieTitle")->add_child_text (_movie_title);
-       root->add_child("ReelNumber")->add_child_text (lexical_cast<string> (_reel_number));
-       root->add_child("Language")->add_child_text (_language);
-
-       if (_load_font_nodes.size() > 1) {
-               boost::throw_exception (MiscError ("multiple LoadFont nodes not supported"));
-       }
-
-       if (!_load_font_nodes.empty ()) {
-               xmlpp::Element* load_font = root->add_child("LoadFont");
-               load_font->set_attribute("Id", _load_font_nodes.front()->id);
-               load_font->set_attribute("URI",  _load_font_nodes.front()->uri);
-       }
-
-       list<shared_ptr<Subtitle> > sorted = _subtitles;
-       if (_need_sort) {
-               sorted.sort (SubtitleSorter ());
-       }
-
-       /* XXX: multiple fonts not supported */
-       /* XXX: script, underlined, weight not supported */
-
-       bool italic = false;
-       Color color;
-       int size = 0;
-       Effect effect = NONE;
-       Color effect_color;
-       int spot_number = 1;
-       Time last_in;
-       Time last_out;
-       Time last_fade_up_time;
-       Time last_fade_down_time;
-
-       xmlpp::Element* font = 0;
-       xmlpp::Element* subtitle = 0;
-
-       for (list<shared_ptr<Subtitle> >::iterator i = sorted.begin(); i != sorted.end(); ++i) {
-
-               /* We will start a new <Font>...</Font> whenever some font property changes.
-                  I suppose we should really make an optimal hierarchy of <Font> tags, but
-                  that seems hard.
-               */
-
-               bool const font_changed =
-                       italic       != (*i)->italic()       ||
-                       color        != (*i)->color()        ||
-                       size         != (*i)->size()         ||
-                       effect       != (*i)->effect()       ||
-                       effect_color != (*i)->effect_color();
-
-               if (font_changed) {
-                       italic = (*i)->italic ();
-                       color = (*i)->color ();
-                       size = (*i)->size ();
-                       effect = (*i)->effect ();
-                       effect_color = (*i)->effect_color ();
-               }
-
-               if (!font || font_changed) {
-                       font = root->add_child ("Font");
-                       string id = "theFontId";
-                       if (!_load_font_nodes.empty()) {
-                               id = _load_font_nodes.front()->id;
-                       }
-                       font->set_attribute ("Id", id);
-                       font->set_attribute ("Italic", italic ? "yes" : "no");
-                       font->set_attribute ("Color", color.to_argb_string());
-                       font->set_attribute ("Size", lexical_cast<string> (size));
-                       font->set_attribute ("Effect", effect_to_string (effect));
-                       font->set_attribute ("EffectColor", effect_color.to_argb_string());
-                       font->set_attribute ("Script", "normal");
-                       font->set_attribute ("Underlined", "no");
-                       font->set_attribute ("Weight", "normal");
-               }
-
-               if (!subtitle || font_changed ||
-                   (last_in != (*i)->in() ||
-                    last_out != (*i)->out() ||
-                    last_fade_up_time != (*i)->fade_up_time() ||
-                    last_fade_down_time != (*i)->fade_down_time()
-                           )) {
-
-                       subtitle = font->add_child ("Subtitle");
-                       subtitle->set_attribute ("SpotNumber", lexical_cast<string> (spot_number++));
-                       subtitle->set_attribute ("TimeIn", (*i)->in().to_string());
-                       subtitle->set_attribute ("TimeOut", (*i)->out().to_string());
-                       subtitle->set_attribute ("FadeUpTime", lexical_cast<string> ((*i)->fade_up_time().to_ticks()));
-                       subtitle->set_attribute ("FadeDownTime", lexical_cast<string> ((*i)->fade_down_time().to_ticks()));
-
-                       last_in = (*i)->in ();
-                       last_out = (*i)->out ();
-                       last_fade_up_time = (*i)->fade_up_time ();
-                       last_fade_down_time = (*i)->fade_down_time ();
-               }
-
-               xmlpp::Element* text = subtitle->add_child ("Text");
-               text->set_attribute ("VAlign", valign_to_string ((*i)->v_align()));             
-               text->set_attribute ("VPosition", lexical_cast<string> ((*i)->v_position()));
-               text->add_child_text ((*i)->text());
-       }
-
-       return doc.write_to_string_formatted ("UTF-8");
-}
-
diff --git a/src/subtitle_asset.h b/src/subtitle_asset.h
deleted file mode 100644 (file)
index cbd3ad5..0000000
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
-    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.
-
-*/
-
-#ifndef LIBDCP_SUBTITLE_ASSET_H
-#define LIBDCP_SUBTITLE_ASSET_H
-
-#include <libcxml/cxml.h>
-#include "content.h"
-#include "dcp_time.h"
-
-namespace dcp
-{
-
-namespace parse
-{
-       class Font;
-       class Text;
-       class Subtitle;
-       class LoadFont;
-}
-
-class Subtitle
-{
-public:
-       Subtitle (
-               std::string font,
-               bool italic,
-               Color color,
-               int size,
-               Time in,
-               Time out,
-               float v_position,
-               VAlign v_align,
-               std::string text,
-               Effect effect,
-               Color effect_color,
-               Time fade_up_time,
-               Time fade_down_time
-               );
-
-       std::string font () const {
-               return _font;
-       }
-
-       bool italic () const {
-               return _italic;
-       }
-
-       Color color () const {
-               return _color;
-       }
-
-       Time in () const {
-               return _in;
-       }
-
-       Time out () const {
-               return _out;
-       }
-
-       std::string text () const {
-               return _text;
-       }
-
-       float v_position () const {
-               return _v_position;
-       }
-
-       VAlign v_align () const {
-               return _v_align;
-       }
-
-       Effect effect () const {
-               return _effect;
-       }
-
-       Color effect_color () const {
-               return _effect_color;
-       }
-
-       Time fade_up_time () const {
-               return _fade_up_time;
-       }
-
-       Time fade_down_time () const {
-               return _fade_down_time;
-       }
-
-       int size () const {
-               return _size;
-       }
-       
-       int size_in_pixels (int screen_height) const;
-
-private:
-       std::string _font;
-       bool _italic;
-       Color _color;
-       /** Size in points as if the screen height is 11 inches, so a 72pt font
-        *  would be 1/11th of the screen height.
-        */ 
-       int _size;
-       Time _in;
-       Time _out;
-       /** Vertical position as a proportion of the screen height from the top
-        *  (between 0 and 1)
-        */
-       float _v_position;
-       VAlign _v_align;
-       std::string _text;
-       Effect _effect;
-       Color _effect_color;
-       Time _fade_up_time;
-       Time _fade_down_time;
-};
-
-bool operator== (Subtitle const & a, Subtitle const & b);
-std::ostream& operator<< (std::ostream& s, Subtitle const & sub);
-
-class SubtitleAsset : public Content
-{
-public:
-       SubtitleAsset (boost::filesystem::path file);
-       SubtitleAsset (std::string directory, std::string movie_title, std::string language);
-
-       void write_to_cpl (xmlpp::Element *) const;
-       virtual bool equals (boost::shared_ptr<const Content>, EqualityOptions, boost::function<void (NoteType, std::string)> note) const {
-               /* XXX */
-               note (ERROR, "subtitle assets not compared yet");
-               return true;
-       }
-
-       std::string language () const {
-               return _language;
-       }
-
-       std::list<boost::shared_ptr<Subtitle> > subtitles_at (Time t) const;
-       std::list<boost::shared_ptr<Subtitle> > const & subtitles () const {
-               return _subtitles;
-       }
-
-       void add (boost::shared_ptr<Subtitle>);
-
-       void write_xml () const;
-       Glib::ustring xml_as_string () const;
-
-private:
-       std::string font_id_to_name (std::string id) const;
-
-       struct ParseState {
-               std::list<boost::shared_ptr<parse::Font> > font_nodes;
-               std::list<boost::shared_ptr<parse::Text> > text_nodes;
-               std::list<boost::shared_ptr<parse::Subtitle> > subtitle_nodes;
-       };
-
-       void maybe_add_subtitle (std::string text, ParseState const & parse_state);
-       
-       void examine_font_nodes (
-               boost::shared_ptr<const cxml::Node> xml,
-               std::list<boost::shared_ptr<parse::Font> > const & font_nodes,
-               ParseState& parse_state
-               );
-       
-       void examine_text_nodes (
-               boost::shared_ptr<const cxml::Node> xml,
-               std::list<boost::shared_ptr<parse::Text> > const & text_nodes,
-               ParseState& parse_state
-               );
-
-       std::string _movie_title;
-       /* strangely, this is sometimes a string */
-       std::string _reel_number;
-       std::string _language;
-       std::list<boost::shared_ptr<parse::LoadFont> > _load_font_nodes;
-
-       std::list<boost::shared_ptr<Subtitle> > _subtitles;
-       bool _need_sort;
-};
-
-}
-
-#endif
diff --git a/src/subtitle_content.cc b/src/subtitle_content.cc
new file mode 100644 (file)
index 0000000..e32118c
--- /dev/null
@@ -0,0 +1,325 @@
+/*
+    Copyright (C) 2012-2014 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 "subtitle_content.h"
+#include "util.h"
+#include "xml.h"
+#include "font.h"
+#include "text.h"
+#include "load_font.h"
+#include "subtitle_string.h"
+#include <libxml++/nodes/element.h>
+#include <boost/lexical_cast.hpp>
+#include <boost/algorithm/string.hpp>
+#include <fstream>
+
+using std::string;
+using std::list;
+using std::ostream;
+using std::ofstream;
+using std::stringstream;
+using boost::shared_ptr;
+using boost::lexical_cast;
+using boost::optional;
+using namespace dcp;
+
+SubtitleContent::SubtitleContent (boost::filesystem::path file)
+       : Content (file)
+       , _need_sort (false)
+{
+       shared_ptr<cxml::Document> xml (new cxml::Document ("DCSubtitle"));
+       xml->read_file (file);
+       
+       _id = xml->string_child ("SubtitleID");
+       _movie_title = xml->string_child ("MovieTitle");
+       _reel_number = xml->string_child ("ReelNumber");
+       _language = xml->string_child ("Language");
+
+       xml->ignore_child ("LoadFont");
+
+       list<shared_ptr<dcp::Font> > font_nodes = type_children<dcp::Font> (xml, "Font");
+       _load_font_nodes = type_children<dcp::LoadFont> (xml, "LoadFont");
+
+       /* Now make Subtitle objects to represent the raw XML nodes
+          in a sane way.
+       */
+
+       ParseState parse_state;
+       examine_font_nodes (xml, font_nodes, parse_state);
+}
+
+SubtitleContent::SubtitleContent (Fraction edit_rate, string movie_title, string language)
+       : Content (edit_rate)
+       , _movie_title (movie_title)
+       , _reel_number ("1")
+       , _language (language)
+       , _need_sort (false)
+{
+
+}
+
+void
+SubtitleContent::examine_font_nodes (
+       shared_ptr<const cxml::Node> xml,
+       list<shared_ptr<dcp::Font> > const & font_nodes,
+       ParseState& parse_state
+       )
+{
+       for (list<shared_ptr<dcp::Font> >::const_iterator i = font_nodes.begin(); i != font_nodes.end(); ++i) {
+
+               parse_state.font_nodes.push_back (*i);
+               maybe_add_subtitle ((*i)->text, parse_state);
+
+               for (list<shared_ptr<dcp::Subtitle> >::iterator j = (*i)->subtitle_nodes.begin(); j != (*i)->subtitle_nodes.end(); ++j) {
+                       parse_state.subtitle_nodes.push_back (*j);
+                       examine_text_nodes (xml, (*j)->text_nodes, parse_state);
+                       examine_font_nodes (xml, (*j)->font_nodes, parse_state);
+                       parse_state.subtitle_nodes.pop_back ();
+               }
+       
+               examine_font_nodes (xml, (*i)->font_nodes, parse_state);
+               examine_text_nodes (xml, (*i)->text_nodes, parse_state);
+               
+               parse_state.font_nodes.pop_back ();
+       }
+}
+
+void
+SubtitleContent::examine_text_nodes (
+       shared_ptr<const cxml::Node> xml,
+       list<shared_ptr<dcp::Text> > const & text_nodes,
+       ParseState& parse_state
+       )
+{
+       for (list<shared_ptr<dcp::Text> >::const_iterator i = text_nodes.begin(); i != text_nodes.end(); ++i) {
+               parse_state.text_nodes.push_back (*i);
+               maybe_add_subtitle ((*i)->text, parse_state);
+               examine_font_nodes (xml, (*i)->font_nodes, parse_state);
+               parse_state.text_nodes.pop_back ();
+       }
+}
+
+void
+SubtitleContent::maybe_add_subtitle (string text, ParseState const & parse_state)
+{
+       if (empty_or_white_space (text)) {
+               return;
+       }
+       
+       if (parse_state.text_nodes.empty() || parse_state.subtitle_nodes.empty ()) {
+               return;
+       }
+
+       assert (!parse_state.text_nodes.empty ());
+       assert (!parse_state.subtitle_nodes.empty ());
+       
+       dcp::Font effective_font (parse_state.font_nodes);
+       dcp::Text effective_text (*parse_state.text_nodes.back ());
+       dcp::Subtitle effective_subtitle (*parse_state.subtitle_nodes.back ());
+
+       _subtitles.push_back (
+               shared_ptr<SubtitleString> (
+                       new SubtitleString (
+                               font_id_to_name (effective_font.id),
+                               effective_font.italic.get(),
+                               effective_font.color.get(),
+                               effective_font.size,
+                               effective_subtitle.in,
+                               effective_subtitle.out,
+                               effective_text.v_position,
+                               effective_text.v_align,
+                               text,
+                               effective_font.effect ? effective_font.effect.get() : NONE,
+                               effective_font.effect_color.get(),
+                               effective_subtitle.fade_up_time,
+                               effective_subtitle.fade_down_time
+                               )
+                       )
+               );
+}
+
+list<shared_ptr<SubtitleString> >
+SubtitleContent::subtitles_at (Time t) const
+{
+       list<shared_ptr<SubtitleString> > s;
+       for (list<shared_ptr<SubtitleString> >::const_iterator i = _subtitles.begin(); i != _subtitles.end(); ++i) {
+               if ((*i)->in() <= t && t <= (*i)->out ()) {
+                       s.push_back (*i);
+               }
+       }
+
+       return s;
+}
+
+std::string
+SubtitleContent::font_id_to_name (string id) const
+{
+       list<shared_ptr<dcp::LoadFont> >::const_iterator i = _load_font_nodes.begin();
+       while (i != _load_font_nodes.end() && (*i)->id != id) {
+               ++i;
+       }
+
+       if (i == _load_font_nodes.end ()) {
+               return "";
+       }
+
+       if ((*i)->uri == "arial.ttf") {
+               return "Arial";
+       }
+
+       return "";
+}
+
+void
+SubtitleContent::add (shared_ptr<SubtitleString> s)
+{
+       _subtitles.push_back (s);
+       _need_sort = true;
+}
+
+struct SubtitleSorter {
+       bool operator() (shared_ptr<SubtitleString> a, shared_ptr<SubtitleString> b) {
+               if (a->in() != b->in()) {
+                       return a->in() < b->in();
+               }
+               return a->v_position() < b->v_position();
+       }
+};
+
+void
+SubtitleContent::write_xml () const
+{
+       FILE* f = fopen_boost (file (), "r");
+       Glib::ustring const s = xml_as_string ();
+       fwrite (s.c_str(), 1, s.length(), f);
+       fclose (f);
+}
+
+Glib::ustring
+SubtitleContent::xml_as_string () const
+{
+       xmlpp::Document doc;
+       xmlpp::Element* root = doc.create_root_node ("DCSubtitle");
+       root->set_attribute ("Version", "1.0");
+
+       root->add_child("SubtitleID")->add_child_text (_id);
+       root->add_child("MovieTitle")->add_child_text (_movie_title);
+       root->add_child("ReelNumber")->add_child_text (lexical_cast<string> (_reel_number));
+       root->add_child("Language")->add_child_text (_language);
+
+       if (_load_font_nodes.size() > 1) {
+               boost::throw_exception (MiscError ("multiple LoadFont nodes not supported"));
+       }
+
+       if (!_load_font_nodes.empty ()) {
+               xmlpp::Element* load_font = root->add_child("LoadFont");
+               load_font->set_attribute("Id", _load_font_nodes.front()->id);
+               load_font->set_attribute("URI",  _load_font_nodes.front()->uri);
+       }
+
+       list<shared_ptr<SubtitleString> > sorted = _subtitles;
+       if (_need_sort) {
+               sorted.sort (SubtitleSorter ());
+       }
+
+       /* XXX: multiple fonts not supported */
+       /* XXX: script, underlined, weight not supported */
+
+       bool italic = false;
+       Color color;
+       int size = 0;
+       Effect effect = NONE;
+       Color effect_color;
+       int spot_number = 1;
+       Time last_in;
+       Time last_out;
+       Time last_fade_up_time;
+       Time last_fade_down_time;
+
+       xmlpp::Element* font = 0;
+       xmlpp::Element* subtitle = 0;
+
+       for (list<shared_ptr<SubtitleString> >::iterator i = sorted.begin(); i != sorted.end(); ++i) {
+
+               /* We will start a new <Font>...</Font> whenever some font property changes.
+                  I suppose we should really make an optimal hierarchy of <Font> tags, but
+                  that seems hard.
+               */
+
+               bool const font_changed =
+                       italic       != (*i)->italic()       ||
+                       color        != (*i)->color()        ||
+                       size         != (*i)->size()         ||
+                       effect       != (*i)->effect()       ||
+                       effect_color != (*i)->effect_color();
+
+               if (font_changed) {
+                       italic = (*i)->italic ();
+                       color = (*i)->color ();
+                       size = (*i)->size ();
+                       effect = (*i)->effect ();
+                       effect_color = (*i)->effect_color ();
+               }
+
+               if (!font || font_changed) {
+                       font = root->add_child ("Font");
+                       string id = "theFontId";
+                       if (!_load_font_nodes.empty()) {
+                               id = _load_font_nodes.front()->id;
+                       }
+                       font->set_attribute ("Id", id);
+                       font->set_attribute ("Italic", italic ? "yes" : "no");
+                       font->set_attribute ("Color", color.to_argb_string());
+                       font->set_attribute ("Size", lexical_cast<string> (size));
+                       font->set_attribute ("Effect", effect_to_string (effect));
+                       font->set_attribute ("EffectColor", effect_color.to_argb_string());
+                       font->set_attribute ("Script", "normal");
+                       font->set_attribute ("Underlined", "no");
+                       font->set_attribute ("Weight", "normal");
+               }
+
+               if (!subtitle || font_changed ||
+                   (last_in != (*i)->in() ||
+                    last_out != (*i)->out() ||
+                    last_fade_up_time != (*i)->fade_up_time() ||
+                    last_fade_down_time != (*i)->fade_down_time()
+                           )) {
+
+                       subtitle = font->add_child ("Subtitle");
+                       subtitle->set_attribute ("SpotNumber", lexical_cast<string> (spot_number++));
+                       subtitle->set_attribute ("TimeIn", (*i)->in().to_string());
+                       subtitle->set_attribute ("TimeOut", (*i)->out().to_string());
+                       subtitle->set_attribute ("FadeUpTime", lexical_cast<string> ((*i)->fade_up_time().to_ticks()));
+                       subtitle->set_attribute ("FadeDownTime", lexical_cast<string> ((*i)->fade_down_time().to_ticks()));
+
+                       last_in = (*i)->in ();
+                       last_out = (*i)->out ();
+                       last_fade_up_time = (*i)->fade_up_time ();
+                       last_fade_down_time = (*i)->fade_down_time ();
+               }
+
+               xmlpp::Element* text = subtitle->add_child ("Text");
+               text->set_attribute ("VAlign", valign_to_string ((*i)->v_align()));             
+               text->set_attribute ("VPosition", lexical_cast<string> ((*i)->v_position()));
+               text->add_child_text ((*i)->text());
+       }
+
+       return doc.write_to_string_formatted ("UTF-8");
+}
+
diff --git a/src/subtitle_content.h b/src/subtitle_content.h
new file mode 100644 (file)
index 0000000..b8db0c2
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+    Copyright (C) 2012-2014 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.
+
+*/
+
+#ifndef LIBDCP_SUBTITLE_CONTENT_H
+#define LIBDCP_SUBTITLE_CONTENT_H
+
+#include "content.h"
+#include "dcp_time.h"
+#include <libcxml/cxml.h>
+
+namespace dcp
+{
+
+class SubtitleString;  
+class Font;
+class Text;
+class Subtitle;
+class LoadFont;
+
+/** @class SubtitleContent
+ *  @brief A representation of an XML file containing subtitles.
+ */
+class SubtitleContent : public Content
+{
+public:
+       SubtitleContent (boost::filesystem::path file);
+       SubtitleContent (Fraction edit_rate, std::string movie_title, std::string language);
+
+       std::string pkl_type () const {
+               return "text/xml";
+       }
+       
+       virtual bool equals (boost::shared_ptr<const Content>, EqualityOptions, boost::function<void (NoteType, std::string)> note) const {
+               /* XXX */
+               note (ERROR, "subtitle content not compared yet");
+               return true;
+       }
+
+       std::string language () const {
+               return _language;
+       }
+
+       std::list<boost::shared_ptr<SubtitleString> > subtitles_at (Time t) const;
+       std::list<boost::shared_ptr<SubtitleString> > const & subtitles () const {
+               return _subtitles;
+       }
+
+       void add (boost::shared_ptr<SubtitleString>);
+
+       void write_xml () const;
+       Glib::ustring xml_as_string () const;
+
+private:
+       std::string font_id_to_name (std::string id) const;
+
+       struct ParseState {
+               std::list<boost::shared_ptr<Font> > font_nodes;
+               std::list<boost::shared_ptr<Text> > text_nodes;
+               std::list<boost::shared_ptr<Subtitle> > subtitle_nodes;
+       };
+
+       void maybe_add_subtitle (std::string text, ParseState const & parse_state);
+       
+       void examine_font_nodes (
+               boost::shared_ptr<const cxml::Node> xml,
+               std::list<boost::shared_ptr<Font> > const & font_nodes,
+               ParseState& parse_state
+               );
+       
+       void examine_text_nodes (
+               boost::shared_ptr<const cxml::Node> xml,
+               std::list<boost::shared_ptr<Text> > const & text_nodes,
+               ParseState& parse_state
+               );
+
+       std::string _movie_title;
+       /* strangely, this is sometimes a string */
+       std::string _reel_number;
+       std::string _language;
+       std::list<boost::shared_ptr<LoadFont> > _load_font_nodes;
+
+       std::list<boost::shared_ptr<SubtitleString> > _subtitles;
+       bool _need_sort;
+};
+
+}
+
+#endif
diff --git a/src/subtitle_string.cc b/src/subtitle_string.cc
new file mode 100644 (file)
index 0000000..66869fd
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+    Copyright (C) 2012-2014 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 "subtitle_string.h"
+#include "xml.h"
+
+using std::string;
+using std::ostream;
+using namespace dcp;
+
+SubtitleString::SubtitleString (
+       string font,
+       bool italic,
+       Color color,
+       int size,
+       Time in,
+       Time out,
+       float v_position,
+       VAlign v_align,
+       string text,
+       Effect effect,
+       Color effect_color,
+       Time fade_up_time,
+       Time fade_down_time
+       )
+       : _font (font)
+       , _italic (italic)
+       , _color (color)
+       , _size (size)
+       , _in (in)
+       , _out (out)
+       , _v_position (v_position)
+       , _v_align (v_align)
+       , _text (text)
+       , _effect (effect)
+       , _effect_color (effect_color)
+       , _fade_up_time (fade_up_time)
+       , _fade_down_time (fade_down_time)
+{
+
+}
+
+int
+SubtitleString::size_in_pixels (int screen_height) const
+{
+       /* Size in the subtitle file is given in points as if the screen
+          height is 11 inches, so a 72pt font would be 1/11th of the screen
+          height.
+       */
+       
+       return _size * screen_height / (11 * 72);
+}
+
+bool
+dcp::operator== (SubtitleString const & a, SubtitleString const & b)
+{
+       return (
+               a.font() == b.font() &&
+               a.italic() == b.italic() &&
+               a.color() == b.color() &&
+               a.size() == b.size() &&
+               a.in() == b.in() &&
+               a.out() == b.out() &&
+               a.v_position() == b.v_position() &&
+               a.v_align() == b.v_align() &&
+               a.text() == b.text() &&
+               a.effect() == b.effect() &&
+               a.effect_color() == b.effect_color() &&
+               a.fade_up_time() == b.fade_up_time() &&
+               a.fade_down_time() == b.fade_down_time()
+               );
+}
+
+ostream&
+dcp::operator<< (ostream& s, SubtitleString const & sub)
+{
+       s << "\n`" << sub.text() << "' from " << sub.in() << " to " << sub.out() << ";\n"
+         << "fade up " << sub.fade_up_time() << ", fade down " << sub.fade_down_time() << ";\n"
+         << "font " << sub.font() << ", ";
+
+       if (sub.italic()) {
+               s << "italic";
+       } else {
+               s << "non-italic";
+       }
+       
+       s << ", size " << sub.size() << ", color " << sub.color() << ", vpos " << sub.v_position() << ", valign " << ((int) sub.v_align()) << ";\n"
+         << "effect " << ((int) sub.effect()) << ", effect color " << sub.effect_color();
+
+       return s;
+}
diff --git a/src/subtitle_string.h b/src/subtitle_string.h
new file mode 100644 (file)
index 0000000..59131f0
--- /dev/null
@@ -0,0 +1,124 @@
+/*
+    Copyright (C) 2012-2014 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 "types.h"
+#include "dcp_time.h"
+#include <string>
+
+namespace dcp {
+
+class SubtitleString
+{
+public:
+       SubtitleString (
+               std::string font,
+               bool italic,
+               Color color,
+               int size,
+               Time in,
+               Time out,
+               float v_position,
+               VAlign v_align,
+               std::string text,
+               Effect effect,
+               Color effect_color,
+               Time fade_up_time,
+               Time fade_down_time
+               );
+
+       std::string font () const {
+               return _font;
+       }
+
+       bool italic () const {
+               return _italic;
+       }
+
+       Color color () const {
+               return _color;
+       }
+
+       Time in () const {
+               return _in;
+       }
+
+       Time out () const {
+               return _out;
+       }
+
+       std::string text () const {
+               return _text;
+       }
+
+       float v_position () const {
+               return _v_position;
+       }
+
+       VAlign v_align () const {
+               return _v_align;
+       }
+
+       Effect effect () const {
+               return _effect;
+       }
+
+       Color effect_color () const {
+               return _effect_color;
+       }
+
+       Time fade_up_time () const {
+               return _fade_up_time;
+       }
+
+       Time fade_down_time () const {
+               return _fade_down_time;
+       }
+
+       int size () const {
+               return _size;
+       }
+       
+       int size_in_pixels (int screen_height) const;
+
+private:
+       std::string _font;
+       bool _italic;
+       Color _color;
+       /** Size in points as if the screen height is 11 inches, so a 72pt font
+        *  would be 1/11th of the screen height.
+        */ 
+       int _size;
+       Time _in;
+       Time _out;
+       /** Vertical position as a proportion of the screen height from the top
+        *  (between 0 and 1)
+        */
+       float _v_position;
+       VAlign _v_align;
+       std::string _text;
+       Effect _effect;
+       Color _effect_color;
+       Time _fade_up_time;
+       Time _fade_down_time;
+};
+
+bool operator== (SubtitleString const & a, SubtitleString const & b);
+std::ostream& operator<< (std::ostream& s, SubtitleString const & sub);
+
+}
diff --git a/src/text.cc b/src/text.cc
new file mode 100644 (file)
index 0000000..5d2a2d1
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+    Copyright (C) 2012-2014 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 "text.h"
+#include "xml.h"
+#include "font.h"
+#include <libcxml/cxml.h>
+
+using std::string;
+using boost::shared_ptr;
+using boost::optional;
+using namespace dcp;
+
+Text::Text (shared_ptr<const cxml::Node> node)
+       : v_align (CENTER)
+{
+       text = node->content ();
+       v_position = node->number_attribute<float> ("VPosition");
+       optional<string> v = node->optional_string_attribute ("VAlign");
+       if (v) {
+               v_align = string_to_valign (v.get ());
+       }
+
+       font_nodes = type_children<Font> (node, "Font");
+}
diff --git a/src/text.h b/src/text.h
new file mode 100644 (file)
index 0000000..81992d6
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+    Copyright (C) 2012-2014 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 "types.h"
+#include <boost/shared_ptr.hpp>
+#include <list>
+
+namespace cxml {
+       class Node;
+}
+
+namespace dcp {
+
+class Font;
+
+class Text
+{
+public:
+       Text ()
+               : v_position (0)
+               , v_align (TOP)
+       {}
+       
+       Text (boost::shared_ptr<const cxml::Node> node);
+
+       float v_position;
+       VAlign v_align;
+       std::string text;
+       std::list<boost::shared_ptr<Font> > font_nodes;
+};
+
+}
index 021d1ecfff401744c7fe9f2f1a08c981c5467536..85dc836259573dd2d397a1e0dbf74fe55591ad80 100644 (file)
@@ -105,14 +105,14 @@ struct EqualityOptions {
                : max_mean_pixel_error (0)
                , max_std_dev_pixel_error (0)
                , max_audio_sample_error (0)
-               , cpl_names_can_differ (false)
+               , cpl_annotation_texts_can_differ (false)
                , mxf_names_can_differ (false)
        {}
 
        double max_mean_pixel_error;
        double max_std_dev_pixel_error;
        int max_audio_sample_error;
-       bool cpl_names_can_differ;
+       bool cpl_annotation_texts_can_differ;
        bool mxf_names_can_differ;
 };
 
@@ -125,6 +125,11 @@ enum NoteType {
        NOTE
 };
 
+enum Standard {
+       INTEROP,
+       SMPTE
+};
+
 /** @class Color
  *  @brief An RGB color (aka colour).
  */
index 3807b4cc44b8897a9583d0b2869781dc93a9aa91..fe89ca72fbe2299c8a20390a4c085deb46e1f170 100644 (file)
  *  @brief Utility methods.
  */
 
-#include <stdexcept>
-#include <sstream>
-#include <iostream>
-#include <iomanip>
-#include <boost/filesystem.hpp>
-#include <boost/lexical_cast.hpp>
-#include <openssl/sha.h>
-#include <libxml++/nodes/element.h>
-#include <libxml++/document.h>
-#include <xmlsec/xmldsig.h>
-#include <xmlsec/dl.h>
-#include <xmlsec/app.h>
-#include <xmlsec/crypto.h>
-#include "KM_util.h"
-#include "KM_fileio.h"
-#include "AS_DCP.h"
 #include "util.h"
 #include "exceptions.h"
 #include "types.h"
 #include "certificates.h"
 #include "gamma_lut.h"
 #include "xyz_frame.h"
+#include "KM_util.h"
+#include "KM_fileio.h"
+#include "AS_DCP.h"
+#include <xmlsec/xmldsig.h>
+#include <xmlsec/dl.h>
+#include <xmlsec/app.h>
+#include <xmlsec/crypto.h>
+#include <libxml++/nodes/element.h>
+#include <libxml++/document.h>
+#include <openssl/sha.h>
+#include <boost/filesystem.hpp>
+#include <boost/lexical_cast.hpp>
+#include <stdexcept>
+#include <sstream>
+#include <iostream>
+#include <iomanip>
 
 using std::string;
 using std::wstring;
@@ -79,10 +79,10 @@ dcp::make_uuid ()
  *  @return Digest.
  */
 string
-dcp::make_digest (string filename, boost::function<void (float)>* progress)
+dcp::make_digest (boost::filesystem::path filename, boost::function<void (float)>* progress)
 {
        Kumu::FileReader reader;
-       Kumu::Result_t r = reader.OpenRead (filename.c_str ());
+       Kumu::Result_t r = reader.OpenRead (filename.string().c_str ());
        if (ASDCP_FAILURE (r)) {
                boost::throw_exception (FileError ("could not open file to compute digest", filename, r));
        }
index f12f0ff039af90dad490318fa294080fe8a22ab4..5d7a9c4f96cc4513da15a76a208211621d8c63b7 100644 (file)
@@ -67,7 +67,7 @@ extern bool operator== (Size const & a, Size const & b);
 extern bool operator!= (Size const & a, Size const & b);
 
 extern std::string make_uuid ();
-extern std::string make_digest (std::string filename, boost::function<void (float)> *);
+extern std::string make_digest (boost::filesystem::path filename, boost::function<void (float)> *);
 extern std::string content_kind_to_string (ContentKind kind);
 extern ContentKind content_kind_from_string (std::string kind);
 extern bool empty_or_white_space (std::string s);
@@ -75,7 +75,7 @@ extern boost::shared_ptr<XYZFrame> decompress_j2k (uint8_t* data, int64_t size,
 
 extern void init ();
 
-extern void sign (xmlpp::Element* parent, CertificateChain const & certificates, boost::filesystem::path signer_key, bool interop);
+extern void sign (xmlpp::Element* parent, CertificateChain const & certificates, boost::filesystem::path signer_key, Standard standard);
 extern void add_signature_value (xmlpp::Element* parent, CertificateChain const & certificates, boost::filesystem::path signer_key, std::string const & ns);
 extern void add_signer (xmlpp::Element* parent, CertificateChain const & certificates, std::string const & ns);
 
index 3e92900afb73b7511e39cd44b3678e4f3b5dca08..60d442feae546a728078f46687d8d759e253a534 100644 (file)
@@ -21,38 +21,48 @@ def build(bld):
                  dcp.cc        
                  dcp_time.cc
                  exceptions.cc
+                 file.cc
+                 font.cc
                  gamma_lut.cc
                  image.cc
                  kdm.cc
                  key.cc
+                 load_font.cc
                  metadata.cc
                  mono_picture_mxf.cc
                  mono_picture_mxf_writer.cc
                  mono_picture_frame.cc
                  mxf.cc
+                 mxf_writer.cc
                  object.cc
                  picture_mxf.cc
                  picture_mxf_writer.cc
                  rec709_linearised_gamma_lut.cc
                  reel.cc
+                 reel_asset.cc
+                 reel_mono_picture_asset.cc
+                 reel_picture_asset.cc
+                 reel_sound_asset.cc
+                 reel_stereo_picture_asset.cc
+                 reel_subtitle_asset.cc
                  rgb_xyz.cc
                  signer.cc
                  signer_chain.cc
                  sound_mxf.cc
+                 sound_mxf_writer.cc
                  sound_frame.cc
                  srgb_linearised_gamma_lut.cc
                  stereo_picture_mxf.cc
                  stereo_picture_mxf_writer.cc
                  stereo_picture_frame.cc
-                 subtitle_asset.cc
+                 subtitle.cc
+                 subtitle_content.cc
+                 subtitle_string.cc
+                 text.cc
                  types.cc
                  util.cc
                  version.cc
                  xyz_frame.cc
-                 parse/asset_map.cc
-                 parse/cpl.cc
-                 parse/pkl.cc
-                 parse/subtitle.cc
                  """
 
     headers = """
diff --git a/test/cpl_sar.cc b/test/cpl_sar.cc
deleted file mode 100644 (file)
index 3ab1ec2..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
-    Copyright (C) 2014 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/test/unit_test.hpp>
-#include <libcxml/cxml.h>
-#include "cpl.h"
-#include "mono_picture_mxf.h"
-
-using boost::shared_ptr;
-
-/* Test for a reported bug where <ScreenAspectRatio> in Interop files uses
-   excessive decimal places and (sometimes) the wrong decimal point character.
-*/
-BOOST_AUTO_TEST_CASE (cpl_sar)
-{
-       shared_ptr<dcp::MonoPictureMXF> mp (new dcp::MonoPictureMXF ("build/test/foo/video.mxf"));
-       mp->set_interop (true);
-
-       {
-               mp->set_size (dcp::Size (1998, 1080));
-               xmlpp::Document doc;
-               xmlpp::Element* el = doc.create_root_node ("Test");
-               mp->write_to_cpl (el);
-               
-               cxml::Node node (el);
-               BOOST_CHECK_EQUAL (node.node_child("MainPicture")->string_child ("ScreenAspectRatio"), "1.85");
-       }
-
-       {
-               mp->set_size (dcp::Size (2048, 858));
-               xmlpp::Document doc;
-               xmlpp::Element* el = doc.create_root_node ("Test");
-               mp->write_to_cpl (el);
-               
-               cxml::Node node (el);
-               BOOST_CHECK_EQUAL (node.node_child("MainPicture")->string_child ("ScreenAspectRatio"), "2.39");
-       }
-}
diff --git a/test/cpl_sar_test.cc b/test/cpl_sar_test.cc
new file mode 100644 (file)
index 0000000..0c62ea8
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+    Copyright (C) 2014 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 "cpl.h"
+#include "reel_mono_picture_asset.h"
+#include "mono_picture_mxf.h"
+#include <libcxml/cxml.h>
+#include <boost/test/unit_test.hpp>
+
+using boost::shared_ptr;
+
+/* Test for a reported bug where <ScreenAspectRatio> in Interop files uses
+   excessive decimal places and (sometimes) the wrong decimal point character.
+*/
+BOOST_AUTO_TEST_CASE (cpl_sar)
+{
+       shared_ptr<dcp::ReelMonoPictureAsset> pa (new dcp::ReelMonoPictureAsset ());
+
+       {
+               pa->set_screen_aspect_ratio (dcp::Fraction (1998, 1080));
+               xmlpp::Document doc;
+               xmlpp::Element* el = doc.create_root_node ("Test");
+               pa->write_to_cpl (el, dcp::INTEROP);
+               
+               cxml::Node node (el);
+               BOOST_CHECK_EQUAL (node.node_child("MainPicture")->string_child ("ScreenAspectRatio"), "1.85");
+       }
+
+       {
+               pa->set_screen_aspect_ratio (dcp::Fraction (2048, 858));
+               xmlpp::Document doc;
+               xmlpp::Element* el = doc.create_root_node ("Test");
+               pa->write_to_cpl (el, dcp::INTEROP);
+               
+               cxml::Node node (el);
+               BOOST_CHECK_EQUAL (node.node_child("MainPicture")->string_child ("ScreenAspectRatio"), "2.39");
+       }
+}
index b1cb5265339c5dbb53c1df522869784cf1e11c06..030f0b58576b110dd0b7dd0094f2ae0cc9337ad3 100644 (file)
@@ -24,6 +24,7 @@
 #include "cpl.h"
 #include "argb_frame.h"
 #include "mono_picture_mxf.h"
+#include "reel_picture_asset.h"
 #include "reel.h"
 #include "test.h"
 
@@ -34,7 +35,7 @@ static shared_ptr<const dcp::ARGBFrame>
 get_frame (dcp::DCP const & dcp)
 {
        shared_ptr<const dcp::Reel> reel = dcp.cpls().front()->reels().front ();
-       shared_ptr<const dcp::PictureMXF> picture = reel->main_picture ();
+       shared_ptr<dcp::PictureMXF> picture = reel->main_picture()->mxf ();
        BOOST_CHECK (picture);
 
        shared_ptr<const dcp::MonoPictureMXF> mono_picture = dynamic_pointer_cast<const dcp::MonoPictureMXF> (picture);
@@ -62,7 +63,7 @@ BOOST_AUTO_TEST_CASE (decryption_test)
                "test/data/private.key"
                );
 
-       encrypted.add_kdm (kdm);
+       encrypted.add (kdm);
 
        shared_ptr<const dcp::ARGBFrame> plaintext_frame = get_frame (plaintext);
        shared_ptr<const dcp::ARGBFrame> encrypted_frame = get_frame (encrypted);
index 06df7058237ec22fdb2467fe528f4f115af08de8..a17b0a01dbcd138125c1aed77615bba99c2edd94 100644 (file)
@@ -33,8 +33,6 @@ BOOST_AUTO_TEST_CASE (read_dcp)
        list<shared_ptr<dcp::CPL> > cpls = d.cpls ();
        BOOST_CHECK_EQUAL (cpls.size(), 1);
 
-       BOOST_CHECK_EQUAL (cpls.front()->name(), "A Test DCP");
+       BOOST_CHECK_EQUAL (cpls.front()->annotation_text(), "A Test DCP");
        BOOST_CHECK_EQUAL (cpls.front()->content_kind(), dcp::FEATURE);
-       BOOST_CHECK_EQUAL (cpls.front()->frames_per_second(), 24);
-       BOOST_CHECK_EQUAL (cpls.front()->length(), 24);
 }
index b67c54f719134ad931fc6a57b8a1292eb1821ef4..1d51a711555fda23e65c4724a266e4de43e2d556 100644 (file)
@@ -48,9 +48,8 @@ BOOST_AUTO_TEST_CASE (recovery)
        
        boost::filesystem::remove_all ("build/test/baz");
        boost::filesystem::create_directories ("build/test/baz");
-       shared_ptr<dcp::MonoPictureMXF> mp (new dcp::MonoPictureMXF (24));
-       mp->set_size (dcp::Size (32, 32));
-       shared_ptr<dcp::PictureMXFWriter> writer = mp->start_write ("build/test/baz/video1.mxf", false);
+       shared_ptr<dcp::MonoPictureMXF> mp (new dcp::MonoPictureMXF (dcp::Fraction (24, 1)));
+       shared_ptr<dcp::PictureMXFWriter> writer = mp->start_write ("build/test/baz/video1.mxf", dcp::SMPTE, false);
 
        int written_size = 0;
        for (int i = 0; i < 24; ++i) {
@@ -77,9 +76,8 @@ BOOST_AUTO_TEST_CASE (recovery)
        Kumu::ResetTestRNG ();
 #endif 
 
-       mp.reset (new dcp::MonoPictureMXF (24));
-       mp->set_size (dcp::Size (32, 32));
-       writer = mp->start_write ("build/test/baz/video2.mxf", true);
+       mp.reset (new dcp::MonoPictureMXF (dcp::Fraction (24, 1)));
+       writer = mp->start_write ("build/test/baz/video2.mxf", dcp::SMPTE, true);
 
        writer->write (data, size);
 
index 5628ec70ecf8859fc0f5a8b0ab09964ff30e59f7..fdb41a2c30d524391f279bf1abd945a9f1d670ae 100644 (file)
@@ -1,8 +1,28 @@
+/*
+    Copyright (C) 2012-2014 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 <iostream>
 #include "dcp.h"
 #include "cpl.h"
 #include "reel.h"
-#include "subtitle_asset.h"
+#include "subtitle_content.h"
+#include "reel_subtitle_asset.h"
 #include "exceptions.h"
 
 using std::cout;
@@ -21,7 +41,7 @@ try
        }
 
        DCP* dcp = new DCP (argv[1]);
-       dcp->read (false);
+       dcp->read ();
        
        list<shared_ptr<CPL> > cpls = dcp->cpls ();
        for (list<boost::shared_ptr<CPL> >::iterator i = cpls.begin(); i != cpls.end(); ++i) {
@@ -30,7 +50,7 @@ try
                for (list<shared_ptr<Reel> >::iterator j = reels.begin(); j != reels.end(); ++j) {
 
                        if ((*j)->main_subtitle()) {
-                               (*j)->main_subtitle()->write_xml ();
+                               (*j)->main_subtitle()->subtitle_content()->write_xml ();
                        }
                }
        }
index 69bf63f90e3b57b62d4b7c2311d37696568f6e6b..8b1efbd77cef0e9354433733f2416beed88551b3 100644 (file)
@@ -30,6 +30,9 @@
 #include "mono_picture_frame.h"
 #include "argb_frame.h"
 #include "signer_chain.h"
+#include "mono_picture_mxf_writer.h"
+#include "reel_picture_asset.h"
+#include "file.h"
 
 using std::list;
 using boost::shared_ptr;
@@ -56,12 +59,9 @@ BOOST_AUTO_TEST_CASE (round_trip_test)
        boost::filesystem::path work_dir = "build/test/round_trip_test";
        boost::filesystem::create_directory (work_dir);
 
-       shared_ptr<dcp::MonoPictureMXF> asset_A (new dcp::MonoPictureMXF (work_dir, "video.mxf"));
-       asset_A->set_edit_rate (24);
-       shared_ptr<PictureMXFWriter> writer;
-       boost::filesystem::path mxf = work_dir + "video.mxf";
-       writer->start_write (mxf, false);
-       TestFile j2c ("test/data/32x32_red_square.j2c");
+       shared_ptr<dcp::MonoPictureMXF> mxf_A (new dcp::MonoPictureMXF (dcp::Fraction (24, 1)));
+       shared_ptr<dcp::PictureMXFWriter> writer = mxf_A->start_write (work_dir / "video.mxf", dcp::SMPTE, false);
+       dcp::File j2c ("test/data/32x32_red_square.j2c");
        for (int i = 0; i < 24; ++i) {
                writer->write (j2c.data (), j2c.size ());
        }
@@ -69,10 +69,12 @@ BOOST_AUTO_TEST_CASE (round_trip_test)
 
        dcp::Key key;
 
-       asset_A->set_key (key);
+       mxf_A->set_key (key);
 
-       shared_ptr<dcp::CPL> cpl (new dcp::CPL (work_dir, "A Test DCP", dcp::FEATURE, 24, 24));
-       cpl->add_reel (shared_ptr<dcp::Reel> (new dcp::Reel (asset_A, shared_ptr<dcp::SoundMXF> (), shared_ptr<dcp::SubtitleAsset> ())));
+       shared_ptr<dcp::CPL> cpl (new dcp::CPL ("A Test DCP", dcp::FEATURE));
+       shared_ptr<dcp::Reel> reel (new dcp::Reel ());
+       reel->add (shared_ptr<dcp::ReelPictureAsset> (mxf_A, 0));
+       cpl->add (reel);
 
        /* A KDM using our certificate chain's leaf key pair */
        dcp::KDM kdm_A (
@@ -105,14 +107,14 @@ BOOST_AUTO_TEST_CASE (round_trip_test)
        }
 
        /* Reload the picture MXF */
-       shared_ptr<dcp::MonoPictureMXF> asset_B (
-               new dcp::MonoPictureMXF (work_dir, "video.mxf")
+       shared_ptr<dcp::MonoPictureMXF> mxf_B (
+               new dcp::MonoPictureMXF (work_dir / "video.mxf")
                );
 
-       asset_B->set_key (kdm_B.keys().front().key());
+       mxf_B->set_key (kdm_B.keys().front().key());
 
-       shared_ptr<dcp::ARGBFrame> frame_A = asset_A->get_frame(0)->argb_frame ();
-       shared_ptr<dcp::ARGBFrame> frame_B = asset_B->get_frame(0)->argb_frame ();
+       shared_ptr<dcp::ARGBFrame> frame_A = mxf_A->get_frame(0)->argb_frame ();
+       shared_ptr<dcp::ARGBFrame> frame_B = mxf_B->get_frame(0)->argb_frame ();
        BOOST_CHECK_EQUAL (frame_A->size().width, frame_B->size().width);
        BOOST_CHECK_EQUAL (frame_A->size().height, frame_B->size().height);
        BOOST_CHECK_EQUAL (memcmp (frame_A->data(), frame_B->data(), frame_A->size().width * frame_A->size().height), 0);
index 40e5476c88f7e74a260d468947e82821d6d98ea2..9b2c2e9b9ad7b8e76b58f9055d6ee492eed1b906 100644 (file)
@@ -1,5 +1,5 @@
 #include <iostream>
-#include "subtitle_asset.h"
+#include "subtitle_content.h"
 
 using namespace std;
 
@@ -10,7 +10,7 @@ int main (int argc, char* argv[])
                exit (EXIT_FAILURE);
        }
        
-       dcp::SubtitleAsset s (argv[1]);
+       dcp::SubtitleContent s (argv[1]);
        cout << s.xml_as_string ();
        return 0;
 }
index b2b2d3632dae157edd5cf0155a1ef10685d8aae4..77dd29d7c571919a87082362da99a25df5404637 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2014 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
 
 */
 
+#include "subtitle_content.h"
+#include "subtitle_string.h"
 #include <boost/test/unit_test.hpp>
-#include "subtitle_asset.h"
 
 using std::list;
 using boost::shared_ptr;
 
-/* Load a subtitle asset from XML and check that it is read correctly */
+/* Load some subtitle content from XML and check that it is read correctly */
 BOOST_AUTO_TEST_CASE (subtitles1)
 {
-       dcp::SubtitleAsset subs ("test/data/subs1.xml");
+       dcp::SubtitleContent subs ("test/data/subs1.xml");
 
        BOOST_CHECK_EQUAL (subs.language(), "French");
 
-       list<shared_ptr<dcp::Subtitle> > s = subs.subtitles_at (dcp::Time (0, 0, 6, 1));
+       list<shared_ptr<dcp::SubtitleString> > s = subs.subtitles_at (dcp::Time (0, 0, 6, 1));
        BOOST_CHECK_EQUAL (s.size(), 1);
-       BOOST_CHECK_EQUAL (*(s.front().get()), dcp::Subtitle (
+       BOOST_CHECK_EQUAL (*(s.front().get()), dcp::SubtitleString (
                                   "Arial",
                                   false,
                                   dcp::Color (255, 255, 255),
@@ -50,7 +51,7 @@ BOOST_AUTO_TEST_CASE (subtitles1)
                                                         
        s = subs.subtitles_at (dcp::Time (0, 0, 7, 190));
        BOOST_CHECK_EQUAL (s.size(), 2);
-       BOOST_CHECK_EQUAL (*(s.front().get()), dcp::Subtitle (
+       BOOST_CHECK_EQUAL (*(s.front().get()), dcp::SubtitleString (
                                   "Arial",
                                   true,
                                   dcp::Color (255, 255, 255),
@@ -65,7 +66,7 @@ BOOST_AUTO_TEST_CASE (subtitles1)
                                   dcp::Time (0, 0, 0, 1),
                                   dcp::Time (0, 0, 0, 1)
                                   ));
-       BOOST_CHECK_EQUAL (*(s.back().get()), dcp::Subtitle (
+       BOOST_CHECK_EQUAL (*(s.back().get()), dcp::SubtitleString (
                                   "Arial",
                                   false,
                                   dcp::Color (255, 255, 255),
@@ -83,7 +84,7 @@ BOOST_AUTO_TEST_CASE (subtitles1)
 
        s = subs.subtitles_at (dcp::Time (0, 0, 11, 95));
        BOOST_CHECK_EQUAL (s.size(), 1);
-       BOOST_CHECK_EQUAL (*(s.back().get()), dcp::Subtitle (
+       BOOST_CHECK_EQUAL (*(s.back().get()), dcp::SubtitleString (
                                   "Arial",
                                   false,
                                   dcp::Color (255, 255, 255),
@@ -101,7 +102,7 @@ BOOST_AUTO_TEST_CASE (subtitles1)
 
        s = subs.subtitles_at (dcp::Time (0, 0, 14, 42));
        BOOST_CHECK_EQUAL (s.size(), 1);
-       BOOST_CHECK_EQUAL (*(s.back().get()), dcp::Subtitle (
+       BOOST_CHECK_EQUAL (*(s.back().get()), dcp::SubtitleString (
                                   "Arial",
                                   false,
                                   dcp::Color (255, 255, 255),
@@ -121,11 +122,11 @@ BOOST_AUTO_TEST_CASE (subtitles1)
 /** And similarly for another one */
 BOOST_AUTO_TEST_CASE (subtitles2)
 {
-       dcp::SubtitleAsset subs ("test/data/subs2.xml");
+       dcp::SubtitleContent subs ("test/data/subs2.xml");
 
-       list<shared_ptr<dcp::Subtitle> > s = subs.subtitles_at (dcp::Time (0, 0, 42, 100));
+       list<shared_ptr<dcp::SubtitleString> > s = subs.subtitles_at (dcp::Time (0, 0, 42, 100));
        BOOST_CHECK_EQUAL (s.size(), 2);
-       BOOST_CHECK_EQUAL (*(s.front().get()), dcp::Subtitle (
+       BOOST_CHECK_EQUAL (*(s.front().get()), dcp::SubtitleString (
                                   "Arial",
                                   true,
                                   dcp::Color (255, 255, 255),
@@ -140,7 +141,7 @@ BOOST_AUTO_TEST_CASE (subtitles2)
                                   dcp::Time (0, 0, 0, 0),
                                   dcp::Time (0, 0, 0, 0)
                                   ));
-       BOOST_CHECK_EQUAL (*(s.back().get()), dcp::Subtitle (
+       BOOST_CHECK_EQUAL (*(s.back().get()), dcp::SubtitleString (
                                   "Arial",
                                   true,
                                   dcp::Color (255, 255, 255),
@@ -158,7 +159,7 @@ BOOST_AUTO_TEST_CASE (subtitles2)
 
        s = subs.subtitles_at (dcp::Time (0, 0, 50, 50));
        BOOST_CHECK_EQUAL (s.size(), 2);
-       BOOST_CHECK_EQUAL (*(s.front().get()), dcp::Subtitle (
+       BOOST_CHECK_EQUAL (*(s.front().get()), dcp::SubtitleString (
                                   "Arial",
                                   true,
                                   dcp::Color (255, 255, 255),
@@ -173,7 +174,7 @@ BOOST_AUTO_TEST_CASE (subtitles2)
                                   dcp::Time (0, 0, 0, 0),
                                   dcp::Time (0, 0, 0, 0)
                                   ));
-       BOOST_CHECK_EQUAL (*(s.back().get()), dcp::Subtitle (
+       BOOST_CHECK_EQUAL (*(s.back().get()), dcp::SubtitleString (
                                   "Arial",
                                   true,
                                   dcp::Color (255, 255, 255),
@@ -191,7 +192,7 @@ BOOST_AUTO_TEST_CASE (subtitles2)
 
        s = subs.subtitles_at (dcp::Time (0, 1, 2, 300));
        BOOST_CHECK_EQUAL (s.size(), 2);
-       BOOST_CHECK_EQUAL (*(s.front().get()), dcp::Subtitle (
+       BOOST_CHECK_EQUAL (*(s.front().get()), dcp::SubtitleString (
                                   "Arial",
                                   true,
                                   dcp::Color (255, 255, 255),
@@ -206,7 +207,7 @@ BOOST_AUTO_TEST_CASE (subtitles2)
                                   dcp::Time (0, 0, 0, 0),
                                   dcp::Time (0, 0, 0, 0)
                                   ));
-       BOOST_CHECK_EQUAL (*(s.back().get()), dcp::Subtitle (
+       BOOST_CHECK_EQUAL (*(s.back().get()), dcp::SubtitleString (
                                   "Arial",
                                   true,
                                   dcp::Color (255, 255, 255),
@@ -224,7 +225,7 @@ BOOST_AUTO_TEST_CASE (subtitles2)
 
        s = subs.subtitles_at (dcp::Time (0, 1, 15, 50));
        BOOST_CHECK_EQUAL (s.size(), 2);
-       BOOST_CHECK_EQUAL (*(s.front().get()), dcp::Subtitle (
+       BOOST_CHECK_EQUAL (*(s.front().get()), dcp::SubtitleString (
                                   "Arial",
                                   true,
                                   dcp::Color (255, 255, 255),
@@ -239,7 +240,7 @@ BOOST_AUTO_TEST_CASE (subtitles2)
                                   dcp::Time (0, 0, 0, 0),
                                   dcp::Time (0, 0, 0, 0)
                                   ));
-       BOOST_CHECK_EQUAL (*(s.back().get()), dcp::Subtitle (
+       BOOST_CHECK_EQUAL (*(s.back().get()), dcp::SubtitleString (
                                   "Arial",
                                   true,
                                   dcp::Color (255, 255, 255),
@@ -257,7 +258,7 @@ BOOST_AUTO_TEST_CASE (subtitles2)
 
        s = subs.subtitles_at (dcp::Time (0, 1, 27, 200));
        BOOST_CHECK_EQUAL (s.size(), 2);
-       BOOST_CHECK_EQUAL (*(s.front().get()), dcp::Subtitle (
+       BOOST_CHECK_EQUAL (*(s.front().get()), dcp::SubtitleString (
                                   "Arial",
                                   true,
                                   dcp::Color (255, 255, 255),
@@ -272,7 +273,7 @@ BOOST_AUTO_TEST_CASE (subtitles2)
                                   dcp::Time (0, 0, 0, 0),
                                   dcp::Time (0, 0, 0, 0)
                                   ));
-       BOOST_CHECK_EQUAL (*(s.back().get()), dcp::Subtitle (
+       BOOST_CHECK_EQUAL (*(s.back().get()), dcp::SubtitleString (
                                   "Arial",
                                   true,
                                   dcp::Color (255, 255, 255),
@@ -290,7 +291,7 @@ BOOST_AUTO_TEST_CASE (subtitles2)
 
        s = subs.subtitles_at (dcp::Time (0, 1, 42, 300));
        BOOST_CHECK_EQUAL (s.size(), 2);
-       BOOST_CHECK_EQUAL (*(s.front().get()), dcp::Subtitle (
+       BOOST_CHECK_EQUAL (*(s.front().get()), dcp::SubtitleString (
                                   "Arial",
                                   false,
                                   dcp::Color (255, 255, 255),
@@ -305,7 +306,7 @@ BOOST_AUTO_TEST_CASE (subtitles2)
                                   dcp::Time (0, 0, 0, 0),
                                   dcp::Time (0, 0, 0, 0)
                                   ));
-       BOOST_CHECK_EQUAL (*(s.back().get()), dcp::Subtitle (
+       BOOST_CHECK_EQUAL (*(s.back().get()), dcp::SubtitleString (
                                   "Arial",
                                   false,
                                   dcp::Color (255, 255, 255),
@@ -323,7 +324,7 @@ BOOST_AUTO_TEST_CASE (subtitles2)
 
        s = subs.subtitles_at (dcp::Time (0, 1, 45, 200));
        BOOST_CHECK_EQUAL (s.size(), 2);
-       BOOST_CHECK_EQUAL (*(s.front().get()), dcp::Subtitle (
+       BOOST_CHECK_EQUAL (*(s.front().get()), dcp::SubtitleString (
                                   "Arial",
                                   false,
                                   dcp::Color (255, 255, 255),
@@ -338,7 +339,7 @@ BOOST_AUTO_TEST_CASE (subtitles2)
                                   dcp::Time (0, 0, 0, 0),
                                   dcp::Time (0, 0, 0, 0)
                                   ));
-       BOOST_CHECK_EQUAL (*(s.back().get()), dcp::Subtitle (
+       BOOST_CHECK_EQUAL (*(s.back().get()), dcp::SubtitleString (
                                   "Arial",
                                   false,
                                   dcp::Color (255, 255, 255),
@@ -356,7 +357,7 @@ BOOST_AUTO_TEST_CASE (subtitles2)
 
        s = subs.subtitles_at (dcp::Time (0, 1, 47, 249));
        BOOST_CHECK_EQUAL (s.size(), 2);
-       BOOST_CHECK_EQUAL (*(s.front().get()), dcp::Subtitle (
+       BOOST_CHECK_EQUAL (*(s.front().get()), dcp::SubtitleString (
                                   "Arial",
                                   false,
                                   dcp::Color (255, 255, 255),
@@ -371,7 +372,7 @@ BOOST_AUTO_TEST_CASE (subtitles2)
                                   dcp::Time (0, 0, 0, 0),
                                   dcp::Time (0, 0, 0, 0)
                                   ));
-       BOOST_CHECK_EQUAL (*(s.back().get()), dcp::Subtitle (
+       BOOST_CHECK_EQUAL (*(s.back().get()), dcp::SubtitleString (
                                   "Arial",
                                   false,
                                   dcp::Color (255, 255, 255),
@@ -389,7 +390,7 @@ BOOST_AUTO_TEST_CASE (subtitles2)
 
        s = subs.subtitles_at (dcp::Time (0, 2, 6, 210));
        BOOST_CHECK_EQUAL (s.size(), 2);
-       BOOST_CHECK_EQUAL (*(s.front().get()), dcp::Subtitle (
+       BOOST_CHECK_EQUAL (*(s.front().get()), dcp::SubtitleString (
                                   "Arial",
                                   true,
                                   dcp::Color (255, 255, 255),
@@ -404,7 +405,7 @@ BOOST_AUTO_TEST_CASE (subtitles2)
                                   dcp::Time (0, 0, 0, 0),
                                   dcp::Time (0, 0, 0, 0)
                                   ));
-       BOOST_CHECK_EQUAL (*(s.back().get()), dcp::Subtitle (
+       BOOST_CHECK_EQUAL (*(s.back().get()), dcp::SubtitleString (
                                   "Arial",
                                   true,
                                   dcp::Color (255, 255, 255),
index ff018cd59e1097f04267d06508938e73662adf5f..f30a9db8470a09301ef7cd4ff2d1158765239d86 100644 (file)
@@ -49,17 +49,3 @@ wav (dcp::Channel)
 
 string test_corpus = "../libdcp-test";
 
-TestFile::TestFile (boost::filesystem::path file)
-{
-       _size = boost::filesystem::file_size (file);
-       _data = new uint8_t[_size];
-       FILE* f = dcp::fopen_boost (file, "r");
-       assert (f);
-       fread (_data, 1, _size, f);
-       fclose (f);
-}
-
-TestFile::~TestFile ()
-{
-       delete[] _data;
-}
index 31b4bf0ab6122b270567ac756509820a5767142d..bc6baccdd43d1be6eba6112979aefae5f53e4c4c 100644 (file)
 */
 
 extern std::string test_corpus;
-
-class TestFile
-{
-public:
-       TestFile (boost::filesystem::path file);
-       ~TestFile ();
-       
-       uint8_t* data () const {
-               return _data;
-       }
-
-       int64_t size () const {
-               return _size;
-       }
-
-private:
-       uint8_t* _data;
-       int64_t _size;
-};
index b2b1b038aeec4f9c06433d77756a93a64b9c6b2f..0cc0e20217b58a56102dd2273eeb795466424765 100644 (file)
@@ -25,7 +25,7 @@ def build(bld):
     obj.source = """
                  certificates_test.cc
                  color_test.cc
-                 cpl_sar.cc
+                 cpl_sar_test.cc
                  dcp_time_test.cc
                  decryption_test.cc
                  frame_info_test.cc
index 70c94d8e32effcb1f4fa8512763e20235e5594b3..b76993bfd2487b19e0cae5e8e54e43eebbd70493 100644 (file)
@@ -1,3 +1,22 @@
+/*
+    Copyright (C) 2012-2014 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 <iostream>
 #include <cstdlib>
 #include <boost/filesystem.hpp>
@@ -7,7 +26,11 @@
 #include "reel.h"
 #include "sound_mxf.h"
 #include "picture_mxf.h"
-#include "subtitle_asset.h"
+#include "subtitle_content.h"
+#include "reel_picture_asset.h"
+#include "reel_sound_asset.h"
+#include "reel_subtitle_asset.h"
+#include "subtitle_string.h"
 #include "cpl.h"
 
 using std::string;
@@ -70,7 +93,7 @@ main (int argc, char* argv[])
        DCP* dcp = 0;
        try {
                dcp = new DCP (argv[optind]);
-               dcp->read (false);
+               dcp->read ();
        } catch (FileError& e) {
                cerr << "Could not read DCP " << argv[optind] << "; " << e.what() << " " << e.filename() << "\n";
                exit (EXIT_FAILURE);
@@ -81,9 +104,7 @@ main (int argc, char* argv[])
        list<shared_ptr<CPL> > cpls = dcp->cpls ();
 
        for (list<shared_ptr<CPL> >::iterator i = cpls.begin(); i != cpls.end(); ++i) {
-               cout << "  CPL: " << (*i)->name() << "\n"
-                    << "    Length: " << (*i)->length() << "\n"
-                    << "    Frames per second: " << (*i)->frames_per_second() << "\n";
+               cout << "  CPL: " << (*i)->annotation_text() << "\n";
                
                list<shared_ptr<Reel> > reels = (*i)->reels ();
 
@@ -92,16 +113,22 @@ main (int argc, char* argv[])
                        cout << "    Reel " << R << "\n";
                        
                        if ((*j)->main_picture()) {
-                               cout << "      Picture:  " << (*j)->main_picture()->size().width << "x" << (*j)->main_picture()->size().height << "\n";
+                               cout << "      Picture:  "
+                                    << (*j)->main_picture()->mxf()->size().width
+                                    << "x"
+                                    << (*j)->main_picture()->mxf()->size().height << "\n";
                        }
                        if ((*j)->main_sound()) {
-                               cout << "      Sound:    " << (*j)->main_sound()->channels() << " channels at " << (*j)->main_sound()->sampling_rate() << "Hz\n";
+                               cout << "      Sound:    "
+                                    << (*j)->main_sound()->mxf()->channels()
+                                    << " channels at "
+                                    << (*j)->main_sound()->mxf()->sampling_rate() << "Hz\n";
                        }
                        if ((*j)->main_subtitle()) {
-                               list<shared_ptr<Subtitle> > subs = (*j)->main_subtitle()->subtitles ();
-                               cout << "      Subtitle: " << subs.size() << " subtitles in " << (*j)->main_subtitle()->language() << "\n";
+                               list<shared_ptr<SubtitleString> > subs = (*j)->main_subtitle()->subtitle_content()->subtitles ();
+                               cout << "      Subtitle: " << subs.size() << " subtitles in " << (*j)->main_subtitle()->subtitle_content()->language() << "\n";
                                if (subtitles) {
-                                       for (list<shared_ptr<Subtitle> >::const_iterator k = subs.begin(); k != subs.end(); ++k) {
+                                       for (list<shared_ptr<SubtitleString> >::const_iterator k = subs.begin(); k != subs.end(); ++k) {
                                                cout << "        " << (*k)->text() << "\n";
                                                cout << "          "
                                                     << "font:" << (*k)->font() << "; "