From 3db0d48f4bb2b65cb3adcce066f80fb8e6fa8e87 Mon Sep 17 00:00:00 2001 From: Urs Fleisch Date: Tue, 24 Feb 2026 06:53:23 +0100 Subject: [PATCH] Support edition, chapter and attachment UIDs in Matroska simple tags (#1311) --- examples/matroskareader.cpp | 15 ++++++ taglib/matroska/ebml/ebmlelement.cpp | 3 ++ taglib/matroska/ebml/ebmlelement.h | 6 +++ taglib/matroska/ebml/ebmlmktags.cpp | 16 +++++- taglib/matroska/matroskasimpletag.cpp | 54 +++++++++++++++++-- taglib/matroska/matroskasimpletag.h | 34 ++++++++++++ taglib/matroska/matroskatag.cpp | 77 +++++++++++++++++++++++---- taglib/matroska/matroskatag.h | 8 +++ tests/test_matroska.cpp | 64 ++++++++++++++++++++-- 9 files changed, 257 insertions(+), 20 deletions(-) diff --git a/examples/matroskareader.cpp b/examples/matroskareader.cpp index e44c2a35..582edf01 100644 --- a/examples/matroskareader.cpp +++ b/examples/matroskareader.cpp @@ -51,6 +51,21 @@ int main(int argc, char *argv[]) TagLib::Utils::formatString("%llu",trackUid).toCString(false) ); } + if(auto editionUid = t.editionUid()) { + PRINT_PRETTY("Edition UID", + TagLib::Utils::formatString("%llu",editionUid).toCString(false) + ); + } + if(auto chapterUid = t.chapterUid()) { + PRINT_PRETTY("Chapter UID", + TagLib::Utils::formatString("%llu",chapterUid).toCString(false) + ); + } + if(auto attachmentUid = t.attachmentUid()) { + PRINT_PRETTY("Attachment UID", + TagLib::Utils::formatString("%llu",attachmentUid).toCString(false) + ); + } const TagLib::String &language = t.language(); PRINT_PRETTY("Language", !language.isEmpty() ? language.toCString(false) : "Not set"); diff --git a/taglib/matroska/ebml/ebmlelement.cpp b/taglib/matroska/ebml/ebmlelement.cpp index 351e2870..c384e3d5 100644 --- a/taglib/matroska/ebml/ebmlelement.cpp +++ b/taglib/matroska/ebml/ebmlelement.cpp @@ -84,6 +84,9 @@ std::unique_ptr EBML::Element::factory(File &file) RETURN_ELEMENT_FOR_CASE(Id::MkCodecID); RETURN_ELEMENT_FOR_CASE(Id::MkTagTargetTypeValue); RETURN_ELEMENT_FOR_CASE(Id::MkTagTrackUID); + RETURN_ELEMENT_FOR_CASE(Id::MkTagEditionUID); + RETURN_ELEMENT_FOR_CASE(Id::MkTagChapterUID); + RETURN_ELEMENT_FOR_CASE(Id::MkTagAttachmentUID); RETURN_ELEMENT_FOR_CASE(Id::MkTagsLanguageDefault); RETURN_ELEMENT_FOR_CASE(Id::MkAttachedFileUID); RETURN_ELEMENT_FOR_CASE(Id::MkSeekPosition); diff --git a/taglib/matroska/ebml/ebmlelement.h b/taglib/matroska/ebml/ebmlelement.h index 8bccf469..19c6a92d 100644 --- a/taglib/matroska/ebml/ebmlelement.h +++ b/taglib/matroska/ebml/ebmlelement.h @@ -48,6 +48,9 @@ namespace TagLib MkTagTargets = 0x63C0, MkTagTargetTypeValue = 0x68CA, MkTagTrackUID = 0x63C5, + MkTagEditionUID = 0x63C9, + MkTagChapterUID = 0x63C4, + MkTagAttachmentUID = 0x63C6, MkSimpleTag = 0x67C8, MkTagName = 0x45A3, MkTagLanguage = 0x447A, @@ -181,6 +184,9 @@ namespace TagLib template <> struct GetElementTypeById { using type = Latin1StringElement; }; template <> struct GetElementTypeById { using type = UIntElement; }; template <> struct GetElementTypeById { using type = UIntElement; }; + template <> struct GetElementTypeById { using type = UIntElement; }; + template <> struct GetElementTypeById { using type = UIntElement; }; + template <> struct GetElementTypeById { using type = UIntElement; }; template <> struct GetElementTypeById { using type = UIntElement; }; template <> struct GetElementTypeById { using type = UIntElement; }; template <> struct GetElementTypeById { using type = UIntElement; }; diff --git a/taglib/matroska/ebml/ebmlmktags.cpp b/taglib/matroska/ebml/ebmlmktags.cpp index e732e26e..29735b07 100644 --- a/taglib/matroska/ebml/ebmlmktags.cpp +++ b/taglib/matroska/ebml/ebmlmktags.cpp @@ -69,6 +69,9 @@ std::unique_ptr EBML::MkTags::parse() const // Parse the element Matroska::SimpleTag::TargetTypeValue targetTypeValue = Matroska::SimpleTag::TargetTypeValue::None; unsigned long long trackUid = 0; + unsigned long long edtionUid = 0; + unsigned long long chapterUid = 0; + unsigned long long attachmentUid = 0; if(targets) { for(const auto &targetsChild : *targets) { if(const Id id = targetsChild->getId(); id == Id::MkTagTargetTypeValue @@ -80,6 +83,15 @@ std::unique_ptr EBML::MkTags::parse() const else if(id == Id::MkTagTrackUID) { trackUid = element_cast(targetsChild)->getValue(); } + else if(id == Id::MkTagEditionUID) { + edtionUid = element_cast(targetsChild)->getValue(); + } + else if(id == Id::MkTagChapterUID) { + chapterUid = element_cast(targetsChild)->getValue(); + } + else if(id == Id::MkTagAttachmentUID) { + attachmentUid = element_cast(targetsChild)->getValue(); + } } } @@ -109,10 +121,10 @@ std::unique_ptr EBML::MkTags::parse() const mTag->addSimpleTag(tagValueString ? Matroska::SimpleTag(tagName, *tagValueString, targetTypeValue, language, defaultLanguageFlag, - trackUid) + trackUid, edtionUid, chapterUid, attachmentUid) : Matroska::SimpleTag(tagName, *tagValueBinary, targetTypeValue, language, defaultLanguageFlag, - trackUid)); + trackUid, edtionUid, chapterUid, attachmentUid)); } } return mTag; diff --git a/taglib/matroska/matroskasimpletag.cpp b/taglib/matroska/matroskasimpletag.cpp index cd9a57d5..b9a74e79 100644 --- a/taglib/matroska/matroskasimpletag.cpp +++ b/taglib/matroska/matroskasimpletag.cpp @@ -30,19 +30,26 @@ class Matroska::SimpleTag::SimpleTagPrivate public: SimpleTagPrivate(const String &name, const String &value, TargetTypeValue targetTypeValue, const String &language, bool defaultLanguage, - unsigned long long trackUid) : + unsigned long long trackUid, unsigned long long editionUid, + unsigned long long chapterUid, unsigned long long attachmentUid) : value(value), name(name), language(language), trackUid(trackUid), + editionUid(editionUid), chapterUid(chapterUid), attachmentUid(attachmentUid), targetTypeValue(targetTypeValue), defaultLanguageFlag(defaultLanguage) {} SimpleTagPrivate(const String &name, const ByteVector &value, TargetTypeValue targetTypeValue, const String &language, bool defaultLanguage, - unsigned long long trackUid) : + unsigned long long trackUid, unsigned long long editionUid, + unsigned long long chapterUid, unsigned long long attachmentUid) : value(value), name(name), language(language), trackUid(trackUid), + editionUid(editionUid), chapterUid(chapterUid), attachmentUid(attachmentUid), targetTypeValue(targetTypeValue), defaultLanguageFlag(defaultLanguage) {} const std::variant value; const String name; const String language; const unsigned long long trackUid; + const unsigned long long editionUid; + const unsigned long long chapterUid; + const unsigned long long attachmentUid; const TargetTypeValue targetTypeValue; const bool defaultLanguageFlag; }; @@ -56,7 +63,19 @@ Matroska::SimpleTag::SimpleTag(const String &name, const String &value, const String &language, bool defaultLanguage, unsigned long long trackUid) : d(std::make_unique(name, value, targetTypeValue, - language, defaultLanguage, trackUid)) + language, defaultLanguage, trackUid, 0, 0, 0)) +{ +} + +Matroska::SimpleTag::SimpleTag(const String &name, const String &value, + TargetTypeValue targetTypeValue, + const String &language, bool defaultLanguage, + unsigned long long trackUid, + unsigned long long editionUid, + unsigned long long chapterUid, + unsigned long long attachmentUid) : + d(std::make_unique(name, value, targetTypeValue, + language, defaultLanguage, trackUid, editionUid, chapterUid, attachmentUid)) { } @@ -65,7 +84,19 @@ Matroska::SimpleTag::SimpleTag(const String &name, const ByteVector &value, const String &language, bool defaultLanguage, unsigned long long trackUid) : d(std::make_unique(name, value, targetTypeValue, - language, defaultLanguage, trackUid)) + language, defaultLanguage, trackUid, 0, 0, 0)) +{ +} + +Matroska::SimpleTag::SimpleTag(const String &name, const ByteVector &value, + TargetTypeValue targetTypeValue, + const String &language, bool defaultLanguage, + unsigned long long trackUid, + unsigned long long editionUid, + unsigned long long chapterUid, + unsigned long long attachmentUid) : + d(std::make_unique(name, value, targetTypeValue, + language, defaultLanguage, trackUid, editionUid, chapterUid, attachmentUid)) { } @@ -118,6 +149,21 @@ unsigned long long Matroska::SimpleTag::trackUid() const return d->trackUid; } +unsigned long long Matroska::SimpleTag::editionUid() const +{ + return d->editionUid; +} + +unsigned long long Matroska::SimpleTag::chapterUid() const +{ + return d->chapterUid; +} + +unsigned long long Matroska::SimpleTag::attachmentUid() const +{ + return d->attachmentUid; +} + Matroska::SimpleTag::ValueType Matroska::SimpleTag::type() const { return std::holds_alternative(d->value) ? BinaryType : StringType; diff --git a/taglib/matroska/matroskasimpletag.h b/taglib/matroska/matroskasimpletag.h index 4edd8b45..64618b90 100644 --- a/taglib/matroska/matroskasimpletag.h +++ b/taglib/matroska/matroskasimpletag.h @@ -60,6 +60,14 @@ namespace TagLib { const String &language = String(), bool defaultLanguage = true, unsigned long long trackUid = 0); + /*! + * Construct a string simple tag. + */ + // BIC: merge with constructor above + SimpleTag(const String& name, const String& value, TargetTypeValue targetTypeValue, const String& language, + bool defaultLanguage, unsigned long long trackUid, unsigned long long editionUid, + unsigned long long chapterUid = 0, unsigned long long attachmentUid = 0); + /*! * Construct a binary simple tag. */ @@ -68,6 +76,14 @@ namespace TagLib { const String &language = String(), bool defaultLanguage = true, unsigned long long trackUid = 0); + /*! + * Construct a binary simple tag. + */ + // BIC: merge with constructor above + SimpleTag(const String& name, const ByteVector& value, TargetTypeValue targetTypeValue, const String& language, + bool defaultLanguage, unsigned long long trackUid, unsigned long long editionUid, + unsigned long long chapterUid = 0, unsigned long long attachmentUid = 0); + /*! * Construct a simple tag as a copy of \a other. */ @@ -124,6 +140,24 @@ namespace TagLib { */ unsigned long long trackUid() const; + /*! + * Returns the UID that identifies the edition that the tags belong to, + * zero if not defined, the tag applies to all editions + */ + unsigned long long editionUid() const; + + /*! + * Returns the UID that identifies the chapter that the tags belong to, + * zero if not defined, the tag applies to all chapters + */ + unsigned long long chapterUid() const; + + /*! + * Returns the UID that identifies the attachment that the tags belong to, + * zero if not defined, the tag applies to all attachments + */ + unsigned long long attachmentUid() const; + /*! * Returns the type of the value. */ diff --git a/taglib/matroska/matroskatag.cpp b/taglib/matroska/matroskatag.cpp index eaec2da7..699a2596 100644 --- a/taglib/matroska/matroskatag.cpp +++ b/taglib/matroska/matroskatag.cpp @@ -121,11 +121,21 @@ void Matroska::Tag::removeSimpleTag(unsigned int index) void Matroska::Tag::removeSimpleTag(const String &name, SimpleTag::TargetTypeValue targetTypeValue, unsigned long long trackUid) +{ + removeSimpleTag(name, targetTypeValue, trackUid, 0, 0, 0); +} + +void Matroska::Tag::removeSimpleTag(const String& name, + SimpleTag::TargetTypeValue targetTypeValue, + unsigned long long trackUid, unsigned long long editionUid, + unsigned long long chapterUid, unsigned long long attachmentUid) { const auto it = std::find_if(d->tags.begin(), d->tags.end(), - [&name, targetTypeValue, trackUid](const SimpleTag &t) { + [&name, targetTypeValue, trackUid, editionUid, chapterUid, attachmentUid]( + const SimpleTag &t) { return t.name() == name && t.targetTypeValue() == targetTypeValue && - t.trackUid() == trackUid; + t.trackUid() == trackUid && t.editionUid() == editionUid && + t.chapterUid() == chapterUid && t.attachmentUid() == attachmentUid; } ); if(it != d->tags.end()) { @@ -260,12 +270,18 @@ ByteVector Matroska::Tag::renderInternal() for(const auto &tag : std::as_const(d->tags)) { auto targetTypeValue = tag.targetTypeValue(); auto trackUid = tag.trackUid(); + auto editionUid = tag.editionUid(); + auto chapterUid = tag.chapterUid(); + auto attachmentUid = tag.attachmentUid(); auto it = std::find_if(targetList.begin(), targetList.end(), [&](const auto &list) { const auto &simpleTag = list.front(); return simpleTag.targetTypeValue() == targetTypeValue && - simpleTag.trackUid() == trackUid; + simpleTag.trackUid() == trackUid && + simpleTag.editionUid() == editionUid && + simpleTag.chapterUid() == chapterUid && + simpleTag.attachmentUid() == attachmentUid; } ); if(it == targetList.end()) { @@ -280,6 +296,9 @@ ByteVector Matroska::Tag::renderInternal() const auto &frontTag = list.front(); const auto targetTypeValue = frontTag.targetTypeValue(); const auto trackUid = frontTag.trackUid(); + const auto editionUid = frontTag.editionUid(); + const auto chapterUid = frontTag.chapterUid(); + const auto attachmentUid = frontTag.attachmentUid(); auto tag = EBML::make_unique_element(); // Build element @@ -294,6 +313,21 @@ ByteVector Matroska::Tag::renderInternal() element->setValue(trackUid); targets->appendElement(std::move(element)); } + if(editionUid != 0) { + auto element = EBML::make_unique_element(); + element->setValue(editionUid); + targets->appendElement(std::move(element)); + } + if(chapterUid != 0) { + auto element = EBML::make_unique_element(); + element->setValue(chapterUid); + targets->appendElement(std::move(element)); + } + if(attachmentUid != 0) { + auto element = EBML::make_unique_element(); + element->setValue(attachmentUid); + targets->appendElement(std::move(element)); + } tag->appendElement(std::move(targets)); // Build element @@ -446,7 +480,8 @@ String Matroska::Tag::TagPrivate::getTag(const String &key) const && t.type() == SimpleTag::StringType && (t.targetTypeValue() == targetTypeValue || (t.targetTypeValue() == SimpleTag::TargetTypeValue::None && !strict)) - && t.trackUid() == 0; + && t.trackUid() == 0 && t.editionUid() == 0 && t.chapterUid() == 0 + && t.attachmentUid() == 0; } ); return it != tags.end() ? it->toString() : String(); @@ -456,7 +491,9 @@ PropertyMap Matroska::Tag::properties() const { PropertyMap properties; for(const auto &simpleTag : std::as_const(d->tags)) { - if(simpleTag.type() == SimpleTag::StringType && simpleTag.trackUid() == 0) { + if(simpleTag.type() == SimpleTag::StringType && simpleTag.trackUid() == 0 && + simpleTag.editionUid() == 0 && simpleTag.chapterUid() == 0 && + simpleTag.attachmentUid() == 0) { if(String key = translateTag(simpleTag.name(), simpleTag.targetTypeValue()); !key.isEmpty()) properties[key].append(simpleTag.toString()); @@ -472,7 +509,8 @@ PropertyMap Matroska::Tag::setProperties(const PropertyMap &propertyMap) // Remove all simple tags which would be returned in properties() for(auto it = d->tags.begin(); it != d->tags.end();) { if(it->type() == SimpleTag::StringType && - it->trackUid() == 0 && + it->trackUid() == 0 && it->editionUid() == 0 && + it->chapterUid() == 0 && it->attachmentUid() == 0 && !translateTag(it->name(), it->targetTypeValue()).isEmpty()) { it = d->tags.erase(it); setNeedsRender(true); @@ -514,7 +552,8 @@ StringList Matroska::Tag::complexPropertyKeys() const StringList keys; for(const SimpleTag &t : std::as_const(d->tags)) { if(t.type() != SimpleTag::StringType || - t.trackUid() != 0 || + t.trackUid() != 0 || t.editionUid() != 0 || + t.chapterUid() != 0 || t.attachmentUid() != 0 || translateTag(t.name(), t.targetTypeValue()).isEmpty()) { keys.append(t.name()); } @@ -529,7 +568,8 @@ List Matroska::Tag::complexProperties(const String &key) const for(const SimpleTag &t : std::as_const(d->tags)) { if(t.name() == key && (t.type() != SimpleTag::StringType || - t.trackUid() != 0 || + t.trackUid() != 0 || t.editionUid() != 0 || + t.chapterUid() != 0 || t.attachmentUid() != 0 || translateTag(t.name(), t.targetTypeValue()).isEmpty())) { VariantMap property; if(t.type() != SimpleTag::StringType) { @@ -545,6 +585,15 @@ List Matroska::Tag::complexProperties(const String &key) const if(t.trackUid()) { property.insert("trackUid", t.trackUid()); } + if(t.editionUid()) { + property.insert("editionUid", t.editionUid()); + } + if(t.chapterUid()) { + property.insert("chapterUid", t.chapterUid()); + } + if(t.attachmentUid()) { + property.insert("attachmentUid", t.attachmentUid()); + } property.insert("language", t.language()); property.insert("defaultLanguage", t.defaultLanguageFlag()); props.append(property); @@ -564,7 +613,8 @@ bool Matroska::Tag::setComplexProperties(const String &key, const List 0) { setNeedsRender(true); @@ -591,11 +641,16 @@ bool Matroska::Tag::setComplexProperties(const String &key, const List(); const bool defaultLanguage = property.value("defaultLanguage", true).value(); const auto trackUid = property.value("trackUid", 0ULL).value(); + const auto editionUid = property.value("editionUid", 0ULL).value(); + const auto chapterUid = property.value("chapterUid", 0ULL).value(); + const auto attachmentUid = property.value("attachmentUid", 0ULL).value(); d->tags.append(property.contains("data") ? SimpleTag(key, property.value("data").value(), - targetTypeValue, language, defaultLanguage, trackUid) + targetTypeValue, language, defaultLanguage, trackUid, + editionUid, chapterUid, attachmentUid) : SimpleTag(key, property.value("value").value(), - targetTypeValue, language, defaultLanguage, trackUid)); + targetTypeValue, language, defaultLanguage, trackUid, + editionUid, chapterUid, attachmentUid)); setNeedsRender(true); result = true; } diff --git a/taglib/matroska/matroskatag.h b/taglib/matroska/matroskatag.h index 21696cc0..9fe8cb2e 100644 --- a/taglib/matroska/matroskatag.h +++ b/taglib/matroska/matroskatag.h @@ -120,6 +120,14 @@ namespace TagLib { void removeSimpleTag(const String &name, SimpleTag::TargetTypeValue targetTypeValue, unsigned long long trackUid = 0); + /*! + * Remove a tag attribute. + */ + // BIC: Merge with the method above + void removeSimpleTag(const String &name, SimpleTag::TargetTypeValue targetTypeValue, + unsigned long long trackUid, unsigned long long editionUid, + unsigned long long chapterUid = 0, unsigned long long attachmentUid = 0); + /*! * Remove all tag attributes. */ diff --git a/tests/test_matroska.cpp b/tests/test_matroska.cpp index b3fd23d7..27f7d2c5 100644 --- a/tests/test_matroska.cpp +++ b/tests/test_matroska.cpp @@ -220,7 +220,8 @@ public: CPPUNIT_ASSERT(tag->isEmpty()); tag->addSimpleTag(Matroska::SimpleTag( "Test Name 2", String("Test Value 2"), - Matroska::SimpleTag::TargetTypeValue::Album)); + Matroska::SimpleTag::TargetTypeValue::Album, + {}, true, 0x72ac, 0xed17, 0xca97, 0xa7ac)); tag->insertSimpleTag(0, Matroska::SimpleTag( "Test Name 1", String("Test Value 1"), Matroska::SimpleTag::TargetTypeValue::Track, "en")); @@ -263,6 +264,9 @@ public: CPPUNIT_ASSERT_EQUAL(true, simpleTags[0].defaultLanguageFlag()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::TargetTypeValue::Track, simpleTags[0].targetTypeValue()); CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[0].trackUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[0].editionUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[0].chapterUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[0].attachmentUid()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::ValueType::StringType, simpleTags[0].type()); CPPUNIT_ASSERT_EQUAL(String("und"), simpleTags[1].language()); @@ -272,6 +276,9 @@ public: CPPUNIT_ASSERT_EQUAL(true, simpleTags[1].defaultLanguageFlag()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::TargetTypeValue::Track, simpleTags[1].targetTypeValue()); CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[1].trackUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[1].editionUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[1].chapterUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[1].attachmentUid()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::ValueType::StringType, simpleTags[1].type()); CPPUNIT_ASSERT_EQUAL(String("und"), simpleTags[2].language()); @@ -281,6 +288,9 @@ public: CPPUNIT_ASSERT_EQUAL(true, simpleTags[2].defaultLanguageFlag()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::TargetTypeValue::Track, simpleTags[2].targetTypeValue()); CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[2].trackUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[2].editionUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[2].chapterUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[2].attachmentUid()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::ValueType::StringType, simpleTags[2].type()); CPPUNIT_ASSERT_EQUAL(String("und"), simpleTags[3].language()); @@ -290,6 +300,9 @@ public: CPPUNIT_ASSERT_EQUAL(true, simpleTags[3].defaultLanguageFlag()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::TargetTypeValue::Track, simpleTags[3].targetTypeValue()); CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[3].trackUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[3].editionUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[3].chapterUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[3].attachmentUid()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::ValueType::StringType, simpleTags[3].type()); CPPUNIT_ASSERT_EQUAL(String("und"), simpleTags[4].language()); @@ -298,7 +311,10 @@ public: CPPUNIT_ASSERT_EQUAL(ByteVector(), simpleTags[4].toByteVector()); CPPUNIT_ASSERT_EQUAL(true, simpleTags[4].defaultLanguageFlag()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::TargetTypeValue::Album, simpleTags[4].targetTypeValue()); - CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[4].trackUid()); + CPPUNIT_ASSERT_EQUAL(0x72acULL, simpleTags[4].trackUid()); + CPPUNIT_ASSERT_EQUAL(0xed17ULL, simpleTags[4].editionUid()); + CPPUNIT_ASSERT_EQUAL(0xca97ULL, simpleTags[4].chapterUid()); + CPPUNIT_ASSERT_EQUAL(0xa7acULL, simpleTags[4].attachmentUid()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::ValueType::StringType, simpleTags[4].type()); const auto &attachedFiles = attachments->attachedFileList(); @@ -315,7 +331,6 @@ public: expectedProps["DATE"] = StringList("1969"); expectedProps["TEST NAME 1"] = StringList("Test Value 1"); expectedProps["TITLE"] = StringList("Test title"); - expectedProps.addUnsupportedData("Test Name 2"); auto props = f.properties(); if (expectedProps != props) { CPPUNIT_ASSERT_EQUAL(expectedProps.toString(), props.toString()); @@ -341,6 +356,10 @@ public: {"name", "Test Name 2"}, {"value", "Test Value 2"}, {"targetTypeValue", 50}, + {"trackUid", 0x72acULL}, + {"editionUid", 0xed17ULL}, + {"chapterUid", 0xca97ULL}, + {"attachmentUid", 0xa7acULL}, }; auto complexProps = f.complexProperties("Test Name 2"); CPPUNIT_ASSERT(List({expectedComplexProps}) == complexProps); @@ -577,6 +596,9 @@ public: CPPUNIT_ASSERT_EQUAL(true, simpleTags[0].defaultLanguageFlag()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::TargetTypeValue::None, simpleTags[0].targetTypeValue()); CPPUNIT_ASSERT_EQUAL(9584013959154292683ULL, simpleTags[0].trackUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[0].editionUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[0].chapterUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[0].attachmentUid()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::ValueType::StringType, simpleTags[0].type()); CPPUNIT_ASSERT_EQUAL(String("und"), simpleTags[1].language()); @@ -586,6 +608,9 @@ public: CPPUNIT_ASSERT_EQUAL(true, simpleTags[1].defaultLanguageFlag()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::TargetTypeValue::Track, simpleTags[1].targetTypeValue()); CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[1].trackUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[1].editionUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[1].chapterUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[1].attachmentUid()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::ValueType::StringType, simpleTags[1].type()); CPPUNIT_ASSERT_EQUAL(String("und"), simpleTags[2].language()); @@ -595,6 +620,9 @@ public: CPPUNIT_ASSERT_EQUAL(true, simpleTags[2].defaultLanguageFlag()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::TargetTypeValue::Track, simpleTags[2].targetTypeValue()); CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[2].trackUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[2].editionUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[2].chapterUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[2].attachmentUid()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::ValueType::StringType, simpleTags[2].type()); CPPUNIT_ASSERT_EQUAL(String("und"), simpleTags[3].language()); @@ -604,6 +632,9 @@ public: CPPUNIT_ASSERT_EQUAL(true, simpleTags[3].defaultLanguageFlag()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::TargetTypeValue::Track, simpleTags[3].targetTypeValue()); CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[3].trackUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[3].editionUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[3].chapterUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[3].attachmentUid()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::ValueType::StringType, simpleTags[3].type()); CPPUNIT_ASSERT_EQUAL(String("und"), simpleTags[4].language()); @@ -613,6 +644,9 @@ public: CPPUNIT_ASSERT_EQUAL(true, simpleTags[4].defaultLanguageFlag()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::TargetTypeValue::Track, simpleTags[4].targetTypeValue()); CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[4].trackUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[4].editionUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[4].chapterUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[4].attachmentUid()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::ValueType::StringType, simpleTags[4].type()); CPPUNIT_ASSERT_EQUAL(String("und"), simpleTags[5].language()); @@ -622,6 +656,9 @@ public: CPPUNIT_ASSERT_EQUAL(true, simpleTags[5].defaultLanguageFlag()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::TargetTypeValue::Track, simpleTags[5].targetTypeValue()); CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[5].trackUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[5].editionUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[5].chapterUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[5].attachmentUid()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::ValueType::StringType, simpleTags[5].type()); CPPUNIT_ASSERT_EQUAL(String("und"), simpleTags[6].language()); @@ -631,6 +668,9 @@ public: CPPUNIT_ASSERT_EQUAL(true, simpleTags[6].defaultLanguageFlag()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::TargetTypeValue::Track, simpleTags[6].targetTypeValue()); CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[6].trackUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[6].editionUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[6].chapterUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[6].attachmentUid()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::ValueType::StringType, simpleTags[6].type()); CPPUNIT_ASSERT_EQUAL(String("und"), simpleTags[7].language()); @@ -640,6 +680,9 @@ public: CPPUNIT_ASSERT_EQUAL(true, simpleTags[7].defaultLanguageFlag()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::TargetTypeValue::Track, simpleTags[7].targetTypeValue()); CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[7].trackUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[7].editionUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[7].chapterUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[7].attachmentUid()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::ValueType::StringType, simpleTags[7].type()); CPPUNIT_ASSERT_EQUAL(String("und"), simpleTags[8].language()); @@ -649,6 +692,9 @@ public: CPPUNIT_ASSERT_EQUAL(true, simpleTags[8].defaultLanguageFlag()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::TargetTypeValue::Album, simpleTags[8].targetTypeValue()); CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[8].trackUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[8].editionUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[8].chapterUid()); + CPPUNIT_ASSERT_EQUAL(0ULL, simpleTags[8].attachmentUid()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::ValueType::StringType, simpleTags[8].type()); auto props = f.properties(); @@ -817,6 +863,9 @@ public: CPPUNIT_ASSERT_EQUAL(trackUidTag.value("name").value(), simpleTags[0].name()); CPPUNIT_ASSERT_EQUAL(trackUidTag.value("defaultLanguage").value(), simpleTags[0].defaultLanguageFlag()); CPPUNIT_ASSERT_EQUAL(trackUidTag.value("trackUid").value(), simpleTags[0].trackUid()); + CPPUNIT_ASSERT_EQUAL(trackUidTag.value("editionUid").value(), simpleTags[0].editionUid()); + CPPUNIT_ASSERT_EQUAL(trackUidTag.value("chapterUid").value(), simpleTags[0].chapterUid()); + CPPUNIT_ASSERT_EQUAL(trackUidTag.value("attachmentUid").value(), simpleTags[0].attachmentUid()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::TargetTypeValue::None, simpleTags[0].targetTypeValue()); CPPUNIT_ASSERT_EQUAL(ByteVector(), simpleTags[0].toByteVector()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::ValueType::StringType, simpleTags[0].type()); @@ -844,6 +893,9 @@ public: CPPUNIT_ASSERT_EQUAL(trackUidTag.value("name").value(), simpleTags[0].name()); CPPUNIT_ASSERT_EQUAL(trackUidTag.value("defaultLanguage").value(), simpleTags[0].defaultLanguageFlag()); CPPUNIT_ASSERT_EQUAL(trackUidTag.value("trackUid").value(), simpleTags[0].trackUid()); + CPPUNIT_ASSERT_EQUAL(trackUidTag.value("editionUid").value(), simpleTags[0].editionUid()); + CPPUNIT_ASSERT_EQUAL(trackUidTag.value("chapterUid").value(), simpleTags[0].chapterUid()); + CPPUNIT_ASSERT_EQUAL(trackUidTag.value("attachmentUid").value(), simpleTags[0].attachmentUid()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::TargetTypeValue::None, simpleTags[0].targetTypeValue()); CPPUNIT_ASSERT_EQUAL(ByteVector(), simpleTags[0].toByteVector()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::ValueType::StringType, simpleTags[0].type()); @@ -853,6 +905,9 @@ public: CPPUNIT_ASSERT_EQUAL(targetTypeTag.value("name").value(), simpleTags[1].name()); CPPUNIT_ASSERT_EQUAL(targetTypeTag.value("defaultLanguage").value(), simpleTags[1].defaultLanguageFlag()); CPPUNIT_ASSERT_EQUAL(targetTypeTag.value("trackUid").value(), simpleTags[1].trackUid()); + CPPUNIT_ASSERT_EQUAL(targetTypeTag.value("editionUid").value(), simpleTags[1].editionUid()); + CPPUNIT_ASSERT_EQUAL(targetTypeTag.value("chapterUid").value(), simpleTags[1].chapterUid()); + CPPUNIT_ASSERT_EQUAL(targetTypeTag.value("attachmentUid").value(), simpleTags[1].attachmentUid()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::TargetTypeValue::Subtrack, simpleTags[1].targetTypeValue()); CPPUNIT_ASSERT_EQUAL(ByteVector(), simpleTags[1].toByteVector()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::ValueType::StringType, simpleTags[1].type()); @@ -862,6 +917,9 @@ public: CPPUNIT_ASSERT_EQUAL(binaryTag.value("name").value(), simpleTags[2].name()); CPPUNIT_ASSERT_EQUAL(binaryTag.value("defaultLanguage").value(), simpleTags[2].defaultLanguageFlag()); CPPUNIT_ASSERT_EQUAL(binaryTag.value("trackUid").value(), simpleTags[2].trackUid()); + CPPUNIT_ASSERT_EQUAL(binaryTag.value("editionUid").value(), simpleTags[2].editionUid()); + CPPUNIT_ASSERT_EQUAL(binaryTag.value("chapterUid").value(), simpleTags[2].chapterUid()); + CPPUNIT_ASSERT_EQUAL(binaryTag.value("attachmentUid").value(), simpleTags[2].attachmentUid()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::TargetTypeValue::Track, simpleTags[2].targetTypeValue()); CPPUNIT_ASSERT_EQUAL(String(), simpleTags[2].toString()); CPPUNIT_ASSERT_EQUAL(Matroska::SimpleTag::ValueType::BinaryType, simpleTags[2].type());