Read-only support for FLAC picture blocks

CCBUG:218696


git-svn-id: svn://anonsvn.kde.org/home/kde/trunk/kdesupport/taglib@1154376 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
This commit is contained in:
Lukáš Lalinský
2010-07-25 11:06:36 +00:00
parent 0f979667be
commit dcef0fbad2
10 changed files with 434 additions and 4 deletions

View 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

View 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
)

View 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 )

View 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

View 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();
}

View 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 &);

197
taglib/flac/flacpicture.cpp Normal file
View File

@ -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;
}

147
taglib/flac/flacpicture.h Normal file
View File

@ -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

Binary file not shown.

View 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);