From 0f11c5ab0cfdbf7725baba103322a19dea664a61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Lalinsk=C3=BD?= Date: Sat, 11 Jul 2009 14:27:17 +0000 Subject: [PATCH] Support for ID3v2.2 PIC frames Patch by Marc Halbruegge BUG:167786 git-svn-id: svn://anonsvn.kde.org/home/kde/trunk/kdesupport/taglib@994836 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- .../id3v2/frames/attachedpictureframe.cpp | 50 ++++++++++++++++++- .../mpeg/id3v2/frames/attachedpictureframe.h | 22 +++++--- taglib/mpeg/id3v2/id3v2framefactory.cpp | 11 +++- tests/test_id3v2.cpp | 20 ++++++++ 4 files changed, 94 insertions(+), 9 deletions(-) diff --git a/taglib/mpeg/id3v2/frames/attachedpictureframe.cpp b/taglib/mpeg/id3v2/frames/attachedpictureframe.cpp index 3ad71557..ee8f3e0b 100644 --- a/taglib/mpeg/id3v2/frames/attachedpictureframe.cpp +++ b/taglib/mpeg/id3v2/frames/attachedpictureframe.cpp @@ -50,7 +50,7 @@ public: AttachedPictureFrame::AttachedPictureFrame() : Frame("APIC") { - d = new AttachedPictureFramePrivate; + d = new AttachedPictureFramePrivate; } AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data) : Frame(data) @@ -174,3 +174,51 @@ AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data, Header *h) : 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 --git a/taglib/mpeg/id3v2/frames/attachedpictureframe.h b/taglib/mpeg/id3v2/frames/attachedpictureframe.h index bd95ed22..90b597b8 100644 --- a/taglib/mpeg/id3v2/frames/attachedpictureframe.h +++ b/taglib/mpeg/id3v2/frames/attachedpictureframe.h @@ -205,14 +205,24 @@ namespace TagLib { protected: virtual void parseFields(const ByteVector &data); virtual ByteVector renderFields() const; - - private: - AttachedPictureFrame(const ByteVector &data, Header *h); - AttachedPictureFrame(const AttachedPictureFrame &); - AttachedPictureFrame &operator=(const AttachedPictureFrame &); - class AttachedPictureFramePrivate; AttachedPictureFramePrivate *d; + + private: + AttachedPictureFrame(const AttachedPictureFrame &); + AttachedPictureFrame &operator=(const AttachedPictureFrame &); + AttachedPictureFrame(const ByteVector &data, Header *h); + + }; + + //! 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 --git a/taglib/mpeg/id3v2/id3v2framefactory.cpp b/taglib/mpeg/id3v2/id3v2framefactory.cpp index 18da4c3e..e412cb30 100644 --- a/taglib/mpeg/id3v2/id3v2framefactory.cpp +++ b/taglib/mpeg/id3v2/id3v2framefactory.cpp @@ -183,7 +183,15 @@ Frame *FrameFactory::createFrame(const ByteVector &origData, Header *tagHeader) 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); @@ -293,7 +301,6 @@ bool FrameFactory::updateFrame(Frame::Header *header) const 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); diff --git a/tests/test_id3v2.cpp b/tests/test_id3v2.cpp index 74701781..5aeaa861 100644 --- a/tests/test_id3v2.cpp +++ b/tests/test_id3v2.cpp @@ -38,6 +38,7 @@ class TestID3v2 : public CppUnit::TestFixture CPPUNIT_TEST(testReadStringField); CPPUNIT_TEST(testParseAPIC); CPPUNIT_TEST(testParseAPIC_UTF16_BOM); + CPPUNIT_TEST(testParseAPICv22); CPPUNIT_TEST(testParseGEOB); CPPUNIT_TEST(testPOPMtoString); CPPUNIT_TEST(testParsePOPM); @@ -132,6 +133,25 @@ public: CPPUNIT_ASSERT_EQUAL(ByteVector("\xff\xd8\xff", 3), f.picture()); } + void testParseAPICv22() + { + ID3v2::FrameFactory *factory = ID3v2::FrameFactory::instance(); + ByteVector data = ByteVector("PIC" + "\x00\x00\x08" + "\x00" + "JPG" + "\x01" + "d\x00" + "\x00", 18); + ID3v2::AttachedPictureFrame *frame = + static_cast(factory->createFrame(data, TagLib::uint(2))); + + CPPUNIT_ASSERT(frame); + CPPUNIT_ASSERT_EQUAL(String("image/jpeg"), frame->mimeType()); + CPPUNIT_ASSERT_EQUAL(ID3v2::AttachedPictureFrame::FileIcon, frame->type()); + CPPUNIT_ASSERT_EQUAL(String("d"), frame->description()); + } + // http://bugs.kde.org/show_bug.cgi?id=151078 void testParseGEOB() {