]> granicus.if.org Git - taglib/commitdiff
Implementation of the ID3v2.4 OWNE frame.
authorRupert Daniel <rupert.daniel@beatport.com>
Wed, 5 Sep 2012 15:37:46 +0000 (16:37 +0100)
committerRupert Daniel <rupert.daniel@beatport.com>
Wed, 5 Sep 2012 15:37:46 +0000 (16:37 +0100)
taglib/mpeg/id3v2/frames/ownershipframe.cpp [new file with mode: 0644]
taglib/mpeg/id3v2/frames/ownershipframe.h [new file with mode: 0644]
taglib/mpeg/id3v2/id3v2framefactory.cpp
taglib/mpeg/id3v2/id3v2tag.cpp
taglib/mpeg/id3v2/id3v2tag.h
tests/test_id3v2.cpp

diff --git a/taglib/mpeg/id3v2/frames/ownershipframe.cpp b/taglib/mpeg/id3v2/frames/ownershipframe.cpp
new file mode 100644 (file)
index 0000000..da8410b
--- /dev/null
@@ -0,0 +1,159 @@
+/***************************************************************************
+    copyright            : (C) 2012 by Rupert Daniel
+    email                : rupert@cancelmonday.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., 51 Franklin Street, Fifth Floor, Boston, MA         *
+ *   02110-1301  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 "ownershipframe.h"
+
+using namespace TagLib;
+using namespace ID3v2;
+
+class OwnershipFrame::OwnershipFramePrivate
+{
+public:
+  String currencyCode;
+  String pricePaid;
+  String datePurchased;
+  String seller;
+  String::Type textEncoding;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// public members
+////////////////////////////////////////////////////////////////////////////////
+
+OwnershipFrame::OwnershipFrame(String::Type encoding) : Frame("OWNE")
+{
+  d = new OwnershipFramePrivate;
+  d->textEncoding = encoding;
+}
+
+OwnershipFrame::OwnershipFrame(const ByteVector &data) : Frame(data)
+{
+  d = new OwnershipFramePrivate;
+  setData(data);
+}
+
+OwnershipFrame::~OwnershipFrame()
+{
+  delete d;
+}
+
+String OwnershipFrame::toString() const
+{
+  return "pricePaid=" + d->pricePaid + " datePurchased=" + d->datePurchased + " seller=" + d->seller;
+}
+
+String OwnershipFrame::pricePaid() const
+{
+  return d->pricePaid;
+}
+
+void OwnershipFrame::setPricePaid(const String &s)
+{
+  d->pricePaid = s;
+}
+
+String OwnershipFrame::datePurchased() const
+{
+  return d->datePurchased;
+}
+
+void OwnershipFrame::setDatePurchased(const String &s)
+{
+  d->datePurchased = s;
+}
+
+String OwnershipFrame::seller() const
+{
+  return d->seller;
+}
+
+void OwnershipFrame::setSeller(const String &s)
+{
+  d->seller = s;
+}
+
+String::Type OwnershipFrame::textEncoding() const
+{
+  return d->textEncoding;
+}
+
+void OwnershipFrame::setTextEncoding(String::Type encoding)
+{
+  d->textEncoding = encoding;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// protected members
+////////////////////////////////////////////////////////////////////////////////
+
+void OwnershipFrame::parseFields(const ByteVector &data)
+{
+  int pos = 0;
+  
+  // Get the text encoding
+  d->textEncoding = String::Type(data[0]);
+  pos += 1;
+  
+  // Read the price paid this is a null terminate string
+  d->pricePaid = readStringField(data, String::Latin1, &pos);
+  
+  // If we don't have at least 8 bytes left then don't parse the rest of the
+  // data
+  if (data.size() - pos < 8) {
+    return;
+  }
+  
+  // Read the date purchased YYYYMMDD
+  d->datePurchased = String(data.mid(pos, 8));
+  pos += 8;
+  
+  // Read the seller
+  d->seller = String(data.mid(pos));
+}
+
+ByteVector OwnershipFrame::renderFields() const
+{
+  ByteVector v;
+  
+  v.append(char(d->textEncoding));
+  v.append(d->pricePaid.data(String::Latin1));
+  v.append(textDelimiter(String::Latin1));
+  v.append(d->datePurchased.data(String::Latin1));
+  v.append(d->seller.data(d->textEncoding));
+  return v;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// private members
+////////////////////////////////////////////////////////////////////////////////
+
+OwnershipFrame::OwnershipFrame(const ByteVector &data, Header *h) : Frame(h)
+{
+  d = new OwnershipFramePrivate;
+  parseFields(fieldData(data));
+}
diff --git a/taglib/mpeg/id3v2/frames/ownershipframe.h b/taglib/mpeg/id3v2/frames/ownershipframe.h
new file mode 100644 (file)
index 0000000..b73832b
--- /dev/null
@@ -0,0 +1,152 @@
+/***************************************************************************
+    copyright            : (C) 2012 by Rupert Daniel
+    email                : rupert@cancelmonday.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., 51 Franklin Street, Fifth Floor, Boston, MA         *
+ *   02110-1301  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_OWNERSHIPFRAME_H
+#define TAGLIB_OWNERSHIPFRAME_H
+
+#include "id3v2frame.h"
+#include "taglib_export.h"
+
+namespace TagLib {
+
+  namespace ID3v2 {
+
+    //! An implementation of ID3v2 "ownership"
+
+    /*!
+     * This implements the ID3v2 ownership (OWNE frame).  It concists of
+     * an price paid, a date purchased (YYYYMMDD) and the name of the seller.
+     */
+
+    class TAGLIB_EXPORT OwnershipFrame : public Frame
+    {
+      friend class FrameFactory;
+
+    public:
+      /*!
+       * Construct an empty ownership frame.
+       */
+      explicit OwnershipFrame(String::Type encoding = String::Latin1);
+
+      /*!
+       * Construct a ownership based on the data in \a data.
+       */
+      explicit OwnershipFrame(const ByteVector &data);
+
+      /*!
+       * Destroys this OwnershipFrame instance.
+       */
+      virtual ~OwnershipFrame();
+
+      /*!
+       * Returns the text of this popularimeter.
+       *
+       * \see text()
+       */
+      virtual String toString() const;
+
+      /*!
+       * Returns the date purchased.
+       *
+       * \see setDatePurchased()
+       */
+      String datePurchased() const;
+
+      /*!
+       * Set the date purchased.
+       *
+       * \see datePurchased()
+       */
+      void setDatePurchased(const String &datePurchased);
+
+
+      /*!
+       * Returns the price paid.
+       *
+       * \see setPricePaid()
+       */
+      String pricePaid() const;
+
+      /*!
+       * Set the price paid.
+       *
+       * \see pricePaid()
+       */
+      void setPricePaid(const String &pricePaid);
+      
+      /*!
+       * Returns the seller.
+       *
+       * \see setSeller()
+       */
+      String seller() const;
+      
+      /*!
+       * Set the seller.
+       *
+       * \see seller()
+       */
+      void setSeller(const String &seller);
+      
+      /*!
+       * Returns the text encoding that will be used in rendering this frame.
+       * This defaults to the type that was either specified in the constructor
+       * or read from the frame when parsed.
+       *
+       * \see setTextEncoding()
+       * \see render()
+       */
+      String::Type textEncoding() const;
+      
+      /*!
+       * Sets the text encoding to be used when rendering this frame to
+       * \a encoding.
+       *
+       * \see textEncoding()
+       * \see render()
+       */
+      void setTextEncoding(String::Type encoding);
+
+    protected:
+      // Reimplementations.
+
+      virtual void parseFields(const ByteVector &data);
+      virtual ByteVector renderFields() const;
+
+    private:
+      /*!
+       * The constructor used by the FrameFactory.
+       */
+      OwnershipFrame(const ByteVector &data, Header *h);
+      OwnershipFrame(const OwnershipFrame &);
+      OwnershipFrame &operator=(const OwnershipFrame &);
+
+      class OwnershipFramePrivate;
+      OwnershipFramePrivate *d;
+    };
+
+  }
+}
+#endif
index bcf69e1aea833abb793489df2f36b3328ad948af..7e2e98a8a2625716e7e9eb26ecf6e63a61f7c819 100644 (file)
@@ -44,6 +44,7 @@
 #include "frames/unsynchronizedlyricsframe.h"
 #include "frames/popularimeterframe.h"
 #include "frames/privateframe.h"
