Blob Blame History Raw
diff -Nur taglib-1.5/taglib/mpeg/mpegheader.cpp taglib/taglib/mpeg/mpegheader.cpp
--- taglib-1.5/taglib/mpeg/mpegheader.cpp	2008-02-04 16:14:46.000000000 +0100
+++ taglib/taglib/mpeg/mpegheader.cpp	2009-01-16 06:16:48.000000000 +0100
@@ -164,7 +164,7 @@
 void MPEG::Header::parse(const ByteVector &data)
 {
   if(data.size() < 4 || uchar(data[0]) != 0xff) {
-    debug("MPEG::Header::parse() -- First byte did not mactch MPEG synch.");
+    debug("MPEG::Header::parse() -- First byte did not match MPEG synch.");
     return;
   }
 
@@ -173,7 +173,7 @@
   // Check for the second byte's part of the MPEG synch
 
   if(!flags[23] || !flags[22] || !flags[21]) {
-    debug("MPEG::Header::parse() -- Second byte did not mactch MPEG synch.");
+    debug("MPEG::Header::parse() -- Second byte did not match MPEG synch.");
     return;
   }
 
diff -Nur taglib-1.5/taglib/mpeg/mpegproperties.cpp taglib/taglib/mpeg/mpegproperties.cpp
--- taglib-1.5/taglib/mpeg/mpegproperties.cpp	2008-02-04 16:14:46.000000000 +0100
+++ taglib/taglib/mpeg/mpegproperties.cpp	2009-07-10 16:34:04.000000000 +0200
@@ -218,8 +218,10 @@
       double timePerFrame =
         double(firstHeader.samplesPerFrame()) / firstHeader.sampleRate();
 
-      d->length = int(timePerFrame * d->xingHeader->totalFrames());
-      d->bitrate = d->length > 0 ? d->xingHeader->totalSize() * 8 / d->length / 1000 : 0;
+      double length = timePerFrame * d->xingHeader->totalFrames();
+
+      d->length = int(length);
+      d->bitrate = d->length > 0 ? d->xingHeader->totalSize() * 8 / length / 1000 : 0;
   }
   else {
     // Since there was no valid Xing header found, we hope that we're in a constant
diff -Nur taglib-1.5/taglib/mpeg/id3v2/frames/attachedpictureframe.cpp taglib/taglib/mpeg/id3v2/frames/attachedpictureframe.cpp
--- taglib-1.5/taglib/mpeg/id3v2/frames/attachedpictureframe.cpp	2008-02-04 16:14:46.000000000 +0100
+++ taglib/taglib/mpeg/id3v2/frames/attachedpictureframe.cpp	2009-07-11 16:27:17.000000000 +0200
@@ -50,7 +50,7 @@
 
 AttachedPictureFrame::AttachedPictureFrame() : Frame("APIC")
 {
-    d = new AttachedPictureFramePrivate;
+  d = new AttachedPictureFramePrivate;
 }
 
 AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data) : Frame(data)
@@ -136,6 +136,12 @@
   int pos = 1;
 
   d->mimeType = readStringField(data, String::Latin1, &pos);
+  /* Now we need at least two more bytes available */	
+  if (pos + 1 >= data.size()) {
+    debug("Truncated picture frame.");
+    return;
+  }
+
   d->type = (TagLib::ID3v2::AttachedPictureFrame::Type)data[pos++];
   d->description = readStringField(data, d->textEncoding, &pos);
 
@@ -168,3 +174,51 @@
   d = new AttachedPictureFramePrivate;
   parseFields(fieldData(data));
 }
