From dfee7020da7b725ab37992e1a9f4400837013eae Mon Sep 17 00:00:00 2001 From: Tsuda Kageyu Date: Fri, 12 Jun 2015 16:40:03 +0900 Subject: [PATCH] APE: Find an ID3v2 tag and calculate the stream length in APE::File. --- taglib/ape/apefile.cpp | 57 +++++++++++++++++++++++++++-- taglib/ape/apefile.h | 3 +- taglib/ape/apeproperties.cpp | 69 +++++++----------------------------- taglib/ape/apeproperties.h | 17 +++++---- 4 files changed, 81 insertions(+), 65 deletions(-) diff --git a/taglib/ape/apefile.cpp b/taglib/ape/apefile.cpp index 3cb9d9a7..9feb198c 100644 --- a/taglib/ape/apefile.cpp +++ b/taglib/ape/apefile.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include "apefile.h" @@ -57,12 +58,17 @@ public: APELocation(-1), APESize(0), ID3v1Location(-1), + ID3v2Header(0), + ID3v2Location(-1), + ID3v2Size(0), properties(0), hasAPE(false), - hasID3v1(false) {} + hasID3v1(false), + hasID3v2(false) {} ~FilePrivate() { + delete ID3v2Header; delete properties; } @@ -71,6 +77,10 @@ public: long ID3v1Location; + ID3v2::Header *ID3v2Header; + long ID3v2Location; + uint ID3v2Size; + TagUnion tag; Properties *properties; @@ -80,6 +90,7 @@ public: bool hasAPE; bool hasID3v1; + bool hasID3v2; }; //////////////////////////////////////////////////////////////////////////////// @@ -251,6 +262,17 @@ bool APE::File::hasID3v1Tag() const void APE::File::read(bool readProperties, Properties::ReadStyle /* propertiesStyle */) { + // Look for an ID3v2 tag + + d->ID3v2Location = findID3v2(); + + if(d->ID3v2Location >= 0) { + seek(d->ID3v2Location); + d->ID3v2Header = new ID3v2::Header(readBlock(ID3v2::Header::size())); + d->ID3v2Size = d->ID3v2Header->completeTagSize(); + d->hasID3v2 = true; + } + // Look for an ID3v1 tag d->ID3v1Location = findID3v1(); @@ -277,7 +299,25 @@ void APE::File::read(bool readProperties, Properties::ReadStyle /* propertiesSty // Look for APE audio properties if(readProperties) { - d->properties = new Properties(this); + + long streamLength; + + if(d->hasAPE) + streamLength = d->APELocation; + else if(d->hasID3v1) + streamLength = d->ID3v1Location; + else + streamLength = length(); + + if(d->hasID3v2) { + seek(d->ID3v2Location + d->ID3v2Size); + streamLength -= (d->ID3v2Location + d->ID3v2Size); + } + else { + seek(0); + } + + d->properties = new Properties(this, streamLength); } } @@ -312,3 +352,16 @@ long APE::File::findID3v1() return -1; } + +long APE::File::findID3v2() +{ + if(!isValid()) + return -1; + + seek(0); + + if(readBlock(3) == ID3v2::Header::fileIdentifier()) + return 0; + + return -1; +} diff --git a/taglib/ape/apefile.h b/taglib/ape/apefile.h index 4d806d1a..f2b6c672 100644 --- a/taglib/ape/apefile.h +++ b/taglib/ape/apefile.h @@ -216,8 +216,9 @@ namespace TagLib { File &operator=(const File &); void read(bool readProperties, Properties::ReadStyle propertiesStyle); - long findID3v1(); long findAPE(); + long findID3v1(); + long findID3v2(); class FilePrivate; FilePrivate *d; diff --git a/taglib/ape/apeproperties.cpp b/taglib/ape/apeproperties.cpp index 233399ef..90ab63ed 100644 --- a/taglib/ape/apeproperties.cpp +++ b/taglib/ape/apeproperties.cpp @@ -67,7 +67,14 @@ APE::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style), d(new PropertiesPrivate()) { - read(file); + debug("APE::Properties::Properties() -- This constructor is no longer used."); +} + +APE::Properties::Properties(File *file, long streamLength, ReadStyle style) : + AudioProperties(style), + d(new PropertiesPrivate()) +{ + read(file, streamLength); } APE::Properties::~Properties() @@ -124,12 +131,14 @@ TagLib::uint APE::Properties::sampleFrames() const // private members //////////////////////////////////////////////////////////////////////////////// -void APE::Properties::read(File *file) +void APE::Properties::read(File *file, long streamLength) { // First we are searching the descriptor - const long offset = findDescriptor(file); - if(offset < 0) + const long offset = file->find("MAC ", file->tell()); + if(offset < 0) { + debug("APE::Properties::read() -- APE descriptor not found"); return; + } // Then we read the header common for all versions of APE file->seek(offset); @@ -139,11 +148,6 @@ void APE::Properties::read(File *file) return; } - if(!commonHeader.startsWith("MAC ")) { - debug("APE::Properties::read() -- invalid header signiture."); - return; - } - d->version = commonHeader.toUShort(4, false); if(d->version >= 3980) @@ -151,14 +155,6 @@ void APE::Properties::read(File *file) else analyzeOld(file); - long streamLength = file->length() - offset; - - if(file->hasID3v1Tag()) - streamLength -= 128; - - if(file->hasAPETag()) - streamLength -= file->APETag()->footer()->completeTagSize(); - if(d->sampleFrames > 0 && d->sampleRate > 0) { const double length = d->sampleFrames * 1000.0 / d->sampleRate; d->length = static_cast(length + 0.5); @@ -166,45 +162,6 @@ void APE::Properties::read(File *file) } } -long APE::Properties::findDescriptor(File *file) -{ - const long ID3v2Location = findID3v2(file); - long ID3v2OriginalSize = 0; - bool hasID3v2 = false; - if(ID3v2Location >= 0) { - const ID3v2::Tag tag(file, ID3v2Location); - ID3v2OriginalSize = tag.header()->completeTagSize(); - if(tag.header()->tagSize() > 0) - hasID3v2 = true; - } - - long offset = 0; - if(hasID3v2) - offset = file->find("MAC ", ID3v2Location + ID3v2OriginalSize); - else - offset = file->find("MAC "); - - if(offset < 0) { - debug("APE::Properties::findDescriptor() -- APE descriptor not found"); - return -1; - } - - return offset; -} - -long APE::Properties::findID3v2(File *file) -{ - if(!file->isValid()) - return -1; - - file->seek(0); - - if(file->readBlock(3) == ID3v2::Header::fileIdentifier()) - return 0; - - return -1; -} - void APE::Properties::analyzeCurrent(File *file) { // Read the descriptor diff --git a/taglib/ape/apeproperties.h b/taglib/ape/apeproperties.h index ce31f84c..fcf125ff 100644 --- a/taglib/ape/apeproperties.h +++ b/taglib/ape/apeproperties.h @@ -51,9 +51,17 @@ namespace TagLib { public: /*! * Create an instance of APE::Properties with the data read from the - * ByteVector \a data. + * APE::File \a file. + * + * \deprecated */ - Properties(File *f, ReadStyle style = Average); + Properties(File *file, ReadStyle style = Average); + + /*! + * Create an instance of APE::Properties with the data read from the + * APE::File \a file. + */ + Properties(File *file, long streamLength, ReadStyle style = Average); /*! * Destroys this APE::Properties instance. @@ -121,10 +129,7 @@ namespace TagLib { Properties(const Properties &); Properties &operator=(const Properties &); - void read(File *file); - - long findDescriptor(File *file); - long findID3v2(File *file); + void read(File *file, long streamLength); void analyzeCurrent(File *file); void analyzeOld(File *file); -- 2.40.0