diff --git a/matroska/matroskatags.dtd b/matroska/matroskatags.dtd
new file mode 100644
index 0000000..4b36958
--- /dev/null
+++ b/matroska/matroskatags.dtd
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/testfiles/mkv/nested-tags.xml b/testfiles/mkv/nested-tags.xml
new file mode 100644
index 0000000..66b1e5a
--- /dev/null
+++ b/testfiles/mkv/nested-tags.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+ TITLE
+ Vanilla Sky
+ und
+
+
+ ARTIST
+ Test artist
+ und
+
+ ADDRESS
+ Test address
+ und
+
+
+
+ 50
+
+
+
+
+ TITLE
+ Main video track
+ und
+
+
+ 3164620769
+ 50
+
+
+
+
+ TITLE
+ English audio track
+ und
+
+
+ 3571773145
+ 50
+
+
+
diff --git a/tests/overall.cpp b/tests/overall.cpp
index 3923ce2..285fe8c 100644
--- a/tests/overall.cpp
+++ b/tests/overall.cpp
@@ -25,6 +25,7 @@
using namespace std;
using namespace ConversionUtilities;
+using namespace TestUtilities;
using namespace Media;
using namespace CPPUNIT_NS;
@@ -53,7 +54,8 @@ class OverallTests : public TestFixture
CPPUNIT_TEST(testMp3Making);
CPPUNIT_TEST(testOggMaking);
CPPUNIT_TEST(testFlacMaking);
- CPPUNIT_TEST(testMkvMaking);
+ CPPUNIT_TEST(testMkvMakingWithDifferentSettings);
+ CPPUNIT_TEST(testMkvMakingNestedTags);
#endif
CPPUNIT_TEST_SUITE_END();
@@ -61,6 +63,7 @@ public:
void setUp();
void tearDown();
+private:
void parseFile(const string &path, void (OverallTests::* checkRoutine)(void));
void makeFile(const string &path, void (OverallTests::* modifyRoutine)(void), void (OverallTests::* checkRoutine)(void));
@@ -73,6 +76,7 @@ public:
void checkMkvTestfile7();
void checkMkvTestfile8();
void checkMkvTestfileHandbrakeChapters();
+ void checkMkvTestfileNestedTags();
void checkMkvTestMetaData();
void checkMkvPaddingConstraints();
@@ -100,14 +104,18 @@ public:
void setMp3TestMetaData();
void setOggTestMetaData();
void removeAllTags();
+ void noop();
+ void createMkvWithNestedTags();
+public:
void testMkvParsing();
void testMp4Parsing();
void testMp3Parsing();
void testOggParsing();
void testFlacParsing();
#ifdef PLATFORM_UNIX
- void testMkvMaking();
+ void testMkvMakingWithDifferentSettings();
+ void testMkvMakingNestedTags();
void testMp4Making();
void testMp3Making();
void testOggMaking();
@@ -123,6 +131,7 @@ private:
TagValue m_testTotalParts;
TagValue m_testPosition;
queue m_preservedMetaData;
+ string m_nestedTagsMkvPath;
TagStatus m_tagStatus;
uint16 m_mode;
};
@@ -143,7 +152,11 @@ void OverallTests::setUp()
}
void OverallTests::tearDown()
-{}
+{
+ if(!m_nestedTagsMkvPath.empty()) {
+ remove(m_nestedTagsMkvPath.data());
+ }
+}
/*!
* \brief Parses the specified file and tests the results using the specified check routine.
@@ -595,6 +608,42 @@ void OverallTests::checkMkvTestfileHandbrakeChapters()
}
}
+/*!
+ * \brief Checks "mtx-test-data/mkv/nested-tags.mkv" ("mtx-test-data/mkv/tags.mkv" where "mkv/nested-tags.xml" has been applied).
+ */
+void OverallTests::checkMkvTestfileNestedTags()
+{
+ CPPUNIT_ASSERT(m_fileInfo.containerFormat() == ContainerFormat::Matroska);
+ const auto tags = m_fileInfo.tags();
+ bool generalTagFound = false;
+ switch(m_tagStatus) {
+ case TagStatus::Original:
+ case TagStatus::TestMetaDataPresent:
+ CPPUNIT_ASSERT_EQUAL(5ul, tags.size());
+ for(const Tag *tag : tags) {
+ CPPUNIT_ASSERT(tag->type() == TagType::MatroskaTag);
+ const auto *mkvTag = static_cast(tag);
+ const auto &target = mkvTag->target();
+ if(target.level() == 50 && target.tracks().empty()) {
+ generalTagFound = true;
+ CPPUNIT_ASSERT_EQUAL("Vanilla Sky"s, tag->value(KnownField::Title).toString());
+ const auto &fields = mkvTag->fields();
+ const auto &artistField = fields.find(mkvTag->fieldId(KnownField::Artist));
+ CPPUNIT_ASSERT(artistField != fields.end());
+ CPPUNIT_ASSERT_EQUAL("Test artist"s, artistField->second.value().toString());
+ const auto &nestedFields = artistField->second.nestedFields();
+ CPPUNIT_ASSERT_EQUAL(1ul, nestedFields.size());
+ CPPUNIT_ASSERT_EQUAL("ADDRESS"s, nestedFields[0].idToString());
+ CPPUNIT_ASSERT_EQUAL("Test address"s, nestedFields[0].value().toString());
+ }
+ }
+ CPPUNIT_ASSERT(generalTagFound);
+ break;
+ case TagStatus::Removed:
+ CPPUNIT_ASSERT(tags.size() == 0);
+ }
+}
+
/*!
* \brief Checks whether test meta data for Matroska files has been applied correctly.
*/
@@ -1298,6 +1347,47 @@ void OverallTests::removeAllTags()
m_fileInfo.removeAllTags();
}
+/*!
+ * \brief Does nothing.
+ * \remarks Used to just resave the file.
+ */
+void OverallTests::noop()
+{
+}
+
+/*!
+ * \brief Creates a Matroska test file with nested tags from "mtx-test-data/mkv/nested-tags.mkv" using "mkv/nested-tags.xml".
+ * \remarks Requires mkvmerge.
+ * \todo Make mkvmerge path variable.
+ */
+void OverallTests::createMkvWithNestedTags()
+{
+#ifdef PLATFORM_UNIX
+ m_nestedTagsMkvPath = workingCopyPathMode("mtx-test-data/mkv/nested-tags.mkv", WorkingCopyMode::NoCopy);
+ remove(m_nestedTagsMkvPath.data());
+
+ cerr << "\n\ncreating testfile \"" << m_nestedTagsMkvPath << "\" with mkvmerge" << endl;
+ const string tagsMkvPath(testFilePath("mtx-test-data/mkv/tags.mkv"));
+ const string tagsXmlPath(testFilePath("mkv/nested-tags.xml"));
+ const char *const mkvmergeArgs[] = {
+ "--ui-language en_US",
+ "--output", m_nestedTagsMkvPath.data(),
+ "--no-global-tags", "--language", "0:und", "--default-track", "0:yes", "--language", "1:und", "--default-track", "1:yes",
+ "(", tagsMkvPath.data(), ")",
+ "--global-tags", tagsXmlPath.data(), "--track-order", "0:0,0:1", nullptr
+ };
+ string mkvmergeOutput, mkvmergeErrors;
+ int res = execHelperApp("/bin/mkvmerge", mkvmergeArgs, mkvmergeOutput, mkvmergeErrors);
+ cout << mkvmergeOutput << endl;
+ cerr << mkvmergeErrors << endl;
+ if(res) {
+ cerr << "Failure (exit code " << res << "); unable to test nested tags" << endl;
+ remove(m_nestedTagsMkvPath.data());
+ m_nestedTagsMkvPath.clear();
+ }
+#endif
+}
+
/*!
* \brief Tests the Matroska parser via MediaFileInfo.
*/
@@ -1315,14 +1405,21 @@ void OverallTests::testMkvParsing()
parseFile(TestUtilities::testFilePath("matroska_wave1/test7.mkv"), &OverallTests::checkMkvTestfile7);
parseFile(TestUtilities::testFilePath("matroska_wave1/test8.mkv"), &OverallTests::checkMkvTestfile8);
parseFile(TestUtilities::testFilePath("mtx-test-data/mkv/handbrake-chapters-2.mkv"), &OverallTests::checkMkvTestfileHandbrakeChapters);
+ createMkvWithNestedTags();
+ if(!m_nestedTagsMkvPath.empty()) {
+ parseFile(m_nestedTagsMkvPath, &OverallTests::checkMkvTestfileNestedTags);
+ }
}
#ifdef PLATFORM_UNIX
/*!
* \brief Tests the Matroska maker via MediaFileInfo.
+ *
+ * This method tests various combinations of the possible settings.
+ *
* \remarks Relies on the parser to check results.
*/
-void OverallTests::testMkvMaking()
+void OverallTests::testMkvMakingWithDifferentSettings()
{
// full parse is required to determine padding
m_fileInfo.setForceFullParse(true);
@@ -1399,6 +1496,23 @@ void OverallTests::testMkvMaking()
makeFile(TestUtilities::workingCopyPath("mtx-test-data/mkv/handbrake-chapters-2.mkv"), modifyRoutine, &OverallTests::checkMkvTestfileHandbrakeChapters);
}
}
+
+/*!
+ * \brief Tests making a Matroska file with nested tags via MediaFileInfo.
+ * \remarks Relies on the parser to check results.
+ */
+void OverallTests::testMkvMakingNestedTags()
+{
+ createMkvWithNestedTags();
+ if(!m_nestedTagsMkvPath.empty()) {
+ cerr << endl << "Matroska maker - rewrite file with nested tags" << endl;
+ m_fileInfo.setMinPadding(0);
+ m_fileInfo.setMaxPadding(0);
+ m_fileInfo.setTagPosition(ElementPosition::BeforeData);
+ m_fileInfo.setIndexPosition(ElementPosition::BeforeData);
+ makeFile(m_nestedTagsMkvPath, &OverallTests::noop, &OverallTests::checkMkvTestfileNestedTags);
+ }
+}
#endif
/*!
diff --git a/tests/testfilecheck.cpp b/tests/testfilecheck.cpp
index 27c14c4..de63259 100644
--- a/tests/testfilecheck.cpp
+++ b/tests/testfilecheck.cpp
@@ -70,6 +70,8 @@ struct TestFile
{"matroska_wave1/test7.mkv", {"95b21c92ad5a4fe00914ff5009e2a64f12fd4c5fb9cb1c3c888ab50bf0ffe483"}},
{"matroska_wave1/test8.mkv", {"9dddcd1550b814dae44d62e2b9f27c0eca31d5e190df2220cbf7492e3d6c63da"}},
{"mtx-test-data/mkv/handbrake-chapters-2.mkv", {"eccc55f3b59a77086b3ffb914525d312c7886eae34e3933352dea2f6f6a1974c"}},
+ {"mtx-test-data/mkv/tags.mkv", {"4330019afc3d846600c1ded38158fcac081297f4e56c749251c236f4871e0287"}},
+ {"mkv/nested-tags.xml", {"85cfcc94920f114e52fd1aa3df24706cd2710626e065a2c8c55dd209ec8dc8ce"}},
{"mp4/test1.m4a", {"4f16e0a22525bd13ba859431406d7f5991e0b4f155c51e10e5f32b0c97034b36"}},
{"mtx-test-data/aac/he-aacv2-ps.m4a", {"be54be0ae45b0184583ced8a84a881a1652a449feb7f6a917e11f60efabb68ac"}},
{"mtx-test-data/alac/othertest-itunes.m4a", {"5e9c64cde00902211533fbe38aaa67ef5f79a945e1d717951b78b4bbf9ff84e8"}},