+
+////////////////////////////////////////////////////////////////////////////////
+// support for ID3v2.2 PIC frames
+////////////////////////////////////////////////////////////////////////////////
+
+void AttachedPictureFrameV22::parseFields(const ByteVector &data)
+{
+  if(data.size() < 5) {
+    debug("A picture frame must contain at least 5 bytes.");
+    return;
+  }
+
+  d->textEncoding = String::Type(data[0]);
+
+  int pos = 1;
+
+  String fixedString = String(data.mid(pos, 3), String::Latin1);
+  pos += 3;
+  // convert fixed string image type to mime string
+  if (fixedString.upper() == "JPG") {
+    d->mimeType = "image/jpeg";
+  } else if (fixedString.upper() == "PNG") {
+    d->mimeType = "image/png";
+  } else {
+    debug("probably unsupported image type");
+    d->mimeType = "image/" + fixedString;
+  }
+
+  d->type = (TagLib::ID3v2::AttachedPictureFrame::Type)data[pos++];
+  d->description = readStringField(data, d->textEncoding, &pos);
+
+  d->data = data.mid(pos);
+}
+
+AttachedPictureFrameV22::AttachedPictureFrameV22(const ByteVector &data, Header *h)
+{
+  d = new AttachedPictureFramePrivate;
+
+  // set v2.2 header to make fieldData work correctly
+  setHeader(h, true);
+
+  parseFields(fieldData(data));
+
+  // now set the v2.4 header
+  Frame::Header *newHeader = new Frame::Header("APIC");
+  newHeader->setFrameSize(h->frameSize());
+  setHeader(newHeader, false);
+}
diff -Nur taglib-1.5/taglib/mpeg/id3v2/frames/attachedpictureframe.h taglib/taglib/mpeg/id3v2/frames/attachedpictureframe.h
--- taglib-1.5/taglib/mpeg/id3v2/frames/attachedpictureframe.h	2008-02-04 16:14:46.000000000 +0100
+++ taglib/taglib/mpeg/id3v2/frames/attachedpictureframe.h	2009-07-11 16:27:17.000000000 +0200
@@ -205,14 +205,24 @@
     protected:
       virtual void parseFields(const ByteVector &data);
       virtual ByteVector renderFields() const;
+      class AttachedPictureFramePrivate;
+      AttachedPictureFramePrivate *d;
 
     private:
-      AttachedPictureFrame(const ByteVector &data, Header *h);
       AttachedPictureFrame(const AttachedPictureFrame &);
       AttachedPictureFrame &operator=(const AttachedPictureFrame &);
+      AttachedPictureFrame(const ByteVector &data, Header *h);
 
-      class AttachedPictureFramePrivate;
-      AttachedPictureFramePrivate *d;
+    };
+
+    //! support for ID3v2.2 PIC frames
+    class TAGLIB_EXPORT AttachedPictureFrameV22 : public AttachedPictureFrame
+    {
+    protected:
+      virtual void parseFields(const ByteVector &data);
+    private:
+      AttachedPictureFrameV22(const ByteVector &data, Header *h);
+      friend class FrameFactory;
     };
   }
 }
diff -Nur taglib-1.5/taglib/mpeg/id3v2/frames/CMakeLists.txt taglib/taglib/mpeg/id3v2/frames/CMakeLists.txt
--- taglib-1.5/taglib/mpeg/id3v2/frames/CMakeLists.txt	2008-01-31 22:48:39.000000000 +0100
+++ taglib/taglib/mpeg/id3v2/frames/CMakeLists.txt	2008-06-26 17:06:20.000000000 +0200
@@ -2,6 +2,8 @@
 	attachedpictureframe.h
 	commentsframe.h
 	generalencapsulatedobjectframe.h
+	popularimeterframe.h
+	privateframe.h
 	relativevolumeframe.h
 	textidentificationframe.h
 	uniquefileidentifierframe.h
