]> granicus.if.org Git - taglib/commitdiff
Mostly get ID3v2.2 working. Sure, it's a standard from 1998 that was
authorScott Wheeler <wheeler@kde.org>
Fri, 20 Feb 2004 01:41:25 +0000 (01:41 +0000)
committerScott Wheeler <wheeler@kde.org>
Fri, 20 Feb 2004 01:41:25 +0000 (01:41 +0000)
replaced in 1999, but apparently iTunes still uses it.

This gets the frame parsing code to support 2.2 and required deprecating
a couple of methods so that an ID3v2 version could be passed along.

There still needs to be a translation table added to handle converting
ID3v2.2 frame names to their ID3v2.4 equivalents, but that can come later.
For now the framelister program from the examples dir is able to read all
of the text frames.

CCMAIL:Keith Brady <keith@funnelboy.org>

git-svn-id: svn://anonsvn.kde.org/home/kde/trunk/kdesupport/taglib@289567 283d02a7-25f6-0310-bc7c-ecb5cbfe19da

examples/strip-id3v1.cpp
mpeg/id3v2/frames/commentsframe.cpp
mpeg/id3v2/frames/textidentificationframe.cpp
mpeg/id3v2/id3v2frame.cpp
mpeg/id3v2/id3v2frame.h
mpeg/id3v2/id3v2framefactory.cpp
mpeg/id3v2/id3v2framefactory.h
mpeg/id3v2/id3v2header.cpp
mpeg/id3v2/id3v2tag.cpp

index ab36d7117b3a57f39c9534ea9c3224ad28fb8b01..f8c8891637a3e07a16aabb5d33150ecc30a837dc 100644 (file)
@@ -35,6 +35,6 @@ int main(int argc, char *argv[])
     std::cout << "******************** Stripping ID3v1 Tag From: \"" << argv[i] << "\"********************" << std::endl;
 
     MPEG::File f(argv[i]);
-    f.strip(MPEG::File::ID3v1);
+    f.strip();
   }
 }
index 4a9083f6bf3f3528d05d4c2a008a2d5fcc6201ff..99af7a4ad9ec91550f7c9435717ebbe6dfd7cfcf 100644 (file)
@@ -43,14 +43,14 @@ public:
 
 CommentsFrame::CommentsFrame(String::Type encoding) : Frame("COMM")
 {
-  d = new CommentsFramePrivate();
+  d = new CommentsFramePrivate;
   d->textEncoding = encoding;
 }
 
 CommentsFrame::CommentsFrame(const ByteVector &data) : Frame(data)
 {
-  d = new CommentsFramePrivate();
-  parseFields(data.mid(Header::size(), size()));
+  d = new CommentsFramePrivate;
+  parseFields(data.mid(Header::size(header()->version()), size()));
 }
 
 CommentsFrame::~CommentsFrame()
@@ -148,5 +148,5 @@ ByteVector CommentsFrame::renderFields() const
 CommentsFrame::CommentsFrame(const ByteVector &data, Header *h) : Frame(h)
 {
   d = new CommentsFramePrivate();
-  parseFields(data.mid(Header::size(), size()));
+  parseFields(data.mid(Header::size(h->version()), size()));
 }
index ae76fb9c36ff1b1f6f878a68316db7dd7ecbc3d0..0d6968615ca8f28215034c37ab3670ae1d5f3b50 100644 (file)
@@ -146,5 +146,5 @@ ByteVector TextIdentificationFrame::renderFields() const
 TextIdentificationFrame::TextIdentificationFrame(const ByteVector &data, Header *h) : Frame(h)
 {
   d = new TextIdentificationFramePrivate;
-  parseFields(data.mid(Header::size(), size()));
+  parseFields(data.mid(Header::size(h->version()), size()));
 }
index 5f0f894a9c8681feae5443723683d542e71b5ee1..2180e6ef935b57b0680cce127298172a2f21f7b9 100644 (file)
@@ -50,6 +50,11 @@ TagLib::uint Frame::headerSize()
   return Header::size();
 }
 
