]> granicus.if.org Git - taglib/commitdiff
Full read/write support for FLAC pictures
authorLukáš Lalinský <lalinsky@gmail.com>
Sat, 8 Jan 2011 10:36:26 +0000 (10:36 +0000)
committerLukáš Lalinský <lalinsky@gmail.com>
Sat, 8 Jan 2011 10:36:26 +0000 (10:36 +0000)
NEEDS MORE TESTING

BUG:218696

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

12 files changed:
taglib/CMakeLists.txt
taglib/flac/flacfile.cpp
taglib/flac/flacmetadatablocks.cpp [deleted file]
taglib/flac/flacmetadatablocks.h [deleted file]
taglib/flac/flacpicture.cpp
taglib/flac/flacpicture.h
taglib/mp4/mp4file.cpp
tests/CMakeLists.txt
tests/data/empty_vorbis.oga [moved from tests/data/empty_vorbis.ogg with 100% similarity]
tests/test_flac.cpp
tests/test_flacmetadatablocks.cpp [deleted file]
tests/test_flacpicture.cpp

index c637091d01330eabef2bc47635b76bca4a93be76..70da391db232a8de707995d3f008a7a2263a306c 100644 (file)
@@ -96,7 +96,6 @@ flac/flacfile.cpp
 flac/flacpicture.cpp
 flac/flacproperties.cpp
 flac/flacmetadatablock.cpp
-flac/flacmetadatablocks.cpp
 flac/flacunknownmetadatablock.cpp
 )
 
index cb402d5fafdb1aef8e9d1df2e16f993b8eafad01..852c4f8c5c48232472a5bd6071b7d21cc5dd666e 100644 (file)
 #include "flacpicture.h"
 #include "flacfile.h"
 #include "flacmetadatablock.h"
+#include "flacunknownmetadatablock.h"
 
 using namespace TagLib;
 
 namespace
 {
   enum { XiphIndex = 0, ID3v2Index = 1, ID3v1Index = 2 };
-  enum {
-    StreamInfo = 0,
-    Padding,
-    Application,
-    SeekTable,
-    VorbisComment,
-    CueSheet,
-    PictureBlock
-  };
   enum { MinPaddingLength = 4096 };
+  enum { LastBlockFlag = 0x80 };
 }
 
 class FLAC::File::FilePrivate
@@ -70,13 +63,15 @@ public:
     scanned(false),
     hasXiphComment(false),
     hasID3v2(false),
-    hasID3v1(false) {}
+    hasID3v1(false)
+  {
+    for(uint i = 0; i < blocks.size(); i++) {
+      delete blocks[i];
+    }
+  }
 
   ~FilePrivate()
   {
-    for(uint i = 0; i < pictureList.size(); i++) {
-      delete pictureList[i];
-    }
     delete properties;
   }
 
@@ -91,7 +86,7 @@ public:
   Properties *properties;
   ByteVector streamInfoData;
   ByteVector xiphCommentData;
-  List<Picture *> pictureList;
+  List<MetadataBlock *> blocks;
 
   long flacStart;
   long streamStart;
@@ -147,113 +142,67 @@ bool FLAC::File::save()
     return false;
   }
 
+  if(!isValid()) {
+    debug("FLAC::File::save() -- Trying to save invalid file.");
+    return false;
+  }
+
   // Create new vorbis comments
 
   Tag::duplicate(&d->tag, xiphComment(true), true);
 
   d->xiphCommentData = xiphComment()->render(false);
 
