From: Carl Hetherington Date: Mon, 30 Jul 2012 21:03:25 +0000 (+0100) Subject: Hacks. X-Git-Tag: v0.06~16 X-Git-Url: https://main.carlh.net/gitweb/?a=commitdiff_plain;h=34a25d89b16a33b5f619ae0eaaa03c17f93980af;p=libdcp.git Hacks. --- diff --git a/src/cpl.cc b/src/cpl.cc new file mode 100644 index 00000000..1eba666c --- /dev/null +++ b/src/cpl.cc @@ -0,0 +1,16 @@ +#include "cpl.h" + +CPL::CPL (string file) +{ + file_is (file); + + _id = string_tag ("Id"); + _annotation_text = string_tag ("AnnotationText"); + _issue_date = string_tag ("IssueDate"); + _creator = string_tag ("Creator"); + _content_title_text = string_tag ("ContentTitleText"); + _content_kind = kind_tag ("ContentKind"); + _content_version = sub (new ContentVersion, "ContentVersion"); + ignore ("RatingList"); + _reel_list = sub (new ReelList, "ReelList"); +} diff --git a/src/cpl.h b/src/cpl.h new file mode 100644 index 00000000..6ec55e61 --- /dev/null +++ b/src/cpl.h @@ -0,0 +1,8 @@ +#include "xml.h" + +class CPL : public XML +{ +public: + CPL (std::string file); + +}; diff --git a/src/dcp.cc b/src/dcp.cc index 27ae9636..8c74ea8e 100644 --- a/src/dcp.cc +++ b/src/dcp.cc @@ -239,32 +239,152 @@ DCP::write_assetmap (string cpl_uuid, int cpl_length, string pkl_uuid, int pkl_l << "\n"; } -string -DCP::content_type_string (ContentType type) + +DCP::DCP (string directory) + : _directory (directory) +{ + string cpl; + string pkl; + string asset_map; + + for (filesystem::directory_iterator i = filesystem::directory_iterator(directory); i != filesystem::directory_iterator(); ++i) { + string const t = i->path()->string (); + if (ends_with (t, "_cpl.xml")) { + if (cpl.empty ()) { + cpl = t; + } else { + throw DCPReadError ("duplicate CPLs found"); + } + } else if (ends_with (t, "_pkl.xml")) { + if (pkl.empty ()) { + pkl = t; + } else { + throw DCPReadError ("duplicate PKLs found"); + } + } else if (ends_with (t, "ASSETMAP.xml")) { + if (asset_map.empty ()) { + asset_map = t; + } else { + throw DCPReadError ("duplicate AssetMaps found"); + } + } + } + + load_cpl (cpl); + load_pkl (pkl); + load_asset_map (asset_map); +} + +void +DCP::load_cpl (string file) { - switch (type) { - case FEATURE: - return "feature"; - case SHORT: - return "short"; - case TRAILER: - return "trailer"; - case TEST: - return "test"; - case TRANSITIONAL: - return "transitional"; - case RATING: - return "rating"; - case TEASER: - return "teaser"; - case POLICY: - return "policy"; - case PUBLIC_SERVICE_ANNOUNCEMENT: - return "psa"; - case ADVERTISEMENT: - return "advertisement"; + xmlpp::DOMParser parser; + parser.parser_file (file); + if (!parser) { + throw DCPReadError ("could not create parser for CPL"); } - assert (false); + xmlpp::Element* root = parser.get_document()->get_root_node (); + dcp_read_assert (root->get_name() == "CompositionPlaylist", "unrecognised CPL format"); + + xmlpp::Node::NodeList children = root->get_children (); + for (xmlpp::Node::NodeList::iterator i = children.begin(); i != children.end(); ++i) { + bool taken = false; + xml_maybe (*i, taken, _cpl_id, "Id"); + xml_maybe (*i, taken, _annotation_text, "AnnotationText"); + xml_maybe (*i, taken, _issue_date, "IssueDate"); + xml_maybe (*i, taken, _creator, "Creator"); + xml_maybe (*i, taken, _content_title_text, "ContentTitleText"); + xml_maybe (*i, taken, _content_kind, "ContentKind"); + + if ((*i)->get_name() == "ContentVersion") { + taken = true; + load_cpl_content_version (*i); + } + + if ((*i)->get_name() == "RatingList") { + taken = true; + } + + if ((*i)->get_name() == "ReelList") { + taken = true; + load_cpl_reel_list (*i); + } + + xml_assert_taken (*i, taken); + } } + +void +DCP::load_cpl_content_version (xmlpp::Node const * node) +{ + xmlpp::Node::NodeList children = node->get_children (); + for (xmlpp::Node::NodeList::iterator i = children.begin(); i != children.end(); ++i) { + bool taken = false; + xml_maybe (*i, taken, _content_version_id, "Id"); + xml_maybe (*i, taken, _content_version_label_text, "LabelText"); + xml_assert_taken (*i, taken); + } +} + +void +DCP::load_cpl_reel_list (xmlpp::Node const * node) +{ + xmlpp::Node::NodeList children = node->get_children (); + bool had_reel = false; + for (xmlpp::Node::NodeList::iterator i = children.begin(); i != children.end(); ++i) { + bool taken = false; + if ((*i)->get_name() == "Reel") { + if (!had_reel) { + load_cpl_reel (*i); + had_reel = true; + } else { + throw DCPReadError ("multiple reels not supported"); + } + } + xml_assert_taken (*i, taken); + } +} + +void +DCP::load_cpl_reel (xmlpp::Node const * node) +{ + xmlpp::Node::NodeList children = node->get_children (); + for (xmlpp::Node::NodeList::iterator i = children.begin(); i != children.end(); ++i) { + bool taken = false; + xml_taken (*i, taken, _reel_id, "Id"); + if ((*i)->name() == "AssetList") { + taken = true; + load_cpl_asset_list (*i); + } + xml_assert_taken (*i, taken); + } +} + +void +DCP::load_cpl_asset_list (xmlpp::Node const * node) +{ + xmlpp::Node::NodeList children = node->get_children (); + for (xmlpp::Node::NodeList::iterator i = children.begin(); i != children.end(); ++i) { + bool taken = false; + if ((*i)->name() == "MainPicture") { + taken = true; + load_cpl_main_picture (*i); + } else if ((*i)->name() == "MainSound") { + taken = true; + load_cpl_main_sound (*i); + } + xml_assert_taken (*i, taken); + } +} + +void +DCP::load_cpl_main_picture (xmlpp::Node const * node) +{ + xmlpp::Node::NodeList children = node->get_children (); + for (xmlpp::Node::NodeList::iterator i = children.begin(); i != children.end(); ++i) { + bool taken = false; + xml_maybe (*i, taken, _video_id, "Id"); + } +} diff --git a/src/dcp.h b/src/dcp.h index 828a6e75..9407c9c7 100644 --- a/src/dcp.h +++ b/src/dcp.h @@ -30,6 +30,10 @@ #include #include "types.h" +namespace xmlpp { + class Node; +} + /** @brief Namespace for everything in libdcp */ namespace libdcp { @@ -43,20 +47,6 @@ class Asset; class DCP { public: - enum ContentType - { - FEATURE, - SHORT, - TRAILER, - TEST, - TRANSITIONAL, - RATING, - TEASER, - POLICY, - PUBLIC_SERVICE_ANNOUNCEMENT, - ADVERTISEMENT - }; - /** Construct a DCP. * @param directory Directory to write files to. * @param name Name. @@ -66,6 +56,8 @@ public: */ DCP (std::string directory, std::string name, ContentType content_type, int fps, int length); + DCP (std::string directory); + /** Add a sound asset. * @param files Pathnames of WAV files to use in the order Left, Right, * Centre, Lfe (sub), Left surround, Right surround; not all files need @@ -130,11 +122,6 @@ private: */ void write_assetmap (std::string cpl_uuid, int cpl_length, std::string pkl_uuid, int pkl_length) const; - /** @param type A content type. - * @return A string representation suitable for use in a CPL. - */ - static std::string content_type_string (ContentType type); - /** the directory that we are writing to */ std::string _directory; /** the name of the DCP */ diff --git a/src/types.h b/src/types.h index e2b91670..63f52f3e 100644 --- a/src/types.h +++ b/src/types.h @@ -37,6 +37,20 @@ enum Channel { RS = 5 ///< right surround }; +enum ContentType +{ + FEATURE, + SHORT, + TRAILER, + TEST, + TRANSITIONAL, + RATING, + TEASER, + POLICY, + PUBLIC_SERVICE_ANNOUNCEMENT, + ADVERTISEMENT +}; + } #endif diff --git a/src/util.cc b/src/util.cc index 849b7d24..9b650fa4 100644 --- a/src/util.cc +++ b/src/util.cc @@ -86,3 +86,42 @@ libdcp::make_digest (string filename, sigc::signal1* progress) char digest[64]; return Kumu::base64encode (byte_buffer, 20, digest, 64); } + +string +libdcp::content_type_to_string (ContentType type) +{ + switch (type) { + case FEATURE: + return "feature"; + case SHORT: + return "short"; + case TRAILER: + return "trailer"; + case TEST: + return "test"; + case TRANSITIONAL: + return "transitional"; + case RATING: + return "rating"; + case TEASER: + return "teaser"; + case POLICY: + return "policy"; + case PUBLIC_SERVICE_ANNOUNCEMENT: + return "psa"; + case ADVERTISEMENT: + return "advertisement"; + } + + assert (false); +} + +bool +libdcp::ends_with (string big, string little) +{ + if (little.size() > big.size()) { + return false; + } + + return big.compare (big.length() - little.length(), little.length(), little) == 0; +} diff --git a/src/util.h b/src/util.h index b6c945a5..f4c7d286 100644 --- a/src/util.h +++ b/src/util.h @@ -39,4 +39,7 @@ extern std::string make_uuid (); */ extern std::string make_digest (std::string filename, sigc::signal1* progress); +extern std::string content_type_to_string (ContentType type); +extern bool ends_with (std::string big, std::string little); + } diff --git a/src/xml.cc b/src/xml.cc new file mode 100644 index 00000000..3863bdff --- /dev/null +++ b/src/xml.cc @@ -0,0 +1,34 @@ +#include "xml.h" + +XMLFile::XMLFile (string file, string root_id) +{ + xmlpp::DomParser parser; + parser.parse_file (file); + if (!parser) { + throw XMLError ("could not parse XML"); + } + + _root = parser.get_document()->get_root_node (); + if (_root->get_name() != root_id) { + throw XMLError ("unrecognised root node"); + } +} + +string +XMLFile::string_tag (string id) +{ + stringstream x; + x << _root->get_name() << "/" << id; + xmlpp::NodeSet n = _root->find (x.str ()); + if (n.empty ()) { + throw XMLError ("missing XML tag"); + } else if (n.size() > 1) { + throw XMLError ("duplicate XML tag"); + } + + xml::Node::NodeList c = n.front()->get_children (); + if (c.empty() + + + return n.front()->get_name (); +} diff --git a/src/xml.h b/src/xml.h new file mode 100644 index 00000000..5cfa4947 --- /dev/null +++ b/src/xml.h @@ -0,0 +1,6 @@ + +class XMLFile +{ +public: + XMLFile (std::string file); +};