mirror of
https://github.com/taglib/taglib.git
synced 2025-06-03 00:58:12 -04:00
APE: Find an ID3v2 tag and calculate the stream length in APE::File.
This commit is contained in:
parent
f15fe869a5
commit
dfee7020da
@ -36,6 +36,7 @@
|
||||
#include <tdebug.h>
|
||||
#include <tagunion.h>
|
||||
#include <id3v1tag.h>
|
||||
#include <id3v2header.h>
|
||||
#include <tpropertymap.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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<int>(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
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user