Add Subtitle::set_text()
[libdcp.git] / src / cpl.cc
index 4c4d2e756adaea268c197f65ef167752d3f85195..6fc52be536d4499ec372f56c806c7e63ee43eb30 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 <fstream>
 #include <libxml/parser.h>
 #include "cpl.h"
 #include "parse/cpl.h"
 #include "util.h"
-#include "picture_asset.h"
+#include "mono_picture_asset.h"
+#include "stereo_picture_asset.h"
 #include "sound_asset.h"
 #include "subtitle_asset.h"
 #include "parse/asset_map.h"
 #include "signer.h"
 #include "exceptions.h"
 #include "compose.hpp"
+#include "raw_convert.h"
 
 using std::string;
 using std::stringstream;
-using std::ofstream;
 using std::ostream;
 using std::list;
 using std::pair;
@@ -71,7 +71,7 @@ CPL::CPL (boost::filesystem::path directory, string file, list<PathAssetMap> ass
        try {
                cpl.reset (new parse::CPL (file));
        } catch (FileError& e) {
-               boost::throw_exception (FileError ("could not load CPL file", file));
+               boost::throw_exception (FileError ("could not load CPL file", file, e.number ()));
        }
        
        /* Now cherry-pick the required bits into our own data structure */
@@ -107,15 +107,13 @@ CPL::CPL (boost::filesystem::path directory, string file, list<PathAssetMap> ass
 
                if (!(*i)->asset_list->main_stereoscopic_picture && p->edit_rate == p->frame_rate) {
 
-                       pair<string, shared_ptr<const parse::AssetMapAsset> > asset = asset_from_id (asset_maps, p->id);
-
                        try {
-                               picture.reset (new MonoPictureAsset (
-                                                      asset.first,
-                                                      asset.second->chunks.front()->path
-                                                      )
-                                       );
+                               pair<string, shared_ptr<const parse::AssetMapAsset> > asset = asset_from_id (asset_maps, p->id);
 
+                               picture.reset (new MonoPictureAsset (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) {
@@ -132,14 +130,10 @@ CPL::CPL (boost::filesystem::path directory, string file, list<PathAssetMap> ass
                        try {
                                pair<string, shared_ptr<const parse::AssetMapAsset> > asset = asset_from_id (asset_maps, p->id);
 
-                               picture.reset (new StereoPictureAsset (
-                                                      asset.first,
-                                                      asset.second->chunks.front()->path,
-                                                      _fps,
-                                                      p->duration
-                                                      )
-                                       );
+                               picture.reset (new StereoPictureAsset (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) {
@@ -160,14 +154,10 @@ CPL::CPL (boost::filesystem::path directory, string file, list<PathAssetMap> ass
                        try {
                                pair<string, shared_ptr<const parse::AssetMapAsset> > asset = asset_from_id (asset_maps, (*i)->asset_list->main_sound->id);
                        
-                               sound.reset (new SoundAsset (
-                                                    asset.first,
-                                                    asset.second->chunks.front()->path
-                                                    )
-                                       );
-
+                               sound.reset (new SoundAsset (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) {
@@ -185,13 +175,10 @@ CPL::CPL (boost::filesystem::path directory, string file, list<PathAssetMap> ass
                        
                        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.reset (new SubtitleAsset (asset.first, asset.second->chunks.front()->path));
 
                        subtitle->set_entry_point ((*i)->asset_list->main_subtitle->entry_point);
+                       subtitle->set_edit_rate (_fps);
                        subtitle->set_duration ((*i)->asset_list->main_subtitle->duration);
                }
                        
@@ -205,14 +192,16 @@ CPL::add_reel (shared_ptr<Reel> reel)
        _reels.push_back (reel);
 }
 
+boost::filesystem::path
+CPL::filename () const
+{
+       return _directory / String::compose ("%1_cpl.xml", _id);
+}
+
 void
 CPL::write_xml (bool interop, XMLMetadata const & metadata, shared_ptr<const Signer> signer) const
 {
-       boost::filesystem::path p;
-       p /= _directory;
-       stringstream s;
-       s << _id << "_cpl.xml";
-       p /= s.str();
+       boost::filesystem::path p = filename ();
 
        xmlpp::Document doc;
        xmlpp::Element* root;
@@ -243,27 +232,32 @@ CPL::write_xml (bool interop, XMLMetadata const & metadata, shared_ptr<const Sig
        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, interop);
+               (*i)->write_to_cpl (reel_list);
        }
 
        if (signer) {
                signer->sign (root, interop);
        }
 
-       doc.write_to_file_formatted (p.string (), "UTF-8");
+       /* 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 ());
 }
 
 void
-CPL::write_to_pkl (xmlpp::Node* node) const
+CPL::write_to_pkl (xmlpp::Node* node, bool interop) 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");
+       asset->add_child("Size")->add_child_text (raw_convert<string> (_length));
+       if (interop) {
+               asset->add_child("Type")->add_child_text ("text/xml;asdcpKind=CPL");
+       } else {
+               asset->add_child("Type")->add_child_text ("text/xml");
+       }
 }
 
 list<shared_ptr<const Asset> >
@@ -295,7 +289,7 @@ CPL::write_to_assetmap (xmlpp::Node* node) const
        chunk->add_child("Path")->add_child_text (_id + "_cpl.xml");
        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> (_length));
+       chunk->add_child("Length")->add_child_text (raw_convert<string> (_length));
 }
        
        
@@ -377,3 +371,11 @@ CPL::asset_from_id (list<PathAssetMap> asset_maps, string id) const
 
        return make_pair ("", shared_ptr<const parse::AssetMapAsset> ());
 }
+
+void
+CPL::set_mxf_keys (Key key)
+{
+       for (list<shared_ptr<Reel> >::const_iterator i = _reels.begin(); i != _reels.end(); ++i) {
+               (*i)->set_mxf_keys (key);
+       }
+}