diff -Nur taglib-1.5/taglib/mpeg/id3v2/frames/generalencapsulatedobjectframe.h taglib/taglib/mpeg/id3v2/frames/generalencapsulatedobjectframe.h
--- taglib-1.5/taglib/mpeg/id3v2/frames/generalencapsulatedobjectframe.h	2008-02-04 16:14:46.000000000 +0100
+++ taglib/taglib/mpeg/id3v2/frames/generalencapsulatedobjectframe.h	2008-06-19 22:44:39.000000000 +0200
@@ -61,6 +61,10 @@
 
       /*!
        * Constructs a GeneralEncapsulatedObjectFrame frame based on \a data.
+       *
+       * \warning This is \em not data for the encapsulated object, for that use
+       * setObject().  This constructor is used when reading the frame from the
+       * disk.
        */
       explicit GeneralEncapsulatedObjectFrame(const ByteVector &data);
 
diff -Nur taglib-1.5/taglib/mpeg/id3v2/frames/Makefile.am taglib/taglib/mpeg/id3v2/frames/Makefile.am
--- taglib-1.5/taglib/mpeg/id3v2/frames/Makefile.am	2008-01-31 22:48:28.000000000 +0100
+++ taglib/taglib/mpeg/id3v2/frames/Makefile.am	2008-06-26 17:06:20.000000000 +0200
@@ -10,6 +10,8 @@
 	attachedpictureframe.cpp \
 	commentsframe.cpp \
 	generalencapsulatedobjectframe.cpp \
+	popularimeterframe.cpp \
+	privateframe.cpp \
 	relativevolumeframe.cpp \
 	textidentificationframe.cpp \
 	uniquefileidentifierframe.cpp \
@@ -21,6 +23,8 @@
 	attachedpictureframe.h \
 	commentsframe.h \
 	generalencapsulatedobjectframe.h \
+	popularimeterframe.h \
+	privateframe.h \
 	relativevolumeframe.h \
 	textidentificationframe.h \
 	uniquefileidentifierframe.h \
