${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mpeg
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mpeg/id3v1
${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mpeg/id3v2
+ ${CMAKE_CURRENT_SOURCE_DIR}/../taglib/mp4
${CMAKE_CURRENT_SOURCE_DIR}/../bindings/c/ )
if(ENABLE_STATIC)
TARGET_LINK_LIBRARIES(strip-id3v1 tag )
+########### next target ###############
+
+ADD_EXECUTABLE(inspect inspect.cpp)
+
+TARGET_LINK_LIBRARIES(inspect tag )
+
+
endif(BUILD_EXAMPLES)
--- /dev/null
+/* Copyright (C) 2012 Lukas Lalinsky <lalinsky@gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <iostream>
+#include <stdlib.h>
+
+#include <fileref.h>
+#include <mp4file.h>
+
+using namespace std;
+using namespace TagLib;
+
+#define MAYBE_PRINT_DESC(_Type) \
+ if(dynamic_cast<_Type *>(f.file())) { \
+ cout << dynamic_cast<_Type *>(f.file())->toString().to8Bit(true) << endl; \
+ found = 1; \
+ }
+
+int main(int argc, char *argv[])
+{
+ // process the command line args
+
+ for(int i = 1; i < argc; i++) {
+
+ cout << "******************** \"" << argv[i] << "\"********************" << endl;
+
+ FileRef f(argv[i]);
+
+ bool found = 0;
+ if(!f.isNull() && f.file()) {
+ MAYBE_PRINT_DESC(MP4::File);
+ MAYBE_PRINT_DESC(File);
+ }
+
+ if(!found) {
+ cout << "could not find any information about the file" << endl;
+ }
+
+ }
+}
***************************************************************************/
#include "audioproperties.h"
+#include "tstringlist.h"
using namespace TagLib;
{
}
+
+String
+AudioProperties::toString() const
+{
+ StringList desc;
+ desc.append("Audio");
+ desc.append(String::number(length()) + " seconds");
+ desc.append(String::number(bitrate()) + " kbps");
+ return desc.toString(", ");
+}
#define TAGLIB_AUDIOPROPERTIES_H
#include "taglib_export.h"
+#include "tstring.h"
namespace TagLib {
*/
virtual int channels() const = 0;
+ String toString() const;
+
protected:
/*!
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");
+}
+
*/
bool save();
+ /*!
+ * Description of the file.
+ */
+ String toString() const;
+
private:
void read(bool readProperties, Properties::ReadStyle audioPropertiesStyle);
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
+#include <stdio.h>
#include <taglib.h>
#include <tdebug.h>
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;
{
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)
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)
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();
+}
+
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);
ByteVectorList toByteVectorList() const;
CoverArtList toCoverArtList() const;
+ ItemType type() const;
+
bool isValid() const;
+ String toString() const;
+
private:
class ItemPrivate;
ItemPrivate *d;
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;
int channels;
int bitsPerSample;
bool encrypted;
+ Format format;
};
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();
}
}
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);
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(", ");
+}
+
virtual int bitsPerSample() const;
bool isEncrypted() const;
+ String toString() const;
+
private:
class PropertiesPrivate;
PropertiesPrivate *d;
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");
+}
+
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);
target->setTrack(source->track());
}
}
+
+String Tag::toString() const
+{
+ StringList desc;
+ desc.append("title=" + title());
+ desc.append("artist=" + artist());
+ desc.append("album=" + album());
+ desc.append("comment=" + comment());
+ desc.append("genre=" + genre());
+ desc.append("year=" + String::number(year()));
+ desc.append("track=" + String::number(track()));
+ return desc.toString("\n");
+}
+
*/
static void duplicate(const Tag *source, Tag *target, bool overwrite = true);
+ String toString() const;
+
protected:
/*!
* Construct a Tag. This is protected since tags should only be instantiated
}
+String File::toString() const
+{
+ StringList desc;
+ AudioProperties *properties = audioProperties();
+ if(properties) {
+ desc.append(properties->toString());
+ }
+ Tag *t = tag();
+ if(t) {
+ desc.append(t->toString());
+ }
+ return desc.toString("\n");
+}
+
////////////////////////////////////////////////////////////////////////////////
// protected members
////////////////////////////////////////////////////////////////////////////////
*/
static bool isWritable(const char *name);
+ /*!
+ * Description of the file.
+ */
+ String toString() const;
+
protected:
/*!
* Construct a File object and opens the \a file. \a file should be a