diff --git a/bindings/c/CMakeLists.txt b/bindings/c/CMakeLists.txt index a12adeaf..79c7a6b9 100644 --- a/bindings/c/CMakeLists.txt +++ b/bindings/c/CMakeLists.txt @@ -9,6 +9,7 @@ INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/../../taglib ${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/mpc ${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/mp4 ${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/mpeg/id3v2 + ${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/mpeg/id3v2/frames ${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/wavpack ${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/ogg/speex ${CMAKE_CURRENT_SOURCE_DIR}/../../taglib/trueaudio diff --git a/taglib/CMakeLists.txt b/taglib/CMakeLists.txt index 619e31d9..04ce64e2 100644 --- a/taglib/CMakeLists.txt +++ b/taglib/CMakeLists.txt @@ -12,6 +12,7 @@ INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/ogg/vorbis ${CMAKE_CURRENT_SOURCE_DIR}/ogg/speex ${CMAKE_CURRENT_SOURCE_DIR}/mpeg/id3v2 + ${CMAKE_CURRENT_SOURCE_DIR}/mpeg/id3v2/frames ${CMAKE_CURRENT_SOURCE_DIR}/mpeg/id3v1 ${CMAKE_CURRENT_SOURCE_DIR}/ape ${CMAKE_CURRENT_SOURCE_DIR}/wavpack @@ -92,6 +93,7 @@ ogg/vorbis/vorbisproperties.cpp SET(flacs_SRCS flac/flacfile.cpp +flac/flacpicture.cpp flac/flacproperties.cpp ) diff --git a/taglib/flac/CMakeLists.txt b/taglib/flac/CMakeLists.txt index 8c983151..62768a43 100644 --- a/taglib/flac/CMakeLists.txt +++ b/taglib/flac/CMakeLists.txt @@ -1 +1 @@ -INSTALL( FILES flacfile.h flacproperties.h DESTINATION ${INCLUDE_INSTALL_DIR}/taglib ) +INSTALL( FILES flacfile.h flacpicture.h flacproperties.h DESTINATION ${INCLUDE_INSTALL_DIR}/taglib ) diff --git a/taglib/flac/Makefile.am b/taglib/flac/Makefile.am index 2d33975e..eebc7247 100644 --- a/taglib/flac/Makefile.am +++ b/taglib/flac/Makefile.am @@ -4,12 +4,13 @@ INCLUDES = \ -I$(top_srcdir)/taglib/toolkit \ -I$(top_srcdir)/taglib/ogg \ -I$(top_srcdir)/taglib/mpeg/id3v2 \ + -I$(top_srcdir)/taglib/mpeg/id3v2/frames \ -I$(top_srcdir)/taglib/mpeg/id3v1 \ $(all_includes) noinst_LTLIBRARIES = libflac.la -libflac_la_SOURCES = flacfile.cpp flacproperties.cpp +libflac_la_SOURCES = flacfile.cpp flacpicture.cpp flacproperties.cpp -taglib_include_HEADERS = flacfile.h flacproperties.h +taglib_include_HEADERS = flacfile.h flacpicture.h flacproperties.h taglib_includedir = $(includedir)/taglib diff --git a/taglib/flac/flacfile.cpp b/taglib/flac/flacfile.cpp index 7f3d9023..799e2fe4 100644 --- a/taglib/flac/flacfile.cpp +++ b/taglib/flac/flacfile.cpp @@ -34,6 +34,7 @@ #include #include +#include "flacpicture.h" #include "flacfile.h" using namespace TagLib; @@ -41,7 +42,15 @@ using namespace TagLib; namespace { enum { XiphIndex = 0, ID3v2Index = 1, ID3v1Index = 2 }; - enum { StreamInfo = 0, Padding, Application, SeekTable, VorbisComment, CueSheet }; + enum { + StreamInfo = 0, + Padding, + Application, + SeekTable, + VorbisComment, + CueSheet, + PictureBlock + }; enum { MinPaddingLength = 4096 }; } @@ -64,6 +73,9 @@ public: ~FilePrivate() { + for(uint i = 0; i < pictureList.size(); i++) { + delete pictureList[i]; + } delete properties; } @@ -78,6 +90,7 @@ public: Properties *properties; ByteVector streamInfoData; ByteVector xiphCommentData; + List pictureList; long flacStart; long streamStart; @@ -423,6 +436,16 @@ void FLAC::File::scan() debug("FLAC::File::scan() -- multiple Vorbis Comment blocks found, using the first one"); } } + else if(blockType == PictureBlock) { + ByteVector pictureData = readBlock(length); + FLAC::Picture *picture = new FLAC::Picture(); + if(picture->parse(pictureData)) { + addPicture(picture); + } + else { + debug("FLAC::File::scan() -- invalid picture found"); + } + } nextBlockOffset += length + 4; @@ -502,3 +525,21 @@ long FLAC::File::findPaddingBreak(long nextBlockOffset, long targetOffset, bool return 0; } + +List FLAC::File::pictureList() +{ + return d->pictureList; +} + +void FLAC::File::addPicture(Picture *picture) +{ + d->pictureList.append(picture); +} + +void FLAC::File::removePictures() +{ + for(uint i = 0; i < d->pictureList.size(); i++) + delete d->pictureList[i]; + d->pictureList.clear(); +} + diff --git a/taglib/flac/flacfile.h b/taglib/flac/flacfile.h index 015ecc8e..84b8680a 100644 --- a/taglib/flac/flacfile.h +++ b/taglib/flac/flacfile.h @@ -28,7 +28,9 @@ #include "taglib_export.h" #include "tfile.h" +#include "tlist.h" +#include "flacpicture.h" #include "flacproperties.h" namespace TagLib { @@ -182,6 +184,24 @@ namespace TagLib { */ long streamLength(); // BIC: remove + /*! + * Returns a list of pictures attached to the FLAC file. + */ + List pictureList(); + + /*! + * Remove all attached images. + */ + void removePictures(); + + /*! + * Add a new picture to the file. The file takes ownership of the + * picture and will handle freeing its memory. + * + * \note The file will be saved only after calling save(). + */ + void addPicture(Picture *picture); + private: File(const File &); File &operator=(const File &); diff --git a/taglib/flac/flacpicture.cpp b/taglib/flac/flacpicture.cpp new file mode 100644 index 00000000..e7f6958c --- /dev/null +++ b/taglib/flac/flacpicture.cpp @@ -0,0 +1,197 @@ +/************************************************************************** + copyright : (C) 2010 by Lukáš Lalinský + 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/ * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include "flacpicture.h" + +using namespace TagLib; + +class FLAC::Picture::PicturePrivate +{ +public: + PicturePrivate() : + type(ID3v2::AttachedPictureFrame::Other), + width(0), + height(0), + colorDepth(0), + numColors(0) + {} + + Type type; + String mimeType; + String description; + int width; + int height; + int colorDepth; + int numColors; + ByteVector data; +}; + +FLAC::Picture::Picture() +{ + d = new PicturePrivate; +} + +FLAC::Picture::Picture(const ByteVector &data) +{ + d = new PicturePrivate; + parse(data); +} + +FLAC::Picture::~Picture() +{ + delete d; +} + +bool FLAC::Picture::parse(const ByteVector &data) +{ + if(data.size() < 32) { + debug("A picture block must contain at least 5 bytes."); + return false; + } + + int pos = 0; + d->type = TagLib::ID3v2::AttachedPictureFrame::Type(data.mid(pos, 4).toUInt()); + pos += 4; + uint mimeTypeLength = data.mid(pos, 4).toUInt(); + pos += 4; + if(pos + mimeTypeLength + 24 > data.size()) { + debug("Invalid picture block."); + return false; + } + d->mimeType = String(data.mid(pos, mimeTypeLength), String::UTF8); + pos += mimeTypeLength; + uint descriptionLength = data.mid(pos, 4).toUInt(); + pos += 4; + if(pos + descriptionLength + 20 > data.size()) { + debug("Invalid picture block."); + return false; + } + d->description = String(data.mid(pos, descriptionLength), String::UTF8); + pos += descriptionLength; + d->width = data.mid(pos, 4).toUInt(); + pos += 4; + d->height = data.mid(pos, 4).toUInt(); + pos += 4; + d->colorDepth = data.mid(pos, 4).toUInt(); + pos += 4; + d->numColors = data.mid(pos, 4).toUInt(); + pos += 4; + uint dataLength = data.mid(pos, 4).toUInt(); + pos += 4; + if(pos + dataLength > data.size()) { + debug("Invalid picture block."); + return false; + } + d->data = data.mid(pos, dataLength); + + return true; +} + +FLAC::Picture::Type FLAC::Picture::type() const +{ + return d->type; +} + +void FLAC::Picture::setType(FLAC::Picture::Type type) +{ + d->type = type; +} + +String FLAC::Picture::mimeType() const +{ + return d->mimeType; +} + +void FLAC::Picture::setMimeType(const String &mimeType) +{ + d->mimeType = mimeType; +} + +String FLAC::Picture::description() const +{ + return d->description; +} + +void FLAC::Picture::setDescription(const String &description) +{ + d->description = description; +} + +int FLAC::Picture::width() const +{ + return d->width; +} + +void FLAC::Picture::setWidth(int width) +{ + d->width = width; +} + +int FLAC::Picture::height() const +{ + return d->height; +} + +void FLAC::Picture::setHeight(int height) +{ + d->height = height; +} + +int FLAC::Picture::colorDepth() const +{ + return d->colorDepth; +} + +void FLAC::Picture::setColorDepth(int colorDepth) +{ + d->colorDepth = colorDepth; +} + +int FLAC::Picture::numColors() const +{ + return d->numColors; +} + +void FLAC::Picture::setNumColors(int numColors) +{ + d->numColors = numColors; +} + +ByteVector FLAC::Picture::data() const +{ + return d->data; +} + +void FLAC::Picture::setData(const ByteVector &data) +{ + d->data = data; +} + diff --git a/taglib/flac/flacpicture.h b/taglib/flac/flacpicture.h new file mode 100644 index 00000000..a05f0666 --- /dev/null +++ b/taglib/flac/flacpicture.h @@ -0,0 +1,147 @@ +/************************************************************************** + copyright : (C) 2010 by Lukáš Lalinský + 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_FLACPICTURE_H +#define TAGLIB_FLACPICTURE_H + +#include "tlist.h" +#include "tbytevector.h" +#include "taglib_export.h" +#include "attachedpictureframe.h" + +namespace TagLib { + + namespace FLAC { + + class TAGLIB_EXPORT Picture + { + public: + typedef ID3v2::AttachedPictureFrame::Type Type; + + Picture(); + Picture(const ByteVector &data); + ~Picture(); + + /*! + * Returns the type of the image. + */ + Type type() const; + + /*! + * Sets the type of the image. + */ + void setType(Type type); + + /*! + * Returns the mime type of the image. This should in most cases be + * "image/png" or "image/jpeg". + */ + String mimeType() const; + + /*! + * Sets the mime type of the image. This should in most cases be + * "image/png" or "image/jpeg". + */ + void setMimeType(const String &m); + + /*! + * Returns a text description of the image. + */ + + String description() const; + + /*! + * Sets a textual description of the image to \a desc. + */ + + void setDescription(const String &desc); + + /*! + * Returns the width of the image. + */ + int width() const; + + /*! + * Sets the width of the image. + */ + void setWidth(int w); + + /*! + * Returns the height of the image. + */ + int height() const; + + /*! + * Sets the height of the image. + */ + void setHeight(int h); + + /*! + * Returns the color depth (in bits-per-pixel) of the image. + */ + int colorDepth() const; + + /*! + * Sets the color depth (in bits-per-pixel) of the image. + */ + void setColorDepth(int depth); + + /*! + * Returns the number of colors used on the image.. + */ + int numColors() const; + + /*! + * Sets the number of colors used on the image (for indexed images). + */ + void setNumColors(int numColors); + + /*! + * Returns the image data. + */ + ByteVector data() const; + + /*! + * Sets the image data. + */ + void setData(const ByteVector &data); + + bool parse(const ByteVector &rawData); + + private: + Picture(const Picture &item); + Picture &operator=(const Picture &item); + + class PicturePrivate; + PicturePrivate *d; + }; + + typedef List PictureList; + + } + +} + +#endif diff --git a/tests/data/silence-44-s.flac b/tests/data/silence-44-s.flac new file mode 100644 index 00000000..24e15deb Binary files /dev/null and b/tests/data/silence-44-s.flac differ diff --git a/tests/test_flac.cpp b/tests/test_flac.cpp index 990299b2..d14a597b 100644 --- a/tests/test_flac.cpp +++ b/tests/test_flac.cpp @@ -15,6 +15,7 @@ class TestFLAC : public CppUnit::TestFixture CPPUNIT_TEST_SUITE(TestFLAC); CPPUNIT_TEST(testSignature); CPPUNIT_TEST(testMultipleCommentBlocks); + CPPUNIT_TEST(testPicture); CPPUNIT_TEST_SUITE_END(); public: @@ -41,6 +42,26 @@ public: delete f; } + void testPicture() + { + ScopedFileCopy copy("silence-44-s", ".flac"); + string newname = copy.fileName(); + + FLAC::File *f = new FLAC::File(newname.c_str()); + List lst = f->pictureList(); + CPPUNIT_ASSERT_EQUAL(TagLib::uint(1), lst.size()); + + FLAC::Picture *pic = lst.front(); + CPPUNIT_ASSERT_EQUAL(3, int(pic->type())); + CPPUNIT_ASSERT_EQUAL(1, pic->width()); + CPPUNIT_ASSERT_EQUAL(1, pic->height()); + CPPUNIT_ASSERT_EQUAL(24, pic->colorDepth()); + CPPUNIT_ASSERT_EQUAL(0, pic->numColors()); + CPPUNIT_ASSERT_EQUAL(String("image/png"), pic->mimeType()); + CPPUNIT_ASSERT_EQUAL(String("A pixel."), pic->description()); + CPPUNIT_ASSERT_EQUAL(TagLib::uint(150), pic->data().size()); + } + }; CPPUNIT_TEST_SUITE_REGISTRATION(TestFLAC);