diff options
| -rw-r--r-- | src/asset.cc | 37 | ||||
| -rw-r--r-- | src/asset.h | 7 | ||||
| -rw-r--r-- | src/cpl.cc | 75 | ||||
| -rw-r--r-- | src/cpl.h | 5 | ||||
| -rw-r--r-- | src/dcp.cc | 92 | ||||
| -rw-r--r-- | src/picture_asset.cc | 21 | ||||
| -rw-r--r-- | src/picture_asset.h | 6 | ||||
| -rw-r--r-- | src/reel.cc | 17 | ||||
| -rw-r--r-- | src/reel.h | 3 | ||||
| -rw-r--r-- | src/sound_asset.cc | 17 | ||||
| -rw-r--r-- | src/sound_asset.h | 6 | ||||
| -rw-r--r-- | src/subtitle_asset.cc | 121 | ||||
| -rw-r--r-- | src/subtitle_asset.h | 5 |
13 files changed, 192 insertions, 220 deletions
diff --git a/src/asset.cc b/src/asset.cc index 58c821a7..84bdd2bd 100644 --- a/src/asset.cc +++ b/src/asset.cc @@ -25,6 +25,7 @@ #include <fstream> #include <boost/filesystem.hpp> #include <boost/function.hpp> +#include <boost/lexical_cast.hpp> #include "AS_DCP.h" #include "KM_util.h" #include "asset.h" @@ -50,31 +51,27 @@ Asset::Asset (string directory, string file_name, int edit_rate, int intrinsic_d } void -Asset::write_to_pkl (ostream& s) const +Asset::write_to_pkl (xmlpp::Node* node) const { - s << " <Asset>\n" - << " <Id>urn:uuid:" << _uuid << "</Id>\n" - << " <AnnotationText>" << _file_name << "</AnnotationText>\n" - << " <Hash>" << digest() << "</Hash>\n" - << " <Size>" << filesystem::file_size(path()) << "</Size>\n" - << " <Type>application/mxf</Type>\n" - << " </Asset>\n"; + xmlpp::Node* asset = node->add_child ("Asset"); + asset->add_child("Id")->add_child_text ("urn:uuid:" + _uuid); + asset->add_child("AnnotationText")->add_child_text (_file_name); + asset->add_child("Hash")->add_child_text (digest ()); + asset->add_child("Size")->add_child_text (lexical_cast<string> (filesystem::file_size(path()))); + asset->add_child("Type")->add_child_text ("application/mxf"); } void -Asset::write_to_assetmap (ostream& s) const +Asset::write_to_assetmap (xmlpp::Node* node) const { - s << " <Asset>\n" - << " <Id>urn:uuid:" << _uuid << "</Id>\n" - << " <ChunkList>\n" - << " <Chunk>\n" - << " <Path>" << _file_name << "</Path>\n" - << " <VolumeIndex>1</VolumeIndex>\n" - << " <Offset>0</Offset>\n" - << " <Length>" << filesystem::file_size(path()) << "</Length>\n" - << " </Chunk>\n" - << " </ChunkList>\n" - << " </Asset>\n"; + xmlpp::Node* asset = node->add_child ("Asset"); + asset->add_child("Id")->add_child_text ("urn:uuid:" + _uuid); + xmlpp::Node* chunk_list = asset->add_child ("ChunkList"); + xmlpp::Node* chunk = chunk_list->add_child ("Chunk"); + chunk->add_child("Path")->add_child_text (_file_name); + 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(path()))); } filesystem::path diff --git a/src/asset.h b/src/asset.h index 06c66356..3bc713a3 100644 --- a/src/asset.h +++ b/src/asset.h @@ -28,6 +28,7 @@ #include <list> #include <boost/filesystem.hpp> #include <boost/function.hpp> +#include <libxml++/libxml++.h> #include "types.h" namespace ASDCP { @@ -55,17 +56,17 @@ public: /** Write details of the asset to a CPL stream. * @param s Stream. */ - virtual void write_to_cpl (std::ostream& s) const = 0; + virtual void write_to_cpl (xmlpp::Node *) const = 0; /** Write details of the asset to a PKL stream. * @param s Stream. */ - void write_to_pkl (std::ostream& s) const; + void write_to_pkl (xmlpp::Node *) const; /** Write details of the asset to a ASSETMAP stream. * @param s Stream. */ - void write_to_assetmap (std::ostream& s) const; + void write_to_assetmap (xmlpp::Node *) const; std::string uuid () const { return _uuid; @@ -34,6 +34,7 @@ using std::ofstream; using std::ostream; using std::list; using boost::shared_ptr; +using boost::lexical_cast; using namespace libdcp; CPL::CPL (string directory, string name, ContentKind content_kind, int length, int frames_per_second) @@ -180,45 +181,42 @@ CPL::write_xml (XMLMetadata const & metadata) const stringstream s; s << _uuid << "_cpl.xml"; p /= s.str(); - ofstream os (p.string().c_str()); - - os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" - << "<CompositionPlaylist xmlns=\"http://www.smpte-ra.org/schemas/429-7/2006/CPL\">\n" - << " <Id>urn:uuid:" << _uuid << "</Id>\n" - << " <AnnotationText>" << _name << "</AnnotationText>\n" - << " <IssueDate>" << metadata.issue_date << "</IssueDate>\n" - << " <Creator>" << metadata.creator << "</Creator>\n" - << " <ContentTitleText>" << _name << "</ContentTitleText>\n" - << " <ContentKind>" << content_kind_to_string (_content_kind) << "</ContentKind>\n" - << " <ContentVersion>\n" - << " <Id>urn:uri:" << _uuid << "_" << metadata.issue_date << "</Id>\n" - << " <LabelText>" << _uuid << "_" << metadata.issue_date << "</LabelText>\n" - << " </ContentVersion>\n" - << " <RatingList/>\n" - << " <ReelList>\n"; + + xmlpp::Document doc; + xmlpp::Element* root = doc.create_root_node ("CompositionPlaylist", "http://www.smpte-ra.org/schemas/429-7/2006/CPL"); + root->add_child("Id")->add_child_text ("urn:uuid:" + _uuid); + root->add_child("AnnotationText")->add_child_text (_name); + root->add_child("IssueDate")->add_child_text (metadata.issue_date); + root->add_child("Creator")->add_child_text (metadata.creator); + root->add_child("ContentTitleText")->add_child_text (_name); + 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:" + _uuid + "_" + metadata.issue_date); + cv->add_child ("LabelText")->add_child_text (_uuid + "_" + metadata.issue_date); + } + root->add_child("RatingList"); + + xmlpp::Node* reel_list = root->add_child ("ReelList"); for (list<shared_ptr<const Reel> >::const_iterator i = _reels.begin(); i != _reels.end(); ++i) { - (*i)->write_to_cpl (os); + (*i)->write_to_cpl (reel_list); } - os << " </ReelList>\n" - << "</CompositionPlaylist>\n"; - - os.close (); + doc.write_to_file_formatted (p.string (), "UTF-8"); _digest = make_digest (p.string ()); _length = boost::filesystem::file_size (p.string ()); } void -CPL::write_to_pkl (ostream& s) const +CPL::write_to_pkl (xmlpp::Node* node) const { - s << " <Asset>\n" - << " <Id>urn:uuid:" << _uuid << "</Id>\n" - << " <Hash>" << _digest << "</Hash>\n" - << " <Size>" << _length << "</Size>\n" - << " <Type>text/xml</Type>\n" - << " </Asset>\n"; + xmlpp::Node* asset = node->add_child ("Asset"); + asset->add_child("Id")->add_child_text ("urn:uuid:" + _uuid); + 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"); } list<shared_ptr<const Asset> > @@ -241,19 +239,16 @@ CPL::assets () const } void -CPL::write_to_assetmap (ostream& s) const +CPL::write_to_assetmap (xmlpp::Node* node) const { - s << " <Asset>\n" - << " <Id>urn:uuid:" << _uuid << "</Id>\n" - << " <ChunkList>\n" - << " <Chunk>\n" - << " <Path>" << _uuid << "_cpl.xml</Path>\n" - << " <VolumeIndex>1</VolumeIndex>\n" - << " <Offset>0</Offset>\n" - << " <Length>" << _length << "</Length>\n" - << " </Chunk>\n" - << " </ChunkList>\n" - << " </Asset>\n"; + xmlpp::Node* asset = node->add_child ("Asset"); + asset->add_child("Id")->add_child_text ("urn:uuid:" + _uuid); + xmlpp::Node* chunk_list = asset->add_child ("ChunkList"); + xmlpp::Node* chunk = chunk_list->add_child ("Chunk"); + chunk->add_child("Path")->add_child_text (_uuid + "_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)); } @@ -20,6 +20,7 @@ #include <list> #include <boost/shared_ptr.hpp> #include <boost/function.hpp> +#include <libxml++/libxml++.h> #include "types.h" namespace libdcp { @@ -74,8 +75,8 @@ public: bool equals (CPL const & other, EqualityOptions options, boost::function<void (NoteType, std::string)> note) const; void write_xml (XMLMetadata const &) const; - void write_to_assetmap (std::ostream& s) const; - void write_to_pkl (std::ostream& s) const; + void write_to_assetmap (xmlpp::Node *) const; + void write_to_pkl (xmlpp::Node *) const; private: std::string _directory; @@ -28,6 +28,7 @@ #include <iostream> #include <boost/filesystem.hpp> #include <boost/algorithm/string.hpp> +#include <boost/lexical_cast.hpp> #include <libxml++/libxml++.h> #include "dcp.h" #include "asset.h" @@ -48,6 +49,7 @@ using std::stringstream; using std::ofstream; using std::ostream; using boost::shared_ptr; +using boost::lexical_cast; using namespace libdcp; DCP::DCP (string directory) @@ -80,30 +82,29 @@ DCP::write_pkl (string pkl_uuid, XMLMetadata const & metadata) const stringstream s; s << pkl_uuid << "_pkl.xml"; p /= s.str(); - ofstream pkl (p.string().c_str()); - - pkl << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" - << "<PackingList xmlns=\"http://www.smpte-ra.org/schemas/429-8/2007/PKL\">\n" - << " <Id>urn:uuid:" << pkl_uuid << "</Id>\n" - /* XXX: this is a bit of a hack */ - << " <AnnotationText>" << _cpls.front()->name() << "</AnnotationText>\n" - << " <IssueDate>" << metadata.issue_date << "</IssueDate>\n" - << " <Issuer>" << metadata.issuer << "</Issuer>\n" - << " <Creator>" << metadata.creator << "</Creator>\n" - << " <AssetList>\n"; + + xmlpp::Document doc; + xmlpp::Element* root = doc.create_root_node ("PackingList", "http://www.smpte-ra.org/schemas/429-8/2007/PKL"); + + root->add_child("Id")->add_child_text ("urn:uuid:" + pkl_uuid); + /* XXX: this is a bit of a hack */ + root->add_child("AnnotationText")->add_child_text (_cpls.front()->name()); + 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); + + xmlpp::Node* asset_list = root->add_child ("AssetList"); list<shared_ptr<const Asset> > a = assets (); for (list<shared_ptr<const Asset> >::const_iterator i = a.begin(); i != a.end(); ++i) { - (*i)->write_to_pkl (pkl); + (*i)->write_to_pkl (asset_list); } for (list<shared_ptr<const CPL> >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) { - (*i)->write_to_pkl (pkl); + (*i)->write_to_pkl (asset_list); } - pkl << " </AssetList>\n" - << "</PackingList>\n"; - + doc.write_to_file_formatted (p.string (), "UTF-8"); return p.string (); } @@ -113,12 +114,11 @@ DCP::write_volindex () const boost::filesystem::path p; p /= _directory; p /= "VOLINDEX.xml"; - ofstream vi (p.string().c_str()); - vi << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" - << "<VolumeIndex xmlns=\"http://www.smpte-ra.org/schemas/429-9/2007/AM\">\n" - << " <Index>1</Index>\n" - << "</VolumeIndex>\n"; + xmlpp::Document doc; + xmlpp::Element* root = doc.create_root_node ("VolumeIndex", "http://www.smpte-ra.org/schemas/429-9/2007/AM"); + root->add_child("Index")->add_child_text ("1"); + doc.write_to_file_formatted (p.string (), "UTF-8"); } void @@ -127,41 +127,37 @@ DCP::write_assetmap (string pkl_uuid, int pkl_length, XMLMetadata const & metada boost::filesystem::path p; p /= _directory; p /= "ASSETMAP.xml"; - ofstream am (p.string().c_str()); - - am << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" - << "<AssetMap xmlns=\"http://www.smpte-ra.org/schemas/429-9/2007/AM\">\n" - << " <Id>urn:uuid:" << make_uuid() << "</Id>\n" - << " <Creator>" << metadata.creator << "</Creator>\n" - << " <VolumeCount>1</VolumeCount>\n" - << " <IssueDate>" << metadata.issue_date << "</IssueDate>\n" - << " <Issuer>" << metadata.issuer << "</Issuer>\n" - << " <AssetList>\n"; - - am << " <Asset>\n" - << " <Id>urn:uuid:" << pkl_uuid << "</Id>\n" - << " <PackingList>true</PackingList>\n" - << " <ChunkList>\n" - << " <Chunk>\n" - << " <Path>" << pkl_uuid << "_pkl.xml</Path>\n" - << " <VolumeIndex>1</VolumeIndex>\n" - << " <Offset>0</Offset>\n" - << " <Length>" << pkl_length << "</Length>\n" - << " </Chunk>\n" - << " </ChunkList>\n" - << " </Asset>\n"; + + xmlpp::Document doc; + xmlpp::Element* root = doc.create_root_node ("AssetMap", "http://www.smpte-ra.org/schemas/429-9/2007/AM"); + + root->add_child("Id")->add_child_text ("urn:uuid:" + make_uuid()); + root->add_child("Creator")->add_child_text (metadata.creator); + 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); + xmlpp::Node* asset_list = root->add_child ("AssetList"); + + xmlpp::Node* asset = asset_list->add_child ("Asset"); + asset->add_child("Id")->add_child_text ("urn:uuid:" + pkl_uuid); + asset->add_child("PackingList")->add_child_text ("true"); + xmlpp::Node* chunk_list = asset->add_child ("ChunkList"); + xmlpp::Node* chunk = chunk_list->add_child ("Chunk"); + chunk->add_child("Path")->add_child_text (pkl_uuid + "_pkl.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> (pkl_length)); for (list<shared_ptr<const CPL> >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) { - (*i)->write_to_assetmap (am); + (*i)->write_to_assetmap (asset_list); } list<shared_ptr<const Asset> > a = assets (); for (list<shared_ptr<const Asset> >::const_iterator i = a.begin(); i != a.end(); ++i) { - (*i)->write_to_assetmap (am); + (*i)->write_to_assetmap (asset_list); } - am << " </AssetList>\n" - << "</AssetMap>\n"; + doc.write_to_file_formatted (p.string (), "UTF-8"); } diff --git a/src/picture_asset.cc b/src/picture_asset.cc index 788e3dc4..72a63173 100644 --- a/src/picture_asset.cc +++ b/src/picture_asset.cc @@ -64,18 +64,17 @@ PictureAsset::PictureAsset (string directory, string mxf_name) } void -PictureAsset::write_to_cpl (ostream& s) const +PictureAsset::write_to_cpl (xmlpp::Node* node) const { - s << " <MainPicture>\n" - << " <Id>urn:uuid:" << _uuid << "</Id>\n" - << " <AnnotationText>" << _file_name << "</AnnotationText>\n" - << " <EditRate>" << _edit_rate << " 1</EditRate>\n" - << " <IntrinsicDuration>" << _intrinsic_duration << "</IntrinsicDuration>\n" - << " <EntryPoint>" << _entry_point << "</EntryPoint>\n" - << " <Duration>" << _duration << "</Duration>\n" - << " <FrameRate>" << _edit_rate << " 1</FrameRate>\n" - << " <ScreenAspectRatio>" << _size.width << " " << _size.height << "</ScreenAspectRatio>\n" - << " </MainPicture>\n"; + xmlpp::Node* mp = node->add_child ("MainPicture"); + mp->add_child ("Id")->add_child_text ("urn:uuid:" + _uuid); + mp->add_child ("AnnotationText")->add_child_text (_file_name); + mp->add_child ("EditRate")->add_child_text (lexical_cast<string> (_edit_rate) + " 1"); + mp->add_child ("IntrinsicDuration")->add_child_text (lexical_cast<string> (_intrinsic_duration)); + mp->add_child ("EntryPoint")->add_child_text (lexical_cast<string> (_entry_point)); + mp->add_child ("Duration")->add_child_text (lexical_cast<string> (_duration)); + mp->add_child ("FrameRate")->add_child_text (lexical_cast<string> (_edit_rate) + " 1"); + mp->add_child ("ScreenAspectRatio")->add_child_text (lexical_cast<string> (_size.width) + " " + lexical_cast<string> (_size.height)); } bool diff --git a/src/picture_asset.h b/src/picture_asset.h index 59c4dc00..3edf3a1c 100644 --- a/src/picture_asset.h +++ b/src/picture_asset.h @@ -59,10 +59,10 @@ public: */ PictureAsset (std::string directory, std::string mxf_name, boost::signals2::signal<void (float)>* progress, int fps, int intrinsic_duration, Size size); - /** Write details of this asset to a CPL stream. - * @param s Stream. + /** Write details of this asset to a CPL XML node. + * @param node Node. */ - void write_to_cpl (std::ostream& s) const; + void write_to_cpl (xmlpp::Node* node) const; bool equals (boost::shared_ptr<const Asset> other, EqualityOptions opt, boost::function<void (NoteType, std::string)> note) const; diff --git a/src/reel.cc b/src/reel.cc index 86533ea2..481b153b 100644 --- a/src/reel.cc +++ b/src/reel.cc @@ -27,26 +27,23 @@ using namespace std; using namespace libdcp; void -Reel::write_to_cpl (ostream& s) const +Reel::write_to_cpl (xmlpp::Node* node) const { - s << " <Reel>\n" - << " <Id>urn:uuid:" << make_uuid() << "</Id>\n" - << " <AssetList>\n"; + xmlpp::Node* reel = node->add_child ("Reel"); + reel->add_child("Id")->add_child_text ("urn:uuid:" + make_uuid()); + xmlpp::Node* asset_list = reel->add_child ("AssetList"); if (_main_picture) { - _main_picture->write_to_cpl (s); + _main_picture->write_to_cpl (asset_list); } if (_main_sound) { - _main_sound->write_to_cpl (s); + _main_sound->write_to_cpl (asset_list); } if (_main_subtitle) { - _main_subtitle->write_to_cpl (s); + _main_subtitle->write_to_cpl (asset_list); } - - s << " </AssetList>\n" - << " </Reel>\n"; } bool @@ -20,6 +20,7 @@ #include <list> #include <boost/shared_ptr.hpp> #include <boost/function.hpp> +#include <libxml++/libxml++.h> #include "types.h" namespace libdcp { @@ -54,7 +55,7 @@ public: return _main_subtitle; } - void write_to_cpl (std::ostream & s) const; + void write_to_cpl (xmlpp::Node *) const; bool equals (boost::shared_ptr<const Reel> other, EqualityOptions opt, boost::function<void (NoteType, std::string)> notes) const; diff --git a/src/sound_asset.cc b/src/sound_asset.cc index 9b6b48aa..4a7abd4d 100644 --- a/src/sound_asset.cc +++ b/src/sound_asset.cc @@ -211,16 +211,15 @@ SoundAsset::construct (boost::function<string (Channel)> get_path, MXFMetadata c } void -SoundAsset::write_to_cpl (ostream& s) const +SoundAsset::write_to_cpl (xmlpp::Node* node) const { - s << " <MainSound>\n" - << " <Id>urn:uuid:" << _uuid << "</Id>\n" - << " <AnnotationText>" << _file_name << "</AnnotationText>\n" - << " <EditRate>" << _edit_rate << " 1</EditRate>\n" - << " <IntrinsicDuration>" << _intrinsic_duration << "</IntrinsicDuration>\n" - << " <EntryPoint>" << _entry_point << "</EntryPoint>\n" - << " <Duration>" << _duration << "</Duration>\n" - << " </MainSound>\n"; + xmlpp::Node* ms = node->add_child ("MainSound"); + ms->add_child ("Id")->add_child_text ("urn:uuid:" + _uuid); + ms->add_child ("AnnotationText")->add_child_text (_file_name); + ms->add_child ("EditRate")->add_child_text (lexical_cast<string> (_edit_rate) + " 1"); + ms->add_child ("IntrinsicDuration")->add_child_text (lexical_cast<string> (_intrinsic_duration)); + ms->add_child ("EntryPoint")->add_child_text (lexical_cast<string> (_entry_point)); + ms->add_child ("Duration")->add_child_text (lexical_cast<string> (_duration)); } bool diff --git a/src/sound_asset.h b/src/sound_asset.h index 5c230e06..1e3553a0 100644 --- a/src/sound_asset.h +++ b/src/sound_asset.h @@ -127,10 +127,10 @@ public: boost::shared_ptr<SoundAssetWriter> start_write (MXFMetadata const & metadata = MXFMetadata ()); - /** Write details of this asset to a CPL stream. - * @param s Stream. + /** Write details of this asset to a CPL XML node. + * @param node Node. */ - void write_to_cpl (std::ostream& s) const; + void write_to_cpl (xmlpp::Node* node) const; bool equals (boost::shared_ptr<const Asset> other, EqualityOptions opt, boost::function<void (NoteType, std::string)> note) const; diff --git a/src/subtitle_asset.cc b/src/subtitle_asset.cc index d89d52de..5decc1e3 100644 --- a/src/subtitle_asset.cc +++ b/src/subtitle_asset.cc @@ -276,15 +276,15 @@ SubtitleAsset::add (shared_ptr<Subtitle> s) } void -SubtitleAsset::write_to_cpl (ostream& s) const +SubtitleAsset::write_to_cpl (xmlpp::Node* node) const { /* XXX: should EditRate, Duration and IntrinsicDuration be in here? */ - - s << " <MainSubtitle>\n" - << " <Id>urn:uuid:" << _uuid << "</Id>\n" - << " <AnnotationText>" << _file_name << "</AnnotationText>\n" - << " <EntryPoint>0</EntryPoint>\n" - << " </MainSubtitle>\n"; + + xmlpp::Node* ms = node->add_child ("MainSubtitle"); + ms->add_child("Id")->add_child_text("urn:uuid:" + _uuid); + ms->add_child("AnnotationText")->add_child_text (_file_name); + /* XXX */ + ms->add_child("EntryPoint")->add_child_text ("0"); } struct SubtitleSorter { @@ -299,26 +299,30 @@ struct SubtitleSorter { void SubtitleAsset::write_xml () const { - ofstream f (path().string().c_str()); - write_xml (f); + ofstream s (path().string().c_str()); + write_xml (s); } void SubtitleAsset::write_xml (ostream& s) const { - s << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" - << "<DCSubtitle Version=\"1.0\">\n" - << " <SubtitleID>" << _uuid << "</SubtitleID>\n" - << " <MovieTitle>" << _movie_title << "</MovieTitle>\n" - << " <ReelNumber>" << _reel_number << "</ReelNumber>\n" - << " <Language>" << _language << "</Language>\n"; + xmlpp::Document doc; + xmlpp::Element* root = doc.create_root_node ("DCSubtitle"); + root->set_attribute ("Version", "1.0"); + + root->add_child("SubtitleID")->add_child_text (_uuid); + 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 ()) { - s << " <LoadFont Id=\"" << _load_font_nodes.front()->id << "\" URI=\"" << _load_font_nodes.front()->uri << "\"/>\n"; + 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; @@ -329,7 +333,6 @@ SubtitleAsset::write_xml (ostream& s) const /* XXX: multiple fonts not supported */ /* XXX: script, underlined, weight not supported */ - bool first = true; bool italic = false; Color color; int size = 0; @@ -341,66 +344,61 @@ SubtitleAsset::write_xml (ostream& s) const 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 should really make an optimal hierarchy of <Font> tags, but + I suppose we should really make an optimal hierarchy of <Font> tags, but that seems hard. */ - bool const font_changed = first || + bool const font_changed = italic != (*i)->italic() || color != (*i)->color() || size != (*i)->size() || effect != (*i)->effect() || effect_color != (*i)->effect_color(); - stringstream a; if (font_changed) { italic = (*i)->italic (); - a << "Italic=\"" << (italic ? "yes" : "no") << "\" "; color = (*i)->color (); - a << "Color=\"" << color.to_argb_string() << "\" "; size = (*i)->size (); - a << "Size=\"" << size << "\" "; effect = (*i)->effect (); - a << "Effect=\"" << effect_to_string(effect) << "\" "; effect_color = (*i)->effect_color (); - a << "EffectColor=\"" << effect_color.to_argb_string() << "\" "; - a << "Script=\"normal\" Underlined=\"no\" Weight=\"normal\""; } - if (first || font_changed || + 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 || (last_in != (*i)->in() || last_out != (*i)->out() || last_fade_up_time != (*i)->fade_up_time() || last_fade_down_time != (*i)->fade_down_time() )) { - if (!first) { - s << " </Subtitle>\n"; - } - - if (font_changed) { - if (!first) { - s << " </Font>\n"; - } - - string id = "theFontId"; - if (!_load_font_nodes.empty()) { - id = _load_font_nodes.front()->id; - } - - s << " <Font Id=\"" << id << "\" " << a.str() << ">\n"; - } - - s << " <Subtitle " - << "SpotNumber=\"" << spot_number++ << "\" " - << "TimeIn=\"" << (*i)->in().to_string() << "\" " - << "TimeOut=\"" << (*i)->out().to_string() << "\" " - << "FadeUpTime=\"" << (*i)->fade_up_time().to_ticks() << "\" " - << "FadeDownTime=\"" << (*i)->fade_down_time().to_ticks() << "\"" - << ">\n"; + 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 (); @@ -408,23 +406,12 @@ SubtitleAsset::write_xml (ostream& s) const last_fade_down_time = (*i)->fade_down_time (); } - s << " <Text " - << "VAlign=\"" << valign_to_string ((*i)->v_align()) << "\" " - << "VPosition=\"" << (*i)->v_position() << "\"" - << ">" << escape ((*i)->text()) << "</Text>\n"; - - first = false; + 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()); } - s << " </Subtitle>\n"; - s << " </Font>\n"; - s << "</DCSubtitle>\n"; + doc.write_to_stream_formatted (s); } -/** XXX: Another reason why we should be writing with libxml++ */ -string -SubtitleAsset::escape (string s) const -{ - boost::replace_all (s, "&", "&"); - return s; -} diff --git a/src/subtitle_asset.h b/src/subtitle_asset.h index 0d662d6c..2da1ce7b 100644 --- a/src/subtitle_asset.h +++ b/src/subtitle_asset.h @@ -123,7 +123,7 @@ public: SubtitleAsset (std::string directory, std::string xml_file); SubtitleAsset (std::string directory, std::string movie_title, std::string language); - void write_to_cpl (std::ostream&) const; + void write_to_cpl (xmlpp::Node *) const; virtual bool equals (boost::shared_ptr<const Asset>, EqualityOptions, boost::function<void (NoteType, std::string)> note) const { /* XXX */ note (ERROR, "subtitle assets not compared yet"); @@ -143,11 +143,10 @@ public: void read_xml (std::string); void write_xml () const; - void write_xml (std::ostream& s) const; + void write_xml (std::ostream &) const; private: std::string font_id_to_name (std::string id) const; - std::string escape (std::string) const; struct ParseState { std::list<boost::shared_ptr<parse::Font> > font_nodes; |
