]> granicus.if.org Git - taglib/commitdiff
Support for POPM ID3 frame
authorLukáš Lalinský <lalinsky@gmail.com>
Thu, 22 May 2008 12:06:45 +0000 (12:06 +0000)
committerLukáš Lalinský <lalinsky@gmail.com>
Thu, 22 May 2008 12:06:45 +0000 (12:06 +0000)
git-svn-id: svn://anonsvn.kde.org/home/kde/trunk/kdesupport/taglib@811137 283d02a7-25f6-0310-bc7c-ecb5cbfe19da

taglib/CMakeLists.txt
taglib/mpeg/id3v2/frames/CMakeLists.txt
taglib/mpeg/id3v2/frames/Makefile.am
taglib/mpeg/id3v2/frames/popularimeterframe.cpp [new file with mode: 0644]
taglib/mpeg/id3v2/frames/popularimeterframe.h [new file with mode: 0644]
taglib/mpeg/id3v2/id3v2framefactory.cpp
taglib/taglib.pro
tests/test_id3v2.cpp

index 73347e01d6056b3abeb8508f5a306edd0d22499b..e7cb745271ae88ea1cffb98ac540cab3290ed8d7 100644 (file)
@@ -63,6 +63,7 @@ SET(frames_SRCS
 mpeg/id3v2/frames/attachedpictureframe.cpp
 mpeg/id3v2/frames/commentsframe.cpp
 mpeg/id3v2/frames/generalencapsulatedobjectframe.cpp
+mpeg/id3v2/frames/popularimeterframe.cpp
 mpeg/id3v2/frames/relativevolumeframe.cpp
 mpeg/id3v2/frames/textidentificationframe.cpp
 mpeg/id3v2/frames/uniquefileidentifierframe.cpp
index 1fb1e208682c8e097c7b1dca76b0de57a566643c..caa08561292c759f30631afeedf24aab97d9f848 100644 (file)
@@ -2,6 +2,7 @@ INSTALL(FILES
        attachedpictureframe.h
        commentsframe.h
        generalencapsulatedobjectframe.h
+       popularimeterframe.h
        relativevolumeframe.h
        textidentificationframe.h
        uniquefileidentifierframe.h
index 517cd753860b9f0fb3b6131155e7cec91fd88102..416e4abc4a1363e506c25389eba99da3028ed128 100644 (file)
@@ -10,6 +10,7 @@ libframes_la_SOURCES = \
        attachedpictureframe.cpp \
        commentsframe.cpp \
        generalencapsulatedobjectframe.cpp \
+       popularimeterframe.cpp \
        relativevolumeframe.cpp \
        textidentificationframe.cpp \
        uniquefileidentifierframe.cpp \
@@ -21,6 +22,7 @@ taglib_include_HEADERS = \
        attachedpictureframe.h \
        commentsframe.h \
        generalencapsulatedobjectframe.h \
+       popularimeterframe.h \
        relativevolumeframe.h \
        textidentificationframe.h \
        uniquefileidentifierframe.h \
diff --git a/taglib/mpeg/id3v2/frames/popularimeterframe.cpp b/taglib/mpeg/id3v2/frames/popularimeterframe.cpp
new file mode 100644 (file)
index 0000000..027ea84
--- /dev/null
@@ -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 = 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 --git a/taglib/mpeg/id3v2/frames/popularimeterframe.h b/taglib/mpeg/id3v2/frames/popularimeterframe.h
new file mode 100644 (file)
index 0000000..2d626f4
--- /dev/null
@@ -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
index 48a202216c189e9454a23648c30013102cc19677..1a4d36ae3e73e3e9d031ef0d3093421f12254ae5 100644 (file)
@@ -41,6 +41,7 @@
 #include "frames/generalencapsulatedobjectframe.h"
 #include "frames/urllinkframe.h"
 #include "frames/unsynchronizedlyricsframe.h"
+#include "frames/popularimeterframe.h"
 
 using namespace TagLib;
 using namespace ID3v2;
@@ -220,6 +221,12 @@ Frame *FrameFactory::createFrame(const ByteVector &origData, Header *tagHeader)
     return f;
   }
 
+  // Popularimeter (frames 4.17)
+
+  if(frameID == "POPM") {
+    return new PopularimeterFrame(data, header);
+  }
+
   return new UnknownFrame(data, header);
 }
 
index 66bf4d6cdea1038cbc082c4a3945f4014381c861..76be4c45cfda1bc020f7d79136d237701474e50d 100644 (file)
@@ -93,6 +93,7 @@ HEADERS += audioproperties.h \
            mpeg/id3v2/frames/attachedpictureframe.h \
            mpeg/id3v2/frames/commentsframe.h \
            mpeg/id3v2/frames/generalencapsulatedobjectframe.h \
+           mpeg/id3v2/frames/popularimeterframe.h \
            mpeg/id3v2/frames/relativevolumeframe.h \
            mpeg/id3v2/frames/textidentificationframe.h \
            mpeg/id3v2/frames/uniquefileidentifierframe.h \
