#include "asset.h"
+#include "asset_map.h"
#include "compose.hpp"
#include "dcp_assert.h"
#include "exceptions.h"
void
-Asset::write_to_assetmap (xmlpp::Node* node, path root) const
+Asset::add_to_assetmap (AssetMap& asset_map, path root) const
{
DCP_ASSERT (_file);
- write_file_to_assetmap (node, root, _file.get(), _id);
+ add_file_to_assetmap (asset_map, root, _file.get(), _id);
}
void
-Asset::write_file_to_assetmap (xmlpp::Node* node, path root, path file, string id)
+Asset::add_file_to_assetmap (AssetMap& asset_map, path root, path file, string id)
{
- auto path = relative_to_root (
- canonical(root),
- canonical(file)
- );
-
- if (!path) {
+ if (!relative_to_root(root, file)) {
/* The path of this asset is not within our DCP, so we assume it's an external
(referenced) one.
*/
return;
}
- auto asset = node->add_child ("Asset");
- asset->add_child("Id")->add_child_text("urn:uuid:" + id);
- auto chunk_list = asset->add_child ("ChunkList");
- auto chunk = chunk_list->add_child ("Chunk");
-
- chunk->add_child("Path")->add_child_text(path.get().generic_string());
- chunk->add_child("VolumeIndex")->add_child_text("1");
- chunk->add_child("Offset")->add_child_text("0");
- chunk->add_child("Length")->add_child_text(raw_convert<string>(file_size(file)));
+ asset_map.add_asset(id, file, false);
}
namespace dcp {
+class AssetMap;
+
+
/** @class Asset
* @brief Parent class for DCP assets, i.e. picture, sound, subtitles, closed captions, CPLs, fonts
*
NoteHandler note
) const;
- virtual void write_to_assetmap (xmlpp::Node* node, boost::filesystem::path root) const;
+ virtual void add_to_assetmap (AssetMap& asset_map, boost::filesystem::path root) const;
virtual void add_to_pkl (std::shared_ptr<PKL> pkl, boost::filesystem::path root) const;
/** The most recent disk file used to read or write this asset */
mutable boost::optional<boost::filesystem::path> _file;
- static void write_file_to_assetmap (xmlpp::Node* node, boost::filesystem::path root, boost::filesystem::path file, std::string id);
+ static void add_file_to_assetmap (AssetMap& asset_map, boost::filesystem::path root, boost::filesystem::path file, std::string id);
private:
friend struct ::asset_test;
--- /dev/null
+/*
+ Copyright (C) 2022 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp 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.
+
+ libdcp 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 libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#include "asset_map.h"
+#include "dcp_assert.h"
+#include "raw_convert.h"
+#include "util.h"
+#include "warnings.h"
+LIBDCP_DISABLE_WARNINGS
+#include <libxml++/libxml++.h>
+LIBDCP_ENABLE_WARNINGS
+#include <boost/algorithm/string.hpp>
+
+
+using std::string;
+using std::vector;
+using boost::algorithm::starts_with;
+using namespace dcp;
+
+
+static string const assetmap_interop_ns = "http://www.digicine.com/PROTO-ASDCP-AM-20040311#";
+static string const assetmap_smpte_ns = "http://www.smpte-ra.org/schemas/429-9/2007/AM";
+
+
+AssetMap::AssetMap(boost::filesystem::path file)
+ : _file(file)
+{
+ cxml::Document doc("AssetMap");
+ doc.read_file(file);
+
+ if (doc.namespace_uri() == assetmap_interop_ns) {
+ _standard = Standard::INTEROP;
+ } else if (doc.namespace_uri() == assetmap_smpte_ns) {
+ _standard = Standard::SMPTE;
+ } else {
+ boost::throw_exception(XMLError("Unrecognised AssetMap namespace " + doc.namespace_uri()));
+ }
+
+ _annotation_text = doc.optional_string_child("AnnotationText");
+ _issue_date = doc.string_child("IssueDate");
+ _issuer = doc.string_child("Issuer");
+ _creator = doc.string_child("Creator");
+
+ for (auto asset: doc.node_child("AssetList")->node_children("Asset")) {
+ _assets.push_back(Asset(asset, _file->parent_path(), _standard));
+ }
+}
+
+
+vector<boost::filesystem::path>
+AssetMap::pkl_paths() const
+{
+ auto paths = std::vector<boost::filesystem::path>();
+ for (auto asset: _assets) {
+ if (asset.pkl()) {
+ paths.push_back(asset.path());
+ }
+ }
+ return paths;
+}
+
+
+std::map<std::string, boost::filesystem::path>
+AssetMap::paths() const
+{
+ auto paths = std::map<string, boost::filesystem::path>();
+ for (auto asset: _assets) {
+ paths[asset.id()] = asset.path();
+ }
+ return paths;
+}
+
+
+void
+AssetMap::add_asset(string id, boost::filesystem::path path, bool pkl)
+{
+ _assets.push_back(Asset(id, path, pkl));
+}
+
+
+void
+AssetMap::write_xml(boost::filesystem::path file)
+{
+ xmlpp::Document doc;
+ xmlpp::Element* root;
+
+ switch (_standard) {
+ case Standard::INTEROP:
+ root = doc.create_root_node("AssetMap", assetmap_interop_ns);
+ break;
+ case Standard::SMPTE:
+ root = doc.create_root_node("AssetMap", assetmap_smpte_ns);
+ break;
+ default:
+ DCP_ASSERT (false);
+ }
+
+ root->add_child("Id")->add_child_text("urn:uuid:" + _id);
+ if (_annotation_text) {
+ root->add_child("AnnotationText")->add_child_text(*_annotation_text);
+ }
+
+ switch (_standard) {
+ case Standard::INTEROP:
+ root->add_child("VolumeCount")->add_child_text("1");
+ root->add_child("IssueDate")->add_child_text(_issue_date);
+ root->add_child("Issuer")->add_child_text(_issuer);
+ root->add_child("Creator")->add_child_text(_creator);
+ break;
+ case Standard::SMPTE:
+ root->add_child("Creator")->add_child_text(_creator);
+ root->add_child("VolumeCount")->add_child_text ("1");
+ root->add_child("IssueDate")->add_child_text(_issue_date);
+ root->add_child("Issuer")->add_child_text(_issuer);
+ break;
+ default:
+ DCP_ASSERT (false);
+ }
+
+ auto const dcp_root_directory = file.parent_path();
+
+ auto asset_list = root->add_child("AssetList");
+
+ for (auto asset: _assets) {
+ auto node = asset_list->add_child("Asset");
+ node->add_child("Id")->add_child_text("urn:uuid:" + asset.id());
+ if (asset.pkl()) {
+ node->add_child("PackingList")->add_child_text("true");
+ }
+ auto chunk_list = node->add_child("ChunkList");
+ auto chunk = chunk_list->add_child("Chunk");
+
+ auto relative_path = relative_to_root(dcp_root_directory, asset.path());
+ DCP_ASSERT(relative_path);
+
+ chunk->add_child("Path")->add_child_text(relative_path->generic_string());
+ chunk->add_child("VolumeIndex")->add_child_text("1");
+ chunk->add_child("Offset")->add_child_text("0");
+ chunk->add_child("Length")->add_child_text(raw_convert<string>(boost::filesystem::file_size(asset.path())));
+ }
+
+ doc.write_to_file_formatted(file.string(), "UTF-8");
+ _file = file;
+}
+
+
+AssetMap::Asset::Asset(cxml::ConstNodePtr node, boost::filesystem::path root, dcp::Standard standard)
+ : Object(remove_urn_uuid(node->string_child("Id")))
+{
+ if (node->node_child("ChunkList")->node_children("Chunk").size() != 1) {
+ boost::throw_exception(XMLError("unsupported asset chunk count"));
+ }
+
+ auto path_from_xml = node->node_child("ChunkList")->node_child("Chunk")->string_child("Path");
+ if (starts_with(path_from_xml, "file://")) {
+ path_from_xml = path_from_xml.substr(7);
+ }
+
+ _path = root / path_from_xml;
+
+ switch (standard) {
+ case Standard::INTEROP:
+ _pkl = static_cast<bool>(node->optional_node_child("PackingList"));
+ break;
+ case Standard::SMPTE:
+ {
+ auto pkl_bool = node->optional_string_child("PackingList");
+ _pkl = pkl_bool && *pkl_bool == "true";
+ break;
+ }
+ }
+}
+
--- /dev/null
+/*
+ Copyright (C) 2022 Carl Hetherington <cth@carlh.net>
+
+ This file is part of libdcp.
+
+ libdcp 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.
+
+ libdcp 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 libdcp. If not, see <http://www.gnu.org/licenses/>.
+
+ In addition, as a special exception, the copyright holders give
+ permission to link the code of portions of this program with the
+ OpenSSL library under certain conditions as described in each
+ individual source file, and distribute linked combinations
+ including the two.
+
+ You must obey the GNU General Public License in all respects
+ for all of the code used other than OpenSSL. If you modify
+ file(s) with this exception, you may extend this exception to your
+ version of the file(s), but you are not obligated to do so. If you
+ do not wish to do so, delete this exception statement from your
+ version. If you delete this exception statement from all source
+ files in the program, then also delete it here.
+*/
+
+
+#include "exceptions.h"
+#include "object.h"
+#include "types.h"
+#include <boost/optional.hpp>
+#include <string>
+
+
+namespace dcp {
+
+
+class AssetMap : public Object
+{
+public:
+ AssetMap(Standard standard, boost::optional<std::string> annotation_text, std::string issue_date, std::string issuer, std::string creator)
+ : _standard(standard)
+ , _annotation_text(annotation_text)
+ , _issue_date(issue_date)
+ , _issuer(issuer)
+ , _creator(creator)
+ {}
+
+ explicit AssetMap(boost::filesystem::path file);
+
+ void add_asset(std::string id, boost::filesystem::path path, bool pkl);
+
+ boost::optional<boost::filesystem::path> path() const {
+ return _file;
+ }
+
+ std::vector<boost::filesystem::path> pkl_paths() const;
+ std::map<std::string, boost::filesystem::path> paths() const;
+ dcp::Standard standard() const {
+ return _standard;
+ }
+
+ void write_xml(boost::filesystem::path file);
+
+ class Asset : public Object
+ {
+ public:
+ Asset(std::string id, boost::filesystem::path path, bool pkl)
+ : Object(id)
+ , _path(path)
+ , _pkl(pkl)
+ {}
+
+ Asset(cxml::ConstNodePtr node, boost::filesystem::path root, dcp::Standard standard);
+
+ boost::filesystem::path path() const {
+ return _path;
+ }
+
+ bool pkl() const {
+ return _pkl;
+ }
+
+ private:
+ boost::filesystem::path _path;
+ bool _pkl = false;
+ };
+
+private:
+ Standard _standard;
+ boost::optional<std::string> _annotation_text;
+ std::string _issue_date;
+ std::string _issuer;
+ std::string _creator;
+ std::vector<Asset> _assets;
+ /** The most recent disk file used to read or write this AssetMap */
+ mutable boost::optional<boost::filesystem::path> _file;
+};
+
+
+}
+
+
using namespace dcp;
-static string const assetmap_interop_ns = "http://www.digicine.com/PROTO-ASDCP-AM-20040311#";
-static string const assetmap_smpte_ns = "http://www.smpte-ra.org/schemas/429-9/2007/AM";
static string const volindex_interop_ns = "http://www.digicine.com/PROTO-ASDCP-VL-20040311#";
static string const volindex_smpte_ns = "http://www.smpte-ra.org/schemas/429-9/2007/AM";
DCP::DCP (DCP&& other)
: _directory(std::move(other._directory))
+ , _asset_map(std::move(other._asset_map))
, _cpls(std::move(other._cpls))
, _pkls(std::move(other._pkls))
- , _asset_map(std::move(other._asset_map))
- , _standard(std::move(other._standard))
{
}
dcp::DCP& DCP::operator= (DCP&& other)
{
_directory = std::move(other._directory);
+ _asset_map = std::move(other._asset_map);
_cpls = std::move(other._cpls);
_pkls = std::move(other._pkls);
- _asset_map = std::move(other._asset_map);
- _standard = std::move(other._standard);
return *this;
}
{
/* Read the ASSETMAP and PKL */
+ boost::filesystem::path asset_map_path;
+
if (boost::filesystem::exists (_directory / "ASSETMAP")) {
- _asset_map = _directory / "ASSETMAP";
+ asset_map_path = _directory / "ASSETMAP";
} else if (boost::filesystem::exists (_directory / "ASSETMAP.xml")) {
- _asset_map = _directory / "ASSETMAP.xml";
+ asset_map_path = _directory / "ASSETMAP.xml";
} else {
boost::throw_exception (MissingAssetmapError(_directory));
}
- cxml::Document asset_map ("AssetMap");
-
- asset_map.read_file (_asset_map.get());
- if (asset_map.namespace_uri() == assetmap_interop_ns) {
- _standard = Standard::INTEROP;
- } else if (asset_map.namespace_uri() == assetmap_smpte_ns) {
- _standard = Standard::SMPTE;
- } else {
- boost::throw_exception (XMLError ("Unrecognised Assetmap namespace " + asset_map.namespace_uri()));
- }
-
- auto asset_nodes = asset_map.node_child("AssetList")->node_children ("Asset");
- map<string, boost::filesystem::path> paths;
- vector<boost::filesystem::path> pkl_paths;
- for (auto i: asset_nodes) {
- if (i->node_child("ChunkList")->node_children("Chunk").size() != 1) {
- boost::throw_exception (XMLError ("unsupported asset chunk count"));
- }
- auto p = i->node_child("ChunkList")->node_child("Chunk")->string_child ("Path");
- if (starts_with (p, "file://")) {
- p = p.substr (7);
- }
- switch (*_standard) {
- case Standard::INTEROP:
- if (i->optional_node_child("PackingList")) {
- pkl_paths.push_back (p);
- } else {
- paths.insert (make_pair(remove_urn_uuid(i->string_child("Id")), p));
- }
- break;
- case Standard::SMPTE:
- {
- auto pkl_bool = i->optional_string_child("PackingList");
- if (pkl_bool && *pkl_bool == "true") {
- pkl_paths.push_back (p);
- } else {
- paths.insert (make_pair(remove_urn_uuid(i->string_child("Id")), p));
- }
- break;
- }
- }
- }
+ _asset_map = AssetMap(asset_map_path);
+ auto const pkl_paths = _asset_map->pkl_paths();
+ auto const standard = _asset_map->standard();
if (pkl_paths.empty()) {
boost::throw_exception (XMLError ("No packing lists found in asset map"));
}
for (auto i: pkl_paths) {
- _pkls.push_back (make_shared<PKL>(_directory / i));
+ _pkls.push_back(make_shared<PKL>(i));
}
/* Now we have:
*/
vector<shared_ptr<Asset>> other_assets;
- for (auto i: paths) {
- auto path = _directory / i.second;
-
- if (i.second.empty()) {
+ auto paths = _asset_map->paths();
+ for (auto path: paths) {
+ if (path.second == _directory) {
/* I can't see how this is valid, but it's
been seen in the wild with a DCP that
claims to come from ClipsterDCI 5.10.0.5.
continue;
}
- if (!boost::filesystem::exists(path)) {
+ if (!boost::filesystem::exists(path.second)) {
if (notes) {
- notes->push_back ({VerificationNote::Type::ERROR, VerificationNote::Code::MISSING_ASSET, path});
+ notes->push_back ({VerificationNote::Type::ERROR, VerificationNote::Code::MISSING_ASSET, path.second});
}
continue;
}
/* Find the <Type> for this asset from the PKL that contains the asset */
optional<string> pkl_type;
for (auto j: _pkls) {
- pkl_type = j->type(i.first);
+ pkl_type = j->type(path.first);
if (pkl_type) {
break;
}
pkl_type = pkl_type->substr(0, pkl_type->find(";"));
if (
- pkl_type == remove_parameters(CPL::static_pkl_type(*_standard)) ||
- pkl_type == remove_parameters(InteropSubtitleAsset::static_pkl_type(*_standard))) {
+ pkl_type == remove_parameters(CPL::static_pkl_type(standard)) ||
+ pkl_type == remove_parameters(InteropSubtitleAsset::static_pkl_type(standard))) {
auto p = new xmlpp::DomParser;
try {
- p->parse_file (path.string());
+ p->parse_file (path.second.string());
} catch (std::exception& e) {
delete p;
- throw ReadError(String::compose("XML error in %1", path.string()), e.what());
+ throw ReadError(String::compose("XML error in %1", path.second.string()), e.what());
}
auto const root = p->get_document()->get_root_node()->get_name();
delete p;
if (root == "CompositionPlaylist") {
- auto cpl = make_shared<CPL>(path);
- if (_standard && cpl->standard() != _standard.get() && notes) {
+ auto cpl = make_shared<CPL>(path.second);
+ if (cpl->standard() != standard && notes) {
notes->push_back ({VerificationNote::Type::ERROR, VerificationNote::Code::MISMATCHED_STANDARD});
}
_cpls.push_back (cpl);
} else if (root == "DCSubtitle") {
- if (_standard && _standard.get() == Standard::SMPTE && notes) {
+ if (standard == Standard::SMPTE && notes) {
notes->push_back (VerificationNote(VerificationNote::Type::ERROR, VerificationNote::Code::MISMATCHED_STANDARD));
}
- other_assets.push_back (make_shared<InteropSubtitleAsset>(path));
+ other_assets.push_back (make_shared<InteropSubtitleAsset>(path.second));
}
} else if (
- *pkl_type == remove_parameters(PictureAsset::static_pkl_type(*_standard)) ||
- *pkl_type == remove_parameters(SoundAsset::static_pkl_type(*_standard)) ||
- *pkl_type == remove_parameters(AtmosAsset::static_pkl_type(*_standard)) ||
- *pkl_type == remove_parameters(SMPTESubtitleAsset::static_pkl_type(*_standard))
+ *pkl_type == remove_parameters(PictureAsset::static_pkl_type(standard)) ||
+ *pkl_type == remove_parameters(SoundAsset::static_pkl_type(standard)) ||
+ *pkl_type == remove_parameters(AtmosAsset::static_pkl_type(standard)) ||
+ *pkl_type == remove_parameters(SMPTESubtitleAsset::static_pkl_type(standard))
) {
bool found_threed_marked_as_twod = false;
- other_assets.push_back (asset_factory(path, ignore_incorrect_picture_mxf_type, &found_threed_marked_as_twod));
+ other_assets.push_back (asset_factory(path.second, ignore_incorrect_picture_mxf_type, &found_threed_marked_as_twod));
if (found_threed_marked_as_twod && notes) {
- notes->push_back ({VerificationNote::Type::WARNING, VerificationNote::Code::THREED_ASSET_MARKED_AS_TWOD, path});
+ notes->push_back ({VerificationNote::Type::WARNING, VerificationNote::Code::THREED_ASSET_MARKED_AS_TWOD, path.second});
}
- } else if (*pkl_type == remove_parameters(FontAsset::static_pkl_type(*_standard))) {
- other_assets.push_back (make_shared<FontAsset>(i.first, path));
+ } else if (*pkl_type == remove_parameters(FontAsset::static_pkl_type(standard))) {
+ other_assets.push_back (make_shared<FontAsset>(path.first, path.second));
} else if (*pkl_type == "image/png") {
/* It's an Interop PNG subtitle; let it go */
} else {
}
-void
-DCP::write_assetmap (
- Standard standard, string pkl_uuid, boost::filesystem::path pkl_path,
- string issuer, string creator, string issue_date, string annotation_text
- ) const
-{
- auto p = _directory;
-
- switch (standard) {
- case Standard::INTEROP:
- p /= "ASSETMAP";
- break;
- case Standard::SMPTE:
- p /= "ASSETMAP.xml";
- break;
- default:
- DCP_ASSERT (false);
- }
-
- xmlpp::Document doc;
- xmlpp::Element* root;
-
- switch (standard) {
- case Standard::INTEROP:
- root = doc.create_root_node ("AssetMap", assetmap_interop_ns);
- break;
- case Standard::SMPTE:
- root = doc.create_root_node ("AssetMap", assetmap_smpte_ns);
- break;
- default:
- DCP_ASSERT (false);
- }
-
- root->add_child("Id")->add_child_text ("urn:uuid:" + make_uuid());
- root->add_child("AnnotationText")->add_child_text (annotation_text);
-
- switch (standard) {
- case Standard::INTEROP:
- root->add_child("VolumeCount")->add_child_text ("1");
- root->add_child("IssueDate")->add_child_text (issue_date);
- root->add_child("Issuer")->add_child_text (issuer);
- root->add_child("Creator")->add_child_text (creator);
- break;
- case Standard::SMPTE:
- root->add_child("Creator")->add_child_text (creator);
- root->add_child("VolumeCount")->add_child_text ("1");
- root->add_child("IssueDate")->add_child_text (issue_date);
- root->add_child("Issuer")->add_child_text (issuer);
- break;
- default:
- DCP_ASSERT (false);
- }
-
- auto asset_list = root->add_child ("AssetList");
-
- auto 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");
- auto chunk_list = asset->add_child ("ChunkList");
- auto chunk = chunk_list->add_child ("Chunk");
- chunk->add_child("Path")->add_child_text (pkl_path.filename().string());
- chunk->add_child("VolumeIndex")->add_child_text ("1");
- chunk->add_child("Offset")->add_child_text ("0");
- chunk->add_child("Length")->add_child_text (raw_convert<string> (boost::filesystem::file_size (pkl_path)));
-
- for (auto i: assets()) {
- i->write_to_assetmap (asset_list, _directory);
- }
-
- doc.write_to_file_formatted (p.string (), "UTF-8");
- _asset_map = p;
-}
-
-
void
DCP::write_xml (
string issuer,
pkl->write_xml (pkl_path, signer);
write_volindex (standard);
- write_assetmap (standard, pkl->id(), pkl_path, issuer, creator, issue_date, annotation_text);
+
+ if (!_asset_map) {
+ _asset_map = AssetMap(standard, annotation_text, issue_date, issuer, creator);
+ _asset_map->add_asset(pkl->id(), pkl_path, true);
+ for (auto asset: assets()) {
+ asset->add_to_assetmap(*_asset_map, _directory);
+ }
+ }
+
+ auto asset_map_path = _directory / (standard == Standard::INTEROP ? "ASSETMAP" : "ASSETMAP.xml");
+ _asset_map->write_xml(asset_map_path);
}
#define LIBDCP_DCP_H
+#include "asset_map.h"
#include "certificate.h"
#include "compose.hpp"
#include "metadata.h"
/** @return Standard of a DCP that was read in */
boost::optional<Standard> standard () const {
- return _standard;
+ if (!_asset_map) {
+ return {};
+ }
+
+ return _asset_map->standard();
}
boost::filesystem::path directory () const {
}
boost::optional<boost::filesystem::path> asset_map_path () {
- return _asset_map;
+ if (!_asset_map) {
+ return {};
+ }
+
+ return _asset_map->path();
}
static std::vector<boost::filesystem::path> directories_from_files (std::vector<boost::filesystem::path> files);
/** The directory that we are writing to */
boost::filesystem::path _directory;
+ boost::optional<AssetMap> _asset_map;
/** The CPLs that make up this DCP */
std::vector<std::shared_ptr<CPL>> _cpls;
/** The PKLs that make up this DCP */
std::vector<std::shared_ptr<PKL>> _pkls;
- /** File that the ASSETMAP was read from or last written to */
- mutable boost::optional<boost::filesystem::path> _asset_map;
-
- /** Standard of DCP that was read in */
- boost::optional<Standard> _standard;
};
void
-InteropSubtitleAsset::write_to_assetmap (xmlpp::Node* node, boost::filesystem::path root) const
+InteropSubtitleAsset::add_to_assetmap (AssetMap& asset_map, boost::filesystem::path root) const
{
- Asset::write_to_assetmap (node, root);
+ Asset::add_to_assetmap (asset_map, root);
for (auto i: _subtitles) {
auto im = dynamic_pointer_cast<dcp::SubtitleImage> (i);
if (im) {
- DCP_ASSERT (im->file());
- write_file_to_assetmap (node, root, im->file().get(), im->id());
+ DCP_ASSERT(im->file());
+ add_file_to_assetmap(asset_map, root, im->file().get(), im->id());
}
}
}
namespace dcp {
+class AssetMap;
class InteropLoadFontNode;
NoteHandler note
) const override;
- void write_to_assetmap (xmlpp::Node* node, boost::filesystem::path root) const override;
+ void add_to_assetmap (AssetMap& asset_map, boost::filesystem::path root) const override;
void add_to_pkl (std::shared_ptr<PKL> pkl, boost::filesystem::path root) const override;
std::vector<std::shared_ptr<LoadFontNode>> load_font_nodes () const override;
array_data.cc
asset.cc
asset_factory.cc
+ asset_map.cc
asset_writer.cc
atmos_asset.cc
atmos_asset_writer.cc
/** Test dcp::relative_to_root */
BOOST_AUTO_TEST_CASE (relative_to_root_test)
{
+ using namespace boost::filesystem;
+
+ path const base = "build/test/relative_to_root_test";
+
{
- boost::filesystem::path root = "a";
+ path root = base / "a";
root /= "b";
- boost::filesystem::path file = "a";
+ path file = base / "a";
file /= "b";
file /= "c";
- boost::optional<boost::filesystem::path> rel = dcp::relative_to_root (root, file);
+ boost::system::error_code ec;
+ create_directories(root, ec);
+ create_directories(file, ec);
+
+ auto rel = dcp::relative_to_root (root, file);
BOOST_CHECK (rel);
- BOOST_CHECK_EQUAL (rel.get(), boost::filesystem::path ("c"));
+ BOOST_CHECK_EQUAL (rel.get(), path("c"));
}
{
- boost::filesystem::path root = "a";
+ path root = "a";
root /= "b";
root /= "c";
- boost::filesystem::path file = "a";
+ path file = "a";
file /= "b";
- boost::optional<boost::filesystem::path> rel = dcp::relative_to_root (root, file);
+ boost::system::error_code ec;
+ create_directories(root, ec);
+ create_directories(file, ec);
+
+ auto rel = dcp::relative_to_root (root, file);
BOOST_CHECK (!rel);
}
{
- boost::filesystem::path root = "a";
+ path root = "a";
- boost::filesystem::path file = "a";
+ path file = "a";
file /= "b";
file /= "c";
- boost::optional<boost::filesystem::path> rel = dcp::relative_to_root (root, file);
+ boost::system::error_code ec;
+ create_directories(root, ec);
+ create_directories(file, ec);
+
+ auto rel = dcp::relative_to_root (root, file);
BOOST_CHECK (rel);
- boost::filesystem::path check = "b";
+ path check = "b";
check /= "c";
BOOST_CHECK_EQUAL (rel.get(), check);
}