-  // A Xiph comment portion of the data stream starts with a 4-byte descriptor.
-  // The first byte indicates the frame type.  The last three bytes are used
-  // to give the length of the data segment.  Here we start
-
-  ByteVector data = ByteVector::fromUInt(d->xiphCommentData.size());
-
-  data[0] = char(VorbisComment);
-  data.append(d->xiphCommentData);
-
-
-   // If file already have comment => find and update it
-   // if not => insert one
-
-   // TODO: Search for padding and use that
-
-  if(d->hasXiphComment) {
-
-    long nextBlockOffset = d->flacStart;
-    bool isLastBlock = false;
-
-    while(!isLastBlock) {
-      seek(nextBlockOffset);
-
-      ByteVector header = readBlock(4);
-      char blockType = header[0] & 0x7f;
-      isLastBlock = (header[0] & 0x80) != 0;
-      uint blockLength = header.mid(1, 3).toUInt();
-
-      if(blockType == VorbisComment) {
+  // Replace metadata blocks
 
-        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;
+  bool foundVorbisCommentBlock = false;
+  List<MetadataBlock *> newBlocks;
+  for(uint i = 0; i < d->blocks.size(); i++) {
+    MetadataBlock *block = d->blocks[i];
+    if(block->code() == MetadataBlock::VorbisComment) {
+      // Set the new Vorbis Comment block
+      block = new UnknownMetadataBlock(MetadataBlock::VorbisComment, d->xiphCommentData);
+      foundVorbisCommentBlock = true;
+    }
+    if(block->code() == MetadataBlock::Padding) {
+      continue;
     }
+    newBlocks.append(block);
+  }
+  if(!foundVorbisCommentBlock) {
+    newBlocks.append(new UnknownMetadataBlock(MetadataBlock::VorbisComment, d->xiphCommentData));
+    foundVorbisCommentBlock = true;
+  }
+  d->blocks = newBlocks;
+
+  // Render data for the metadata blocks
+
+  ByteVector data;
+  for(uint i = 0; i < newBlocks.size(); i++) {
+    FLAC::MetadataBlock *block = newBlocks[i];
+    ByteVector blockData = block->render();
+    ByteVector blockHeader = ByteVector::fromUInt(blockData.size());
+    blockHeader[0] = block->code();
+    data.append(blockHeader);
+    data.append(blockData);
   }
-  else {
-
-    const long firstBlockOffset = d->flacStart;
-    seek(firstBlockOffset);
-
-    ByteVector header = readBlock(4);
-    bool isLastBlock = (header[0] & 0x80) != 0;
-    uint blockLength = header.mid(1, 3).toUInt();
 
-    if(isLastBlock) {
+  // Adjust the padding block(s)
 
-      // If the first block was previously also the last block, then we want to
-      // mark it as no longer being the first block (the writeBlock() call) and
-      // then set the data for the block that we're about to write to mark our
-      // new block as the last block.
+  long originalLength = d->streamStart - d->flacStart;
+  int paddingLength = originalLength - data.size() - 4; 
+  if (paddingLength < 0) {
+    paddingLength = MinPaddingLength;
+  }
+  ByteVector padding = ByteVector::fromUInt(paddingLength);
+  padding.resize(paddingLength + 4);
+  padding[0] = FLAC::MetadataBlock::Padding | LastBlockFlag;
+  data.append(padding);
 
-      seek(firstBlockOffset);
-      writeBlock(static_cast<char>(header[0] & 0x7F));
-      data[0] |= 0x80;
-    }
+  // Write the data to the file
 
-    insert(data, firstBlockOffset + blockLength + 4, 0);
-    d->hasXiphComment = true;
-  }
+  insert(data, d->flacStart, originalLength);
+  d->hasXiphComment = true;
 
   // Update ID3 tags
 
@@ -410,13 +359,14 @@ void FLAC::File::scan()
 
   // First block should be the stream_info metadata
 
-  if(blockType != StreamInfo) {
+  if(blockType != MetadataBlock::StreamInfo) {
     debug("FLAC::File::scan() -- invalid FLAC stream");
     setValid(false);
     return;
   }
 
   d->streamInfoData = readBlock(length);
+  d->blocks.append(new UnknownMetadataBlock(blockType, d->streamInfoData));
   nextBlockOffset += length + 4;
 
   // Search through the remaining metadata
@@ -427,27 +377,42 @@ void FLAC::File::scan()
     isLastBlock = (header[0] & 0x80) != 0;
     length = header.mid(1, 3).toUInt();
 
+    ByteVector data = readBlock(length);
+    if(data.size() != length) {
+      debug("FLAC::File::scan() -- FLAC stream corrupted");
+      setValid(false);
+      return;
+    }
+
+    MetadataBlock *block = 0;
+
     // Found the vorbis-comment
-    if(blockType == VorbisComment) {
+    if(blockType == MetadataBlock::VorbisComment) {
       if(!d->hasXiphComment) {
-        d->xiphCommentData = readBlock(length);
+        d->xiphCommentData = data;
         d->hasXiphComment = true;
       }
       else {
         debug("FLAC::File::scan() -- multiple Vorbis Comment blocks found, using the first one");
       }
     }
-    else if(blockType == PictureBlock) {
-      ByteVector pictureData = readBlock(length);
+    else if(blockType == MetadataBlock::Picture) {
       FLAC::Picture *picture = new FLAC::Picture();
-      if(picture->parse(pictureData)) {
-        addPicture(picture);
+      if(picture->parse(data)) {
+        block = picture;
       }
       else {
-        debug("FLAC::File::scan() -- invalid picture found");
+        debug("FLAC::File::scan() -- invalid picture found, discarting");
       }
     }
 
+    if(!block) {
+      block = new UnknownMetadataBlock(blockType, data);
+    }
+    if(block->code() != MetadataBlock::Padding) {
+      d->blocks.append(block);
+    }
+
     nextBlockOffset += length + 4;
 
     if(nextBlockOffset >= File::length()) {
@@ -496,51 +461,35 @@ long FLAC::File::findID3v2()
   return -1;
 }
 
-long FLAC::File::findPaddingBreak(long nextBlockOffset, long targetOffset, bool *isLast)
+List<FLAC::Picture *> FLAC::File::pictureList()
 {
-  // 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;
+  List<Picture *> pictures;
+  for(uint i = 0; i < d->blocks.size(); i++) {
+    Picture *picture = dynamic_cast<Picture *>(d->blocks[i]);
+    if(picture) {
+      pictures.append(picture);
     }
-
-    if(isLastBlock)
-      break;
   }
-
-  return 0;
-}
-
-List<FLAC::Picture *> FLAC::File::pictureList()
-{
-  return d->pictureList;
+  return pictures;
 }
 
 void FLAC::File::addPicture(Picture *picture)
 {
-  d->pictureList.append(picture);
+  d->blocks.append(picture);
 }
 
 void FLAC::File::removePictures()
 {
-  for(uint i = 0; i < d->pictureList.size(); i++)
-    delete d->pictureList[i];
-  d->pictureList.clear();
+  List<MetadataBlock *> newBlocks;
+  for(uint i = 0; i < d->blocks.size(); i++) {
+    Picture *picture = dynamic_cast<Picture *>(d->blocks[i]);
+    if(picture) {
+      delete picture;
+    }
+    else {
+      newBlocks.append(d->blocks[i]);
+    }
+  }
+  d->blocks = newBlocks;
 }
 
diff --git a/taglib/flac/flacmetadatablocks.cpp b/taglib/flac/flacmetadatablocks.cpp
deleted file mode 100644 (file)
index e5bd638..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-/**************************************************************************
-    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 "flacfile.h"
-#include "flacunknownmetadatablock.h"
-#include "flacmetadatablock.h"
-#include "flacmetadatablocks.h"
-
-using namespace TagLib;
-
-class FLAC::MetadataBlocks::MetadataBlocksPrivate 
-{
-public:
-  MetadataBlocksPrivate() {}
-
-  List<MetadataBlock *> blocks;
-};
-
-FLAC::MetadataBlocks::MetadataBlocks()
-{
-  d = new MetadataBlocksPrivate();
-}
-
-FLAC::MetadataBlocks::~MetadataBlocks()
-{
-  delete d;
-}
-
-const List<FLAC::MetadataBlock *> &FLAC::MetadataBlocks::metadataBlockList() const
-{
-  return d->blocks;
-}
-
-bool FLAC::MetadataBlocks::read(FLAC::File *file)
-{
-  bool isLastBlock = false;
-  while(!isLastBlock) {
-    ByteVector header = file->readBlock(4);
-    if(header.size() != 4) {
-      debug("FLAC::MetadataBlocks::read -- Unable to read 4 bytes long header");
-      return false;
-    }
-    char blockType = header[0] & 0x7f;
-    isLastBlock = (header[0] & 0x80) != 0;
-    uint length = header.mid(1, 3).toUInt();
-    ByteVector data = file->readBlock(length);
-    if(data.size() != length) {
-      debug("FLAC::MetadataBlocks::read -- Unable to read " + String::number(length) + " bytes long block body");
-      return false;
-    }
-    if(blockType != FLAC::MetadataBlock::Padding) {
-      FLAC::MetadataBlock *block = new FLAC::UnknownMetadataBlock(blockType, data);
-      d->blocks.append(block);
-    }
-  }
-  return true;
-}
-
-ByteVector FLAC::MetadataBlocks::render(int originalLength) const
-{
-  ByteVector result;
-  for(uint i = 0; i < d->blocks.size(); i++) {
-    FLAC::MetadataBlock *block = d->blocks[i];
-    if(block->code() == FLAC::MetadataBlock::Padding)
-      continue;
-    ByteVector data = block->render();
-    ByteVector header = ByteVector::fromUInt(data.size());
-    header[0] = block->code();
-    result.append(header);
-    result.append(data);
-  }
-  int paddingLength = originalLength - result.size() - 4; 
-  // We have to resize the file, add some padding
-  if (paddingLength < 0) {
-    paddingLength = 4096;
-  }
-  ByteVector padding = ByteVector::fromUInt(paddingLength);
-  padding.resize(paddingLength + 4);
-  padding[0] = FLAC::MetadataBlock::Padding | 0x80;
-  result.append(padding);
-  return result;
-}
-
diff --git a/taglib/flac/flacmetadatablocks.h b/taglib/flac/flacmetadatablocks.h
deleted file mode 100644 (file)
index e029c28..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/**************************************************************************
-    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_FLACMETADATABLOCKS_H
-#define TAGLIB_FLACMETADATABLOCKS_H
-
-#include "tlist.h"
-#include "tbytevector.h"
-#include "taglib_export.h"
-
-namespace TagLib {
-
-  namespace FLAC {
-
-    class File;
-
-    class TAGLIB_EXPORT MetadataBlocks
-    {
-    public:
-      MetadataBlocks();
-      virtual ~MetadataBlocks();
-
-      /*!
-       * Read the blocks from a file.
-       */
-      bool read(File *file);
-
-      /*!
-       * Render the blocks into a byte vector.
-       */
-      ByteVector render(int originalLength) const;
-
-      const List<MetadataBlock *> &metadataBlockList() const;
-
-    private:
-      MetadataBlocks(const MetadataBlocks &item);
-      MetadataBlocks &operator=(const MetadataBlocks &item);
-
-      class MetadataBlocksPrivate;
-      MetadataBlocksPrivate *d;
-    };
-
-  }
-
-}
-
-#endif
index 40e69b12d2ea0b7dd4bbbc511b83e847b59f1a98..44ef38674f1f8a9d3d88a50060fd4b9ae65539e4 100644 (file)
@@ -37,7 +37,7 @@ class FLAC::Picture::PicturePrivate
 {
 public:
   PicturePrivate() :
-    type(ID3v2::AttachedPictureFrame::Other),
+    type(FLAC::Picture::Other),
     width(0),
     height(0),
     colorDepth(0),
@@ -83,7 +83,7 @@ bool FLAC::Picture::parse(const ByteVector &data)
   }
 
   int pos = 0;
-  d->type = TagLib::ID3v2::AttachedPictureFrame::Type(data.mid(pos, 4).toUInt());
+  d->type = FLAC::Picture::Type(data.mid(pos, 4).toUInt());
   pos += 4;
   uint mimeTypeLength = data.mid(pos, 4).toUInt();
   pos += 4;
index 447bcaf898a05c0db05d14c82b45998de265541a..22adc36eb2f23681cab8ab3adc41ec8110117e1b 100644 (file)
@@ -27,9 +27,9 @@
 #define TAGLIB_FLACPICTURE_H
 
 #include "tlist.h"
+#include "tstring.h"
 #include "tbytevector.h"
 #include "taglib_export.h"
-#include "attachedpictureframe.h"
 #include "flacmetadatablock.h"
 
 namespace TagLib {
@@ -39,7 +39,54 @@ namespace TagLib {
     class TAGLIB_EXPORT Picture : public MetadataBlock
     {
     public:
-      typedef ID3v2::AttachedPictureFrame::Type Type;
+
+      /*!
+       * This describes the function or content of the picture.
+       */
+      enum Type {
+        //! A type not enumerated below
+        Other              = 0x00,
+        //! 32x32 PNG image that should be used as the file icon
+        FileIcon           = 0x01,
+        //! File icon of a different size or format
+        OtherFileIcon      = 0x02,
+        //! Front cover image of the album
+        FrontCover         = 0x03,
+        //! Back cover image of the album
+        BackCover          = 0x04,
+        //! Inside leaflet page of the album
+        LeafletPage        = 0x05,
+        //! Image from the album itself
+        Media              = 0x06,
+        //! Picture of the lead artist or soloist
+        LeadArtist         = 0x07,
+        //! Picture of the artist or performer
+        Artist             = 0x08,
+        //! Picture of the conductor
+        Conductor          = 0x09,
+        //! Picture of the band or orchestra
+        Band               = 0x0A,
+        //! Picture of the composer
+        Composer           = 0x0B,
+        //! Picture of the lyricist or text writer
+        Lyricist           = 0x0C,
+        //! Picture of the recording location or studio
+        RecordingLocation  = 0x0D,
+        //! Picture of the artists during recording
+        DuringRecording    = 0x0E,
+        //! Picture of the artists during performance
+        DuringPerformance  = 0x0F,
+        //! Picture from a movie or video related to the track
+        MovieScreenCapture = 0x10,
+        //! Picture of a large, coloured fish
+        ColouredFish       = 0x11,
+        //! Illustration related to the track
+        Illustration       = 0x12,
+        //! Logo of the band or performer
+        BandLogo           = 0x13,
+        //! Logo of the publisher (record company)
+        PublisherLogo      = 0x14
+      };
 
       Picture();
       Picture(const ByteVector &data);
@@ -135,10 +182,13 @@ namespace TagLib {
       int code() const;
 
       /*!
-       * Render the content of the block.
+       * Render the content to the FLAC picture block format.
        */
       ByteVector render() const;
 
+      /*!
+       * Parse the picture data in the FLAC picture block format.
+       */
       bool parse(const ByteVector &rawData);
 
     private:
index 1e4bd4dbc61a181c5848e3f5b5470c011aa69b8a..fcaa67d4655b7e7d2df9352f2b1cb62d9b0813c5 100644 (file)
@@ -134,8 +134,10 @@ MP4::File::save()
     return false;
   }
 
-  if(!isValid())
+  if(!isValid()) {
+    debug("MP4::File::save() -- Trying to save invalid file.");
     return false;
+  }
 
   return d->tag->save();
 }
index f06f2a4d2784fe6c58b9c31f337b15b30a0e3652..86408af0b09c86d64e5f1db3bc27f35c65b7a537 100644 (file)
@@ -41,7 +41,6 @@ SET(test_runner_SRCS
   test_oggflac.cpp
   test_flac.cpp
   test_flacpicture.cpp
-  test_flacmetadatablocks.cpp
   test_flacunknownmetadatablock.cpp
   test_ape.cpp
   test_apetag.cpp
index d14a597b6fed38d06eaad5724ddb11a6130a1003..1f50666cbbd4cf92318ec3fbabe0a380f48abb32 100644 (file)
@@ -15,7 +15,11 @@ class TestFLAC : public CppUnit::TestFixture
   CPPUNIT_TEST_SUITE(TestFLAC);
   CPPUNIT_TEST(testSignature);
   CPPUNIT_TEST(testMultipleCommentBlocks);
-  CPPUNIT_TEST(testPicture);
+  CPPUNIT_TEST(testReadPicture);
+  CPPUNIT_TEST(testAddPicture);
+  CPPUNIT_TEST(testReplacePicture);
+  CPPUNIT_TEST(testRemoveAllPictures);
+  CPPUNIT_TEST(testRepeatedSave);
   CPPUNIT_TEST_SUITE_END();
 
 public:
@@ -42,7 +46,7 @@ public:
     delete f;
   }
 
-  void testPicture()
+  void testReadPicture()
   {
     ScopedFileCopy copy("silence-44-s", ".flac");
     string newname = copy.fileName();
@@ -52,7 +56,7 @@ public:
     CPPUNIT_ASSERT_EQUAL(TagLib::uint(1), lst.size());
 
     FLAC::Picture *pic = lst.front();
-    CPPUNIT_ASSERT_EQUAL(3, int(pic->type()));
+    CPPUNIT_ASSERT_EQUAL(FLAC::Picture::FrontCover, pic->type());
     CPPUNIT_ASSERT_EQUAL(1, pic->width());
     CPPUNIT_ASSERT_EQUAL(1, pic->height());
     CPPUNIT_ASSERT_EQUAL(24, pic->colorDepth());
@@ -62,6 +66,136 @@ public:
     CPPUNIT_ASSERT_EQUAL(TagLib::uint(150), pic->data().size());
   }
 
+  void testAddPicture()
+  {
+    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 *newpic = new FLAC::Picture();
+    newpic->setType(FLAC::Picture::BackCover);
+    newpic->setWidth(5);
+    newpic->setHeight(6);
+    newpic->setColorDepth(16);
+    newpic->setNumColors(7);
+    newpic->setMimeType("image/jpeg");
+    newpic->setDescription("new image");
+    newpic->setData("JPEG data");
+    f->addPicture(newpic);
+    f->save();
+
+    f = new FLAC::File(newname.c_str());
+    lst = f->pictureList();
+    CPPUNIT_ASSERT_EQUAL(TagLib::uint(2), lst.size());
+
+    FLAC::Picture *pic = lst[0];
+    CPPUNIT_ASSERT_EQUAL(FLAC::Picture::FrontCover, 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());
+
+    pic = lst[1];
+    CPPUNIT_ASSERT_EQUAL(FLAC::Picture::BackCover, pic->type());
+    CPPUNIT_ASSERT_EQUAL(5, pic->width());
+    CPPUNIT_ASSERT_EQUAL(6, pic->height());
+    CPPUNIT_ASSERT_EQUAL(16, pic->colorDepth());
+    CPPUNIT_ASSERT_EQUAL(7, pic->numColors());
+    CPPUNIT_ASSERT_EQUAL(String("image/jpeg"), pic->mimeType());
+    CPPUNIT_ASSERT_EQUAL(String("new image"), pic->description());
+    CPPUNIT_ASSERT_EQUAL(ByteVector("JPEG data"), pic->data());
+  }
+
+  void testReplacePicture()
+  {
+    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 *newpic = new FLAC::Picture();
+    newpic->setType(FLAC::Picture::BackCover);
+    newpic->setWidth(5);
+    newpic->setHeight(6);
+    newpic->setColorDepth(16);
+    newpic->setNumColors(7);
+    newpic->setMimeType("image/jpeg");
+    newpic->setDescription("new image");
+    newpic->setData("JPEG data");
+    f->removePictures();
+    f->addPicture(newpic);
+    f->save();
+
+    f = new FLAC::File(newname.c_str());
+    lst = f->pictureList();
+    CPPUNIT_ASSERT_EQUAL(TagLib::uint(1), lst.size());
+
+    FLAC::Picture *pic = lst[0];
+    CPPUNIT_ASSERT_EQUAL(FLAC::Picture::BackCover, pic->type());
+    CPPUNIT_ASSERT_EQUAL(5, pic->width());
+    CPPUNIT_ASSERT_EQUAL(6, pic->height());
+    CPPUNIT_ASSERT_EQUAL(16, pic->colorDepth());
+    CPPUNIT_ASSERT_EQUAL(7, pic->numColors());
+    CPPUNIT_ASSERT_EQUAL(String("image/jpeg"), pic->mimeType());
+    CPPUNIT_ASSERT_EQUAL(String("new image"), pic->description());
+    CPPUNIT_ASSERT_EQUAL(ByteVector("JPEG data"), pic->data());
+  }
+
+  void testRemoveAllPictures()
+  {
+    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 *newpic = new FLAC::Picture();
+    newpic->setType(FLAC::Picture::BackCover);
+    newpic->setWidth(5);
+    newpic->setHeight(6);
+    newpic->setColorDepth(16);
+    newpic->setNumColors(7);
+    newpic->setMimeType("image/jpeg");
+    newpic->setDescription("new image");
+    newpic->setData("JPEG data");
+    f->removePictures();
+    f->addPicture(newpic);
+    f->save();
+
+    f = new FLAC::File(newname.c_str());
+    lst = f->pictureList();
+    CPPUNIT_ASSERT_EQUAL(TagLib::uint(0), lst.size());
+  }
+
+  void testRepeatedSave()
+  {
+    ScopedFileCopy copy("silence-44-s", ".flac");
+    string newname = copy.fileName();
+
+    FLAC::File *f = new FLAC::File(newname.c_str());
+    Tag *tag = f->tag();
+    CPPUNIT_ASSERT_EQUAL(String("Silence"), tag->title());
+    tag->setTitle("NEW TITLE");
+    f->save();
+    CPPUNIT_ASSERT_EQUAL(String("NEW TITLE"), tag->title());
+    tag->setTitle("NEW TITLE 2");
+    f->save();
+    CPPUNIT_ASSERT_EQUAL(String("NEW TITLE 2"), tag->title());
+
+    f = new FLAC::File(newname.c_str());
+    tag = f->tag();
+    CPPUNIT_ASSERT_EQUAL(String("NEW TITLE 2"), tag->title());
+  }
+
 };
 
 CPPUNIT_TEST_SUITE_REGISTRATION(TestFLAC);
diff --git a/tests/test_flacmetadatablocks.cpp b/tests/test_flacmetadatablocks.cpp
deleted file mode 100644 (file)
index 59954ca..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-#include <cppunit/extensions/HelperMacros.h>
-#include <string>
-#include <stdio.h>
-#include <tag.h>
-#include <tstringlist.h>
-#include <tbytevectorlist.h>
-#include <flacfile.h>
-#include <flacmetadatablock.h>
-#include <flacmetadatablocks.h>
-#include "utils.h"
-
-using namespace std;
-using namespace TagLib;
-
-class TestFLACMetadataBlocks : public CppUnit::TestFixture
-{
-  CPPUNIT_TEST_SUITE(TestFLACMetadataBlocks);
-  CPPUNIT_TEST(testRead);
-  CPPUNIT_TEST_SUITE_END();
-
-public:
-
-  void testRead()
-  {
-    FLAC::File f("data/silence-44-s.flac");
-    FLAC::MetadataBlocks b;
-    f.seek(4);
-    b.read(&f);
-    List<FLAC::MetadataBlock *> blocks = b.metadataBlockList();
-    CPPUNIT_ASSERT_EQUAL(TagLib::uint(5), blocks.size());
-    CPPUNIT_ASSERT_EQUAL(0 + FLAC::MetadataBlock::StreamInfo, blocks[0]->code());
-    CPPUNIT_ASSERT_EQUAL(0 + FLAC::MetadataBlock::SeekTable, blocks[1]->code());
-    CPPUNIT_ASSERT_EQUAL(0 + FLAC::MetadataBlock::VorbisComment, blocks[2]->code());
-    CPPUNIT_ASSERT_EQUAL(0 + FLAC::MetadataBlock::CueSheet, blocks[3]->code());
-    CPPUNIT_ASSERT_EQUAL(0 + FLAC::MetadataBlock::Picture, blocks[4]->code());
-  }
-
-};
-
-CPPUNIT_TEST_SUITE_REGISTRATION(TestFLACMetadataBlocks);
-
index 180455cf0938ddbffeb70d7a5860f48b7c37c600..5ed13951b0b71c8f2692ad9377a7fd1d955bdb67 100644 (file)
@@ -6,7 +6,6 @@
 #include <tbytevectorlist.h>
 #include <flacfile.h>
 #include <flacmetadatablock.h>
-#include <flacmetadatablocks.h>
 #include "utils.h"
 
 using namespace std;