35 #include "asset_map.h"
38 #include "filesystem.h"
41 LIBDCP_DISABLE_WARNINGS
42 #include <libxml++/libxml++.h>
43 LIBDCP_ENABLE_WARNINGS
44 #include <boost/algorithm/string.hpp>
51 using boost::algorithm::starts_with;
55 static string const assetmap_interop_ns =
"http://www.digicine.com/PROTO-ASDCP-AM-20040311#";
56 static string const assetmap_smpte_ns =
"http://www.smpte-ra.org/schemas/429-9/2007/AM";
59 AssetMap::AssetMap(boost::filesystem::path file)
62 cxml::Document doc(
"AssetMap");
64 doc.read_file(dcp::filesystem::fix_long_path(file));
65 if (doc.namespace_uri() == assetmap_interop_ns) {
66 _standard = Standard::INTEROP;
67 }
else if (doc.namespace_uri() == assetmap_smpte_ns) {
68 _standard = Standard::SMPTE;
70 boost::throw_exception(
XMLError(
"Unrecognised Assetmap namespace " + doc.namespace_uri()));
73 _id = remove_urn_uuid(doc.string_child(
"Id"));
74 _annotation_text = doc.optional_string_child(
"AnnotationText");
75 _issue_date = doc.string_child(
"IssueDate");
76 _issuer = doc.string_child(
"Issuer");
77 _creator = doc.string_child(
"Creator");
79 for (
auto asset: doc.node_child(
"AssetList")->node_children(
"Asset")) {
80 _assets.push_back(
Asset(asset, _file->parent_path(), _standard));
85 AssetMap::Asset::Asset(cxml::ConstNodePtr node, boost::filesystem::path root, dcp::Standard standard)
86 :
Object(remove_urn_uuid(node->string_child(
"Id")))
88 if (node->node_child(
"ChunkList")->node_children(
"Chunk").size() != 1) {
89 boost::throw_exception (
XMLError (
"unsupported asset chunk count"));
92 auto path_from_xml = node->node_child(
"ChunkList")->node_child(
"Chunk")->string_child(
"Path");
93 if (starts_with(path_from_xml,
"file://")) {
94 path_from_xml = path_from_xml.substr(7);
97 _path = root / path_from_xml;
100 case Standard::INTEROP:
101 _pkl =
static_cast<bool>(node->optional_node_child(
"PackingList"));
103 case Standard::SMPTE:
105 auto pkl_bool = node->optional_string_child(
"PackingList");
106 _pkl = pkl_bool && *pkl_bool ==
"true";
114 AssetMap::add_asset(
string id, boost::filesystem::path path,
bool pkl)
116 _assets.push_back(
Asset(
id, path, pkl));
121 AssetMap::clear_assets()
127 map<std::string, boost::filesystem::path>
128 AssetMap::asset_ids_and_paths()
const
130 auto paths = map<string, boost::filesystem::path>();
131 for (
auto asset: _assets) {
132 paths[asset.id()] = asset.path();
138 vector<boost::filesystem::path>
139 AssetMap::pkl_paths()
const
141 auto paths = std::vector<boost::filesystem::path>();
142 for (
auto asset: _assets) {
144 paths.push_back(asset.path());
152 AssetMap::write_xml(boost::filesystem::path file)
const
155 xmlpp::Element* root;
158 case Standard::INTEROP:
159 root = doc.create_root_node(
"AssetMap", assetmap_interop_ns);
161 case Standard::SMPTE:
162 root = doc.create_root_node(
"AssetMap", assetmap_smpte_ns);
168 cxml::add_text_child(root,
"Id",
"urn:uuid:" + _id);
169 if (_annotation_text) {
170 cxml::add_text_child(root,
"AnnotationText", *_annotation_text);
174 case Standard::INTEROP:
175 cxml::add_text_child(root,
"VolumeCount",
"1");
176 cxml::add_text_child(root,
"IssueDate", _issue_date);
177 cxml::add_text_child(root,
"Issuer", _issuer);
178 cxml::add_text_child(root,
"Creator", _creator);
180 case Standard::SMPTE:
181 cxml::add_text_child(root,
"Creator", _creator);
182 cxml::add_text_child(root,
"VolumeCount",
"1");
183 cxml::add_text_child(root,
"IssueDate", _issue_date);
184 cxml::add_text_child(root,
"Issuer", _issuer);
190 auto asset_list = cxml::add_child(root,
"AssetList");
191 for (
auto const& asset: _assets) {
192 asset.write_xml(asset_list, file.parent_path());
195 doc.write_to_file_formatted(dcp::filesystem::fix_long_path(file).
string(),
"UTF-8");
201 AssetMap::Asset::write_xml(xmlpp::Element* asset_list, boost::filesystem::path dcp_root_directory)
const
203 auto node = cxml::add_child(asset_list,
"Asset");
204 cxml::add_text_child(node,
"Id",
"urn:uuid:" + _id);
206 cxml::add_text_child(node,
"PackingList",
"true");
208 auto chunk_list = cxml::add_child(node,
"ChunkList");
209 auto chunk = cxml::add_child(chunk_list,
"Chunk");
211 auto relative_path = relative_to_root(filesystem::canonical(dcp_root_directory), filesystem::canonical(_path));
212 DCP_ASSERT(relative_path);
214 cxml::add_text_child(chunk,
"Path", relative_path->generic_string());
215 cxml::add_text_child(chunk,
"VolumeIndex",
"1");
216 cxml::add_text_child(chunk,
"Offset",
"0");
217 cxml::add_text_child(chunk,
"Length", raw_convert<string>(filesystem::file_size(_path)));
Parent class for DCP assets, i.e. picture, sound, subtitles, closed captions, CPLs,...
Some part of a DCP that has a UUID.
Exceptions thrown by libdcp.
Namespace for everything in libdcp.
Methods for conversion to/from string.