2 Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include <boost/filesystem.hpp>
27 #include "sound_asset.h"
28 #include "picture_asset.h"
33 using namespace boost;
34 using namespace libdcp;
37 * @param d Directory to write files to.
39 * @param c Content type.
40 * @param fps Frames per second.
41 * @param length Length in frames.
43 DCP::DCP (string d, string n, ContentType c, int fps, int length)
52 /** Add a sound asset.
53 * @param files Pathnames of WAV files to use in the order Left, Right, Centre, Lfe (sub), Left surround, Right surround.
56 DCP::add_sound_asset (list<string> const & files)
61 _assets.push_back (shared_ptr<SoundAsset> (new SoundAsset (files, p.string(), &Progress, _fps, _length)));
64 /** Add a picture asset.
65 * @param files Pathnames of JPEG2000 files, in frame order.
68 DCP::add_picture_asset (list<string> const & files, int w, int h)
73 _assets.push_back (shared_ptr<PictureAsset> (new PictureAsset (files, p.string(), &Progress, _fps, _length, w, h)));
76 /** Write the required XML files to the directory that was
77 * passed into the constructor.
80 DCP::write_xml () const
82 string cpl_uuid = make_uuid ();
83 string cpl_path = write_cpl (cpl_uuid);
84 int cpl_length = filesystem::file_size (cpl_path);
85 string cpl_digest = make_digest (cpl_path, 0);
87 string pkl_uuid = make_uuid ();
88 string pkl_path = write_pkl (pkl_uuid, cpl_uuid, cpl_digest, cpl_length);
91 write_assetmap (cpl_uuid, cpl_length, pkl_uuid, filesystem::file_size (pkl_path));
94 /** Write the CPL file.
95 * @param cpl_uuid UUID to use.
96 * @return CPL pathname.
99 DCP::write_cpl (string cpl_uuid) const
104 s << cpl_uuid << "_cpl.xml";
106 ofstream cpl (p.string().c_str());
108 cpl << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
109 << "<CompositionPlaylist xmlns=\"http://www.smpte-ra.org/schemas/429-7/2006/CPL\">\n"
110 << " <Id>urn:uuid:" << cpl_uuid << "</Id>\n"
111 << " <AnnotationText>" << _name << "</AnnotationText>\n"
112 << " <IssueDate>" << Tags::instance()->issue_date << "</IssueDate>\n"
113 << " <Creator>" << Tags::instance()->creator << "</Creator>\n"
114 << " <ContentTitleText>" << _name << "</ContentTitleText>\n"
115 << " <ContentKind>" << content_type_string (_content_type) << "</ContentKind>\n"
116 << " <ContentVersion>\n"
117 << " <Id>urn:uri:" << cpl_uuid << "_" << Tags::instance()->issue_date << "</Id>\n"
118 << " <LabelText>" << cpl_uuid << "_" << Tags::instance()->issue_date << "</LabelText>\n"
119 << " </ContentVersion>\n"
120 << " <RatingList/>\n"
124 << " <Id>urn:uuid:" << make_uuid() << "</Id>\n"
127 for (list<shared_ptr<Asset> >::const_iterator i = _assets.begin(); i != _assets.end(); ++i) {
128 (*i)->write_to_cpl (cpl);
131 cpl << " </AssetList>\n"
134 << "</CompositionPlaylist>\n";
139 /** Write the PKL file.
140 * @param pkl_uuid UUID to use.
141 * @param cpl_uuid UUID of the CPL file.
142 * @param cpl_digest SHA digest of the CPL file.
143 * @param cpl_length Length of the CPL file in bytes.
146 DCP::write_pkl (string pkl_uuid, string cpl_uuid, string cpl_digest, int cpl_length) const
151 s << pkl_uuid << "_pkl.xml";
153 ofstream pkl (p.string().c_str());
155 pkl << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
156 << "<PackingList xmlns=\"http://www.smpte-ra.org/schemas/429-8/2007/PKL\">\n"
157 << " <Id>urn:uuid:" << pkl_uuid << "</Id>\n"
158 << " <AnnotationText>" << _name << "</AnnotationText>\n"
159 << " <IssueDate>" << Tags::instance()->issue_date << "</IssueDate>\n"
160 << " <Issuer>" << Tags::instance()->issuer << "</Issuer>\n"
161 << " <Creator>" << Tags::instance()->creator << "</Creator>\n"
164 for (list<shared_ptr<Asset> >::const_iterator i = _assets.begin(); i != _assets.end(); ++i) {
165 (*i)->write_to_pkl (pkl);
169 << " <Id>urn:uuid:" << cpl_uuid << "</Id>\n"
170 << " <Hash>" << cpl_digest << "</Hash>\n"
171 << " <Size>" << cpl_length << "</Size>\n"
172 << " <Type>text/xml</Type>\n"
175 pkl << " </AssetList>\n"
176 << "</PackingList>\n";
181 /** Write the VOLINDEX file */
183 DCP::write_volindex () const
188 ofstream vi (p.string().c_str());
190 vi << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
191 << "<VolumeIndex xmlns=\"http://www.smpte-ra.org/schemas/429-9/2007/AM\">\n"
192 << " <Index>1</Index>\n"
193 << "</VolumeIndex>\n";
196 /** Write the ASSETMAP file.
197 * @param cpl_uuid UUID of our CPL.
198 * @param cpl_length Length of our CPL in bytes.
199 * @param pkl_uuid UUID of our PKL.
200 * @param pkl_length Length of our PKL in bytes.
203 DCP::write_assetmap (string cpl_uuid, int cpl_length, string pkl_uuid, int pkl_length) const
208 ofstream am (p.string().c_str());
210 am << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
211 << "<AssetMap xmlns=\"http://www.smpte-ra.org/schemas/429-9/2007/AM\">\n"
212 << " <Id>urn:uuid:" << make_uuid() << "</Id>\n"
213 << " <Creator>" << Tags::instance()->creator << "</Creator>\n"
214 << " <VolumeCount>1</VolumeCount>\n"
215 << " <IssueDate>" << Tags::instance()->issue_date << "</IssueDate>\n"
216 << " <Issuer>" << Tags::instance()->issuer << "</Issuer>\n"
220 << " <Id>urn:uuid:" << pkl_uuid << "</Id>\n"
221 << " <PackingList>true</PackingList>\n"
224 << " <Path>" << pkl_uuid << "_pkl.xml</Path>\n"
225 << " <VolumeIndex>1</VolumeIndex>\n"
226 << " <Offset>0</Offset>\n"
227 << " <Length>" << pkl_length << "</Length>\n"
233 << " <Id>urn:uuid:" << cpl_uuid << "</Id>\n"
236 << " <Path>" << cpl_uuid << "_cpl.xml</Path>\n"
237 << " <VolumeIndex>1</VolumeIndex>\n"
238 << " <Offset>0</Offset>\n"
239 << " <Length>" << cpl_length << "</Length>\n"
244 for (list<shared_ptr<Asset> >::const_iterator i = _assets.begin(); i != _assets.end(); ++i) {
245 (*i)->write_to_assetmap (am);
248 am << " </AssetList>\n"
252 /** @param t A content type.
253 * @return A string representation suitable for use in a CPL.
256 DCP::content_type_string (ContentType t)
268 return "transitional";
275 case PUBLIC_SERVICE_ANNOUNCEMENT:
278 return "advertisement";