]> granicus.if.org Git - taglib/commitdiff
Read-only support for FLAC picture blocks
authorLukáš Lalinský <lalinsky@gmail.com>
Sun, 25 Jul 2010 11:06:36 +0000 (11:06 +0000)
committerLukáš Lalinský <lalinsky@gmail.com>
Sun, 25 Jul 2010 11:06:36 +0000 (11:06 +0000)
CCBUG:218696

git-svn-id: svn://anonsvn.kde.org/home/kde/trunk/kdesupport/taglib@1154376 283d02a7-25f6-0310-bc7c-ecb5cbfe19da

bindings/c/CMakeLists.txt
taglib/CMakeLists.txt
taglib/flac/CMakeLists.txt
taglib/flac/Makefile.am
taglib/flac/flacfile.cpp
taglib/flac/flacfile.h
taglib/flac/flacpicture.cpp [new file with mode: 0644]
taglib/flac/flacpicture.h [new file with mode: 0644]
tests/data/silence-44-s.flac [new file with mode: 0644]
tests/test_flac.cpp

index a12adeaf0684c1e4127f8b35ddec73712fe7b2a3..79c7a6b969983cdf57b8d8c37cea4962dba408eb 100644 (file)
@@ -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
index 619e31d915aa9baf323cadf0beb8d3bcbb904ef9..04ce64e2fd74070e3a637241bcd7e32d49c674a7 100644 (file)
@@ -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
 )
 
index 8c9831518dc37a9ecace5798151fd307be5e847b..62768a43cd06acee7d95418114bbf57a1c15345c 100644 (file)
@@ -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 )
index 2d33975e732ff308462172a72ce62d60fbd5012a..eebc7247af17fb211b7bf98d90c5ca1c4d9c556f 100644 (file)
@@ -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
index 7f3d9023ab2a0ae5e78a133204643ec949e07677..799e2fe4d8581e169b0687d1bfeb77ec43b8c06d 100644 (file)
@@ -34,6 +34,7 @@
 #include <id3v1tag.h>
 #include <xiphcomment.h>
 
+#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<Picture *> 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::Picture *> 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();
+}
+
index 015ecc8eb607a6025ced78b010bf3bc0658ca69f..84b8680ae968b05dc1ec3777a935a68ac0dd2bb1 100644 (file)
@@ -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<Picture *> 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 (file)
index 0000000..e7f6958
--- /dev/null
@@ -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 <config.h>
+#endif
+
+#include <taglib.h>
+#include <tdebug.h>
+#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 (file)
index 0000000..a05f066
--- /dev/null
@@ -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<Picture> PictureList;
+
+  }
+
+}
+
+#endif
diff --git a/tests/data/silence-44-s.flac b/tests/data/silence-44-s.flac
new file mode 100644 (file)
index 0000000..24e15de
Binary files /dev/null and b/tests/data/silence-44-s.flac differ
index 990299b2d2605f4669d294d0105fbbda3b89ede6..d14a597b6fed38d06eaad5724ddb11a6130a1003 100644 (file)
@@ -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<FLAC::Picture *> 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);