Add a tool to inspect audio files, only MP4 is implemented for now

This commit is contained in:
Lukáš Lalinský
2012-11-11 16:43:36 +01:00
parent 3a5aeb4573
commit 45b0279b41
16 changed files with 252 additions and 2 deletions

View File

@ -149,3 +149,16 @@ MP4::File::save()
return d->tag->save();
}
String
MP4::File::toString() const
{
StringList desc;
if(d->properties) {
desc.append(d->properties->toString());
}
if(d->tag) {
desc.append(d->tag->toString());
}
return desc.toString("\n");
}

View File

@ -100,6 +100,11 @@ namespace TagLib {
*/
bool save();
/*!
* Description of the file.
*/
String toString() const;
private:
void read(bool readProperties, Properties::ReadStyle audioPropertiesStyle);

View File

@ -26,6 +26,7 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <taglib.h>
#include <tdebug.h>
@ -36,10 +37,11 @@ using namespace TagLib;
class MP4::Item::ItemPrivate : public RefCounter
{
public:
ItemPrivate() : RefCounter(), valid(true), atomDataType(TypeUndefined) {}
ItemPrivate() : RefCounter(), valid(true), atomDataType(MP4::TypeUndefined), type(MP4::Item::TypeUndefined) {}
bool valid;
AtomDataType atomDataType;
ItemType type;
union {
bool m_bool;
int m_int;
@ -86,30 +88,35 @@ MP4::Item::Item(bool value)
{
d = new ItemPrivate;
d->m_bool = value;
d->type = TypeBool;
}
MP4::Item::Item(int value)
{
d = new ItemPrivate;
d->m_int = value;
d->type = TypeInt;
}
MP4::Item::Item(uchar value)
{
d = new ItemPrivate;
d->m_byte = value;
d->type = TypeByte;
}
MP4::Item::Item(uint value)
{
d = new ItemPrivate;
d->m_uint = value;
d->type = TypeUInt;
}
MP4::Item::Item(long long value)
{
d = new ItemPrivate;
d->m_longlong = value;
d->type = TypeLongLong;
}
MP4::Item::Item(int value1, int value2)
@ -117,24 +124,28 @@ MP4::Item::Item(int value1, int value2)
d = new ItemPrivate;
d->m_intPair.first = value1;
d->m_intPair.second = value2;
d->type = TypeIntPair;
}
MP4::Item::Item(const ByteVectorList &value)
{
d = new ItemPrivate;
d->m_byteVectorList = value;
d->type = TypeByteVectorList;
}
MP4::Item::Item(const StringList &value)
{
d = new ItemPrivate;
d->m_stringList = value;
d->type = TypeStringList;
}
MP4::Item::Item(const MP4::CoverArtList &value)
{
d = new ItemPrivate;
d->m_coverArtList = value;
d->type = TypeCoverArtList;
}
void MP4::Item::setAtomDataType(MP4::AtomDataType type)
@ -207,3 +218,46 @@ MP4::Item::isValid() const
return d->valid;
}
String
MP4::Item::toString() const
{
StringList desc;
char tmp[256];
switch (d->type) {
case TypeBool:
return d->m_bool ? "true" : "false";
case TypeInt:
sprintf(tmp, "%d", d->m_int);
return tmp;
case TypeIntPair:
sprintf(tmp, "%d/%d", d->m_intPair.first, d->m_intPair.second);
return tmp;
case TypeByte:
sprintf(tmp, "%d", d->m_byte);
return tmp;
case TypeUInt:
sprintf(tmp, "%u", d->m_uint);
return tmp;
case TypeLongLong:
sprintf(tmp, "%lld", d->m_longlong);
return tmp;
case TypeStringList:
return d->m_stringList.toString(" / ");
case TypeByteVectorList:
for(int i = 0; i < d->m_byteVectorList.size(); i++) {
sprintf(tmp, "[%d bytes of data]", d->m_byteVectorList[i].size());
desc.append(tmp);
}
return desc.toString(", ");
case TypeCoverArtList:
for(int i = 0; i < d->m_coverArtList.size(); i++) {
sprintf(tmp, "[%d bytes of data]", d->m_coverArtList[i].data().size());
desc.append(tmp);
}
return desc.toString(", ");
case TypeUndefined:
return "[unknown]";
}
return String();
}

View File

@ -41,6 +41,19 @@ namespace TagLib {
int first, second;
};
enum ItemType {
TypeUndefined = 0,
TypeBool,
TypeInt,
TypeIntPair,
TypeByte,
TypeUInt,
TypeLongLong,
TypeStringList,
TypeByteVectorList,
TypeCoverArtList,
};
Item();
Item(const Item &item);
Item &operator=(const Item &item);
@ -69,8 +82,12 @@ namespace TagLib {
ByteVectorList toByteVectorList() const;
CoverArtList toCoverArtList() const;
ItemType type() const;
bool isValid() const;
String toString() const;
private:
class ItemPrivate;
ItemPrivate *d;

View File

@ -38,7 +38,13 @@ using namespace TagLib;
class MP4::Properties::PropertiesPrivate
{
public:
PropertiesPrivate() : length(0), bitrate(0), sampleRate(0), channels(0), bitsPerSample(0), encrypted(false) {}
PropertiesPrivate() : length(0), bitrate(0), sampleRate(0), channels(0), bitsPerSample(0), encrypted(false), format(Unknown) {}
enum Format {
Unknown = 0,
AAC = 1,
ALAC = 2,
};
int length;
int bitrate;
@ -46,6 +52,7 @@ public:
int channels;
int bitsPerSample;
bool encrypted;
Format format;
};
MP4::Properties::Properties(File *file, MP4::Atoms *atoms, ReadStyle style)
@ -118,6 +125,7 @@ MP4::Properties::Properties(File *file, MP4::Atoms *atoms, ReadStyle style)
file->seek(atom->offset);
data = file->readBlock(atom->length);
if(data.mid(20, 4) == "mp4a") {
d->format = PropertiesPrivate::AAC;
d->channels = data.mid(40, 2).toShort();
d->bitsPerSample = data.mid(42, 2).toShort();
d->sampleRate = data.mid(46, 4).toUInt();
@ -138,6 +146,7 @@ MP4::Properties::Properties(File *file, MP4::Atoms *atoms, ReadStyle style)
}
}
else if (data.mid(20, 4) == "alac") {
d->format = PropertiesPrivate::ALAC;
if (atom->length == 88 && data.mid(56, 4) == "alac") {
d->bitsPerSample = data.at(69);
d->channels = data.at(73);
@ -193,3 +202,23 @@ MP4::Properties::isEncrypted() const
return d->encrypted;
}
String
MP4::Properties::toString() const
{
String format;
if(d->format == PropertiesPrivate::AAC) {
format = "AAC";
}
else if(d->format == PropertiesPrivate::ALAC) {
format = "ALAC";
}
else {
format = "Unknown";
}
StringList desc;
desc.append("MPEG-4 audio (" + format + ")");
desc.append(String::number(length()) + " seconds");
desc.append(String::number(bitrate()) + " kbps");
return desc.toString(", ");
}

View File

@ -50,6 +50,8 @@ namespace TagLib {
virtual int bitsPerSample() const;
bool isEncrypted() const;
String toString() const;
private:
class PropertiesPrivate;
PropertiesPrivate *d;

View File

@ -759,3 +759,13 @@ MP4::Tag::itemListMap()
return d->items;
}
String
MP4::Tag::toString() const
{
StringList desc;
for(MP4::ItemListMap::Iterator i = d->items.begin(); i != d->items.end(); i++) {
desc.append(i->first + "=" + i->second.toString());
}
return desc.toString("\n");
}

View File

@ -67,6 +67,8 @@ namespace TagLib {
ItemListMap &itemListMap();
String toString() const;
private:
AtomDataList parseData2(Atom *atom, TagLib::File *file, int expectedFlags = -1, bool freeForm = false);
TagLib::ByteVectorList parseData(Atom *atom, TagLib::File *file, int expectedFlags = -1, bool freeForm = false);