- Cherry-pick bug-fix patches from 1.6 development (also replaces the old

taglib-1.5-kde#161721.patch):
169810)
107659)
Fixed overflow while calculating bitrate of FLAC files with a very high
    bitrate.
:year() now falls back to YEAR if DATE doesn't exist and
    XiphComment::year() falls back to TRACKNUM if TRACKNUMBER doesn't
    exist. (BUG:144396)
:split().
:operator[] and in String::operator+=. (BUG:169389)
176373)
167786)
188578)
168382)
172556)
Added support for PRIV ID3v2 frames.
Empty ID3v2 genres are no longer treated as numeric ID3v1 genres.
Added support for the POPM (rating/playcount) ID3v2 frame.
161721)
This commit is contained in:
Michael Schwendt 2009-08-22 10:44:21 +00:00
parent ab38c0c224
commit f69b1b0917
8 changed files with 1187 additions and 16 deletions

32
taglib-1.5-1.6-ape.patch Normal file
View File

@ -0,0 +1,32 @@
diff -Nur taglib-1.5/taglib/ape/apeitem.cpp taglib/taglib/ape/apeitem.cpp
--- taglib-1.5/taglib/ape/apeitem.cpp 2008-02-12 17:30:25.000000000 +0100
+++ taglib/taglib/ape/apeitem.cpp 2009-01-11 00:15:33.000000000 +0100
@@ -160,14 +160,14 @@
bool APE::Item::isEmpty() const
{
switch(d->type) {
- case 0:
- case 1:
+ case Text:
+ case Binary:
if(d->text.isEmpty())
return true;
if(d->text.size() == 1 && d->text.front().isEmpty())
return true;
return false;
- case 2:
+ case Locator:
return d->value.isEmpty();
default:
return false;
@@ -206,8 +206,9 @@
if(isEmpty())
return data;
- if(d->type != Item::Binary) {
+ if(d->type == Text) {
StringList::ConstIterator it = d->text.begin();
+
value.append(it->data(String::UTF8));
it++;
for(; it != d->text.end(); ++it) {

133
taglib-1.5-1.6-flac.patch Normal file
View File

@ -0,0 +1,133 @@
diff -Nur taglib-1.5/taglib/flac/flacfile.cpp taglib/taglib/flac/flacfile.cpp
--- taglib-1.5/taglib/flac/flacfile.cpp 2008-01-31 06:19:03.000000000 +0100
+++ taglib/taglib/flac/flacfile.cpp 2009-07-12 23:53:18.000000000 +0200
@@ -42,6 +42,7 @@
{
enum { XiphIndex = 0, ID3v2Index = 1, ID3v1Index = 2 };
enum { StreamInfo = 0, Padding, Application, SeekTable, VorbisComment, CueSheet };
+ enum { MinPaddingLength = 4096 };
}
class FLAC::File::FilePrivate
@@ -167,9 +168,49 @@
uint blockLength = header.mid(1, 3).toUInt();
if(blockType == VorbisComment) {
- data[0] = header[0];
- insert(data, nextBlockOffset, blockLength + 4);
- break;
+
+ long paddingBreak = 0;
+
+ if(!isLastBlock) {
+ paddingBreak = findPaddingBreak(nextBlockOffset + blockLength + 4,
+ nextBlockOffset + d->xiphCommentData.size() + 8,
+ &isLastBlock);
+ }
+
+ uint paddingLength = 0;
+
+ if(paddingBreak) {
+
+ // There is space for comment and padding blocks without rewriting the
+ // whole file. Note: This cannot overflow.
+
+ paddingLength = paddingBreak - (nextBlockOffset + d->xiphCommentData.size() + 8);
+ }
+ else {
+
+ // Not enough space, so we will have to rewrite the whole file
+ // following this block
+
+ paddingLength = d->xiphCommentData.size();
+
+ if(paddingLength < MinPaddingLength)
+ paddingLength = MinPaddingLength;
+
+ paddingBreak = nextBlockOffset + blockLength + 4;
+ }
+
+ ByteVector padding = ByteVector::fromUInt(paddingLength);
+
+ padding[0] = 1;
+
+ if(isLastBlock)
+ padding[0] |= 0x80;
+
+ padding.resize(paddingLength + 4);
+ ByteVector pair(data);
+ pair.append(padding);
+ insert(pair, nextBlockOffset, paddingBreak - nextBlockOffset);
+ break;
}
nextBlockOffset += blockLength + 4;
@@ -373,11 +414,8 @@
isLastBlock = (header[0] & 0x80) != 0;
length = header.mid(1, 3).toUInt();
- if(blockType == Padding) {
- // debug("FLAC::File::scan() -- Padding found");
- }
// Found the vorbis-comment
- else if(blockType == VorbisComment) {
+ if(blockType == VorbisComment) {
d->xiphCommentData = readBlock(length);
d->hasXiphComment = true;
}
@@ -429,3 +467,34 @@
return -1;
}
+
+long FLAC::File::findPaddingBreak(long nextBlockOffset, long targetOffset, bool *isLast)
+{
+ // Starting from nextBlockOffset, step over padding blocks to find the
+ // address of a block which is after targetOffset. Return zero if
+ // a non-padding block occurs before that point.
+
+ while(true) {
+ seek(nextBlockOffset);
+
+ ByteVector header = readBlock(4);
+ char blockType = header[0] & 0x7f;
+ bool isLastBlock = header[0] & 0x80;
+ uint length = header.mid(1, 3).toUInt();
+
+ if(blockType != Padding)
+ break;
+
+ nextBlockOffset += 4 + length;
+
+ if(nextBlockOffset >= targetOffset) {
+ *isLast = isLastBlock;
+ return nextBlockOffset;
+ }
+
+ if(isLastBlock)
+ break;
+ }
+
+ return 0;
+}
diff -Nur taglib-1.5/taglib/flac/flacfile.h taglib/taglib/flac/flacfile.h
--- taglib-1.5/taglib/flac/flacfile.h 2008-01-31 05:07:29.000000000 +0100
+++ taglib/taglib/flac/flacfile.h 2009-07-12 23:53:18.000000000 +0200
@@ -191,6 +191,7 @@
long findID3v2();
long findID3v1();
ByteVector xiphCommentData() const;
+ long findPaddingBreak(long nextPageOffset, long targetOffset, bool *isLast);
class FilePrivate;
FilePrivate *d;
diff -Nur taglib-1.5/taglib/flac/flacproperties.cpp taglib/taglib/flac/flacproperties.cpp
--- taglib-1.5/taglib/flac/flacproperties.cpp 2008-01-11 01:55:09.000000000 +0100
+++ taglib/taglib/flac/flacproperties.cpp 2008-04-08 14:15:20.000000000 +0200
@@ -146,5 +146,5 @@
// Real bitrate:
- d->bitrate = d->length > 0 ? ((d->streamLength * 8L) / d->length) / 1000 : 0;
+ d->bitrate = d->length > 0 ? ((d->streamLength * 8UL) / d->length) / 1000 : 0;
}

View File

@ -0,0 +1,12 @@
diff -Nur taglib-1.5-orig/taglib/CMakeLists.txt taglib-1.5/taglib/CMakeLists.txt
--- taglib-1.5-orig/taglib/CMakeLists.txt 2008-02-12 05:15:20.000000000 +0100
+++ taglib-1.5/taglib/CMakeLists.txt 2009-08-22 12:18:40.000000000 +0200
@@ -62,6 +62,8 @@
mpeg/id3v2/frames/attachedpictureframe.cpp
mpeg/id3v2/frames/commentsframe.cpp
mpeg/id3v2/frames/generalencapsulatedobjectframe.cpp
+mpeg/id3v2/frames/popularimeterframe.cpp
+mpeg/id3v2/frames/privateframe.cpp
mpeg/id3v2/frames/relativevolumeframe.cpp
mpeg/id3v2/frames/textidentificationframe.cpp
mpeg/id3v2/frames/uniquefileidentifierframe.cpp

887
taglib-1.5-1.6-mpeg.patch Normal file
View File

@ -0,0 +1,887 @@
diff -Nur taglib-1.5/taglib/mpeg/mpegheader.cpp taglib/taglib/mpeg/mpegheader.cpp
--- taglib-1.5/taglib/mpeg/mpegheader.cpp 2008-02-04 16:14:46.000000000 +0100
+++ taglib/taglib/mpeg/mpegheader.cpp 2009-01-16 06:16:48.000000000 +0100
@@ -164,7 +164,7 @@
void MPEG::Header::parse(const ByteVector &data)
{
if(data.size() < 4 || uchar(data[0]) != 0xff) {
- debug("MPEG::Header::parse() -- First byte did not mactch MPEG synch.");
+ debug("MPEG::Header::parse() -- First byte did not match MPEG synch.");
return;
}
@@ -173,7 +173,7 @@
// Check for the second byte's part of the MPEG synch
if(!flags[23] || !flags[22] || !flags[21]) {
- debug("MPEG::Header::parse() -- Second byte did not mactch MPEG synch.");
+ debug("MPEG::Header::parse() -- Second byte did not match MPEG synch.");
return;
}
diff -Nur taglib-1.5/taglib/mpeg/mpegproperties.cpp taglib/taglib/mpeg/mpegproperties.cpp
--- taglib-1.5/taglib/mpeg/mpegproperties.cpp 2008-02-04 16:14:46.000000000 +0100
+++ taglib/taglib/mpeg/mpegproperties.cpp 2009-07-10 16:34:04.000000000 +0200
@@ -218,8 +218,10 @@
double timePerFrame =
double(firstHeader.samplesPerFrame()) / firstHeader.sampleRate();
- d->length = int(timePerFrame * d->xingHeader->totalFrames());
- d->bitrate = d->length > 0 ? d->xingHeader->totalSize() * 8 / d->length / 1000 : 0;
+ double length = timePerFrame * d->xingHeader->totalFrames();
+
+ d->length = int(length);
+ d->bitrate = d->length > 0 ? d->xingHeader->totalSize() * 8 / length / 1000 : 0;
}
else {
// Since there was no valid Xing header found, we hope that we're in a constant
diff -Nur taglib-1.5/taglib/mpeg/id3v2/frames/attachedpictureframe.cpp taglib/taglib/mpeg/id3v2/frames/attachedpictureframe.cpp
--- taglib-1.5/taglib/mpeg/id3v2/frames/attachedpictureframe.cpp 2008-02-04 16:14:46.000000000 +0100
+++ taglib/taglib/mpeg/id3v2/frames/attachedpictureframe.cpp 2009-07-11 16:27:17.000000000 +0200
@@ -50,7 +50,7 @@
AttachedPictureFrame::AttachedPictureFrame() : Frame("APIC")
{
- d = new AttachedPictureFramePrivate;
+ d = new AttachedPictureFramePrivate;
}
AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data) : Frame(data)
@@ -136,6 +136,12 @@
int pos = 1;
d->mimeType = readStringField(data, String::Latin1, &pos);
+ /* Now we need at least two more bytes available */
+ if (pos + 1 >= data.size()) {
+ debug("Truncated picture frame.");
+ return;
+ }
+
d->type = (TagLib::ID3v2::AttachedPictureFrame::Type)data[pos++];
d->description = readStringField(data, d->textEncoding, &pos);
@@ -168,3 +174,51 @@
d = new AttachedPictureFramePrivate;
parseFields(fieldData(data));
}
+
+////////////////////////////////////////////////////////////////////////////////
+// support for ID3v2.2 PIC frames
+////////////////////////////////////////////////////////////////////////////////
+
+void AttachedPictureFrameV22::parseFields(const ByteVector &data)
+{
+ if(data.size() < 5) {
+ debug("A picture frame must contain at least 5 bytes.");
+ return;
+ }
+
+ d->textEncoding = String::Type(data[0]);
+
+ int pos = 1;
+
+ String fixedString = String(data.mid(pos, 3), String::Latin1);
+ pos += 3;
+ // convert fixed string image type to mime string
+ if (fixedString.upper() == "JPG") {
+ d->mimeType = "image/jpeg";
+ } else if (fixedString.upper() == "PNG") {
+ d->mimeType = "image/png";
+ } else {
+ debug("probably unsupported image type");
+ d->mimeType = "image/" + fixedString;
+ }
+
+ d->type = (TagLib::ID3v2::AttachedPictureFrame::Type)data[pos++];
+ d->description = readStringField(data, d->textEncoding, &pos);
+
+ d->data = data.mid(pos);
+}
+
+AttachedPictureFrameV22::AttachedPictureFrameV22(const ByteVector &data, Header *h)
+{
+ d = new AttachedPictureFramePrivate;
+
+ // set v2.2 header to make fieldData work correctly
+ setHeader(h, true);
+
+ parseFields(fieldData(data));
+
+ // now set the v2.4 header
+ Frame::Header *newHeader = new Frame::Header("APIC");
+ newHeader->setFrameSize(h->frameSize());
+ setHeader(newHeader, false);
+}
diff -Nur taglib-1.5/taglib/mpeg/id3v2/frames/attachedpictureframe.h taglib/taglib/mpeg/id3v2/frames/attachedpictureframe.h
--- taglib-1.5/taglib/mpeg/id3v2/frames/attachedpictureframe.h 2008-02-04 16:14:46.000000000 +0100
+++ taglib/taglib/mpeg/id3v2/frames/attachedpictureframe.h 2009-07-11 16:27:17.000000000 +0200
@@ -205,14 +205,24 @@
protected:
virtual void parseFields(const ByteVector &data);
virtual ByteVector renderFields() const;
+ class AttachedPictureFramePrivate;
+ AttachedPictureFramePrivate *d;
private:
- AttachedPictureFrame(const ByteVector &data, Header *h);
AttachedPictureFrame(const AttachedPictureFrame &);
AttachedPictureFrame &operator=(const AttachedPictureFrame &);
+ AttachedPictureFrame(const ByteVector &data, Header *h);
- class AttachedPictureFramePrivate;
- AttachedPictureFramePrivate *d;
+ };
+
+ //! support for ID3v2.2 PIC frames
+ class TAGLIB_EXPORT AttachedPictureFrameV22 : public AttachedPictureFrame
+ {
+ protected:
+ virtual void parseFields(const ByteVector &data);
+ private:
+ AttachedPictureFrameV22(const ByteVector &data, Header *h);
+ friend class FrameFactory;
};
}
}
diff -Nur taglib-1.5/taglib/mpeg/id3v2/frames/CMakeLists.txt taglib/taglib/mpeg/id3v2/frames/CMakeLists.txt
--- taglib-1.5/taglib/mpeg/id3v2/frames/CMakeLists.txt 2008-01-31 22:48:39.000000000 +0100
+++ taglib/taglib/mpeg/id3v2/frames/CMakeLists.txt 2008-06-26 17:06:20.000000000 +0200
@@ -2,6 +2,8 @@
attachedpictureframe.h
commentsframe.h
generalencapsulatedobjectframe.h
+ popularimeterframe.h
+ privateframe.h
relativevolumeframe.h
textidentificationframe.h
uniquefileidentifierframe.h
diff -Nur taglib-1.5/taglib/mpeg/id3v2/frames/generalencapsulatedobjectframe.h taglib/taglib/mpeg/id3v2/frames/generalencapsulatedobjectframe.h
--- taglib-1.5/taglib/mpeg/id3v2/frames/generalencapsulatedobjectframe.h 2008-02-04 16:14:46.000000000 +0100
+++ taglib/taglib/mpeg/id3v2/frames/generalencapsulatedobjectframe.h 2008-06-19 22:44:39.000000000 +0200
@@ -61,6 +61,10 @@
/*!
* Constructs a GeneralEncapsulatedObjectFrame frame based on \a data.
+ *
+ * \warning This is \em not data for the encapsulated object, for that use
+ * setObject(). This constructor is used when reading the frame from the
+ * disk.
*/
explicit GeneralEncapsulatedObjectFrame(const ByteVector &data);
diff -Nur taglib-1.5/taglib/mpeg/id3v2/frames/Makefile.am taglib/taglib/mpeg/id3v2/frames/Makefile.am
--- taglib-1.5/taglib/mpeg/id3v2/frames/Makefile.am 2008-01-31 22:48:28.000000000 +0100
+++ taglib/taglib/mpeg/id3v2/frames/Makefile.am 2008-06-26 17:06:20.000000000 +0200
@@ -10,6 +10,8 @@
attachedpictureframe.cpp \
commentsframe.cpp \
generalencapsulatedobjectframe.cpp \
+ popularimeterframe.cpp \
+ privateframe.cpp \
relativevolumeframe.cpp \
textidentificationframe.cpp \
uniquefileidentifierframe.cpp \
@@ -21,6 +23,8 @@
attachedpictureframe.h \
commentsframe.h \
generalencapsulatedobjectframe.h \
+ popularimeterframe.h \
+ privateframe.h \
relativevolumeframe.h \
textidentificationframe.h \
uniquefileidentifierframe.h \
diff -Nur taglib-1.5/taglib/mpeg/id3v2/frames/popularimeterframe.cpp taglib/taglib/mpeg/id3v2/frames/popularimeterframe.cpp
--- taglib-1.5/taglib/mpeg/id3v2/frames/popularimeterframe.cpp 1970-01-01 01:00:00.000000000 +0100
+++ taglib/taglib/mpeg/id3v2/frames/popularimeterframe.cpp 2008-05-22 22:40:14.000000000 +0200
@@ -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 = (unsigned char)(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 -Nur taglib-1.5/taglib/mpeg/id3v2/frames/popularimeterframe.h taglib/taglib/mpeg/id3v2/frames/popularimeterframe.h
--- taglib-1.5/taglib/mpeg/id3v2/frames/popularimeterframe.h 1970-01-01 01:00:00.000000000 +0100
+++ taglib/taglib/mpeg/id3v2/frames/popularimeterframe.h 2008-05-22 14:06:45.000000000 +0200
@@ -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
diff -Nur taglib-1.5/taglib/mpeg/id3v2/frames/privateframe.cpp taglib/taglib/mpeg/id3v2/frames/privateframe.cpp
--- taglib-1.5/taglib/mpeg/id3v2/frames/privateframe.cpp 1970-01-01 01:00:00.000000000 +0100
+++ taglib/taglib/mpeg/id3v2/frames/privateframe.cpp 2008-06-27 00:11:11.000000000 +0200
@@ -0,0 +1,128 @@
+/***************************************************************************
+ copyright : (C) 2008 by Serkan Kalyoncu
+ copyright : (C) 2008 by Scott Wheeler
+ email : wheeler@kde.org
+***************************************************************************/
+
+/***************************************************************************
+ * 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 <tbytevectorlist.h>
+#include <id3v2tag.h>
+#include <tdebug.h>
+
+#include "privateframe.h"
+
+using namespace TagLib;
+using namespace ID3v2;
+
+
+class PrivateFrame::PrivateFramePrivate
+{
+public:
+ ByteVector data;
+ String owner;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// public members
+////////////////////////////////////////////////////////////////////////////////
+
+PrivateFrame::PrivateFrame() : Frame("PRIV")
+{
+ d = new PrivateFramePrivate;
+}
+
+PrivateFrame::PrivateFrame(const ByteVector &data) : Frame(data)
+{
+ d = new PrivateFramePrivate;
+ setData(data);
+}
+
+PrivateFrame::~PrivateFrame()
+{
+ delete d;
+}
+
+String PrivateFrame::toString() const
+{
+ return d->owner;
+}
+
+String PrivateFrame::owner() const
+{
+ return d->owner;
+}
+
+ByteVector PrivateFrame::data() const
+{
+ return d->data;
+}
+
+void PrivateFrame::setOwner(const String &s)
+{
+ d->owner = s;
+}
+
+void PrivateFrame::setData(const ByteVector & data)
+{
+ d->data = data;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// protected members
+////////////////////////////////////////////////////////////////////////////////
+
+void PrivateFrame::parseFields(const ByteVector &data)
+{
+ if(data.size() < 2) {
+ debug("A private frame must contain at least 2 bytes.");
+ return;
+ }
+
+ // Owner identifier is assumed to be Latin1
+
+ const int byteAlign = 1;
+ const int endOfOwner = data.find(textDelimiter(String::Latin1), 0, byteAlign);
+
+ d->owner = String(data.mid(0, endOfOwner));
+ d->data = data.mid(endOfOwner + 1);
+}
+
+ByteVector PrivateFrame::renderFields() const
+{
+ ByteVector v;
+
+ v.append(d->owner.data(String::Latin1));
+ v.append(textDelimiter(String::Latin1));
+ v.append(d->data);
+
+ return v;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// private members
+////////////////////////////////////////////////////////////////////////////////
+
+PrivateFrame::PrivateFrame(const ByteVector &data, Header *h) : Frame(h)
+{
+ d = new PrivateFramePrivate();
+ parseFields(fieldData(data));
+}
diff -Nur taglib-1.5/taglib/mpeg/id3v2/frames/privateframe.h taglib/taglib/mpeg/id3v2/frames/privateframe.h
--- taglib-1.5/taglib/mpeg/id3v2/frames/privateframe.h 1970-01-01 01:00:00.000000000 +0100
+++ taglib/taglib/mpeg/id3v2/frames/privateframe.h 2008-06-27 00:11:11.000000000 +0200
@@ -0,0 +1,111 @@
+/***************************************************************************
+ copyright : (C) 2008 by Serkan Kalyoncu
+ copyright : (C) 2008 by Scott Wheeler
+ email : wheeler@kde.org
+***************************************************************************/
+
+/***************************************************************************
+ * 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_PRIVATEFRAME_H
+#define TAGLIB_PRIVATEFRAME_H
+
+#include "id3v2frame.h"
+#include "taglib_export.h"
+
+namespace TagLib {
+
+ namespace ID3v2 {
+
+ //! An implementation of ID3v2 privateframe
+
+ class TAGLIB_EXPORT PrivateFrame : public Frame
+ {
+ friend class FrameFactory;
+
+ public:
+ /*!
+ * Construct an empty private frame.
+ */
+ PrivateFrame();
+
+ /*!
+ * Construct a private frame based on the data in \a data.
+ *
+ * \note This is the constructor used when parsing the frame from a file.
+ */
+ explicit PrivateFrame(const ByteVector &data);
+
+ /*!
+ * Destroys this private frame instance.
+ */
+ virtual ~PrivateFrame();
+
+ /*!
+ * Returns the text of this private frame, currently just the owner.
+ *
+ * \see text()
+ */
+ virtual String toString() const;
+
+ /*!
+ * \return The owner of the private frame.
+ * \note This should contain an email address or link to a website.
+ */
+ String owner() const;
+
+ /*!
+ *
+ */
+ ByteVector data() const;
+
+ /*!
+ * Sets the owner of the frame to \a s.
+ * \note This should contain an email address or link to a website.
+ */
+ void setOwner(const String &s);
+
+ /*!
+ *
+ */
+ void setData(const ByteVector &v);
+
+ protected:
+ // Reimplementations.
+
+ virtual void parseFields(const ByteVector &data);
+ virtual ByteVector renderFields() const;
+
+ private:
+ /*!
+ * The constructor used by the FrameFactory.
+ */
+ PrivateFrame(const ByteVector &data, Header *h);
+
+ PrivateFrame(const PrivateFrame &);
+ PrivateFrame &operator=(const PrivateFrame &);
+
+ class PrivateFramePrivate;
+ PrivateFramePrivate *d;
+ };
+
+ }
+}
+#endif
diff -Nur taglib-1.5/taglib/mpeg/id3v2/id3v2footer.cpp taglib/taglib/mpeg/id3v2/id3v2footer.cpp
--- taglib-1.5/taglib/mpeg/id3v2/id3v2footer.cpp 2008-02-04 16:14:46.000000000 +0100
+++ taglib/taglib/mpeg/id3v2/id3v2footer.cpp 2008-12-05 17:43:38.000000000 +0100
@@ -45,7 +45,7 @@
}
-const unsigned int Footer::size()
+TagLib::uint Footer::size()
{
return FooterPrivate::size;
}
diff -Nur taglib-1.5/taglib/mpeg/id3v2/id3v2footer.h taglib/taglib/mpeg/id3v2/id3v2footer.h
--- taglib-1.5/taglib/mpeg/id3v2/id3v2footer.h 2008-02-04 16:14:46.000000000 +0100
+++ taglib/taglib/mpeg/id3v2/id3v2footer.h 2008-12-05 01:37:39.000000000 +0100
@@ -62,7 +62,7 @@
/*!
* Returns the size of the footer. Presently this is always 10 bytes.
*/
- static const unsigned int size();
+ static uint size();
/*!
* Renders the footer based on the data in \a header.
diff -Nur taglib-1.5/taglib/mpeg/id3v2/id3v2framefactory.cpp taglib/taglib/mpeg/id3v2/id3v2framefactory.cpp
--- taglib-1.5/taglib/mpeg/id3v2/id3v2framefactory.cpp 2008-02-21 01:43:14.000000000 +0100
+++ taglib/taglib/mpeg/id3v2/id3v2framefactory.cpp 2009-07-11 16:27:17.000000000 +0200
@@ -31,6 +31,7 @@
#include "id3v2framefactory.h"
#include "id3v2synchdata.h"
+#include "id3v1genres.h"
#include "frames/attachedpictureframe.h"
#include "frames/commentsframe.h"
@@ -41,6 +42,8 @@
#include "frames/generalencapsulatedobjectframe.h"
#include "frames/urllinkframe.h"
#include "frames/unsynchronizedlyricsframe.h"
+#include "frames/popularimeterframe.h"
+#include "frames/privateframe.h"
using namespace TagLib;
using namespace ID3v2;
@@ -180,7 +183,15 @@
return f;
}
- // Relative Volume Adjustment (frames 4.11)
+ // ID3v2.2 Attached Picture
+
+ if(frameID == "PIC") {
+ AttachedPictureFrame *f = new AttachedPictureFrameV22(data, header);
+ d->setTextEncoding(f);
+ return f;
+ }
+
+ // Relative Volume Adjustment (frames 4.11)
if(frameID == "RVA2")
return new RelativeVolumeFrame(data, header);
@@ -220,6 +231,16 @@
return f;
}
+ // Popularimeter (frames 4.17)
+
+ if(frameID == "POPM")
+ return new PopularimeterFrame(data, header);
+
+ // Private (frames 4.27)
+
+ if(frameID == "PRIV")
+ return new PrivateFrame(data, header);
+
return new UnknownFrame(data, header);
}
@@ -280,7 +301,6 @@
convertFrame("IPL", "TIPL", header);
convertFrame("MCI", "MCDI", header);
convertFrame("MLL", "MLLT", header);
- convertFrame("PIC", "APIC", header);
convertFrame("POP", "POPM", header);
convertFrame("REV", "RVRB", header);
convertFrame("SLT", "SYLT", header);
@@ -382,26 +402,31 @@
void FrameFactory::updateGenre(TextIdentificationFrame *frame) const
{
- StringList fields;
- String s = frame->toString();
+ StringList fields = frame->fieldList();
+ StringList newfields;
- while(s.startsWith("(")) {
-
- int closing = s.find(")");
-
- if(closing < 0)
- break;
-
- fields.append(s.substr(1, closing - 1));
-
- s = s.substr(closing + 1);
+ for(StringList::Iterator it = fields.begin(); it != fields.end(); ++it) {
+ String s = *it;
+ int end = s.find(")");
+
+ if(s.startsWith("(") && end > 0) {
+ // "(12)Genre"
+ String text = s.substr(end + 1);
+ int number = s.substr(1, end - 1).toInt();
+ if (number > 0 && number <= 255 && !(ID3v1::genre(number) == text))
+ newfields.append(s.substr(1, end - 1));
+ if (!text.isEmpty())
+ newfields.append(text);
+ }
+ else {
+ // "Genre" or "12"
+ newfields.append(s);
+ }
}
- if(!s.isEmpty())
- fields.append(s);
-
- if(fields.isEmpty())
+ if(newfields.isEmpty())
fields.append(String::null);
- frame->setText(fields);
+ frame->setText(newfields);
+
}
diff -Nur taglib-1.5/taglib/mpeg/id3v2/id3v2tag.cpp taglib/taglib/mpeg/id3v2/id3v2tag.cpp
--- taglib-1.5/taglib/mpeg/id3v2/id3v2tag.cpp 2008-02-04 21:33:54.000000000 +0100
+++ taglib/taglib/mpeg/id3v2/id3v2tag.cpp 2009-07-11 16:43:58.000000000 +0200
@@ -125,7 +125,9 @@
for(FrameList::ConstIterator it = comments.begin(); it != comments.end(); ++it)
{
- if(static_cast<CommentsFrame *>(*it)->description().isEmpty())
+ CommentsFrame *frame = dynamic_cast<CommentsFrame *>(*it);
+
+ if(frame && frame->description().isEmpty())
return (*it)->toString();
}
@@ -159,6 +161,9 @@
for(StringList::Iterator it = fields.begin(); it != fields.end(); ++it) {
+ if((*it).isEmpty())
+ continue;
+
bool isNumber = true;
for(String::ConstIterator charIt = (*it).begin();
@@ -347,6 +352,11 @@
// Loop through the frames rendering them and adding them to the tagData.
for(FrameList::Iterator it = d->frameList.begin(); it != d->frameList.end(); it++) {
+ if ((*it)->header()->frameID().size() != 4) {
+ debug("A frame of unsupported or unknown type \'"
+ + String((*it)->header()->frameID()) + "\' has been discarded");
+ continue;
+ }
if(!(*it)->header()->tagAlterPreservation())
tagData.append((*it)->render());
}

46
taglib-1.5-1.6-ogg.patch Normal file
View File

@ -0,0 +1,46 @@
diff -Nur taglib-1.5/taglib/ogg/xiphcomment.cpp taglib/taglib/ogg/xiphcomment.cpp
--- taglib-1.5/taglib/ogg/xiphcomment.cpp 2008-02-04 16:14:46.000000000 +0100
+++ taglib/taglib/ogg/xiphcomment.cpp 2009-07-11 15:17:06.000000000 +0200
@@ -103,16 +103,20 @@
TagLib::uint Ogg::XiphComment::year() const
{
- if(d->fieldListMap["DATE"].isEmpty())
- return 0;
- return d->fieldListMap["DATE"].front().toInt();
+ if(!d->fieldListMap["DATE"].isEmpty())
+ return d->fieldListMap["DATE"].front().toInt();
+ if(!d->fieldListMap["YEAR"].isEmpty())
+ return d->fieldListMap["YEAR"].front().toInt();
+ return 0;
}
TagLib::uint Ogg::XiphComment::track() const
{
- if(d->fieldListMap["TRACKNUMBER"].isEmpty())
- return 0;
- return d->fieldListMap["TRACKNUMBER"].front().toInt();
+ if(!d->fieldListMap["TRACKNUMBER"].isEmpty())
+ return d->fieldListMap["TRACKNUMBER"].front().toInt();
+ if(!d->fieldListMap["TRACKNUM"].isEmpty())
+ return d->fieldListMap["TRACKNUM"].front().toInt();
+ return 0;
}
void Ogg::XiphComment::setTitle(const String &s)
@@ -142,6 +146,7 @@
void Ogg::XiphComment::setYear(uint i)
{
+ removeField("YEAR");
if(i == 0)
removeField("DATE");
else
@@ -150,6 +155,7 @@
void Ogg::XiphComment::setTrack(uint i)
{
+ removeField("TRACKNUM");
if(i == 0)
removeField("TRACKNUMBER");
else

View File

@ -0,0 +1,42 @@
diff -Nur taglib-1.5/taglib/toolkit/tbytevector.cpp taglib/taglib/toolkit/tbytevector.cpp
--- taglib-1.5/taglib/toolkit/tbytevector.cpp 2008-02-12 04:18:52.000000000 +0100
+++ taglib/taglib/toolkit/tbytevector.cpp 2008-12-04 13:37:36.000000000 +0100
@@ -147,12 +147,12 @@
public:
ByteVectorMirror(const ByteVector &source) : v(source) {}
- const char operator[](int index) const
+ char operator[](int index) const
{
return v[v.size() - index - 1];
}
- const char at(int index) const
+ char at(int index) const
{
return v.at(v.size() - index - 1);
}
diff -Nur taglib-1.5/taglib/toolkit/tbytevector.h taglib/taglib/toolkit/tbytevector.h
--- taglib-1.5/taglib/toolkit/tbytevector.h 2008-02-05 19:51:48.000000000 +0100
+++ taglib/taglib/toolkit/tbytevector.h 2009-07-02 22:54:32.000000000 +0200
@@ -30,7 +30,7 @@
#include "taglib_export.h"
#include <vector>
-#include <ostream>
+#include <iostream>
namespace TagLib {
diff -Nur taglib-1.5/taglib/toolkit/tbytevectorlist.cpp taglib/taglib/toolkit/tbytevectorlist.cpp
--- taglib-1.5/taglib/toolkit/tbytevectorlist.cpp 2008-02-04 16:14:45.000000000 +0100
+++ taglib/taglib/toolkit/tbytevectorlist.cpp 2009-07-11 15:24:21.000000000 +0200
@@ -52,7 +52,7 @@
offset != -1 && (max == 0 || max > int(l.size()) + 1);
offset = v.find(pattern, offset + pattern.size(), byteAlign))
{
- if(offset - previousOffset > 1)
+ if(offset - previousOffset >= 1)
l.append(v.mid(previousOffset, offset - previousOffset));
else
l.append(ByteVector::null);

View File

@ -1,14 +0,0 @@
diff -up taglib-1.5/taglib/mpeg/id3v2/id3v2tag.cpp.kde#161721 taglib-1.5/taglib/mpeg/id3v2/id3v2tag.cpp
--- taglib-1.5/taglib/mpeg/id3v2/id3v2tag.cpp.kde#161721 2008-02-04 14:33:54.000000000 -0600
+++ taglib-1.5/taglib/mpeg/id3v2/id3v2tag.cpp 2008-10-06 15:52:08.000000000 -0500
@@ -125,7 +125,9 @@ String ID3v2::Tag::comment() const
for(FrameList::ConstIterator it = comments.begin(); it != comments.end(); ++it)
{
- if(static_cast<CommentsFrame *>(*it)->description().isEmpty())
+ CommentsFrame *frame = dynamic_cast<CommentsFrame *>(*it);
+
+ if(frame && frame->description().isEmpty())
return (*it)->toString();
}

View File

@ -30,7 +30,12 @@ Patch2: taglib-1.5rc1-multilib.patch
Patch3: taglib-1.5-tests.patch
## upstream patches
Patch100: taglib-1.5-kde#161721.patch
Patch101: taglib-1.5-1.6-ape.patch
Patch102: taglib-1.5-1.6-ogg.patch
Patch103: taglib-1.5-1.6-flac.patch
Patch104: taglib-1.5-1.6-toolkit.patch
Patch105: taglib-1.5-1.6-mpeg.patch
Patch106: taglib-1.5-1.6-mpeg-cmake.patch
BuildRequires: cmake
BuildRequires: pkgconfig
@ -60,7 +65,12 @@ Files needed when building software with %{name}.
%patch2 -p1 -b .multilib
%patch3 -p1 -b .tests
%patch100 -p1 -b .kde#161721.patch
%patch101 -p1 -b .ape
%patch102 -p1 -b .ogg
%patch103 -p1 -b .flac
%patch104 -p1 -b .toolkit
%patch105 -p1 -b .mpeg
%patch106 -p1 -b .mpeg-build
%build
@ -117,6 +127,29 @@ rm -rf %{buildroot}
* Sat Aug 22 2009 Michael Schwendt <mschwendt@fedoraproject.org> - 1.5-6
- Add %%check section and conditionally build with tests.
- Update descriptions (and mention the additional file formats).
- Cherry-pick bug-fix patches from 1.6 development (also replaces the
old taglib-1.5-kde#161721.patch):
* Fixed crash when saving a Locator APEv2 tag. (BUG:169810)
* TagLib can now use FLAC padding block. (BUG:107659)
* Fixed overflow while calculating bitrate of FLAC files with a very
high bitrate.
* XiphComment::year() now falls back to YEAR if DATE doesn't exist
and XiphComment::year() falls back to TRACKNUM if TRACKNUMBER doesn't
exist. (BUG:144396)
* Fixed a bug in ByteVectorList::split().
* Fixed a possible crash in the non-const version of String::operator[]
and in String::operator+=. (BUG:169389)
* ID3v2.2 frames are now not incorrectly saved. (BUG:176373)
* Support for ID3v2.2 PIC frames. (BUG:167786)
* Improved ID3v2.3 genre parsing. (BUG:188578)
* Better checking of corrupted ID3v2 APIC data. (BUG:168382)
* Bitrate calculating using the Xing header now uses floating point
numbers. (BUG:172556)
* Added support for PRIV ID3v2 frames.
* Empty ID3v2 genres are no longer treated as numeric ID3v1 genres.
* Added support for the POPM (rating/playcount) ID3v2 frame.
* Fixed crash on handling unsupported ID3v2 frames, e.g. on encrypted
frames. (BUG:161721)
* Sun Jul 26 2009 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 1.5-5
- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild