--- /dev/null
+/***************************************************************************
+ 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));
+}
--- /dev/null
+/***************************************************************************
+ 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
#include "frames/unsynchronizedlyricsframe.h"
#include "frames/popularimeterframe.h"
#include "frames/privateframe.h"
+#include "frames/ownershipframe.h"
using namespace TagLib;
using namespace ID3v2;
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);
}
// StringHandler implementation
////////////////////////////////////////////////////////////////////////////////
+Latin1StringHandler::Latin1StringHandler()
+{
+}
+
Latin1StringHandler::~Latin1StringHandler()
{
}
class TAGLIB_EXPORT Latin1StringHandler
{
public:
+ Latin1StringHandler();
virtual ~Latin1StringHandler();
/*!
#include <relativevolumeframe.h>
#include <popularimeterframe.h>
#include <urllinkframe.h>
+#include <ownershipframe.h>
#include <tdebug.h>
#include <tpropertymap.h>
#include "utils.h"
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);
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:
"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()
{
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");
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);