+#include "frames/ownershipframe.h"
 
 using namespace TagLib;
 using namespace ID3v2;
@@ -238,6 +239,14 @@ Frame *FrameFactory::createFrame(const ByteVector &origData, Header *tagHeader)
 
   if(frameID == "PRIV")
     return new PrivateFrame(data, header);
+  
+  // Ownership (frames 4.22)
+  
+  if(frameID == "OWNE") {
+    OwnershipFrame *f = new OwnershipFrame(data, header);
+    d->setTextEncoding(f);
+    return f;
+  }
 
   return new UnknownFrame(data, header);
 }
index ffb0189cebc64c4552bdd0f405cac06501c836df..54e63920364b26dbf3fd66184f345d2729b83d87 100644 (file)
@@ -81,6 +81,10 @@ const ID3v2::Latin1StringHandler *ID3v2::Tag::TagPrivate::stringHandler = &defau
 // StringHandler implementation
 ////////////////////////////////////////////////////////////////////////////////
 
+Latin1StringHandler::Latin1StringHandler()
+{
+}
+
 Latin1StringHandler::~Latin1StringHandler()
 {
 }
index e6d6d4fdace0ee21cb9ff4b2a215ad233f35bea5..5fd5c1f125a34f1a0e1025af13b0afd6c4a1595f 100644 (file)
@@ -77,6 +77,7 @@ namespace TagLib {
     class TAGLIB_EXPORT Latin1StringHandler
     {
     public:
+      Latin1StringHandler();
       virtual ~Latin1StringHandler();
 
       /*!
index 29758aa40269c3bfae0b5d33f006c259876b728b..243f975331dcf1039d06f9e453c65dbad82324bb 100644 (file)
@@ -15,6 +15,7 @@
 #include <relativevolumeframe.h>
 #include <popularimeterframe.h>
 #include <urllinkframe.h>
+#include <ownershipframe.h>
 #include <tdebug.h>
 #include <tpropertymap.h>
 #include "utils.h"
@@ -61,6 +62,8 @@ class TestID3v2 : public CppUnit::TestFixture
   CPPUNIT_TEST(testRenderUrlLinkFrame);
   CPPUNIT_TEST(testParseUserUrlLinkFrame);
   CPPUNIT_TEST(testRenderUserUrlLinkFrame);
+  CPPUNIT_TEST(testParseOwnershipFrame);
+  CPPUNIT_TEST(testRenderOwnershipFrame);
   CPPUNIT_TEST(testSaveUTF16Comment);
   CPPUNIT_TEST(testUpdateGenre23_1);
   CPPUNIT_TEST(testUpdateGenre23_2);
@@ -69,11 +72,8 @@ class TestID3v2 : public CppUnit::TestFixture
   CPPUNIT_TEST(testDowngradeTo23);
   // CPPUNIT_TEST(testUpdateFullDate22); TODO TYE+TDA should be upgraded to TDRC together
   CPPUNIT_TEST(testCompressedFrameWithBrokenLength);
-  CPPUNIT_TEST(testW000);
   CPPUNIT_TEST(testPropertyInterface);
   CPPUNIT_TEST(testPropertyInterface2);
-  CPPUNIT_TEST(testDeleteFrame);
-  CPPUNIT_TEST(testSaveAndStripID3v1ShouldNotAddFrameFromID3v1ToId3v2);
   CPPUNIT_TEST_SUITE_END();
 
 public:
@@ -386,6 +386,38 @@ public:
                  "http://example.com", 33),  // URL
       f.render());
   }
+  
+  void testParseOwnershipFrame()
+  {
+    ID3v2::OwnershipFrame f(
+                            ByteVector("OWNE"                      // Frame ID
+                                       "\x00\x00\x00\x19"          // Frame size
+                                       "\x00\x00"                  // Frame flags
+                                       "\x00"                      // Text encoding
+                                       "GBP1.99\x00"               // Price paid
+                                       "20120905"                  // Date of purchase
+                                       "Beatport", 35));           // Seller
+    CPPUNIT_ASSERT_EQUAL(String("GBP1.99"), f.pricePaid());
+    CPPUNIT_ASSERT_EQUAL(String("20120905"), f.datePurchased());
+    CPPUNIT_ASSERT_EQUAL(String("Beatport"), f.seller());
+  }
+
+  void testRenderOwnershipFrame()
+  {
+    ID3v2::OwnershipFrame f;
+    f.setPricePaid("GBP1.99");
+    f.setDatePurchased("20120905");
+    f.setSeller("Beatport");
+    CPPUNIT_ASSERT_EQUAL(
+                         ByteVector("OWNE"                      // Frame ID
+                                    "\x00\x00\x00\x19"          // Frame size
+                                    "\x00\x00"                  // Frame flags
+                                    "\x00"                      // Text encoding
+                                    "GBP1.99\x00"               // Price paid
+                                    "20120905"                  // Date of purchase
+                                    "Beatport", 35),  // URL
+                         f.render());
+  }
 
   void testItunes24FrameSize()
   {
@@ -554,16 +586,6 @@ public:
     CPPUNIT_ASSERT_EQUAL(TagLib::uint(86414), frame->picture().size());
   }
 
-  void testW000()
-  {
-    MPEG::File f(TEST_FILE_PATH_C("w000.mp3"), false);
-    CPPUNIT_ASSERT(f.ID3v2Tag()->frameListMap().contains("W000"));
-    ID3v2::UrlLinkFrame *frame =
-        dynamic_cast<TagLib::ID3v2::UrlLinkFrame*>(f.ID3v2Tag()->frameListMap()["W000"].front());
-    CPPUNIT_ASSERT(frame);
-    CPPUNIT_ASSERT_EQUAL(String("lukas.lalinsky@example.com____"), frame->url());
-  }
-
   void testPropertyInterface()
   {
     ScopedFileCopy copy("rare_frames", ".mp3");
@@ -641,43 +663,6 @@ public:
     CPPUNIT_ASSERT(tag.frameList("TIPL").isEmpty());
   }
 
-  void testDeleteFrame()
-  {
-    ScopedFileCopy copy("rare_frames", ".mp3");
-    string newname = copy.fileName();
-    MPEG::File f(newname.c_str());
-    ID3v2::Tag *t = f.ID3v2Tag();
-    ID3v2::Frame *frame = t->frameList("TCON")[0];
-    CPPUNIT_ASSERT_EQUAL(1u, t->frameList("TCON").size());
-    t->removeFrame(frame, true);
-    f.save(MPEG::File::ID3v2);
-
-    MPEG::File f2(newname.c_str());
-    t = f2.ID3v2Tag();
-    CPPUNIT_ASSERT(t->frameList("TCON").isEmpty());
-  }
-  void testSaveAndStripID3v1ShouldNotAddFrameFromID3v1ToId3v2()
-  {
-    ScopedFileCopy copy("xing", ".mp3");
-    string newname = copy.fileName();
-
-    {
-      MPEG::File foo(newname.c_str());
-      foo.tag()->setArtist("Artist");
-      foo.save(MPEG::File::ID3v1 | MPEG::File::ID3v2);
-    }
-
-    {
-      MPEG::File bar(newname.c_str());
-      bar.ID3v2Tag()->removeFrames("TPE1");
-      // Should strip ID3v1 here and not add old values to ID3v2 again
-      bar.save(MPEG::File::ID3v2, true);
-    }
-
-    MPEG::File f(newname.c_str());
-    CPPUNIT_ASSERT(!f.ID3v2Tag()->frameListMap().contains("TPE1"));
-  }
-
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(TestID3v2);