Support new classical music frames introduced with iTunes 12.5, #758.

M4A:
    ©wrk: Work (string)
    ©mvn: Movement Name (string)
    ©mvi: Movement Number (number)
    ©mvc: Movement Count (number)
    shwm: Show Work & Movement (0/1)

ID3 (2.3, 2.4; MVN, MVI for 2.2):
    MVNM: Movement Name
    MVIN: Movement Number/Count
This commit is contained in:
Urs Fleisch
2016-10-18 20:34:53 +02:00
parent 0dac721ce2
commit 1b64bb0cb7
5 changed files with 119 additions and 14 deletions

View File

@ -109,6 +109,7 @@ class TestID3v2 : public CppUnit::TestFixture
CPPUNIT_TEST(testW000);
CPPUNIT_TEST(testPropertyInterface);
CPPUNIT_TEST(testPropertyInterface2);
CPPUNIT_TEST(testPropertiesMovement);
CPPUNIT_TEST(testDeleteFrame);
CPPUNIT_TEST(testSaveAndStripID3v1ShouldNotAddFrameFromID3v1ToId3v2);
CPPUNIT_TEST(testParseChapterFrame);
@ -921,6 +922,47 @@ public:
CPPUNIT_ASSERT_EQUAL(frame6, ID3v2::UniqueFileIdentifierFrame::findByOwner(&tag, "http://musicbrainz.org"));
}
void testPropertiesMovement()
{
ID3v2::Tag tag;
ID3v2::TextIdentificationFrame *frameMvnm = new ID3v2::TextIdentificationFrame("MVNM");
frameMvnm->setText("Movement Name");
tag.addFrame(frameMvnm);
ID3v2::TextIdentificationFrame *frameMvin = new ID3v2::TextIdentificationFrame("MVIN");
frameMvin->setText("2/3");
tag.addFrame(frameMvin);
PropertyMap properties = tag.properties();
CPPUNIT_ASSERT(properties.contains("MOVEMENTNAME"));
CPPUNIT_ASSERT(properties.contains("MOVEMENTNUMBER"));
CPPUNIT_ASSERT_EQUAL(String("Movement Name"), properties["MOVEMENTNAME"].front());
CPPUNIT_ASSERT_EQUAL(String("2/3"), properties["MOVEMENTNUMBER"].front());
ByteVector frameDataMvnm("MVNM"
"\x00\x00\x00\x0e"
"\x00\x00"
"\x00"
"Movement Name", 24);
CPPUNIT_ASSERT_EQUAL(frameDataMvnm, frameMvnm->render());
ByteVector frameDataMvin("MVIN"
"\x00\x00\x00\x04"
"\x00\x00"
"\x00"
"2/3", 14);
CPPUNIT_ASSERT_EQUAL(frameDataMvin, frameMvin->render());
ID3v2::FrameFactory *factory = ID3v2::FrameFactory::instance();
ID3v2::TextIdentificationFrame *parsedFrameMvnm =
dynamic_cast<ID3v2::TextIdentificationFrame *>(factory->createFrame(frameDataMvnm));
ID3v2::TextIdentificationFrame *parsedFrameMvin =
dynamic_cast<ID3v2::TextIdentificationFrame *>(factory->createFrame(frameDataMvin));
CPPUNIT_ASSERT(parsedFrameMvnm);
CPPUNIT_ASSERT(parsedFrameMvin);
CPPUNIT_ASSERT_EQUAL(String("Movement Name"), parsedFrameMvnm->toString());
CPPUNIT_ASSERT_EQUAL(String("2/3"), parsedFrameMvin->toString());
}
void testDeleteFrame()
{
ScopedFileCopy copy("rare_frames", ".mp3");

View File

@ -55,6 +55,7 @@ class TestMP4 : public CppUnit::TestFixture
CPPUNIT_TEST(testCovrWrite);
CPPUNIT_TEST(testCovrRead2);
CPPUNIT_TEST(testProperties);
CPPUNIT_TEST(testPropertiesMovement);
CPPUNIT_TEST(testFuzzedFile);
CPPUNIT_TEST(testRepeatedSave);
CPPUNIT_TEST_SUITE_END();
@ -378,6 +379,58 @@ public:
f.setProperties(tags);
}
void testPropertiesMovement()
{
MP4::File f(TEST_FILE_PATH_C("has-tags.m4a"));
PropertyMap tags = f.properties();
tags["WORK"] = StringList("Foo");
tags["MOVEMENTNAME"] = StringList("Bar");
tags["MOVEMENTNUMBER"] = StringList("2");
tags["MOVEMENTCOUNT"] = StringList("3");
tags["SHOWWORKMOVEMENT"] = StringList("1");
f.setProperties(tags);
tags = f.properties();
CPPUNIT_ASSERT(f.tag()->contains("\251wrk"));
CPPUNIT_ASSERT_EQUAL(StringList("Foo"), f.tag()->item("\251wrk").toStringList());
CPPUNIT_ASSERT_EQUAL(StringList("Foo"), tags["WORK"]);
CPPUNIT_ASSERT(f.tag()->contains("\251mvn"));
CPPUNIT_ASSERT_EQUAL(StringList("Bar"), f.tag()->item("\251mvn").toStringList());
CPPUNIT_ASSERT_EQUAL(StringList("Bar"), tags["MOVEMENTNAME"]);
CPPUNIT_ASSERT(f.tag()->contains("\251mvi"));
CPPUNIT_ASSERT_EQUAL(2, f.tag()->item("\251mvi").toInt());
CPPUNIT_ASSERT_EQUAL(StringList("2"), tags["MOVEMENTNUMBER"]);
CPPUNIT_ASSERT(f.tag()->contains("\251mvc"));
CPPUNIT_ASSERT_EQUAL(3, f.tag()->item("\251mvc").toInt());
CPPUNIT_ASSERT_EQUAL(StringList("3"), tags["MOVEMENTCOUNT"]);
CPPUNIT_ASSERT(f.tag()->contains("shwm"));
CPPUNIT_ASSERT_EQUAL(true, f.tag()->item("shwm").toBool());
CPPUNIT_ASSERT_EQUAL(StringList("1"), tags["SHOWWORKMOVEMENT"]);
tags["SHOWWORKMOVEMENT"] = StringList("0");
f.setProperties(tags);
tags = f.properties();
CPPUNIT_ASSERT(f.tag()->contains("shwm"));
CPPUNIT_ASSERT_EQUAL(false, f.tag()->item("shwm").toBool());
CPPUNIT_ASSERT_EQUAL(StringList("0"), tags["SHOWWORKMOVEMENT"]);
tags["WORK"] = StringList();
tags["MOVEMENTNAME"] = StringList();
tags["MOVEMENTNUMBER"] = StringList();
tags["MOVEMENTCOUNT"] = StringList();
tags["SHOWWORKMOVEMENT"] = StringList();
f.setProperties(tags);
}
void testFuzzedFile()
{
MP4::File f(TEST_FILE_PATH_C("infloop.m4a"));