diff options
Diffstat (limited to 'src/metadata')
147 files changed, 14352 insertions, 0 deletions
diff --git a/src/metadata/Makefile.am b/src/metadata/Makefile.am new file mode 100644 index 0000000..8e7209f --- /dev/null +++ b/src/metadata/Makefile.am @@ -0,0 +1,37 @@ +if with_mp4v2 +MP4_SUBDIR = mp4 +MP4_LDADD = mp4/libtagmp4.la +else +MP4_SUBDIR = m4a +MP4_LDADD = m4a/libtagm4a.la +endif + +SUBDIRS = speex wavpack trueaudio asf audible rmff $(MP4_SUBDIR) aac wav ape optimfrog + + +INCLUDES = $(all_includes) $(taglib_includes) +METASOURCES = AUTO +libmetadata_la_LDFLAGS = $(all_libraries) +noinst_LTLIBRARIES = libmetadata.la + +libmetadata_la_SOURCES = \ + tplugins.cpp \ + tagengine.cpp + +noinst_HEADERS = \ + tplugins.h \ + tagengine.h + +libmetadata_la_LIBADD = \ + speex/libtagspeex.la \ + trueaudio/libtagtrueaudio.la \ + wavpack/libtagwavpack.la \ + asf/libtagasf.la \ + wav/libtagwav.la \ + rmff/libtagrealmedia.la \ + $(MP4_LDADD) \ + $(taglib_libs) \ + aac/libtagaac.la \ + audible/libtagaudible.la \ + ape/libtagmonkeysaudio.la \ + optimfrog/libtagoptimfrog.la diff --git a/src/metadata/aac/Makefile.am b/src/metadata/aac/Makefile.am new file mode 100644 index 0000000..b6b0f43 --- /dev/null +++ b/src/metadata/aac/Makefile.am @@ -0,0 +1,12 @@ +SUBDIRS = +METASOURCES = AUTO +INCLUDES = $(all_includes) $(taglib_includes) + +libtagaac_la_LDFLAGS = $(all_libraries) +noinst_LTLIBRARIES = libtagaac.la + +libtagaac_la_SOURCES = \ + aacfiletyperesolver.cpp + +noinst_HEADERS = \ + aacfiletyperesolver.h diff --git a/src/metadata/aac/aacfiletyperesolver.cpp b/src/metadata/aac/aacfiletyperesolver.cpp new file mode 100644 index 0000000..fcc2a86 --- /dev/null +++ b/src/metadata/aac/aacfiletyperesolver.cpp @@ -0,0 +1,38 @@ +/*************************************************************************** + copyright : (C) 2006 by Martin Aumueller + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "aacfiletyperesolver.h" +#include <taglib/mpegfile.h> + +#include <string.h> + +TagLib::File *AACFileTypeResolver::createFile(const char *fileName, + bool readProperties, + TagLib::AudioProperties::ReadStyle propertiesStyle) const +{ + const char *ext = strrchr(fileName, '.'); + if(ext && !strcasecmp(ext, ".aac")) + { + return new TagLib::MPEG::File(fileName, readProperties, propertiesStyle); + } + + return 0; +} diff --git a/src/metadata/aac/aacfiletyperesolver.h b/src/metadata/aac/aacfiletyperesolver.h new file mode 100644 index 0000000..6c33b71 --- /dev/null +++ b/src/metadata/aac/aacfiletyperesolver.h @@ -0,0 +1,36 @@ +/*************************************************************************** + copyright : (C) 2006 by Martin Aumueller + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_AACFILETYPERESOLVER_H +#define TAGLIB_AACFILETYPERESOLVER_H + +#include <taglib/tfile.h> +#include <taglib/fileref.h> + + +class AACFileTypeResolver : public TagLib::FileRef::FileTypeResolver +{ + TagLib::File *createFile(const char *fileName, + bool readAudioProperties, + TagLib::AudioProperties::ReadStyle audioPropertiesStyle) const; +}; + +#endif diff --git a/src/metadata/ape/Makefile.am b/src/metadata/ape/Makefile.am new file mode 100755 index 0000000..156cf91 --- /dev/null +++ b/src/metadata/ape/Makefile.am @@ -0,0 +1,6 @@ +INCLUDES = $(all_includes) $(taglib_includes) +METASOURCES = AUTO +libtagmonkeysaudio_la_LDFLAGS = $(all_libraries) +noinst_LTLIBRARIES = libtagmonkeysaudio.la +noinst_HEADERS = taglib_monkeysaudiofiletyperesolver.h +libtagmonkeysaudio_la_SOURCES = taglib_monkeysaudiofiletyperesolver.cpp diff --git a/src/metadata/ape/taglib_monkeysaudiofiletyperesolver.cpp b/src/metadata/ape/taglib_monkeysaudiofiletyperesolver.cpp new file mode 100755 index 0000000..fea0344 --- /dev/null +++ b/src/metadata/ape/taglib_monkeysaudiofiletyperesolver.cpp @@ -0,0 +1,21 @@ +// (c) 2006 Martin Aumueller <[email protected]> +// modified 2006 Daniel Faust <[email protected]> +// See COPYING file for licensing information + +#include "taglib_monkeysaudiofiletyperesolver.h" +#include <taglib/mpcfile.h> + +#include <string.h> + +TagLib::File *MonkeysAudioFileTypeResolver::createFile(const char *fileName, + bool readProperties, + TagLib::AudioProperties::ReadStyle propertiesStyle) const +{ + const char *ext = strrchr(fileName, '.'); + if(ext && (!strcasecmp(ext, ".ape") || !strcasecmp(ext, ".mac"))) + { + return new TagLib::MPC::File(fileName, readProperties, propertiesStyle); + } + + return 0; +} diff --git a/src/metadata/ape/taglib_monkeysaudiofiletyperesolver.h b/src/metadata/ape/taglib_monkeysaudiofiletyperesolver.h new file mode 100755 index 0000000..4af4a7b --- /dev/null +++ b/src/metadata/ape/taglib_monkeysaudiofiletyperesolver.h @@ -0,0 +1,19 @@ +// (c) 2006 Martin Aumueller <[email protected]> +// modified 2006 Daniel Faust <[email protected]> +// See COPYING file for licensing information + +#ifndef TAGLIB_MONKEYSAUDIOFILETYPERESOLVER_H +#define TAGLIB_MONKEYSAUDIOFILETYPERESOLVER_H + +#include <taglib/tfile.h> +#include <taglib/fileref.h> + + +class MonkeysAudioFileTypeResolver : public TagLib::FileRef::FileTypeResolver +{ + TagLib::File *createFile(const char *fileName, + bool readAudioProperties, + TagLib::AudioProperties::ReadStyle audioPropertiesStyle) const; +}; + +#endif diff --git a/src/metadata/asf/Makefile.am b/src/metadata/asf/Makefile.am new file mode 100644 index 0000000..63fa0e1 --- /dev/null +++ b/src/metadata/asf/Makefile.am @@ -0,0 +1,20 @@ +SUBDIRS = + +INCLUDES = $(all_includes) $(taglib_includes) +METASOURCES = AUTO +libtagasf_la_LDFLAGS = $(all_libraries) +noinst_LTLIBRARIES = libtagasf.la + +libtagasf_la_SOURCES = \ + asfattribute.cpp \ + asfproperties.cpp \ + asftag.cpp \ + asffile.cpp \ + taglib_asffiletyperesolver.cpp + +noinst_HEADERS = \ + asfattribute.h \ + asfproperties.h \ + asftag.h \ + asffile.h \ + taglib_asffiletyperesolver.h diff --git a/src/metadata/asf/asfattribute.cpp b/src/metadata/asf/asfattribute.cpp new file mode 100644 index 0000000..bfe81c5 --- /dev/null +++ b/src/metadata/asf/asfattribute.cpp @@ -0,0 +1,304 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : [email protected] + **************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * + * USA * + ***************************************************************************/ + +#include <taglib.h> +#include "asfattribute.h" +#include "asffile.h" + +using namespace TagLib; + +class ASF::Attribute::AttributePrivate : public RefCounter +{ +public: + AttributePrivate() + : stream(0), + language(0) {} + AttributeTypes type; + String stringValue; + ByteVector byteVectorValue; + union { + unsigned int intValue; + unsigned short shortValue; + unsigned long long longLongValue; + bool boolValue; + }; + int stream; + int language; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +ASF::Attribute::Attribute() +{ + d = new AttributePrivate; + d->type = UnicodeType; +} + +ASF::Attribute::Attribute(const ASF::Attribute &other) + : d(other.d) +{ + d->ref(); +} + +ASF::Attribute & +ASF::Attribute::operator=(const ASF::Attribute &other) +{ + if(d->deref()) + delete d; + d = other.d; + d->ref(); + return *this; +} + +ASF::Attribute::~Attribute() +{ + if(d->deref()) + delete d; +} + +ASF::Attribute::Attribute(const String &value) +{ + d = new AttributePrivate; + d->type = UnicodeType; + d->stringValue = value; +} + +ASF::Attribute::Attribute(const ByteVector &value) +{ + d = new AttributePrivate; + d->type = BytesType; + d->byteVectorValue = value; +} + +ASF::Attribute::Attribute(unsigned int value) +{ + d = new AttributePrivate; + d->type = DWordType; + d->intValue = value; +} + +ASF::Attribute::Attribute(unsigned long long value) +{ + d = new AttributePrivate; + d->type = QWordType; + d->longLongValue = value; +} + +ASF::Attribute::Attribute(unsigned short value) +{ + d = new AttributePrivate; + d->type = WordType; + d->shortValue = value; +} + +ASF::Attribute::Attribute(bool value) +{ + d = new AttributePrivate; + d->type = BoolType; + d->boolValue = value; +} + +ASF::Attribute::AttributeTypes +ASF::Attribute::type() const +{ + return d->type; +} + +String +ASF::Attribute::toString() const +{ + return d->stringValue; +} + +ByteVector +ASF::Attribute::toByteVector() const +{ + return d->byteVectorValue; +} + +unsigned short +ASF::Attribute::toBool() const +{ + return d->shortValue; +} + +unsigned short +ASF::Attribute::toUShort() const +{ + return d->shortValue; +} + +unsigned int +ASF::Attribute::toUInt() const +{ + return d->intValue; +} + +unsigned long long +ASF::Attribute::toULongLong() const +{ + return d->longLongValue; +} + +String +ASF::Attribute::parse(ASF::File &f, int kind) +{ + int size, nameLength; + String name; + + // extended content descriptor + if(kind == 0) { + nameLength = f.readWORD(); + name = f.readString(nameLength); + d->type = ASF::Attribute::AttributeTypes(f.readWORD()); + size = f.readWORD(); + } + // metadata & metadata library + else { + int temp = f.readWORD(); + // metadata library + if(kind == 2) { + d->language = temp; + } + d->stream = f.readWORD(); + nameLength = f.readWORD(); + d->type = ASF::Attribute::AttributeTypes(f.readWORD()); + size = f.readDWORD(); + name = f.readString(nameLength); + } + + switch(d->type) { + case WordType: + d->shortValue = f.readWORD(); + break; + + case BoolType: + if(kind == 0) { + d->boolValue = f.readDWORD() == 1; + } + else { + d->boolValue = f.readWORD() == 1; + } + break; + + case DWordType: + d->intValue = f.readDWORD(); + break; + + case QWordType: + d->longLongValue = f.readQWORD(); + break; + + case UnicodeType: + d->stringValue = f.readString(size); + break; + + case BytesType: + case GuidType: + d->byteVectorValue = f.readBlock(size); + break; + } + + return name; +} + +ByteVector +ASF::Attribute::render(const String &name, int kind) const +{ + ByteVector data; + + switch (d->type) { + case WordType: + data.append(ByteVector::fromShort(d->shortValue, false)); + break; + + case BoolType: + if(kind == 0) { + data.append(ByteVector::fromUInt(d->boolValue ? 1 : 0, false)); + } + else { + data.append(ByteVector::fromShort(d->boolValue ? 1 : 0, false)); + } + break; + + case DWordType: + data.append(ByteVector::fromUInt(d->intValue, false)); + break; + + case QWordType: + data.append(ByteVector::fromLongLong(d->longLongValue, false)); + break; + + case UnicodeType: + data.append(File::renderString(d->stringValue)); + break; + + case BytesType: + case GuidType: + data.append(d->byteVectorValue); + break; + } + + if(kind == 0) { + data = File::renderString(name, true) + + ByteVector::fromShort((int)d->type, false) + + ByteVector::fromShort(data.size(), false) + + data; + } + else { + ByteVector nameData = File::renderString(name); + data = ByteVector::fromShort(kind == 2 ? d->language : 0, false) + + ByteVector::fromShort(d->stream, false) + + ByteVector::fromShort(nameData.size(), false) + + ByteVector::fromShort((int)d->type, false) + + ByteVector::fromUInt(data.size(), false) + + nameData + + data; + } + + return data; +} + +int +ASF::Attribute::language() const +{ + return d->language; +} + +void +ASF::Attribute::setLanguage(int value) +{ + d->language = value; +} + +int +ASF::Attribute::stream() const +{ + return d->stream; +} + +void +ASF::Attribute::setStream(int value) +{ + d->stream = value; +} diff --git a/src/metadata/asf/asfattribute.h b/src/metadata/asf/asfattribute.h new file mode 100644 index 0000000..9a8e3c9 --- /dev/null +++ b/src/metadata/asf/asfattribute.h @@ -0,0 +1,176 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : [email protected] + **************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * + * USA * + ***************************************************************************/ + +#ifndef TAGLIB_ASFATTRIBUTE_H +#define TAGLIB_ASFATTRIBUTE_H + +#include <tstring.h> +#include <tbytevector.h> + +namespace TagLib +{ + + namespace ASF + { + + class File; + + class Attribute + { + public: + + /*! + * Enum of types an Attribute can have. + */ + enum AttributeTypes { + UnicodeType = 0, + BytesType = 1, + BoolType = 2, + DWordType = 3, + QWordType = 4, + WordType = 5, + GuidType = 6 + }; + + /*! + * Constructs an empty attribute. + */ + Attribute(); + + /*! + * Constructs an attribute with \a key and a UnicodeType \a value. + */ + Attribute(const String &value); + + /*! + * Constructs an attribute with \a key and a BytesType \a value. + */ + Attribute(const ByteVector &value); + + /*! + * Constructs an attribute with \a key and a DWordType \a value. + */ + Attribute(unsigned int value); + + /*! + * Constructs an attribute with \a key and a QWordType \a value. + */ + Attribute(unsigned long long value); + + /*! + * Constructs an attribute with \a key and a WordType \a value. + */ + Attribute(unsigned short value); + + /*! + * Constructs an attribute with \a key and a BoolType \a value. + */ + Attribute(bool value); + + /*! + * Construct an attribute as a copy of \a other. + */ + Attribute(const Attribute &item); + + /*! + * Copies the contents of \a other into this item. + */ + ASF::Attribute &operator=(const Attribute &other); + + /*! + * Destroys the attribute. + */ + virtual ~Attribute(); + + /*! + * Returns type of the value. + */ + AttributeTypes type() const; + + /*! + * Returns the BoolType \a value. + */ + unsigned short toBool() const; + + /*! + * Returns the WordType \a value. + */ + unsigned short toUShort() const; + + /*! + * Returns the DWordType \a value. + */ + unsigned int toUInt() const; + + /*! + * Returns the QWordType \a value. + */ + unsigned long long toULongLong() const; + + /*! + * Returns the UnicodeType \a value. + */ + String toString() const; + + /*! + * Returns the BytesType \a value. + */ + ByteVector toByteVector() const; + + /*! + * Returns the language number, or 0 is no stream number was set. + */ + int language() const; + + /*! + * Sets the language number. + */ + void setLanguage(int value); + + /*! + * Returns the stream number, or 0 is no stream number was set. + */ + int stream() const; + + /*! + * Sets the stream number. + */ + void setStream(int value); + +#ifndef DO_NOT_DOCUMENT + /* THIS IS PRIVATE, DON'T TOUCH IT! */ + String parse(ASF::File &file, int kind = 0); +#endif + + private: + friend class File; + + ByteVector render(const String &name, int kind = 0) const; + + class AttributePrivate; + AttributePrivate *d; + }; + + } + +} + +#endif diff --git a/src/metadata/asf/asffile.cpp b/src/metadata/asf/asffile.cpp new file mode 100644 index 0000000..55a12cc --- /dev/null +++ b/src/metadata/asf/asffile.cpp @@ -0,0 +1,547 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : [email protected] + **************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * + * USA * + ***************************************************************************/ + +#include <tbytevectorlist.h> +#include <tstring.h> +#include "asffile.h" +#include "asftag.h" +#include "asfproperties.h" + +using namespace TagLib; + +class ASF::File::FilePrivate +{ +public: + FilePrivate(): + size(0), + tag(0), + properties(0), + contentDescriptionObject(0), + extendedContentDescriptionObject(0), + headerExtensionObject(0), + metadataObject(0), + metadataLibraryObject(0) {} + unsigned long long size; + ASF::Tag *tag; + ASF::Properties *properties; + List<ASF::File::BaseObject *> objects; + ASF::File::ContentDescriptionObject *contentDescriptionObject; + ASF::File::ExtendedContentDescriptionObject *extendedContentDescriptionObject; + ASF::File::HeaderExtensionObject *headerExtensionObject; + ASF::File::MetadataObject *metadataObject; + ASF::File::MetadataLibraryObject *metadataLibraryObject; +}; + +static ByteVector headerGuid("\x30\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C", 16); +static ByteVector filePropertiesGuid("\xA1\xDC\xAB\x8C\x47\xA9\xCF\x11\x8E\xE4\x00\xC0\x0C\x20\x53\x65", 16); +static ByteVector streamPropertiesGuid("\x91\x07\xDC\xB7\xB7\xA9\xCF\x11\x8E\xE6\x00\xC0\x0C\x20\x53\x65", 16); +static ByteVector contentDescriptionGuid("\x33\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C", 16); +static ByteVector extendedContentDescriptionGuid("\x40\xA4\xD0\xD2\x07\xE3\xD2\x11\x97\xF0\x00\xA0\xC9\x5E\xA8\x50", 16); +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); + +class ASF::File::BaseObject +{ +public: + ByteVector data; + virtual ~BaseObject() {} + virtual ByteVector guid() = 0; + virtual void parse(ASF::File *file, unsigned int size); + virtual ByteVector render(ASF::File *file); +}; + +class ASF::File::UnknownObject : public ASF::File::BaseObject +{ + ByteVector myGuid; +public: + UnknownObject(const ByteVector &guid); + ByteVector guid(); +}; + +class ASF::File::FilePropertiesObject : public ASF::File::BaseObject +{ +public: + ByteVector guid(); + void parse(ASF::File *file, uint size); +}; + +class ASF::File::StreamPropertiesObject : public ASF::File::BaseObject +{ +public: + ByteVector guid(); + void parse(ASF::File *file, uint size); +}; + +class ASF::File::ContentDescriptionObject : public ASF::File::BaseObject +{ +public: + ByteVector guid(); + void parse(ASF::File *file, uint size); + ByteVector render(ASF::File *file); +}; + +class ASF::File::ExtendedContentDescriptionObject : public ASF::File::BaseObject +{ +public: + ByteVectorList attributeData; + ByteVector guid(); + void parse(ASF::File *file, uint size); + ByteVector render(ASF::File *file); +}; + +class ASF::File::MetadataObject : public ASF::File::BaseObject +{ +public: + ByteVectorList attributeData; + ByteVector guid(); + void parse(ASF::File *file, uint size); + ByteVector render(ASF::File *file); +}; + +class ASF::File::MetadataLibraryObject : public ASF::File::BaseObject +{ +public: + ByteVectorList attributeData; + ByteVector guid(); + void parse(ASF::File *file, uint size); + ByteVector render(ASF::File *file); +}; + +class ASF::File::HeaderExtensionObject : public ASF::File::BaseObject +{ +public: + List<ASF::File::BaseObject *> objects; + ByteVector guid(); + void parse(ASF::File *file, uint size); + ByteVector render(ASF::File *file); +}; + +void +ASF::File::BaseObject::parse(ASF::File *file, unsigned int size) +{ + data = file->readBlock(size - 24); +} + +ByteVector +ASF::File::BaseObject::render(ASF::File * /*file*/) +{ + return guid() + ByteVector::fromLongLong(data.size() + 24, false) + data; +} + +ASF::File::UnknownObject::UnknownObject(const ByteVector &guid) : myGuid(guid) +{ +} + +ByteVector +ASF::File::UnknownObject::guid() +{ + return myGuid; +} + +ByteVector +ASF::File::FilePropertiesObject::guid() +{ + return filePropertiesGuid; +} + +void +ASF::File::FilePropertiesObject::parse(ASF::File *file, uint size) +{ + BaseObject::parse(file, size); + file->d->properties->setLength((int)(data.mid(40, 8).toLongLong(false) / 10000000L - data.mid(56, 8).toLongLong(false) / 1000L)); +} + +ByteVector +ASF::File::StreamPropertiesObject::guid() +{ + return streamPropertiesGuid; +} + +void +ASF::File::StreamPropertiesObject::parse(ASF::File *file, uint size) +{ + BaseObject::parse(file, size); + file->d->properties->setChannels(data.mid(56, 2).toShort(false)); + file->d->properties->setSampleRate(data.mid(58, 4).toUInt(false)); + file->d->properties->setBitrate(data.mid(62, 4).toUInt(false) * 8 / 1000); +} + +ByteVector +ASF::File::ContentDescriptionObject::guid() +{ + return contentDescriptionGuid; +} + +void +ASF::File::ContentDescriptionObject::parse(ASF::File *file, uint /*size*/) +{ + file->d->contentDescriptionObject = this; + int titleLength = file->readWORD(); + int artistLength = file->readWORD(); + int copyrightLength = file->readWORD(); + int commentLength = file->readWORD(); + int ratingLength = file->readWORD(); + file->d->tag->setTitle(file->readString(titleLength)); + file->d->tag->setArtist(file->readString(artistLength)); + file->d->tag->setCopyright(file->readString(copyrightLength)); + file->d->tag->setComment(file->readString(commentLength)); + file->d->tag->setRating(file->readString(ratingLength)); +} + +ByteVector +ASF::File::ContentDescriptionObject::render(ASF::File *file) +{ + ByteVector v1 = file->renderString(file->d->tag->title()); + ByteVector v2 = file->renderString(file->d->tag->artist()); + ByteVector v3 = file->renderString(file->d->tag->copyright()); + ByteVector v4 = file->renderString(file->d->tag->comment()); + ByteVector v5 = file->renderString(file->d->tag->rating()); + data.clear(); + data.append(ByteVector::fromShort(v1.size(), false)); + data.append(ByteVector::fromShort(v2.size(), false)); + data.append(ByteVector::fromShort(v3.size(), false)); + data.append(ByteVector::fromShort(v4.size(), false)); + data.append(ByteVector::fromShort(v5.size(), false)); + data.append(v1); + data.append(v2); + data.append(v3); + data.append(v4); + data.append(v5); + return BaseObject::render(file); +} + +ByteVector +ASF::File::ExtendedContentDescriptionObject::guid() +{ + return extendedContentDescriptionGuid; +} + +void +ASF::File::ExtendedContentDescriptionObject::parse(ASF::File *file, uint /*size*/) +{ + file->d->extendedContentDescriptionObject = this; + int count = file->readWORD(); + while(count--) { + ASF::Attribute attribute; + String name = attribute.parse(*file); + file->d->tag->addAttribute(name, attribute); + } +} + +ByteVector +ASF::File::ExtendedContentDescriptionObject::render(ASF::File *file) +{ + data.clear(); + data.append(ByteVector::fromShort(attributeData.size(), false)); + data.append(attributeData.toByteVector(ByteVector::null)); + return BaseObject::render(file); +} + +ByteVector +ASF::File::MetadataObject::guid() +{ + return metadataGuid; +} + +void +ASF::File::MetadataObject::parse(ASF::File *file, uint /*size*/) +{ + file->d->metadataObject = this; + int count = file->readWORD(); + while(count--) { + ASF::Attribute attribute; + String name = attribute.parse(*file, 1); + file->d->tag->addAttribute(name, attribute); + } +} + +ByteVector +ASF::File::MetadataObject::render(ASF::File *file) +{ + data.clear(); + data.append(ByteVector::fromShort(attributeData.size(), false)); + data.append(attributeData.toByteVector(ByteVector::null)); + return BaseObject::render(file); +} + +ByteVector +ASF::File::MetadataLibraryObject::guid() +{ + return metadataLibraryGuid; +} + +void +ASF::File::MetadataLibraryObject::parse(ASF::File *file, uint /*size*/) +{ + file->d->metadataLibraryObject = this; + int count = file->readWORD(); + while(count--) { + ASF::Attribute attribute; + String name = attribute.parse(*file, 2); + file->d->tag->addAttribute(name, attribute); + } +} + +ByteVector +ASF::File::MetadataLibraryObject::render(ASF::File *file) +{ + data.clear(); + data.append(ByteVector::fromShort(attributeData.size(), false)); + data.append(attributeData.toByteVector(ByteVector::null)); + return BaseObject::render(file); +} + +ByteVector +ASF::File::HeaderExtensionObject::guid() +{ + return headerExtensionGuid; +} + +void +ASF::File::HeaderExtensionObject::parse(ASF::File *file, uint /*size*/) +{ + file->d->headerExtensionObject = this; + file->seek(18, File::Current); + long long dataSize = file->readDWORD(); + long long dataPos = 0; + while(dataPos < dataSize) { + ByteVector guid = file->readBlock(16); + long long size = file->readQWORD(); + BaseObject *obj; + if(guid == metadataGuid) { + obj = new MetadataObject(); + } + else if(guid == metadataLibraryGuid) { + obj = new MetadataLibraryObject(); + } + else { + obj = new UnknownObject(guid); + } + obj->parse(file, size); + objects.append(obj); + dataPos += size; + } +} + +ByteVector +ASF::File::HeaderExtensionObject::render(ASF::File *file) +{ + data.clear(); + for(unsigned int i = 0; i < objects.size(); i++) { + data.append(objects[i]->render(file)); + } + data = ByteVector("\x11\xD2\xD3\xAB\xBA\xA9\xcf\x11\x8E\xE6\x00\xC0\x0C\x20\x53\x65\x06\x00", 18) + ByteVector::fromUInt(data.size(), false) + data; + return BaseObject::render(file); +} + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +ASF::File::File(const char *file, bool readProperties, Properties::ReadStyle propertiesStyle) + : TagLib::File(file) +{ + d = new FilePrivate; + read(readProperties, propertiesStyle); +} + +ASF::File::~File() +{ + for(unsigned int i = 0; i < d->objects.size(); i++) { + delete d->objects[i]; + } + if(d->tag) { + delete d->tag; + } + if(d->properties) { + delete d->properties; + } + delete d; +} + +ASF::Tag *ASF::File::tag() const +{ + return d->tag; +} + +ASF::Properties *ASF::File::audioProperties() const +{ + return d->properties; +} + +void ASF::File::read(bool /*readProperties*/, Properties::ReadStyle /*propertiesStyle*/) +{ + if(!isValid()) + return; + + ByteVector guid = readBlock(16); + if(guid != headerGuid) { + return; + } + + d->tag = new ASF::Tag(); + d->properties = new ASF::Properties(); + + d->size = readQWORD(); + int numObjects = readDWORD(); + seek(2, Current); + + for(int i = 0; i < numObjects; i++) { + ByteVector guid = readBlock(16); + long size = (long)readQWORD(); + BaseObject *obj; + if(guid == filePropertiesGuid) { + obj = new FilePropertiesObject(); + } + else if(guid == streamPropertiesGuid) { + obj = new StreamPropertiesObject(); + } + else if(guid == contentDescriptionGuid) { + obj = new ContentDescriptionObject(); + } + else if(guid == extendedContentDescriptionGuid) { + obj = new ExtendedContentDescriptionObject(); + } + else if(guid == headerExtensionGuid) { + obj = new HeaderExtensionObject(); + } + else { + obj = new UnknownObject(guid); + } + obj->parse(this, size); + d->objects.append(obj); + } +} + +bool ASF::File::save() +{ + if(readOnly()) { + return false; + } + + if(!d->contentDescriptionObject) { + d->contentDescriptionObject = new ContentDescriptionObject(); + d->objects.append(d->contentDescriptionObject); + } + if(!d->extendedContentDescriptionObject) { + d->extendedContentDescriptionObject = new ExtendedContentDescriptionObject(); + d->objects.append(d->extendedContentDescriptionObject); + } + if(!d->headerExtensionObject) { + d->headerExtensionObject = new HeaderExtensionObject(); + d->objects.append(d->headerExtensionObject); + } + if(!d->metadataObject) { + d->metadataObject = new MetadataObject(); + d->headerExtensionObject->objects.append(d->metadataObject); + } + if(!d->metadataLibraryObject) { + d->metadataLibraryObject = new MetadataLibraryObject(); + d->headerExtensionObject->objects.append(d->metadataLibraryObject); + } + + ASF::AttributeListMap::ConstIterator it = d->tag->attributeListMap().begin(); + for(; it != d->tag->attributeListMap().end(); it++) { + const String &name = it->first; + const AttributeList &attributes = it->second; + bool inExtendedContentDescriptionObject = false; + bool inMetadataObject = false; + for(unsigned int j = 0; j < attributes.size(); j++) { + const Attribute &attribute = attributes[j]; + if(!inExtendedContentDescriptionObject && attribute.language() == 0 && attribute.stream() == 0) { + d->extendedContentDescriptionObject->attributeData.append(attribute.render(name)); + inExtendedContentDescriptionObject = true; + } + else if(!inMetadataObject && attribute.language() == 0 && attribute.stream() != 0) { + d->metadataObject->attributeData.append(attribute.render(name, 1)); + inMetadataObject = true; + } + else { + d->metadataLibraryObject->attributeData.append(attribute.render(name, 2)); + } + } + } + + ByteVector data; + for(unsigned int i = 0; i < d->objects.size(); i++) { + data.append(d->objects[i]->render(this)); + } + data = headerGuid + ByteVector::fromLongLong(data.size() + 30, false) + ByteVector::fromUInt(d->objects.size(), false) + ByteVector("\x01\x02", 2) + data; + insert(data, 0, d->size); + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +int ASF::File::readBYTE() +{ + ByteVector v = readBlock(1); + return v[0]; +} + +int ASF::File::readWORD() +{ + ByteVector v = readBlock(2); + return v.toShort(false); +} + +unsigned int ASF::File::readDWORD() +{ + ByteVector v = readBlock(4); + return v.toUInt(false); +} + +long long ASF::File::readQWORD() +{ + ByteVector v = readBlock(8); + return v.toLongLong(false); +} + +String +ASF::File::readString(int length) +{ + ByteVector data = readBlock(length); + unsigned int size = data.size(); + while (size >= 2) { + if(data[size - 1] != '\0' || data[size - 2] != '\0') { + break; + } + size -= 2; + } + if(size != data.size()) { + data.resize(size); + } + return String(data, String::UTF16LE); +} + +ByteVector +ASF::File::renderString(const String &str, bool includeLength) +{ + ByteVector data = str.data(String::UTF16LE) + ByteVector::fromShort(0, false); + if(includeLength) { + data = ByteVector::fromShort(data.size(), false) + data; + } + return data; +} diff --git a/src/metadata/asf/asffile.h b/src/metadata/asf/asffile.h new file mode 100644 index 0000000..db97331 --- /dev/null +++ b/src/metadata/asf/asffile.h @@ -0,0 +1,114 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : [email protected] + **************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * + * USA * + ***************************************************************************/ + +#ifndef TAGLIB_ASFFILE_H +#define TAGLIB_ASFFILE_H + +#include <tag.h> +#include <tfile.h> +#include "asfproperties.h" +#include "asftag.h" + +namespace TagLib { + + //! An implementation of ASF (WMA) metadata + namespace ASF { + + /*! + * This implements and provides an interface for ASF 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 ASF files. + */ + class File : public TagLib::File + { + public: + + /*! + * Contructs an ASF 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. + * + * \note In the current implementation, both \a readProperties and + * \a propertiesStyle are ignored. + */ + File(const char *file, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns a pointer to the ASF tag of the file. + * + * ASF::Tag implements the tag interface, so this serves as the + * reimplementation of TagLib::File::tag(). + * + * \note The Tag <b>is still</b> owned by the ASF::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + */ + virtual Tag *tag() const; + + /*! + * Returns the ASF audio properties for this file. + */ + virtual Properties *audioProperties() const; + + /*! + * Save the file. + * + * This returns true if the save was successful. + */ + virtual bool save(); + + private: + + int readBYTE(); + int readWORD(); + unsigned int readDWORD(); + long long readQWORD(); + static ByteVector renderString(const String &str, bool includeLength = false); + String readString(int len); + void read(bool readProperties, Properties::ReadStyle propertiesStyle); + + friend class Attribute; + + class BaseObject; + class UnknownObject; + class FilePropertiesObject; + class StreamPropertiesObject; + class ContentDescriptionObject; + class ExtendedContentDescriptionObject; + class HeaderExtensionObject; + class MetadataObject; + class MetadataLibraryObject; + + class FilePrivate; + FilePrivate *d; + }; + + } + +} + +#endif diff --git a/src/metadata/asf/asfproperties.cpp b/src/metadata/asf/asfproperties.cpp new file mode 100644 index 0000000..ca1d983 --- /dev/null +++ b/src/metadata/asf/asfproperties.cpp @@ -0,0 +1,95 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : [email protected] + **************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * + * USA * + ***************************************************************************/ + +#include <tstring.h> +#include "asfproperties.h" + +using namespace TagLib; + +class ASF::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate(): length(0), bitrate(0), sampleRate(0), channels(0) {} + int length; + int bitrate; + int sampleRate; + int channels; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +ASF::Properties::Properties() : AudioProperties(AudioProperties::Average) +{ + d = new PropertiesPrivate; +} + +ASF::Properties::~Properties() +{ + if(d) + delete d; +} + +int ASF::Properties::length() const +{ + return d->length; +} + +int ASF::Properties::bitrate() const +{ + return d->bitrate; +} + +int ASF::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int ASF::Properties::channels() const +{ + return d->channels; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void ASF::Properties::setLength(int length) +{ + d->length = length; +} + +void ASF::Properties::setBitrate(int length) +{ + d->bitrate = length; +} + +void ASF::Properties::setSampleRate(int length) +{ + d->sampleRate = length; +} + +void ASF::Properties::setChannels(int length) +{ + d->channels = length; +} + diff --git a/src/metadata/asf/asfproperties.h b/src/metadata/asf/asfproperties.h new file mode 100644 index 0000000..150db8a --- /dev/null +++ b/src/metadata/asf/asfproperties.h @@ -0,0 +1,69 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : [email protected] + **************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * + * USA * + ***************************************************************************/ + +#ifndef TAGLIB_ASFPROPERTIES_H +#define TAGLIB_ASFPROPERTIES_H + +#include <audioproperties.h> +#include <tstring.h> + +namespace TagLib { + + namespace ASF { + + //! An implementation of ASF audio properties + class Properties : public AudioProperties + { + public: + + /*! + * Create an instance of ASF::Properties. + */ + Properties(); + + /*! + * Destroys this ASF::Properties instance. + */ + virtual ~Properties(); + + // Reimplementations. + virtual int length() const; + virtual int bitrate() const; + virtual int sampleRate() const; + virtual int channels() const; + +#ifndef DO_NOT_DOCUMENT + void setLength(int value); + void setBitrate(int value); + void setSampleRate(int value); + void setChannels(int value); +#endif + + private: + class PropertiesPrivate; + PropertiesPrivate *d; + }; + + } + +} + +#endif diff --git a/src/metadata/asf/asftag.cpp b/src/metadata/asf/asftag.cpp new file mode 100644 index 0000000..300887e --- /dev/null +++ b/src/metadata/asf/asftag.cpp @@ -0,0 +1,202 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : [email protected] + **************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * + * USA * + ***************************************************************************/ + +#include "asftag.h" + +using namespace TagLib; + +class ASF::Tag::TagPrivate +{ +public: + String title; + String artist; + String copyright; + String comment; + String rating; + AttributeListMap attributeListMap; +}; + +ASF::Tag::Tag() +: TagLib::Tag() +{ + d = new TagPrivate; +} + +ASF::Tag::~Tag() +{ + if(d) + delete d; +} + +String +ASF::Tag::title() const +{ + return d->title; +} + +String +ASF::Tag::artist() const +{ + return d->artist; +} + +String +ASF::Tag::album() const +{ + if(d->attributeListMap.contains("WM/AlbumTitle")) + return d->attributeListMap["WM/AlbumTitle"][0].toString(); + return String::null; +} + +String +ASF::Tag::copyright() const +{ + return d->copyright; +} + +String +ASF::Tag::comment() const +{ + return d->comment; +} + +String +ASF::Tag::rating() const +{ + return d->rating; +} + +unsigned int +ASF::Tag::year() const +{ + if(d->attributeListMap.contains("WM/Year")) + return d->attributeListMap["WM/Year"][0].toString().toInt(); + return 0; +} + +unsigned int +ASF::Tag::track() const +{ + if(d->attributeListMap.contains("WM/TrackNumber")) + return d->attributeListMap["WM/TrackNumber"][0].toString().toInt(); + if(d->attributeListMap.contains("WM/Track")) + return d->attributeListMap["WM/Track"][0].toUInt(); + return 0; +} + +String +ASF::Tag::genre() const +{ + if(d->attributeListMap.contains("WM/Genre")) + return d->attributeListMap["WM/Genre"][0].toString(); + return String::null; +} + +void +ASF::Tag::setTitle(const String &value) +{ + d->title = value; +} + +void +ASF::Tag::setArtist(const String &value) +{ + d->artist = value; +} + +void +ASF::Tag::setCopyright(const String &value) +{ + d->copyright = value; +} + +void +ASF::Tag::setComment(const String &value) +{ + d->comment = value; +} + +void +ASF::Tag::setRating(const String &value) +{ + d->rating = value; +} + +void +ASF::Tag::setAlbum(const String &value) +{ + setAttribute("WM/AlbumTitle", value); +} + +void +ASF::Tag::setGenre(const String &value) +{ + setAttribute("WM/Genre", value); +} + +void +ASF::Tag::setYear(uint value) +{ + setAttribute("WM/Year", String::number(value)); +} + +void +ASF::Tag::setTrack(uint value) +{ + setAttribute("WM/TrackNumber", String::number(value)); +} + +ASF::AttributeListMap& +ASF::Tag::attributeListMap() +{ + return d->attributeListMap; +} + +void ASF::Tag::removeItem(const String &key) +{ + AttributeListMap::Iterator it = d->attributeListMap.find(key); + if(it != d->attributeListMap.end()) + d->attributeListMap.erase(it); +} + +void ASF::Tag::setAttribute(const String &name, const Attribute &attribute) +{ + AttributeList value; + value.append(attribute); + d->attributeListMap.insert(name, value); +} + +void ASF::Tag::addAttribute(const String &name, const Attribute &attribute) +{ + if(d->attributeListMap.contains(name)) { + d->attributeListMap[name].append(attribute); + } + else { + setAttribute(name, attribute); + } +} + +bool ASF::Tag::isEmpty() const { + return TagLib::Tag::isEmpty() && + copyright().isEmpty() && + rating().isEmpty() && + d->attributeListMap.isEmpty(); +} diff --git a/src/metadata/asf/asftag.h b/src/metadata/asf/asftag.h new file mode 100644 index 0000000..f282dee --- /dev/null +++ b/src/metadata/asf/asftag.h @@ -0,0 +1,181 @@ +/************************************************************************** + copyright : (C) 2005-2007 by Lukáš Lalinský + email : [email protected] + **************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * + * USA * + ***************************************************************************/ + +#ifndef TAGLIB_ASFTAG_H +#define TAGLIB_ASFTAG_H + +#include <tag.h> +#include <tlist.h> +#include <tmap.h> +#include "asfattribute.h" + +namespace TagLib { + + namespace ASF { + + typedef List<Attribute> AttributeList; + typedef Map<String, AttributeList> AttributeListMap; + + class Tag : public TagLib::Tag { + + friend class File; + + public: + + Tag(); + + virtual ~Tag(); + + /*! + * Returns the track name. + */ + virtual String title() const; + + /*! + * Returns the artist name. + */ + virtual String artist() const; + + /*! + * Returns the album name; if no album name is present in the tag + * String::null will be returned. + */ + virtual String album() const; + + /*! + * Returns the track comment. + */ + virtual String comment() const; + + /*! + * Returns the genre name; if no genre is present in the tag String::null + * will be returned. + */ + virtual String genre() const; + + /*! + * Returns the rating. + */ + virtual String rating() const; + + /*! + * Returns the genre name; if no genre is present in the tag String::null + * will be returned. + */ + virtual String copyright() const; + + /*! + * Returns the year; if there is no year set, this will return 0. + */ + virtual uint year() const; + + /*! + * Returns the track number; if there is no track number set, this will + * return 0. + */ + virtual uint track() const; + + /*! + * Sets the title to \a s. + */ + virtual void setTitle(const String &s); + + /*! + * Sets the artist to \a s. + */ + virtual void setArtist(const String &s); + + /*! + * Sets the album to \a s. If \a s is String::null then this value will be + * cleared. + */ + virtual void setAlbum(const String &s); + + /*! + * Sets the comment to \a s. + */ + virtual void setComment(const String &s); + + /*! + * Sets the rating to \a s. + */ + virtual void setRating(const String &s); + + /*! + * Sets the copyright to \a s. + */ + virtual void setCopyright(const String &s); + + /*! + * Sets the genre to \a s. + */ + virtual void setGenre(const String &s); + + /*! + * Sets the year to \a i. If \a s is 0 then this value will be cleared. + */ + virtual void setYear(uint i); + + /*! + * Sets the track to \a i. If \a s is 0 then this value will be cleared. + */ + virtual void setTrack(uint i); + + /*! + * Returns true if the tag does not contain any data. This should be + * reimplemented in subclasses that provide more than the basic tagging + * abilities in this class. + */ + virtual bool isEmpty() const; + + /*! + * Returns a reference to the item list map. This is an AttributeListMap of + * all of the items in the tag. + * + * This is the most powerfull structure for accessing the items of the tag. + */ + AttributeListMap &attributeListMap(); + + /*! + * Removes the \a key attribute from the tag + */ + void removeItem(const String &name); + + /*! + * Sets the \a key attribute to the value of \a attribute. If an attribute + * with the \a key is already present, it will be replaced. + */ + void setAttribute(const String &name, const Attribute &attribute); + + /*! + * Sets the \a key attribute to the value of \a attribute. If an attribute + * with the \a key is already present, it will be added to the list. + */ + void addAttribute(const String &name, const Attribute &attribute); + + private: + + class TagPrivate; + TagPrivate *d; + }; + } +} +#endif diff --git a/src/metadata/asf/taglib_asffiletyperesolver.cpp b/src/metadata/asf/taglib_asffiletyperesolver.cpp new file mode 100644 index 0000000..f9ed059 --- /dev/null +++ b/src/metadata/asf/taglib_asffiletyperesolver.cpp @@ -0,0 +1,47 @@ +/*************************************************************************** + copyright : (C) 2005 by Martin Aumueller + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +// (c) 2005 Martin Aumueller <[email protected]> +// See COPYING file for licensing information + +#include "taglib_asffiletyperesolver.h" +#include "asffile.h" + +#include <string.h> + +TagLib::File *ASFFileTypeResolver::createFile(const char *fileName, + bool readProperties, + TagLib::AudioProperties::ReadStyle propertiesStyle) const +{ + const char *ext = strrchr(fileName, '.'); + if(ext && (!strcasecmp(ext, ".wma") || !strcasecmp(ext, ".asf"))) + { + TagLib::ASF::File *f = new TagLib::ASF::File(fileName, readProperties, propertiesStyle); + if(f->isValid()) + return f; + else + { + delete f; + } + } + + return 0; +} diff --git a/src/metadata/asf/taglib_asffiletyperesolver.h b/src/metadata/asf/taglib_asffiletyperesolver.h new file mode 100644 index 0000000..ab524b4 --- /dev/null +++ b/src/metadata/asf/taglib_asffiletyperesolver.h @@ -0,0 +1,42 @@ +/*************************************************************************** + copyright : (C) 2005 by Martin Aumueller + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +// (c) 2005 Martin Aumueller <[email protected]> +// See COPYING file for licensing information + +#ifndef TAGLIB_ASFFILETYPERESOLVER_H +#define TAGLIB_ASFFILETYPERESOLVER_H + +#include <taglib/tfile.h> +#include <taglib/fileref.h> + + +class ASFFileTypeResolver : public TagLib::FileRef::FileTypeResolver +{ + TagLib::File *createFile(const char *fileName, + bool readAudioProperties, + TagLib::AudioProperties::ReadStyle audioPropertiesStyle) const; + +public: + virtual ~ASFFileTypeResolver() {} +}; + +#endif diff --git a/src/metadata/audible/Makefile.am b/src/metadata/audible/Makefile.am new file mode 100644 index 0000000..dcade34 --- /dev/null +++ b/src/metadata/audible/Makefile.am @@ -0,0 +1,17 @@ +SUBDIRS = + +INCLUDES = $(all_includes) $(taglib_includes) +METASOURCES = AUTO +libtagaudible_la_LDFLAGS = $(all_libraries) +noinst_LTLIBRARIES = libtagaudible.la + +libtagaudible_la_SOURCES = audibleproperties.cpp \ + audibletag.cpp \ + taglib_audiblefile.cpp \ + taglib_audiblefiletyperesolver.cpp + +noinst_HEADERS = audibleproperties.h \ + audibletag.h \ + taglib_audiblefile.h \ + taglib_audiblefiletyperesolver.h + diff --git a/src/metadata/audible/audibleproperties.cpp b/src/metadata/audible/audibleproperties.cpp new file mode 100644 index 0000000..4f39322 --- /dev/null +++ b/src/metadata/audible/audibleproperties.cpp @@ -0,0 +1,86 @@ +/*************************************************************************** + copyright : (C) 2005 by Martin Aumueller + email : [email protected] + + copyright : (C) 2005 by Andy Leadbetter + email : [email protected] + (original mp4 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <stdio.h> + +#include "audibleproperties.h" + +#include <taglib/tstring.h> + +#include "taglib_audiblefile.h" + +#include <netinet/in.h> // ntohl + +using namespace TagLib; + + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Audible::Properties::Properties(Properties::ReadStyle style) : AudioProperties(style) +{ + m_length = 0; + m_bitrate = 0; + m_sampleRate = 0; + m_channels = 0; +} + +Audible::Properties::~Properties() +{ +} + +int Audible::Properties::length() const +{ + return m_length; +} + +int Audible::Properties::bitrate() const +{ + return m_bitrate; +} + +int Audible::Properties::sampleRate() const +{ + return m_sampleRate; +} + +int Audible::Properties::channels() const +{ + return m_channels; +} + +#define LENGTH_OFF 61 + +void Audible::Properties::readAudibleProperties( FILE *fp, int off ) +{ + fseek(fp, off+LENGTH_OFF, SEEK_SET ); + fread(&m_length, sizeof(m_length), 1, fp); + m_length = ntohl(m_length); + //fprintf(stderr, "len (sec): %d\n", m_length); + m_bitrate = 0; + m_sampleRate = 0; + m_channels = 1; +} diff --git a/src/metadata/audible/audibleproperties.h b/src/metadata/audible/audibleproperties.h new file mode 100644 index 0000000..948fc30 --- /dev/null +++ b/src/metadata/audible/audibleproperties.h @@ -0,0 +1,85 @@ +/*************************************************************************** + copyright : (C) 2005 by Martin Aumueller + email : [email protected] + + copyright : (C) 2005 by Andy Leadbetter + email : [email protected] + (original mp4 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_AUDIBLEPROPERTIES_H +#define TAGLIB_AUDIBLEPROPERTIES_H + +#include <config.h> + +#include <taglib/audioproperties.h> +#include <taglib/tstring.h> + +namespace TagLib { + + namespace Audible { + + class File; + + /*! + * This reads the data from a Audible stream to support the + * AudioProperties API. + */ + + class Properties : public AudioProperties + { + public: + /*! + * Initialize this structure + */ + Properties(Properties::ReadStyle style); + + /*! + * Destroys this Audible Properties instance. + */ + virtual ~Properties(); + + // Reimplementations. + + virtual int length() const; + virtual int bitrate() const; + virtual int sampleRate() const; + virtual int channels() const; + + void readAudibleProperties(FILE *file, int off); + + + private: + void readAudioTrackProperties(FILE *file); + friend class Audible::File; + + int m_length; + int m_bitrate; + int m_sampleRate; + int m_channels; + + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(); + }; + } +} + +#endif diff --git a/src/metadata/audible/audibletag.cpp b/src/metadata/audible/audibletag.cpp new file mode 100644 index 0000000..0fe786f --- /dev/null +++ b/src/metadata/audible/audibletag.cpp @@ -0,0 +1,163 @@ +/*************************************************************************** + copyright : (C) 2005 by Martin Aumueller + email : [email protected] + + copyright : (C) 2005 by Andy Leadbetter + email : [email protected] + (original mp4 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <stdio.h> + +#include "audibletag.h" + +#include <taglib/tag.h> + +#include <netinet/in.h> // ntohl +#include <stdlib.h> +#include <string.h> + +using namespace TagLib; + +Audible::Tag::Tag() : TagLib::Tag::Tag() { + m_title = String::null; + m_artist = String::null; + m_album = String::null; + m_comment = String::null; + m_genre = String::null; + m_year = 0; + m_track = 0; + m_userID = 0; + m_tagsEndOffset = -1; +} + +Audible::Tag::~Tag() { +} + +bool Audible::Tag::isEmpty() const { + return m_title == String::null && + m_artist == String::null && + m_album == String::null && + m_comment == String::null && + m_genre == String::null && + m_year == 0 && + m_track == 0 && + m_userID == 0; +} + +void Audible::Tag::duplicate(const Tag *source, Tag *target, bool overwrite) { + // No nonstandard information stored yet + Tag::duplicate(source, target, overwrite); +} + +#define OFF_PRODUCT_ID 197 +#define OFF_TAGS 189 + +void Audible::Tag::readTags( FILE *fp ) +{ + char buf[1023]; + fseek(fp, OFF_PRODUCT_ID, SEEK_SET); + fread(buf, strlen("product_id"), 1, fp); + if(memcmp(buf, "product_id", strlen("product_id"))) + { + buf[20]='\0'; + fprintf(stderr, "no valid Audible aa file: %s\n", buf); + return; + } + + // Now parse tag. + + fseek(fp, OFF_TAGS, SEEK_SET); + char *name, *value; + + m_tagsEndOffset = OFF_TAGS; + + bool lasttag = false; + while(!lasttag) + { + lasttag = !readTag(fp, &name, &value); + if(!strcmp(name, "title")) + { + m_title = String(value, String::Latin1); + } + else if(!strcmp(name, "author")) + { + m_artist = String(value, String::Latin1); + } + else if(!strcmp(name, "long_description")) + { + m_comment = String(value, String::Latin1); + } + else if(!strcmp(name, "description")) + { + if( m_comment.isNull() ) + m_comment = String(value, String::Latin1); + } + else if(!strcmp(name, "pubdate")) + { + m_year = 0; + char *p = strrchr(value, '-'); + if(p) + m_year = strtol(p+1, NULL, 10); + } + else if(!strcmp(name, "user_id")) + { + m_userID = strtol(value, NULL, 10); + } + + delete[] name; + delete[] value; + } + + m_album = String("", String::Latin1); + m_track = 0; + m_genre = String("Audiobook", String::Latin1); +} + +bool Audible::Tag::readTag( FILE *fp, char **name, char **value) +{ + uint32_t nlen; + fread(&nlen, sizeof(nlen), 1, fp); + nlen = ntohl(nlen); + //fprintf(stderr, "tagname len=%x\n", (unsigned)nlen); + *name = new char[nlen+1]; + (*name)[nlen] = '\0'; + + uint32_t vlen; + fread(&vlen, sizeof(vlen), 1, fp); + vlen = ntohl(vlen); + //fprintf(stderr, "tag len=%x\n", (unsigned)vlen); + *value = new char[vlen+1]; + (*value)[vlen] = '\0'; + + fread(*name, nlen, 1, fp); + fread(*value, vlen, 1, fp); + char lasttag; + fread(&lasttag, 1, 1, fp); + //fprintf(stderr, "%s: \"%s\"\n", *name, *value); + + m_tagsEndOffset += 2 * 4 + nlen + vlen + 1; + + return !lasttag; +} + +int Audible::Tag::getTagsEndOffset() +{ + return m_tagsEndOffset; +} diff --git a/src/metadata/audible/audibletag.h b/src/metadata/audible/audibletag.h new file mode 100644 index 0000000..f03966f --- /dev/null +++ b/src/metadata/audible/audibletag.h @@ -0,0 +1,185 @@ +/*************************************************************************** + copyright : (C) 2005 by Martin Aumueller + email : [email protected] + + copyright : (C) 2005 by Andy Leadbetter + email : [email protected] + (original mp4 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_AUDIBLETAG_H +#define TAGLIB_AUDIBLETAG_H + +#include <config.h> + +#include <taglib/tag.h> +#include "taglib_audiblefile.h" + +namespace TagLib { + + namespace Audible { + /*! + * This implements the generic TagLib::Tag API + */ + class Tag : public TagLib::Tag + { + public: + Tag(); + + /*! + * read tags from the aa file. + */ + void readTags( FILE *file ); + + /*! + * Destroys this AudibleTag instance. + */ + virtual ~Tag(); + + /*! + * Returns the track name; if no track name is present in the tag + * String::null will be returned. + */ + virtual String title() const { return m_title; } + + /*! + * Returns the artist name; if no artist name is present in the tag + * String::null will be returned. + */ + virtual String artist() const { return m_artist; } + + /*! + * Returns the album name; if no album name is present in the tag + * String::null will be returned. + */ + virtual String album() const { return m_album; } + + /*! + * Returns the track comment; if no comment is present in the tag + * String::null will be returned. + */ + virtual String comment() const { return m_comment; } + + /*! + * Returns the genre name; if no genre is present in the tag String::null + * will be returned. + */ + virtual String genre() const { return m_genre; } + + /*! + * Returns the year; if there is no year set, this will return 0. + */ + virtual uint year() const { return m_year; } + + /*! + * Returns the track number; if there is no track number set, this will + * return 0. + */ + virtual uint track() const { return m_track; } + + /*! + * Returns the user id for this file. + */ + virtual uint userID() const { return m_userID; } + + /*! + * Sets the title to \a s. If \a s is String::null then this value will be + * cleared. + */ + virtual void setTitle(const String &s) { m_title = s; } + + /*! + * Sets the artist to \a s. If \a s is String::null then this value will be + * cleared. + */ + virtual void setArtist(const String &s) { m_artist = s; } + + /*! + * Sets the album to \a s. If \a s is String::null then this value will be + * cleared. + */ + virtual void setAlbum(const String &s) { m_album = s; } + + /*! + * Sets the album to \a s. If \a s is String::null then this value will be + * cleared. + */ + virtual void setComment(const String &s) { m_comment = s; } + + /*! + * Sets the genre to \a s. If \a s is String::null then this value will be + * cleared. For tag formats that use a fixed set of genres, the appropriate + * value will be selected based on a string comparison. A list of available + * genres for those formats should be available in that type's + * implementation. + */ + virtual void setGenre(const String &s) { m_genre = s; } + + /*! + * Sets the year to \a i. If \a s is 0 then this value will be cleared. + */ + virtual void setYear(uint i) { m_year = i; } + + /*! + * Sets the track to \a i. If \a s is 0 then this value will be cleared. + */ + virtual void setTrack(uint i) { m_track = i; } + + /*! + * Returns true if the tag does not contain any data. This should be + * reimplemented in subclasses that provide more than the basic tagging + * abilities in this class. + */ + virtual bool isEmpty() const; + + /*! + * Copies the generic data from one tag to another. + * + * \note This will not affect any of the lower level details of the tag. For + * instance if any of the tag type specific data (maybe a URL for a band) is + * set, this will not modify or copy that. This just copies using the API + * in this class. + * + * If \a overwrite is true then the values will be unconditionally copied. + * If false only empty values will be overwritten. + */ + static void duplicate(const Tag *source, Tag *target, bool overwrite = true); + + virtual void setUserID(uint id) { m_userID = id; } + + int getTagsEndOffset(); + + + + protected: + String m_title; + String m_artist; + String m_album; + String m_comment; + String m_genre; + uint m_year; + uint m_track; + uint m_userID; + bool readTag( FILE *fp, char **name, char **value); + int m_tagsEndOffset; + }; + } +} + +#endif diff --git a/src/metadata/audible/taglib_audiblefile.cpp b/src/metadata/audible/taglib_audiblefile.cpp new file mode 100644 index 0000000..47f5182 --- /dev/null +++ b/src/metadata/audible/taglib_audiblefile.cpp @@ -0,0 +1,121 @@ +/*************************************************************************** + copyright : (C) 2005 by Martin Aumueller + email : [email protected] + + copyright : (C) 2005 by Andy Leadbetter + email : [email protected] + (original mp4 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <stdio.h> + +#include "taglib_audiblefile.h" + +#include "audibletag.h" +#include <taglib/tfile.h> +#include <taglib/audioproperties.h> + +namespace TagLib { +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Audible::File::File(const char *file, + bool readProperties, + Properties::ReadStyle propertiesStyle, + FILE *fp) + : TagLib::File(file) + , audibletag( NULL ) + , properties( NULL ) +{ + + // debug ("Audible::File: create new file object."); + //debug ( file ); + + /** + * Create the Audible file. + */ + + if(fp) + audiblefile = fp; + else + audiblefile = fopen(file, "rb"); + + if( isOpen() ) + { + read(readProperties, propertiesStyle ); + } +} + +Audible::File::~File() +{ + if(audiblefile) + fclose(audiblefile); + delete audibletag; + delete properties; +} + +TagLib::Tag *Audible::File::tag() const +{ + return audibletag; +} + +TagLib::Audible::Tag *Audible::File::getAudibleTag() const +{ + return audibletag; +} + +Audible::Properties *Audible::File::audioProperties() const +{ + return properties; +} + +bool Audible::File::save() +{ + return false; +} + +bool Audible::File::isOpen() +{ + return audiblefile != NULL; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void Audible::File::read(bool readProperties, Properties::ReadStyle propertiesStyle) +{ + properties = new Audible::Properties(propertiesStyle); + audibletag = new Audible::Tag(); + + if (audiblefile != NULL) { + audibletag->readTags( audiblefile ); + int off = audibletag->getTagsEndOffset(); + //fprintf(stderr, "off=%d\n", off); + + if(readProperties) + { + // Parse bitrate etc. + properties->readAudibleProperties( audiblefile, off ); + } + } +} + +} diff --git a/src/metadata/audible/taglib_audiblefile.h b/src/metadata/audible/taglib_audiblefile.h new file mode 100644 index 0000000..c1860ae --- /dev/null +++ b/src/metadata/audible/taglib_audiblefile.h @@ -0,0 +1,93 @@ +/*************************************************************************** + copyright : (C) 2005 by Martin Aumueller + email : [email protected] + + copyright : (C) 2005 by Andy Leadbetter + email : [email protected] + (original mp4 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_AUDIBLEFILE_H +#define TAGLIB_AUDIBLEFILE_H + +#include <taglib/tfile.h> +#include "audibleproperties.h" +#include "audibletag.h" + +namespace TagLib { + + namespace Audible { + + class Tag; + + class File : public TagLib::File + { + public: + /*! + * Contructs a Audible 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(const char *file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average, + FILE *fp=NULL); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + + virtual TagLib::Tag *tag() const; + + /*! + * Returns the Audible::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Audible::Properties *audioProperties() const; + + /*! + * Save the file. + * This is the same as calling save(AllTags); + * + * \note As of now, saving Audible tags is not supported. + */ + virtual bool save(); + + void read(bool readProperties, Properties::ReadStyle propertiesStyle); + + Audible::Tag *getAudibleTag() const; + + bool isAudibleFile() const; + + protected: + File(const File &); + File &operator=(const File &); + bool isOpen(); + + + Audible::Tag *audibletag; + Audible::Properties *properties; + + FILE *audiblefile; + }; + } +} + +#endif diff --git a/src/metadata/audible/taglib_audiblefiletyperesolver.cpp b/src/metadata/audible/taglib_audiblefiletyperesolver.cpp new file mode 100644 index 0000000..152b17c --- /dev/null +++ b/src/metadata/audible/taglib_audiblefiletyperesolver.cpp @@ -0,0 +1,44 @@ +/*************************************************************************** + copyright : (C) 2005 by Martin Aumueller + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <stdio.h> + +#include "taglib_audiblefiletyperesolver.h" +#include "taglib_audiblefile.h" + +#include <string.h> + +TagLib::File *AudibleFileTypeResolver::createFile(const char *fileName, + bool readProperties, + TagLib::AudioProperties::ReadStyle propertiesStyle) const +{ + const char *ext = strrchr(fileName, '.'); + if(ext && !strcasecmp(ext, ".aa")) + { + FILE *fp = fopen(fileName, "rb"); + if(!fp) + return 0; + + return new TagLib::Audible::File(fileName, readProperties, propertiesStyle, fp); + } + + return 0; +} diff --git a/src/metadata/audible/taglib_audiblefiletyperesolver.h b/src/metadata/audible/taglib_audiblefiletyperesolver.h new file mode 100644 index 0000000..6f1e705 --- /dev/null +++ b/src/metadata/audible/taglib_audiblefiletyperesolver.h @@ -0,0 +1,36 @@ +/*************************************************************************** + copyright : (C) 2005 by Martin Aumueller + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_AUDIBLEFILETYPERESOLVER_H +#define TAGLIB_AUDIBLEFILETYPERESOLVER_H + +#include <taglib/tfile.h> +#include <taglib/fileref.h> + + +class AudibleFileTypeResolver : public TagLib::FileRef::FileTypeResolver +{ + TagLib::File *createFile(const char *fileName, + bool readAudioProperties, + TagLib::AudioProperties::ReadStyle audioPropertiesStyle) const; +}; + +#endif diff --git a/src/metadata/m4a/Makefile.am b/src/metadata/m4a/Makefile.am new file mode 100644 index 0000000..34d9af4 --- /dev/null +++ b/src/metadata/m4a/Makefile.am @@ -0,0 +1,84 @@ +SUBDIRS = +METASOURCES = AUTO +INCLUDES = $(all_includes) $(taglib_includes) + +libtagm4a_la_LDFLAGS = $(all_libraries) +noinst_LTLIBRARIES = libtagm4a.la + +libtagm4a_la_SOURCES = \ + taglib_mp4filetyperesolver.cpp \ + mp4file.cpp \ + mp4itunestag.cpp \ + mp4isobox.cpp \ + mp4isofullbox.cpp \ + mp4skipbox.cpp \ + mp4moovbox.cpp \ + mp4mvhdbox.cpp \ + mp4ilstbox.cpp \ + boxfactory.cpp \ + mp4fourcc.cpp \ + mp4udtabox.cpp \ + mp4metabox.cpp \ + mp4tagsproxy.cpp \ + mp4mdiabox.cpp \ + mp4minfbox.cpp \ + mp4audioproperties.cpp \ + mp4hdlrbox.cpp \ + mp4stblbox.cpp \ + mp4audiosampleentry.cpp \ + mp4stsdbox.cpp \ + mp4sampleentry.cpp \ + mp4trakbox.cpp \ + mp4propsproxy.cpp \ + itunesnambox.cpp \ + itunesartbox.cpp \ + itunesalbbox.cpp \ + itunescvrbox.cpp \ + itunesgenbox.cpp \ + itunestrknbox.cpp \ + itunesdaybox.cpp \ + itunescmtbox.cpp \ + itunesgrpbox.cpp \ + ituneswrtbox.cpp \ + itunesdiskbox.cpp \ + itunestmpobox.cpp \ + itunesdatabox.cpp + +noinst_HEADERS = \ + taglib_mp4filetyperesolver.h \ + mp4file.h \ + mp4itunestag.h \ + mp4isobox.h \ + mp4isofullbox.h \ + mp4skipbox.h \ + mp4moovbox.h \ + mp4mvhdbox.h \ + mp4ilstbox.h \ + boxfactory.h \ + mp4fourcc.h \ + mp4udtabox.h \ + mp4metabox.h \ + mp4tagsproxy.h \ + mp4audioproperties.h \ + mp4hdlrbox.h \ + mp4propsproxy.h \ + mp4mdiabox.h \ + mp4stsdbox.h \ + mp4trakbox.h \ + mp4stblbox.h \ + mp4audiosampleentry.h \ + mp4minfbox.h \ + mp4sampleentry.h \ + itunesnambox.h \ + itunesartbox.h \ + itunesalbbox.h \ + itunesgenbox.h \ + itunestrknbox.h \ + itunesdaybox.h \ + itunescmtbox.h \ + itunescvrbox.h \ + itunesgrpbox.h \ + ituneswrtbox.h \ + itunesdiskbox.h \ + itunestmpobox.h \ + itunesdatabox.h diff --git a/src/metadata/m4a/boxfactory.cpp b/src/metadata/m4a/boxfactory.cpp new file mode 100644 index 0000000..0fc8eb4 --- /dev/null +++ b/src/metadata/m4a/boxfactory.cpp @@ -0,0 +1,150 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <iostream> +#include "tstring.h" +#include "boxfactory.h" +#include "mp4skipbox.h" +#include "mp4moovbox.h" +#include "mp4mvhdbox.h" +#include "mp4trakbox.h" +#include "mp4mdiabox.h" +#include "mp4minfbox.h" +#include "mp4stblbox.h" +#include "mp4stsdbox.h" +#include "mp4hdlrbox.h" +#include "mp4udtabox.h" +#include "mp4metabox.h" +#include "mp4ilstbox.h" +#include "itunesnambox.h" +#include "itunesartbox.h" +#include "itunesalbbox.h" +#include "itunesgenbox.h" +#include "itunesdaybox.h" +#include "itunestrknbox.h" +#include "itunescmtbox.h" +#include "itunesgrpbox.h" +#include "ituneswrtbox.h" +#include "itunesdiskbox.h" +#include "itunestmpobox.h" +#include "itunescvrbox.h" +#include "itunesdatabox.h" + +using namespace TagLib; + +MP4::BoxFactory::BoxFactory() +{ +} + +MP4::BoxFactory::~BoxFactory() +{ +} + +//! factory function +MP4::Mp4IsoBox* MP4::BoxFactory::createInstance( TagLib::File* anyfile, MP4::Fourcc fourcc, uint size, long offset ) const +{ + MP4::File * file = dynamic_cast<MP4::File *>(anyfile); + if(!file) + return 0; + + //std::cout << "creating box for: " << fourcc.toString() << std::endl; + + switch( fourcc ) + { + case 0x6d6f6f76: // 'moov' + return new MP4::Mp4MoovBox( file, fourcc, size, offset ); + break; + case 0x6d766864: // 'mvhd' + return new MP4::Mp4MvhdBox( file, fourcc, size, offset ); + break; + case 0x7472616b: // 'trak' + return new MP4::Mp4TrakBox( file, fourcc, size, offset ); + break; + case 0x6d646961: // 'mdia' + return new MP4::Mp4MdiaBox( file, fourcc, size, offset ); + break; + case 0x6d696e66: // 'minf' + return new MP4::Mp4MinfBox( file, fourcc, size, offset ); + break; + case 0x7374626c: // 'stbl' + return new MP4::Mp4StblBox( file, fourcc, size, offset ); + break; + case 0x73747364: // 'stsd' + return new MP4::Mp4StsdBox( file, fourcc, size, offset ); + break; + case 0x68646c72: // 'hdlr' + return new MP4::Mp4HdlrBox( file, fourcc, size, offset ); + break; + case 0x75647461: // 'udta' + return new MP4::Mp4UdtaBox( file, fourcc, size, offset ); + break; + case 0x6d657461: // 'meta' + return new MP4::Mp4MetaBox( file, fourcc, size, offset ); + break; + case 0x696c7374: // 'ilst' + return new MP4::Mp4IlstBox( file, fourcc, size, offset ); + break; + case 0xa96e616d: // '_nam' + return new MP4::ITunesNamBox( file, fourcc, size, offset ); + break; + case 0xa9415254: // '_ART' + return new MP4::ITunesArtBox( file, fourcc, size, offset ); + break; + case 0xa9616c62: // '_alb' + return new MP4::ITunesAlbBox( file, fourcc, size, offset ); + break; + case 0xa967656e: // '_gen' + return new MP4::ITunesGenBox( file, fourcc, size, offset ); + break; + case 0x676e7265: // 'gnre' + return new MP4::ITunesGenBox( file, fourcc, size, offset ); + break; + case 0xa9646179: // '_day' + return new MP4::ITunesDayBox( file, fourcc, size, offset ); + break; + case 0x74726b6e: // 'trkn' + return new MP4::ITunesTrknBox( file, fourcc, size, offset ); + break; + case 0xa9636d74: // '_cmt' + return new MP4::ITunesCmtBox( file, fourcc, size, offset ); + break; + case 0xa9677270: // '_grp' + return new MP4::ITunesGrpBox( file, fourcc, size, offset ); + break; + case 0xa9777274: // '_wrt' + return new MP4::ITunesWrtBox( file, fourcc, size, offset ); + break; + case 0x6469736b: // 'disk' + return new MP4::ITunesDiskBox( file, fourcc, size, offset ); + break; + case 0x746d706f: // 'tmpo' + return new MP4::ITunesTmpoBox( file, fourcc, size, offset ); + break; + case 0x636f7672: // 'covr' + return new MP4::ITunesCvrBox( file, fourcc, size, offset ); + break; + case 0x64616461: // 'data' + return new MP4::ITunesDataBox( file, fourcc, size, offset ); + break; + default: + return new MP4::Mp4SkipBox( file, fourcc, size, offset ); + } +} diff --git a/src/metadata/m4a/boxfactory.h b/src/metadata/m4a/boxfactory.h new file mode 100644 index 0000000..7edcd6c --- /dev/null +++ b/src/metadata/m4a/boxfactory.h @@ -0,0 +1,45 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef BOXFACTORY_H +#define BOXFACTORY_H + +#include "taglib.h" +#include "mp4isobox.h" + +namespace TagLib +{ + namespace MP4 + { + class BoxFactory + { + public: + BoxFactory(); + ~BoxFactory(); + + //! factory function + Mp4IsoBox* createInstance( TagLib::File* anyfile, MP4::Fourcc fourcc, uint size, long offset ) const; + }; // class BoxFactory + + } // namepace MP4 +} // namepace TagLib + +#endif // BOXFACTORY_H diff --git a/src/metadata/m4a/itunesalbbox.cpp b/src/metadata/m4a/itunesalbbox.cpp new file mode 100644 index 0000000..5832fa0 --- /dev/null +++ b/src/metadata/m4a/itunesalbbox.cpp @@ -0,0 +1,89 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <iostream> +#include "itunesalbbox.h" +#include "itunesdatabox.h" +#include "mp4isobox.h" +#include "mp4file.h" +#include "tfile.h" +#include "mp4tagsproxy.h" + +using namespace TagLib; + +class MP4::ITunesAlbBox::ITunesAlbBoxPrivate +{ +public: + ITunesDataBox* dataBox; +}; + +MP4::ITunesAlbBox::ITunesAlbBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) + :Mp4IsoBox(file, fourcc, size, offset) +{ + d = new MP4::ITunesAlbBox::ITunesAlbBoxPrivate(); + d->dataBox = 0; +} + +MP4::ITunesAlbBox::~ITunesAlbBox() +{ + if( d->dataBox != 0 ) + delete d->dataBox; + delete d; +} + +//! parse the content of the box +void MP4::ITunesAlbBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() ); + + // parse data box + TagLib::uint size; + MP4::Fourcc fourcc; + + if(mp4file->readSizeAndType( size, fourcc ) == true) + { + // check for type - must be 'data' + if( fourcc != MP4::Fourcc("data") ) + { + std::cerr << "bad atom in itunes tag - skipping it." << std::endl; + // jump over data tag + mp4file->seek( size-8, TagLib::File::Current ); + return; + } + d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() ); + d->dataBox->parsebox(); + } + else + { + // reading unsuccessful - serious error! + std::cerr << "Error in parsing ITunesAlbBox - serious Error in taglib!" << std::endl; + return; + } + // register data box + mp4file->tagProxy()->registerBox( Mp4TagsProxy::album, d->dataBox ); + +#if 0 + // get data pointer - just for debugging... + TagLib::String dataString( d->dataBox->data() ); + std::cout << "Content of album box: " << dataString << std::endl; +#endif +} + diff --git a/src/metadata/m4a/itunesalbbox.h b/src/metadata/m4a/itunesalbbox.h new file mode 100644 index 0000000..f2462c2 --- /dev/null +++ b/src/metadata/m4a/itunesalbbox.h @@ -0,0 +1,50 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef ITUNESALBBOX_H +#define ITUNESALBBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class ITunesAlbBox: public Mp4IsoBox + { + public: + ITunesAlbBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + ~ITunesAlbBox(); + + private: + //! parse the content of the box + virtual void parse(); + + protected: + class ITunesAlbBoxPrivate; + ITunesAlbBoxPrivate* d; + }; // class ITunesAlbBox + + } // namespace MP4 +} // namespace TagLib + +#endif // ITUNESALBBOX_H diff --git a/src/metadata/m4a/itunesartbox.cpp b/src/metadata/m4a/itunesartbox.cpp new file mode 100644 index 0000000..19e717d --- /dev/null +++ b/src/metadata/m4a/itunesartbox.cpp @@ -0,0 +1,89 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <iostream> +#include "itunesartbox.h" +#include "itunesdatabox.h" +#include "mp4isobox.h" +#include "mp4file.h" +#include "tfile.h" +#include "mp4tagsproxy.h" + +using namespace TagLib; + +class MP4::ITunesArtBox::ITunesArtBoxPrivate +{ +public: + ITunesDataBox* dataBox; +}; + +MP4::ITunesArtBox::ITunesArtBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) + :Mp4IsoBox(file, fourcc, size, offset) +{ + d = new MP4::ITunesArtBox::ITunesArtBoxPrivate(); + d->dataBox = 0; +} + +MP4::ITunesArtBox::~ITunesArtBox() +{ + if( d->dataBox != 0 ) + delete d->dataBox; + delete d; +} + +//! parse the content of the box +void MP4::ITunesArtBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() ); + + // parse data box + TagLib::uint size; + MP4::Fourcc fourcc; + + if(mp4file->readSizeAndType( size, fourcc ) == true) + { + // check for type - must be 'data' + if( fourcc != MP4::Fourcc("data") ) + { + std::cerr << "bad atom in itunes tag - skipping it." << std::endl; + // jump over data tag + mp4file->seek( size-8, TagLib::File::Current ); + return; + } + d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() ); + d->dataBox->parsebox(); + } + else + { + // reading unsuccessful - serious error! + std::cerr << "Error in parsing ITunesArtBox - serious Error in taglib!" << std::endl; + return; + } + // register data box + mp4file->tagProxy()->registerBox( Mp4TagsProxy::artist, d->dataBox ); + +#if 0 + // get data pointer - just for debugging... + TagLib::String dataString( d->dataBox->data() ); + std::cout << "Content of artist box: " << dataString << std::endl; +#endif +} + diff --git a/src/metadata/m4a/itunesartbox.h b/src/metadata/m4a/itunesartbox.h new file mode 100644 index 0000000..5d197aa --- /dev/null +++ b/src/metadata/m4a/itunesartbox.h @@ -0,0 +1,50 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef ITUNESARTBOX_H +#define ITUNESARTBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class ITunesArtBox: public Mp4IsoBox + { + public: + ITunesArtBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + ~ITunesArtBox(); + + private: + //! parse the content of the box + virtual void parse(); + + protected: + class ITunesArtBoxPrivate; + ITunesArtBoxPrivate* d; + }; // class ITunesArtBox + + } // namespace MP4 +} // namespace TagLib + +#endif // ITUNESARTBOX_H diff --git a/src/metadata/m4a/itunescmtbox.cpp b/src/metadata/m4a/itunescmtbox.cpp new file mode 100644 index 0000000..c79f0f7 --- /dev/null +++ b/src/metadata/m4a/itunescmtbox.cpp @@ -0,0 +1,89 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <iostream> +#include "itunescmtbox.h" +#include "itunesdatabox.h" +#include "mp4isobox.h" +#include "mp4file.h" +#include "tfile.h" +#include "mp4tagsproxy.h" + +using namespace TagLib; + +class MP4::ITunesCmtBox::ITunesCmtBoxPrivate +{ +public: + ITunesDataBox* dataBox; +}; + +MP4::ITunesCmtBox::ITunesCmtBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) + :Mp4IsoBox(file, fourcc, size, offset) +{ + d = new MP4::ITunesCmtBox::ITunesCmtBoxPrivate(); + d->dataBox = 0; +} + +MP4::ITunesCmtBox::~ITunesCmtBox() +{ + if( d->dataBox != 0 ) + delete d->dataBox; + delete d; +} + +//! parse the content of the box +void MP4::ITunesCmtBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() ); + + // parse data box + TagLib::uint size; + MP4::Fourcc fourcc; + + if(mp4file->readSizeAndType( size, fourcc ) == true) + { + // check for type - must be 'data' + if( fourcc != MP4::Fourcc("data") ) + { + std::cerr << "bad atom in itunes tag - skipping it." << std::endl; + // jump over data tag + mp4file->seek( size-8, TagLib::File::Current ); + return; + } + d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() ); + d->dataBox->parsebox(); + } + else + { + // reading unsuccessful - serious error! + std::cerr << "Error in parsing ITunesCmtBox - serious Error in taglib!" << std::endl; + return; + } + // register data box + mp4file->tagProxy()->registerBox( Mp4TagsProxy::comment, d->dataBox ); + +#if 0 + // get data pointer - just for debugging... + TagLib::String dataString( d->dataBox->data() ); + std::cout << "Content of title box: " << dataString << std::endl; +#endif +} + diff --git a/src/metadata/m4a/itunescmtbox.h b/src/metadata/m4a/itunescmtbox.h new file mode 100644 index 0000000..83ad65d --- /dev/null +++ b/src/metadata/m4a/itunescmtbox.h @@ -0,0 +1,50 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef ITUNESCMTBOX_H +#define ITUNESCMTBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class ITunesCmtBox: public Mp4IsoBox + { + public: + ITunesCmtBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + ~ITunesCmtBox(); + + private: + //! parse the content of the box + virtual void parse(); + + protected: + class ITunesCmtBoxPrivate; + ITunesCmtBoxPrivate* d; + }; // class ITunesCmtBox + + } // namespace MP4 +} // namespace TagLib + +#endif // ITUNESCMTBOX_H diff --git a/src/metadata/m4a/itunescvrbox.cpp b/src/metadata/m4a/itunescvrbox.cpp new file mode 100644 index 0000000..4a7b3db --- /dev/null +++ b/src/metadata/m4a/itunescvrbox.cpp @@ -0,0 +1,89 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <iostream> +#include "itunescvrbox.h" +#include "itunesdatabox.h" +#include "mp4isobox.h" +#include "mp4file.h" +#include "tfile.h" +#include "mp4tagsproxy.h" + +using namespace TagLib; + +class MP4::ITunesCvrBox::ITunesCvrBoxPrivate +{ +public: + ITunesDataBox* dataBox; +}; + +MP4::ITunesCvrBox::ITunesCvrBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) + :Mp4IsoBox(file, fourcc, size, offset) +{ + d = new MP4::ITunesCvrBox::ITunesCvrBoxPrivate(); + d->dataBox = 0; +} + +MP4::ITunesCvrBox::~ITunesCvrBox() +{ + if( d->dataBox != 0 ) + delete d->dataBox; + delete d; +} + +//! parse the content of the box +void MP4::ITunesCvrBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() ); + + // parse data box + TagLib::uint size; + MP4::Fourcc fourcc; + + if(mp4file->readSizeAndType( size, fourcc ) == true) + { + // check for type - must be 'data' + if( fourcc != MP4::Fourcc("data") ) + { + std::cerr << "bad atom in itunes tag - skipping it." << std::endl; + // jump over data tag + mp4file->seek( size-8, TagLib::File::Current ); + return; + } + d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() ); + d->dataBox->parsebox(); + } + else + { + // reading unsuccessful - serious error! + std::cerr << "Error in parsing ITunesCvrBox - serious Error in taglib!" << std::endl; + return; + } + // register data box + mp4file->tagProxy()->registerBox( Mp4TagsProxy::cover, d->dataBox ); + +#if 0 + // get data pointer - just for debugging... + TagLib::String dataString( d->dataBox->data() ); + std::cout << "Content of album box: " << dataString << std::endl; +#endif +} + diff --git a/src/metadata/m4a/itunescvrbox.h b/src/metadata/m4a/itunescvrbox.h new file mode 100644 index 0000000..a2693c2 --- /dev/null +++ b/src/metadata/m4a/itunescvrbox.h @@ -0,0 +1,50 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef ITUNESCVRBOX_H +#define ITUNESCVRBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class ITunesCvrBox: public Mp4IsoBox + { + public: + ITunesCvrBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + ~ITunesCvrBox(); + + private: + //! parse the content of the box + virtual void parse(); + + protected: + class ITunesCvrBoxPrivate; + ITunesCvrBoxPrivate* d; + }; // class ITunesCvrBox + + } // namespace MP4 +} // namespace TagLib + +#endif // ITUNESCVRBOX_H diff --git a/src/metadata/m4a/itunesdatabox.cpp b/src/metadata/m4a/itunesdatabox.cpp new file mode 100644 index 0000000..7565a42 --- /dev/null +++ b/src/metadata/m4a/itunesdatabox.cpp @@ -0,0 +1,63 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <iostream> +#include "itunesdatabox.h" +#include "tbytevector.h" +#include "mp4isobox.h" +#include "tfile.h" + +using namespace TagLib; + +class MP4::ITunesDataBox::ITunesDataBoxPrivate +{ +public: + ByteVector data; +}; + +MP4::ITunesDataBox::ITunesDataBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) + :Mp4IsoFullBox(file, fourcc, size, offset) +{ + d = new MP4::ITunesDataBox::ITunesDataBoxPrivate(); +} + +MP4::ITunesDataBox::~ITunesDataBox() +{ + delete d; +} + +ByteVector MP4::ITunesDataBox::data() const +{ + return d->data; +} + +//! parse the content of the box +void MP4::ITunesDataBox::parse() +{ + // skip first 4 byte - don't know what they are supposed to be for - simply 4 zeros + file()->seek( 4, TagLib::File::Current ); + // read contents - remaining size is box_size-12-4 (12:fullbox header, 4:starting zeros of data box) +#if 0 + std::cout << " reading data box with data length: " << size()-16 << std::endl; +#endif + d->data = file()->readBlock( size()-12-4 ); +} + diff --git a/src/metadata/m4a/itunesdatabox.h b/src/metadata/m4a/itunesdatabox.h new file mode 100644 index 0000000..d0c802c --- /dev/null +++ b/src/metadata/m4a/itunesdatabox.h @@ -0,0 +1,53 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef ITUNESDATABOX_H +#define ITUNESDATABOX_H + +#include "mp4isofullbox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class ITunesDataBox: public Mp4IsoFullBox + { + public: + ITunesDataBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + ~ITunesDataBox(); + + //! get the internal data, which can be txt or binary data as well + ByteVector data() const; + + private: + //! parse the content of the box + virtual void parse(); + + protected: + class ITunesDataBoxPrivate; + ITunesDataBoxPrivate* d; + }; // class ITunesDataBox + + } // namespace MP4 +} // namespace TagLib + +#endif // ITUNESDATABOX_H diff --git a/src/metadata/m4a/itunesdaybox.cpp b/src/metadata/m4a/itunesdaybox.cpp new file mode 100644 index 0000000..16568d7 --- /dev/null +++ b/src/metadata/m4a/itunesdaybox.cpp @@ -0,0 +1,89 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <iostream> +#include "itunesdaybox.h" +#include "itunesdatabox.h" +#include "mp4isobox.h" +#include "mp4file.h" +#include "tfile.h" +#include "mp4tagsproxy.h" + +using namespace TagLib; + +class MP4::ITunesDayBox::ITunesDayBoxPrivate +{ +public: + ITunesDataBox* dataBox; +}; + +MP4::ITunesDayBox::ITunesDayBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) + :Mp4IsoBox(file, fourcc, size, offset) +{ + d = new MP4::ITunesDayBox::ITunesDayBoxPrivate(); + d->dataBox = 0; +} + +MP4::ITunesDayBox::~ITunesDayBox() +{ + if( d->dataBox != 0 ) + delete d->dataBox; + delete d; +} + +//! parse the content of the box +void MP4::ITunesDayBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() ); + + // parse data box + TagLib::uint size; + MP4::Fourcc fourcc; + + if(mp4file->readSizeAndType( size, fourcc ) == true) + { + // check for type - must be 'data' + if( fourcc != MP4::Fourcc("data") ) + { + std::cerr << "bad atom in itunes tag - skipping it." << std::endl; + // jump over data tag + mp4file->seek( size-8, TagLib::File::Current ); + return; + } + d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() ); + d->dataBox->parsebox(); + } + else + { + // reading unsuccessful - serious error! + std::cerr << "Error in parsing ITunesDayBox - serious Error in taglib!" << std::endl; + return; + } + // register data box + mp4file->tagProxy()->registerBox( Mp4TagsProxy::year, d->dataBox ); + +#if 0 + // get data pointer - just for debugging... + TagLib::String dataString( d->dataBox->data() ); + std::cout << "Content of day box: " << dataString.substr(0,4) << std::endl; +#endif +} + diff --git a/src/metadata/m4a/itunesdaybox.h b/src/metadata/m4a/itunesdaybox.h new file mode 100644 index 0000000..7291363 --- /dev/null +++ b/src/metadata/m4a/itunesdaybox.h @@ -0,0 +1,50 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef ITUNESDAYBOX_H +#define ITUNESDAYBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class ITunesDayBox: public Mp4IsoBox + { + public: + ITunesDayBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + ~ITunesDayBox(); + + private: + //! parse the content of the box + virtual void parse(); + + protected: + class ITunesDayBoxPrivate; + ITunesDayBoxPrivate* d; + }; // class ITunesDayBox + + } // namespace MP4 +} // namespace TagLib + +#endif // ITUNESDAYBOX_H diff --git a/src/metadata/m4a/itunesdiskbox.cpp b/src/metadata/m4a/itunesdiskbox.cpp new file mode 100644 index 0000000..93c47f2 --- /dev/null +++ b/src/metadata/m4a/itunesdiskbox.cpp @@ -0,0 +1,93 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <iostream> +#include "itunesdiskbox.h" +#include "itunesdatabox.h" +#include "mp4isobox.h" +#include "mp4file.h" +#include "tfile.h" +#include "mp4tagsproxy.h" + +using namespace TagLib; + +class MP4::ITunesDiskBox::ITunesDiskBoxPrivate +{ +public: + ITunesDataBox* dataBox; +}; + +MP4::ITunesDiskBox::ITunesDiskBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) + :Mp4IsoBox(file, fourcc, size, offset) +{ + d = new MP4::ITunesDiskBox::ITunesDiskBoxPrivate(); + d->dataBox = 0; +} + +MP4::ITunesDiskBox::~ITunesDiskBox() +{ + if( d->dataBox != 0 ) + delete d->dataBox; + delete d; +} + +//! parse the content of the box +void MP4::ITunesDiskBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() ); + + // parse data box + TagLib::uint size; + MP4::Fourcc fourcc; + + if(mp4file->readSizeAndType( size, fourcc ) == true) + { + // check for type - must be 'data' + if( fourcc != MP4::Fourcc("data") ) + { + std::cerr << "bad atom in itunes tag - skipping it." << std::endl; + // jump over data tag + mp4file->seek( size-8, TagLib::File::Current ); + return; + } + d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() ); + d->dataBox->parsebox(); + } + else + { + // reading unsuccessful - serious error! + std::cerr << "Error in parsing ITunesDiskBox - serious Error in taglib!" << std::endl; + return; + } + // register data box + mp4file->tagProxy()->registerBox( Mp4TagsProxy::disk, d->dataBox ); + +#if 0 + // get data pointer - just for debugging... + TagLib::ByteVector trknData = d->dataBox->data(); + TagLib::String trknumber = TagLib::String::number( static_cast<int>( static_cast<unsigned char>(trknData[0]) << 24 | + static_cast<unsigned char>(trknData[1]) << 16 | + static_cast<unsigned char>(trknData[2]) << 8 | + static_cast<unsigned char>(trknData[3]) ) ); + std::cout << "Content of tracknumber box: " << trknumber << std::endl; +#endif +} + diff --git a/src/metadata/m4a/itunesdiskbox.h b/src/metadata/m4a/itunesdiskbox.h new file mode 100644 index 0000000..bad73da --- /dev/null +++ b/src/metadata/m4a/itunesdiskbox.h @@ -0,0 +1,50 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef ITUNESDISKBOX_H +#define ITUNESDISKBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class ITunesDiskBox: public Mp4IsoBox + { + public: + ITunesDiskBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + ~ITunesDiskBox(); + + private: + //! parse the content of the box + virtual void parse(); + + protected: + class ITunesDiskBoxPrivate; + ITunesDiskBoxPrivate* d; + }; // class ITunesDiskBox + + } // namespace MP4 +} // namespace TagLib + +#endif // ITUNESDISKBOX_H diff --git a/src/metadata/m4a/itunesgenbox.cpp b/src/metadata/m4a/itunesgenbox.cpp new file mode 100644 index 0000000..08708bc --- /dev/null +++ b/src/metadata/m4a/itunesgenbox.cpp @@ -0,0 +1,89 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <iostream> +#include "itunesgenbox.h" +#include "itunesdatabox.h" +#include "mp4isobox.h" +#include "mp4file.h" +#include "tfile.h" +#include "mp4tagsproxy.h" + +using namespace TagLib; + +class MP4::ITunesGenBox::ITunesGenBoxPrivate +{ +public: + ITunesDataBox* dataBox; +}; + +MP4::ITunesGenBox::ITunesGenBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) + :Mp4IsoBox(file, fourcc, size, offset) +{ + d = new MP4::ITunesGenBox::ITunesGenBoxPrivate(); + d->dataBox = 0; +} + +MP4::ITunesGenBox::~ITunesGenBox() +{ + if( d->dataBox != 0 ) + delete d->dataBox; + delete d; +} + +//! parse the content of the box +void MP4::ITunesGenBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() ); + + // parse data box + TagLib::uint size; + MP4::Fourcc fourcc; + + if(mp4file->readSizeAndType( size, fourcc ) == true) + { + // check for type - must be 'data' + if( fourcc != MP4::Fourcc("data") ) + { + std::cerr << "bad atom in itunes tag - skipping it." << std::endl; + // jump over data tag + mp4file->seek( size-8, TagLib::File::Current ); + return; + } + d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() ); + d->dataBox->parsebox(); + } + else + { + // reading unsuccessful - serious error! + std::cerr << "Error in parsing ITunesGenBox - serious Error in taglib!" << std::endl; + return; + } + // register data box + mp4file->tagProxy()->registerBox( Mp4TagsProxy::genre, d->dataBox ); + +#if 0 + // get data pointer - just for debugging... + TagLib::String dataString( d->dataBox->data() ); + std::cout << "Content of genre box: " << dataString << std::endl; +#endif +} + diff --git a/src/metadata/m4a/itunesgenbox.h b/src/metadata/m4a/itunesgenbox.h new file mode 100644 index 0000000..deb7fe3 --- /dev/null +++ b/src/metadata/m4a/itunesgenbox.h @@ -0,0 +1,50 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef ITUNESGENBOX_H +#define ITUNESGENBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class ITunesGenBox: public Mp4IsoBox + { + public: + ITunesGenBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + ~ITunesGenBox(); + + private: + //! parse the content of the box + virtual void parse(); + + protected: + class ITunesGenBoxPrivate; + ITunesGenBoxPrivate* d; + }; // class ITunesGenBox + + } // namespace MP4 +} // namespace TagLib + +#endif // ITUNESGENBOX_H diff --git a/src/metadata/m4a/itunesgrpbox.cpp b/src/metadata/m4a/itunesgrpbox.cpp new file mode 100644 index 0000000..061b6bd --- /dev/null +++ b/src/metadata/m4a/itunesgrpbox.cpp @@ -0,0 +1,89 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <iostream> +#include "itunesgrpbox.h" +#include "itunesdatabox.h" +#include "mp4isobox.h" +#include "mp4file.h" +#include "tfile.h" +#include "mp4tagsproxy.h" + +using namespace TagLib; + +class MP4::ITunesGrpBox::ITunesGrpBoxPrivate +{ +public: + ITunesDataBox* dataBox; +}; + +MP4::ITunesGrpBox::ITunesGrpBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) + :Mp4IsoBox(file, fourcc, size, offset) +{ + d = new MP4::ITunesGrpBox::ITunesGrpBoxPrivate(); + d->dataBox = 0; +} + +MP4::ITunesGrpBox::~ITunesGrpBox() +{ + if( d->dataBox != 0 ) + delete d->dataBox; + delete d; +} + +//! parse the content of the box +void MP4::ITunesGrpBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() ); + + // parse data box + TagLib::uint size; + MP4::Fourcc fourcc; + + if(mp4file->readSizeAndType( size, fourcc ) == true) + { + // check for type - must be 'data' + if( fourcc != MP4::Fourcc("data") ) + { + std::cerr << "bad atom in itunes tag - skipping it." << std::endl; + // jump over data tag + mp4file->seek( size-8, TagLib::File::Current ); + return; + } + d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() ); + d->dataBox->parsebox(); + } + else + { + // reading unsuccessful - serious error! + std::cerr << "Error in parsing ITunesGrpBox - serious Error in taglib!" << std::endl; + return; + } + // register data box + mp4file->tagProxy()->registerBox( Mp4TagsProxy::grouping, d->dataBox ); + +#if 0 + // get data pointer - just for debugging... + TagLib::String dataString( d->dataBox->data() ); + std::cout << "Content of title box: " << dataString << std::endl; +#endif +} + diff --git a/src/metadata/m4a/itunesgrpbox.h b/src/metadata/m4a/itunesgrpbox.h new file mode 100644 index 0000000..62922f0 --- /dev/null +++ b/src/metadata/m4a/itunesgrpbox.h @@ -0,0 +1,50 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef ITUNESGRPBOX_H +#define ITUNESGRPBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class ITunesGrpBox: public Mp4IsoBox + { + public: + ITunesGrpBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + ~ITunesGrpBox(); + + private: + //! parse the content of the box + virtual void parse(); + + protected: + class ITunesGrpBoxPrivate; + ITunesGrpBoxPrivate* d; + }; // class ITunesGrpBox + + } // namespace MP4 +} // namespace TagLib + +#endif // ITUNESGRPBOX_H diff --git a/src/metadata/m4a/itunesnambox.cpp b/src/metadata/m4a/itunesnambox.cpp new file mode 100644 index 0000000..6cc954b --- /dev/null +++ b/src/metadata/m4a/itunesnambox.cpp @@ -0,0 +1,89 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <iostream> +#include "itunesnambox.h" +#include "itunesdatabox.h" +#include "mp4isobox.h" +#include "mp4file.h" +#include "tfile.h" +#include "mp4tagsproxy.h" + +using namespace TagLib; + +class MP4::ITunesNamBox::ITunesNamBoxPrivate +{ +public: + ITunesDataBox* dataBox; +}; + +MP4::ITunesNamBox::ITunesNamBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) + :Mp4IsoBox(file, fourcc, size, offset) +{ + d = new MP4::ITunesNamBox::ITunesNamBoxPrivate(); + d->dataBox = 0; +} + +MP4::ITunesNamBox::~ITunesNamBox() +{ + if( d->dataBox != 0 ) + delete d->dataBox; + delete d; +} + +//! parse the content of the box +void MP4::ITunesNamBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() ); + + // parse data box + TagLib::uint size; + MP4::Fourcc fourcc; + + if(mp4file->readSizeAndType( size, fourcc ) == true) + { + // check for type - must be 'data' + if( fourcc != MP4::Fourcc("data") ) + { + std::cerr << "bad atom in itunes tag - skipping it." << std::endl; + // jump over data tag + mp4file->seek( size-8, TagLib::File::Current ); + return; + } + d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() ); + d->dataBox->parsebox(); + } + else + { + // reading unsuccessful - serious error! + std::cerr << "Error in parsing ITunesNamBox - serious Error in taglib!" << std::endl; + return; + } + // register data box + mp4file->tagProxy()->registerBox( Mp4TagsProxy::title, d->dataBox ); + +#if 0 + // get data pointer - just for debugging... + TagLib::String dataString( d->dataBox->data() ); + std::cout << "Content of title box: " << dataString << std::endl; +#endif +} + diff --git a/src/metadata/m4a/itunesnambox.h b/src/metadata/m4a/itunesnambox.h new file mode 100644 index 0000000..434fd84 --- /dev/null +++ b/src/metadata/m4a/itunesnambox.h @@ -0,0 +1,50 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef ITUNESNAMBOX_H +#define ITUNESNAMBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class ITunesNamBox: public Mp4IsoBox + { + public: + ITunesNamBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + ~ITunesNamBox(); + + private: + //! parse the content of the box + virtual void parse(); + + protected: + class ITunesNamBoxPrivate; + ITunesNamBoxPrivate* d; + }; // class ITunesNamBox + + } // namespace MP4 +} // namespace TagLib + +#endif // ITUNESNAMBOX_H diff --git a/src/metadata/m4a/itunestmpobox.cpp b/src/metadata/m4a/itunestmpobox.cpp new file mode 100644 index 0000000..3d0ad2d --- /dev/null +++ b/src/metadata/m4a/itunestmpobox.cpp @@ -0,0 +1,93 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <iostream> +#include "itunestmpobox.h" +#include "itunesdatabox.h" +#include "mp4isobox.h" +#include "mp4file.h" +#include "tfile.h" +#include "mp4tagsproxy.h" + +using namespace TagLib; + +class MP4::ITunesTmpoBox::ITunesTmpoBoxPrivate +{ +public: + ITunesDataBox* dataBox; +}; + +MP4::ITunesTmpoBox::ITunesTmpoBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) + :Mp4IsoBox(file, fourcc, size, offset) +{ + d = new MP4::ITunesTmpoBox::ITunesTmpoBoxPrivate(); + d->dataBox = 0; +} + +MP4::ITunesTmpoBox::~ITunesTmpoBox() +{ + if( d->dataBox != 0 ) + delete d->dataBox; + delete d; +} + +//! parse the content of the box +void MP4::ITunesTmpoBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() ); + + // parse data box + TagLib::uint size; + MP4::Fourcc fourcc; + + if(mp4file->readSizeAndType( size, fourcc ) == true) + { + // check for type - must be 'data' + if( fourcc != MP4::Fourcc("data") ) + { + std::cerr << "bad atom in itunes tag - skipping it." << std::endl; + // jump over data tag + mp4file->seek( size-8, TagLib::File::Current ); + return; + } + d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() ); + d->dataBox->parsebox(); + } + else + { + // reading unsuccessful - serious error! + std::cerr << "Error in parsing ITunesTmpoBox - serious Error in taglib!" << std::endl; + return; + } + // register data box + mp4file->tagProxy()->registerBox( Mp4TagsProxy::bpm, d->dataBox ); + +#if 0 + // get data pointer - just for debugging... + TagLib::ByteVector trknData = d->dataBox->data(); + TagLib::String trknumber = TagLib::String::number( static_cast<int>( static_cast<unsigned char>(trknData[0]) << 24 | + static_cast<unsigned char>(trknData[1]) << 16 | + static_cast<unsigned char>(trknData[2]) << 8 | + static_cast<unsigned char>(trknData[3]) ) ); + std::cout << "Content of tracknumber box: " << trknumber << std::endl; +#endif +} + diff --git a/src/metadata/m4a/itunestmpobox.h b/src/metadata/m4a/itunestmpobox.h new file mode 100644 index 0000000..981f938 --- /dev/null +++ b/src/metadata/m4a/itunestmpobox.h @@ -0,0 +1,50 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef ITUNESTMPOBOX_H +#define ITUNESTMPOBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class ITunesTmpoBox: public Mp4IsoBox + { + public: + ITunesTmpoBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + ~ITunesTmpoBox(); + + private: + //! parse the content of the box + virtual void parse(); + + protected: + class ITunesTmpoBoxPrivate; + ITunesTmpoBoxPrivate* d; + }; // class ITunesTmpoBox + + } // namespace MP4 +} // namespace TagLib + +#endif // ITUNESTMPOBOX_H diff --git a/src/metadata/m4a/itunestrknbox.cpp b/src/metadata/m4a/itunestrknbox.cpp new file mode 100644 index 0000000..f8d36cb --- /dev/null +++ b/src/metadata/m4a/itunestrknbox.cpp @@ -0,0 +1,93 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <iostream> +#include "itunestrknbox.h" +#include "itunesdatabox.h" +#include "mp4isobox.h" +#include "mp4file.h" +#include "tfile.h" +#include "mp4tagsproxy.h" + +using namespace TagLib; + +class MP4::ITunesTrknBox::ITunesTrknBoxPrivate +{ +public: + ITunesDataBox* dataBox; +}; + +MP4::ITunesTrknBox::ITunesTrknBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) + :Mp4IsoBox(file, fourcc, size, offset) +{ + d = new MP4::ITunesTrknBox::ITunesTrknBoxPrivate(); + d->dataBox = 0; +} + +MP4::ITunesTrknBox::~ITunesTrknBox() +{ + if( d->dataBox != 0 ) + delete d->dataBox; + delete d; +} + +//! parse the content of the box +void MP4::ITunesTrknBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() ); + + // parse data box + TagLib::uint size; + MP4::Fourcc fourcc; + + if(mp4file->readSizeAndType( size, fourcc ) == true) + { + // check for type - must be 'data' + if( fourcc != MP4::Fourcc("data") ) + { + std::cerr << "bad atom in itunes tag - skipping it." << std::endl; + // jump over data tag + mp4file->seek( size-8, TagLib::File::Current ); + return; + } + d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() ); + d->dataBox->parsebox(); + } + else + { + // reading unsuccessful - serious error! + std::cerr << "Error in parsing ITunesTrknBox - serious Error in taglib!" << std::endl; + return; + } + // register data box + mp4file->tagProxy()->registerBox( Mp4TagsProxy::trackno, d->dataBox ); + +#if 0 + // get data pointer - just for debugging... + TagLib::ByteVector trknData = d->dataBox->data(); + TagLib::String trknumber = TagLib::String::number( static_cast<int>( static_cast<unsigned char>(trknData[0]) << 24 | + static_cast<unsigned char>(trknData[1]) << 16 | + static_cast<unsigned char>(trknData[2]) << 8 | + static_cast<unsigned char>(trknData[3]) ) ); + std::cout << "Content of tracknumber box: " << trknumber << std::endl; +#endif +} + diff --git a/src/metadata/m4a/itunestrknbox.h b/src/metadata/m4a/itunestrknbox.h new file mode 100644 index 0000000..f603e1f --- /dev/null +++ b/src/metadata/m4a/itunestrknbox.h @@ -0,0 +1,50 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef ITUNESTRKNBOX_H +#define ITUNESTRKNBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class ITunesTrknBox: public Mp4IsoBox + { + public: + ITunesTrknBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + ~ITunesTrknBox(); + + private: + //! parse the content of the box + virtual void parse(); + + protected: + class ITunesTrknBoxPrivate; + ITunesTrknBoxPrivate* d; + }; // class ITunesTrknBox + + } // namespace MP4 +} // namespace TagLib + +#endif // ITUNESTRKNBOX_H diff --git a/src/metadata/m4a/ituneswrtbox.cpp b/src/metadata/m4a/ituneswrtbox.cpp new file mode 100644 index 0000000..ecf3c43 --- /dev/null +++ b/src/metadata/m4a/ituneswrtbox.cpp @@ -0,0 +1,89 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <iostream> +#include "ituneswrtbox.h" +#include "itunesdatabox.h" +#include "mp4isobox.h" +#include "mp4file.h" +#include "tfile.h" +#include "mp4tagsproxy.h" + +using namespace TagLib; + +class MP4::ITunesWrtBox::ITunesWrtBoxPrivate +{ +public: + ITunesDataBox* dataBox; +}; + +MP4::ITunesWrtBox::ITunesWrtBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) + :Mp4IsoBox(file, fourcc, size, offset) +{ + d = new MP4::ITunesWrtBox::ITunesWrtBoxPrivate(); + d->dataBox = 0; +} + +MP4::ITunesWrtBox::~ITunesWrtBox() +{ + if( d->dataBox != 0 ) + delete d->dataBox; + delete d; +} + +//! parse the content of the box +void MP4::ITunesWrtBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() ); + + // parse data box + TagLib::uint size; + MP4::Fourcc fourcc; + + if(mp4file->readSizeAndType( size, fourcc ) == true) + { + // check for type - must be 'data' + if( fourcc != MP4::Fourcc("data") ) + { + std::cerr << "bad atom in itunes tag - skipping it." << std::endl; + // jump over data tag + mp4file->seek( size-8, TagLib::File::Current ); + return; + } + d->dataBox = new ITunesDataBox( mp4file, fourcc, size, mp4file->tell() ); + d->dataBox->parsebox(); + } + else + { + // reading unsuccessful - serious error! + std::cerr << "Error in parsing ITunesWrtBox - serious Error in taglib!" << std::endl; + return; + } + // register data box + mp4file->tagProxy()->registerBox( Mp4TagsProxy::composer, d->dataBox ); + +#if 0 + // get data pointer - just for debugging... + TagLib::String dataString( d->dataBox->data() ); + std::cout << "Content of title box: " << dataString << std::endl; +#endif +} + diff --git a/src/metadata/m4a/ituneswrtbox.h b/src/metadata/m4a/ituneswrtbox.h new file mode 100644 index 0000000..740d94c --- /dev/null +++ b/src/metadata/m4a/ituneswrtbox.h @@ -0,0 +1,50 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef ITUNESWRTBOX_H +#define ITUNESWRTBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class ITunesWrtBox: public Mp4IsoBox + { + public: + ITunesWrtBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + ~ITunesWrtBox(); + + private: + //! parse the content of the box + virtual void parse(); + + protected: + class ITunesWrtBoxPrivate; + ITunesWrtBoxPrivate* d; + }; // class ITunesWrtBox + + } // namespace MP4 +} // namespace TagLib + +#endif // ITUNESWRTBOX_H diff --git a/src/metadata/m4a/mp4audioproperties.cpp b/src/metadata/m4a/mp4audioproperties.cpp new file mode 100644 index 0000000..77afab1 --- /dev/null +++ b/src/metadata/m4a/mp4audioproperties.cpp @@ -0,0 +1,75 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "mp4audioproperties.h" +#include "mp4propsproxy.h" + +using namespace TagLib; + +class MP4::AudioProperties::AudioPropertiesPrivate +{ +public: + MP4::Mp4PropsProxy* propsproxy; +}; // AudioPropertiesPrivate + +MP4::AudioProperties::AudioProperties():TagLib::AudioProperties(TagLib::AudioProperties::Average) +{ + d = new MP4::AudioProperties::AudioPropertiesPrivate(); +} + +MP4::AudioProperties::~AudioProperties() +{ + delete d; +} + +void MP4::AudioProperties::setProxy( Mp4PropsProxy* proxy ) +{ + d->propsproxy = proxy; +} + +int MP4::AudioProperties::length() const +{ + if( d->propsproxy == 0 ) + return 0; + return d->propsproxy->seconds(); +} + +int MP4::AudioProperties::bitrate() const +{ + if( d->propsproxy == 0 ) + return 0; + return d->propsproxy->bitRate()/1000; +} + +int MP4::AudioProperties::sampleRate() const +{ + if( d->propsproxy == 0 ) + return 0; + return d->propsproxy->sampleRate(); +} + +int MP4::AudioProperties::channels() const +{ + if( d->propsproxy == 0 ) + return 0; + return d->propsproxy->channels(); +} + diff --git a/src/metadata/m4a/mp4audioproperties.h b/src/metadata/m4a/mp4audioproperties.h new file mode 100644 index 0000000..4e61790 --- /dev/null +++ b/src/metadata/m4a/mp4audioproperties.h @@ -0,0 +1,73 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4AUDIOPROPERTIES_H +#define MP4AUDIOPROPERTIES_H MP4AUDIOPROPERTIES_H + +#include "audioproperties.h" + +namespace TagLib +{ + namespace MP4 + { + class Mp4PropsProxy; + + class AudioProperties : public TagLib::AudioProperties + { + public: + //! constructor + AudioProperties(); + //! destructor + ~AudioProperties(); + + //! function to set the proxy + void setProxy( Mp4PropsProxy* proxy ); + + /*! + * Returns the length of the file in seconds. + */ + int length() const; + + /*! + * Returns the most appropriate bit rate for the file in kb/s. For constant + * bitrate formats this is simply the bitrate of the file. For variable + * bitrate formats this is either the average or nominal bitrate. + */ + int bitrate() const; + + /*! + * Returns the sample rate in Hz. + */ + int sampleRate() const; + + /*! + * Returns the number of audio channels. + */ + int channels() const; + + private: + class AudioPropertiesPrivate; + AudioPropertiesPrivate* d; + }; + } // namespace MP4 +} // namespace TagLib + +#endif // MP4AUDIOPROPERTIES_H diff --git a/src/metadata/m4a/mp4audiosampleentry.cpp b/src/metadata/m4a/mp4audiosampleentry.cpp new file mode 100644 index 0000000..fb87547 --- /dev/null +++ b/src/metadata/m4a/mp4audiosampleentry.cpp @@ -0,0 +1,146 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <iostream> +#include "mp4audiosampleentry.h" +#include "mp4isobox.h" +#include "mp4file.h" +#include "mp4propsproxy.h" + +using namespace TagLib; + +class MP4::Mp4AudioSampleEntry::Mp4AudioSampleEntryPrivate +{ +public: + TagLib::uint channelcount; + TagLib::uint samplerate; + TagLib::uint bitrate; +}; + +MP4::Mp4AudioSampleEntry::Mp4AudioSampleEntry( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) + :Mp4SampleEntry(file, fourcc, size, offset) +{ + d = new MP4::Mp4AudioSampleEntry::Mp4AudioSampleEntryPrivate(); +} + +MP4::Mp4AudioSampleEntry::~Mp4AudioSampleEntry() +{ + delete d; +} + +TagLib::uint MP4::Mp4AudioSampleEntry::channels() const +{ + return d->channelcount; +} + +TagLib::uint MP4::Mp4AudioSampleEntry::samplerate() const +{ + return d->samplerate; +} + +TagLib::uint MP4::Mp4AudioSampleEntry::bitrate() const +{ + return d->bitrate; +} + +void MP4::Mp4AudioSampleEntry::parseEntry() +{ + TagLib::MP4::File* mp4file = dynamic_cast<TagLib::MP4::File*>(file()); + if(!mp4file) + return; + + // read 8 reserved bytes + mp4file->seek( 8, TagLib::File::Current ); + // read channelcount + if(!mp4file->readShort( d->channelcount )) + return; + // seek over samplesize, pre_defined and reserved + mp4file->seek( 6, TagLib::File::Current ); + // read samplerate + if(!mp4file->readInt( d->samplerate )) + return; + + // register box at proxy + mp4file->propProxy()->registerAudioSampleEntry( this ); + + + //std::cout << "fourcc of audio sample entry: " << fourcc().toString() << std::endl; + // check for both mp4a (plain files) and drms (encrypted files) + if( (fourcc() == MP4::Fourcc("mp4a")) || + (fourcc() == MP4::Fourcc("drms")) ) + { + TagLib::MP4::Fourcc fourcc; + TagLib::uint esds_size; + + if (!mp4file->readSizeAndType( esds_size, fourcc )) + return; + + // read esds' main parts + if( size()-48 > 0 ) + ByteVector flags_version = mp4file->readBlock(4); + else + return; + + ByteVector EsDescrTag = mp4file->readBlock(1); + // first 4 bytes contain full box specifics (version & flags) + // upcoming byte must be ESDescrTag (0x03) + if( EsDescrTag[0] == 0x03 ) + { + TagLib::uint descr_len = mp4file->readSystemsLen(); + TagLib::uint EsId; + if( !mp4file->readShort( EsId ) ) + return; + ByteVector priority = mp4file->readBlock(1); + if( descr_len < 20 ) + return; + } + else + { + TagLib::uint EsId; + if( !mp4file->readShort( EsId ) ) + return; + } + // read decoder configuration tag (0x04) + ByteVector DecCfgTag = mp4file->readBlock(1); + if( DecCfgTag[0] != 0x04 ) + return; + // read decoder configuration length + // TagLib::uint deccfg_len = mp4file->readSystemsLen(); + // read object type Id + ByteVector objId = mp4file->readBlock(1); + // read stream type id + ByteVector strId = mp4file->readBlock(1); + // read buffer Size DB + ByteVector bufferSizeDB = mp4file->readBlock(3); + // read max bitrate + TagLib::uint max_bitrate; + if( !mp4file->readInt( max_bitrate ) ) + return; + // read average bitrate + if( !mp4file->readInt( d->bitrate ) ) + return; + // skip the rest + mp4file->seek( offset()+size()-8, File::Beginning ); + } + else + mp4file->seek( size()-36, File::Current ); +} + diff --git a/src/metadata/m4a/mp4audiosampleentry.h b/src/metadata/m4a/mp4audiosampleentry.h new file mode 100644 index 0000000..c39c5e3 --- /dev/null +++ b/src/metadata/m4a/mp4audiosampleentry.h @@ -0,0 +1,57 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4AUDIOSAMPLEENTRY_H +#define MP4AUDIOSAMPLEENTRY_H + +#include "mp4sampleentry.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class Mp4AudioSampleEntry: public Mp4SampleEntry + { + public: + Mp4AudioSampleEntry( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + ~Mp4AudioSampleEntry(); + + //! function to get the number of channels + TagLib::uint channels() const; + //! function to get the sample rate + TagLib::uint samplerate() const; + //! function to get the average bitrate of the audio stream + TagLib::uint bitrate() const; + + private: + //! parse the content of the box + void parseEntry(); + + protected: + class Mp4AudioSampleEntryPrivate; + Mp4AudioSampleEntryPrivate* d; + }; // class Mp4AudioSampleEntry + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4AUDIOSAMPLEENTRY_H diff --git a/src/metadata/m4a/mp4file.cpp b/src/metadata/m4a/mp4file.cpp new file mode 100644 index 0000000..7d37d59 --- /dev/null +++ b/src/metadata/m4a/mp4file.cpp @@ -0,0 +1,377 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <tbytevector.h> +#include <tstring.h> +#include "tlist.h" + +#include "mp4itunestag.h" +#include "mp4file.h" +#include "boxfactory.h" +#include "mp4tagsproxy.h" +#include "mp4propsproxy.h" +#include "mp4audioproperties.h" +#include "itunesdatabox.h" + +using namespace TagLib; + +class MP4::File::FilePrivate +{ +public: + //! list for all boxes of the mp4 file + TagLib::List<MP4::Mp4IsoBox*> boxes; + //! the box factory - will create all boxes by tag and size + MP4::BoxFactory boxfactory; + //! proxy for the tags is filled after parsing + MP4::Mp4TagsProxy tagsProxy; + //! proxy for audio properties + MP4::Mp4PropsProxy propsProxy; + //! the tag returned by tag() function + MP4::Tag mp4tag; + //! container for the audio properties returned by properties() function + MP4::AudioProperties mp4audioproperties; + //! is set to valid after successfully parsing + bool isValid; +}; + +//! function to fill the tags with converted proxy data, which has been parsed out of the file previously +static void fillTagFromProxy( MP4::Mp4TagsProxy& proxy, MP4::Tag& mp4tag ); + +MP4::File::File(const char *file, bool , AudioProperties::ReadStyle ) + :TagLib::File( file ) +{ + // create member container + d = new MP4::File::FilePrivate(); + + + d->isValid = false; + TagLib::uint size; + MP4::Fourcc fourcc; + + while( readSizeAndType( size, fourcc ) == true ) + { + // create the appropriate subclass and parse it + MP4::Mp4IsoBox* curbox = d->boxfactory.createInstance( this, fourcc, size, tell() ); + curbox->parsebox(); + d->boxes.append( curbox ); + } + + for( TagLib::List<MP4::Mp4IsoBox*>::Iterator iter = d->boxes.begin(); + iter != d->boxes.end(); + iter++ ) + { + if( (*iter)->fourcc() == MP4::Fourcc("moov") ) + { + d->isValid = true; + break; + } + } + + //if( d->isValid ) + //debug( "file is valid" ); + //else + //debug( "file is NOT valid" ); + + // fill tags from proxy data + fillTagFromProxy( d->tagsProxy, d->mp4tag ); +} + +MP4::File::~File() +{ + TagLib::List<Mp4IsoBox*>::Iterator delIter; + for( delIter = d->boxes.begin(); + delIter != d->boxes.end(); + delIter++ ) + { + delete *delIter; + } + delete d; +} + +Tag *MP4::File::tag() const +{ + return &d->mp4tag; +} + +AudioProperties * MP4::File::audioProperties() const +{ + d->mp4audioproperties.setProxy( &d->propsProxy ); + return &d->mp4audioproperties; +} + +bool MP4::File::save() +{ + return false; +} + +void MP4::File::remove() +{ +} + +TagLib::uint MP4::File::readSystemsLen() +{ + TagLib::uint length = 0; + TagLib::uint nbytes = 0; + ByteVector input; + TagLib::uchar tmp_input; + + do + { + input = readBlock(1); + tmp_input = static_cast<TagLib::uchar>(input[0]); + nbytes++; + length = (length<<7) | (tmp_input&0x7F); + } while( (tmp_input&0x80) && (nbytes<4) ); + + return length; +} + +bool MP4::File::readSizeAndType( TagLib::uint& size, MP4::Fourcc& fourcc ) +{ + // read the two blocks from file + ByteVector readsize = readBlock(4); + ByteVector readtype = readBlock(4); + + if( (readsize.size() != 4) || (readtype.size() != 4) ) + return false; + + // set size + size = static_cast<unsigned char>(readsize[0]) << 24 | + static_cast<unsigned char>(readsize[1]) << 16 | + static_cast<unsigned char>(readsize[2]) << 8 | + static_cast<unsigned char>(readsize[3]); + + // type and size seem to be part of the stored size + if( size < 8 ) + return false; + + // set fourcc + fourcc = readtype.data(); + + return true; +} + +bool MP4::File::readInt( TagLib::uint& toRead ) +{ + ByteVector readbuffer = readBlock(4); + if( readbuffer.size() != 4 ) + return false; + + toRead = static_cast<unsigned char>(readbuffer[0]) << 24 | + static_cast<unsigned char>(readbuffer[1]) << 16 | + static_cast<unsigned char>(readbuffer[2]) << 8 | + static_cast<unsigned char>(readbuffer[3]); + return true; +} + +bool MP4::File::readShort( TagLib::uint& toRead ) +{ + ByteVector readbuffer = readBlock(2); + if( readbuffer.size() != 2 ) + return false; + + toRead = static_cast<unsigned char>(readbuffer[0]) << 8 | + static_cast<unsigned char>(readbuffer[1]); + return true; +} + +bool MP4::File::readLongLong( TagLib::ulonglong& toRead ) +{ + ByteVector readbuffer = readBlock(8); + if( readbuffer.size() != 8 ) + return false; + + toRead = static_cast<ulonglong>(static_cast<unsigned char>(readbuffer[0])) << 56 | + static_cast<ulonglong>(static_cast<unsigned char>(readbuffer[1])) << 48 | + static_cast<ulonglong>(static_cast<unsigned char>(readbuffer[2])) << 40 | + static_cast<ulonglong>(static_cast<unsigned char>(readbuffer[3])) << 32 | + static_cast<ulonglong>(static_cast<unsigned char>(readbuffer[4])) << 24 | + static_cast<ulonglong>(static_cast<unsigned char>(readbuffer[5])) << 16 | + static_cast<ulonglong>(static_cast<unsigned char>(readbuffer[6])) << 8 | + static_cast<ulonglong>(static_cast<unsigned char>(readbuffer[7])); + return true; +} + +bool MP4::File::readFourcc( TagLib::MP4::Fourcc& fourcc ) +{ + ByteVector readtype = readBlock(4); + + if( readtype.size() != 4) + return false; + + // set fourcc + fourcc = readtype.data(); + + return true; +} + +MP4::Mp4TagsProxy* MP4::File::tagProxy() const +{ + return &d->tagsProxy; +} + +MP4::Mp4PropsProxy* MP4::File::propProxy() const +{ + return &d->propsProxy; +} + +void fillTagFromProxy( MP4::Mp4TagsProxy& proxy, MP4::Tag& mp4tag ) +{ + // tmp buffer for each tag + MP4::ITunesDataBox* databox; + + databox = proxy.titleData(); + if( databox != 0 ) + { + // convert data to string + TagLib::String datastring( databox->data(), String::UTF8 ); + // check if string was set + if( !datastring.isEmpty() ) + mp4tag.setTitle( datastring ); + } + + databox = proxy.artistData(); + if( databox != 0 ) + { + // convert data to string + TagLib::String datastring( databox->data(), String::UTF8 ); + // check if string was set + if( !datastring.isEmpty() ) + mp4tag.setArtist( datastring ); + } + + databox = proxy.albumData(); + if( databox != 0 ) + { + // convert data to string + TagLib::String datastring( databox->data(), String::UTF8 ); + // check if string was set + if( !datastring.isEmpty() ) + mp4tag.setAlbum( datastring ); + } + + databox = proxy.genreData(); + if( databox != 0 ) + { + // convert data to string + TagLib::String datastring( databox->data(), String::UTF8 ); + // check if string was set + if( !datastring.isEmpty() ) + mp4tag.setGenre( datastring ); + } + + databox = proxy.yearData(); + if( databox != 0 ) + { + // convert data to string + TagLib::String datastring( databox->data(), String::UTF8 ); + // check if string was set + if( !datastring.isEmpty() ) + mp4tag.setYear( datastring.toInt() ); + } + + databox = proxy.trknData(); + if( databox != 0 ) + { + // convert data to uint + TagLib::ByteVector datavec = databox->data(); + if( datavec.size() >= 4 ) + { + TagLib::uint trackno = static_cast<TagLib::uint>( static_cast<unsigned char>(datavec[0]) << 24 | + static_cast<unsigned char>(datavec[1]) << 16 | + static_cast<unsigned char>(datavec[2]) << 8 | + static_cast<unsigned char>(datavec[3]) ); + mp4tag.setTrack( trackno ); + } + else + mp4tag.setTrack( 0 ); + } + + databox = proxy.commentData(); + if( databox != 0 ) + { + // convert data to string + TagLib::String datastring( databox->data(), String::UTF8 ); + // check if string was set + if( !datastring.isEmpty() ) + mp4tag.setComment( datastring ); + } + + databox = proxy.groupingData(); + if( databox != 0 ) + { + // convert data to string + TagLib::String datastring( databox->data(), String::UTF8 ); + // check if string was set + if( !datastring.isEmpty() ) + mp4tag.setGrouping( datastring ); + } + + databox = proxy.composerData(); + if( databox != 0 ) + { + // convert data to string + TagLib::String datastring( databox->data(), String::UTF8 ); + // check if string was set + if( !datastring.isEmpty() ) + mp4tag.setComposer( datastring ); + } + + databox = proxy.diskData(); + if( databox != 0 ) + { + // convert data to uint + TagLib::ByteVector datavec = databox->data(); + if( datavec.size() >= 4 ) + { + TagLib::uint discno = static_cast<TagLib::uint>( static_cast<unsigned char>(datavec[0]) << 24 | + static_cast<unsigned char>(datavec[1]) << 16 | + static_cast<unsigned char>(datavec[2]) << 8 | + static_cast<unsigned char>(datavec[3]) ); + mp4tag.setDisk( discno ); + } + else + mp4tag.setDisk( 0 ); + } + + databox = proxy.bpmData(); + if( databox != 0 ) + { + // convert data to uint + TagLib::ByteVector datavec = databox->data(); + + if( datavec.size() >= 2 ) + { + TagLib::uint bpm = static_cast<TagLib::uint>( static_cast<unsigned char>(datavec[0]) << 8 | + static_cast<unsigned char>(datavec[1]) ); + mp4tag.setBpm( bpm ); + } + else + mp4tag.setBpm( 0 ); + } + + databox = proxy.coverData(); + if( databox != 0 ) + { + // get byte vector + mp4tag.setCover( databox->data() ); + } +} diff --git a/src/metadata/m4a/mp4file.h b/src/metadata/m4a/mp4file.h new file mode 100644 index 0000000..9e40dbc --- /dev/null +++ b/src/metadata/m4a/mp4file.h @@ -0,0 +1,169 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +/*************************************************************************** + copyright : (C) 2002, 2003 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * + * USA * + ***************************************************************************/ + +#ifndef TAGLIB_MP4FILE_H +#define TAGLIB_MP4FILE_H + +#include <tfile.h> +#include <audioproperties.h> + +#include "mp4fourcc.h" + +namespace TagLib { + + typedef unsigned long long ulonglong; + + class Tag; + + namespace MP4 + { + class Mp4TagsProxy; + class Mp4PropsProxy; + + //! An implementation of TagLib::File with mp4 itunes specific methods + + /*! + * This implements and provides an interface for mp4 itunes 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 mp4 itunes files. (TODO) + */ + + class File : public TagLib::File + { + public: + /*! + * Contructs an mp4 itunes 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(const char *file, bool readProperties = true, + AudioProperties::ReadStyle propertiesStyle = AudioProperties::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 mp4 itunes::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual AudioProperties *audioProperties() const; + + /*! + * Saves the file. + */ + virtual bool save(); + + /*! + * This will remove 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 remove(); + + /*! + * Helper function for parsing the MP4 file - reads the size and type of the next box. + * Returns true if read succeeded - not at EOF + */ + bool readSizeAndType( TagLib::uint& size, MP4::Fourcc& fourcc ); + + /*! + * Helper function to read the length of an descriptor in systems manner + */ + TagLib::uint readSystemsLen(); + + /*! + * Helper function for reading an unsigned int out of the file (big endian method) + */ + bool readInt( TagLib::uint& toRead ); + + /*! + * Helper function for reading an unsigned short out of the file (big endian method) + */ + bool readShort( TagLib::uint& toRead ); + + /*! + * Helper function for reading an unsigned long long (64bit) out of the file (big endian method) + */ + bool readLongLong( TagLib::ulonglong& toRead ); + + /*! + * Helper function to read a fourcc code + */ + bool readFourcc( TagLib::MP4::Fourcc& fourcc ); + + /*! + * Function to get the tags proxy for registration of the tags boxes. + * The proxy provides direct access to the data boxes of the certain tags - normally + * covered by several levels of subboxes + */ + Mp4TagsProxy* tagProxy() const; + + /*! + * Function to get the properties proxy for registration of the properties boxes. + * The proxy provides direct access to the needed boxes describing audio properties. + */ + Mp4PropsProxy* propProxy() const; + + private: + File(const File &); + File &operator=(const File &); + + class FilePrivate; + FilePrivate *d; + }; + + } // namespace MP4 + +} // namespace TagLib + +#endif // TAGLIB_MP4FILE_H diff --git a/src/metadata/m4a/mp4fourcc.cpp b/src/metadata/m4a/mp4fourcc.cpp new file mode 100644 index 0000000..dac0f99 --- /dev/null +++ b/src/metadata/m4a/mp4fourcc.cpp @@ -0,0 +1,84 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "mp4fourcc.h" + +using namespace TagLib; + +MP4::Fourcc::Fourcc() +{ + m_fourcc = 0U; +} + +MP4::Fourcc::Fourcc( TagLib::String fourcc ) +{ + m_fourcc = 0U; + + if( fourcc.size() >= 4 ) + m_fourcc = static_cast<unsigned char>(fourcc[0]) << 24 | + static_cast<unsigned char>(fourcc[1]) << 16 | + static_cast<unsigned char>(fourcc[2]) << 8 | + static_cast<unsigned char>(fourcc[3]); +} + +MP4::Fourcc::~Fourcc() +{} + +TagLib::String MP4::Fourcc::toString() const +{ + TagLib::String fourcc; + fourcc.append(static_cast<char>(m_fourcc >> 24 & 0xFF)); + fourcc.append(static_cast<char>(m_fourcc >> 16 & 0xFF)); + fourcc.append(static_cast<char>(m_fourcc >> 8 & 0xFF)); + fourcc.append(static_cast<char>(m_fourcc & 0xFF)); + + return fourcc; +} + +MP4::Fourcc::operator unsigned int() const +{ + return m_fourcc; +} + +bool MP4::Fourcc::operator == (unsigned int fourccB ) const +{ + return (m_fourcc==fourccB); +} + +bool MP4::Fourcc::operator != (unsigned int fourccB ) const +{ + return (m_fourcc!=fourccB); +} + +MP4::Fourcc& MP4::Fourcc::operator = (unsigned int fourcc ) +{ + m_fourcc = fourcc; + return *this; +} + +MP4::Fourcc& MP4::Fourcc::operator = (char fourcc[4]) +{ + m_fourcc = static_cast<unsigned char>(fourcc[0]) << 24 | + static_cast<unsigned char>(fourcc[1]) << 16 | + static_cast<unsigned char>(fourcc[2]) << 8 | + static_cast<unsigned char>(fourcc[3]); + return *this; +} diff --git a/src/metadata/m4a/mp4fourcc.h b/src/metadata/m4a/mp4fourcc.h new file mode 100644 index 0000000..90e498a --- /dev/null +++ b/src/metadata/m4a/mp4fourcc.h @@ -0,0 +1,63 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4FOURCC_H +#define MP4FOURCC_H + +#include "tstring.h" + +namespace TagLib +{ + namespace MP4 + { + /*! union for easy fourcc / type handling */ + class Fourcc + { + public: + //! std constructor + Fourcc(); + //! string constructor + Fourcc(TagLib::String fourcc); + + //! destructor + ~Fourcc(); + + //! function to get a string version of the fourcc + TagLib::String toString() const; + //! cast operator to unsigned int + operator unsigned int() const; + //! comparison operator + bool operator == (unsigned int fourccB ) const; + //! comparison operator + bool operator != (unsigned int fourccB ) const; + //! assigment operator for unsigned int + Fourcc& operator = (unsigned int fourcc ); + //! assigment operator for character string + Fourcc& operator = (char fourcc[4]); + + private: + uint m_fourcc; /*!< integer code of the fourcc */ + }; + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4FOURCC_H diff --git a/src/metadata/m4a/mp4hdlrbox.cpp b/src/metadata/m4a/mp4hdlrbox.cpp new file mode 100644 index 0000000..a3ec5f7 --- /dev/null +++ b/src/metadata/m4a/mp4hdlrbox.cpp @@ -0,0 +1,75 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <deque> +#include <iostream> +#include "mp4hdlrbox.h" +#include "boxfactory.h" +#include "mp4file.h" + +using namespace TagLib; + +class MP4::Mp4HdlrBox::Mp4HdlrBoxPrivate +{ +public: + TagLib::uint pre_defined; + MP4::Fourcc handler_type; + TagLib::String hdlr_string; +}; // class Mp4HdlrBoxPrivate + +MP4::Mp4HdlrBox::Mp4HdlrBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ) + : Mp4IsoFullBox( file, fourcc, size, offset ) +{ + d = new MP4::Mp4HdlrBox::Mp4HdlrBoxPrivate(); +} + +MP4::Mp4HdlrBox::~Mp4HdlrBox() +{ + delete d; +} + +MP4::Fourcc MP4::Mp4HdlrBox::hdlr_type() const +{ + return d->handler_type; +} + +TagLib::String MP4::Mp4HdlrBox::hdlr_string() const +{ + return d->hdlr_string; +} + +void MP4::Mp4HdlrBox::parse() +{ + TagLib::uint totalread = 12+20; + + TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() ); + if( mp4file->readInt( d->pre_defined ) == false ) + return; + if( mp4file->readFourcc( d->handler_type ) == false ) + return; + + // read reserved into trash + mp4file->seek( 3*4, TagLib::File::Current ); + + // check if there are bytes remaining - used for hdlr string + if( size() - totalread != 0 ) + d->hdlr_string = mp4file->readBlock( size()-totalread ); +} diff --git a/src/metadata/m4a/mp4hdlrbox.h b/src/metadata/m4a/mp4hdlrbox.h new file mode 100644 index 0000000..0a6bf54 --- /dev/null +++ b/src/metadata/m4a/mp4hdlrbox.h @@ -0,0 +1,53 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4HDLRBOX_H +#define MP4HDLRBOX_H + +#include "mp4isofullbox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class Mp4HdlrBox: public Mp4IsoFullBox + { + public: + Mp4HdlrBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ); + ~Mp4HdlrBox(); + + //! parse hdlr contents + void parse(); + //! get the handler type + MP4::Fourcc hdlr_type() const; + //! get the hdlr string + TagLib::String hdlr_string() const; + + private: + class Mp4HdlrBoxPrivate; + Mp4HdlrBoxPrivate* d; + }; // Mp4HdlrBox + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4HDLRBOX_H diff --git a/src/metadata/m4a/mp4ilstbox.cpp b/src/metadata/m4a/mp4ilstbox.cpp new file mode 100644 index 0000000..1d5ae9a --- /dev/null +++ b/src/metadata/m4a/mp4ilstbox.cpp @@ -0,0 +1,97 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "tlist.h" +#include <iostream> +#include "mp4ilstbox.h" +#include "boxfactory.h" +#include "mp4file.h" + +using namespace TagLib; + +class MP4::Mp4IlstBox::Mp4IlstBoxPrivate +{ +public: + //! container for all boxes in ilst box + TagLib::List<Mp4IsoBox*> ilstBoxes; + //! a box factory for creating the appropriate boxes + MP4::BoxFactory boxfactory; +}; // class Mp4IlstBoxPrivate + +MP4::Mp4IlstBox::Mp4IlstBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ) + : Mp4IsoBox( file, fourcc, size, offset ) +{ + d = new MP4::Mp4IlstBox::Mp4IlstBoxPrivate(); +} + +MP4::Mp4IlstBox::~Mp4IlstBox() +{ + TagLib::List<Mp4IsoBox*>::Iterator delIter; + for( delIter = d->ilstBoxes.begin(); + delIter != d->ilstBoxes.end(); + delIter++ ) + { + delete *delIter; + } + delete d; +} + +void MP4::Mp4IlstBox::parse() +{ +#if 0 + std::cout << " parsing ilst box" << std::endl; +#endif + + TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() ); + + TagLib::uint totalsize = 8; + // parse all contained boxes + TagLib::uint size; + MP4::Fourcc fourcc; + +#if 0 + std::cout << " "; +#endif + while( (mp4file->readSizeAndType( size, fourcc ) == true) ) + { + totalsize += size; + + // check for errors + if( totalsize > MP4::Mp4IsoBox::size() ) + { + std::cerr << "Error in mp4 file " << mp4file->name() << " ilst box contains bad box with name: " << fourcc.toString() << std::endl; + return; + } + + // create the appropriate subclass and parse it + MP4::Mp4IsoBox* curbox = d->boxfactory.createInstance( mp4file, fourcc, size, mp4file->tell() ); + curbox->parsebox(); + d->ilstBoxes.append( curbox ); + + // check for end of ilst box + if( totalsize == MP4::Mp4IsoBox::size() ) + break; + +#if 0 + std::cout << " "; +#endif + } +} diff --git a/src/metadata/m4a/mp4ilstbox.h b/src/metadata/m4a/mp4ilstbox.h new file mode 100644 index 0000000..9e7ad1c --- /dev/null +++ b/src/metadata/m4a/mp4ilstbox.h @@ -0,0 +1,49 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4ILSTBOX_H +#define MP4ILSTBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class Mp4IlstBox: public Mp4IsoBox + { + public: + Mp4IlstBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ); + ~Mp4IlstBox(); + + //! parse ilst contents + void parse(); + + private: + class Mp4IlstBoxPrivate; + Mp4IlstBoxPrivate* d; + }; // Mp4IlstBox + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4ILSTBOX_H diff --git a/src/metadata/m4a/mp4isobox.cpp b/src/metadata/m4a/mp4isobox.cpp new file mode 100644 index 0000000..7f08924 --- /dev/null +++ b/src/metadata/m4a/mp4isobox.cpp @@ -0,0 +1,76 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "mp4isobox.h" +#include "tfile.h" + +using namespace TagLib; + +class MP4::Mp4IsoBox::Mp4IsoBoxPrivate +{ +public: + MP4::Fourcc fourcc; + TagLib::uint size; + long offset; + TagLib::File* file; +}; + +MP4::Mp4IsoBox::Mp4IsoBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ) +{ + d = new MP4::Mp4IsoBox::Mp4IsoBoxPrivate(); + d->file = file; + d->fourcc = fourcc; + d->size = size; + d->offset = offset; +} + +MP4::Mp4IsoBox::~Mp4IsoBox() +{ + delete d; +} + +void MP4::Mp4IsoBox::parsebox() +{ + // seek to offset + file()->seek( offset(), File::Beginning ); + // simply call parse method of sub class + parse(); +} + +MP4::Fourcc MP4::Mp4IsoBox::fourcc() const +{ + return d->fourcc; +} + +TagLib::uint MP4::Mp4IsoBox::size() const +{ + return d->size; +} + +long MP4::Mp4IsoBox::offset() const +{ + return d->offset; +} + +TagLib::File* MP4::Mp4IsoBox::file() const +{ + return d->file; +} diff --git a/src/metadata/m4a/mp4isobox.h b/src/metadata/m4a/mp4isobox.h new file mode 100644 index 0000000..4d4edc9 --- /dev/null +++ b/src/metadata/m4a/mp4isobox.h @@ -0,0 +1,67 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4ISOBOX_H +#define MP4ISOBOX_H + +#include "taglib.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + class File; + + namespace MP4 + { + class Mp4IsoBox + { + public: + //! constructor for base class + Mp4IsoBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + //! destructor - simply freeing private ptr + virtual ~Mp4IsoBox(); + + //! function to get the fourcc code + MP4::Fourcc fourcc() const; + //! function to get the size of tha atom/box + uint size() const; + //! function to get the offset of the atom in the mp4 file + long offset() const; + + //! parse wrapper to get common interface for both box and fullbox + virtual void parsebox(); + //! pure virtual function for all subclasses to implement + virtual void parse() = 0; + + protected: + //! function to get the file pointer + TagLib::File* file() const; + + protected: + class Mp4IsoBoxPrivate; + Mp4IsoBoxPrivate* d; + }; + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4ISOBOX_H + diff --git a/src/metadata/m4a/mp4isofullbox.cpp b/src/metadata/m4a/mp4isofullbox.cpp new file mode 100644 index 0000000..f938ad4 --- /dev/null +++ b/src/metadata/m4a/mp4isofullbox.cpp @@ -0,0 +1,67 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "mp4isofullbox.h" +#include "tfile.h" + +using namespace TagLib; + +class MP4::Mp4IsoFullBox::Mp4IsoFullBoxPrivate +{ +public: + uchar version; + uint flags; +}; // Mp4IsoFullBoxPrivate + + +MP4::Mp4IsoFullBox::Mp4IsoFullBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) +: Mp4IsoBox( file, fourcc, size, offset ) +{ + d = new MP4::Mp4IsoFullBox::Mp4IsoFullBoxPrivate(); +} + +MP4::Mp4IsoFullBox::~Mp4IsoFullBox() +{ + delete d; +} + +void MP4::Mp4IsoFullBox::parsebox() +{ + // seek to offset + Mp4IsoBox::file()->seek(Mp4IsoBox::offset(), File::Beginning ); + // parse version and flags + ByteVector version_flags = Mp4IsoBox::file()->readBlock(4); + d->version = version_flags[0]; + d->flags = version_flags[1] << 16 || version_flags[2] << 8 || version_flags[3]; + // call parse method of subclass + parse(); +} + +TagLib::uchar MP4::Mp4IsoFullBox::version() +{ + return d->version; +} + +TagLib::uint MP4::Mp4IsoFullBox::flags() +{ + return d->flags; +} + diff --git a/src/metadata/m4a/mp4isofullbox.h b/src/metadata/m4a/mp4isofullbox.h new file mode 100644 index 0000000..bc01b61 --- /dev/null +++ b/src/metadata/m4a/mp4isofullbox.h @@ -0,0 +1,57 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4ISOFULLBOX_H +#define MP4ISOFULLBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class Mp4IsoFullBox : public Mp4IsoBox + { + public: + //! constructor for full box + Mp4IsoFullBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + //! destructor for mp4 iso full box + virtual ~Mp4IsoFullBox(); + + //! function to get the version of box + uchar version(); + //! function to get the flag map + uint flags(); + + //! parse wrapper to get common interface for both box and fullbox + virtual void parsebox(); + + protected: + class Mp4IsoFullBoxPrivate; + Mp4IsoFullBoxPrivate* d; + }; + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4ISOFULLBOX_H + diff --git a/src/metadata/m4a/mp4itunestag.cpp b/src/metadata/m4a/mp4itunestag.cpp new file mode 100644 index 0000000..aabd644 --- /dev/null +++ b/src/metadata/m4a/mp4itunestag.cpp @@ -0,0 +1,197 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "mp4itunestag.h" + +using namespace TagLib; + +class MP4::Tag::TagPrivate +{ +public: + MP4::File* mp4file; + TagLib::String title; + TagLib::String artist; + TagLib::String album; + TagLib::String genre; + TagLib::uint year; + TagLib::uint track; + TagLib::String comment; + TagLib::String grouping; + TagLib::String composer; + TagLib::uint disk; + TagLib::uint bpm; + bool isEmpty; + TagLib::ByteVector cover; +}; + + +MP4::Tag::Tag( ) +{ + d = new TagPrivate(); + d->year = 0; + d->track = 0; + d->disk = 0; + d->bpm = 0; + d->isEmpty = true; +} + +MP4::Tag::~Tag() +{ + delete d; +} + +String MP4::Tag::title() const +{ + return d->title; +} + +String MP4::Tag::artist() const +{ + return d->artist; +} + +String MP4::Tag::album() const +{ + return d->album; +} + +String MP4::Tag::comment() const +{ + return d->comment; +} + +String MP4::Tag::genre() const +{ + return d->genre; +} + +TagLib::uint MP4::Tag::year() const +{ + return d->year; +} + +TagLib::uint MP4::Tag::track() const +{ + return d->track; +} + +String MP4::Tag::grouping() const +{ + return d->grouping; +} + +String MP4::Tag::composer() const +{ + return d->composer; +} + +TagLib::uint MP4::Tag::disk() const +{ + return d->disk; +} + +TagLib::uint MP4::Tag::bpm() const +{ + return d->bpm; +} + +TagLib::ByteVector MP4::Tag::cover() const +{ + return d->cover; +} + +void MP4::Tag::setTitle(const String &s) +{ + d->title = s; + d->isEmpty = false; +} + +void MP4::Tag::setArtist(const String &s) +{ + d->artist = s; + d->isEmpty = false; +} + +void MP4::Tag::setAlbum(const String &s) +{ + d->album = s; + d->isEmpty = false; +} + +void MP4::Tag::setComment(const String &s) +{ + d->comment = s; + d->isEmpty = false; +} + +void MP4::Tag::setGenre(const String &s) +{ + d->genre = s; + d->isEmpty = false; +} + +void MP4::Tag::setYear(const TagLib::uint i) +{ + d->year = i; + d->isEmpty = false; +} + +void MP4::Tag::setTrack(const TagLib::uint i) +{ + d->track = i; + d->isEmpty = false; +} + +void MP4::Tag::setGrouping(const String &s) +{ + d->grouping = s; + d->isEmpty = false; +} + +void MP4::Tag::setComposer(const String &s) +{ + d->composer = s; + d->isEmpty = false; +} + +void MP4::Tag::setDisk(const TagLib::uint i) +{ + d->disk = i; + d->isEmpty = false; +} + +void MP4::Tag::setBpm(const TagLib::uint i) +{ + d->bpm = i; + d->isEmpty = false; +} + +void MP4::Tag::setCover(const TagLib::ByteVector& c) +{ + d->cover = c; + d->isEmpty = false; +} + +bool MP4::Tag::isEmpty() const +{ + return d->isEmpty; +} + diff --git a/src/metadata/m4a/mp4itunestag.h b/src/metadata/m4a/mp4itunestag.h new file mode 100644 index 0000000..9e572a7 --- /dev/null +++ b/src/metadata/m4a/mp4itunestag.h @@ -0,0 +1,95 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4ITUNESTAG_H +#define MP4ITUNESTAG_H + +#include "taglib.h" +#include "tstring.h" +#include "tag.h" + +namespace TagLib +{ + namespace MP4 + { + class File; + + class Tag : public TagLib::Tag + { + public: + /*! + * Constructs an empty MP4 iTunes tag. + */ + Tag( ); + + /*! + * Destroys this Tag instance. + */ + virtual ~Tag(); + + // Reimplementations. + + virtual String title() const; + virtual String artist() const; + virtual String album() const; + virtual String comment() const; + virtual String genre() const; + virtual uint year() const; + virtual uint track() const; + + virtual void setTitle(const String &s); + virtual void setArtist(const String &s); + virtual void setAlbum(const String &s); + virtual void setComment(const String &s); + virtual void setGenre(const String &s); + virtual void setYear(const uint i); + virtual void setTrack(const uint i); + + // MP4 specific fields + + String grouping() const; + String composer() const; + uint disk() const; + uint bpm() const; + ByteVector cover() const; + int compilation() const { return -1; } + + void setGrouping(const String &s); + void setComposer(const String &s); + void setDisk(const uint i); + void setBpm(const uint i); + void setCover( const ByteVector& cover ); + void setCompilation( bool /*isCompilation*/ ) {} + + virtual bool isEmpty() const; + + private: + Tag(const Tag &); + Tag &operator=(const Tag &); + + class TagPrivate; + TagPrivate *d; + }; + } // namespace MP4 + +} // namespace TagLib + +#endif // MP4ITUNESTAG_H diff --git a/src/metadata/m4a/mp4mdiabox.cpp b/src/metadata/m4a/mp4mdiabox.cpp new file mode 100644 index 0000000..c3b30ad --- /dev/null +++ b/src/metadata/m4a/mp4mdiabox.cpp @@ -0,0 +1,111 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "tlist.h" +#include <iostream> +#include "mp4mdiabox.h" +#include "mp4hdlrbox.h" +#include "mp4minfbox.h" +#include "boxfactory.h" +#include "mp4file.h" + +using namespace TagLib; + +class MP4::Mp4MdiaBox::Mp4MdiaBoxPrivate +{ +public: + //! container for all boxes in mdia box + TagLib::List<Mp4IsoBox*> mdiaBoxes; + //! a box factory for creating the appropriate boxes + MP4::BoxFactory boxfactory; +}; // class Mp4MdiaBoxPrivate + +MP4::Mp4MdiaBox::Mp4MdiaBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ) + : Mp4IsoBox( file, fourcc, size, offset ) +{ + d = new MP4::Mp4MdiaBox::Mp4MdiaBoxPrivate(); +} + +MP4::Mp4MdiaBox::~Mp4MdiaBox() +{ + TagLib::List<Mp4IsoBox*>::Iterator delIter; + for( delIter = d->mdiaBoxes.begin(); + delIter != d->mdiaBoxes.end(); + delIter++ ) + { + delete *delIter; + } + delete d; +} + +void MP4::Mp4MdiaBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() ); + + TagLib::uint totalsize = 8; + // parse all contained boxes + TagLib::uint size; + MP4::Fourcc fourcc; + + // stores the current handler type + TagLib::MP4::Fourcc hdlrtype; + + while( (mp4file->readSizeAndType( size, fourcc ) == true) ) + { + totalsize += size; + + // check for errors + if( totalsize > MP4::Mp4IsoBox::size() ) + { + std::cerr << "Error in mp4 file " << mp4file->name() << " mdia box contains bad box with name: " << fourcc.toString() << std::endl; + return; + } + + // create the appropriate subclass and parse it + MP4::Mp4IsoBox* curbox = d->boxfactory.createInstance( mp4file, fourcc, size, mp4file->tell() ); + if( static_cast<TagLib::uint>( fourcc ) == 0x6d696e66 /*"minf"*/ ) + { + // cast to minf + Mp4MinfBox* minfbox = dynamic_cast<Mp4MinfBox*>( curbox ); + if(!minfbox) + return; + // set handler type + minfbox->setHandlerType( hdlrtype ); + } + + curbox->parsebox(); + d->mdiaBoxes.append( curbox ); + + if(static_cast<TagLib::uint>( fourcc ) == 0x68646c72 /*"hdlr"*/ ) + { + // cast to hdlr box + Mp4HdlrBox* hdlrbox = dynamic_cast<Mp4HdlrBox*>( curbox ); + if(!hdlrbox) + return; + // get handler type + hdlrtype = hdlrbox->hdlr_type(); + } + // check for end of mdia box + if( totalsize == MP4::Mp4IsoBox::size() ) + break; + + } +} diff --git a/src/metadata/m4a/mp4mdiabox.h b/src/metadata/m4a/mp4mdiabox.h new file mode 100644 index 0000000..16503bd --- /dev/null +++ b/src/metadata/m4a/mp4mdiabox.h @@ -0,0 +1,49 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4MDIABOX_H +#define MP4MDIABOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class Mp4MdiaBox: public Mp4IsoBox + { + public: + Mp4MdiaBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ); + ~Mp4MdiaBox(); + + //! parse mdia contents + void parse(); + + private: + class Mp4MdiaBoxPrivate; + Mp4MdiaBoxPrivate* d; + }; // Mp4MdiaBox + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4MDIABOX_H diff --git a/src/metadata/m4a/mp4metabox.cpp b/src/metadata/m4a/mp4metabox.cpp new file mode 100644 index 0000000..30eebf2 --- /dev/null +++ b/src/metadata/m4a/mp4metabox.cpp @@ -0,0 +1,86 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <tlist.h> +#include <iostream> +#include "mp4metabox.h" +#include "boxfactory.h" +#include "mp4file.h" + +using namespace TagLib; + +class MP4::Mp4MetaBox::Mp4MetaBoxPrivate +{ +public: + //! container for all boxes in meta box + TagLib::List<Mp4IsoBox*> metaBoxes; + //! a box factory for creating the appropriate boxes + MP4::BoxFactory boxfactory; +}; // class Mp4MetaBoxPrivate + +MP4::Mp4MetaBox::Mp4MetaBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ) + : Mp4IsoFullBox( file, fourcc, size, offset ) +{ + d = new MP4::Mp4MetaBox::Mp4MetaBoxPrivate(); +} + +MP4::Mp4MetaBox::~Mp4MetaBox() +{ + TagLib::List<Mp4IsoBox*>::Iterator delIter; + for( delIter = d->metaBoxes.begin(); + delIter != d->metaBoxes.end(); + delIter++ ) + { + delete *delIter; + } + delete d; +} + +void MP4::Mp4MetaBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() ); + + TagLib::uint totalsize = 12; // initial size of box + // parse all contained boxes + TagLib::uint size; + MP4::Fourcc fourcc; + + while( (mp4file->readSizeAndType( size, fourcc ) == true) ) + { + totalsize += size; + + // check for errors + if( totalsize > MP4::Mp4IsoBox::size() ) + { + std::cerr << "Error in mp4 file " << mp4file->name() << " meta box contains bad box with name: " << fourcc.toString() << std::endl; + return; + } + + // create the appropriate subclass and parse it + MP4::Mp4IsoBox* curbox = d->boxfactory.createInstance( mp4file, fourcc, size, mp4file->tell() ); + curbox->parsebox(); + d->metaBoxes.append( curbox ); + + // check for end of meta box + if( totalsize == MP4::Mp4IsoBox::size() ) + break; + } +} diff --git a/src/metadata/m4a/mp4metabox.h b/src/metadata/m4a/mp4metabox.h new file mode 100644 index 0000000..58d9667 --- /dev/null +++ b/src/metadata/m4a/mp4metabox.h @@ -0,0 +1,49 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4METABOX_H +#define MP4METABOX_H + +#include "mp4isofullbox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class Mp4MetaBox: public Mp4IsoFullBox + { + public: + Mp4MetaBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ); + ~Mp4MetaBox(); + + //! parse meta contents + void parse(); + + private: + class Mp4MetaBoxPrivate; + Mp4MetaBoxPrivate* d; + }; // Mp4MetaBox + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4METABOX_H diff --git a/src/metadata/m4a/mp4minfbox.cpp b/src/metadata/m4a/mp4minfbox.cpp new file mode 100644 index 0000000..0081dda --- /dev/null +++ b/src/metadata/m4a/mp4minfbox.cpp @@ -0,0 +1,104 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "tlist.h" +#include <iostream> +#include "mp4minfbox.h" +#include "mp4stblbox.h" +#include "boxfactory.h" +#include "mp4file.h" + +using namespace TagLib; + +class MP4::Mp4MinfBox::Mp4MinfBoxPrivate +{ +public: + //! container for all boxes in minf box + TagLib::List<Mp4IsoBox*> minfBoxes; + //! a box factory for creating the appropriate boxes + MP4::BoxFactory boxfactory; + //! stores the handler type of the current trak + MP4::Fourcc handler_type; +}; // class Mp4MinfBoxPrivate + +MP4::Mp4MinfBox::Mp4MinfBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ) + : Mp4IsoBox( file, fourcc, size, offset ) +{ + d = new MP4::Mp4MinfBox::Mp4MinfBoxPrivate(); +} + +MP4::Mp4MinfBox::~Mp4MinfBox() +{ + TagLib::List<Mp4IsoBox*>::Iterator delIter; + for( delIter = d->minfBoxes.begin(); + delIter != d->minfBoxes.end(); + delIter++ ) + { + delete *delIter; + } + delete d; +} + +void MP4::Mp4MinfBox::setHandlerType( MP4::Fourcc fourcc ) +{ + d->handler_type = fourcc; +} + +void MP4::Mp4MinfBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() ); + + TagLib::uint totalsize = 8; + // parse all contained boxes + TagLib::uint size; + MP4::Fourcc fourcc; + + while( (mp4file->readSizeAndType( size, fourcc ) == true) ) + { + totalsize += size; + + // check for errors + if( totalsize > MP4::Mp4IsoBox::size() ) + { + std::cerr << "Error in mp4 file " << mp4file->name() << " minf box contains bad box with name: " << fourcc.toString() << std::endl; + return; + } + + // create the appropriate subclass and parse it + MP4::Mp4IsoBox* curbox = d->boxfactory.createInstance( mp4file, fourcc, size, mp4file->tell() ); + if(static_cast<TagLib::uint>( fourcc ) == 0x7374626c /*stbl*/ ) + { + // cast to hdlr box + Mp4StblBox* stblbox = dynamic_cast<Mp4StblBox*>( curbox ); + if(!stblbox) + return; + // set handler type + stblbox->setHandlerType( d->handler_type ); + } + + curbox->parsebox(); + d->minfBoxes.append( curbox ); + + // check for end of minf box + if( totalsize == MP4::Mp4IsoBox::size() ) + break; + } +} diff --git a/src/metadata/m4a/mp4minfbox.h b/src/metadata/m4a/mp4minfbox.h new file mode 100644 index 0000000..9195d30 --- /dev/null +++ b/src/metadata/m4a/mp4minfbox.h @@ -0,0 +1,51 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4MINFBOX_H +#define MP4MINFBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class Mp4MinfBox: public Mp4IsoBox + { + public: + Mp4MinfBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ); + ~Mp4MinfBox(); + + //! parse minf contents + void parse(); + //! set the handler type - needed for stsd + void setHandlerType( MP4::Fourcc fourcc ); + + private: + class Mp4MinfBoxPrivate; + Mp4MinfBoxPrivate* d; + }; // Mp4MinfBox + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4MINFBOX_H diff --git a/src/metadata/m4a/mp4moovbox.cpp b/src/metadata/m4a/mp4moovbox.cpp new file mode 100644 index 0000000..24826ec --- /dev/null +++ b/src/metadata/m4a/mp4moovbox.cpp @@ -0,0 +1,86 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "tlist.h" +#include <iostream> +#include "mp4moovbox.h" +#include "boxfactory.h" +#include "mp4file.h" + +using namespace TagLib; + +class MP4::Mp4MoovBox::Mp4MoovBoxPrivate +{ +public: + //! container for all boxes in moov box + TagLib::List<Mp4IsoBox*> moovBoxes; + //! a box factory for creating the appropriate boxes + MP4::BoxFactory boxfactory; +}; // class Mp4MoovBoxPrivate + +MP4::Mp4MoovBox::Mp4MoovBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ) + : Mp4IsoBox( file, fourcc, size, offset ) +{ + d = new MP4::Mp4MoovBox::Mp4MoovBoxPrivate(); +} + +MP4::Mp4MoovBox::~Mp4MoovBox() +{ + TagLib::List<Mp4IsoBox*>::Iterator delIter; + for( delIter = d->moovBoxes.begin(); + delIter != d->moovBoxes.end(); + delIter++ ) + { + delete *delIter; + } + delete d; +} + +void MP4::Mp4MoovBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() ); + + TagLib::uint totalsize = 8; + // parse all contained boxes + TagLib::uint size; + MP4::Fourcc fourcc; + + while( (mp4file->readSizeAndType( size, fourcc ) == true) ) + { + totalsize += size; + + // check for errors + if( totalsize > MP4::Mp4IsoBox::size() ) + { + std::cerr << "Error in mp4 file " << mp4file->name() << " moov box contains bad box with name: " << fourcc.toString() << std::endl; + return; + } + + // create the appropriate subclass and parse it + MP4::Mp4IsoBox* curbox = d->boxfactory.createInstance( mp4file, fourcc, size, mp4file->tell() ); + curbox->parsebox(); + d->moovBoxes.append( curbox ); + + // check for end of moov box + if( totalsize == MP4::Mp4IsoBox::size() ) + break; + } +} diff --git a/src/metadata/m4a/mp4moovbox.h b/src/metadata/m4a/mp4moovbox.h new file mode 100644 index 0000000..390953f --- /dev/null +++ b/src/metadata/m4a/mp4moovbox.h @@ -0,0 +1,49 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4MOOVBOX_H +#define MP4MOOVBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class Mp4MoovBox: public Mp4IsoBox + { + public: + Mp4MoovBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ); + ~Mp4MoovBox(); + + //! parse moov contents + void parse(); + + private: + class Mp4MoovBoxPrivate; + Mp4MoovBoxPrivate* d; + }; // Mp4MoovBox + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4MOOVBOX_H diff --git a/src/metadata/m4a/mp4mvhdbox.cpp b/src/metadata/m4a/mp4mvhdbox.cpp new file mode 100644 index 0000000..36053e4 --- /dev/null +++ b/src/metadata/m4a/mp4mvhdbox.cpp @@ -0,0 +1,140 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <deque> +#include <iostream> +#include "mp4mvhdbox.h" +#include "boxfactory.h" +#include "mp4file.h" +#include "mp4propsproxy.h" + +using namespace TagLib; + +class MP4::Mp4MvhdBox::Mp4MvhdBoxPrivate +{ +public: + //! creation time of the file + TagLib::ulonglong creationTime; + //! modification time of the file - since midnight, Jan. 1, 1904, UTC-time + TagLib::ulonglong modificationTime; + //! timescale for the file - referred by all time specifications in this box + TagLib::uint timescale; + //! duration of presentation + TagLib::ulonglong duration; + //! playout speed + TagLib::uint rate; + //! volume for entire presentation + TagLib::uint volume; + //! track ID for an additional track (next new track) + TagLib::uint nextTrackID; +}; // class Mp4MvhdBoxPrivate + +MP4::Mp4MvhdBox::Mp4MvhdBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ) + : Mp4IsoFullBox( file, fourcc, size, offset ) +{ + d = new MP4::Mp4MvhdBox::Mp4MvhdBoxPrivate(); +} + +MP4::Mp4MvhdBox::~Mp4MvhdBox() +{ + delete d; +} + +TagLib::ulonglong MP4::Mp4MvhdBox::creationTime() const +{ + return d->creationTime; +} + +TagLib::ulonglong MP4::Mp4MvhdBox::modificationTime() const +{ + return d->modificationTime; +} + +TagLib::uint MP4::Mp4MvhdBox::timescale() const +{ + return d->timescale; +} + +TagLib::ulonglong MP4::Mp4MvhdBox::duration() const +{ + return d->duration; +} + +TagLib::uint MP4::Mp4MvhdBox::rate() const +{ + return d->rate; +} + +TagLib::uint MP4::Mp4MvhdBox::volume() const +{ + return d->volume; +} + +TagLib::uint MP4::Mp4MvhdBox::nextTrackID() const +{ + return d->nextTrackID; +} + + +void MP4::Mp4MvhdBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() ); + + if( version() == 1 ) + { + if( !mp4file->readLongLong( d->creationTime ) ) + return; + if( !mp4file->readLongLong( d->modificationTime ) ) + return; + if( !mp4file->readInt( d->timescale ) ) + return; + if( !mp4file->readLongLong( d->duration ) ) + return; + } + else + { + TagLib::uint creationTime_tmp, modificationTime_tmp, duration_tmp; + + if( !mp4file->readInt( creationTime_tmp ) ) + return; + if( !mp4file->readInt( modificationTime_tmp ) ) + return; + if( !mp4file->readInt( d->timescale ) ) + return; + if( !mp4file->readInt( duration_tmp ) ) + return; + + d->creationTime = creationTime_tmp; + d->modificationTime = modificationTime_tmp; + d->duration = duration_tmp; + } + if( !mp4file->readInt( d->rate ) ) + return; + if( !mp4file->readInt( d->volume ) ) + return; + // jump over unused fields + mp4file->seek( 68, File::Current ); + + if( !mp4file->readInt( d->nextTrackID ) ) + return; + // register at proxy + mp4file->propProxy()->registerMvhd( this ); +} diff --git a/src/metadata/m4a/mp4mvhdbox.h b/src/metadata/m4a/mp4mvhdbox.h new file mode 100644 index 0000000..b133485 --- /dev/null +++ b/src/metadata/m4a/mp4mvhdbox.h @@ -0,0 +1,65 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4MVHDBOX_H +#define MP4MVHDBOX_H + +#include "mp4isofullbox.h" +#include "mp4fourcc.h" +#include "mp4file.h" // ulonglong + +namespace TagLib +{ + namespace MP4 + { + class Mp4MvhdBox: public Mp4IsoFullBox + { + public: + Mp4MvhdBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ); + ~Mp4MvhdBox(); + + //! function to get the creation time of the mp4 file + ulonglong creationTime() const; + //! function to get the modification time of the mp4 file + ulonglong modificationTime() const; + //! function to get the timescale referenced by the above timestamps + uint timescale() const; + //! function to get the presentation duration in the mp4 file + ulonglong duration() const; + //! function to get the rate (playout speed) - typically 1.0; + uint rate() const; + //! function to get volume level for presentation - typically 1.0; + uint volume() const; + //! function to get the track ID for adding new tracks - useless for this lib + uint nextTrackID() const; + + //! parse mvhd contents + void parse(); + + private: + class Mp4MvhdBoxPrivate; + Mp4MvhdBoxPrivate* d; + }; // Mp4MvhdBox + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4MVHDBOX_H diff --git a/src/metadata/m4a/mp4propsproxy.cpp b/src/metadata/m4a/mp4propsproxy.cpp new file mode 100644 index 0000000..ebee9c2 --- /dev/null +++ b/src/metadata/m4a/mp4propsproxy.cpp @@ -0,0 +1,89 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "mp4propsproxy.h" + +using namespace TagLib; + +class MP4::Mp4PropsProxy::Mp4PropsProxyPrivate +{ +public: + //! the movie header box + MP4::Mp4MvhdBox* mvhdbox; + //! the sample table box + MP4::Mp4AudioSampleEntry* audiosampleentry; +}; + + +MP4::Mp4PropsProxy::Mp4PropsProxy() +{ + d = new MP4::Mp4PropsProxy::Mp4PropsProxyPrivate(); + d->mvhdbox = 0; + d->audiosampleentry = 0; +} + +MP4::Mp4PropsProxy::~Mp4PropsProxy() +{ + delete d; +} + +TagLib::uint MP4::Mp4PropsProxy::seconds() const +{ + if( d->mvhdbox ) + return static_cast<TagLib::uint>( d->mvhdbox->duration() / d->mvhdbox->timescale() ); + else + return 0; +} + +TagLib::uint MP4::Mp4PropsProxy::channels() const +{ + if( d->audiosampleentry ) + return d->audiosampleentry->channels(); + else + return 0; +} + +TagLib::uint MP4::Mp4PropsProxy::sampleRate() const +{ + if( d->audiosampleentry ) + return (d->audiosampleentry->samplerate()>>16); + else + return 0; +} + +TagLib::uint MP4::Mp4PropsProxy::bitRate() const +{ + if( d->audiosampleentry ) + return (d->audiosampleentry->bitrate()); + else + return 0; +} + +void MP4::Mp4PropsProxy::registerMvhd( MP4::Mp4MvhdBox* mvhdbox ) +{ + d->mvhdbox = mvhdbox; +} + +void MP4::Mp4PropsProxy::registerAudioSampleEntry( MP4::Mp4AudioSampleEntry* audioSampleEntry ) +{ + d->audiosampleentry = audioSampleEntry; +} + diff --git a/src/metadata/m4a/mp4propsproxy.h b/src/metadata/m4a/mp4propsproxy.h new file mode 100644 index 0000000..0ea29e2 --- /dev/null +++ b/src/metadata/m4a/mp4propsproxy.h @@ -0,0 +1,65 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4PROPSPROXY_H +#define MP4PROPSPROXY_H MP4PROPSPROXY_H +#include "mp4mvhdbox.h" +#include "mp4audiosampleentry.h" + +namespace TagLib +{ + namespace MP4 + { + //! Mp4PropsProxy is used to access the stsd box and mvhd box directly + /*! this class works as a shortcut to avoid stepping through all parent boxes + * to access the boxes in question + */ + class Mp4PropsProxy + { + public: + //! constructor for properties proxy + Mp4PropsProxy(); + //! destructor + ~Mp4PropsProxy(); + + //! function to get length of media in seconds + TagLib::uint seconds() const; + //! function to get the nunmber of channels + TagLib::uint channels() const; + //! function to get the sample rate + TagLib::uint sampleRate() const; + //! function to get the bitrate rate + TagLib::uint bitRate() const; + + //! function to register the movie header box - mvhd + void registerMvhd( MP4::Mp4MvhdBox* mvhdbox ); + //! function to register the sample description box + void registerAudioSampleEntry( MP4::Mp4AudioSampleEntry* audiosampleentry ); + + private: + class Mp4PropsProxyPrivate; + Mp4PropsProxyPrivate* d; + + }; // Mp4PropsProxy + } // MP4 +} // TagLib + +#endif // MP4PROPSPROXY_H diff --git a/src/metadata/m4a/mp4sampleentry.cpp b/src/metadata/m4a/mp4sampleentry.cpp new file mode 100644 index 0000000..e5619ea --- /dev/null +++ b/src/metadata/m4a/mp4sampleentry.cpp @@ -0,0 +1,59 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "mp4sampleentry.h" +#include "mp4isobox.h" +#include "mp4file.h" + +using namespace TagLib; + +class MP4::Mp4SampleEntry::Mp4SampleEntryPrivate +{ +public: + TagLib::uint data_reference_index; +}; + +MP4::Mp4SampleEntry::Mp4SampleEntry( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) + :Mp4IsoBox(file, fourcc, size, offset) +{ + d = new MP4::Mp4SampleEntry::Mp4SampleEntryPrivate(); +} + +MP4::Mp4SampleEntry::~Mp4SampleEntry() +{ + delete d; +} + +//! parse the content of the box +void MP4::Mp4SampleEntry::parse() +{ + TagLib::MP4::File* mp4file = dynamic_cast<TagLib::MP4::File*>(file()); + if(!mp4file) + return; + + // skip the first 6 bytes + mp4file->seek( 6, TagLib::File::Current ); + // read data reference index + if(!mp4file->readShort( d->data_reference_index)) + return; + parseEntry(); +} + diff --git a/src/metadata/m4a/mp4sampleentry.h b/src/metadata/m4a/mp4sampleentry.h new file mode 100644 index 0000000..39475f7 --- /dev/null +++ b/src/metadata/m4a/mp4sampleentry.h @@ -0,0 +1,54 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4SAMPLEENTRY_H +#define MP4SAMPLEENTRY_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class Mp4SampleEntry: public Mp4IsoBox + { + public: + Mp4SampleEntry( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + ~Mp4SampleEntry(); + + public: + //! parse the content of the box + virtual void parse(); + + private: + //! function to be implemented in subclass + virtual void parseEntry() = 0; + + protected: + class Mp4SampleEntryPrivate; + Mp4SampleEntryPrivate* d; + }; // class Mp4SampleEntry + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4SAMPLEENTRY_H diff --git a/src/metadata/m4a/mp4skipbox.cpp b/src/metadata/m4a/mp4skipbox.cpp new file mode 100644 index 0000000..8cb5218 --- /dev/null +++ b/src/metadata/m4a/mp4skipbox.cpp @@ -0,0 +1,50 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "mp4skipbox.h" +#include "mp4isobox.h" +#include "tfile.h" + +using namespace TagLib; + +class MP4::Mp4SkipBox::Mp4SkipBoxPrivate +{ +public: +}; + +MP4::Mp4SkipBox::Mp4SkipBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ) + :Mp4IsoBox(file, fourcc, size, offset) +{ + d = new MP4::Mp4SkipBox::Mp4SkipBoxPrivate(); +} + +MP4::Mp4SkipBox::~Mp4SkipBox() +{ + delete d; +} + +//! parse the content of the box +void MP4::Mp4SkipBox::parse() +{ + // skip contents + file()->seek( size() - 8, TagLib::File::Current ); +} + diff --git a/src/metadata/m4a/mp4skipbox.h b/src/metadata/m4a/mp4skipbox.h new file mode 100644 index 0000000..896fcaa --- /dev/null +++ b/src/metadata/m4a/mp4skipbox.h @@ -0,0 +1,50 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4SKIPBOX_H +#define MP4SKIPBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class Mp4SkipBox: public Mp4IsoBox + { + public: + Mp4SkipBox( TagLib::File* file, MP4::Fourcc fourcc, uint size, long offset ); + ~Mp4SkipBox(); + + private: + //! parse the content of the box + virtual void parse(); + + protected: + class Mp4SkipBoxPrivate; + Mp4SkipBoxPrivate* d; + }; // class Mp4SkipBox + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4SKIPBOX_H diff --git a/src/metadata/m4a/mp4stblbox.cpp b/src/metadata/m4a/mp4stblbox.cpp new file mode 100644 index 0000000..f67de59 --- /dev/null +++ b/src/metadata/m4a/mp4stblbox.cpp @@ -0,0 +1,105 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "tlist.h" +#include <iostream> +#include "mp4stblbox.h" +#include "mp4stsdbox.h" +#include "boxfactory.h" +#include "mp4file.h" + +using namespace TagLib; + +class MP4::Mp4StblBox::Mp4StblBoxPrivate +{ +public: + //! container for all boxes in stbl box + TagLib::List<Mp4IsoBox*> stblBoxes; + //! a box factory for creating the appropriate boxes + MP4::BoxFactory boxfactory; + //! the handler type for the current trak + MP4::Fourcc handler_type; +}; // class Mp4StblBoxPrivate + +MP4::Mp4StblBox::Mp4StblBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ) + : Mp4IsoBox( file, fourcc, size, offset ) +{ + d = new MP4::Mp4StblBox::Mp4StblBoxPrivate(); +} + +MP4::Mp4StblBox::~Mp4StblBox() +{ + TagLib::List<Mp4IsoBox*>::Iterator delIter; + for( delIter = d->stblBoxes.begin(); + delIter != d->stblBoxes.end(); + delIter++ ) + { + delete *delIter; + } + delete d; +} + +void MP4::Mp4StblBox::setHandlerType( MP4::Fourcc fourcc ) +{ + d->handler_type = fourcc; +} + +void MP4::Mp4StblBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() ); + + TagLib::uint totalsize = 8; + // parse all contained boxes + TagLib::uint size; + MP4::Fourcc fourcc; + + while( (mp4file->readSizeAndType( size, fourcc ) == true) ) + { + totalsize += size; + + // check for errors + if( totalsize > MP4::Mp4IsoBox::size() ) + { + std::cerr << "Error in mp4 file " << mp4file->name() << " stbl box contains bad box with name: " << fourcc.toString() << std::endl; + return; + } + + // create the appropriate subclass and parse it + MP4::Mp4IsoBox* curbox = d->boxfactory.createInstance( mp4file, fourcc, size, mp4file->tell() ); + + // check for stsd + if( static_cast<TagLib::uint>(fourcc) == 0x73747364 /*'stsd'*/ ) + { + // cast to stsd box + MP4::Mp4StsdBox* stsdbox = dynamic_cast<MP4::Mp4StsdBox*>(curbox); + if(!stsdbox) + return; + // set the handler type + stsdbox->setHandlerType( d->handler_type ); + } + curbox->parsebox(); + d->stblBoxes.append( curbox ); + + // check for end of stbl box + if( totalsize == MP4::Mp4IsoBox::size() ) + break; + } +} diff --git a/src/metadata/m4a/mp4stblbox.h b/src/metadata/m4a/mp4stblbox.h new file mode 100644 index 0000000..39619a6 --- /dev/null +++ b/src/metadata/m4a/mp4stblbox.h @@ -0,0 +1,51 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4STBLBOX_H +#define MP4STBLBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class Mp4StblBox: public Mp4IsoBox + { + public: + Mp4StblBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ); + ~Mp4StblBox(); + + //! parse stbl contents + void parse(); + //! set the handler type - needed for stsd + void setHandlerType( MP4::Fourcc fourcc ); + + private: + class Mp4StblBoxPrivate; + Mp4StblBoxPrivate* d; + }; // Mp4StblBox + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4STBLBOX_H diff --git a/src/metadata/m4a/mp4stsdbox.cpp b/src/metadata/m4a/mp4stsdbox.cpp new file mode 100644 index 0000000..6bb8cbe --- /dev/null +++ b/src/metadata/m4a/mp4stsdbox.cpp @@ -0,0 +1,91 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "tlist.h" +#include <iostream> +#include "mp4stsdbox.h" +#include "mp4audiosampleentry.h" +#include "mp4file.h" + +using namespace TagLib; + +class MP4::Mp4StsdBox::Mp4StsdBoxPrivate +{ +public: + //! the handler type for the current trak + MP4::Fourcc handler_type; + //! the audio sample entry + MP4::Mp4AudioSampleEntry* audioSampleEntry; +}; // class Mp4StsdBoxPrivate + +MP4::Mp4StsdBox::Mp4StsdBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ) + : Mp4IsoFullBox( file, fourcc, size, offset ) +{ + d = new MP4::Mp4StsdBox::Mp4StsdBoxPrivate(); +} + +MP4::Mp4StsdBox::~Mp4StsdBox() +{ + delete d; +} + +void MP4::Mp4StsdBox::setHandlerType( MP4::Fourcc fourcc ) +{ + d->handler_type = fourcc; +} + +void MP4::Mp4StsdBox::parse() +{ + MP4::File* mp4file = dynamic_cast<MP4::File*>( file() ); + if(!mp4file) + return; + + TagLib::uint totalsize = 12; // initial size of box + + // check for handler type - only parse if 'soun': + if( static_cast<TagLib::uint>(d->handler_type) == 0x736f756e ) + { + // read entry count + TagLib::uint entry_count; + if(!mp4file->readInt( entry_count )) + return; + + // simply read first entry and skip all following + // read size and type + TagLib::uint cursize; + MP4::Fourcc fourcc; + if( !mp4file->readSizeAndType( cursize, fourcc )) + return; + + totalsize += 12; + // alocate an AudioSampleEntry + d->audioSampleEntry = new MP4::Mp4AudioSampleEntry( mp4file, fourcc, cursize, mp4file->tell() ); + // parse the AudioSampleEntry + d->audioSampleEntry->parse(); + totalsize += cursize-8; + // skip the remaining box contents + mp4file->seek( size()-totalsize, TagLib::File::Current ); + } + else + { + mp4file->seek( size()-totalsize, TagLib::File::Current ); + } +} diff --git a/src/metadata/m4a/mp4stsdbox.h b/src/metadata/m4a/mp4stsdbox.h new file mode 100644 index 0000000..90bc014 --- /dev/null +++ b/src/metadata/m4a/mp4stsdbox.h @@ -0,0 +1,51 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4STSDBOX_H +#define MP4STSDBOX_H + +#include "mp4isofullbox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class Mp4StsdBox: public Mp4IsoFullBox + { + public: + Mp4StsdBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ); + ~Mp4StsdBox(); + + //! parse stsd contents + void parse(); + //! set the handler type - needed for stsd + void setHandlerType( MP4::Fourcc fourcc ); + + private: + class Mp4StsdBoxPrivate; + Mp4StsdBoxPrivate* d; + }; // Mp4StsdBox + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4STSDBOX_H diff --git a/src/metadata/m4a/mp4tagsproxy.cpp b/src/metadata/m4a/mp4tagsproxy.cpp new file mode 100644 index 0000000..0a77427 --- /dev/null +++ b/src/metadata/m4a/mp4tagsproxy.cpp @@ -0,0 +1,168 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "mp4tagsproxy.h" +#include "itunesdatabox.h" + +using namespace TagLib; + +class MP4::Mp4TagsProxy::Mp4TagsProxyPrivate +{ +public: + ITunesDataBox* titleData; + ITunesDataBox* artistData; + ITunesDataBox* albumData; + ITunesDataBox* coverData; + ITunesDataBox* genreData; + ITunesDataBox* yearData; + ITunesDataBox* trknData; + ITunesDataBox* commentData; + ITunesDataBox* groupingData; + ITunesDataBox* composerData; + ITunesDataBox* diskData; + ITunesDataBox* bpmData; +}; + +MP4::Mp4TagsProxy::Mp4TagsProxy() +{ + d = new MP4::Mp4TagsProxy::Mp4TagsProxyPrivate(); + d->titleData = 0; + d->artistData = 0; + d->albumData = 0; + d->coverData = 0; + d->genreData = 0; + d->yearData = 0; + d->trknData = 0; + d->commentData = 0; + d->groupingData = 0; + d->composerData = 0; + d->diskData = 0; + d->bpmData = 0; +} + +MP4::Mp4TagsProxy::~Mp4TagsProxy() +{ + delete d; +} + +MP4::ITunesDataBox* MP4::Mp4TagsProxy::titleData() const +{ + return d->titleData; +} + +MP4::ITunesDataBox* MP4::Mp4TagsProxy::artistData() const +{ + return d->artistData; +} + +MP4::ITunesDataBox* MP4::Mp4TagsProxy::albumData() const +{ + return d->albumData; +} + +MP4::ITunesDataBox* MP4::Mp4TagsProxy::genreData() const +{ + return d->genreData; +} + +MP4::ITunesDataBox* MP4::Mp4TagsProxy::yearData() const +{ + return d->yearData; +} + +MP4::ITunesDataBox* MP4::Mp4TagsProxy::trknData() const +{ + return d->trknData; +} + +MP4::ITunesDataBox* MP4::Mp4TagsProxy::commentData() const +{ + return d->commentData; +} + +MP4::ITunesDataBox* MP4::Mp4TagsProxy::groupingData() const +{ + return d->groupingData; +} + +MP4::ITunesDataBox* MP4::Mp4TagsProxy::composerData() const +{ + return d->composerData; +} + +MP4::ITunesDataBox* MP4::Mp4TagsProxy::diskData() const +{ + return d->diskData; +} + +MP4::ITunesDataBox* MP4::Mp4TagsProxy::bpmData() const +{ + return d->bpmData; +} + +MP4::ITunesDataBox* MP4::Mp4TagsProxy::coverData() const +{ + return d->coverData; +} + +void MP4::Mp4TagsProxy::registerBox( EBoxType boxtype, ITunesDataBox* databox ) +{ + switch( boxtype ) + { + case title: + d->titleData = databox; + break; + case artist: + d->artistData = databox; + break; + case album: + d->albumData = databox; + break; + case cover: + d->coverData = databox; + break; + case genre: + d->genreData = databox; + break; + case year: + d->yearData = databox; + break; + case trackno: + d->trknData = databox; + break; + case comment: + d->commentData = databox; + break; + case grouping: + d->groupingData = databox; + break; + case composer: + d->composerData = databox; + break; + case disk: + d->diskData = databox; + break; + case bpm: + d->bpmData = databox; + break; + } +} + diff --git a/src/metadata/m4a/mp4tagsproxy.h b/src/metadata/m4a/mp4tagsproxy.h new file mode 100644 index 0000000..c8bcbf0 --- /dev/null +++ b/src/metadata/m4a/mp4tagsproxy.h @@ -0,0 +1,99 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4TAGSPROXY_H +#define MP4TAGSPROXY_H + +namespace TagLib +{ + namespace MP4 + { + // forward declaration(s) + class ITunesDataBox; + /*! proxy for mp4 itunes tag relevant boxes + * + * this class works as a proxy for the specific tag boxes + * in an mp4 itunes file. the boxes are mired in + * the mp4 file structure and stepping through all box layers + * is avoided by registration at the proxy object. + */ + class Mp4TagsProxy + { + public: + /*! enum for all supported box types */ + typedef enum + { + title = 0, + artist, + album, + cover, + genre, + year, + trackno, + comment, + grouping, + composer, + disk, + bpm + } EBoxType; + + //! constructor + Mp4TagsProxy(); + //! destructor + ~Mp4TagsProxy(); + + //! function to get the data box for the title + ITunesDataBox* titleData() const; + //! function to get the data box for the artist + ITunesDataBox* artistData() const; + //! function to get the data box for the album + ITunesDataBox* albumData() const; + //! function to get the data box for the genre + ITunesDataBox* genreData() const; + //! function to get the data box for the year + ITunesDataBox* yearData() const; + //! function to get the data box for the track number + ITunesDataBox* trknData() const; + //! function to get the data box for the comment + ITunesDataBox* commentData() const; + //! function to get the data box for the grouping + ITunesDataBox* groupingData() const; + //! function to get the data box for the composer + ITunesDataBox* composerData() const; + //! function to get the data box for the disk number + ITunesDataBox* diskData() const; + //! function to get the data box for the bpm + ITunesDataBox* bpmData() const; + //! function to get the data box for the cover + ITunesDataBox* coverData() const; + + //! function to register a data box for a certain box type + void registerBox( EBoxType boxtype, ITunesDataBox* databox ); + + private: + class Mp4TagsProxyPrivate; + //! private data of tags proxy + Mp4TagsProxyPrivate* d; + }; // class Mp4TagsProxy + } // namespace MP4 +} // namespace TagLib + +#endif // MP4TAGSPROXY_H diff --git a/src/metadata/m4a/mp4trakbox.cpp b/src/metadata/m4a/mp4trakbox.cpp new file mode 100644 index 0000000..c573ec7 --- /dev/null +++ b/src/metadata/m4a/mp4trakbox.cpp @@ -0,0 +1,86 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "tlist.h" +#include <iostream> +#include "mp4trakbox.h" +#include "boxfactory.h" +#include "mp4file.h" + +using namespace TagLib; + +class MP4::Mp4TrakBox::Mp4TrakBoxPrivate +{ +public: + //! container for all boxes in trak box + TagLib::List<Mp4IsoBox*> trakBoxes; + //! a box factory for creating the appropriate boxes + MP4::BoxFactory boxfactory; +}; // class Mp4TrakBoxPrivate + +MP4::Mp4TrakBox::Mp4TrakBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ) + : Mp4IsoBox( file, fourcc, size, offset ) +{ + d = new MP4::Mp4TrakBox::Mp4TrakBoxPrivate(); +} + +MP4::Mp4TrakBox::~Mp4TrakBox() +{ + TagLib::List<Mp4IsoBox*>::Iterator delIter; + for( delIter = d->trakBoxes.begin(); + delIter != d->trakBoxes.end(); + delIter++ ) + { + delete *delIter; + } + delete d; +} + +void MP4::Mp4TrakBox::parse() +{ + TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() ); + + TagLib::uint totalsize = 8; + // parse all contained boxes + TagLib::uint size; + MP4::Fourcc fourcc; + + while( (mp4file->readSizeAndType( size, fourcc ) == true) ) + { + totalsize += size; + + // check for errors + if( totalsize > MP4::Mp4IsoBox::size() ) + { + std::cerr << "Error in mp4 file " << mp4file->name() << " trak box contains bad box with name: " << fourcc.toString() << std::endl; + return; + } + + // create the appropriate subclass and parse it + MP4::Mp4IsoBox* curbox = d->boxfactory.createInstance( mp4file, fourcc, size, mp4file->tell() ); + curbox->parsebox(); + d->trakBoxes.append( curbox ); + + // check for end of trak box + if( totalsize == MP4::Mp4IsoBox::size() ) + break; + } +} diff --git a/src/metadata/m4a/mp4trakbox.h b/src/metadata/m4a/mp4trakbox.h new file mode 100644 index 0000000..b362fa3 --- /dev/null +++ b/src/metadata/m4a/mp4trakbox.h @@ -0,0 +1,49 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4TRAKBOX_H +#define MP4TRAKBOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class Mp4TrakBox: public Mp4IsoBox + { + public: + Mp4TrakBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ); + ~Mp4TrakBox(); + + //! parse trak contents + void parse(); + + private: + class Mp4TrakBoxPrivate; + Mp4TrakBoxPrivate* d; + }; // Mp4TrakBox + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4TRAKBOX_H diff --git a/src/metadata/m4a/mp4udtabox.cpp b/src/metadata/m4a/mp4udtabox.cpp new file mode 100644 index 0000000..268d1c1 --- /dev/null +++ b/src/metadata/m4a/mp4udtabox.cpp @@ -0,0 +1,95 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "tlist.h" +#include <iostream> +#include "mp4udtabox.h" +#include "boxfactory.h" +#include "mp4file.h" + +using namespace TagLib; + +class MP4::Mp4UdtaBox::Mp4UdtaBoxPrivate +{ +public: + //! container for all boxes in udta box + TagLib::List<Mp4IsoBox*> udtaBoxes; + //! a box factory for creating the appropriate boxes + MP4::BoxFactory boxfactory; +}; // class Mp4UdtaBoxPrivate + +MP4::Mp4UdtaBox::Mp4UdtaBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ) + : Mp4IsoBox( file, fourcc, size, offset ) +{ + d = new MP4::Mp4UdtaBox::Mp4UdtaBoxPrivate(); +} + +MP4::Mp4UdtaBox::~Mp4UdtaBox() +{ + TagLib::List<Mp4IsoBox*>::Iterator delIter; + for( delIter = d->udtaBoxes.begin(); + delIter != d->udtaBoxes.end(); + delIter++ ) + { + delete *delIter; + } + delete d; +} + +void MP4::Mp4UdtaBox::parse() +{ +#if 0 + std::cout << " parsing udta box" << std::endl; +#endif + TagLib::MP4::File* mp4file = static_cast<MP4::File*>( file() ); + + TagLib::uint totalsize = 8; + // parse all contained boxes + TagLib::uint size; + MP4::Fourcc fourcc; + +#if 0 + std::cout << " "; +#endif + while( (mp4file->readSizeAndType( size, fourcc ) == true) ) + { + totalsize += size; + + // check for errors + if( totalsize > MP4::Mp4IsoBox::size() ) + { + std::cerr << "Error in mp4 file " << mp4file->name() << " udta box contains bad box with name: " << fourcc.toString() << std::endl; + return; + } + + // create the appropriate subclass and parse it + MP4::Mp4IsoBox* curbox = d->boxfactory.createInstance( mp4file, fourcc, size, mp4file->tell() ); + curbox->parsebox(); + d->udtaBoxes.append( curbox ); + + // check for end of udta box + if( totalsize == MP4::Mp4IsoBox::size() ) + break; +#if 0 + std::cout << " "; +#endif + } +} diff --git a/src/metadata/m4a/mp4udtabox.h b/src/metadata/m4a/mp4udtabox.h new file mode 100644 index 0000000..4873e32 --- /dev/null +++ b/src/metadata/m4a/mp4udtabox.h @@ -0,0 +1,49 @@ +/*************************************************************************** + copyright : (C) 2002, 2003, 2006 by Jochen Issing + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef MP4UDTABOX_H +#define MP4UDTABOX_H + +#include "mp4isobox.h" +#include "mp4fourcc.h" + +namespace TagLib +{ + namespace MP4 + { + class Mp4UdtaBox: public Mp4IsoBox + { + public: + Mp4UdtaBox( TagLib::File* file, MP4::Fourcc fourcc, TagLib::uint size, long offset ); + ~Mp4UdtaBox(); + + //! parse moov contents + void parse(); + + private: + class Mp4UdtaBoxPrivate; + Mp4UdtaBoxPrivate* d; + }; // Mp4UdtaBox + + } // namespace MP4 +} // namespace TagLib + +#endif // MP4UDTABOX_H diff --git a/src/metadata/m4a/taglib_mp4filetyperesolver.cpp b/src/metadata/m4a/taglib_mp4filetyperesolver.cpp new file mode 100644 index 0000000..9566a93 --- /dev/null +++ b/src/metadata/m4a/taglib_mp4filetyperesolver.cpp @@ -0,0 +1,42 @@ +/*************************************************************************** + copyright : (C) 2006 by Martin Aumueller + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "taglib_mp4filetyperesolver.h" +#include "mp4file.h" + +#include <string.h> + +TagLib::File *MP4FileTypeResolver::createFile(const char *fileName, + bool readProperties, + TagLib::AudioProperties::ReadStyle propertiesStyle) const +{ +// fprintf(stderr, "mp4?: %s\n", fileName); + const char *ext = strrchr(fileName, '.'); + if(ext && (!strcasecmp(ext, ".m4a") + || !strcasecmp(ext, ".m4b") || !strcasecmp(ext, ".m4p") + || !strcasecmp(ext, ".mp4") + || !strcasecmp(ext, ".m4v") || !strcasecmp(ext, ".mp4v"))) + { + return new TagLib::MP4::File(fileName, readProperties, propertiesStyle); + } + + return 0; +} diff --git a/src/metadata/m4a/taglib_mp4filetyperesolver.h b/src/metadata/m4a/taglib_mp4filetyperesolver.h new file mode 100644 index 0000000..fbc3dd4 --- /dev/null +++ b/src/metadata/m4a/taglib_mp4filetyperesolver.h @@ -0,0 +1,36 @@ +/*************************************************************************** + copyright : (C) 2006 by Martin Aumueller + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_MP4FILETYPERESOLVER_H +#define TAGLIB_MP4FILETYPERESOLVER_H + +#include <taglib/tfile.h> +#include <taglib/fileref.h> + + +class MP4FileTypeResolver : public TagLib::FileRef::FileTypeResolver +{ + TagLib::File *createFile(const char *fileName, + bool readAudioProperties, + TagLib::AudioProperties::ReadStyle audioPropertiesStyle) const; +}; + +#endif diff --git a/src/metadata/mp4/Makefile.am b/src/metadata/mp4/Makefile.am new file mode 100644 index 0000000..e0779c6 --- /dev/null +++ b/src/metadata/mp4/Makefile.am @@ -0,0 +1,18 @@ +SUBDIRS = + +INCLUDES = $(all_includes) $(MP4V2_INCLUDES) $(taglib_includes) +METASOURCES = AUTO +libtagmp4_la_LDFLAGS = $(all_libraries) $(MP4V2_LIBS) +noinst_LTLIBRARIES = libtagmp4.la + +libtagmp4_la_SOURCES = \ + mp4properties.cpp \ + mp4tag.cpp \ + mp4file.cpp \ + taglib_mp4filetyperesolver.cpp + +noinst_HEADERS = \ + mp4properties.h \ + mp4tag.h \ + mp4file.h \ + taglib_mp4filetyperesolver.h diff --git a/src/metadata/optimfrog/Makefile.am b/src/metadata/optimfrog/Makefile.am new file mode 100755 index 0000000..f2b7e6b --- /dev/null +++ b/src/metadata/optimfrog/Makefile.am @@ -0,0 +1,6 @@ +INCLUDES = $(all_includes) $(taglib_includes) +METASOURCES = AUTO +libtagoptimfrog_la_LDFLAGS = $(all_libraries) +noinst_LTLIBRARIES = libtagoptimfrog.la +noinst_HEADERS = taglib_optimfrogfiletyperesolver.h +libtagoptimfrog_la_SOURCES = taglib_optimfrogfiletyperesolver.cpp diff --git a/src/metadata/optimfrog/taglib_optimfrogfiletyperesolver.cpp b/src/metadata/optimfrog/taglib_optimfrogfiletyperesolver.cpp new file mode 100755 index 0000000..13cde6a --- /dev/null +++ b/src/metadata/optimfrog/taglib_optimfrogfiletyperesolver.cpp @@ -0,0 +1,21 @@ +// (c) 2006 Martin Aumueller <[email protected]> +// modified 2006 Daniel Faust <[email protected]> +// See COPYING file for licensing information + +#include "taglib_optimfrogfiletyperesolver.h" +#include <taglib/mpcfile.h> + +#include <string.h> + +TagLib::File *OptimFrogFileTypeResolver::createFile(const char *fileName, + bool readProperties, + TagLib::AudioProperties::ReadStyle propertiesStyle) const +{ + const char *ext = strrchr(fileName, '.'); + if(ext && !strcasecmp(ext, ".ofr")) + { + return new TagLib::MPC::File(fileName, readProperties, propertiesStyle); + } + + return 0; +} diff --git a/src/metadata/optimfrog/taglib_optimfrogfiletyperesolver.h b/src/metadata/optimfrog/taglib_optimfrogfiletyperesolver.h new file mode 100755 index 0000000..b277ed5 --- /dev/null +++ b/src/metadata/optimfrog/taglib_optimfrogfiletyperesolver.h @@ -0,0 +1,19 @@ +// (c) 2006 Martin Aumueller <[email protected]> +// modified 2006 Daniel Faust <[email protected]> +// See COPYING file for licensing information + +#ifndef TAGLIB_OPTIMFROGFILETYPERESOLVER_H +#define TAGLIB_OPTIMFROGFILETYPERESOLVER_H + +#include <taglib/tfile.h> +#include <taglib/fileref.h> + + +class OptimFrogFileTypeResolver : public TagLib::FileRef::FileTypeResolver +{ + TagLib::File *createFile(const char *fileName, + bool readAudioProperties, + TagLib::AudioProperties::ReadStyle audioPropertiesStyle) const; +}; + +#endif diff --git a/src/metadata/rmff/Makefile.am b/src/metadata/rmff/Makefile.am new file mode 100644 index 0000000..b493e66 --- /dev/null +++ b/src/metadata/rmff/Makefile.am @@ -0,0 +1,15 @@ +SUBDIRS = + +INCLUDES = $(all_includes) $(taglib_includes) +METASOURCES = AUTO +libtagrealmedia_la_LDFLAGS = $(all_libraries) +noinst_LTLIBRARIES = libtagrealmedia.la + +libtagrealmedia_la_SOURCES = rmff.cpp \ + taglib_realmediafile.cpp \ + taglib_realmediafiletyperesolver.cpp + +noinst_HEADERS = rmff.h \ + taglib_realmediafile.h \ + taglib_realmediafiletyperesolver.h + diff --git a/src/metadata/rmff/rmff.cpp b/src/metadata/rmff/rmff.cpp new file mode 100644 index 0000000..da0edd5 --- /dev/null +++ b/src/metadata/rmff/rmff.cpp @@ -0,0 +1,998 @@ +/*************************************************************************** + copyright : (C) 2005 by Paul Cifarelli + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * 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., 51 Franklin St, 5th fl, Boston, MA 02110-1301, * + * USA, or check http://www.fsf.org/about/contact.html * + * * + * Note that no RealNetworks code appears or is duplicated, copied, or * + + used as a template in this code. The code was written from scratch * + * using the reference documentation found at: * + * * + * https://common.helixcommunity.org/nonav/2003/HCS_SDK_r5/helixsdk.htm * + * * + ***************************************************************************/ +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> +#include <netinet/in.h> +#include <taglib.h> +#include <id3v1tag.h> +#include <id3v2tag.h> +#include <tfile.h> +#include <fileref.h> +#include <iostream> + +#include <string.h> + +#include "rmff.h" + +#define UNPACK4(a, buf, i) memcpy((void *)&a, (void *) &buf[i], 4),i+=4,a=ntohl(a) +#define UNPACK2(a, buf, i) memcpy((void *)&a, (void *) &buf[i], 2),i+=2,a=ntohs(a) + +using namespace TagLib; +using namespace TagLib::RealMedia; + +RMFFile::RMFFile(const char *filename) : File(filename), m_id3tag(0) +{ + if (isOpen()) + m_id3tag = new ID3v1::Tag(this, length() - 128); +} + +RMFFile::~RMFFile() +{ + delete m_id3tag; +} + +bool RMFFile::save() +{ + ByteVector bv = m_id3tag->render(); //TODO finish this + return false; +} + + +String RealMediaFF::title () const +{ + return !m_err && m_id3v1tag ? m_id3v1tag->tag()->title() : ""; +} + +String RealMediaFF::artist () const +{ + return !m_err && m_id3v1tag ? m_id3v1tag->tag()->artist() : ""; +} + +String RealMediaFF::album () const +{ + return !m_err && m_id3v1tag ? m_id3v1tag->tag()->album() : ""; +} + +String RealMediaFF::comment() const +{ + return !m_err && m_id3v1tag ? m_id3v1tag->tag()->comment() : ""; +} + +String RealMediaFF::genre() const +{ + return !m_err && m_id3v1tag ? m_id3v1tag->tag()->genre() : ""; +} + +TagLib::uint RealMediaFF::year() const +{ + return !m_err && m_id3v1tag ? m_id3v1tag->tag()->year() : 0; +} + +TagLib::uint RealMediaFF::track() const +{ + return !m_err && m_id3v1tag ? m_id3v1tag->tag()->track() : 0; +} + +// properties +int RealMediaFF::length () const +{ + return m_readProperties && !m_err && m_props ? m_props->duration : 0; +} + +int RealMediaFF::bitrate () const +{ + return m_readProperties && !m_err && m_props ? m_props->avg_bit_rate : 0; +} + +int RealMediaFF::sampleRate () const +{ + return 0; +} + +int RealMediaFF::channels () const +{ + return 0; +} + + +RealMediaFF::RealMediaFF(const char *file, bool readProperties, AudioProperties::ReadStyle /*propertiesStyle*/) +: m_filename(0) +, m_head(0) +, m_tail(0) +, m_err(0) +, m_hdr(0) +, m_props(0) +, media_hdrs(0) +, m_contenthdr(0) +, m_md(0) +, m_title(0) +, m_author(0) +, m_copyright(0) +, m_comment(0) +, m_id3v1tag(0) +, m_flipYearInMetadataSection(0) +, m_readProperties(readProperties) +{ + m_filename = strdup(file); + + m_fd = open(m_filename, O_RDONLY); + if (m_fd < 0) + { + m_err = -1; + return; + } + + // ok, for RM files, the properties are embedded, so we ignore propertiesStyle + if (m_readProperties) + { + init(); + + // and now for the really complicated stuff... + if (initMetadataSection()) + std::cerr << "ERROR reading Metadata\n"; + } + + // now get the ID3v1 tag at the end of this file + m_id3v1tag = new RMFFile(m_filename); +} + + +RealMediaFF::RealMediaFF(RealMediaFF &src) +: m_filename(0) +, m_head(0) +, m_tail(0) +, m_err(0) +, m_hdr(0) +, m_props(0) +, media_hdrs(0) +, m_contenthdr(0) +, m_md(0) +, m_title(0) +, m_author(0) +, m_copyright(0) +, m_comment(0) +, m_id3v1tag(0) +, m_flipYearInMetadataSection(0) +, m_readProperties(src.m_readProperties) +{ + m_filename=strdup(src.m_filename); + + m_fd = open(m_filename, O_RDONLY); + if (m_fd < 0) + { + m_err = -1; + return; + } + + // ok, for RM files, the properties are embedded, so we ignore propertiesStyle + if (m_readProperties) + { + init(); + + // and now for the really complicated stuff... + if (initMetadataSection()) + std::cerr << "ERROR reading Metadata\n"; + } + + // now get the ID3v1 tag at the end of this file + m_id3v1tag = new RMFFile(m_filename); +} + +RealMediaFF::~RealMediaFF() +{ + ::free(m_filename); + + Collectable *hdr = m_head, *next; + while (hdr) + { + next = hdr->fwd; + delete hdr; + hdr = next; + } + + delete m_id3v1tag; + delete m_md; + + close(m_fd); +} + +bool RealMediaFF::isEmpty() const +{ + return m_id3v1tag->tag()->isEmpty(); +} + + +void RealMediaFF::saveHeader(Collectable *hdr) +{ + hdr->fwd = 0; + if (!m_head) + m_head = m_tail = hdr; + else + { + m_tail->fwd = hdr; + m_tail = hdr; + } +} + + +int RealMediaFF::init() +{ + int nbytes; + unsigned char buf[65536]; + UINT32 object_id; + UINT32 sz; + UINT32 consumed = 0; + + off_t s; + if ( (s = lseek(m_fd, 0, SEEK_SET)) ) + { + m_err = -1; + return m_err; + } + + m_hdr = new File_Header_v0_v1; + nbytes = getChunk(buf, 65536, m_hdr->s.object_id, m_hdr->s.size, consumed); + if (nbytes < 0 || m_hdr->s.size != consumed || memcmp((void *)&m_hdr->s.object_id, ".RMF", 4)) + { + //std::cerr << "SERIOUS ERROR - not likely a RealMedia file\n"; + m_err = -1; + return m_err; + } + if (!getRealFileHeader(m_hdr, buf, m_hdr->s.object_id, m_hdr->s.size)) + { + saveHeader(m_hdr); + consumed = 0; + nbytes = getChunk(buf, 65536, object_id, sz, consumed); + if (nbytes < 0 || sz != consumed) + { + m_err = -1; + return m_err; + } + + while (!m_err && memcmp((void *)&object_id, "DATA", 4)) + { + char oid[5]; + memcpy((void *)oid, (void *)&object_id, 4); + oid[4] = 0; + if (!memcmp((void *)&object_id, "PROP", 4)) + { + m_props = new RMProperties; + getRealPropertyHeader(m_props, buf, object_id, sz); + saveHeader(m_props); + } + + if (!memcmp((void *)&object_id, "MDPR", 4)) + { + media_hdrs = new MediaProperties; + getMediaPropHeader(media_hdrs, buf, object_id, sz); + saveHeader(media_hdrs); + } + + if (!memcmp((void *)&object_id, "CONT", 4)) + { + m_contenthdr = new ContentDescription; + getContentDescription(m_contenthdr, buf, object_id, sz); + saveHeader(m_contenthdr); + } + + consumed = 0; + do + { + nbytes = getChunk(buf, 65536, object_id, sz, consumed); + } while ( !m_err && memcmp((void *)&object_id, "DATA", 4) && (consumed < sz) ); + } + } + + return 0; +} + +int RealMediaFF::getHdr(unsigned char *buf, size_t sz, UINT32 &fourcc, UINT32 &csz) +{ + int nbytes = 0, i = 0; + + if (sz < (size_t)RMFF_HDR_SIZE) + return 0; + + if ( (nbytes = read(m_fd, (void *) buf, RMFF_HDR_SIZE)) != RMFF_HDR_SIZE ) + { + m_err = -1; + + return (nbytes); + } + + memcpy((void *)&fourcc, buf, 4); i+=4; + UNPACK4(csz,buf,i); + + return nbytes; +} + +int RealMediaFF::getChunk(unsigned char *buf, size_t sz, UINT32 &fourcc, UINT32 &csz, UINT32 &alreadyconsumed) +{ + int nbytes = 0, i = 0, readamount; + csz = 0; + + if (!alreadyconsumed) + { + if ( (nbytes = getHdr(buf, sz, fourcc, csz)) != RMFF_HDR_SIZE ) + { + m_err = -1; + alreadyconsumed += nbytes > 0 ? nbytes : 0; + return nbytes; + } + alreadyconsumed += RMFF_HDR_SIZE; + readamount = csz - RMFF_HDR_SIZE; + i = RMFF_HDR_SIZE; + } + else + readamount = csz - alreadyconsumed; + + if ( (nbytes = read(m_fd, (void *) &buf[i], readamount > (int)sz - i ? (int)sz - i : readamount )) != readamount ) + { + if (nbytes < 0) + { + m_err = -1; + } + else + alreadyconsumed += nbytes; + + return (nbytes<0 ? i : i + nbytes); + } + + alreadyconsumed += nbytes; + return (csz); +} + +int RealMediaFF::getRealFileHeader(File_Header_v0_v1 *hdr, const unsigned char *buf, UINT32 object_id, int sz) +{ + int i = 0; + + // RealMedia header + hdr->s.object_id = object_id; + hdr->s.size = sz; + + i = RMFF_HDR_SIZE; + UNPACK2(hdr->object_version, buf, i); + + if ( !strncmp((const char *) &hdr->s.object_id, ".RMF", 4) && + (hdr->object_version == 0 || hdr->object_version == 1) ) + { + UNPACK4(hdr->file_version, buf, i); + UNPACK4(hdr->num_headers, buf, i); + } + return 0; +} + +int RealMediaFF::getRealPropertyHeader(RMProperties *props, const unsigned char *buf, UINT32 object_id, int sz) +{ + int i = 0; + + // Properties + props->s.object_id = object_id; + props->s.size = sz; + + i = RMFF_HDR_SIZE; + UNPACK2(props->object_version, buf, i); + + if ( !strncmp((const char *)&props->s.object_id,"PROP",4) && (props->object_version == 0) ) + { + UNPACK4(props->max_bit_rate, buf, i); + UNPACK4(props->avg_bit_rate, buf, i); + UNPACK4(props->max_packet_size, buf, i); + UNPACK4(props->avg_packet_size, buf, i); + UNPACK4(props->num_packets, buf, i); + UNPACK4(props->duration, buf, i); + UNPACK4(props->preroll, buf, i); + UNPACK4(props->index_offset, buf, i); + UNPACK4(props->data_offset, buf, i); + UNPACK2(props->num_streams, buf, i); + UNPACK2(props->flags, buf, i); + } + return 0; +} + + +int RealMediaFF::getMediaPropHeader(MediaProperties *media_hdr, const unsigned char *buf, UINT32 object_id, int sz) +{ + int i = 0; + + // Properties + media_hdr->s.object_id = object_id; + media_hdr->s.size = sz; + + i = RMFF_HDR_SIZE; + UNPACK2(media_hdr->object_version, buf, i); + + if ( !strncmp((const char *)&media_hdr->s.object_id, "MDPR", 4) && media_hdr->object_version == 0) + { + UNPACK2(media_hdr->stream_number, buf, i); + UNPACK4(media_hdr->max_bit_rate, buf, i); + UNPACK4(media_hdr->avg_bit_rate, buf, i); + UNPACK4(media_hdr->max_packet_size, buf, i); + UNPACK4(media_hdr->avg_packet_size, buf, i); + UNPACK4(media_hdr->start_time, buf, i); + UNPACK4(media_hdr->preroll, buf, i); + UNPACK4(media_hdr->duration, buf, i); + media_hdr->stream_name_size = buf[i]; i++; + memcpy(media_hdr->stream_name, &buf[i], media_hdr->stream_name_size); + media_hdr->stream_name[media_hdr->stream_name_size] = 0; + i += media_hdr->stream_name_size; + media_hdr->mime_type_size = buf[i]; i++; + memcpy(media_hdr->mime_type, &buf[i], media_hdr->mime_type_size); + i += media_hdr->mime_type_size; + UNPACK4(media_hdr->type_specific_len, buf, i); + if (media_hdr->type_specific_len) + { + media_hdr->type_specific_data = new UINT8[media_hdr->type_specific_len]; + memcpy(media_hdr->type_specific_data, &buf[i], media_hdr->type_specific_len); + + if (!strncmp((const char *)media_hdr->mime_type, "logical-fileinfo", 16)) + { + media_hdr->lstr = new LogicalStream; + UNPACK4(media_hdr->lstr->size, buf, i); + UNPACK2(media_hdr->lstr->object_version, buf, i); + if (media_hdr->lstr->object_version == 0) + { + UNPACK2(media_hdr->lstr->num_physical_streams, buf, i); + if (media_hdr->lstr->num_physical_streams > 0) + { + media_hdr->lstr->physical_stream_numbers = new UINT16[ media_hdr->lstr->num_physical_streams ]; + media_hdr->lstr->data_offsets = new UINT32[ media_hdr->lstr->num_physical_streams ]; + for (int j=0; j<media_hdr->lstr->num_physical_streams; j++) + { + UNPACK2(media_hdr->lstr->physical_stream_numbers[j], buf, i); + } + for (int j=0; j<media_hdr->lstr->num_physical_streams; j++) + { + UNPACK4(media_hdr->lstr->data_offsets[j], buf, i); + } + } + + UNPACK2(media_hdr->lstr->num_rules, buf, i); + if (media_hdr->lstr->num_rules > 0) + { + media_hdr->lstr->rule_to_physical_stream_number_map = new UINT16[ media_hdr->lstr->num_rules ]; + for (int j=0; j<media_hdr->lstr->num_rules; j++) + { + UNPACK2(media_hdr->lstr->rule_to_physical_stream_number_map[j], buf, i); + } + } + UNPACK2(media_hdr->lstr->num_properties, buf, i); + if (media_hdr->lstr->num_properties > 0) + { + media_hdr->lstr->properties = new NameValueProperty[ media_hdr->lstr->num_properties ]; + for (int j=0; j<media_hdr->lstr->num_properties; j++) + { + UNPACK4(media_hdr->lstr->properties[j].size, buf, i); + UNPACK2(media_hdr->lstr->properties[j].object_version, buf, i); + if (media_hdr->lstr->properties[j].object_version == 0) + { + media_hdr->lstr->properties[j].name_length = buf[i]; i++; + if (media_hdr->lstr->properties[j].name_length) + { + media_hdr->lstr->properties[j].name = new UINT8[ media_hdr->lstr->properties[j].name_length + 1]; + memcpy((void *)media_hdr->lstr->properties[j].name, (void *)&buf[i], + media_hdr->lstr->properties[j].name_length); + media_hdr->lstr->properties[j].name[ media_hdr->lstr->properties[j].name_length ] = 0; + i+=media_hdr->lstr->properties[j].name_length; + } + + UNPACK4(media_hdr->lstr->properties[j].type, buf, i); + UNPACK2(media_hdr->lstr->properties[j].value_length, buf, i); + if (media_hdr->lstr->properties[j].value_length) + { + media_hdr->lstr->properties[j].value_data = new UINT8[ media_hdr->lstr->properties[j].value_length + 1]; + memcpy((void *)media_hdr->lstr->properties[j].value_data, (void *)&buf[i], + media_hdr->lstr->properties[j].value_length); + media_hdr->lstr->properties[j].value_data[ media_hdr->lstr->properties[j].value_length ] = 0; + i+=media_hdr->lstr->properties[j].value_length; + } + } + } + } + } + else + media_hdr->lstr = 0; + } + } + else + media_hdr->type_specific_data = 0; + } + else + { + m_err = -1; + return m_err; + } + + return 0; +} + + +int RealMediaFF::getContentDescription(ContentDescription *cont, const unsigned char *buf, UINT32 object_id, int sz) +{ + int i = 0; + + // Properties + cont->s.object_id = object_id; + cont->s.size = sz; + + i = RMFF_HDR_SIZE; + UNPACK2(cont->object_version, buf, i); + + if ( !strncmp((const char *)&cont->s.object_id, "CONT", 4) && cont->object_version == 0) + { + UNPACK2(cont->title_len, buf, i); + cont->title = new UINT8[cont->title_len + 1]; + memcpy((void *)cont->title, (void *)&buf[i], cont->title_len); i+=cont->title_len; + m_title = (char *)cont->title; + m_title[cont->title_len] = 0; + + UNPACK2(cont->author_len, buf, i); + cont->author = new UINT8[cont->author_len + 1]; + memcpy((void *)cont->author, (void *)&buf[i], cont->author_len); i+=cont->author_len; + m_author = (char *)cont->author; + m_author[cont->author_len] = 0; + + UNPACK2(cont->copyright_len, buf, i); + cont->copyright = new UINT8[cont->copyright_len + 1]; + memcpy((void *)cont->copyright, (void *)&buf[i], cont->copyright_len); i+=cont->copyright_len; + m_copyright = (char *)cont->copyright; + m_copyright[cont->copyright_len] = 0; + + UNPACK2(cont->comment_len, buf, i); + cont->comment = new UINT8[cont->comment_len + 1]; + memcpy((void *)cont->comment, (void *)&buf[i], cont->comment_len); i+=cont->comment_len; + m_comment = (char *)cont->comment; + m_comment[cont->comment_len] = 0; + } + else + { + m_err = -1; + return m_err; + } + + return 0; +} + + +int RealMediaFF::seekChunk(UINT32 object_id) +{ + if (!m_err) + { + off_t s, tot; + UINT32 oid = 0, sz = 0; + unsigned char buf[255]; + int nbytes = 0; + + if ( (s = lseek(m_fd, 0, SEEK_SET)) != 0) + return -1; + + tot = 0; + while( (nbytes = getHdr(buf, 255, oid, sz)) == RMFF_HDR_SIZE && memcmp((void *)&oid, (void *)&object_id, 4) ) + { + tot += sz; + if (sz > (unsigned) RMFF_HDR_SIZE) + { + if ( (s = lseek(m_fd, sz - RMFF_HDR_SIZE, SEEK_CUR)) != tot ) + return -1; + } + else + return -1; // bail in this case, since the chuck sz includes the header size + } + if ( (s = lseek(m_fd, -RMFF_HDR_SIZE, SEEK_CUR)) != tot ) + return -1; + + return s; + } + return -1; +} + +int RealMediaFF::getMDProperties(MDProperties *props, const unsigned char *buf) +{ + int i = 0; + + int start = i; + + UNPACK4(props->size, buf, i); + UNPACK4(props->type, buf, i); + UNPACK4(props->flags, buf, i); + UNPACK4(props->value_offset, buf, i); + UNPACK4(props->subproperties_offset, buf, i); + UNPACK4(props->num_subproperties, buf, i); + UNPACK4(props->name_length, buf, i); + props->name = new UINT8[ props->name_length + 1 ]; + memcpy((void *)props->name, (void *)&buf[i], props->name_length); + props->name[ props->name_length ] = 0; + i+=props->name_length; + + i = start + props->value_offset; + UNPACK4(props->value_length, buf, i); + props->value = new UINT8[ props->value_length ]; + memcpy( (void *) props->value, (void *)&buf[i], props->value_length ); + + if ( (props->type == MPT_ULONG) || (props->type == MPT_FLAG && props->value_length == 4) ) + { + // wOOt! the Year is a ULONG, and its stored little endian?! my guess is this is a bug in + // RealPlayer 10 for Windows (where I created my test files) + // This hack is intended to ensure that we at least interpret the Year properly. + if (!strcmp((char *)props->name, "Year")) + { + if ( *(unsigned long *)props->value > 65536 ) + { + *(unsigned long *)(props->value) = ntohl(*(unsigned long *)(props->value)); + m_flipYearInMetadataSection = true; + } + else + m_flipYearInMetadataSection = false; + } + else + *(unsigned long *)(props->value) = ntohl(*(unsigned long *)(props->value)); + } + + i += props->value_length; + + i = start + props->subproperties_offset; + props->subproperties_list = new PropListEntry[ props->num_subproperties ]; + for (int j=0; j<(int)props->num_subproperties; j++) + { + UNPACK4(props->subproperties_list[j].offset, buf, i); + UNPACK4(props->subproperties_list[j].num_props_for_name, buf, i); + } + + props->subproperties = new MDProperties[ props->num_subproperties ]; + for (int j=0; j<(int)props->num_subproperties; j++) + { + i = start + props->subproperties_list[j].offset; + getMDProperties(&props->subproperties[j], &buf[i]); + } + + return 0; +} + +int RealMediaFF::initMetadataSection() +{ + UINT32 object_id; + off_t s; + int nbytes; + unsigned char buf[65536]; + UINT32 consumed; + + memcpy((void *)&object_id, "RMMD", 4); + if ( (s = seekChunk(object_id)) < 0 ) + { + m_err = -1; + return m_err; + } + + m_md = new MetadataSection; + consumed = 0; + nbytes = getChunk(buf, 65536, m_md->s.object_id, m_md->s.size, consumed); + if (nbytes < 0 || m_md->s.size != consumed || memcmp((void *)&m_md->s.object_id, "RMMD", 4)) + { + //std::cerr << "SERIOUS ERROR - not able to find the chunk I just seek'd to!\n"; + m_err = -1; + return m_err; + } + // Properties + int i = RMFF_HDR_SIZE; + memcpy((void *)&m_md->object_id, (void *)&buf[i], 4); i+=4; + UNPACK4(m_md->object_version, buf, i); + if ( !strncmp((const char *)&m_md->s.object_id, "RMMD", 4) ) + { + if (!getMDProperties(&m_md->properties, &buf[i])) + saveHeader(m_md); + } + else + { + m_err = -1; + return m_err; + } + + return 0; +} + +#ifdef TESTING + +void RealMediaFF::printRealFileHeader(std::ostream &os) +{ + char object_id[5]; + + if (m_hdr) + { + strncpy(object_id, (const char *)&m_hdr->s.object_id, 4); + object_id[4]=0; + + os << "HDR object_id: " << object_id << std::endl; + os << "HDR size: " << m_hdr->s.size << std::endl; + os << "HDR object version: " << m_hdr->object_version << std::endl; + os << "HDR file version: " << m_hdr->file_version << std::endl; + os << "HDR num headers: " << m_hdr->num_headers << std::endl; + } +} + + +void RealMediaFF::printRealPropHeader(std::ostream &os) +{ + char object_id[5]; + + if (m_props) + { + strncpy(object_id, (const char *)&m_props->s.object_id, 4); + object_id[4]=0; + + os << "PROPS object_id: " << object_id << std::endl; + os << "PROPS size: " << m_props->s.size << std::endl; + os << "PROPS object_version: " << m_props->object_version << std::endl; + + os << "PROPS max_bit_rate: " << m_props->max_bit_rate << std::endl; + os << "PROPS avg_bit_rate: " << m_props->avg_bit_rate << std::endl; + os << "PROPS max_packet_size: " << m_props->max_packet_size << std::endl; + os << "PROPS avg_packet_size: " << m_props->avg_packet_size << std::endl; + os << "PROPS num_packets: " << m_props->num_packets << std::endl; + os << "PROPS duration: " << m_props->duration << std::endl; + os << "PROPS preroll: " << m_props->preroll << std::endl; + os << "PROPS index_offset: " << m_props->index_offset << std::endl; + os << "PROPS data_offset: " << m_props->data_offset << std::endl; + os << "PROPS num_streams: " << m_props->num_streams << std::endl; + os << "PROPS flags: " << m_props->flags << std::endl; + } +} + + +void RealMediaFF::printMediaPropHeaders(std::ostream &os) +{ + int i = 0; + char object_id[5]; + MediaProperties *media_hdr = (MediaProperties *)m_head; + + while (media_hdr) + { + strncpy(object_id, (const char *)&media_hdr->s.object_id, 4); + object_id[4]=0; + + if (!strncmp(object_id, "MDPR", 4)) + { + os << "MEDIA HDR" << i << " object_id: " << object_id << std::endl; + os << "MEDIA HDR" << i << " size: " << media_hdr->s.size << std::endl; + os << "MEDIA HDR" << i << " max_bit_rate: " << media_hdr->max_bit_rate << std::endl; + os << "MEDIA HDR" << i << " avg_bit_rate: " << media_hdr->avg_bit_rate << std::endl; + os << "MEDIA HDR" << i << " max_packet_size: " << media_hdr->max_packet_size << std::endl; + os << "MEDIA HDR" << i << " avg_packet_size: " << media_hdr->avg_packet_size << std::endl; + os << "MEDIA HDR" << i << " start_time: " << media_hdr->start_time << std::endl; + os << "MEDIA HDR" << i << " preroll: " << media_hdr->preroll << std::endl; + os << "MEDIA HDR" << i << " duration: " << media_hdr->duration << std::endl; + os << "MEDIA HDR" << i << " stream_name: " << media_hdr->stream_name << std::endl; + os << "MEDIA HDR" << i << " mime type: " << media_hdr->mime_type << std::endl; + + + if (media_hdr->lstr) + { + os << "MEDIA HDR" << i << " LOGSTR info size: " << media_hdr->lstr->size << std::endl; + os << "MEDIA HDR" << i << " LOGSTR info num_physical_streams: " << media_hdr->lstr->num_physical_streams << std::endl; + os << "MEDIA HDR" << i << " LOGSTR info num_rules: " << media_hdr->lstr->num_rules << std::endl; + os << "MEDIA HDR" << i << " LOGSTR info num_properties: " << media_hdr->lstr->num_properties << std::endl; + for (int j=0; media_hdr->lstr->properties && j<media_hdr->lstr->num_properties; j++) + { + if (media_hdr->lstr->properties[j].name) + os << "MEDIA HDR" << i << " LOGSTR info prop name: " << media_hdr->lstr->properties[j].name << std::endl; + os << "MEDIA HDR" << i << " LOGSTR info prop type: " << media_hdr->lstr->properties[j].type << std::endl; + os << "MEDIA HDR" << i << " LOGSTR info prop value_length: " << media_hdr->lstr->properties[j].value_length << std::endl; + if (media_hdr->lstr->properties[j].value_data) + { + if (media_hdr->lstr->properties[j].type == 0) + os << "MEDIA HDR" << i << " LOGSTR info prop value: " << + *(unsigned long *)media_hdr->lstr->properties[j].value_data << std::endl; + else if (media_hdr->lstr->properties[j].type == 2) + os << "MEDIA HDR" << i << " LOGSTR info prop value: " << media_hdr->lstr->properties[j].value_data << std::endl; + else + os << "MEDIA HDR" << i << " LOGSTR info prop value: <binary>\n"; + } + } + } + + i++; + } + media_hdr = (MediaProperties *)media_hdr->fwd; + } +} + + +void RealMediaFF::printContentDescription(std::ostream &os) +{ + char object_id[5]; + + if (m_contenthdr) + { + strncpy(object_id, (const char *)&m_contenthdr->s.object_id, 4); + object_id[4]=0; + + os << "CONT object_id: " << object_id << std::endl; + os << "CONT title(" << m_contenthdr->title_len << "):\t\t<" << m_contenthdr->title << ">" << std::endl; + os << "CONT author(" << m_contenthdr->author_len << "):\t\t<" << m_contenthdr->author << ">" << std::endl; + os << "CONT copyright(" << m_contenthdr->copyright_len << "):\t\t<" << m_contenthdr->copyright << ">" << std::endl; + os << "CONT comment(" << m_contenthdr->comment_len << "):\t\t<" << m_contenthdr->comment << ">" << std::endl; + } +} + +void RealMediaFF::printID3v1Tag(std::ostream &os) +{ + if (m_id3v1tag) + { + os << "ID3 tag : " << ID3v1::Tag::fileIdentifier() << std::endl; + os << "ID3 title : " << m_id3v1tag->tag()->title() << std::endl; + os << "ID3 artist : " << m_id3v1tag->tag()->artist() << std::endl; + os << "ID3 album : " << m_id3v1tag->tag()->album() << std::endl; + os << "ID3 year : " << m_id3v1tag->tag()->year() << std::endl; + os << "ID3 comment : " << m_id3v1tag->tag()->comment() << std::endl; + os << "ID3 track : " << m_id3v1tag->tag()->track() << std::endl; + os << "ID3 genre : " << m_id3v1tag->tag()->genre() << std::endl; + } +} + + +void RealMediaFF::printMDProperties(std::ostream &os, char *nam, MDProperties *props) +{ + char name[8192]; + + strcpy(name, nam); + os << "MDP subproperties for: " << name << std::endl; + + os << "MD properties.size: " << props->size << std::endl; + os << "MD properties.type: " << props->type << std::endl; + os << "MD properties.flags: " << props->flags << std::endl; + os << "MD properties.value_offset: " << props->value_offset << std::endl; + os << "MD properties.subproperties_offset: " << props->subproperties_offset << std::endl; + os << "MD properties.num_subproperties: " << props->num_subproperties << std::endl; + os << "MD properties.name_length: " << props->name_length << std::endl; + os << "MD properties.name: " << (char *)props->name << std::endl; + + os << "MD properties.value_length: " << props->value_length << std::endl; + + switch (props->type) + { + case MPT_TEXT: + case MPT_TEXTLIST: + case MPT_URL: + case MPT_DATE: + case MPT_FILENAME: + os << "MD properties.value: " << (char *)props->value << std::endl; + break; + case MPT_FLAG: + if (props->value_length == 4) + os << "MD properties.value: " << *(unsigned long *)props->value << std::endl; + else + os << "MD properties.value: " << *props->value << std::endl; + break; + case MPT_ULONG: + os << "MD properties.value: " << *(unsigned long *)props->value << std::endl; + break; + case MPT_BINARY: + os << "MD properties.value: <binary>" << std::endl; + break; + case MPT_GROUPING: + os << "MD properties.value: <grouping>" << std::endl; + break; + case MPT_REFERENCE: + os << "MD properties.value: <reference>" << std::endl; + break; + } + + if (props->num_subproperties) + { + strcat(name, (char *)props->name); + strcat(name, "/"); + } + for (int j=0; j<props->num_subproperties; j++) + { + os << "MD properties.sub_properties_list[" << j << "].offset: " << + props->subproperties_list[j].offset << std::endl; + os << "MD properties.sub_properties_list[" << j << "].num_props_for_name: " << + props->subproperties_list[j].num_props_for_name << std::endl; + + os << std::endl; + + printMDProperties(os, name, &props->subproperties[j]); + } +} + + +void RealMediaFF::printMetadataSection(std::ostream &os) +{ + char name[8192]; + char oid[5]; + + memcpy((void *)oid, (void *)&m_md->s.object_id, 4); + oid[4] = 0; + + os << "MetadataSection: "; + os << "MS object_id: " << oid << std::endl; + os << "MS SIZE: " << m_md->s.size << std::endl; + os << "MD object_id: " << (char *)&m_md->object_id << std::endl; + os << "MD object_version: " << m_md->object_version << std::endl; + os << std::endl; + + strcpy(name, ""); + printMDProperties(os, name, &m_md->properties); +} + + +std::ostream &RealMediaFF::operator<<(std::ostream &os) +{ + if (m_readProperties) + { + printRealFileHeader(os); + printRealPropHeader(os); + printMediaPropHeaders(os); + printContentDescription(os); + printMetadataSection(os); + } + printID3v1Tag(os); + + return os; +} + +std::ostream &operator<<(std::ostream &os, RealMediaFF &rmff) +{ + rmff.operator<<(os); + + return os; +} + + +int main(int argc, char *argv[]) +{ + char *m_filen; + + if (argc > 1) + m_filen = argv[1]; + else + m_filen = "./Drown.ra"; + + RealMediaFF rmff(m_filen); + + if (!rmff.err()) + std::cout << rmff; + + /* + UINT32 oid = 0; + memcpy( (void *)&oid, (void *) ".RMF", 4); + off_t pos = rmff.seekChunk(oid); + std::cout << "POS=" << pos << std::endl; + + memcpy( (void *)&oid, (void *) "MDPR", 4); + pos = rmff.seekChunk(oid); + std::cout << "POS=" << pos << std::endl; + + memcpy( (void *)&oid, (void *) "RMMD", 4); + pos = rmff.seekChunk(oid); + std::cout << "POS=" << pos << std::endl; + */ +} +#endif diff --git a/src/metadata/rmff/rmff.h b/src/metadata/rmff/rmff.h new file mode 100644 index 0000000..326b8ae --- /dev/null +++ b/src/metadata/rmff/rmff.h @@ -0,0 +1,348 @@ +/*************************************************************************** + copyright : (C) 2005 by Paul Cifarelli + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * 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., 51 Franklin St, 5th fl, Boston, MA 02110-1301, * + * USA, or check http://www.fsf.org/about/contact.html * + * * + * Note that no RealNetworks code appears or is duplicated, copied, or * + + used as a template in this code. The code was written from scratch * + * using the reference documentation found at: * + * * + * https://common.helixcommunity.org/nonav/2003/HCS_SDK_r5/helixsdk.htm * + * * + ***************************************************************************/ +#ifndef _RMFF_H_INCLUDED_ +#define _RMFF_H_INCLUDED_ + +#include <config.h> + +namespace TagLib +{ + namespace RealMedia + { +#if SIZEOF_LONG == 4 + typedef unsigned long UINT32; +#elif SIZEOF_INT == 4 + typedef unsigned int UINT32; +#else +#error At least 1 builtin type needs to be 4 bytes!! +#endif + typedef unsigned short UINT16; + typedef unsigned char UINT8; + + static const int RMFF_HDR_SIZE = 8; // packed hdr size + + // some assumptions on these 2 enum defs, based solely on the order they are listed on the website + enum PROPERTY_TYPES + { + MPT_TEXT = 1, // The value is string data. + MPT_TEXTLIST, // The value is a separated list of strings, + // separator specified as sub-property/type descriptor. + MPT_FLAG, // The value is a boolean flag-either 1 byte or 4 bytes, check size value. + MPT_ULONG, // The value is a four-byte integer. + MPT_BINARY, // The value is a byte stream. + MPT_URL, // The value is string data. + MPT_DATE, // The value is a string representation of the date in the form: + // YYYYmmDDHHMMSS (m = month, M = minutes). + MPT_FILENAME, // The value is string data. + MPT_GROUPING, // This property has subproperties, but its own value is empty. + MPT_REFERENCE // The value is a large buffer of data, use sub-properties/type + // descriptors to identify mime-type. + }; + + enum PROPERTY_FLAGS + { + MPT_READONLY = 1, // Read only, cannot be modified. + MPT_PRIVATE = 2, // Private, do not expose to users. + MPT_TYPE_DESCRIPTOR = 4 // Type descriptor used to further define type of value. + }; + + struct Collectable + { + Collectable() : fwd(0) {} + virtual ~Collectable() {} + Collectable *fwd; + }; + + struct File_Header_Start + { + UINT32 object_id; + UINT32 size; + }; + + struct File_Header_v0_v1 : public Collectable + { + File_Header_Start s; + UINT16 object_version; + + UINT32 file_version; + UINT32 num_headers; + }; + + struct RMProperties : public Collectable + { + File_Header_Start s; + UINT16 object_version; + + UINT32 max_bit_rate; + UINT32 avg_bit_rate; + UINT32 max_packet_size; + UINT32 avg_packet_size; + UINT32 num_packets; + UINT32 duration; + UINT32 preroll; + UINT32 index_offset; + UINT32 data_offset; + UINT16 num_streams; + UINT16 flags; + }; + + + struct NameValueProperty + { + NameValueProperty() : name(0), value_data(0) {} + virtual ~NameValueProperty() { delete [] name; delete [] value_data; } + + UINT32 size; + UINT16 object_version; + + UINT8 name_length; + UINT8 *name; + UINT32 type; + UINT16 value_length; + UINT8 *value_data; + }; + + + struct LogicalStream + { + LogicalStream() : physical_stream_numbers(0), data_offsets(0), rule_to_physical_stream_number_map(0), properties(0) {} + virtual ~LogicalStream() + { delete [] physical_stream_numbers; delete [] data_offsets; + delete [] rule_to_physical_stream_number_map; delete [] properties; } + + UINT32 size; + UINT16 object_version; + + UINT16 num_physical_streams; + UINT16 *physical_stream_numbers; + UINT32 *data_offsets; + UINT16 num_rules; + UINT16 *rule_to_physical_stream_number_map; + UINT16 num_properties; + NameValueProperty *properties; + }; + + struct MediaProperties : public Collectable + { + MediaProperties() : type_specific_data(0), lstr(0) {} + virtual ~MediaProperties() { delete lstr; delete [] type_specific_data; } + + File_Header_Start s; + UINT16 object_version; + + UINT16 stream_number; + UINT32 max_bit_rate; + UINT32 avg_bit_rate; + UINT32 max_packet_size; + UINT32 avg_packet_size; + UINT32 start_time; + UINT32 preroll; + UINT32 duration; + UINT8 stream_name_size; + UINT8 stream_name[256]; + UINT8 mime_type_size; + UINT8 mime_type[256]; + UINT32 type_specific_len; + UINT8 *type_specific_data; + + LogicalStream *lstr; // only one of these + }; + + + struct ContentDescription : public Collectable + { + ContentDescription() : title(0), author(0), copyright(0), comment(0) {} + virtual ~ContentDescription() { delete [] title; delete [] author; delete [] copyright; delete [] comment; } + + File_Header_Start s; + UINT16 object_version; + + UINT16 title_len; + UINT8 *title; + UINT16 author_len; + UINT8 *author; + UINT16 copyright_len; + UINT8 *copyright; + UINT16 comment_len; + UINT8 *comment; + }; + + + struct PropListEntry + { + UINT32 offset; + UINT32 num_props_for_name; + }; + + struct MDProperties + { + MDProperties() : name(0), value(0), subproperties(0) {} + virtual ~MDProperties() + { delete [] name; delete [] value; delete [] subproperties_list; delete [] subproperties; } + + UINT32 size; + UINT32 type; + UINT32 flags; + UINT32 value_offset; + UINT32 subproperties_offset; + UINT32 num_subproperties; + UINT32 name_length; + UINT8 *name; + UINT32 value_length; + UINT8 *value; + PropListEntry *subproperties_list; // num_subproperties + MDProperties *subproperties; // num_subproperties + }; + + struct MetadataSection : public Collectable + { + File_Header_Start s; + + UINT32 object_id; + UINT32 object_version; + + // this is the 1 "unnamed root property" + MDProperties properties; + }; + + class Tag; + class File; + + // RealMedia File Format contains a normal ID3v1 Tag at the end of the file + // no sense reinventing the wheel, so this class is just so we can use TagLib + // to manage it + class RMFFile : public TagLib::File + { + public: + RMFFile(const char *filename); + virtual ~RMFFile(); + bool save(); + TagLib::Tag *tag() const { return m_id3tag; } + TagLib::AudioProperties *audioProperties() const { return 0; } + + private: + TagLib::ID3v1::Tag *m_id3tag; + }; + + class TagLib::AudioProperties; + + class RealMediaFF + { + public: + RealMediaFF(const char *file, bool readProperties = true, + TagLib::AudioProperties::ReadStyle propertiesStyle = TagLib::AudioProperties::Average); + RealMediaFF(RealMediaFF &src); + ~RealMediaFF(); + + int err() const { return m_err; } + bool isEmpty() const; + + // tag + TagLib::String title () const; + TagLib::String artist () const; + TagLib::String album () const; + TagLib::String comment () const; + TagLib::String genre () const; + TagLib::uint year () const; + TagLib::uint track () const; + // TODO write support + //void setTitle (const String &s); + //void setArtist (const String &s); + //void setAlbum (const String &s); + //void setComment (const String &s); + //void setGenre (const String &s); + //void setYear (uint i); + //void setTrack (uint i); + + // properties + int length () const; + int bitrate () const; + int sampleRate () const; + int channels () const; + +#ifdef TESTING + std::ostream &operator<<(std::ostream &os); +#endif + + private: + RealMediaFF(); + char *m_filename; + Collectable *m_head; + Collectable *m_tail; + int m_fd; + int m_err; + + File_Header_v0_v1 *m_hdr; + RMProperties *m_props; + MediaProperties *media_hdrs; + ContentDescription *m_contenthdr; + MetadataSection *m_md; + + char *m_title; + char *m_author; + char *m_copyright; + char *m_comment; + + RMFFile *m_id3v1tag; + + bool m_flipYearInMetadataSection; + bool m_readProperties; + + int init(); + int initMetadataSection(); + void saveHeader(Collectable *hdr); + int seekChunk(UINT32 object_id); + + int getHdr(unsigned char *buf, size_t sz, UINT32 &fourcc, UINT32 &csz); + int getChunk(unsigned char *buf, size_t sz, UINT32 &fourcc, UINT32 &csz, UINT32 &consumed); + int getRealFileHeader(File_Header_v0_v1 *hdr, const unsigned char *buf, UINT32 object_id, int sz); + int getRealPropertyHeader(RMProperties *props, const unsigned char *buf, UINT32 object_id, int sz); + int getMediaPropHeader(MediaProperties *mh, const unsigned char *buf, UINT32 object_id, int sz); + int getContentDescription(ContentDescription *cont, const unsigned char *buf, UINT32 object_id, int sz); + int getMDProperties(MDProperties *md, const unsigned char *buf); + +#ifdef TESTING + void printRealFileHeader(std::ostream &os); + void printRealPropHeader(std::ostream &os); + void printMediaPropHeaders(std::ostream &os); + void printContentDescription(std::ostream &os); + void printID3v1Tag(std::ostream &os); + void printMetadataSection(std::ostream &os); + void printMDProperties(std::ostream &os, char *name, MDProperties *props); +#endif + }; + + } // namespace RealMedia +} // namespace TagLib + +#ifdef TESTING +std::ostream &operator<<(std::ostream &os, TagLib::RealMedia::RealMediaFF &rmff); +#endif + +#endif diff --git a/src/metadata/rmff/taglib_realmediafile.cpp b/src/metadata/rmff/taglib_realmediafile.cpp new file mode 100644 index 0000000..b28c846 --- /dev/null +++ b/src/metadata/rmff/taglib_realmediafile.cpp @@ -0,0 +1,213 @@ +/*************************************************************************** + copyright : (C) 2005 by Paul Cifarelli + email : [email protected] + + copyright : (C) 2005 by Lukas Lalinsky + email : [email protected] + (portions) + ***************************************************************************/ + +/*************************************************************************** + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +/*************************************************************************** + * 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 or higher 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., 51 Franklin St, 5th fl, Boston, MA 02110-1301, * + * USA, or check http://www.fsf.org/about/contact.html * + ***************************************************************************/ + +#include <tfile.h> +#include <audioproperties.h> +#include <tstring.h> +#include <id3v1tag.h> +#include "rmff.h" +#include "taglib_realmediafile.h" + +using namespace TagLib; +using namespace TagLib::RealMedia; + + +RealMedia::Tag::Tag(RealMediaFF *rmff, bool allocnew) : m_rmff(rmff), m_owner(allocnew) +{ + if (m_owner) + m_rmff = new RealMediaFF(*rmff); +} + +RealMedia::Tag::~Tag () +{ + if (m_owner) + delete m_rmff; +} + +String RealMedia::Tag::title () const +{ + return m_rmff->title(); +} + +String RealMedia::Tag::artist () const +{ + return m_rmff->artist(); +} + +String RealMedia::Tag::album () const +{ + return m_rmff->album(); +} + +String RealMedia::Tag::comment () const +{ + return m_rmff->comment(); +} + +String RealMedia::Tag::genre () const +{ + return m_rmff->genre(); +} + +TagLib::uint RealMedia::Tag::year () const +{ + return m_rmff->year(); +} + +TagLib::uint RealMedia::Tag::track () const +{ + return m_rmff->track(); +} + +void RealMedia::Tag::setTitle (const String &) +{ +// TODO: write support +} + +void RealMedia::Tag::setArtist (const String &) +{ +// TODO: write support +} + +void RealMedia::Tag::setAlbum (const String &) +{ +// TODO: write support +} + +void RealMedia::Tag::setComment (const String &) +{ +// TODO: write support +} + +void RealMedia::Tag::setGenre (const String &) +{ +// TODO: write support +} + +void RealMedia::Tag::setYear (uint) +{ +// TODO: write support +} + +void RealMedia::Tag::setTrack (uint) +{ +// TODO: write support +} + +bool RealMedia::Tag::isEmpty() const +{ + return TagLib::Tag::isEmpty() && m_rmff->isEmpty(); +} + +void RealMedia::Tag::duplicate(const Tag *source, Tag *target, bool overwrite) +{ + TagLib::Tag::duplicate(source, target, overwrite); + if (overwrite) + { + if (target->m_owner) + { + delete target->m_rmff; + target->m_rmff = new RealMediaFF(*source->m_rmff); + } + else + target->m_rmff = source->m_rmff; + } + else + { + if (target->isEmpty()) + if (target->m_owner) + { + delete target->m_rmff; + target->m_rmff = new RealMediaFF(*source->m_rmff); + } + else + target->m_rmff = source->m_rmff; + } +} + + + +int RealMedia::Properties::length () const +{ + return (m_rmff->length() / 1000); +} + +int RealMedia::Properties::bitrate () const +{ + return (m_rmff->bitrate() / 1000); +} + +int RealMedia::Properties::sampleRate () const +{ + return m_rmff->sampleRate(); +} + +int RealMedia::Properties::channels () const +{ + return m_rmff->channels(); +} + + +RealMedia::File::File(const char *file, bool readProperties, Properties::ReadStyle propertiesStyle) + : TagLib::File(file), m_rmfile(0), m_tag(0), m_props(0) +{ + m_rmfile = new RealMediaFF(file, readProperties, propertiesStyle); + m_tag = new RealMedia::Tag(m_rmfile); + m_props = new RealMedia::Properties(m_rmfile); +} + +RealMedia::File::~File() +{ + delete m_props; + delete m_tag; + delete m_rmfile; +} + +TagLib::Tag *RealMedia::File::tag() const +{ + return m_tag; +} + +RealMedia::Tag *RealMedia::File::RealMediaTag() const +{ + return m_tag; +} + +RealMedia::Properties *RealMedia::File::audioProperties() const +{ + return m_props; // m_rmfile->properties; +} + + + + + diff --git a/src/metadata/rmff/taglib_realmediafile.h b/src/metadata/rmff/taglib_realmediafile.h new file mode 100644 index 0000000..0f0ca58 --- /dev/null +++ b/src/metadata/rmff/taglib_realmediafile.h @@ -0,0 +1,133 @@ +/*************************************************************************** + copyright : (C) 2005 by Paul Cifarelli + email : [email protected] + + copyright : (C) 2005 by Lukas Lalinsky + email : [email protected] + (portions) + ***************************************************************************/ + +/*************************************************************************** + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +/*************************************************************************** + * 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 or higher 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., 51 Franklin St, 5th fl, Boston, MA 02110-1301, * + * USA, or check http://www.fsf.org/about/contact.html * + ***************************************************************************/ +#ifndef _TAGLIB_REALMEDIAFILE_H_ +#define _TAGLIB_REALMEDIAFILE_H_ + +#include <tfile.h> +#include <audioproperties.h> +#include <tag.h> + +#include <iostream> + +class RealMediaFF; +namespace TagLib { + + namespace RealMedia { + + class Tag : public TagLib::Tag + { + public: + Tag(RealMediaFF *rmff, bool allocnew = false); + virtual ~Tag (); + virtual String title () const; + virtual String artist () const; + virtual String album () const; + virtual String comment () const; + virtual String genre () const; + virtual uint year () const; + virtual uint track () const; + virtual void setTitle (const String &s); + virtual void setArtist (const String &s); + virtual void setAlbum (const String &s); + virtual void setComment (const String &s); + virtual void setGenre (const String &s); + virtual void setYear (uint i); + virtual void setTrack (uint i); + + bool isEmpty() const; + void duplicate(const Tag *source, Tag *target, bool overwrite); + + private: + Tag(); + RealMediaFF *m_rmff; + bool m_owner; + }; + + + class Properties : public TagLib::AudioProperties + { + public: + Properties(RealMediaFF *rmff) : TagLib::AudioProperties(Average), m_rmff(rmff) {} + virtual ~Properties() {} // you don't own rmff + virtual int length () const; + virtual int bitrate () const; + virtual int sampleRate () const; + virtual int channels () const; + + private: + Properties(); + RealMediaFF *m_rmff; + }; + + class File : public TagLib::File + { + public: + + File(const char *file, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average); + + virtual ~File(); + + /* + * Returns the TagLib::Tag for this file. + */ + virtual TagLib::Tag *tag() const; + + /* + * Returns the RealMedia::RealMediaTag for this file. + */ + virtual Tag *RealMediaTag() const; + + /* + * Returns the RealMedia::Properties for this file. + */ + virtual Properties *audioProperties() const; + + + /* + * Save the file. + * + * This returns true if the save was successful. + */ + virtual bool save() { return false; } // for now + + private: + + RealMediaFF *m_rmfile; + Tag *m_tag; + Properties *m_props; + }; + + } + +} + +#endif diff --git a/src/metadata/rmff/taglib_realmediafiletyperesolver.cpp b/src/metadata/rmff/taglib_realmediafiletyperesolver.cpp new file mode 100644 index 0000000..a8660a6 --- /dev/null +++ b/src/metadata/rmff/taglib_realmediafiletyperesolver.cpp @@ -0,0 +1,53 @@ +/*************************************************************************** + copyright : (C) 2005 by Paul Cifarelli + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin St, 5th fl, Boston, MA 02110-1301, * + * USA, or check http://www.fsf.org/about/contact.html * + * * + ***************************************************************************/ + +#include <tfile.h> +#include <audioproperties.h> +#include <id3v1tag.h> +#include "taglib_realmediafiletyperesolver.h" +#include "taglib_realmediafile.h" +#include "rmff.h" + +#include <string.h> + +TagLib::File *RealMediaFileTypeResolver::createFile(const char *fileName, + bool readProperties, + TagLib::AudioProperties::ReadStyle propertiesStyle) const +{ + const char *ext = strrchr(fileName, '.'); + if(ext && (!strcasecmp(ext, ".ra") || !strcasecmp(ext, ".rv") || !strcasecmp(ext, ".rm") || + !strcasecmp(ext, ".rmj") || !strcasecmp(ext, ".rmvb") )) + { + TagLib::RealMedia::File *f = new TagLib::RealMedia::File(fileName, readProperties, propertiesStyle); + if(f->isValid()) + return f; + else + { + delete f; + } + } + + return 0; +} diff --git a/src/metadata/rmff/taglib_realmediafiletyperesolver.h b/src/metadata/rmff/taglib_realmediafiletyperesolver.h new file mode 100644 index 0000000..b292e10 --- /dev/null +++ b/src/metadata/rmff/taglib_realmediafiletyperesolver.h @@ -0,0 +1,39 @@ +/*************************************************************************** + copyright : (C) 2005 by Paul Cifarelli + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin St, 5th fl, Boston, MA 02110-1301, * + * USA, or check http://www.fsf.org/about/contact.html * + * * + ***************************************************************************/ +#ifndef _TAGLIB_REALMEDIAFILETYPERESOLVER_H_ +#define _TAGLIB_REALMEDIAFILETYPERESOLVER_H_ + +#include <taglib/tfile.h> +#include <taglib/fileref.h> + + +class RealMediaFileTypeResolver : public TagLib::FileRef::FileTypeResolver +{ + TagLib::File *createFile(const char *fileName, + bool readAudioProperties, + TagLib::AudioProperties::ReadStyle audioPropertiesStyle) const; +}; + +#endif diff --git a/src/metadata/speex/Makefile.am b/src/metadata/speex/Makefile.am new file mode 100644 index 0000000..6bf01aa --- /dev/null +++ b/src/metadata/speex/Makefile.am @@ -0,0 +1,16 @@ +SUBDIRS = + +INCLUDES = $(all_includes) $(taglib_includes) +METASOURCES = AUTO +libtagspeex_la_LDFLAGS = $(all_libraries) +noinst_LTLIBRARIES = libtagspeex.la + +libtagspeex_la_SOURCES = \ + speexfile.cpp \ + speexproperties.cpp \ + taglib_speexfiletyperesolver.cpp + +noinst_HEADERS = speexfile.h \ + speexproperties.h \ + taglib_speexfiletyperesolver.h + diff --git a/src/metadata/speex/speexfile.cpp b/src/metadata/speex/speexfile.cpp new file mode 100644 index 0000000..eccaded --- /dev/null +++ b/src/metadata/speex/speexfile.cpp @@ -0,0 +1,111 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : [email protected] + + copyright : (C) 2002 by Scott Wheeler + email : [email protected] + (original Vorbis 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <bitset> + +#include <tstring.h> +#if 0 +#include <tdebug.h> +#endif + +#include "speexfile.h" + +using namespace TagLib; + +class Speex::File::FilePrivate +{ +public: + FilePrivate() : + comment(0), + properties(0) {} + + ~FilePrivate() + { + delete comment; + delete properties; + } + + Ogg::XiphComment *comment; + Properties *properties; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Speex::File::File(const char *file, bool readProperties, + Properties::ReadStyle propertiesStyle) : Ogg::File(file) +{ + d = new FilePrivate; + read(readProperties, propertiesStyle); +} + +Speex::File::~File() +{ + delete d; +} + +Ogg::XiphComment *Speex::File::tag() const +{ + return d->comment; +} + +Speex::Properties *Speex::File::audioProperties() const +{ + return d->properties; +} + +bool Speex::File::save() +{ + if(!d->comment) + d->comment = new Ogg::XiphComment; + + setPacket(1, d->comment->render()); + + return Ogg::File::save(); +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void Speex::File::read(bool readProperties, Properties::ReadStyle propertiesStyle) +{ + ByteVector speexHeaderData = packet(0); + + if(!speexHeaderData.startsWith("Speex ")) { +#if 0 + debug("Speex::File::read() -- invalid Speex identification header"); +#endif + return; + } + + ByteVector commentHeaderData = packet(1); + + d->comment = new Ogg::XiphComment(commentHeaderData); + + if(readProperties) + d->properties = new Properties(this, propertiesStyle); +} diff --git a/src/metadata/speex/speexfile.h b/src/metadata/speex/speexfile.h new file mode 100644 index 0000000..d300ac3 --- /dev/null +++ b/src/metadata/speex/speexfile.h @@ -0,0 +1,93 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : [email protected] + + copyright : (C) 2002 by Scott Wheeler + email : [email protected] + (original Vorbis 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_SPEEXFILE_H +#define TAGLIB_SPEEXFILE_H + +#include <oggfile.h> +#include <xiphcomment.h> + +#include "speexproperties.h" + +namespace TagLib { + + //! A namespace containing classes for Speex metadata + + namespace Speex { + + //! An implementation of Ogg::File with Speex specific methods + + /*! + * This is the central class in the Ogg Speex metadata processing collection + * of classes. It's built upon Ogg::File which handles processing of the Ogg + * logical bitstream and breaking it down into pages which are handled by + * the codec implementations, in this case Speex specifically. + */ + + class File : public Ogg::File + { + public: + /*! + * Contructs a Speex 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(const char *file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + /*! + * Returns the XiphComment for this file. XiphComment implements the tag + * interface, so this serves as the reimplementation of + * TagLib::File::tag(). + */ + virtual Ogg::XiphComment *tag() const; + + /*! + * Returns the Speex::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + virtual bool save(); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties, Properties::ReadStyle propertiesStyle); + + class FilePrivate; + FilePrivate *d; + }; + } + +} + +#endif diff --git a/src/metadata/speex/speexproperties.cpp b/src/metadata/speex/speexproperties.cpp new file mode 100644 index 0000000..edd2b71 --- /dev/null +++ b/src/metadata/speex/speexproperties.cpp @@ -0,0 +1,171 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : [email protected] + + copyright : (C) 2002 by Scott Wheeler + email : [email protected] + (original Vorbis 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <tstring.h> +#if 0 +#include <tdebug.h> +#endif + +#include <oggpageheader.h> + +#include "speexproperties.h" +#include "speexfile.h" + +using namespace TagLib; + +class Speex::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate(File *f, ReadStyle s) : + file(f), + style(s), + length(0), + bitrate(0), + sampleRate(0), + channels(0), + speexVersion(0), + vbr(false), + mode(0) {} + + File *file; + ReadStyle style; + int length; + int bitrate; + int sampleRate; + int channels; + int speexVersion; + bool vbr; + int mode; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Speex::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style) +{ + d = new PropertiesPrivate(file, style); + read(); +} + +Speex::Properties::~Properties() +{ + delete d; +} + +int Speex::Properties::length() const +{ + return d->length; +} + +int Speex::Properties::bitrate() const +{ + return int(float(d->bitrate) / float(1000) + 0.5); +} + +int Speex::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int Speex::Properties::channels() const +{ + return d->channels; +} + +int Speex::Properties::speexVersion() const +{ + return d->speexVersion; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void Speex::Properties::read() +{ + // Get the identification header from the Ogg implementation. + + ByteVector data = d->file->packet(0); + + int pos = 28; + + // speex_version_id; /**< Version for Speex (for checking compatibility) */ + d->speexVersion = data.mid(pos, 4).toUInt(false); + pos += 4; + + // header_size; /**< Total size of the header ( sizeof(SpeexHeader) ) */ + pos += 4; + + // rate; /**< Sampling rate used */ + d->sampleRate = data.mid(pos, 4).toUInt(false); + pos += 4; + + // mode; /**< Mode used (0 for narrowband, 1 for wideband) */ + d->mode = data.mid(pos, 4).toUInt(false); + pos += 4; + + // mode_bitstream_version; /**< Version ID of the bit-stream */ + pos += 4; + + // nb_channels; /**< Number of channels encoded */ + d->channels = data.mid(pos, 4).toUInt(false); + pos += 4; + + // bitrate; /**< Bit-rate used */ + d->bitrate = data.mid(pos, 4).toUInt(false); + pos += 4; + + // frame_size; /**< Size of frames */ + //unsigned int frameSize = data.mid(pos, 4).toUInt(false); + pos += 4; + + // vbr; /**< 1 for a VBR encoding, 0 otherwise */ + d->vbr = data.mid(pos, 4).toUInt(false) == 1; + pos += 4; + + // frames_per_packet; /**< Number of frames stored per Ogg packet */ + //unsigned int framesPerPacket = data.mid(pos, 4).toUInt(false); + + const Ogg::PageHeader *first = d->file->firstPageHeader(); + const Ogg::PageHeader *last = d->file->lastPageHeader(); + + if(first && last) { + long long start = first->absoluteGranularPosition(); + long long end = last->absoluteGranularPosition(); + + if(start >= 0 && end >= 0 && d->sampleRate > 0) + d->length = (end - start) / (long long) d->sampleRate; +#if 0 + else + debug("Speex::Properties::read() -- Either the PCM values for the start or " + "end of this file was incorrect or the sample rate is zero."); +#endif + } +#if 0 + else + debug("Speex::Properties::read() -- Could not find valid first and last Ogg pages."); +#endif +} diff --git a/src/metadata/speex/speexproperties.h b/src/metadata/speex/speexproperties.h new file mode 100644 index 0000000..355ff3c --- /dev/null +++ b/src/metadata/speex/speexproperties.h @@ -0,0 +1,83 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : [email protected] + + copyright : (C) 2002 by Scott Wheeler + email : [email protected] + (original Vorbis 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_SPEEXPROPERTIES_H +#define TAGLIB_SPEEXPROPERTIES_H + +#include <audioproperties.h> + +namespace TagLib { + + namespace Speex { + + class File; + + //! An implementation of audio property reading for Ogg Speex + + /*! + * This reads the data from an Ogg Speex stream found in the AudioProperties + * API. + */ + + class Properties : public AudioProperties + { + public: + /*! + * Create an instance of Vorbis::Properties with the data read from the + * Vorbis::File \a file. + */ + Properties(File *file, ReadStyle style = Average); + + /*! + * Destroys this VorbisProperties instance. + */ + virtual ~Properties(); + + // Reimplementations. + + virtual int length() const; + virtual int bitrate() const; + virtual int sampleRate() const; + virtual int channels() const; + + /*! + * Returns the Vorbis version, currently "0" (as specified by the spec). + */ + int speexVersion() const; + + private: + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } + +} + +#endif diff --git a/src/metadata/speex/taglib_speexfiletyperesolver.cpp b/src/metadata/speex/taglib_speexfiletyperesolver.cpp new file mode 100644 index 0000000..9a5de0d --- /dev/null +++ b/src/metadata/speex/taglib_speexfiletyperesolver.cpp @@ -0,0 +1,44 @@ +/*************************************************************************** + copyright : (C) 2006 by Martin Aumueller + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "taglib_speexfiletyperesolver.h" +#include "speexfile.h" + +#include <string.h> + +TagLib::File *SpeexFileTypeResolver::createFile(const char *fileName, + bool readProperties, + TagLib::AudioProperties::ReadStyle propertiesStyle) const +{ + const char *ext = strrchr(fileName, '.'); + if(ext && !strcasecmp(ext, ".spx")) + { + TagLib::Speex::File *f = new TagLib::Speex::File(fileName, readProperties, propertiesStyle); + if(f->isValid()) + return f; + else + { + delete f; + } + } + + return 0; +} diff --git a/src/metadata/speex/taglib_speexfiletyperesolver.h b/src/metadata/speex/taglib_speexfiletyperesolver.h new file mode 100644 index 0000000..b5c5c2c --- /dev/null +++ b/src/metadata/speex/taglib_speexfiletyperesolver.h @@ -0,0 +1,36 @@ +/*************************************************************************** + copyright : (C) 2006 by Martin Aumueller + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_SPEEXFILETYPERESOLVER_H +#define TAGLIB_SPEEXFILETYPERESOLVER_H + +#include <taglib/tfile.h> +#include <taglib/fileref.h> + + +class SpeexFileTypeResolver : public TagLib::FileRef::FileTypeResolver +{ + TagLib::File *createFile(const char *fileName, + bool readAudioProperties, + TagLib::AudioProperties::ReadStyle audioPropertiesStyle) const; +}; + +#endif diff --git a/src/metadata/tagengine.cpp b/src/metadata/tagengine.cpp new file mode 100755 index 0000000..34abd23 --- /dev/null +++ b/src/metadata/tagengine.cpp @@ -0,0 +1,419 @@ + +#include "tagengine.h" + +#include <qfile.h> + +// #include <taglib/attachedpictureframe.h> +#include <taglib/fileref.h> +#include <taglib/id3v1genres.h> //used to load genre list +#include <taglib/mpegfile.h> +#include <taglib/tag.h> +#include <taglib/tstring.h> +#include <taglib/tlist.h> +#include <taglib/apetag.h> +#include <taglib/id3v2tag.h> +#include <taglib/id3v1tag.h> +#include <taglib/mpcfile.h> +#include <taglib/mpegfile.h> +#include <taglib/oggfile.h> +#include <taglib/oggflacfile.h> +#include <taglib/vorbisfile.h> +#include <taglib/flacfile.h> +#include <taglib/textidentificationframe.h> +#include <taglib/uniquefileidentifierframe.h> +#include <taglib/xiphcomment.h> +#include "wavpack/wvfile.h" +#include "trueaudio/ttafile.h" + +#include <config.h> +#ifdef HAVE_MP4V2 +#include "mp4/mp4file.h" +#include "mp4/mp4tag.h" +#else +#include "m4a/mp4file.h" +#include "m4a/mp4itunestag.h" +#endif + + +// TODO COMPILATION tag +// FIXME BPM tag + +TagData::TagData( const QString& _artist, const QString& _composer, + const QString& _album, const QString& _title, + const QString& _genre, const QString& _comment, + int _track, int _disc, int _year, + int _length, int _fileSize, int _bitrate, int _samplingRate ) +{ + artist = _artist; + composer = _composer; + album = _album; + title = _title; + genre = _genre; + comment = _comment; + track = _track; + disc = _disc; + year = _year; + length = _length; + fileSize = _fileSize; + bitrate = _bitrate; + samplingRate = _samplingRate; +} + +TagData::~TagData() +{} + + +TagEngine::TagEngine() +{ + TagLib::StringList genres = TagLib::ID3v1::genreList(); + for( TagLib::StringList::ConstIterator it = genres.begin(), end = genres.end(); it != end; ++it ) + genreList += TStringToQString( (*it) ); + + genreList.sort(); +} + +TagEngine::~TagEngine() +{} + +TagData* TagEngine::readTags( const QString& file ) +{ + TagLib::FileRef fileref( QFile::encodeName(file) ); + TagData* tagData = new TagData(); + + if( !fileref.isNull() ) + { + TagLib::Tag *tag = fileref.tag(); + + tagData->track = 0; + tagData->year = 0; + tagData->disc = 0; + tagData->track_gain = 210588; // 0 is a valid value + tagData->album_gain = 210588; + + if( tag ) + { + tagData->title = TStringToQString( tag->title() ).stripWhiteSpace(); + tagData->artist = TStringToQString( tag->artist() ).stripWhiteSpace(); + tagData->album = TStringToQString( tag->album() ).stripWhiteSpace(); + tagData->genre = TStringToQString( tag->genre() ).stripWhiteSpace(); + tagData->comment = TStringToQString( tag->comment() ).stripWhiteSpace(); + tagData->track = tag->track(); + tagData->year = tag->year(); + } + + TagLib::AudioProperties *audioProperties = fileref.audioProperties(); + + if( audioProperties ) + { + tagData->length = audioProperties->length(); + // TODO read all information + //tagData->fileSize = ; + // = audioProperties->channels(); + //tagData->bitrate = audioProperties->bitrate(); + tagData->samplingRate = audioProperties->sampleRate(); + } + + QString disc; + QString track_gain; + QString album_gain; + if ( TagLib::MPEG::File *file = dynamic_cast<TagLib::MPEG::File *>( fileref.file() ) ) + { + if ( file->ID3v2Tag() ) + { + if ( !file->ID3v2Tag()->frameListMap()[ "TPOS" ].isEmpty() ) + disc = TStringToQString( file->ID3v2Tag()->frameListMap()["TPOS"].front()->toString() ).stripWhiteSpace(); + + if ( !file->ID3v2Tag()->frameListMap()[ "TCOM" ].isEmpty() ) + tagData->composer = TStringToQString( file->ID3v2Tag()->frameListMap()["TCOM"].front()->toString() ).stripWhiteSpace(); + } + if ( file->APETag() ) + { + if ( !file->APETag()->itemListMap()[ "REPLAYGAIN_TRACK_GAIN" ].isEmpty() ) + track_gain = TStringToQString( file->APETag()->itemListMap()["REPLAYGAIN_TRACK_GAIN"].toString() ).stripWhiteSpace(); + + if ( !file->APETag()->itemListMap()[ "REPLAYGAIN_ALBUM_GAIN" ].isEmpty() ) + album_gain = TStringToQString( file->APETag()->itemListMap()["REPLAYGAIN_ALBUM_GAIN"].toString() ).stripWhiteSpace(); + } + } + else if ( TagLib::Ogg::Vorbis::File *file = dynamic_cast<TagLib::Ogg::Vorbis::File *>( fileref.file() ) ) + { + if ( file->tag() ) + { + if ( !file->tag()->fieldListMap()[ "COMPOSER" ].isEmpty() ) + tagData->composer = TStringToQString( file->tag()->fieldListMap()["COMPOSER"].front() ).stripWhiteSpace(); + + if ( !file->tag()->fieldListMap()[ "DISCNUMBER" ].isEmpty() ) + disc = TStringToQString( file->tag()->fieldListMap()["DISCNUMBER"].front() ).stripWhiteSpace(); + + if ( !file->tag()->fieldListMap()[ "REPLAYGAIN_TRACK_GAIN" ].isEmpty() ) + track_gain = TStringToQString( file->tag()->fieldListMap()["REPLAYGAIN_TRACK_GAIN"].front() ).stripWhiteSpace(); + + if ( !file->tag()->fieldListMap()[ "REPLAYGAIN_ALBUM_GAIN" ].isEmpty() ) + album_gain = TStringToQString( file->tag()->fieldListMap()["REPLAYGAIN_ALBUM_GAIN"].front() ).stripWhiteSpace(); + } + } + else if ( TagLib::FLAC::File *file = dynamic_cast<TagLib::FLAC::File *>( fileref.file() ) ) + { + if ( file->xiphComment() ) + { + if ( !file->xiphComment()->fieldListMap()[ "COMPOSER" ].isEmpty() ) + tagData->composer = TStringToQString( file->xiphComment()->fieldListMap()["COMPOSER"].front() ).stripWhiteSpace(); + + if ( !file->xiphComment()->fieldListMap()[ "DISCNUMBER" ].isEmpty() ) + disc = TStringToQString( file->xiphComment()->fieldListMap()["DISCNUMBER"].front() ).stripWhiteSpace(); + + if ( !file->xiphComment()->fieldListMap()[ "REPLAYGAIN_TRACK_GAIN" ].isEmpty() ) + track_gain = TStringToQString( file->xiphComment()->fieldListMap()["REPLAYGAIN_TRACK_GAIN"].front() ).stripWhiteSpace(); + + if ( !file->xiphComment()->fieldListMap()[ "REPLAYGAIN_ALBUM_GAIN" ].isEmpty() ) + album_gain = TStringToQString( file->xiphComment()->fieldListMap()["REPLAYGAIN_ALBUM_GAIN"].front() ).stripWhiteSpace(); + } + + /*if ( file->tag() ) + { + if ( !file->tag()->fieldListMap()[ "REPLAYGAIN_TRACK_GAIN" ].isEmpty() ) + track_gain = TStringToQString( file->tag()->fieldListMap()["REPLAYGAIN_TRACK_GAIN"].front() ).stripWhiteSpace(); + + if ( !file->tag()->fieldListMap()[ "REPLAYGAIN_ALBUM_GAIN" ].isEmpty() ) + album_gain = TStringToQString( file->tag()->fieldListMap()["REPLAYGAIN_ALBUM_GAIN"].front() ).stripWhiteSpace(); + }*/ + } + else if ( TagLib::MP4::File *file = dynamic_cast<TagLib::MP4::File *>( fileref.file() ) ) + { + TagLib::MP4::Tag *mp4tag = dynamic_cast<TagLib::MP4::Tag *>( file->tag() ); + if( mp4tag ) + { + tagData->composer = TStringToQString( mp4tag->composer() ); + + disc = QString::number( mp4tag->disk() ); + } + } +/* else if ( TagLib::MPC::File *file = dynamic_cast<TagLib::MPC::File *>( fileref.file() ) ) + { + if ( file->APETag() ) + { + if ( !file->APETag()->itemListMap()[ "REPLAYGAIN_TRACK_GAIN" ].isEmpty() ) + track_gain = TStringToQString( file->APETag()->itemListMap()["REPLAYGAIN_TRACK_GAIN"].toString() ).stripWhiteSpace(); + + if ( !file->APETag()->itemListMap()[ "REPLAYGAIN_ALBUM_GAIN" ].isEmpty() ) + album_gain = TStringToQString( file->APETag()->itemListMap()["REPLAYGAIN_ALBUM_GAIN"].toString() ).stripWhiteSpace(); + } + }*/ + else if ( TagLib::WavPack::File *file = dynamic_cast<TagLib::WavPack::File *>( fileref.file() ) ) + { + if ( file->APETag() ) + { + if ( !file->APETag()->itemListMap()[ "REPLAYGAIN_TRACK_GAIN" ].isEmpty() ) + track_gain = TStringToQString( file->APETag()->itemListMap()["REPLAYGAIN_TRACK_GAIN"].toString() ).stripWhiteSpace(); + + if ( !file->APETag()->itemListMap()[ "REPLAYGAIN_ALBUM_GAIN" ].isEmpty() ) + album_gain = TStringToQString( file->APETag()->itemListMap()["REPLAYGAIN_ALBUM_GAIN"].toString() ).stripWhiteSpace(); + } + } + else if ( TagLib::TTA::File *file = dynamic_cast<TagLib::TTA::File *>( fileref.file() ) ) + { + if ( file->ID3v2Tag() ) + { + if ( !file->ID3v2Tag()->frameListMap()[ "TPOS" ].isEmpty() ) + disc = TStringToQString( file->ID3v2Tag()->frameListMap()["TPOS"].front()->toString() ).stripWhiteSpace(); + + if ( !file->ID3v2Tag()->frameListMap()[ "TCOM" ].isEmpty() ) + tagData->composer = TStringToQString( file->ID3v2Tag()->frameListMap()["TCOM"].front()->toString() ).stripWhiteSpace(); + } + } + + if( !disc.isEmpty() ) + { + int i = disc.find('/'); + if( i != -1 ) + // disc.right( i ).toInt() is total number of discs, we don't use this at the moment + tagData->disc = disc.left( i ).toInt(); + else + tagData->disc = disc.toInt(); + } + + if( !track_gain.isEmpty() ) + { + int i = track_gain.find(' '); + if( i != -1 ) + tagData->track_gain = track_gain.left( i ).toFloat(); + else + tagData->track_gain = track_gain.toFloat(); + } + + if( !album_gain.isEmpty() ) + { + int i = album_gain.find(' '); + if( i != -1 ) + tagData->album_gain = album_gain.left( i ).toFloat(); + else + tagData->album_gain = album_gain.toFloat(); + } + + return tagData; + } + + return 0; +} + +bool TagEngine::writeTags( const QString& file, TagData* tagData ) +{ + if( !tagData ) tagData = new TagData(); + + //Set default codec to UTF-8 (see bugs 111246 and 111232) + TagLib::ID3v2::FrameFactory::instance()->setDefaultTextEncoding( TagLib::String::UTF8 ); + + TagLib::FileRef fileref( QFile::encodeName(file), false ); + + if ( !fileref.isNull() ) + { + TagLib::Tag* tag = fileref.tag(); + if ( tag ) + { + tag->setTitle( QStringToTString(tagData->title) ); + tag->setArtist( QStringToTString(tagData->artist) ); + tag->setAlbum( QStringToTString(tagData->album) ); + tag->setTrack( tagData->track ); + tag->setYear( tagData->year ); + tag->setComment( QStringToTString(tagData->comment) ); + tag->setGenre( QStringToTString(tagData->genre) ); + } + else + { + return false; + } + + if ( TagLib::MPEG::File *file = dynamic_cast<TagLib::MPEG::File *>( fileref.file() ) ) + { + if ( file->ID3v2Tag() ) + { + if ( !file->ID3v2Tag()->frameListMap()[ "TPOS" ].isEmpty() ) + { + file->ID3v2Tag()->frameListMap()[ "TPOS" ].front()->setText( QStringToTString( QString::number(tagData->disc) ) ); + } + else + { + TagLib::ID3v2::TextIdentificationFrame *frame = new TagLib::ID3v2::TextIdentificationFrame( "TPOS", TagLib::ID3v2::FrameFactory::instance()->defaultTextEncoding() ); + frame->setText( QStringToTString( QString::number(tagData->disc) ) ); + file->ID3v2Tag()->addFrame( frame ); + } + + if ( !file->ID3v2Tag()->frameListMap()[ "TCOM" ].isEmpty() ) + { + file->ID3v2Tag()->frameListMap()[ "TCOM" ].front()->setText( QStringToTString( tagData->composer ) ); + } + else + { + TagLib::ID3v2::TextIdentificationFrame *frame = new TagLib::ID3v2::TextIdentificationFrame( "TCOM", TagLib::ID3v2::FrameFactory::instance()->defaultTextEncoding() ); + frame->setText( QStringToTString( tagData->composer ) ); + file->ID3v2Tag()->addFrame( frame ); + } + + // HACK sets the id3v2 genre tag as string + if ( !file->ID3v2Tag()->frameListMap()[ "TCON" ].isEmpty() ) + { + file->ID3v2Tag()->frameListMap()[ "TCON" ].front()->setText( QStringToTString( tagData->genre ) ); + } + else + { + TagLib::ID3v2::TextIdentificationFrame *frame = new TagLib::ID3v2::TextIdentificationFrame( "TCON", TagLib::ID3v2::FrameFactory::instance()->defaultTextEncoding() ); + frame->setText( QStringToTString( tagData->genre ) ); + file->ID3v2Tag()->addFrame( frame ); + } + + // HACK sets the id3v2 year tag + if ( !file->ID3v2Tag()->frameListMap()[ "TYER" ].isEmpty() ) + { + file->ID3v2Tag()->frameListMap()[ "TYER" ].front()->setText( QStringToTString( QString::number(tagData->year) ) ); + } + else + { + TagLib::ID3v2::TextIdentificationFrame *frame = new TagLib::ID3v2::TextIdentificationFrame( "TYER", TagLib::ID3v2::FrameFactory::instance()->defaultTextEncoding() ); + frame->setText( QStringToTString( QString::number(tagData->year) ) ); + file->ID3v2Tag()->addFrame( frame ); + } + } + } + else if ( TagLib::Ogg::Vorbis::File *file = dynamic_cast<TagLib::Ogg::Vorbis::File *>( fileref.file() ) ) + { + if ( file->tag() ) + { + file->tag()->addField( "COMPOSER", QStringToTString( tagData->composer ), true ); + + file->tag()->addField( "DISCNUMBER", QStringToTString( QString::number(tagData->disc) ), true ); + } + } + else if ( TagLib::FLAC::File *file = dynamic_cast<TagLib::FLAC::File *>( fileref.file() ) ) + { + if ( file->xiphComment() ) + { + file->xiphComment()->addField( "COMPOSER", QStringToTString( tagData->composer ), true ); + + file->xiphComment()->addField( "DISCNUMBER", QStringToTString( QString::number(tagData->disc) ), true ); + } + } + else if ( TagLib::MP4::File *file = dynamic_cast<TagLib::MP4::File *>( fileref.file() ) ) + { + TagLib::MP4::Tag *mp4tag = dynamic_cast<TagLib::MP4::Tag *>( file->tag() ); + if( mp4tag ) + { + mp4tag->setComposer( QStringToTString( tagData->composer ) ); + + mp4tag->setDisk( tagData->disc ); + } + } + if ( TagLib::TTA::File *file = dynamic_cast<TagLib::TTA::File *>( fileref.file() ) ) + { + if ( file->ID3v2Tag() ) + { + if ( !file->ID3v2Tag()->frameListMap()[ "TPOS" ].isEmpty() ) + { + file->ID3v2Tag()->frameListMap()[ "TPOS" ].front()->setText( QStringToTString( QString::number(tagData->disc) ) ); + } + else + { + TagLib::ID3v2::TextIdentificationFrame *frame = new TagLib::ID3v2::TextIdentificationFrame( "TPOS", TagLib::ID3v2::FrameFactory::instance()->defaultTextEncoding() ); + frame->setText( QStringToTString( QString::number(tagData->disc) ) ); + file->ID3v2Tag()->addFrame( frame ); + } + + if ( !file->ID3v2Tag()->frameListMap()[ "TCOM" ].isEmpty() ) + { + file->ID3v2Tag()->frameListMap()[ "TCOM" ].front()->setText( QStringToTString( tagData->composer ) ); + } + else + { + TagLib::ID3v2::TextIdentificationFrame *frame = new TagLib::ID3v2::TextIdentificationFrame( "TCOM", TagLib::ID3v2::FrameFactory::instance()->defaultTextEncoding() ); + frame->setText( QStringToTString( tagData->composer ) ); + file->ID3v2Tag()->addFrame( frame ); + } + } + } + + return fileref.save(); + } + return false; +} + +// bool TagEngine::canWrite( QString format ) +// { +// format = format.lower(); +// +// if( format == "ogg" || +// format == "flac" || format == "fla" || +// format == "mp3" || // TODO mp2 ? +// format == "mpc" || +// format == "aac" || +// format == "ape" || format == "mac" || +// format == "aa" || +// format == "m4a" || format == "m4b" || format == "m4p" || format == "mp4" || format == "m4v" || format == "mp4v" || +// format == "ra" || format == "rv" || format == "rm" || format == "rmj" || format == "rmvb" || +// format == "wma" || format == "asf" ) +// { +// return true; +// } +// else { +// return false; +// } +// } + diff --git a/src/metadata/tagengine.h b/src/metadata/tagengine.h new file mode 100755 index 0000000..e21a48c --- /dev/null +++ b/src/metadata/tagengine.h @@ -0,0 +1,79 @@ + + +#ifndef TAGENGINE_H +#define TAGENGINE_H + +#include <qstring.h> +#include <qstringlist.h> + +/** + * @short All metainformation can be stored in this class + * @author Daniel Faust <[email protected]> + * @version 0.3 + */ +class TagData +{ +public: + /** + * Constructor + */ + TagData( const QString& _artist = QString::null, const QString& _composer = QString::null, + const QString& _album = QString::null, const QString& _title = QString::null, + const QString& _genre = QString::null, const QString& _comment = QString::null, + int _track = 0, int _disc = 0, int _year = 0, + int _length = 0, int _fileSize = 0, int _bitrate = 0, int _samplingRate = 0 ); + + /** + * Destructor + */ + virtual ~TagData(); + + /** The tags */ + QString artist; + QString composer; + QString album; + QString title; + QString genre; + QString comment; + int track; + int disc; + int year; + float track_gain; + float album_gain; + + /** The technical information */ + int length; + int fileSize; + int bitrate; + int samplingRate; +}; + + +/** + * @short Manages everything that has something to do with tags + * @author Daniel Faust <[email protected]> + * @version 0.3 + */ +class TagEngine +{ +public: + /** + * Constructor + */ + TagEngine(); + + /** + * Destructor + */ + virtual ~TagEngine(); + + /** A list of all genre */ + QStringList genreList; + + TagData* readTags( const QString& file ); + bool writeTags( const QString& file, TagData* tagData ); + +// bool canWrite( QString format ); // NOTE no const because this string is being modyfied +}; + +#endif // TAGENGINE_H diff --git a/src/metadata/tplugins.cpp b/src/metadata/tplugins.cpp new file mode 100755 index 0000000..b84d601 --- /dev/null +++ b/src/metadata/tplugins.cpp @@ -0,0 +1,151 @@ +/*************************************************************************** + copyright : (C) 2005, 2006 by Martin Aumueller + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <config.h> +// #include <debug.h> + +#include <qfile.h> +#include <kmimetype.h> + +#include <taglib/fileref.h> +#include <taglib/tfile.h> + +#ifdef HAVE_MP4V2 +#include "mp4/taglib_mp4filetyperesolver.h" +#include "mp4/mp4file.h" +#else +#include "m4a/taglib_mp4filetyperesolver.h" +#include "m4a/mp4file.h" +#endif + +#include "trueaudio/taglib_trueaudiofiletyperesolver.h" +#include "trueaudio/ttafile.h" +#include "wavpack/taglib_wavpackfiletyperesolver.h" +#include "wavpack/wvfile.h" +#include "speex/taglib_speexfiletyperesolver.h" +#include "speex/speexfile.h" +#include "asf/taglib_asffiletyperesolver.h" +#include "asf/asffile.h" +#include "rmff/taglib_realmediafiletyperesolver.h" +#include "rmff/taglib_realmediafile.h" +#include "audible/taglib_audiblefiletyperesolver.h" +#include "audible/taglib_audiblefile.h" +#include "wav/wavfiletyperesolver.h" +#include "wav/wavfile.h" +#include "aac/aacfiletyperesolver.h" +#include "ape/taglib_monkeysaudiofiletyperesolver.h" +#include "optimfrog/taglib_optimfrogfiletyperesolver.h" + +#include <taglib/mpegfile.h> +#include <taglib/oggfile.h> +#include <taglib/oggflacfile.h> +#include <taglib/vorbisfile.h> +#include <taglib/flacfile.h> +#include <taglib/mpcfile.h> + + +class MimeTypeFileTypeResolver : public TagLib::FileRef::FileTypeResolver +{ + TagLib::File *createFile(const char *fileName, + bool readAudioProperties, + TagLib::AudioProperties::ReadStyle audioPropertiesStyle) const; +}; + +TagLib::File *MimeTypeFileTypeResolver::createFile(const char *fileName, + bool readProperties, + TagLib::AudioProperties::ReadStyle propertiesStyle) const +{ + QString fn = QFile::decodeName( fileName ); + int accuracy = 0; + + KMimeType::Ptr mimetype = KMimeType::findByFileContent( fn, &accuracy ); + if( accuracy <= 0 ) + mimetype = KMimeType::findByPath( fn ); + + if( mimetype->is( "audio/aac" ) + || mimetype->is( "audio/mpeg" ) + || mimetype->is( "audio/mpegurl" ) + || mimetype->is( "audio/x-mpegurl" ) + || mimetype->is( "audio/x-mp3" )) + { + return new TagLib::MPEG::File(fileName, readProperties, propertiesStyle); + } + else if( mimetype->is( "audio/mp4" ) || mimetype->is( "video/mp4" ) ) + { + return new TagLib::MP4::File(fileName, readProperties, propertiesStyle); + } + else if( mimetype->is( "audio/x-ms-wma" ) + || mimetype->is( "video/x-ms-asf" ) + || mimetype->is( "video/x-msvideo" ) + || mimetype->is( "video/x-ms-wmv" ) ) + { + return new TagLib::ASF::File(fileName, readProperties, propertiesStyle); + } + else if( mimetype->is( "audio/vnd.rn-realaudio" ) + || mimetype->is( "audio/x-pn-realaudio" ) + || mimetype->is( "audio/x-pn-realaudioplugin" ) + || mimetype->is( "audio/vnd.rn-realvideo" ) ) + { + return new TagLib::RealMedia::File(fileName, readProperties, propertiesStyle); + } + else if( mimetype->is( "audio/vorbis" ) ) + { + return new TagLib::Ogg::Vorbis::File(fileName, readProperties, propertiesStyle); + } + else if( mimetype->is( "audio/x-oggflac" ) ) + { + return new TagLib::Ogg::FLAC::File(fileName, readProperties, propertiesStyle); + } + else if( mimetype->is( "audio/x-flac" ) ) + { + return new TagLib::FLAC::File(fileName, readProperties, propertiesStyle); + } + else if( mimetype->is( "audio/x-musepack" ) ) + { + return new TagLib::MPC::File(fileName, readProperties, propertiesStyle); + } + else if( mimetype->is( "audio/x-musepack" ) + || mimetype->is( "audio/x-ape" ) + || mimetype->is( "application/x-ofr" ) ) + { + return new TagLib::MPC::File(fileName, readProperties, propertiesStyle); + } + +// debug() << "kmimetype filetype guessing failed for" << fileName << endl; + + return 0; +} + +void registerTaglibPlugins() +{ + //TagLib::FileRef::addFileTypeResolver(new MimeTypeFileTypeResolver); + TagLib::FileRef::addFileTypeResolver(new MP4FileTypeResolver); + TagLib::FileRef::addFileTypeResolver(new ASFFileTypeResolver); + TagLib::FileRef::addFileTypeResolver(new RealMediaFileTypeResolver); + TagLib::FileRef::addFileTypeResolver(new AudibleFileTypeResolver); + TagLib::FileRef::addFileTypeResolver(new AACFileTypeResolver); + TagLib::FileRef::addFileTypeResolver(new WavPackFileTypeResolver); + TagLib::FileRef::addFileTypeResolver(new SpeexFileTypeResolver); + TagLib::FileRef::addFileTypeResolver(new TTAFileTypeResolver); + TagLib::FileRef::addFileTypeResolver(new WavFileTypeResolver); + TagLib::FileRef::addFileTypeResolver(new MonkeysAudioFileTypeResolver); + TagLib::FileRef::addFileTypeResolver(new OptimFrogFileTypeResolver); +} diff --git a/src/metadata/tplugins.h b/src/metadata/tplugins.h new file mode 100755 index 0000000..1ef356f --- /dev/null +++ b/src/metadata/tplugins.h @@ -0,0 +1,27 @@ +/*************************************************************************** + copyright : (C) 2005 by Martin Aumueller + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef METADATA_TPLUGIN_H +#define METADATA_TPLUGIN_H + +void registerTaglibPlugins(); + +#endif diff --git a/src/metadata/trueaudio/Makefile.am b/src/metadata/trueaudio/Makefile.am new file mode 100644 index 0000000..01af09f --- /dev/null +++ b/src/metadata/trueaudio/Makefile.am @@ -0,0 +1,16 @@ +SUBDIRS = + +INCLUDES = $(all_includes) $(taglib_includes) +METASOURCES = AUTO +libtagtrueaudio_la_LDFLAGS = $(all_libraries) +noinst_LTLIBRARIES = libtagtrueaudio.la + +libtagtrueaudio_la_SOURCES = \ + ttafile.cpp \ + ttaproperties.cpp \ + taglib_trueaudiofiletyperesolver.cpp + +noinst_HEADERS = ttafile.h \ + ttaproperties.h \ + taglib_trueaudiofiletyperesolver.h + diff --git a/src/metadata/trueaudio/combinedtag.h b/src/metadata/trueaudio/combinedtag.h new file mode 100644 index 0000000..7d530d2 --- /dev/null +++ b/src/metadata/trueaudio/combinedtag.h @@ -0,0 +1,171 @@ +/*************************************************************************** + copyright : (C) 2004 by Allan Sandfeld Jensen + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef DO_NOT_DOCUMENT // Tell Doxygen not to document this header + +#ifndef TAGLIB_COMBINEDTAG_H +#define TAGLIB_COMBINEDTAG_H + +//////////////////////////////////////////////////////////////////////////////// +// Note that this header is not installed. +//////////////////////////////////////////////////////////////////////////////// + +#include <tag.h> + +namespace TagLib { + + /*! + * A union of two TagLib::Tags. + */ + class CombinedTag : public TagLib::Tag + { + public: + CombinedTag(Tag *tag1 = 0, Tag *tag2 = 0) + : TagLib::Tag(), + tag1(tag1), tag2(tag2) {} + + virtual String title() const { + if(tag1 && !tag1->title().isEmpty()) + return tag1->title(); + + if(tag2) + return tag2->title(); + + return String::null; + } + + virtual String artist() const { + if(tag1 && !tag1->artist().isEmpty()) + return tag1->artist(); + + if(tag2) + return tag2->artist(); + + return String::null; + } + + virtual String album() const { + if(tag1 && !tag1->album().isEmpty()) + return tag1->album(); + + if(tag2) + return tag2->album(); + + return String::null; + } + + virtual String comment() const { + if(tag1 && !tag1->comment().isEmpty()) + return tag1->comment(); + + if(tag2) + return tag2->comment(); + + return String::null; + } + + virtual String genre() const { + if(tag1 && !tag1->genre().isEmpty()) + return tag1->genre(); + + if(tag2) + return tag2->genre(); + + return String::null; + } + + virtual uint year() const { + if(tag1 && tag1->year() > 0) + return tag1->year(); + + if(tag2) + return tag2->year(); + + return 0; + } + + virtual uint track() const { + if(tag1 && tag1->track() > 0) + return tag1->track(); + + if(tag2) + return tag2->track(); + + return 0; + } + + virtual void setTitle(const String &s) { + if(tag1) + tag1->setTitle(s); + if(tag2) + tag2->setTitle(s); + } + + virtual void setArtist(const String &s) { + if(tag1) + tag1->setArtist(s); + if(tag2) + tag2->setArtist(s); + } + + virtual void setAlbum(const String &s) { + if(tag1) + tag1->setAlbum(s); + if(tag2) + tag2->setAlbum(s); + } + + virtual void setComment(const String &s) { + if(tag1) + tag1->setComment(s); + if(tag2) + tag2->setComment(s); + } + + virtual void setGenre(const String &s) { + if(tag1) + tag1->setGenre(s); + if(tag2) + tag2->setGenre(s); + } + + virtual void setYear(uint i) { + if(tag1) + tag1->setYear(i); + if(tag2) + tag2->setYear(i); + } + + virtual void setTrack(uint i) { + if(tag1) + tag1->setTrack(i); + if(tag2) + tag2->setTrack(i); + } + + private: + Tag *tag1; + Tag *tag2; + }; +} + +#endif +#endif diff --git a/src/metadata/trueaudio/taglib_trueaudiofiletyperesolver.cpp b/src/metadata/trueaudio/taglib_trueaudiofiletyperesolver.cpp new file mode 100644 index 0000000..e84e501 --- /dev/null +++ b/src/metadata/trueaudio/taglib_trueaudiofiletyperesolver.cpp @@ -0,0 +1,44 @@ +/*************************************************************************** + copyright : (C) 2006 by Martin Aumueller + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "taglib_trueaudiofiletyperesolver.h" +#include "ttafile.h" + +#include <string.h> + +TagLib::File *TTAFileTypeResolver::createFile(const char *fileName, + bool readProperties, + TagLib::AudioProperties::ReadStyle propertiesStyle) const +{ + const char *ext = strrchr(fileName, '.'); + if(ext && !strcasecmp(ext, ".tta")) + { + TagLib::TTA::File *f = new TagLib::TTA::File(fileName, readProperties, propertiesStyle); + if(f->isValid()) + return f; + else + { + delete f; + } + } + + return 0; +} diff --git a/src/metadata/trueaudio/taglib_trueaudiofiletyperesolver.h b/src/metadata/trueaudio/taglib_trueaudiofiletyperesolver.h new file mode 100644 index 0000000..e436e43 --- /dev/null +++ b/src/metadata/trueaudio/taglib_trueaudiofiletyperesolver.h @@ -0,0 +1,36 @@ +/*************************************************************************** + copyright : (C) 2006 by Martin Aumueller + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_TRUEAUDIOFILETYPERESOLVER_H +#define TAGLIB_TRUEAUDIOFILETYPERESOLVER_H + +#include <taglib/tfile.h> +#include <taglib/fileref.h> + + +class TTAFileTypeResolver : public TagLib::FileRef::FileTypeResolver +{ + TagLib::File *createFile(const char *fileName, + bool readAudioProperties, + TagLib::AudioProperties::ReadStyle audioPropertiesStyle) const; +}; + +#endif diff --git a/src/metadata/trueaudio/ttafile.cpp b/src/metadata/trueaudio/ttafile.cpp new file mode 100644 index 0000000..3a02e20 --- /dev/null +++ b/src/metadata/trueaudio/ttafile.cpp @@ -0,0 +1,307 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : [email protected] + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : [email protected] + (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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <tbytevector.h> +#include <tstring.h> +#if 0 +#include <tdebug.h> +#endif + +#include "ttafile.h" +#include "id3v1tag.h" +#include "id3v2tag.h" +#include "id3v2header.h" +#include "combinedtag.h" + +using namespace TagLib; + +class TTA::File::FilePrivate +{ +public: + FilePrivate(const ID3v2::FrameFactory *frameFactory = ID3v2::FrameFactory::instance()) : + ID3v2FrameFactory(frameFactory), + ID3v2Tag(0), + ID3v2Location(-1), + ID3v2OriginalSize(0), + ID3v1Tag(0), + ID3v1Location(-1), + tag(0), + properties(0), + scanned(false), + hasID3v1(false), + hasID3v2(false) {} + + ~FilePrivate() + { + if (tag != ID3v1Tag && tag != ID3v2Tag) delete tag; + delete ID3v1Tag; + delete ID3v2Tag; + delete properties; + } + + const ID3v2::FrameFactory *ID3v2FrameFactory; + ID3v2::Tag *ID3v2Tag; + long ID3v2Location; + uint ID3v2OriginalSize; + + ID3v1::Tag *ID3v1Tag; + long ID3v1Location; + + Tag *tag; + + Properties *properties; + bool scanned; + + // These indicate whether the file *on disk* has these tags, not if + // this data structure does. This is used in computing offsets. + + bool hasID3v1; + bool hasID3v2; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +TTA::File::File(const char *file, bool readProperties, + Properties::ReadStyle propertiesStyle) : TagLib::File(file) +{ + d = new FilePrivate; + if(isOpen()) + read(readProperties, propertiesStyle); +} + +TTA::File::File(const char *file, ID3v2::FrameFactory *frameFactory, + bool readProperties, Properties::ReadStyle propertiesStyle) : + TagLib::File(file) +{ + d = new FilePrivate(frameFactory); + if(isOpen()) + read(readProperties, propertiesStyle); +} + +TTA::File::~File() +{ + delete d; +} + +TagLib::Tag *TTA::File::tag() const +{ + return d->tag; +} + +TTA::Properties *TTA::File::audioProperties() const +{ + return d->properties; +} + +void TTA::File::setID3v2FrameFactory(const ID3v2::FrameFactory *factory) +{ + d->ID3v2FrameFactory = factory; +} + +bool TTA::File::save() +{ + if(readOnly()) { +#if 0 + debug("TTA::File::save() -- File is read only."); +#endif + return false; + } + + // Update ID3v2 tag + + if(d->ID3v2Tag) { + if(!d->hasID3v2) { + d->ID3v2Location = 0; + d->ID3v2OriginalSize = 0; + } + insert(d->ID3v2Tag->render(), d->ID3v2Location, d->ID3v2OriginalSize); + d->hasID3v2 = true; + } + else if(d->hasID3v2) { + removeBlock(d->ID3v2Location, d->ID3v2OriginalSize); + d->hasID3v2 = false; + } + + // Update ID3v1 tag + + if(d->ID3v1Tag) { + if(!d->hasID3v1) { + seek(0, End); + d->ID3v1Location = tell(); + } + else + seek(d->ID3v1Location); + writeBlock(d->ID3v1Tag->render()); + d->hasID3v1 = true; + } + else if(d->hasID3v1) { + removeBlock(d->ID3v1Location, 128); + d->hasID3v1 = false; + } + + return true; +} + +ID3v1::Tag *TTA::File::ID3v1Tag(bool create) +{ + if(!create || d->ID3v1Tag) + return d->ID3v1Tag; + + // no ID3v1 tag exists and we've been asked to create one + + d->ID3v1Tag = new ID3v1::Tag; + + if(d->ID3v2Tag) + d->tag = new CombinedTag(d->ID3v2Tag, d->ID3v1Tag); + else + d->tag = d->ID3v1Tag; + + return d->ID3v1Tag; +} + +ID3v2::Tag *TTA::File::ID3v2Tag(bool create) +{ + if(!create || d->ID3v2Tag) + return d->ID3v2Tag; + + // no ID3v2 tag exists and we've been asked to create one + + d->ID3v2Tag = new ID3v2::Tag; + + if(d->ID3v1Tag) + d->tag = new CombinedTag(d->ID3v2Tag, d->ID3v1Tag); + else + d->tag = d->ID3v2Tag; + + return d->ID3v2Tag; +} + +void TTA::File::remove(int tags) +{ + if(tags & ID3v1) { + delete d->ID3v1Tag; + d->ID3v1Tag = 0; + + if(d->ID3v2Tag) + d->tag = d->ID3v2Tag; + else + d->tag = d->ID3v2Tag = new ID3v2::Tag; + } + + if(tags & ID3v2) { + delete d->ID3v2Tag; + d->ID3v2Tag = 0; + + if(d->ID3v1Tag) + d->tag = d->ID3v1Tag; + else + d->tag = d->ID3v2Tag = new ID3v2::Tag; + } +} + + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void TTA::File::read(bool readProperties, Properties::ReadStyle /* propertiesStyle */) +{ + // Look for an ID3v2 tag + + d->ID3v2Location = findID3v2(); + + if(d->ID3v2Location >= 0) { + + d->ID3v2Tag = new ID3v2::Tag(this, d->ID3v2Location, d->ID3v2FrameFactory); + + d->ID3v2OriginalSize = d->ID3v2Tag->header()->completeTagSize(); + + if(d->ID3v2Tag->header()->tagSize() <= 0) { + delete d->ID3v2Tag; + d->ID3v2Tag = 0; + } + else + d->hasID3v2 = true; + } + + // Look for an ID3v1 tag + + d->ID3v1Location = findID3v1(); + + if(d->ID3v1Location >= 0) { + d->ID3v1Tag = new ID3v1::Tag(this, d->ID3v1Location); + d->hasID3v1 = true; + } + + if(d->hasID3v1 && d->hasID3v2) + d->tag = new CombinedTag(d->ID3v2Tag, d->ID3v1Tag); + else { + if(d->hasID3v1) + d->tag = d->ID3v1Tag; + else { + if(d->hasID3v2) + d->tag = d->ID3v2Tag; + else + d->tag = d->ID3v2Tag = new ID3v2::Tag; + } + } + + // Look for TTA metadata + + if(readProperties) { + seek(d->ID3v2Location + d->ID3v2OriginalSize); + d->properties = new Properties(readBlock(TTA::HeaderSize), + length() - d->ID3v2OriginalSize); + } +} + +long TTA::File::findID3v1() +{ + if(!isValid()) + return -1; + + seek(-128, End); + long p = tell(); + + if(readBlock(3) == ID3v1::Tag::fileIdentifier()) + return p; + + return -1; +} + +long TTA::File::findID3v2() +{ + if(!isValid()) + return -1; + + seek(0); + + if(readBlock(3) == ID3v2::Header::fileIdentifier()) + return 0; + + return -1; +} diff --git a/src/metadata/trueaudio/ttafile.h b/src/metadata/trueaudio/ttafile.h new file mode 100644 index 0000000..2cb0785 --- /dev/null +++ b/src/metadata/trueaudio/ttafile.h @@ -0,0 +1,178 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : [email protected] + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : [email protected] + (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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_TTAFILE_H +#define TAGLIB_TTAFILE_H + +#include "tfile.h" + +#include "ttaproperties.h" + +namespace TagLib { + + class Tag; + + namespace ID3v2 { class Tag; class FrameFactory; } + namespace ID3v1 { class Tag; } + + //! An implementation of TTA metadata + + /*! + * This is implementation of TTA metadata. + * + * This supports ID3v1 and ID3v2 tags as well as reading stream + * properties from the file. + */ + + namespace TTA { + + //! An implementation of TagLib::File with TTA specific methods + + /*! + * This implements and provides an interface for TTA 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 TTA files. + */ + + class 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 ID3v2 tags. + ID3v2 = 0x0002, + //! Matches all tag types. + AllTags = 0xffff + }; + + /*! + * Contructs an MPC 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(const char *file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average); + + /*! + * Contructs an MPC 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. The frames will be created using + * \a frameFactory. + */ + File(const char *file, ID3v2::FrameFactory *frameFactory, + 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 MPC::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Set the ID3v2::FrameFactory to something other than the default. + * + * \see ID3v2FrameFactory + */ + void setID3v2FrameFactory(const ID3v2::FrameFactory *factory); + + /*! + * Saves the file. + */ + virtual bool save(); + + /*! + * Returns a pointer to the ID3v2 tag of the file. + * + * If \a create is false (the default) this will return a null pointer + * if there is no valid ID3v2 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 TTA::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 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 TTA::File and should not be + * deleted by the user. It will be deleted when the file (object) is + * destroyed. + */ + ID3v2::Tag *ID3v2Tag(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 remove(int tags = AllTags); + + private: + File(const File &); + File &operator=(const File &); + + void read(bool readProperties, Properties::ReadStyle propertiesStyle); + void scan(); + long findID3v1(); + long findID3v2(); + + class FilePrivate; + FilePrivate *d; + }; + } +} + +#endif diff --git a/src/metadata/trueaudio/ttaproperties.cpp b/src/metadata/trueaudio/ttaproperties.cpp new file mode 100644 index 0000000..c4f6a29 --- /dev/null +++ b/src/metadata/trueaudio/ttaproperties.cpp @@ -0,0 +1,134 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : [email protected] + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : [email protected] + (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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <tstring.h> +#if 0 +#include <tdebug.h> +#endif +#include <bitset> + +#include "ttaproperties.h" +#include "ttafile.h" + +using namespace TagLib; + +class TTA::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate(const ByteVector &d, long length, ReadStyle s) : + data(d), + streamLength(length), + style(s), + version(0), + length(0), + bitrate(0), + sampleRate(0), + channels(0), + bitsPerSample(0) {} + + ByteVector data; + long streamLength; + ReadStyle style; + int version; + int length; + int bitrate; + int sampleRate; + int channels; + int bitsPerSample; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +TTA::Properties::Properties(const ByteVector &data, long streamLength, ReadStyle style) : AudioProperties(style) +{ + d = new PropertiesPrivate(data, streamLength, style); + read(); +} + +TTA::Properties::~Properties() +{ + delete d; +} + +int TTA::Properties::length() const +{ + return d->length; +} + +int TTA::Properties::bitrate() const +{ + return d->bitrate; +} + +int TTA::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int TTA::Properties::bitsPerSample() const +{ + return d->bitsPerSample; +} + +int TTA::Properties::channels() const +{ + return d->channels; +} + +int TTA::Properties::ttaVersion() const +{ + return d->version; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void TTA::Properties::read() +{ + if(!d->data.startsWith("TTA")) + return; + + int pos = 3; + + d->version = d->data[pos] - '0'; + pos += 1 + 2; + + d->channels = d->data.mid(pos, 2).toShort(false); + pos += 2; + + d->bitsPerSample = d->data.mid(pos, 2).toShort(false); + pos += 2; + + d->sampleRate = d->data.mid(pos, 4).toUInt(false); + pos += 4; + + unsigned long samples = d->data.mid(pos, 4).toUInt(false); + d->length = samples / d->sampleRate; + + d->bitrate = d->length > 0 ? ((d->streamLength * 8L) / d->length) / 1000 : 0; +} diff --git a/src/metadata/trueaudio/ttaproperties.h b/src/metadata/trueaudio/ttaproperties.h new file mode 100644 index 0000000..e694e3d --- /dev/null +++ b/src/metadata/trueaudio/ttaproperties.h @@ -0,0 +1,86 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : [email protected] + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : [email protected] + (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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_TTAPROPERTIES_H +#define TAGLIB_TTAPROPERTIES_H + +#include "audioproperties.h" + +namespace TagLib { + + namespace TTA { + + class File; + + static const uint HeaderSize = 18; + + //! An implementation of audio property reading for TTA + + /*! + * This reads the data from an TTA stream found in the AudioProperties + * API. + */ + + class Properties : public AudioProperties + { + public: + /*! + * Create an instance of TTA::Properties with the data read from the + * ByteVector \a data. + */ + Properties(const ByteVector &data, long streamLength, ReadStyle style = Average); + + /*! + * Destroys this TTA::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 the major version number. + */ + int ttaVersion() const; + + private: + void read(); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } +} + +#endif diff --git a/src/metadata/wav/Makefile.am b/src/metadata/wav/Makefile.am new file mode 100644 index 0000000..add569f --- /dev/null +++ b/src/metadata/wav/Makefile.am @@ -0,0 +1,15 @@ +SUBDIRS = + +INCLUDES = $(all_includes) $(taglib_includes) +METASOURCES = AUTO +libtagwav_la_LDFLAGS = $(all_libraries) +noinst_LTLIBRARIES = libtagwav.la + +libtagwav_la_SOURCES = wavproperties.cpp \ + wavfile.cpp \ + wavfiletyperesolver.cpp + +noinst_HEADERS = wavproperties.h \ + wavfile.h \ + wavfiletyperesolver.h + diff --git a/src/metadata/wav/wavfile.cpp b/src/metadata/wav/wavfile.cpp new file mode 100644 index 0000000..303c5b2 --- /dev/null +++ b/src/metadata/wav/wavfile.cpp @@ -0,0 +1,115 @@ +/*************************************************************************** + copyright : (C) 2006 by Martin Aumueller + email : [email protected] + + copyright : (C) 2005 by Andy Leadbetter + email : [email protected] + (original mp4 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <stdio.h> + +#include "wavfile.h" + +#include <taglib/tfile.h> +#include <taglib/audioproperties.h> +#include <taglib/tag.h> + +namespace TagLib { +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Wav::File::File(const char *file, + bool readProperties, + Properties::ReadStyle propertiesStyle, + FILE *fp) + : TagLib::File(file) + , wavtag( NULL ) + , properties( NULL ) +{ + + // debug ("Wav::File: create new file object."); + //debug ( file ); + + /** + * Create the Wav file. + */ + + if(fp) + wavfile = fp; + else + wavfile = fopen(file, "rb"); + + if( isOpen() ) + { + read(readProperties, propertiesStyle ); + } +} + +Wav::File::~File() +{ + if(wavfile) + fclose(wavfile); + delete properties; +} + +TagLib::Tag *Wav::File::tag() const +{ + return NULL; +} + +TagLib::Tag *Wav::File::getWavTag() const +{ + return NULL; +} + +Wav::Properties *Wav::File::audioProperties() const +{ + return properties; +} + +bool Wav::File::save() +{ + return false; +} + +bool Wav::File::isOpen() +{ + return wavfile != NULL; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void Wav::File::read(bool readProperties, Properties::ReadStyle propertiesStyle) +{ + properties = new Wav::Properties(propertiesStyle); + + if (wavfile != NULL) { + if(readProperties) + { + // Parse bitrate etc. + properties->readWavProperties( wavfile ); + } + } +} + +} diff --git a/src/metadata/wav/wavfile.h b/src/metadata/wav/wavfile.h new file mode 100644 index 0000000..e47fdfb --- /dev/null +++ b/src/metadata/wav/wavfile.h @@ -0,0 +1,92 @@ +/*************************************************************************** + copyright : (C) 2006 by Martin Aumueller + email : [email protected] + + copyright : (C) 2005 by Andy Leadbetter + email : [email protected] + (original mp4 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_WAVFILE_H +#define TAGLIB_WAVFILE_H + +#include <taglib/tfile.h> +#include "wavproperties.h" + +namespace TagLib { + + namespace Wav { + + class Tag; + + class File : public TagLib::File + { + public: + /*! + * Contructs a Wav 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(const char *file, bool readProperties = true, + Properties::ReadStyle propertiesStyle = Properties::Average, + FILE *fp=NULL); + + /*! + * Destroys this instance of the File. + */ + virtual ~File(); + + + virtual TagLib::Tag *tag() const; + + /*! + * Returns the Wav::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Wav::Properties *audioProperties() const; + + /*! + * Save the file. + * This is the same as calling save(AllTags); + * + * \note As of now, saving Wav tags is not supported. + */ + virtual bool save(); + + void read(bool readProperties, Properties::ReadStyle propertiesStyle); + + TagLib::Tag *getWavTag() const; + + bool isWavFile() const; + + protected: + File(const File &); + File &operator=(const File &); + bool isOpen(); + + + TagLib::Tag *wavtag; + Wav::Properties *properties; + + FILE *wavfile; + }; + } +} + +#endif diff --git a/src/metadata/wav/wavfiletyperesolver.cpp b/src/metadata/wav/wavfiletyperesolver.cpp new file mode 100644 index 0000000..830742f --- /dev/null +++ b/src/metadata/wav/wavfiletyperesolver.cpp @@ -0,0 +1,44 @@ +/*************************************************************************** + copyright : (C) 2006 by Martin Aumueller + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <stdio.h> + +#include "wavfiletyperesolver.h" +#include "wavfile.h" + +#include <string.h> + +TagLib::File *WavFileTypeResolver::createFile(const char *fileName, + bool readProperties, + TagLib::AudioProperties::ReadStyle propertiesStyle) const +{ + const char *ext = strrchr(fileName, '.'); + if(ext && !strcasecmp(ext, ".wav")) + { + FILE *fp = fopen(fileName, "rb"); + if(!fp) + return 0; + + return new TagLib::Wav::File(fileName, readProperties, propertiesStyle, fp); + } + + return 0; +} diff --git a/src/metadata/wav/wavfiletyperesolver.h b/src/metadata/wav/wavfiletyperesolver.h new file mode 100644 index 0000000..de818c9 --- /dev/null +++ b/src/metadata/wav/wavfiletyperesolver.h @@ -0,0 +1,36 @@ +/*************************************************************************** + copyright : (C) 2006 by Martin Aumueller + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_WAVFILETYPERESOLVER_H +#define TAGLIB_WAVFILETYPERESOLVER_H + +#include <taglib/tfile.h> +#include <taglib/fileref.h> + + +class WavFileTypeResolver : public TagLib::FileRef::FileTypeResolver +{ + TagLib::File *createFile(const char *fileName, + bool readAudioProperties, + TagLib::AudioProperties::ReadStyle audioPropertiesStyle) const; +}; + +#endif diff --git a/src/metadata/wav/wavproperties.cpp b/src/metadata/wav/wavproperties.cpp new file mode 100644 index 0000000..20ba1ab --- /dev/null +++ b/src/metadata/wav/wavproperties.cpp @@ -0,0 +1,108 @@ +/*************************************************************************** + copyright : (C) 2006 by Martin Aumueller + email : [email protected] + + copyright : (C) 2005 by Andy Leadbetter + email : [email protected] + (original mp4 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <stdio.h> + +#include "wavproperties.h" + +#include <taglib/tstring.h> + +#include "wavfile.h" + +#include <netinet/in.h> // ntohl + +using namespace TagLib; + +struct WavHeader +{ + uint32_t riff_id; + uint32_t riff_size; + uint32_t wave_id; + uint32_t format_id; + uint32_t format_size; + uint16_t format_tag; + uint16_t num_channels; + uint32_t num_samples_per_sec; + uint32_t num_avg_bytes_per_sec; + uint16_t num_block_align; + uint16_t bits_per_sample; + uint32_t data_id; + uint32_t num_data_bytes; +}; + + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +Wav::Properties::Properties(Properties::ReadStyle style) : AudioProperties(style) +{ + m_length = 0; + m_bitrate = 0; + m_sampleRate = 0; + m_channels = 0; +} + +Wav::Properties::~Properties() +{ +} + +int Wav::Properties::length() const +{ + return m_length; +} + +int Wav::Properties::bitrate() const +{ + return m_bitrate; +} + +int Wav::Properties::sampleRate() const +{ + return m_sampleRate; +} + +int Wav::Properties::channels() const +{ + return m_channels; +} + +#define swap16(x) ((((x)&0xff00)>>8) | (((x)&0x00ff)<<8)) +#define swap32(x) ((swap16((x)&0x0000ffff)<<16) | swap16(((x)&0xffff0000)>>16)) + +void Wav::Properties::readWavProperties( FILE *fp ) +{ + fseek(fp, 0, SEEK_SET ); + WavHeader header; + if( fread(&header, sizeof(header), 1, fp) != 1 ) + { + return; + } + + m_channels = ntohs(swap16(header.num_channels)); + m_sampleRate = ntohl(swap32(header.num_samples_per_sec)); + m_bitrate = ntohl(swap32(header.num_avg_bytes_per_sec)) * 8 / 1000; + m_length = ntohl(swap32(header.num_data_bytes))/ntohl(swap32(header.num_avg_bytes_per_sec)); +} diff --git a/src/metadata/wav/wavproperties.h b/src/metadata/wav/wavproperties.h new file mode 100644 index 0000000..a02e734 --- /dev/null +++ b/src/metadata/wav/wavproperties.h @@ -0,0 +1,85 @@ +/*************************************************************************** + copyright : (C) 2006 by Martin Aumueller + email : [email protected] + + copyright : (C) 2005 by Andy Leadbetter + email : [email protected] + (original mp4 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_WAVPROPERTIES_H +#define TAGLIB_WAVPROPERTIES_H + +#include <config.h> + +#include <taglib/audioproperties.h> +#include <taglib/tstring.h> + +namespace TagLib { + + namespace Wav { + + class File; + + /*! + * This reads the data from a Wav stream to support the + * AudioProperties API. + */ + + class Properties : public AudioProperties + { + public: + /*! + * Initialize this structure + */ + Properties(Properties::ReadStyle style); + + /*! + * Destroys this Wav Properties instance. + */ + virtual ~Properties(); + + // Reimplementations. + + virtual int length() const; + virtual int bitrate() const; + virtual int sampleRate() const; + virtual int channels() const; + + void readWavProperties(FILE *file); + + + private: + void readAudioTrackProperties(FILE *file); + friend class Wav::File; + + int m_length; + int m_bitrate; + int m_sampleRate; + int m_channels; + + Properties(const Properties &); + Properties &operator=(const Properties &); + + void read(); + }; + } +} + +#endif diff --git a/src/metadata/wavpack/Makefile.am b/src/metadata/wavpack/Makefile.am new file mode 100644 index 0000000..93a98c6 --- /dev/null +++ b/src/metadata/wavpack/Makefile.am @@ -0,0 +1,16 @@ +SUBDIRS = + +INCLUDES = $(all_includes) $(taglib_includes) +METASOURCES = AUTO +libtagwavpack_la_LDFLAGS = $(all_libraries) +noinst_LTLIBRARIES = libtagwavpack.la + +libtagwavpack_la_SOURCES = \ + wvfile.cpp \ + wvproperties.cpp \ + taglib_wavpackfiletyperesolver.cpp + +noinst_HEADERS = wvfile.h \ + wvproperties.h \ + taglib_wavpackfiletyperesolver.h + diff --git a/src/metadata/wavpack/combinedtag.h b/src/metadata/wavpack/combinedtag.h new file mode 100644 index 0000000..7d530d2 --- /dev/null +++ b/src/metadata/wavpack/combinedtag.h @@ -0,0 +1,171 @@ +/*************************************************************************** + copyright : (C) 2004 by Allan Sandfeld Jensen + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef DO_NOT_DOCUMENT // Tell Doxygen not to document this header + +#ifndef TAGLIB_COMBINEDTAG_H +#define TAGLIB_COMBINEDTAG_H + +//////////////////////////////////////////////////////////////////////////////// +// Note that this header is not installed. +//////////////////////////////////////////////////////////////////////////////// + +#include <tag.h> + +namespace TagLib { + + /*! + * A union of two TagLib::Tags. + */ + class CombinedTag : public TagLib::Tag + { + public: + CombinedTag(Tag *tag1 = 0, Tag *tag2 = 0) + : TagLib::Tag(), + tag1(tag1), tag2(tag2) {} + + virtual String title() const { + if(tag1 && !tag1->title().isEmpty()) + return tag1->title(); + + if(tag2) + return tag2->title(); + + return String::null; + } + + virtual String artist() const { + if(tag1 && !tag1->artist().isEmpty()) + return tag1->artist(); + + if(tag2) + return tag2->artist(); + + return String::null; + } + + virtual String album() const { + if(tag1 && !tag1->album().isEmpty()) + return tag1->album(); + + if(tag2) + return tag2->album(); + + return String::null; + } + + virtual String comment() const { + if(tag1 && !tag1->comment().isEmpty()) + return tag1->comment(); + + if(tag2) + return tag2->comment(); + + return String::null; + } + + virtual String genre() const { + if(tag1 && !tag1->genre().isEmpty()) + return tag1->genre(); + + if(tag2) + return tag2->genre(); + + return String::null; + } + + virtual uint year() const { + if(tag1 && tag1->year() > 0) + return tag1->year(); + + if(tag2) + return tag2->year(); + + return 0; + } + + virtual uint track() const { + if(tag1 && tag1->track() > 0) + return tag1->track(); + + if(tag2) + return tag2->track(); + + return 0; + } + + virtual void setTitle(const String &s) { + if(tag1) + tag1->setTitle(s); + if(tag2) + tag2->setTitle(s); + } + + virtual void setArtist(const String &s) { + if(tag1) + tag1->setArtist(s); + if(tag2) + tag2->setArtist(s); + } + + virtual void setAlbum(const String &s) { + if(tag1) + tag1->setAlbum(s); + if(tag2) + tag2->setAlbum(s); + } + + virtual void setComment(const String &s) { + if(tag1) + tag1->setComment(s); + if(tag2) + tag2->setComment(s); + } + + virtual void setGenre(const String &s) { + if(tag1) + tag1->setGenre(s); + if(tag2) + tag2->setGenre(s); + } + + virtual void setYear(uint i) { + if(tag1) + tag1->setYear(i); + if(tag2) + tag2->setYear(i); + } + + virtual void setTrack(uint i) { + if(tag1) + tag1->setTrack(i); + if(tag2) + tag2->setTrack(i); + } + + private: + Tag *tag1; + Tag *tag2; + }; +} + +#endif +#endif diff --git a/src/metadata/wavpack/taglib_wavpackfiletyperesolver.cpp b/src/metadata/wavpack/taglib_wavpackfiletyperesolver.cpp new file mode 100644 index 0000000..fe289a2 --- /dev/null +++ b/src/metadata/wavpack/taglib_wavpackfiletyperesolver.cpp @@ -0,0 +1,44 @@ +/*************************************************************************** + copyright : (C) 2006 by Martin Aumueller + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include "taglib_wavpackfiletyperesolver.h" +#include "wvfile.h" + +#include <string.h> + +TagLib::File *WavPackFileTypeResolver::createFile(const char *fileName, + bool readProperties, + TagLib::AudioProperties::ReadStyle propertiesStyle) const +{ + const char *ext = strrchr(fileName, '.'); + if(ext && !strcasecmp(ext, ".wv")) + { + TagLib::WavPack::File *f = new TagLib::WavPack::File(fileName, readProperties, propertiesStyle); + if(f->isValid()) + return f; + else + { + delete f; + } + } + + return 0; +} diff --git a/src/metadata/wavpack/taglib_wavpackfiletyperesolver.h b/src/metadata/wavpack/taglib_wavpackfiletyperesolver.h new file mode 100644 index 0000000..b9d4500 --- /dev/null +++ b/src/metadata/wavpack/taglib_wavpackfiletyperesolver.h @@ -0,0 +1,36 @@ +/*************************************************************************** + copyright : (C) 2006 by Martin Aumueller + email : [email protected] + ***************************************************************************/ + +/*************************************************************************** + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_WAVPACKFILETYPERESOLVER_H +#define TAGLIB_WAVPACKFILETYPERESOLVER_H + +#include <taglib/tfile.h> +#include <taglib/fileref.h> + + +class WavPackFileTypeResolver : public TagLib::FileRef::FileTypeResolver +{ + TagLib::File *createFile(const char *fileName, + bool readAudioProperties, + TagLib::AudioProperties::ReadStyle audioPropertiesStyle) const; +}; + +#endif diff --git a/src/metadata/wavpack/wvfile.cpp b/src/metadata/wavpack/wvfile.cpp new file mode 100644 index 0000000..3890bc9 --- /dev/null +++ b/src/metadata/wavpack/wvfile.cpp @@ -0,0 +1,311 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : [email protected] + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : [email protected] + (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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <tbytevector.h> +#include <tstring.h> +#if 0 +#include <tdebug.h> +#endif + +#include "wvfile.h" +#include "id3v1tag.h" +#include "id3v2header.h" +#include "apetag.h" +#include "apefooter.h" +#include "combinedtag.h" + +using namespace TagLib; + +class WavPack::File::FilePrivate +{ +public: + FilePrivate() : + APETag(0), + APELocation(-1), + APESize(0), + ID3v1Tag(0), + ID3v1Location(-1), + tag(0), + properties(0), + scanned(false), + hasAPE(false), + hasID3v1(false) {} + + ~FilePrivate() + { + if (tag != ID3v1Tag && tag != APETag) delete tag; + delete ID3v1Tag; + delete APETag; + delete properties; + } + + APE::Tag *APETag; + long APELocation; + uint APESize; + + ID3v1::Tag *ID3v1Tag; + long ID3v1Location; + + Tag *tag; + + Properties *properties; + bool scanned; + + // 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 +//////////////////////////////////////////////////////////////////////////////// + +WavPack::File::File(const char *file, bool readProperties, + Properties::ReadStyle propertiesStyle) : TagLib::File(file) +{ + d = new FilePrivate; + read(readProperties, propertiesStyle); +} + +WavPack::File::~File() +{ + delete d; +} + +TagLib::Tag *WavPack::File::tag() const +{ + return d->tag; +} + +WavPack::Properties *WavPack::File::audioProperties() const +{ + return d->properties; +} + +bool WavPack::File::save() +{ + if(readOnly()) { +#if 0 + debug("WavPack::File::save() -- File is read only."); +#endif + return false; + } + + // Update ID3v1 tag + + if(d->ID3v1Tag) { + if(d->hasID3v1) { + seek(d->ID3v1Location); + writeBlock(d->ID3v1Tag->render()); + } + else { + seek(0, End); + d->ID3v1Location = tell(); + writeBlock(d->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(d->APETag) { + if(d->hasAPE) + insert(d->APETag->render(), d->APELocation, d->APESize); + else { + if(d->hasID3v1) { + insert(d->APETag->render(), d->ID3v1Location, 0); + d->APESize = d->APETag->footer()->completeTagSize(); + d->hasAPE = true; + d->APELocation = d->ID3v1Location; + d->ID3v1Location += d->APESize; + } + else { + seek(0, End); + d->APELocation = tell(); + writeBlock(d->APETag->render()); + d->APESize = d->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 *WavPack::File::ID3v1Tag(bool create) +{ + if(!create || d->ID3v1Tag) + return d->ID3v1Tag; + + // no ID3v1 tag exists and we've been asked to create one + + d->ID3v1Tag = new ID3v1::Tag; + + if(d->APETag) + d->tag = new CombinedTag(d->APETag, d->ID3v1Tag); + else + d->tag = d->ID3v1Tag; + + return d->ID3v1Tag; +} + +APE::Tag *WavPack::File::APETag(bool create) +{ + if(!create || d->APETag) + return d->APETag; + + // no APE tag exists and we've been asked to create one + + d->APETag = new APE::Tag; + + if(d->ID3v1Tag) + d->tag = new CombinedTag(d->APETag, d->ID3v1Tag); + else + d->tag = d->APETag; + + return d->APETag; +} + +void WavPack::File::remove(int tags) +{ + if(tags & ID3v1) { + delete d->ID3v1Tag; + d->ID3v1Tag = 0; + + if(d->APETag) + d->tag = d->APETag; + else + d->tag = d->APETag = new APE::Tag; + } + + if(tags & APE) { + delete d->APETag; + d->APETag = 0; + + if(d->ID3v1Tag) + d->tag = d->ID3v1Tag; + else + d->tag = d->APETag = new APE::Tag; + } +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +void WavPack::File::read(bool readProperties, Properties::ReadStyle /* propertiesStyle */) +{ + // Look for an ID3v1 tag + + d->ID3v1Location = findID3v1(); + + if(d->ID3v1Location >= 0) { + d->ID3v1Tag = new ID3v1::Tag(this, d->ID3v1Location); + d->hasID3v1 = true; + } + + // Look for an APE tag + + d->APELocation = findAPE(); + + if(d->APELocation >= 0) { + d->APETag = new APE::Tag(this, d->APELocation); + d->APESize = d->APETag->footer()->completeTagSize(); + d->APELocation = d->APELocation + d->APETag->footer()->size() - d->APESize; + d->hasAPE = true; + } + + if(d->hasID3v1 && d->hasAPE) + d->tag = new CombinedTag(d->APETag, d->ID3v1Tag); + else { + if(d->hasID3v1) + d->tag = d->ID3v1Tag; + else { + if(d->hasAPE) + d->tag = d->APETag; + else + d->tag = d->APETag = new APE::Tag; + } + } + + // Look for WavPack audio properties + + if(readProperties) { + seek(0); + d->properties = new Properties(readBlock(WavPack::HeaderSize), + length() - d->APESize); + } +} + +long WavPack::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 WavPack::File::findID3v1() +{ + if(!isValid()) + return -1; + + seek(-128, End); + long p = tell(); + + if(readBlock(3) == ID3v1::Tag::fileIdentifier()) + return p; + + return -1; +} diff --git a/src/metadata/wavpack/wvfile.h b/src/metadata/wavpack/wvfile.h new file mode 100644 index 0000000..6c57f6d --- /dev/null +++ b/src/metadata/wavpack/wvfile.h @@ -0,0 +1,160 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : [email protected] + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : [email protected] + (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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_WVFILE_H +#define TAGLIB_WVFILE_H + +#include "tfile.h" + +#include "wvproperties.h" + +namespace TagLib { + + class Tag; + + namespace ID3v1 { class Tag; } + namespace APE { class Tag; } + + //! An implementation of WavPack metadata + + /*! + * This is implementation of WavPack metadata. + * + * This supports ID3v1 and APE (v1 and v2) style comments as well as reading stream + * properties from the file. + */ + + namespace WavPack { + + //! An implementation of TagLib::File with WavPack specific methods + + /*! + * This implements and provides an interface for 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 WavPack files. + */ + + class 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(const char *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 MPC::Properties for this file. If no audio properties + * were read then this will return a null pointer. + */ + virtual Properties *audioProperties() const; + + /*! + * Saves the file. + */ + 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 remove(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 diff --git a/src/metadata/wavpack/wvproperties.cpp b/src/metadata/wavpack/wvproperties.cpp new file mode 100644 index 0000000..376824d --- /dev/null +++ b/src/metadata/wavpack/wvproperties.cpp @@ -0,0 +1,141 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : [email protected] + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : [email protected] + (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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#include <tstring.h> +#if 0 +#include <tdebug.h> +#endif +#include <bitset> + +#include "wvproperties.h" +#include "wvfile.h" + +using namespace TagLib; + +class WavPack::Properties::PropertiesPrivate +{ +public: + PropertiesPrivate(const ByteVector &d, long length, ReadStyle s) : + data(d), + streamLength(length), + style(s), + length(0), + bitrate(0), + sampleRate(0), + channels(0), + version(0), + bitsPerSample(0) {} + + ByteVector data; + long streamLength; + ReadStyle style; + int length; + int bitrate; + int sampleRate; + int channels; + int version; + int bitsPerSample; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +WavPack::Properties::Properties(const ByteVector &data, long streamLength, ReadStyle style) : AudioProperties(style) +{ + d = new PropertiesPrivate(data, streamLength, style); + read(); +} + +WavPack::Properties::~Properties() +{ + delete d; +} + +int WavPack::Properties::length() const +{ + return d->length; +} + +int WavPack::Properties::bitrate() const +{ + return d->bitrate; +} + +int WavPack::Properties::sampleRate() const +{ + return d->sampleRate; +} + +int WavPack::Properties::channels() const +{ + return d->channels; +} + +int WavPack::Properties::version() const +{ + return d->version; +} + +int WavPack::Properties::bitsPerSample() const +{ + return d->bitsPerSample; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +static const unsigned int sample_rates[] = { 6000, 8000, 9600, 11025, 12000, + 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000, 192000 }; + +#define BYTES_STORED 3 +#define MONO_FLAG 4 + +#define SHIFT_LSB 13 +#define SHIFT_MASK (0x1fL << SHIFT_LSB) + +#define SRATE_LSB 23 +#define SRATE_MASK (0xfL << SRATE_LSB) + +void WavPack::Properties::read() +{ + if(!d->data.startsWith("wvpk")) + return; + + d->version = d->data.mid(8, 2).toShort(false); + + unsigned int flags = d->data.mid(24, 4).toUInt(false); + d->bitsPerSample = ((flags & BYTES_STORED) + 1) * 8 - + ((flags & SHIFT_MASK) >> SHIFT_LSB); + d->sampleRate = sample_rates[(flags & SRATE_MASK) >> SRATE_LSB]; + d->channels = (flags & MONO_FLAG) ? 1 : 2; + + unsigned int samples = d->data.mid(12, 4).toUInt(false); + d->length = d->sampleRate > 0 ? (samples + (d->sampleRate / 2)) / d->sampleRate : 0; + + d->bitrate = d->length > 0 ? ((d->streamLength * 8L) / d->length) / 1000 : 0; +} + diff --git a/src/metadata/wavpack/wvproperties.h b/src/metadata/wavpack/wvproperties.h new file mode 100644 index 0000000..b615adf --- /dev/null +++ b/src/metadata/wavpack/wvproperties.h @@ -0,0 +1,86 @@ +/*************************************************************************** + copyright : (C) 2006 by Lukáš Lalinský + email : [email protected] + + copyright : (C) 2004 by Allan Sandfeld Jensen + email : [email protected] + (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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301 USA * + ***************************************************************************/ + +#ifndef TAGLIB_WVPROPERTIES_H +#define TAGLIB_WVPROPERTIES_H + +#include "audioproperties.h" + +namespace TagLib { + + namespace WavPack { + + class File; + + static const uint HeaderSize = 32; + + //! An implementation of audio property reading for WavPack + + /*! + * This reads the data from an WavPack stream found in the AudioProperties + * API. + */ + + class Properties : public AudioProperties + { + public: + /*! + * Create an instance of WavPack::Properties with the data read from the + * ByteVector \a data. + */ + Properties(const ByteVector &data, long streamLength, ReadStyle style = Average); + + /*! + * Destroys this WavPack::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 WavPack version. + */ + int version() const; + + private: + void read(); + + class PropertiesPrivate; + PropertiesPrivate *d; + }; + } +} + +#endif |