diff --git a/CHANGELOG.md b/CHANGELOG.md index 762b0046..7ff8cbaf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Added - Added support for silent audioTrackUid references with ID 0. See `AudioTrackUid::isSilent` and `AudioTrackUid::getSilent`. +- Added `audioFormatExtended` `version` attribute; this should be set for BS.2076-2 compliance: `document->set(Version("ITU-R_BS.2076-2"));`. ### Changed - Decimal times are now written without trailing zeros past 5 decimal places. To interoperate with ADM parsers which don't support more than 5 digits, users should round times in the ADM document before writing. diff --git a/docs/reference_document.rst b/docs/reference_document.rst index 9026b132..f976ea22 100644 --- a/docs/reference_document.rst +++ b/docs/reference_document.rst @@ -4,3 +4,4 @@ ADM Document ############ .. doxygenclass:: adm::Document +.. doxygentypedef:: adm::Version diff --git a/include/adm/document.hpp b/include/adm/document.hpp index 3d7a3ed8..3e605782 100644 --- a/include/adm/document.hpp +++ b/include/adm/document.hpp @@ -2,20 +2,48 @@ #pragma once #include +#include #include #include "adm/elements.hpp" +#include "adm/detail/auto_base.hpp" #include "adm/detail/id_assigner.hpp" +#include "adm/detail/named_type.hpp" #include "adm/export.h" namespace adm { + /// tag for version + struct VersionTag {}; + /// NamedType for audioFormatExtended version attribute + using Version = detail::NamedType; + + namespace detail { + extern template class ADM_EXPORT_TEMPLATE_METHODS + OptionalParameter; + + using DocumentBase = HasParameters>; + } // namespace detail + /** - * @ingroup main * @brief Class representation of a whole ADM document - * @headerfile document.hpp * + * \rst + * +---------------+-----------------+----------------------------+ + * | ADM Parameter | Parameter Type | Pattern Type | + * +===============+=================+============================+ + * | version | :type:`Version` | :class:`OptionalParameter` | + * +---------------+-----------------+----------------------------+ + * \endrst + * + * Note that: + * - version is defined in BS.2076-2 as being required, so should be set + * manually to produce compliant documents. The version element does not + * affect parsing of other elements, so for example new defaults for old + * elements are not applied. */ - class Document : public std::enable_shared_from_this { + class Document : public std::enable_shared_from_this, + private detail::DocumentBase, + public detail::AddWrapperMethods { public: /** * @brief Static helper function to create an Document @@ -202,6 +230,12 @@ namespace adm { const AudioTrackUidId &trackUidId) const; ///@} + using detail::DocumentBase::set; + using detail::AddWrapperMethods::get; + using detail::AddWrapperMethods::has; + using detail::AddWrapperMethods::isDefault; + using detail::AddWrapperMethods::unset; + private: ADM_EXPORT Document(); ADM_EXPORT Document(const Document &) = default; @@ -251,6 +285,13 @@ namespace adm { template bool checkParent(const std::shared_ptr &element, const char *type); + using detail::DocumentBase::get; + using detail::DocumentBase::has; + using detail::DocumentBase::isDefault; + using detail::DocumentBase::unset; + + friend class detail::AddWrapperMethods; + std::vector> audioProgrammes_; std::vector> audioContents_; std::vector> audioObjects_; diff --git a/src/document.cpp b/src/document.cpp index 58099975..8968a3d0 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -9,6 +9,10 @@ #include namespace adm { + namespace detail { + template class OptionalParameter; + } // namespace detail + Document::Document() { idAssigner_.document(this); } std::shared_ptr Document::create() { diff --git a/src/private/xml_parser.cpp b/src/private/xml_parser.cpp index 9f97b982..c8671a45 100644 --- a/src/private/xml_parser.cpp +++ b/src/private/xml_parser.cpp @@ -55,6 +55,8 @@ namespace adm { root = findAudioFormatExtendedNodeEbuCore(xmlDocument.first_node()); } if (root) { + setOptionalAttribute(root, "version", document_); + // add ADM elements to ADM document for (NodePtr node = root->first_node(); node; node = node->next_sibling()) { diff --git a/src/private/xml_writer.cpp b/src/private/xml_writer.cpp index a68bca19..b850b03e 100644 --- a/src/private/xml_writer.cpp +++ b/src/private/xml_writer.cpp @@ -38,6 +38,7 @@ namespace adm { root = xmlDocument.addEbuStructure(); } // clang-format off + root.addOptionalAttribute(document, "version"); root.addBaseElements(document, "audioProgramme", &formatAudioProgramme); root.addBaseElements(document, "audioContent", &formatAudioContent); root.addBaseElements(document, "audioObject", &formatAudioObject); diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 8b4a396b..c7abdaa6 100755 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -68,6 +68,7 @@ add_adm_test("route_tracer_tests") add_adm_test("screen_edge_lock_tests") add_adm_test("speaker_position_tests") add_adm_test("type_descriptor_tests") +add_adm_test("version_tests") add_adm_test("xml_audio_block_format_objects_tests") add_adm_test("xml_loudness_metadata_tests") add_adm_test("xml_parser_audio_block_format_direct_speakers_tests") diff --git a/tests/test_data/version.accepted.xml b/tests/test_data/version.accepted.xml new file mode 100644 index 00000000..edc7e1af --- /dev/null +++ b/tests/test_data/version.accepted.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tests/test_data/xml_parser/version.xml b/tests/test_data/xml_parser/version.xml new file mode 100644 index 00000000..1f8b60ca --- /dev/null +++ b/tests/test_data/xml_parser/version.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/tests/version_tests.cpp b/tests/version_tests.cpp new file mode 100644 index 00000000..ad8cee13 --- /dev/null +++ b/tests/version_tests.cpp @@ -0,0 +1,28 @@ +#include +#include "helper/parameter_checks.hpp" +#include "adm/document.hpp" +#include "adm/parse.hpp" +#include "adm/write.hpp" +#include "helper/file_comparator.hpp" + +using namespace adm; +using namespace adm_test; + +TEST_CASE("version") { + auto document = Document::create(); + + check_optional_param(document, + canBeSetTo(Version{"ITU-R_BS.2076-2"})); +} + +TEST_CASE("xml/version") { + auto document = parseXml("xml_parser/version.xml"); + + REQUIRE(document->has()); + REQUIRE(document->get().get() == "ITU-R_BS.2076-2"); + + std::stringstream xml; + writeXml(xml, document); + + CHECK_THAT(xml.str(), EqualsXmlFile("version")); +}