Added taglib from songbird repository for m4a support.
parent
da9e4e28fd
commit
8454204f44
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,6 @@
|
||||||
|
There are a few other people that have done bindings externally that I have
|
||||||
|
been made aware of. I have not personally reviewed these bindings, but I'm
|
||||||
|
listing them here so that those who find them useful are able to find them:
|
||||||
|
|
||||||
|
- Ruby - http://www.hakubi.us/ruby-taglib/
|
||||||
|
- Python - http://namingmuse.berlios.de/
|
0
Frameworks/TagLib/Files/bindings/c/tag_c.cpp → Frameworks/TagLib/taglib/bindings/c/tag_c.cpp
Normal file → Executable file
0
Frameworks/TagLib/Files/bindings/c/tag_c.cpp → Frameworks/TagLib/taglib/bindings/c/tag_c.cpp
Normal file → Executable file
0
Frameworks/TagLib/Files/bindings/c/tag_c.h → Frameworks/TagLib/taglib/bindings/c/tag_c.h
Normal file → Executable file
0
Frameworks/TagLib/Files/bindings/c/tag_c.h → Frameworks/TagLib/taglib/bindings/c/tag_c.h
Normal file → Executable file
|
@ -1,4 +1,4 @@
|
||||||
/* config.h. Generated by configure. */
|
/* config.h. Generated from config.h.in by configure. */
|
||||||
/* config.h.in. Generated from configure.in by autoheader. */
|
/* config.h.in. Generated from configure.in by autoheader. */
|
||||||
|
|
||||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||||
|
@ -28,9 +28,6 @@
|
||||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||||
#define HAVE_SYS_TYPES_H 1
|
#define HAVE_SYS_TYPES_H 1
|
||||||
|
|
||||||
/* C++ compiler supports template repository */
|
|
||||||
#define HAVE_TEMPLATE_REPOSITORY 1
|
|
||||||
|
|
||||||
/* Define to 1 if you have the <unistd.h> header file. */
|
/* Define to 1 if you have the <unistd.h> header file. */
|
||||||
#define HAVE_UNISTD_H 1
|
#define HAVE_UNISTD_H 1
|
||||||
|
|
||||||
|
@ -62,4 +59,4 @@
|
||||||
#define STDC_HEADERS 1
|
#define STDC_HEADERS 1
|
||||||
|
|
||||||
/* Version number of package */
|
/* Version number of package */
|
||||||
#define VERSION "0.1"
|
#define VERSION "1.4"
|
0
Frameworks/TagLib/Files/taglib/ape/ape-tag-format.txt → Frameworks/TagLib/taglib/taglib/ape/ape-tag-format.txt
Normal file → Executable file
0
Frameworks/TagLib/Files/taglib/ape/ape-tag-format.txt → Frameworks/TagLib/taglib/taglib/ape/ape-tag-format.txt
Normal file → Executable file
0
Frameworks/TagLib/Files/taglib/ape/apefooter.cpp → Frameworks/TagLib/taglib/taglib/ape/apefooter.cpp
Normal file → Executable file
0
Frameworks/TagLib/Files/taglib/ape/apefooter.cpp → Frameworks/TagLib/taglib/taglib/ape/apefooter.cpp
Normal file → Executable file
0
Frameworks/TagLib/Files/taglib/ape/apefooter.h → Frameworks/TagLib/taglib/taglib/ape/apefooter.h
Normal file → Executable file
0
Frameworks/TagLib/Files/taglib/ape/apefooter.h → Frameworks/TagLib/taglib/taglib/ape/apefooter.h
Normal file → Executable file
0
Frameworks/TagLib/Files/taglib/ape/apeitem.cpp → Frameworks/TagLib/taglib/taglib/ape/apeitem.cpp
Normal file → Executable file
0
Frameworks/TagLib/Files/taglib/ape/apeitem.cpp → Frameworks/TagLib/taglib/taglib/ape/apeitem.cpp
Normal file → Executable file
0
Frameworks/TagLib/Files/taglib/ape/apeitem.h → Frameworks/TagLib/taglib/taglib/ape/apeitem.h
Normal file → Executable file
0
Frameworks/TagLib/Files/taglib/ape/apeitem.h → Frameworks/TagLib/taglib/taglib/ape/apeitem.h
Normal file → Executable file
8
Frameworks/TagLib/Files/taglib/ape/apetag.cpp → Frameworks/TagLib/taglib/taglib/ape/apetag.cpp
Normal file → Executable file
8
Frameworks/TagLib/Files/taglib/ape/apetag.cpp → Frameworks/TagLib/taglib/taglib/ape/apetag.cpp
Normal file → Executable file
|
@ -19,6 +19,14 @@
|
||||||
* USA *
|
* USA *
|
||||||
***************************************************************************/
|
***************************************************************************/
|
||||||
|
|
||||||
|
#ifdef __SUNPRO_CC
|
||||||
|
// Sun Studio finds multiple specializations of Map because
|
||||||
|
// it considers specializations with and without class types
|
||||||
|
// to be different; this define forces Map to use only the
|
||||||
|
// specialization with the class keyword.
|
||||||
|
#define WANT_CLASS_INSTANTIATION_OF_MAP (1)
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <tdebug.h>
|
#include <tdebug.h>
|
||||||
#include <tfile.h>
|
#include <tfile.h>
|
||||||
#include <tstring.h>
|
#include <tstring.h>
|
0
Frameworks/TagLib/Files/taglib/ape/apetag.h → Frameworks/TagLib/taglib/taglib/ape/apetag.h
Normal file → Executable file
0
Frameworks/TagLib/Files/taglib/ape/apetag.h → Frameworks/TagLib/taglib/taglib/ape/apetag.h
Normal file → Executable file
0
Frameworks/TagLib/Files/taglib/audioproperties.cpp → Frameworks/TagLib/taglib/taglib/audioproperties.cpp
Normal file → Executable file
0
Frameworks/TagLib/Files/taglib/audioproperties.cpp → Frameworks/TagLib/taglib/taglib/audioproperties.cpp
Normal file → Executable file
4
Frameworks/TagLib/Files/taglib/audioproperties.h → Frameworks/TagLib/taglib/taglib/audioproperties.h
Normal file → Executable file
4
Frameworks/TagLib/Files/taglib/audioproperties.h → Frameworks/TagLib/taglib/taglib/audioproperties.h
Normal file → Executable file
|
@ -22,6 +22,8 @@
|
||||||
#ifndef TAGLIB_AUDIOPROPERTIES_H
|
#ifndef TAGLIB_AUDIOPROPERTIES_H
|
||||||
#define TAGLIB_AUDIOPROPERTIES_H
|
#define TAGLIB_AUDIOPROPERTIES_H
|
||||||
|
|
||||||
|
#include "taglib_export.h"
|
||||||
|
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
//! A simple, abstract interface to common audio properties
|
//! A simple, abstract interface to common audio properties
|
||||||
|
@ -33,7 +35,7 @@ namespace TagLib {
|
||||||
* interface that is sufficient for most applications.
|
* interface that is sufficient for most applications.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class AudioProperties
|
class TAGLIB_EXPORT AudioProperties
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
7
Frameworks/TagLib/Files/taglib/fileref.cpp → Frameworks/TagLib/taglib/taglib/fileref.cpp
Normal file → Executable file
7
Frameworks/TagLib/Files/taglib/fileref.cpp → Frameworks/TagLib/taglib/taglib/fileref.cpp
Normal file → Executable file
|
@ -27,6 +27,7 @@
|
||||||
#include "vorbisfile.h"
|
#include "vorbisfile.h"
|
||||||
#include "flacfile.h"
|
#include "flacfile.h"
|
||||||
#include "mpcfile.h"
|
#include "mpcfile.h"
|
||||||
|
#include "mp4file.h"
|
||||||
|
|
||||||
using namespace TagLib;
|
using namespace TagLib;
|
||||||
|
|
||||||
|
@ -109,6 +110,8 @@ StringList FileRef::defaultFileExtensions()
|
||||||
l.append("flac");
|
l.append("flac");
|
||||||
l.append("mp3");
|
l.append("mp3");
|
||||||
l.append("mpc");
|
l.append("mpc");
|
||||||
|
l.append("m4a");
|
||||||
|
//l.append("m4p");
|
||||||
|
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
@ -171,6 +174,10 @@ File *FileRef::create(const char *fileName, bool readAudioProperties,
|
||||||
return new FLAC::File(fileName, readAudioProperties, audioPropertiesStyle);
|
return new FLAC::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
if(s.substr(s.size() - 4, 4).upper() == ".MPC")
|
if(s.substr(s.size() - 4, 4).upper() == ".MPC")
|
||||||
return new MPC::File(fileName, readAudioProperties, audioPropertiesStyle);
|
return new MPC::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
|
if(s.substr(s.size() - 4, 4).upper() == ".M4A")
|
||||||
|
return new MP4::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
|
//if(s.substr(s.size() - 4, 4).upper() == ".M4P")
|
||||||
|
//return new MP4::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
3
Frameworks/TagLib/Files/taglib/fileref.h → Frameworks/TagLib/taglib/taglib/fileref.h
Normal file → Executable file
3
Frameworks/TagLib/Files/taglib/fileref.h → Frameworks/TagLib/taglib/taglib/fileref.h
Normal file → Executable file
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#include <tstringlist.h>
|
#include <tstringlist.h>
|
||||||
|
|
||||||
|
#include "taglib_export.h"
|
||||||
#include "audioproperties.h"
|
#include "audioproperties.h"
|
||||||
|
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
@ -52,7 +53,7 @@ namespace TagLib {
|
||||||
* \see addFileTypeResolver()
|
* \see addFileTypeResolver()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class FileRef
|
class TAGLIB_EXPORT FileRef
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
100
Frameworks/TagLib/Files/taglib/flac/flacfile.cpp → Frameworks/TagLib/taglib/taglib/flac/flacfile.cpp
Normal file → Executable file
100
Frameworks/TagLib/Files/taglib/flac/flacfile.cpp → Frameworks/TagLib/taglib/taglib/flac/flacfile.cpp
Normal file → Executable file
|
@ -98,6 +98,13 @@ public:
|
||||||
// public members
|
// public members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
FLAC::File::File(ID3v2::FrameFactory *frameFactory) : TagLib::File()
|
||||||
|
{
|
||||||
|
d = new FilePrivate;
|
||||||
|
if (frameFactory)
|
||||||
|
d->ID3v2FrameFactory = frameFactory;
|
||||||
|
}
|
||||||
|
|
||||||
FLAC::File::File(const char *file, bool readProperties,
|
FLAC::File::File(const char *file, bool readProperties,
|
||||||
Properties::ReadStyle propertiesStyle) :
|
Properties::ReadStyle propertiesStyle) :
|
||||||
TagLib::File(file)
|
TagLib::File(file)
|
||||||
|
@ -130,6 +137,52 @@ FLAC::Properties *FLAC::File::audioProperties() const
|
||||||
return d->properties;
|
return d->properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FLAC::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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for FLAC metadata, including vorbis comments
|
||||||
|
|
||||||
|
scan();
|
||||||
|
|
||||||
|
if (!isValid()) return;
|
||||||
|
|
||||||
|
if(d->hasXiphComment)
|
||||||
|
d->comment = new Ogg::XiphComment(xiphCommentData());
|
||||||
|
|
||||||
|
if(d->hasXiphComment || d->hasID3v2 || d->hasID3v1)
|
||||||
|
d->tag = new FLAC::Tag(d->comment, d->ID3v2Tag, d->ID3v1Tag);
|
||||||
|
else
|
||||||
|
d->tag = new FLAC::Tag(new Ogg::XiphComment);
|
||||||
|
|
||||||
|
if(readProperties)
|
||||||
|
d->properties = new Properties(streamInfoData(), streamLength(), propertiesStyle);
|
||||||
|
}
|
||||||
|
|
||||||
bool FLAC::File::save()
|
bool FLAC::File::save()
|
||||||
{
|
{
|
||||||
|
@ -275,53 +328,6 @@ void FLAC::File::setID3v2FrameFactory(const ID3v2::FrameFactory *factory)
|
||||||
// private members
|
// private members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void FLAC::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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look for FLAC metadata, including vorbis comments
|
|
||||||
|
|
||||||
scan();
|
|
||||||
|
|
||||||
if (!isValid()) return;
|
|
||||||
|
|
||||||
if(d->hasXiphComment)
|
|
||||||
d->comment = new Ogg::XiphComment(xiphCommentData());
|
|
||||||
|
|
||||||
if(d->hasXiphComment || d->hasID3v2 || d->hasID3v1)
|
|
||||||
d->tag = new FLAC::Tag(d->comment, d->ID3v2Tag, d->ID3v1Tag);
|
|
||||||
else
|
|
||||||
d->tag = new FLAC::Tag(new Ogg::XiphComment);
|
|
||||||
|
|
||||||
if(readProperties)
|
|
||||||
d->properties = new Properties(streamInfoData(), streamLength(), propertiesStyle);
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteVector FLAC::File::streamInfoData()
|
ByteVector FLAC::File::streamInfoData()
|
||||||
{
|
{
|
||||||
if (isValid())
|
if (isValid())
|
18
Frameworks/TagLib/Files/taglib/flac/flacfile.h → Frameworks/TagLib/taglib/taglib/flac/flacfile.h
Normal file → Executable file
18
Frameworks/TagLib/Files/taglib/flac/flacfile.h → Frameworks/TagLib/taglib/taglib/flac/flacfile.h
Normal file → Executable file
|
@ -22,6 +22,7 @@
|
||||||
#ifndef TAGLIB_FLACFILE_H
|
#ifndef TAGLIB_FLACFILE_H
|
||||||
#define TAGLIB_FLACFILE_H
|
#define TAGLIB_FLACFILE_H
|
||||||
|
|
||||||
|
#include "taglib_export.h"
|
||||||
#include "tfile.h"
|
#include "tfile.h"
|
||||||
|
|
||||||
#include "flacproperties.h"
|
#include "flacproperties.h"
|
||||||
|
@ -56,9 +57,15 @@ namespace TagLib {
|
||||||
* information specific to FLAC files.
|
* information specific to FLAC files.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class File : public TagLib::File
|
class TAGLIB_EXPORT File : public TagLib::File
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
/*!
|
||||||
|
* Contructs a FLAC file object without reading a file. Allows object
|
||||||
|
* fields to be set up before reading.
|
||||||
|
*/
|
||||||
|
File(ID3v2::FrameFactory *frameFactory = NULL);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Contructs a FLAC file from \a file. If \a readProperties is true the
|
* Contructs a FLAC file from \a file. If \a readProperties is true the
|
||||||
* file's audio properties will also be read using \a propertiesStyle. If
|
* file's audio properties will also be read using \a propertiesStyle. If
|
||||||
|
@ -104,6 +111,14 @@ namespace TagLib {
|
||||||
*/
|
*/
|
||||||
virtual Properties *audioProperties() const;
|
virtual Properties *audioProperties() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Reads from FLAC file. If \a readProperties is true the file's audio
|
||||||
|
* properties will also be read using \a propertiesStyle. If false,
|
||||||
|
* \a propertiesStyle is ignored.
|
||||||
|
*/
|
||||||
|
void read(bool readProperties = true,
|
||||||
|
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Save the file. This will primarily save the XiphComment, but
|
* Save the file. This will primarily save the XiphComment, but
|
||||||
* will also keep any old ID3-tags up to date. If the file
|
* will also keep any old ID3-tags up to date. If the file
|
||||||
|
@ -181,7 +196,6 @@ namespace TagLib {
|
||||||
File(const File &);
|
File(const File &);
|
||||||
File &operator=(const File &);
|
File &operator=(const File &);
|
||||||
|
|
||||||
void read(bool readProperties, Properties::ReadStyle propertiesStyle);
|
|
||||||
void scan();
|
void scan();
|
||||||
long findID3v2();
|
long findID3v2();
|
||||||
long findID3v1();
|
long findID3v1();
|
0
Frameworks/TagLib/Files/taglib/flac/flacproperties.cpp → Frameworks/TagLib/taglib/taglib/flac/flacproperties.cpp
Normal file → Executable file
0
Frameworks/TagLib/Files/taglib/flac/flacproperties.cpp → Frameworks/TagLib/taglib/taglib/flac/flacproperties.cpp
Normal file → Executable file
0
Frameworks/TagLib/Files/taglib/flac/flacproperties.h → Frameworks/TagLib/taglib/taglib/flac/flacproperties.h
Normal file → Executable file
0
Frameworks/TagLib/Files/taglib/flac/flacproperties.h → Frameworks/TagLib/taglib/taglib/flac/flacproperties.h
Normal file → Executable file
0
Frameworks/TagLib/Files/taglib/flac/flactag.h → Frameworks/TagLib/taglib/taglib/flac/flactag.h
Normal file → Executable file
0
Frameworks/TagLib/Files/taglib/flac/flactag.h → Frameworks/TagLib/taglib/taglib/flac/flactag.h
Normal file → Executable file
|
@ -0,0 +1,129 @@
|
||||||
|
#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 = static_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 );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
#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
|
|
@ -0,0 +1,68 @@
|
||||||
|
#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 debuging...
|
||||||
|
TagLib::String dataString( d->dataBox->data() );
|
||||||
|
std::cout << "Content of album box: " << dataString << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
#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
|
|
@ -0,0 +1,68 @@
|
||||||
|
#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 debuging...
|
||||||
|
TagLib::String dataString( d->dataBox->data() );
|
||||||
|
std::cout << "Content of artist box: " << dataString << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
#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
|
|
@ -0,0 +1,68 @@
|
||||||
|
#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 debuging...
|
||||||
|
TagLib::String dataString( d->dataBox->data() );
|
||||||
|
std::cout << "Content of title box: " << dataString << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
#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
|
|
@ -0,0 +1,68 @@
|
||||||
|
#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 debuging...
|
||||||
|
TagLib::String dataString( d->dataBox->data() );
|
||||||
|
std::cout << "Content of album box: " << dataString << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
#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
|
|
@ -0,0 +1,42 @@
|
||||||
|
#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 );
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
#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
|
|
@ -0,0 +1,68 @@
|
||||||
|
#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 debuging...
|
||||||
|
TagLib::String dataString( d->dataBox->data() );
|
||||||
|
std::cout << "Content of day box: " << dataString.substr(0,4) << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
#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
|
|
@ -0,0 +1,72 @@
|
||||||
|
#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 debuging...
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
#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
|
|
@ -0,0 +1,68 @@
|
||||||
|
#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 debuging...
|
||||||
|
TagLib::String dataString( d->dataBox->data() );
|
||||||
|
std::cout << "Content of genre box: " << dataString << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
#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
|
|
@ -0,0 +1,68 @@
|
||||||
|
#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 debuging...
|
||||||
|
TagLib::String dataString( d->dataBox->data() );
|
||||||
|
std::cout << "Content of title box: " << dataString << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
#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
|
|
@ -0,0 +1,68 @@
|
||||||
|
#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 debuging...
|
||||||
|
TagLib::String dataString( d->dataBox->data() );
|
||||||
|
std::cout << "Content of title box: " << dataString << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
#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
|
|
@ -0,0 +1,72 @@
|
||||||
|
#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 debuging...
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
#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
|
|
@ -0,0 +1,72 @@
|
||||||
|
#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 debuging...
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
#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
|
|
@ -0,0 +1,68 @@
|
||||||
|
#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 debuging...
|
||||||
|
TagLib::String dataString( d->dataBox->data() );
|
||||||
|
std::cout << "Content of title box: " << dataString << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
#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
|
|
@ -0,0 +1,54 @@
|
||||||
|
#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();
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
#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 lenght 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
|
|
@ -0,0 +1,124 @@
|
||||||
|
#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 = static_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;
|
||||||
|
|
||||||
|
mp4file->readSizeAndType( esds_size, fourcc );
|
||||||
|
|
||||||
|
// 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 );
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
#ifndef MP4AUDIOSAMPLEENTRY_H
|
||||||
|
#define MP4AUDIOSAMPLEENTRY_H
|
||||||
|
|
||||||
|
#include "mp4sampleentry.h"
|
||||||
|
#include "mp4fourcc.h"
|
||||||
|
|
||||||
|
namespace TagLib
|
||||||
|
{
|
||||||
|
namespace MP4
|
||||||
|
{
|
||||||
|
class Mp4AudioSampleEntry: public Mp4SampleEntry
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Mp4AudioSampleEntry( 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
|
|
@ -0,0 +1,390 @@
|
||||||
|
#include <tbytevector.h>
|
||||||
|
#include <tstring.h>
|
||||||
|
#include <tdebug.h>
|
||||||
|
#include "tlist.h"
|
||||||
|
|
||||||
|
#include "id3v1genres.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 successfull 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() : TagLib::File()
|
||||||
|
{
|
||||||
|
// create member container
|
||||||
|
d = new MP4::File::FilePrivate();
|
||||||
|
d->isValid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
MP4::File::File(const char *file, bool , AudioProperties::ReadStyle )
|
||||||
|
:TagLib::File( file )
|
||||||
|
{
|
||||||
|
// create member container
|
||||||
|
d = new MP4::File::FilePrivate();
|
||||||
|
|
||||||
|
read();
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MP4::File::read( bool, TagLib::AudioProperties::ReadStyle )
|
||||||
|
{
|
||||||
|
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 );
|
||||||
|
}
|
||||||
|
|
||||||
|
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]);
|
||||||
|
if (size == 0)
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This function has been updated based on information at */
|
||||||
|
/* "http://atomicparsley.sourceforge.net/mpeg-4files.html". */
|
||||||
|
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 == "") )
|
||||||
|
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 == "") )
|
||||||
|
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 == "") )
|
||||||
|
mp4tag.setAlbum( datastring );
|
||||||
|
}
|
||||||
|
|
||||||
|
databox = proxy.genreData();
|
||||||
|
if( databox != 0 )
|
||||||
|
{
|
||||||
|
if (databox->flags() == 0)
|
||||||
|
{
|
||||||
|
// convert data to uint
|
||||||
|
TagLib::ByteVector datavec = databox->data();
|
||||||
|
int genreVal = static_cast<int>( datavec[1] );
|
||||||
|
if (genreVal > 0)
|
||||||
|
{
|
||||||
|
TagLib::String datastring = ID3v1::genre( genreVal - 1 );
|
||||||
|
// check if string was set
|
||||||
|
if( !(datastring == "") )
|
||||||
|
mp4tag.setGenre( datastring );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// convert data to string
|
||||||
|
TagLib::String datastring( databox->data(), String::UTF8 );
|
||||||
|
// check if string was set
|
||||||
|
if( !(datastring == "") )
|
||||||
|
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 == "") )
|
||||||
|
mp4tag.setYear( datastring.toInt() );
|
||||||
|
}
|
||||||
|
|
||||||
|
databox = proxy.trknData();
|
||||||
|
if( databox != 0 )
|
||||||
|
{
|
||||||
|
// convert data to uint
|
||||||
|
TagLib::ByteVector datavec = databox->data();
|
||||||
|
if( datavec.size() >= 6 )
|
||||||
|
{
|
||||||
|
TagLib::uint notracks = static_cast<TagLib::uint>( datavec[5] );
|
||||||
|
mp4tag.setNumTracks( notracks );
|
||||||
|
}
|
||||||
|
if( datavec.size() >= 4 )
|
||||||
|
{
|
||||||
|
TagLib::uint trackno = static_cast<TagLib::uint>( 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 == "") )
|
||||||
|
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 == "") )
|
||||||
|
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 == "") )
|
||||||
|
mp4tag.setComposer( datastring );
|
||||||
|
}
|
||||||
|
|
||||||
|
databox = proxy.diskData();
|
||||||
|
if( databox != 0 )
|
||||||
|
{
|
||||||
|
// convert data to uint
|
||||||
|
TagLib::ByteVector datavec = databox->data();
|
||||||
|
if( datavec.size() >= 6 )
|
||||||
|
{
|
||||||
|
TagLib::uint nodiscs = static_cast<TagLib::uint>( datavec[5] );
|
||||||
|
mp4tag.setNumDisks( nodiscs );
|
||||||
|
}
|
||||||
|
if( datavec.size() >= 4 )
|
||||||
|
{
|
||||||
|
TagLib::uint discno = static_cast<TagLib::uint>( 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() );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,162 @@
|
||||||
|
/***************************************************************************
|
||||||
|
copyright : (C) 2002, 2003 by Jochen Issing
|
||||||
|
email : jochen.issing@isign-softart.de
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
/***************************************************************************
|
||||||
|
* This library is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU Lesser General Public License version *
|
||||||
|
* 2.1 as published by the Free Software Foundation. *
|
||||||
|
* *
|
||||||
|
* This library is distributed in the hope that it will be useful, but *
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||||
|
* Lesser General Public License for more details. *
|
||||||
|
* *
|
||||||
|
* You should have received a copy of the GNU Lesser General Public *
|
||||||
|
* License along with this library; if not, write to the Free Software *
|
||||||
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||||
|
* USA *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
|
#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 object without reading a file. Allows object
|
||||||
|
* fields to be set up before reading.
|
||||||
|
*/
|
||||||
|
File();
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* 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,
|
||||||
|
TagLib::AudioProperties::ReadStyle propertiesStyle = TagLib::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;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Reads from mp4 itunes file. If \a readProperties is true the file's
|
||||||
|
* audio properties will also be read using \a propertiesStyle. If false,
|
||||||
|
* \a propertiesStyle is ignored.
|
||||||
|
*/
|
||||||
|
void read(bool readProperties = true,
|
||||||
|
TagLib::AudioProperties::ReadStyle propertiesStyle = TagLib::AudioProperties::Average);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* 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
|
|
@ -0,0 +1,63 @@
|
||||||
|
#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;
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
#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
|
|
@ -0,0 +1,54 @@
|
||||||
|
#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 );
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
#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
|
|
@ -0,0 +1,76 @@
|
||||||
|
#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
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
#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
|
|
@ -0,0 +1,55 @@
|
||||||
|
#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;
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
#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
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
#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
|
||||||
|
|
|
@ -0,0 +1,202 @@
|
||||||
|
#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::uint numTracks;
|
||||||
|
TagLib::String comment;
|
||||||
|
TagLib::String grouping;
|
||||||
|
TagLib::String composer;
|
||||||
|
TagLib::uint disk;
|
||||||
|
TagLib::uint numDisks;
|
||||||
|
TagLib::uint bpm;
|
||||||
|
bool isEmpty;
|
||||||
|
TagLib::ByteVector cover;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
MP4::Tag::Tag( )
|
||||||
|
{
|
||||||
|
d = new TagPrivate();
|
||||||
|
d->year = 0;
|
||||||
|
d->track = 0;
|
||||||
|
d->numTracks = 0;
|
||||||
|
d->disk = 0;
|
||||||
|
d->numTracks = 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
TagLib::uint MP4::Tag::numTracks() const
|
||||||
|
{
|
||||||
|
return d->numTracks;
|
||||||
|
}
|
||||||
|
|
||||||
|
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::numDisks() const
|
||||||
|
{
|
||||||
|
return d->numDisks;
|
||||||
|
}
|
||||||
|
|
||||||
|
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(TagLib::uint i)
|
||||||
|
{
|
||||||
|
d->year = i;
|
||||||
|
d->isEmpty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MP4::Tag::setTrack(TagLib::uint i)
|
||||||
|
{
|
||||||
|
d->track = i;
|
||||||
|
d->isEmpty = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MP4::Tag::setNumTracks(TagLib::uint i)
|
||||||
|
{
|
||||||
|
d->numTracks = 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::setNumDisks(const TagLib::uint i)
|
||||||
|
{
|
||||||
|
d->numDisks = 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;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
#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(uint i);
|
||||||
|
virtual void setTrack(uint i);
|
||||||
|
|
||||||
|
// MP4 specific fields
|
||||||
|
|
||||||
|
String grouping() const;
|
||||||
|
String composer() const;
|
||||||
|
uint numTracks() const;
|
||||||
|
uint disk() const;
|
||||||
|
uint numDisks() const;
|
||||||
|
uint bpm() const;
|
||||||
|
ByteVector cover() const;
|
||||||
|
|
||||||
|
void setGrouping(const String &s);
|
||||||
|
void setComposer(const String &s);
|
||||||
|
void setNumTracks(const uint i);
|
||||||
|
void setDisk(const uint i);
|
||||||
|
void setNumDisks(const uint i);
|
||||||
|
void setBpm(const uint i);
|
||||||
|
void setCover( const ByteVector& cover );
|
||||||
|
|
||||||
|
virtual bool isEmpty() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Tag(const Tag &);
|
||||||
|
Tag &operator=(const Tag &);
|
||||||
|
|
||||||
|
class TagPrivate;
|
||||||
|
TagPrivate *d;
|
||||||
|
};
|
||||||
|
} // namespace MP4
|
||||||
|
|
||||||
|
} // namespace TagLib
|
||||||
|
|
||||||
|
#endif // MP4ITUNESTAG_H
|
|
@ -0,0 +1,90 @@
|
||||||
|
#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 = static_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 = static_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;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
#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
|
|
@ -0,0 +1,65 @@
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
#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
|
|
@ -0,0 +1,83 @@
|
||||||
|
#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 = static_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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
#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
|
|
@ -0,0 +1,65 @@
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
#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
|
|
@ -0,0 +1,119 @@
|
||||||
|
#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 );
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
#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
|
|
@ -0,0 +1,68 @@
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
#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
|
|
@ -0,0 +1,38 @@
|
||||||
|
#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 = static_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();
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
#ifndef MP4SAMPLEENTRY_H
|
||||||
|
#define MP4SAMPLEENTRY_H
|
||||||
|
|
||||||
|
#include "mp4isobox.h"
|
||||||
|
#include "mp4fourcc.h"
|
||||||
|
|
||||||
|
namespace TagLib
|
||||||
|
{
|
||||||
|
namespace MP4
|
||||||
|
{
|
||||||
|
class Mp4SampleEntry: public Mp4IsoBox
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Mp4SampleEntry( 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
|
|
@ -0,0 +1,29 @@
|
||||||
|
#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 );
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
#ifndef MP4SKIPBOX_H
|
||||||
|
#define MP4SKIPBOX_H
|
||||||
|
|
||||||
|
#include "mp4isobox.h"
|
||||||
|
#include "mp4fourcc.h"
|
||||||
|
|
||||||
|
namespace TagLib
|
||||||
|
{
|
||||||
|
namespace MP4
|
||||||
|
{
|
||||||
|
class Mp4SkipBox: public Mp4IsoBox
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Mp4SkipBox( 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
|
|
@ -0,0 +1,84 @@
|
||||||
|
#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 = static_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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
#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
|
|
@ -0,0 +1,70 @@
|
||||||
|
#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 = static_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 );
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
#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
|
|
@ -0,0 +1,147 @@
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
#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
|
|
@ -0,0 +1,65 @@
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
#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
|
|
@ -0,0 +1,74 @@
|
||||||
|
#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
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
#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
|
0
Frameworks/TagLib/Files/taglib/mpc/combinedtag.h → Frameworks/TagLib/taglib/taglib/mpc/combinedtag.h
Normal file → Executable file
0
Frameworks/TagLib/Files/taglib/mpc/combinedtag.h → Frameworks/TagLib/taglib/taglib/mpc/combinedtag.h
Normal file → Executable file
127
Frameworks/TagLib/Files/taglib/mpc/mpcfile.cpp → Frameworks/TagLib/taglib/taglib/mpc/mpcfile.cpp
Normal file → Executable file
127
Frameworks/TagLib/Files/taglib/mpc/mpcfile.cpp → Frameworks/TagLib/taglib/taglib/mpc/mpcfile.cpp
Normal file → Executable file
|
@ -89,6 +89,11 @@ public:
|
||||||
// public members
|
// public members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
MPC::File::File() : TagLib::File()
|
||||||
|
{
|
||||||
|
d = new FilePrivate;
|
||||||
|
}
|
||||||
|
|
||||||
MPC::File::File(const char *file, bool readProperties,
|
MPC::File::File(const char *file, bool readProperties,
|
||||||
Properties::ReadStyle propertiesStyle) : TagLib::File(file)
|
Properties::ReadStyle propertiesStyle) : TagLib::File(file)
|
||||||
{
|
{
|
||||||
|
@ -111,6 +116,67 @@ MPC::Properties *MPC::File::audioProperties() const
|
||||||
return d->properties;
|
return d->properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MPC::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
|
||||||
|
|
||||||
|
findAPE();
|
||||||
|
|
||||||
|
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 and skip an ID3v2 tag
|
||||||
|
|
||||||
|
d->ID3v2Location = findID3v2();
|
||||||
|
|
||||||
|
if(d->ID3v2Location >= 0) {
|
||||||
|
seek(d->ID3v2Location);
|
||||||
|
d->ID3v2Header = new ID3v2::Header(readBlock(ID3v2::Header::size()));
|
||||||
|
d->ID3v2Size = d->ID3v2Header->completeTagSize();
|
||||||
|
d->hasID3v2 = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(d->hasID3v2)
|
||||||
|
seek(d->ID3v2Location + d->ID3v2Size);
|
||||||
|
else
|
||||||
|
seek(0);
|
||||||
|
|
||||||
|
// Look for MPC metadata
|
||||||
|
|
||||||
|
if(readProperties) {
|
||||||
|
d->properties = new Properties(readBlock(MPC::HeaderSize),
|
||||||
|
length() - d->ID3v2Size - d->APESize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool MPC::File::save()
|
bool MPC::File::save()
|
||||||
{
|
{
|
||||||
if(readOnly()) {
|
if(readOnly()) {
|
||||||
|
@ -254,67 +320,6 @@ void MPC::File::remove(int tags)
|
||||||
// private members
|
// private members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void MPC::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
|
|
||||||
|
|
||||||
findAPE();
|
|
||||||
|
|
||||||
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 and skip an ID3v2 tag
|
|
||||||
|
|
||||||
d->ID3v2Location = findID3v2();
|
|
||||||
|
|
||||||
if(d->ID3v2Location >= 0) {
|
|
||||||
seek(d->ID3v2Location);
|
|
||||||
d->ID3v2Header = new ID3v2::Header(readBlock(ID3v2::Header::size()));
|
|
||||||
d->ID3v2Size = d->ID3v2Header->completeTagSize();
|
|
||||||
d->hasID3v2 = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(d->hasID3v2)
|
|
||||||
seek(d->ID3v2Location + d->ID3v2Size);
|
|
||||||
else
|
|
||||||
seek(0);
|
|
||||||
|
|
||||||
// Look for MPC metadata
|
|
||||||
|
|
||||||
if(readProperties) {
|
|
||||||
d->properties = new Properties(readBlock(MPC::HeaderSize),
|
|
||||||
length() - d->ID3v2Size - d->APESize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
long MPC::File::findAPE()
|
long MPC::File::findAPE()
|
||||||
{
|
{
|
||||||
if(!isValid())
|
if(!isValid())
|
18
Frameworks/TagLib/Files/taglib/mpc/mpcfile.h → Frameworks/TagLib/taglib/taglib/mpc/mpcfile.h
Normal file → Executable file
18
Frameworks/TagLib/Files/taglib/mpc/mpcfile.h → Frameworks/TagLib/taglib/taglib/mpc/mpcfile.h
Normal file → Executable file
|
@ -22,6 +22,7 @@
|
||||||
#ifndef TAGLIB_MPCFILE_H
|
#ifndef TAGLIB_MPCFILE_H
|
||||||
#define TAGLIB_MPCFILE_H
|
#define TAGLIB_MPCFILE_H
|
||||||
|
|
||||||
|
#include "taglib_export.h"
|
||||||
#include "tfile.h"
|
#include "tfile.h"
|
||||||
|
|
||||||
#include "mpcproperties.h"
|
#include "mpcproperties.h"
|
||||||
|
@ -55,7 +56,7 @@ namespace TagLib {
|
||||||
* The only invalid tag combination supported is an ID3v1 tag after an APE tag.
|
* The only invalid tag combination supported is an ID3v1 tag after an APE tag.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class File : public TagLib::File
|
class TAGLIB_EXPORT File : public TagLib::File
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/*!
|
/*!
|
||||||
|
@ -75,6 +76,12 @@ namespace TagLib {
|
||||||
AllTags = 0xffff
|
AllTags = 0xffff
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Contructs an MPC file object without reading a file. Allows object
|
||||||
|
* fields to be set up before reading.
|
||||||
|
*/
|
||||||
|
File();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Contructs an MPC file from \a file. If \a readProperties is true the
|
* 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
|
* file's audio properties will also be read using \a propertiesStyle. If
|
||||||
|
@ -100,6 +107,14 @@ namespace TagLib {
|
||||||
*/
|
*/
|
||||||
virtual Properties *audioProperties() const;
|
virtual Properties *audioProperties() const;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Reads from MPC file. If \a readProperties is true the file's audio
|
||||||
|
* properties will also be read using \a propertiesStyle. If false,
|
||||||
|
* \a propertiesStyle is ignored.
|
||||||
|
*/
|
||||||
|
void read(bool readProperties = true,
|
||||||
|
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Saves the file.
|
* Saves the file.
|
||||||
*/
|
*/
|
||||||
|
@ -147,7 +162,6 @@ namespace TagLib {
|
||||||
File(const File &);
|
File(const File &);
|
||||||
File &operator=(const File &);
|
File &operator=(const File &);
|
||||||
|
|
||||||
void read(bool readProperties, Properties::ReadStyle propertiesStyle);
|
|
||||||
void scan();
|
void scan();
|
||||||
long findAPE();
|
long findAPE();
|
||||||
long findID3v1();
|
long findID3v1();
|
16
Frameworks/TagLib/Files/taglib/mpc/mpcproperties.cpp → Frameworks/TagLib/taglib/taglib/mpc/mpcproperties.cpp
Normal file → Executable file
16
Frameworks/TagLib/Files/taglib/mpc/mpcproperties.cpp → Frameworks/TagLib/taglib/taglib/mpc/mpcproperties.cpp
Normal file → Executable file
|
@ -81,13 +81,6 @@ int MPC::Properties::sampleRate() const
|
||||||
return d->sampleRate;
|
return d->sampleRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
int MPC::Properties::sampleWidth() const
|
|
||||||
{
|
|
||||||
return d->sampleWidth;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
int MPC::Properties::channels() const
|
int MPC::Properties::channels() const
|
||||||
{
|
{
|
||||||
return d->channels;
|
return d->channels;
|
||||||
|
@ -121,18 +114,21 @@ void MPC::Properties::read()
|
||||||
d->channels = 2;
|
d->channels = 2;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
unsigned int headerData = d->data.mid(0, 4).toUInt(false);
|
uint headerData = d->data.mid(0, 4).toUInt(false);
|
||||||
|
|
||||||
d->bitrate = (headerData >> 23) & 0x01ff;
|
d->bitrate = (headerData >> 23) & 0x01ff;
|
||||||
d->version = (headerData >> 11) & 0x03ff;
|
d->version = (headerData >> 11) & 0x03ff;
|
||||||
d->sampleRate = 44100;
|
d->sampleRate = 44100;
|
||||||
d->channels = 2;
|
d->channels = 2;
|
||||||
|
|
||||||
if(d->version >= 5)
|
if(d->version >= 5)
|
||||||
frames = d->data.mid(4, 4).toUInt(false);
|
frames = d->data.mid(4, 4).toUInt(false);
|
||||||
else
|
else
|
||||||
frames = d->data.mid(4, 2).toUInt(false);
|
frames = d->data.mid(6, 2).toUInt(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int samples = frames * 1152 - 576;
|
uint samples = frames * 1152 - 576;
|
||||||
|
|
||||||
d->length = d->sampleRate > 0 ? (samples + (d->sampleRate / 2)) / d->sampleRate : 0;
|
d->length = d->sampleRate > 0 ? (samples + (d->sampleRate / 2)) / d->sampleRate : 0;
|
||||||
|
|
||||||
if(!d->bitrate)
|
if(!d->bitrate)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue