Format taglib sources

This commit is contained in:
Jonas Kvinge
2020-06-13 19:02:42 +02:00
parent 72bff7fa35
commit 4ce099294c
224 changed files with 12905 additions and 15623 deletions

View File

@@ -32,18 +32,17 @@
using namespace Strawberry_TagLib::TagLib;
const char *MP4::Atom::containers[11] = {
"moov", "udta", "mdia", "meta", "ilst",
"stbl", "minf", "moof", "traf", "trak",
"stsd"
"moov", "udta", "mdia", "meta", "ilst",
"stbl", "minf", "moof", "traf", "trak",
"stsd"
};
MP4::Atom::Atom(File *file)
{
MP4::Atom::Atom(File *file) {
children.setAutoDelete(true);
offset = file->tell();
ByteVector header = file->readBlock(8);
if(header.size() != 8) {
if (header.size() != 8) {
// The atom header must be 8 bytes long, otherwise there is either
// trailing garbage or the file is truncated
debug("MP4: Couldn't read 8 bytes of data for atom header");
@@ -54,14 +53,14 @@ MP4::Atom::Atom(File *file)
length = header.toUInt();
if(length == 0) {
if (length == 0) {
// The last atom which extends to the end of the file.
length = file->length() - offset;
}
else if(length == 1) {
else if (length == 1) {
// The atom has a 64-bit length.
const long long longLength = file->readBlock(8).toLongLong();
if(longLength <= LONG_MAX) {
if (longLength <= LONG_MAX) {
// The actual length fits in long. That's always the case if long is 64-bit.
length = static_cast<long>(longLength);
}
@@ -73,7 +72,7 @@ MP4::Atom::Atom(File *file)
}
}
if(length < 8) {
if (length < 8) {
debug("MP4: Invalid atom size");
length = 0;
file->seek(0, File::End);
@@ -82,18 +81,18 @@ MP4::Atom::Atom(File *file)
name = header.mid(4, 4);
for(int i = 0; i < numContainers; i++) {
if(name == containers[i]) {
if(name == "meta") {
for (int i = 0; i < numContainers; i++) {
if (name == containers[i]) {
if (name == "meta") {
file->seek(4, File::Current);
}
else if(name == "stsd") {
else if (name == "stsd") {
file->seek(8, File::Current);
}
while(file->tell() < offset + length) {
while (file->tell() < offset + length) {
MP4::Atom *child = new MP4::Atom(file);
children.append(child);
if(child->length == 0)
if (child->length == 0)
return;
}
return;
@@ -103,18 +102,16 @@ MP4::Atom::Atom(File *file)
file->seek(offset + length);
}
MP4::Atom::~Atom()
{
MP4::Atom::~Atom() {
}
MP4::Atom *
MP4::Atom::find(const char *name1, const char *name2, const char *name3, const char *name4)
{
if(name1 == 0) {
MP4::Atom::find(const char *name1, const char *name2, const char *name3, const char *name4) {
if (name1 == 0) {
return this;
}
for(AtomList::ConstIterator it = children.begin(); it != children.end(); ++it) {
if((*it)->name == name1) {
for (AtomList::ConstIterator it = children.begin(); it != children.end(); ++it) {
if ((*it)->name == name1) {
return (*it)->find(name2, name3, name4);
}
}
@@ -122,43 +119,39 @@ MP4::Atom::find(const char *name1, const char *name2, const char *name3, const c
}
MP4::AtomList
MP4::Atom::findall(const char *_name, bool recursive)
{
MP4::Atom::findall(const char *_name, bool recursive) {
MP4::AtomList result;
for(AtomList::ConstIterator it = children.begin(); it != children.end(); ++it) {
if((*it)->name == _name) {
for (AtomList::ConstIterator it = children.begin(); it != children.end(); ++it) {
if ((*it)->name == _name) {
result.append(*it);
}
if(recursive) {
if (recursive) {
result.append((*it)->findall(_name, recursive));
}
}
return result;
}
bool
MP4::Atom::path(MP4::AtomList &path, const char *name1, const char *name2, const char *name3)
{
bool MP4::Atom::path(MP4::AtomList &path, const char *name1, const char *name2, const char *name3) {
path.append(this);
if(name1 == 0) {
if (name1 == 0) {
return true;
}
for(AtomList::ConstIterator it = children.begin(); it != children.end(); ++it) {
if((*it)->name == name1) {
for (AtomList::ConstIterator it = children.begin(); it != children.end(); ++it) {
if ((*it)->name == name1) {
return (*it)->path(path, name2, name3);
}
}
return false;
}
MP4::Atoms::Atoms(File *file)
{
MP4::Atoms::Atoms(File *file) {
atoms.setAutoDelete(true);
file->seek(0, File::End);
long end = file->tell();
file->seek(0);
while(file->tell() + 8 <= end) {
while (file->tell() + 8 <= end) {
MP4::Atom *atom = new MP4::Atom(file);
atoms.append(atom);
if (atom->length == 0)
@@ -166,15 +159,13 @@ MP4::Atoms::Atoms(File *file)
}
}
MP4::Atoms::~Atoms()
{
MP4::Atoms::~Atoms() {
}
MP4::Atom *
MP4::Atoms::find(const char *name1, const char *name2, const char *name3, const char *name4)
{
for(AtomList::ConstIterator it = atoms.begin(); it != atoms.end(); ++it) {
if((*it)->name == name1) {
MP4::Atoms::find(const char *name1, const char *name2, const char *name3, const char *name4) {
for (AtomList::ConstIterator it = atoms.begin(); it != atoms.end(); ++it) {
if ((*it)->name == name1) {
return (*it)->find(name2, name3, name4);
}
}
@@ -182,12 +173,11 @@ MP4::Atoms::find(const char *name1, const char *name2, const char *name3, const
}
MP4::AtomList
MP4::Atoms::path(const char *name1, const char *name2, const char *name3, const char *name4)
{
MP4::Atoms::path(const char *name1, const char *name2, const char *name3, const char *name4) {
MP4::AtomList path;
for(AtomList::ConstIterator it = atoms.begin(); it != atoms.end(); ++it) {
if((*it)->name == name1) {
if(!(*it)->path(path, name2, name3, name4)) {
for (AtomList::ConstIterator it = atoms.begin(); it != atoms.end(); ++it) {
if ((*it)->name == name1) {
if (!(*it)->path(path, name2, name3, name4)) {
path.clear();
}
return path;

View File

@@ -27,87 +27,85 @@
#ifndef DO_NOT_DOCUMENT
#ifndef TAGLIB_MP4ATOM_H
#define TAGLIB_MP4ATOM_H
# ifndef TAGLIB_MP4ATOM_H
# define TAGLIB_MP4ATOM_H
#include "tfile.h"
#include "tlist.h"
# include "tfile.h"
# include "tlist.h"
namespace Strawberry_TagLib {
namespace TagLib {
namespace MP4 {
namespace MP4 {
class Atom;
typedef Strawberry_TagLib::TagLib::List<Atom *> AtomList;
class Atom;
typedef Strawberry_TagLib::TagLib::List<Atom *> AtomList;
enum AtomDataType
{
TypeImplicit = 0, // for use with tags for which no type needs to be indicated because only one type is allowed
TypeUTF8 = 1, // without any count or null terminator
TypeUTF16 = 2, // also known as UTF-16BE
TypeSJIS = 3, // deprecated unless it is needed for special Japanese characters
TypeHTML = 6, // the HTML file header specifies which HTML version
TypeXML = 7, // the XML header must identify the DTD or schemas
TypeUUID = 8, // also known as GUID; stored as 16 bytes in binary (valid as an ID)
TypeISRC = 9, // stored as UTF-8 text (valid as an ID)
TypeMI3P = 10, // stored as UTF-8 text (valid as an ID)
TypeGIF = 12, // (deprecated) a GIF image
TypeJPEG = 13, // a JPEG image
TypePNG = 14, // a PNG image
TypeURL = 15, // absolute, in UTF-8 characters
TypeDuration = 16, // in milliseconds, 32-bit integer
TypeDateTime = 17, // in UTC, counting seconds since midnight, January 1, 1904; 32 or 64-bits
TypeGenred = 18, // a list of enumerated values
TypeInteger = 21, // a signed big-endian integer with length one of { 1,2,3,4,8 } bytes
TypeRIAAPA = 24, // RIAA parental advisory; { -1=no, 1=yes, 0=unspecified }, 8-bit integer
TypeUPC = 25, // Universal Product Code, in text UTF-8 format (valid as an ID)
TypeBMP = 27, // Windows bitmap image
TypeUndefined = 255 // undefined
};
enum AtomDataType {
TypeImplicit = 0, // for use with tags for which no type needs to be indicated because only one type is allowed
TypeUTF8 = 1, // without any count or null terminator
TypeUTF16 = 2, // also known as UTF-16BE
TypeSJIS = 3, // deprecated unless it is needed for special Japanese characters
TypeHTML = 6, // the HTML file header specifies which HTML version
TypeXML = 7, // the XML header must identify the DTD or schemas
TypeUUID = 8, // also known as GUID; stored as 16 bytes in binary (valid as an ID)
TypeISRC = 9, // stored as UTF-8 text (valid as an ID)
TypeMI3P = 10, // stored as UTF-8 text (valid as an ID)
TypeGIF = 12, // (deprecated) a GIF image
TypeJPEG = 13, // a JPEG image
TypePNG = 14, // a PNG image
TypeURL = 15, // absolute, in UTF-8 characters
TypeDuration = 16, // in milliseconds, 32-bit integer
TypeDateTime = 17, // in UTC, counting seconds since midnight, January 1, 1904; 32 or 64-bits
TypeGenred = 18, // a list of enumerated values
TypeInteger = 21, // a signed big-endian integer with length one of { 1,2,3,4,8 } bytes
TypeRIAAPA = 24, // RIAA parental advisory; { -1=no, 1=yes, 0=unspecified }, 8-bit integer
TypeUPC = 25, // Universal Product Code, in text UTF-8 format (valid as an ID)
TypeBMP = 27, // Windows bitmap image
TypeUndefined = 255 // undefined
};
struct AtomData {
AtomData(AtomDataType _type, ByteVector _data) : type(_type), locale(0), data(_data) {}
AtomDataType type;
int locale;
ByteVector data;
};
struct AtomData {
AtomData(AtomDataType _type, ByteVector _data) : type(_type), locale(0), data(_data) {}
AtomDataType type;
int locale;
ByteVector data;
};
typedef Strawberry_TagLib::TagLib::List<AtomData> AtomDataList;
typedef Strawberry_TagLib::TagLib::List<AtomData> AtomDataList;
class Atom
{
public:
Atom(File *file);
~Atom();
Atom *find(const char *name1, const char *name2 = 0, const char *name3 = 0, const char *name4 = 0);
bool path(AtomList &path, const char *name1, const char *name2 = 0, const char *name3 = 0);
AtomList findall(const char *name, bool recursive = false);
long offset;
long length;
Strawberry_TagLib::TagLib::ByteVector name;
AtomList children;
private:
static const int numContainers = 11;
static const char *containers[11];
};
class Atom {
public:
Atom(File *file);
~Atom();
Atom *find(const char *name1, const char *name2 = 0, const char *name3 = 0, const char *name4 = 0);
bool path(AtomList &path, const char *name1, const char *name2 = 0, const char *name3 = 0);
AtomList findall(const char *name, bool recursive = false);
long offset;
long length;
Strawberry_TagLib::TagLib::ByteVector name;
AtomList children;
//! Root-level atoms
class Atoms
{
public:
Atoms(File *file);
~Atoms();
Atom *find(const char *name1, const char *name2 = 0, const char *name3 = 0, const char *name4 = 0);
AtomList path(const char *name1, const char *name2 = 0, const char *name3 = 0, const char *name4 = 0);
AtomList atoms;
};
private:
static const int numContainers = 11;
static const char *containers[11];
};
}
//! Root-level atoms
class Atoms {
public:
Atoms(File *file);
~Atoms();
Atom *find(const char *name1, const char *name2 = 0, const char *name3 = 0, const char *name4 = 0);
AtomList path(const char *name1, const char *name2 = 0, const char *name3 = 0, const char *name4 = 0);
AtomList atoms;
};
}
}
#endif
} // namespace MP4
} // namespace TagLib
} // namespace Strawberry_TagLib
# endif
#endif

View File

@@ -30,12 +30,10 @@
using namespace Strawberry_TagLib::TagLib;
class MP4::CoverArt::CoverArtPrivate : public RefCounter
{
public:
CoverArtPrivate() :
RefCounter(),
format(MP4::CoverArt::JPEG) {}
class MP4::CoverArt::CoverArtPrivate : public RefCounter {
public:
CoverArtPrivate() : RefCounter(),
format(MP4::CoverArt::JPEG) {}
Format format;
ByteVector data;
@@ -45,49 +43,39 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
MP4::CoverArt::CoverArt(Format format, const ByteVector &data) :
d(new CoverArtPrivate())
{
MP4::CoverArt::CoverArt(Format format, const ByteVector &data) : d(new CoverArtPrivate()) {
d->format = format;
d->data = data;
}
MP4::CoverArt::CoverArt(const CoverArt &item) :
d(item.d)
{
MP4::CoverArt::CoverArt(const CoverArt &item) : d(item.d) {
d->ref();
}
MP4::CoverArt &
MP4::CoverArt::operator=(const CoverArt &item)
{
MP4::CoverArt::operator=(const CoverArt &item) {
CoverArt(item).swap(*this);
return *this;
}
void
MP4::CoverArt::swap(CoverArt &item)
{
void MP4::CoverArt::swap(CoverArt &item) {
using std::swap;
swap(d, item.d);
}
MP4::CoverArt::~CoverArt()
{
if(d->deref()) {
MP4::CoverArt::~CoverArt() {
if (d->deref()) {
delete d;
}
}
MP4::CoverArt::Format
MP4::CoverArt::format() const
{
MP4::CoverArt::format() const {
return d->format;
}
ByteVector
MP4::CoverArt::data() const
{
MP4::CoverArt::data() const {
return d->data;
}

View File

@@ -34,53 +34,52 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace MP4 {
namespace MP4 {
class TAGLIB_EXPORT CoverArt
{
public:
/*!
class TAGLIB_EXPORT CoverArt {
public:
/*!
* This describes the image type.
*/
enum Format {
JPEG = TypeJPEG,
PNG = TypePNG,
BMP = TypeBMP,
GIF = TypeGIF,
Unknown = TypeImplicit,
};
enum Format {
JPEG = TypeJPEG,
PNG = TypePNG,
BMP = TypeBMP,
GIF = TypeGIF,
Unknown = TypeImplicit,
};
CoverArt(Format format, const ByteVector &data);
~CoverArt();
CoverArt(Format format, const ByteVector &data);
~CoverArt();
CoverArt(const CoverArt &item);
CoverArt(const CoverArt &item);
/*!
/*!
* Copies the contents of \a item into this CoverArt.
*/
CoverArt &operator=(const CoverArt &item);
CoverArt &operator=(const CoverArt &item);
/*!
/*!
* Exchanges the content of the CoverArt by the content of \a item.
*/
void swap(CoverArt &item);
void swap(CoverArt &item);
//! Format of the image
Format format() const;
//! Format of the image
Format format() const;
//! The image data
ByteVector data() const;
//! The image data
ByteVector data() const;
private:
class CoverArtPrivate;
CoverArtPrivate *d;
};
private:
class CoverArtPrivate;
CoverArtPrivate *d;
};
typedef List<CoverArt> CoverArtList;
typedef List<CoverArt> CoverArtList;
}
} // namespace MP4
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@@ -34,40 +34,35 @@
using namespace Strawberry_TagLib::TagLib;
namespace
{
bool checkValid(const MP4::AtomList &list)
{
for(MP4::AtomList::ConstIterator it = list.begin(); it != list.end(); ++it) {
namespace {
bool checkValid(const MP4::AtomList &list) {
for (MP4::AtomList::ConstIterator it = list.begin(); it != list.end(); ++it) {
if((*it)->length == 0)
return false;
if ((*it)->length == 0)
return false;
if(!checkValid((*it)->children))
return false;
}
return true;
if (!checkValid((*it)->children))
return false;
}
return true;
}
} // namespace
class MP4::File::FilePrivate
{
public:
FilePrivate() :
tag(0),
atoms(0),
properties(0) {}
class MP4::File::FilePrivate {
public:
FilePrivate() : tag(0),
atoms(0),
properties(0) {}
~FilePrivate()
{
~FilePrivate() {
delete atoms;
delete tag;
delete properties;
}
MP4::Tag *tag;
MP4::Atoms *atoms;
MP4::Tag *tag;
MP4::Atoms *atoms;
MP4::Properties *properties;
};
@@ -75,8 +70,7 @@ public:
// static members
////////////////////////////////////////////////////////////////////////////////
bool MP4::File::isSupported(IOStream *stream)
{
bool MP4::File::isSupported(IOStream *stream) {
// An MP4 file has to have an "ftyp" box first.
const ByteVector id = Utils::readHeader(stream, 8, false);
@@ -87,87 +81,73 @@ bool MP4::File::isSupported(IOStream *stream)
// public members
////////////////////////////////////////////////////////////////////////////////
MP4::File::File(FileName file, bool readProperties, AudioProperties::ReadStyle) :
Strawberry_TagLib::TagLib::File(file),
d(new FilePrivate())
{
if(isOpen())
MP4::File::File(FileName file, bool readProperties, AudioProperties::ReadStyle) : Strawberry_TagLib::TagLib::File(file),
d(new FilePrivate()) {
if (isOpen())
read(readProperties);
}
MP4::File::File(IOStream *stream, bool readProperties, AudioProperties::ReadStyle) :
Strawberry_TagLib::TagLib::File(stream),
d(new FilePrivate())
{
if(isOpen())
MP4::File::File(IOStream *stream, bool readProperties, AudioProperties::ReadStyle) : Strawberry_TagLib::TagLib::File(stream),
d(new FilePrivate()) {
if (isOpen())
read(readProperties);
}
MP4::File::~File()
{
MP4::File::~File() {
delete d;
}
MP4::Tag *
MP4::File::tag() const
{
MP4::File::tag() const {
return d->tag;
}
PropertyMap MP4::File::properties() const
{
PropertyMap MP4::File::properties() const {
return d->tag->properties();
}
void MP4::File::removeUnsupportedProperties(const StringList &properties)
{
void MP4::File::removeUnsupportedProperties(const StringList &properties) {
d->tag->removeUnsupportedProperties(properties);
}
PropertyMap MP4::File::setProperties(const PropertyMap &properties)
{
PropertyMap MP4::File::setProperties(const PropertyMap &properties) {
return d->tag->setProperties(properties);
}
MP4::Properties *
MP4::File::audioProperties() const
{
MP4::File::audioProperties() const {
return d->properties;
}
void
MP4::File::read(bool readProperties)
{
if(!isValid())
void MP4::File::read(bool readProperties) {
if (!isValid())
return;
d->atoms = new Atoms(this);
if(!checkValid(d->atoms->atoms)) {
if (!checkValid(d->atoms->atoms)) {
setValid(false);
return;
}
// must have a moov atom, otherwise consider it invalid
if(!d->atoms->find("moov")) {
if (!d->atoms->find("moov")) {
setValid(false);
return;
}
d->tag = new Tag(this, d->atoms);
if(readProperties) {
if (readProperties) {
d->properties = new Properties(this, d->atoms);
}
}
bool
MP4::File::save()
{
if(readOnly()) {
bool MP4::File::save() {
if (readOnly()) {
debug("MP4::File::save() -- File is read only.");
return false;
}
if(!isValid()) {
if (!isValid()) {
debug("MP4::File::save() -- Trying to save invalid file.");
return false;
}
@@ -175,8 +155,6 @@ MP4::File::save()
return d->tag->save();
}
bool
MP4::File::hasMP4Tag() const
{
bool MP4::File::hasMP4Tag() const {
return (d->atoms->find("moov", "udta", "meta", "ilst") != 0);
}

View File

@@ -35,30 +35,29 @@
namespace Strawberry_TagLib {
namespace TagLib {
//! An implementation of MP4 (AAC, ALAC, ...) metadata
namespace MP4 {
//! An implementation of MP4 (AAC, ALAC, ...) metadata
namespace MP4 {
class Atoms;
class Atoms;
/*!
/*!
* This implements and provides an interface for MP4 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 files.
*/
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File
{
public:
/*!
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File {
public:
/*!
* Constructs an MP4 file from \a file. If \a readProperties is true the
* file's audio properties will also be read.
*
* \note In the current implementation, \a propertiesStyle is ignored.
*/
File(FileName file, bool readProperties = true,
Properties::ReadStyle audioPropertiesStyle = Properties::Average);
File(FileName file, bool readProperties = true,
Properties::ReadStyle audioPropertiesStyle = Properties::Average);
/*!
/*!
* Constructs an MP4 file from \a stream. If \a readProperties is true the
* file's audio properties will also be read.
*
@@ -67,15 +66,15 @@ namespace TagLib {
*
* \note In the current implementation, \a propertiesStyle is ignored.
*/
File(IOStream *stream, bool readProperties = true,
Properties::ReadStyle audioPropertiesStyle = Properties::Average);
File(IOStream *stream, bool readProperties = true,
Properties::ReadStyle audioPropertiesStyle = Properties::Average);
/*!
/*!
* Destroys this instance of the File.
*/
virtual ~File();
virtual ~File();
/*!
/*!
* Returns a pointer to the MP4 tag of the file.
*
* MP4::Tag implements the tag interface, so this serves as the
@@ -85,61 +84,61 @@ namespace TagLib {
* deleted by the user. It will be deleted when the file (object) is
* destroyed.
*/
Tag *tag() const;
Tag *tag() const;
/*!
/*!
* Implements the unified property interface -- export function.
*/
PropertyMap properties() const;
PropertyMap properties() const;
/*!
/*!
* Removes unsupported properties. Forwards to the actual Tag's
* removeUnsupportedProperties() function.
*/
void removeUnsupportedProperties(const StringList &properties);
void removeUnsupportedProperties(const StringList &properties);
/*!
/*!
* Implements the unified property interface -- import function.
*/
PropertyMap setProperties(const PropertyMap &);
PropertyMap setProperties(const PropertyMap &);
/*!
/*!
* Returns the MP4 audio properties for this file.
*/
Properties *audioProperties() const;
Properties *audioProperties() const;
/*!
/*!
* Save the file.
*
* This returns true if the save was successful.
*/
bool save();
bool save();
/*!
/*!
* Returns whether or not the file on disk actually has an MP4 tag, or the
* file has a Metadata Item List (ilst) atom.
*/
bool hasMP4Tag() const;
bool hasMP4Tag() const;
/*!
/*!
* Returns whether or not the given \a stream can be opened as an ASF
* file.
*
* \note This method is designed to do a quick check. The result may
* not necessarily be correct.
*/
static bool isSupported(IOStream *stream);
static bool isSupported(IOStream *stream);
private:
void read(bool readProperties);
private:
void read(bool readProperties);
class FilePrivate;
FilePrivate *d;
};
class FilePrivate;
FilePrivate *d;
};
}
} // namespace MP4
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@@ -30,13 +30,11 @@
using namespace Strawberry_TagLib::TagLib;
class MP4::Item::ItemPrivate : public RefCounter
{
public:
ItemPrivate() :
RefCounter(),
valid(true),
atomDataType(TypeUndefined) {}
class MP4::Item::ItemPrivate : public RefCounter {
public:
ItemPrivate() : RefCounter(),
valid(true),
atomDataType(TypeUndefined) {}
bool valid;
AtomDataType atomDataType;
@@ -53,160 +51,119 @@ public:
MP4::CoverArtList m_coverArtList;
};
MP4::Item::Item() :
d(new ItemPrivate())
{
MP4::Item::Item() : d(new ItemPrivate()) {
d->valid = false;
}
MP4::Item::Item(const Item &item) :
d(item.d)
{
MP4::Item::Item(const Item &item) : d(item.d) {
d->ref();
}
MP4::Item &
MP4::Item::operator=(const Item &item)
{
MP4::Item::operator=(const Item &item) {
Item(item).swap(*this);
return *this;
}
void
MP4::Item::swap(Item &item)
{
void MP4::Item::swap(Item &item) {
using std::swap;
swap(d, item.d);
}
MP4::Item::~Item()
{
if(d->deref())
MP4::Item::~Item() {
if (d->deref())
delete d;
}
MP4::Item::Item(bool value) :
d(new ItemPrivate())
{
MP4::Item::Item(bool value) : d(new ItemPrivate()) {
d->m_bool = value;
}
MP4::Item::Item(int value) :
d(new ItemPrivate())
{
MP4::Item::Item(int value) : d(new ItemPrivate()) {
d->m_int = value;
}
MP4::Item::Item(unsigned char value) :
d(new ItemPrivate())
{
MP4::Item::Item(unsigned char value) : d(new ItemPrivate()) {
d->m_byte = value;
}
MP4::Item::Item(unsigned int value) :
d(new ItemPrivate())
{
MP4::Item::Item(unsigned int value) : d(new ItemPrivate()) {
d->m_uint = value;
}
MP4::Item::Item(long long value) :
d(new ItemPrivate())
{
MP4::Item::Item(long long value) : d(new ItemPrivate()) {
d->m_longlong = value;
}
MP4::Item::Item(int value1, int value2) :
d(new ItemPrivate())
{
MP4::Item::Item(int value1, int value2) : d(new ItemPrivate()) {
d->m_intPair.first = value1;
d->m_intPair.second = value2;
}
MP4::Item::Item(const ByteVectorList &value) :
d(new ItemPrivate())
{
MP4::Item::Item(const ByteVectorList &value) : d(new ItemPrivate()) {
d->m_byteVectorList = value;
}
MP4::Item::Item(const StringList &value) :
d(new ItemPrivate())
{
MP4::Item::Item(const StringList &value) : d(new ItemPrivate()) {
d->m_stringList = value;
}
MP4::Item::Item(const MP4::CoverArtList &value) :
d(new ItemPrivate())
{
MP4::Item::Item(const MP4::CoverArtList &value) : d(new ItemPrivate()) {
d->m_coverArtList = value;
}
void MP4::Item::setAtomDataType(MP4::AtomDataType type)
{
void MP4::Item::setAtomDataType(MP4::AtomDataType type) {
d->atomDataType = type;
}
MP4::AtomDataType MP4::Item::atomDataType() const
{
MP4::AtomDataType MP4::Item::atomDataType() const {
return d->atomDataType;
}
bool
MP4::Item::toBool() const
{
bool MP4::Item::toBool() const {
return d->m_bool;
}
int
MP4::Item::toInt() const
{
int MP4::Item::toInt() const {
return d->m_int;
}
unsigned char
MP4::Item::toByte() const
{
MP4::Item::toByte() const {
return d->m_byte;
}
unsigned int
MP4::Item::toUInt() const
{
MP4::Item::toUInt() const {
return d->m_uint;
}
long long
MP4::Item::toLongLong() const
{
MP4::Item::toLongLong() const {
return d->m_longlong;
}
MP4::Item::IntPair
MP4::Item::toIntPair() const
{
MP4::Item::toIntPair() const {
return d->m_intPair;
}
StringList
MP4::Item::toStringList() const
{
MP4::Item::toStringList() const {
return d->m_stringList;
}
ByteVectorList
MP4::Item::toByteVectorList() const
{
MP4::Item::toByteVectorList() const {
return d->m_byteVectorList;
}
MP4::CoverArtList
MP4::Item::toCoverArtList() const
{
MP4::Item::toCoverArtList() const {
return d->m_coverArtList;
}
bool
MP4::Item::isValid() const
{
bool MP4::Item::isValid() const {
return d->valid;
}

View File

@@ -33,63 +33,62 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace MP4 {
namespace MP4 {
class TAGLIB_EXPORT Item
{
public:
struct IntPair {
int first, second;
};
class TAGLIB_EXPORT Item {
public:
struct IntPair {
int first, second;
};
Item();
Item(const Item &item);
Item();
Item(const Item &item);
/*!
/*!
* Copies the contents of \a item into this Item.
*/
Item &operator=(const Item &item);
Item &operator=(const Item &item);
/*!
/*!
* Exchanges the content of the Item by the content of \a item.
*/
void swap(Item &item);
void swap(Item &item);
~Item();
~Item();
Item(int value);
Item(unsigned char value);
Item(unsigned int value);
Item(long long value);
Item(bool value);
Item(int first, int second);
Item(const StringList &value);
Item(const ByteVectorList &value);
Item(const CoverArtList &value);
Item(int value);
Item(unsigned char value);
Item(unsigned int value);
Item(long long value);
Item(bool value);
Item(int first, int second);
Item(const StringList &value);
Item(const ByteVectorList &value);
Item(const CoverArtList &value);
void setAtomDataType(AtomDataType type);
AtomDataType atomDataType() const;
void setAtomDataType(AtomDataType type);
AtomDataType atomDataType() const;
int toInt() const;
unsigned char toByte() const;
unsigned int toUInt() const;
long long toLongLong() const;
bool toBool() const;
IntPair toIntPair() const;
StringList toStringList() const;
ByteVectorList toByteVectorList() const;
CoverArtList toCoverArtList() const;
int toInt() const;
unsigned char toByte() const;
unsigned int toUInt() const;
long long toLongLong() const;
bool toBool() const;
IntPair toIntPair() const;
StringList toStringList() const;
ByteVectorList toByteVectorList() const;
CoverArtList toCoverArtList() const;
bool isValid() const;
bool isValid() const;
private:
class ItemPrivate;
ItemPrivate *d;
};
private:
class ItemPrivate;
ItemPrivate *d;
};
}
} // namespace MP4
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@@ -31,17 +31,15 @@
using namespace Strawberry_TagLib::TagLib;
class MP4::Properties::PropertiesPrivate
{
public:
PropertiesPrivate() :
length(0),
bitrate(0),
sampleRate(0),
channels(0),
bitsPerSample(0),
encrypted(false),
codec(MP4::Properties::Unknown) {}
class MP4::Properties::PropertiesPrivate {
public:
PropertiesPrivate() : length(0),
bitrate(0),
sampleRate(0),
channels(0),
bitsPerSample(0),
encrypted(false),
codec(MP4::Properties::Unknown) {}
int length;
int bitrate;
@@ -56,69 +54,49 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
MP4::Properties::Properties(File *file, MP4::Atoms *atoms, ReadStyle style) :
AudioProperties(style),
d(new PropertiesPrivate())
{
MP4::Properties::Properties(File *file, MP4::Atoms *atoms, ReadStyle style) : AudioProperties(style),
d(new PropertiesPrivate()) {
read(file, atoms);
}
MP4::Properties::~Properties()
{
MP4::Properties::~Properties() {
delete d;
}
int
MP4::Properties::channels() const
{
int MP4::Properties::channels() const {
return d->channels;
}
int
MP4::Properties::sampleRate() const
{
int MP4::Properties::sampleRate() const {
return d->sampleRate;
}
int
MP4::Properties::length() const
{
int MP4::Properties::length() const {
return lengthInSeconds();
}
int
MP4::Properties::lengthInSeconds() const
{
int MP4::Properties::lengthInSeconds() const {
return d->length / 1000;
}
int
MP4::Properties::lengthInMilliseconds() const
{
int MP4::Properties::lengthInMilliseconds() const {
return d->length;
}
int
MP4::Properties::bitrate() const
{
int MP4::Properties::bitrate() const {
return d->bitrate;
}
int
MP4::Properties::bitsPerSample() const
{
int MP4::Properties::bitsPerSample() const {
return d->bitsPerSample;
}
bool
MP4::Properties::isEncrypted() const
{
bool MP4::Properties::isEncrypted() const {
return d->encrypted;
}
MP4::Properties::Codec
MP4::Properties::codec() const
{
MP4::Properties::codec() const {
return d->codec;
}
@@ -126,11 +104,9 @@ MP4::Properties::codec() const
// private members
////////////////////////////////////////////////////////////////////////////////
void
MP4::Properties::read(File *file, Atoms *atoms)
{
void MP4::Properties::read(File *file, Atoms *atoms) {
MP4::Atom *moov = atoms->find("moov");
if(!moov) {
if (!moov) {
debug("MP4: Atom 'moov' not found");
return;
}
@@ -139,27 +115,27 @@ MP4::Properties::read(File *file, Atoms *atoms)
ByteVector data;
const MP4::AtomList trakList = moov->findall("trak");
for(MP4::AtomList::ConstIterator it = trakList.begin(); it != trakList.end(); ++it) {
for (MP4::AtomList::ConstIterator it = trakList.begin(); it != trakList.end(); ++it) {
trak = *it;
MP4::Atom *hdlr = trak->find("mdia", "hdlr");
if(!hdlr) {
if (!hdlr) {
debug("MP4: Atom 'trak.mdia.hdlr' not found");
return;
}
file->seek(hdlr->offset);
data = file->readBlock(hdlr->length);
if(data.containsAt("soun", 16)) {
if (data.containsAt("soun", 16)) {
break;
}
trak = 0;
}
if(!trak) {
if (!trak) {
debug("MP4: No audio tracks");
return;
}
MP4::Atom *mdhd = trak->find("mdia", "mdhd");
if(!mdhd) {
if (!mdhd) {
debug("MP4: Atom 'trak.mdia.mdhd' not found");
return;
}
@@ -170,46 +146,46 @@ MP4::Properties::read(File *file, Atoms *atoms)
const unsigned int version = data[8];
long long unit;
long long length;
if(version == 1) {
if(data.size() < 36 + 8) {
if (version == 1) {
if (data.size() < 36 + 8) {
debug("MP4: Atom 'trak.mdia.mdhd' is smaller than expected");
return;
}
unit = data.toUInt(28U);
unit = data.toUInt(28U);
length = data.toLongLong(32U);
}
else {
if(data.size() < 24 + 8) {
if (data.size() < 24 + 8) {
debug("MP4: Atom 'trak.mdia.mdhd' is smaller than expected");
return;
}
unit = data.toUInt(20U);
unit = data.toUInt(20U);
length = data.toUInt(24U);
}
if(unit > 0 && length > 0)
if (unit > 0 && length > 0)
d->length = static_cast<int>(length * 1000.0 / unit + 0.5);
MP4::Atom *atom = trak->find("mdia", "minf", "stbl", "stsd");
if(!atom) {
if (!atom) {
return;
}
file->seek(atom->offset);
data = file->readBlock(atom->length);
if(data.containsAt("mp4a", 20)) {
d->codec = AAC;
d->channels = data.toShort(40U);
if (data.containsAt("mp4a", 20)) {
d->codec = AAC;
d->channels = data.toShort(40U);
d->bitsPerSample = data.toShort(42U);
d->sampleRate = data.toUInt(46U);
if(data.containsAt("esds", 56) && data[64] == 0x03) {
d->sampleRate = data.toUInt(46U);
if (data.containsAt("esds", 56) && data[64] == 0x03) {
unsigned int pos = 65;
if(data.containsAt("\x80\x80\x80", pos)) {
if (data.containsAt("\x80\x80\x80", pos)) {
pos += 3;
}
pos += 4;
if(data[pos] == 0x04) {
if (data[pos] == 0x04) {
pos += 1;
if(data.containsAt("\x80\x80\x80", pos)) {
if (data.containsAt("\x80\x80\x80", pos)) {
pos += 3;
}
pos += 10;
@@ -217,18 +193,18 @@ MP4::Properties::read(File *file, Atoms *atoms)
}
}
}
else if(data.containsAt("alac", 20)) {
if(atom->length == 88 && data.containsAt("alac", 56)) {
d->codec = ALAC;
else if (data.containsAt("alac", 20)) {
if (atom->length == 88 && data.containsAt("alac", 56)) {
d->codec = ALAC;
d->bitsPerSample = data.at(69);
d->channels = data.at(73);
d->bitrate = static_cast<int>(data.toUInt(80U) / 1000.0 + 0.5);
d->sampleRate = data.toUInt(84U);
d->channels = data.at(73);
d->bitrate = static_cast<int>(data.toUInt(80U) / 1000.0 + 0.5);
d->sampleRate = data.toUInt(84U);
}
}
MP4::Atom *drms = atom->find("drms");
if(drms) {
if (drms) {
d->encrypted = true;
}
}

View File

@@ -32,25 +32,24 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace MP4 {
namespace MP4 {
class Atoms;
class File;
class Atoms;
class File;
//! An implementation of MP4 audio properties
class TAGLIB_EXPORT Properties : public AudioProperties
{
public:
enum Codec {
Unknown = 0,
AAC,
ALAC
};
//! An implementation of MP4 audio properties
class TAGLIB_EXPORT Properties : public AudioProperties {
public:
enum Codec {
Unknown = 0,
AAC,
ALAC
};
Properties(File *file, Atoms *atoms, ReadStyle style = Average);
virtual ~Properties();
Properties(File *file, Atoms *atoms, ReadStyle style = Average);
virtual ~Properties();
/*!
/*!
* Returns the length of the file in seconds. The length is rounded down to
* the nearest whole second.
*
@@ -58,65 +57,65 @@ namespace TagLib {
*
* \deprecated
*/
TAGLIB_DEPRECATED virtual int length() const;
TAGLIB_DEPRECATED virtual int length() const;
/*!
/*!
* Returns the length of the file in seconds. The length is rounded down to
* the nearest whole second.
*
* \see lengthInMilliseconds()
*/
// BIC: make virtual
int lengthInSeconds() const;
// BIC: make virtual
int lengthInSeconds() const;
/*!
/*!
* Returns the length of the file in milliseconds.
*
* \see lengthInSeconds()
*/
// BIC: make virtual
int lengthInMilliseconds() const;
// BIC: make virtual
int lengthInMilliseconds() const;
/*!
/*!
* Returns the average bit rate of the file in kb/s.
*/
virtual int bitrate() const;
virtual int bitrate() const;
/*!
/*!
* Returns the sample rate in Hz.
*/
virtual int sampleRate() const;
virtual int sampleRate() const;
/*!
/*!
* Returns the number of audio channels.
*/
virtual int channels() const;
virtual int channels() const;
/*!
/*!
* Returns the number of bits per audio sample.
*/
virtual int bitsPerSample() const;
virtual int bitsPerSample() const;
/*!
/*!
* Returns whether or not the file is encrypted.
*/
bool isEncrypted() const;
bool isEncrypted() const;
/*!
/*!
* Returns the codec used in the file.
*/
Codec codec() const;
Codec codec() const;
private:
void read(File *file, Atoms *atoms);
private:
void read(File *file, Atoms *atoms);
class PropertiesPrivate;
PropertiesPrivate *d;
};
class PropertiesPrivate;
PropertiesPrivate *d;
};
}
} // namespace MP4
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -38,122 +38,121 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace MP4 {
namespace MP4 {
/*!
/*!
* \deprecated
*/
TAGLIB_DEPRECATED typedef Strawberry_TagLib::TagLib::Map<String, Item> ItemListMap;
typedef Strawberry_TagLib::TagLib::Map<String, Item> ItemMap;
TAGLIB_DEPRECATED typedef Strawberry_TagLib::TagLib::Map<String, Item> ItemListMap;
typedef Strawberry_TagLib::TagLib::Map<String, Item> ItemMap;
class TAGLIB_EXPORT Tag: public Strawberry_TagLib::TagLib::Tag
{
public:
Tag();
Tag(Strawberry_TagLib::TagLib::File *file, Atoms *atoms);
virtual ~Tag();
bool save();
class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag {
public:
Tag();
Tag(Strawberry_TagLib::TagLib::File *file, Atoms *atoms);
virtual ~Tag();
bool save();
virtual String title() const;
virtual String artist() const;
virtual String album() const;
virtual String comment() const;
virtual String genre() const;
virtual unsigned int year() const;
virtual unsigned int track() const;
virtual String title() const;
virtual String artist() const;
virtual String album() const;
virtual String comment() const;
virtual String genre() const;
virtual unsigned int year() const;
virtual unsigned int track() const;
virtual void setTitle(const String &value);
virtual void setArtist(const String &value);
virtual void setAlbum(const String &value);
virtual void setComment(const String &value);
virtual void setGenre(const String &value);
virtual void setYear(unsigned int value);
virtual void setTrack(unsigned int value);
virtual void setTitle(const String &value);
virtual void setArtist(const String &value);
virtual void setAlbum(const String &value);
virtual void setComment(const String &value);
virtual void setGenre(const String &value);
virtual void setYear(unsigned int value);
virtual void setTrack(unsigned int value);
virtual bool isEmpty() const;
virtual bool isEmpty() const;
/*!
/*!
* \deprecated Use the item() and setItem() API instead
*/
TAGLIB_DEPRECATED ItemMap &itemListMap();
TAGLIB_DEPRECATED ItemMap &itemListMap();
/*!
/*!
* Returns a string-keyed map of the MP4::Items for this tag.
*/
const ItemMap &itemMap() const;
const ItemMap &itemMap() const;
/*!
/*!
* \return The item, if any, corresponding to \a key.
*/
Item item(const String &key) const;
Item item(const String &key) const;
/*!
/*!
* Sets the value of \a key to \a value, overwriting any previous value.
*/
void setItem(const String &key, const Item &value);
void setItem(const String &key, const Item &value);
/*!
/*!
* Removes the entry with \a key from the tag, or does nothing if it does
* not exist.
*/
void removeItem(const String &key);
void removeItem(const String &key);
/*!
/*!
* \return True if the tag contains an entry for \a key.
*/
bool contains(const String &key) const;
bool contains(const String &key) const;
PropertyMap properties() const;
void removeUnsupportedProperties(const StringList& properties);
PropertyMap setProperties(const PropertyMap &properties);
PropertyMap properties() const;
void removeUnsupportedProperties(const StringList &properties);
PropertyMap setProperties(const PropertyMap &properties);
private:
AtomDataList parseData2(const Atom *atom, int expectedFlags = -1,
bool freeForm = false);
ByteVectorList parseData(const Atom *atom, int expectedFlags = -1,
bool freeForm = false);
void parseText(const Atom *atom, int expectedFlags = 1);
void parseFreeForm(const Atom *atom);
void parseInt(const Atom *atom);
void parseByte(const Atom *atom);
void parseUInt(const Atom *atom);
void parseLongLong(const Atom *atom);
void parseGnre(const Atom *atom);
void parseIntPair(const Atom *atom);
void parseBool(const Atom *atom);
void parseCovr(const Atom *atom);
private:
AtomDataList parseData2(const Atom *atom, int expectedFlags = -1,
bool freeForm = false);
ByteVectorList parseData(const Atom *atom, int expectedFlags = -1,
bool freeForm = false);
void parseText(const Atom *atom, int expectedFlags = 1);
void parseFreeForm(const Atom *atom);
void parseInt(const Atom *atom);
void parseByte(const Atom *atom);
void parseUInt(const Atom *atom);
void parseLongLong(const Atom *atom);
void parseGnre(const Atom *atom);
void parseIntPair(const Atom *atom);
void parseBool(const Atom *atom);
void parseCovr(const Atom *atom);
ByteVector padIlst(const ByteVector &data, int length = -1) const;
ByteVector renderAtom(const ByteVector &name, const ByteVector &data) const;
ByteVector renderData(const ByteVector &name, int flags,
const ByteVectorList &data) const;
ByteVector renderText(const ByteVector &name, const Item &item,
int flags = TypeUTF8) const;
ByteVector renderFreeForm(const String &name, const Item &item) const;
ByteVector renderBool(const ByteVector &name, const Item &item) const;
ByteVector renderInt(const ByteVector &name, const Item &item) const;
ByteVector renderByte(const ByteVector &name, const Item &item) const;
ByteVector renderUInt(const ByteVector &name, const Item &item) const;
ByteVector renderLongLong(const ByteVector &name, const Item &item) const;
ByteVector renderIntPair(const ByteVector &name, const Item &item) const;
ByteVector renderIntPairNoTrailing(const ByteVector &name, const Item &item) const;
ByteVector renderCovr(const ByteVector &name, const Item &item) const;
ByteVector padIlst(const ByteVector &data, int length = -1) const;
ByteVector renderAtom(const ByteVector &name, const ByteVector &data) const;
ByteVector renderData(const ByteVector &name, int flags,
const ByteVectorList &data) const;
ByteVector renderText(const ByteVector &name, const Item &item,
int flags = TypeUTF8) const;
ByteVector renderFreeForm(const String &name, const Item &item) const;
ByteVector renderBool(const ByteVector &name, const Item &item) const;
ByteVector renderInt(const ByteVector &name, const Item &item) const;
ByteVector renderByte(const ByteVector &name, const Item &item) const;
ByteVector renderUInt(const ByteVector &name, const Item &item) const;
ByteVector renderLongLong(const ByteVector &name, const Item &item) const;
ByteVector renderIntPair(const ByteVector &name, const Item &item) const;
ByteVector renderIntPairNoTrailing(const ByteVector &name, const Item &item) const;
ByteVector renderCovr(const ByteVector &name, const Item &item) const;
void updateParents(const AtomList &path, long delta, int ignore = 0);
void updateOffsets(long delta, long offset);
void updateParents(const AtomList &path, long delta, int ignore = 0);
void updateOffsets(long delta, long offset);
void saveNew(ByteVector data);
void saveExisting(ByteVector data, const AtomList &path);
void saveNew(ByteVector data);
void saveExisting(ByteVector data, const AtomList &path);
void addItem(const String &name, const Item &value);
void addItem(const String &name, const Item &value);
class TagPrivate;
TagPrivate *d;
};
class TagPrivate;
TagPrivate *d;
};
}
} // namespace MP4
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif