From: Carl Hetherington Date: Sun, 10 Jan 2016 14:13:43 +0000 (+0000) Subject: Template Package and bring some stuff up to there and PackageBase. X-Git-Url: https://git.carlh.net/gitweb/?a=commitdiff_plain;h=0ffc4c35a9ae232f3bed9329997c043c42372f6f;p=libdcp.git Template Package and bring some stuff up to there and PackageBase. --- diff --git a/src/dc_package.cc b/src/dc_package.cc index e1c69b63..b78f3e85 100644 --- a/src/dc_package.cc +++ b/src/dc_package.cc @@ -66,38 +66,11 @@ using boost::algorithm::starts_with; using namespace dcp::dc; Package::Package (boost::filesystem::path directory) - : dcp::Package (directory) + : dcp::Package (directory) { } -void -Package::read (bool keep_going, ReadErrors* errors) -{ - list > other_assets; - - BOOST_FOREACH (shared_ptr i, read_assetmap (keep_going, errors)) { - shared_ptr cpl = dynamic_pointer_cast (i); - if (cpl) { - _cpls.push_back (cpl); - } else { - other_assets.push_back (i); - } - } - - BOOST_FOREACH (shared_ptr i, cpls ()) { - i->resolve_refs (other_assets); - } -} - -void -Package::resolve_refs (list > assets) -{ - BOOST_FOREACH (shared_ptr i, cpls ()) { - i->resolve_refs (assets); - } -} - bool Package::equals (Package const & other, dcp::EqualityOptions opt, dcp::NoteHandler note) const { @@ -198,110 +171,6 @@ Package::write_pkl (dcp::Standard standard, string pkl_uuid, dcp::XMLMetadata me return p.string (); } -/** Write the VOLINDEX file. - * @param standard DCP standard to use (INTEROP or SMPTE) - */ -void -Package::write_volindex (Standard standard) const -{ - boost::filesystem::path p = _directory; - switch (standard) { - case DCP_INTEROP: - p /= "VOLINDEX"; - break; - case DCP_SMPTE: - p /= "VOLINDEX.xml"; - break; - case IMP: - /* XXX */ - DCP_ASSERT (false); - break; - } - - xmlpp::Document doc; - xmlpp::Element* root = 0; - - switch (standard) { - case DCP_INTEROP: - root = doc.create_root_node ("VolumeIndex", "http://www.digicine.com/PROTO-ASDCP-AM-20040311#"); - break; - case DCP_SMPTE: - case IMP: - root = doc.create_root_node ("VolumeIndex", "http://www.smpte-ra.org/schemas/429-9/2007/AM"); - break; - } - - root->add_child("Index")->add_child_text ("1"); - doc.write_to_file (p.string (), "UTF-8"); -} - -void -Package::write_assetmap (Standard standard, string pkl_uuid, int pkl_length, dcp::XMLMetadata metadata) const -{ - boost::filesystem::path p = _directory; - - switch (standard) { - case DCP_INTEROP: - p /= "ASSETMAP"; - break; - case DCP_SMPTE: - case IMP: - p /= "ASSETMAP.xml"; - break; - } - - xmlpp::Document doc; - xmlpp::Element* root = 0; - - switch (standard) { - case DCP_INTEROP: - root = doc.create_root_node ("AssetMap", "http://www.digicine.com/PROTO-ASDCP-AM-20040311#"); - break; - case DCP_SMPTE: - case IMP: - root = doc.create_root_node ("AssetMap", "http://www.smpte-ra.org/schemas/429-9/2007/AM"); - break; - } - - root->add_child("Id")->add_child_text ("urn:uuid:" + make_uuid()); - root->add_child("AnnotationText")->add_child_text ("Created by " + metadata.creator); - - switch (standard) { - case DCP_INTEROP: - 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); - root->add_child("Creator")->add_child_text (metadata.creator); - break; - case DCP_SMPTE: - case IMP: - 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); - break; - } - - 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_" + pkl_uuid + ".xml"); - 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 (pkl_length)); - - BOOST_FOREACH (shared_ptr i, assets ()) { - i->write_to_assetmap (asset_list, _directory); - } - - /* This must not be the _formatted version otherwise signature digests will be wrong */ - doc.write_to_file (p.string (), "UTF-8"); -} - /** Write all the XML files for this DCP. * @param standand INTEROP or SMPTE. * @param metadata Metadata to use for PKL and asset map files. diff --git a/src/dc_package.h b/src/dc_package.h index eb194398..c0348419 100644 --- a/src/dc_package.h +++ b/src/dc_package.h @@ -56,7 +56,7 @@ class DCPReadError; /** @class Package * @brief A class to create or read a DCP. */ -class Package : public dcp::Package +class Package : public dcp::Package { public: /** Construct a DCP package. You can pass an existing DCP's directory @@ -68,12 +68,6 @@ public: */ Package (boost::filesystem::path directory); - /** Read the DCP's structure into this object. - * @param keep_going true to try to keep going in the face of (some) errors. - * @param errors List of errors that will be added to if keep_going is true. - */ - void read (bool keep_going = false, ReadErrors* errors = 0); - /** Compare this DCP with another, according to various options. * @param other DCP to compare this one to. * @param options Options to define what "equality" means. @@ -111,19 +105,8 @@ private: boost::shared_ptr signer ) const; - void write_volindex (Standard standard) const; - - /** Write the ASSETMAP file. - * @param pkl_uuid UUID of our PKL. - * @param pkl_length Length of our PKL in bytes. - */ - void write_assetmap (Standard standard, std::string pkl_uuid, int pkl_length, XMLMetadata metadata) const; - boost::shared_ptr xml_asset_factory (boost::filesystem::path file, std::string root) const; boost::shared_ptr mxf_asset_factory (boost::filesystem::path file) const; - - /** the CPLs that make up this DCP */ - std::list > _cpls; }; } diff --git a/src/im_package.cc b/src/im_package.cc index aeef6760..852f3505 100644 --- a/src/im_package.cc +++ b/src/im_package.cc @@ -22,7 +22,14 @@ using namespace dcp::im; Package::Package (boost::filesystem::path directory) - : dcp::Package (directory) + : dcp::Package (directory) { } + +list +Package::assets () const +{ + /* XXX */ + return list (); +} diff --git a/src/im_package.h b/src/im_package.h index 46c0872d..4056ae8e 100644 --- a/src/im_package.h +++ b/src/im_package.h @@ -20,10 +20,12 @@ namespace dcp { namespace im { -class Package : public dcp::Package +class Package : public dcp::Package { public: Package (boost::filesystem::path directory); + + std::list > assets () const; }; } diff --git a/src/package.cc b/src/package.cc deleted file mode 100644 index 74ab725c..00000000 --- a/src/package.cc +++ /dev/null @@ -1,118 +0,0 @@ -/* - Copyright (C) 2012-2016 Carl Hetherington - - 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 - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program 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 this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -*/ - -#include "package.h" -#include "compose.hpp" -#include "exceptions.h" -#include "util.h" -#include "font_asset.h" -#include -#include -#include -#include - -using std::list; -using std::map; -using std::string; -using boost::shared_ptr; -using boost::algorithm::starts_with; -using namespace dcp; - -Package::Package (boost::filesystem::path directory) -{ - if (!boost::filesystem::exists (directory)) { - boost::filesystem::create_directories (directory); - } - - _directory = boost::filesystem::canonical (directory); -} - -list > -Package::read_assetmap (bool keep_going, ReadErrors* errors) const -{ - boost::filesystem::path asset_map_file; - if (boost::filesystem::exists (_directory / "ASSETMAP")) { - asset_map_file = _directory / "ASSETMAP"; - } else if (boost::filesystem::exists (_directory / "ASSETMAP.xml")) { - asset_map_file = _directory / "ASSETMAP.xml"; - } else { - boost::throw_exception (PackageReadError (String::compose ("could not find AssetMap file in `%1'", _directory.string()))); - } - - cxml::Document asset_map ("AssetMap"); - asset_map.read_file (asset_map_file); - list > asset_nodes = asset_map.node_child("AssetList")->node_children ("Asset"); - map paths; - BOOST_FOREACH (shared_ptr i, asset_nodes) { - if (i->node_child("ChunkList")->node_children("Chunk").size() != 1) { - boost::throw_exception (XMLError ("unsupported asset chunk count")); - } - string p = i->node_child("ChunkList")->node_child("Chunk")->string_child ("Path"); - if (starts_with (p, "file://")) { - p = p.substr (7); - } - paths.insert (make_pair (remove_urn_uuid (i->string_child ("Id")), p)); - } - - /* Read all the assets from the asset map */ - /* XXX: I think we should be looking at the PKL here to decide type, not - the extension of the file. - */ - - list > assets; - - for (map::const_iterator i = paths.begin(); i != paths.end(); ++i) { - boost::filesystem::path path = _directory / i->second; - - if (!boost::filesystem::exists (path)) { - if (keep_going) { - if (errors) { - errors->push_back (shared_ptr (new MissingAssetError (path))); - } - } else { - throw MissingAssetError (path); - } - continue; - } - - if (boost::filesystem::extension(path) == ".xml") { - xmlpp::DomParser* p = new xmlpp::DomParser; - try { - p->parse_file (path.string()); - } catch (std::exception& e) { - delete p; - continue; - } - - string const root = p->get_document()->get_root_node()->get_name (); - delete p; - - shared_ptr a = xml_asset_factory (path, root); - if (a) { - assets.push_back (a); - } - } else if (boost::filesystem::extension (path) == ".mxf") { - assets.push_back (mxf_asset_factory (path)); - } else if (boost::filesystem::extension (path) == ".ttf") { - assets.push_back (shared_ptr (new FontAsset (i->first, path))); - } - } - - return assets; -} diff --git a/src/package.h b/src/package.h index b3d3b4ed..ac33ac9f 100644 --- a/src/package.h +++ b/src/package.h @@ -20,29 +20,52 @@ #ifndef LIBDCP_PACKAGE_H #define LIBDCP_PACKAGE_H -#include "exceptions.h" -#include +#include "package_base.h" +#include "dc_cpl.h" +#include namespace dcp { class Asset; -class Package +template +class Package : public PackageBase { public: - Package (boost::filesystem::path directory); - - typedef std::list > ReadErrors; + Package (boost::filesystem::path directory) + : PackageBase (directory) + { + + } + + void read (bool keep_going = false, ReadErrors* errors = 0) + { + std::list > other_assets; + + BOOST_FOREACH (boost::shared_ptr i, read_assetmap (keep_going, errors)) { + boost::shared_ptr cpl = boost::dynamic_pointer_cast (i); + if (cpl) { + _cpls.push_back (cpl); + } else { + other_assets.push_back (i); + } + } + + BOOST_FOREACH (boost::shared_ptr i, _cpls) { + i->resolve_refs (other_assets); + } + } + + void resolve_refs (std::list > assets) + { + BOOST_FOREACH (boost::shared_ptr i, _cpls) { + i->resolve_refs (assets); + } + } protected: - - virtual boost::shared_ptr xml_asset_factory (boost::filesystem::path file, std::string root) const = 0; - virtual boost::shared_ptr mxf_asset_factory (boost::filesystem::path file) const = 0; - - std::list > read_assetmap (bool keep_going, ReadErrors* errors) const; - - /** the directory that the package is in */ - boost::filesystem::path _directory; + /** the CPLs that make up this package */ + std::list > _cpls; }; } diff --git a/src/package_base.cc b/src/package_base.cc new file mode 100644 index 00000000..aa4658d2 --- /dev/null +++ b/src/package_base.cc @@ -0,0 +1,225 @@ +/* + Copyright (C) 2012-2016 Carl Hetherington + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include "package_base.h" +#include "compose.hpp" +#include "exceptions.h" +#include "util.h" +#include "dcp_assert.h" +#include "font_asset.h" +#include "raw_convert.h" +#include +#include +#include +#include + +using std::list; +using std::map; +using std::string; +using boost::shared_ptr; +using boost::algorithm::starts_with; +using namespace dcp; + +PackageBase::PackageBase (boost::filesystem::path directory) +{ + if (!boost::filesystem::exists (directory)) { + boost::filesystem::create_directories (directory); + } + + _directory = boost::filesystem::canonical (directory); +} + +list > +PackageBase::read_assetmap (bool keep_going, ReadErrors* errors) const +{ + boost::filesystem::path asset_map_file; + if (boost::filesystem::exists (_directory / "ASSETMAP")) { + asset_map_file = _directory / "ASSETMAP"; + } else if (boost::filesystem::exists (_directory / "ASSETMAP.xml")) { + asset_map_file = _directory / "ASSETMAP.xml"; + } else { + boost::throw_exception (PackageReadError (String::compose ("could not find AssetMap file in `%1'", _directory.string()))); + } + + cxml::Document asset_map ("AssetMap"); + asset_map.read_file (asset_map_file); + list > asset_nodes = asset_map.node_child("AssetList")->node_children ("Asset"); + map paths; + BOOST_FOREACH (shared_ptr i, asset_nodes) { + if (i->node_child("ChunkList")->node_children("Chunk").size() != 1) { + boost::throw_exception (XMLError ("unsupported asset chunk count")); + } + string p = i->node_child("ChunkList")->node_child("Chunk")->string_child ("Path"); + if (starts_with (p, "file://")) { + p = p.substr (7); + } + paths.insert (make_pair (remove_urn_uuid (i->string_child ("Id")), p)); + } + + /* Read all the assets from the asset map */ + /* XXX: I think we should be looking at the PKL here to decide type, not + the extension of the file. + */ + + list > assets; + + for (map::const_iterator i = paths.begin(); i != paths.end(); ++i) { + boost::filesystem::path path = _directory / i->second; + + if (!boost::filesystem::exists (path)) { + if (keep_going) { + if (errors) { + errors->push_back (shared_ptr (new MissingAssetError (path))); + } + } else { + throw MissingAssetError (path); + } + continue; + } + + if (boost::filesystem::extension(path) == ".xml") { + xmlpp::DomParser* p = new xmlpp::DomParser; + try { + p->parse_file (path.string()); + } catch (std::exception& e) { + delete p; + continue; + } + + string const root = p->get_document()->get_root_node()->get_name (); + delete p; + + shared_ptr a = xml_asset_factory (path, root); + if (a) { + assets.push_back (a); + } + } else if (boost::filesystem::extension (path) == ".mxf") { + assets.push_back (mxf_asset_factory (path)); + } else if (boost::filesystem::extension (path) == ".ttf") { + assets.push_back (shared_ptr (new FontAsset (i->first, path))); + } + } + + return assets; +} + + +/** Write the VOLINDEX file. + * @param standard DCP standard to use (INTEROP or SMPTE) + */ +void +PackageBase::write_volindex (Standard standard) const +{ + boost::filesystem::path p = _directory; + switch (standard) { + case DCP_INTEROP: + p /= "VOLINDEX"; + break; + case DCP_SMPTE: + p /= "VOLINDEX.xml"; + break; + case IMP: + /* XXX */ + DCP_ASSERT (false); + break; + } + + xmlpp::Document doc; + xmlpp::Element* root = 0; + + switch (standard) { + case DCP_INTEROP: + root = doc.create_root_node ("VolumeIndex", "http://www.digicine.com/PROTO-ASDCP-AM-20040311#"); + break; + case DCP_SMPTE: + case IMP: + root = doc.create_root_node ("VolumeIndex", "http://www.smpte-ra.org/schemas/429-9/2007/AM"); + break; + } + + root->add_child("Index")->add_child_text ("1"); + doc.write_to_file (p.string (), "UTF-8"); +} + +void +PackageBase::write_assetmap (Standard standard, string pkl_uuid, int pkl_length, dcp::XMLMetadata metadata) const +{ + boost::filesystem::path p = _directory; + + switch (standard) { + case DCP_INTEROP: + p /= "ASSETMAP"; + break; + case DCP_SMPTE: + case IMP: + p /= "ASSETMAP.xml"; + break; + } + + xmlpp::Document doc; + xmlpp::Element* root = 0; + + switch (standard) { + case DCP_INTEROP: + root = doc.create_root_node ("AssetMap", "http://www.digicine.com/PROTO-ASDCP-AM-20040311#"); + break; + case DCP_SMPTE: + case IMP: + root = doc.create_root_node ("AssetMap", "http://www.smpte-ra.org/schemas/429-9/2007/AM"); + break; + } + + root->add_child("Id")->add_child_text ("urn:uuid:" + make_uuid()); + root->add_child("AnnotationText")->add_child_text ("Created by " + metadata.creator); + + switch (standard) { + case DCP_INTEROP: + 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); + root->add_child("Creator")->add_child_text (metadata.creator); + break; + case DCP_SMPTE: + case IMP: + 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); + break; + } + + 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_" + pkl_uuid + ".xml"); + 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 (pkl_length)); + + BOOST_FOREACH (shared_ptr i, assets ()) { + i->write_to_assetmap (asset_list, _directory); + } + + /* This must not be the _formatted version otherwise signature digests will be wrong */ + doc.write_to_file (p.string (), "UTF-8"); +} diff --git a/src/package_base.h b/src/package_base.h new file mode 100644 index 00000000..090d9955 --- /dev/null +++ b/src/package_base.h @@ -0,0 +1,62 @@ +/* + Copyright (C) 2012-2016 Carl Hetherington + + 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 + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program 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 this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef LIBDCP_PACKAGE_BASE_H +#define LIBDCP_PACKAGE_BASE_H + +#include "exceptions.h" +#include "types.h" +#include "metadata.h" +#include + +namespace dcp { + +class Asset; + +class PackageBase +{ +public: + PackageBase (boost::filesystem::path directory); + + typedef std::list > ReadErrors; + + virtual std::list > assets () const = 0; + +protected: + + virtual boost::shared_ptr xml_asset_factory (boost::filesystem::path file, std::string root) const = 0; + virtual boost::shared_ptr mxf_asset_factory (boost::filesystem::path file) const = 0; + + std::list > read_assetmap (bool keep_going, ReadErrors* errors) const; + + void write_volindex (Standard standard) const; + + /** Write the ASSETMAP file. + * @param pkl_uuid UUID of our PKL. + * @param pkl_length Length of our PKL in bytes. + */ + void write_assetmap (Standard standard, std::string pkl_uuid, int pkl_length, XMLMetadata metadata) const; + + /** the directory that the package is in */ + boost::filesystem::path _directory; +}; + +} + +#endif diff --git a/src/wscript b/src/wscript index ff722325..8442c6de 100644 --- a/src/wscript +++ b/src/wscript @@ -51,7 +51,7 @@ def build(bld): asset_writer.cc object.cc openjpeg_image.cc - package.cc + package_base.cc picture_asset.cc picture_asset_writer.cc reel.cc diff --git a/tools/common.cc b/tools/common.cc index c8b7c606..ed1e823a 100644 --- a/tools/common.cc +++ b/tools/common.cc @@ -27,9 +27,9 @@ using boost::dynamic_pointer_cast; void dcp::filter_errors (dcp::dc::Package::ReadErrors& errors, bool ignore_missing_assets) { - for (Package::ReadErrors::iterator i = errors.begin(); i != errors.end(); ) { + for (PackageBase::ReadErrors::iterator i = errors.begin(); i != errors.end(); ) { - Package::ReadErrors::iterator tmp = i; + PackageBase::ReadErrors::iterator tmp = i; ++tmp; if (ignore_missing_assets && dynamic_pointer_cast (*i)) {