Support for POPM ID3 frame

git-svn-id: svn://anonsvn.kde.org/home/kde/trunk/kdesupport/taglib@811137 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
This commit is contained in:
Lukáš Lalinský 2008-05-22 12:06:45 +00:00
parent 51ca869f65
commit f6994ec26c
8 changed files with 357 additions and 0 deletions

View 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

View File

@ -2,6 +2,7 @@ INSTALL(FILES
attachedpictureframe.h
commentsframe.h
generalencapsulatedobjectframe.h
popularimeterframe.h
relativevolumeframe.h
textidentificationframe.h
uniquefileidentifierframe.h

View 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 \

View File

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

View File

@ -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

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

View 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 \

View 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()
{