mirror of
https://github.com/taglib/taglib.git
synced 2025-05-27 21:20:26 -04:00
Read ID3v2.3 genres with multiple references to ID3v1 genres (#988)
As described in id3v2.3.0.txt (4.2.1, TCON), now multiple genres are possible, e.g. "(51)(39)". Additionally, support the keywords RX and CR.
This commit is contained in:
parent
30d839538d
commit
d602ae483e
@ -60,22 +60,24 @@ namespace
|
||||
|
||||
for(StringList::ConstIterator it = fields.begin(); it != fields.end(); ++it) {
|
||||
String s = *it;
|
||||
int end = s.find(")");
|
||||
int offset = 0;
|
||||
int end = 0;
|
||||
|
||||
if(s.startsWith("(") && end > 0) {
|
||||
while(s.length() > offset && s[offset] == '(' &&
|
||||
(end = s.find(")", offset + 1)) > offset) {
|
||||
// "(12)Genre"
|
||||
String text = s.substr(end + 1);
|
||||
const String genreCode = s.substr(offset + 1, end - 1);
|
||||
s = s.substr(end + 1);
|
||||
bool ok;
|
||||
int number = s.substr(1, end - 1).toInt(&ok);
|
||||
if(ok && number >= 0 && number <= 255 && !(ID3v1::genre(number) == text))
|
||||
newfields.append(s.substr(1, end - 1));
|
||||
if(!text.isEmpty())
|
||||
newfields.append(text);
|
||||
int number = genreCode.toInt(&ok);
|
||||
if((ok && number >= 0 && number <= 255 &&
|
||||
!(ID3v1::genre(number) == s)) ||
|
||||
genreCode == "RX" || genreCode == "CR")
|
||||
newfields.append(genreCode);
|
||||
}
|
||||
else {
|
||||
if(!s.isEmpty())
|
||||
// "Genre" or "12"
|
||||
newfields.append(s);
|
||||
}
|
||||
}
|
||||
|
||||
if(newfields.isEmpty())
|
||||
|
@ -101,6 +101,7 @@ class TestID3v2 : public CppUnit::TestFixture
|
||||
CPPUNIT_TEST(testSaveUTF16Comment);
|
||||
CPPUNIT_TEST(testUpdateGenre23_1);
|
||||
CPPUNIT_TEST(testUpdateGenre23_2);
|
||||
CPPUNIT_TEST(testUpdateGenre23_3);
|
||||
CPPUNIT_TEST(testUpdateGenre24);
|
||||
CPPUNIT_TEST(testUpdateDate22);
|
||||
CPPUNIT_TEST(testDowngradeTo23);
|
||||
@ -686,7 +687,7 @@ public:
|
||||
// "Refinement" is different from the ID3v1 genre
|
||||
ID3v2::FrameFactory *factory = ID3v2::FrameFactory::instance();
|
||||
ByteVector data = ByteVector("TCON" // Frame ID
|
||||
"\x00\x00\x00\x13" // Frame size
|
||||
"\x00\x00\x00\x0d" // Frame size
|
||||
"\x00\x00" // Frame flags
|
||||
"\x00" // Encoding
|
||||
"(4)Eurodisco", 23); // Text
|
||||
@ -703,6 +704,29 @@ public:
|
||||
CPPUNIT_ASSERT_EQUAL(String("Disco Eurodisco"), tag.genre());
|
||||
}
|
||||
|
||||
void testUpdateGenre23_3()
|
||||
{
|
||||
// Multiple references and a refinement
|
||||
ID3v2::FrameFactory *factory = ID3v2::FrameFactory::instance();
|
||||
ByteVector data = ByteVector("TCON" // Frame ID
|
||||
"\x00\x00\x00\x15" // Frame size
|
||||
"\x00\x00" // Frame flags
|
||||
"\x00" // Encoding
|
||||
"(9)(138)Viking Metal", 31); // Text
|
||||
ID3v2::Header header;
|
||||
header.setMajorVersion(3);
|
||||
ID3v2::TextIdentificationFrame *frame =
|
||||
dynamic_cast<TagLib::ID3v2::TextIdentificationFrame*>(factory->createFrame(data, &header));
|
||||
CPPUNIT_ASSERT_EQUAL(3U, frame->fieldList().size());
|
||||
CPPUNIT_ASSERT_EQUAL(String("9"), frame->fieldList()[0]);
|
||||
CPPUNIT_ASSERT_EQUAL(String("138"), frame->fieldList()[1]);
|
||||
CPPUNIT_ASSERT_EQUAL(String("Viking Metal"), frame->fieldList()[2]);
|
||||
|
||||
ID3v2::Tag tag;
|
||||
tag.addFrame(frame);
|
||||
CPPUNIT_ASSERT_EQUAL(String("Metal Black Metal Viking Metal"), tag.genre());
|
||||
}
|
||||
|
||||
void testUpdateGenre24()
|
||||
{
|
||||
ID3v2::FrameFactory *factory = ID3v2::FrameFactory::instance();
|
||||
|
Loading…
Reference in New Issue
Block a user