From 27332c35ac52295281a4ddcfac48360480750b6e Mon Sep 17 00:00:00 2001 From: Daniel Faust Date: Tue, 5 Jul 2011 17:24:59 +0200 Subject: Find APE tags even if there's a Lyrics3v2 tag present http://bugs.kde.org/show_bug.cgi?id=254223 --- NEWS | 1 + taglib/mpeg/mpegfile.cpp | 95 +++++++++++++++++++++++++++++++++++++++++++++++- taglib/mpeg/mpegfile.h | 1 + 3 files changed, 96 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index b157c457..48b01078 100644 --- a/NEWS +++ b/NEWS @@ -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..3bba91da 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,87 @@ 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); + long size = 15; + int exp = 1; + int value = 0; + for(int i=sizeVector.size(); i>0; i--) { + switch(sizeVector.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; + } + size += value * exp; + exp *= 10; + } + d->lyrics3v2Size = size; + 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(); diff --git a/taglib/mpeg/mpegfile.h b/taglib/mpeg/mpegfile.h index cff5469d..d621a470 100644 --- a/taglib/mpeg/mpegfile.h +++ b/taglib/mpeg/mpegfile.h @@ -287,6 +287,7 @@ namespace TagLib { void read(bool readProperties, Properties::ReadStyle propertiesStyle); long findID3v2(); long findID3v1(); + void findLyrics3v2(); void findAPE(); /*! -- cgit v1.2.3 From 0ea8e44df79892ccdf27ce1d82c92dff3c678efa Mon Sep 17 00:00:00 2001 From: Daniel Faust Date: Thu, 7 Jul 2011 17:57:22 +0200 Subject: String to number conversion moved to new function - long readNumber(ByteVector vector) --- taglib/mpeg/mpegfile.cpp | 102 +++++++++++++++++++++++++---------------------- taglib/mpeg/mpegfile.h | 5 +++ 2 files changed, 59 insertions(+), 48 deletions(-) diff --git a/taglib/mpeg/mpegfile.cpp b/taglib/mpeg/mpegfile.cpp index 3bba91da..985370c9 100644 --- a/taglib/mpeg/mpegfile.cpp +++ b/taglib/mpeg/mpegfile.cpp @@ -607,54 +607,8 @@ void MPEG::File::findLyrics3v2() seek(offset, End); ByteVector sizeVector = readBlock(6); - long size = 15; - int exp = 1; - int value = 0; - for(int i=sizeVector.size(); i>0; i--) { - switch(sizeVector.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; - } - size += value * exp; - exp *= 10; - } - d->lyrics3v2Size = size; + d->lyrics3v2Size = 15 + readNumber(sizeVector); + return; } } @@ -690,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 d621a470..270cd7ae 100644 --- a/taglib/mpeg/mpegfile.h +++ b/taglib/mpeg/mpegfile.h @@ -290,6 +290,11 @@ namespace TagLib { 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 -- cgit v1.2.3