+TagLib 1.7
+==========
+
+ * Support for reading/writing tags from Monkey's Audio files.
+
TagLib 1.6.3 (Apr 17, 2010)
===========================
ape/apetag.cpp
ape/apefooter.cpp
ape/apeitem.cpp
+ape/apefile.cpp
+ape/apeproperties.cpp
)
SET(wavpack_SRCS
-INSTALL( FILES apetag.h apefooter.h apeitem.h DESTINATION ${INCLUDE_INSTALL_DIR}/taglib)
+INSTALL( FILES apefile.h apeproperties.h apetag.h apefooter.h apeitem.h DESTINATION ${INCLUDE_INSTALL_DIR}/taglib)
noinst_LTLIBRARIES = libape.la
-libape_la_SOURCES = apetag.cpp apefooter.cpp apeitem.cpp
+libape_la_SOURCES = apetag.cpp apefooter.cpp apeitem.cpp apefile.cpp apeproperties.cpp
-taglib_include_HEADERS = apetag.h apefooter.h apeitem.h
+taglib_include_HEADERS = apetag.h apefooter.h apeitem.h apefile.h apeproperties.cpp
taglib_includedir = $(includedir)/taglib
--- /dev/null
+/***************************************************************************
+ copyright : (C) 2010 by Alex Novichkov
+ email : novichko@atnet.ru
+
+ copyright : (C) 2006 by Lukáš Lalinský
+ email : lalinsky@gmail.com
+ (original WavPack implementation)
+
+ copyright : (C) 2004 by Allan Sandfeld Jensen
+ email : kde@carewolf.org
+ (original MPC implementation)
+ ***************************************************************************/
+
+/***************************************************************************
+ * This library is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Lesser General Public License version *
+ * 2.1 as published by the Free Software Foundation. *
+ * *
+ * This library is distributed in the hope that it will be useful, but *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with this library; if not, write to the Free Software *
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
+ * USA *
+ * *
+ * Alternatively, this file is available under the Mozilla Public *
+ * License Version 1.1. You may obtain a copy of the License at *
+ * http://www.mozilla.org/MPL/ *
+ ***************************************************************************/
+
+#include <tbytevector.h>
+#include <tstring.h>
+#include <tdebug.h>
+#include <tagunion.h>
+
+#include "apefile.h"
+#include "id3v1tag.h"
+
+#include "apetag.h"
+#include "apefooter.h"
+
+using namespace TagLib;
+
+namespace
+{
+ enum { APEIndex, ID3v1Index };
+}
+
+class APE::File::FilePrivate
+{
+public:
+ FilePrivate() :
+ APELocation(-1),
+ APESize(0),
+ ID3v1Location(-1),
+ properties(0),
+ hasAPE(false),
+ hasID3v1(false) {}
+
+ ~FilePrivate()
+ {
+ delete properties;
+ }
+
+ long APELocation;
+ uint APESize;
+
+ long ID3v1Location;
+
+ TagUnion tag;
+
+ Properties *properties;
+
+ // These indicate whether the file *on disk* has these tags, not if
+ // this data structure does. This is used in computing offsets.
+
+ bool hasAPE;
+ bool hasID3v1;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// public members
+////////////////////////////////////////////////////////////////////////////////
+
+APE::File::File(FileName file, bool readProperties,
+ Properties::ReadStyle propertiesStyle) : TagLib::File(file)
+{
+ d = new FilePrivate;
+ read(readProperties, propertiesStyle);
+}
+
+APE::File::~File()
+{
+ delete d;
+}
+
+TagLib::Tag *APE::File::tag() const
+{
+ return &d->tag;
+}
+
+APE::Properties *APE::File::audioProperties() const
+{
+ return d->properties;
+}
+
+bool APE::File::save()
+{
+ if(readOnly()) {
+ debug("APE::File::save() -- File is read only.");
+ return false;
+ }
+
+ // Update ID3v1 tag
+
+ if(ID3v1Tag()) {
+ if(d->hasID3v1) {
+ seek(d->ID3v1Location);
+ writeBlock(ID3v1Tag()->render());
+ }
+ else {
+ seek(0, End);
+ d->ID3v1Location = tell();
+ writeBlock(ID3v1Tag()->render());
+ d->hasID3v1 = true;
+ }
+ }
+ else {
+ if(d->hasID3v1) {
+ removeBlock(d->ID3v1Location, 128);
+ d->hasID3v1 = false;
+ if(d->hasAPE) {
+ if(d->APELocation > d->ID3v1Location)
+ d->APELocation -= 128;
+ }
+ }
+ }
+
+ // Update APE tag
+
+ if(APETag()) {
+ if(d->hasAPE)
+ insert(APETag()->render(), d->APELocation, d->APESize);
+ else {
+ if(d->hasID3v1) {
+ insert(APETag()->render(), d->ID3v1Location, 0);
+ d->APESize = APETag()->footer()->completeTagSize();
+ d->hasAPE = true;
+ d->APELocation = d->ID3v1Location;
+ d->ID3v1Location += d->APESize;
+ }
+ else {
+ seek(0, End);
+ d->APELocation = tell();
+ writeBlock(APETag()->render());
+ d->APESize = APETag()->footer()->completeTagSize();
+ d->hasAPE = true;
+ }
+ }
+ }
+ else {
+ if(d->hasAPE) {
+ removeBlock(d->APELocation, d->APESize);
+ d->hasAPE = false;
+ if(d->hasID3v1) {
+ if(d->ID3v1Location > d->APELocation) {
+ d->ID3v1Location -= d->APESize;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+ID3v1::Tag *APE::File::ID3v1Tag(bool create)
+{
+ return d->tag.access<ID3v1::Tag>(ID3v1Index, create);
+}
+
+APE::Tag *APE::File::APETag(bool create)
+{
+ return d->tag.access<APE::Tag>(APEIndex, create);
+}
+
+void APE::File::strip(int tags)
+{
+ if(tags & ID3v1) {
+ d->tag.set(ID3v1Index, 0);
+ APETag(true);
+ }
+
+ if(tags & APE) {
+ d->tag.set(APEIndex, 0);
+
+ if(!ID3v1Tag())
+ APETag(true);
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// private members
+////////////////////////////////////////////////////////////////////////////////
+
+void APE::File::read(bool readProperties, Properties::ReadStyle /* propertiesStyle */)
+{
+ // Look for an ID3v1 tag
+
+ d->ID3v1Location = findID3v1();
+
+ if(d->ID3v1Location >= 0) {
+ d->tag.set(ID3v1Index, new ID3v1::Tag(this, d->ID3v1Location));
+ d->hasID3v1 = true;
+ }
+
+ // Look for an APE tag
+
+ d->APELocation = findAPE();
+
+ if(d->APELocation >= 0) {
+ d->tag.set(APEIndex, new APE::Tag(this, d->APELocation));
+ d->APESize = APETag()->footer()->completeTagSize();
+ d->APELocation = d->APELocation + APETag()->footer()->size() - d->APESize;
+ d->hasAPE = true;
+ }
+
+ if(!d->hasID3v1)
+ APETag(true);
+
+ // Look for APE audio properties
+
+ if(readProperties) {
+ d->properties = new Properties(this);
+ }
+}
+
+long APE::File::findAPE()
+{
+ if(!isValid())
+ return -1;
+
+ if(d->hasID3v1)
+ seek(-160, End);
+ else
+ seek(-32, End);
+
+ long p = tell();
+
+ if(readBlock(8) == APE::Tag::fileIdentifier())
+ return p;
+
+ return -1;
+}
+
+long APE::File::findID3v1()
+{
+ if(!isValid())
+ return -1;
+
+ seek(-128, End);
+ long p = tell();
+
+ if(readBlock(3) == ID3v1::Tag::fileIdentifier())
+ return p;
+
+ return -1;
+}
--- /dev/null
+/***************************************************************************
+ copyright : (C) 2010 by Alex Novichkov
+ email : novichko@atnet.ru
+
+ copyright : (C) 2006 by Lukáš Lalinský
+ email : lalinsky@gmail.com
+ (original WavPack implementation)
+
+ copyright : (C) 2004 by Allan Sandfeld Jensen
+ email : kde@carewolf.org
+ (original MPC implementation)
+ ***************************************************************************/
+
+/***************************************************************************
+ * This library is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Lesser General Public License version *
+ * 2.1 as published by the Free Software Foundation. *
+ * *
+ * This library is distributed in the hope that it will be useful, but *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with this library; if not, write to the Free Software *
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
+ * USA *
+ * *
+ * Alternatively, this file is available under the Mozilla Public *
+ * License Version 1.1. You may obtain a copy of the License at *
+ * http://www.mozilla.org/MPL/ *
+ ***************************************************************************/
+
+#ifndef TAGLIB_APEFILE_H
+#define TAGLIB_APEFILE_H
+
+#include "tfile.h"
+#include "taglib_export.h"
+#include "apeproperties.h"
+
+namespace TagLib {
+
+ class Tag;
+
+ namespace ID3v1 { class Tag; }
+ namespace APE { class Tag; }
+
+ //! An implementation of APE metadata
+
+ /*!
+ * This is implementation of APE metadata.
+ *
+ * This supports ID3v1 and APE (v1 and v2) style comments as well as reading stream
+ * properties from the file.
+ */
+
+ namespace APE {
+
+ //! An implementation of TagLib::File with APE specific methods
+
+ /*!
+ * This implements and provides an interface APE WavPack files to the
+ * TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
+ * the abstract TagLib::File API as well as providing some additional
+ * information specific to APE files.
+ */
+
+ class TAGLIB_EXPORT File : public TagLib::File
+ {
+ public:
+ /*!
+ * This set of flags is used for various operations and is suitable for
+ * being OR-ed together.
+ */
+ enum TagTypes {
+ //! Empty set. Matches no tag types.
+ NoTags = 0x0000,
+ //! Matches ID3v1 tags.
+ ID3v1 = 0x0001,
+ //! Matches APE tags.
+ APE = 0x0002,
+ //! Matches all tag types.
+ AllTags = 0xffff
+ };
+
+ /*!
+ * Contructs an WavPack file from \a file. If \a readProperties is true the
+ * file's audio properties will also be read using \a propertiesStyle. If
+ * false, \a propertiesStyle is ignored.
+ */
+ File(FileName file, bool readProperties = true,
+ Properties::ReadStyle propertiesStyle = Properties::Average);
+
+ /*!
+ * Destroys this instance of the File.
+ */
+ virtual ~File();
+
+ /*!
+ * Returns the Tag for this file. This will be an APE tag, an ID3v1 tag
+ * or a combination of the two.
+ */
+ virtual TagLib::Tag *tag() const;
+
+ /*!
+ * Returns the APE::Properties for this file. If no audio properties
+ * were read then this will return a null pointer.
+ */
+ virtual Properties *audioProperties() const;
+
+ /*!
+ * Saves the file.
+ *
+ * \note According to the official Monkey's Audio SDK, an APE file
+ * can only have either ID3V1 or APE tags, so a parameter is used here.
+ */
+ virtual bool save();
+
+ /*!
+ * Returns a pointer to the ID3v1 tag of the file.
+ *
+ * If \a create is false (the default) this will return a null pointer
+ * if there is no valid ID3v1 tag. If \a create is true it will create
+ * an ID3v1 tag if one does not exist. If there is already an APE tag, the
+ * new ID3v1 tag will be placed after it.
+ *
+ * \note The Tag <b>is still</b> owned by the APE::File and should not be
+ * deleted by the user. It will be deleted when the file (object) is
+ * destroyed.
+ */
+ ID3v1::Tag *ID3v1Tag(bool create = false);
+
+ /*!
+ * Returns a pointer to the APE tag of the file.
+ *
+ * If \a create is false (the default) this will return a null pointer
+ * if there is no valid APE tag. If \a create is true it will create
+ * a APE tag if one does not exist.
+ *
+ * \note The Tag <b>is still</b> owned by the APE::File and should not be
+ * deleted by the user. It will be deleted when the file (object) is
+ * destroyed.
+ */
+ APE::Tag *APETag(bool create = false);
+
+ /*!
+ * This will remove the tags that match the OR-ed together TagTypes from the
+ * file. By default it removes all tags.
+ *
+ * \note This will also invalidate pointers to the tags
+ * as their memory will be freed.
+ * \note In order to make the removal permanent save() still needs to be called
+ */
+ void strip(int tags = AllTags);
+
+ private:
+ File(const File &);
+ File &operator=(const File &);
+
+ void read(bool readProperties, Properties::ReadStyle propertiesStyle);
+ void scan();
+ long findID3v1();
+ long findAPE();
+
+ class FilePrivate;
+ FilePrivate *d;
+ };
+ }
+}
+
+#endif
--- /dev/null
+/***************************************************************************
+ copyright : (C) 2010 by Alex Novichkov
+ email : novichko@atnet.ru
+
+ copyright : (C) 2006 by Lukáš Lalinský
+ email : lalinsky@gmail.com
+ (original WavPack implementation)
+ ***************************************************************************/
+
+/***************************************************************************
+ * This library is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Lesser General Public License version *
+ * 2.1 as published by the Free Software Foundation. *
+ * *
+ * This library is distributed in the hope that it will be useful, but *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with this library; if not, write to the Free Software *
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
+ * USA *
+ * *
+ * Alternatively, this file is available under the Mozilla Public *
+ * License Version 1.1. You may obtain a copy of the License at *
+ * http://www.mozilla.org/MPL/ *
+ ***************************************************************************/
+
+#include <tstring.h>
+#include <tdebug.h>
+#include <bitset>
+#include "id3v2tag.h"
+#include "apeproperties.h"
+#include "apefile.h"
+
+using namespace TagLib;
+
+class APE::Properties::PropertiesPrivate
+{
+public:
+ PropertiesPrivate(File *file, long streamLength) :
+ length(0),
+ bitrate(0),
+ sampleRate(0),
+ channels(0),
+ version(0),
+ bitsPerSample(0),
+ file(file),
+ streamLength(streamLength) {}
+
+ long streamLength;
+ int length;
+ int bitrate;
+ int sampleRate;
+ int channels;
+ int version;
+ int bitsPerSample;
+ File *file;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+// public members
+////////////////////////////////////////////////////////////////////////////////
+
+APE::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style)
+{
+ d = new PropertiesPrivate(file, file->length());
+ read();
+}
+
+APE::Properties::~Properties()
+{
+ delete d;
+}
+
+int APE::Properties::length() const
+{
+ return d->length;
+}
+
+int APE::Properties::bitrate() const
+{
+ return d->bitrate;
+}
+
+int APE::Properties::sampleRate() const
+{
+ return d->sampleRate;
+}
+
+int APE::Properties::channels() const
+{
+ return d->channels;
+}
+
+int APE::Properties::version() const
+{
+ return d->version;
+}
+
+int APE::Properties::bitsPerSample() const
+{
+ return d->bitsPerSample;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// private members
+////////////////////////////////////////////////////////////////////////////////
+
+
+void APE::Properties::read()
+{
+ // First we are searching the descriptor
+ long offset = findDescriptor();
+ if(offset < 0)
+ return;
+
+ // Then we read the header common for all versions of APE
+ d->file->seek(offset);
+ ByteVector commonHeader=d->file->readBlock(6);
+ if(!commonHeader.startsWith("MAC "))
+ return;
+ d->version = commonHeader.mid(4).toUInt(false);
+
+ if(d->version >= 3980) {
+ analyzeCurrent();
+ }
+ else {
+ analyzeOld();
+ }
+}
+
+long APE::Properties::findDescriptor()
+{
+ long ID3v2Location = findID3v2();
+ long ID3v2OriginalSize = 0;
+ bool hasID3v2 = false;
+ if(ID3v2Location >= 0) {
+ ID3v2::Tag tag(d->file, ID3v2Location, 0);
+ ID3v2OriginalSize = tag.header()->completeTagSize();
+ if(tag.header()->tagSize() > 0)
+ hasID3v2 = true;
+ }
+
+ long offset = 0;
+ if(hasID3v2)
+ offset = d->file->find("MAC ", ID3v2Location + ID3v2OriginalSize);
+ else
+ offset = d->file->find("MAC ");
+
+ if(offset < 0) {
+ debug("APE::Properties::findDescriptor() -- APE descriptor not found");
+ return -1;
+ }
+
+ return offset;
+}
+
+long APE::Properties::findID3v2()
+{
+ if(!d->file->isValid())
+ return -1;
+
+ d->file->seek(0);
+
+ if(d->file->readBlock(3) == ID3v2::Header::fileIdentifier())
+ return 0;
+
+ return -1;
+}
+
+void APE::Properties::analyzeCurrent()
+{
+ // Read the descriptor
+ d->file->seek(2, File::Current);
+ ByteVector descriptor = d->file->readBlock(44);
+ uint descriptorBytes = descriptor.mid(0,4).toUInt(false);
+
+ if ((descriptorBytes - 52) > 0)
+ d->file->seek(descriptorBytes - 52, File::Current);
+
+ // Read the header
+ ByteVector header = d->file->readBlock(24);
+
+ // Get the APE info
+ d->channels = header.mid(18, 2).toShort(false);
+ d->sampleRate = header.mid(20, 4).toUInt(false);
+ d->bitsPerSample = header.mid(16, 2).toShort(false);
+ //d->compressionLevel =
+
+ uint totalFrames = header.mid(12, 4).toUInt(false);
+ uint blocksPerFrame = header.mid(4, 4).toUInt(false);
+ uint finalFrameBlocks = header.mid(8, 4).toUInt(false);
+ uint totalBlocks = totalFrames > 0 ? (totalFrames - 1) * blocksPerFrame + finalFrameBlocks : 0;
+ d->length = totalBlocks / d->sampleRate;
+ d->bitrate = d->length > 0 ? ((d->streamLength * 8L) / d->length) / 1000 : 0;
+}
+
+void APE::Properties::analyzeOld()
+{
+ ByteVector header = d->file->readBlock(26);
+ uint totalFrames = header.mid(18, 4).toUInt(false);
+
+ // Fail on 0 length APE files (catches non-finalized APE files)
+ if(totalFrames == 0)
+ return;
+
+ short compressionLevel = header.mid(0, 2).toShort(false);
+ uint blocksPerFrame;
+ if(d->version >= 3950)
+ blocksPerFrame = 73728 * 4;
+ else if(d->version >= 3900 || (d->version >= 3800 && compressionLevel == 4000))
+ blocksPerFrame = 73728;
+ else
+ blocksPerFrame = 9216;
+ d->channels = header.mid(4, 2).toShort(false);
+ d->sampleRate = header.mid(6, 4).toUInt(false);
+ uint finalFrameBlocks = header.mid(22, 4).toUInt(false);
+ uint totalBlocks = totalFrames > 0 ? (totalFrames - 1) * blocksPerFrame + finalFrameBlocks : 0;
+ d->length = totalBlocks / d->sampleRate;
+ d->bitrate = d->length > 0 ? ((d->streamLength * 8L) / d->length) / 1000 : 0;
+}
+
--- /dev/null
+/***************************************************************************
+ copyright : (C) 2010 by Alex Novichkov
+ email : novichko@atnet.ru
+
+ copyright : (C) 2006 by Lukáš Lalinský
+ email : lalinsky@gmail.com
+ (original WavPack implementation)
+ ***************************************************************************/
+
+/***************************************************************************
+ * This library is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU Lesser General Public License version *
+ * 2.1 as published by the Free Software Foundation. *
+ * *
+ * This library is distributed in the hope that it will be useful, but *
+ * WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
+ * Lesser General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Lesser General Public *
+ * License along with this library; if not, write to the Free Software *
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
+ * USA *
+ * *
+ * Alternatively, this file is available under the Mozilla Public *
+ * License Version 1.1. You may obtain a copy of the License at *
+ * http://www.mozilla.org/MPL/ *
+ ***************************************************************************/
+
+#ifndef TAGLIB_APEPROPERTIES_H
+#define TAGLIB_APEPROPERTIES_H
+
+#include "taglib_export.h"
+#include "audioproperties.h"
+
+namespace TagLib {
+
+ namespace APE {
+
+ class File;
+
+ //! An implementation of audio property reading for APE
+
+ /*!
+ * This reads the data from an APE stream found in the AudioProperties
+ * API.
+ */
+
+ class TAGLIB_EXPORT Properties : public AudioProperties
+ {
+ public:
+ /*!
+ * Create an instance of APE::Properties with the data read from the
+ * ByteVector \a data.
+ */
+ Properties(File *f, ReadStyle style = Average);
+
+ /*!
+ * Destroys this APE::Properties instance.
+ */
+ virtual ~Properties();
+
+ // Reimplementations.
+
+ virtual int length() const;
+ virtual int bitrate() const;
+ virtual int sampleRate() const;
+ virtual int channels() const;
+
+ /*!
+ * Returns number of bits per sample.
+ */
+ int bitsPerSample() const;
+
+ /*!
+ * Returns APE version.
+ */
+ int version() const;
+
+ private:
+ Properties(const Properties &);
+ Properties &operator=(const Properties &);
+
+ void read();
+
+ long findDescriptor();
+ long findID3v2();
+
+ void analyzeCurrent();
+ void analyzeOld();
+
+ class PropertiesPrivate;
+ PropertiesPrivate *d;
+ };
+ }
+}
+
+#endif
* Create an APE tag and parse the data in \a file with APE footer at
* \a tagOffset.
*/
- Tag(File *file, long footerLocation);
+ Tag(TagLib::File *file, long footerLocation);
/*!
* Destroys this Tag instance.
/***************************************************************************
copyright : (C) 2002 - 2008 by Scott Wheeler
email : wheeler@kde.org
+
+ copyright : (C) 2010 by Alex Novichkov
+ email : novichko@atnet.ru
+ (added APE file support)
***************************************************************************/
/***************************************************************************
#include "trueaudiofile.h"
#include "aifffile.h"
#include "wavfile.h"
+#include "apefile.h"
using namespace TagLib;
l.append("aif");
l.append("aiff");
l.append("wav");
+ l.append("ape");
return l;
}
return new RIFF::WAV::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "AIFF")
return new RIFF::AIFF::File(fileName, readAudioProperties, audioPropertiesStyle);
+ if(ext == "APE")
+ return new APE::File(fileName, readAudioProperties, audioPropertiesStyle);
}
return 0;
INCLUDE_DIRECTORIES(
${CMAKE_CURRENT_SOURCE_DIR}/../taglib
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/toolkit
+ ${CMAKE_CURRENT_SOURCE_DIR}/../taglib/ape
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/asf
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mpeg/id3v1
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mpeg/id3v2
test_ogg.cpp
test_oggflac.cpp
test_flac.cpp
+ test_ape.cpp
)
IF(WITH_MP4)
SET(test_runner_SRCS ${test_runner_SRCS}
-I$(top_srcdir)/taglib\
-I$(top_srcdir)/taglib/toolkit \
-I$(top_srcdir)/taglib/trueaudio \
+ -I$(top_srcdir)/taglib/ape \
-I$(top_srcdir)/taglib/mpeg \
-I$(top_srcdir)/taglib/mpeg/id3v1 \
-I$(top_srcdir)/taglib/mpeg/id3v2 \
test_map.cpp \
test_mpeg.cpp \
test_synchdata.cpp \
+ test_ape.cpp \
test_trueaudio.cpp \
test_bytevector.cpp \
test_string.cpp \
--- /dev/null
+#include <cppunit/extensions/HelperMacros.h>
+#include <string>
+#include <stdio.h>
+#include <tag.h>
+#include <tstringlist.h>
+#include <tbytevectorlist.h>
+#include <apefile.h>
+#include "utils.h"
+
+using namespace std;
+using namespace TagLib;
+
+class TestAPE : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(TestAPE);
+ CPPUNIT_TEST(testProperties399);
+ CPPUNIT_TEST(testProperties396);
+ CPPUNIT_TEST(testProperties390);
+ CPPUNIT_TEST_SUITE_END();
+
+public:
+
+ void testProperties399()
+ {
+ APE::File f("data/mac-399.ape");
+ CPPUNIT_ASSERT_EQUAL(3, f.audioProperties()->length());
+ CPPUNIT_ASSERT_EQUAL(0, f.audioProperties()->bitrate());
+ CPPUNIT_ASSERT_EQUAL(2, f.audioProperties()->channels());
+ CPPUNIT_ASSERT_EQUAL(44100, f.audioProperties()->sampleRate());
+ }
+
+ void testProperties396()
+ {
+ APE::File f("data/mac-396.ape");
+ CPPUNIT_ASSERT_EQUAL(3, f.audioProperties()->length());
+ CPPUNIT_ASSERT_EQUAL(0, f.audioProperties()->bitrate());
+ CPPUNIT_ASSERT_EQUAL(2, f.audioProperties()->channels());
+ CPPUNIT_ASSERT_EQUAL(44100, f.audioProperties()->sampleRate());
+ }
+
+ void testProperties390()
+ {
+ APE::File f("data/mac-390-hdr.ape");
+ CPPUNIT_ASSERT_EQUAL(15, f.audioProperties()->length());
+ CPPUNIT_ASSERT_EQUAL(0, f.audioProperties()->bitrate());
+ CPPUNIT_ASSERT_EQUAL(2, f.audioProperties()->channels());
+ CPPUNIT_ASSERT_EQUAL(44100, f.audioProperties()->sampleRate());
+ }
+
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(TestAPE);
CPPUNIT_TEST(testMP4_3);
#endif
CPPUNIT_TEST(testTrueAudio);
+ CPPUNIT_TEST(testAPE);
CPPUNIT_TEST_SUITE_END();
public:
CPPUNIT_ASSERT(dynamic_cast<Ogg::FLAC::File *>(f->file()) == NULL);
}
+ void testAPE()
+ {
+ fileRefSave("mac-399.ape", ".ape");
+ }
};
CPPUNIT_TEST_SUITE_REGISTRATION(TestFileRef);