@@ -148,6 +149,7 @@ SOURCES += audioproperties.cpp \
            mpeg/id3v2/frames/attachedpictureframe.cpp \
            mpeg/id3v2/frames/commentsframe.cpp \
            mpeg/id3v2/frames/generalencapsulatedobjectframe.cpp \
+           mpeg/id3v2/frames/popularimeterframe.cpp \
            mpeg/id3v2/frames/relativevolumeframe.cpp \
            mpeg/id3v2/frames/textidentificationframe.cpp \
            mpeg/id3v2/frames/uniquefileidentifierframe.cpp \
index ed5e0b00036c71b34e85c555bbcdd89ef6b84f60..027ecacc610054771066a283d1818185e05607e8 100644 (file)
@@ -9,6 +9,7 @@
 #include <attachedpictureframe.h>
 #include <generalencapsulatedobjectframe.h>
 #include <relativevolumeframe.h>
+#include <popularimeterframe.h>
 #include <urllinkframe.h>
 #include "utils.h"
 
@@ -37,6 +38,11 @@ class TestID3v2 : public CppUnit::TestFixture
   CPPUNIT_TEST(testParseAPIC);
   CPPUNIT_TEST(testParseAPIC_UTF16_BOM);
   CPPUNIT_TEST(testParseGEOB);
+  CPPUNIT_TEST(testPOPMtoString);
+  CPPUNIT_TEST(testParsePOPM);
+  CPPUNIT_TEST(testParsePOPMWithoutCounter);
+  CPPUNIT_TEST(testRenderPOPM);
+  CPPUNIT_TEST(testPOPMFromFile);
   CPPUNIT_TEST(testParseRelativeVolumeFrame);
   CPPUNIT_TEST(testParseUniqueFileIdentifierFrame);
   CPPUNIT_TEST(testParseEmptyUniqueFileIdentifierFrame);
@@ -138,6 +144,75 @@ public:
     CPPUNIT_ASSERT_EQUAL(String("d"), f.description());
   }
 
+  void testParsePOPM()
+  {
+    ID3v2::PopularimeterFrame f(ByteVector("POPM"
+                                           "\x00\x00\x00\x17"
+                                           "\x00\x00"
+                                           "email@example.com\x00"
+                                           "\x02"
+                                           "\x00\x00\x00\x03", 33));
+    CPPUNIT_ASSERT_EQUAL(String("email@example.com"), f.email());
+    CPPUNIT_ASSERT_EQUAL(2, f.rating());
+    CPPUNIT_ASSERT_EQUAL(TagLib::uint(3), f.counter());
+  }
+
+  void testParsePOPMWithoutCounter()
+  {
+    ID3v2::PopularimeterFrame f(ByteVector("POPM"
+                                           "\x00\x00\x00\x13"
+                                           "\x00\x00"
+                                           "email@example.com\x00"
+                                           "\x02", 29));
+    CPPUNIT_ASSERT_EQUAL(String("email@example.com"), f.email());
+    CPPUNIT_ASSERT_EQUAL(2, f.rating());
+    CPPUNIT_ASSERT_EQUAL(TagLib::uint(0), f.counter());
+  }
+
+  void testRenderPOPM()
+  {
+    ID3v2::PopularimeterFrame f;
+    f.setEmail("email@example.com");
+    f.setRating(2);
+    f.setCounter(3);
+    CPPUNIT_ASSERT_EQUAL(
+      ByteVector("POPM"
+                 "\x00\x00\x00\x17"
+                 "\x00\x00"
+                 "email@example.com\x00"
+                 "\x02"
+                 "\x00\x00\x00\x03", 33),
+      f.render());
+  }
+
+  void testPOPMtoString()
+  {
+    ID3v2::PopularimeterFrame f;
+    f.setEmail("email@example.com");
+    f.setRating(2);
+    f.setCounter(3);
+    CPPUNIT_ASSERT_EQUAL(
+      String("email@example.com rating=2 counter=3"), f.toString());
+  }
+
+  void testPOPMFromFile()
+  {
+    string newname = copyFile("xing", ".mp3");
+
+    ID3v2::PopularimeterFrame *f = new ID3v2::PopularimeterFrame();
+    f->setEmail("email@example.com");
+    f->setRating(2);
+    f->setCounter(3);
+
+    MPEG::File foo(newname.c_str());
+    foo.ID3v2Tag()->addFrame(f);
+    foo.save();
+
+    MPEG::File bar(newname.c_str());
+    CPPUNIT_ASSERT_EQUAL(String("email@example.com"), dynamic_cast<ID3v2::PopularimeterFrame *>(bar.ID3v2Tag()->frameList("POPM").front())->email());
+    deleteFile(newname);
+  }
+
   // http://bugs.kde.org/show_bug.cgi?id=150481
   void testParseRelativeVolumeFrame()
   {