diff --git a/CMakeLists.txt b/CMakeLists.txt index 5294fae6..723b2b7a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,6 +45,19 @@ SET(TAGLIB_LIB_PATCH_VERSION "0") SET(TAGLIB_LIB_VERSION_STRING "${TAGLIB_LIB_MAJOR_VERSION}.${TAGLIB_LIB_MINOR_VERSION}.${TAGLIB_LIB_PATCH_VERSION}") +# 1. If the library source code has changed at all since the last update, then increment revision. +# 2. If any interfaces have been added, removed, or changed since the last update, increment current, and set revision to 0. +# 3. If any interfaces have been added since the last public release, then increment age. +# 4. If any interfaces have been removed since the last public release, then set age to 0. +SET(TAGLIB_SOVERSION_CURRENT 11) +SET(TAGLIB_SOVERSION_REVISION 0) +SET(TAGLIB_SOVERSION_AGE 10) + +MATH(EXPR TAGLIB_SOVERSION_MAJOR "${TAGLIB_SOVERSION_CURRENT} - ${TAGLIB_SOVERSION_AGE}") +MATH(EXPR TAGLIB_SOVERSION_MINOR "${TAGLIB_SOVERSION_AGE}") +MATH(EXPR TAGLIB_SOVERSION_PATCH "${TAGLIB_SOVERSION_REVISION}") + + include(ConfigureChecks.cmake) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/taglib-config.cmake ${CMAKE_CURRENT_BINARY_DIR}/taglib-config ) diff --git a/NEWS b/NEWS index 71a84c7f..5a9603a6 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,8 @@ +TagLib 1.8 (In Development) +=========================== + + * Added methods for checking if WMA and MP4 files are DRM-protected. + TagLib 1.7 (Mar 11, 2011) ========================= diff --git a/bindings/c/CMakeLists.txt b/bindings/c/CMakeLists.txt index 79c7a6b9..fa4056df 100644 --- a/bindings/c/CMakeLists.txt +++ b/bindings/c/CMakeLists.txt @@ -19,9 +19,11 @@ INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/../../taglib configure_file(${CMAKE_CURRENT_SOURCE_DIR}/taglib_c.pc.cmake ${CMAKE_CURRENT_BINARY_DIR}/taglib_c.pc ) ########### next target ############### -ADD_LIBRARY(tag_c SHARED tag_c.cpp) if(ENABLE_STATIC) + add_library(tag_c STATIC tag_c.cpp) set_target_properties(tag_c PROPERTIES COMPILE_DEFINITIONS TAGLIB_STATIC) +else(ENABLE_STATIC) + add_library(tag_c SHARED tag_c.cpp) endif(ENABLE_STATIC) TARGET_LINK_LIBRARIES(tag_c tag ) diff --git a/taglib/CMakeLists.txt b/taglib/CMakeLists.txt index f050a5c4..23f4796b 100644 --- a/taglib/CMakeLists.txt +++ b/taglib/CMakeLists.txt @@ -204,8 +204,8 @@ if(ZLIB_FOUND) endif(ZLIB_FOUND) SET_TARGET_PROPERTIES(tag PROPERTIES - VERSION ${TAGLIB_LIB_MAJOR_VERSION}.${TAGLIB_LIB_MINOR_VERSION}.${TAGLIB_LIB_PATCH_VERSION} - SOVERSION ${TAGLIB_LIB_MAJOR_VERSION} + VERSION ${TAGLIB_SOVERSION_MAJOR}.${TAGLIB_SOVERSION_MINOR}.${TAGLIB_SOVERSION_PATCH} + SOVERSION ${TAGLIB_SOVERSION_MAJOR} INSTALL_NAME_DIR ${LIB_INSTALL_DIR} DEFINE_SYMBOL MAKE_TAGLIB_LIB LINK_INTERFACE_LIBRARIES "" diff --git a/taglib/asf/asffile.cpp b/taglib/asf/asffile.cpp index e39f856f..734898d4 100644 --- a/taglib/asf/asffile.cpp +++ b/taglib/asf/asffile.cpp @@ -69,6 +69,9 @@ static ByteVector extendedContentDescriptionGuid("\x40\xA4\xD0\xD2\x07\xE3\xD2\x static ByteVector headerExtensionGuid("\xb5\x03\xbf_.\xa9\xcf\x11\x8e\xe3\x00\xc0\x0c Se", 16); static ByteVector metadataGuid("\xEA\xCB\xF8\xC5\xAF[wH\204g\xAA\214D\xFAL\xCA", 16); static ByteVector metadataLibraryGuid("\224\034#D\230\224\321I\241A\x1d\x13NEpT", 16); +static ByteVector contentEncryptionGuid("\xFB\xB3\x11\x22\x23\xBD\xD2\x11\xB4\xB7\x00\xA0\xC9\x55\xFC\x6E", 16); +static ByteVector extendedContentEncryptionGuid("\x14\xE6\x8A\x29\x22\x26 \x17\x4C\xB9\x35\xDA\xE0\x7E\xE9\x28\x9C", 16); +static ByteVector advancedContentEncryptionGuid("\xB6\x9B\x07\x7A\xA4\xDA\x12\x4E\xA5\xCA\x91\xD3\x8D\xC1\x1A\x8D", 16); class ASF::File::BaseObject { @@ -446,6 +449,11 @@ void ASF::File::read(bool /*readProperties*/, Properties::ReadStyle /*properties obj = new HeaderExtensionObject(); } else { + if(guid == contentEncryptionGuid || + guid == extendedContentEncryptionGuid || + guid == advancedContentEncryptionGuid) { + d->properties->setEncrypted(true); + } obj = new UnknownObject(guid); } obj->parse(this, size); diff --git a/taglib/asf/asfproperties.cpp b/taglib/asf/asfproperties.cpp index 02d2d942..6597de13 100644 --- a/taglib/asf/asfproperties.cpp +++ b/taglib/asf/asfproperties.cpp @@ -38,11 +38,12 @@ using namespace TagLib; class ASF::Properties::PropertiesPrivate { public: - PropertiesPrivate(): length(0), bitrate(0), sampleRate(0), channels(0) {} + PropertiesPrivate(): length(0), bitrate(0), sampleRate(0), channels(0), encrypted(false) {} int length; int bitrate; int sampleRate; int channels; + bool encrypted; }; //////////////////////////////////////////////////////////////////////////////// @@ -80,6 +81,11 @@ int ASF::Properties::channels() const return d->channels; } +bool ASF::Properties::isEncrypted() const +{ + return d->encrypted; +} + //////////////////////////////////////////////////////////////////////////////// // private members //////////////////////////////////////////////////////////////////////////////// @@ -104,4 +110,9 @@ void ASF::Properties::setChannels(int length) d->channels = length; } +void ASF::Properties::setEncrypted(bool encrypted) +{ + d->encrypted = encrypted; +} + #endif diff --git a/taglib/asf/asfproperties.h b/taglib/asf/asfproperties.h index 290eac77..ca7b581d 100644 --- a/taglib/asf/asfproperties.h +++ b/taglib/asf/asfproperties.h @@ -54,12 +54,14 @@ namespace TagLib { virtual int bitrate() const; virtual int sampleRate() const; virtual int channels() const; + bool isEncrypted() const; #ifndef DO_NOT_DOCUMENT void setLength(int value); void setBitrate(int value); void setSampleRate(int value); void setChannels(int value); + void setEncrypted(bool value); #endif private: diff --git a/taglib/flac/flacfile.cpp b/taglib/flac/flacfile.cpp index c8cc1fb8..f882ae7b 100644 --- a/taglib/flac/flacfile.cpp +++ b/taglib/flac/flacfile.cpp @@ -149,7 +149,7 @@ bool FLAC::File::save() // Create new vorbis comments - Tag::duplicate(&d->tag, xiphComment(true), true); + Tag::duplicate(&d->tag, xiphComment(true), false); d->xiphCommentData = xiphComment()->render(false); diff --git a/taglib/mp4/mp4atom.cpp b/taglib/mp4/mp4atom.cpp index 26d6d25a..de42d3c4 100644 --- a/taglib/mp4/mp4atom.cpp +++ b/taglib/mp4/mp4atom.cpp @@ -35,9 +35,10 @@ using namespace TagLib; -const char *MP4::Atom::containers[10] = { +const char *MP4::Atom::containers[11] = { "moov", "udta", "mdia", "meta", "ilst", "stbl", "minf", "moof", "traf", "trak", + "stsd" }; MP4::Atom::Atom(File *file) @@ -82,6 +83,9 @@ MP4::Atom::Atom(File *file) if(name == "meta") { file->seek(4, File::Current); } + else if(name == "stsd") { + file->seek(8, File::Current); + } while(file->tell() < offset + length) { MP4::Atom *child = new MP4::Atom(file); children.append(child); diff --git a/taglib/mp4/mp4atom.h b/taglib/mp4/mp4atom.h index 7d9dac28..2c0de3d2 100644 --- a/taglib/mp4/mp4atom.h +++ b/taglib/mp4/mp4atom.h @@ -53,8 +53,8 @@ namespace TagLib { TagLib::ByteVector name; AtomList children; private: - static const int numContainers = 10; - static const char *containers[10]; + static const int numContainers = 11; + static const char *containers[11]; }; //! Root-level atoms diff --git a/taglib/mp4/mp4properties.cpp b/taglib/mp4/mp4properties.cpp index a62bda99..512b66b1 100644 --- a/taglib/mp4/mp4properties.cpp +++ b/taglib/mp4/mp4properties.cpp @@ -40,13 +40,14 @@ using namespace TagLib; class MP4::Properties::PropertiesPrivate { public: - PropertiesPrivate() : length(0), bitrate(0), sampleRate(0), channels(0), bitsPerSample(0) {} + PropertiesPrivate() : length(0), bitrate(0), sampleRate(0), channels(0), bitsPerSample(0), encrypted(false) {} int length; int bitrate; int sampleRate; int channels; int bitsPerSample; + bool encrypted; }; MP4::Properties::Properties(File *file, MP4::Atoms *atoms, ReadStyle style) @@ -129,6 +130,11 @@ MP4::Properties::Properties(File *file, MP4::Atoms *atoms, ReadStyle style) } } } + + MP4::Atom *drms = atom->find("drms"); + if(drms) { + d->encrypted = true; + } } MP4::Properties::~Properties() @@ -166,4 +172,10 @@ MP4::Properties::bitsPerSample() const return d->bitsPerSample; } +bool +MP4::Properties::isEncrypted() const +{ + return d->encrypted; +} + #endif diff --git a/taglib/mp4/mp4properties.h b/taglib/mp4/mp4properties.h index ef813850..7906824d 100644 --- a/taglib/mp4/mp4properties.h +++ b/taglib/mp4/mp4properties.h @@ -48,6 +48,7 @@ namespace TagLib { virtual int sampleRate() const; virtual int channels() const; virtual int bitsPerSample() const; + bool isEncrypted() const; private: class PropertiesPrivate; diff --git a/taglib/toolkit/taglib.h b/taglib/toolkit/taglib.h index 418d6d02..922640d1 100644 --- a/taglib/toolkit/taglib.h +++ b/taglib/toolkit/taglib.h @@ -48,6 +48,7 @@ # include # define TAGLIB_ATOMIC_MAC #elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# define NOMINMAX # include # define TAGLIB_ATOMIC_WIN #elif defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 401) \ diff --git a/tests/test_flac.cpp b/tests/test_flac.cpp index ba3d99da..4b54a7ca 100644 --- a/tests/test_flac.cpp +++ b/tests/test_flac.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "utils.h" using namespace std; @@ -20,6 +21,7 @@ class TestFLAC : public CppUnit::TestFixture CPPUNIT_TEST(testReplacePicture); CPPUNIT_TEST(testRemoveAllPictures); CPPUNIT_TEST(testRepeatedSave); + CPPUNIT_TEST(testSaveMultipleValues); CPPUNIT_TEST_SUITE_END(); public: @@ -186,6 +188,26 @@ public: CPPUNIT_ASSERT_EQUAL(String("NEW TITLE 2"), tag->title()); } + void testSaveMultipleValues() + { + ScopedFileCopy copy("silence-44-s", ".flac", false); + string newname = copy.fileName(); + + FLAC::File *f = new FLAC::File(newname.c_str()); + Ogg::XiphComment* c = f->xiphComment(true); + c->addField("ARTIST", "artist 1", true); + c->addField("ARTIST", "artist 2", false); + f->save(); + delete f; + + f = new FLAC::File(newname.c_str()); + c = f->xiphComment(true); + Ogg::FieldListMap m = c->fieldListMap(); + CPPUNIT_ASSERT_EQUAL(TagLib::uint(2), m["ARTIST"].size()); + CPPUNIT_ASSERT_EQUAL(String("artist 1"), m["ARTIST"][0]); + CPPUNIT_ASSERT_EQUAL(String("artist 2"), m["ARTIST"][1]); + } + }; CPPUNIT_TEST_SUITE_REGISTRATION(TestFLAC);