diff options
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | taglib/mpeg/mpegfile.cpp | 101 | ||||
-rw-r--r-- | taglib/mpeg/mpegfile.h | 6 |
3 files changed, 107 insertions, 1 deletions
@@ -4,6 +4,7 @@ TagLib 1.8 (In Development) * Support for writing ID3v2.3 tags. * Added methods for checking if WMA and MP4 files are DRM-protected. * Started using atomic int operations for reference counting. + * Find APE tags even if there's a Lyrics3v2 tag present (BUG:254223). TagLib 1.7 (Mar 11, 2011) ========================= diff --git a/taglib/mpeg/mpegfile.cpp b/taglib/mpeg/mpegfile.cpp index a3bad823..985370c9 100644 --- a/taglib/mpeg/mpegfile.cpp +++ b/taglib/mpeg/mpegfile.cpp @@ -56,7 +56,9 @@ public: ID3v1Location(-1), hasID3v2(false), hasID3v1(false), + hasLyrics3v2(false), hasAPE(false), + lyrics3v2Size(0), properties(0) { @@ -85,7 +87,9 @@ public: bool hasID3v2; bool hasID3v1; + bool hasLyrics3v2; bool hasAPE; + long lyrics3v2Size; Properties *properties; }; @@ -198,6 +202,10 @@ bool MPEG::File::save(int tags, bool stripOthers, int id3v2Version) if(ID3v1Tag()) d->ID3v1Location = findID3v1(); + // Lyrics3v2 tag location has changed, update if it exists + + findLyrics3v2(); + // APE tag location has changed, update if it exists if(APETag()) @@ -296,6 +304,10 @@ bool MPEG::File::strip(int tags, bool freeMemory) if(ID3v1Tag()) d->ID3v1Location = findID3v1(); + // Lyrics3v2 tag location has changed, update if it exists + + findLyrics3v2(); + // APE tag location has changed, update if it exists if(APETag()) @@ -432,6 +444,10 @@ void MPEG::File::read(bool readProperties, Properties::ReadStyle propertiesStyle d->tag.set(ID3v1Index, new ID3v1::Tag(this, d->ID3v1Location)); d->hasID3v1 = true; } + + // Look for a Lyrics3v2 tag + + findLyrics3v2(); // Look for an APE tag @@ -576,10 +592,41 @@ long MPEG::File::findID3v1() return -1; } +void MPEG::File::findLyrics3v2() +{ + if(isValid()) { + long offset = -9; + if( d->hasID3v1 ) + offset -= 128; + seek(offset, End); + + if(readBlock(9) == "LYRICS200") { + d->hasLyrics3v2 = true; + + offset -= 6; + seek(offset, End); + + ByteVector sizeVector = readBlock(6); + d->lyrics3v2Size = 15 + readNumber(sizeVector); + + return; + } + } + + d->hasLyrics3v2 = false; + d->lyrics3v2Size = 0; +} + void MPEG::File::findAPE() { if(isValid()) { - seek(d->hasID3v1 ? -160 : -32, End); + long offset = -32; + if(d->hasID3v1) + offset -= 128; + if(d->hasLyrics3v2) + offset -= d->lyrics3v2Size; + + seek(offset, End); long p = tell(); @@ -597,6 +644,58 @@ void MPEG::File::findAPE() d->APEFooterLocation = -1; } +long MPEG::File::readNumber(ByteVector vector) +{ + long number = 0; + int exp = 1; + int value = 0; + for(int i=vector.size(); i>0; i--) { + switch(vector.at(i-1)) { + case '1': { + value = 1; + break; + } + case '2': { + value = 2; + break; + } + case '3': { + value = 3; + break; + } + case '4': { + value = 4; + break; + } + case '5': { + value = 5; + break; + } + case '6': { + value = 6; + break; + } + case '7': { + value = 7; + break; + } + case '8': { + value = 8; + break; + } + case '9': { + value = 9; + break; + } + default: + value = 0; + } + number += value * exp; + exp *= 10; + } + return number; +} + bool MPEG::File::secondSynchByte(char byte) { if(uchar(byte) == 0xff) diff --git a/taglib/mpeg/mpegfile.h b/taglib/mpeg/mpegfile.h index cff5469d..270cd7ae 100644 --- a/taglib/mpeg/mpegfile.h +++ b/taglib/mpeg/mpegfile.h @@ -287,9 +287,15 @@ namespace TagLib { void read(bool readProperties, Properties::ReadStyle propertiesStyle); long findID3v2(); long findID3v1(); + void findLyrics3v2(); void findAPE(); /*! + * Extracts a number from a ByteVector + */ + long readNumber(ByteVector vector); + + /*! * MPEG frames can be recognized by the bit pattern 11111111 111, so the * first byte is easy to check for, however checking to see if the second byte * starts with \e 111 is a bit more tricky, hence this member function. |