]> granicus.if.org Git - taglib/commitdiff
APE: Find an ID3v2 tag and calculate the stream length in APE::File.
authorTsuda Kageyu <tsuda.kageyu@gmail.com>
Fri, 12 Jun 2015 07:40:03 +0000 (16:40 +0900)
committerTsuda Kageyu <tsuda.kageyu@gmail.com>
Fri, 19 Jun 2015 19:34:34 +0000 (04:34 +0900)
taglib/ape/apefile.cpp
taglib/ape/apefile.h
taglib/ape/apeproperties.cpp
taglib/ape/apeproperties.h

index 3cb9d9a70459cf53407f3e80bd1a0346c1a17389..9feb198c6728c3653ac091cd958ead374056cc1f 100644 (file)
@@ -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;
+}
index 4d806d1ac3816ae63e368987635e925437532ad4..f2b6c672b52c1626de6db3ab0cf79dc6e9256b30 100644 (file)
@@ -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;
index 233399ef1aa711dfb5ba53b629d880441fb8c5c5..90ab63edc627efcef5ac01219db2b8e40f42bafa 100644 (file)
@@ -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
index ce31f84cc37dea348f422cdae8d46f0b2f8572ac..fcf125ff5df63792c4043b989fc2c62f47daa4f5 100644 (file)
@@ -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);