This commit is contained in:
Lukáš Lalinský 2012-09-06 19:24:22 +02:00
commit d2f20e8d2a
6 changed files with 369 additions and 6 deletions

View File

@ -0,0 +1,162 @@
/***************************************************************************
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"
#include <id3v2tag.h>
using namespace TagLib;
using namespace ID3v2;
class OwnershipFrame::OwnershipFramePrivate
{
public:
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
if(d->textEncoding == String::Latin1)
d->seller = Tag::latin1StringHandler()->parse(data.mid(pos));
else
d->seller = String(data.mid(pos), d->textEncoding);
}
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));
}

View File

@ -0,0 +1,151 @@
/***************************************************************************
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 consists of
* a 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

View 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);
}

View File

@ -81,6 +81,10 @@ const ID3v2::Latin1StringHandler *ID3v2::Tag::TagPrivate::stringHandler = &defau
// StringHandler implementation
////////////////////////////////////////////////////////////////////////////////
Latin1StringHandler::Latin1StringHandler()
{
}
Latin1StringHandler::~Latin1StringHandler()
{
}

View File

@ -77,6 +77,7 @@ namespace TagLib {
class TAGLIB_EXPORT Latin1StringHandler
{
public:
Latin1StringHandler();
virtual ~Latin1StringHandler();
/*!

View 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);
@ -386,6 +389,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()
{
@ -553,13 +588,13 @@ public:
CPPUNIT_ASSERT_EQUAL(String(""), frame->description());
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());
dynamic_cast<TagLib::ID3v2::UrlLinkFrame*>(f.ID3v2Tag()->frameListMap()["W000"].front());
CPPUNIT_ASSERT(frame);
CPPUNIT_ASSERT_EQUAL(String("lukas.lalinsky@example.com____"), frame->url());
}
@ -651,29 +686,30 @@ public:
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"));
}