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

@ -46,16 +46,14 @@
using namespace Strawberry_TagLib::TagLib;
namespace
{
enum { ApeAPEIndex = 0, ApeID3v1Index = 1 };
namespace {
enum { ApeAPEIndex = 0,
ApeID3v1Index = 1 };
}
class APE::File::FilePrivate
{
public:
FilePrivate() :
APELocation(-1),
class APE::File::FilePrivate {
public:
FilePrivate() : APELocation(-1),
APESize(0),
ID3v1Location(-1),
ID3v2Header(0),
@ -63,8 +61,7 @@ public:
ID3v2Size(0),
properties(0) {}
~FilePrivate()
{
~FilePrivate() {
delete ID3v2Header;
delete properties;
}
@ -87,8 +84,7 @@ public:
// static members
////////////////////////////////////////////////////////////////////////////////
bool APE::File::isSupported(IOStream*)
{
bool APE::File::isSupported(IOStream *) {
// An APE file has an ID "MAC " somewhere. An ID3v2 tag may precede.
// FIXME:
@ -102,69 +98,58 @@ bool APE::File::isSupported(IOStream*)
// public members
////////////////////////////////////////////////////////////////////////////////
APE::File::File(FileName file, bool readProperties, Properties::ReadStyle) :
Strawberry_TagLib::TagLib::File(file),
d(new FilePrivate())
{
if(isOpen())
APE::File::File(FileName file, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file),
d(new FilePrivate()) {
if (isOpen())
read(readProperties);
}
APE::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) :
Strawberry_TagLib::TagLib::File(stream),
d(new FilePrivate())
{
if(isOpen())
APE::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(stream),
d(new FilePrivate()) {
if (isOpen())
read(readProperties);
}
APE::File::~File()
{
APE::File::~File() {
delete d;
}
Strawberry_TagLib::TagLib::Tag *APE::File::tag() const
{
Strawberry_TagLib::TagLib::Tag *APE::File::tag() const {
return &d->tag;
}
PropertyMap APE::File::properties() const
{
PropertyMap APE::File::properties() const {
return d->tag.properties();
}
void APE::File::removeUnsupportedProperties(const StringList &properties)
{
void APE::File::removeUnsupportedProperties(const StringList &properties) {
d->tag.removeUnsupportedProperties(properties);
}
PropertyMap APE::File::setProperties(const PropertyMap &properties)
{
if(ID3v1Tag())
PropertyMap APE::File::setProperties(const PropertyMap &properties) {
if (ID3v1Tag())
ID3v1Tag()->setProperties(properties);
return APETag(true)->setProperties(properties);
}
APE::Properties *APE::File::audioProperties() const
{
APE::Properties *APE::File::audioProperties() const {
return d->properties;
}
bool APE::File::save()
{
if(readOnly()) {
bool APE::File::save() {
if (readOnly()) {
debug("APE::File::save() -- File is read only.");
return false;
}
// Update ID3v1 tag
if(ID3v1Tag() && !ID3v1Tag()->isEmpty()) {
if (ID3v1Tag() && !ID3v1Tag()->isEmpty()) {
// ID3v1 tag is not empty. Update the old one or create a new one.
if(d->ID3v1Location >= 0) {
if (d->ID3v1Location >= 0) {
seek(d->ID3v1Location);
}
else {
@ -178,7 +163,7 @@ bool APE::File::save()
// ID3v1 tag is empty. Remove the old one.
if(d->ID3v1Location >= 0) {
if (d->ID3v1Location >= 0) {
truncate(d->ID3v1Location);
d->ID3v1Location = -1;
}
@ -186,12 +171,12 @@ bool APE::File::save()
// Update APE tag
if(APETag() && !APETag()->isEmpty()) {
if (APETag() && !APETag()->isEmpty()) {
// APE tag is not empty. Update the old one or create a new one.
if(d->APELocation < 0) {
if(d->ID3v1Location >= 0)
if (d->APELocation < 0) {
if (d->ID3v1Location >= 0)
d->APELocation = d->ID3v1Location;
else
d->APELocation = length();
@ -200,7 +185,7 @@ bool APE::File::save()
const ByteVector data = APETag()->render();
insert(data, d->APELocation, d->APESize);
if(d->ID3v1Location >= 0)
if (d->ID3v1Location >= 0)
d->ID3v1Location += (static_cast<long>(data.size()) - d->APESize);
d->APESize = data.size();
@ -209,10 +194,10 @@ bool APE::File::save()
// APE tag is empty. Remove the old one.
if(d->APELocation >= 0) {
if (d->APELocation >= 0) {
removeBlock(d->APELocation, d->APESize);
if(d->ID3v1Location >= 0)
if (d->ID3v1Location >= 0)
d->ID3v1Location -= d->APESize;
d->APELocation = -1;
@ -223,35 +208,30 @@ bool APE::File::save()
return true;
}
ID3v1::Tag *APE::File::ID3v1Tag(bool create)
{
ID3v1::Tag *APE::File::ID3v1Tag(bool create) {
return d->tag.access<ID3v1::Tag>(ApeID3v1Index, create);
}
APE::Tag *APE::File::APETag(bool create)
{
APE::Tag *APE::File::APETag(bool create) {
return d->tag.access<APE::Tag>(ApeAPEIndex, create);
}
void APE::File::strip(int tags)
{
if(tags & ID3v1)
void APE::File::strip(int tags) {
if (tags & ID3v1)
d->tag.set(ApeID3v1Index, 0);
if(tags & APE)
if (tags & APE)
d->tag.set(ApeAPEIndex, 0);
if(!ID3v1Tag())
if (!ID3v1Tag())
APETag(true);
}
bool APE::File::hasAPETag() const
{
bool APE::File::hasAPETag() const {
return (d->APELocation >= 0);
}
bool APE::File::hasID3v1Tag() const
{
bool APE::File::hasID3v1Tag() const {
return (d->ID3v1Location >= 0);
}
@ -259,13 +239,12 @@ bool APE::File::hasID3v1Tag() const
// private members
////////////////////////////////////////////////////////////////////////////////
void APE::File::read(bool readProperties)
{
void APE::File::read(bool readProperties) {
// Look for an ID3v2 tag
d->ID3v2Location = Utils::findID3v2(this);
if(d->ID3v2Location >= 0) {
if (d->ID3v2Location >= 0) {
seek(d->ID3v2Location);
d->ID3v2Header = new ID3v2::Header(readBlock(ID3v2::Header::size()));
d->ID3v2Size = d->ID3v2Header->completeTagSize();
@ -275,36 +254,36 @@ void APE::File::read(bool readProperties)
d->ID3v1Location = Utils::findID3v1(this);
if(d->ID3v1Location >= 0)
if (d->ID3v1Location >= 0)
d->tag.set(ApeID3v1Index, new ID3v1::Tag(this, d->ID3v1Location));
// Look for an APE tag
d->APELocation = Utils::findAPE(this, d->ID3v1Location);
if(d->APELocation >= 0) {
if (d->APELocation >= 0) {
d->tag.set(ApeAPEIndex, new APE::Tag(this, d->APELocation));
d->APESize = APETag()->footer()->completeTagSize();
d->APELocation = d->APELocation + APE::Footer::size() - d->APESize;
}
if(d->ID3v1Location < 0)
if (d->ID3v1Location < 0)
APETag(true);
// Look for APE audio properties
if(readProperties) {
if (readProperties) {
long streamLength;
if(d->APELocation >= 0)
if (d->APELocation >= 0)
streamLength = d->APELocation;
else if(d->ID3v1Location >= 0)
else if (d->ID3v1Location >= 0)
streamLength = d->ID3v1Location;
else
streamLength = length();
if(d->ID3v2Location >= 0) {
if (d->ID3v2Location >= 0) {
seek(d->ID3v2Location + d->ID3v2Size);
streamLength -= (d->ID3v2Location + d->ID3v2Size);
}

View File

@ -41,33 +41,36 @@
namespace Strawberry_TagLib {
namespace TagLib {
class Tag;
class Tag;
namespace ID3v1 { class Tag; }
namespace APE { class Tag; }
namespace ID3v1 {
class Tag;
}
namespace APE {
class Tag;
}
//! An implementation of APE metadata
//! An implementation of APE metadata
/*!
/*!
* This is implementation of APE metadata.
*
* This supports ID3v1 and APE (v1 and v2) style comments as well as reading stream
* properties from the file.
*/
namespace APE {
namespace APE {
//! An implementation of TagLib::File with APE specific methods
//! An implementation of TagLib::File with APE specific methods
/*!
/*!
* This implements and provides an interface for APE 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 APE files.
*/
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File
{
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File {
public:
/*!
* This set of flags is used for various operations and is suitable for
@ -229,9 +232,9 @@ namespace TagLib {
class FilePrivate;
FilePrivate *d;
};
}
}
}
};
} // namespace APE
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -35,11 +35,9 @@
using namespace Strawberry_TagLib::TagLib;
using namespace APE;
class APE::Footer::FooterPrivate
{
public:
FooterPrivate() :
version(0),
class APE::Footer::FooterPrivate {
public:
FooterPrivate() : version(0),
footerPresent(true),
headerPresent(false),
isHeader(false),
@ -61,13 +59,11 @@ public:
// static members
////////////////////////////////////////////////////////////////////////////////
unsigned int APE::Footer::size()
{
unsigned int APE::Footer::size() {
return 32;
}
ByteVector APE::Footer::fileIdentifier()
{
ByteVector APE::Footer::fileIdentifier() {
return ByteVector("APETAGEX");
}
@ -75,88 +71,70 @@ ByteVector APE::Footer::fileIdentifier()
// public members
////////////////////////////////////////////////////////////////////////////////
APE::Footer::Footer() :
d(new FooterPrivate())
{
APE::Footer::Footer() : d(new FooterPrivate()) {
}
APE::Footer::Footer(const ByteVector &data) :
d(new FooterPrivate())
{
APE::Footer::Footer(const ByteVector &data) : d(new FooterPrivate()) {
parse(data);
}
APE::Footer::~Footer()
{
APE::Footer::~Footer() {
delete d;
}
unsigned int APE::Footer::version() const
{
unsigned int APE::Footer::version() const {
return d->version;
}
bool APE::Footer::headerPresent() const
{
bool APE::Footer::headerPresent() const {
return d->headerPresent;
}
bool APE::Footer::footerPresent() const
{
bool APE::Footer::footerPresent() const {
return d->footerPresent;
}
bool APE::Footer::isHeader() const
{
bool APE::Footer::isHeader() const {
return d->isHeader;
}
void APE::Footer::setHeaderPresent(bool b) const
{
void APE::Footer::setHeaderPresent(bool b) const {
d->headerPresent = b;
}
unsigned int APE::Footer::itemCount() const
{
unsigned int APE::Footer::itemCount() const {
return d->itemCount;
}
void APE::Footer::setItemCount(unsigned int s)
{
void APE::Footer::setItemCount(unsigned int s) {
d->itemCount = s;
}
unsigned int APE::Footer::tagSize() const
{
unsigned int APE::Footer::tagSize() const {
return d->tagSize;
}
unsigned int APE::Footer::completeTagSize() const
{
if(d->headerPresent)
unsigned int APE::Footer::completeTagSize() const {
if (d->headerPresent)
return d->tagSize + size();
else
return d->tagSize;
}
void APE::Footer::setTagSize(unsigned int s)
{
void APE::Footer::setTagSize(unsigned int s) {
d->tagSize = s;
}
void APE::Footer::setData(const ByteVector &data)
{
void APE::Footer::setData(const ByteVector &data) {
parse(data);
}
ByteVector APE::Footer::renderFooter() const
{
ByteVector APE::Footer::renderFooter() const {
return render(false);
}
ByteVector APE::Footer::renderHeader() const
{
if(!d->headerPresent)
ByteVector APE::Footer::renderHeader() const {
if (!d->headerPresent)
return ByteVector();
else
return render(true);
@ -166,9 +144,8 @@ ByteVector APE::Footer::renderHeader() const
// protected members
////////////////////////////////////////////////////////////////////////////////
void APE::Footer::parse(const ByteVector &data)
{
if(data.size() < size())
void APE::Footer::parse(const ByteVector &data) {
if (data.size() < size())
return;
// The first eight bytes, data[0..7], are the File Identifier, "APETAGEX".
@ -192,11 +169,9 @@ void APE::Footer::parse(const ByteVector &data)
d->headerPresent = flags[31];
d->footerPresent = !flags[30];
d->isHeader = flags[29];
}
ByteVector APE::Footer::render(bool isHeader) const
{
ByteVector APE::Footer::render(bool isHeader) const {
ByteVector v;
// add the file identifier -- "APETAGEX"

View File

@ -32,19 +32,18 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace APE {
namespace APE {
//! An implementation of APE footers
//! An implementation of APE footers
/*!
/*!
* This class implements APE footers (and headers). It attempts to follow, both
* semantically and programmatically, the structure specified in
* the APE v2.0 standard. The API is based on the properties of APE footer and
* headers specified there.
*/
class TAGLIB_EXPORT Footer
{
class TAGLIB_EXPORT Footer {
public:
/*!
* Constructs an empty APE footer.
@ -166,10 +165,10 @@ namespace TagLib {
class FooterPrivate;
FooterPrivate *d;
};
};
}
}
}
} // namespace APE
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -31,11 +31,9 @@
using namespace Strawberry_TagLib::TagLib;
using namespace APE;
class APE::Item::ItemPrivate
{
public:
ItemPrivate() :
type(Text),
class APE::Item::ItemPrivate {
public:
ItemPrivate() : type(Text),
readOnly(false) {}
Item::ItemTypes type;
@ -49,30 +47,22 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
APE::Item::Item() :
d(new ItemPrivate())
{
APE::Item::Item() : d(new ItemPrivate()) {
}
APE::Item::Item(const String &key, const String &value) :
d(new ItemPrivate())
{
APE::Item::Item(const String &key, const String &value) : d(new ItemPrivate()) {
d->key = key;
d->text.append(value);
}
APE::Item::Item(const String &key, const StringList &values) :
d(new ItemPrivate())
{
APE::Item::Item(const String &key, const StringList &values) : d(new ItemPrivate()) {
d->key = key;
d->text = values;
}
APE::Item::Item(const String &key, const ByteVector &value, bool binary) :
d(new ItemPrivate())
{
APE::Item::Item(const String &key, const ByteVector &value, bool binary) : d(new ItemPrivate()) {
d->key = key;
if(binary) {
if (binary) {
d->type = Binary;
d->value = value;
}
@ -81,118 +71,99 @@ APE::Item::Item(const String &key, const ByteVector &value, bool binary) :
}
}
APE::Item::Item(const Item &item) :
d(new ItemPrivate(*item.d))
{
APE::Item::Item(const Item &item) : d(new ItemPrivate(*item.d)) {
}
APE::Item::~Item()
{
APE::Item::~Item() {
delete d;
}
Item &APE::Item::operator=(const Item &item)
{
Item &APE::Item::operator=(const Item &item) {
Item(item).swap(*this);
return *this;
}
void APE::Item::swap(Item &item)
{
void APE::Item::swap(Item &item) {
using std::swap;
swap(d, item.d);
}
void APE::Item::setReadOnly(bool readOnly)
{
void APE::Item::setReadOnly(bool readOnly) {
d->readOnly = readOnly;
}
bool APE::Item::isReadOnly() const
{
bool APE::Item::isReadOnly() const {
return d->readOnly;
}
void APE::Item::setType(APE::Item::ItemTypes val)
{
void APE::Item::setType(APE::Item::ItemTypes val) {
d->type = val;
}
APE::Item::ItemTypes APE::Item::type() const
{
APE::Item::ItemTypes APE::Item::type() const {
return d->type;
}
String APE::Item::key() const
{
String APE::Item::key() const {
return d->key;
}
ByteVector APE::Item::binaryData() const
{
ByteVector APE::Item::binaryData() const {
return d->value;
}
void APE::Item::setBinaryData(const ByteVector &value)
{
void APE::Item::setBinaryData(const ByteVector &value) {
d->type = Binary;
d->value = value;
d->text.clear();
}
ByteVector APE::Item::value() const
{
ByteVector APE::Item::value() const {
// This seems incorrect as it won't be actually rendering the value to keep it
// up to date.
return d->value;
}
void APE::Item::setKey(const String &key)
{
void APE::Item::setKey(const String &key) {
d->key = key;
}
void APE::Item::setValue(const String &value)
{
void APE::Item::setValue(const String &value) {
d->type = Text;
d->text = value;
d->value.clear();
}
void APE::Item::setValues(const StringList &value)
{
void APE::Item::setValues(const StringList &value) {
d->type = Text;
d->text = value;
d->value.clear();
}
void APE::Item::appendValue(const String &value)
{
void APE::Item::appendValue(const String &value) {
d->type = Text;
d->text.append(value);
d->value.clear();
}
void APE::Item::appendValues(const StringList &values)
{
void APE::Item::appendValues(const StringList &values) {
d->type = Text;
d->text.append(values);
d->value.clear();
}
int APE::Item::size() const
{
int APE::Item::size() const {
int result = 8 + d->key.size() + 1;
switch(d->type) {
switch (d->type) {
case Text:
if(!d->text.isEmpty()) {
if (!d->text.isEmpty()) {
StringList::ConstIterator it = d->text.begin();
result += it->data(String::UTF8).size();
it++;
for(; it != d->text.end(); ++it)
for (; it != d->text.end(); ++it)
result += 1 + it->data(String::UTF8).size();
}
break;
@ -205,31 +176,27 @@ int APE::Item::size() const
return result;
}
StringList APE::Item::toStringList() const
{
StringList APE::Item::toStringList() const {
return d->text;
}
StringList APE::Item::values() const
{
StringList APE::Item::values() const {
return d->text;
}
String APE::Item::toString() const
{
if(d->type == Text && !isEmpty())
String APE::Item::toString() const {
if (d->type == Text && !isEmpty())
return d->text.front();
else
return String();
}
bool APE::Item::isEmpty() const
{
switch(d->type) {
bool APE::Item::isEmpty() const {
switch (d->type) {
case Text:
if(d->text.isEmpty())
if (d->text.isEmpty())
return true;
if(d->text.size() == 1 && d->text.front().isEmpty())
if (d->text.size() == 1 && d->text.front().isEmpty())
return true;
return false;
case Binary:
@ -240,11 +207,10 @@ bool APE::Item::isEmpty() const
}
}
void APE::Item::parse(const ByteVector &data)
{
void APE::Item::parse(const ByteVector &data) {
// 11 bytes is the minimum size for an APE item
if(data.size() < 11) {
if (data.size() < 11) {
debug("APE::Item::parse() -- no data in item");
return;
}
@ -262,27 +228,26 @@ void APE::Item::parse(const ByteVector &data)
setReadOnly(flags & 1);
setType(ItemTypes((flags >> 1) & 3));
if(Text == d->type)
if (Text == d->type)
d->text = StringList(ByteVectorList::split(value, '\0'), String::UTF8);
else
d->value = value;
}
ByteVector APE::Item::render() const
{
ByteVector APE::Item::render() const {
ByteVector data;
unsigned int flags = ((d->readOnly) ? 1 : 0) | (d->type << 1);
ByteVector value;
if(isEmpty())
if (isEmpty())
return data;
if(d->type == Text) {
if (d->type == Text) {
StringList::ConstIterator it = d->text.begin();
value.append(it->data(String::UTF8));
it++;
for(; it != d->text.end(); ++it) {
for (; it != d->text.end(); ++it) {
value.append('\0');
value.append(it->data(String::UTF8));
}

View File

@ -33,15 +33,14 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace APE {
namespace APE {
//! An implementation of APE-items
//! An implementation of APE-items
/*!
/*!
* This class provides the features of items in the APEv2 standard.
*/
class TAGLIB_EXPORT Item
{
class TAGLIB_EXPORT Item {
public:
/*!
* Enum of types an Item can have. The value of 3 is reserved.
@ -183,7 +182,7 @@ namespace TagLib {
/*!
* Parse the item from the ByteVector \a data.
*/
void parse(const ByteVector& data);
void parse(const ByteVector &data);
/*!
* Set the item to read-only.
@ -215,12 +214,10 @@ namespace TagLib {
private:
class ItemPrivate;
ItemPrivate *d;
};
}
};
} // namespace APE
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -38,11 +38,9 @@
using namespace Strawberry_TagLib::TagLib;
class APE::Properties::PropertiesPrivate
{
public:
PropertiesPrivate() :
length(0),
class APE::Properties::PropertiesPrivate {
public:
PropertiesPrivate() : length(0),
bitrate(0),
sampleRate(0),
channels(0),
@ -63,67 +61,53 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
APE::Properties::Properties(File *, ReadStyle style) :
AudioProperties(style),
d(new PropertiesPrivate())
{
APE::Properties::Properties(File *, ReadStyle style) : AudioProperties(style),
d(new PropertiesPrivate()) {
debug("APE::Properties::Properties() -- This constructor is no longer used.");
}
APE::Properties::Properties(File *file, long streamLength, ReadStyle style) :
AudioProperties(style),
d(new PropertiesPrivate())
{
APE::Properties::Properties(File *file, long streamLength, ReadStyle style) : AudioProperties(style),
d(new PropertiesPrivate()) {
read(file, streamLength);
}
APE::Properties::~Properties()
{
APE::Properties::~Properties() {
delete d;
}
int APE::Properties::length() const
{
int APE::Properties::length() const {
return lengthInSeconds();
}
int APE::Properties::lengthInSeconds() const
{
int APE::Properties::lengthInSeconds() const {
return d->length / 1000;
}
int APE::Properties::lengthInMilliseconds() const
{
int APE::Properties::lengthInMilliseconds() const {
return d->length;
}
int APE::Properties::bitrate() const
{
int APE::Properties::bitrate() const {
return d->bitrate;
}
int APE::Properties::sampleRate() const
{
int APE::Properties::sampleRate() const {
return d->sampleRate;
}
int APE::Properties::channels() const
{
int APE::Properties::channels() const {
return d->channels;
}
int APE::Properties::version() const
{
int APE::Properties::version() const {
return d->version;
}
int APE::Properties::bitsPerSample() const
{
int APE::Properties::bitsPerSample() const {
return d->bitsPerSample;
}
unsigned int APE::Properties::sampleFrames() const
{
unsigned int APE::Properties::sampleFrames() const {
return d->sampleFrames;
}
@ -131,67 +115,63 @@ unsigned int APE::Properties::sampleFrames() const
// private members
////////////////////////////////////////////////////////////////////////////////
namespace
{
int headerVersion(const ByteVector &header)
{
if(header.size() < 6 || !header.startsWith("MAC "))
namespace {
int headerVersion(const ByteVector &header) {
if (header.size() < 6 || !header.startsWith("MAC "))
return -1;
return header.toUShort(4, false);
}
}
} // namespace
void APE::Properties::read(File *file, long streamLength)
{
void APE::Properties::read(File *file, long streamLength) {
// First, we assume that the file pointer is set at the first descriptor.
long offset = file->tell();
int version = headerVersion(file->readBlock(6));
// Next, we look for the descriptor.
if(version < 0) {
if (version < 0) {
offset = file->find("MAC ", offset);
file->seek(offset);
version = headerVersion(file->readBlock(6));
}
if(version < 0) {
if (version < 0) {
debug("APE::Properties::read() -- APE descriptor not found");
return;
}
d->version = version;
if(d->version >= 3980)
if (d->version >= 3980)
analyzeCurrent(file);
else
analyzeOld(file);
if(d->sampleFrames > 0 && d->sampleRate > 0) {
if (d->sampleFrames > 0 && d->sampleRate > 0) {
const double length = d->sampleFrames * 1000.0 / d->sampleRate;
d->length = static_cast<int>(length + 0.5);
d->bitrate = static_cast<int>(streamLength * 8.0 / length + 0.5);
}
}
void APE::Properties::analyzeCurrent(File *file)
{
void APE::Properties::analyzeCurrent(File *file) {
// Read the descriptor
file->seek(2, File::Current);
const ByteVector descriptor = file->readBlock(44);
if(descriptor.size() < 44) {
if (descriptor.size() < 44) {
debug("APE::Properties::analyzeCurrent() -- descriptor is too short.");
return;
}
const unsigned int descriptorBytes = descriptor.toUInt(0, false);
if((descriptorBytes - 52) > 0)
if ((descriptorBytes - 52) > 0)
file->seek(descriptorBytes - 52, File::Current);
// Read the header
const ByteVector header = file->readBlock(24);
if(header.size() < 24) {
if (header.size() < 24) {
debug("APE::Properties::analyzeCurrent() -- MAC header is too short.");
return;
}
@ -202,7 +182,7 @@ void APE::Properties::analyzeCurrent(File *file)
d->bitsPerSample = header.toShort(16, false);
const unsigned int totalFrames = header.toUInt(12, false);
if(totalFrames == 0)
if (totalFrames == 0)
return;
const unsigned int blocksPerFrame = header.toUInt(4, false);
@ -210,10 +190,9 @@ void APE::Properties::analyzeCurrent(File *file)
d->sampleFrames = (totalFrames - 1) * blocksPerFrame + finalFrameBlocks;
}
void APE::Properties::analyzeOld(File *file)
{
void APE::Properties::analyzeOld(File *file) {
const ByteVector header = file->readBlock(26);
if(header.size() < 26) {
if (header.size() < 26) {
debug("APE::Properties::analyzeOld() -- MAC header is too short.");
return;
}
@ -221,14 +200,14 @@ void APE::Properties::analyzeOld(File *file)
const unsigned int totalFrames = header.toUInt(18, false);
// Fail on 0 length APE files (catches non-finalized APE files)
if(totalFrames == 0)
if (totalFrames == 0)
return;
const short compressionLevel = header.toShort(0, false);
unsigned int blocksPerFrame;
if(d->version >= 3950)
if (d->version >= 3950)
blocksPerFrame = 73728 * 4;
else if(d->version >= 3900 || (d->version >= 3800 && compressionLevel == 4000))
else if (d->version >= 3900 || (d->version >= 3800 && compressionLevel == 4000))
blocksPerFrame = 73728;
else
blocksPerFrame = 9216;
@ -243,7 +222,7 @@ void APE::Properties::analyzeOld(File *file)
// Get the bit depth from the RIFF-fmt chunk.
file->seek(16, File::Current);
const ByteVector fmt = file->readBlock(28);
if(fmt.size() < 28 || !fmt.startsWith("WAVEfmt ")) {
if (fmt.size() < 28 || !fmt.startsWith("WAVEfmt ")) {
debug("APE::Properties::analyzeOld() -- fmt header is too short.");
return;
}

View File

@ -36,19 +36,18 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace APE {
namespace APE {
class File;
class File;
//! An implementation of audio property reading for APE
//! An implementation of audio property reading for APE
/*!
/*!
* This reads the data from an APE stream found in the AudioProperties
* API.
*/
class TAGLIB_EXPORT Properties : public AudioProperties
{
class TAGLIB_EXPORT Properties : public AudioProperties {
public:
/*!
* Create an instance of APE::Properties with the data read from the
@ -137,9 +136,9 @@ namespace TagLib {
class PropertiesPrivate;
PropertiesPrivate *d;
};
}
}
}
};
} // namespace APE
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -28,7 +28,7 @@
// 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)
# define WANT_CLASS_INSTANTIATION_OF_MAP (1)
#endif
#include <tfile.h>
@ -45,39 +45,35 @@
using namespace Strawberry_TagLib::TagLib;
using namespace APE;
namespace
{
const unsigned int MinKeyLength = 2;
const unsigned int MaxKeyLength = 255;
namespace {
const unsigned int MinKeyLength = 2;
const unsigned int MaxKeyLength = 255;
bool isKeyValid(const ByteVector &key) {
bool isKeyValid(const ByteVector &key)
{
const char *invalidKeys[] = { "ID3", "TAG", "OGGS", "MP+", 0 };
// only allow printable ASCII including space (32..126)
for(ByteVector::ConstIterator it = key.begin(); it != key.end(); ++it) {
for (ByteVector::ConstIterator it = key.begin(); it != key.end(); ++it) {
const int c = static_cast<unsigned char>(*it);
if(c < 32 || c > 126)
if (c < 32 || c > 126)
return false;
}
const String upperKey = String(key).upper();
for(size_t i = 0; invalidKeys[i] != 0; ++i) {
if(upperKey == invalidKeys[i])
for (size_t i = 0; invalidKeys[i] != 0; ++i) {
if (upperKey == invalidKeys[i])
return false;
}
return true;
}
}
} // namespace
class APE::Tag::TagPrivate
{
public:
TagPrivate() :
file(0),
footerLocation(0) {}
class APE::Tag::TagPrivate {
public:
TagPrivate() : file(0), footerLocation(0) {}
File *file;
long footerLocation;
@ -90,150 +86,140 @@ public:
// public methods
////////////////////////////////////////////////////////////////////////////////
APE::Tag::Tag() :
Strawberry_TagLib::TagLib::Tag(),
d(new TagPrivate())
{
}
APE::Tag::Tag() : Strawberry_TagLib::TagLib::Tag(), d(new TagPrivate()) {}
APE::Tag::Tag(Strawberry_TagLib::TagLib::File *file, long footerLocation) : Strawberry_TagLib::TagLib::Tag(), d(new TagPrivate()) {
APE::Tag::Tag(Strawberry_TagLib::TagLib::File *file, long footerLocation) :
Strawberry_TagLib::TagLib::Tag(),
d(new TagPrivate())
{
d->file = file;
d->footerLocation = footerLocation;
read();
}
APE::Tag::~Tag()
{
APE::Tag::~Tag() {
delete d;
}
ByteVector APE::Tag::fileIdentifier()
{
ByteVector APE::Tag::fileIdentifier() {
return ByteVector::fromCString("APETAGEX");
}
String APE::Tag::title() const
{
if(d->itemListMap["TITLE"].isEmpty())
String APE::Tag::title() const {
if (d->itemListMap["TITLE"].isEmpty())
return String();
return d->itemListMap["TITLE"].values().toString();
}
String APE::Tag::artist() const
{
if(d->itemListMap["ARTIST"].isEmpty())
String APE::Tag::artist() const {
if (d->itemListMap["ARTIST"].isEmpty())
return String();
return d->itemListMap["ARTIST"].values().toString();
}
String APE::Tag::album() const
{
if(d->itemListMap["ALBUM"].isEmpty())
String APE::Tag::album() const {
if (d->itemListMap["ALBUM"].isEmpty())
return String();
return d->itemListMap["ALBUM"].values().toString();
}
String APE::Tag::comment() const
{
if(d->itemListMap["COMMENT"].isEmpty())
String APE::Tag::comment() const {
if (d->itemListMap["COMMENT"].isEmpty())
return String();
return d->itemListMap["COMMENT"].values().toString();
}
String APE::Tag::genre() const
{
if(d->itemListMap["GENRE"].isEmpty())
String APE::Tag::genre() const {
if (d->itemListMap["GENRE"].isEmpty())
return String();
return d->itemListMap["GENRE"].values().toString();
}
unsigned int APE::Tag::year() const
{
if(d->itemListMap["YEAR"].isEmpty())
unsigned int APE::Tag::year() const {
if (d->itemListMap["YEAR"].isEmpty())
return 0;
return d->itemListMap["YEAR"].toString().toInt();
}
unsigned int APE::Tag::track() const
{
if(d->itemListMap["TRACK"].isEmpty())
unsigned int APE::Tag::track() const {
if (d->itemListMap["TRACK"].isEmpty())
return 0;
return d->itemListMap["TRACK"].toString().toInt();
}
void APE::Tag::setTitle(const String &s)
{
void APE::Tag::setTitle(const String &s) {
addValue("TITLE", s, true);
}
void APE::Tag::setArtist(const String &s)
{
void APE::Tag::setArtist(const String &s) {
addValue("ARTIST", s, true);
}
void APE::Tag::setAlbum(const String &s)
{
void APE::Tag::setAlbum(const String &s) {
addValue("ALBUM", s, true);
}
void APE::Tag::setComment(const String &s)
{
void APE::Tag::setComment(const String &s) {
addValue("COMMENT", s, true);
}
void APE::Tag::setGenre(const String &s)
{
void APE::Tag::setGenre(const String &s) {
addValue("GENRE", s, true);
}
void APE::Tag::setYear(unsigned int i)
{
if(i == 0)
void APE::Tag::setYear(unsigned int i) {
if (i == 0)
removeItem("YEAR");
else
addValue("YEAR", String::number(i), true);
}
void APE::Tag::setTrack(unsigned int i)
{
if(i == 0)
void APE::Tag::setTrack(unsigned int i) {
if (i == 0)
removeItem("TRACK");
else
addValue("TRACK", String::number(i), true);
}
namespace
{
// conversions of tag keys between what we use in PropertyMap and what's usual
// for APE tags
// usual, APE
const char *keyConversions[][2] = {{"TRACKNUMBER", "TRACK" },
{"DATE", "YEAR" },
{"ALBUMARTIST", "ALBUM ARTIST"},
{"DISCNUMBER", "DISC" },
{"REMIXER", "MIXARTIST" }};
const size_t keyConversionsSize = sizeof(keyConversions) / sizeof(keyConversions[0]);
}
namespace {
// conversions of tag keys between what we use in PropertyMap and what's usual
// for APE tags
// usual, APE
const char *keyConversions[][2] = { { "TRACKNUMBER", "TRACK" },
{ "DATE", "YEAR" },
{ "ALBUMARTIST", "ALBUM ARTIST" },
{ "DISCNUMBER", "DISC" },
{ "REMIXER", "MIXARTIST" } };
const size_t keyConversionsSize = sizeof(keyConversions) / sizeof(keyConversions[0]);
} // namespace
PropertyMap APE::Tag::properties() const
{
PropertyMap APE::Tag::properties() const {
PropertyMap properties;
ItemListMap::ConstIterator it = itemListMap().begin();
for(; it != itemListMap().end(); ++it) {
for (; it != itemListMap().end(); ++it) {
String tagName = it->first.upper();
// if the item is Binary or Locator, or if the key is an invalid string,
// add to unsupportedData
if(it->second.type() != Item::Text || tagName.isEmpty()) {
if (it->second.type() != Item::Text || tagName.isEmpty()) {
properties.unsupportedData().append(it->first);
}
else {
// Some tags need to be handled specially
for(size_t i = 0; i < keyConversionsSize; ++i) {
if(tagName == keyConversions[i][1])
for (size_t i = 0; i < keyConversionsSize; ++i) {
if (tagName == keyConversions[i][1])
tagName = keyConversions[i][0];
}
properties[tagName].append(it->second.toStringList());
@ -242,20 +228,18 @@ PropertyMap APE::Tag::properties() const
return properties;
}
void APE::Tag::removeUnsupportedProperties(const StringList &properties)
{
void APE::Tag::removeUnsupportedProperties(const StringList &properties) {
StringList::ConstIterator it = properties.begin();
for(; it != properties.end(); ++it)
for (; it != properties.end(); ++it)
removeItem(*it);
}
PropertyMap APE::Tag::setProperties(const PropertyMap &origProps)
{
PropertyMap APE::Tag::setProperties(const PropertyMap &origProps) {
PropertyMap properties(origProps); // make a local copy that can be modified
// see comment in properties()
for(size_t i = 0; i < keyConversionsSize; ++i)
if(properties.contains(keyConversions[i][0])) {
for (size_t i = 0; i < keyConversionsSize; ++i)
if (properties.contains(keyConversions[i][0])) {
properties.insert(keyConversions[i][1], properties[keyConversions[i][0]]);
properties.erase(keyConversions[i][0]);
}
@ -263,31 +247,31 @@ PropertyMap APE::Tag::setProperties(const PropertyMap &origProps)
// first check if tags need to be removed completely
StringList toRemove;
ItemListMap::ConstIterator remIt = itemListMap().begin();
for(; remIt != itemListMap().end(); ++remIt) {
for (; remIt != itemListMap().end(); ++remIt) {
String key = remIt->first.upper();
// only remove if a) key is valid, b) type is text, c) key not contained in new properties
if(!key.isEmpty() && remIt->second.type() == APE::Item::Text && !properties.contains(key))
if (!key.isEmpty() && remIt->second.type() == APE::Item::Text && !properties.contains(key))
toRemove.append(remIt->first);
}
for(StringList::ConstIterator removeIt = toRemove.begin(); removeIt != toRemove.end(); removeIt++)
for (StringList::ConstIterator removeIt = toRemove.begin(); removeIt != toRemove.end(); removeIt++)
removeItem(*removeIt);
// now sync in the "forward direction"
PropertyMap::ConstIterator it = properties.begin();
PropertyMap invalid;
for(; it != properties.end(); ++it) {
for (; it != properties.end(); ++it) {
const String &tagName = it->first;
if(!checkKey(tagName))
if (!checkKey(tagName))
invalid.insert(it->first, it->second);
else if(!(itemListMap().contains(tagName)) || !(itemListMap()[tagName].values() == it->second)) {
if(it->second.isEmpty())
else if (!(itemListMap().contains(tagName)) || !(itemListMap()[tagName].values() == it->second)) {
if (it->second.isEmpty())
removeItem(tagName);
else {
StringList::ConstIterator valueIt = it->second.begin();
addValue(tagName, *valueIt, true);
++valueIt;
for(; valueIt != it->second.end(); ++valueIt)
for (; valueIt != it->second.end(); ++valueIt)
addValue(tagName, *valueIt, false);
}
}
@ -295,35 +279,30 @@ PropertyMap APE::Tag::setProperties(const PropertyMap &origProps)
return invalid;
}
bool APE::Tag::checkKey(const String &key)
{
if(key.size() < MinKeyLength || key.size() > MaxKeyLength)
bool APE::Tag::checkKey(const String &key) {
if (key.size() < MinKeyLength || key.size() > MaxKeyLength)
return false;
return isKeyValid(key.data(String::UTF8));
}
APE::Footer *APE::Tag::footer() const
{
APE::Footer *APE::Tag::footer() const {
return &d->footer;
}
const APE::ItemListMap& APE::Tag::itemListMap() const
{
const APE::ItemListMap &APE::Tag::itemListMap() const {
return d->itemListMap;
}
void APE::Tag::removeItem(const String &key)
{
void APE::Tag::removeItem(const String &key) {
d->itemListMap.erase(key.upper());
}
void APE::Tag::addValue(const String &key, const String &value, bool replace)
{
if(replace)
void APE::Tag::addValue(const String &key, const String &value, bool replace) {
if (replace)
removeItem(key);
if(value.isEmpty())
if (value.isEmpty())
return;
// Text items may contain more than one value.
@ -331,25 +310,23 @@ void APE::Tag::addValue(const String &key, const String &value, bool replace)
ItemListMap::Iterator it = d->itemListMap.find(key.upper());
if(it != d->itemListMap.end() && it->second.type() == Item::Text)
if (it != d->itemListMap.end() && it->second.type() == Item::Text)
it->second.appendValue(value);
else
setItem(key, Item(key, value));
}
void APE::Tag::setData(const String &key, const ByteVector &value)
{
void APE::Tag::setData(const String &key, const ByteVector &value) {
removeItem(key);
if(value.isEmpty())
if (value.isEmpty())
return;
setItem(key, Item(key, value, true));
}
void APE::Tag::setItem(const String &key, const Item &item)
{
if(!checkKey(key)) {
void APE::Tag::setItem(const String &key, const Item &item) {
if (!checkKey(key)) {
debug("APE::Tag::setItem() - Couldn't set an item due to an invalid key.");
return;
}
@ -357,8 +334,7 @@ void APE::Tag::setItem(const String &key, const Item &item)
d->itemListMap[key.upper()] = item;
}
bool APE::Tag::isEmpty() const
{
bool APE::Tag::isEmpty() const {
return d->itemListMap.isEmpty();
}
@ -366,14 +342,13 @@ bool APE::Tag::isEmpty() const
// protected methods
////////////////////////////////////////////////////////////////////////////////
void APE::Tag::read()
{
if(d->file && d->file->isValid()) {
void APE::Tag::read() {
if (d->file && d->file->isValid()) {
d->file->seek(d->footerLocation);
d->footer.setData(d->file->readBlock(Footer::size()));
if(d->footer.tagSize() <= Footer::size() ||
if (d->footer.tagSize() <= Footer::size() ||
d->footer.tagSize() > static_cast<unsigned long>(d->file->length()))
return;
@ -382,12 +357,11 @@ void APE::Tag::read()
}
}
ByteVector APE::Tag::render() const
{
ByteVector APE::Tag::render() const {
ByteVector data;
unsigned int itemCount = 0;
for(ItemListMap::ConstIterator it = d->itemListMap.begin(); it != d->itemListMap.end(); ++it) {
for (ItemListMap::ConstIterator it = d->itemListMap.begin(); it != d->itemListMap.end(); ++it) {
data.append(it->second.render());
itemCount++;
}
@ -399,19 +373,18 @@ ByteVector APE::Tag::render() const
return d->footer.renderHeader() + data + d->footer.renderFooter();
}
void APE::Tag::parse(const ByteVector &data)
{
void APE::Tag::parse(const ByteVector &data) {
// 11 bytes is the minimum size for an APE item
if(data.size() < 11)
if (data.size() < 11)
return;
unsigned int pos = 0;
for(unsigned int i = 0; i < d->footer.itemCount() && pos <= data.size() - 11; i++) {
for (unsigned int i = 0; i < d->footer.itemCount() && pos <= data.size() - 11; i++) {
const int nullPos = data.find('\0', pos + 8);
if(nullPos < 0) {
if (nullPos < 0) {
debug("APE::Tag::parse() - Couldn't find a key/value separator. Stopped parsing.");
return;
}
@ -419,10 +392,7 @@ void APE::Tag::parse(const ByteVector &data)
const unsigned int keyLength = nullPos - pos - 8;
const unsigned int valLegnth = data.toUInt(pos, false);
if(keyLength >= MinKeyLength
&& keyLength <= MaxKeyLength
&& isKeyValid(data.mid(pos + 8, keyLength)))
{
if (keyLength >= MinKeyLength && keyLength <= MaxKeyLength && isKeyValid(data.mid(pos + 8, keyLength))) {
APE::Item item;
item.parse(data.mid(pos));

View File

@ -37,26 +37,25 @@
namespace Strawberry_TagLib {
namespace TagLib {
class File;
class File;
//! An implementation of the APE tagging format
//! An implementation of the APE tagging format
namespace APE {
namespace APE {
class Footer;
class Footer;
/*!
/*!
* A mapping between a list of item names, or keys, and the associated item.
*
* \see APE::Tag::itemListMap()
*/
typedef Map<const String, Item> ItemListMap;
typedef Map<const String, Item> ItemListMap;
//! An APE tag implementation
//! An APE tag implementation
class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag
{
class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag {
public:
/*!
* Create an APE tag with default values.
@ -133,7 +132,7 @@ namespace TagLib {
/*!
* Check if the given String is a valid APE tag key.
*/
static bool checkKey(const String&);
static bool checkKey(const String &);
/*!
* Returns a pointer to the tag's footer.
@ -185,7 +184,6 @@ namespace TagLib {
bool isEmpty() const;
protected:
/*!
* Reads from the file specified in the constructor.
*/
@ -202,9 +200,9 @@ namespace TagLib {
class TagPrivate;
TagPrivate *d;
};
}
}
}
};
} // namespace APE
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -33,11 +33,9 @@
using namespace Strawberry_TagLib::TagLib;
class ASF::Attribute::AttributePrivate : public RefCounter
{
public:
AttributePrivate() :
pictureValue(ASF::Picture::fromInvalid()),
class ASF::Attribute::AttributePrivate : public RefCounter {
public:
AttributePrivate() : pictureValue(ASF::Picture::fromInvalid()),
numericValue(0),
stream(0),
language(0) {}
@ -54,135 +52,105 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
ASF::Attribute::Attribute() :
d(new AttributePrivate())
{
ASF::Attribute::Attribute() : d(new AttributePrivate()) {
d->type = UnicodeType;
}
ASF::Attribute::Attribute(const ASF::Attribute &other) :
d(other.d)
{
ASF::Attribute::Attribute(const ASF::Attribute &other) : d(other.d) {
d->ref();
}
ASF::Attribute::Attribute(const String &value) :
d(new AttributePrivate())
{
ASF::Attribute::Attribute(const String &value) : d(new AttributePrivate()) {
d->type = UnicodeType;
d->stringValue = value;
}
ASF::Attribute::Attribute(const ByteVector &value) :
d(new AttributePrivate())
{
ASF::Attribute::Attribute(const ByteVector &value) : d(new AttributePrivate()) {
d->type = BytesType;
d->byteVectorValue = value;
}
ASF::Attribute::Attribute(const ASF::Picture &value) :
d(new AttributePrivate())
{
ASF::Attribute::Attribute(const ASF::Picture &value) : d(new AttributePrivate()) {
d->type = BytesType;
d->pictureValue = value;
}
ASF::Attribute::Attribute(unsigned int value) :
d(new AttributePrivate())
{
ASF::Attribute::Attribute(unsigned int value) : d(new AttributePrivate()) {
d->type = DWordType;
d->numericValue = value;
}
ASF::Attribute::Attribute(unsigned long long value) :
d(new AttributePrivate())
{
ASF::Attribute::Attribute(unsigned long long value) : d(new AttributePrivate()) {
d->type = QWordType;
d->numericValue = value;
}
ASF::Attribute::Attribute(unsigned short value) :
d(new AttributePrivate())
{
ASF::Attribute::Attribute(unsigned short value) : d(new AttributePrivate()) {
d->type = WordType;
d->numericValue = value;
}
ASF::Attribute::Attribute(bool value) :
d(new AttributePrivate())
{
ASF::Attribute::Attribute(bool value) : d(new AttributePrivate()) {
d->type = BoolType;
d->numericValue = value;
}
ASF::Attribute &ASF::Attribute::operator=(const ASF::Attribute &other)
{
ASF::Attribute &ASF::Attribute::operator=(const ASF::Attribute &other) {
Attribute(other).swap(*this);
return *this;
}
void ASF::Attribute::swap(Attribute &other)
{
void ASF::Attribute::swap(Attribute &other) {
using std::swap;
swap(d, other.d);
}
ASF::Attribute::~Attribute()
{
if(d->deref())
ASF::Attribute::~Attribute() {
if (d->deref())
delete d;
}
ASF::Attribute::AttributeTypes ASF::Attribute::type() const
{
ASF::Attribute::AttributeTypes ASF::Attribute::type() const {
return d->type;
}
String ASF::Attribute::toString() const
{
String ASF::Attribute::toString() const {
return d->stringValue;
}
ByteVector ASF::Attribute::toByteVector() const
{
if(d->pictureValue.isValid())
ByteVector ASF::Attribute::toByteVector() const {
if (d->pictureValue.isValid())
return d->pictureValue.render();
return d->byteVectorValue;
}
unsigned short ASF::Attribute::toBool() const
{
unsigned short ASF::Attribute::toBool() const {
return d->numericValue ? 1 : 0;
}
unsigned short ASF::Attribute::toUShort() const
{
unsigned short ASF::Attribute::toUShort() const {
return static_cast<unsigned short>(d->numericValue);
}
unsigned int ASF::Attribute::toUInt() const
{
unsigned int ASF::Attribute::toUInt() const {
return static_cast<unsigned int>(d->numericValue);
}
unsigned long long ASF::Attribute::toULongLong() const
{
unsigned long long ASF::Attribute::toULongLong() const {
return static_cast<unsigned long long>(d->numericValue);
}
ASF::Picture ASF::Attribute::toPicture() const
{
ASF::Picture ASF::Attribute::toPicture() const {
return d->pictureValue;
}
String ASF::Attribute::parse(ASF::File &f, int kind)
{
String ASF::Attribute::parse(ASF::File &f, int kind) {
unsigned int size, nameLength;
String name;
d->pictureValue = Picture::fromInvalid();
// extended content descriptor
if(kind == 0) {
if (kind == 0) {
nameLength = readWORD(&f);
name = readString(&f, nameLength);
d->type = ASF::Attribute::AttributeTypes(readWORD(&f));
@ -192,7 +160,7 @@ String ASF::Attribute::parse(ASF::File &f, int kind)
else {
int temp = readWORD(&f);
// metadata library
if(kind == 2) {
if (kind == 2) {
d->language = temp;
}
d->stream = readWORD(&f);
@ -202,17 +170,17 @@ String ASF::Attribute::parse(ASF::File &f, int kind)
name = readString(&f, nameLength);
}
if(kind != 2 && size > 65535) {
if (kind != 2 && size > 65535) {
debug("ASF::Attribute::parse() -- Value larger than 64kB");
}
switch(d->type) {
switch (d->type) {
case WordType:
d->numericValue = readWORD(&f);
break;
case BoolType:
if(kind == 0) {
if (kind == 0) {
d->numericValue = (readDWORD(&f) != 0);
}
else {
@ -238,9 +206,9 @@ String ASF::Attribute::parse(ASF::File &f, int kind)
break;
}
if(d->type == BytesType && name == "WM/Picture") {
if (d->type == BytesType && name == "WM/Picture") {
d->pictureValue.parse(d->byteVectorValue);
if(d->pictureValue.isValid()) {
if (d->pictureValue.isValid()) {
d->byteVectorValue.clear();
}
}
@ -248,8 +216,7 @@ String ASF::Attribute::parse(ASF::File &f, int kind)
return name;
}
int ASF::Attribute::dataSize() const
{
int ASF::Attribute::dataSize() const {
switch (d->type) {
case WordType:
return 2;
@ -262,7 +229,7 @@ int ASF::Attribute::dataSize() const
case UnicodeType:
return d->stringValue.size() * 2 + 2;
case BytesType:
if(d->pictureValue.isValid())
if (d->pictureValue.isValid())
return d->pictureValue.dataSize();
break;
case GuidType:
@ -271,8 +238,7 @@ int ASF::Attribute::dataSize() const
return 0;
}
ByteVector ASF::Attribute::render(const String &name, int kind) const
{
ByteVector ASF::Attribute::render(const String &name, int kind) const {
ByteVector data;
switch (d->type) {
@ -281,7 +247,7 @@ ByteVector ASF::Attribute::render(const String &name, int kind) const
break;
case BoolType:
if(kind == 0) {
if (kind == 0) {
data.append(ByteVector::fromUInt(toBool(), false));
}
else {
@ -302,7 +268,7 @@ ByteVector ASF::Attribute::render(const String &name, int kind) const
break;
case BytesType:
if(d->pictureValue.isValid()) {
if (d->pictureValue.isValid()) {
data.append(d->pictureValue.render());
break;
}
@ -312,7 +278,7 @@ ByteVector ASF::Attribute::render(const String &name, int kind) const
break;
}
if(kind == 0) {
if (kind == 0) {
data = renderString(name, true) +
ByteVector::fromShort((int)d->type, false) +
ByteVector::fromShort(data.size(), false) +
@ -332,22 +298,18 @@ ByteVector ASF::Attribute::render(const String &name, int kind) const
return data;
}
int ASF::Attribute::language() const
{
int ASF::Attribute::language() const {
return d->language;
}
void ASF::Attribute::setLanguage(int value)
{
void ASF::Attribute::setLanguage(int value) {
d->language = value;
}
int ASF::Attribute::stream() const
{
int ASF::Attribute::stream() const {
return d->stream;
}
void ASF::Attribute::setStream(int value)
{
void ASF::Attribute::setStream(int value) {
d->stream = value;
}

View File

@ -32,19 +32,15 @@
#include "asfpicture.h"
namespace Strawberry_TagLib {
namespace TagLib
{
namespace TagLib {
namespace ASF
{
namespace ASF {
class File;
class Picture;
class File;
class Picture;
class TAGLIB_EXPORT Attribute
{
class TAGLIB_EXPORT Attribute {
public:
/*!
* Enum of types an Attribute can have.
*/
@ -201,10 +197,10 @@ namespace TagLib
class AttributePrivate;
AttributePrivate *d;
};
}
};
} // namespace ASF
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -36,9 +36,8 @@
using namespace Strawberry_TagLib::TagLib;
class ASF::File::FilePrivate
{
public:
class ASF::File::FilePrivate {
public:
class BaseObject;
class UnknownObject;
class FilePropertiesObject;
@ -50,21 +49,18 @@ public:
class MetadataObject;
class MetadataLibraryObject;
FilePrivate():
headerSize(0),
FilePrivate() : headerSize(0),
tag(0),
properties(0),
contentDescriptionObject(0),
extendedContentDescriptionObject(0),
headerExtensionObject(0),
metadataObject(0),
metadataLibraryObject(0)
{
metadataLibraryObject(0) {
objects.setAutoDelete(true);
}
~FilePrivate()
{
~FilePrivate() {
delete tag;
delete properties;
}
@ -83,25 +79,23 @@ public:
MetadataLibraryObject *metadataLibraryObject;
};
namespace
{
const ByteVector headerGuid("\x30\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C", 16);
const ByteVector filePropertiesGuid("\xA1\xDC\xAB\x8C\x47\xA9\xCF\x11\x8E\xE4\x00\xC0\x0C\x20\x53\x65", 16);
const ByteVector streamPropertiesGuid("\x91\x07\xDC\xB7\xB7\xA9\xCF\x11\x8E\xE6\x00\xC0\x0C\x20\x53\x65", 16);
const ByteVector contentDescriptionGuid("\x33\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C", 16);
const ByteVector extendedContentDescriptionGuid("\x40\xA4\xD0\xD2\x07\xE3\xD2\x11\x97\xF0\x00\xA0\xC9\x5E\xA8\x50", 16);
const ByteVector headerExtensionGuid("\xb5\x03\xbf_.\xa9\xcf\x11\x8e\xe3\x00\xc0\x0c Se", 16);
const ByteVector metadataGuid("\xEA\xCB\xF8\xC5\xAF[wH\204g\xAA\214D\xFAL\xCA", 16);
const ByteVector metadataLibraryGuid("\224\034#D\230\224\321I\241A\x1d\x13NEpT", 16);
const ByteVector codecListGuid("\x40\x52\xd1\x86\x1d\x31\xd0\x11\xa3\xa4\x00\xa0\xc9\x03\x48\xf6", 16);
const ByteVector contentEncryptionGuid("\xFB\xB3\x11\x22\x23\xBD\xD2\x11\xB4\xB7\x00\xA0\xC9\x55\xFC\x6E", 16);
const ByteVector extendedContentEncryptionGuid("\x14\xE6\x8A\x29\x22\x26 \x17\x4C\xB9\x35\xDA\xE0\x7E\xE9\x28\x9C", 16);
const ByteVector advancedContentEncryptionGuid("\xB6\x9B\x07\x7A\xA4\xDA\x12\x4E\xA5\xCA\x91\xD3\x8D\xC1\x1A\x8D", 16);
}
namespace {
const ByteVector headerGuid("\x30\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C", 16);
const ByteVector filePropertiesGuid("\xA1\xDC\xAB\x8C\x47\xA9\xCF\x11\x8E\xE4\x00\xC0\x0C\x20\x53\x65", 16);
const ByteVector streamPropertiesGuid("\x91\x07\xDC\xB7\xB7\xA9\xCF\x11\x8E\xE6\x00\xC0\x0C\x20\x53\x65", 16);
const ByteVector contentDescriptionGuid("\x33\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C", 16);
const ByteVector extendedContentDescriptionGuid("\x40\xA4\xD0\xD2\x07\xE3\xD2\x11\x97\xF0\x00\xA0\xC9\x5E\xA8\x50", 16);
const ByteVector headerExtensionGuid("\xb5\x03\xbf_.\xa9\xcf\x11\x8e\xe3\x00\xc0\x0c Se", 16);
const ByteVector metadataGuid("\xEA\xCB\xF8\xC5\xAF[wH\204g\xAA\214D\xFAL\xCA", 16);
const ByteVector metadataLibraryGuid("\224\034#D\230\224\321I\241A\x1d\x13NEpT", 16);
const ByteVector codecListGuid("\x40\x52\xd1\x86\x1d\x31\xd0\x11\xa3\xa4\x00\xa0\xc9\x03\x48\xf6", 16);
const ByteVector contentEncryptionGuid("\xFB\xB3\x11\x22\x23\xBD\xD2\x11\xB4\xB7\x00\xA0\xC9\x55\xFC\x6E", 16);
const ByteVector extendedContentEncryptionGuid("\x14\xE6\x8A\x29\x22\x26 \x17\x4C\xB9\x35\xDA\xE0\x7E\xE9\x28\x9C", 16);
const ByteVector advancedContentEncryptionGuid("\xB6\x9B\x07\x7A\xA4\xDA\x12\x4E\xA5\xCA\x91\xD3\x8D\xC1\x1A\x8D", 16);
} // namespace
class ASF::File::FilePrivate::BaseObject
{
public:
class ASF::File::FilePrivate::BaseObject {
public:
ByteVector data;
virtual ~BaseObject() {}
virtual ByteVector guid() const = 0;
@ -109,66 +103,59 @@ public:
virtual ByteVector render(ASF::File *file);
};
class ASF::File::FilePrivate::UnknownObject : public ASF::File::FilePrivate::BaseObject
{
class ASF::File::FilePrivate::UnknownObject : public ASF::File::FilePrivate::BaseObject {
ByteVector myGuid;
public:
public:
explicit UnknownObject(const ByteVector &guid);
ByteVector guid() const;
};
class ASF::File::FilePrivate::FilePropertiesObject : public ASF::File::FilePrivate::BaseObject
{
public:
class ASF::File::FilePrivate::FilePropertiesObject : public ASF::File::FilePrivate::BaseObject {
public:
ByteVector guid() const;
void parse(ASF::File *file, unsigned int size);
};
class ASF::File::FilePrivate::StreamPropertiesObject : public ASF::File::FilePrivate::BaseObject
{
public:
class ASF::File::FilePrivate::StreamPropertiesObject : public ASF::File::FilePrivate::BaseObject {
public:
ByteVector guid() const;
void parse(ASF::File *file, unsigned int size);
};
class ASF::File::FilePrivate::ContentDescriptionObject : public ASF::File::FilePrivate::BaseObject
{
public:
class ASF::File::FilePrivate::ContentDescriptionObject : public ASF::File::FilePrivate::BaseObject {
public:
ByteVector guid() const;
void parse(ASF::File *file, unsigned int size);
ByteVector render(ASF::File *file);
};
class ASF::File::FilePrivate::ExtendedContentDescriptionObject : public ASF::File::FilePrivate::BaseObject
{
public:
class ASF::File::FilePrivate::ExtendedContentDescriptionObject : public ASF::File::FilePrivate::BaseObject {
public:
ByteVectorList attributeData;
ByteVector guid() const;
void parse(ASF::File *file, unsigned int size);
ByteVector render(ASF::File *file);
};
class ASF::File::FilePrivate::MetadataObject : public ASF::File::FilePrivate::BaseObject
{
public:
class ASF::File::FilePrivate::MetadataObject : public ASF::File::FilePrivate::BaseObject {
public:
ByteVectorList attributeData;
ByteVector guid() const;
void parse(ASF::File *file, unsigned int size);
ByteVector render(ASF::File *file);
};
class ASF::File::FilePrivate::MetadataLibraryObject : public ASF::File::FilePrivate::BaseObject
{
public:
class ASF::File::FilePrivate::MetadataLibraryObject : public ASF::File::FilePrivate::BaseObject {
public:
ByteVectorList attributeData;
ByteVector guid() const;
void parse(ASF::File *file, unsigned int size);
ByteVector render(ASF::File *file);
};
class ASF::File::FilePrivate::HeaderExtensionObject : public ASF::File::FilePrivate::BaseObject
{
public:
class ASF::File::FilePrivate::HeaderExtensionObject : public ASF::File::FilePrivate::BaseObject {
public:
List<ASF::File::FilePrivate::BaseObject *> objects;
HeaderExtensionObject();
ByteVector guid() const;
@ -176,53 +163,45 @@ public:
ByteVector render(ASF::File *file);
};
class ASF::File::FilePrivate::CodecListObject : public ASF::File::FilePrivate::BaseObject
{
public:
class ASF::File::FilePrivate::CodecListObject : public ASF::File::FilePrivate::BaseObject {
public:
ByteVector guid() const;
void parse(ASF::File *file, unsigned int size);
private:
enum CodecType
{
private:
enum CodecType {
Video = 0x0001,
Audio = 0x0002,
Unknown = 0xFFFF
};
};
void ASF::File::FilePrivate::BaseObject::parse(ASF::File *file, unsigned int size)
{
void ASF::File::FilePrivate::BaseObject::parse(ASF::File *file, unsigned int size) {
data.clear();
if(size > 24 && size <= (unsigned int)(file->length()))
if (size > 24 && size <= (unsigned int)(file->length()))
data = file->readBlock(size - 24);
else
data = ByteVector();
}
ByteVector ASF::File::FilePrivate::BaseObject::render(ASF::File * /*file*/)
{
ByteVector ASF::File::FilePrivate::BaseObject::render(ASF::File * /*file*/) {
return guid() + ByteVector::fromLongLong(data.size() + 24, false) + data;
}
ASF::File::FilePrivate::UnknownObject::UnknownObject(const ByteVector &guid) : myGuid(guid)
{
ASF::File::FilePrivate::UnknownObject::UnknownObject(const ByteVector &guid) : myGuid(guid) {
}
ByteVector ASF::File::FilePrivate::UnknownObject::guid() const
{
ByteVector ASF::File::FilePrivate::UnknownObject::guid() const {
return myGuid;
}
ByteVector ASF::File::FilePrivate::FilePropertiesObject::guid() const
{
ByteVector ASF::File::FilePrivate::FilePropertiesObject::guid() const {
return filePropertiesGuid;
}
void ASF::File::FilePrivate::FilePropertiesObject::parse(ASF::File *file, unsigned int size)
{
void ASF::File::FilePrivate::FilePropertiesObject::parse(ASF::File *file, unsigned int size) {
BaseObject::parse(file, size);
if(data.size() < 64) {
if (data.size() < 64) {
debug("ASF::File::FilePrivate::FilePropertiesObject::parse() -- data is too short.");
return;
}
@ -232,15 +211,13 @@ void ASF::File::FilePrivate::FilePropertiesObject::parse(ASF::File *file, unsign
file->d->properties->setLengthInMilliseconds(static_cast<int>(duration / 10000.0 - preroll + 0.5));
}
ByteVector ASF::File::FilePrivate::StreamPropertiesObject::guid() const
{
ByteVector ASF::File::FilePrivate::StreamPropertiesObject::guid() const {
return streamPropertiesGuid;
}
void ASF::File::FilePrivate::StreamPropertiesObject::parse(ASF::File *file, unsigned int size)
{
void ASF::File::FilePrivate::StreamPropertiesObject::parse(ASF::File *file, unsigned int size) {
BaseObject::parse(file, size);
if(data.size() < 70) {
if (data.size() < 70) {
debug("ASF::File::FilePrivate::StreamPropertiesObject::parse() -- data is too short.");
return;
}
@ -252,27 +229,24 @@ void ASF::File::FilePrivate::StreamPropertiesObject::parse(ASF::File *file, unsi
file->d->properties->setBitsPerSample(data.toUShort(68, false));
}
ByteVector ASF::File::FilePrivate::ContentDescriptionObject::guid() const
{
ByteVector ASF::File::FilePrivate::ContentDescriptionObject::guid() const {
return contentDescriptionGuid;
}
void ASF::File::FilePrivate::ContentDescriptionObject::parse(ASF::File *file, unsigned int /*size*/)
{
void ASF::File::FilePrivate::ContentDescriptionObject::parse(ASF::File *file, unsigned int /*size*/) {
const int titleLength = readWORD(file);
const int artistLength = readWORD(file);
const int copyrightLength = readWORD(file);
const int commentLength = readWORD(file);
const int ratingLength = readWORD(file);
file->d->tag->setTitle(readString(file,titleLength));
file->d->tag->setArtist(readString(file,artistLength));
file->d->tag->setCopyright(readString(file,copyrightLength));
file->d->tag->setComment(readString(file,commentLength));
file->d->tag->setRating(readString(file,ratingLength));
file->d->tag->setTitle(readString(file, titleLength));
file->d->tag->setArtist(readString(file, artistLength));
file->d->tag->setCopyright(readString(file, copyrightLength));
file->d->tag->setComment(readString(file, commentLength));
file->d->tag->setRating(readString(file, ratingLength));
}
ByteVector ASF::File::FilePrivate::ContentDescriptionObject::render(ASF::File *file)
{
ByteVector ASF::File::FilePrivate::ContentDescriptionObject::render(ASF::File *file) {
const ByteVector v1 = renderString(file->d->tag->title());
const ByteVector v2 = renderString(file->d->tag->artist());
const ByteVector v3 = renderString(file->d->tag->copyright());
@ -292,108 +266,96 @@ ByteVector ASF::File::FilePrivate::ContentDescriptionObject::render(ASF::File *f
return BaseObject::render(file);
}
ByteVector ASF::File::FilePrivate::ExtendedContentDescriptionObject::guid() const
{
ByteVector ASF::File::FilePrivate::ExtendedContentDescriptionObject::guid() const {
return extendedContentDescriptionGuid;
}
void ASF::File::FilePrivate::ExtendedContentDescriptionObject::parse(ASF::File *file, unsigned int /*size*/)
{
void ASF::File::FilePrivate::ExtendedContentDescriptionObject::parse(ASF::File *file, unsigned int /*size*/) {
int count = readWORD(file);
while(count--) {
while (count--) {
ASF::Attribute attribute;
String name = attribute.parse(*file);
file->d->tag->addAttribute(name, attribute);
}
}
ByteVector ASF::File::FilePrivate::ExtendedContentDescriptionObject::render(ASF::File *file)
{
ByteVector ASF::File::FilePrivate::ExtendedContentDescriptionObject::render(ASF::File *file) {
data.clear();
data.append(ByteVector::fromShort(attributeData.size(), false));
data.append(attributeData.toByteVector(""));
return BaseObject::render(file);
}
ByteVector ASF::File::FilePrivate::MetadataObject::guid() const
{
ByteVector ASF::File::FilePrivate::MetadataObject::guid() const {
return metadataGuid;
}
void ASF::File::FilePrivate::MetadataObject::parse(ASF::File *file, unsigned int /*size*/)
{
void ASF::File::FilePrivate::MetadataObject::parse(ASF::File *file, unsigned int /*size*/) {
int count = readWORD(file);
while(count--) {
while (count--) {
ASF::Attribute attribute;
String name = attribute.parse(*file, 1);
file->d->tag->addAttribute(name, attribute);
}
}
ByteVector ASF::File::FilePrivate::MetadataObject::render(ASF::File *file)
{
ByteVector ASF::File::FilePrivate::MetadataObject::render(ASF::File *file) {
data.clear();
data.append(ByteVector::fromShort(attributeData.size(), false));
data.append(attributeData.toByteVector(""));
return BaseObject::render(file);
}
ByteVector ASF::File::FilePrivate::MetadataLibraryObject::guid() const
{
ByteVector ASF::File::FilePrivate::MetadataLibraryObject::guid() const {
return metadataLibraryGuid;
}
void ASF::File::FilePrivate::MetadataLibraryObject::parse(ASF::File *file, unsigned int /*size*/)
{
void ASF::File::FilePrivate::MetadataLibraryObject::parse(ASF::File *file, unsigned int /*size*/) {
int count = readWORD(file);
while(count--) {
while (count--) {
ASF::Attribute attribute;
String name = attribute.parse(*file, 2);
file->d->tag->addAttribute(name, attribute);
}
}
ByteVector ASF::File::FilePrivate::MetadataLibraryObject::render(ASF::File *file)
{
ByteVector ASF::File::FilePrivate::MetadataLibraryObject::render(ASF::File *file) {
data.clear();
data.append(ByteVector::fromShort(attributeData.size(), false));
data.append(attributeData.toByteVector(""));
return BaseObject::render(file);
}
ASF::File::FilePrivate::HeaderExtensionObject::HeaderExtensionObject()
{
ASF::File::FilePrivate::HeaderExtensionObject::HeaderExtensionObject() {
objects.setAutoDelete(true);
}
ByteVector ASF::File::FilePrivate::HeaderExtensionObject::guid() const
{
ByteVector ASF::File::FilePrivate::HeaderExtensionObject::guid() const {
return headerExtensionGuid;
}
void ASF::File::FilePrivate::HeaderExtensionObject::parse(ASF::File *file, unsigned int /*size*/)
{
void ASF::File::FilePrivate::HeaderExtensionObject::parse(ASF::File *file, unsigned int /*size*/) {
file->seek(18, File::Current);
long long dataSize = readDWORD(file);
long long dataPos = 0;
while(dataPos < dataSize) {
while (dataPos < dataSize) {
ByteVector guid = file->readBlock(16);
if(guid.size() != 16) {
if (guid.size() != 16) {
file->setValid(false);
break;
}
bool ok;
long long size = readQWORD(file, &ok);
if(!ok) {
if (!ok) {
file->setValid(false);
break;
}
BaseObject *obj;
if(guid == metadataGuid) {
if (guid == metadataGuid) {
file->d->metadataObject = new MetadataObject();
obj = file->d->metadataObject;
}
else if(guid == metadataLibraryGuid) {
else if (guid == metadataLibraryGuid) {
file->d->metadataLibraryObject = new MetadataLibraryObject();
obj = file->d->metadataLibraryObject;
}
@ -406,25 +368,22 @@ void ASF::File::FilePrivate::HeaderExtensionObject::parse(ASF::File *file, unsig
}
}
ByteVector ASF::File::FilePrivate::HeaderExtensionObject::render(ASF::File *file)
{
ByteVector ASF::File::FilePrivate::HeaderExtensionObject::render(ASF::File *file) {
data.clear();
for(List<BaseObject *>::ConstIterator it = objects.begin(); it != objects.end(); ++it) {
for (List<BaseObject *>::ConstIterator it = objects.begin(); it != objects.end(); ++it) {
data.append((*it)->render(file));
}
data = ByteVector("\x11\xD2\xD3\xAB\xBA\xA9\xcf\x11\x8E\xE6\x00\xC0\x0C\x20\x53\x65\x06\x00", 18) + ByteVector::fromUInt(data.size(), false) + data;
return BaseObject::render(file);
}
ByteVector ASF::File::FilePrivate::CodecListObject::guid() const
{
ByteVector ASF::File::FilePrivate::CodecListObject::guid() const {
return codecListGuid;
}
void ASF::File::FilePrivate::CodecListObject::parse(ASF::File *file, unsigned int size)
{
void ASF::File::FilePrivate::CodecListObject::parse(ASF::File *file, unsigned int size) {
BaseObject::parse(file, size);
if(data.size() <= 20) {
if (data.size() <= 20) {
debug("ASF::File::FilePrivate::CodecListObject::parse() -- data is too short.");
return;
}
@ -434,9 +393,9 @@ void ASF::File::FilePrivate::CodecListObject::parse(ASF::File *file, unsigned in
const int count = data.toUInt(pos, false);
pos += 4;
for(int i = 0; i < count; ++i) {
for (int i = 0; i < count; ++i) {
if(pos >= data.size())
if (pos >= data.size())
break;
const CodecType type = static_cast<CodecType>(data.toUShort(pos, false));
@ -457,7 +416,7 @@ void ASF::File::FilePrivate::CodecListObject::parse(ASF::File *file, unsigned in
const int infoLength = data.toUShort(pos, false);
pos += 2 + infoLength * 2;
if(type == CodecListObject::Audio) {
if (type == CodecListObject::Audio) {
// First audio codec found.
const String name(data.mid(namePos, nameLength * 2), String::UTF16LE);
@ -475,8 +434,7 @@ void ASF::File::FilePrivate::CodecListObject::parse(ASF::File *file, unsigned in
// static members
////////////////////////////////////////////////////////////////////////////////
bool ASF::File::isSupported(IOStream *stream)
{
bool ASF::File::isSupported(IOStream *stream) {
// An ASF file has to start with the designated GUID.
const ByteVector id = Utils::readHeader(stream, 16, false);
@ -487,81 +445,70 @@ bool ASF::File::isSupported(IOStream *stream)
// public members
////////////////////////////////////////////////////////////////////////////////
ASF::File::File(FileName file, bool, Properties::ReadStyle) :
Strawberry_TagLib::TagLib::File(file),
d(new FilePrivate())
{
if(isOpen())
ASF::File::File(FileName file, bool, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file),
d(new FilePrivate()) {
if (isOpen())
read();
}
ASF::File::File(IOStream *stream, bool, Properties::ReadStyle) :
Strawberry_TagLib::TagLib::File(stream),
d(new FilePrivate())
{
if(isOpen())
ASF::File::File(IOStream *stream, bool, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(stream),
d(new FilePrivate()) {
if (isOpen())
read();
}
ASF::File::~File()
{
ASF::File::~File() {
delete d;
}
ASF::Tag *ASF::File::tag() const
{
ASF::Tag *ASF::File::tag() const {
return d->tag;
}
PropertyMap ASF::File::properties() const
{
PropertyMap ASF::File::properties() const {
return d->tag->properties();
}
void ASF::File::removeUnsupportedProperties(const StringList &properties)
{
void ASF::File::removeUnsupportedProperties(const StringList &properties) {
d->tag->removeUnsupportedProperties(properties);
}
PropertyMap ASF::File::setProperties(const PropertyMap &properties)
{
PropertyMap ASF::File::setProperties(const PropertyMap &properties) {
return d->tag->setProperties(properties);
}
ASF::Properties *ASF::File::audioProperties() const
{
ASF::Properties *ASF::File::audioProperties() const {
return d->properties;
}
bool ASF::File::save()
{
if(readOnly()) {
bool ASF::File::save() {
if (readOnly()) {
debug("ASF::File::save() -- File is read only.");
return false;
}
if(!isValid()) {
if (!isValid()) {
debug("ASF::File::save() -- Trying to save invalid file.");
return false;
}
if(!d->contentDescriptionObject) {
if (!d->contentDescriptionObject) {
d->contentDescriptionObject = new FilePrivate::ContentDescriptionObject();
d->objects.append(d->contentDescriptionObject);
}
if(!d->extendedContentDescriptionObject) {
if (!d->extendedContentDescriptionObject) {
d->extendedContentDescriptionObject = new FilePrivate::ExtendedContentDescriptionObject();
d->objects.append(d->extendedContentDescriptionObject);
}
if(!d->headerExtensionObject) {
if (!d->headerExtensionObject) {
d->headerExtensionObject = new FilePrivate::HeaderExtensionObject();
d->objects.append(d->headerExtensionObject);
}
if(!d->metadataObject) {
if (!d->metadataObject) {
d->metadataObject = new FilePrivate::MetadataObject();
d->headerExtensionObject->objects.append(d->metadataObject);
}
if(!d->metadataLibraryObject) {
if (!d->metadataLibraryObject) {
d->metadataLibraryObject = new FilePrivate::MetadataLibraryObject();
d->headerExtensionObject->objects.append(d->metadataLibraryObject);
}
@ -572,7 +519,7 @@ bool ASF::File::save()
const AttributeListMap allAttributes = d->tag->attributeListMap();
for(AttributeListMap::ConstIterator it = allAttributes.begin(); it != allAttributes.end(); ++it) {
for (AttributeListMap::ConstIterator it = allAttributes.begin(); it != allAttributes.end(); ++it) {
const String &name = it->first;
const AttributeList &attributes = it->second;
@ -580,17 +527,17 @@ bool ASF::File::save()
bool inExtendedContentDescriptionObject = false;
bool inMetadataObject = false;
for(AttributeList::ConstIterator jt = attributes.begin(); jt != attributes.end(); ++jt) {
for (AttributeList::ConstIterator jt = attributes.begin(); jt != attributes.end(); ++jt) {
const Attribute &attribute = *jt;
const bool largeValue = (attribute.dataSize() > 65535);
const bool guid = (attribute.type() == Attribute::GuidType);
if(!inExtendedContentDescriptionObject && !guid && !largeValue && attribute.language() == 0 && attribute.stream() == 0) {
if (!inExtendedContentDescriptionObject && !guid && !largeValue && attribute.language() == 0 && attribute.stream() == 0) {
d->extendedContentDescriptionObject->attributeData.append(attribute.render(name));
inExtendedContentDescriptionObject = true;
}
else if(!inMetadataObject && !guid && !largeValue && attribute.language() == 0 && attribute.stream() != 0) {
else if (!inMetadataObject && !guid && !largeValue && attribute.language() == 0 && attribute.stream() != 0) {
d->metadataObject->attributeData.append(attribute.render(name, 1));
inMetadataObject = true;
}
@ -601,7 +548,7 @@ bool ASF::File::save()
}
ByteVector data;
for(List<FilePrivate::BaseObject *>::ConstIterator it = d->objects.begin(); it != d->objects.end(); ++it) {
for (List<FilePrivate::BaseObject *>::ConstIterator it = d->objects.begin(); it != d->objects.end(); ++it) {
data.append((*it)->render(this));
}
@ -621,12 +568,11 @@ bool ASF::File::save()
// private members
////////////////////////////////////////////////////////////////////////////////
void ASF::File::read()
{
if(!isValid())
void ASF::File::read() {
if (!isValid())
return;
if(readBlock(16) != headerGuid) {
if (readBlock(16) != headerGuid) {
debug("ASF::File::read(): Not an ASF file.");
setValid(false);
return;
@ -637,12 +583,12 @@ void ASF::File::read()
bool ok;
d->headerSize = readQWORD(this, &ok);
if(!ok) {
if (!ok) {
setValid(false);
return;
}
int numObjects = readDWORD(this, &ok);
if(!ok) {
if (!ok) {
setValid(false);
return;
}
@ -650,43 +596,43 @@ void ASF::File::read()
FilePrivate::FilePropertiesObject *filePropertiesObject = 0;
FilePrivate::StreamPropertiesObject *streamPropertiesObject = 0;
for(int i = 0; i < numObjects; i++) {
for (int i = 0; i < numObjects; i++) {
const ByteVector guid = readBlock(16);
if(guid.size() != 16) {
if (guid.size() != 16) {
setValid(false);
break;
}
long size = (long)readQWORD(this, &ok);
if(!ok) {
if (!ok) {
setValid(false);
break;
}
FilePrivate::BaseObject *obj;
if(guid == filePropertiesGuid) {
if (guid == filePropertiesGuid) {
filePropertiesObject = new FilePrivate::FilePropertiesObject();
obj = filePropertiesObject;
}
else if(guid == streamPropertiesGuid) {
else if (guid == streamPropertiesGuid) {
streamPropertiesObject = new FilePrivate::StreamPropertiesObject();
obj = streamPropertiesObject;
}
else if(guid == contentDescriptionGuid) {
else if (guid == contentDescriptionGuid) {
d->contentDescriptionObject = new FilePrivate::ContentDescriptionObject();
obj = d->contentDescriptionObject;
}
else if(guid == extendedContentDescriptionGuid) {
else if (guid == extendedContentDescriptionGuid) {
d->extendedContentDescriptionObject = new FilePrivate::ExtendedContentDescriptionObject();
obj = d->extendedContentDescriptionObject;
}
else if(guid == headerExtensionGuid) {
else if (guid == headerExtensionGuid) {
d->headerExtensionObject = new FilePrivate::HeaderExtensionObject();
obj = d->headerExtensionObject;
}
else if(guid == codecListGuid) {
else if (guid == codecListGuid) {
obj = new FilePrivate::CodecListObject();
}
else {
if(guid == contentEncryptionGuid ||
if (guid == contentEncryptionGuid ||
guid == extendedContentEncryptionGuid ||
guid == advancedContentEncryptionGuid) {
d->properties->setEncrypted(true);
@ -697,7 +643,7 @@ void ASF::File::read()
d->objects.append(obj);
}
if(!filePropertiesObject || !streamPropertiesObject) {
if (!filePropertiesObject || !streamPropertiesObject) {
debug("ASF::File::read(): Missing mandatory header objects.");
setValid(false);
return;

View File

@ -35,19 +35,17 @@
namespace Strawberry_TagLib {
namespace TagLib {
//! An implementation of ASF (WMA) metadata
namespace ASF {
//! An implementation of ASF (WMA) metadata
namespace ASF {
/*!
/*!
* This implements and provides an interface for ASF files to the
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
* the abstract TagLib::File API as well as providing some additional
* information specific to ASF files.
*/
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File
{
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File {
public:
/*!
* Constructs an ASF file from \a file.
*
@ -130,11 +128,11 @@ namespace TagLib {
class FilePrivate;
FilePrivate *d;
};
};
}
} // namespace ASF
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -34,9 +34,8 @@
using namespace Strawberry_TagLib::TagLib;
class ASF::Picture::PicturePrivate : public RefCounter
{
public:
class ASF::Picture::PicturePrivate : public RefCounter {
public:
bool valid;
Type type;
String mimeType;
@ -48,126 +47,107 @@ public:
// Picture class members
////////////////////////////////////////////////////////////////////////////////
ASF::Picture::Picture() :
d(new PicturePrivate())
{
ASF::Picture::Picture() : d(new PicturePrivate()) {
d->valid = true;
}
ASF::Picture::Picture(const Picture& other) :
d(other.d)
{
ASF::Picture::Picture(const Picture& other) : d(other.d) {
d->ref();
}
ASF::Picture::~Picture()
{
if(d->deref())
ASF::Picture::~Picture() {
if (d->deref())
delete d;
}
bool ASF::Picture::isValid() const
{
bool ASF::Picture::isValid() const {
return d->valid;
}
String ASF::Picture::mimeType() const
{
String ASF::Picture::mimeType() const {
return d->mimeType;
}
void ASF::Picture::setMimeType(const String &value)
{
void ASF::Picture::setMimeType(const String& value) {
d->mimeType = value;
}
ASF::Picture::Type ASF::Picture::type() const
{
ASF::Picture::Type ASF::Picture::type() const {
return d->type;
}
void ASF::Picture::setType(const ASF::Picture::Type& t)
{
void ASF::Picture::setType(const ASF::Picture::Type& t) {
d->type = t;
}
String ASF::Picture::description() const
{
String ASF::Picture::description() const {
return d->description;
}
void ASF::Picture::setDescription(const String &desc)
{
void ASF::Picture::setDescription(const String& desc) {
d->description = desc;
}
ByteVector ASF::Picture::picture() const
{
ByteVector ASF::Picture::picture() const {
return d->picture;
}
void ASF::Picture::setPicture(const ByteVector &p)
{
void ASF::Picture::setPicture(const ByteVector& p) {
d->picture = p;
}
int ASF::Picture::dataSize() const
{
return
9 + (d->mimeType.length() + d->description.length()) * 2 +
int ASF::Picture::dataSize() const {
return 9 + (d->mimeType.length() + d->description.length()) * 2 +
d->picture.size();
}
ASF::Picture& ASF::Picture::operator=(const ASF::Picture& other)
{
ASF::Picture& ASF::Picture::operator=(const ASF::Picture& other) {
Picture(other).swap(*this);
return *this;
}
void ASF::Picture::swap(Picture &other)
{
void ASF::Picture::swap(Picture& other) {
using std::swap;
swap(d, other.d);
}
ByteVector ASF::Picture::render() const
{
if(!isValid())
ByteVector ASF::Picture::render() const {
if (!isValid())
return ByteVector();
return
ByteVector((char)d->type) +
return ByteVector((char)d->type) +
ByteVector::fromUInt(d->picture.size(), false) +
renderString(d->mimeType) +
renderString(d->description) +
d->picture;
}
void ASF::Picture::parse(const ByteVector& bytes)
{
void ASF::Picture::parse(const ByteVector& bytes) {
d->valid = false;
if(bytes.size() < 9)
if (bytes.size() < 9)
return;
int pos = 0;
d->type = (Type)bytes[0]; ++pos;
const unsigned int dataLen = bytes.toUInt(pos, false); pos+=4;
d->type = (Type)bytes[0];
++pos;
const unsigned int dataLen = bytes.toUInt(pos, false);
pos += 4;
const ByteVector nullStringTerminator(2, 0);
int endPos = bytes.find(nullStringTerminator, pos, 2);
if(endPos < 0)
if (endPos < 0)
return;
d->mimeType = String(bytes.mid(pos, endPos - pos), String::UTF16LE);
pos = endPos+2;
pos = endPos + 2;
endPos = bytes.find(nullStringTerminator, pos, 2);
if(endPos < 0)
if (endPos < 0)
return;
d->description = String(bytes.mid(pos, endPos - pos), String::UTF16LE);
pos = endPos+2;
pos = endPos + 2;
if(dataLen + pos != bytes.size())
if (dataLen + pos != bytes.size())
return;
d->picture = bytes.mid(pos, dataLen);
@ -175,8 +155,7 @@ void ASF::Picture::parse(const ByteVector& bytes)
return;
}
ASF::Picture ASF::Picture::fromInvalid()
{
ASF::Picture ASF::Picture::fromInvalid() {
Picture ret;
ret.d->valid = false;
return ret;

View File

@ -32,14 +32,12 @@
#include "attachedpictureframe.h"
namespace Strawberry_TagLib {
namespace TagLib
{
namespace ASF
{
namespace TagLib {
namespace ASF {
//! An ASF attached picture interface implementation
//! An ASF attached picture interface implementation
/*!
/*!
* This is an implementation of ASF attached pictures interface. Pictures may be
* included in attributes, one per WM/Picture attribute (but there may be multiple WM/Picture
* attribute in a single tag). These pictures are usually in either JPEG or
@ -47,9 +45,8 @@ namespace TagLib
* \see Attribute::toPicture()
* \see Attribute::Attribute(const Picture& picture)
*/
class TAGLIB_EXPORT Picture {
class TAGLIB_EXPORT Picture {
public:
/*!
* This describes the function or content of the picture.
*/
@ -121,7 +118,7 @@ namespace TagLib
/*!
* Exchanges the content of the Picture by the content of \a other.
*/
void swap(Picture &other);
void swap(Picture& other);
/*!
* Returns true if Picture stores valid picture
@ -144,7 +141,7 @@ namespace TagLib
* \see picture()
* \see setPicture(const ByteArray&)
*/
void setMimeType(const String &value);
void setMimeType(const String& value);
/*!
* Returns the type of the image.
@ -174,7 +171,7 @@ namespace TagLib
*
* \see description()
*/
void setDescription(const String &desc);
void setDescription(const String& desc);
/*!
* Returns the image data as a ByteVector.
@ -195,7 +192,7 @@ namespace TagLib
* \see mimeType()
* \see setMimeType()
*/
void setPicture(const ByteVector &p);
void setPicture(const ByteVector& p);
/*!
* Returns picture as binary raw data \a value
@ -209,16 +206,16 @@ namespace TagLib
#ifndef DO_NOT_DOCUMENT
/* THIS IS PRIVATE, DON'T TOUCH IT! */
void parse(const ByteVector& );
void parse(const ByteVector&);
static Picture fromInvalid();
#endif
private:
class PicturePrivate;
PicturePrivate *d;
};
}
}
}
PicturePrivate* d;
};
} // namespace ASF
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif // ASFPICTURE_H

View File

@ -29,11 +29,9 @@
using namespace Strawberry_TagLib::TagLib;
class ASF::Properties::PropertiesPrivate
{
public:
PropertiesPrivate() :
length(0),
class ASF::Properties::PropertiesPrivate {
public:
PropertiesPrivate() : length(0),
bitrate(0),
sampleRate(0),
channels(0),
@ -56,69 +54,55 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
ASF::Properties::Properties() :
AudioProperties(AudioProperties::Average),
d(new PropertiesPrivate())
{
ASF::Properties::Properties() : AudioProperties(AudioProperties::Average),
d(new PropertiesPrivate()) {
}
ASF::Properties::~Properties()
{
ASF::Properties::~Properties() {
delete d;
}
int ASF::Properties::length() const
{
int ASF::Properties::length() const {
return lengthInSeconds();
}
int ASF::Properties::lengthInSeconds() const
{
int ASF::Properties::lengthInSeconds() const {
return d->length / 1000;
}
int ASF::Properties::lengthInMilliseconds() const
{
int ASF::Properties::lengthInMilliseconds() const {
return d->length;
}
int ASF::Properties::bitrate() const
{
int ASF::Properties::bitrate() const {
return d->bitrate;
}
int ASF::Properties::sampleRate() const
{
int ASF::Properties::sampleRate() const {
return d->sampleRate;
}
int ASF::Properties::channels() const
{
int ASF::Properties::channels() const {
return d->channels;
}
int ASF::Properties::bitsPerSample() const
{
int ASF::Properties::bitsPerSample() const {
return d->bitsPerSample;
}
ASF::Properties::Codec ASF::Properties::codec() const
{
ASF::Properties::Codec ASF::Properties::codec() const {
return d->codec;
}
String ASF::Properties::codecName() const
{
String ASF::Properties::codecName() const {
return d->codecName;
}
String ASF::Properties::codecDescription() const
{
String ASF::Properties::codecDescription() const {
return d->codecDescription;
}
bool ASF::Properties::isEncrypted() const
{
bool ASF::Properties::isEncrypted() const {
return d->encrypted;
}
@ -126,40 +110,32 @@ bool ASF::Properties::isEncrypted() const
// private members
////////////////////////////////////////////////////////////////////////////////
void ASF::Properties::setLength(int /*length*/)
{
void ASF::Properties::setLength(int /*length*/) {
debug("ASF::Properties::setLength() -- This method is deprecated. Do not use.");
}
void ASF::Properties::setLengthInMilliseconds(int value)
{
void ASF::Properties::setLengthInMilliseconds(int value) {
d->length = value;
}
void ASF::Properties::setBitrate(int value)
{
void ASF::Properties::setBitrate(int value) {
d->bitrate = value;
}
void ASF::Properties::setSampleRate(int value)
{
void ASF::Properties::setSampleRate(int value) {
d->sampleRate = value;
}
void ASF::Properties::setChannels(int value)
{
void ASF::Properties::setChannels(int value) {
d->channels = value;
}
void ASF::Properties::setBitsPerSample(int value)
{
void ASF::Properties::setBitsPerSample(int value) {
d->bitsPerSample = value;
}
void ASF::Properties::setCodec(int value)
{
switch(value)
{
void ASF::Properties::setCodec(int value) {
switch (value) {
case 0x0160:
d->codec = WMA1;
break;
@ -178,17 +154,14 @@ void ASF::Properties::setCodec(int value)
}
}
void ASF::Properties::setCodecName(const String &value)
{
void ASF::Properties::setCodecName(const String &value) {
d->codecName = value;
}
void ASF::Properties::setCodecDescription(const String &value)
{
void ASF::Properties::setCodecDescription(const String &value) {
d->codecDescription = value;
}
void ASF::Properties::setEncrypted(bool value)
{
void ASF::Properties::setEncrypted(bool value) {
d->encrypted = value;
}

View File

@ -33,18 +33,15 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ASF {
namespace ASF {
//! An implementation of ASF audio properties
class TAGLIB_EXPORT Properties : public AudioProperties
{
//! An implementation of ASF audio properties
class TAGLIB_EXPORT Properties : public AudioProperties {
public:
/*!
* Audio codec types can be used in ASF file.
*/
enum Codec
{
enum Codec {
/*!
* Couldn't detect the codec.
*/
@ -178,11 +175,11 @@ namespace TagLib {
private:
class PropertiesPrivate;
PropertiesPrivate *d;
};
};
}
} // namespace ASF
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -28,9 +28,8 @@
using namespace Strawberry_TagLib::TagLib;
class ASF::Tag::TagPrivate
{
public:
class ASF::Tag::TagPrivate {
public:
String title;
String artist;
String copyright;
@ -39,162 +38,133 @@ public:
AttributeListMap attributeListMap;
};
ASF::Tag::Tag() :
Strawberry_TagLib::TagLib::Tag(),
d(new TagPrivate())
{
ASF::Tag::Tag() : Strawberry_TagLib::TagLib::Tag(),
d(new TagPrivate()) {
}
ASF::Tag::~Tag()
{
ASF::Tag::~Tag() {
delete d;
}
String ASF::Tag::title() const
{
String ASF::Tag::title() const {
return d->title;
}
String ASF::Tag::artist() const
{
String ASF::Tag::artist() const {
return d->artist;
}
String ASF::Tag::album() const
{
if(d->attributeListMap.contains("WM/AlbumTitle"))
String ASF::Tag::album() const {
if (d->attributeListMap.contains("WM/AlbumTitle"))
return d->attributeListMap["WM/AlbumTitle"][0].toString();
return String();
}
String ASF::Tag::copyright() const
{
String ASF::Tag::copyright() const {
return d->copyright;
}
String ASF::Tag::comment() const
{
String ASF::Tag::comment() const {
return d->comment;
}
String ASF::Tag::rating() const
{
String ASF::Tag::rating() const {
return d->rating;
}
unsigned int ASF::Tag::year() const
{
if(d->attributeListMap.contains("WM/Year"))
unsigned int ASF::Tag::year() const {
if (d->attributeListMap.contains("WM/Year"))
return d->attributeListMap["WM/Year"][0].toString().toInt();
return 0;
}
unsigned int ASF::Tag::track() const
{
if(d->attributeListMap.contains("WM/TrackNumber")) {
unsigned int ASF::Tag::track() const {
if (d->attributeListMap.contains("WM/TrackNumber")) {
const ASF::Attribute attr = d->attributeListMap["WM/TrackNumber"][0];
if(attr.type() == ASF::Attribute::DWordType)
if (attr.type() == ASF::Attribute::DWordType)
return attr.toUInt();
else
return attr.toString().toInt();
}
if(d->attributeListMap.contains("WM/Track"))
if (d->attributeListMap.contains("WM/Track"))
return d->attributeListMap["WM/Track"][0].toUInt();
return 0;
}
String ASF::Tag::genre() const
{
if(d->attributeListMap.contains("WM/Genre"))
String ASF::Tag::genre() const {
if (d->attributeListMap.contains("WM/Genre"))
return d->attributeListMap["WM/Genre"][0].toString();
return String();
}
void ASF::Tag::setTitle(const String &value)
{
void ASF::Tag::setTitle(const String &value) {
d->title = value;
}
void ASF::Tag::setArtist(const String &value)
{
void ASF::Tag::setArtist(const String &value) {
d->artist = value;
}
void ASF::Tag::setCopyright(const String &value)
{
void ASF::Tag::setCopyright(const String &value) {
d->copyright = value;
}
void ASF::Tag::setComment(const String &value)
{
void ASF::Tag::setComment(const String &value) {
d->comment = value;
}
void ASF::Tag::setRating(const String &value)
{
void ASF::Tag::setRating(const String &value) {
d->rating = value;
}
void ASF::Tag::setAlbum(const String &value)
{
void ASF::Tag::setAlbum(const String &value) {
setAttribute("WM/AlbumTitle", value);
}
void ASF::Tag::setGenre(const String &value)
{
void ASF::Tag::setGenre(const String &value) {
setAttribute("WM/Genre", value);
}
void ASF::Tag::setYear(unsigned int value)
{
void ASF::Tag::setYear(unsigned int value) {
setAttribute("WM/Year", String::number(value));
}
void ASF::Tag::setTrack(unsigned int value)
{
void ASF::Tag::setTrack(unsigned int value) {
setAttribute("WM/TrackNumber", String::number(value));
}
ASF::AttributeListMap& ASF::Tag::attributeListMap()
{
ASF::AttributeListMap &ASF::Tag::attributeListMap() {
return d->attributeListMap;
}
const ASF::AttributeListMap &ASF::Tag::attributeListMap() const
{
const ASF::AttributeListMap &ASF::Tag::attributeListMap() const {
return d->attributeListMap;
}
bool ASF::Tag::contains(const String &key) const
{
bool ASF::Tag::contains(const String &key) const {
return d->attributeListMap.contains(key);
}
void ASF::Tag::removeItem(const String &key)
{
void ASF::Tag::removeItem(const String &key) {
d->attributeListMap.erase(key);
}
ASF::AttributeList ASF::Tag::attribute(const String &name) const
{
ASF::AttributeList ASF::Tag::attribute(const String &name) const {
return d->attributeListMap[name];
}
void ASF::Tag::setAttribute(const String &name, const Attribute &attribute)
{
void ASF::Tag::setAttribute(const String &name, const Attribute &attribute) {
AttributeList value;
value.append(attribute);
d->attributeListMap.insert(name, value);
}
void ASF::Tag::setAttribute(const String &name, const AttributeList &values)
{
void ASF::Tag::setAttribute(const String &name, const AttributeList &values) {
d->attributeListMap.insert(name, values);
}
void ASF::Tag::addAttribute(const String &name, const Attribute &attribute)
{
if(d->attributeListMap.contains(name)) {
void ASF::Tag::addAttribute(const String &name, const Attribute &attribute) {
if (d->attributeListMap.contains(name)) {
d->attributeListMap[name].append(attribute);
}
else {
@ -202,17 +172,15 @@ void ASF::Tag::addAttribute(const String &name, const Attribute &attribute)
}
}
bool ASF::Tag::isEmpty() const
{
bool ASF::Tag::isEmpty() const {
return Strawberry_TagLib::TagLib::Tag::isEmpty() &&
copyright().isEmpty() &&
rating().isEmpty() &&
d->attributeListMap.isEmpty();
}
namespace
{
const char *keyTranslation[][2] = {
namespace {
const char *keyTranslation[][2] = {
{ "WM/AlbumTitle", "ALBUM" },
{ "WM/AlbumArtist", "ALBUMARTIST" },
{ "WM/Composer", "COMPOSER" },
@ -252,45 +220,43 @@ namespace
{ "MusicIP/PUID", "MUSICIP_PUID" },
{ "Acoustid/Id", "ACOUSTID_ID" },
{ "Acoustid/Fingerprint", "ACOUSTID_FINGERPRINT" },
};
const size_t keyTranslationSize = sizeof(keyTranslation) / sizeof(keyTranslation[0]);
};
const size_t keyTranslationSize = sizeof(keyTranslation) / sizeof(keyTranslation[0]);
String translateKey(const String &key)
{
for(size_t i = 0; i < keyTranslationSize; ++i) {
if(key == keyTranslation[i][0])
String translateKey(const String &key) {
for (size_t i = 0; i < keyTranslationSize; ++i) {
if (key == keyTranslation[i][0])
return keyTranslation[i][1];
}
return String();
}
}
} // namespace
PropertyMap ASF::Tag::properties() const
{
PropertyMap ASF::Tag::properties() const {
PropertyMap props;
if(!d->title.isEmpty()) {
if (!d->title.isEmpty()) {
props["TITLE"] = d->title;
}
if(!d->artist.isEmpty()) {
if (!d->artist.isEmpty()) {
props["ARTIST"] = d->artist;
}
if(!d->copyright.isEmpty()) {
if (!d->copyright.isEmpty()) {
props["COPYRIGHT"] = d->copyright;
}
if(!d->comment.isEmpty()) {
if (!d->comment.isEmpty()) {
props["COMMENT"] = d->comment;
}
ASF::AttributeListMap::ConstIterator it = d->attributeListMap.begin();
for(; it != d->attributeListMap.end(); ++it) {
for (; it != d->attributeListMap.end(); ++it) {
const String key = translateKey(it->first);
if(!key.isEmpty()) {
if (!key.isEmpty()) {
AttributeList::ConstIterator it2 = it->second.begin();
for(; it2 != it->second.end(); ++it2) {
if(key == "TRACKNUMBER") {
if(it2->type() == ASF::Attribute::DWordType)
for (; it2 != it->second.end(); ++it2) {
if (key == "TRACKNUMBER") {
if (it2->type() == ASF::Attribute::DWordType)
props.insert(key, String::number(it2->toUInt()));
else
props.insert(key, it2->toString());
@ -307,37 +273,35 @@ PropertyMap ASF::Tag::properties() const
return props;
}
void ASF::Tag::removeUnsupportedProperties(const StringList &props)
{
void ASF::Tag::removeUnsupportedProperties(const StringList &props) {
StringList::ConstIterator it = props.begin();
for(; it != props.end(); ++it)
for (; it != props.end(); ++it)
d->attributeListMap.erase(*it);
}
PropertyMap ASF::Tag::setProperties(const PropertyMap &props)
{
PropertyMap ASF::Tag::setProperties(const PropertyMap &props) {
static Map<String, String> reverseKeyMap;
if(reverseKeyMap.isEmpty()) {
if (reverseKeyMap.isEmpty()) {
int numKeys = sizeof(keyTranslation) / sizeof(keyTranslation[0]);
for(int i = 0; i < numKeys; i++) {
for (int i = 0; i < numKeys; i++) {
reverseKeyMap[keyTranslation[i][1]] = keyTranslation[i][0];
}
}
PropertyMap origProps = properties();
PropertyMap::ConstIterator it = origProps.begin();
for(; it != origProps.end(); ++it) {
if(!props.contains(it->first) || props[it->first].isEmpty()) {
if(it->first == "TITLE") {
for (; it != origProps.end(); ++it) {
if (!props.contains(it->first) || props[it->first].isEmpty()) {
if (it->first == "TITLE") {
d->title.clear();
}
else if(it->first == "ARTIST") {
else if (it->first == "ARTIST") {
d->artist.clear();
}
else if(it->first == "COMMENT") {
else if (it->first == "COMMENT") {
d->comment.clear();
}
else if(it->first == "COPYRIGHT") {
else if (it->first == "COPYRIGHT") {
d->copyright.clear();
}
else {
@ -348,25 +312,25 @@ PropertyMap ASF::Tag::setProperties(const PropertyMap &props)
PropertyMap ignoredProps;
it = props.begin();
for(; it != props.end(); ++it) {
if(reverseKeyMap.contains(it->first)) {
for (; it != props.end(); ++it) {
if (reverseKeyMap.contains(it->first)) {
String name = reverseKeyMap[it->first];
removeItem(name);
StringList::ConstIterator it2 = it->second.begin();
for(; it2 != it->second.end(); ++it2) {
for (; it2 != it->second.end(); ++it2) {
addAttribute(name, *it2);
}
}
else if(it->first == "TITLE") {
else if (it->first == "TITLE") {
d->title = it->second.toString();
}
else if(it->first == "ARTIST") {
else if (it->first == "ARTIST") {
d->artist = it->second.toString();
}
else if(it->first == "COMMENT") {
else if (it->first == "COMMENT") {
d->comment = it->second.toString();
}
else if(it->first == "COPYRIGHT") {
else if (it->first == "COPYRIGHT") {
d->copyright = it->second.toString();
}
else {

View File

@ -35,17 +35,16 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ASF {
namespace ASF {
typedef List<Attribute> AttributeList;
typedef Map<String, AttributeList> AttributeListMap;
typedef List<Attribute> AttributeList;
typedef Map<String, AttributeList> AttributeListMap;
class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag {
class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag {
friend class File;
public:
Tag();
virtual ~Tag();
@ -198,15 +197,14 @@ namespace TagLib {
void addAttribute(const String &name, const Attribute &attribute);
PropertyMap properties() const;
void removeUnsupportedProperties(const StringList& properties);
void removeUnsupportedProperties(const StringList &properties);
PropertyMap setProperties(const PropertyMap &properties);
private:
class TagPrivate;
TagPrivate *d;
};
}
}
}
};
} // namespace ASF
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -31,75 +31,67 @@
#ifndef DO_NOT_DOCUMENT // tell Doxygen not to document this header
namespace Strawberry_TagLib {
namespace TagLib
{
namespace ASF
{
namespace
{
namespace TagLib {
namespace ASF {
namespace {
inline unsigned short readWORD(File *file, bool *ok = 0)
{
inline unsigned short readWORD(File *file, bool *ok = 0) {
const ByteVector v = file->readBlock(2);
if(v.size() != 2) {
if(ok) *ok = false;
if (v.size() != 2) {
if (ok) *ok = false;
return 0;
}
if(ok) *ok = true;
if (ok) *ok = true;
return v.toUShort(false);
}
}
inline unsigned int readDWORD(File *file, bool *ok = 0)
{
inline unsigned int readDWORD(File *file, bool *ok = 0) {
const ByteVector v = file->readBlock(4);
if(v.size() != 4) {
if(ok) *ok = false;
if (v.size() != 4) {
if (ok) *ok = false;
return 0;
}
if(ok) *ok = true;
if (ok) *ok = true;
return v.toUInt(false);
}
}
inline long long readQWORD(File *file, bool *ok = 0)
{
inline long long readQWORD(File *file, bool *ok = 0) {
const ByteVector v = file->readBlock(8);
if(v.size() != 8) {
if(ok) *ok = false;
if (v.size() != 8) {
if (ok) *ok = false;
return 0;
}
if(ok) *ok = true;
if (ok) *ok = true;
return v.toLongLong(false);
}
}
inline String readString(File *file, int length)
{
inline String readString(File *file, int length) {
ByteVector data = file->readBlock(length);
unsigned int size = data.size();
while (size >= 2) {
if(data[size - 1] != '\0' || data[size - 2] != '\0') {
if (data[size - 1] != '\0' || data[size - 2] != '\0') {
break;
}
size -= 2;
}
if(size != data.size()) {
if (size != data.size()) {
data.resize(size);
}
return String(data, String::UTF16LE);
}
}
inline ByteVector renderString(const String &str, bool includeLength = false)
{
inline ByteVector renderString(const String &str, bool includeLength = false) {
ByteVector data = str.data(String::UTF16LE) + ByteVector::fromShort(0, false);
if(includeLength) {
if (includeLength) {
data = ByteVector::fromShort(data.size(), false) + data;
}
return data;
}
}
}
}
}
}
} // namespace
} // namespace ASF
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -49,60 +49,54 @@ using namespace Strawberry_TagLib::TagLib;
// Should be true virtual functions in taglib2.
#define VIRTUAL_FUNCTION_WORKAROUND(function_name, default_value) \
if(dynamic_cast<const APE::Properties*>(this)) \
if (dynamic_cast<const APE::Properties*>(this)) \
return dynamic_cast<const APE::Properties*>(this)->function_name(); \
else if(dynamic_cast<const ASF::Properties*>(this)) \
else if (dynamic_cast<const ASF::Properties*>(this)) \
return dynamic_cast<const ASF::Properties*>(this)->function_name(); \
else if(dynamic_cast<const FLAC::Properties*>(this)) \
else if (dynamic_cast<const FLAC::Properties*>(this)) \
return dynamic_cast<const FLAC::Properties*>(this)->function_name(); \
else if(dynamic_cast<const MP4::Properties*>(this)) \
else if (dynamic_cast<const MP4::Properties*>(this)) \
return dynamic_cast<const MP4::Properties*>(this)->function_name(); \
else if(dynamic_cast<const MPC::Properties*>(this)) \
else if (dynamic_cast<const MPC::Properties*>(this)) \
return dynamic_cast<const MPC::Properties*>(this)->function_name(); \
else if(dynamic_cast<const MPEG::Properties*>(this)) \
else if (dynamic_cast<const MPEG::Properties*>(this)) \
return dynamic_cast<const MPEG::Properties*>(this)->function_name(); \
else if(dynamic_cast<const Ogg::Opus::Properties*>(this)) \
else if (dynamic_cast<const Ogg::Opus::Properties*>(this)) \
return dynamic_cast<const Ogg::Opus::Properties*>(this)->function_name(); \
else if(dynamic_cast<const Ogg::Speex::Properties*>(this)) \
else if (dynamic_cast<const Ogg::Speex::Properties*>(this)) \
return dynamic_cast<const Ogg::Speex::Properties*>(this)->function_name(); \
else if(dynamic_cast<const TrueAudio::Properties*>(this)) \
else if (dynamic_cast<const TrueAudio::Properties*>(this)) \
return dynamic_cast<const TrueAudio::Properties*>(this)->function_name(); \
else if(dynamic_cast<const RIFF::AIFF::Properties*>(this)) \
else if (dynamic_cast<const RIFF::AIFF::Properties*>(this)) \
return dynamic_cast<const RIFF::AIFF::Properties*>(this)->function_name(); \
else if(dynamic_cast<const RIFF::WAV::Properties*>(this)) \
else if (dynamic_cast<const RIFF::WAV::Properties*>(this)) \
return dynamic_cast<const RIFF::WAV::Properties*>(this)->function_name(); \
else if(dynamic_cast<const Vorbis::Properties*>(this)) \
else if (dynamic_cast<const Vorbis::Properties*>(this)) \
return dynamic_cast<const Vorbis::Properties*>(this)->function_name(); \
else if(dynamic_cast<const WavPack::Properties*>(this)) \
else if (dynamic_cast<const WavPack::Properties*>(this)) \
return dynamic_cast<const WavPack::Properties*>(this)->function_name(); \
else if(dynamic_cast<const DSF::Properties*>(this)) \
else if (dynamic_cast<const DSF::Properties*>(this)) \
return dynamic_cast<const DSF::Properties*>(this)->function_name(); \
else if(dynamic_cast<const DSDIFF::Properties*>(this)) \
else if (dynamic_cast<const DSDIFF::Properties*>(this)) \
return dynamic_cast<const DSDIFF::Properties*>(this)->function_name(); \
else \
return (default_value);
class AudioProperties::AudioPropertiesPrivate
{
class AudioProperties::AudioPropertiesPrivate {
};
////////////////////////////////////////////////////////////////////////////////
// public methods
////////////////////////////////////////////////////////////////////////////////
AudioProperties::~AudioProperties()
{
AudioProperties::~AudioProperties() {
}
int AudioProperties::lengthInSeconds() const
{
int AudioProperties::lengthInSeconds() const {
VIRTUAL_FUNCTION_WORKAROUND(lengthInSeconds, 0)
}
int AudioProperties::lengthInMilliseconds() const
{
int AudioProperties::lengthInMilliseconds() const {
VIRTUAL_FUNCTION_WORKAROUND(lengthInMilliseconds, 0)
}
@ -110,8 +104,5 @@ int AudioProperties::lengthInMilliseconds() const
// protected methods
////////////////////////////////////////////////////////////////////////////////
AudioProperties::AudioProperties(ReadStyle) :
d(0)
{
AudioProperties::AudioProperties(ReadStyle) : d(0) {
}

View File

@ -31,19 +31,17 @@
namespace Strawberry_TagLib {
namespace TagLib {
//! A simple, abstract interface to common audio properties
//! A simple, abstract interface to common audio properties
/*!
/*!
* The values here are common to most audio formats. For more specific, codec
* dependent values, please see see the subclasses APIs. This is meant to
* compliment the TagLib::File and TagLib::Tag APIs in providing a simple
* interface that is sufficient for most applications.
*/
class TAGLIB_EXPORT AudioProperties
{
class TAGLIB_EXPORT AudioProperties {
public:
/*!
* Reading audio properties from a file can sometimes be very time consuming
* and for the most accurate results can often involve reading the entire
@ -105,7 +103,6 @@ namespace TagLib {
virtual int channels() const = 0;
protected:
/*!
* Construct an audio properties instance. This is protected as this class
* should not be instantiated directly, but should be instantiated via its
@ -121,9 +118,9 @@ namespace TagLib {
class AudioPropertiesPrivate;
AudioPropertiesPrivate *d;
};
};
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -30,128 +30,110 @@
using namespace Strawberry_TagLib::TagLib;
using namespace DSDIFF::DIIN;
class DSDIFF::DIIN::Tag::TagPrivate
{
public:
TagPrivate()
{
class DSDIFF::DIIN::Tag::TagPrivate {
public:
TagPrivate() {
}
String title;
String artist;
};
DSDIFF::DIIN::Tag::Tag() : Strawberry_TagLib::TagLib::Tag()
{
DSDIFF::DIIN::Tag::Tag() : Strawberry_TagLib::TagLib::Tag() {
d = new TagPrivate;
}
DSDIFF::DIIN::Tag::~Tag()
{
DSDIFF::DIIN::Tag::~Tag() {
delete d;
}
String DSDIFF::DIIN::Tag::title() const
{
String DSDIFF::DIIN::Tag::title() const {
return d->title;
}
String DSDIFF::DIIN::Tag::artist() const
{
String DSDIFF::DIIN::Tag::artist() const {
return d->artist;
}
String DSDIFF::DIIN::Tag::album() const
{
String DSDIFF::DIIN::Tag::album() const {
return String();
}
String DSDIFF::DIIN::Tag::comment() const
{
String DSDIFF::DIIN::Tag::comment() const {
return String();
}
String DSDIFF::DIIN::Tag::genre() const
{
String DSDIFF::DIIN::Tag::genre() const {
return String();
}
unsigned int DSDIFF::DIIN::Tag::year() const
{
unsigned int DSDIFF::DIIN::Tag::year() const {
return 0;
}
unsigned int DSDIFF::DIIN::Tag::track() const
{
unsigned int DSDIFF::DIIN::Tag::track() const {
return 0;
}
void DSDIFF::DIIN::Tag::setTitle(const String &title)
{
if(title.isNull() || title.isEmpty())
void DSDIFF::DIIN::Tag::setTitle(const String &title) {
if (title.isNull() || title.isEmpty())
d->title = String();
else
d->title = title;
}
void DSDIFF::DIIN::Tag::setArtist(const String &artist)
{
if(artist.isNull() || artist.isEmpty())
void DSDIFF::DIIN::Tag::setArtist(const String &artist) {
if (artist.isNull() || artist.isEmpty())
d->artist = String();
else
d->artist = artist;
}
void DSDIFF::DIIN::Tag::setAlbum(const String &)
{
void DSDIFF::DIIN::Tag::setAlbum(const String &) {
}
void DSDIFF::DIIN::Tag::setComment(const String &)
{
void DSDIFF::DIIN::Tag::setComment(const String &) {
}
void DSDIFF::DIIN::Tag::setGenre(const String &)
{
void DSDIFF::DIIN::Tag::setGenre(const String &) {
}
void DSDIFF::DIIN::Tag::setYear(unsigned int)
{
void DSDIFF::DIIN::Tag::setYear(unsigned int) {
}
void DSDIFF::DIIN::Tag::setTrack(unsigned int)
{
void DSDIFF::DIIN::Tag::setTrack(unsigned int) {
}
PropertyMap DSDIFF::DIIN::Tag::properties() const
{
PropertyMap DSDIFF::DIIN::Tag::properties() const {
PropertyMap properties;
properties["TITLE"] = d->title;
properties["ARTIST"] = d->artist;
return properties;
}
PropertyMap DSDIFF::DIIN::Tag::setProperties(const PropertyMap &origProps)
{
PropertyMap DSDIFF::DIIN::Tag::setProperties(const PropertyMap &origProps) {
PropertyMap properties(origProps);
properties.removeEmpty();
StringList oneValueSet;
if(properties.contains("TITLE")) {
if (properties.contains("TITLE")) {
d->title = properties["TITLE"].front();
oneValueSet.append("TITLE");
} else
}
else
d->title = String();
if(properties.contains("ARTIST")) {
if (properties.contains("ARTIST")) {
d->artist = properties["ARTIST"].front();
oneValueSet.append("ARTIST");
} else
}
else
d->artist = String();
// for each tag that has been set above, remove the first entry in the corresponding
// value list. The others will be returned as unsupported by this format.
for(StringList::Iterator it = oneValueSet.begin(); it != oneValueSet.end(); ++it) {
if(properties[*it].size() == 1)
for (StringList::Iterator it = oneValueSet.begin(); it != oneValueSet.end(); ++it) {
if (properties[*it].size() == 1)
properties.erase(*it);
else
properties[*it].erase(properties[*it].begin());
@ -159,4 +141,3 @@ PropertyMap DSDIFF::DIIN::Tag::setProperties(const PropertyMap &origProps)
return properties;
}

View File

@ -31,17 +31,16 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace DSDIFF {
namespace DSDIFF {
namespace DIIN {
namespace DIIN {
/*!
/*!
* Tags from the Edited Master Chunk Info
*
* Only Title and Artist tags are supported
*/
class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag
{
class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag {
public:
Tag();
virtual ~Tag();
@ -142,11 +141,10 @@ namespace TagLib {
class TagPrivate;
TagPrivate *d;
};
}
}
}
}
};
} // namespace DIIN
} // namespace DSDIFF
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -37,70 +37,62 @@
using namespace Strawberry_TagLib::TagLib;
namespace
{
struct Chunk64
{
namespace {
struct Chunk64 {
ByteVector name;
unsigned long long offset;
unsigned long long size;
char padding;
};
};
typedef std::vector<Chunk64> ChunkList;
typedef std::vector<Chunk64> ChunkList;
int chunkIndex(const ChunkList &chunks, const ByteVector &id)
{
for (unsigned long int i = 0 ; i < chunks.size() ; i++) {
if(chunks[i].name == id)
int chunkIndex(const ChunkList &chunks, const ByteVector &id) {
for (unsigned long int i = 0; i < chunks.size(); i++) {
if (chunks[i].name == id)
return i;
}
return -1;
}
}
bool isValidChunkID(const ByteVector &name)
{
if(name.size() != 4)
bool isValidChunkID(const ByteVector &name) {
if (name.size() != 4)
return false;
for (int i = 0 ; i < 4 ; i++) {
for (int i = 0; i < 4; i++) {
if (name[i] < 32)
return false;
}
return true;
}
enum {
ID3v2Index = 0,
DIINIndex = 1
};
enum {
PROPChunk = 0,
DIINChunk = 1
};
}
class DSDIFF::File::FilePrivate
{
public:
FilePrivate() :
endianness(BigEndian),
enum {
ID3v2Index = 0,
DIINIndex = 1
};
enum {
PROPChunk = 0,
DIINChunk = 1
};
} // namespace
class DSDIFF::File::FilePrivate {
public:
FilePrivate() : endianness(BigEndian),
size(0),
isID3InPropChunk(false),
duplicateID3V2chunkIndex(-1),
properties(0),
id3v2TagChunkID("ID3 "),
hasID3v2(false),
hasDiin(false)
{
hasDiin(false) {
childChunkIndex[ID3v2Index] = -1;
childChunkIndex[DIINIndex] = -1;
}
~FilePrivate()
{
~FilePrivate() {
delete properties;
}
@ -135,8 +127,7 @@ public:
// static members
////////////////////////////////////////////////////////////////////////////////
bool DSDIFF::File::isSupported(IOStream *stream)
{
bool DSDIFF::File::isSupported(IOStream *stream) {
// A DSDIFF file has to start with "FRM8????????DSD ".
const ByteVector id = Utils::readHeader(stream, 16, false);
@ -148,93 +139,79 @@ bool DSDIFF::File::isSupported(IOStream *stream)
////////////////////////////////////////////////////////////////////////////////
DSDIFF::File::File(FileName file, bool readProperties,
Properties::ReadStyle propertiesStyle) : Strawberry_TagLib::TagLib::File(file)
{
Properties::ReadStyle propertiesStyle) : Strawberry_TagLib::TagLib::File(file) {
d = new FilePrivate;
d->endianness = BigEndian;
if(isOpen())
if (isOpen())
read(readProperties, propertiesStyle);
}
DSDIFF::File::File(IOStream *stream, bool readProperties,
Properties::ReadStyle propertiesStyle) : Strawberry_TagLib::TagLib::File(stream)
{
Properties::ReadStyle propertiesStyle) : Strawberry_TagLib::TagLib::File(stream) {
d = new FilePrivate;
d->endianness = BigEndian;
if(isOpen())
if (isOpen())
read(readProperties, propertiesStyle);
}
DSDIFF::File::~File()
{
DSDIFF::File::~File() {
delete d;
}
Strawberry_TagLib::TagLib::Tag *DSDIFF::File::tag() const
{
Strawberry_TagLib::TagLib::Tag *DSDIFF::File::tag() const {
return &d->tag;
}
ID3v2::Tag *DSDIFF::File::ID3v2Tag(bool create) const
{
ID3v2::Tag *DSDIFF::File::ID3v2Tag(bool create) const {
return d->tag.access<ID3v2::Tag>(ID3v2Index, create);
}
bool DSDIFF::File::hasID3v2Tag() const
{
bool DSDIFF::File::hasID3v2Tag() const {
return d->hasID3v2;
}
DSDIFF::DIIN::Tag *DSDIFF::File::DIINTag(bool create) const
{
DSDIFF::DIIN::Tag *DSDIFF::File::DIINTag(bool create) const {
return d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, create);
}
bool DSDIFF::File::hasDIINTag() const
{
bool DSDIFF::File::hasDIINTag() const {
return d->hasDiin;
}
PropertyMap DSDIFF::File::properties() const
{
if(d->hasID3v2)
PropertyMap DSDIFF::File::properties() const {
if (d->hasID3v2)
return d->tag.access<ID3v2::Tag>(ID3v2Index, false)->properties();
return PropertyMap();
}
void DSDIFF::File::removeUnsupportedProperties(const StringList &unsupported)
{
if(d->hasID3v2)
void DSDIFF::File::removeUnsupportedProperties(const StringList &unsupported) {
if (d->hasID3v2)
d->tag.access<ID3v2::Tag>(ID3v2Index, false)->removeUnsupportedProperties(unsupported);
if(d->hasDiin)
if (d->hasDiin)
d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, false)->removeUnsupportedProperties(unsupported);
}
PropertyMap DSDIFF::File::setProperties(const PropertyMap &properties)
{
PropertyMap DSDIFF::File::setProperties(const PropertyMap &properties) {
return d->tag.access<ID3v2::Tag>(ID3v2Index, true)->setProperties(properties);
}
DSDIFF::Properties *DSDIFF::File::audioProperties() const
{
DSDIFF::Properties *DSDIFF::File::audioProperties() const {
return d->properties;
}
bool DSDIFF::File::save()
{
bool DSDIFF::File::save() {
return save(AllTags);
}
bool DSDIFF::File::save(TagTypes tags, StripTags, ID3v2::Version version)
{
if(readOnly()) {
bool DSDIFF::File::save(TagTypes tags, StripTags, ID3v2::Version version) {
if (readOnly()) {
debug("DSDIFF::File::save() -- File is read only.");
return false;
}
if(!isValid()) {
if (!isValid()) {
debug("DSDIFF::File::save() -- Trying to save invalid file.");
return false;
}
@ -246,9 +223,9 @@ bool DSDIFF::File::save(TagTypes tags, StripTags, ID3v2::Version version)
ID3v2::Tag *id3v2Tag = d->tag.access<ID3v2::Tag>(ID3v2Index, false);
if(tags & ID3v2 && id3v2Tag) {
if(d->isID3InPropChunk) {
if(id3v2Tag && !id3v2Tag->isEmpty()) {
if (tags & ID3v2 && id3v2Tag) {
if (d->isID3InPropChunk) {
if (id3v2Tag && !id3v2Tag->isEmpty()) {
setChildChunkData(d->id3v2TagChunkID, id3v2Tag->render(version), PROPChunk);
d->hasID3v2 = true;
}
@ -259,7 +236,7 @@ bool DSDIFF::File::save(TagTypes tags, StripTags, ID3v2::Version version)
}
}
else {
if(id3v2Tag && !id3v2Tag->isEmpty()) {
if (id3v2Tag && !id3v2Tag->isEmpty()) {
setRootChunkData(d->id3v2TagChunkID, id3v2Tag->render(version));
d->hasID3v2 = true;
}
@ -275,8 +252,8 @@ bool DSDIFF::File::save(TagTypes tags, StripTags, ID3v2::Version version)
DSDIFF::DIIN::Tag *diinTag = d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, false);
if(tags & DIIN && diinTag) {
if(!diinTag->title().isEmpty()) {
if (tags & DIIN && diinTag) {
if (!diinTag->title().isEmpty()) {
ByteVector diinTitle;
diinTitle.append(ByteVector::fromUInt(diinTag->title().size(), d->endianness == BigEndian));
diinTitle.append(ByteVector::fromCString(diinTag->title().toCString()));
@ -285,7 +262,7 @@ bool DSDIFF::File::save(TagTypes tags, StripTags, ID3v2::Version version)
else
setChildChunkData("DITI", ByteVector(), DIINChunk);
if(!diinTag->artist().isEmpty()) {
if (!diinTag->artist().isEmpty()) {
ByteVector diinArtist;
diinArtist.append(ByteVector::fromUInt(diinTag->artist().size(), d->endianness == BigEndian));
diinArtist.append(ByteVector::fromCString(diinTag->artist().toCString()));
@ -296,7 +273,7 @@ bool DSDIFF::File::save(TagTypes tags, StripTags, ID3v2::Version version)
}
// Third: remove the duplicate ID3V2 chunk (inside PROP chunk) if any
if(d->duplicateID3V2chunkIndex>=0) {
if (d->duplicateID3V2chunkIndex >= 0) {
setChildChunkData(d->duplicateID3V2chunkIndex, ByteVector(), PROPChunk);
d->duplicateID3V2chunkIndex = -1;
}
@ -304,9 +281,8 @@ bool DSDIFF::File::save(TagTypes tags, StripTags, ID3v2::Version version)
return true;
}
void DSDIFF::File::strip(TagTypes tags)
{
if(tags & ID3v2) {
void DSDIFF::File::strip(TagTypes tags) {
if (tags & ID3v2) {
removeRootChunk("ID3 ");
removeRootChunk("id3 ");
d->hasID3v2 = false;
@ -314,7 +290,7 @@ void DSDIFF::File::strip(TagTypes tags)
/// TODO: needs to also account for ID3v2 tags under the PROP chunk
}
if(tags & DIIN) {
if (tags & DIIN) {
removeRootChunk("DITI");
removeRootChunk("DIAR");
d->hasDiin = false;
@ -326,8 +302,7 @@ void DSDIFF::File::strip(TagTypes tags)
// private members
////////////////////////////////////////////////////////////////////////////////
void DSDIFF::File::removeRootChunk(unsigned int i)
{
void DSDIFF::File::removeRootChunk(unsigned int i) {
unsigned long long chunkSize = d->chunks[i].size + d->chunks[i].padding + 12;
d->size -= chunkSize;
@ -337,24 +312,21 @@ void DSDIFF::File::removeRootChunk(unsigned int i)
// Update the internal offsets
for(unsigned long r = i + 1; r < d->chunks.size(); r++)
d->chunks[r].offset = d->chunks[r - 1].offset + 12
+ d->chunks[r - 1].size + d->chunks[r - 1].padding;
for (unsigned long r = i + 1; r < d->chunks.size(); r++)
d->chunks[r].offset = d->chunks[r - 1].offset + 12 + d->chunks[r - 1].size + d->chunks[r - 1].padding;
d->chunks.erase(d->chunks.begin() + i);
}
void DSDIFF::File::removeRootChunk(const ByteVector &id)
{
void DSDIFF::File::removeRootChunk(const ByteVector &id) {
int i = chunkIndex(d->chunks, id);
if(i >= 0)
if (i >= 0)
removeRootChunk(i);
}
void DSDIFF::File::setRootChunkData(unsigned int i, const ByteVector &data)
{
if(data.isEmpty()) {
void DSDIFF::File::setRootChunkData(unsigned int i, const ByteVector &data) {
if (data.isEmpty()) {
removeRootChunk(i);
return;
}
@ -380,16 +352,15 @@ void DSDIFF::File::setRootChunkData(unsigned int i, const ByteVector &data)
updateRootChunksStructure(i + 1);
}
void DSDIFF::File::setRootChunkData(const ByteVector &name, const ByteVector &data)
{
if(d->chunks.size() == 0) {
void DSDIFF::File::setRootChunkData(const ByteVector &name, const ByteVector &data) {
if (d->chunks.size() == 0) {
debug("DSDIFF::File::setPropChunkData - No valid chunks found.");
return;
}
int i = chunkIndex(d->chunks, name);
if(i >= 0) {
if (i >= 0) {
setRootChunkData(i, data);
return;
}
@ -418,8 +389,7 @@ void DSDIFF::File::setRootChunkData(const ByteVector &name, const ByteVector &da
d->chunks.push_back(chunk);
}
void DSDIFF::File::removeChildChunk(unsigned int i, unsigned int childChunkNum)
{
void DSDIFF::File::removeChildChunk(unsigned int i, unsigned int childChunkNum) {
ChunkList &childChunks = d->childChunks[childChunkNum];
// Update global size
@ -441,30 +411,27 @@ void DSDIFF::File::removeChildChunk(unsigned int i, unsigned int childChunkNum)
// Update the internal offsets
// For child chunks
if((i + 1) < childChunks.size()) {
if ((i + 1) < childChunks.size()) {
childChunks[i + 1].offset = childChunks[i].offset;
i++;
for(i++; i < childChunks.size(); i++)
childChunks[i].offset = childChunks[i - 1].offset + 12
+ childChunks[i - 1].size + childChunks[i - 1].padding;
for (i++; i < childChunks.size(); i++)
childChunks[i].offset = childChunks[i - 1].offset + 12 + childChunks[i - 1].size + childChunks[i - 1].padding;
}
// And for root chunks
for(i = d->childChunkIndex[childChunkNum] + 1; i < d->chunks.size(); i++)
d->chunks[i].offset = d->chunks[i - 1].offset + 12
+ d->chunks[i - 1].size + d->chunks[i - 1].padding;
for (i = d->childChunkIndex[childChunkNum] + 1; i < d->chunks.size(); i++)
d->chunks[i].offset = d->chunks[i - 1].offset + 12 + d->chunks[i - 1].size + d->chunks[i - 1].padding;
childChunks.erase(childChunks.begin() + i);
}
void DSDIFF::File::setChildChunkData(unsigned int i,
const ByteVector &data,
unsigned int childChunkNum)
{
unsigned int childChunkNum) {
ChunkList &childChunks = d->childChunks[childChunkNum];
if(data.isEmpty()) {
if (data.isEmpty()) {
removeChildChunk(i, childChunkNum);
return;
}
@ -496,9 +463,8 @@ void DSDIFF::File::setChildChunkData(unsigned int i,
// Now update the internal offsets
// For child Chunks
for(i++; i < childChunks.size(); i++)
childChunks[i].offset = childChunks[i - 1].offset + 12
+ childChunks[i - 1].size + childChunks[i - 1].padding;
for (i++; i < childChunks.size(); i++)
childChunks[i].offset = childChunks[i - 1].offset + 12 + childChunks[i - 1].size + childChunks[i - 1].padding;
// And for root chunks
updateRootChunksStructure(d->childChunkIndex[childChunkNum] + 1);
@ -506,17 +472,16 @@ void DSDIFF::File::setChildChunkData(unsigned int i,
void DSDIFF::File::setChildChunkData(const ByteVector &name,
const ByteVector &data,
unsigned int childChunkNum)
{
unsigned int childChunkNum) {
ChunkList &childChunks = d->childChunks[childChunkNum];
if(childChunks.size() == 0) {
if (childChunks.size() == 0) {
debug("DSDIFF::File::setPropChunkData - No valid chunks found.");
return;
}
for(unsigned int i = 0; i < childChunks.size(); i++) {
if(childChunks[i].name == name) {
for (unsigned int i = 0; i < childChunks.size(); i++) {
if (childChunks[i].name == name) {
setChildChunkData(i, data, childChunkNum);
return;
}
@ -524,7 +489,7 @@ void DSDIFF::File::setChildChunkData(const ByteVector &name,
// Do not attempt to remove a non existing chunk
if(data.isEmpty())
if (data.isEmpty())
return;
// Couldn't find an existing chunk, so let's create a new one.
@ -539,8 +504,7 @@ void DSDIFF::File::setChildChunkData(const ByteVector &name,
// And the child chunk size
d->chunks[d->childChunkIndex[childChunkNum]].size += (offset & 1)
+ ((data.size() + 1) & ~1) + 12;
d->chunks[d->childChunkIndex[childChunkNum]].size += (offset & 1) + ((data.size() + 1) & ~1) + 12;
insert(ByteVector::fromLongLong(d->chunks[d->childChunkIndex[childChunkNum]].size,
d->endianness == BigEndian),
d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8);
@ -548,7 +512,7 @@ void DSDIFF::File::setChildChunkData(const ByteVector &name,
// Now add the chunk to the file
unsigned long long nextRootChunkIdx = length();
if((d->childChunkIndex[childChunkNum] + 1) < static_cast<int>(d->chunks.size()))
if ((d->childChunkIndex[childChunkNum] + 1) < static_cast<int>(d->chunks.size()))
nextRootChunkIdx = d->chunks[d->childChunkIndex[childChunkNum] + 1].offset - 12;
writeChunk(name, data, offset,
@ -568,37 +532,31 @@ void DSDIFF::File::setChildChunkData(const ByteVector &name,
childChunks.push_back(chunk);
}
void DSDIFF::File::updateRootChunksStructure(unsigned int startingChunk)
{
for(unsigned int i = startingChunk; i < d->chunks.size(); i++)
d->chunks[i].offset = d->chunks[i - 1].offset + 12
+ d->chunks[i - 1].size + d->chunks[i - 1].padding;
void DSDIFF::File::updateRootChunksStructure(unsigned int startingChunk) {
for (unsigned int i = startingChunk; i < d->chunks.size(); i++)
d->chunks[i].offset = d->chunks[i - 1].offset + 12 + d->chunks[i - 1].size + d->chunks[i - 1].padding;
// Update childchunks structure as well
if(d->childChunkIndex[PROPChunk] >= static_cast<int>(startingChunk)) {
if (d->childChunkIndex[PROPChunk] >= static_cast<int>(startingChunk)) {
ChunkList &childChunksToUpdate = d->childChunks[PROPChunk];
if(childChunksToUpdate.size() > 0) {
if (childChunksToUpdate.size() > 0) {
childChunksToUpdate[0].offset = d->chunks[d->childChunkIndex[PROPChunk]].offset + 12;
for(unsigned int i = 1; i < childChunksToUpdate.size(); i++)
childChunksToUpdate[i].offset = childChunksToUpdate[i - 1].offset + 12
+ childChunksToUpdate[i - 1].size + childChunksToUpdate[i - 1].padding;
for (unsigned int i = 1; i < childChunksToUpdate.size(); i++)
childChunksToUpdate[i].offset = childChunksToUpdate[i - 1].offset + 12 + childChunksToUpdate[i - 1].size + childChunksToUpdate[i - 1].padding;
}
}
if(d->childChunkIndex[DIINChunk] >= static_cast<int>(startingChunk)) {
if (d->childChunkIndex[DIINChunk] >= static_cast<int>(startingChunk)) {
ChunkList &childChunksToUpdate = d->childChunks[DIINChunk];
if(childChunksToUpdate.size() > 0) {
if (childChunksToUpdate.size() > 0) {
childChunksToUpdate[0].offset = d->chunks[d->childChunkIndex[DIINChunk]].offset + 12;
for(unsigned int i = 1; i < childChunksToUpdate.size(); i++)
childChunksToUpdate[i].offset = childChunksToUpdate[i - 1].offset + 12
+ childChunksToUpdate[i - 1].size + childChunksToUpdate[i - 1].padding;
for (unsigned int i = 1; i < childChunksToUpdate.size(); i++)
childChunksToUpdate[i].offset = childChunksToUpdate[i - 1].offset + 12 + childChunksToUpdate[i - 1].size + childChunksToUpdate[i - 1].padding;
}
}
}
void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesStyle)
{
void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesStyle) {
bool bigEndian = (d->endianness == BigEndian);
d->type = readBlock(4);
@ -607,20 +565,19 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
// + 12: chunk header at least, fix for additional junk bytes
while(tell() + 12 <= length()) {
while (tell() + 12 <= length()) {
ByteVector chunkName = readBlock(4);
unsigned long long chunkSize = readBlock(8).toLongLong(bigEndian);
if(!isValidChunkID(chunkName)) {
if (!isValidChunkID(chunkName)) {
debug("DSDIFF::File::read() -- Chunk '" + chunkName + "' has invalid ID");
setValid(false);
break;
}
if(static_cast<unsigned long long>(tell()) + chunkSize >
if (static_cast<unsigned long long>(tell()) + chunkSize >
static_cast<unsigned long long>(length())) {
debug("DSDIFF::File::read() -- Chunk '" + chunkName
+ "' has invalid size (larger than the file size)");
debug("DSDIFF::File::read() -- Chunk '" + chunkName + "' has invalid size (larger than the file size)");
setValid(false);
break;
}
@ -636,9 +593,9 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
chunk.padding = 0;
long uPosNotPadded = tell();
if((uPosNotPadded & 0x01) != 0) {
if ((uPosNotPadded & 0x01) != 0) {
ByteVector iByte = readBlock(1);
if((iByte.size() != 1) || (iByte[0] != 0))
if ((iByte.size() != 1) || (iByte[0] != 0))
// Not well formed, re-seek
seek(uPosNotPadded, Beginning);
else
@ -656,36 +613,35 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
// For DST compressed frames
unsigned short dstFrameRate = 0;
for(unsigned int i = 0; i < d->chunks.size(); i++) {
if(d->chunks[i].name == "DSD ") {
for (unsigned int i = 0; i < d->chunks.size(); i++) {
if (d->chunks[i].name == "DSD ") {
lengthDSDSamplesTimeChannels = d->chunks[i].size * 8;
audioDataSizeinBytes = d->chunks[i].size;
}
else if(d->chunks[i].name == "DST ") {
else if (d->chunks[i].name == "DST ") {
// Now decode the chunks inside the DST chunk to read the DST Frame Information one
long long dstChunkEnd = d->chunks[i].offset + d->chunks[i].size;
seek(d->chunks[i].offset);
audioDataSizeinBytes = d->chunks[i].size;
while(tell() + 12 <= dstChunkEnd) {
while (tell() + 12 <= dstChunkEnd) {
ByteVector dstChunkName = readBlock(4);
long long dstChunkSize = readBlock(8).toLongLong(bigEndian);
if(!isValidChunkID(dstChunkName)) {
if (!isValidChunkID(dstChunkName)) {
debug("DSDIFF::File::read() -- DST Chunk '" + dstChunkName + "' has invalid ID");
setValid(false);
break;
}
if(static_cast<long long>(tell()) + dstChunkSize > dstChunkEnd) {
debug("DSDIFF::File::read() -- DST Chunk '" + dstChunkName
+ "' has invalid size (larger than the DST chunk)");
if (static_cast<long long>(tell()) + dstChunkSize > dstChunkEnd) {
debug("DSDIFF::File::read() -- DST Chunk '" + dstChunkName + "' has invalid size (larger than the DST chunk)");
setValid(false);
break;
}
if(dstChunkName == "FRTE") {
if (dstChunkName == "FRTE") {
// Found the DST frame information chunk
dstNumFrames = readBlock(4).toUInt(bigEndian);
dstFrameRate = readBlock(2).toUShort(bigEndian);
@ -697,33 +653,32 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
// Check padding
long uPosNotPadded = tell();
if((uPosNotPadded & 0x01) != 0) {
if ((uPosNotPadded & 0x01) != 0) {
ByteVector iByte = readBlock(1);
if((iByte.size() != 1) || (iByte[0] != 0))
if ((iByte.size() != 1) || (iByte[0] != 0))
// Not well formed, re-seek
seek(uPosNotPadded, Beginning);
}
}
}
else if(d->chunks[i].name == "PROP") {
else if (d->chunks[i].name == "PROP") {
d->childChunkIndex[PROPChunk] = i;
// Now decodes the chunks inside the PROP chunk
long long propChunkEnd = d->chunks[i].offset + d->chunks[i].size;
// +4 to remove the 'SND ' marker at beginning of 'PROP' chunk
seek(d->chunks[i].offset + 4);
while(tell() + 12 <= propChunkEnd) {
while (tell() + 12 <= propChunkEnd) {
ByteVector propChunkName = readBlock(4);
long long propChunkSize = readBlock(8).toLongLong(bigEndian);
if(!isValidChunkID(propChunkName)) {
if (!isValidChunkID(propChunkName)) {
debug("DSDIFF::File::read() -- PROP Chunk '" + propChunkName + "' has invalid ID");
setValid(false);
break;
}
if(static_cast<long long>(tell()) + propChunkSize > propChunkEnd) {
debug("DSDIFF::File::read() -- PROP Chunk '" + propChunkName
+ "' has invalid size (larger than the PROP chunk)");
if (static_cast<long long>(tell()) + propChunkSize > propChunkEnd) {
debug("DSDIFF::File::read() -- PROP Chunk '" + propChunkName + "' has invalid size (larger than the PROP chunk)");
setValid(false);
break;
}
@ -738,9 +693,9 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
// Check padding
chunk.padding = 0;
long uPosNotPadded = tell();
if((uPosNotPadded & 0x01) != 0) {
if ((uPosNotPadded & 0x01) != 0) {
ByteVector iByte = readBlock(1);
if((iByte.size() != 1) || (iByte[0] != 0))
if ((iByte.size() != 1) || (iByte[0] != 0))
// Not well formed, re-seek
seek(uPosNotPadded, Beginning);
else
@ -749,7 +704,7 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
d->childChunks[PROPChunk].push_back(chunk);
}
}
else if(d->chunks[i].name == "DIIN") {
else if (d->chunks[i].name == "DIIN") {
d->childChunkIndex[DIINChunk] = i;
d->hasDiin = true;
@ -758,19 +713,18 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
long long diinChunkEnd = d->chunks[i].offset + d->chunks[i].size;
seek(d->chunks[i].offset);
while(tell() + 12 <= diinChunkEnd) {
while (tell() + 12 <= diinChunkEnd) {
ByteVector diinChunkName = readBlock(4);
long long diinChunkSize = readBlock(8).toLongLong(bigEndian);
if(!isValidChunkID(diinChunkName)) {
if (!isValidChunkID(diinChunkName)) {
debug("DSDIFF::File::read() -- DIIN Chunk '" + diinChunkName + "' has invalid ID");
setValid(false);
break;
}
if(static_cast<long long>(tell()) + diinChunkSize > diinChunkEnd) {
debug("DSDIFF::File::read() -- DIIN Chunk '" + diinChunkName
+ "' has invalid size (larger than the DIIN chunk)");
if (static_cast<long long>(tell()) + diinChunkSize > diinChunkEnd) {
debug("DSDIFF::File::read() -- DIIN Chunk '" + diinChunkName + "' has invalid size (larger than the DIIN chunk)");
setValid(false);
break;
}
@ -787,9 +741,9 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
chunk.padding = 0;
long uPosNotPadded = tell();
if((uPosNotPadded & 0x01) != 0) {
if ((uPosNotPadded & 0x01) != 0) {
ByteVector iByte = readBlock(1);
if((iByte.size() != 1) || (iByte[0] != 0))
if ((iByte.size() != 1) || (iByte[0] != 0))
// Not well formed, re-seek
seek(uPosNotPadded, Beginning);
else
@ -798,7 +752,7 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
d->childChunks[DIINChunk].push_back(chunk);
}
}
else if(d->chunks[i].name == "ID3 " || d->chunks[i].name == "id3 ") {
else if (d->chunks[i].name == "ID3 " || d->chunks[i].name == "id3 ") {
d->id3v2TagChunkID = d->chunks[i].name;
d->tag.set(ID3v2Index, new ID3v2::Tag(this, d->chunks[i].offset));
d->isID3InPropChunk = false;
@ -806,10 +760,10 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
}
}
if(!isValid())
if (!isValid())
return;
if(d->childChunkIndex[PROPChunk] < 0) {
if (d->childChunkIndex[PROPChunk] < 0) {
debug("DSDIFF::File::read() -- no PROP chunk found");
setValid(false);
return;
@ -817,13 +771,13 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
// Read properties
unsigned int sampleRate=0;
unsigned short channels=0;
unsigned int sampleRate = 0;
unsigned short channels = 0;
for(unsigned int i = 0; i < d->childChunks[PROPChunk].size(); i++) {
if(d->childChunks[PROPChunk][i].name == "ID3 " ||
for (unsigned int i = 0; i < d->childChunks[PROPChunk].size(); i++) {
if (d->childChunks[PROPChunk][i].name == "ID3 " ||
d->childChunks[PROPChunk][i].name == "id3 ") {
if(d->hasID3v2) {
if (d->hasID3v2) {
d->duplicateID3V2chunkIndex = i;
// ID3V2 tag has already been found at root level
continue;
@ -833,12 +787,12 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
d->isID3InPropChunk = true;
d->hasID3v2 = true;
}
else if(d->childChunks[PROPChunk][i].name == "FS ") {
else if (d->childChunks[PROPChunk][i].name == "FS ") {
// Sample rate
seek(d->childChunks[PROPChunk][i].offset);
sampleRate = readBlock(4).toUInt(0, 4, bigEndian);
}
else if(d->childChunks[PROPChunk][i].name == "CHNL") {
else if (d->childChunks[PROPChunk][i].name == "CHNL") {
// Channels
seek(d->childChunks[PROPChunk][i].offset);
channels = readBlock(2).toShort(0, bigEndian);
@ -849,20 +803,20 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, true);
if(d->hasDiin) {
for(unsigned int i = 0; i < d->childChunks[DIINChunk].size(); i++) {
if(d->childChunks[DIINChunk][i].name == "DITI") {
if (d->hasDiin) {
for (unsigned int i = 0; i < d->childChunks[DIINChunk].size(); i++) {
if (d->childChunks[DIINChunk][i].name == "DITI") {
seek(d->childChunks[DIINChunk][i].offset);
unsigned int titleStrLength = readBlock(4).toUInt(0, 4, bigEndian);
if(titleStrLength <= d->childChunks[DIINChunk][i].size) {
if (titleStrLength <= d->childChunks[DIINChunk][i].size) {
ByteVector titleStr = readBlock(titleStrLength);
d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, false)->setTitle(titleStr);
}
}
else if(d->childChunks[DIINChunk][i].name == "DIAR") {
else if (d->childChunks[DIINChunk][i].name == "DIAR") {
seek(d->childChunks[DIINChunk][i].offset);
unsigned int artistStrLength = readBlock(4).toUInt(0, 4, bigEndian);
if(artistStrLength <= d->childChunks[DIINChunk][i].size) {
if (artistStrLength <= d->childChunks[DIINChunk][i].size) {
ByteVector artistStr = readBlock(artistStrLength);
d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, false)->setArtist(artistStr);
}
@ -870,23 +824,23 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
}
}
if(readProperties) {
if(lengthDSDSamplesTimeChannels == 0) {
if (readProperties) {
if (lengthDSDSamplesTimeChannels == 0) {
// DST compressed signal : need to compute length of DSD uncompressed frames
if(dstFrameRate > 0)
lengthDSDSamplesTimeChannels = (unsigned long long) dstNumFrames *
(unsigned long long) sampleRate /
(unsigned long long) dstFrameRate;
if (dstFrameRate > 0)
lengthDSDSamplesTimeChannels = (unsigned long long)dstNumFrames *
(unsigned long long)sampleRate /
(unsigned long long)dstFrameRate;
else
lengthDSDSamplesTimeChannels = 0;
}
else {
// In DSD uncompressed files, the read number of samples is the total for each channel
if(channels > 0)
if (channels > 0)
lengthDSDSamplesTimeChannels /= channels;
}
int bitrate = 0;
if(lengthDSDSamplesTimeChannels > 0)
if (lengthDSDSamplesTimeChannels > 0)
bitrate = (audioDataSizeinBytes * 8 * sampleRate) / lengthDSDSamplesTimeChannels / 1000;
d->properties = new Properties(sampleRate,
@ -896,7 +850,7 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
propertiesStyle);
}
if(!ID3v2Tag()) {
if (!ID3v2Tag()) {
d->tag.access<ID3v2::Tag>(ID3v2Index, true);
// By default, ID3 chunk is at root level
d->isID3InPropChunk = false;
@ -906,18 +860,16 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
void DSDIFF::File::writeChunk(const ByteVector &name, const ByteVector &data,
unsigned long long offset, unsigned long replace,
unsigned int leadingPadding)
{
unsigned int leadingPadding) {
ByteVector combined;
if(leadingPadding)
if (leadingPadding)
combined.append(ByteVector(leadingPadding, '\x00'));
combined.append(name);
combined.append(ByteVector::fromLongLong(data.size(), d->endianness == BigEndian));
combined.append(data);
if((data.size() & 0x01) != 0)
if ((data.size() & 0x01) != 0)
combined.append('\x00');
insert(combined, offset, replace);
}

View File

@ -34,9 +34,9 @@
namespace Strawberry_TagLib {
namespace TagLib {
//! An implementation of DSDIFF metadata
//! An implementation of DSDIFF metadata
/*!
/*!
* This is implementation of DSDIFF metadata.
*
* This supports an ID3v2 tag as well as reading stream from the ID3 RIFF
@ -48,21 +48,19 @@ namespace TagLib {
* In addition, title and artist info are stored as part of the standard
*/
namespace DSDIFF {
namespace DSDIFF {
//! An implementation of TagLib::File with DSDIFF specific methods
//! An implementation of TagLib::File with DSDIFF specific methods
/*!
/*!
* This implements and provides an interface for DSDIFF 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 DSDIFF files.
*/
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File
{
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File {
public:
/*!
* This set of flags is used for various operations and is suitable for
* being OR-ed together.
@ -218,7 +216,8 @@ namespace TagLib {
static bool isSupported(IOStream *stream);
protected:
enum Endianness { BigEndian, LittleEndian };
enum Endianness { BigEndian,
LittleEndian };
File(FileName file, Endianness endianness);
File(IOStream *stream, Endianness endianness);
@ -279,10 +278,9 @@ namespace TagLib {
class FilePrivate;
FilePrivate *d;
};
}
}
}
};
} // namespace DSDIFF
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -30,17 +30,14 @@
using namespace Strawberry_TagLib::TagLib;
class DSDIFF::Properties::PropertiesPrivate
{
public:
PropertiesPrivate() :
length(0),
class DSDIFF::Properties::PropertiesPrivate {
public:
PropertiesPrivate() : length(0),
bitrate(0),
sampleRate(0),
channels(0),
sampleWidth(0),
sampleCount(0)
{
sampleCount(0) {
}
int length;
@ -59,8 +56,7 @@ DSDIFF::Properties::Properties(const unsigned int sampleRate,
const unsigned short channels,
const unsigned long long samplesCount,
const int bitrate,
ReadStyle style) : AudioProperties(style)
{
ReadStyle style) : AudioProperties(style) {
d = new PropertiesPrivate;
d->channels = channels;
@ -68,53 +64,41 @@ DSDIFF::Properties::Properties(const unsigned int sampleRate,
d->sampleWidth = 1;
d->sampleRate = sampleRate;
d->bitrate = bitrate;
d->length = d->sampleRate > 0
? static_cast<int>((d->sampleCount * 1000.0) / d->sampleRate + 0.5)
: 0;
d->length = d->sampleRate > 0 ? static_cast<int>((d->sampleCount * 1000.0) / d->sampleRate + 0.5) : 0;
}
DSDIFF::Properties::~Properties()
{
DSDIFF::Properties::~Properties() {
delete d;
}
int DSDIFF::Properties::length() const
{
int DSDIFF::Properties::length() const {
return lengthInSeconds();
}
int DSDIFF::Properties::lengthInSeconds() const
{
int DSDIFF::Properties::lengthInSeconds() const {
return d->length / 1000;
}
int DSDIFF::Properties::lengthInMilliseconds() const
{
int DSDIFF::Properties::lengthInMilliseconds() const {
return d->length;
}
int DSDIFF::Properties::bitrate() const
{
int DSDIFF::Properties::bitrate() const {
return d->bitrate;
}
int DSDIFF::Properties::sampleRate() const
{
int DSDIFF::Properties::sampleRate() const {
return d->sampleRate;
}
int DSDIFF::Properties::channels() const
{
int DSDIFF::Properties::channels() const {
return d->channels;
}
int DSDIFF::Properties::bitsPerSample() const
{
int DSDIFF::Properties::bitsPerSample() const {
return d->sampleWidth;
}
long long DSDIFF::Properties::sampleCount() const
{
long long DSDIFF::Properties::sampleCount() const {
return d->sampleCount;
}

View File

@ -31,19 +31,18 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace DSDIFF {
namespace DSDIFF {
class File;
class File;
//! An implementation of audio property reading for DSDIFF
//! An implementation of audio property reading for DSDIFF
/*!
/*!
* This reads the data from an DSDIFF stream found in the AudioProperties
* API.
*/
class TAGLIB_EXPORT Properties : public AudioProperties
{
class TAGLIB_EXPORT Properties : public AudioProperties {
public:
/*!
* Create an instance of DSDIFF::Properties with the data read from the
@ -76,10 +75,9 @@ namespace TagLib {
class PropertiesPrivate;
PropertiesPrivate *d;
};
}
}
}
};
} // namespace DSDIFF
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -36,19 +36,15 @@ using namespace Strawberry_TagLib::TagLib;
// The DSF specification is located at http://dsd-guide.com/sites/default/files/white-papers/DSFFileFormatSpec_E.pdf
class DSF::File::FilePrivate
{
public:
FilePrivate() :
fileSize(0),
class DSF::File::FilePrivate {
public:
FilePrivate() : fileSize(0),
metadataOffset(0),
properties(nullptr),
tag(nullptr)
{
tag(nullptr) {
}
~FilePrivate()
{
~FilePrivate() {
delete properties;
delete tag;
}
@ -63,8 +59,7 @@ public:
// static members
////////////////////////////////////////////////////////////////////////////////
bool DSF::File::isSupported(IOStream *stream)
{
bool DSF::File::isSupported(IOStream *stream) {
// A DSF file has to start with "DSD "
const ByteVector id = Utils::readHeader(stream, 4, false);
return id.startsWith("DSD ");
@ -75,73 +70,63 @@ bool DSF::File::isSupported(IOStream *stream)
////////////////////////////////////////////////////////////////////////////////
DSF::File::File(FileName file, bool readProperties,
Properties::ReadStyle propertiesStyle) :
Strawberry_TagLib::TagLib::File(file),
d(new FilePrivate())
{
if(isOpen())
Properties::ReadStyle propertiesStyle) : Strawberry_TagLib::TagLib::File(file),
d(new FilePrivate()) {
if (isOpen())
read(readProperties, propertiesStyle);
}
DSF::File::File(IOStream *stream, bool readProperties,
Properties::ReadStyle propertiesStyle) :
Strawberry_TagLib::TagLib::File(stream),
d(new FilePrivate())
{
if(isOpen())
Properties::ReadStyle propertiesStyle) : Strawberry_TagLib::TagLib::File(stream),
d(new FilePrivate()) {
if (isOpen())
read(readProperties, propertiesStyle);
}
DSF::File::~File()
{
DSF::File::~File() {
delete d;
}
ID3v2::Tag *DSF::File::tag() const
{
ID3v2::Tag *DSF::File::tag() const {
return d->tag;
}
PropertyMap DSF::File::properties() const
{
PropertyMap DSF::File::properties() const {
return d->tag->properties();
}
PropertyMap DSF::File::setProperties(const PropertyMap &properties)
{
PropertyMap DSF::File::setProperties(const PropertyMap &properties) {
return d->tag->setProperties(properties);
}
DSF::Properties *DSF::File::audioProperties() const
{
DSF::Properties *DSF::File::audioProperties() const {
return d->properties;
}
bool DSF::File::save()
{
if(readOnly()) {
bool DSF::File::save() {
if (readOnly()) {
debug("DSF::File::save() -- File is read only.");
return false;
}
if(!isValid()) {
if (!isValid()) {
debug("DSF::File::save() -- Trying to save invalid file.");
return false;
}
// Three things must be updated: the file size, the tag data, and the metadata offset
if(d->tag->isEmpty()) {
if (d->tag->isEmpty()) {
long long newFileSize = d->metadataOffset ? d->metadataOffset : d->fileSize;
// Update the file size
if(d->fileSize != newFileSize) {
if (d->fileSize != newFileSize) {
insert(ByteVector::fromLongLong(newFileSize, false), 12, 8);
d->fileSize = newFileSize;
}
// Update the metadata offset to 0 since there is no longer a tag
if(d->metadataOffset) {
if (d->metadataOffset) {
insert(ByteVector::fromLongLong(0ULL, false), 20, 8);
d->metadataOffset = 0;
}
@ -157,13 +142,13 @@ bool DSF::File::save()
long long oldTagSize = d->fileSize - newMetadataOffset;
// Update the file size
if(d->fileSize != newFileSize) {
if (d->fileSize != newFileSize) {
insert(ByteVector::fromLongLong(newFileSize, false), 12, 8);
d->fileSize = newFileSize;
}
// Update the metadata offset
if(d->metadataOffset != newMetadataOffset) {
if (d->metadataOffset != newMetadataOffset) {
insert(ByteVector::fromLongLong(newMetadataOffset, false), 20, 8);
d->metadataOffset = newMetadataOffset;
}
@ -180,14 +165,13 @@ bool DSF::File::save()
////////////////////////////////////////////////////////////////////////////////
void DSF::File::read(bool, Properties::ReadStyle propertiesStyle)
{
void DSF::File::read(bool, Properties::ReadStyle propertiesStyle) {
// A DSF file consists of four chunks: DSD chunk, format chunk, data chunk, and metadata chunk
// The file format is not chunked in the sense of a RIFF File, though
// DSD chunk
ByteVector chunkName = readBlock(4);
if(chunkName != "DSD ") {
if (chunkName != "DSD ") {
debug("DSF::File::read() -- Not a DSF file.");
setValid(false);
return;
@ -196,7 +180,7 @@ void DSF::File::read(bool, Properties::ReadStyle propertiesStyle)
long long chunkSize = readBlock(8).toLongLong(false);
// Integrity check
if(28 != chunkSize) {
if (28 != chunkSize) {
debug("DSF::File::read() -- File is corrupted, wrong chunk size");
setValid(false);
return;
@ -205,7 +189,7 @@ void DSF::File::read(bool, Properties::ReadStyle propertiesStyle)
d->fileSize = readBlock(8).toLongLong(false);
// File is malformed or corrupted
if(d->fileSize != length()) {
if (d->fileSize != length()) {
debug("DSF::File::read() -- File is corrupted wrong length");
setValid(false);
return;
@ -214,7 +198,7 @@ void DSF::File::read(bool, Properties::ReadStyle propertiesStyle)
d->metadataOffset = readBlock(8).toLongLong(false);
// File is malformed or corrupted
if(d->metadataOffset > d->fileSize) {
if (d->metadataOffset > d->fileSize) {
debug("DSF::File::read() -- Invalid metadata offset.");
setValid(false);
return;
@ -222,7 +206,7 @@ void DSF::File::read(bool, Properties::ReadStyle propertiesStyle)
// Format chunk
chunkName = readBlock(4);
if(chunkName != "fmt ") {
if (chunkName != "fmt ") {
debug("DSF::File::read() -- Missing 'fmt ' chunk.");
setValid(false);
return;
@ -235,9 +219,8 @@ void DSF::File::read(bool, Properties::ReadStyle propertiesStyle)
// Skip the data chunk
// A metadata offset of 0 indicates the absence of an ID3v2 tag
if(0 == d->metadataOffset)
if (0 == d->metadataOffset)
d->tag = new ID3v2::Tag();
else
d->tag = new ID3v2::Tag(this, d->metadataOffset);
}

View File

@ -33,27 +33,26 @@
namespace Strawberry_TagLib {
namespace TagLib {
//! An implementation of DSF metadata
//! An implementation of DSF metadata
/*!
/*!
* This is implementation of DSF metadata.
*
* This supports an ID3v2 tag as well as properties from the file.
*/
namespace DSF {
namespace DSF {
//! An implementation of Strawberry_TagLib::TagLib::File with DSF specific methods
//! An implementation of Strawberry_TagLib::TagLib::File with DSF specific methods
/*!
/*!
* This implements and provides an interface for DSF files to the
* Strawberry_TagLib::TagLib::Tag and Strawberry_TagLib::TagLib::AudioProperties interfaces by way of implementing
* the abstract Strawberry_TagLib::TagLib::File API as well as providing some additional
* information specific to DSF files.
*/
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File
{
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File {
public:
/*!
* Constructs an DSF file from \a file. If \a readProperties is true the
@ -121,10 +120,9 @@ namespace TagLib {
class FilePrivate;
FilePrivate *d;
};
}
}
}
};
} // namespace DSF
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -30,11 +30,9 @@
using namespace Strawberry_TagLib::TagLib;
class DSF::Properties::PropertiesPrivate
{
public:
PropertiesPrivate() :
formatVersion(0),
class DSF::Properties::PropertiesPrivate {
public:
PropertiesPrivate() : formatVersion(0),
formatID(0),
channelType(0),
channelNum(0),
@ -43,8 +41,7 @@ public:
sampleCount(0),
blockSizePerChannel(0),
bitrate(0),
length(0)
{
length(0) {
}
// Nomenclature is from DSF file format specification
@ -66,75 +63,61 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
DSF::Properties::Properties(const ByteVector &data, ReadStyle style) : Strawberry_TagLib::TagLib::AudioProperties(style)
{
DSF::Properties::Properties(const ByteVector &data, ReadStyle style) : Strawberry_TagLib::TagLib::AudioProperties(style) {
d = new PropertiesPrivate;
read(data);
}
DSF::Properties::~Properties()
{
DSF::Properties::~Properties() {
delete d;
}
int DSF::Properties::length() const
{
int DSF::Properties::length() const {
return lengthInSeconds();
}
int DSF::Properties::lengthInSeconds() const
{
int DSF::Properties::lengthInSeconds() const {
return d->length / 1000;
}
int DSF::Properties::lengthInMilliseconds() const
{
int DSF::Properties::lengthInMilliseconds() const {
return d->length;
}
int DSF::Properties::bitrate() const
{
int DSF::Properties::bitrate() const {
return d->bitrate;
}
int DSF::Properties::sampleRate() const
{
int DSF::Properties::sampleRate() const {
return d->samplingFrequency;
}
int DSF::Properties::channels() const
{
int DSF::Properties::channels() const {
return d->channelNum;
}
// DSF specific
int DSF::Properties::formatVersion() const
{
int DSF::Properties::formatVersion() const {
return d->formatVersion;
}
int DSF::Properties::formatID() const
{
int DSF::Properties::formatID() const {
return d->formatID;
}
int DSF::Properties::channelType() const
{
int DSF::Properties::channelType() const {
return d->channelType;
}
int DSF::Properties::bitsPerSample() const
{
int DSF::Properties::bitsPerSample() const {
return d->bitsPerSample;
}
long long DSF::Properties::sampleCount() const
{
long long DSF::Properties::sampleCount() const {
return d->sampleCount;
}
int DSF::Properties::blockSizePerChannel() const
{
int DSF::Properties::blockSizePerChannel() const {
return d->blockSizePerChannel;
}
@ -142,20 +125,16 @@ int DSF::Properties::blockSizePerChannel() const
// private members
////////////////////////////////////////////////////////////////////////////////
void DSF::Properties::read(const ByteVector &data)
{
d->formatVersion = data.toUInt(0U,false);
d->formatID = data.toUInt(4U,false);
d->channelType = data.toUInt(8U,false);
d->channelNum = data.toUInt(12U,false);
d->samplingFrequency = data.toUInt(16U,false);
d->bitsPerSample = data.toUInt(20U,false);
d->sampleCount = data.toLongLong(24U,false);
d->blockSizePerChannel = data.toUInt(32U,false);
void DSF::Properties::read(const ByteVector &data) {
d->formatVersion = data.toUInt(0U, false);
d->formatID = data.toUInt(4U, false);
d->channelType = data.toUInt(8U, false);
d->channelNum = data.toUInt(12U, false);
d->samplingFrequency = data.toUInt(16U, false);
d->bitsPerSample = data.toUInt(20U, false);
d->sampleCount = data.toLongLong(24U, false);
d->blockSizePerChannel = data.toUInt(32U, false);
d->bitrate
= static_cast<unsigned int>((d->samplingFrequency * d->bitsPerSample * d->channelNum) / 1000.0 + 0.5);
d->length
= d->samplingFrequency > 0 ? static_cast<unsigned int>(d->sampleCount * 1000.0 / d->samplingFrequency + 0.5) : 0;
d->bitrate = static_cast<unsigned int>((d->samplingFrequency * d->bitsPerSample * d->channelNum) / 1000.0 + 0.5);
d->length = d->samplingFrequency > 0 ? static_cast<unsigned int>(d->sampleCount * 1000.0 / d->samplingFrequency + 0.5) : 0;
}

View File

@ -31,19 +31,18 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace DSF {
namespace DSF {
class File;
class File;
//! An implementation of audio property reading for DSF
//! An implementation of audio property reading for DSF
/*!
/*!
* This reads the data from a DSF stream found in the AudioProperties
* API.
*/
class TAGLIB_EXPORT Properties : public Strawberry_TagLib::TagLib::AudioProperties
{
class TAGLIB_EXPORT Properties : public Strawberry_TagLib::TagLib::AudioProperties {
public:
/*!
* Create an instance of DSF::AudioProperties with the data read from the
@ -85,10 +84,9 @@ namespace TagLib {
class PropertiesPrivate;
PropertiesPrivate *d;
};
}
}
}
};
} // namespace DSF
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -57,31 +57,28 @@
using namespace Strawberry_TagLib::TagLib;
namespace
{
typedef List<const FileRef::FileTypeResolver *> ResolverList;
ResolverList fileTypeResolvers;
namespace {
typedef List<const FileRef::FileTypeResolver *> ResolverList;
ResolverList fileTypeResolvers;
// Detect the file type by user-defined resolvers.
// Detect the file type by user-defined resolvers.
File *detectByResolvers(FileName fileName, bool readAudioProperties,
AudioProperties::ReadStyle audioPropertiesStyle)
{
File *detectByResolvers(FileName fileName, bool readAudioProperties,
AudioProperties::ReadStyle audioPropertiesStyle) {
ResolverList::ConstIterator it = fileTypeResolvers.begin();
for(; it != fileTypeResolvers.end(); ++it) {
for (; it != fileTypeResolvers.end(); ++it) {
File *file = (*it)->createFile(fileName, readAudioProperties, audioPropertiesStyle);
if(file)
if (file)
return file;
}
return nullptr;
}
}
// Detect the file type based on the file extension.
// Detect the file type based on the file extension.
File* detectByExtension(IOStream *stream, bool readAudioProperties,
AudioProperties::ReadStyle audioPropertiesStyle)
{
File *detectByExtension(IOStream *stream, bool readAudioProperties,
AudioProperties::ReadStyle audioPropertiesStyle) {
#ifdef _WIN32
const String s = stream->name().toString();
#else
@ -90,122 +87,120 @@ namespace
String ext;
const int pos = s.rfind(".");
if(pos != -1)
if (pos != -1)
ext = s.substr(pos + 1).upper();
// If this list is updated, the method defaultFileExtensions() should also be
// updated. However at some point that list should be created at the same time
// that a default file type resolver is created.
if(ext.isEmpty())
if (ext.isEmpty())
return nullptr;
// .oga can be any audio in the Ogg container. So leave it to content-based detection.
if(ext == "MP3")
if (ext == "MP3")
return new MPEG::File(stream, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
if(ext == "OGG")
if (ext == "OGG")
return new Ogg::Vorbis::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "FLAC")
if (ext == "FLAC")
return new FLAC::File(stream, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
if(ext == "MPC")
if (ext == "MPC")
return new MPC::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "WV")
if (ext == "WV")
return new WavPack::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "SPX")
if (ext == "SPX")
return new Ogg::Speex::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "OPUS")
if (ext == "OPUS")
return new Ogg::Opus::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "TTA")
if (ext == "TTA")
return new TrueAudio::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "M4A" || ext == "M4R" || ext == "M4B" || ext == "M4P" || ext == "MP4" || ext == "3G2" || ext == "M4V")
if (ext == "M4A" || ext == "M4R" || ext == "M4B" || ext == "M4P" || ext == "MP4" || ext == "3G2" || ext == "M4V")
return new MP4::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "WMA" || ext == "ASF")
if (ext == "WMA" || ext == "ASF")
return new ASF::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "AIF" || ext == "AIFF" || ext == "AFC" || ext == "AIFC")
if (ext == "AIF" || ext == "AIFF" || ext == "AFC" || ext == "AIFC")
return new RIFF::AIFF::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "WAV")
if (ext == "WAV")
return new RIFF::WAV::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "APE")
if (ext == "APE")
return new APE::File(stream, readAudioProperties, audioPropertiesStyle);
// module, nst and wow are possible but uncommon extensions
if(ext == "MOD" || ext == "MODULE" || ext == "NST" || ext == "WOW")
if (ext == "MOD" || ext == "MODULE" || ext == "NST" || ext == "WOW")
return new Mod::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "S3M")
if (ext == "S3M")
return new S3M::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "IT")
if (ext == "IT")
return new IT::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "XM")
if (ext == "XM")
return new XM::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "DFF" || ext == "DSDIFF")
if (ext == "DFF" || ext == "DSDIFF")
return new DSDIFF::File(stream, readAudioProperties, audioPropertiesStyle);
if(ext == "DSF")
if (ext == "DSF")
return new DSF::File(stream, readAudioProperties, audioPropertiesStyle);
return nullptr;
}
}
// Detect the file type based on the actual content of the stream.
// Detect the file type based on the actual content of the stream.
File *detectByContent(IOStream *stream, bool readAudioProperties,
AudioProperties::ReadStyle audioPropertiesStyle)
{
File *detectByContent(IOStream *stream, bool readAudioProperties,
AudioProperties::ReadStyle audioPropertiesStyle) {
File *file = 0;
if(MPEG::File::isSupported(stream))
if (MPEG::File::isSupported(stream))
file = new MPEG::File(stream, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
else if(Ogg::Vorbis::File::isSupported(stream))
else if (Ogg::Vorbis::File::isSupported(stream))
file = new Ogg::Vorbis::File(stream, readAudioProperties, audioPropertiesStyle);
else if(Ogg::FLAC::File::isSupported(stream))
else if (Ogg::FLAC::File::isSupported(stream))
file = new Ogg::FLAC::File(stream, readAudioProperties, audioPropertiesStyle);
else if(FLAC::File::isSupported(stream))
else if (FLAC::File::isSupported(stream))
file = new FLAC::File(stream, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
else if(MPC::File::isSupported(stream))
else if (MPC::File::isSupported(stream))
file = new MPC::File(stream, readAudioProperties, audioPropertiesStyle);
else if(WavPack::File::isSupported(stream))
else if (WavPack::File::isSupported(stream))
file = new WavPack::File(stream, readAudioProperties, audioPropertiesStyle);
else if(Ogg::Speex::File::isSupported(stream))
else if (Ogg::Speex::File::isSupported(stream))
file = new Ogg::Speex::File(stream, readAudioProperties, audioPropertiesStyle);
else if(Ogg::Opus::File::isSupported(stream))
else if (Ogg::Opus::File::isSupported(stream))
file = new Ogg::Opus::File(stream, readAudioProperties, audioPropertiesStyle);
else if(TrueAudio::File::isSupported(stream))
else if (TrueAudio::File::isSupported(stream))
file = new TrueAudio::File(stream, readAudioProperties, audioPropertiesStyle);
else if(MP4::File::isSupported(stream))
else if (MP4::File::isSupported(stream))
file = new MP4::File(stream, readAudioProperties, audioPropertiesStyle);
else if(ASF::File::isSupported(stream))
else if (ASF::File::isSupported(stream))
file = new ASF::File(stream, readAudioProperties, audioPropertiesStyle);
else if(RIFF::AIFF::File::isSupported(stream))
else if (RIFF::AIFF::File::isSupported(stream))
file = new RIFF::AIFF::File(stream, readAudioProperties, audioPropertiesStyle);
else if(RIFF::WAV::File::isSupported(stream))
else if (RIFF::WAV::File::isSupported(stream))
file = new RIFF::WAV::File(stream, readAudioProperties, audioPropertiesStyle);
else if(APE::File::isSupported(stream))
else if (APE::File::isSupported(stream))
file = new APE::File(stream, readAudioProperties, audioPropertiesStyle);
else if(DSDIFF::File::isSupported(stream))
else if (DSDIFF::File::isSupported(stream))
file = new DSDIFF::File(stream, readAudioProperties, audioPropertiesStyle);
else if(DSF::File::isSupported(stream))
else if (DSF::File::isSupported(stream))
file = new DSF::File(stream, readAudioProperties, audioPropertiesStyle);
// isSupported() only does a quick check, so double check the file here.
if(file) {
if(file->isValid())
if (file) {
if (file->isValid())
return file;
else
delete file;
}
return nullptr;
}
}
// Internal function that supports FileRef::create().
// This looks redundant, but necessary in order not to change the previous
// behavior of FileRef::create().
// Internal function that supports FileRef::create().
// This looks redundant, but necessary in order not to change the previous
// behavior of FileRef::create().
File* createInternal(FileName fileName, bool readAudioProperties,
AudioProperties::ReadStyle audioPropertiesStyle)
{
File *createInternal(FileName fileName, bool readAudioProperties,
AudioProperties::ReadStyle audioPropertiesStyle) {
File *file = detectByResolvers(fileName, readAudioProperties, audioPropertiesStyle);
if(file)
if (file)
return file;
#ifdef _WIN32
@ -216,17 +211,17 @@ namespace
String ext;
const int pos = s.rfind(".");
if(pos != -1)
if (pos != -1)
ext = s.substr(pos + 1).upper();
if(ext.isEmpty())
if (ext.isEmpty())
return nullptr;
if(ext == "MP3")
if (ext == "MP3")
return new MPEG::File(fileName, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
if(ext == "OGG")
if (ext == "OGG")
return new Ogg::Vorbis::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "OGA") {
if (ext == "OGA") {
/* .oga can be any audio in the Ogg container. First try FLAC, then Vorbis. */
File *file_flac = new Ogg::FLAC::File(fileName, readAudioProperties, audioPropertiesStyle);
if (file_flac->isValid())
@ -234,51 +229,49 @@ namespace
delete file_flac;
return new Ogg::Vorbis::File(fileName, readAudioProperties, audioPropertiesStyle);
}
if(ext == "FLAC")
if (ext == "FLAC")
return new FLAC::File(fileName, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
if(ext == "MPC")
if (ext == "MPC")
return new MPC::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "WV")
if (ext == "WV")
return new WavPack::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "SPX")
if (ext == "SPX")
return new Ogg::Speex::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "OPUS")
if (ext == "OPUS")
return new Ogg::Opus::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "TTA")
if (ext == "TTA")
return new TrueAudio::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "M4A" || ext == "M4R" || ext == "M4B" || ext == "M4P" || ext == "MP4" || ext == "3G2" || ext == "M4V")
if (ext == "M4A" || ext == "M4R" || ext == "M4B" || ext == "M4P" || ext == "MP4" || ext == "3G2" || ext == "M4V")
return new MP4::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "WMA" || ext == "ASF")
if (ext == "WMA" || ext == "ASF")
return new ASF::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "AIF" || ext == "AIFF" || ext == "AFC" || ext == "AIFC")
if (ext == "AIF" || ext == "AIFF" || ext == "AFC" || ext == "AIFC")
return new RIFF::AIFF::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "WAV")
if (ext == "WAV")
return new RIFF::WAV::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "APE")
if (ext == "APE")
return new APE::File(fileName, readAudioProperties, audioPropertiesStyle);
// module, nst and wow are possible but uncommon extensions
if(ext == "MOD" || ext == "MODULE" || ext == "NST" || ext == "WOW")
if (ext == "MOD" || ext == "MODULE" || ext == "NST" || ext == "WOW")
return new Mod::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "S3M")
if (ext == "S3M")
return new S3M::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "IT")
if (ext == "IT")
return new IT::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "XM")
if (ext == "XM")
return new XM::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "DFF" || ext == "DSDIFF")
if (ext == "DFF" || ext == "DSDIFF")
return new DSDIFF::File(fileName, readAudioProperties, audioPropertiesStyle);
if(ext == "DSF")
if (ext == "DSF")
return new DSF::File(fileName, readAudioProperties, audioPropertiesStyle);
return nullptr;
}
}
} // namespace
class FileRef::FileRefPrivate : public RefCounter
{
public:
FileRefPrivate() :
RefCounter(),
class FileRef::FileRefPrivate : public RefCounter {
public:
FileRefPrivate() : RefCounter(),
file(0),
stream(0) {}
@ -295,68 +288,53 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
FileRef::FileRef() :
d(new FileRefPrivate())
{
FileRef::FileRef() : d(new FileRefPrivate()) {
}
FileRef::FileRef(FileName fileName, bool readAudioProperties,
AudioProperties::ReadStyle audioPropertiesStyle) :
d(new FileRefPrivate())
{
AudioProperties::ReadStyle audioPropertiesStyle) : d(new FileRefPrivate()) {
parse(fileName, readAudioProperties, audioPropertiesStyle);
}
FileRef::FileRef(IOStream* stream, bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle) :
d(new FileRefPrivate())
{
FileRef::FileRef(IOStream *stream, bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle) : d(new FileRefPrivate()) {
parse(stream, readAudioProperties, audioPropertiesStyle);
}
FileRef::FileRef(File *file) :
d(new FileRefPrivate())
{
FileRef::FileRef(File *file) : d(new FileRefPrivate()) {
d->file = file;
}
FileRef::FileRef(const FileRef &ref) :
d(ref.d)
{
FileRef::FileRef(const FileRef &ref) : d(ref.d) {
d->ref();
}
FileRef::~FileRef()
{
if(d->deref())
FileRef::~FileRef() {
if (d->deref())
delete d;
}
Tag *FileRef::tag() const
{
if(isNull()) {
Tag *FileRef::tag() const {
if (isNull()) {
debug("FileRef::tag() - Called without a valid file.");
return nullptr;
}
return d->file->tag();
}
AudioProperties *FileRef::audioProperties() const
{
if(isNull()) {
AudioProperties *FileRef::audioProperties() const {
if (isNull()) {
debug("FileRef::audioProperties() - Called without a valid file.");
return nullptr;
}
return d->file->audioProperties();
}
File *FileRef::file() const
{
File *FileRef::file() const {
return d->file;
}
bool FileRef::save()
{
if(isNull()) {
bool FileRef::save() {
if (isNull()) {
debug("FileRef::save() - Called without a valid file.");
return false;
}
@ -369,8 +347,7 @@ const FileRef::FileTypeResolver *FileRef::addFileTypeResolver(const FileRef::Fil
return resolver;
}
StringList FileRef::defaultFileExtensions()
{
StringList FileRef::defaultFileExtensions() {
StringList l;
l.append("ogg");
@ -408,31 +385,26 @@ StringList FileRef::defaultFileExtensions()
return l;
}
bool FileRef::isNull() const
{
bool FileRef::isNull() const {
return (!d->file || !d->file->isValid());
}
FileRef &FileRef::operator=(const FileRef &ref)
{
FileRef &FileRef::operator=(const FileRef &ref) {
FileRef(ref).swap(*this);
return *this;
}
void FileRef::swap(FileRef &ref)
{
void FileRef::swap(FileRef &ref) {
using std::swap;
swap(d, ref.d);
}
bool FileRef::operator==(const FileRef &ref) const
{
bool FileRef::operator==(const FileRef &ref) const {
return (ref.d->file == d->file);
}
bool FileRef::operator!=(const FileRef &ref) const
{
bool FileRef::operator!=(const FileRef &ref) const {
return (ref.d->file != d->file);
}
@ -447,25 +419,24 @@ File *FileRef::create(FileName fileName, bool readAudioProperties,
////////////////////////////////////////////////////////////////////////////////
void FileRef::parse(FileName fileName, bool readAudioProperties,
AudioProperties::ReadStyle audioPropertiesStyle)
{
AudioProperties::ReadStyle audioPropertiesStyle) {
// Try user-defined resolvers.
d->file = detectByResolvers(fileName, readAudioProperties, audioPropertiesStyle);
if(d->file)
if (d->file)
return;
// Try to resolve file types based on the file extension.
d->stream = new FileStream(fileName);
d->file = detectByExtension(d->stream, readAudioProperties, audioPropertiesStyle);
if(d->file)
if (d->file)
return;
// At last, try to resolve file types based on the actual content.
d->file = detectByContent(d->stream, readAudioProperties, audioPropertiesStyle);
if(d->file)
if (d->file)
return;
// Stream have to be closed here if failed to resolve file types.
@ -475,14 +446,13 @@ void FileRef::parse(FileName fileName, bool readAudioProperties,
}
void FileRef::parse(IOStream *stream, bool readAudioProperties,
AudioProperties::ReadStyle audioPropertiesStyle)
{
AudioProperties::ReadStyle audioPropertiesStyle) {
// User-defined resolvers won't work with a stream.
// Try to resolve file types based on the file extension.
d->file = detectByExtension(stream, readAudioProperties, audioPropertiesStyle);
if(d->file)
if (d->file)
return;
// At last, try to resolve file types based on the actual content of the file.

View File

@ -35,11 +35,11 @@
namespace Strawberry_TagLib {
namespace TagLib {
class Tag;
class Tag;
//! This class provides a simple abstraction for creating and handling files
//! This class provides a simple abstraction for creating and handling files
/*!
/*!
* FileRef exists to provide a minimal, generic and value-based wrapper around
* a File. It is lightweight and implicitly shared, and as such suitable for
* pass-by-value use. This hides some of the uglier details of TagLib::File
@ -57,10 +57,8 @@ namespace TagLib {
* \see addFileTypeResolver()
*/
class TAGLIB_EXPORT FileRef
{
class TAGLIB_EXPORT FileRef {
public:
//! A class for pluggable file type resolution.
/*!
@ -90,8 +88,7 @@ namespace TagLib {
* to TagLib.
*/
class TAGLIB_EXPORT FileTypeResolver
{
class TAGLIB_EXPORT FileTypeResolver {
public:
virtual ~FileTypeResolver();
/*!
@ -140,7 +137,7 @@ namespace TagLib {
* \note TagLib will *not* take ownership of the stream, the caller is
* responsible for deleting it after the File object.
*/
explicit FileRef(IOStream* stream,
explicit FileRef(IOStream *stream,
bool readAudioProperties = true,
AudioProperties::ReadStyle
audioPropertiesStyle = AudioProperties::Average);
@ -281,9 +278,9 @@ namespace TagLib {
class FileRefPrivate;
FileRefPrivate *d;
};
};
}
} // namespace Strawberry_TagLib::TagLib
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif // TAGLIB_FILEREF_H

View File

@ -43,38 +43,35 @@
using namespace Strawberry_TagLib::TagLib;
namespace
{
typedef List<FLAC::MetadataBlock *> BlockList;
typedef BlockList::Iterator BlockIterator;
typedef BlockList::Iterator BlockConstIterator;
namespace {
typedef List<FLAC::MetadataBlock *> BlockList;
typedef BlockList::Iterator BlockIterator;
typedef BlockList::Iterator BlockConstIterator;
enum { FlacXiphIndex = 0, FlacID3v2Index = 1, FlacID3v1Index = 2 };
enum { FlacXiphIndex = 0,
FlacID3v2Index = 1,
FlacID3v1Index = 2 };
const long MinPaddingLength = 4096;
const long MaxPaddingLegnth = 1024 * 1024;
const long MinPaddingLength = 4096;
const long MaxPaddingLegnth = 1024 * 1024;
const char LastBlockFlag = '\x80';
}
const char LastBlockFlag = '\x80';
} // namespace
class FLAC::File::FilePrivate
{
public:
explicit FilePrivate(const ID3v2::FrameFactory *frameFactory = ID3v2::FrameFactory::instance()) :
ID3v2FrameFactory(frameFactory),
class FLAC::File::FilePrivate {
public:
explicit FilePrivate(const ID3v2::FrameFactory *frameFactory = ID3v2::FrameFactory::instance()) : ID3v2FrameFactory(frameFactory),
ID3v2Location(-1),
ID3v2OriginalSize(0),
ID3v1Location(-1),
properties(0),
flacStart(0),
streamStart(0),
scanned(false)
{
scanned(false) {
blocks.setAutoDelete(true);
}
~FilePrivate()
{
~FilePrivate() {
delete properties;
}
@ -99,8 +96,7 @@ public:
// static members
////////////////////////////////////////////////////////////////////////////////
bool FLAC::File::isSupported(IOStream *stream)
{
bool FLAC::File::isSupported(IOStream *stream) {
// A FLAC file has an ID "fLaC" somewhere. An ID3v2 tag may precede.
const ByteVector buffer = Utils::readHeader(stream, bufferSize(), true);
@ -111,84 +107,71 @@ bool FLAC::File::isSupported(IOStream *stream)
// public members
////////////////////////////////////////////////////////////////////////////////
FLAC::File::File(FileName file, bool readProperties, Properties::ReadStyle) :
Strawberry_TagLib::TagLib::File(file),
d(new FilePrivate())
{
if(isOpen())
FLAC::File::File(FileName file, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file),
d(new FilePrivate()) {
if (isOpen())
read(readProperties);
}
FLAC::File::File(FileName file, ID3v2::FrameFactory *frameFactory,
bool readProperties, Properties::ReadStyle) :
Strawberry_TagLib::TagLib::File(file),
d(new FilePrivate(frameFactory))
{
if(isOpen())
bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file),
d(new FilePrivate(frameFactory)) {
if (isOpen())
read(readProperties);
}
FLAC::File::File(IOStream *stream, ID3v2::FrameFactory *frameFactory,
bool readProperties, Properties::ReadStyle) :
Strawberry_TagLib::TagLib::File(stream),
d(new FilePrivate(frameFactory))
{
if(isOpen())
bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(stream),
d(new FilePrivate(frameFactory)) {
if (isOpen())
read(readProperties);
}
FLAC::File::~File()
{
FLAC::File::~File() {
delete d;
}
Strawberry_TagLib::TagLib::Tag *FLAC::File::tag() const
{
Strawberry_TagLib::TagLib::Tag *FLAC::File::tag() const {
return &d->tag;
}
PropertyMap FLAC::File::properties() const
{
PropertyMap FLAC::File::properties() const {
return d->tag.properties();
}
void FLAC::File::removeUnsupportedProperties(const StringList &unsupported)
{
void FLAC::File::removeUnsupportedProperties(const StringList &unsupported) {
d->tag.removeUnsupportedProperties(unsupported);
}
PropertyMap FLAC::File::setProperties(const PropertyMap &properties)
{
PropertyMap FLAC::File::setProperties(const PropertyMap &properties) {
return xiphComment(true)->setProperties(properties);
}
FLAC::Properties *FLAC::File::audioProperties() const
{
FLAC::Properties *FLAC::File::audioProperties() const {
return d->properties;
}
bool FLAC::File::save()
{
if(readOnly()) {
bool FLAC::File::save() {
if (readOnly()) {
debug("FLAC::File::save() - Cannot save to a read only file.");
return false;
}
if(!isValid()) {
if (!isValid()) {
debug("FLAC::File::save() -- Trying to save invalid file.");
return false;
}
// Create new vorbis comments
if(!hasXiphComment())
if (!hasXiphComment())
Tag::duplicate(&d->tag, xiphComment(true), false);
d->xiphCommentData = xiphComment()->render(false);
// Replace metadata blocks
for(BlockIterator it = d->blocks.begin(); it != d->blocks.end(); ++it) {
if((*it)->code() == MetadataBlock::VorbisComment) {
for (BlockIterator it = d->blocks.begin(); it != d->blocks.end(); ++it) {
if ((*it)->code() == MetadataBlock::VorbisComment) {
// Set the new Vorbis Comment block
delete *it;
d->blocks.erase(it);
@ -201,7 +184,7 @@ bool FLAC::File::save()
// Render data for the metadata blocks
ByteVector data;
for(BlockConstIterator it = d->blocks.begin(); it != d->blocks.end(); ++it) {
for (BlockConstIterator it = d->blocks.begin(); it != d->blocks.end(); ++it) {
ByteVector blockData = (*it)->render();
ByteVector blockHeader = ByteVector::fromUInt(blockData.size());
blockHeader[0] = (*it)->code();
@ -214,7 +197,7 @@ bool FLAC::File::save()
long originalLength = d->streamStart - d->flacStart;
long paddingLength = originalLength - data.size() - 4;
if(paddingLength <= 0) {
if (paddingLength <= 0) {
paddingLength = MinPaddingLength;
}
else {
@ -224,7 +207,7 @@ bool FLAC::File::save()
threshold = std::max(threshold, MinPaddingLength);
threshold = std::min(threshold, MaxPaddingLegnth);
if(paddingLength > threshold)
if (paddingLength > threshold)
paddingLength = MinPaddingLength;
}
@ -239,16 +222,16 @@ bool FLAC::File::save()
d->streamStart += (static_cast<long>(data.size()) - originalLength);
if(d->ID3v1Location >= 0)
if (d->ID3v1Location >= 0)
d->ID3v1Location += (static_cast<long>(data.size()) - originalLength);
// Update ID3 tags
if(ID3v2Tag() && !ID3v2Tag()->isEmpty()) {
if (ID3v2Tag() && !ID3v2Tag()->isEmpty()) {
// ID3v2 tag is not empty. Update the old one or create a new one.
if(d->ID3v2Location < 0)
if (d->ID3v2Location < 0)
d->ID3v2Location = 0;
data = ID3v2Tag()->render();
@ -257,7 +240,7 @@ bool FLAC::File::save()
d->flacStart += (static_cast<long>(data.size()) - d->ID3v2OriginalSize);
d->streamStart += (static_cast<long>(data.size()) - d->ID3v2OriginalSize);
if(d->ID3v1Location >= 0)
if (d->ID3v1Location >= 0)
d->ID3v1Location += (static_cast<long>(data.size()) - d->ID3v2OriginalSize);
d->ID3v2OriginalSize = data.size();
@ -266,13 +249,13 @@ bool FLAC::File::save()
// ID3v2 tag is empty. Remove the old one.
if(d->ID3v2Location >= 0) {
if (d->ID3v2Location >= 0) {
removeBlock(d->ID3v2Location, d->ID3v2OriginalSize);
d->flacStart -= d->ID3v2OriginalSize;
d->streamStart -= d->ID3v2OriginalSize;
if(d->ID3v1Location >= 0)
if (d->ID3v1Location >= 0)
d->ID3v1Location -= d->ID3v2OriginalSize;
d->ID3v2Location = -1;
@ -280,11 +263,11 @@ bool FLAC::File::save()
}
}
if(ID3v1Tag() && !ID3v1Tag()->isEmpty()) {
if (ID3v1Tag() && !ID3v1Tag()->isEmpty()) {
// ID3v1 tag is not empty. Update the old one or create a new one.
if(d->ID3v1Location >= 0) {
if (d->ID3v1Location >= 0) {
seek(d->ID3v1Location);
}
else {
@ -298,7 +281,7 @@ bool FLAC::File::save()
// ID3v1 tag is empty. Remove the old one.
if(d->ID3v1Location >= 0) {
if (d->ID3v1Location >= 0) {
truncate(d->ID3v1Location);
d->ID3v1Location = -1;
}
@ -307,69 +290,59 @@ bool FLAC::File::save()
return true;
}
ID3v2::Tag *FLAC::File::ID3v2Tag(bool create)
{
ID3v2::Tag *FLAC::File::ID3v2Tag(bool create) {
return d->tag.access<ID3v2::Tag>(FlacID3v2Index, create);
}
ID3v1::Tag *FLAC::File::ID3v1Tag(bool create)
{
ID3v1::Tag *FLAC::File::ID3v1Tag(bool create) {
return d->tag.access<ID3v1::Tag>(FlacID3v1Index, create);
}
Ogg::XiphComment *FLAC::File::xiphComment(bool create)
{
Ogg::XiphComment *FLAC::File::xiphComment(bool create) {
return d->tag.access<Ogg::XiphComment>(FlacXiphIndex, create);
}
void FLAC::File::setID3v2FrameFactory(const ID3v2::FrameFactory *factory)
{
void FLAC::File::setID3v2FrameFactory(const ID3v2::FrameFactory *factory) {
d->ID3v2FrameFactory = factory;
}
ByteVector FLAC::File::streamInfoData()
{
ByteVector FLAC::File::streamInfoData() {
debug("FLAC::File::streamInfoData() -- This function is obsolete. Returning an empty ByteVector.");
return ByteVector();
}
long FLAC::File::streamLength()
{
long FLAC::File::streamLength() {
debug("FLAC::File::streamLength() -- This function is obsolete. Returning zero.");
return 0;
}
List<FLAC::Picture *> FLAC::File::pictureList()
{
List<FLAC::Picture *> FLAC::File::pictureList() {
List<Picture *> pictures;
for(BlockConstIterator it = d->blocks.begin(); it != d->blocks.end(); ++it) {
for (BlockConstIterator it = d->blocks.begin(); it != d->blocks.end(); ++it) {
Picture *picture = dynamic_cast<Picture *>(*it);
if(picture) {
if (picture) {
pictures.append(picture);
}
}
return pictures;
}
void FLAC::File::addPicture(Picture *picture)
{
void FLAC::File::addPicture(Picture *picture) {
d->blocks.append(picture);
}
void FLAC::File::removePicture(Picture *picture, bool del)
{
void FLAC::File::removePicture(Picture *picture, bool del) {
BlockIterator it = d->blocks.find(picture);
if(it != d->blocks.end())
if (it != d->blocks.end())
d->blocks.erase(it);
if(del)
if (del)
delete picture;
}
void FLAC::File::removePictures()
{
for(BlockIterator it = d->blocks.begin(); it != d->blocks.end(); ) {
if(dynamic_cast<Picture *>(*it)) {
void FLAC::File::removePictures() {
for (BlockIterator it = d->blocks.begin(); it != d->blocks.end();) {
if (dynamic_cast<Picture *>(*it)) {
delete *it;
it = d->blocks.erase(it);
}
@ -379,32 +352,28 @@ void FLAC::File::removePictures()
}
}
void FLAC::File::strip(int tags)
{
if(tags & ID3v1)
void FLAC::File::strip(int tags) {
if (tags & ID3v1)
d->tag.set(FlacID3v1Index, 0);
if(tags & ID3v2)
if (tags & ID3v2)
d->tag.set(FlacID3v2Index, 0);
if(tags & XiphComment) {
if (tags & XiphComment) {
xiphComment()->removeAllFields();
xiphComment()->removeAllPictures();
}
}
bool FLAC::File::hasXiphComment() const
{
bool FLAC::File::hasXiphComment() const {
return !d->xiphCommentData.isEmpty();
}
bool FLAC::File::hasID3v1Tag() const
{
bool FLAC::File::hasID3v1Tag() const {
return (d->ID3v1Location >= 0);
}
bool FLAC::File::hasID3v2Tag() const
{
bool FLAC::File::hasID3v2Tag() const {
return (d->ID3v2Location >= 0);
}
@ -412,13 +381,12 @@ bool FLAC::File::hasID3v2Tag() const
// private members
////////////////////////////////////////////////////////////////////////////////
void FLAC::File::read(bool readProperties)
{
void FLAC::File::read(bool readProperties) {
// Look for an ID3v2 tag
d->ID3v2Location = Utils::findID3v2(this);
if(d->ID3v2Location >= 0) {
if (d->ID3v2Location >= 0) {
d->tag.set(FlacID3v2Index, new ID3v2::Tag(this, d->ID3v2Location, d->ID3v2FrameFactory));
d->ID3v2OriginalSize = ID3v2Tag()->header()->completeTagSize();
}
@ -427,22 +395,22 @@ void FLAC::File::read(bool readProperties)
d->ID3v1Location = Utils::findID3v1(this);
if(d->ID3v1Location >= 0)
if (d->ID3v1Location >= 0)
d->tag.set(FlacID3v1Index, new ID3v1::Tag(this, d->ID3v1Location));
// Look for FLAC metadata, including vorbis comments
scan();
if(!isValid())
if (!isValid())
return;
if(!d->xiphCommentData.isEmpty())
if (!d->xiphCommentData.isEmpty())
d->tag.set(FlacXiphIndex, new Ogg::XiphComment(d->xiphCommentData));
else
d->tag.set(FlacXiphIndex, new Ogg::XiphComment());
if(readProperties) {
if (readProperties) {
// First block should be the stream_info metadata
@ -450,7 +418,7 @@ void FLAC::File::read(bool readProperties)
long streamLength;
if(d->ID3v1Location >= 0)
if (d->ID3v1Location >= 0)
streamLength = d->ID3v1Location - d->streamStart;
else
streamLength = length() - d->streamStart;
@ -459,24 +427,23 @@ void FLAC::File::read(bool readProperties)
}
}
void FLAC::File::scan()
{
void FLAC::File::scan() {
// Scan the metadata pages
if(d->scanned)
if (d->scanned)
return;
if(!isValid())
if (!isValid())
return;
long nextBlockOffset;
if(d->ID3v2Location >= 0)
if (d->ID3v2Location >= 0)
nextBlockOffset = find("fLaC", d->ID3v2Location + d->ID3v2OriginalSize);
else
nextBlockOffset = find("fLaC");
if(nextBlockOffset < 0) {
if (nextBlockOffset < 0) {
debug("FLAC::File::scan() -- FLAC stream not found");
setValid(false);
return;
@ -485,7 +452,7 @@ void FLAC::File::scan()
nextBlockOffset += 4;
d->flacStart = nextBlockOffset;
while(true) {
while (true) {
seek(nextBlockOffset);
const ByteVector header = readBlock(4);
@ -508,22 +475,20 @@ void FLAC::File::scan()
// First block should be the stream_info metadata
if(d->blocks.isEmpty() && blockType != MetadataBlock::StreamInfo) {
if (d->blocks.isEmpty() && blockType != MetadataBlock::StreamInfo) {
debug("FLAC::File::scan() -- First block should be the stream_info metadata");
setValid(false);
return;
}
if(blockLength == 0
&& blockType != MetadataBlock::Padding && blockType != MetadataBlock::SeekTable)
{
if (blockLength == 0 && blockType != MetadataBlock::Padding && blockType != MetadataBlock::SeekTable) {
debug("FLAC::File::scan() -- Zero-sized metadata block found");
setValid(false);
return;
}
const ByteVector data = readBlock(blockLength);
if(data.size() != blockLength) {
if (data.size() != blockLength) {
debug("FLAC::File::scan() -- Failed to read a metadata block");
setValid(false);
return;
@ -532,8 +497,8 @@ void FLAC::File::scan()
MetadataBlock *block = 0;
// Found the vorbis-comment
if(blockType == MetadataBlock::VorbisComment) {
if(d->xiphCommentData.isEmpty()) {
if (blockType == MetadataBlock::VorbisComment) {
if (d->xiphCommentData.isEmpty()) {
d->xiphCommentData = data;
block = new UnknownMetadataBlock(MetadataBlock::VorbisComment, data);
}
@ -541,9 +506,9 @@ void FLAC::File::scan()
debug("FLAC::File::scan() -- multiple Vorbis Comment blocks found, discarding");
}
}
else if(blockType == MetadataBlock::Picture) {
else if (blockType == MetadataBlock::Picture) {
FLAC::Picture *picture = new FLAC::Picture();
if(picture->parse(data)) {
if (picture->parse(data)) {
block = picture;
}
else {
@ -551,19 +516,19 @@ void FLAC::File::scan()
delete picture;
}
}
else if(blockType == MetadataBlock::Padding) {
else if (blockType == MetadataBlock::Padding) {
// Skip all padding blocks.
}
else {
block = new UnknownMetadataBlock(blockType, data);
}
if(block)
if (block)
d->blocks.append(block);
nextBlockOffset += blockLength + 4;
if(isLastBlock)
if (isLastBlock)
break;
}

View File

@ -37,14 +37,21 @@
namespace Strawberry_TagLib {
namespace TagLib {
class Tag;
namespace ID3v2 { class FrameFactory; class Tag; }
namespace ID3v1 { class Tag; }
namespace Ogg { class XiphComment; }
class Tag;
namespace ID3v2 {
class FrameFactory;
class Tag;
} // namespace ID3v2
namespace ID3v1 {
class Tag;
}
namespace Ogg {
class XiphComment;
}
//! An implementation of FLAC metadata
//! An implementation of FLAC metadata
/*!
/*!
* This is implementation of FLAC metadata for non-Ogg FLAC files. At some
* point when Ogg / FLAC is more common there will be a similar implementation
* under the Ogg hierarchy.
@ -53,19 +60,18 @@ namespace TagLib {
* properties from the file.
*/
namespace FLAC {
namespace FLAC {
//! An implementation of TagLib::File with FLAC specific methods
//! An implementation of TagLib::File with FLAC specific methods
/*!
/*!
* This implements and provides an interface for FLAC 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 FLAC files.
*/
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File
{
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File {
public:
/*!
* This set of flags is used for various operations and is suitable for
@ -337,9 +343,9 @@ namespace TagLib {
class FilePrivate;
FilePrivate *d;
};
}
}
}
};
} // namespace FLAC
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -29,19 +29,14 @@
using namespace Strawberry_TagLib::TagLib;
class FLAC::MetadataBlock::MetadataBlockPrivate
{
public:
class FLAC::MetadataBlock::MetadataBlockPrivate {
public:
MetadataBlockPrivate() {}
};
FLAC::MetadataBlock::MetadataBlock()
{
FLAC::MetadataBlock::MetadataBlock() {
d = 0;
}
FLAC::MetadataBlock::~MetadataBlock()
{
FLAC::MetadataBlock::~MetadataBlock() {
}

View File

@ -33,10 +33,9 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace FLAC {
namespace FLAC {
class TAGLIB_EXPORT MetadataBlock
{
class TAGLIB_EXPORT MetadataBlock {
public:
MetadataBlock();
virtual ~MetadataBlock();
@ -67,11 +66,11 @@ namespace TagLib {
class MetadataBlockPrivate;
MetadataBlockPrivate *d;
};
};
}
} // namespace FLAC
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -29,16 +29,14 @@
using namespace Strawberry_TagLib::TagLib;
class FLAC::Picture::PicturePrivate
{
public:
PicturePrivate() :
type(FLAC::Picture::Other),
class FLAC::Picture::PicturePrivate {
public:
PicturePrivate() : type(FLAC::Picture::Other),
width(0),
height(0),
colorDepth(0),
numColors(0)
{}
numColors(0) {
}
Type type;
String mimeType;
@ -50,30 +48,23 @@ public:
ByteVector data;
};
FLAC::Picture::Picture() :
d(new PicturePrivate())
{
FLAC::Picture::Picture() : d(new PicturePrivate()) {
}
FLAC::Picture::Picture(const ByteVector &data) :
d(new PicturePrivate())
{
FLAC::Picture::Picture(const ByteVector &data) : d(new PicturePrivate()) {
parse(data);
}
FLAC::Picture::~Picture()
{
FLAC::Picture::~Picture() {
delete d;
}
int FLAC::Picture::code() const
{
int FLAC::Picture::code() const {
return FLAC::MetadataBlock::Picture;
}
bool FLAC::Picture::parse(const ByteVector &data)
{
if(data.size() < 32) {
bool FLAC::Picture::parse(const ByteVector &data) {
if (data.size() < 32) {
debug("A picture block must contain at least 5 bytes.");
return false;
}
@ -83,7 +74,7 @@ bool FLAC::Picture::parse(const ByteVector &data)
pos += 4;
unsigned int mimeTypeLength = data.toUInt(pos);
pos += 4;
if(pos + mimeTypeLength + 24 > data.size()) {
if (pos + mimeTypeLength + 24 > data.size()) {
debug("Invalid picture block.");
return false;
}
@ -91,7 +82,7 @@ bool FLAC::Picture::parse(const ByteVector &data)
pos += mimeTypeLength;
unsigned int descriptionLength = data.toUInt(pos);
pos += 4;
if(pos + descriptionLength + 20 > data.size()) {
if (pos + descriptionLength + 20 > data.size()) {
debug("Invalid picture block.");
return false;
}
@ -107,7 +98,7 @@ bool FLAC::Picture::parse(const ByteVector &data)
pos += 4;
unsigned int dataLength = data.toUInt(pos);
pos += 4;
if(pos + dataLength > data.size()) {
if (pos + dataLength > data.size()) {
debug("Invalid picture block.");
return false;
}
@ -116,8 +107,7 @@ bool FLAC::Picture::parse(const ByteVector &data)
return true;
}
ByteVector FLAC::Picture::render() const
{
ByteVector FLAC::Picture::render() const {
ByteVector result;
result.append(ByteVector::fromUInt(d->type));
ByteVector mimeTypeData = d->mimeType.data(String::UTF8);
@ -135,83 +125,66 @@ ByteVector FLAC::Picture::render() const
return result;
}
FLAC::Picture::Type FLAC::Picture::type() const
{
FLAC::Picture::Type FLAC::Picture::type() const {
return d->type;
}
void FLAC::Picture::setType(FLAC::Picture::Type type)
{
void FLAC::Picture::setType(FLAC::Picture::Type type) {
d->type = type;
}
String FLAC::Picture::mimeType() const
{
String FLAC::Picture::mimeType() const {
return d->mimeType;
}
void FLAC::Picture::setMimeType(const String &mimeType)
{
void FLAC::Picture::setMimeType(const String &mimeType) {
d->mimeType = mimeType;
}
String FLAC::Picture::description() const
{
String FLAC::Picture::description() const {
return d->description;
}
void FLAC::Picture::setDescription(const String &description)
{
void FLAC::Picture::setDescription(const String &description) {
d->description = description;
}
int FLAC::Picture::width() const
{
int FLAC::Picture::width() const {
return d->width;
}
void FLAC::Picture::setWidth(int width)
{
void FLAC::Picture::setWidth(int width) {
d->width = width;
}
int FLAC::Picture::height() const
{
int FLAC::Picture::height() const {
return d->height;
}
void FLAC::Picture::setHeight(int height)
{
void FLAC::Picture::setHeight(int height) {
d->height = height;
}
int FLAC::Picture::colorDepth() const
{
int FLAC::Picture::colorDepth() const {
return d->colorDepth;
}
void FLAC::Picture::setColorDepth(int colorDepth)
{
void FLAC::Picture::setColorDepth(int colorDepth) {
d->colorDepth = colorDepth;
}
int FLAC::Picture::numColors() const
{
int FLAC::Picture::numColors() const {
return d->numColors;
}
void FLAC::Picture::setNumColors(int numColors)
{
void FLAC::Picture::setNumColors(int numColors) {
d->numColors = numColors;
}
ByteVector FLAC::Picture::data() const
{
ByteVector FLAC::Picture::data() const {
return d->data;
}
void FLAC::Picture::setData(const ByteVector &data)
{
void FLAC::Picture::setData(const ByteVector &data) {
d->data = data;
}

View File

@ -35,12 +35,10 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace FLAC {
namespace FLAC {
class TAGLIB_EXPORT Picture : public MetadataBlock
{
class TAGLIB_EXPORT Picture : public MetadataBlock {
public:
/*!
* This describes the function or content of the picture.
*/
@ -198,13 +196,13 @@ namespace TagLib {
class PicturePrivate;
PicturePrivate *d;
};
};
typedef List<Picture> PictureList;
typedef List<Picture> PictureList;
}
} // namespace FLAC
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -31,11 +31,9 @@
using namespace Strawberry_TagLib::TagLib;
class FLAC::Properties::PropertiesPrivate
{
public:
PropertiesPrivate() :
length(0),
class FLAC::Properties::PropertiesPrivate {
public:
PropertiesPrivate() : length(0),
bitrate(0),
sampleRate(0),
bitsPerSample(0),
@ -55,72 +53,57 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
FLAC::Properties::Properties(ByteVector data, long streamLength, ReadStyle style) :
AudioProperties(style),
d(new PropertiesPrivate())
{
FLAC::Properties::Properties(ByteVector data, long streamLength, ReadStyle style) : AudioProperties(style),
d(new PropertiesPrivate()) {
read(data, streamLength);
}
FLAC::Properties::Properties(File *, ReadStyle style) :
AudioProperties(style),
d(new PropertiesPrivate())
{
FLAC::Properties::Properties(File *, ReadStyle style) : AudioProperties(style),
d(new PropertiesPrivate()) {
debug("FLAC::Properties::Properties() - This constructor is no longer used.");
}
FLAC::Properties::~Properties()
{
FLAC::Properties::~Properties() {
delete d;
}
int FLAC::Properties::length() const
{
int FLAC::Properties::length() const {
return lengthInSeconds();
}
int FLAC::Properties::lengthInSeconds() const
{
int FLAC::Properties::lengthInSeconds() const {
return d->length / 1000;
}
int FLAC::Properties::lengthInMilliseconds() const
{
int FLAC::Properties::lengthInMilliseconds() const {
return d->length;
}
int FLAC::Properties::bitrate() const
{
int FLAC::Properties::bitrate() const {
return d->bitrate;
}
int FLAC::Properties::sampleRate() const
{
int FLAC::Properties::sampleRate() const {
return d->sampleRate;
}
int FLAC::Properties::bitsPerSample() const
{
int FLAC::Properties::bitsPerSample() const {
return d->bitsPerSample;
}
int FLAC::Properties::sampleWidth() const
{
int FLAC::Properties::sampleWidth() const {
return bitsPerSample();
}
int FLAC::Properties::channels() const
{
int FLAC::Properties::channels() const {
return d->channels;
}
unsigned long long FLAC::Properties::sampleFrames() const
{
unsigned long long FLAC::Properties::sampleFrames() const {
return d->sampleFrames;
}
ByteVector FLAC::Properties::signature() const
{
ByteVector FLAC::Properties::signature() const {
return d->signature;
}
@ -128,9 +111,8 @@ ByteVector FLAC::Properties::signature() const
// private members
////////////////////////////////////////////////////////////////////////////////
void FLAC::Properties::read(const ByteVector &data, long streamLength)
{
if(data.size() < 18) {
void FLAC::Properties::read(const ByteVector &data, long streamLength) {
if (data.size() < 18) {
debug("FLAC::Properties::read() - FLAC properties must contain at least 18 bytes.");
return;
}
@ -165,12 +147,12 @@ void FLAC::Properties::read(const ByteVector &data, long streamLength)
d->sampleFrames = (hi << 32) | lo;
if(d->sampleFrames > 0 && d->sampleRate > 0) {
if (d->sampleFrames > 0 && d->sampleRate > 0) {
const double length = d->sampleFrames * 1000.0 / d->sampleRate;
d->length = static_cast<int>(length + 0.5);
d->bitrate = static_cast<int>(streamLength * 8.0 / length + 0.5);
}
if(data.size() >= pos + 16)
if (data.size() >= pos + 16)
d->signature = data.mid(pos, 16);
}

View File

@ -32,19 +32,18 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace FLAC {
namespace FLAC {
class File;
class File;
//! An implementation of audio property reading for FLAC
//! An implementation of audio property reading for FLAC
/*!
/*!
* This reads the data from an FLAC stream found in the AudioProperties
* API.
*/
class TAGLIB_EXPORT Properties : public AudioProperties
{
class TAGLIB_EXPORT Properties : public AudioProperties {
public:
/*!
* Create an instance of FLAC::Properties with the data read from the
@ -142,9 +141,9 @@ namespace TagLib {
class PropertiesPrivate;
PropertiesPrivate *d;
};
}
}
}
};
} // namespace FLAC
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -30,49 +30,39 @@
using namespace Strawberry_TagLib::TagLib;
class FLAC::UnknownMetadataBlock::UnknownMetadataBlockPrivate
{
public:
class FLAC::UnknownMetadataBlock::UnknownMetadataBlockPrivate {
public:
UnknownMetadataBlockPrivate() : code(0) {}
int code;
ByteVector data;
};
FLAC::UnknownMetadataBlock::UnknownMetadataBlock(int code, const ByteVector &data) :
d(new UnknownMetadataBlockPrivate())
{
FLAC::UnknownMetadataBlock::UnknownMetadataBlock(int code, const ByteVector &data) : d(new UnknownMetadataBlockPrivate()) {
d->code = code;
d->data = data;
}
FLAC::UnknownMetadataBlock::~UnknownMetadataBlock()
{
FLAC::UnknownMetadataBlock::~UnknownMetadataBlock() {
delete d;
}
int FLAC::UnknownMetadataBlock::code() const
{
int FLAC::UnknownMetadataBlock::code() const {
return d->code;
}
void FLAC::UnknownMetadataBlock::setCode(int code)
{
void FLAC::UnknownMetadataBlock::setCode(int code) {
d->code = code;
}
ByteVector FLAC::UnknownMetadataBlock::data() const
{
ByteVector FLAC::UnknownMetadataBlock::data() const {
return d->data;
}
void FLAC::UnknownMetadataBlock::setData(const ByteVector &data)
{
void FLAC::UnknownMetadataBlock::setData(const ByteVector &data) {
d->data = data;
}
ByteVector FLAC::UnknownMetadataBlock::render() const
{
ByteVector FLAC::UnknownMetadataBlock::render() const {
return d->data;
}

View File

@ -34,10 +34,9 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace FLAC {
namespace FLAC {
class TAGLIB_EXPORT UnknownMetadataBlock : public MetadataBlock
{
class TAGLIB_EXPORT UnknownMetadataBlock : public MetadataBlock {
public:
UnknownMetadataBlock(int blockType, const ByteVector &data);
~UnknownMetadataBlock();
@ -73,11 +72,11 @@ namespace TagLib {
class UnknownMetadataBlockPrivate;
UnknownMetadataBlockPrivate *d;
};
};
}
} // namespace FLAC
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -33,12 +33,10 @@
using namespace Strawberry_TagLib::TagLib;
using namespace IT;
class IT::File::FilePrivate
{
public:
class IT::File::FilePrivate {
public:
explicit FilePrivate(AudioProperties::ReadStyle propertiesStyle)
: tag(), properties(propertiesStyle)
{
: tag(), properties(propertiesStyle) {
}
Mod::Tag tag;
@ -46,52 +44,41 @@ public:
};
IT::File::File(FileName file, bool readProperties,
AudioProperties::ReadStyle propertiesStyle) :
Mod::FileBase(file),
d(new FilePrivate(propertiesStyle))
{
if(isOpen())
AudioProperties::ReadStyle propertiesStyle) : Mod::FileBase(file),
d(new FilePrivate(propertiesStyle)) {
if (isOpen())
read(readProperties);
}
IT::File::File(IOStream *stream, bool readProperties,
AudioProperties::ReadStyle propertiesStyle) :
Mod::FileBase(stream),
d(new FilePrivate(propertiesStyle))
{
if(isOpen())
AudioProperties::ReadStyle propertiesStyle) : Mod::FileBase(stream),
d(new FilePrivate(propertiesStyle)) {
if (isOpen())
read(readProperties);
}
IT::File::~File()
{
IT::File::~File() {
delete d;
}
Mod::Tag *IT::File::tag() const
{
Mod::Tag *IT::File::tag() const {
return &d->tag;
}
PropertyMap IT::File::properties() const
{
PropertyMap IT::File::properties() const {
return d->tag.properties();
}
PropertyMap IT::File::setProperties(const PropertyMap &properties)
{
PropertyMap IT::File::setProperties(const PropertyMap &properties) {
return d->tag.setProperties(properties);
}
IT::Properties *IT::File::audioProperties() const
{
IT::Properties *IT::File::audioProperties() const {
return &d->properties;
}
bool IT::File::save()
{
if(readOnly())
{
bool IT::File::save() {
if (readOnly()) {
debug("IT::File::save() - Cannot save to a read only file.");
return false;
}
@ -105,37 +92,37 @@ bool IT::File::save()
unsigned short instrumentCount = 0;
unsigned short sampleCount = 0;
if(!readU16L(length) || !readU16L(instrumentCount) || !readU16L(sampleCount))
if (!readU16L(length) || !readU16L(instrumentCount) || !readU16L(sampleCount))
return false;
seek(15, Current);
// write comment as instrument and sample names:
StringList lines = d->tag.comment().split("\n");
for(unsigned short i = 0; i < instrumentCount; ++ i) {
for (unsigned short i = 0; i < instrumentCount; ++i) {
seek(192L + length + ((long)i << 2));
unsigned long instrumentOffset = 0;
if(!readU32L(instrumentOffset))
if (!readU32L(instrumentOffset))
return false;
seek(instrumentOffset + 32);
if(i < lines.size())
if (i < lines.size())
writeString(lines[i], 25);
else
writeString(String(), 25);
writeByte(0);
}
for(unsigned short i = 0; i < sampleCount; ++ i) {
for (unsigned short i = 0; i < sampleCount; ++i) {
seek(192L + length + ((long)instrumentCount << 2) + ((long)i << 2));
unsigned long sampleOffset = 0;
if(!readU32L(sampleOffset))
if (!readU32L(sampleOffset))
return false;
seek(sampleOffset + 20);
if((unsigned int)(i + instrumentCount) < lines.size())
if ((unsigned int)(i + instrumentCount) < lines.size())
writeString(lines[i + instrumentCount], 25);
else
writeString(String(), 25);
@ -144,13 +131,13 @@ bool IT::File::save()
// write rest as message:
StringList messageLines;
for(unsigned int i = instrumentCount + sampleCount; i < lines.size(); ++ i)
for (unsigned int i = instrumentCount + sampleCount; i < lines.size(); ++i)
messageLines.append(lines[i]);
ByteVector message = messageLines.toString("\r").data(String::Latin1);
// it's actually not really stated if the message needs a
// terminating NUL but it does not hurt to add one:
if(message.size() > 7999)
if (message.size() > 7999)
message.resize(7999);
message.append((char)0);
@ -159,26 +146,25 @@ bool IT::File::save()
unsigned long messageOffset = 0;
seek(46);
if(!readU16L(special))
if (!readU16L(special))
return false;
unsigned long fileSize = File::length();
if(special & Properties::MessageAttached) {
if (special & Properties::MessageAttached) {
seek(54);
if(!readU16L(messageLength) || !readU32L(messageOffset))
if (!readU16L(messageLength) || !readU32L(messageOffset))
return false;
if(messageLength == 0)
if (messageLength == 0)
messageOffset = fileSize;
}
else
{
else {
messageOffset = fileSize;
seek(46);
writeU16L(special | 0x1);
}
if(messageOffset + messageLength >= fileSize) {
if (messageOffset + messageLength >= fileSize) {
// append new message
seek(54);
writeU16L(message.size());
@ -199,9 +185,8 @@ bool IT::File::save()
return true;
}
void IT::File::read(bool)
{
if(!isOpen())
void IT::File::read(bool) {
if (!isOpen())
return;
seek(0);
@ -233,14 +218,14 @@ void IT::File::read(bool)
// sample/instrument names are abused as comments so
// I just add all together.
String message;
if(special & Properties::MessageAttached) {
if (special & Properties::MessageAttached) {
READ_U16L_AS(messageLength);
READ_U32L_AS(messageOffset);
seek(messageOffset);
ByteVector messageBytes = readBlock(messageLength);
READ_ASSERT(messageBytes.size() == messageLength);
int index = messageBytes.find((char) 0);
if(index > -1)
int index = messageBytes.find((char)0);
if (index > -1)
messageBytes.resize(index, 0);
messageBytes.replace('\r', '\n');
message = messageBytes;
@ -252,23 +237,23 @@ void IT::File::read(bool)
ByteVector volumes = readBlock(64);
READ_ASSERT(pannings.size() == 64 && volumes.size() == 64);
int channels = 0;
for(int i = 0; i < 64; ++ i) {
for (int i = 0; i < 64; ++i) {
// Strictly speaking an IT file has always 64 channels, but
// I don't count disabled and muted channels.
// But this always gives 64 channels for all my files anyway.
// Strangely VLC does report other values. I wonder how VLC
// gets it's values.
if((unsigned char) pannings[i] < 128 && volumes[i] > 0)
if ((unsigned char)pannings[i] < 128 && volumes[i] > 0)
++channels;
}
d->properties.setChannels(channels);
// real length might be shorter because of skips and terminator
unsigned short realLength = 0;
for(unsigned short i = 0; i < length; ++ i) {
for (unsigned short i = 0; i < length; ++i) {
READ_BYTE_AS(order);
if(order == 255) break;
if(order != 254) ++ realLength;
if (order == 255) break;
if (order != 254) ++realLength;
}
d->properties.setLengthInPatterns(realLength);
@ -279,7 +264,7 @@ void IT::File::read(bool)
// Currently I just discard anything after a nil, but
// e.g. VLC seems to interpret a nil as a space. I
// don't know what is the proper behaviour.
for(unsigned short i = 0; i < instrumentCount; ++ i) {
for (unsigned short i = 0; i < instrumentCount; ++i) {
seek(192L + length + ((long)i << 2));
READ_U32L_AS(instrumentOffset);
seek(instrumentOffset);
@ -295,7 +280,7 @@ void IT::File::read(bool)
comment.append(instrumentName);
}
for(unsigned short i = 0; i < sampleCount; ++ i) {
for (unsigned short i = 0; i < sampleCount; ++i) {
seek(192L + length + ((long)instrumentCount << 2) + ((long)i << 2));
READ_U32L_AS(sampleOffset);
@ -328,7 +313,7 @@ void IT::File::read(bool)
comment.append(sampleName);
}
if(message.size() > 0)
if (message.size() > 0)
comment.append(message);
d->tag.setComment(comment.toString("\n"));
d->tag.setTrackerName("Impulse Tracker");

View File

@ -32,9 +32,9 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace IT {
namespace IT {
class TAGLIB_EXPORT File : public Mod::FileBase {
class TAGLIB_EXPORT File : public Mod::FileBase {
public:
/*!
* Constructs a Impulse Tracker file from \a file.
@ -103,9 +103,9 @@ namespace TagLib {
class FilePrivate;
FilePrivate *d;
};
}
}
}
};
} // namespace IT
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -29,11 +29,9 @@
using namespace Strawberry_TagLib::TagLib;
using namespace IT;
class IT::Properties::PropertiesPrivate
{
public:
PropertiesPrivate() :
channels(0),
class IT::Properties::PropertiesPrivate {
public:
PropertiesPrivate() : channels(0),
lengthInPatterns(0),
instrumentCount(0),
sampleCount(0),
@ -47,8 +45,7 @@ public:
tempo(0),
bpmSpeed(0),
panningSeparation(0),
pitchWheelDepth(0)
{
pitchWheelDepth(0) {
}
int channels;
@ -68,193 +65,154 @@ public:
unsigned char pitchWheelDepth;
};
IT::Properties::Properties(AudioProperties::ReadStyle propertiesStyle) :
AudioProperties(propertiesStyle),
d(new PropertiesPrivate())
{
IT::Properties::Properties(AudioProperties::ReadStyle propertiesStyle) : AudioProperties(propertiesStyle),
d(new PropertiesPrivate()) {
}
IT::Properties::~Properties()
{
IT::Properties::~Properties() {
delete d;
}
int IT::Properties::length() const
{
int IT::Properties::length() const {
return 0;
}
int IT::Properties::lengthInSeconds() const
{
int IT::Properties::lengthInSeconds() const {
return 0;
}
int IT::Properties::lengthInMilliseconds() const
{
int IT::Properties::lengthInMilliseconds() const {
return 0;
}
int IT::Properties::bitrate() const
{
int IT::Properties::bitrate() const {
return 0;
}
int IT::Properties::sampleRate() const
{
int IT::Properties::sampleRate() const {
return 0;
}
int IT::Properties::channels() const
{
int IT::Properties::channels() const {
return d->channels;
}
unsigned short IT::Properties::lengthInPatterns() const
{
unsigned short IT::Properties::lengthInPatterns() const {
return d->lengthInPatterns;
}
bool IT::Properties::stereo() const
{
bool IT::Properties::stereo() const {
return d->flags & Stereo;
}
unsigned short IT::Properties::instrumentCount() const
{
unsigned short IT::Properties::instrumentCount() const {
return d->instrumentCount;
}
unsigned short IT::Properties::sampleCount() const
{
unsigned short IT::Properties::sampleCount() const {
return d->sampleCount;
}
unsigned short IT::Properties::patternCount() const
{
unsigned short IT::Properties::patternCount() const {
return d->patternCount;
}
unsigned short IT::Properties::version() const
{
unsigned short IT::Properties::version() const {
return d->version;
}
unsigned short IT::Properties::compatibleVersion() const
{
unsigned short IT::Properties::compatibleVersion() const {
return d->compatibleVersion;
}
unsigned short IT::Properties::flags() const
{
unsigned short IT::Properties::flags() const {
return d->flags;
}
unsigned short IT::Properties::special() const
{
unsigned short IT::Properties::special() const {
return d->special;
}
unsigned char IT::Properties::globalVolume() const
{
unsigned char IT::Properties::globalVolume() const {
return d->globalVolume;
}
unsigned char IT::Properties::mixVolume() const
{
unsigned char IT::Properties::mixVolume() const {
return d->mixVolume;
}
unsigned char IT::Properties::tempo() const
{
unsigned char IT::Properties::tempo() const {
return d->tempo;
}
unsigned char IT::Properties::bpmSpeed() const
{
unsigned char IT::Properties::bpmSpeed() const {
return d->bpmSpeed;
}
unsigned char IT::Properties::panningSeparation() const
{
unsigned char IT::Properties::panningSeparation() const {
return d->panningSeparation;
}
unsigned char IT::Properties::pitchWheelDepth() const
{
unsigned char IT::Properties::pitchWheelDepth() const {
return d->pitchWheelDepth;
}
void IT::Properties::setChannels(int channels)
{
void IT::Properties::setChannels(int channels) {
d->channels = channels;
}
void IT::Properties::setLengthInPatterns(unsigned short lengthInPatterns)
{
void IT::Properties::setLengthInPatterns(unsigned short lengthInPatterns) {
d->lengthInPatterns = lengthInPatterns;
}
void IT::Properties::setInstrumentCount(unsigned short instrumentCount)
{
void IT::Properties::setInstrumentCount(unsigned short instrumentCount) {
d->instrumentCount = instrumentCount;
}
void IT::Properties::setSampleCount(unsigned short sampleCount)
{
void IT::Properties::setSampleCount(unsigned short sampleCount) {
d->sampleCount = sampleCount;
}
void IT::Properties::setPatternCount(unsigned short patternCount)
{
void IT::Properties::setPatternCount(unsigned short patternCount) {
d->patternCount = patternCount;
}
void IT::Properties::setFlags(unsigned short flags)
{
void IT::Properties::setFlags(unsigned short flags) {
d->flags = flags;
}
void IT::Properties::setSpecial(unsigned short special)
{
void IT::Properties::setSpecial(unsigned short special) {
d->special = special;
}
void IT::Properties::setCompatibleVersion(unsigned short compatibleVersion)
{
void IT::Properties::setCompatibleVersion(unsigned short compatibleVersion) {
d->compatibleVersion = compatibleVersion;
}
void IT::Properties::setVersion(unsigned short version)
{
void IT::Properties::setVersion(unsigned short version) {
d->version = version;
}
void IT::Properties::setGlobalVolume(unsigned char globalVolume)
{
void IT::Properties::setGlobalVolume(unsigned char globalVolume) {
d->globalVolume = globalVolume;
}
void IT::Properties::setMixVolume(unsigned char mixVolume)
{
void IT::Properties::setMixVolume(unsigned char mixVolume) {
d->mixVolume = mixVolume;
}
void IT::Properties::setTempo(unsigned char tempo)
{
void IT::Properties::setTempo(unsigned char tempo) {
d->tempo = tempo;
}
void IT::Properties::setBpmSpeed(unsigned char bpmSpeed)
{
void IT::Properties::setBpmSpeed(unsigned char bpmSpeed) {
d->bpmSpeed = bpmSpeed;
}
void IT::Properties::setPanningSeparation(unsigned char panningSeparation)
{
void IT::Properties::setPanningSeparation(unsigned char panningSeparation) {
d->panningSeparation = panningSeparation;
}
void IT::Properties::setPitchWheelDepth(unsigned char pitchWheelDepth)
{
void IT::Properties::setPitchWheelDepth(unsigned char pitchWheelDepth) {
d->pitchWheelDepth = pitchWheelDepth;
}

View File

@ -31,9 +31,10 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace IT {
class TAGLIB_EXPORT Properties : public AudioProperties {
namespace IT {
class TAGLIB_EXPORT Properties : public AudioProperties {
friend class File;
public:
/*! Flag bits. */
enum {
@ -82,28 +83,28 @@ namespace TagLib {
void setChannels(int channels);
void setLengthInPatterns(unsigned short lengthInPatterns);
void setInstrumentCount(unsigned short instrumentCount);
void setSampleCount (unsigned short sampleCount);
void setSampleCount(unsigned short sampleCount);
void setPatternCount(unsigned short patternCount);
void setVersion (unsigned short version);
void setVersion(unsigned short version);
void setCompatibleVersion(unsigned short compatibleVersion);
void setFlags (unsigned short flags);
void setSpecial (unsigned short special);
void setFlags(unsigned short flags);
void setSpecial(unsigned short special);
void setGlobalVolume(unsigned char globalVolume);
void setMixVolume (unsigned char mixVolume);
void setTempo (unsigned char tempo);
void setBpmSpeed (unsigned char bpmSpeed);
void setMixVolume(unsigned char mixVolume);
void setTempo(unsigned char tempo);
void setBpmSpeed(unsigned char bpmSpeed);
void setPanningSeparation(unsigned char panningSeparation);
void setPitchWheelDepth (unsigned char pitchWheelDepth);
void setPitchWheelDepth(unsigned char pitchWheelDepth);
private:
Properties(const Properties&);
Properties &operator=(const Properties&);
Properties(const Properties &);
Properties &operator=(const Properties &);
class PropertiesPrivate;
PropertiesPrivate *d;
};
}
}
}
};
} // namespace IT
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -33,12 +33,10 @@
using namespace Strawberry_TagLib::TagLib;
using namespace Mod;
class Mod::File::FilePrivate
{
public:
class Mod::File::FilePrivate {
public:
explicit FilePrivate(AudioProperties::ReadStyle propertiesStyle)
: properties(propertiesStyle)
{
: properties(propertiesStyle) {
}
Mod::Tag tag;
@ -46,51 +44,41 @@ public:
};
Mod::File::File(FileName file, bool readProperties,
AudioProperties::ReadStyle propertiesStyle) :
Mod::FileBase(file),
d(new FilePrivate(propertiesStyle))
{
if(isOpen())
AudioProperties::ReadStyle propertiesStyle) : Mod::FileBase(file),
d(new FilePrivate(propertiesStyle)) {
if (isOpen())
read(readProperties);
}
Mod::File::File(IOStream *stream, bool readProperties,
AudioProperties::ReadStyle propertiesStyle) :
Mod::FileBase(stream),
d(new FilePrivate(propertiesStyle))
{
if(isOpen())
AudioProperties::ReadStyle propertiesStyle) : Mod::FileBase(stream),
d(new FilePrivate(propertiesStyle)) {
if (isOpen())
read(readProperties);
}
Mod::File::~File()
{
Mod::File::~File() {
delete d;
}
Mod::Tag *Mod::File::tag() const
{
Mod::Tag *Mod::File::tag() const {
return &d->tag;
}
Mod::Properties *Mod::File::audioProperties() const
{
Mod::Properties *Mod::File::audioProperties() const {
return &d->properties;
}
PropertyMap Mod::File::properties() const
{
PropertyMap Mod::File::properties() const {
return d->tag.properties();
}
PropertyMap Mod::File::setProperties(const PropertyMap &properties)
{
PropertyMap Mod::File::setProperties(const PropertyMap &properties) {
return d->tag.setProperties(properties);
}
bool Mod::File::save()
{
if(readOnly()) {
bool Mod::File::save() {
if (readOnly()) {
debug("Mod::File::save() - Cannot save to a read only file.");
return false;
}
@ -98,21 +86,20 @@ bool Mod::File::save()
writeString(d->tag.title(), 20);
StringList lines = d->tag.comment().split("\n");
unsigned int n = std::min(lines.size(), d->properties.instrumentCount());
for(unsigned int i = 0; i < n; ++ i) {
for (unsigned int i = 0; i < n; ++i) {
writeString(lines[i], 22);
seek(8, Current);
}
for(unsigned int i = n; i < d->properties.instrumentCount(); ++ i) {
for (unsigned int i = n; i < d->properties.instrumentCount(); ++i) {
writeString(String(), 22);
seek(8, Current);
}
return true;
}
void Mod::File::read(bool)
{
if(!isOpen())
void Mod::File::read(bool) {
if (!isOpen())
return;
seek(1080);
@ -121,27 +108,27 @@ void Mod::File::read(bool)
int channels = 4;
unsigned int instruments = 31;
if(modId == "M.K." || modId == "M!K!" || modId == "M&K!" || modId == "N.T.") {
if (modId == "M.K." || modId == "M!K!" || modId == "M&K!" || modId == "N.T.") {
d->tag.setTrackerName("ProTracker");
channels = 4;
}
else if(modId.startsWith("FLT") || modId.startsWith("TDZ")) {
else if (modId.startsWith("FLT") || modId.startsWith("TDZ")) {
d->tag.setTrackerName("StarTrekker");
char digit = modId[3];
READ_ASSERT(digit >= '0' && digit <= '9');
channels = digit - '0';
}
else if(modId.endsWith("CHN")) {
else if (modId.endsWith("CHN")) {
d->tag.setTrackerName("StarTrekker");
char digit = modId[0];
READ_ASSERT(digit >= '0' && digit <= '9');
channels = digit - '0';
}
else if(modId == "CD81" || modId == "OKTA") {
else if (modId == "CD81" || modId == "OKTA") {
d->tag.setTrackerName("Atari Oktalyzer");
channels = 8;
}
else if(modId.endsWith("CH") || modId.endsWith("CN")) {
else if (modId.endsWith("CH") || modId.endsWith("CN")) {
d->tag.setTrackerName("TakeTracker");
char digit = modId[0];
READ_ASSERT(digit >= '0' && digit <= '9');
@ -164,7 +151,7 @@ void Mod::File::read(bool)
READ_STRING(d->tag.setTitle, 20);
StringList comment;
for(unsigned int i = 0; i < instruments; ++ i) {
for (unsigned int i = 0; i < instruments; ++i) {
READ_STRING_AS(instrumentName, 22);
// value in words, * 2 (<< 1) for bytes:
READ_U16B_AS(sampleLength);
@ -172,10 +159,10 @@ void Mod::File::read(bool)
READ_BYTE_AS(fineTuneByte);
int fineTune = fineTuneByte & 0xF;
// > 7 means negative value
if(fineTune > 7) fineTune -= 16;
if (fineTune > 7) fineTune -= 16;
READ_BYTE_AS(volume);
if(volume > 64) volume = 64;
if (volume > 64) volume = 64;
// volume in decibels: 20 * log10(volume / 64)
// value in words, * 2 (<< 1) for bytes:

View File

@ -36,10 +36,9 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace Mod {
namespace Mod {
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::Mod::FileBase
{
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::Mod::FileBase {
public:
/*!
* Constructs a Protracker file from \a file.
@ -106,11 +105,11 @@ namespace TagLib {
class FilePrivate;
FilePrivate *d;
};
};
}
} // namespace Mod
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -30,28 +30,23 @@
using namespace Strawberry_TagLib::TagLib;
using namespace Mod;
Mod::FileBase::FileBase(FileName file) : Strawberry_TagLib::TagLib::File(file)
{
Mod::FileBase::FileBase(FileName file) : Strawberry_TagLib::TagLib::File(file) {
}
Mod::FileBase::FileBase(IOStream *stream) : Strawberry_TagLib::TagLib::File(stream)
{
Mod::FileBase::FileBase(IOStream *stream) : Strawberry_TagLib::TagLib::File(stream) {
}
void Mod::FileBase::writeString(const String &s, unsigned long size, char padding)
{
void Mod::FileBase::writeString(const String &s, unsigned long size, char padding) {
ByteVector data(s.data(String::Latin1));
data.resize(size, padding);
writeBlock(data);
}
bool Mod::FileBase::readString(String &s, unsigned long size)
{
bool Mod::FileBase::readString(String &s, unsigned long size) {
ByteVector data(readBlock(size));
if(data.size() < size) return false;
int index = data.find((char) 0);
if(index > -1)
{
if (data.size() < size) return false;
int index = data.find((char)0);
if (index > -1) {
data.resize(index);
}
data.replace('\xff', ' ');
@ -60,66 +55,58 @@ bool Mod::FileBase::readString(String &s, unsigned long size)
return true;
}
void Mod::FileBase::writeByte(unsigned char _byte)
{
void Mod::FileBase::writeByte(unsigned char _byte) {
ByteVector data(1, _byte);
writeBlock(data);
}
void Mod::FileBase::writeU16L(unsigned short number)
{
void Mod::FileBase::writeU16L(unsigned short number) {
writeBlock(ByteVector::fromShort(number, false));
}
void Mod::FileBase::writeU32L(unsigned long number)
{
void Mod::FileBase::writeU32L(unsigned long number) {
writeBlock(ByteVector::fromUInt(number, false));
}
void Mod::FileBase::writeU16B(unsigned short number)
{
void Mod::FileBase::writeU16B(unsigned short number) {
writeBlock(ByteVector::fromShort(number, true));
}
void Mod::FileBase::writeU32B(unsigned long number)
{
void Mod::FileBase::writeU32B(unsigned long number) {
writeBlock(ByteVector::fromUInt(number, true));
}
bool Mod::FileBase::readByte(unsigned char &_byte)
{
bool Mod::FileBase::readByte(unsigned char &_byte) {
ByteVector data(readBlock(1));
if(data.size() < 1) return false;
if (data.size() < 1) return false;
_byte = data[0];
return true;
}
bool Mod::FileBase::readU16L(unsigned short &number)
{
bool Mod::FileBase::readU16L(unsigned short &number) {
ByteVector data(readBlock(2));
if(data.size() < 2) return false;
if (data.size() < 2) return false;
number = data.toUShort(false);
return true;
}
bool Mod::FileBase::readU32L(unsigned long &number) {
ByteVector data(readBlock(4));
if(data.size() < 4) return false;
if (data.size() < 4) return false;
number = data.toUInt(false);
return true;
}
bool Mod::FileBase::readU16B(unsigned short &number)
{
bool Mod::FileBase::readU16B(unsigned short &number) {
ByteVector data(readBlock(2));
if(data.size() < 2) return false;
if (data.size() < 2) return false;
number = data.toUShort(true);
return true;
}
bool Mod::FileBase::readU32B(unsigned long &number) {
ByteVector data(readBlock(4));
if(data.size() < 4) return false;
if (data.size() < 4) return false;
number = data.toUInt(true);
return true;
}

View File

@ -37,10 +37,9 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace Mod {
namespace Mod {
class TAGLIB_EXPORT FileBase : public Strawberry_TagLib::TagLib::File
{
class TAGLIB_EXPORT FileBase : public Strawberry_TagLib::TagLib::File {
protected:
FileBase(FileName file);
FileBase(IOStream *stream);
@ -58,11 +57,11 @@ namespace TagLib {
bool readU32L(unsigned long &number);
bool readU16B(unsigned short &number);
bool readU32B(unsigned long &number);
};
};
}
} // namespace Mod
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -24,43 +24,42 @@
// some helper-macros only used internally by (s3m|it|xm)file.cpp
#define READ_ASSERT(cond) \
if(!(cond)) \
{ \
if (!(cond)) { \
setValid(false); \
return; \
}
#define READ(setter,type,read) \
#define READ(setter, type, read) \
{ \
type number; \
READ_ASSERT(read(number)); \
setter(number); \
}
#define READ_BYTE(setter) READ(setter,unsigned char,readByte)
#define READ_U16L(setter) READ(setter,unsigned short,readU16L)
#define READ_U32L(setter) READ(setter,unsigned long,readU32L)
#define READ_U16B(setter) READ(setter,unsigned short,readU16B)
#define READ_U32B(setter) READ(setter,unsigned long,readU32B)
#define READ_BYTE(setter) READ(setter, unsigned char, readByte)
#define READ_U16L(setter) READ(setter, unsigned short, readU16L)
#define READ_U32L(setter) READ(setter, unsigned long, readU32L)
#define READ_U16B(setter) READ(setter, unsigned short, readU16B)
#define READ_U32B(setter) READ(setter, unsigned long, readU32B)
#define READ_STRING(setter,size) \
#define READ_STRING(setter, size) \
{ \
String s; \
READ_ASSERT(readString(s, size)); \
setter(s); \
}
#define READ_AS(type,name,read) \
#define READ_AS(type, name, read) \
type name = 0; \
READ_ASSERT(read(name));
#define READ_BYTE_AS(name) READ_AS(unsigned char,name,readByte)
#define READ_U16L_AS(name) READ_AS(unsigned short,name,readU16L)
#define READ_U32L_AS(name) READ_AS(unsigned long,name,readU32L)
#define READ_U16B_AS(name) READ_AS(unsigned short,name,readU16B)
#define READ_U32B_AS(name) READ_AS(unsigned long,name,readU32B)
#define READ_BYTE_AS(name) READ_AS(unsigned char, name, readByte)
#define READ_U16L_AS(name) READ_AS(unsigned short, name, readU16L)
#define READ_U32L_AS(name) READ_AS(unsigned long, name, readU32L)
#define READ_U16B_AS(name) READ_AS(unsigned short, name, readU16B)
#define READ_U32B_AS(name) READ_AS(unsigned long, name, readU32B)
#define READ_STRING_AS(name,size) \
#define READ_STRING_AS(name, size) \
String name; \
READ_ASSERT(readString(name, size));

View File

@ -29,14 +29,11 @@
using namespace Strawberry_TagLib::TagLib;
using namespace Mod;
class Mod::Properties::PropertiesPrivate
{
public:
PropertiesPrivate() :
channels(0),
class Mod::Properties::PropertiesPrivate {
public:
PropertiesPrivate() : channels(0),
instrumentCount(0),
lengthInPatterns(0)
{
lengthInPatterns(0) {
}
int channels;
@ -44,68 +41,54 @@ public:
unsigned char lengthInPatterns;
};
Mod::Properties::Properties(AudioProperties::ReadStyle propertiesStyle) :
AudioProperties(propertiesStyle),
d(new PropertiesPrivate())
{
Mod::Properties::Properties(AudioProperties::ReadStyle propertiesStyle) : AudioProperties(propertiesStyle),
d(new PropertiesPrivate()) {
}
Mod::Properties::~Properties()
{
Mod::Properties::~Properties() {
delete d;
}
int Mod::Properties::length() const
{
int Mod::Properties::length() const {
return 0;
}
int Mod::Properties::lengthInSeconds() const
{
int Mod::Properties::lengthInSeconds() const {
return 0;
}
int Mod::Properties::lengthInMilliseconds() const
{
int Mod::Properties::lengthInMilliseconds() const {
return 0;
}
int Mod::Properties::bitrate() const
{
int Mod::Properties::bitrate() const {
return 0;
}
int Mod::Properties::sampleRate() const
{
int Mod::Properties::sampleRate() const {
return 0;
}
int Mod::Properties::channels() const
{
int Mod::Properties::channels() const {
return d->channels;
}
unsigned int Mod::Properties::instrumentCount() const
{
unsigned int Mod::Properties::instrumentCount() const {
return d->instrumentCount;
}
unsigned char Mod::Properties::lengthInPatterns() const
{
unsigned char Mod::Properties::lengthInPatterns() const {
return d->lengthInPatterns;
}
void Mod::Properties::setChannels(int channels)
{
void Mod::Properties::setChannels(int channels) {
d->channels = channels;
}
void Mod::Properties::setInstrumentCount(unsigned int instrumentCount)
{
void Mod::Properties::setInstrumentCount(unsigned int instrumentCount) {
d->instrumentCount = instrumentCount;
}
void Mod::Properties::setLengthInPatterns(unsigned char lengthInPatterns)
{
void Mod::Properties::setLengthInPatterns(unsigned char lengthInPatterns) {
d->lengthInPatterns = lengthInPatterns;
}

View File

@ -32,10 +32,9 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace Mod {
namespace Mod {
class TAGLIB_EXPORT Properties : public AudioProperties
{
class TAGLIB_EXPORT Properties : public AudioProperties {
public:
Properties(AudioProperties::ReadStyle propertiesStyle);
virtual ~Properties();
@ -58,16 +57,16 @@ namespace TagLib {
private:
friend class File;
Properties(const Properties&);
Properties &operator=(const Properties&);
Properties(const Properties &);
Properties &operator=(const Properties &);
class PropertiesPrivate;
PropertiesPrivate *d;
};
};
}
} // namespace Mod
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -31,11 +31,9 @@
using namespace Strawberry_TagLib::TagLib;
using namespace Mod;
class Mod::Tag::TagPrivate
{
public:
TagPrivate()
{
class Mod::Tag::TagPrivate {
public:
TagPrivate() {
}
String title;
@ -43,132 +41,114 @@ public:
String trackerName;
};
Mod::Tag::Tag() :
Strawberry_TagLib::TagLib::Tag(),
d(new TagPrivate())
{
Mod::Tag::Tag() : Strawberry_TagLib::TagLib::Tag(),
d(new TagPrivate()) {
}
Mod::Tag::~Tag()
{
Mod::Tag::~Tag() {
delete d;
}
String Mod::Tag::title() const
{
String Mod::Tag::title() const {
return d->title;
}
String Mod::Tag::artist() const
{
String Mod::Tag::artist() const {
return String();
}
String Mod::Tag::album() const
{
String Mod::Tag::album() const {
return String();
}
String Mod::Tag::comment() const
{
String Mod::Tag::comment() const {
return d->comment;
}
String Mod::Tag::genre() const
{
String Mod::Tag::genre() const {
return String();
}
unsigned int Mod::Tag::year() const
{
unsigned int Mod::Tag::year() const {
return 0;
}
unsigned int Mod::Tag::track() const
{
unsigned int Mod::Tag::track() const {
return 0;
}
String Mod::Tag::trackerName() const
{
String Mod::Tag::trackerName() const {
return d->trackerName;
}
void Mod::Tag::setTitle(const String &title)
{
void Mod::Tag::setTitle(const String &title) {
d->title = title;
}
void Mod::Tag::setArtist(const String &)
{
void Mod::Tag::setArtist(const String &) {
}
void Mod::Tag::setAlbum(const String &)
{
void Mod::Tag::setAlbum(const String &) {
}
void Mod::Tag::setComment(const String &comment)
{
void Mod::Tag::setComment(const String &comment) {
d->comment = comment;
}
void Mod::Tag::setGenre(const String &)
{
void Mod::Tag::setGenre(const String &) {
}
void Mod::Tag::setYear(unsigned int)
{
void Mod::Tag::setYear(unsigned int) {
}
void Mod::Tag::setTrack(unsigned int)
{
void Mod::Tag::setTrack(unsigned int) {
}
void Mod::Tag::setTrackerName(const String &trackerName)
{
void Mod::Tag::setTrackerName(const String &trackerName) {
d->trackerName = trackerName;
}
PropertyMap Mod::Tag::properties() const
{
PropertyMap Mod::Tag::properties() const {
PropertyMap properties;
properties["TITLE"] = d->title;
properties["COMMENT"] = d->comment;
if(!(d->trackerName.isEmpty()))
if (!(d->trackerName.isEmpty()))
properties["TRACKERNAME"] = d->trackerName;
return properties;
}
PropertyMap Mod::Tag::setProperties(const PropertyMap &origProps)
{
PropertyMap Mod::Tag::setProperties(const PropertyMap &origProps) {
PropertyMap properties(origProps);
properties.removeEmpty();
StringList oneValueSet;
if(properties.contains("TITLE")) {
if (properties.contains("TITLE")) {
d->title = properties["TITLE"].front();
oneValueSet.append("TITLE");
} else
}
else
d->title.clear();
if(properties.contains("COMMENT")) {
if (properties.contains("COMMENT")) {
d->comment = properties["COMMENT"].front();
oneValueSet.append("COMMENT");
} else
}
else
d->comment.clear();
if(properties.contains("TRACKERNAME")) {
if (properties.contains("TRACKERNAME")) {
d->trackerName = properties["TRACKERNAME"].front();
oneValueSet.append("TRACKERNAME");
} else
}
else
d->trackerName.clear();
// for each tag that has been set above, remove the first entry in the corresponding
// value list. The others will be returned as unsupported by this format.
for(StringList::ConstIterator it = oneValueSet.begin(); it != oneValueSet.end(); ++it) {
if(properties[*it].size() == 1)
for (StringList::ConstIterator it = oneValueSet.begin(); it != oneValueSet.end(); ++it) {
if (properties[*it].size() == 1)
properties.erase(*it);
else
properties[*it].erase( properties[*it].begin() );
properties[*it].erase(properties[*it].begin());
}
return properties;
}

View File

@ -31,9 +31,9 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace Mod {
namespace Mod {
/*!
/*!
* Tags for module files (Mod, S3M, IT, XM).
*
* Note that only the \a title is supported as such by most
@ -45,8 +45,7 @@ namespace TagLib {
* but it is common practice to abuse instrument/sample/pattern
* names as multiline comments. TagLib does so as well.
*/
class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag
{
class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag {
public:
Tag();
virtual ~Tag();
@ -186,11 +185,11 @@ namespace TagLib {
class TagPrivate;
TagPrivate *d;
};
};
}
} // namespace Mod
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -37,13 +37,12 @@ const char *MP4::Atom::containers[11] = {
"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,22 +27,21 @@
#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
{
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
@ -64,19 +63,18 @@ namespace TagLib {
TypeUPC = 25, // Universal Product Code, in text UTF-8 format (valid as an ID)
TypeBMP = 27, // Windows bitmap image
TypeUndefined = 255 // undefined
};
};
struct AtomData {
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
{
class Atom {
public:
Atom(File *file);
~Atom();
@ -87,27 +85,27 @@ namespace TagLib {
long length;
Strawberry_TagLib::TagLib::ByteVector name;
AtomList children;
private:
static const int numContainers = 11;
static const char *containers[11];
};
};
//! Root-level atoms
class Atoms
{
//! 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;
};
};
}
} // namespace MP4
}
}
#endif
} // namespace TagLib
} // namespace Strawberry_TagLib
# endif
#endif

View File

@ -30,11 +30,9 @@
using namespace Strawberry_TagLib::TagLib;
class MP4::CoverArt::CoverArtPrivate : public RefCounter
{
public:
CoverArtPrivate() :
RefCounter(),
class MP4::CoverArt::CoverArtPrivate : public RefCounter {
public:
CoverArtPrivate() : RefCounter(),
format(MP4::CoverArt::JPEG) {}
Format format;
@ -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,10 +34,9 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace MP4 {
namespace MP4 {
class TAGLIB_EXPORT CoverArt
{
class TAGLIB_EXPORT CoverArt {
public:
/*!
* This describes the image type.
@ -74,13 +73,13 @@ namespace TagLib {
private:
class CoverArtPrivate;
CoverArtPrivate *d;
};
};
typedef List<CoverArt> CoverArtList;
typedef List<CoverArt> CoverArtList;
}
} // namespace MP4
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -34,33 +34,28 @@
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)
if ((*it)->length == 0)
return false;
if(!checkValid((*it)->children))
if (!checkValid((*it)->children))
return false;
}
return true;
}
}
} // namespace
class MP4::File::FilePrivate
{
public:
FilePrivate() :
tag(0),
class MP4::File::FilePrivate {
public:
FilePrivate() : tag(0),
atoms(0),
properties(0) {}
~FilePrivate()
{
~FilePrivate() {
delete atoms;
delete tag;
delete 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,19 +35,18 @@
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
{
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File {
public:
/*!
* Constructs an MP4 file from \a file. If \a readProperties is true the
@ -135,11 +134,11 @@ namespace TagLib {
class FilePrivate;
FilePrivate *d;
};
};
}
} // namespace MP4
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -30,11 +30,9 @@
using namespace Strawberry_TagLib::TagLib;
class MP4::Item::ItemPrivate : public RefCounter
{
public:
ItemPrivate() :
RefCounter(),
class MP4::Item::ItemPrivate : public RefCounter {
public:
ItemPrivate() : RefCounter(),
valid(true),
atomDataType(TypeUndefined) {}
@ -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,10 +33,9 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace MP4 {
namespace MP4 {
class TAGLIB_EXPORT Item
{
class TAGLIB_EXPORT Item {
public:
struct IntPair {
int first, second;
@ -85,11 +84,11 @@ namespace TagLib {
private:
class ItemPrivate;
ItemPrivate *d;
};
};
}
} // namespace MP4
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -31,11 +31,9 @@
using namespace Strawberry_TagLib::TagLib;
class MP4::Properties::PropertiesPrivate
{
public:
PropertiesPrivate() :
length(0),
class MP4::Properties::PropertiesPrivate {
public:
PropertiesPrivate() : length(0),
bitrate(0),
sampleRate(0),
channels(0),
@ -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,8 +146,8 @@ 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;
}
@ -179,37 +155,37 @@ MP4::Properties::read(File *file, Atoms *atoms)
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);
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)) {
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) {
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,8 +193,8 @@ MP4::Properties::read(File *file, Atoms *atoms)
}
}
}
else if(data.containsAt("alac", 20)) {
if(atom->length == 88 && data.containsAt("alac", 56)) {
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);
@ -228,7 +204,7 @@ MP4::Properties::read(File *file, Atoms *atoms)
}
MP4::Atom *drms = atom->find("drms");
if(drms) {
if (drms) {
d->encrypted = true;
}
}

View File

@ -32,14 +32,13 @@
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
{
//! An implementation of MP4 audio properties
class TAGLIB_EXPORT Properties : public AudioProperties {
public:
enum Codec {
Unknown = 0,
@ -112,11 +111,11 @@ namespace TagLib {
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,16 +38,15 @@
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
{
class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag {
public:
Tag();
Tag(Strawberry_TagLib::TagLib::File *file, Atoms *atoms);
@ -104,7 +103,7 @@ namespace TagLib {
bool contains(const String &key) const;
PropertyMap properties() const;
void removeUnsupportedProperties(const StringList& properties);
void removeUnsupportedProperties(const StringList &properties);
PropertyMap setProperties(const PropertyMap &properties);
private:
@ -149,11 +148,11 @@ namespace TagLib {
class TagPrivate;
TagPrivate *d;
};
};
}
} // namespace MP4
}
}
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -38,16 +38,14 @@
using namespace Strawberry_TagLib::TagLib;
namespace
{
enum { MPCAPEIndex = 0, MPCID3v1Index = 1 };
namespace {
enum { MPCAPEIndex = 0,
MPCID3v1Index = 1 };
}
class MPC::File::FilePrivate
{
public:
FilePrivate() :
APELocation(-1),
class MPC::File::FilePrivate {
public:
FilePrivate() : APELocation(-1),
APESize(0),
ID3v1Location(-1),
ID3v2Header(0),
@ -55,8 +53,7 @@ public:
ID3v2Size(0),
properties(0) {}
~FilePrivate()
{
~FilePrivate() {
delete ID3v2Header;
delete properties;
}
@ -79,8 +76,7 @@ public:
// static members
////////////////////////////////////////////////////////////////////////////////
bool MPC::File::isSupported(IOStream *stream)
{
bool MPC::File::isSupported(IOStream *stream) {
// A newer MPC file has to start with "MPCK" or "MP+", but older files don't
// have keys to do a quick check.
@ -92,71 +88,60 @@ bool MPC::File::isSupported(IOStream *stream)
// public members
////////////////////////////////////////////////////////////////////////////////
MPC::File::File(FileName file, bool readProperties, Properties::ReadStyle) :
Strawberry_TagLib::TagLib::File(file),
d(new FilePrivate())
{
if(isOpen())
MPC::File::File(FileName file, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file),
d(new FilePrivate()) {
if (isOpen())
read(readProperties);
}
MPC::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) :
Strawberry_TagLib::TagLib::File(stream),
d(new FilePrivate())
{
if(isOpen())
MPC::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(stream),
d(new FilePrivate()) {
if (isOpen())
read(readProperties);
}
MPC::File::~File()
{
MPC::File::~File() {
delete d;
}
Strawberry_TagLib::TagLib::Tag *MPC::File::tag() const
{
Strawberry_TagLib::TagLib::Tag *MPC::File::tag() const {
return &d->tag;
}
PropertyMap MPC::File::properties() const
{
PropertyMap MPC::File::properties() const {
return d->tag.properties();
}
void MPC::File::removeUnsupportedProperties(const StringList &properties)
{
void MPC::File::removeUnsupportedProperties(const StringList &properties) {
d->tag.removeUnsupportedProperties(properties);
}
PropertyMap MPC::File::setProperties(const PropertyMap &properties)
{
if(ID3v1Tag())
PropertyMap MPC::File::setProperties(const PropertyMap &properties) {
if (ID3v1Tag())
ID3v1Tag()->setProperties(properties);
return APETag(true)->setProperties(properties);
}
MPC::Properties *MPC::File::audioProperties() const
{
MPC::Properties *MPC::File::audioProperties() const {
return d->properties;
}
bool MPC::File::save()
{
if(readOnly()) {
bool MPC::File::save() {
if (readOnly()) {
debug("MPC::File::save() -- File is read only.");
return false;
}
// Possibly strip ID3v2 tag
if(!d->ID3v2Header && d->ID3v2Location >= 0) {
if (!d->ID3v2Header && d->ID3v2Location >= 0) {
removeBlock(d->ID3v2Location, d->ID3v2Size);
if(d->APELocation >= 0)
if (d->APELocation >= 0)
d->APELocation -= d->ID3v2Size;
if(d->ID3v1Location >= 0)
if (d->ID3v1Location >= 0)
d->ID3v1Location -= d->ID3v2Size;
d->ID3v2Location = -1;
@ -165,11 +150,11 @@ bool MPC::File::save()
// Update ID3v1 tag
if(ID3v1Tag() && !ID3v1Tag()->isEmpty()) {
if (ID3v1Tag() && !ID3v1Tag()->isEmpty()) {
// ID3v1 tag is not empty. Update the old one or create a new one.
if(d->ID3v1Location >= 0) {
if (d->ID3v1Location >= 0) {
seek(d->ID3v1Location);
}
else {
@ -183,7 +168,7 @@ bool MPC::File::save()
// ID3v1 tag is empty. Remove the old one.
if(d->ID3v1Location >= 0) {
if (d->ID3v1Location >= 0) {
truncate(d->ID3v1Location);
d->ID3v1Location = -1;
}
@ -191,12 +176,12 @@ bool MPC::File::save()
// Update APE tag
if(APETag() && !APETag()->isEmpty()) {
if (APETag() && !APETag()->isEmpty()) {
// APE tag is not empty. Update the old one or create a new one.
if(d->APELocation < 0) {
if(d->ID3v1Location >= 0)
if (d->APELocation < 0) {
if (d->ID3v1Location >= 0)
d->APELocation = d->ID3v1Location;
else
d->APELocation = length();
@ -205,7 +190,7 @@ bool MPC::File::save()
const ByteVector data = APETag()->render();
insert(data, d->APELocation, d->APESize);
if(d->ID3v1Location >= 0)
if (d->ID3v1Location >= 0)
d->ID3v1Location += (static_cast<long>(data.size()) - d->APESize);
d->APESize = data.size();
@ -214,10 +199,10 @@ bool MPC::File::save()
// APE tag is empty. Remove the old one.
if(d->APELocation >= 0) {
if (d->APELocation >= 0) {
removeBlock(d->APELocation, d->APESize);
if(d->ID3v1Location >= 0)
if (d->ID3v1Location >= 0)
d->ID3v1Location -= d->APESize;
d->APELocation = -1;
@ -228,45 +213,39 @@ bool MPC::File::save()
return true;
}
ID3v1::Tag *MPC::File::ID3v1Tag(bool create)
{
ID3v1::Tag *MPC::File::ID3v1Tag(bool create) {
return d->tag.access<ID3v1::Tag>(MPCID3v1Index, create);
}
APE::Tag *MPC::File::APETag(bool create)
{
APE::Tag *MPC::File::APETag(bool create) {
return d->tag.access<APE::Tag>(MPCAPEIndex, create);
}
void MPC::File::strip(int tags)
{
if(tags & ID3v1)
void MPC::File::strip(int tags) {
if (tags & ID3v1)
d->tag.set(MPCID3v1Index, 0);
if(tags & APE)
if (tags & APE)
d->tag.set(MPCAPEIndex, 0);
if(!ID3v1Tag())
if (!ID3v1Tag())
APETag(true);
if(tags & ID3v2) {
if (tags & ID3v2) {
delete d->ID3v2Header;
d->ID3v2Header = 0;
}
}
void MPC::File::remove(int tags)
{
void MPC::File::remove(int tags) {
strip(tags);
}
bool MPC::File::hasID3v1Tag() const
{
bool MPC::File::hasID3v1Tag() const {
return (d->ID3v1Location >= 0);
}
bool MPC::File::hasAPETag() const
{
bool MPC::File::hasAPETag() const {
return (d->APELocation >= 0);
}
@ -274,13 +253,12 @@ bool MPC::File::hasAPETag() const
// private members
////////////////////////////////////////////////////////////////////////////////
void MPC::File::read(bool readProperties)
{
void MPC::File::read(bool readProperties) {
// Look for an ID3v2 tag
d->ID3v2Location = Utils::findID3v2(this);
if(d->ID3v2Location >= 0) {
if (d->ID3v2Location >= 0) {
seek(d->ID3v2Location);
d->ID3v2Header = new ID3v2::Header(readBlock(ID3v2::Header::size()));
d->ID3v2Size = d->ID3v2Header->completeTagSize();
@ -290,36 +268,36 @@ void MPC::File::read(bool readProperties)
d->ID3v1Location = Utils::findID3v1(this);
if(d->ID3v1Location >= 0)
if (d->ID3v1Location >= 0)
d->tag.set(MPCID3v1Index, new ID3v1::Tag(this, d->ID3v1Location));
// Look for an APE tag
d->APELocation = Utils::findAPE(this, d->ID3v1Location);
if(d->APELocation >= 0) {
if (d->APELocation >= 0) {
d->tag.set(MPCAPEIndex, new APE::Tag(this, d->APELocation));
d->APESize = APETag()->footer()->completeTagSize();
d->APELocation = d->APELocation + APE::Footer::size() - d->APESize;
}
if(d->ID3v1Location < 0)
if (d->ID3v1Location < 0)
APETag(true);
// Look for MPC metadata
if(readProperties) {
if (readProperties) {
long streamLength;
if(d->APELocation >= 0)
if (d->APELocation >= 0)
streamLength = d->APELocation;
else if(d->ID3v1Location >= 0)
else if (d->ID3v1Location >= 0)
streamLength = d->ID3v1Location;
else
streamLength = length();
if(d->ID3v2Location >= 0) {
if (d->ID3v2Location >= 0) {
seek(d->ID3v2Location + d->ID3v2Size);
streamLength -= (d->ID3v2Location + d->ID3v2Size);
}

View File

@ -37,14 +37,18 @@
namespace Strawberry_TagLib {
namespace TagLib {
class Tag;
class Tag;
namespace ID3v1 { class Tag; }
namespace APE { class Tag; }
namespace ID3v1 {
class Tag;
}
namespace APE {
class Tag;
}
//! An implementation of MPC metadata
//! An implementation of MPC metadata
/*!
/*!
* This is implementation of MPC metadata.
*
* This supports ID3v1 and APE (v1 and v2) style comments as well as reading stream
@ -52,11 +56,11 @@ namespace TagLib {
* and ignored.
*/
namespace MPC {
namespace MPC {
//! An implementation of TagLib::File with MPC specific methods
//! An implementation of TagLib::File with MPC specific methods
/*!
/*!
* This implements and provides an interface for MPC files to the
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
* the abstract TagLib::File API as well as providing some additional
@ -64,8 +68,7 @@ namespace TagLib {
* The only invalid tag combination supported is an ID3v1 tag after an APE tag.
*/
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File
{
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File {
public:
/*!
* This set of flags is used for various operations and is suitable for
@ -232,9 +235,9 @@ namespace TagLib {
class FilePrivate;
FilePrivate *d;
};
}
}
}
};
} // namespace MPC
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -33,11 +33,9 @@
using namespace Strawberry_TagLib::TagLib;
class MPC::Properties::PropertiesPrivate
{
public:
PropertiesPrivate() :
version(0),
class MPC::Properties::PropertiesPrivate {
public:
PropertiesPrivate() : version(0),
length(0),
bitrate(0),
sampleRate(0),
@ -66,19 +64,15 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
MPC::Properties::Properties(const ByteVector &data, long streamLength, ReadStyle style) :
AudioProperties(style),
d(new PropertiesPrivate())
{
MPC::Properties::Properties(const ByteVector &data, long streamLength, ReadStyle style) : AudioProperties(style),
d(new PropertiesPrivate()) {
readSV7(data, streamLength);
}
MPC::Properties::Properties(File *file, long streamLength, ReadStyle style) :
AudioProperties(style),
d(new PropertiesPrivate())
{
MPC::Properties::Properties(File *file, long streamLength, ReadStyle style) : AudioProperties(style),
d(new PropertiesPrivate()) {
ByteVector magic = file->readBlock(4);
if(magic == "MPCK") {
if (magic == "MPCK") {
// Musepack version 8
readSV8(file, streamLength);
}
@ -88,73 +82,59 @@ MPC::Properties::Properties(File *file, long streamLength, ReadStyle style) :
}
}
MPC::Properties::~Properties()
{
MPC::Properties::~Properties() {
delete d;
}
int MPC::Properties::length() const
{
int MPC::Properties::length() const {
return lengthInSeconds();
}
int MPC::Properties::lengthInSeconds() const
{
int MPC::Properties::lengthInSeconds() const {
return d->length / 1000;
}
int MPC::Properties::lengthInMilliseconds() const
{
int MPC::Properties::lengthInMilliseconds() const {
return d->length;
}
int MPC::Properties::bitrate() const
{
int MPC::Properties::bitrate() const {
return d->bitrate;
}
int MPC::Properties::sampleRate() const
{
int MPC::Properties::sampleRate() const {
return d->sampleRate;
}
int MPC::Properties::channels() const
{
int MPC::Properties::channels() const {
return d->channels;
}
int MPC::Properties::mpcVersion() const
{
int MPC::Properties::mpcVersion() const {
return d->version;
}
unsigned int MPC::Properties::totalFrames() const
{
unsigned int MPC::Properties::totalFrames() const {
return d->totalFrames;
}
unsigned int MPC::Properties::sampleFrames() const
{
unsigned int MPC::Properties::sampleFrames() const {
return d->sampleFrames;
}
int MPC::Properties::trackGain() const
{
int MPC::Properties::trackGain() const {
return d->trackGain;
}
int MPC::Properties::trackPeak() const
{
int MPC::Properties::trackPeak() const {
return d->trackPeak;
}
int MPC::Properties::albumGain() const
{
int MPC::Properties::albumGain() const {
return d->albumGain;
}
int MPC::Properties::albumPeak() const
{
int MPC::Properties::albumPeak() const {
return d->albumPeak;
}
@ -162,10 +142,8 @@ int MPC::Properties::albumPeak() const
// private members
////////////////////////////////////////////////////////////////////////////////
namespace
{
unsigned long readSize(File *file, unsigned int &sizeLength, bool &eof)
{
namespace {
unsigned long readSize(File *file, unsigned int &sizeLength, bool &eof) {
sizeLength = 0;
eof = false;
@ -174,7 +152,7 @@ namespace
do {
const ByteVector b = file->readBlock(1);
if(b.isEmpty()) {
if (b.isEmpty()) {
eof = true;
break;
}
@ -182,38 +160,36 @@ namespace
tmp = b[0];
size = (size << 7) | (tmp & 0x7F);
sizeLength++;
} while((tmp & 0x80));
} while ((tmp & 0x80));
return size;
}
}
unsigned long readSize(const ByteVector &data, unsigned int &pos)
{
unsigned long readSize(const ByteVector &data, unsigned int &pos) {
unsigned char tmp;
unsigned long size = 0;
do {
tmp = data[pos++];
size = (size << 7) | (tmp & 0x7F);
} while((tmp & 0x80) && (pos < data.size()));
} while ((tmp & 0x80) && (pos < data.size()));
return size;
}
// This array looks weird, but the same as original MusePack code found at:
// https://www.musepack.net/index.php?pg=src
const unsigned short sftable [8] = { 44100, 48000, 37800, 32000, 0, 0, 0, 0 };
}
void MPC::Properties::readSV8(File *file, long streamLength)
{
// This array looks weird, but the same as original MusePack code found at:
// https://www.musepack.net/index.php?pg=src
const unsigned short sftable[8] = { 44100, 48000, 37800, 32000, 0, 0, 0, 0 };
} // namespace
void MPC::Properties::readSV8(File *file, long streamLength) {
bool readSH = false, readRG = false;
while(!readSH && !readRG) {
while (!readSH && !readRG) {
const ByteVector packetType = file->readBlock(2);
unsigned int packetSizeLength;
bool eof;
const unsigned long packetSize = readSize(file, packetSizeLength, eof);
if(eof) {
if (eof) {
debug("MPC::Properties::readSV8() - Reached to EOF.");
break;
}
@ -221,16 +197,16 @@ void MPC::Properties::readSV8(File *file, long streamLength)
const unsigned long dataSize = packetSize - 2 - packetSizeLength;
const ByteVector data = file->readBlock(dataSize);
if(data.size() != dataSize) {
if (data.size() != dataSize) {
debug("MPC::Properties::readSV8() - dataSize doesn't match the actual data size.");
break;
}
if(packetType == "SH") {
if (packetType == "SH") {
// Stream Header
// http://trac.musepack.net/wiki/SV8Specification#StreamHeaderPacket
if(dataSize <= 5) {
if (dataSize <= 5) {
debug("MPC::Properties::readSV8() - \"SH\" packet is too short to parse.");
break;
}
@ -241,13 +217,13 @@ void MPC::Properties::readSV8(File *file, long streamLength)
d->version = data[pos];
pos += 1;
d->sampleFrames = readSize(data, pos);
if(pos > dataSize - 3) {
if (pos > dataSize - 3) {
debug("MPC::Properties::readSV8() - \"SH\" packet is corrupt.");
break;
}
const unsigned long begSilence = readSize(data, pos);
if(pos > dataSize - 2) {
if (pos > dataSize - 2) {
debug("MPC::Properties::readSV8() - \"SH\" packet is corrupt.");
break;
}
@ -259,7 +235,7 @@ void MPC::Properties::readSV8(File *file, long streamLength)
d->channels = ((flags >> 4) & 0x0F) + 1;
const unsigned int frameCount = d->sampleFrames - begSilence;
if(frameCount > 0 && d->sampleRate > 0) {
if (frameCount > 0 && d->sampleRate > 0) {
const double length = frameCount * 1000.0 / d->sampleRate;
d->length = static_cast<int>(length + 0.5);
d->bitrate = static_cast<int>(streamLength * 8.0 / length + 0.5);
@ -269,7 +245,7 @@ void MPC::Properties::readSV8(File *file, long streamLength)
// Replay Gain
// http://trac.musepack.net/wiki/SV8Specification#ReplaygainPacket
if(dataSize <= 9) {
if (dataSize <= 9) {
debug("MPC::Properties::readSV8() - \"RG\" packet is too short to parse.");
break;
}
@ -277,7 +253,7 @@ void MPC::Properties::readSV8(File *file, long streamLength)
readRG = true;
const int replayGainVersion = data[0];
if(replayGainVersion == 1) {
if (replayGainVersion == 1) {
d->trackGain = data.toShort(1, true);
d->trackPeak = data.toShort(3, true);
d->albumGain = data.toShort(5, true);
@ -285,7 +261,7 @@ void MPC::Properties::readSV8(File *file, long streamLength)
}
}
else if(packetType == "SE") {
else if (packetType == "SE") {
break;
}
@ -295,11 +271,10 @@ void MPC::Properties::readSV8(File *file, long streamLength)
}
}
void MPC::Properties::readSV7(const ByteVector &data, long streamLength)
{
if(data.startsWith("MP+")) {
void MPC::Properties::readSV7(const ByteVector &data, long streamLength) {
if (data.startsWith("MP+")) {
d->version = data[3] & 15;
if(d->version < 7)
if (d->version < 7)
return;
d->totalFrames = data.toUInt(4, false);
@ -316,15 +291,15 @@ void MPC::Properties::readSV7(const ByteVector &data, long streamLength)
d->albumPeak = data.toUShort(16, false);
// convert gain info
if(d->trackGain != 0) {
if (d->trackGain != 0) {
int tmp = (int)((64.82 - (short)d->trackGain / 100.) * 256. + .5);
if(tmp >= (1 << 16) || tmp < 0) tmp = 0;
if (tmp >= (1 << 16) || tmp < 0) tmp = 0;
d->trackGain = tmp;
}
if(d->albumGain != 0) {
if (d->albumGain != 0) {
int tmp = (int)((64.82 - d->albumGain / 100.) * 256. + .5);
if(tmp >= (1 << 16) || tmp < 0) tmp = 0;
if (tmp >= (1 << 16) || tmp < 0) tmp = 0;
d->albumGain = tmp;
}
@ -335,7 +310,7 @@ void MPC::Properties::readSV7(const ByteVector &data, long streamLength)
d->albumPeak = (int)(log10((double)d->albumPeak) * 20 * 256 + .5);
bool trueGapless = (gapless >> 31) & 0x0001;
if(trueGapless) {
if (trueGapless) {
unsigned int lastFrameSamples = (gapless >> 20) & 0x07FF;
d->sampleFrames = d->totalFrames * 1152 - lastFrameSamples;
}
@ -350,7 +325,7 @@ void MPC::Properties::readSV7(const ByteVector &data, long streamLength)
d->sampleRate = 44100;
d->channels = 2;
if(d->version >= 5)
if (d->version >= 5)
d->totalFrames = data.toUInt(4, false);
else
d->totalFrames = data.toUShort(6, false);
@ -358,11 +333,11 @@ void MPC::Properties::readSV7(const ByteVector &data, long streamLength)
d->sampleFrames = d->totalFrames * 1152 - 576;
}
if(d->sampleFrames > 0 && d->sampleRate > 0) {
if (d->sampleFrames > 0 && d->sampleRate > 0) {
const double length = d->sampleFrames * 1000.0 / d->sampleRate;
d->length = static_cast<int>(length + 0.5);
if(d->bitrate == 0)
if (d->bitrate == 0)
d->bitrate = static_cast<int>(streamLength * 8.0 / length + 0.5);
}
}

View File

@ -32,21 +32,20 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace MPC {
namespace MPC {
class File;
class File;
static const unsigned int HeaderSize = 8 * 7;
static const unsigned int HeaderSize = 8 * 7;
//! An implementation of audio property reading for MPC
//! An implementation of audio property reading for MPC
/*!
/*!
* This reads the data from an MPC stream found in the AudioProperties
* API.
*/
class TAGLIB_EXPORT Properties : public AudioProperties
{
class TAGLIB_EXPORT Properties : public AudioProperties {
public:
/*!
* Create an instance of MPC::Properties with the data read from the
@ -152,9 +151,9 @@ namespace TagLib {
class PropertiesPrivate;
PropertiesPrivate *d;
};
}
}
}
};
} // namespace MPC
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -27,9 +27,8 @@
using namespace Strawberry_TagLib::TagLib;
namespace
{
const wchar_t *genres[] = {
namespace {
const wchar_t *genres[] = {
L"Blues",
L"Classic Rock",
L"Country",
@ -222,42 +221,38 @@ namespace
L"Dubstep",
L"Garage Rock",
L"Psybient"
};
const int genresSize = sizeof(genres) / sizeof(genres[0]);
}
};
const int genresSize = sizeof(genres) / sizeof(genres[0]);
} // namespace
StringList ID3v1::genreList()
{
StringList ID3v1::genreList() {
StringList l;
for(int i = 0; i < genresSize; i++) {
for (int i = 0; i < genresSize; i++) {
l.append(genres[i]);
}
return l;
}
ID3v1::GenreMap ID3v1::genreMap()
{
ID3v1::GenreMap ID3v1::genreMap() {
GenreMap m;
for(int i = 0; i < genresSize; i++) {
for (int i = 0; i < genresSize; i++) {
m.insert(genres[i], i);
}
return m;
}
String ID3v1::genre(int i)
{
if(i >= 0 && i < genresSize)
String ID3v1::genre(int i) {
if (i >= 0 && i < genresSize)
return String(genres[i]); // always make a copy
else
return String();
}
int ID3v1::genreIndex(const String &name)
{
for(int i = 0; i < genresSize; ++i) {
if(name == genres[i])
int ID3v1::genreIndex(const String &name) {
for (int i = 0; i < genresSize; ++i) {
if (name == genres[i])
return i;
}

View File

@ -32,37 +32,37 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v1 {
namespace ID3v1 {
typedef Map<String, int> GenreMap;
typedef Map<String, int> GenreMap;
/*!
/*!
* Returns the list of canonical ID3v1 genre names in the order that they
* are listed in the standard.
*/
StringList TAGLIB_EXPORT genreList();
StringList TAGLIB_EXPORT genreList();
/*!
/*!
* A "reverse mapping" that goes from the canonical ID3v1 genre name to the
* respective genre number. genreMap()["Rock"] ==
*/
GenreMap TAGLIB_EXPORT genreMap();
GenreMap TAGLIB_EXPORT genreMap();
/*!
/*!
* Returns the name of the genre at \a index in the ID3v1 genre list. If
* \a index is out of range -- less than zero or greater than 191 -- a null
* string will be returned.
*/
String TAGLIB_EXPORT genre(int index);
String TAGLIB_EXPORT genre(int index);
/*!
/*!
* Returns the genre index for the (case sensitive) genre \a name. If the
* genre is not in the list 255 (which signifies an unknown genre in ID3v1)
* will be returned.
*/
int TAGLIB_EXPORT genreIndex(const String &name);
}
}
}
int TAGLIB_EXPORT genreIndex(const String &name);
} // namespace ID3v1
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -32,17 +32,14 @@
using namespace Strawberry_TagLib::TagLib;
using namespace ID3v1;
namespace
{
const ID3v1::StringHandler defaultStringHandler;
const ID3v1::StringHandler *stringHandler = &defaultStringHandler;
}
namespace {
const ID3v1::StringHandler defaultStringHandler;
const ID3v1::StringHandler *stringHandler = &defaultStringHandler;
} // namespace
class ID3v1::Tag::TagPrivate
{
public:
TagPrivate() :
file(0),
class ID3v1::Tag::TagPrivate {
public:
TagPrivate() : file(0),
tagOffset(0),
track(0),
genre(255) {}
@ -63,18 +60,15 @@ public:
// StringHandler implementation
////////////////////////////////////////////////////////////////////////////////
StringHandler::StringHandler()
{
StringHandler::StringHandler() {
}
String ID3v1::StringHandler::parse(const ByteVector &data) const
{
String ID3v1::StringHandler::parse(const ByteVector &data) const {
return String(data, String::Latin1).stripWhiteSpace();
}
ByteVector ID3v1::StringHandler::render(const String &s) const
{
if(s.isLatin1())
ByteVector ID3v1::StringHandler::render(const String &s) const {
if (s.isLatin1())
return s.data(String::Latin1);
else
return ByteVector();
@ -84,29 +78,23 @@ ByteVector ID3v1::StringHandler::render(const String &s) const
// public methods
////////////////////////////////////////////////////////////////////////////////
ID3v1::Tag::Tag() :
Strawberry_TagLib::TagLib::Tag(),
d(new TagPrivate())
{
ID3v1::Tag::Tag() : Strawberry_TagLib::TagLib::Tag(),
d(new TagPrivate()) {
}
ID3v1::Tag::Tag(File *file, long tagOffset) :
Strawberry_TagLib::TagLib::Tag(),
d(new TagPrivate())
{
ID3v1::Tag::Tag(File *file, long tagOffset) : Strawberry_TagLib::TagLib::Tag(),
d(new TagPrivate()) {
d->file = file;
d->tagOffset = tagOffset;
read();
}
ID3v1::Tag::~Tag()
{
ID3v1::Tag::~Tag() {
delete d;
}
ByteVector ID3v1::Tag::render() const
{
ByteVector ID3v1::Tag::render() const {
ByteVector data;
data.append(fileIdentifier());
@ -122,94 +110,76 @@ ByteVector ID3v1::Tag::render() const
return data;
}
ByteVector ID3v1::Tag::fileIdentifier()
{
ByteVector ID3v1::Tag::fileIdentifier() {
return ByteVector::fromCString("TAG");
}
String ID3v1::Tag::title() const
{
String ID3v1::Tag::title() const {
return d->title;
}
String ID3v1::Tag::artist() const
{
String ID3v1::Tag::artist() const {
return d->artist;
}
String ID3v1::Tag::album() const
{
String ID3v1::Tag::album() const {
return d->album;
}
String ID3v1::Tag::comment() const
{
String ID3v1::Tag::comment() const {
return d->comment;
}
String ID3v1::Tag::genre() const
{
String ID3v1::Tag::genre() const {
return ID3v1::genre(d->genre);
}
unsigned int ID3v1::Tag::year() const
{
unsigned int ID3v1::Tag::year() const {
return d->year.toInt();
}
unsigned int ID3v1::Tag::track() const
{
unsigned int ID3v1::Tag::track() const {
return d->track;
}
void ID3v1::Tag::setTitle(const String &s)
{
void ID3v1::Tag::setTitle(const String &s) {
d->title = s;
}
void ID3v1::Tag::setArtist(const String &s)
{
void ID3v1::Tag::setArtist(const String &s) {
d->artist = s;
}
void ID3v1::Tag::setAlbum(const String &s)
{
void ID3v1::Tag::setAlbum(const String &s) {
d->album = s;
}
void ID3v1::Tag::setComment(const String &s)
{
void ID3v1::Tag::setComment(const String &s) {
d->comment = s;
}
void ID3v1::Tag::setGenre(const String &s)
{
void ID3v1::Tag::setGenre(const String &s) {
d->genre = ID3v1::genreIndex(s);
}
void ID3v1::Tag::setYear(unsigned int i)
{
void ID3v1::Tag::setYear(unsigned int i) {
d->year = i > 0 ? String::number(i) : String();
}
void ID3v1::Tag::setTrack(unsigned int i)
{
void ID3v1::Tag::setTrack(unsigned int i) {
d->track = i < 256 ? i : 0;
}
unsigned int ID3v1::Tag::genreNumber() const
{
unsigned int ID3v1::Tag::genreNumber() const {
return d->genre;
}
void ID3v1::Tag::setGenreNumber(unsigned int i)
{
void ID3v1::Tag::setGenreNumber(unsigned int i) {
d->genre = i < 256 ? i : 255;
}
void ID3v1::Tag::setStringHandler(const StringHandler *handler)
{
if(handler)
void ID3v1::Tag::setStringHandler(const StringHandler *handler) {
if (handler)
stringHandler = handler;
else
stringHandler = &defaultStringHandler;
@ -219,23 +189,21 @@ void ID3v1::Tag::setStringHandler(const StringHandler *handler)
// protected methods
////////////////////////////////////////////////////////////////////////////////
void ID3v1::Tag::read()
{
if(d->file && d->file->isValid()) {
void ID3v1::Tag::read() {
if (d->file && d->file->isValid()) {
d->file->seek(d->tagOffset);
// read the tag -- always 128 bytes
const ByteVector data = d->file->readBlock(128);
// some initial sanity checking
if(data.size() == 128 && data.startsWith("TAG"))
if (data.size() == 128 && data.startsWith("TAG"))
parse(data);
else
debug("ID3v1 tag is not valid or could not be read at the specified offset.");
}
}
void ID3v1::Tag::parse(const ByteVector &data)
{
void ID3v1::Tag::parse(const ByteVector &data) {
int offset = 3;
d->title = stringHandler->parse(data.mid(offset, 30));
@ -255,7 +223,7 @@ void ID3v1::Tag::parse(const ByteVector &data)
// indicate the end of a C-String, specifically the comment string, a value of
// zero must be assumed to be just that.
if(data[offset + 28] == 0 && data[offset + 29] != 0) {
if (data[offset + 28] == 0 && data[offset + 29] != 0) {
// ID3v1.1 detected
d->comment = stringHandler->parse(data.mid(offset, 28));

View File

@ -33,15 +33,15 @@
namespace Strawberry_TagLib {
namespace TagLib {
class File;
class File;
//! An ID3v1 implementation
//! An ID3v1 implementation
namespace ID3v1 {
namespace ID3v1 {
//! A abstraction for the string to data encoding in ID3v1 tags.
//! A abstraction for the string to data encoding in ID3v1 tags.
/*!
/*!
* ID3v1 should in theory always contain ISO-8859-1 (Latin1) data. In
* practice it does not. TagLib by default only supports ISO-8859-1 data
* in ID3v1 tags.
@ -58,8 +58,7 @@ namespace TagLib {
* \see ID3v1::Tag::setStringHandler()
*/
class TAGLIB_EXPORT StringHandler
{
class TAGLIB_EXPORT StringHandler {
TAGLIB_IGNORE_MISSING_DESTRUCTOR
public:
// BIC: Add virtual destructor.
@ -81,11 +80,11 @@ namespace TagLib {
* ISO-8859-1.
*/
virtual ByteVector render(const String &s) const;
};
};
//! The main class in the ID3v1 implementation
//! The main class in the ID3v1 implementation
/*!
/*!
* This is an implementation of the ID3v1 format. ID3v1 is both the simplest
* and most common of tag formats but is rather limited. Because of its
* pervasiveness and the way that applications have been written around the
@ -103,8 +102,7 @@ namespace TagLib {
* truncation happens automatically when the tag is rendered.
*/
class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag
{
class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag {
public:
/*!
* Create an ID3v1 tag with default values.
@ -196,9 +194,9 @@ namespace TagLib {
class TagPrivate;
TagPrivate *d;
};
}
}
}
};
} // namespace ID3v1
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -31,9 +31,8 @@
using namespace Strawberry_TagLib::TagLib;
using namespace ID3v2;
class AttachedPictureFrame::AttachedPictureFramePrivate
{
public:
class AttachedPictureFrame::AttachedPictureFramePrivate {
public:
AttachedPictureFramePrivate() : textEncoding(String::Latin1),
type(AttachedPictureFrame::Other) {}
@ -48,77 +47,61 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
AttachedPictureFrame::AttachedPictureFrame() :
Frame("APIC"),
d(new AttachedPictureFramePrivate())
{
AttachedPictureFrame::AttachedPictureFrame() : Frame("APIC"),
d(new AttachedPictureFramePrivate()) {
}
AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data) :
Frame(data),
d(new AttachedPictureFramePrivate())
{
AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data) : Frame(data),
d(new AttachedPictureFramePrivate()) {
setData(data);
}
AttachedPictureFrame::~AttachedPictureFrame()
{
AttachedPictureFrame::~AttachedPictureFrame() {
delete d;
}
String AttachedPictureFrame::toString() const
{
String AttachedPictureFrame::toString() const {
String s = "[" + d->mimeType + "]";
return d->description.isEmpty() ? s : d->description + " " + s;
}
String::Type AttachedPictureFrame::textEncoding() const
{
String::Type AttachedPictureFrame::textEncoding() const {
return d->textEncoding;
}
void AttachedPictureFrame::setTextEncoding(String::Type t)
{
void AttachedPictureFrame::setTextEncoding(String::Type t) {
d->textEncoding = t;
}
String AttachedPictureFrame::mimeType() const
{
String AttachedPictureFrame::mimeType() const {
return d->mimeType;
}
void AttachedPictureFrame::setMimeType(const String &m)
{
void AttachedPictureFrame::setMimeType(const String &m) {
d->mimeType = m;
}
AttachedPictureFrame::Type AttachedPictureFrame::type() const
{
AttachedPictureFrame::Type AttachedPictureFrame::type() const {
return d->type;
}
void AttachedPictureFrame::setType(Type t)
{
void AttachedPictureFrame::setType(Type t) {
d->type = t;
}
String AttachedPictureFrame::description() const
{
String AttachedPictureFrame::description() const {
return d->description;
}
void AttachedPictureFrame::setDescription(const String &desc)
{
void AttachedPictureFrame::setDescription(const String &desc) {
d->description = desc;
}
ByteVector AttachedPictureFrame::picture() const
{
ByteVector AttachedPictureFrame::picture() const {
return d->data;
}
void AttachedPictureFrame::setPicture(const ByteVector &p)
{
void AttachedPictureFrame::setPicture(const ByteVector &p) {
d->data = p;
}
@ -126,9 +109,8 @@ void AttachedPictureFrame::setPicture(const ByteVector &p)
// protected members
////////////////////////////////////////////////////////////////////////////////
void AttachedPictureFrame::parseFields(const ByteVector &data)
{
if(data.size() < 5) {
void AttachedPictureFrame::parseFields(const ByteVector &data) {
if (data.size() < 5) {
debug("A picture frame must contain at least 5 bytes.");
return;
}
@ -139,7 +121,7 @@ void AttachedPictureFrame::parseFields(const ByteVector &data)
d->mimeType = readStringField(data, String::Latin1, &pos);
/* Now we need at least two more bytes available */
if(static_cast<unsigned int>(pos) + 1 >= data.size()) {
if (static_cast<unsigned int>(pos) + 1 >= data.size()) {
debug("Truncated picture frame.");
return;
}
@ -150,8 +132,7 @@ void AttachedPictureFrame::parseFields(const ByteVector &data)
d->data = data.mid(pos);
}
ByteVector AttachedPictureFrame::renderFields() const
{
ByteVector AttachedPictureFrame::renderFields() const {
ByteVector data;
String::Type encoding = checkTextEncoding(d->description, d->textEncoding);
@ -171,10 +152,8 @@ ByteVector AttachedPictureFrame::renderFields() const
// private members
////////////////////////////////////////////////////////////////////////////////
AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data, Header *h) :
Frame(h),
d(new AttachedPictureFramePrivate())
{
AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data, Header *h) : Frame(h),
d(new AttachedPictureFramePrivate()) {
parseFields(fieldData(data));
}
@ -182,9 +161,8 @@ AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data, Header *h) :
// support for ID3v2.2 PIC frames
////////////////////////////////////////////////////////////////////////////////
void AttachedPictureFrameV22::parseFields(const ByteVector &data)
{
if(data.size() < 5) {
void AttachedPictureFrameV22::parseFields(const ByteVector &data) {
if (data.size() < 5) {
debug("A picture frame must contain at least 5 bytes.");
return;
}
@ -198,9 +176,11 @@ void AttachedPictureFrameV22::parseFields(const ByteVector &data)
// convert fixed string image type to mime string
if (fixedString.upper() == "JPG") {
d->mimeType = "image/jpeg";
} else if (fixedString.upper() == "PNG") {
}
else if (fixedString.upper() == "PNG") {
d->mimeType = "image/png";
} else {
}
else {
debug("probably unsupported image type");
d->mimeType = "image/" + fixedString;
}
@ -211,8 +191,7 @@ void AttachedPictureFrameV22::parseFields(const ByteVector &data)
d->data = data.mid(pos);
}
AttachedPictureFrameV22::AttachedPictureFrameV22(const ByteVector &data, Header *h)
{
AttachedPictureFrameV22::AttachedPictureFrameV22(const ByteVector &data, Header *h) {
// set v2.2 header to make fieldData work correctly
setHeader(h, true);

View File

@ -33,23 +33,21 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
namespace ID3v2 {
//! An ID3v2 attached picture frame implementation
//! An ID3v2 attached picture frame implementation
/*!
/*!
* This is an implementation of ID3v2 attached pictures. Pictures may be
* included in tags, one per APIC frame (but there may be multiple APIC
* frames in a single tag). These pictures are usually in either JPEG or
* PNG format.
*/
class TAGLIB_EXPORT AttachedPictureFrame : public Frame
{
class TAGLIB_EXPORT AttachedPictureFrame : public Frame {
friend class FrameFactory;
public:
/*!
* This describes the function or content of the picture.
*/
@ -213,20 +211,19 @@ namespace TagLib {
AttachedPictureFrame(const AttachedPictureFrame &);
AttachedPictureFrame &operator=(const AttachedPictureFrame &);
AttachedPictureFrame(const ByteVector &data, Header *h);
};
};
//! support for ID3v2.2 PIC frames
class TAGLIB_EXPORT AttachedPictureFrameV22 : public AttachedPictureFrame
{
//! support for ID3v2.2 PIC frames
class TAGLIB_EXPORT AttachedPictureFrameV22 : public AttachedPictureFrame {
protected:
virtual void parseFields(const ByteVector &data);
private:
AttachedPictureFrameV22(const ByteVector &data, Header *h);
friend class FrameFactory;
};
}
}
}
};
} // namespace ID3v2
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -33,16 +33,13 @@
using namespace Strawberry_TagLib::TagLib;
using namespace ID3v2;
class ChapterFrame::ChapterFramePrivate
{
public:
ChapterFramePrivate() :
tagHeader(0),
class ChapterFrame::ChapterFramePrivate {
public:
ChapterFramePrivate() : tagHeader(0),
startTime(0),
endTime(0),
startOffset(0),
endOffset(0)
{
endOffset(0) {
embeddedFrameList.setAutoDelete(true);
}
@ -60,10 +57,8 @@ public:
// public methods
////////////////////////////////////////////////////////////////////////////////
ChapterFrame::ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data) :
ID3v2::Frame(data),
d(new ChapterFramePrivate())
{
ChapterFrame::ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data) : ID3v2::Frame(data),
d(new ChapterFramePrivate()) {
d->tagHeader = tagHeader;
setData(data);
}
@ -71,10 +66,8 @@ ChapterFrame::ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &dat
ChapterFrame::ChapterFrame(const ByteVector &elementID,
unsigned int startTime, unsigned int endTime,
unsigned int startOffset, unsigned int endOffset,
const FrameList &embeddedFrames) :
ID3v2::Frame("CHAP"),
d(new ChapterFramePrivate())
{
const FrameList &embeddedFrames) : ID3v2::Frame("CHAP"),
d(new ChapterFramePrivate()) {
// setElementID has a workaround for a previously silly API where you had to
// specifically include the null byte.
@ -85,92 +78,77 @@ ChapterFrame::ChapterFrame(const ByteVector &elementID,
d->startOffset = startOffset;
d->endOffset = endOffset;
for(FrameList::ConstIterator it = embeddedFrames.begin();
it != embeddedFrames.end(); ++it)
for (FrameList::ConstIterator it = embeddedFrames.begin();
it != embeddedFrames.end();
++it)
addEmbeddedFrame(*it);
}
ChapterFrame::~ChapterFrame()
{
ChapterFrame::~ChapterFrame() {
delete d;
}
ByteVector ChapterFrame::elementID() const
{
ByteVector ChapterFrame::elementID() const {
return d->elementID;
}
unsigned int ChapterFrame::startTime() const
{
unsigned int ChapterFrame::startTime() const {
return d->startTime;
}
unsigned int ChapterFrame::endTime() const
{
unsigned int ChapterFrame::endTime() const {
return d->endTime;
}
unsigned int ChapterFrame::startOffset() const
{
unsigned int ChapterFrame::startOffset() const {
return d->startOffset;
}
unsigned int ChapterFrame::endOffset() const
{
unsigned int ChapterFrame::endOffset() const {
return d->endOffset;
}
void ChapterFrame::setElementID(const ByteVector &eID)
{
void ChapterFrame::setElementID(const ByteVector &eID) {
d->elementID = eID;
if(d->elementID.endsWith(char(0)))
if (d->elementID.endsWith(char(0)))
d->elementID = d->elementID.mid(0, d->elementID.size() - 1);
}
void ChapterFrame::setStartTime(const unsigned int &sT)
{
void ChapterFrame::setStartTime(const unsigned int &sT) {
d->startTime = sT;
}
void ChapterFrame::setEndTime(const unsigned int &eT)
{
void ChapterFrame::setEndTime(const unsigned int &eT) {
d->endTime = eT;
}
void ChapterFrame::setStartOffset(const unsigned int &sO)
{
void ChapterFrame::setStartOffset(const unsigned int &sO) {
d->startOffset = sO;
}
void ChapterFrame::setEndOffset(const unsigned int &eO)
{
void ChapterFrame::setEndOffset(const unsigned int &eO) {
d->endOffset = eO;
}
const FrameListMap &ChapterFrame::embeddedFrameListMap() const
{
const FrameListMap &ChapterFrame::embeddedFrameListMap() const {
return d->embeddedFrameListMap;
}
const FrameList &ChapterFrame::embeddedFrameList() const
{
const FrameList &ChapterFrame::embeddedFrameList() const {
return d->embeddedFrameList;
}
const FrameList &ChapterFrame::embeddedFrameList(const ByteVector &frameID) const
{
const FrameList &ChapterFrame::embeddedFrameList(const ByteVector &frameID) const {
return d->embeddedFrameListMap[frameID];
}
void ChapterFrame::addEmbeddedFrame(Frame *frame)
{
void ChapterFrame::addEmbeddedFrame(Frame *frame) {
d->embeddedFrameList.append(frame);
d->embeddedFrameListMap[frame->frameID()].append(frame);
}
void ChapterFrame::removeEmbeddedFrame(Frame *frame, bool del)
{
void ChapterFrame::removeEmbeddedFrame(Frame *frame, bool del) {
// remove the frame from the frame list
FrameList::Iterator it = d->embeddedFrameList.find(frame);
d->embeddedFrameList.erase(it);
@ -180,33 +158,32 @@ void ChapterFrame::removeEmbeddedFrame(Frame *frame, bool del)
d->embeddedFrameListMap[frame->frameID()].erase(it);
// ...and delete as desired
if(del)
if (del)
delete frame;
}
void ChapterFrame::removeEmbeddedFrames(const ByteVector &id)
{
void ChapterFrame::removeEmbeddedFrames(const ByteVector &id) {
FrameList l = d->embeddedFrameListMap[id];
for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it)
for (FrameList::ConstIterator it = l.begin(); it != l.end(); ++it)
removeEmbeddedFrame(*it, true);
}
String ChapterFrame::toString() const
{
String ChapterFrame::toString() const {
String s = String(d->elementID) +
": start time: " + String::number(d->startTime) +
", end time: " + String::number(d->endTime);
if(d->startOffset != 0xFFFFFFFF)
if (d->startOffset != 0xFFFFFFFF)
s += ", start offset: " + String::number(d->startOffset);
if(d->endOffset != 0xFFFFFFFF)
if (d->endOffset != 0xFFFFFFFF)
s += ", end offset: " + String::number(d->endOffset);
if(!d->embeddedFrameList.isEmpty()) {
if (!d->embeddedFrameList.isEmpty()) {
StringList frameIDs;
for(FrameList::ConstIterator it = d->embeddedFrameList.begin();
it != d->embeddedFrameList.end(); ++it)
for (FrameList::ConstIterator it = d->embeddedFrameList.begin();
it != d->embeddedFrameList.end();
++it)
frameIDs.append((*it)->frameID());
s += ", sub-frames: [ " + frameIDs.toString(", ") + " ]";
}
@ -214,8 +191,7 @@ String ChapterFrame::toString() const
return s;
}
PropertyMap ChapterFrame::asProperties() const
{
PropertyMap ChapterFrame::asProperties() const {
PropertyMap map;
map.unsupportedData().append(frameID() + String("/") + d->elementID);
@ -227,22 +203,20 @@ ChapterFrame *ChapterFrame::findByElementID(const ID3v2::Tag *tag, const ByteVec
{
ID3v2::FrameList comments = tag->frameList("CHAP");
for(ID3v2::FrameList::ConstIterator it = comments.begin();
for (ID3v2::FrameList::ConstIterator it = comments.begin();
it != comments.end();
++it)
{
++it) {
ChapterFrame *frame = dynamic_cast<ChapterFrame *>(*it);
if(frame && frame->elementID() == eID)
if (frame && frame->elementID() == eID)
return frame;
}
return nullptr;
}
void ChapterFrame::parseFields(const ByteVector &data)
{
void ChapterFrame::parseFields(const ByteVector &data) {
unsigned int size = data.size();
if(size < 18) {
if (size < 18) {
debug("A CHAP frame must contain at least 18 bytes (1 byte element ID "
"terminated by null and 4x4 bytes for start and end time and offset).");
return;
@ -263,17 +237,17 @@ void ChapterFrame::parseFields(const ByteVector &data)
// Embedded frames are optional
if(size < header()->size())
if (size < header()->size())
return;
while(embPos < size - header()->size()) {
while (embPos < size - header()->size()) {
Frame *frame = FrameFactory::instance()->createFrame(data.mid(pos + embPos), d->tagHeader);
if(!frame)
if (!frame)
return;
// Checks to make sure that frame parsed correctly.
if(frame->size() <= 0) {
if (frame->size() <= 0) {
delete frame;
return;
}
@ -283,8 +257,7 @@ void ChapterFrame::parseFields(const ByteVector &data)
}
}
ByteVector ChapterFrame::renderFields() const
{
ByteVector ChapterFrame::renderFields() const {
ByteVector data;
data.append(d->elementID);
@ -294,16 +267,14 @@ ByteVector ChapterFrame::renderFields() const
data.append(ByteVector::fromUInt(d->startOffset, true));
data.append(ByteVector::fromUInt(d->endOffset, true));
FrameList l = d->embeddedFrameList;
for(FrameList::ConstIterator it = l.begin(); it != l.end(); ++it)
for (FrameList::ConstIterator it = l.begin(); it != l.end(); ++it)
data.append((*it)->render());
return data;
}
ChapterFrame::ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data, Header *h) :
Frame(h),
d(new ChapterFramePrivate())
{
ChapterFrame::ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data, Header *h) : Frame(h),
d(new ChapterFramePrivate()) {
d->tagHeader = tagHeader;
parseFields(fieldData(data));
}

View File

@ -33,17 +33,16 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
namespace ID3v2 {
/*!
/*!
* This is an implementation of ID3v2 chapter frames. The purpose of this
* frame is to describe a single chapter within an audio file.
*/
//! An implementation of ID3v2 chapter frames
//! An implementation of ID3v2 chapter frames
class TAGLIB_EXPORT ChapterFrame : public ID3v2::Frame
{
class TAGLIB_EXPORT ChapterFrame : public ID3v2::Frame {
friend class FrameFactory;
public:
@ -243,9 +242,9 @@ namespace TagLib {
class ChapterFramePrivate;
ChapterFramePrivate *d;
};
}
}
}
};
} // namespace ID3v2
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -34,9 +34,8 @@
using namespace Strawberry_TagLib::TagLib;
using namespace ID3v2;
class CommentsFrame::CommentsFramePrivate
{
public:
class CommentsFrame::CommentsFramePrivate {
public:
CommentsFramePrivate() : textEncoding(String::Latin1) {}
String::Type textEncoding;
ByteVector language;
@ -48,75 +47,60 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
CommentsFrame::CommentsFrame(String::Type encoding) :
Frame("COMM"),
d(new CommentsFramePrivate())
{
CommentsFrame::CommentsFrame(String::Type encoding) : Frame("COMM"),
d(new CommentsFramePrivate()) {
d->textEncoding = encoding;
}
CommentsFrame::CommentsFrame(const ByteVector &data) :
Frame(data),
d(new CommentsFramePrivate())
{
CommentsFrame::CommentsFrame(const ByteVector &data) : Frame(data),
d(new CommentsFramePrivate()) {
setData(data);
}
CommentsFrame::~CommentsFrame()
{
CommentsFrame::~CommentsFrame() {
delete d;
}
String CommentsFrame::toString() const
{
String CommentsFrame::toString() const {
return d->text;
}
ByteVector CommentsFrame::language() const
{
ByteVector CommentsFrame::language() const {
return d->language;
}
String CommentsFrame::description() const
{
String CommentsFrame::description() const {
return d->description;
}
String CommentsFrame::text() const
{
String CommentsFrame::text() const {
return d->text;
}
void CommentsFrame::setLanguage(const ByteVector &languageEncoding)
{
void CommentsFrame::setLanguage(const ByteVector &languageEncoding) {
d->language = languageEncoding.mid(0, 3);
}
void CommentsFrame::setDescription(const String &s)
{
void CommentsFrame::setDescription(const String &s) {
d->description = s;
}
void CommentsFrame::setText(const String &s)
{
void CommentsFrame::setText(const String &s) {
d->text = s;
}
String::Type CommentsFrame::textEncoding() const
{
String::Type CommentsFrame::textEncoding() const {
return d->textEncoding;
}
void CommentsFrame::setTextEncoding(String::Type encoding)
{
void CommentsFrame::setTextEncoding(String::Type encoding) {
d->textEncoding = encoding;
}
PropertyMap CommentsFrame::asProperties() const
{
PropertyMap CommentsFrame::asProperties() const {
String key = description().upper();
PropertyMap map;
if(key.isEmpty() || key == "COMMENT")
if (key.isEmpty() || key == "COMMENT")
map.insert("COMMENT", text());
else
map.insert("COMMENT:" + key, text());
@ -127,12 +111,11 @@ CommentsFrame *CommentsFrame::findByDescription(const ID3v2::Tag *tag, const Str
{
ID3v2::FrameList comments = tag->frameList("COMM");
for(ID3v2::FrameList::ConstIterator it = comments.begin();
for (ID3v2::FrameList::ConstIterator it = comments.begin();
it != comments.end();
++it)
{
++it) {
CommentsFrame *frame = dynamic_cast<CommentsFrame *>(*it);
if(frame && frame->description() == d)
if (frame && frame->description() == d)
return frame;
}
@ -143,9 +126,8 @@ CommentsFrame *CommentsFrame::findByDescription(const ID3v2::Tag *tag, const Str
// protected members
////////////////////////////////////////////////////////////////////////////////
void CommentsFrame::parseFields(const ByteVector &data)
{
if(data.size() < 5) {
void CommentsFrame::parseFields(const ByteVector &data) {
if (data.size() < 5) {
debug("A comment frame must contain at least 5 bytes.");
return;
}
@ -157,19 +139,19 @@ void CommentsFrame::parseFields(const ByteVector &data)
ByteVectorList l = ByteVectorList::split(data.mid(4), textDelimiter(d->textEncoding), byteAlign, 2);
if(l.size() == 2) {
if(d->textEncoding == String::Latin1) {
if (l.size() == 2) {
if (d->textEncoding == String::Latin1) {
d->description = Tag::latin1StringHandler()->parse(l.front());
d->text = Tag::latin1StringHandler()->parse(l.back());
} else {
}
else {
d->description = String(l.front(), d->textEncoding);
d->text = String(l.back(), d->textEncoding);
}
}
}
ByteVector CommentsFrame::renderFields() const
{
ByteVector CommentsFrame::renderFields() const {
ByteVector v;
String::Type encoding = d->textEncoding;
@ -190,9 +172,7 @@ ByteVector CommentsFrame::renderFields() const
// private members
////////////////////////////////////////////////////////////////////////////////
CommentsFrame::CommentsFrame(const ByteVector &data, Header *h) :
Frame(h),
d(new CommentsFramePrivate())
{
CommentsFrame::CommentsFrame(const ByteVector &data, Header *h) : Frame(h),
d(new CommentsFramePrivate()) {
parseFields(fieldData(data));
}

View File

@ -32,17 +32,16 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
namespace ID3v2 {
//! An implementation of ID3v2 comments
//! An implementation of ID3v2 comments
/*!
/*!
* This implements the ID3v2 comment format. An ID3v2 comment consists of
* a language encoding, a description and a single text field.
*/
class TAGLIB_EXPORT CommentsFrame : public Frame
{
class TAGLIB_EXPORT CommentsFrame : public Frame {
friend class FrameFactory;
public:
@ -173,9 +172,9 @@ namespace TagLib {
class CommentsFramePrivate;
CommentsFramePrivate *d;
};
};
}
}
}
} // namespace ID3v2
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -32,11 +32,9 @@
using namespace Strawberry_TagLib::TagLib;
using namespace ID3v2;
class EventTimingCodesFrame::EventTimingCodesFramePrivate
{
public:
EventTimingCodesFramePrivate() :
timestampFormat(EventTimingCodesFrame::AbsoluteMilliseconds) {}
class EventTimingCodesFrame::EventTimingCodesFramePrivate {
public:
EventTimingCodesFramePrivate() : timestampFormat(EventTimingCodesFrame::AbsoluteMilliseconds) {}
EventTimingCodesFrame::TimestampFormat timestampFormat;
EventTimingCodesFrame::SynchedEventList synchedEvents;
};
@ -45,50 +43,40 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
EventTimingCodesFrame::EventTimingCodesFrame() :
Frame("ETCO"),
d(new EventTimingCodesFramePrivate())
{
EventTimingCodesFrame::EventTimingCodesFrame() : Frame("ETCO"),
d(new EventTimingCodesFramePrivate()) {
}
EventTimingCodesFrame::EventTimingCodesFrame(const ByteVector &data) :
Frame(data),
d(new EventTimingCodesFramePrivate())
{
EventTimingCodesFrame::EventTimingCodesFrame(const ByteVector &data) : Frame(data),
d(new EventTimingCodesFramePrivate()) {
setData(data);
}
EventTimingCodesFrame::~EventTimingCodesFrame()
{
EventTimingCodesFrame::~EventTimingCodesFrame() {
delete d;
}
String EventTimingCodesFrame::toString() const
{
String EventTimingCodesFrame::toString() const {
return String();
}
EventTimingCodesFrame::TimestampFormat
EventTimingCodesFrame::timestampFormat() const
{
EventTimingCodesFrame::timestampFormat() const {
return d->timestampFormat;
}
EventTimingCodesFrame::SynchedEventList
EventTimingCodesFrame::synchedEvents() const
{
EventTimingCodesFrame::synchedEvents() const {
return d->synchedEvents;
}
void EventTimingCodesFrame::setTimestampFormat(
EventTimingCodesFrame::TimestampFormat f)
{
EventTimingCodesFrame::TimestampFormat f) {
d->timestampFormat = f;
}
void EventTimingCodesFrame::setSynchedEvents(
const EventTimingCodesFrame::SynchedEventList &e)
{
const EventTimingCodesFrame::SynchedEventList &e) {
d->synchedEvents = e;
}
@ -96,10 +84,9 @@ void EventTimingCodesFrame::setSynchedEvents(
// protected members
////////////////////////////////////////////////////////////////////////////////
void EventTimingCodesFrame::parseFields(const ByteVector &data)
{
void EventTimingCodesFrame::parseFields(const ByteVector &data) {
const int end = data.size();
if(end < 1) {
if (end < 1) {
debug("An event timing codes frame must contain at least 1 byte.");
return;
}
@ -108,7 +95,7 @@ void EventTimingCodesFrame::parseFields(const ByteVector &data)
int pos = 1;
d->synchedEvents.clear();
while(pos + 4 < end) {
while (pos + 4 < end) {
EventType type = static_cast<EventType>(static_cast<unsigned char>(data[pos++]));
unsigned int time = data.toUInt(pos, true);
pos += 4;
@ -116,12 +103,11 @@ void EventTimingCodesFrame::parseFields(const ByteVector &data)
}
}
ByteVector EventTimingCodesFrame::renderFields() const
{
ByteVector EventTimingCodesFrame::renderFields() const {
ByteVector v;
v.append(char(d->timestampFormat));
for(SynchedEventList::ConstIterator it = d->synchedEvents.begin();
for (SynchedEventList::ConstIterator it = d->synchedEvents.begin();
it != d->synchedEvents.end();
++it) {
const SynchedEvent &entry = *it;
@ -136,9 +122,7 @@ ByteVector EventTimingCodesFrame::renderFields() const
// private members
////////////////////////////////////////////////////////////////////////////////
EventTimingCodesFrame::EventTimingCodesFrame(const ByteVector &data, Header *h) :
Frame(h),
d(new EventTimingCodesFramePrivate())
{
EventTimingCodesFrame::EventTimingCodesFrame(const ByteVector &data, Header *h) : Frame(h),
d(new EventTimingCodesFramePrivate()) {
parseFields(fieldData(data));
}

View File

@ -32,18 +32,16 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
namespace ID3v2 {
//! ID3v2 event timing codes frame
/*!
//! ID3v2 event timing codes frame
/*!
* An implementation of ID3v2 event timing codes.
*/
class TAGLIB_EXPORT EventTimingCodesFrame : public Frame
{
class TAGLIB_EXPORT EventTimingCodesFrame : public Frame {
friend class FrameFactory;
public:
/*!
* Specifies the timestamp format used.
*/
@ -179,9 +177,9 @@ namespace TagLib {
class EventTimingCodesFramePrivate;
EventTimingCodesFramePrivate *d;
};
};
}
}
}
} // namespace ID3v2
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -34,9 +34,8 @@
using namespace Strawberry_TagLib::TagLib;
using namespace ID3v2;
class GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFramePrivate
{
public:
class GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFramePrivate {
public:
GeneralEncapsulatedObjectFramePrivate() : textEncoding(String::Latin1) {}
String::Type textEncoding;
@ -50,84 +49,68 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame() :
Frame("GEOB"),
d(new GeneralEncapsulatedObjectFramePrivate())
{
GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame() : Frame("GEOB"),
d(new GeneralEncapsulatedObjectFramePrivate()) {
}
GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame(const ByteVector &data) :
Frame(data),
d(new GeneralEncapsulatedObjectFramePrivate())
{
GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame(const ByteVector &data) : Frame(data),
d(new GeneralEncapsulatedObjectFramePrivate()) {
setData(data);
}
GeneralEncapsulatedObjectFrame::~GeneralEncapsulatedObjectFrame()
{
GeneralEncapsulatedObjectFrame::~GeneralEncapsulatedObjectFrame() {
delete d;
}
String GeneralEncapsulatedObjectFrame::toString() const
{
String GeneralEncapsulatedObjectFrame::toString() const {
String text = "[" + d->mimeType + "]";
if(!d->fileName.isEmpty())
if (!d->fileName.isEmpty())
text += " " + d->fileName;
if(!d->description.isEmpty())
if (!d->description.isEmpty())
text += " \"" + d->description + "\"";
return text;
}
String::Type GeneralEncapsulatedObjectFrame::textEncoding() const
{
String::Type GeneralEncapsulatedObjectFrame::textEncoding() const {
return d->textEncoding;
}
void GeneralEncapsulatedObjectFrame::setTextEncoding(String::Type encoding)
{
void GeneralEncapsulatedObjectFrame::setTextEncoding(String::Type encoding) {
d->textEncoding = encoding;
}
String GeneralEncapsulatedObjectFrame::mimeType() const
{
String GeneralEncapsulatedObjectFrame::mimeType() const {
return d->mimeType;
}
void GeneralEncapsulatedObjectFrame::setMimeType(const String &type)
{
void GeneralEncapsulatedObjectFrame::setMimeType(const String &type) {
d->mimeType = type;
}
String GeneralEncapsulatedObjectFrame::fileName() const
{
String GeneralEncapsulatedObjectFrame::fileName() const {
return d->fileName;
}
void GeneralEncapsulatedObjectFrame::setFileName(const String &name)
{
void GeneralEncapsulatedObjectFrame::setFileName(const String &name) {
d->fileName = name;
}
String GeneralEncapsulatedObjectFrame::description() const
{
String GeneralEncapsulatedObjectFrame::description() const {
return d->description;
}
void GeneralEncapsulatedObjectFrame::setDescription(const String &desc)
{
void GeneralEncapsulatedObjectFrame::setDescription(const String &desc) {
d->description = desc;
}
ByteVector GeneralEncapsulatedObjectFrame::object() const
{
ByteVector GeneralEncapsulatedObjectFrame::object() const {
return d->data;
}
void GeneralEncapsulatedObjectFrame::setObject(const ByteVector &data)
{
void GeneralEncapsulatedObjectFrame::setObject(const ByteVector &data) {
d->data = data;
}
@ -135,9 +118,8 @@ void GeneralEncapsulatedObjectFrame::setObject(const ByteVector &data)
// protected members
////////////////////////////////////////////////////////////////////////////////
void GeneralEncapsulatedObjectFrame::parseFields(const ByteVector &data)
{
if(data.size() < 4) {
void GeneralEncapsulatedObjectFrame::parseFields(const ByteVector &data) {
if (data.size() < 4) {
debug("An object frame must contain at least 4 bytes.");
return;
}
@ -153,8 +135,7 @@ void GeneralEncapsulatedObjectFrame::parseFields(const ByteVector &data)
d->data = data.mid(pos);
}
ByteVector GeneralEncapsulatedObjectFrame::renderFields() const
{
ByteVector GeneralEncapsulatedObjectFrame::renderFields() const {
StringList sl;
sl.append(d->fileName);
sl.append(d->description);
@ -179,9 +160,7 @@ ByteVector GeneralEncapsulatedObjectFrame::renderFields() const
// private members
////////////////////////////////////////////////////////////////////////////////
GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame(const ByteVector &data, Header *h) :
Frame(h),
d(new GeneralEncapsulatedObjectFramePrivate())
{
GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame(const ByteVector &data, Header *h) : Frame(h),
d(new GeneralEncapsulatedObjectFramePrivate()) {
parseFields(fieldData(data));
}

View File

@ -36,11 +36,11 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
namespace ID3v2 {
//! An ID3v2 general encapsulated object frame implementation
//! An ID3v2 general encapsulated object frame implementation
/*!
/*!
* This is an implementation of ID3v2 general encapsulated objects.
* Arbitrary binary data may be included in tags, stored in GEOB frames.
* There may be multiple GEOB frames in a single tag. Each GEOB it
@ -49,12 +49,10 @@ namespace TagLib {
* uniquely identifies the GEOB frame in the tag.
*/
class TAGLIB_EXPORT GeneralEncapsulatedObjectFrame : public Frame
{
class TAGLIB_EXPORT GeneralEncapsulatedObjectFrame : public Frame {
friend class FrameFactory;
public:
/*!
* Constructs an empty object frame. The description, file name and text
* encoding should be set manually.
@ -173,9 +171,9 @@ namespace TagLib {
class GeneralEncapsulatedObjectFramePrivate;
GeneralEncapsulatedObjectFramePrivate *d;
};
}
}
}
};
} // namespace ID3v2
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -32,9 +32,8 @@
using namespace Strawberry_TagLib::TagLib;
using namespace ID3v2;
class OwnershipFrame::OwnershipFramePrivate
{
public:
class OwnershipFrame::OwnershipFramePrivate {
public:
String pricePaid;
String datePurchased;
String seller;
@ -45,67 +44,53 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
OwnershipFrame::OwnershipFrame(String::Type encoding) :
Frame("OWNE"),
d(new OwnershipFramePrivate())
{
OwnershipFrame::OwnershipFrame(String::Type encoding) : Frame("OWNE"),
d(new OwnershipFramePrivate()) {
d->textEncoding = encoding;
}
OwnershipFrame::OwnershipFrame(const ByteVector &data) :
Frame(data),
d(new OwnershipFramePrivate())
{
OwnershipFrame::OwnershipFrame(const ByteVector &data) : Frame(data),
d(new OwnershipFramePrivate()) {
setData(data);
}
OwnershipFrame::~OwnershipFrame()
{
OwnershipFrame::~OwnershipFrame() {
delete d;
}
String OwnershipFrame::toString() const
{
String OwnershipFrame::toString() const {
return "pricePaid=" + d->pricePaid + " datePurchased=" + d->datePurchased + " seller=" + d->seller;
}
String OwnershipFrame::pricePaid() const
{
String OwnershipFrame::pricePaid() const {
return d->pricePaid;
}
void OwnershipFrame::setPricePaid(const String &s)
{
void OwnershipFrame::setPricePaid(const String &s) {
d->pricePaid = s;
}
String OwnershipFrame::datePurchased() const
{
String OwnershipFrame::datePurchased() const {
return d->datePurchased;
}
void OwnershipFrame::setDatePurchased(const String &s)
{
void OwnershipFrame::setDatePurchased(const String &s) {
d->datePurchased = s;
}
String OwnershipFrame::seller() const
{
String OwnershipFrame::seller() const {
return d->seller;
}
void OwnershipFrame::setSeller(const String &s)
{
void OwnershipFrame::setSeller(const String &s) {
d->seller = s;
}
String::Type OwnershipFrame::textEncoding() const
{
String::Type OwnershipFrame::textEncoding() const {
return d->textEncoding;
}
void OwnershipFrame::setTextEncoding(String::Type encoding)
{
void OwnershipFrame::setTextEncoding(String::Type encoding) {
d->textEncoding = encoding;
}
@ -113,8 +98,7 @@ void OwnershipFrame::setTextEncoding(String::Type encoding)
// protected members
////////////////////////////////////////////////////////////////////////////////
void OwnershipFrame::parseFields(const ByteVector &data)
{
void OwnershipFrame::parseFields(const ByteVector &data) {
int pos = 0;
// Get the text encoding
@ -126,7 +110,7 @@ void OwnershipFrame::parseFields(const ByteVector &data)
// If we don't have at least 8 bytes left then don't parse the rest of the
// data
if(data.size() - pos < 8) {
if (data.size() - pos < 8) {
return;
}
@ -135,14 +119,13 @@ void OwnershipFrame::parseFields(const ByteVector &data)
pos += 8;
// Read the seller
if(d->textEncoding == String::Latin1)
if (d->textEncoding == String::Latin1)
d->seller = Tag::latin1StringHandler()->parse(data.mid(pos));
else
d->seller = String(data.mid(pos), d->textEncoding);
}
ByteVector OwnershipFrame::renderFields() const
{
ByteVector OwnershipFrame::renderFields() const {
StringList sl;
sl.append(d->seller);
@ -163,9 +146,7 @@ ByteVector OwnershipFrame::renderFields() const
// private members
////////////////////////////////////////////////////////////////////////////////
OwnershipFrame::OwnershipFrame(const ByteVector &data, Header *h) :
Frame(h),
d(new OwnershipFramePrivate())
{
OwnershipFrame::OwnershipFrame(const ByteVector &data, Header *h) : Frame(h),
d(new OwnershipFramePrivate()) {
parseFields(fieldData(data));
}

View File

@ -32,17 +32,16 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
namespace ID3v2 {
//! An implementation of ID3v2 "ownership"
//! An implementation of ID3v2 "ownership"
/*!
/*!
* This implements the ID3v2 ownership (OWNE frame). It consists of
* a price paid, a date purchased (YYYYMMDD) and the name of the seller.
*/
class TAGLIB_EXPORT OwnershipFrame : public Frame
{
class TAGLIB_EXPORT OwnershipFrame : public Frame {
friend class FrameFactory;
public:
@ -145,9 +144,9 @@ namespace TagLib {
class OwnershipFramePrivate;
OwnershipFramePrivate *d;
};
};
}
}
}
} // namespace ID3v2
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -28,9 +28,8 @@
using namespace Strawberry_TagLib::TagLib;
using namespace ID3v2;
class PodcastFrame::PodcastFramePrivate
{
public:
class PodcastFrame::PodcastFramePrivate {
public:
ByteVector fieldData;
};
@ -38,20 +37,16 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
PodcastFrame::PodcastFrame() :
Frame("PCST"),
d(new PodcastFramePrivate())
{
PodcastFrame::PodcastFrame() : Frame("PCST"),
d(new PodcastFramePrivate()) {
d->fieldData = ByteVector(4, '\0');
}
PodcastFrame::~PodcastFrame()
{
PodcastFrame::~PodcastFrame() {
delete d;
}
String PodcastFrame::toString() const
{
String PodcastFrame::toString() const {
return String();
}
@ -59,13 +54,11 @@ String PodcastFrame::toString() const
// protected members
////////////////////////////////////////////////////////////////////////////////
void PodcastFrame::parseFields(const ByteVector &data)
{
void PodcastFrame::parseFields(const ByteVector &data) {
d->fieldData = data;
}
ByteVector PodcastFrame::renderFields() const
{
ByteVector PodcastFrame::renderFields() const {
return d->fieldData;
}
@ -73,9 +66,7 @@ ByteVector PodcastFrame::renderFields() const
// private members
////////////////////////////////////////////////////////////////////////////////
PodcastFrame::PodcastFrame(const ByteVector &data, Header *h) :
Frame(h),
d(new PodcastFramePrivate())
{
PodcastFrame::PodcastFrame(const ByteVector &data, Header *h) : Frame(h),
d(new PodcastFramePrivate()) {
parseFields(fieldData(data));
}

View File

@ -32,14 +32,13 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
namespace ID3v2 {
//! ID3v2 podcast frame
/*!
//! ID3v2 podcast frame
/*!
* An implementation of ID3v2 podcast flag, a frame with four zero bytes.
*/
class TAGLIB_EXPORT PodcastFrame : public Frame
{
class TAGLIB_EXPORT PodcastFrame : public Frame {
friend class FrameFactory;
public:
@ -74,9 +73,9 @@ namespace TagLib {
class PodcastFramePrivate;
PodcastFramePrivate *d;
};
};
}
}
}
} // namespace ID3v2
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -30,9 +30,8 @@
using namespace Strawberry_TagLib::TagLib;
using namespace ID3v2;
class PopularimeterFrame::PopularimeterFramePrivate
{
public:
class PopularimeterFrame::PopularimeterFramePrivate {
public:
PopularimeterFramePrivate() : rating(0), counter(0) {}
String email;
int rating;
@ -43,56 +42,44 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
PopularimeterFrame::PopularimeterFrame() :
Frame("POPM"),
d(new PopularimeterFramePrivate())
{
PopularimeterFrame::PopularimeterFrame() : Frame("POPM"),
d(new PopularimeterFramePrivate()) {
}
PopularimeterFrame::PopularimeterFrame(const ByteVector &data) :
Frame(data),
d(new PopularimeterFramePrivate())
{
PopularimeterFrame::PopularimeterFrame(const ByteVector &data) : Frame(data),
d(new PopularimeterFramePrivate()) {
setData(data);
}
PopularimeterFrame::~PopularimeterFrame()
{
PopularimeterFrame::~PopularimeterFrame() {
delete d;
}
String PopularimeterFrame::toString() const
{
String PopularimeterFrame::toString() const {
return d->email + " rating=" + String::number(d->rating) + " counter=" + String::number(d->counter);
}
String PopularimeterFrame::email() const
{
String PopularimeterFrame::email() const {
return d->email;
}
void PopularimeterFrame::setEmail(const String &s)
{
void PopularimeterFrame::setEmail(const String &s) {
d->email = s;
}
int PopularimeterFrame::rating() const
{
int PopularimeterFrame::rating() const {
return d->rating;
}
void PopularimeterFrame::setRating(int s)
{
void PopularimeterFrame::setRating(int s) {
d->rating = s;
}
unsigned int PopularimeterFrame::counter() const
{
unsigned int PopularimeterFrame::counter() const {
return d->counter;
}
void PopularimeterFrame::setCounter(unsigned int s)
{
void PopularimeterFrame::setCounter(unsigned int s) {
d->counter = s;
}
@ -100,24 +87,22 @@ void PopularimeterFrame::setCounter(unsigned int s)
// protected members
////////////////////////////////////////////////////////////////////////////////
void PopularimeterFrame::parseFields(const ByteVector &data)
{
void PopularimeterFrame::parseFields(const ByteVector &data) {
int pos = 0, size = int(data.size());
d->email = readStringField(data, String::Latin1, &pos);
d->rating = 0;
d->counter = 0;
if(pos < size) {
if (pos < size) {
d->rating = (unsigned char)(data[pos++]);
if(pos < size) {
if (pos < size) {
d->counter = data.toUInt(static_cast<unsigned int>(pos));
}
}
}
ByteVector PopularimeterFrame::renderFields() const
{
ByteVector PopularimeterFrame::renderFields() const {
ByteVector data;
data.append(d->email.data(String::Latin1));
@ -132,9 +117,7 @@ ByteVector PopularimeterFrame::renderFields() const
// private members
////////////////////////////////////////////////////////////////////////////////
PopularimeterFrame::PopularimeterFrame(const ByteVector &data, Header *h) :
Frame(h),
d(new PopularimeterFramePrivate())
{
PopularimeterFrame::PopularimeterFrame(const ByteVector &data, Header *h) : Frame(h),
d(new PopularimeterFramePrivate()) {
parseFields(fieldData(data));
}

View File

@ -32,17 +32,16 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
namespace ID3v2 {
//! An implementation of ID3v2 "popularimeter"
//! An implementation of ID3v2 "popularimeter"
/*!
/*!
* This implements the ID3v2 popularimeter (POPM frame). It consists of
* an email, a rating and an optional counter.
*/
class TAGLIB_EXPORT PopularimeterFrame : public Frame
{
class TAGLIB_EXPORT PopularimeterFrame : public Frame {
friend class FrameFactory;
public:
@ -126,9 +125,9 @@ namespace TagLib {
class PopularimeterFramePrivate;
PopularimeterFramePrivate *d;
};
};
}
}
}
} // namespace ID3v2
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -34,9 +34,8 @@ using namespace Strawberry_TagLib::TagLib;
using namespace ID3v2;
class PrivateFrame::PrivateFramePrivate
{
public:
class PrivateFrame::PrivateFramePrivate {
public:
ByteVector data;
String owner;
};
@ -45,46 +44,36 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
PrivateFrame::PrivateFrame() :
Frame("PRIV"),
d(new PrivateFramePrivate())
{
PrivateFrame::PrivateFrame() : Frame("PRIV"),
d(new PrivateFramePrivate()) {
}
PrivateFrame::PrivateFrame(const ByteVector &data) :
Frame(data),
d(new PrivateFramePrivate())
{
PrivateFrame::PrivateFrame(const ByteVector &data) : Frame(data),
d(new PrivateFramePrivate()) {
setData(data);
}
PrivateFrame::~PrivateFrame()
{
PrivateFrame::~PrivateFrame() {
delete d;
}
String PrivateFrame::toString() const
{
String PrivateFrame::toString() const {
return d->owner;
}
String PrivateFrame::owner() const
{
String PrivateFrame::owner() const {
return d->owner;
}
ByteVector PrivateFrame::data() const
{
ByteVector PrivateFrame::data() const {
return d->data;
}
void PrivateFrame::setOwner(const String &s)
{
void PrivateFrame::setOwner(const String &s) {
d->owner = s;
}
void PrivateFrame::setData(const ByteVector & data)
{
void PrivateFrame::setData(const ByteVector &data) {
d->data = data;
}
@ -92,9 +81,8 @@ void PrivateFrame::setData(const ByteVector & data)
// protected members
////////////////////////////////////////////////////////////////////////////////
void PrivateFrame::parseFields(const ByteVector &data)
{
if(data.size() < 2) {
void PrivateFrame::parseFields(const ByteVector &data) {
if (data.size() < 2) {
debug("A private frame must contain at least 2 bytes.");
return;
}
@ -108,8 +96,7 @@ void PrivateFrame::parseFields(const ByteVector &data)
d->data = data.mid(endOfOwner + 1);
}
ByteVector PrivateFrame::renderFields() const
{
ByteVector PrivateFrame::renderFields() const {
ByteVector v;
v.append(d->owner.data(String::Latin1));
@ -123,9 +110,7 @@ ByteVector PrivateFrame::renderFields() const
// private members
////////////////////////////////////////////////////////////////////////////////
PrivateFrame::PrivateFrame(const ByteVector &data, Header *h) :
Frame(h),
d(new PrivateFramePrivate())
{
PrivateFrame::PrivateFrame(const ByteVector &data, Header *h) : Frame(h),
d(new PrivateFramePrivate()) {
parseFields(fieldData(data));
}

View File

@ -33,12 +33,11 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
namespace ID3v2 {
//! An implementation of ID3v2 privateframe
//! An implementation of ID3v2 privateframe
class TAGLIB_EXPORT PrivateFrame : public Frame
{
class TAGLIB_EXPORT PrivateFrame : public Frame {
friend class FrameFactory;
public:
@ -105,9 +104,9 @@ namespace TagLib {
class PrivateFramePrivate;
PrivateFramePrivate *d;
};
};
}
}
}
} // namespace ID3v2
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -31,8 +31,7 @@
using namespace Strawberry_TagLib::TagLib;
using namespace ID3v2;
struct ChannelData
{
struct ChannelData {
ChannelData() : channelType(RelativeVolumeFrame::Other), volumeAdjustment(0) {}
RelativeVolumeFrame::ChannelType channelType;
@ -40,9 +39,8 @@ struct ChannelData
RelativeVolumeFrame::PeakVolume peakVolume;
};
class RelativeVolumeFrame::RelativeVolumeFramePrivate
{
public:
class RelativeVolumeFrame::RelativeVolumeFramePrivate {
public:
String identification;
Map<ChannelType, ChannelData> channels;
};
@ -51,35 +49,28 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
RelativeVolumeFrame::RelativeVolumeFrame() :
Frame("RVA2"),
d(new RelativeVolumeFramePrivate())
{
RelativeVolumeFrame::RelativeVolumeFrame() : Frame("RVA2"),
d(new RelativeVolumeFramePrivate()) {
}
RelativeVolumeFrame::RelativeVolumeFrame(const ByteVector &data) :
Frame(data),
d(new RelativeVolumeFramePrivate())
{
RelativeVolumeFrame::RelativeVolumeFrame(const ByteVector &data) : Frame(data),
d(new RelativeVolumeFramePrivate()) {
setData(data);
}
RelativeVolumeFrame::~RelativeVolumeFrame()
{
RelativeVolumeFrame::~RelativeVolumeFrame() {
delete d;
}
String RelativeVolumeFrame::toString() const
{
String RelativeVolumeFrame::toString() const {
return d->identification;
}
List<RelativeVolumeFrame::ChannelType> RelativeVolumeFrame::channels() const
{
List<RelativeVolumeFrame::ChannelType> RelativeVolumeFrame::channels() const {
List<ChannelType> l;
Map<ChannelType, ChannelData>::ConstIterator it = d->channels.begin();
for(; it != d->channels.end(); ++it)
for (; it != d->channels.end(); ++it)
l.append((*it).first);
return l;
@ -87,85 +78,68 @@ List<RelativeVolumeFrame::ChannelType> RelativeVolumeFrame::channels() const
// deprecated
RelativeVolumeFrame::ChannelType RelativeVolumeFrame::channelType() const
{
RelativeVolumeFrame::ChannelType RelativeVolumeFrame::channelType() const {
return MasterVolume;
}
// deprecated
void RelativeVolumeFrame::setChannelType(ChannelType)
{
void RelativeVolumeFrame::setChannelType(ChannelType) {
}
short RelativeVolumeFrame::volumeAdjustmentIndex(ChannelType type) const
{
short RelativeVolumeFrame::volumeAdjustmentIndex(ChannelType type) const {
return d->channels.contains(type) ? d->channels[type].volumeAdjustment : 0;
}
short RelativeVolumeFrame::volumeAdjustmentIndex() const
{
short RelativeVolumeFrame::volumeAdjustmentIndex() const {
return volumeAdjustmentIndex(MasterVolume);
}
void RelativeVolumeFrame::setVolumeAdjustmentIndex(short index, ChannelType type)
{
void RelativeVolumeFrame::setVolumeAdjustmentIndex(short index, ChannelType type) {
d->channels[type].volumeAdjustment = index;
}
void RelativeVolumeFrame::setVolumeAdjustmentIndex(short index)
{
void RelativeVolumeFrame::setVolumeAdjustmentIndex(short index) {
setVolumeAdjustmentIndex(index, MasterVolume);
}
float RelativeVolumeFrame::volumeAdjustment(ChannelType type) const
{
float RelativeVolumeFrame::volumeAdjustment(ChannelType type) const {
return d->channels.contains(type) ? float(d->channels[type].volumeAdjustment) / float(512) : 0;
}
float RelativeVolumeFrame::volumeAdjustment() const
{
float RelativeVolumeFrame::volumeAdjustment() const {
return volumeAdjustment(MasterVolume);
}
void RelativeVolumeFrame::setVolumeAdjustment(float adjustment, ChannelType type)
{
void RelativeVolumeFrame::setVolumeAdjustment(float adjustment, ChannelType type) {
d->channels[type].volumeAdjustment = short(adjustment * float(512));
}
void RelativeVolumeFrame::setVolumeAdjustment(float adjustment)
{
void RelativeVolumeFrame::setVolumeAdjustment(float adjustment) {
setVolumeAdjustment(adjustment, MasterVolume);
}
RelativeVolumeFrame::PeakVolume RelativeVolumeFrame::peakVolume(ChannelType type) const
{
RelativeVolumeFrame::PeakVolume RelativeVolumeFrame::peakVolume(ChannelType type) const {
return d->channels.contains(type) ? d->channels[type].peakVolume : PeakVolume();
}
RelativeVolumeFrame::PeakVolume RelativeVolumeFrame::peakVolume() const
{
RelativeVolumeFrame::PeakVolume RelativeVolumeFrame::peakVolume() const {
return peakVolume(MasterVolume);
}
void RelativeVolumeFrame::setPeakVolume(const PeakVolume &peak, ChannelType type)
{
void RelativeVolumeFrame::setPeakVolume(const PeakVolume &peak, ChannelType type) {
d->channels[type].peakVolume = peak;
}
void RelativeVolumeFrame::setPeakVolume(const PeakVolume &peak)
{
void RelativeVolumeFrame::setPeakVolume(const PeakVolume &peak) {
setPeakVolume(peak, MasterVolume);
}
String RelativeVolumeFrame::identification() const
{
String RelativeVolumeFrame::identification() const {
return d->identification;
}
void RelativeVolumeFrame::setIdentification(const String &s)
{
void RelativeVolumeFrame::setIdentification(const String &s) {
d->identification = s;
}
@ -173,14 +147,13 @@ void RelativeVolumeFrame::setIdentification(const String &s)
// protected members
////////////////////////////////////////////////////////////////////////////////
void RelativeVolumeFrame::parseFields(const ByteVector &data)
{
void RelativeVolumeFrame::parseFields(const ByteVector &data) {
int pos = 0;
d->identification = readStringField(data, String::Latin1, &pos);
// Each channel is at least 4 bytes.
while(pos <= (int)data.size() - 4) {
while (pos <= (int)data.size() - 4) {
ChannelType type = ChannelType(data[pos]);
pos += 1;
@ -199,8 +172,7 @@ void RelativeVolumeFrame::parseFields(const ByteVector &data)
}
}
ByteVector RelativeVolumeFrame::renderFields() const
{
ByteVector RelativeVolumeFrame::renderFields() const {
ByteVector data;
data.append(d->identification.data(String::Latin1));
@ -208,7 +180,7 @@ ByteVector RelativeVolumeFrame::renderFields() const
Map<ChannelType, ChannelData>::ConstIterator it = d->channels.begin();
for(; it != d->channels.end(); ++it) {
for (; it != d->channels.end(); ++it) {
ChannelType type = (*it).first;
const ChannelData &channel = (*it).second;
@ -225,9 +197,7 @@ ByteVector RelativeVolumeFrame::renderFields() const
// private members
////////////////////////////////////////////////////////////////////////////////
RelativeVolumeFrame::RelativeVolumeFrame(const ByteVector &data, Header *h) :
Frame(h),
d(new RelativeVolumeFramePrivate())
{
RelativeVolumeFrame::RelativeVolumeFrame(const ByteVector &data, Header *h) : Frame(h),
d(new RelativeVolumeFramePrivate()) {
parseFields(fieldData(data));
}

View File

@ -33,11 +33,11 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
namespace ID3v2 {
//! An ID3v2 relative volume adjustment frame implementation
//! An ID3v2 relative volume adjustment frame implementation
/*!
/*!
* This is an implementation of ID3v2 relative volume adjustment. The
* presence of this frame makes it possible to specify an increase in volume
* for an audio file or specific audio tracks in that file.
@ -47,12 +47,10 @@ namespace TagLib {
* different channel types.
*/
class TAGLIB_EXPORT RelativeVolumeFrame : public Frame
{
class TAGLIB_EXPORT RelativeVolumeFrame : public Frame {
friend class FrameFactory;
public:
/*!
* This indicates the type of volume adjustment that should be applied.
*/
@ -83,8 +81,7 @@ namespace TagLib {
* The peak volume is described as a series of bits that is padded to fill
* a block of bytes. These two values should always be updated in tandem.
*/
struct PeakVolume
{
struct PeakVolume {
/*!
* Constructs an empty peak volume description.
*/
@ -268,9 +265,9 @@ namespace TagLib {
class RelativeVolumeFramePrivate;
RelativeVolumeFramePrivate *d;
};
};
}
}
}
} // namespace ID3v2
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@ -32,11 +32,9 @@
using namespace Strawberry_TagLib::TagLib;
using namespace ID3v2;
class SynchronizedLyricsFrame::SynchronizedLyricsFramePrivate
{
public:
SynchronizedLyricsFramePrivate() :
textEncoding(String::Latin1),
class SynchronizedLyricsFrame::SynchronizedLyricsFramePrivate {
public:
SynchronizedLyricsFramePrivate() : textEncoding(String::Latin1),
timestampFormat(SynchronizedLyricsFrame::AbsoluteMilliseconds),
type(SynchronizedLyricsFrame::Lyrics) {}
String::Type textEncoding;
@ -51,90 +49,72 @@ public:
// public members
////////////////////////////////////////////////////////////////////////////////
SynchronizedLyricsFrame::SynchronizedLyricsFrame(String::Type encoding) :
Frame("SYLT"),
d(new SynchronizedLyricsFramePrivate())
{
SynchronizedLyricsFrame::SynchronizedLyricsFrame(String::Type encoding) : Frame("SYLT"),
d(new SynchronizedLyricsFramePrivate()) {
d->textEncoding = encoding;
}
SynchronizedLyricsFrame::SynchronizedLyricsFrame(const ByteVector &data) :
Frame(data),
d(new SynchronizedLyricsFramePrivate())
{
SynchronizedLyricsFrame::SynchronizedLyricsFrame(const ByteVector &data) : Frame(data),
d(new SynchronizedLyricsFramePrivate()) {
setData(data);
}
SynchronizedLyricsFrame::~SynchronizedLyricsFrame()
{
SynchronizedLyricsFrame::~SynchronizedLyricsFrame() {
delete d;
}
String SynchronizedLyricsFrame::toString() const
{
String SynchronizedLyricsFrame::toString() const {
return d->description;
}
String::Type SynchronizedLyricsFrame::textEncoding() const
{
String::Type SynchronizedLyricsFrame::textEncoding() const {
return d->textEncoding;
}
ByteVector SynchronizedLyricsFrame::language() const
{
ByteVector SynchronizedLyricsFrame::language() const {
return d->language;
}
SynchronizedLyricsFrame::TimestampFormat
SynchronizedLyricsFrame::timestampFormat() const
{
SynchronizedLyricsFrame::timestampFormat() const {
return d->timestampFormat;
}
SynchronizedLyricsFrame::Type SynchronizedLyricsFrame::type() const
{
SynchronizedLyricsFrame::Type SynchronizedLyricsFrame::type() const {
return d->type;
}
String SynchronizedLyricsFrame::description() const
{
String SynchronizedLyricsFrame::description() const {
return d->description;
}
SynchronizedLyricsFrame::SynchedTextList
SynchronizedLyricsFrame::synchedText() const
{
SynchronizedLyricsFrame::synchedText() const {
return d->synchedText;
}
void SynchronizedLyricsFrame::setTextEncoding(String::Type encoding)
{
void SynchronizedLyricsFrame::setTextEncoding(String::Type encoding) {
d->textEncoding = encoding;
}
void SynchronizedLyricsFrame::setLanguage(const ByteVector &languageEncoding)
{
void SynchronizedLyricsFrame::setLanguage(const ByteVector &languageEncoding) {
d->language = languageEncoding.mid(0, 3);
}
void SynchronizedLyricsFrame::setTimestampFormat(SynchronizedLyricsFrame::TimestampFormat f)
{
void SynchronizedLyricsFrame::setTimestampFormat(SynchronizedLyricsFrame::TimestampFormat f) {
d->timestampFormat = f;
}
void SynchronizedLyricsFrame::setType(SynchronizedLyricsFrame::Type t)
{
void SynchronizedLyricsFrame::setType(SynchronizedLyricsFrame::Type t) {
d->type = t;
}
void SynchronizedLyricsFrame::setDescription(const String &s)
{
void SynchronizedLyricsFrame::setDescription(const String &s) {
d->description = s;
}
void SynchronizedLyricsFrame::setSynchedText(
const SynchronizedLyricsFrame::SynchedTextList &t)
{
const SynchronizedLyricsFrame::SynchedTextList &t) {
d->synchedText = t;
}
@ -142,10 +122,9 @@ void SynchronizedLyricsFrame::setSynchedText(
// protected members
////////////////////////////////////////////////////////////////////////////////
void SynchronizedLyricsFrame::parseFields(const ByteVector &data)
{
void SynchronizedLyricsFrame::parseFields(const ByteVector &data) {
const int end = data.size();
if(end < 7) {
if (end < 7) {
debug("A synchronized lyrics frame must contain at least 7 bytes.");
return;
}
@ -158,7 +137,7 @@ void SynchronizedLyricsFrame::parseFields(const ByteVector &data)
int pos = 6;
d->description = readStringField(data, d->textEncoding, &pos);
if(pos == 6)
if (pos == 6)
return;
/*
@ -169,27 +148,28 @@ void SynchronizedLyricsFrame::parseFields(const ByteVector &data)
* case of strings without BOM so that readStringField() will work.
*/
String::Type encWithEndianness = d->textEncoding;
if(d->textEncoding == String::UTF16) {
if (d->textEncoding == String::UTF16) {
unsigned short bom = data.toUShort(6, true);
if(bom == 0xfffe) {
if (bom == 0xfffe) {
encWithEndianness = String::UTF16LE;
} else if(bom == 0xfeff) {
}
else if (bom == 0xfeff) {
encWithEndianness = String::UTF16BE;
}
}
d->synchedText.clear();
while(pos < end) {
while (pos < end) {
String::Type enc = d->textEncoding;
// If a UTF16 string has no BOM, use the encoding found above.
if(enc == String::UTF16 && pos + 1 < end) {
if (enc == String::UTF16 && pos + 1 < end) {
unsigned short bom = data.toUShort(pos, true);
if(bom != 0xfffe && bom != 0xfeff) {
if (bom != 0xfffe && bom != 0xfeff) {
enc = encWithEndianness;
}
}
String text = readStringField(data, enc, &pos);
if(pos + 4 > end)
if (pos + 4 > end)
return;
unsigned int time = data.toUInt(pos, true);
@ -199,14 +179,13 @@ void SynchronizedLyricsFrame::parseFields(const ByteVector &data)
}
}
ByteVector SynchronizedLyricsFrame::renderFields() const
{
ByteVector SynchronizedLyricsFrame::renderFields() const {
ByteVector v;
String::Type encoding = d->textEncoding;
encoding = checkTextEncoding(d->description, encoding);
for(SynchedTextList::ConstIterator it = d->synchedText.begin();
for (SynchedTextList::ConstIterator it = d->synchedText.begin();
it != d->synchedText.end();
++it) {
encoding = checkTextEncoding(it->text, encoding);
@ -218,7 +197,7 @@ ByteVector SynchronizedLyricsFrame::renderFields() const
v.append(char(d->type));
v.append(d->description.data(encoding));
v.append(textDelimiter(encoding));
for(SynchedTextList::ConstIterator it = d->synchedText.begin();
for (SynchedTextList::ConstIterator it = d->synchedText.begin();
it != d->synchedText.end();
++it) {
const SynchedText &entry = *it;
@ -234,9 +213,7 @@ ByteVector SynchronizedLyricsFrame::renderFields() const
// private members
////////////////////////////////////////////////////////////////////////////////
SynchronizedLyricsFrame::SynchronizedLyricsFrame(const ByteVector &data, Header *h) :
Frame(h),
d(new SynchronizedLyricsFramePrivate())
{
SynchronizedLyricsFrame::SynchronizedLyricsFrame(const ByteVector &data, Header *h) : Frame(h),
d(new SynchronizedLyricsFramePrivate()) {
parseFields(fieldData(data));
}

View File

@ -32,18 +32,16 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
namespace ID3v2 {
//! ID3v2 synchronized lyrics frame
/*!
//! ID3v2 synchronized lyrics frame
/*!
* An implementation of ID3v2 synchronized lyrics.
*/
class TAGLIB_EXPORT SynchronizedLyricsFrame : public Frame
{
class TAGLIB_EXPORT SynchronizedLyricsFrame : public Frame {
friend class FrameFactory;
public:
/*!
* Specifies the timestamp format used.
*/
@ -225,9 +223,9 @@ namespace TagLib {
class SynchronizedLyricsFramePrivate;
SynchronizedLyricsFramePrivate *d;
};
};
}
}
}
} // namespace ID3v2
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

Some files were not shown because too many files have changed in this diff Show More