flac/flacpicture.cpp
flac/flacproperties.cpp
flac/flacmetadatablock.cpp
-flac/flacmetadatablocks.cpp
flac/flacunknownmetadatablock.cpp
)
#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
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;
}
Properties *properties;
ByteVector streamInfoData;
ByteVector xiphCommentData;
- List<Picture *> pictureList;
+ List<MetadataBlock *> blocks;
long flacStart;
long streamStart;
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
// 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
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()) {
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;
}
+++ /dev/null
-/**************************************************************************
- 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;
-}
-
+++ /dev/null
-/**************************************************************************
- 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
{
public:
PicturePrivate() :
- type(ID3v2::AttachedPictureFrame::Other),
+ type(FLAC::Picture::Other),
width(0),
height(0),
colorDepth(0),
}
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;
#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 {
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);
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:
return false;
}
- if(!isValid())
+ if(!isValid()) {
+ debug("MP4::File::save() -- Trying to save invalid file.");
return false;
+ }
return d->tag->save();
}
test_oggflac.cpp
test_flac.cpp
test_flacpicture.cpp
- test_flacmetadatablocks.cpp
test_flacunknownmetadatablock.cpp
test_ape.cpp
test_apetag.cpp
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:
delete f;
}
- void testPicture()
+ void testReadPicture()
{
ScopedFileCopy copy("silence-44-s", ".flac");
string newname = copy.fileName();
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());
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);
+++ /dev/null
-#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);
-
#include <tbytevectorlist.h>
#include <flacfile.h>
#include <flacmetadatablock.h>
-#include <flacmetadatablocks.h>
#include "utils.h"
using namespace std;