+TagLib::uint Frame::headerSize(uint version)
+{
+  return Header::size(version);
+}
+
 ByteVector Frame::textDelimiter(String::Type t)
 {
   ByteVector d = char(0);
@@ -108,13 +113,13 @@ ByteVector Frame::render() const
 
 Frame::Frame(const ByteVector &data)
 {
-  d = new FramePrivate();
+  d = new FramePrivate;
   d->header = new Header(data);
 }
 
 Frame::Frame(Header *h)
 {
-  d = new FramePrivate();
+  d = new FramePrivate;
   d->header = h;
 }
 
@@ -139,7 +144,8 @@ void Frame::parse(const ByteVector &data)
     d->header = new Header(data);
 
   // size() is the lenght of the field data
-  parseFields(data.mid(Header::size(), size()));
+
+  parseFields(data.mid(Header::size(d->header->version()), size()));
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -149,11 +155,11 @@ void Frame::parse(const ByteVector &data)
 class Frame::Header::HeaderPrivate
 {
 public:
-  HeaderPrivate() : frameSize(0) {}
+  HeaderPrivate() : frameSize(0), version(4) {}
 
   ByteVector frameID;
   uint frameSize;
-  static const unsigned int size = 10;
+  uint version;
 };
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -162,7 +168,21 @@ public:
 
 TagLib::uint Frame::Header::size()
 {
-  return HeaderPrivate::size;
+  return size(4);
+}
+
+TagLib::uint Frame::Header::size(uint version)
+{
+  switch(version) {
+  case 0:
+  case 1:
+  case 2:
+    return 6;
+  case 3:
+  case 4:
+  default:
+    return 10;
+  }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -175,6 +195,12 @@ Frame::Header::Header(const ByteVector &data, bool synchSafeInts)
   setData(data, synchSafeInts);
 }
 
+Frame::Header::Header(const ByteVector &data, uint version)
+{
+  d = new HeaderPrivate;
+  setData(data, version);
+}
+
 Frame::Header::~Header()
 {
   delete d;
@@ -182,33 +208,78 @@ Frame::Header::~Header()
 
 void Frame::Header::setData(const ByteVector &data, bool synchSafeInts)
 {
-  if(data.size() < 4) {
-    debug("You must at least specify a frame ID.");
-    return;
-  }
+  setData(data, uint(synchSafeInts ? 4 : 3));
+}
+
+void Frame::Header::setData(const ByteVector &data, uint version)
+{
+  d->version = version;
+
+  switch(version) {
+  case 0:
+  case 1:
+  case 2:
+  {
 
-  // set the frame ID -- the first four bytes
+    // ID3v2.2 
 
-  d->frameID = data.mid(0, 4);
+    if(data.size() < 3) {
+      debug("You must at least specify a frame ID.");
+      return;
+    }
 
-  // If the full header information was not passed in, do not continue to the
-  // steps to parse the frame size and flags.
+    // Set the frame ID -- the first three bytes
 
-  if(data.size() < 10) {
-    d->frameSize = 0;
-    return;
+    d->frameID = data.mid(0, 3);
+
+    // If the full header information was not passed in, do not continue to the
+    // steps to parse the frame size and flags.
+
+    if(data.size() < 6) {
+      d->frameSize = 0;
+      return;
+    }
+
+    d->frameSize = data.mid(3, 3).toUInt();
+
+    break;
   }
+  case 3:
+  case 4:
+  default:
+  {
+    // ID3v2.3 / ID3v2.4
 
-  // Set the size -- the frame size is the four bytes starting at byte four in
-  // the frame header (structure 4)
+    if(data.size() < 4) {
+      debug("You must at least specify a frame ID.");
+      return;
+    }
 
-  if(synchSafeInts)
-    d->frameSize = SynchData::toUInt(data.mid(4, 4));
-  else
-    d->frameSize = data.mid(4, 4).toUInt();
+    // Set the frame ID -- the first four bytes
+
+    d->frameID = data.mid(0, 4);
+
+    // If the full header information was not passed in, do not continue to the
+    // steps to parse the frame size and flags.
+
+    if(data.size() < 10) {
+      d->frameSize = 0;
+      return;
+    }
 
-  // read flags
-  // ...
+    // Set the size -- the frame size is the four bytes starting at byte four in
+    // the frame header (structure 4)
+
+    if(version >= 4)
+      d->frameSize = SynchData::toUInt(data.mid(4, 4));
+    else
+      d->frameSize = data.mid(4, 4).toUInt();
+
+    // TODO: read flags
+
+    break;
+  }
+  }
 }
 
 ByteVector Frame::Header::frameID() const
@@ -231,6 +302,11 @@ void Frame::Header::setFrameSize(uint size)
   d->frameSize = size;
 }
 
+TagLib::uint Frame::Header::version() const
+{
+  return d->version;
+}
+
 ByteVector Frame::Header::render() const
 {
   ByteVector flags(2, char(0)); // just blank for the moment
index b772ea40a53df5650aa89ba2e720498f567c8fe7..920429c66cc8a72517cbe9a84c9a7d7cbd1dbee9 100644 (file)
@@ -65,8 +65,20 @@ namespace TagLib {
 
       /*!
        * Returns the size of the frame header
+       *
+       * \deprecated This is only accurate for ID3v2.3 or ID3v2.4.  Please use
+       * the call below which accepts an ID3v2 version number.  In the next
+       * non-binary compatible release this will be made into a non-static
+       * member that checks the internal ID3v2 version.
        */
-      static uint headerSize();
+      static uint headerSize(); // BIC: remove and make non-static
+
+      /*!
+       * Returns the size of the frame header for the given ID3v2 version.
+       *
+       * \deprecated Please see the explanation above.
+       */
+      static uint headerSize(uint version); // BIC: remove and make non-static
 
       /*!
        * Sets the data that will be used as the frame.  Since the length is not
@@ -187,8 +199,20 @@ namespace TagLib {
        * Construct a Frame Header based on \a data.  \a data must at least
        * contain a 4 byte frame ID, and optionally can contain flag data and the
        * frame size.  i.e. Just the frame id -- "TALB" -- is a valid value.
+       *
+       * \deprecated Please use the constructor below that accepts a version
+       * number.
+       */
+      explicit Header(const ByteVector &data, bool synchSafeInts);
+
+      /*!
+       * Construct a Frame Header based on \a data.  \a data must at least
+       * contain a 4 byte frame ID, and optionally can contain flag data and the
+       * frame size.  i.e. Just the frame id -- "TALB" -- is a valid value.
+       *
+       * \a version should be the ID3v2 version of the tag.
        */
-      explicit Header(const ByteVector &data, bool synchSafeInts = true);
+      explicit Header(const ByteVector &data, uint version = 4);
 
       /*!
        * Destroys this Header instance.
@@ -197,8 +221,17 @@ namespace TagLib {
 
       /*!
        * Sets the data for the Header.
+       *
+       * \deprecated Please use the version below that accepts an ID3v2 version
+       * number.
+       */
+      void setData(const ByteVector &data, bool synchSafeInts);
+
+      /*!
+       * Sets the data for the Header.  \a version should indicate the ID3v2
+       * version number of the tag that this frame is contained in.
        */
-      void setData(const ByteVector &data, bool synchSafeInts = true);
+      void setData(const ByteVector &data, uint version = 4);
 
       /*!
        * Returns the Frame ID (Structure, <a href="id3v2-structure.html#4">4</a>)
@@ -228,11 +261,29 @@ namespace TagLib {
       void setFrameSize(uint size);
 
       /*!
-       * Returns the size of the frame header in bytes.  Currently this is
-       * always 10.
+       * Returns the ID3v2 version of the header (as passed in from the
+       * construction of the header).
+       */
+      uint version() const;
+
+      /*!
+       * Returns the size of the frame header in bytes.
+       *
+       * \deprecated Please use the version of this method that accepts a
+       * version.  This is only accurate for ID3v2.3 and ID3v2.4.  This will be
+       * removed in the next binary incompatible release (2.0) and will be
+       * replaced with a non-static method that checks the frame version.
        */
       static uint size();
 
+      /*!
+       * Returns the size of the frame header in bytes for the ID3v2 version
+       * that's given.
+       *
+       * \deprecated Please see the explanation in the version above.
+       */
+      static uint size(uint version);
+
       /*!
        * Render the Header back to binary format in a ByteVector.
        */
index 8d4352faebfaed1d23196eb454c0e1bce0c7260b..aa9189aeb7ba514c3651b732e7a57fa34d490360 100644 (file)
@@ -56,15 +56,20 @@ FrameFactory *FrameFactory::instance()
 
 Frame *FrameFactory::createFrame(const ByteVector &data, bool synchSafeInts) const
 {
-  Frame::Header *header = new Frame::Header(data, synchSafeInts);
+  return createFrame(data, uint(synchSafeInts ? 4 : 3));
+}
+
+Frame *FrameFactory::createFrame(const ByteVector &data, uint version) const
+{
+  Frame::Header *header = new Frame::Header(data, version);
 
   TagLib::ByteVector frameID = header->frameID();
 
   // A quick sanity check -- make sure that the frameID is 4 uppercase Latin1
   // characters.  Also make sure that there is data in the frame.
 
-  if(!frameID.size() == 4 || header->frameSize() <= 0)
-    return 0;
+  if(!frameID.size() == (version < 3 ? 3 : 4) || header->frameSize() <= 0)
+      return 0;
 
   for(ByteVector::ConstIterator it = frameID.begin(); it != frameID.end(); it++) {
     if( (*it < 'A' || *it > 'Z') && (*it < '1' || *it > '9') ) {
index f1cefcdea8c579ec1d58ac3d581845d9d714dfe6..544b0f0e9edf3d2ef52db49537e5f069d366335f 100644 (file)
@@ -1,4 +1,4 @@
-/***************************************************************************
+ /***************************************************************************
     copyright            : (C) 2002, 2003 by Scott Wheeler
     email                : wheeler@kde.org
  ***************************************************************************/
@@ -56,8 +56,18 @@ namespace TagLib {
        * Create a frame based on \a data.  \a synchSafeInts should only be set
        * false if we are parsing an old tag (v2.3 or older) that does not support
        * synchsafe ints.
+       *
+       * \deprecated Please use the method below that accepts an ID3 version
+       * number in new code.
+       */
+      Frame *createFrame(const ByteVector &data, bool synchSafeInts) const;
+
+      /*!
+       * Create a frame based on \a data.  \a version should indicate the ID3v2
+       * version of the tag.  As ID3v2.4 is the most current version of the
+       * standard 4 is the default.
        */
-      Frame *createFrame(const ByteVector &data, bool synchSafeInts = true) const;
+      Frame *createFrame(const ByteVector &data, uint version = 4) const;
 
       /*!
        * Returns the default text encoding for text frames.  If setTextEncoding()
index caa28e2cf1aa5933b83788272aa2ed2c33be2c95..4ed09e8a59cf1e00e8f0e5f3d964d15d64b65d74 100644 (file)
@@ -78,12 +78,12 @@ ByteVector Header::fileIdentifier()
 
 Header::Header()
 {
-  d = new HeaderPrivate();
+  d = new HeaderPrivate;
 }
 
 Header::Header(const ByteVector &data)
 {
-  d = new HeaderPrivate();
+  d = new HeaderPrivate;
   parse(data);
 }
 
index 871cd130eaf8dfe756a969bf02bc1bf345846193..a3a0d60e29227e878028f628700a5c13bf57da40 100644 (file)
@@ -365,7 +365,7 @@ void ID3v2::Tag::parse(const ByteVector &data)
   // Make sure that there is at least enough room in the remaining frame data for
   // a frame header.
 
-  while(frameDataPosition < frameDataLength - Frame::headerSize()) {
+  while(frameDataPosition < frameDataLength - Frame::headerSize(d->header.majorVersion())) {
 
     // If the next data is position is 0, assume that we've hit the padding
     // portion of the frame data.
@@ -379,10 +379,8 @@ void ID3v2::Tag::parse(const ByteVector &data)
       return;
     }
 
-    bool synchSafeInts = d->header.majorVersion() >= 4;
-
     Frame *frame = d->factory->createFrame(data.mid(frameDataOffset + frameDataPosition),
-                                           synchSafeInts);
+                                           d->header.majorVersion());
 
     if(!frame)
       return;
@@ -394,7 +392,7 @@ void ID3v2::Tag::parse(const ByteVector &data)
       return;
     }
 
-    frameDataPosition += frame->size() + Frame::headerSize();
+    frameDataPosition += frame->size() + Frame::headerSize(d->header.majorVersion());
     addFrame(frame);
   }
 }