mirror of
https://github.com/taglib/taglib.git
synced 2025-11-15 14:12:56 -05:00
Merge branch 'master' into taglib2
Conflicts: tests/test_aiff.cpp tests/test_flac.cpp
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@ -42,3 +42,5 @@ CMakeFiles/
|
||||
/taglib/tag.dir/Release
|
||||
/ALL_BUILD.dir
|
||||
/ZERO_CHECK.dir
|
||||
taglib.xcodeproj
|
||||
CMakeScripts
|
||||
|
||||
@ -36,12 +36,16 @@ using namespace ID3v2;
|
||||
class ChapterFrame::ChapterFramePrivate
|
||||
{
|
||||
public:
|
||||
ChapterFramePrivate()
|
||||
{
|
||||
embeddedFrameList.setAutoDelete(true);
|
||||
}
|
||||
|
||||
ByteVector elementID;
|
||||
uint startTime;
|
||||
uint endTime;
|
||||
uint startOffset;
|
||||
uint endOffset;
|
||||
const FrameFactory *factory;
|
||||
FrameListMap embeddedFrameListMap;
|
||||
FrameList embeddedFrameList;
|
||||
};
|
||||
@ -54,11 +58,11 @@ ChapterFrame::ChapterFrame(const ByteVector &data) :
|
||||
ID3v2::Frame(data)
|
||||
{
|
||||
d = new ChapterFramePrivate;
|
||||
d->factory = FrameFactory::instance();
|
||||
setData(data);
|
||||
}
|
||||
|
||||
ChapterFrame::ChapterFrame(const ByteVector &eID, const uint &sT, const uint &eT, const uint &sO, const uint &eO, const FrameList &eF) :
|
||||
ChapterFrame::ChapterFrame(const ByteVector &eID, const uint &sT, const uint &eT,
|
||||
const uint &sO, const uint &eO, const FrameList &eF) :
|
||||
ID3v2::Frame("CHAP")
|
||||
{
|
||||
d = new ChapterFramePrivate;
|
||||
@ -70,7 +74,6 @@ ChapterFrame::ChapterFrame(const ByteVector &eID, const uint &sT, const uint &eT
|
||||
FrameList l = eF;
|
||||
for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it)
|
||||
addEmbeddedFrame(*it);
|
||||
d->factory = FrameFactory::instance();
|
||||
}
|
||||
|
||||
ChapterFrame::~ChapterFrame()
|
||||
@ -207,7 +210,8 @@ void ChapterFrame::parseFields(const ByteVector &data)
|
||||
{
|
||||
uint size = data.size();
|
||||
if(size < 18) {
|
||||
debug("A CHAP frame must contain at least 18 bytes (1 byte element ID terminated by null and 4x4 bytes for start and end time and offset).");
|
||||
debug("A CHAP frame must contain at least 18 bytes (1 byte element ID "
|
||||
"terminated by null and 4x4 bytes for start and end time and offset).");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -225,7 +229,7 @@ void ChapterFrame::parseFields(const ByteVector &data)
|
||||
size -= pos;
|
||||
while((uint)embPos < size - Frame::headerSize(4))
|
||||
{
|
||||
Frame *frame = d->factory->createFrame(data.mid(pos + embPos));
|
||||
Frame *frame = FrameFactory::instance()->createFrame(data.mid(pos + embPos));
|
||||
|
||||
if(!frame)
|
||||
return;
|
||||
@ -261,6 +265,5 @@ ChapterFrame::ChapterFrame(const ByteVector &data, Header *h) :
|
||||
Frame(h)
|
||||
{
|
||||
d = new ChapterFramePrivate;
|
||||
d->factory = FrameFactory::instance();
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ namespace TagLib {
|
||||
namespace ID3v2 {
|
||||
|
||||
/*!
|
||||
* This is an implementation of ID3v2 chapter frames. The purpose of this
|
||||
* This is an implementation of ID3v2 chapter frames. The purpose of this
|
||||
* frame is to describe a single chapter within an audio file.
|
||||
*/
|
||||
|
||||
@ -56,48 +56,49 @@ namespace TagLib {
|
||||
* start time \a sT, end time \a eT, start offset \a sO,
|
||||
* end offset \a eO and embedded frames, that are in \a eF.
|
||||
*/
|
||||
ChapterFrame(const ByteVector &eID, const uint &sT, const uint &eT, const uint &sO, const uint &eO, const FrameList &eF);
|
||||
ChapterFrame(const ByteVector &eID, const uint &sT, const uint &eT, const uint &sO,
|
||||
const uint &eO, const FrameList &eF);
|
||||
|
||||
/*!
|
||||
* Destroys the frame.
|
||||
*/
|
||||
~ChapterFrame();
|
||||
|
||||
|
||||
/*!
|
||||
* Returns the element ID of the frame. Element ID
|
||||
* is a null terminated string, however it's not human-readable.
|
||||
*
|
||||
*
|
||||
* \see setElementID()
|
||||
*/
|
||||
ByteVector elementID() const;
|
||||
|
||||
|
||||
/*!
|
||||
* Returns time of chapter's start (in miliseconds).
|
||||
*
|
||||
*
|
||||
* \see setStartTime()
|
||||
*/
|
||||
uint startTime() const;
|
||||
|
||||
|
||||
/*!
|
||||
* Returns time of chapter's end (in miliseconds).
|
||||
*
|
||||
*
|
||||
* \see setEndTime()
|
||||
*/
|
||||
uint endTime() const;
|
||||
|
||||
|
||||
/*!
|
||||
* Returns zero based byte offset (count of bytes from the beginning
|
||||
* of the audio file) of chapter's start.
|
||||
*
|
||||
*
|
||||
* \note If returned value is 0xFFFFFFFF, start time should be used instead.
|
||||
* \see setStartOffset()
|
||||
*/
|
||||
uint startOffset() const;
|
||||
|
||||
|
||||
/*!
|
||||
* Returns zero based byte offset (count of bytes from the beginning
|
||||
* of the audio file) of chapter's end.
|
||||
*
|
||||
*
|
||||
* \note If returned value is 0xFFFFFFFF, end time should be used instead.
|
||||
* \see setEndOffset()
|
||||
*/
|
||||
@ -106,48 +107,48 @@ namespace TagLib {
|
||||
/*!
|
||||
* Sets the element ID of the frame to \a eID. If \a eID isn't
|
||||
* null terminated, a null char is appended automatically.
|
||||
*
|
||||
*
|
||||
* \see elementID()
|
||||
*/
|
||||
void setElementID(const ByteVector &eID);
|
||||
|
||||
|
||||
/*!
|
||||
* Sets time of chapter's start (in miliseconds) to \a sT.
|
||||
*
|
||||
*
|
||||
* \see startTime()
|
||||
*/
|
||||
void setStartTime(const uint &sT);
|
||||
|
||||
|
||||
/*!
|
||||
* Sets time of chapter's end (in miliseconds) to \a eT.
|
||||
*
|
||||
*
|
||||
* \see endTime()
|
||||
*/
|
||||
void setEndTime(const uint &eT);
|
||||
|
||||
|
||||
/*!
|
||||
* Sets zero based byte offset (count of bytes from the beginning
|
||||
* of the audio file) of chapter's start to \a sO.
|
||||
*
|
||||
*
|
||||
* \see startOffset()
|
||||
*/
|
||||
void setStartOffset(const uint &sO);
|
||||
|
||||
|
||||
/*!
|
||||
* Sets zero based byte offset (count of bytes from the beginning
|
||||
* of the audio file) of chapter's end to \a eO.
|
||||
*
|
||||
*
|
||||
* \see endOffset()
|
||||
*/
|
||||
void setEndOffset(const uint &eO);
|
||||
|
||||
|
||||
/*!
|
||||
* Returns a reference to the frame list map. This is an FrameListMap of
|
||||
* all of the frames embedded in the CHAP frame.
|
||||
*
|
||||
* This is the most convenient structure for accessing the CHAP frame's
|
||||
* embedded frames. Many frame types allow multiple instances of the same
|
||||
* frame type so this is a map of lists. In most cases however there will
|
||||
* This is the most convenient structure for accessing the CHAP frame's
|
||||
* embedded frames. Many frame types allow multiple instances of the same
|
||||
* frame type so this is a map of lists. In most cases however there will
|
||||
* only be a single frame of a certain type.
|
||||
*
|
||||
* \warning You should not modify this data structure directly, instead
|
||||
@ -156,13 +157,13 @@ namespace TagLib {
|
||||
* \see embeddedFrameList()
|
||||
*/
|
||||
const FrameListMap &embeddedFrameListMap() const;
|
||||
|
||||
|
||||
/*!
|
||||
* Returns a reference to the embedded frame list. This is an FrameList
|
||||
* Returns a reference to the embedded frame list. This is an FrameList
|
||||
* of all of the frames embedded in the CHAP frame in the order that they
|
||||
* were parsed.
|
||||
*
|
||||
* This can be useful if for example you want iterate over the CHAP frame's
|
||||
* This can be useful if for example you want iterate over the CHAP frame's
|
||||
* embedded frames in the order that they occur in the CHAP frame.
|
||||
*
|
||||
* \warning You should not modify this data structure directly, instead
|
||||
@ -171,7 +172,7 @@ namespace TagLib {
|
||||
const FrameList &embeddedFrameList() const;
|
||||
|
||||
/*!
|
||||
* Returns the embedded frame list for frames with the id \a frameID
|
||||
* Returns the embedded frame list for frames with the id \a frameID
|
||||
* or an empty list if there are no embedded frames of that type. This
|
||||
* is just a convenience and is equivalent to:
|
||||
*
|
||||
@ -184,7 +185,7 @@ namespace TagLib {
|
||||
const FrameList &embeddedFrameList(const ByteVector &frameID) const;
|
||||
|
||||
/*!
|
||||
* Add an embedded frame to the CHAP frame. At this point the CHAP frame
|
||||
* Add an embedded frame to the CHAP frame. At this point the CHAP frame
|
||||
* takes ownership of the embedded frame and will handle freeing its memory.
|
||||
*
|
||||
* \note Using this method will invalidate any pointers on the list
|
||||
@ -193,7 +194,7 @@ namespace TagLib {
|
||||
void addEmbeddedFrame(Frame *frame);
|
||||
|
||||
/*!
|
||||
* Remove an embedded frame from the CHAP frame. If \a del is true the frame's
|
||||
* Remove an embedded frame from the CHAP frame. If \a del is true the frame's
|
||||
* memory will be freed; if it is false, it must be deleted by the user.
|
||||
*
|
||||
* \note Using this method will invalidate any pointers on the list
|
||||
@ -202,7 +203,7 @@ namespace TagLib {
|
||||
void removeEmbeddedFrame(Frame *frame, bool del = true);
|
||||
|
||||
/*!
|
||||
* Remove all embedded frames of type \a id from the CHAP frame and free their
|
||||
* Remove all embedded frames of type \a id from the CHAP frame and free their
|
||||
* memory.
|
||||
*
|
||||
* \note Using this method will invalidate any pointers on the list
|
||||
|
||||
@ -35,11 +35,15 @@ using namespace ID3v2;
|
||||
class TableOfContentsFrame::TableOfContentsFramePrivate
|
||||
{
|
||||
public:
|
||||
TableOfContentsFramePrivate()
|
||||
{
|
||||
embeddedFrameList.setAutoDelete(true);
|
||||
}
|
||||
|
||||
ByteVector elementID;
|
||||
bool isTopLevel;
|
||||
bool isOrdered;
|
||||
ByteVectorList childElements;
|
||||
const FrameFactory *factory;
|
||||
FrameListMap embeddedFrameListMap;
|
||||
FrameList embeddedFrameList;
|
||||
};
|
||||
@ -52,11 +56,11 @@ TableOfContentsFrame::TableOfContentsFrame(const ByteVector &data) :
|
||||
ID3v2::Frame(data)
|
||||
{
|
||||
d = new TableOfContentsFramePrivate;
|
||||
d->factory = FrameFactory::instance();
|
||||
setData(data);
|
||||
}
|
||||
|
||||
TableOfContentsFrame::TableOfContentsFrame(const ByteVector &eID, const ByteVectorList &ch, const FrameList &eF) :
|
||||
TableOfContentsFrame::TableOfContentsFrame(const ByteVector &eID, const ByteVectorList &ch,
|
||||
const FrameList &eF) :
|
||||
ID3v2::Frame("CTOC")
|
||||
{
|
||||
d = new TableOfContentsFramePrivate;
|
||||
@ -65,7 +69,6 @@ TableOfContentsFrame::TableOfContentsFrame(const ByteVector &eID, const ByteVect
|
||||
FrameList l = eF;
|
||||
for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it)
|
||||
addEmbeddedFrame(*it);
|
||||
d->factory = FrameFactory::instance();
|
||||
}
|
||||
|
||||
TableOfContentsFrame::~TableOfContentsFrame()
|
||||
@ -188,7 +191,8 @@ PropertyMap TableOfContentsFrame::asProperties() const
|
||||
return map;
|
||||
}
|
||||
|
||||
TableOfContentsFrame *TableOfContentsFrame::findByElementID(const ID3v2::Tag *tag, const ByteVector &eID) // static
|
||||
TableOfContentsFrame *TableOfContentsFrame::findByElementID(const ID3v2::Tag *tag,
|
||||
const ByteVector &eID) // static
|
||||
{
|
||||
ID3v2::FrameList tablesOfContents = tag->frameList("CTOC");
|
||||
|
||||
@ -224,7 +228,9 @@ void TableOfContentsFrame::parseFields(const ByteVector &data)
|
||||
{
|
||||
uint size = data.size();
|
||||
if(size < 6) {
|
||||
debug("A CTOC frame must contain at least 6 bytes (1 byte element ID terminated by null, 1 byte flags, 1 byte entry count and 1 byte child element ID terminated by null.");
|
||||
debug("A CTOC frame must contain at least 6 bytes (1 byte element ID terminated by "
|
||||
"null, 1 byte flags, 1 byte entry count and 1 byte child element ID terminated "
|
||||
"by null.");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -244,7 +250,7 @@ void TableOfContentsFrame::parseFields(const ByteVector &data)
|
||||
size -= pos;
|
||||
while((uint)embPos < size - Frame::headerSize(4))
|
||||
{
|
||||
Frame *frame = d->factory->createFrame(data.mid(pos + embPos));
|
||||
Frame *frame = FrameFactory::instance()->createFrame(data.mid(pos + embPos));
|
||||
|
||||
if(!frame)
|
||||
return;
|
||||
@ -288,6 +294,5 @@ TableOfContentsFrame::TableOfContentsFrame(const ByteVector &data, Header *h) :
|
||||
Frame(h)
|
||||
{
|
||||
d = new TableOfContentsFramePrivate;
|
||||
d->factory = FrameFactory::instance();
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
||||
@ -25,11 +25,10 @@ public:
|
||||
|
||||
RIFF::AIFF::File *f = new RIFF::AIFF::File(filename.c_str());
|
||||
CPPUNIT_ASSERT_EQUAL(705, f->audioProperties()->bitrate());
|
||||
CPPUNIT_ASSERT(!f->audioProperties()->isAiffC());
|
||||
|
||||
CPPUNIT_ASSERT(f->audioProperties()->isAiffC());
|
||||
delete f;
|
||||
}
|
||||
|
||||
|
||||
void testAiffCProperties()
|
||||
{
|
||||
ScopedFileCopy copy("alaw", ".aifc");
|
||||
@ -39,7 +38,6 @@ public:
|
||||
CPPUNIT_ASSERT(f->audioProperties()->isAiffC());
|
||||
CPPUNIT_ASSERT_EQUAL(ByteVector("ALAW"), f->audioProperties()->compressionType());
|
||||
CPPUNIT_ASSERT_EQUAL(String("SGI CCITT G.711 A-law"), f->audioProperties()->compressionName());
|
||||
|
||||
delete f;
|
||||
}
|
||||
|
||||
|
||||
@ -172,6 +172,7 @@ public:
|
||||
FileRef *f = new FileRef(TEST_FILE_PATH_C("empty_flac.oga"));
|
||||
CPPUNIT_ASSERT(dynamic_cast<Ogg::Vorbis::File *>(f->file()) == NULL);
|
||||
CPPUNIT_ASSERT(dynamic_cast<Ogg::FLAC::File *>(f->file()) != NULL);
|
||||
delete f;
|
||||
}
|
||||
|
||||
void testOGA_Vorbis()
|
||||
@ -179,6 +180,7 @@ public:
|
||||
FileRef *f = new FileRef(TEST_FILE_PATH_C("empty_vorbis.oga"));
|
||||
CPPUNIT_ASSERT(dynamic_cast<Ogg::Vorbis::File *>(f->file()) != NULL);
|
||||
CPPUNIT_ASSERT(dynamic_cast<Ogg::FLAC::File *>(f->file()) == NULL);
|
||||
delete f;
|
||||
}
|
||||
|
||||
void testAPE()
|
||||
|
||||
@ -69,6 +69,7 @@ public:
|
||||
CPPUNIT_ASSERT_EQUAL(String("image/png"), pic->mimeType());
|
||||
CPPUNIT_ASSERT_EQUAL(String("A pixel."), pic->description());
|
||||
CPPUNIT_ASSERT_EQUAL(size_t(150), pic->data().size());
|
||||
delete f;
|
||||
}
|
||||
|
||||
void testAddPicture()
|
||||
|
||||
@ -209,6 +209,8 @@ public:
|
||||
CPPUNIT_ASSERT_EQUAL(String("image/jpeg"), frame->mimeType());
|
||||
CPPUNIT_ASSERT_EQUAL(ID3v2::AttachedPictureFrame::FileIcon, frame->type());
|
||||
CPPUNIT_ASSERT_EQUAL(String("d"), frame->description());
|
||||
|
||||
delete frame;
|
||||
}
|
||||
|
||||
void testDontRender22()
|
||||
@ -921,9 +923,9 @@ public:
|
||||
f.setEndTime(5);
|
||||
f.setStartOffset(2);
|
||||
f.setEndOffset(3);
|
||||
ID3v2::TextIdentificationFrame eF("TIT2");
|
||||
eF.setText("CH1");
|
||||
f.addEmbeddedFrame(&eF);
|
||||
ID3v2::TextIdentificationFrame *eF = new ID3v2::TextIdentificationFrame("TIT2");
|
||||
eF->setText("CH1");
|
||||
f.addEmbeddedFrame(eF);
|
||||
CPPUNIT_ASSERT_EQUAL(
|
||||
ByteVector("CHAP" // Frame ID
|
||||
"\x00\x00\x00\x20" // Frame size
|
||||
@ -979,9 +981,9 @@ public:
|
||||
f.setIsOrdered(true);
|
||||
f.addChildElement(ByteVector("\x43\x00", 2));
|
||||
f.addChildElement(ByteVector("\x44\x00", 2));
|
||||
ID3v2::TextIdentificationFrame eF("TIT2");
|
||||
eF.setText("TC1");
|
||||
f.addEmbeddedFrame(&eF);
|
||||
ID3v2::TextIdentificationFrame *eF = new ID3v2::TextIdentificationFrame("TIT2");
|
||||
eF->setText("TC1");
|
||||
f.addEmbeddedFrame(eF);
|
||||
CPPUNIT_ASSERT_EQUAL(
|
||||
ByteVector("CTOC" // Frame ID
|
||||
"\x00\x00\x00\x16" // Frame size
|
||||
|
||||
@ -142,6 +142,7 @@ public:
|
||||
CPPUNIT_ASSERT_EQUAL(String("82,164"), f->tag()->itemListMap()["----:com.apple.iTunes:replaygain_track_minmax"].toStringList()[0]);
|
||||
CPPUNIT_ASSERT_EQUAL(String("Pearl Jam"), f->tag()->artist());
|
||||
CPPUNIT_ASSERT_EQUAL(String("foo"), f->tag()->comment());
|
||||
delete f;
|
||||
}
|
||||
|
||||
void test64BitAtom()
|
||||
@ -158,6 +159,7 @@ public:
|
||||
|
||||
f->tag()->itemListMap()["pgap"] = true;
|
||||
f->save();
|
||||
delete atoms;
|
||||
delete f;
|
||||
|
||||
f = new MP4::File(filename.c_str());
|
||||
@ -168,6 +170,7 @@ public:
|
||||
moov = atoms->atoms[0];
|
||||
// original size + 'pgap' size + padding
|
||||
CPPUNIT_ASSERT_EQUAL(long(77 + 25 + 974), moov->length);
|
||||
delete atoms;
|
||||
delete f;
|
||||
}
|
||||
|
||||
|
||||
@ -86,6 +86,8 @@ public:
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(ByteVector("TEST"), f->chunkName(2));
|
||||
CPPUNIT_ASSERT_EQUAL(ByteVector("foo"), f->chunkData(2));
|
||||
|
||||
delete f;
|
||||
}
|
||||
|
||||
void testLastChunkAtEvenPosition()
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
@ -26,7 +27,9 @@ inline string testFilePath(const string &filename)
|
||||
|
||||
inline string copyFile(const string &filename, const string &ext)
|
||||
{
|
||||
string newname = string(tempnam(NULL, NULL)) + ext;
|
||||
char *newname_c = tempnam(NULL, NULL);
|
||||
string newname = string(newname_c) + ext;
|
||||
free(newname_c);
|
||||
string oldname = testFilePath(filename) + ext;
|
||||
#ifdef _WIN32
|
||||
CopyFileA(oldname.c_str(), newname.c_str(), FALSE);
|
||||
|
||||
Reference in New Issue
Block a user