diff -Nur taglib-1.5/taglib/mpeg/id3v2/frames/popularimeterframe.cpp taglib/taglib/mpeg/id3v2/frames/popularimeterframe.cpp
--- taglib-1.5/taglib/mpeg/id3v2/frames/popularimeterframe.cpp	1970-01-01 01:00:00.000000000 +0100
+++ taglib/taglib/mpeg/id3v2/frames/popularimeterframe.cpp	2008-05-22 22:40:14.000000000 +0200
@@ -0,0 +1,137 @@
+/***************************************************************************
+    copyright            : (C) 2008 by Lukas Lalinsky
+    email                : lalinsky@gmail.com
+ ***************************************************************************/
+
+/***************************************************************************
+ *   This library is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Lesser General Public License version   *
+ *   2.1 as published by the Free Software Foundation.                     *
+ *                                                                         *
+ *   This library is distributed in the hope that it will be useful, but   *
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
+ *   Lesser General Public License for more details.                       *
+ *                                                                         *
+ *   You should have received a copy of the GNU Lesser General Public      *
+ *   License along with this library; if not, write to the Free Software   *
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
+ *   USA                                                                   *
+ *                                                                         *
+ *   Alternatively, this file is available under the Mozilla Public        *
+ *   License Version 1.1.  You may obtain a copy of the License at         *
+ *   http://www.mozilla.org/MPL/                                           *
+ ***************************************************************************/
+
+#include <tdebug.h>
+
+#include "popularimeterframe.h"
+
+using namespace TagLib;
+using namespace ID3v2;
+
+class PopularimeterFrame::PopularimeterFramePrivate
+{
+public:
+  PopularimeterFramePrivate() : rating(0), counter(0) {}
+  String email;
+  int rating;
+  TagLib::uint counter;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// public members
+////////////////////////////////////////////////////////////////////////////////
+
+PopularimeterFrame::PopularimeterFrame() : Frame("POPM")
+{
+  d = new PopularimeterFramePrivate;
+}
+
+PopularimeterFrame::PopularimeterFrame(const ByteVector &data) : Frame(data)
+{
+  d = new PopularimeterFramePrivate;
+  setData(data);
+}
+
+PopularimeterFrame::~PopularimeterFrame()
+{
+  delete d;
+}
+
+String PopularimeterFrame::toString() const
+{
+  return d->email + " rating=" + String::number(d->rating) + " counter=" + String::number(d->counter);
+}
+
+String PopularimeterFrame::email() const
+{
+  return d->email;
+}
+
+void PopularimeterFrame::setEmail(const String &s)
+{
+  d->email = s;
+}
+
+int PopularimeterFrame::rating() const
+{
+  return d->rating;
+}
+
+void PopularimeterFrame::setRating(int s)
+{
+  d->rating = s;
+}
+
+TagLib::uint PopularimeterFrame::counter() const
+{
+  return d->counter;
+}
+
+void PopularimeterFrame::setCounter(TagLib::uint s)
+{
+  d->counter = s;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// protected members
+////////////////////////////////////////////////////////////////////////////////
+
+void PopularimeterFrame::parseFields(const ByteVector &data)
+{
+  int pos = 0, size = int(data.size());
+
+  d->email = readStringField(data, String::Latin1, &pos);
+
+  d->rating = 0;
+  d->counter = 0;
+  if(pos < size) {
+    d->rating = (unsigned char)(data[pos++]);
+    if(pos < size) {
+      d->counter = data.mid(pos, 4).toUInt();
+    }
+  }
+}
+
+ByteVector PopularimeterFrame::renderFields() const
+{
+  ByteVector data;
+
+  data.append(d->email.data(String::Latin1));
+  data.append(textDelimiter(String::Latin1));
+  data.append(char(d->rating));
+  data.append(ByteVector::fromUInt(d->counter));
+
+  return data;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// private members
+////////////////////////////////////////////////////////////////////////////////
+
+PopularimeterFrame::PopularimeterFrame(const ByteVector &data, Header *h) : Frame(h)
+{
+  d = new PopularimeterFramePrivate;
+  parseFields(fieldData(data));
+}
diff -Nur taglib-1.5/taglib/mpeg/id3v2/frames/popularimeterframe.h taglib/taglib/mpeg/id3v2/frames/popularimeterframe.h
--- taglib-1.5/taglib/mpeg/id3v2/frames/popularimeterframe.h	1970-01-01 01:00:00.000000000 +0100
+++ taglib/taglib/mpeg/id3v2/frames/popularimeterframe.h	2008-05-22 14:06:45.000000000 +0200
@@ -0,0 +1,132 @@
+/***************************************************************************
+    copyright            : (C) 2008 by Lukas Lalinsky
+    email                : lalinsky@gmail.com
+ ***************************************************************************/
+
+/***************************************************************************
+ *   This library is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Lesser General Public License version   *
+ *   2.1 as published by the Free Software Foundation.                     *
+ *                                                                         *
+ *   This library is distributed in the hope that it will be useful, but   *
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
+ *   Lesser General Public License for more details.                       *
+ *                                                                         *
+ *   You should have received a copy of the GNU Lesser General Public      *
+ *   License along with this library; if not, write to the Free Software   *
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
+ *   USA                                                                   *
+ *                                                                         *
+ *   Alternatively, this file is available under the Mozilla Public        *
+ *   License Version 1.1.  You may obtain a copy of the License at         *
+ *   http://www.mozilla.org/MPL/                                           *
+ ***************************************************************************/
+
+#ifndef TAGLIB_POPULARIMETERFRAME_H
+#define TAGLIB_POPULARIMETERFRAME_H
+
+#include <id3v2frame.h>
+#include "taglib_export.h"
+
+namespace TagLib {
+
+  namespace ID3v2 {
+
+    //! An implementation of ID3v2 "popularimeter"
+
+    /*!
+     * This implements the ID3v2 popularimeter (POPM frame).  It concists of
+     * an email, a rating and an optional counter.
+     */
+
+    class TAGLIB_EXPORT PopularimeterFrame : public Frame
+    {
+      friend class FrameFactory;
+
+    public:
+      /*!
+       * Construct an empty popularimeter frame.
+       */
+      explicit PopularimeterFrame();
+
+      /*!
+       * Construct a popularimeter based on the data in \a data.
+       */
+      explicit PopularimeterFrame(const ByteVector &data);
+
+      /*!
+       * Destroys this PopularimeterFrame instance.
+       */
+      virtual ~PopularimeterFrame();
+
+      /*!
+       * Returns the text of this popularimeter.
+       *
+       * \see text()
+       */
+      virtual String toString() const;
+
+      /*!
+       * Returns the email.
+       *
+       * \see setEmail()
+       */
+      String email() const;
+
+      /*!
+       * Set the email.
+       *
+       * \see email()
+       */
+      void setEmail(const String &email);
+
+      /*!
+       * Returns the rating.
+       *
+       * \see setRating()
+       */
+      int rating() const;
+
+      /*!
+       * Set the rating.
+       *
+       * \see rating()
+       */
+      void setRating(int rating);
+
+      /*!
+       * Returns the counter.
+       *
+       * \see setCounter()
+       */
+      uint counter() const;
+
+      /*!
+       * Set the counter.
+       *
+       * \see counter()
+       */
+      void setCounter(uint counter);
+
+    protected:
+      // Reimplementations.
+
+      virtual void parseFields(const ByteVector &data);
+      virtual ByteVector renderFields() const;
+
+    private:
+      /*!
+       * The constructor used by the FrameFactory.
+       */
+      PopularimeterFrame(const ByteVector &data, Header *h);
+      PopularimeterFrame(const PopularimeterFrame &);
+      PopularimeterFrame &operator=(const PopularimeterFrame &);
+
+      class PopularimeterFramePrivate;
+      PopularimeterFramePrivate *d;
+    };
+
+  }
+}
+#endif
diff -Nur taglib-1.5/taglib/mpeg/id3v2/frames/privateframe.cpp taglib/taglib/mpeg/id3v2/frames/privateframe.cpp
--- taglib-1.5/taglib/mpeg/id3v2/frames/privateframe.cpp	1970-01-01 01:00:00.000000000 +0100
+++ taglib/taglib/mpeg/id3v2/frames/privateframe.cpp	2008-06-27 00:11:11.000000000 +0200
@@ -0,0 +1,128 @@
+/***************************************************************************
+    copyright            : (C) 2008 by Serkan Kalyoncu
+    copyright            : (C) 2008 by Scott Wheeler
+    email                : wheeler@kde.org
+***************************************************************************/
+
+/***************************************************************************
+ *   This library is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Lesser General Public License version   *
+ *   2.1 as published by the Free Software Foundation.                     *
+ *                                                                         *
+ *   This library is distributed in the hope that it will be useful, but   *
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
+ *   Lesser General Public License for more details.                       *
+ *                                                                         *
+ *   You should have received a copy of the GNU Lesser General Public      *
+ *   License along with this library; if not, write to the Free Software   *
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
+ *   USA                                                                   *
+ *                                                                         *
+ *   Alternatively, this file is available under the Mozilla Public        *
+ *   License Version 1.1.  You may obtain a copy of the License at         *
+ *   http://www.mozilla.org/MPL/                                           *
+ ***************************************************************************/
+
+#include <tbytevectorlist.h>
+#include <id3v2tag.h>
+#include <tdebug.h>
+
+#include "privateframe.h"
+
+using namespace TagLib;
+using namespace ID3v2;
+
+
+class PrivateFrame::PrivateFramePrivate
+{
+public:
+  ByteVector data;
+  String owner;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// public members
+////////////////////////////////////////////////////////////////////////////////
+
+PrivateFrame::PrivateFrame() : Frame("PRIV")
+{
+  d = new PrivateFramePrivate;
+}
+
+PrivateFrame::PrivateFrame(const ByteVector &data) : Frame(data)
+{
+  d = new PrivateFramePrivate;
+  setData(data);
+}
+
+PrivateFrame::~PrivateFrame()
+{
+  delete d;
+}
+
+String PrivateFrame::toString() const
+{
+  return d->owner;
+}
+
+String PrivateFrame::owner() const
+{
+  return d->owner;
+}
+
+ByteVector PrivateFrame::data() const
+{
+  return d->data;
+}
+
+void PrivateFrame::setOwner(const String &s)
+{
+  d->owner = s;
+}
+
+void PrivateFrame::setData(const ByteVector & data)
+{
+  d->data = data;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// protected members
+////////////////////////////////////////////////////////////////////////////////
+
+void PrivateFrame::parseFields(const ByteVector &data)
+{
+  if(data.size() < 2) {
+    debug("A private frame must contain at least 2 bytes.");
+    return;
+  }
+
+  // Owner identifier is assumed to be Latin1
+  
+  const int byteAlign =  1;
+  const int endOfOwner = data.find(textDelimiter(String::Latin1), 0, byteAlign);
+
+  d->owner =  String(data.mid(0, endOfOwner));
+  d->data = data.mid(endOfOwner + 1);
+}
+
+ByteVector PrivateFrame::renderFields() const
+{
+  ByteVector v;
+
+  v.append(d->owner.data(String::Latin1));
+  v.append(textDelimiter(String::Latin1));
+  v.append(d->data);
+
+  return v;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// private members
+////////////////////////////////////////////////////////////////////////////////
+
+PrivateFrame::PrivateFrame(const ByteVector &data, Header *h) : Frame(h)
+{
+  d = new PrivateFramePrivate();
+  parseFields(fieldData(data));
+}
diff -Nur taglib-1.5/taglib/mpeg/id3v2/frames/privateframe.h taglib/taglib/mpeg/id3v2/frames/privateframe.h
--- taglib-1.5/taglib/mpeg/id3v2/frames/privateframe.h	1970-01-01 01:00:00.000000000 +0100
+++ taglib/taglib/mpeg/id3v2/frames/privateframe.h	2008-06-27 00:11:11.000000000 +0200
@@ -0,0 +1,111 @@
+/***************************************************************************
+    copyright            : (C) 2008 by Serkan Kalyoncu
+    copyright            : (C) 2008 by Scott Wheeler
+    email                : wheeler@kde.org
+***************************************************************************/
+
+/***************************************************************************
+ *   This library is free software; you can redistribute it and/or modify  *
+ *   it under the terms of the GNU Lesser General Public License version   *
+ *   2.1 as published by the Free Software Foundation.                     *
+ *                                                                         *
+ *   This library is distributed in the hope that it will be useful, but   *
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of            *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU     *
+ *   Lesser General Public License for more details.                       *
+ *                                                                         *
+ *   You should have received a copy of the GNU Lesser General Public      *
+ *   License along with this library; if not, write to the Free Software   *
+ *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
+ *   USA                                                                   *
+ *                                                                         *
+ *   Alternatively, this file is available under the Mozilla Public        *
+ *   License Version 1.1.  You may obtain a copy of the License at         *
+ *   http://www.mozilla.org/MPL/                                           *
+ ***************************************************************************/
+
+#ifndef TAGLIB_PRIVATEFRAME_H
+#define TAGLIB_PRIVATEFRAME_H
+
+#include "id3v2frame.h"
+#include "taglib_export.h"
+
+namespace TagLib {
+
+  namespace ID3v2 {
+
+    //! An implementation of ID3v2 privateframe
+
+    class TAGLIB_EXPORT PrivateFrame : public Frame
+    {
+      friend class FrameFactory;
+
+    public:
+      /*!
+       * Construct an empty private frame.
+       */
+      PrivateFrame();
+
+      /*!
+       * Construct a private frame based on the data in \a data.
+       *
+       * \note This is the constructor used when parsing the frame from a file.
+       */
+      explicit PrivateFrame(const ByteVector &data);
+
+      /*!
+       * Destroys this private frame instance.
+       */
+      virtual ~PrivateFrame();
+
+      /*!
+       * Returns the text of this private frame, currently just the owner.
+       *
+       * \see text()
+       */
+      virtual String toString() const;
+
+      /*!
+       * \return The owner of the private frame.
+       * \note This should contain an email address or link to a website.
+       */
+      String owner() const;
+
+      /*!
+       *
+       */
+      ByteVector data() const;
+
+      /*!
+       * Sets the owner of the frame to \a s.
+       * \note This should contain an email address or link to a website.
+       */
+      void setOwner(const String &s);
+
+      /*!
+       *
+       */
+      void setData(const ByteVector &v);
+
+    protected:
+      // Reimplementations.
+
+      virtual void parseFields(const ByteVector &data);
+      virtual ByteVector renderFields() const;
+
+    private:
+      /*!
+       * The constructor used by the FrameFactory.
+       */
+      PrivateFrame(const ByteVector &data, Header *h);
+
+      PrivateFrame(const PrivateFrame &);
+      PrivateFrame &operator=(const PrivateFrame &);
+
+      class PrivateFramePrivate;
+      PrivateFramePrivate *d;
+    };
+
+  }
+}
+#endif
diff -Nur taglib-1.5/taglib/mpeg/id3v2/id3v2footer.cpp taglib/taglib/mpeg/id3v2/id3v2footer.cpp
--- taglib-1.5/taglib/mpeg/id3v2/id3v2footer.cpp	2008-02-04 16:14:46.000000000 +0100
+++ taglib/taglib/mpeg/id3v2/id3v2footer.cpp	2008-12-05 17:43:38.000000000 +0100
@@ -45,7 +45,7 @@
 
 }
 
-const unsigned int Footer::size()
+TagLib::uint Footer::size()
 {
   return FooterPrivate::size;
 }
diff -Nur taglib-1.5/taglib/mpeg/id3v2/id3v2footer.h taglib/taglib/mpeg/id3v2/id3v2footer.h
--- taglib-1.5/taglib/mpeg/id3v2/id3v2footer.h	2008-02-04 16:14:46.000000000 +0100
+++ taglib/taglib/mpeg/id3v2/id3v2footer.h	2008-12-05 01:37:39.000000000 +0100
@@ -62,7 +62,7 @@
       /*!
        * Returns the size of the footer.  Presently this is always 10 bytes.
        */
-      static const unsigned int size();
+      static uint size();
 
       /*!
        * Renders the footer based on the data in \a header.
diff -Nur taglib-1.5/taglib/mpeg/id3v2/id3v2framefactory.cpp taglib/taglib/mpeg/id3v2/id3v2framefactory.cpp
--- taglib-1.5/taglib/mpeg/id3v2/id3v2framefactory.cpp	2008-02-21 01:43:14.000000000 +0100
+++ taglib/taglib/mpeg/id3v2/id3v2framefactory.cpp	2009-07-11 16:27:17.000000000 +0200
@@ -31,6 +31,7 @@
 
 #include "id3v2framefactory.h"
 #include "id3v2synchdata.h"
+#include "id3v1genres.h"
 
 #include "frames/attachedpictureframe.h"
 #include "frames/commentsframe.h"
@@ -41,6 +42,8 @@
 #include "frames/generalencapsulatedobjectframe.h"
 #include "frames/urllinkframe.h"
 #include "frames/unsynchronizedlyricsframe.h"
+#include "frames/popularimeterframe.h"
+#include "frames/privateframe.h"
 
 using namespace TagLib;
 using namespace ID3v2;
@@ -180,7 +183,15 @@
     return f;
   }
 
-  // Relative Volume Adjustment (frames 4.11)
+  // ID3v2.2 Attached Picture
+
+	if(frameID == "PIC") {
+    AttachedPictureFrame *f = new AttachedPictureFrameV22(data, header);
+    d->setTextEncoding(f);
+    return f;
+  }
+
+	// Relative Volume Adjustment (frames 4.11)
 
   if(frameID == "RVA2")
     return new RelativeVolumeFrame(data, header);
@@ -220,6 +231,16 @@
     return f;
   }
 
+  // Popularimeter (frames 4.17)
+
+  if(frameID == "POPM")
+    return new PopularimeterFrame(data, header);
+
+  // Private (frames 4.27)
+
+  if(frameID == "PRIV")
+    return new PrivateFrame(data, header);
+
   return new UnknownFrame(data, header);
 }
 
@@ -280,7 +301,6 @@
     convertFrame("IPL", "TIPL", header);
     convertFrame("MCI", "MCDI", header);
     convertFrame("MLL", "MLLT", header);
-    convertFrame("PIC", "APIC", header);
     convertFrame("POP", "POPM", header);
     convertFrame("REV", "RVRB", header);
     convertFrame("SLT", "SYLT", header);
@@ -382,26 +402,31 @@
 
 void FrameFactory::updateGenre(TextIdentificationFrame *frame) const
 {
-  StringList fields;
-  String s = frame->toString();
+  StringList fields = frame->fieldList();
+  StringList newfields;
 
-  while(s.startsWith("(")) {
-
-    int closing = s.find(")");
-
-    if(closing < 0)
-      break;
-
-    fields.append(s.substr(1, closing - 1));
-
-    s = s.substr(closing + 1);
+  for(StringList::Iterator it = fields.begin(); it != fields.end(); ++it) {
+    String s = *it;
+    int end = s.find(")");
+
+    if(s.startsWith("(") && end > 0) {
+      // "(12)Genre"
+      String text = s.substr(end + 1);
+      int number = s.substr(1, end - 1).toInt();
+      if (number > 0 && number <= 255 && !(ID3v1::genre(number) == text))
+        newfields.append(s.substr(1, end - 1));
+      if (!text.isEmpty())
+        newfields.append(text);
+    }
+    else {
+      // "Genre" or "12"
+      newfields.append(s);
+    }
   }
 
-  if(!s.isEmpty())
-    fields.append(s);
-
-  if(fields.isEmpty())
+  if(newfields.isEmpty())
     fields.append(String::null);
 
-  frame->setText(fields);
+  frame->setText(newfields);
+
 }
diff -Nur taglib-1.5/taglib/mpeg/id3v2/id3v2tag.cpp taglib/taglib/mpeg/id3v2/id3v2tag.cpp
--- taglib-1.5/taglib/mpeg/id3v2/id3v2tag.cpp	2008-02-04 21:33:54.000000000 +0100
+++ taglib/taglib/mpeg/id3v2/id3v2tag.cpp	2009-07-11 16:43:58.000000000 +0200
@@ -125,7 +125,9 @@
 
   for(FrameList::ConstIterator it = comments.begin(); it != comments.end(); ++it)
   {
-    if(static_cast<CommentsFrame *>(*it)->description().isEmpty())
+    CommentsFrame *frame = dynamic_cast<CommentsFrame *>(*it);
+
+    if(frame && frame->description().isEmpty())
       return (*it)->toString();
   }
 
@@ -159,6 +161,9 @@
 
   for(StringList::Iterator it = fields.begin(); it != fields.end(); ++it) {
 
+    if((*it).isEmpty())
+      continue;
+
     bool isNumber = true;
 
     for(String::ConstIterator charIt = (*it).begin();
@@ -347,6 +352,11 @@
   // Loop through the frames rendering them and adding them to the tagData.
 
   for(FrameList::Iterator it = d->frameList.begin(); it != d->frameList.end(); it++) {
+    if ((*it)->header()->frameID().size() != 4) {
+      debug("A frame of unsupported or unknown type \'"
+          + String((*it)->header()->frameID()) + "\' has been discarded");
+      continue;
+    }
     if(!(*it)->header()->tagAlterPreservation())
       tagData.append((*it)->render());
   }