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 + +#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 +#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 +#include +#include + +#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(*it)->description().isEmpty()) + CommentsFrame *frame = dynamic_cast(*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()); }