mirror of
https://github.com/taglib/taglib.git
synced 2026-06-07 14:59:24 -04:00
Compare commits
28 Commits
v1.11beta2
...
v1.11.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e36a9cabb9 | ||
|
|
597dcde72a | ||
|
|
6a96a6426a | ||
|
|
69c65284a5 | ||
|
|
97aaa0f979 | ||
|
|
0dac721ce2 | ||
|
|
bbeeca6fdb | ||
|
|
7e90313690 | ||
|
|
1d3c95f692 | ||
|
|
8c3801f18d | ||
|
|
c9bdd416ef | ||
|
|
9f28e037fe | ||
|
|
92c070ba9e | ||
|
|
75e3ec73aa | ||
|
|
3e47a036fb | ||
|
|
9b995544e4 | ||
|
|
d8e5077961 | ||
|
|
6422054540 | ||
|
|
1b878102f0 | ||
|
|
0a85f9b227 | ||
|
|
31f3109b47 | ||
|
|
76f8ff388f | ||
|
|
7627ae48ed | ||
|
|
b2a6768704 | ||
|
|
7d270a7e20 | ||
|
|
bf53dc6131 | ||
|
|
ff8b6a91e7 | ||
|
|
1a82419872 |
4
AUTHORS
4
AUTHORS
@@ -2,6 +2,8 @@ Scott Wheeler <wheeler@kde.org>
|
||||
Author, maintainer
|
||||
Lukas Lalinsky <lalinsky@gmail.com>
|
||||
Implementation of multiple new file formats, many bug fixes, maintainer
|
||||
Tsuda Kageyu <tsuda.kageyu@gmail.com>
|
||||
A lot of bug fixes and performance improvements, maintainer.
|
||||
Ismael Orenstein <orenstein@kde.org>
|
||||
Xing header implementation
|
||||
Allan Sandfeld Jensen <kde@carewolf.org>
|
||||
@@ -10,8 +12,6 @@ Teemu Tervo <teemu.tervo@gmx.net>
|
||||
Numerous bug reports and fixes
|
||||
Mathias Panzenböck <grosser.meister.morti@gmx.net>
|
||||
Mod, S3M, IT and XM metadata implementations
|
||||
Tsuda Kageyu <tsuda.kageyu@gmail.com>
|
||||
A lot of fixes and improvements, i.e. memory copy reduction etc.
|
||||
|
||||
Please send all patches and questions to taglib-devel@kde.org rather than to
|
||||
individual developers!
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
project(taglib)
|
||||
|
||||
cmake_minimum_required(VERSION 2.8.0 FATAL_ERROR)
|
||||
|
||||
project(taglib)
|
||||
|
||||
if(NOT ${CMAKE_VERSION} VERSION_LESS 2.8.12)
|
||||
cmake_policy(SET CMP0022 OLD)
|
||||
endif()
|
||||
@@ -12,6 +12,7 @@ if(DEFINED ENABLE_STATIC)
|
||||
message(FATAL_ERROR "This option is no longer available, use BUILD_SHARED_LIBS instead")
|
||||
endif()
|
||||
|
||||
option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
|
||||
if(NOT BUILD_SHARED_LIBS)
|
||||
add_definitions(-DTAGLIB_STATIC)
|
||||
endif()
|
||||
@@ -89,9 +90,9 @@ endif()
|
||||
# 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 17)
|
||||
set(TAGLIB_SOVERSION_CURRENT 18)
|
||||
set(TAGLIB_SOVERSION_REVISION 0)
|
||||
set(TAGLIB_SOVERSION_AGE 16)
|
||||
set(TAGLIB_SOVERSION_AGE 17)
|
||||
|
||||
math(EXPR TAGLIB_SOVERSION_MAJOR "${TAGLIB_SOVERSION_CURRENT} - ${TAGLIB_SOVERSION_AGE}")
|
||||
math(EXPR TAGLIB_SOVERSION_MINOR "${TAGLIB_SOVERSION_AGE}")
|
||||
|
||||
16
NEWS
16
NEWS
@@ -1,5 +1,17 @@
|
||||
TagLib 1.11 (Mar 4, 2016)
|
||||
=========================
|
||||
TagLib 1.11.1 (Oct 24, 2016)
|
||||
============================
|
||||
|
||||
* Fixed binary incompatible change in TagLib::String.
|
||||
* Fixed reading ID3v2 CTOC frames with a lot of entries.
|
||||
* Fixed seeking ByteVectorStream from the end.
|
||||
|
||||
TagLib 1.11 (Apr 29, 2016)
|
||||
==========================
|
||||
|
||||
1.11:
|
||||
|
||||
* Fixed reading APE items with long keys.
|
||||
* Fixed reading ID3v2 SYLT frames when description is empty.
|
||||
|
||||
1.11 BETA 2:
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ TAGLIB_C_EXPORT TagLib_File *taglib_file_new_type(const char *filename, TagLib_F
|
||||
TAGLIB_C_EXPORT void taglib_file_free(TagLib_File *file);
|
||||
|
||||
/*!
|
||||
* Returns true if the file is open and readble and valid information for
|
||||
* Returns true if the file is open and readable and valid information for
|
||||
* the Tag and / or AudioProperties was found.
|
||||
*/
|
||||
|
||||
@@ -137,7 +137,7 @@ TAGLIB_C_EXPORT BOOL taglib_file_is_valid(const TagLib_File *file);
|
||||
TAGLIB_C_EXPORT TagLib_Tag *taglib_file_tag(const TagLib_File *file);
|
||||
|
||||
/*!
|
||||
* Returns a pointer to the the audio properties associated with this file. This
|
||||
* Returns a pointer to the audio properties associated with this file. This
|
||||
* will be freed automatically when the file is freed.
|
||||
*/
|
||||
TAGLIB_C_EXPORT const TagLib_AudioProperties *taglib_file_audioproperties(const TagLib_File *file);
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace
|
||||
{
|
||||
const char *invalidKeys[] = { "ID3", "TAG", "OGGS", "MP+", 0 };
|
||||
|
||||
if(length < 2 || length > 16)
|
||||
if(length < 2 || length > 255)
|
||||
return false;
|
||||
|
||||
// only allow printable ASCII including space (32..126)
|
||||
|
||||
@@ -198,7 +198,7 @@ String ChapterFrame::toString() const
|
||||
s += ", start offset: " + String::number(d->startOffset);
|
||||
|
||||
if(d->endOffset != 0xFFFFFFFF)
|
||||
s += ", start offset: " + String::number(d->endOffset);
|
||||
s += ", end offset: " + String::number(d->endOffset);
|
||||
|
||||
if(!d->embeddedFrameList.isEmpty()) {
|
||||
StringList frameIDs;
|
||||
|
||||
@@ -158,7 +158,7 @@ void SynchronizedLyricsFrame::parseFields(const ByteVector &data)
|
||||
int pos = 6;
|
||||
|
||||
d->description = readStringField(data, d->textEncoding, &pos);
|
||||
if(d->description.isEmpty())
|
||||
if(pos == 6)
|
||||
return;
|
||||
|
||||
/*
|
||||
|
||||
@@ -272,9 +272,9 @@ void TableOfContentsFrame::parseFields(const ByteVector &data)
|
||||
int pos = 0;
|
||||
unsigned int embPos = 0;
|
||||
d->elementID = readStringField(data, String::Latin1, &pos).data(String::Latin1);
|
||||
d->isTopLevel = (data.at(pos) & 2) > 0;
|
||||
d->isOrdered = (data.at(pos++) & 1) > 0;
|
||||
unsigned int entryCount = data.at(pos++);
|
||||
d->isTopLevel = (data.at(pos) & 2) != 0;
|
||||
d->isOrdered = (data.at(pos++) & 1) != 0;
|
||||
unsigned int entryCount = static_cast<unsigned char>(data.at(pos++));
|
||||
for(unsigned int i = 0; i < entryCount; i++) {
|
||||
ByteVector childElementID = readStringField(data, String::Latin1, &pos).data(String::Latin1);
|
||||
d->childElements.append(childElementID);
|
||||
|
||||
@@ -102,13 +102,14 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
FrameFactory FrameFactory::factory;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FrameFactory *FrameFactory::instance()
|
||||
{
|
||||
static FrameFactory factory;
|
||||
return &factory;
|
||||
}
|
||||
|
||||
@@ -538,4 +539,3 @@ bool FrameFactory::updateFrame(Frame::Header *header) const
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,6 @@ namespace TagLib {
|
||||
{
|
||||
public:
|
||||
static FrameFactory *instance();
|
||||
|
||||
/*!
|
||||
* Create a frame based on \a data. \a synchSafeInts should only be set
|
||||
* false if we are parsing an old tag (v2.3 or older) that does not support
|
||||
@@ -153,6 +152,8 @@ namespace TagLib {
|
||||
FrameFactory(const FrameFactory &);
|
||||
FrameFactory &operator=(const FrameFactory &);
|
||||
|
||||
static FrameFactory factory;
|
||||
|
||||
class FrameFactoryPrivate;
|
||||
FrameFactoryPrivate *d;
|
||||
};
|
||||
|
||||
@@ -30,9 +30,9 @@
|
||||
|
||||
#define TAGLIB_MAJOR_VERSION 1
|
||||
#define TAGLIB_MINOR_VERSION 11
|
||||
#define TAGLIB_PATCH_VERSION 0
|
||||
#define TAGLIB_PATCH_VERSION 1
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 1))
|
||||
#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 1)) || defined(__clang__)
|
||||
#define TAGLIB_IGNORE_MISSING_DESTRUCTOR _Pragma("GCC diagnostic ignored \"-Wnon-virtual-dtor\"")
|
||||
#else
|
||||
#define TAGLIB_IGNORE_MISSING_DESTRUCTOR
|
||||
|
||||
@@ -137,7 +137,7 @@ void ByteVectorStream::seek(long offset, Position p)
|
||||
d->position += offset;
|
||||
break;
|
||||
case End:
|
||||
d->position = length() - offset;
|
||||
d->position = length() + offset; // offset is expected to be negative
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -787,6 +787,12 @@ void String::detach()
|
||||
if(d->count() > 1)
|
||||
String(d->data.c_str()).swap(*this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const String::Type String::WCharByteOrder = wcharByteOrder();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -536,6 +536,13 @@ namespace TagLib {
|
||||
void detach();
|
||||
|
||||
private:
|
||||
/*!
|
||||
* \deprecated This variable is no longer used, but NEVER remove this. It
|
||||
* may lead to a linkage error.
|
||||
*/
|
||||
// BIC: remove
|
||||
static const Type WCharByteOrder;
|
||||
|
||||
class StringPrivate;
|
||||
StringPrivate *d;
|
||||
};
|
||||
|
||||
Binary file not shown.
BIN
tests/data/toc_many_children.mp3
Normal file
BIN
tests/data/toc_many_children.mp3
Normal file
Binary file not shown.
@@ -38,6 +38,7 @@ class TestByteVectorStream : public CppUnit::TestFixture
|
||||
CPPUNIT_TEST(testReadBlock);
|
||||
CPPUNIT_TEST(testRemoveBlock);
|
||||
CPPUNIT_TEST(testInsert);
|
||||
CPPUNIT_TEST(testSeekEnd);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
@@ -112,6 +113,19 @@ public:
|
||||
CPPUNIT_ASSERT_EQUAL(ByteVector("yyx123foa"), *stream.data());
|
||||
}
|
||||
|
||||
void testSeekEnd()
|
||||
{
|
||||
ByteVector v("abcdefghijklmnopqrstuvwxyz");
|
||||
ByteVectorStream stream(v);
|
||||
CPPUNIT_ASSERT_EQUAL(26L, stream.length());
|
||||
|
||||
stream.seek(-4, IOStream::End);
|
||||
CPPUNIT_ASSERT_EQUAL(ByteVector("w"), stream.readBlock(1));
|
||||
|
||||
stream.seek(-25, IOStream::End);
|
||||
CPPUNIT_ASSERT_EQUAL(ByteVector("b"), stream.readBlock(1));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(TestByteVectorStream);
|
||||
|
||||
@@ -94,6 +94,7 @@ class TestID3v2 : public CppUnit::TestFixture
|
||||
CPPUNIT_TEST(testParseOwnershipFrame);
|
||||
CPPUNIT_TEST(testRenderOwnershipFrame);
|
||||
CPPUNIT_TEST(testParseSynchronizedLyricsFrame);
|
||||
CPPUNIT_TEST(testParseSynchronizedLyricsFrameWithEmptyDescritpion);
|
||||
CPPUNIT_TEST(testRenderSynchronizedLyricsFrame);
|
||||
CPPUNIT_TEST(testParseEventTimingCodesFrame);
|
||||
CPPUNIT_TEST(testRenderEventTimingCodesFrame);
|
||||
@@ -117,6 +118,7 @@ class TestID3v2 : public CppUnit::TestFixture
|
||||
CPPUNIT_TEST(testShrinkPadding);
|
||||
CPPUNIT_TEST(testEmptyFrame);
|
||||
CPPUNIT_TEST(testDuplicateTags);
|
||||
CPPUNIT_TEST(testParseTOCFrameWithManyChildren);
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
public:
|
||||
@@ -248,7 +250,7 @@ public:
|
||||
"d\x00"
|
||||
"\x00", 14);
|
||||
ID3v2::AttachedPictureFrame *frame =
|
||||
static_cast<TagLib::ID3v2::AttachedPictureFrame*>(factory->createFrame(data, (unsigned int)2));
|
||||
dynamic_cast<TagLib::ID3v2::AttachedPictureFrame*>(factory->createFrame(data, (unsigned int)2));
|
||||
|
||||
CPPUNIT_ASSERT(frame);
|
||||
CPPUNIT_ASSERT_EQUAL(String("image/jpeg"), frame->mimeType());
|
||||
@@ -268,8 +270,8 @@ public:
|
||||
"\x01"
|
||||
"d\x00"
|
||||
"\x00", 14);
|
||||
ID3v2::AttachedPictureFrame *frame =
|
||||
static_cast<TagLib::ID3v2::AttachedPictureFrame*>(factory->createFrame(data, (unsigned int)2));
|
||||
ID3v2::UnknownFrame *frame =
|
||||
dynamic_cast<TagLib::ID3v2::UnknownFrame*>(factory->createFrame(data, (unsigned int)2));
|
||||
|
||||
CPPUNIT_ASSERT(frame);
|
||||
|
||||
@@ -527,6 +529,35 @@ public:
|
||||
CPPUNIT_ASSERT_EQUAL((unsigned int)4567, stl[1].time);
|
||||
}
|
||||
|
||||
void testParseSynchronizedLyricsFrameWithEmptyDescritpion()
|
||||
{
|
||||
ID3v2::SynchronizedLyricsFrame f(
|
||||
ByteVector("SYLT" // Frame ID
|
||||
"\x00\x00\x00\x21" // Frame size
|
||||
"\x00\x00" // Frame flags
|
||||
"\x00" // Text encoding
|
||||
"eng" // Language
|
||||
"\x02" // Time stamp format
|
||||
"\x01" // Content type
|
||||
"\x00" // Content descriptor
|
||||
"Example\x00" // 1st text
|
||||
"\x00\x00\x04\xd2" // 1st time stamp
|
||||
"Lyrics\x00" // 2nd text
|
||||
"\x00\x00\x11\xd7", 40)); // 2nd time stamp
|
||||
CPPUNIT_ASSERT_EQUAL(String::Latin1, f.textEncoding());
|
||||
CPPUNIT_ASSERT_EQUAL(ByteVector("eng", 3), f.language());
|
||||
CPPUNIT_ASSERT_EQUAL(ID3v2::SynchronizedLyricsFrame::AbsoluteMilliseconds,
|
||||
f.timestampFormat());
|
||||
CPPUNIT_ASSERT_EQUAL(ID3v2::SynchronizedLyricsFrame::Lyrics, f.type());
|
||||
CPPUNIT_ASSERT(f.description().isEmpty());
|
||||
ID3v2::SynchronizedLyricsFrame::SynchedTextList stl = f.synchedText();
|
||||
CPPUNIT_ASSERT_EQUAL((unsigned int)2, stl.size());
|
||||
CPPUNIT_ASSERT_EQUAL(String("Example"), stl[0].text);
|
||||
CPPUNIT_ASSERT_EQUAL((unsigned int)1234, stl[0].time);
|
||||
CPPUNIT_ASSERT_EQUAL(String("Lyrics"), stl[1].text);
|
||||
CPPUNIT_ASSERT_EQUAL((unsigned int)4567, stl[1].time);
|
||||
}
|
||||
|
||||
void testRenderSynchronizedLyricsFrame()
|
||||
{
|
||||
ID3v2::SynchronizedLyricsFrame f;
|
||||
@@ -633,7 +664,7 @@ public:
|
||||
"\x00" // Encoding
|
||||
"(22)Death Metal", 26); // Text
|
||||
ID3v2::TextIdentificationFrame *frame =
|
||||
static_cast<TagLib::ID3v2::TextIdentificationFrame*>(factory->createFrame(data, (unsigned int)3));
|
||||
dynamic_cast<TagLib::ID3v2::TextIdentificationFrame*>(factory->createFrame(data, (unsigned int)3));
|
||||
CPPUNIT_ASSERT_EQUAL((unsigned int)1, frame->fieldList().size());
|
||||
CPPUNIT_ASSERT_EQUAL(String("Death Metal"), frame->fieldList()[0]);
|
||||
|
||||
@@ -652,7 +683,7 @@ public:
|
||||
"\x00" // Encoding
|
||||
"(4)Eurodisco", 23); // Text
|
||||
ID3v2::TextIdentificationFrame *frame =
|
||||
static_cast<TagLib::ID3v2::TextIdentificationFrame*>(factory->createFrame(data, (unsigned int)3));
|
||||
dynamic_cast<TagLib::ID3v2::TextIdentificationFrame*>(factory->createFrame(data, (unsigned int)3));
|
||||
CPPUNIT_ASSERT_EQUAL((unsigned int)2, frame->fieldList().size());
|
||||
CPPUNIT_ASSERT_EQUAL(String("4"), frame->fieldList()[0]);
|
||||
CPPUNIT_ASSERT_EQUAL(String("Eurodisco"), frame->fieldList()[1]);
|
||||
@@ -671,7 +702,7 @@ public:
|
||||
"\0" // Encoding
|
||||
"14\0Eurodisco", 23); // Text
|
||||
ID3v2::TextIdentificationFrame *frame =
|
||||
static_cast<TagLib::ID3v2::TextIdentificationFrame*>(factory->createFrame(data, (unsigned int)4));
|
||||
dynamic_cast<TagLib::ID3v2::TextIdentificationFrame*>(factory->createFrame(data, (unsigned int)4));
|
||||
CPPUNIT_ASSERT_EQUAL((unsigned int)2, frame->fieldList().size());
|
||||
CPPUNIT_ASSERT_EQUAL(String("14"), frame->fieldList()[0]);
|
||||
CPPUNIT_ASSERT_EQUAL(String("Eurodisco"), frame->fieldList()[1]);
|
||||
@@ -727,11 +758,11 @@ public:
|
||||
}
|
||||
{
|
||||
MPEG::File bar(newname.c_str());
|
||||
tf = static_cast<ID3v2::TextIdentificationFrame *>(bar.ID3v2Tag()->frameList("TDOR").front());
|
||||
tf = dynamic_cast<ID3v2::TextIdentificationFrame *>(bar.ID3v2Tag()->frameList("TDOR").front());
|
||||
CPPUNIT_ASSERT(tf);
|
||||
CPPUNIT_ASSERT_EQUAL((unsigned int)1, tf->fieldList().size());
|
||||
CPPUNIT_ASSERT_EQUAL(String("2011"), tf->fieldList().front());
|
||||
tf = static_cast<ID3v2::TextIdentificationFrame *>(bar.ID3v2Tag()->frameList("TDRC").front());
|
||||
tf = dynamic_cast<ID3v2::TextIdentificationFrame *>(bar.ID3v2Tag()->frameList("TDRC").front());
|
||||
CPPUNIT_ASSERT(tf);
|
||||
CPPUNIT_ASSERT_EQUAL((unsigned int)1, tf->fieldList().size());
|
||||
CPPUNIT_ASSERT_EQUAL(String("2012-04-17T12:01"), tf->fieldList().front());
|
||||
@@ -1187,6 +1218,12 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void testParseTOCFrameWithManyChildren()
|
||||
{
|
||||
MPEG::File f(TEST_FILE_PATH_C("toc_many_children.mp3"));
|
||||
CPPUNIT_ASSERT(f.isValid());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION(TestID3v2);
|
||||
|
||||
Reference in New Issue
Block a user