From kde-commits Sun Jan 16 11:57:12 2011 From: =?utf-8?q?Luk=C3=A1=C5=A1=20Lalinsk=C3=BD?= Date: Sun, 16 Jan 2011 11:57:12 +0000 To: kde-commits Subject: kdesupport/taglib Message-Id: <20110116115713.052B63E1F1 () svn ! kde ! org> X-MARC-Message: https://marc.info/?l=kde-commits&m=129517906432469 SVN commit 1214788 by lalinsky: Support for ASF embedded pictures Patch by Anton Sergunov CCMAIL: setosha@gmail.com M +1 -0 taglib/CMakeLists.txt M +1 -1 taglib/asf/CMakeLists.txt M +2 -2 taglib/asf/Makefile.am M +33 -3 taglib/asf/asfattribute.cpp M +20 -1 taglib/asf/asfattribute.h M +1 -1 taglib/asf/asffile.cpp M +1 -0 taglib/asf/asffile.h A taglib/asf/asfpicture.cpp [License: LGPL (v2.1) (wrong address)] A taglib/asf/asfpicture.h [License: UNKNOWN] M +4 -0 taglib/taglib.pro M +5 -0 taglib/toolkit/tbytevector.cpp M +11 -0 taglib/toolkit/tbytevector.h M +74 -0 tests/test_asf.cpp M +10 -0 tests/test_bytevector.cpp --- trunk/kdesupport/taglib/taglib/CMakeLists.txt #1214787:1214788 @@ -150,6 +150,7 @@ asf/asffile.cpp asf/asfproperties.cpp asf/asfattribute.cpp +asf/asfpicture.cpp ) ELSE(WITH_ASF) SET(asf_SRCS) --- trunk/kdesupport/taglib/taglib/asf/CMakeLists.txt #1214787:1214788 @@ -1 +1 @@ -INSTALL( FILES asffile.h asfproperties.h asftag.h asfattribute.h DESTINATION ${INCLUDE_INSTALL_DIR}/taglib) +INSTALL( FILES asffile.h asfproperties.h asftag.h asfattribute.h asfpicture.h DESTINATION ${INCLUDE_INSTALL_DIR}/taglib) --- trunk/kdesupport/taglib/taglib/asf/Makefile.am #1214787:1214788 @@ -6,7 +6,7 @@ noinst_LTLIBRARIES = libasf.la -libasf_la_SOURCES = asfattribute.cpp asffile.cpp asfproperties.cpp asftag.cpp +libasf_la_SOURCES = asfattribute.cpp asffile.cpp asfproperties.cpp asftag.cpp asfpicture.cpp -taglib_include_HEADERS = asfattribute.h asffile.h asfproperties.h asftag.h +taglib_include_HEADERS = asfattribute.h asffile.h asfproperties.h asftag.h asfpicture.h taglib_includedir = $(includedir)/taglib --- trunk/kdesupport/taglib/taglib/asf/asfattribute.cpp #1214787:1214788 @@ -40,11 +40,13 @@ { public: AttributePrivate() - : stream(0), + : pictureValue(ASF::Picture::fromInvalid()), + stream(0), language(0) {} AttributeTypes type; String stringValue; ByteVector byteVectorValue; + ASF::Picture pictureValue; union { unsigned int intValue; unsigned short shortValue; @@ -101,6 +103,13 @@ d->byteVectorValue = value; } +ASF::Attribute::Attribute(const ASF::Picture &value) +{ + d = new AttributePrivate; + d->type = BytesType; + d->pictureValue = value; +} + ASF::Attribute::Attribute(unsigned int value) { d = new AttributePrivate; @@ -144,6 +153,8 @@ ByteVector ASF::Attribute::toByteVector() const { + if(d->pictureValue.isValid()) + return d->pictureValue.render(); return d->byteVectorValue; } @@ -171,12 +182,18 @@ return d->longLongValue; } +ASF::Picture +ASF::Attribute::toPicture() const +{ + return d->pictureValue; +} + String ASF::Attribute::parse(ASF::File &f, int kind) { - int size, nameLength; + uint size, nameLength; String name; - + d->pictureValue = Picture::fromInvalid(); // extended content descriptor if(kind == 0) { nameLength = f.readWORD(); @@ -234,6 +251,13 @@ break; } + if(d->type == BytesType && name == "WM/Picture") { + d->pictureValue.parse(d->byteVectorValue); + if(d->pictureValue.isValid()) { + d->byteVectorValue.clear(); + } + } + return name; } @@ -252,6 +276,8 @@ case UnicodeType: return d->stringValue.size() * 2 + 2; case BytesType: + if(d->pictureValue.isValid()) + return d->pictureValue.dataSize(); case GuidType: return d->byteVectorValue.size(); } @@ -290,6 +316,10 @@ break; case BytesType: + if(d->pictureValue.isValid()) { + data.append(d->pictureValue.render()); + break; + } case GuidType: data.append(d->byteVectorValue); break; --- trunk/kdesupport/taglib/taglib/asf/asfattribute.h #1214787:1214788 @@ -29,6 +29,7 @@ #include "tstring.h" #include "tbytevector.h" #include "taglib_export.h" +#include "asfpicture.h" namespace TagLib { @@ -37,6 +38,7 @@ { class File; + class Picture; class TAGLIB_EXPORT Attribute { @@ -71,6 +73,19 @@ Attribute(const ByteVector &value); /*! + * Constructs an attribute with \a key and a Picture \a value. + * + * This attribute is compatible with the ID3 frame, APIC. The ID3 specification for the APIC frame stipulates that, + * while there may be any number of APIC frames associated with a file, + * only one may be of type 1 and only one may be of type 2. + * + * The specification also states that the description of the picture can be no longer than 64 characters, but can be empty. + * WM/Picture attributes added with TagLib::ASF are not automatically validated to conform to ID3 specifications. + * You must add code in your application to perform validations if you want to maintain complete compatibility with ID3. + */ + Attribute(const Picture &value); + + /*! * Constructs an attribute with \a key and a DWordType \a value. */ Attribute(unsigned int value); @@ -141,6 +156,11 @@ ByteVector toByteVector() const; /*! + * Returns the Picture \a value. + */ + Picture toPicture() const; + + /*! * Returns the language number, or 0 is no stream number was set. */ int language() const; @@ -176,7 +196,6 @@ class AttributePrivate; AttributePrivate *d; }; - } } --- trunk/kdesupport/taglib/taglib/asf/asffile.cpp #1214787:1214788 @@ -518,7 +518,7 @@ int ASF::File::readWORD() { ByteVector v = readBlock(2); - return v.toShort(false); + return v.toUShort(false); } unsigned int ASF::File::readDWORD() --- trunk/kdesupport/taglib/taglib/asf/asffile.h #1214787:1214788 @@ -97,6 +97,7 @@ void read(bool readProperties, Properties::ReadStyle propertiesStyle); friend class Attribute; + friend class Picture; class BaseObject; class UnknownObject; --- trunk/kdesupport/taglib/taglib/taglib.pro #1214787:1214788 @@ -63,6 +63,7 @@ ape/apetag.h \ flac/flacfile.h \ flac/flacproperties.h \ + flac/flacpicture.h \ mpc/mpcfile.h \ mpc/mpcproperties.h \ mp4/mp4atom.h \ @@ -124,10 +125,12 @@ asf/asffile.cpp \ asf/asfproperties.cpp \ asf/asftag.cpp \ + asf/asfpicture.cpp \ audioproperties.cpp \ fileref.cpp \ flac/flacfile.cpp \ flac/flacproperties.cpp \ + flac/flacpicture.cpp \ mp4/mp4atom.cpp \ mp4/mp4coverart.cpp \ mp4/mp4file.cpp \ @@ -197,6 +200,7 @@ asf/asffile.h \ asf/asfproperties.h \ asf/asftag.h \ + asf/asfpicture.h \ audioproperties.h \ fileref.h \ flac/flacfile.h \ --- trunk/kdesupport/taglib/taglib/toolkit/tbytevector.cpp #1214787:1214788 @@ -565,6 +565,11 @@ return toNumber(d->data, mostSignificantByteFirst); } +unsigned short ByteVector::toUShort(bool mostSignificantByteFirst) const +{ + return toNumber(d->data, mostSignificantByteFirst); +} + long long ByteVector::toLongLong(bool mostSignificantByteFirst) const { return toNumber(d->data, mostSignificantByteFirst); --- trunk/kdesupport/taglib/taglib/toolkit/tbytevector.h #1214787:1214788 @@ -267,6 +267,17 @@ short toShort(bool mostSignificantByteFirst = true) const; /*! + * Converts the first 2 bytes of the vector to a unsigned short. + * + * If \a mostSignificantByteFirst is true this will operate left to right + * evaluating the integer. For example if \a mostSignificantByteFirst is + * true then $00 $01 == 0x0001 == 1, if false, $01 00 == 0x01000000 == 1. + * + * \see fromShort() + */ + unsigned short toUShort(bool mostSignificantByteFirst = true) const; + + /*! * Converts the first 8 bytes of the vector to a (signed) long long. * * If \a mostSignificantByteFirst is true this will operate left to right --- trunk/kdesupport/taglib/tests/test_asf.cpp #1214787:1214788 @@ -20,6 +20,8 @@ CPPUNIT_TEST(testSaveLanguage); CPPUNIT_TEST(testDWordTrackNumber); CPPUNIT_TEST(testSaveLargeValue); + CPPUNIT_TEST(testSavePicture); + CPPUNIT_TEST(testSaveMultiplePictures); CPPUNIT_TEST_SUITE_END(); public: @@ -141,6 +143,78 @@ delete f; } + void testSavePicture() + { + ScopedFileCopy copy("silence-1", ".wma"); + string newname = copy.fileName(); + + ASF::File *f = new ASF::File(newname.c_str()); + ASF::AttributeList values; + ASF::Picture picture; + picture.setMimeType("image/jpeg"); + picture.setType(ASF::Picture::FrontCover); + picture.setDescription("description"); + picture.setPicture("data"); + ASF::Attribute attr(picture); + values.append(attr); + f->tag()->attributeListMap()["WM/Picture"] = values; + f->save(); + delete f; + + f = new ASF::File(newname.c_str()); + ASF::AttributeList values2 = f->tag()->attributeListMap()["WM/Picture"]; + CPPUNIT_ASSERT_EQUAL(TagLib::uint(1), values2.size()); + ASF::Attribute attr2 = values2.front(); + ASF::Picture picture2 = attr2.toPicture(); + CPPUNIT_ASSERT(picture2.isValid()); + CPPUNIT_ASSERT_EQUAL(String("image/jpeg"), picture2.mimeType()); + CPPUNIT_ASSERT_EQUAL(ASF::Picture::FrontCover, picture2.type()); + CPPUNIT_ASSERT_EQUAL(String("description"), picture2.description()); + CPPUNIT_ASSERT_EQUAL(ByteVector("data"), picture2.picture()); + delete f; + } + + void testSaveMultiplePictures() + { + ScopedFileCopy copy("silence-1", ".wma"); + string newname = copy.fileName(); + + ASF::File *f = new ASF::File(newname.c_str()); + ASF::AttributeList values; + ASF::Picture picture; + picture.setMimeType("image/jpeg"); + picture.setType(ASF::Picture::FrontCover); + picture.setDescription("description"); + picture.setPicture("data"); + values.append(ASF::Attribute(picture)); + ASF::Picture picture2; + picture2.setMimeType("image/png"); + picture2.setType(ASF::Picture::BackCover); + picture2.setDescription("back cover"); + picture2.setPicture("PNG data"); + values.append(ASF::Attribute(picture2)); + f->tag()->attributeListMap()["WM/Picture"] = values; + f->save(); + delete f; + + f = new ASF::File(newname.c_str()); + ASF::AttributeList values2 = f->tag()->attributeListMap()["WM/Picture"]; + CPPUNIT_ASSERT_EQUAL(TagLib::uint(2), values2.size()); + ASF::Picture picture3 = values2[1].toPicture(); + CPPUNIT_ASSERT(picture3.isValid()); + CPPUNIT_ASSERT_EQUAL(String("image/jpeg"), picture3.mimeType()); + CPPUNIT_ASSERT_EQUAL(ASF::Picture::FrontCover, picture3.type()); + CPPUNIT_ASSERT_EQUAL(String("description"), picture3.description()); + CPPUNIT_ASSERT_EQUAL(ByteVector("data"), picture3.picture()); + ASF::Picture picture4 = values2[0].toPicture(); + CPPUNIT_ASSERT(picture4.isValid()); + CPPUNIT_ASSERT_EQUAL(String("image/png"), picture4.mimeType()); + CPPUNIT_ASSERT_EQUAL(ASF::Picture::BackCover, picture4.type()); + CPPUNIT_ASSERT_EQUAL(String("back cover"), picture4.description()); + CPPUNIT_ASSERT_EQUAL(ByteVector("PNG data"), picture4.picture()); + delete f; + } + }; CPPUNIT_TEST_SUITE_REGISTRATION(TestASF); --- trunk/kdesupport/taglib/tests/test_bytevector.cpp #1214787:1214788 @@ -38,6 +38,7 @@ CPPUNIT_TEST(testRfind1); CPPUNIT_TEST(testRfind2); CPPUNIT_TEST(testToHex); + CPPUNIT_TEST(testToUShort); CPPUNIT_TEST_SUITE_END(); public: @@ -181,6 +182,15 @@ CPPUNIT_ASSERT_EQUAL(ByteVector("f0e1d2c3b4a5968778695a4b3c2d1e0f"), v.toHex()); } + void testToUShort() + { + CPPUNIT_ASSERT_EQUAL((unsigned short)0xFFFF, ByteVector("\xff\xff", 2).toUShort()); + CPPUNIT_ASSERT_EQUAL((unsigned short)0x0001, ByteVector("\x00\x01", 2).toUShort()); + CPPUNIT_ASSERT_EQUAL((unsigned short)0x0100, ByteVector("\x00\x01", 2).toUShort(false)); + CPPUNIT_ASSERT_EQUAL((unsigned short)0xFF01, ByteVector("\xFF\x01", 2).toUShort()); + CPPUNIT_ASSERT_EQUAL((unsigned short)0x01FF, ByteVector("\xFF\x01", 2).toUShort(false)); + } + }; CPPUNIT_TEST_SUITE_REGISTRATION(TestByteVector);