mirror of
https://github.com/taglib/taglib.git
synced 2025-07-18 21:14:23 -04:00
Add FLAC::Picture support to Xiph Comment
This commit is contained in:
@ -26,17 +26,22 @@
|
||||
#include <tbytevector.h>
|
||||
#include <tdebug.h>
|
||||
|
||||
#include <flacpicture.h>
|
||||
#include <xiphcomment.h>
|
||||
#include <tpropertymap.h>
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
|
||||
typedef List<FLAC::Picture*> PictureList;
|
||||
|
||||
class Ogg::XiphComment::XiphCommentPrivate
|
||||
{
|
||||
public:
|
||||
FieldListMap fieldListMap;
|
||||
String vendorID;
|
||||
String commentField;
|
||||
PictureList pictureList;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -181,6 +186,8 @@ TagLib::uint Ogg::XiphComment::fieldCount() const
|
||||
for(; it != d->fieldListMap.end(); ++it)
|
||||
count += (*it).second.size();
|
||||
|
||||
count += d->pictureList.size();
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
@ -275,6 +282,36 @@ bool Ogg::XiphComment::contains(const String &key) const
|
||||
return d->fieldListMap.contains(key) && !d->fieldListMap[key].isEmpty();
|
||||
}
|
||||
|
||||
void Ogg::XiphComment::removePicture(FLAC::Picture *picture, bool del)
|
||||
{
|
||||
List<FLAC::Picture *>::Iterator it = d->pictureList.find(picture);
|
||||
if(it != d->pictureList.end())
|
||||
d->pictureList.erase(it);
|
||||
|
||||
if(del)
|
||||
delete picture;
|
||||
}
|
||||
|
||||
void Ogg::XiphComment::removePictures()
|
||||
{
|
||||
PictureList newList;
|
||||
for(uint i = 0; i < d->pictureList.size(); i++) {
|
||||
delete d->pictureList[i];
|
||||
}
|
||||
d->pictureList = newList;
|
||||
}
|
||||
|
||||
void Ogg::XiphComment::addPicture(FLAC::Picture * picture)
|
||||
{
|
||||
d->pictureList.append(picture);
|
||||
}
|
||||
|
||||
|
||||
List<FLAC::Picture *> Ogg::XiphComment::pictureList()
|
||||
{
|
||||
return d->pictureList;
|
||||
}
|
||||
|
||||
ByteVector Ogg::XiphComment::render() const
|
||||
{
|
||||
return render(true);
|
||||
@ -321,6 +358,13 @@ ByteVector Ogg::XiphComment::render(bool addFramingBit) const
|
||||
}
|
||||
}
|
||||
|
||||
for(PictureList::ConstIterator it = d->pictureList.begin(); it != d->pictureList.end(); ++it) {
|
||||
ByteVector picture = (*it)->render().toBase64();
|
||||
data.append(ByteVector::fromUInt(picture.size()+23,false));
|
||||
data.append("METADATA_BLOCK_PICTURE=");
|
||||
data.append(picture);
|
||||
}
|
||||
|
||||
// Append the "framing bit".
|
||||
|
||||
if(addFramingBit)
|
||||
@ -363,20 +407,41 @@ void Ogg::XiphComment::parse(const ByteVector &data)
|
||||
const uint commentLength = data.toUInt(pos, false);
|
||||
pos += 4;
|
||||
|
||||
String comment = String(data.mid(pos, commentLength), String::UTF8);
|
||||
pos += commentLength;
|
||||
if(pos > data.size()) {
|
||||
ByteVector entry = data.mid(pos, commentLength);
|
||||
|
||||
// Don't go past data end
|
||||
pos+=commentLength;
|
||||
if (pos>data.size())
|
||||
break;
|
||||
|
||||
// Handle Pictures separately
|
||||
if(entry.startsWith("METADATA_BLOCK_PICTURE=")) {
|
||||
|
||||
// Decode base64 picture data
|
||||
ByteVector picturedata = entry.mid(23, entry.size()-23).fromBase64();
|
||||
|
||||
if(picturedata.size()==0) {
|
||||
debug("Empty picture data. Discarding content");
|
||||
continue;
|
||||
}
|
||||
|
||||
FLAC::Picture * picture = new FLAC::Picture();
|
||||
if(picture->parse(picturedata))
|
||||
d->pictureList.append(picture);
|
||||
else
|
||||
debug("Unable to parse METADATA_BLOCK_PICTURE. Discarding content.");
|
||||
}
|
||||
else {
|
||||
|
||||
int commentSeparatorPosition = comment.find("=");
|
||||
if(commentSeparatorPosition == -1) {
|
||||
break;
|
||||
// Check for field separator
|
||||
int sep = entry.find('=');
|
||||
if (sep == -1)
|
||||
break;
|
||||
|
||||
// Parse key and value
|
||||
String key = String(entry.mid(0,sep), String::UTF8);
|
||||
String value = String(entry.mid(sep+1, commentLength-sep), String::UTF8);
|
||||
addField(key, value, false);
|
||||
}
|
||||
|
||||
String key = comment.substr(0, commentSeparatorPosition);
|
||||
String value = comment.substr(commentSeparatorPosition + 1);
|
||||
|
||||
addField(key, value, false);
|
||||
}
|
||||
}
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "tstring.h"
|
||||
#include "tstringlist.h"
|
||||
#include "tbytevector.h"
|
||||
#include "flacpicture.h"
|
||||
#include "taglib_export.h"
|
||||
|
||||
namespace TagLib {
|
||||
@ -205,6 +206,31 @@ namespace TagLib {
|
||||
*/
|
||||
ByteVector render(bool addFramingBit) const;
|
||||
|
||||
|
||||
/*!
|
||||
* Returns a list of pictures attached to the xiph comment.
|
||||
*/
|
||||
List<FLAC::Picture *> pictureList();
|
||||
|
||||
/*!
|
||||
* Removes an picture. If \a del is true the picture's memory
|
||||
* will be freed; if it is false, it must be deleted by the user.
|
||||
*/
|
||||
void removePicture(FLAC::Picture *picture, bool del = true);
|
||||
|
||||
/*!
|
||||
* Remove all pictures.
|
||||
*/
|
||||
void removePictures();
|
||||
|
||||
/*!
|
||||
* Add a new picture to the comment block. The comment block takes ownership of the
|
||||
* picture and will handle freeing its memory.
|
||||
*
|
||||
* \note The file will be saved only after calling save().
|
||||
*/
|
||||
void addPicture(FLAC::Picture *picture);
|
||||
|
||||
protected:
|
||||
/*!
|
||||
* Reads the tag from the file specified in the constructor and fills the
|
||||
|
@ -21,6 +21,7 @@ class TestOGG : public CppUnit::TestFixture
|
||||
CPPUNIT_TEST(testDictInterface1);
|
||||
CPPUNIT_TEST(testDictInterface2);
|
||||
CPPUNIT_TEST(testAudioProperties);
|
||||
CPPUNIT_TEST(testPicture);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
@ -134,6 +135,33 @@ public:
|
||||
CPPUNIT_ASSERT_EQUAL(112000, f.audioProperties()->bitrateNominal());
|
||||
CPPUNIT_ASSERT_EQUAL(0, f.audioProperties()->bitrateMinimum());
|
||||
}
|
||||
|
||||
void testPicture()
|
||||
{
|
||||
ScopedFileCopy copy("empty", ".ogg");
|
||||
string newname = copy.fileName();
|
||||
|
||||
Vorbis::File *f = new Vorbis::File(newname.c_str());
|
||||
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->tag()->addPicture(newpic);
|
||||
f->save();
|
||||
delete f;
|
||||
|
||||
f = new Vorbis::File(newname.c_str());
|
||||
List<FLAC::Picture *> lst = f->tag()->pictureList();
|
||||
CPPUNIT_ASSERT_EQUAL(TagLib::uint(1), lst.size());
|
||||
delete f;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(TestOGG);
|
||||
|
Reference in New Issue
Block a user