Format taglib sources
This commit is contained in:
parent
72bff7fa35
commit
4ce099294c
119
3rdparty/taglib/ape/apefile.cpp
vendored
119
3rdparty/taglib/ape/apefile.cpp
vendored
@ -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);
|
||||
}
|
||||
|
31
3rdparty/taglib/ape/apefile.h
vendored
31
3rdparty/taglib/ape/apefile.h
vendored
@ -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
|
||||
|
77
3rdparty/taglib/ape/apefooter.cpp
vendored
77
3rdparty/taglib/ape/apefooter.cpp
vendored
@ -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"
|
||||
|
17
3rdparty/taglib/ape/apefooter.h
vendored
17
3rdparty/taglib/ape/apefooter.h
vendored
@ -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
|
||||
|
123
3rdparty/taglib/ape/apeitem.cpp
vendored
123
3rdparty/taglib/ape/apeitem.cpp
vendored
@ -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));
|
||||
}
|
||||
|
21
3rdparty/taglib/ape/apeitem.h
vendored
21
3rdparty/taglib/ape/apeitem.h
vendored
@ -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
|
||||
|
||||
|
||||
|
95
3rdparty/taglib/ape/apeproperties.cpp
vendored
95
3rdparty/taglib/ape/apeproperties.cpp
vendored
@ -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;
|
||||
}
|
||||
|
19
3rdparty/taglib/ape/apeproperties.h
vendored
19
3rdparty/taglib/ape/apeproperties.h
vendored
@ -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
|
||||
|
248
3rdparty/taglib/ape/apetag.cpp
vendored
248
3rdparty/taglib/ape/apetag.cpp
vendored
@ -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));
|
||||
|
||||
|
28
3rdparty/taglib/ape/apetag.h
vendored
28
3rdparty/taglib/ape/apetag.h
vendored
@ -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
|
||||
|
124
3rdparty/taglib/asf/asfattribute.cpp
vendored
124
3rdparty/taglib/asf/asfattribute.cpp
vendored
@ -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;
|
||||
}
|
||||
|
22
3rdparty/taglib/asf/asfattribute.h
vendored
22
3rdparty/taglib/asf/asfattribute.h
vendored
@ -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
|
||||
|
316
3rdparty/taglib/asf/asffile.cpp
vendored
316
3rdparty/taglib/asf/asffile.cpp
vendored
@ -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;
|
||||
|
18
3rdparty/taglib/asf/asffile.h
vendored
18
3rdparty/taglib/asf/asffile.h
vendored
@ -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
|
||||
|
89
3rdparty/taglib/asf/asfpicture.cpp
vendored
89
3rdparty/taglib/asf/asfpicture.cpp
vendored
@ -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;
|
||||
|
33
3rdparty/taglib/asf/asfpicture.h
vendored
33
3rdparty/taglib/asf/asfpicture.h
vendored
@ -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
|
||||
|
83
3rdparty/taglib/asf/asfproperties.cpp
vendored
83
3rdparty/taglib/asf/asfproperties.cpp
vendored
@ -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;
|
||||
}
|
||||
|
19
3rdparty/taglib/asf/asfproperties.h
vendored
19
3rdparty/taglib/asf/asfproperties.h
vendored
@ -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
|
||||
|
186
3rdparty/taglib/asf/asftag.cpp
vendored
186
3rdparty/taglib/asf/asftag.cpp
vendored
@ -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 {
|
||||
|
20
3rdparty/taglib/asf/asftag.h
vendored
20
3rdparty/taglib/asf/asftag.h
vendored
@ -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
|
||||
|
66
3rdparty/taglib/asf/asfutils.h
vendored
66
3rdparty/taglib/asf/asfutils.h
vendored
@ -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
|
||||
|
||||
|
49
3rdparty/taglib/audioproperties.cpp
vendored
49
3rdparty/taglib/audioproperties.cpp
vendored
@ -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) {
|
||||
}
|
||||
|
15
3rdparty/taglib/audioproperties.h
vendored
15
3rdparty/taglib/audioproperties.h
vendored
@ -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
|
||||
|
81
3rdparty/taglib/dsdiff/dsdiffdiintag.cpp
vendored
81
3rdparty/taglib/dsdiff/dsdiffdiintag.cpp
vendored
@ -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;
|
||||
}
|
||||
|
||||
|
20
3rdparty/taglib/dsdiff/dsdiffdiintag.h
vendored
20
3rdparty/taglib/dsdiff/dsdiffdiintag.h
vendored
@ -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
|
||||
|
||||
|
360
3rdparty/taglib/dsdiff/dsdifffile.cpp
vendored
360
3rdparty/taglib/dsdiff/dsdifffile.cpp
vendored
@ -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);
|
||||
}
|
||||
|
||||
|
26
3rdparty/taglib/dsdiff/dsdifffile.h
vendored
26
3rdparty/taglib/dsdiff/dsdifffile.h
vendored
@ -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
|
||||
|
||||
|
46
3rdparty/taglib/dsdiff/dsdiffproperties.cpp
vendored
46
3rdparty/taglib/dsdiff/dsdiffproperties.cpp
vendored
@ -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;
|
||||
}
|
||||
|
||||
|
20
3rdparty/taglib/dsdiff/dsdiffproperties.h
vendored
20
3rdparty/taglib/dsdiff/dsdiffproperties.h
vendored
@ -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
|
||||
|
||||
|
81
3rdparty/taglib/dsf/dsffile.cpp
vendored
81
3rdparty/taglib/dsf/dsffile.cpp
vendored
@ -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);
|
||||
}
|
||||
|
||||
|
22
3rdparty/taglib/dsf/dsffile.h
vendored
22
3rdparty/taglib/dsf/dsffile.h
vendored
@ -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
|
||||
|
||||
|
79
3rdparty/taglib/dsf/dsfproperties.cpp
vendored
79
3rdparty/taglib/dsf/dsfproperties.cpp
vendored
@ -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;
|
||||
}
|
||||
|
||||
|
20
3rdparty/taglib/dsf/dsfproperties.h
vendored
20
3rdparty/taglib/dsf/dsfproperties.h
vendored
@ -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
|
||||
|
||||
|
258
3rdparty/taglib/fileref.cpp
vendored
258
3rdparty/taglib/fileref.cpp
vendored
@ -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.
|
||||
|
21
3rdparty/taglib/fileref.h
vendored
21
3rdparty/taglib/fileref.h
vendored
@ -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
|
||||
|
227
3rdparty/taglib/flac/flacfile.cpp
vendored
227
3rdparty/taglib/flac/flacfile.cpp
vendored
@ -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;
|
||||
}
|
||||
|
||||
|
36
3rdparty/taglib/flac/flacfile.h
vendored
36
3rdparty/taglib/flac/flacfile.h
vendored
@ -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
|
||||
|
13
3rdparty/taglib/flac/flacmetadatablock.cpp
vendored
13
3rdparty/taglib/flac/flacmetadatablock.cpp
vendored
@ -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() {
|
||||
}
|
||||
|
||||
|
13
3rdparty/taglib/flac/flacmetadatablock.h
vendored
13
3rdparty/taglib/flac/flacmetadatablock.h
vendored
@ -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
|
||||
|
89
3rdparty/taglib/flac/flacpicture.cpp
vendored
89
3rdparty/taglib/flac/flacpicture.cpp
vendored
@ -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;
|
||||
}
|
||||
|
||||
|
16
3rdparty/taglib/flac/flacpicture.h
vendored
16
3rdparty/taglib/flac/flacpicture.h
vendored
@ -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
|
||||
|
62
3rdparty/taglib/flac/flacproperties.cpp
vendored
62
3rdparty/taglib/flac/flacproperties.cpp
vendored
@ -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);
|
||||
}
|
||||
|
19
3rdparty/taglib/flac/flacproperties.h
vendored
19
3rdparty/taglib/flac/flacproperties.h
vendored
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
13
3rdparty/taglib/flac/flacunknownmetadatablock.h
vendored
13
3rdparty/taglib/flac/flacunknownmetadatablock.h
vendored
@ -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
|
||||
|
103
3rdparty/taglib/it/itfile.cpp
vendored
103
3rdparty/taglib/it/itfile.cpp
vendored
@ -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");
|
||||
|
12
3rdparty/taglib/it/itfile.h
vendored
12
3rdparty/taglib/it/itfile.h
vendored
@ -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
|
||||
|
128
3rdparty/taglib/it/itproperties.cpp
vendored
128
3rdparty/taglib/it/itproperties.cpp
vendored
@ -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;
|
||||
}
|
||||
|
33
3rdparty/taglib/it/itproperties.h
vendored
33
3rdparty/taglib/it/itproperties.h
vendored
@ -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
|
||||
|
69
3rdparty/taglib/mod/modfile.cpp
vendored
69
3rdparty/taglib/mod/modfile.cpp
vendored
@ -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:
|
||||
|
13
3rdparty/taglib/mod/modfile.h
vendored
13
3rdparty/taglib/mod/modfile.h
vendored
@ -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
|
||||
|
53
3rdparty/taglib/mod/modfilebase.cpp
vendored
53
3rdparty/taglib/mod/modfilebase.cpp
vendored
@ -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;
|
||||
}
|
||||
|
13
3rdparty/taglib/mod/modfilebase.h
vendored
13
3rdparty/taglib/mod/modfilebase.h
vendored
@ -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
|
||||
|
31
3rdparty/taglib/mod/modfileprivate.h
vendored
31
3rdparty/taglib/mod/modfileprivate.h
vendored
@ -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));
|
||||
|
||||
|
53
3rdparty/taglib/mod/modproperties.cpp
vendored
53
3rdparty/taglib/mod/modproperties.cpp
vendored
@ -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;
|
||||
}
|
||||
|
17
3rdparty/taglib/mod/modproperties.h
vendored
17
3rdparty/taglib/mod/modproperties.h
vendored
@ -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
|
||||
|
94
3rdparty/taglib/mod/modtag.cpp
vendored
94
3rdparty/taglib/mod/modtag.cpp
vendored
@ -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;
|
||||
}
|
||||
|
15
3rdparty/taglib/mod/modtag.h
vendored
15
3rdparty/taglib/mod/modtag.h
vendored
@ -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
|
||||
|
80
3rdparty/taglib/mp4/mp4atom.cpp
vendored
80
3rdparty/taglib/mp4/mp4atom.cpp
vendored
@ -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;
|
||||
|
48
3rdparty/taglib/mp4/mp4atom.h
vendored
48
3rdparty/taglib/mp4/mp4atom.h
vendored
@ -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
|
||||
|
34
3rdparty/taglib/mp4/mp4coverart.cpp
vendored
34
3rdparty/taglib/mp4/mp4coverart.cpp
vendored
@ -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;
|
||||
}
|
||||
|
15
3rdparty/taglib/mp4/mp4coverart.h
vendored
15
3rdparty/taglib/mp4/mp4coverart.h
vendored
@ -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
|
||||
|
86
3rdparty/taglib/mp4/mp4file.cpp
vendored
86
3rdparty/taglib/mp4/mp4file.cpp
vendored
@ -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);
|
||||
}
|
||||
|
19
3rdparty/taglib/mp4/mp4file.h
vendored
19
3rdparty/taglib/mp4/mp4file.h
vendored
@ -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
|
||||
|
103
3rdparty/taglib/mp4/mp4item.cpp
vendored
103
3rdparty/taglib/mp4/mp4item.cpp
vendored
@ -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;
|
||||
}
|
||||
|
13
3rdparty/taglib/mp4/mp4item.h
vendored
13
3rdparty/taglib/mp4/mp4item.h
vendored
@ -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
|
||||
|
94
3rdparty/taglib/mp4/mp4properties.cpp
vendored
94
3rdparty/taglib/mp4/mp4properties.cpp
vendored
@ -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;
|
||||
}
|
||||
}
|
||||
|
19
3rdparty/taglib/mp4/mp4properties.h
vendored
19
3rdparty/taglib/mp4/mp4properties.h
vendored
@ -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
|
||||
|
472
3rdparty/taglib/mp4/mp4tag.cpp
vendored
472
3rdparty/taglib/mp4/mp4tag.cpp
vendored
File diff suppressed because it is too large
Load Diff
21
3rdparty/taglib/mp4/mp4tag.h
vendored
21
3rdparty/taglib/mp4/mp4tag.h
vendored
@ -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
|
||||
|
130
3rdparty/taglib/mpc/mpcfile.cpp
vendored
130
3rdparty/taglib/mpc/mpcfile.cpp
vendored
@ -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);
|
||||
}
|
||||
|
31
3rdparty/taglib/mpc/mpcfile.h
vendored
31
3rdparty/taglib/mpc/mpcfile.h
vendored
@ -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
|
||||
|
139
3rdparty/taglib/mpc/mpcproperties.cpp
vendored
139
3rdparty/taglib/mpc/mpcproperties.cpp
vendored
@ -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);
|
||||
}
|
||||
}
|
||||
|
21
3rdparty/taglib/mpc/mpcproperties.h
vendored
21
3rdparty/taglib/mpc/mpcproperties.h
vendored
@ -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
|
||||
|
33
3rdparty/taglib/mpeg/id3v1/id3v1genres.cpp
vendored
33
3rdparty/taglib/mpeg/id3v1/id3v1genres.cpp
vendored
@ -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;
|
||||
}
|
||||
|
||||
|
26
3rdparty/taglib/mpeg/id3v1/id3v1genres.h
vendored
26
3rdparty/taglib/mpeg/id3v1/id3v1genres.h
vendored
@ -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
|
||||
|
114
3rdparty/taglib/mpeg/id3v1/id3v1tag.cpp
vendored
114
3rdparty/taglib/mpeg/id3v1/id3v1tag.cpp
vendored
@ -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));
|
||||
|
30
3rdparty/taglib/mpeg/id3v1/id3v1tag.h
vendored
30
3rdparty/taglib/mpeg/id3v1/id3v1tag.h
vendored
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
133
3rdparty/taglib/mpeg/id3v2/frames/chapterframe.cpp
vendored
133
3rdparty/taglib/mpeg/id3v2/frames/chapterframe.cpp
vendored
@ -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));
|
||||
}
|
||||
|
17
3rdparty/taglib/mpeg/id3v2/frames/chapterframe.h
vendored
17
3rdparty/taglib/mpeg/id3v2/frames/chapterframe.h
vendored
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
17
3rdparty/taglib/mpeg/id3v2/frames/podcastframe.h
vendored
17
3rdparty/taglib/mpeg/id3v2/frames/podcastframe.h
vendored
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
15
3rdparty/taglib/mpeg/id3v2/frames/privateframe.h
vendored
15
3rdparty/taglib/mpeg/id3v2/frames/privateframe.h
vendored
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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
Loading…
x
Reference in New Issue
Block a user