Format taglib sources
This commit is contained in:
parent
72bff7fa35
commit
4ce099294c
131
3rdparty/taglib/ape/apefile.cpp
vendored
131
3rdparty/taglib/ape/apefile.cpp
vendored
@ -46,25 +46,22 @@
|
|||||||
|
|
||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
namespace
|
namespace {
|
||||||
{
|
enum { ApeAPEIndex = 0,
|
||||||
enum { ApeAPEIndex = 0, ApeID3v1Index = 1 };
|
ApeID3v1Index = 1 };
|
||||||
}
|
}
|
||||||
|
|
||||||
class APE::File::FilePrivate
|
class APE::File::FilePrivate {
|
||||||
{
|
public:
|
||||||
public:
|
FilePrivate() : APELocation(-1),
|
||||||
FilePrivate() :
|
APESize(0),
|
||||||
APELocation(-1),
|
ID3v1Location(-1),
|
||||||
APESize(0),
|
ID3v2Header(0),
|
||||||
ID3v1Location(-1),
|
ID3v2Location(-1),
|
||||||
ID3v2Header(0),
|
ID3v2Size(0),
|
||||||
ID3v2Location(-1),
|
properties(0) {}
|
||||||
ID3v2Size(0),
|
|
||||||
properties(0) {}
|
|
||||||
|
|
||||||
~FilePrivate()
|
~FilePrivate() {
|
||||||
{
|
|
||||||
delete ID3v2Header;
|
delete ID3v2Header;
|
||||||
delete properties;
|
delete properties;
|
||||||
}
|
}
|
||||||
@ -87,8 +84,7 @@ public:
|
|||||||
// static members
|
// 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.
|
// An APE file has an ID "MAC " somewhere. An ID3v2 tag may precede.
|
||||||
|
|
||||||
// FIXME:
|
// FIXME:
|
||||||
@ -102,69 +98,58 @@ bool APE::File::isSupported(IOStream*)
|
|||||||
// public members
|
// public members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
APE::File::File(FileName file, bool readProperties, Properties::ReadStyle) :
|
APE::File::File(FileName file, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file),
|
||||||
Strawberry_TagLib::TagLib::File(file),
|
d(new FilePrivate()) {
|
||||||
d(new FilePrivate())
|
if (isOpen())
|
||||||
{
|
|
||||||
if(isOpen())
|
|
||||||
read(readProperties);
|
read(readProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
APE::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) :
|
APE::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(stream),
|
||||||
Strawberry_TagLib::TagLib::File(stream),
|
d(new FilePrivate()) {
|
||||||
d(new FilePrivate())
|
if (isOpen())
|
||||||
{
|
|
||||||
if(isOpen())
|
|
||||||
read(readProperties);
|
read(readProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
APE::File::~File()
|
APE::File::~File() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
Strawberry_TagLib::TagLib::Tag *APE::File::tag() const
|
Strawberry_TagLib::TagLib::Tag *APE::File::tag() const {
|
||||||
{
|
|
||||||
return &d->tag;
|
return &d->tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyMap APE::File::properties() const
|
PropertyMap APE::File::properties() const {
|
||||||
{
|
|
||||||
return d->tag.properties();
|
return d->tag.properties();
|
||||||
}
|
}
|
||||||
|
|
||||||
void APE::File::removeUnsupportedProperties(const StringList &properties)
|
void APE::File::removeUnsupportedProperties(const StringList &properties) {
|
||||||
{
|
|
||||||
d->tag.removeUnsupportedProperties(properties);
|
d->tag.removeUnsupportedProperties(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyMap APE::File::setProperties(const PropertyMap &properties)
|
PropertyMap APE::File::setProperties(const PropertyMap &properties) {
|
||||||
{
|
if (ID3v1Tag())
|
||||||
if(ID3v1Tag())
|
|
||||||
ID3v1Tag()->setProperties(properties);
|
ID3v1Tag()->setProperties(properties);
|
||||||
|
|
||||||
return APETag(true)->setProperties(properties);
|
return APETag(true)->setProperties(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
APE::Properties *APE::File::audioProperties() const
|
APE::Properties *APE::File::audioProperties() const {
|
||||||
{
|
|
||||||
return d->properties;
|
return d->properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool APE::File::save()
|
bool APE::File::save() {
|
||||||
{
|
if (readOnly()) {
|
||||||
if(readOnly()) {
|
|
||||||
debug("APE::File::save() -- File is read only.");
|
debug("APE::File::save() -- File is read only.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update ID3v1 tag
|
// 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.
|
// 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);
|
seek(d->ID3v1Location);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -178,7 +163,7 @@ bool APE::File::save()
|
|||||||
|
|
||||||
// ID3v1 tag is empty. Remove the old one.
|
// ID3v1 tag is empty. Remove the old one.
|
||||||
|
|
||||||
if(d->ID3v1Location >= 0) {
|
if (d->ID3v1Location >= 0) {
|
||||||
truncate(d->ID3v1Location);
|
truncate(d->ID3v1Location);
|
||||||
d->ID3v1Location = -1;
|
d->ID3v1Location = -1;
|
||||||
}
|
}
|
||||||
@ -186,12 +171,12 @@ bool APE::File::save()
|
|||||||
|
|
||||||
// Update APE tag
|
// 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.
|
// APE tag is not empty. Update the old one or create a new one.
|
||||||
|
|
||||||
if(d->APELocation < 0) {
|
if (d->APELocation < 0) {
|
||||||
if(d->ID3v1Location >= 0)
|
if (d->ID3v1Location >= 0)
|
||||||
d->APELocation = d->ID3v1Location;
|
d->APELocation = d->ID3v1Location;
|
||||||
else
|
else
|
||||||
d->APELocation = length();
|
d->APELocation = length();
|
||||||
@ -200,7 +185,7 @@ bool APE::File::save()
|
|||||||
const ByteVector data = APETag()->render();
|
const ByteVector data = APETag()->render();
|
||||||
insert(data, d->APELocation, d->APESize);
|
insert(data, d->APELocation, d->APESize);
|
||||||
|
|
||||||
if(d->ID3v1Location >= 0)
|
if (d->ID3v1Location >= 0)
|
||||||
d->ID3v1Location += (static_cast<long>(data.size()) - d->APESize);
|
d->ID3v1Location += (static_cast<long>(data.size()) - d->APESize);
|
||||||
|
|
||||||
d->APESize = data.size();
|
d->APESize = data.size();
|
||||||
@ -209,10 +194,10 @@ bool APE::File::save()
|
|||||||
|
|
||||||
// APE tag is empty. Remove the old one.
|
// APE tag is empty. Remove the old one.
|
||||||
|
|
||||||
if(d->APELocation >= 0) {
|
if (d->APELocation >= 0) {
|
||||||
removeBlock(d->APELocation, d->APESize);
|
removeBlock(d->APELocation, d->APESize);
|
||||||
|
|
||||||
if(d->ID3v1Location >= 0)
|
if (d->ID3v1Location >= 0)
|
||||||
d->ID3v1Location -= d->APESize;
|
d->ID3v1Location -= d->APESize;
|
||||||
|
|
||||||
d->APELocation = -1;
|
d->APELocation = -1;
|
||||||
@ -223,35 +208,30 @@ bool APE::File::save()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ID3v1::Tag *APE::File::ID3v1Tag(bool create)
|
ID3v1::Tag *APE::File::ID3v1Tag(bool create) {
|
||||||
{
|
|
||||||
return d->tag.access<ID3v1::Tag>(ApeID3v1Index, 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);
|
return d->tag.access<APE::Tag>(ApeAPEIndex, create);
|
||||||
}
|
}
|
||||||
|
|
||||||
void APE::File::strip(int tags)
|
void APE::File::strip(int tags) {
|
||||||
{
|
if (tags & ID3v1)
|
||||||
if(tags & ID3v1)
|
|
||||||
d->tag.set(ApeID3v1Index, 0);
|
d->tag.set(ApeID3v1Index, 0);
|
||||||
|
|
||||||
if(tags & APE)
|
if (tags & APE)
|
||||||
d->tag.set(ApeAPEIndex, 0);
|
d->tag.set(ApeAPEIndex, 0);
|
||||||
|
|
||||||
if(!ID3v1Tag())
|
if (!ID3v1Tag())
|
||||||
APETag(true);
|
APETag(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool APE::File::hasAPETag() const
|
bool APE::File::hasAPETag() const {
|
||||||
{
|
|
||||||
return (d->APELocation >= 0);
|
return (d->APELocation >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool APE::File::hasID3v1Tag() const
|
bool APE::File::hasID3v1Tag() const {
|
||||||
{
|
|
||||||
return (d->ID3v1Location >= 0);
|
return (d->ID3v1Location >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,13 +239,12 @@ bool APE::File::hasID3v1Tag() const
|
|||||||
// private members
|
// private members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void APE::File::read(bool readProperties)
|
void APE::File::read(bool readProperties) {
|
||||||
{
|
|
||||||
// Look for an ID3v2 tag
|
// Look for an ID3v2 tag
|
||||||
|
|
||||||
d->ID3v2Location = Utils::findID3v2(this);
|
d->ID3v2Location = Utils::findID3v2(this);
|
||||||
|
|
||||||
if(d->ID3v2Location >= 0) {
|
if (d->ID3v2Location >= 0) {
|
||||||
seek(d->ID3v2Location);
|
seek(d->ID3v2Location);
|
||||||
d->ID3v2Header = new ID3v2::Header(readBlock(ID3v2::Header::size()));
|
d->ID3v2Header = new ID3v2::Header(readBlock(ID3v2::Header::size()));
|
||||||
d->ID3v2Size = d->ID3v2Header->completeTagSize();
|
d->ID3v2Size = d->ID3v2Header->completeTagSize();
|
||||||
@ -275,36 +254,36 @@ void APE::File::read(bool readProperties)
|
|||||||
|
|
||||||
d->ID3v1Location = Utils::findID3v1(this);
|
d->ID3v1Location = Utils::findID3v1(this);
|
||||||
|
|
||||||
if(d->ID3v1Location >= 0)
|
if (d->ID3v1Location >= 0)
|
||||||
d->tag.set(ApeID3v1Index, new ID3v1::Tag(this, d->ID3v1Location));
|
d->tag.set(ApeID3v1Index, new ID3v1::Tag(this, d->ID3v1Location));
|
||||||
|
|
||||||
// Look for an APE tag
|
// Look for an APE tag
|
||||||
|
|
||||||
d->APELocation = Utils::findAPE(this, d->ID3v1Location);
|
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->tag.set(ApeAPEIndex, new APE::Tag(this, d->APELocation));
|
||||||
d->APESize = APETag()->footer()->completeTagSize();
|
d->APESize = APETag()->footer()->completeTagSize();
|
||||||
d->APELocation = d->APELocation + APE::Footer::size() - d->APESize;
|
d->APELocation = d->APELocation + APE::Footer::size() - d->APESize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(d->ID3v1Location < 0)
|
if (d->ID3v1Location < 0)
|
||||||
APETag(true);
|
APETag(true);
|
||||||
|
|
||||||
// Look for APE audio properties
|
// Look for APE audio properties
|
||||||
|
|
||||||
if(readProperties) {
|
if (readProperties) {
|
||||||
|
|
||||||
long streamLength;
|
long streamLength;
|
||||||
|
|
||||||
if(d->APELocation >= 0)
|
if (d->APELocation >= 0)
|
||||||
streamLength = d->APELocation;
|
streamLength = d->APELocation;
|
||||||
else if(d->ID3v1Location >= 0)
|
else if (d->ID3v1Location >= 0)
|
||||||
streamLength = d->ID3v1Location;
|
streamLength = d->ID3v1Location;
|
||||||
else
|
else
|
||||||
streamLength = length();
|
streamLength = length();
|
||||||
|
|
||||||
if(d->ID3v2Location >= 0) {
|
if (d->ID3v2Location >= 0) {
|
||||||
seek(d->ID3v2Location + d->ID3v2Size);
|
seek(d->ID3v2Location + d->ID3v2Size);
|
||||||
streamLength -= (d->ID3v2Location + d->ID3v2Size);
|
streamLength -= (d->ID3v2Location + d->ID3v2Size);
|
||||||
}
|
}
|
||||||
|
131
3rdparty/taglib/ape/apefile.h
vendored
131
3rdparty/taglib/ape/apefile.h
vendored
@ -41,59 +41,62 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
class Tag;
|
class Tag;
|
||||||
|
|
||||||
namespace ID3v1 { class Tag; }
|
namespace ID3v1 {
|
||||||
namespace APE { class Tag; }
|
class Tag;
|
||||||
|
}
|
||||||
|
namespace APE {
|
||||||
|
class Tag;
|
||||||
|
}
|
||||||
|
|
||||||
//! An implementation of APE metadata
|
//! An implementation of APE metadata
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* This is 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
|
* This supports ID3v1 and APE (v1 and v2) style comments as well as reading stream
|
||||||
* properties from the file.
|
* 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
|
* This implements and provides an interface for APE files to the
|
||||||
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
|
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
|
||||||
* the abstract TagLib::File API as well as providing some additional
|
* the abstract TagLib::File API as well as providing some additional
|
||||||
* information specific to APE files.
|
* information specific to APE files.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File
|
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File {
|
||||||
{
|
public:
|
||||||
public:
|
/*!
|
||||||
/*!
|
|
||||||
* This set of flags is used for various operations and is suitable for
|
* This set of flags is used for various operations and is suitable for
|
||||||
* being OR-ed together.
|
* being OR-ed together.
|
||||||
*/
|
*/
|
||||||
enum TagTypes {
|
enum TagTypes {
|
||||||
//! Empty set. Matches no tag types.
|
//! Empty set. Matches no tag types.
|
||||||
NoTags = 0x0000,
|
NoTags = 0x0000,
|
||||||
//! Matches ID3v1 tags.
|
//! Matches ID3v1 tags.
|
||||||
ID3v1 = 0x0001,
|
ID3v1 = 0x0001,
|
||||||
//! Matches APE tags.
|
//! Matches APE tags.
|
||||||
APE = 0x0002,
|
APE = 0x0002,
|
||||||
//! Matches all tag types.
|
//! Matches all tag types.
|
||||||
AllTags = 0xffff
|
AllTags = 0xffff
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs an APE file from \a file. If \a readProperties is true the
|
* Constructs an APE file from \a file. If \a readProperties is true the
|
||||||
* file's audio properties will also be read.
|
* file's audio properties will also be read.
|
||||||
*
|
*
|
||||||
* \note In the current implementation, \a propertiesStyle is ignored.
|
* \note In the current implementation, \a propertiesStyle is ignored.
|
||||||
*/
|
*/
|
||||||
File(FileName file, bool readProperties = true,
|
File(FileName file, bool readProperties = true,
|
||||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs an APE file from \a stream. If \a readProperties is true the
|
* Constructs an APE file from \a stream. If \a readProperties is true the
|
||||||
* file's audio properties will also be read.
|
* file's audio properties will also be read.
|
||||||
*
|
*
|
||||||
@ -102,55 +105,55 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \note In the current implementation, \a propertiesStyle is ignored.
|
* \note In the current implementation, \a propertiesStyle is ignored.
|
||||||
*/
|
*/
|
||||||
File(IOStream *stream, bool readProperties = true,
|
File(IOStream *stream, bool readProperties = true,
|
||||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys this instance of the File.
|
* Destroys this instance of the File.
|
||||||
*/
|
*/
|
||||||
virtual ~File();
|
virtual ~File();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the Tag for this file. This will be an APE tag, an ID3v1 tag
|
* Returns the Tag for this file. This will be an APE tag, an ID3v1 tag
|
||||||
* or a combination of the two.
|
* or a combination of the two.
|
||||||
*/
|
*/
|
||||||
virtual Strawberry_TagLib::TagLib::Tag *tag() const;
|
virtual Strawberry_TagLib::TagLib::Tag *tag() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Implements the unified property interface -- export function.
|
* Implements the unified property interface -- export function.
|
||||||
* If the file contains both an APE and an ID3v1 tag, only APE
|
* If the file contains both an APE and an ID3v1 tag, only APE
|
||||||
* will be converted to the PropertyMap.
|
* will be converted to the PropertyMap.
|
||||||
*/
|
*/
|
||||||
PropertyMap properties() const;
|
PropertyMap properties() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Removes unsupported properties. Forwards to the actual Tag's
|
* Removes unsupported properties. Forwards to the actual Tag's
|
||||||
* removeUnsupportedProperties() function.
|
* removeUnsupportedProperties() function.
|
||||||
*/
|
*/
|
||||||
void removeUnsupportedProperties(const StringList &properties);
|
void removeUnsupportedProperties(const StringList &properties);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Implements the unified property interface -- import function.
|
* Implements the unified property interface -- import function.
|
||||||
* Creates an APEv2 tag if necessary. A potentially existing ID3v1
|
* Creates an APEv2 tag if necessary. A potentially existing ID3v1
|
||||||
* tag will be updated as well.
|
* tag will be updated as well.
|
||||||
*/
|
*/
|
||||||
PropertyMap setProperties(const PropertyMap &);
|
PropertyMap setProperties(const PropertyMap &);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the APE::Properties for this file. If no audio properties
|
* Returns the APE::Properties for this file. If no audio properties
|
||||||
* were read then this will return a null pointer.
|
* were read then this will return a null pointer.
|
||||||
*/
|
*/
|
||||||
virtual Properties *audioProperties() const;
|
virtual Properties *audioProperties() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Saves the file.
|
* Saves the file.
|
||||||
*
|
*
|
||||||
* \note According to the official Monkey's Audio SDK, an APE file
|
* \note According to the official Monkey's Audio SDK, an APE file
|
||||||
* can only have either ID3V1 or APE tags, so a parameter is used here.
|
* can only have either ID3V1 or APE tags, so a parameter is used here.
|
||||||
*/
|
*/
|
||||||
virtual bool save();
|
virtual bool save();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns a pointer to the ID3v1 tag of the file.
|
* Returns a pointer to the ID3v1 tag of the file.
|
||||||
*
|
*
|
||||||
* If \a create is false (the default) this may return a null pointer
|
* If \a create is false (the default) this may return a null pointer
|
||||||
@ -167,9 +170,9 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \see hasID3v1Tag()
|
* \see hasID3v1Tag()
|
||||||
*/
|
*/
|
||||||
ID3v1::Tag *ID3v1Tag(bool create = false);
|
ID3v1::Tag *ID3v1Tag(bool create = false);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns a pointer to the APE tag of the file.
|
* Returns a pointer to the APE tag of the file.
|
||||||
*
|
*
|
||||||
* If \a create is false (the default) this may return a null pointer
|
* If \a create is false (the default) this may return a null pointer
|
||||||
@ -186,9 +189,9 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \see hasAPETag()
|
* \see hasAPETag()
|
||||||
*/
|
*/
|
||||||
APE::Tag *APETag(bool create = false);
|
APE::Tag *APETag(bool create = false);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* This will remove the tags that match the OR-ed together TagTypes from the
|
* This will remove the tags that match the OR-ed together TagTypes from the
|
||||||
* file. By default it removes all tags.
|
* file. By default it removes all tags.
|
||||||
*
|
*
|
||||||
@ -196,42 +199,42 @@ namespace TagLib {
|
|||||||
* as their memory will be freed.
|
* as their memory will be freed.
|
||||||
* \note In order to make the removal permanent save() still needs to be called
|
* \note In order to make the removal permanent save() still needs to be called
|
||||||
*/
|
*/
|
||||||
void strip(int tags = AllTags);
|
void strip(int tags = AllTags);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns whether or not the file on disk actually has an APE tag.
|
* Returns whether or not the file on disk actually has an APE tag.
|
||||||
*
|
*
|
||||||
* \see APETag()
|
* \see APETag()
|
||||||
*/
|
*/
|
||||||
bool hasAPETag() const;
|
bool hasAPETag() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns whether or not the file on disk actually has an ID3v1 tag.
|
* Returns whether or not the file on disk actually has an ID3v1 tag.
|
||||||
*
|
*
|
||||||
* \see ID3v1Tag()
|
* \see ID3v1Tag()
|
||||||
*/
|
*/
|
||||||
bool hasID3v1Tag() const;
|
bool hasID3v1Tag() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns whether or not the given \a stream can be opened as an APE
|
* Returns whether or not the given \a stream can be opened as an APE
|
||||||
* file.
|
* file.
|
||||||
*
|
*
|
||||||
* \note This method is designed to do a quick check. The result may
|
* \note This method is designed to do a quick check. The result may
|
||||||
* not necessarily be correct.
|
* not necessarily be correct.
|
||||||
*/
|
*/
|
||||||
static bool isSupported(IOStream *stream);
|
static bool isSupported(IOStream *stream);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
File(const File &);
|
File(const File &);
|
||||||
File &operator=(const File &);
|
File &operator=(const File &);
|
||||||
|
|
||||||
void read(bool readProperties);
|
void read(bool readProperties);
|
||||||
|
|
||||||
class FilePrivate;
|
class FilePrivate;
|
||||||
FilePrivate *d;
|
FilePrivate *d;
|
||||||
};
|
};
|
||||||
}
|
} // namespace APE
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
89
3rdparty/taglib/ape/apefooter.cpp
vendored
89
3rdparty/taglib/ape/apefooter.cpp
vendored
@ -35,16 +35,14 @@
|
|||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
using namespace APE;
|
using namespace APE;
|
||||||
|
|
||||||
class APE::Footer::FooterPrivate
|
class APE::Footer::FooterPrivate {
|
||||||
{
|
public:
|
||||||
public:
|
FooterPrivate() : version(0),
|
||||||
FooterPrivate() :
|
footerPresent(true),
|
||||||
version(0),
|
headerPresent(false),
|
||||||
footerPresent(true),
|
isHeader(false),
|
||||||
headerPresent(false),
|
itemCount(0),
|
||||||
isHeader(false),
|
tagSize(0) {}
|
||||||
itemCount(0),
|
|
||||||
tagSize(0) {}
|
|
||||||
|
|
||||||
unsigned int version;
|
unsigned int version;
|
||||||
|
|
||||||
@ -61,13 +59,11 @@ public:
|
|||||||
// static members
|
// static members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
unsigned int APE::Footer::size()
|
unsigned int APE::Footer::size() {
|
||||||
{
|
|
||||||
return 32;
|
return 32;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector APE::Footer::fileIdentifier()
|
ByteVector APE::Footer::fileIdentifier() {
|
||||||
{
|
|
||||||
return ByteVector("APETAGEX");
|
return ByteVector("APETAGEX");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,88 +71,70 @@ ByteVector APE::Footer::fileIdentifier()
|
|||||||
// public members
|
// public members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
APE::Footer::Footer() :
|
APE::Footer::Footer() : d(new FooterPrivate()) {
|
||||||
d(new FooterPrivate())
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
APE::Footer::Footer(const ByteVector &data) :
|
APE::Footer::Footer(const ByteVector &data) : d(new FooterPrivate()) {
|
||||||
d(new FooterPrivate())
|
|
||||||
{
|
|
||||||
parse(data);
|
parse(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
APE::Footer::~Footer()
|
APE::Footer::~Footer() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int APE::Footer::version() const
|
unsigned int APE::Footer::version() const {
|
||||||
{
|
|
||||||
return d->version;
|
return d->version;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool APE::Footer::headerPresent() const
|
bool APE::Footer::headerPresent() const {
|
||||||
{
|
|
||||||
return d->headerPresent;
|
return d->headerPresent;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool APE::Footer::footerPresent() const
|
bool APE::Footer::footerPresent() const {
|
||||||
{
|
|
||||||
return d->footerPresent;
|
return d->footerPresent;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool APE::Footer::isHeader() const
|
bool APE::Footer::isHeader() const {
|
||||||
{
|
|
||||||
return d->isHeader;
|
return d->isHeader;
|
||||||
}
|
}
|
||||||
|
|
||||||
void APE::Footer::setHeaderPresent(bool b) const
|
void APE::Footer::setHeaderPresent(bool b) const {
|
||||||
{
|
|
||||||
d->headerPresent = b;
|
d->headerPresent = b;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int APE::Footer::itemCount() const
|
unsigned int APE::Footer::itemCount() const {
|
||||||
{
|
|
||||||
return d->itemCount;
|
return d->itemCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void APE::Footer::setItemCount(unsigned int s)
|
void APE::Footer::setItemCount(unsigned int s) {
|
||||||
{
|
|
||||||
d->itemCount = s;
|
d->itemCount = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int APE::Footer::tagSize() const
|
unsigned int APE::Footer::tagSize() const {
|
||||||
{
|
|
||||||
return d->tagSize;
|
return d->tagSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int APE::Footer::completeTagSize() const
|
unsigned int APE::Footer::completeTagSize() const {
|
||||||
{
|
if (d->headerPresent)
|
||||||
if(d->headerPresent)
|
|
||||||
return d->tagSize + size();
|
return d->tagSize + size();
|
||||||
else
|
else
|
||||||
return d->tagSize;
|
return d->tagSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void APE::Footer::setTagSize(unsigned int s)
|
void APE::Footer::setTagSize(unsigned int s) {
|
||||||
{
|
|
||||||
d->tagSize = s;
|
d->tagSize = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void APE::Footer::setData(const ByteVector &data)
|
void APE::Footer::setData(const ByteVector &data) {
|
||||||
{
|
|
||||||
parse(data);
|
parse(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector APE::Footer::renderFooter() const
|
ByteVector APE::Footer::renderFooter() const {
|
||||||
{
|
|
||||||
return render(false);
|
return render(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector APE::Footer::renderHeader() const
|
ByteVector APE::Footer::renderHeader() const {
|
||||||
{
|
if (!d->headerPresent)
|
||||||
if(!d->headerPresent)
|
|
||||||
return ByteVector();
|
return ByteVector();
|
||||||
else
|
else
|
||||||
return render(true);
|
return render(true);
|
||||||
@ -166,9 +144,8 @@ ByteVector APE::Footer::renderHeader() const
|
|||||||
// protected members
|
// protected members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void APE::Footer::parse(const ByteVector &data)
|
void APE::Footer::parse(const ByteVector &data) {
|
||||||
{
|
if (data.size() < size())
|
||||||
if(data.size() < size())
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// The first eight bytes, data[0..7], are the File Identifier, "APETAGEX".
|
// 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->headerPresent = flags[31];
|
||||||
d->footerPresent = !flags[30];
|
d->footerPresent = !flags[30];
|
||||||
d->isHeader = flags[29];
|
d->isHeader = flags[29];
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector APE::Footer::render(bool isHeader) const
|
ByteVector APE::Footer::render(bool isHeader) const {
|
||||||
{
|
|
||||||
ByteVector v;
|
ByteVector v;
|
||||||
|
|
||||||
// add the file identifier -- "APETAGEX"
|
// add the file identifier -- "APETAGEX"
|
||||||
@ -221,7 +196,7 @@ ByteVector APE::Footer::render(bool isHeader) const
|
|||||||
std::bitset<32> flags;
|
std::bitset<32> flags;
|
||||||
|
|
||||||
flags[31] = d->headerPresent;
|
flags[31] = d->headerPresent;
|
||||||
flags[30] = false; // footer is always present
|
flags[30] = false; // footer is always present
|
||||||
flags[29] = isHeader;
|
flags[29] = isHeader;
|
||||||
|
|
||||||
v.append(ByteVector::fromUInt(flags.to_ulong(), false));
|
v.append(ByteVector::fromUInt(flags.to_ulong(), false));
|
||||||
|
111
3rdparty/taglib/ape/apefooter.h
vendored
111
3rdparty/taglib/ape/apefooter.h
vendored
@ -32,144 +32,143 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace 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
|
* This class implements APE footers (and headers). It attempts to follow, both
|
||||||
* semantically and programmatically, the structure specified in
|
* semantically and programmatically, the structure specified in
|
||||||
* the APE v2.0 standard. The API is based on the properties of APE footer and
|
* the APE v2.0 standard. The API is based on the properties of APE footer and
|
||||||
* headers specified there.
|
* headers specified there.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class TAGLIB_EXPORT Footer
|
class TAGLIB_EXPORT Footer {
|
||||||
{
|
public:
|
||||||
public:
|
/*!
|
||||||
/*!
|
|
||||||
* Constructs an empty APE footer.
|
* Constructs an empty APE footer.
|
||||||
*/
|
*/
|
||||||
Footer();
|
Footer();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs an APE footer based on \a data. parse() is called
|
* Constructs an APE footer based on \a data. parse() is called
|
||||||
* immediately.
|
* immediately.
|
||||||
*/
|
*/
|
||||||
Footer(const ByteVector &data);
|
Footer(const ByteVector &data);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys the footer.
|
* Destroys the footer.
|
||||||
*/
|
*/
|
||||||
virtual ~Footer();
|
virtual ~Footer();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the version number. (Note: This is the 1000 or 2000.)
|
* Returns the version number. (Note: This is the 1000 or 2000.)
|
||||||
*/
|
*/
|
||||||
unsigned int version() const;
|
unsigned int version() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns true if a header is present in the tag.
|
* Returns true if a header is present in the tag.
|
||||||
*/
|
*/
|
||||||
bool headerPresent() const;
|
bool headerPresent() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns true if a footer is present in the tag.
|
* Returns true if a footer is present in the tag.
|
||||||
*/
|
*/
|
||||||
bool footerPresent() const;
|
bool footerPresent() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns true this is actually the header.
|
* Returns true this is actually the header.
|
||||||
*/
|
*/
|
||||||
bool isHeader() const;
|
bool isHeader() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets whether the header should be rendered or not
|
* Sets whether the header should be rendered or not
|
||||||
*/
|
*/
|
||||||
void setHeaderPresent(bool b) const;
|
void setHeaderPresent(bool b) const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the number of items in the tag.
|
* Returns the number of items in the tag.
|
||||||
*/
|
*/
|
||||||
unsigned int itemCount() const;
|
unsigned int itemCount() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Set the item count to \a s.
|
* Set the item count to \a s.
|
||||||
* \see itemCount()
|
* \see itemCount()
|
||||||
*/
|
*/
|
||||||
void setItemCount(unsigned int s);
|
void setItemCount(unsigned int s);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the tag size in bytes. This is the size of the frame content and footer.
|
* Returns the tag size in bytes. This is the size of the frame content and footer.
|
||||||
* The size of the \e entire tag will be this plus the header size, if present.
|
* The size of the \e entire tag will be this plus the header size, if present.
|
||||||
*
|
*
|
||||||
* \see completeTagSize()
|
* \see completeTagSize()
|
||||||
*/
|
*/
|
||||||
unsigned int tagSize() const;
|
unsigned int tagSize() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the tag size, including if present, the header
|
* Returns the tag size, including if present, the header
|
||||||
* size.
|
* size.
|
||||||
*
|
*
|
||||||
* \see tagSize()
|
* \see tagSize()
|
||||||
*/
|
*/
|
||||||
unsigned int completeTagSize() const;
|
unsigned int completeTagSize() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Set the tag size to \a s.
|
* Set the tag size to \a s.
|
||||||
* \see tagSize()
|
* \see tagSize()
|
||||||
*/
|
*/
|
||||||
void setTagSize(unsigned int s);
|
void setTagSize(unsigned int s);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the size of the footer. Presently this is always 32 bytes.
|
* Returns the size of the footer. Presently this is always 32 bytes.
|
||||||
*/
|
*/
|
||||||
static unsigned int size();
|
static unsigned int size();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the string used to identify an APE tag inside of a file.
|
* Returns the string used to identify an APE tag inside of a file.
|
||||||
* Presently this is always "APETAGEX".
|
* Presently this is always "APETAGEX".
|
||||||
*/
|
*/
|
||||||
static ByteVector fileIdentifier();
|
static ByteVector fileIdentifier();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the data that will be used as the footer. 32 bytes,
|
* Sets the data that will be used as the footer. 32 bytes,
|
||||||
* starting from \a data will be used.
|
* starting from \a data will be used.
|
||||||
*/
|
*/
|
||||||
void setData(const ByteVector &data);
|
void setData(const ByteVector &data);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Renders the footer back to binary format.
|
* Renders the footer back to binary format.
|
||||||
*/
|
*/
|
||||||
ByteVector renderFooter() const;
|
ByteVector renderFooter() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Renders the header corresponding to the footer. If headerPresent is
|
* Renders the header corresponding to the footer. If headerPresent is
|
||||||
* set to false, it returns an empty ByteVector.
|
* set to false, it returns an empty ByteVector.
|
||||||
*/
|
*/
|
||||||
ByteVector renderHeader() const;
|
ByteVector renderHeader() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/*!
|
/*!
|
||||||
* Called by setData() to parse the footer data. It makes this information
|
* Called by setData() to parse the footer data. It makes this information
|
||||||
* available through the public API.
|
* available through the public API.
|
||||||
*/
|
*/
|
||||||
void parse(const ByteVector &data);
|
void parse(const ByteVector &data);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Called by renderFooter and renderHeader
|
* Called by renderFooter and renderHeader
|
||||||
*/
|
*/
|
||||||
ByteVector render(bool isHeader) const;
|
ByteVector render(bool isHeader) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Footer(const Footer &);
|
Footer(const Footer &);
|
||||||
Footer &operator=(const Footer &);
|
Footer &operator=(const Footer &);
|
||||||
|
|
||||||
class FooterPrivate;
|
class FooterPrivate;
|
||||||
FooterPrivate *d;
|
FooterPrivate *d;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace APE
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
129
3rdparty/taglib/ape/apeitem.cpp
vendored
129
3rdparty/taglib/ape/apeitem.cpp
vendored
@ -31,12 +31,10 @@
|
|||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
using namespace APE;
|
using namespace APE;
|
||||||
|
|
||||||
class APE::Item::ItemPrivate
|
class APE::Item::ItemPrivate {
|
||||||
{
|
public:
|
||||||
public:
|
ItemPrivate() : type(Text),
|
||||||
ItemPrivate() :
|
readOnly(false) {}
|
||||||
type(Text),
|
|
||||||
readOnly(false) {}
|
|
||||||
|
|
||||||
Item::ItemTypes type;
|
Item::ItemTypes type;
|
||||||
String key;
|
String key;
|
||||||
@ -49,30 +47,22 @@ public:
|
|||||||
// public members
|
// public members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
APE::Item::Item() :
|
APE::Item::Item() : d(new ItemPrivate()) {
|
||||||
d(new ItemPrivate())
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
APE::Item::Item(const String &key, const String &value) :
|
APE::Item::Item(const String &key, const String &value) : d(new ItemPrivate()) {
|
||||||
d(new ItemPrivate())
|
|
||||||
{
|
|
||||||
d->key = key;
|
d->key = key;
|
||||||
d->text.append(value);
|
d->text.append(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
APE::Item::Item(const String &key, const StringList &values) :
|
APE::Item::Item(const String &key, const StringList &values) : d(new ItemPrivate()) {
|
||||||
d(new ItemPrivate())
|
|
||||||
{
|
|
||||||
d->key = key;
|
d->key = key;
|
||||||
d->text = values;
|
d->text = values;
|
||||||
}
|
}
|
||||||
|
|
||||||
APE::Item::Item(const String &key, const ByteVector &value, bool binary) :
|
APE::Item::Item(const String &key, const ByteVector &value, bool binary) : d(new ItemPrivate()) {
|
||||||
d(new ItemPrivate())
|
|
||||||
{
|
|
||||||
d->key = key;
|
d->key = key;
|
||||||
if(binary) {
|
if (binary) {
|
||||||
d->type = Binary;
|
d->type = Binary;
|
||||||
d->value = value;
|
d->value = value;
|
||||||
}
|
}
|
||||||
@ -81,118 +71,99 @@ APE::Item::Item(const String &key, const ByteVector &value, bool binary) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
APE::Item::Item(const Item &item) :
|
APE::Item::Item(const Item &item) : d(new ItemPrivate(*item.d)) {
|
||||||
d(new ItemPrivate(*item.d))
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
APE::Item::~Item()
|
APE::Item::~Item() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
Item &APE::Item::operator=(const Item &item)
|
Item &APE::Item::operator=(const Item &item) {
|
||||||
{
|
|
||||||
Item(item).swap(*this);
|
Item(item).swap(*this);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void APE::Item::swap(Item &item)
|
void APE::Item::swap(Item &item) {
|
||||||
{
|
|
||||||
using std::swap;
|
using std::swap;
|
||||||
|
|
||||||
swap(d, item.d);
|
swap(d, item.d);
|
||||||
}
|
}
|
||||||
|
|
||||||
void APE::Item::setReadOnly(bool readOnly)
|
void APE::Item::setReadOnly(bool readOnly) {
|
||||||
{
|
|
||||||
d->readOnly = readOnly;
|
d->readOnly = readOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool APE::Item::isReadOnly() const
|
bool APE::Item::isReadOnly() const {
|
||||||
{
|
|
||||||
return d->readOnly;
|
return d->readOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
void APE::Item::setType(APE::Item::ItemTypes val)
|
void APE::Item::setType(APE::Item::ItemTypes val) {
|
||||||
{
|
|
||||||
d->type = val;
|
d->type = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
APE::Item::ItemTypes APE::Item::type() const
|
APE::Item::ItemTypes APE::Item::type() const {
|
||||||
{
|
|
||||||
return d->type;
|
return d->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
String APE::Item::key() const
|
String APE::Item::key() const {
|
||||||
{
|
|
||||||
return d->key;
|
return d->key;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector APE::Item::binaryData() const
|
ByteVector APE::Item::binaryData() const {
|
||||||
{
|
|
||||||
return d->value;
|
return d->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void APE::Item::setBinaryData(const ByteVector &value)
|
void APE::Item::setBinaryData(const ByteVector &value) {
|
||||||
{
|
|
||||||
d->type = Binary;
|
d->type = Binary;
|
||||||
d->value = value;
|
d->value = value;
|
||||||
d->text.clear();
|
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
|
// This seems incorrect as it won't be actually rendering the value to keep it
|
||||||
// up to date.
|
// up to date.
|
||||||
|
|
||||||
return d->value;
|
return d->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void APE::Item::setKey(const String &key)
|
void APE::Item::setKey(const String &key) {
|
||||||
{
|
|
||||||
d->key = key;
|
d->key = key;
|
||||||
}
|
}
|
||||||
|
|
||||||
void APE::Item::setValue(const String &value)
|
void APE::Item::setValue(const String &value) {
|
||||||
{
|
|
||||||
d->type = Text;
|
d->type = Text;
|
||||||
d->text = value;
|
d->text = value;
|
||||||
d->value.clear();
|
d->value.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void APE::Item::setValues(const StringList &value)
|
void APE::Item::setValues(const StringList &value) {
|
||||||
{
|
|
||||||
d->type = Text;
|
d->type = Text;
|
||||||
d->text = value;
|
d->text = value;
|
||||||
d->value.clear();
|
d->value.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void APE::Item::appendValue(const String &value)
|
void APE::Item::appendValue(const String &value) {
|
||||||
{
|
|
||||||
d->type = Text;
|
d->type = Text;
|
||||||
d->text.append(value);
|
d->text.append(value);
|
||||||
d->value.clear();
|
d->value.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void APE::Item::appendValues(const StringList &values)
|
void APE::Item::appendValues(const StringList &values) {
|
||||||
{
|
|
||||||
d->type = Text;
|
d->type = Text;
|
||||||
d->text.append(values);
|
d->text.append(values);
|
||||||
d->value.clear();
|
d->value.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
int APE::Item::size() const
|
int APE::Item::size() const {
|
||||||
{
|
|
||||||
int result = 8 + d->key.size() + 1;
|
int result = 8 + d->key.size() + 1;
|
||||||
switch(d->type) {
|
switch (d->type) {
|
||||||
case Text:
|
case Text:
|
||||||
if(!d->text.isEmpty()) {
|
if (!d->text.isEmpty()) {
|
||||||
StringList::ConstIterator it = d->text.begin();
|
StringList::ConstIterator it = d->text.begin();
|
||||||
|
|
||||||
result += it->data(String::UTF8).size();
|
result += it->data(String::UTF8).size();
|
||||||
it++;
|
it++;
|
||||||
for(; it != d->text.end(); ++it)
|
for (; it != d->text.end(); ++it)
|
||||||
result += 1 + it->data(String::UTF8).size();
|
result += 1 + it->data(String::UTF8).size();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -205,31 +176,27 @@ int APE::Item::size() const
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringList APE::Item::toStringList() const
|
StringList APE::Item::toStringList() const {
|
||||||
{
|
|
||||||
return d->text;
|
return d->text;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringList APE::Item::values() const
|
StringList APE::Item::values() const {
|
||||||
{
|
|
||||||
return d->text;
|
return d->text;
|
||||||
}
|
}
|
||||||
|
|
||||||
String APE::Item::toString() const
|
String APE::Item::toString() const {
|
||||||
{
|
if (d->type == Text && !isEmpty())
|
||||||
if(d->type == Text && !isEmpty())
|
|
||||||
return d->text.front();
|
return d->text.front();
|
||||||
else
|
else
|
||||||
return String();
|
return String();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool APE::Item::isEmpty() const
|
bool APE::Item::isEmpty() const {
|
||||||
{
|
switch (d->type) {
|
||||||
switch(d->type) {
|
|
||||||
case Text:
|
case Text:
|
||||||
if(d->text.isEmpty())
|
if (d->text.isEmpty())
|
||||||
return true;
|
return true;
|
||||||
if(d->text.size() == 1 && d->text.front().isEmpty())
|
if (d->text.size() == 1 && d->text.front().isEmpty())
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
case Binary:
|
case Binary:
|
||||||
@ -240,17 +207,16 @@ 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
|
// 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");
|
debug("APE::Item::parse() -- no data in item");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsigned int valueLength = data.toUInt(0, false);
|
const unsigned int valueLength = data.toUInt(0, false);
|
||||||
const unsigned int flags = data.toUInt(4, false);
|
const unsigned int flags = data.toUInt(4, false);
|
||||||
|
|
||||||
// An item key can contain ASCII characters from 0x20 up to 0x7E, not UTF-8.
|
// An item key can contain ASCII characters from 0x20 up to 0x7E, not UTF-8.
|
||||||
// We assume that the validity of the given key has been checked.
|
// We assume that the validity of the given key has been checked.
|
||||||
@ -262,27 +228,26 @@ void APE::Item::parse(const ByteVector &data)
|
|||||||
setReadOnly(flags & 1);
|
setReadOnly(flags & 1);
|
||||||
setType(ItemTypes((flags >> 1) & 3));
|
setType(ItemTypes((flags >> 1) & 3));
|
||||||
|
|
||||||
if(Text == d->type)
|
if (Text == d->type)
|
||||||
d->text = StringList(ByteVectorList::split(value, '\0'), String::UTF8);
|
d->text = StringList(ByteVectorList::split(value, '\0'), String::UTF8);
|
||||||
else
|
else
|
||||||
d->value = value;
|
d->value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector APE::Item::render() const
|
ByteVector APE::Item::render() const {
|
||||||
{
|
|
||||||
ByteVector data;
|
ByteVector data;
|
||||||
unsigned int flags = ((d->readOnly) ? 1 : 0) | (d->type << 1);
|
unsigned int flags = ((d->readOnly) ? 1 : 0) | (d->type << 1);
|
||||||
ByteVector value;
|
ByteVector value;
|
||||||
|
|
||||||
if(isEmpty())
|
if (isEmpty())
|
||||||
return data;
|
return data;
|
||||||
|
|
||||||
if(d->type == Text) {
|
if (d->type == Text) {
|
||||||
StringList::ConstIterator it = d->text.begin();
|
StringList::ConstIterator it = d->text.begin();
|
||||||
|
|
||||||
value.append(it->data(String::UTF8));
|
value.append(it->data(String::UTF8));
|
||||||
it++;
|
it++;
|
||||||
for(; it != d->text.end(); ++it) {
|
for (; it != d->text.end(); ++it) {
|
||||||
value.append('\0');
|
value.append('\0');
|
||||||
value.append(it->data(String::UTF8));
|
value.append(it->data(String::UTF8));
|
||||||
}
|
}
|
||||||
|
159
3rdparty/taglib/ape/apeitem.h
vendored
159
3rdparty/taglib/ape/apeitem.h
vendored
@ -33,194 +33,191 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace 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.
|
* This class provides the features of items in the APEv2 standard.
|
||||||
*/
|
*/
|
||||||
class TAGLIB_EXPORT Item
|
class TAGLIB_EXPORT Item {
|
||||||
{
|
public:
|
||||||
public:
|
/*!
|
||||||
/*!
|
|
||||||
* Enum of types an Item can have. The value of 3 is reserved.
|
* Enum of types an Item can have. The value of 3 is reserved.
|
||||||
*/
|
*/
|
||||||
enum ItemTypes {
|
enum ItemTypes {
|
||||||
//! Item contains text information coded in UTF-8
|
//! Item contains text information coded in UTF-8
|
||||||
Text = 0,
|
Text = 0,
|
||||||
//! Item contains binary information
|
//! Item contains binary information
|
||||||
Binary = 1,
|
Binary = 1,
|
||||||
//! Item is a locator of external stored information
|
//! Item is a locator of external stored information
|
||||||
Locator = 2
|
Locator = 2
|
||||||
};
|
};
|
||||||
/*!
|
/*!
|
||||||
* Constructs an empty item.
|
* Constructs an empty item.
|
||||||
*/
|
*/
|
||||||
Item();
|
Item();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs a text item with \a key and \a value.
|
* Constructs a text item with \a key and \a value.
|
||||||
*/
|
*/
|
||||||
// BIC: Remove this, StringList has a constructor from a single string
|
// BIC: Remove this, StringList has a constructor from a single string
|
||||||
Item(const String &key, const String &value);
|
Item(const String &key, const String &value);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs a text item with \a key and \a values.
|
* Constructs a text item with \a key and \a values.
|
||||||
*/
|
*/
|
||||||
Item(const String &key, const StringList &values);
|
Item(const String &key, const StringList &values);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs an item with \a key and \a value.
|
* Constructs an item with \a key and \a value.
|
||||||
* If \a binary is true a Binary item will be created, otherwise \a value will be interpreted as text
|
* If \a binary is true a Binary item will be created, otherwise \a value will be interpreted as text
|
||||||
*/
|
*/
|
||||||
Item(const String &key, const ByteVector &value, bool binary);
|
Item(const String &key, const ByteVector &value, bool binary);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Construct an item as a copy of \a item.
|
* Construct an item as a copy of \a item.
|
||||||
*/
|
*/
|
||||||
Item(const Item &item);
|
Item(const Item &item);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys the item.
|
* Destroys the item.
|
||||||
*/
|
*/
|
||||||
virtual ~Item();
|
virtual ~Item();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Copies the contents of \a item into this item.
|
* Copies the contents of \a item into this item.
|
||||||
*/
|
*/
|
||||||
Item &operator=(const Item &item);
|
Item &operator=(const Item &item);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Exchanges the content of this item by the content of \a item.
|
* Exchanges the content of this item by the content of \a item.
|
||||||
*/
|
*/
|
||||||
void swap(Item &item);
|
void swap(Item &item);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the key.
|
* Returns the key.
|
||||||
*/
|
*/
|
||||||
String key() const;
|
String key() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the binary value.
|
* Returns the binary value.
|
||||||
* If the item type is not \a Binary, always returns an empty ByteVector.
|
* If the item type is not \a Binary, always returns an empty ByteVector.
|
||||||
*/
|
*/
|
||||||
ByteVector binaryData() const;
|
ByteVector binaryData() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Set the binary value to \a value
|
* Set the binary value to \a value
|
||||||
* The item's type will also be set to \a Binary
|
* The item's type will also be set to \a Binary
|
||||||
*/
|
*/
|
||||||
void setBinaryData(const ByteVector &value);
|
void setBinaryData(const ByteVector &value);
|
||||||
|
|
||||||
#ifndef DO_NOT_DOCUMENT
|
#ifndef DO_NOT_DOCUMENT
|
||||||
/* Remove in next binary incompatible release */
|
/* Remove in next binary incompatible release */
|
||||||
ByteVector value() const;
|
ByteVector value() const;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the key for the item to \a key.
|
* Sets the key for the item to \a key.
|
||||||
*/
|
*/
|
||||||
void setKey(const String &key);
|
void setKey(const String &key);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the text value of the item to \a value and clears any previous contents.
|
* Sets the text value of the item to \a value and clears any previous contents.
|
||||||
*
|
*
|
||||||
* \see toString()
|
* \see toString()
|
||||||
*/
|
*/
|
||||||
void setValue(const String &value);
|
void setValue(const String &value);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the text value of the item to the list of values in \a value and clears
|
* Sets the text value of the item to the list of values in \a value and clears
|
||||||
* any previous contents.
|
* any previous contents.
|
||||||
*
|
*
|
||||||
* \see toStringList()
|
* \see toStringList()
|
||||||
*/
|
*/
|
||||||
void setValues(const StringList &values);
|
void setValues(const StringList &values);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Appends \a value to create (or extend) the current list of text values.
|
* Appends \a value to create (or extend) the current list of text values.
|
||||||
*
|
*
|
||||||
* \see toString()
|
* \see toString()
|
||||||
*/
|
*/
|
||||||
void appendValue(const String &value);
|
void appendValue(const String &value);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Appends \a values to extend the current list of text values.
|
* Appends \a values to extend the current list of text values.
|
||||||
*
|
*
|
||||||
* \see toStringList()
|
* \see toStringList()
|
||||||
*/
|
*/
|
||||||
void appendValues(const StringList &values);
|
void appendValues(const StringList &values);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the size of the full item.
|
* Returns the size of the full item.
|
||||||
*/
|
*/
|
||||||
int size() const;
|
int size() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the value as a single string. In case of multiple strings,
|
* Returns the value as a single string. In case of multiple strings,
|
||||||
* the first is returned. If the data type is not \a Text, always returns
|
* the first is returned. If the data type is not \a Text, always returns
|
||||||
* an empty String.
|
* an empty String.
|
||||||
*/
|
*/
|
||||||
String toString() const;
|
String toString() const;
|
||||||
|
|
||||||
#ifndef DO_NOT_DOCUMENT
|
#ifndef DO_NOT_DOCUMENT
|
||||||
/* Remove in next binary incompatible release */
|
/* Remove in next binary incompatible release */
|
||||||
StringList toStringList() const;
|
StringList toStringList() const;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the list of text values. If the data type is not \a Text, always
|
* Returns the list of text values. If the data type is not \a Text, always
|
||||||
* returns an empty StringList.
|
* returns an empty StringList.
|
||||||
*/
|
*/
|
||||||
StringList values() const;
|
StringList values() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Render the item to a ByteVector.
|
* Render the item to a ByteVector.
|
||||||
*/
|
*/
|
||||||
ByteVector render() const;
|
ByteVector render() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Parse the item from the ByteVector \a data.
|
* Parse the item from the ByteVector \a data.
|
||||||
*/
|
*/
|
||||||
void parse(const ByteVector& data);
|
void parse(const ByteVector &data);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Set the item to read-only.
|
* Set the item to read-only.
|
||||||
*/
|
*/
|
||||||
void setReadOnly(bool readOnly);
|
void setReadOnly(bool readOnly);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Return true if the item is read-only.
|
* Return true if the item is read-only.
|
||||||
*/
|
*/
|
||||||
bool isReadOnly() const;
|
bool isReadOnly() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the type of the item to \a type.
|
* Sets the type of the item to \a type.
|
||||||
*
|
*
|
||||||
* \see ItemTypes
|
* \see ItemTypes
|
||||||
*/
|
*/
|
||||||
void setType(ItemTypes type);
|
void setType(ItemTypes type);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the type of the item.
|
* Returns the type of the item.
|
||||||
*/
|
*/
|
||||||
ItemTypes type() const;
|
ItemTypes type() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns if the item has any real content.
|
* Returns if the item has any real content.
|
||||||
*/
|
*/
|
||||||
bool isEmpty() const;
|
bool isEmpty() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class ItemPrivate;
|
class ItemPrivate;
|
||||||
ItemPrivate *d;
|
ItemPrivate *d;
|
||||||
};
|
};
|
||||||
}
|
} // namespace APE
|
||||||
|
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
121
3rdparty/taglib/ape/apeproperties.cpp
vendored
121
3rdparty/taglib/ape/apeproperties.cpp
vendored
@ -38,17 +38,15 @@
|
|||||||
|
|
||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
class APE::Properties::PropertiesPrivate
|
class APE::Properties::PropertiesPrivate {
|
||||||
{
|
public:
|
||||||
public:
|
PropertiesPrivate() : length(0),
|
||||||
PropertiesPrivate() :
|
bitrate(0),
|
||||||
length(0),
|
sampleRate(0),
|
||||||
bitrate(0),
|
channels(0),
|
||||||
sampleRate(0),
|
version(0),
|
||||||
channels(0),
|
bitsPerSample(0),
|
||||||
version(0),
|
sampleFrames(0) {}
|
||||||
bitsPerSample(0),
|
|
||||||
sampleFrames(0) {}
|
|
||||||
|
|
||||||
int length;
|
int length;
|
||||||
int bitrate;
|
int bitrate;
|
||||||
@ -63,67 +61,53 @@ public:
|
|||||||
// public members
|
// public members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
APE::Properties::Properties(File *, ReadStyle style) :
|
APE::Properties::Properties(File *, ReadStyle style) : AudioProperties(style),
|
||||||
AudioProperties(style),
|
d(new PropertiesPrivate()) {
|
||||||
d(new PropertiesPrivate())
|
|
||||||
{
|
|
||||||
debug("APE::Properties::Properties() -- This constructor is no longer used.");
|
debug("APE::Properties::Properties() -- This constructor is no longer used.");
|
||||||
}
|
}
|
||||||
|
|
||||||
APE::Properties::Properties(File *file, long streamLength, ReadStyle style) :
|
APE::Properties::Properties(File *file, long streamLength, ReadStyle style) : AudioProperties(style),
|
||||||
AudioProperties(style),
|
d(new PropertiesPrivate()) {
|
||||||
d(new PropertiesPrivate())
|
|
||||||
{
|
|
||||||
read(file, streamLength);
|
read(file, streamLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
APE::Properties::~Properties()
|
APE::Properties::~Properties() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
int APE::Properties::length() const
|
int APE::Properties::length() const {
|
||||||
{
|
|
||||||
return lengthInSeconds();
|
return lengthInSeconds();
|
||||||
}
|
}
|
||||||
|
|
||||||
int APE::Properties::lengthInSeconds() const
|
int APE::Properties::lengthInSeconds() const {
|
||||||
{
|
|
||||||
return d->length / 1000;
|
return d->length / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
int APE::Properties::lengthInMilliseconds() const
|
int APE::Properties::lengthInMilliseconds() const {
|
||||||
{
|
|
||||||
return d->length;
|
return d->length;
|
||||||
}
|
}
|
||||||
|
|
||||||
int APE::Properties::bitrate() const
|
int APE::Properties::bitrate() const {
|
||||||
{
|
|
||||||
return d->bitrate;
|
return d->bitrate;
|
||||||
}
|
}
|
||||||
|
|
||||||
int APE::Properties::sampleRate() const
|
int APE::Properties::sampleRate() const {
|
||||||
{
|
|
||||||
return d->sampleRate;
|
return d->sampleRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
int APE::Properties::channels() const
|
int APE::Properties::channels() const {
|
||||||
{
|
|
||||||
return d->channels;
|
return d->channels;
|
||||||
}
|
}
|
||||||
|
|
||||||
int APE::Properties::version() const
|
int APE::Properties::version() const {
|
||||||
{
|
|
||||||
return d->version;
|
return d->version;
|
||||||
}
|
}
|
||||||
|
|
||||||
int APE::Properties::bitsPerSample() const
|
int APE::Properties::bitsPerSample() const {
|
||||||
{
|
|
||||||
return d->bitsPerSample;
|
return d->bitsPerSample;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int APE::Properties::sampleFrames() const
|
unsigned int APE::Properties::sampleFrames() const {
|
||||||
{
|
|
||||||
return d->sampleFrames;
|
return d->sampleFrames;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,89 +115,84 @@ unsigned int APE::Properties::sampleFrames() const
|
|||||||
// private members
|
// private members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
namespace
|
namespace {
|
||||||
{
|
int headerVersion(const ByteVector &header) {
|
||||||
int headerVersion(const ByteVector &header)
|
if (header.size() < 6 || !header.startsWith("MAC "))
|
||||||
{
|
return -1;
|
||||||
if(header.size() < 6 || !header.startsWith("MAC "))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return header.toUShort(4, false);
|
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.
|
// First, we assume that the file pointer is set at the first descriptor.
|
||||||
long offset = file->tell();
|
long offset = file->tell();
|
||||||
int version = headerVersion(file->readBlock(6));
|
int version = headerVersion(file->readBlock(6));
|
||||||
|
|
||||||
// Next, we look for the descriptor.
|
// Next, we look for the descriptor.
|
||||||
if(version < 0) {
|
if (version < 0) {
|
||||||
offset = file->find("MAC ", offset);
|
offset = file->find("MAC ", offset);
|
||||||
file->seek(offset);
|
file->seek(offset);
|
||||||
version = headerVersion(file->readBlock(6));
|
version = headerVersion(file->readBlock(6));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(version < 0) {
|
if (version < 0) {
|
||||||
debug("APE::Properties::read() -- APE descriptor not found");
|
debug("APE::Properties::read() -- APE descriptor not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->version = version;
|
d->version = version;
|
||||||
|
|
||||||
if(d->version >= 3980)
|
if (d->version >= 3980)
|
||||||
analyzeCurrent(file);
|
analyzeCurrent(file);
|
||||||
else
|
else
|
||||||
analyzeOld(file);
|
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;
|
const double length = d->sampleFrames * 1000.0 / d->sampleRate;
|
||||||
d->length = static_cast<int>(length + 0.5);
|
d->length = static_cast<int>(length + 0.5);
|
||||||
d->bitrate = static_cast<int>(streamLength * 8.0 / 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
|
// Read the descriptor
|
||||||
file->seek(2, File::Current);
|
file->seek(2, File::Current);
|
||||||
const ByteVector descriptor = file->readBlock(44);
|
const ByteVector descriptor = file->readBlock(44);
|
||||||
if(descriptor.size() < 44) {
|
if (descriptor.size() < 44) {
|
||||||
debug("APE::Properties::analyzeCurrent() -- descriptor is too short.");
|
debug("APE::Properties::analyzeCurrent() -- descriptor is too short.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsigned int descriptorBytes = descriptor.toUInt(0, false);
|
const unsigned int descriptorBytes = descriptor.toUInt(0, false);
|
||||||
|
|
||||||
if((descriptorBytes - 52) > 0)
|
if ((descriptorBytes - 52) > 0)
|
||||||
file->seek(descriptorBytes - 52, File::Current);
|
file->seek(descriptorBytes - 52, File::Current);
|
||||||
|
|
||||||
// Read the header
|
// Read the header
|
||||||
const ByteVector header = file->readBlock(24);
|
const ByteVector header = file->readBlock(24);
|
||||||
if(header.size() < 24) {
|
if (header.size() < 24) {
|
||||||
debug("APE::Properties::analyzeCurrent() -- MAC header is too short.");
|
debug("APE::Properties::analyzeCurrent() -- MAC header is too short.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the APE info
|
// Get the APE info
|
||||||
d->channels = header.toShort(18, false);
|
d->channels = header.toShort(18, false);
|
||||||
d->sampleRate = header.toUInt(20, false);
|
d->sampleRate = header.toUInt(20, false);
|
||||||
d->bitsPerSample = header.toShort(16, false);
|
d->bitsPerSample = header.toShort(16, false);
|
||||||
|
|
||||||
const unsigned int totalFrames = header.toUInt(12, false);
|
const unsigned int totalFrames = header.toUInt(12, false);
|
||||||
if(totalFrames == 0)
|
if (totalFrames == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const unsigned int blocksPerFrame = header.toUInt(4, false);
|
const unsigned int blocksPerFrame = header.toUInt(4, false);
|
||||||
const unsigned int finalFrameBlocks = header.toUInt(8, false);
|
const unsigned int finalFrameBlocks = header.toUInt(8, false);
|
||||||
d->sampleFrames = (totalFrames - 1) * blocksPerFrame + finalFrameBlocks;
|
d->sampleFrames = (totalFrames - 1) * blocksPerFrame + finalFrameBlocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
void APE::Properties::analyzeOld(File *file)
|
void APE::Properties::analyzeOld(File *file) {
|
||||||
{
|
|
||||||
const ByteVector header = file->readBlock(26);
|
const ByteVector header = file->readBlock(26);
|
||||||
if(header.size() < 26) {
|
if (header.size() < 26) {
|
||||||
debug("APE::Properties::analyzeOld() -- MAC header is too short.");
|
debug("APE::Properties::analyzeOld() -- MAC header is too short.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -221,20 +200,20 @@ void APE::Properties::analyzeOld(File *file)
|
|||||||
const unsigned int totalFrames = header.toUInt(18, false);
|
const unsigned int totalFrames = header.toUInt(18, false);
|
||||||
|
|
||||||
// Fail on 0 length APE files (catches non-finalized APE files)
|
// Fail on 0 length APE files (catches non-finalized APE files)
|
||||||
if(totalFrames == 0)
|
if (totalFrames == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const short compressionLevel = header.toShort(0, false);
|
const short compressionLevel = header.toShort(0, false);
|
||||||
unsigned int blocksPerFrame;
|
unsigned int blocksPerFrame;
|
||||||
if(d->version >= 3950)
|
if (d->version >= 3950)
|
||||||
blocksPerFrame = 73728 * 4;
|
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;
|
blocksPerFrame = 73728;
|
||||||
else
|
else
|
||||||
blocksPerFrame = 9216;
|
blocksPerFrame = 9216;
|
||||||
|
|
||||||
// Get the APE info
|
// Get the APE info
|
||||||
d->channels = header.toShort(4, false);
|
d->channels = header.toShort(4, false);
|
||||||
d->sampleRate = header.toUInt(6, false);
|
d->sampleRate = header.toUInt(6, false);
|
||||||
|
|
||||||
const unsigned int finalFrameBlocks = header.toUInt(22, false);
|
const unsigned int finalFrameBlocks = header.toUInt(22, false);
|
||||||
@ -243,7 +222,7 @@ void APE::Properties::analyzeOld(File *file)
|
|||||||
// Get the bit depth from the RIFF-fmt chunk.
|
// Get the bit depth from the RIFF-fmt chunk.
|
||||||
file->seek(16, File::Current);
|
file->seek(16, File::Current);
|
||||||
const ByteVector fmt = file->readBlock(28);
|
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.");
|
debug("APE::Properties::analyzeOld() -- fmt header is too short.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
89
3rdparty/taglib/ape/apeproperties.h
vendored
89
3rdparty/taglib/ape/apeproperties.h
vendored
@ -36,40 +36,39 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace 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
|
* This reads the data from an APE stream found in the AudioProperties
|
||||||
* API.
|
* API.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class TAGLIB_EXPORT Properties : public AudioProperties
|
class TAGLIB_EXPORT Properties : public AudioProperties {
|
||||||
{
|
public:
|
||||||
public:
|
/*!
|
||||||
/*!
|
|
||||||
* Create an instance of APE::Properties with the data read from the
|
* Create an instance of APE::Properties with the data read from the
|
||||||
* APE::File \a file.
|
* APE::File \a file.
|
||||||
*
|
*
|
||||||
* \deprecated
|
* \deprecated
|
||||||
*/
|
*/
|
||||||
TAGLIB_DEPRECATED Properties(File *file, ReadStyle style = Average);
|
TAGLIB_DEPRECATED Properties(File *file, ReadStyle style = Average);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Create an instance of APE::Properties with the data read from the
|
* Create an instance of APE::Properties with the data read from the
|
||||||
* APE::File \a file.
|
* APE::File \a file.
|
||||||
*/
|
*/
|
||||||
Properties(File *file, long streamLength, ReadStyle style = Average);
|
Properties(File *file, long streamLength, ReadStyle style = Average);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys this APE::Properties instance.
|
* Destroys this APE::Properties instance.
|
||||||
*/
|
*/
|
||||||
virtual ~Properties();
|
virtual ~Properties();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the length of the file in seconds. The length is rounded down to
|
* Returns the length of the file in seconds. The length is rounded down to
|
||||||
* the nearest whole second.
|
* the nearest whole second.
|
||||||
*
|
*
|
||||||
@ -77,69 +76,69 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \deprecated
|
* \deprecated
|
||||||
*/
|
*/
|
||||||
TAGLIB_DEPRECATED virtual int length() const;
|
TAGLIB_DEPRECATED virtual int length() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the length of the file in seconds. The length is rounded down to
|
* Returns the length of the file in seconds. The length is rounded down to
|
||||||
* the nearest whole second.
|
* the nearest whole second.
|
||||||
*
|
*
|
||||||
* \see lengthInMilliseconds()
|
* \see lengthInMilliseconds()
|
||||||
*/
|
*/
|
||||||
// BIC: make virtual
|
// BIC: make virtual
|
||||||
int lengthInSeconds() const;
|
int lengthInSeconds() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the length of the file in milliseconds.
|
* Returns the length of the file in milliseconds.
|
||||||
*
|
*
|
||||||
* \see lengthInSeconds()
|
* \see lengthInSeconds()
|
||||||
*/
|
*/
|
||||||
// BIC: make virtual
|
// BIC: make virtual
|
||||||
int lengthInMilliseconds() const;
|
int lengthInMilliseconds() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the average bit rate of the file in kb/s.
|
* Returns the average bit rate of the file in kb/s.
|
||||||
*/
|
*/
|
||||||
virtual int bitrate() const;
|
virtual int bitrate() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the sample rate in Hz.
|
* Returns the sample rate in Hz.
|
||||||
*/
|
*/
|
||||||
virtual int sampleRate() const;
|
virtual int sampleRate() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the number of audio channels.
|
* Returns the number of audio channels.
|
||||||
*/
|
*/
|
||||||
virtual int channels() const;
|
virtual int channels() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the number of bits per audio sample.
|
* Returns the number of bits per audio sample.
|
||||||
*/
|
*/
|
||||||
int bitsPerSample() const;
|
int bitsPerSample() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the total number of audio samples in file.
|
* Returns the total number of audio samples in file.
|
||||||
*/
|
*/
|
||||||
unsigned int sampleFrames() const;
|
unsigned int sampleFrames() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns APE version.
|
* Returns APE version.
|
||||||
*/
|
*/
|
||||||
int version() const;
|
int version() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Properties(const Properties &);
|
Properties(const Properties &);
|
||||||
Properties &operator=(const Properties &);
|
Properties &operator=(const Properties &);
|
||||||
|
|
||||||
void read(File *file, long streamLength);
|
void read(File *file, long streamLength);
|
||||||
|
|
||||||
void analyzeCurrent(File *file);
|
void analyzeCurrent(File *file);
|
||||||
void analyzeOld(File *file);
|
void analyzeOld(File *file);
|
||||||
|
|
||||||
class PropertiesPrivate;
|
class PropertiesPrivate;
|
||||||
PropertiesPrivate *d;
|
PropertiesPrivate *d;
|
||||||
};
|
};
|
||||||
}
|
} // namespace APE
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
272
3rdparty/taglib/ape/apetag.cpp
vendored
272
3rdparty/taglib/ape/apetag.cpp
vendored
@ -28,7 +28,7 @@
|
|||||||
// it considers specializations with and without class types
|
// it considers specializations with and without class types
|
||||||
// to be different; this define forces Map to use only the
|
// to be different; this define forces Map to use only the
|
||||||
// specialization with the class keyword.
|
// specialization with the class keyword.
|
||||||
#define WANT_CLASS_INSTANTIATION_OF_MAP (1)
|
# define WANT_CLASS_INSTANTIATION_OF_MAP (1)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <tfile.h>
|
#include <tfile.h>
|
||||||
@ -45,39 +45,35 @@
|
|||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
using namespace APE;
|
using namespace APE;
|
||||||
|
|
||||||
namespace
|
namespace {
|
||||||
{
|
const unsigned int MinKeyLength = 2;
|
||||||
const unsigned int MinKeyLength = 2;
|
const unsigned int MaxKeyLength = 255;
|
||||||
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)
|
const char *invalidKeys[] = { "ID3", "TAG", "OGGS", "MP+", 0 };
|
||||||
|
|
||||||
for(ByteVector::ConstIterator it = key.begin(); it != key.end(); ++it) {
|
// only allow printable ASCII including space (32..126)
|
||||||
const int c = static_cast<unsigned char>(*it);
|
|
||||||
if(c < 32 || c > 126)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const String upperKey = String(key).upper();
|
for (ByteVector::ConstIterator it = key.begin(); it != key.end(); ++it) {
|
||||||
for(size_t i = 0; invalidKeys[i] != 0; ++i) {
|
const int c = static_cast<unsigned char>(*it);
|
||||||
if(upperKey == invalidKeys[i])
|
if (c < 32 || c > 126)
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
class APE::Tag::TagPrivate
|
const String upperKey = String(key).upper();
|
||||||
{
|
for (size_t i = 0; invalidKeys[i] != 0; ++i) {
|
||||||
public:
|
if (upperKey == invalidKeys[i])
|
||||||
TagPrivate() :
|
return false;
|
||||||
file(0),
|
}
|
||||||
footerLocation(0) {}
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
class APE::Tag::TagPrivate {
|
||||||
|
public:
|
||||||
|
TagPrivate() : file(0), footerLocation(0) {}
|
||||||
|
|
||||||
File *file;
|
File *file;
|
||||||
long footerLocation;
|
long footerLocation;
|
||||||
@ -90,150 +86,140 @@ public:
|
|||||||
// public methods
|
// public methods
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
APE::Tag::Tag() :
|
APE::Tag::Tag() : Strawberry_TagLib::TagLib::Tag(), d(new TagPrivate()) {}
|
||||||
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->file = file;
|
||||||
d->footerLocation = footerLocation;
|
d->footerLocation = footerLocation;
|
||||||
|
|
||||||
read();
|
read();
|
||||||
}
|
}
|
||||||
|
|
||||||
APE::Tag::~Tag()
|
APE::Tag::~Tag() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector APE::Tag::fileIdentifier()
|
ByteVector APE::Tag::fileIdentifier() {
|
||||||
{
|
|
||||||
return ByteVector::fromCString("APETAGEX");
|
return ByteVector::fromCString("APETAGEX");
|
||||||
}
|
}
|
||||||
|
|
||||||
String APE::Tag::title() const
|
String APE::Tag::title() const {
|
||||||
{
|
|
||||||
if(d->itemListMap["TITLE"].isEmpty())
|
if (d->itemListMap["TITLE"].isEmpty())
|
||||||
return String();
|
return String();
|
||||||
return d->itemListMap["TITLE"].values().toString();
|
return d->itemListMap["TITLE"].values().toString();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String APE::Tag::artist() const
|
String APE::Tag::artist() const {
|
||||||
{
|
|
||||||
if(d->itemListMap["ARTIST"].isEmpty())
|
if (d->itemListMap["ARTIST"].isEmpty())
|
||||||
return String();
|
return String();
|
||||||
return d->itemListMap["ARTIST"].values().toString();
|
return d->itemListMap["ARTIST"].values().toString();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String APE::Tag::album() const
|
String APE::Tag::album() const {
|
||||||
{
|
|
||||||
if(d->itemListMap["ALBUM"].isEmpty())
|
if (d->itemListMap["ALBUM"].isEmpty())
|
||||||
return String();
|
return String();
|
||||||
return d->itemListMap["ALBUM"].values().toString();
|
return d->itemListMap["ALBUM"].values().toString();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String APE::Tag::comment() const
|
String APE::Tag::comment() const {
|
||||||
{
|
|
||||||
if(d->itemListMap["COMMENT"].isEmpty())
|
if (d->itemListMap["COMMENT"].isEmpty())
|
||||||
return String();
|
return String();
|
||||||
return d->itemListMap["COMMENT"].values().toString();
|
return d->itemListMap["COMMENT"].values().toString();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String APE::Tag::genre() const
|
String APE::Tag::genre() const {
|
||||||
{
|
|
||||||
if(d->itemListMap["GENRE"].isEmpty())
|
if (d->itemListMap["GENRE"].isEmpty())
|
||||||
return String();
|
return String();
|
||||||
return d->itemListMap["GENRE"].values().toString();
|
return d->itemListMap["GENRE"].values().toString();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int APE::Tag::year() const
|
unsigned int APE::Tag::year() const {
|
||||||
{
|
|
||||||
if(d->itemListMap["YEAR"].isEmpty())
|
if (d->itemListMap["YEAR"].isEmpty())
|
||||||
return 0;
|
return 0;
|
||||||
return d->itemListMap["YEAR"].toString().toInt();
|
return d->itemListMap["YEAR"].toString().toInt();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int APE::Tag::track() const
|
unsigned int APE::Tag::track() const {
|
||||||
{
|
|
||||||
if(d->itemListMap["TRACK"].isEmpty())
|
if (d->itemListMap["TRACK"].isEmpty())
|
||||||
return 0;
|
return 0;
|
||||||
return d->itemListMap["TRACK"].toString().toInt();
|
return d->itemListMap["TRACK"].toString().toInt();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void APE::Tag::setTitle(const String &s)
|
void APE::Tag::setTitle(const String &s) {
|
||||||
{
|
|
||||||
addValue("TITLE", s, true);
|
addValue("TITLE", s, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void APE::Tag::setArtist(const String &s)
|
void APE::Tag::setArtist(const String &s) {
|
||||||
{
|
|
||||||
addValue("ARTIST", s, true);
|
addValue("ARTIST", s, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void APE::Tag::setAlbum(const String &s)
|
void APE::Tag::setAlbum(const String &s) {
|
||||||
{
|
|
||||||
addValue("ALBUM", s, true);
|
addValue("ALBUM", s, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void APE::Tag::setComment(const String &s)
|
void APE::Tag::setComment(const String &s) {
|
||||||
{
|
|
||||||
addValue("COMMENT", s, true);
|
addValue("COMMENT", s, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void APE::Tag::setGenre(const String &s)
|
void APE::Tag::setGenre(const String &s) {
|
||||||
{
|
|
||||||
addValue("GENRE", s, true);
|
addValue("GENRE", s, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void APE::Tag::setYear(unsigned int i)
|
void APE::Tag::setYear(unsigned int i) {
|
||||||
{
|
if (i == 0)
|
||||||
if(i == 0)
|
|
||||||
removeItem("YEAR");
|
removeItem("YEAR");
|
||||||
else
|
else
|
||||||
addValue("YEAR", String::number(i), true);
|
addValue("YEAR", String::number(i), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void APE::Tag::setTrack(unsigned int i)
|
void APE::Tag::setTrack(unsigned int i) {
|
||||||
{
|
if (i == 0)
|
||||||
if(i == 0)
|
|
||||||
removeItem("TRACK");
|
removeItem("TRACK");
|
||||||
else
|
else
|
||||||
addValue("TRACK", String::number(i), true);
|
addValue("TRACK", String::number(i), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace
|
namespace {
|
||||||
{
|
// conversions of tag keys between what we use in PropertyMap and what's usual
|
||||||
// conversions of tag keys between what we use in PropertyMap and what's usual
|
// for APE tags
|
||||||
// for APE tags
|
// usual, APE
|
||||||
// usual, APE
|
const char *keyConversions[][2] = { { "TRACKNUMBER", "TRACK" },
|
||||||
const char *keyConversions[][2] = {{"TRACKNUMBER", "TRACK" },
|
{ "DATE", "YEAR" },
|
||||||
{"DATE", "YEAR" },
|
{ "ALBUMARTIST", "ALBUM ARTIST" },
|
||||||
{"ALBUMARTIST", "ALBUM ARTIST"},
|
{ "DISCNUMBER", "DISC" },
|
||||||
{"DISCNUMBER", "DISC" },
|
{ "REMIXER", "MIXARTIST" } };
|
||||||
{"REMIXER", "MIXARTIST" }};
|
const size_t keyConversionsSize = sizeof(keyConversions) / sizeof(keyConversions[0]);
|
||||||
const size_t keyConversionsSize = sizeof(keyConversions) / sizeof(keyConversions[0]);
|
} // namespace
|
||||||
}
|
|
||||||
|
|
||||||
PropertyMap APE::Tag::properties() const
|
PropertyMap APE::Tag::properties() const {
|
||||||
{
|
|
||||||
PropertyMap properties;
|
PropertyMap properties;
|
||||||
ItemListMap::ConstIterator it = itemListMap().begin();
|
ItemListMap::ConstIterator it = itemListMap().begin();
|
||||||
for(; it != itemListMap().end(); ++it) {
|
for (; it != itemListMap().end(); ++it) {
|
||||||
String tagName = it->first.upper();
|
String tagName = it->first.upper();
|
||||||
// if the item is Binary or Locator, or if the key is an invalid string,
|
// if the item is Binary or Locator, or if the key is an invalid string,
|
||||||
// add to unsupportedData
|
// add to unsupportedData
|
||||||
if(it->second.type() != Item::Text || tagName.isEmpty()) {
|
if (it->second.type() != Item::Text || tagName.isEmpty()) {
|
||||||
properties.unsupportedData().append(it->first);
|
properties.unsupportedData().append(it->first);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Some tags need to be handled specially
|
// Some tags need to be handled specially
|
||||||
for(size_t i = 0; i < keyConversionsSize; ++i) {
|
for (size_t i = 0; i < keyConversionsSize; ++i) {
|
||||||
if(tagName == keyConversions[i][1])
|
if (tagName == keyConversions[i][1])
|
||||||
tagName = keyConversions[i][0];
|
tagName = keyConversions[i][0];
|
||||||
}
|
}
|
||||||
properties[tagName].append(it->second.toStringList());
|
properties[tagName].append(it->second.toStringList());
|
||||||
@ -242,20 +228,18 @@ PropertyMap APE::Tag::properties() const
|
|||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
void APE::Tag::removeUnsupportedProperties(const StringList &properties)
|
void APE::Tag::removeUnsupportedProperties(const StringList &properties) {
|
||||||
{
|
|
||||||
StringList::ConstIterator it = properties.begin();
|
StringList::ConstIterator it = properties.begin();
|
||||||
for(; it != properties.end(); ++it)
|
for (; it != properties.end(); ++it)
|
||||||
removeItem(*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
|
||||||
PropertyMap properties(origProps); // make a local copy that can be modified
|
|
||||||
|
|
||||||
// see comment in properties()
|
// see comment in properties()
|
||||||
for(size_t i = 0; i < keyConversionsSize; ++i)
|
for (size_t i = 0; i < keyConversionsSize; ++i)
|
||||||
if(properties.contains(keyConversions[i][0])) {
|
if (properties.contains(keyConversions[i][0])) {
|
||||||
properties.insert(keyConversions[i][1], properties[keyConversions[i][0]]);
|
properties.insert(keyConversions[i][1], properties[keyConversions[i][0]]);
|
||||||
properties.erase(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
|
// first check if tags need to be removed completely
|
||||||
StringList toRemove;
|
StringList toRemove;
|
||||||
ItemListMap::ConstIterator remIt = itemListMap().begin();
|
ItemListMap::ConstIterator remIt = itemListMap().begin();
|
||||||
for(; remIt != itemListMap().end(); ++remIt) {
|
for (; remIt != itemListMap().end(); ++remIt) {
|
||||||
String key = remIt->first.upper();
|
String key = remIt->first.upper();
|
||||||
// only remove if a) key is valid, b) type is text, c) key not contained in new properties
|
// 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);
|
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);
|
removeItem(*removeIt);
|
||||||
|
|
||||||
// now sync in the "forward direction"
|
// now sync in the "forward direction"
|
||||||
PropertyMap::ConstIterator it = properties.begin();
|
PropertyMap::ConstIterator it = properties.begin();
|
||||||
PropertyMap invalid;
|
PropertyMap invalid;
|
||||||
for(; it != properties.end(); ++it) {
|
for (; it != properties.end(); ++it) {
|
||||||
const String &tagName = it->first;
|
const String &tagName = it->first;
|
||||||
if(!checkKey(tagName))
|
if (!checkKey(tagName))
|
||||||
invalid.insert(it->first, it->second);
|
invalid.insert(it->first, it->second);
|
||||||
else if(!(itemListMap().contains(tagName)) || !(itemListMap()[tagName].values() == it->second)) {
|
else if (!(itemListMap().contains(tagName)) || !(itemListMap()[tagName].values() == it->second)) {
|
||||||
if(it->second.isEmpty())
|
if (it->second.isEmpty())
|
||||||
removeItem(tagName);
|
removeItem(tagName);
|
||||||
else {
|
else {
|
||||||
StringList::ConstIterator valueIt = it->second.begin();
|
StringList::ConstIterator valueIt = it->second.begin();
|
||||||
addValue(tagName, *valueIt, true);
|
addValue(tagName, *valueIt, true);
|
||||||
++valueIt;
|
++valueIt;
|
||||||
for(; valueIt != it->second.end(); ++valueIt)
|
for (; valueIt != it->second.end(); ++valueIt)
|
||||||
addValue(tagName, *valueIt, false);
|
addValue(tagName, *valueIt, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -295,35 +279,30 @@ PropertyMap APE::Tag::setProperties(const PropertyMap &origProps)
|
|||||||
return invalid;
|
return invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool APE::Tag::checkKey(const String &key)
|
bool APE::Tag::checkKey(const String &key) {
|
||||||
{
|
if (key.size() < MinKeyLength || key.size() > MaxKeyLength)
|
||||||
if(key.size() < MinKeyLength || key.size() > MaxKeyLength)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return isKeyValid(key.data(String::UTF8));
|
return isKeyValid(key.data(String::UTF8));
|
||||||
}
|
}
|
||||||
|
|
||||||
APE::Footer *APE::Tag::footer() const
|
APE::Footer *APE::Tag::footer() const {
|
||||||
{
|
|
||||||
return &d->footer;
|
return &d->footer;
|
||||||
}
|
}
|
||||||
|
|
||||||
const APE::ItemListMap& APE::Tag::itemListMap() const
|
const APE::ItemListMap &APE::Tag::itemListMap() const {
|
||||||
{
|
|
||||||
return d->itemListMap;
|
return d->itemListMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
void APE::Tag::removeItem(const String &key)
|
void APE::Tag::removeItem(const String &key) {
|
||||||
{
|
|
||||||
d->itemListMap.erase(key.upper());
|
d->itemListMap.erase(key.upper());
|
||||||
}
|
}
|
||||||
|
|
||||||
void APE::Tag::addValue(const String &key, const String &value, bool replace)
|
void APE::Tag::addValue(const String &key, const String &value, bool replace) {
|
||||||
{
|
if (replace)
|
||||||
if(replace)
|
|
||||||
removeItem(key);
|
removeItem(key);
|
||||||
|
|
||||||
if(value.isEmpty())
|
if (value.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Text items may contain more than one value.
|
// 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());
|
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);
|
it->second.appendValue(value);
|
||||||
else
|
else
|
||||||
setItem(key, Item(key, value));
|
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);
|
removeItem(key);
|
||||||
|
|
||||||
if(value.isEmpty())
|
if (value.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
setItem(key, Item(key, value, true));
|
setItem(key, Item(key, value, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
void APE::Tag::setItem(const String &key, const Item &item)
|
void APE::Tag::setItem(const String &key, const Item &item) {
|
||||||
{
|
if (!checkKey(key)) {
|
||||||
if(!checkKey(key)) {
|
|
||||||
debug("APE::Tag::setItem() - Couldn't set an item due to an invalid key.");
|
debug("APE::Tag::setItem() - Couldn't set an item due to an invalid key.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -357,8 +334,7 @@ void APE::Tag::setItem(const String &key, const Item &item)
|
|||||||
d->itemListMap[key.upper()] = item;
|
d->itemListMap[key.upper()] = item;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool APE::Tag::isEmpty() const
|
bool APE::Tag::isEmpty() const {
|
||||||
{
|
|
||||||
return d->itemListMap.isEmpty();
|
return d->itemListMap.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -366,15 +342,14 @@ bool APE::Tag::isEmpty() const
|
|||||||
// protected methods
|
// protected methods
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void APE::Tag::read()
|
void APE::Tag::read() {
|
||||||
{
|
if (d->file && d->file->isValid()) {
|
||||||
if(d->file && d->file->isValid()) {
|
|
||||||
|
|
||||||
d->file->seek(d->footerLocation);
|
d->file->seek(d->footerLocation);
|
||||||
d->footer.setData(d->file->readBlock(Footer::size()));
|
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()))
|
d->footer.tagSize() > static_cast<unsigned long>(d->file->length()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
d->file->seek(d->footerLocation + Footer::size() - d->footer.tagSize());
|
d->file->seek(d->footerLocation + Footer::size() - d->footer.tagSize());
|
||||||
@ -382,12 +357,11 @@ void APE::Tag::read()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector APE::Tag::render() const
|
ByteVector APE::Tag::render() const {
|
||||||
{
|
|
||||||
ByteVector data;
|
ByteVector data;
|
||||||
unsigned int itemCount = 0;
|
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());
|
data.append(it->second.render());
|
||||||
itemCount++;
|
itemCount++;
|
||||||
}
|
}
|
||||||
@ -399,19 +373,18 @@ ByteVector APE::Tag::render() const
|
|||||||
return d->footer.renderHeader() + data + d->footer.renderFooter();
|
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
|
// 11 bytes is the minimum size for an APE item
|
||||||
|
|
||||||
if(data.size() < 11)
|
if (data.size() < 11)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
unsigned int pos = 0;
|
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);
|
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.");
|
debug("APE::Tag::parse() - Couldn't find a key/value separator. Stopped parsing.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -419,10 +392,7 @@ void APE::Tag::parse(const ByteVector &data)
|
|||||||
const unsigned int keyLength = nullPos - pos - 8;
|
const unsigned int keyLength = nullPos - pos - 8;
|
||||||
const unsigned int valLegnth = data.toUInt(pos, false);
|
const unsigned int valLegnth = data.toUInt(pos, false);
|
||||||
|
|
||||||
if(keyLength >= MinKeyLength
|
if (keyLength >= MinKeyLength && keyLength <= MaxKeyLength && isKeyValid(data.mid(pos + 8, keyLength))) {
|
||||||
&& keyLength <= MaxKeyLength
|
|
||||||
&& isKeyValid(data.mid(pos + 8, keyLength)))
|
|
||||||
{
|
|
||||||
APE::Item item;
|
APE::Item item;
|
||||||
item.parse(data.mid(pos));
|
item.parse(data.mid(pos));
|
||||||
|
|
||||||
|
140
3rdparty/taglib/ape/apetag.h
vendored
140
3rdparty/taglib/ape/apetag.h
vendored
@ -37,74 +37,73 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace 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.
|
* A mapping between a list of item names, or keys, and the associated item.
|
||||||
*
|
*
|
||||||
* \see APE::Tag::itemListMap()
|
* \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:
|
||||||
public:
|
/*!
|
||||||
/*!
|
|
||||||
* Create an APE tag with default values.
|
* Create an APE tag with default values.
|
||||||
*/
|
*/
|
||||||
Tag();
|
Tag();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Create an APE tag and parse the data in \a file with APE footer at
|
* Create an APE tag and parse the data in \a file with APE footer at
|
||||||
* \a tagOffset.
|
* \a tagOffset.
|
||||||
*/
|
*/
|
||||||
Tag(Strawberry_TagLib::TagLib::File *file, long footerLocation);
|
Tag(Strawberry_TagLib::TagLib::File *file, long footerLocation);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys this Tag instance.
|
* Destroys this Tag instance.
|
||||||
*/
|
*/
|
||||||
virtual ~Tag();
|
virtual ~Tag();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Renders the in memory values to a ByteVector suitable for writing to
|
* Renders the in memory values to a ByteVector suitable for writing to
|
||||||
* the file.
|
* the file.
|
||||||
*/
|
*/
|
||||||
ByteVector render() const;
|
ByteVector render() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the string "APETAGEX" suitable for usage in locating the tag in a
|
* Returns the string "APETAGEX" suitable for usage in locating the tag in a
|
||||||
* file.
|
* file.
|
||||||
*/
|
*/
|
||||||
static ByteVector fileIdentifier();
|
static ByteVector fileIdentifier();
|
||||||
|
|
||||||
// Reimplementations.
|
// Reimplementations.
|
||||||
|
|
||||||
virtual String title() const;
|
virtual String title() const;
|
||||||
virtual String artist() const;
|
virtual String artist() const;
|
||||||
virtual String album() const;
|
virtual String album() const;
|
||||||
virtual String comment() const;
|
virtual String comment() const;
|
||||||
virtual String genre() const;
|
virtual String genre() const;
|
||||||
virtual unsigned int year() const;
|
virtual unsigned int year() const;
|
||||||
virtual unsigned int track() const;
|
virtual unsigned int track() const;
|
||||||
|
|
||||||
virtual void setTitle(const String &s);
|
virtual void setTitle(const String &s);
|
||||||
virtual void setArtist(const String &s);
|
virtual void setArtist(const String &s);
|
||||||
virtual void setAlbum(const String &s);
|
virtual void setAlbum(const String &s);
|
||||||
virtual void setComment(const String &s);
|
virtual void setComment(const String &s);
|
||||||
virtual void setGenre(const String &s);
|
virtual void setGenre(const String &s);
|
||||||
virtual void setYear(unsigned int i);
|
virtual void setYear(unsigned int i);
|
||||||
virtual void setTrack(unsigned int i);
|
virtual void setTrack(unsigned int i);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Implements the unified tag dictionary interface -- export function.
|
* Implements the unified tag dictionary interface -- export function.
|
||||||
* APE tags are perfectly compatible with the dictionary interface because they
|
* APE tags are perfectly compatible with the dictionary interface because they
|
||||||
* support both arbitrary tag names and multiple values. Currently only
|
* support both arbitrary tag names and multiple values. Currently only
|
||||||
@ -118,29 +117,29 @@ namespace TagLib {
|
|||||||
* TRACK to TRACKNUMBER, YEAR to DATE, and ALBUM ARTIST to ALBUMARTIST, respectively,
|
* TRACK to TRACKNUMBER, YEAR to DATE, and ALBUM ARTIST to ALBUMARTIST, respectively,
|
||||||
* in order to be compliant with the names used in other formats.
|
* in order to be compliant with the names used in other formats.
|
||||||
*/
|
*/
|
||||||
PropertyMap properties() const;
|
PropertyMap properties() const;
|
||||||
|
|
||||||
void removeUnsupportedProperties(const StringList &properties);
|
void removeUnsupportedProperties(const StringList &properties);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Implements the unified tag dictionary interface -- import function. The same
|
* Implements the unified tag dictionary interface -- import function. The same
|
||||||
* comments as for the export function apply; additionally note that the APE tag
|
* comments as for the export function apply; additionally note that the APE tag
|
||||||
* specification requires keys to have between 2 and 16 printable ASCII characters
|
* specification requires keys to have between 2 and 16 printable ASCII characters
|
||||||
* with the exception of the fixed strings "ID3", "TAG", "OGGS", and "MP+".
|
* with the exception of the fixed strings "ID3", "TAG", "OGGS", and "MP+".
|
||||||
*/
|
*/
|
||||||
PropertyMap setProperties(const PropertyMap &);
|
PropertyMap setProperties(const PropertyMap &);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Check if the given String is a valid APE tag key.
|
* 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.
|
* Returns a pointer to the tag's footer.
|
||||||
*/
|
*/
|
||||||
Footer *footer() const;
|
Footer *footer() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns a reference to the item list map. This is an ItemListMap of
|
* Returns a reference to the item list map. This is an ItemListMap of
|
||||||
* all of the items in the tag.
|
* all of the items in the tag.
|
||||||
*
|
*
|
||||||
@ -152,59 +151,58 @@ namespace TagLib {
|
|||||||
* \warning You should not modify this data structure directly, instead
|
* \warning You should not modify this data structure directly, instead
|
||||||
* use setItem() and removeItem().
|
* use setItem() and removeItem().
|
||||||
*/
|
*/
|
||||||
const ItemListMap &itemListMap() const;
|
const ItemListMap &itemListMap() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Removes the \a key item from the tag
|
* Removes the \a key item from the tag
|
||||||
*/
|
*/
|
||||||
void removeItem(const String &key);
|
void removeItem(const String &key);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Adds to the text item specified by \a key the data \a value. If \a replace
|
* Adds to the text item specified by \a key the data \a value. If \a replace
|
||||||
* is true, then all of the other values on the same key will be removed
|
* is true, then all of the other values on the same key will be removed
|
||||||
* first. If a binary item exists for \a key it will be removed first.
|
* first. If a binary item exists for \a key it will be removed first.
|
||||||
*/
|
*/
|
||||||
void addValue(const String &key, const String &value, bool replace = true);
|
void addValue(const String &key, const String &value, bool replace = true);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Set the binary data for the key specified by \a item to \a value
|
* Set the binary data for the key specified by \a item to \a value
|
||||||
* This will convert the item to type \a Binary if it isn't already and
|
* This will convert the item to type \a Binary if it isn't already and
|
||||||
* all of the other values on the same key will be removed.
|
* all of the other values on the same key will be removed.
|
||||||
*/
|
*/
|
||||||
void setData(const String &key, const ByteVector &value);
|
void setData(const String &key, const ByteVector &value);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the \a key item to the value of \a item. If an item with the \a key is already
|
* Sets the \a key item to the value of \a item. If an item with the \a key is already
|
||||||
* present, it will be replaced.
|
* present, it will be replaced.
|
||||||
*/
|
*/
|
||||||
void setItem(const String &key, const Item &item);
|
void setItem(const String &key, const Item &item);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns true if the tag does not contain any data.
|
* Returns true if the tag does not contain any data.
|
||||||
*/
|
*/
|
||||||
bool isEmpty() const;
|
bool isEmpty() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
/*!
|
||||||
/*!
|
|
||||||
* Reads from the file specified in the constructor.
|
* Reads from the file specified in the constructor.
|
||||||
*/
|
*/
|
||||||
void read();
|
void read();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Parses the body of the tag in \a data.
|
* Parses the body of the tag in \a data.
|
||||||
*/
|
*/
|
||||||
void parse(const ByteVector &data);
|
void parse(const ByteVector &data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Tag(const Tag &);
|
Tag(const Tag &);
|
||||||
Tag &operator=(const Tag &);
|
Tag &operator=(const Tag &);
|
||||||
|
|
||||||
class TagPrivate;
|
class TagPrivate;
|
||||||
TagPrivate *d;
|
TagPrivate *d;
|
||||||
};
|
};
|
||||||
}
|
} // namespace APE
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
286
3rdparty/taglib/asf/asfattribute.cpp
vendored
286
3rdparty/taglib/asf/asfattribute.cpp
vendored
@ -33,14 +33,12 @@
|
|||||||
|
|
||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
class ASF::Attribute::AttributePrivate : public RefCounter
|
class ASF::Attribute::AttributePrivate : public RefCounter {
|
||||||
{
|
public:
|
||||||
public:
|
AttributePrivate() : pictureValue(ASF::Picture::fromInvalid()),
|
||||||
AttributePrivate() :
|
numericValue(0),
|
||||||
pictureValue(ASF::Picture::fromInvalid()),
|
stream(0),
|
||||||
numericValue(0),
|
language(0) {}
|
||||||
stream(0),
|
|
||||||
language(0) {}
|
|
||||||
AttributeTypes type;
|
AttributeTypes type;
|
||||||
String stringValue;
|
String stringValue;
|
||||||
ByteVector byteVectorValue;
|
ByteVector byteVectorValue;
|
||||||
@ -54,135 +52,105 @@ public:
|
|||||||
// public members
|
// public members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ASF::Attribute::Attribute() :
|
ASF::Attribute::Attribute() : d(new AttributePrivate()) {
|
||||||
d(new AttributePrivate())
|
|
||||||
{
|
|
||||||
d->type = UnicodeType;
|
d->type = UnicodeType;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASF::Attribute::Attribute(const ASF::Attribute &other) :
|
ASF::Attribute::Attribute(const ASF::Attribute &other) : d(other.d) {
|
||||||
d(other.d)
|
|
||||||
{
|
|
||||||
d->ref();
|
d->ref();
|
||||||
}
|
}
|
||||||
|
|
||||||
ASF::Attribute::Attribute(const String &value) :
|
ASF::Attribute::Attribute(const String &value) : d(new AttributePrivate()) {
|
||||||
d(new AttributePrivate())
|
|
||||||
{
|
|
||||||
d->type = UnicodeType;
|
d->type = UnicodeType;
|
||||||
d->stringValue = value;
|
d->stringValue = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASF::Attribute::Attribute(const ByteVector &value) :
|
ASF::Attribute::Attribute(const ByteVector &value) : d(new AttributePrivate()) {
|
||||||
d(new AttributePrivate())
|
|
||||||
{
|
|
||||||
d->type = BytesType;
|
d->type = BytesType;
|
||||||
d->byteVectorValue = value;
|
d->byteVectorValue = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASF::Attribute::Attribute(const ASF::Picture &value) :
|
ASF::Attribute::Attribute(const ASF::Picture &value) : d(new AttributePrivate()) {
|
||||||
d(new AttributePrivate())
|
|
||||||
{
|
|
||||||
d->type = BytesType;
|
d->type = BytesType;
|
||||||
d->pictureValue = value;
|
d->pictureValue = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASF::Attribute::Attribute(unsigned int value) :
|
ASF::Attribute::Attribute(unsigned int value) : d(new AttributePrivate()) {
|
||||||
d(new AttributePrivate())
|
|
||||||
{
|
|
||||||
d->type = DWordType;
|
d->type = DWordType;
|
||||||
d->numericValue = value;
|
d->numericValue = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASF::Attribute::Attribute(unsigned long long value) :
|
ASF::Attribute::Attribute(unsigned long long value) : d(new AttributePrivate()) {
|
||||||
d(new AttributePrivate())
|
|
||||||
{
|
|
||||||
d->type = QWordType;
|
d->type = QWordType;
|
||||||
d->numericValue = value;
|
d->numericValue = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASF::Attribute::Attribute(unsigned short value) :
|
ASF::Attribute::Attribute(unsigned short value) : d(new AttributePrivate()) {
|
||||||
d(new AttributePrivate())
|
|
||||||
{
|
|
||||||
d->type = WordType;
|
d->type = WordType;
|
||||||
d->numericValue = value;
|
d->numericValue = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASF::Attribute::Attribute(bool value) :
|
ASF::Attribute::Attribute(bool value) : d(new AttributePrivate()) {
|
||||||
d(new AttributePrivate())
|
|
||||||
{
|
|
||||||
d->type = BoolType;
|
d->type = BoolType;
|
||||||
d->numericValue = value;
|
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);
|
Attribute(other).swap(*this);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASF::Attribute::swap(Attribute &other)
|
void ASF::Attribute::swap(Attribute &other) {
|
||||||
{
|
|
||||||
using std::swap;
|
using std::swap;
|
||||||
|
|
||||||
swap(d, other.d);
|
swap(d, other.d);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASF::Attribute::~Attribute()
|
ASF::Attribute::~Attribute() {
|
||||||
{
|
if (d->deref())
|
||||||
if(d->deref())
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASF::Attribute::AttributeTypes ASF::Attribute::type() const
|
ASF::Attribute::AttributeTypes ASF::Attribute::type() const {
|
||||||
{
|
|
||||||
return d->type;
|
return d->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
String ASF::Attribute::toString() const
|
String ASF::Attribute::toString() const {
|
||||||
{
|
|
||||||
return d->stringValue;
|
return d->stringValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector ASF::Attribute::toByteVector() const
|
ByteVector ASF::Attribute::toByteVector() const {
|
||||||
{
|
if (d->pictureValue.isValid())
|
||||||
if(d->pictureValue.isValid())
|
|
||||||
return d->pictureValue.render();
|
return d->pictureValue.render();
|
||||||
return d->byteVectorValue;
|
return d->byteVectorValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned short ASF::Attribute::toBool() const
|
unsigned short ASF::Attribute::toBool() const {
|
||||||
{
|
|
||||||
return d->numericValue ? 1 : 0;
|
return d->numericValue ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned short ASF::Attribute::toUShort() const
|
unsigned short ASF::Attribute::toUShort() const {
|
||||||
{
|
|
||||||
return static_cast<unsigned short>(d->numericValue);
|
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);
|
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);
|
return static_cast<unsigned long long>(d->numericValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASF::Picture ASF::Attribute::toPicture() const
|
ASF::Picture ASF::Attribute::toPicture() const {
|
||||||
{
|
|
||||||
return d->pictureValue;
|
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;
|
unsigned int size, nameLength;
|
||||||
String name;
|
String name;
|
||||||
d->pictureValue = Picture::fromInvalid();
|
d->pictureValue = Picture::fromInvalid();
|
||||||
// extended content descriptor
|
// extended content descriptor
|
||||||
if(kind == 0) {
|
if (kind == 0) {
|
||||||
nameLength = readWORD(&f);
|
nameLength = readWORD(&f);
|
||||||
name = readString(&f, nameLength);
|
name = readString(&f, nameLength);
|
||||||
d->type = ASF::Attribute::AttributeTypes(readWORD(&f));
|
d->type = ASF::Attribute::AttributeTypes(readWORD(&f));
|
||||||
@ -192,7 +160,7 @@ String ASF::Attribute::parse(ASF::File &f, int kind)
|
|||||||
else {
|
else {
|
||||||
int temp = readWORD(&f);
|
int temp = readWORD(&f);
|
||||||
// metadata library
|
// metadata library
|
||||||
if(kind == 2) {
|
if (kind == 2) {
|
||||||
d->language = temp;
|
d->language = temp;
|
||||||
}
|
}
|
||||||
d->stream = readWORD(&f);
|
d->stream = readWORD(&f);
|
||||||
@ -202,45 +170,45 @@ String ASF::Attribute::parse(ASF::File &f, int kind)
|
|||||||
name = readString(&f, nameLength);
|
name = readString(&f, nameLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(kind != 2 && size > 65535) {
|
if (kind != 2 && size > 65535) {
|
||||||
debug("ASF::Attribute::parse() -- Value larger than 64kB");
|
debug("ASF::Attribute::parse() -- Value larger than 64kB");
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(d->type) {
|
switch (d->type) {
|
||||||
case WordType:
|
case WordType:
|
||||||
d->numericValue = readWORD(&f);
|
d->numericValue = readWORD(&f);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BoolType:
|
case BoolType:
|
||||||
if(kind == 0) {
|
if (kind == 0) {
|
||||||
d->numericValue = (readDWORD(&f) != 0);
|
d->numericValue = (readDWORD(&f) != 0);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
d->numericValue = (readWORD(&f) != 0);
|
d->numericValue = (readWORD(&f) != 0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DWordType:
|
case DWordType:
|
||||||
d->numericValue = readDWORD(&f);
|
d->numericValue = readDWORD(&f);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QWordType:
|
case QWordType:
|
||||||
d->numericValue = readQWORD(&f);
|
d->numericValue = readQWORD(&f);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UnicodeType:
|
case UnicodeType:
|
||||||
d->stringValue = readString(&f, size);
|
d->stringValue = readString(&f, size);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BytesType:
|
case BytesType:
|
||||||
case GuidType:
|
case GuidType:
|
||||||
d->byteVectorValue = f.readBlock(size);
|
d->byteVectorValue = f.readBlock(size);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(d->type == BytesType && name == "WM/Picture") {
|
if (d->type == BytesType && name == "WM/Picture") {
|
||||||
d->pictureValue.parse(d->byteVectorValue);
|
d->pictureValue.parse(d->byteVectorValue);
|
||||||
if(d->pictureValue.isValid()) {
|
if (d->pictureValue.isValid()) {
|
||||||
d->byteVectorValue.clear();
|
d->byteVectorValue.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -248,106 +216,100 @@ String ASF::Attribute::parse(ASF::File &f, int kind)
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ASF::Attribute::dataSize() const
|
int ASF::Attribute::dataSize() const {
|
||||||
{
|
|
||||||
switch (d->type) {
|
switch (d->type) {
|
||||||
case WordType:
|
case WordType:
|
||||||
return 2;
|
return 2;
|
||||||
case BoolType:
|
case BoolType:
|
||||||
return 4;
|
return 4;
|
||||||
case DWordType:
|
case DWordType:
|
||||||
return 4;
|
return 4;
|
||||||
case QWordType:
|
case QWordType:
|
||||||
return 5;
|
return 5;
|
||||||
case UnicodeType:
|
case UnicodeType:
|
||||||
return d->stringValue.size() * 2 + 2;
|
return d->stringValue.size() * 2 + 2;
|
||||||
case BytesType:
|
case BytesType:
|
||||||
if(d->pictureValue.isValid())
|
if (d->pictureValue.isValid())
|
||||||
return d->pictureValue.dataSize();
|
return d->pictureValue.dataSize();
|
||||||
break;
|
break;
|
||||||
case GuidType:
|
case GuidType:
|
||||||
return d->byteVectorValue.size();
|
return d->byteVectorValue.size();
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector ASF::Attribute::render(const String &name, int kind) const
|
ByteVector ASF::Attribute::render(const String &name, int kind) const {
|
||||||
{
|
|
||||||
ByteVector data;
|
ByteVector data;
|
||||||
|
|
||||||
switch (d->type) {
|
switch (d->type) {
|
||||||
case WordType:
|
case WordType:
|
||||||
data.append(ByteVector::fromShort(toUShort(), false));
|
data.append(ByteVector::fromShort(toUShort(), false));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BoolType:
|
case BoolType:
|
||||||
if(kind == 0) {
|
if (kind == 0) {
|
||||||
data.append(ByteVector::fromUInt(toBool(), false));
|
data.append(ByteVector::fromUInt(toBool(), false));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
data.append(ByteVector::fromShort(toBool(), false));
|
data.append(ByteVector::fromShort(toBool(), false));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DWordType:
|
case DWordType:
|
||||||
data.append(ByteVector::fromUInt(toUInt(), false));
|
data.append(ByteVector::fromUInt(toUInt(), false));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QWordType:
|
case QWordType:
|
||||||
data.append(ByteVector::fromLongLong(toULongLong(), false));
|
data.append(ByteVector::fromLongLong(toULongLong(), false));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UnicodeType:
|
case UnicodeType:
|
||||||
data.append(renderString(d->stringValue));
|
data.append(renderString(d->stringValue));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BytesType:
|
case BytesType:
|
||||||
if(d->pictureValue.isValid()) {
|
if (d->pictureValue.isValid()) {
|
||||||
data.append(d->pictureValue.render());
|
data.append(d->pictureValue.render());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case GuidType:
|
||||||
|
data.append(d->byteVectorValue);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
break;
|
|
||||||
case GuidType:
|
|
||||||
data.append(d->byteVectorValue);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(kind == 0) {
|
if (kind == 0) {
|
||||||
data = renderString(name, true) +
|
data = renderString(name, true) +
|
||||||
ByteVector::fromShort((int)d->type, false) +
|
ByteVector::fromShort((int)d->type, false) +
|
||||||
ByteVector::fromShort(data.size(), false) +
|
ByteVector::fromShort(data.size(), false) +
|
||||||
data;
|
data;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ByteVector nameData = renderString(name);
|
ByteVector nameData = renderString(name);
|
||||||
data = ByteVector::fromShort(kind == 2 ? d->language : 0, false) +
|
data = ByteVector::fromShort(kind == 2 ? d->language : 0, false) +
|
||||||
ByteVector::fromShort(d->stream, false) +
|
ByteVector::fromShort(d->stream, false) +
|
||||||
ByteVector::fromShort(nameData.size(), false) +
|
ByteVector::fromShort(nameData.size(), false) +
|
||||||
ByteVector::fromShort((int)d->type, false) +
|
ByteVector::fromShort((int)d->type, false) +
|
||||||
ByteVector::fromUInt(data.size(), false) +
|
ByteVector::fromUInt(data.size(), false) +
|
||||||
nameData +
|
nameData +
|
||||||
data;
|
data;
|
||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ASF::Attribute::language() const
|
int ASF::Attribute::language() const {
|
||||||
{
|
|
||||||
return d->language;
|
return d->language;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASF::Attribute::setLanguage(int value)
|
void ASF::Attribute::setLanguage(int value) {
|
||||||
{
|
|
||||||
d->language = value;
|
d->language = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ASF::Attribute::stream() const
|
int ASF::Attribute::stream() const {
|
||||||
{
|
|
||||||
return d->stream;
|
return d->stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASF::Attribute::setStream(int value)
|
void ASF::Attribute::setStream(int value) {
|
||||||
{
|
|
||||||
d->stream = value;
|
d->stream = value;
|
||||||
}
|
}
|
||||||
|
158
3rdparty/taglib/asf/asfattribute.h
vendored
158
3rdparty/taglib/asf/asfattribute.h
vendored
@ -32,48 +32,44 @@
|
|||||||
#include "asfpicture.h"
|
#include "asfpicture.h"
|
||||||
|
|
||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib
|
namespace TagLib {
|
||||||
{
|
|
||||||
|
|
||||||
namespace ASF
|
namespace ASF {
|
||||||
{
|
|
||||||
|
|
||||||
class File;
|
class File;
|
||||||
class Picture;
|
class Picture;
|
||||||
|
|
||||||
class TAGLIB_EXPORT Attribute
|
class TAGLIB_EXPORT Attribute {
|
||||||
{
|
public:
|
||||||
public:
|
/*!
|
||||||
|
|
||||||
/*!
|
|
||||||
* Enum of types an Attribute can have.
|
* Enum of types an Attribute can have.
|
||||||
*/
|
*/
|
||||||
enum AttributeTypes {
|
enum AttributeTypes {
|
||||||
UnicodeType = 0,
|
UnicodeType = 0,
|
||||||
BytesType = 1,
|
BytesType = 1,
|
||||||
BoolType = 2,
|
BoolType = 2,
|
||||||
DWordType = 3,
|
DWordType = 3,
|
||||||
QWordType = 4,
|
QWordType = 4,
|
||||||
WordType = 5,
|
WordType = 5,
|
||||||
GuidType = 6
|
GuidType = 6
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs an empty attribute.
|
* Constructs an empty attribute.
|
||||||
*/
|
*/
|
||||||
Attribute();
|
Attribute();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs an attribute with \a key and a UnicodeType \a value.
|
* Constructs an attribute with \a key and a UnicodeType \a value.
|
||||||
*/
|
*/
|
||||||
Attribute(const String &value);
|
Attribute(const String &value);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs an attribute with \a key and a BytesType \a value.
|
* Constructs an attribute with \a key and a BytesType \a value.
|
||||||
*/
|
*/
|
||||||
Attribute(const ByteVector &value);
|
Attribute(const ByteVector &value);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs an attribute with \a key and a Picture \a value.
|
* Constructs an attribute with \a key and a Picture \a value.
|
||||||
*
|
*
|
||||||
* This attribute is compatible with the ID3 frame, APIC. The ID3 specification for the APIC frame stipulates that,
|
* This attribute is compatible with the ID3 frame, APIC. The ID3 specification for the APIC frame stipulates that,
|
||||||
@ -84,127 +80,127 @@ namespace TagLib
|
|||||||
* WM/Picture attributes added with TagLib::ASF are not automatically validated to conform to ID3 specifications.
|
* WM/Picture attributes added with TagLib::ASF are not automatically validated to conform to ID3 specifications.
|
||||||
* You must add code in your application to perform validations if you want to maintain complete compatibility with ID3.
|
* You must add code in your application to perform validations if you want to maintain complete compatibility with ID3.
|
||||||
*/
|
*/
|
||||||
Attribute(const Picture &value);
|
Attribute(const Picture &value);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs an attribute with \a key and a DWordType \a value.
|
* Constructs an attribute with \a key and a DWordType \a value.
|
||||||
*/
|
*/
|
||||||
Attribute(unsigned int value);
|
Attribute(unsigned int value);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs an attribute with \a key and a QWordType \a value.
|
* Constructs an attribute with \a key and a QWordType \a value.
|
||||||
*/
|
*/
|
||||||
Attribute(unsigned long long value);
|
Attribute(unsigned long long value);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs an attribute with \a key and a WordType \a value.
|
* Constructs an attribute with \a key and a WordType \a value.
|
||||||
*/
|
*/
|
||||||
Attribute(unsigned short value);
|
Attribute(unsigned short value);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs an attribute with \a key and a BoolType \a value.
|
* Constructs an attribute with \a key and a BoolType \a value.
|
||||||
*/
|
*/
|
||||||
Attribute(bool value);
|
Attribute(bool value);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Construct an attribute as a copy of \a other.
|
* Construct an attribute as a copy of \a other.
|
||||||
*/
|
*/
|
||||||
Attribute(const Attribute &item);
|
Attribute(const Attribute &item);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Copies the contents of \a other into this item.
|
* Copies the contents of \a other into this item.
|
||||||
*/
|
*/
|
||||||
Attribute &operator=(const Attribute &other);
|
Attribute &operator=(const Attribute &other);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Exchanges the content of the Attribute by the content of \a other.
|
* Exchanges the content of the Attribute by the content of \a other.
|
||||||
*/
|
*/
|
||||||
void swap(Attribute &other);
|
void swap(Attribute &other);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys the attribute.
|
* Destroys the attribute.
|
||||||
*/
|
*/
|
||||||
virtual ~Attribute();
|
virtual ~Attribute();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns type of the value.
|
* Returns type of the value.
|
||||||
*/
|
*/
|
||||||
AttributeTypes type() const;
|
AttributeTypes type() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the BoolType \a value.
|
* Returns the BoolType \a value.
|
||||||
*/
|
*/
|
||||||
unsigned short toBool() const;
|
unsigned short toBool() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the WordType \a value.
|
* Returns the WordType \a value.
|
||||||
*/
|
*/
|
||||||
unsigned short toUShort() const;
|
unsigned short toUShort() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the DWordType \a value.
|
* Returns the DWordType \a value.
|
||||||
*/
|
*/
|
||||||
unsigned int toUInt() const;
|
unsigned int toUInt() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the QWordType \a value.
|
* Returns the QWordType \a value.
|
||||||
*/
|
*/
|
||||||
unsigned long long toULongLong() const;
|
unsigned long long toULongLong() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the UnicodeType \a value.
|
* Returns the UnicodeType \a value.
|
||||||
*/
|
*/
|
||||||
String toString() const;
|
String toString() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the BytesType \a value.
|
* Returns the BytesType \a value.
|
||||||
*/
|
*/
|
||||||
ByteVector toByteVector() const;
|
ByteVector toByteVector() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the Picture \a value.
|
* Returns the Picture \a value.
|
||||||
*/
|
*/
|
||||||
Picture toPicture() const;
|
Picture toPicture() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the language number, or 0 is no stream number was set.
|
* Returns the language number, or 0 is no stream number was set.
|
||||||
*/
|
*/
|
||||||
int language() const;
|
int language() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the language number.
|
* Sets the language number.
|
||||||
*/
|
*/
|
||||||
void setLanguage(int value);
|
void setLanguage(int value);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the stream number, or 0 is no stream number was set.
|
* Returns the stream number, or 0 is no stream number was set.
|
||||||
*/
|
*/
|
||||||
int stream() const;
|
int stream() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the stream number.
|
* Sets the stream number.
|
||||||
*/
|
*/
|
||||||
void setStream(int value);
|
void setStream(int value);
|
||||||
|
|
||||||
#ifndef DO_NOT_DOCUMENT
|
#ifndef DO_NOT_DOCUMENT
|
||||||
/* THIS IS PRIVATE, DON'T TOUCH IT! */
|
/* THIS IS PRIVATE, DON'T TOUCH IT! */
|
||||||
String parse(ASF::File &file, int kind = 0);
|
String parse(ASF::File &file, int kind = 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//! Returns the size of the stored data
|
//! Returns the size of the stored data
|
||||||
int dataSize() const;
|
int dataSize() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class File;
|
friend class File;
|
||||||
|
|
||||||
ByteVector render(const String &name, int kind = 0) const;
|
ByteVector render(const String &name, int kind = 0) const;
|
||||||
|
|
||||||
class AttributePrivate;
|
class AttributePrivate;
|
||||||
AttributePrivate *d;
|
AttributePrivate *d;
|
||||||
};
|
};
|
||||||
}
|
} // namespace ASF
|
||||||
|
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
358
3rdparty/taglib/asf/asffile.cpp
vendored
358
3rdparty/taglib/asf/asffile.cpp
vendored
@ -36,9 +36,8 @@
|
|||||||
|
|
||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
class ASF::File::FilePrivate
|
class ASF::File::FilePrivate {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
class BaseObject;
|
class BaseObject;
|
||||||
class UnknownObject;
|
class UnknownObject;
|
||||||
class FilePropertiesObject;
|
class FilePropertiesObject;
|
||||||
@ -50,21 +49,18 @@ public:
|
|||||||
class MetadataObject;
|
class MetadataObject;
|
||||||
class MetadataLibraryObject;
|
class MetadataLibraryObject;
|
||||||
|
|
||||||
FilePrivate():
|
FilePrivate() : headerSize(0),
|
||||||
headerSize(0),
|
tag(0),
|
||||||
tag(0),
|
properties(0),
|
||||||
properties(0),
|
contentDescriptionObject(0),
|
||||||
contentDescriptionObject(0),
|
extendedContentDescriptionObject(0),
|
||||||
extendedContentDescriptionObject(0),
|
headerExtensionObject(0),
|
||||||
headerExtensionObject(0),
|
metadataObject(0),
|
||||||
metadataObject(0),
|
metadataLibraryObject(0) {
|
||||||
metadataLibraryObject(0)
|
|
||||||
{
|
|
||||||
objects.setAutoDelete(true);
|
objects.setAutoDelete(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
~FilePrivate()
|
~FilePrivate() {
|
||||||
{
|
|
||||||
delete tag;
|
delete tag;
|
||||||
delete properties;
|
delete properties;
|
||||||
}
|
}
|
||||||
@ -76,32 +72,30 @@ public:
|
|||||||
|
|
||||||
List<BaseObject *> objects;
|
List<BaseObject *> objects;
|
||||||
|
|
||||||
ContentDescriptionObject *contentDescriptionObject;
|
ContentDescriptionObject *contentDescriptionObject;
|
||||||
ExtendedContentDescriptionObject *extendedContentDescriptionObject;
|
ExtendedContentDescriptionObject *extendedContentDescriptionObject;
|
||||||
HeaderExtensionObject *headerExtensionObject;
|
HeaderExtensionObject *headerExtensionObject;
|
||||||
MetadataObject *metadataObject;
|
MetadataObject *metadataObject;
|
||||||
MetadataLibraryObject *metadataLibraryObject;
|
MetadataLibraryObject *metadataLibraryObject;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace
|
namespace {
|
||||||
{
|
const ByteVector headerGuid("\x30\x26\xB2\x75\x8E\x66\xCF\x11\xA6\xD9\x00\xAA\x00\x62\xCE\x6C", 16);
|
||||||
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 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 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 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 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 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 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 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 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 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 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);
|
||||||
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
|
class ASF::File::FilePrivate::BaseObject {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
ByteVector data;
|
ByteVector data;
|
||||||
virtual ~BaseObject() {}
|
virtual ~BaseObject() {}
|
||||||
virtual ByteVector guid() const = 0;
|
virtual ByteVector guid() const = 0;
|
||||||
@ -109,66 +103,59 @@ public:
|
|||||||
virtual ByteVector render(ASF::File *file);
|
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;
|
ByteVector myGuid;
|
||||||
public:
|
|
||||||
|
public:
|
||||||
explicit UnknownObject(const ByteVector &guid);
|
explicit UnknownObject(const ByteVector &guid);
|
||||||
ByteVector guid() const;
|
ByteVector guid() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ASF::File::FilePrivate::FilePropertiesObject : public ASF::File::FilePrivate::BaseObject
|
class ASF::File::FilePrivate::FilePropertiesObject : public ASF::File::FilePrivate::BaseObject {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
ByteVector guid() const;
|
ByteVector guid() const;
|
||||||
void parse(ASF::File *file, unsigned int size);
|
void parse(ASF::File *file, unsigned int size);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ASF::File::FilePrivate::StreamPropertiesObject : public ASF::File::FilePrivate::BaseObject
|
class ASF::File::FilePrivate::StreamPropertiesObject : public ASF::File::FilePrivate::BaseObject {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
ByteVector guid() const;
|
ByteVector guid() const;
|
||||||
void parse(ASF::File *file, unsigned int size);
|
void parse(ASF::File *file, unsigned int size);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ASF::File::FilePrivate::ContentDescriptionObject : public ASF::File::FilePrivate::BaseObject
|
class ASF::File::FilePrivate::ContentDescriptionObject : public ASF::File::FilePrivate::BaseObject {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
ByteVector guid() const;
|
ByteVector guid() const;
|
||||||
void parse(ASF::File *file, unsigned int size);
|
void parse(ASF::File *file, unsigned int size);
|
||||||
ByteVector render(ASF::File *file);
|
ByteVector render(ASF::File *file);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ASF::File::FilePrivate::ExtendedContentDescriptionObject : public ASF::File::FilePrivate::BaseObject
|
class ASF::File::FilePrivate::ExtendedContentDescriptionObject : public ASF::File::FilePrivate::BaseObject {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
ByteVectorList attributeData;
|
ByteVectorList attributeData;
|
||||||
ByteVector guid() const;
|
ByteVector guid() const;
|
||||||
void parse(ASF::File *file, unsigned int size);
|
void parse(ASF::File *file, unsigned int size);
|
||||||
ByteVector render(ASF::File *file);
|
ByteVector render(ASF::File *file);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ASF::File::FilePrivate::MetadataObject : public ASF::File::FilePrivate::BaseObject
|
class ASF::File::FilePrivate::MetadataObject : public ASF::File::FilePrivate::BaseObject {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
ByteVectorList attributeData;
|
ByteVectorList attributeData;
|
||||||
ByteVector guid() const;
|
ByteVector guid() const;
|
||||||
void parse(ASF::File *file, unsigned int size);
|
void parse(ASF::File *file, unsigned int size);
|
||||||
ByteVector render(ASF::File *file);
|
ByteVector render(ASF::File *file);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ASF::File::FilePrivate::MetadataLibraryObject : public ASF::File::FilePrivate::BaseObject
|
class ASF::File::FilePrivate::MetadataLibraryObject : public ASF::File::FilePrivate::BaseObject {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
ByteVectorList attributeData;
|
ByteVectorList attributeData;
|
||||||
ByteVector guid() const;
|
ByteVector guid() const;
|
||||||
void parse(ASF::File *file, unsigned int size);
|
void parse(ASF::File *file, unsigned int size);
|
||||||
ByteVector render(ASF::File *file);
|
ByteVector render(ASF::File *file);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ASF::File::FilePrivate::HeaderExtensionObject : public ASF::File::FilePrivate::BaseObject
|
class ASF::File::FilePrivate::HeaderExtensionObject : public ASF::File::FilePrivate::BaseObject {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
List<ASF::File::FilePrivate::BaseObject *> objects;
|
List<ASF::File::FilePrivate::BaseObject *> objects;
|
||||||
HeaderExtensionObject();
|
HeaderExtensionObject();
|
||||||
ByteVector guid() const;
|
ByteVector guid() const;
|
||||||
@ -176,71 +163,61 @@ public:
|
|||||||
ByteVector render(ASF::File *file);
|
ByteVector render(ASF::File *file);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ASF::File::FilePrivate::CodecListObject : public ASF::File::FilePrivate::BaseObject
|
class ASF::File::FilePrivate::CodecListObject : public ASF::File::FilePrivate::BaseObject {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
ByteVector guid() const;
|
ByteVector guid() const;
|
||||||
void parse(ASF::File *file, unsigned int size);
|
void parse(ASF::File *file, unsigned int size);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum CodecType
|
enum CodecType {
|
||||||
{
|
Video = 0x0001,
|
||||||
Video = 0x0001,
|
Audio = 0x0002,
|
||||||
Audio = 0x0002,
|
|
||||||
Unknown = 0xFFFF
|
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();
|
data.clear();
|
||||||
if(size > 24 && size <= (unsigned int)(file->length()))
|
if (size > 24 && size <= (unsigned int)(file->length()))
|
||||||
data = file->readBlock(size - 24);
|
data = file->readBlock(size - 24);
|
||||||
else
|
else
|
||||||
data = ByteVector();
|
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;
|
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;
|
return myGuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector ASF::File::FilePrivate::FilePropertiesObject::guid() const
|
ByteVector ASF::File::FilePrivate::FilePropertiesObject::guid() const {
|
||||||
{
|
|
||||||
return filePropertiesGuid;
|
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);
|
BaseObject::parse(file, size);
|
||||||
if(data.size() < 64) {
|
if (data.size() < 64) {
|
||||||
debug("ASF::File::FilePrivate::FilePropertiesObject::parse() -- data is too short.");
|
debug("ASF::File::FilePrivate::FilePropertiesObject::parse() -- data is too short.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const long long duration = data.toLongLong(40, false);
|
const long long duration = data.toLongLong(40, false);
|
||||||
const long long preroll = data.toLongLong(56, false);
|
const long long preroll = data.toLongLong(56, false);
|
||||||
file->d->properties->setLengthInMilliseconds(static_cast<int>(duration / 10000.0 - preroll + 0.5));
|
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;
|
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);
|
BaseObject::parse(file, size);
|
||||||
if(data.size() < 70) {
|
if (data.size() < 70) {
|
||||||
debug("ASF::File::FilePrivate::StreamPropertiesObject::parse() -- data is too short.");
|
debug("ASF::File::FilePrivate::StreamPropertiesObject::parse() -- data is too short.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -252,27 +229,24 @@ void ASF::File::FilePrivate::StreamPropertiesObject::parse(ASF::File *file, unsi
|
|||||||
file->d->properties->setBitsPerSample(data.toUShort(68, false));
|
file->d->properties->setBitsPerSample(data.toUShort(68, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector ASF::File::FilePrivate::ContentDescriptionObject::guid() const
|
ByteVector ASF::File::FilePrivate::ContentDescriptionObject::guid() const {
|
||||||
{
|
|
||||||
return contentDescriptionGuid;
|
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 titleLength = readWORD(file);
|
const int artistLength = readWORD(file);
|
||||||
const int artistLength = readWORD(file);
|
|
||||||
const int copyrightLength = readWORD(file);
|
const int copyrightLength = readWORD(file);
|
||||||
const int commentLength = readWORD(file);
|
const int commentLength = readWORD(file);
|
||||||
const int ratingLength = readWORD(file);
|
const int ratingLength = readWORD(file);
|
||||||
file->d->tag->setTitle(readString(file,titleLength));
|
file->d->tag->setTitle(readString(file, titleLength));
|
||||||
file->d->tag->setArtist(readString(file,artistLength));
|
file->d->tag->setArtist(readString(file, artistLength));
|
||||||
file->d->tag->setCopyright(readString(file,copyrightLength));
|
file->d->tag->setCopyright(readString(file, copyrightLength));
|
||||||
file->d->tag->setComment(readString(file,commentLength));
|
file->d->tag->setComment(readString(file, commentLength));
|
||||||
file->d->tag->setRating(readString(file,ratingLength));
|
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 v1 = renderString(file->d->tag->title());
|
||||||
const ByteVector v2 = renderString(file->d->tag->artist());
|
const ByteVector v2 = renderString(file->d->tag->artist());
|
||||||
const ByteVector v3 = renderString(file->d->tag->copyright());
|
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);
|
return BaseObject::render(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector ASF::File::FilePrivate::ExtendedContentDescriptionObject::guid() const
|
ByteVector ASF::File::FilePrivate::ExtendedContentDescriptionObject::guid() const {
|
||||||
{
|
|
||||||
return extendedContentDescriptionGuid;
|
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);
|
int count = readWORD(file);
|
||||||
while(count--) {
|
while (count--) {
|
||||||
ASF::Attribute attribute;
|
ASF::Attribute attribute;
|
||||||
String name = attribute.parse(*file);
|
String name = attribute.parse(*file);
|
||||||
file->d->tag->addAttribute(name, attribute);
|
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.clear();
|
||||||
data.append(ByteVector::fromShort(attributeData.size(), false));
|
data.append(ByteVector::fromShort(attributeData.size(), false));
|
||||||
data.append(attributeData.toByteVector(""));
|
data.append(attributeData.toByteVector(""));
|
||||||
return BaseObject::render(file);
|
return BaseObject::render(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector ASF::File::FilePrivate::MetadataObject::guid() const
|
ByteVector ASF::File::FilePrivate::MetadataObject::guid() const {
|
||||||
{
|
|
||||||
return metadataGuid;
|
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);
|
int count = readWORD(file);
|
||||||
while(count--) {
|
while (count--) {
|
||||||
ASF::Attribute attribute;
|
ASF::Attribute attribute;
|
||||||
String name = attribute.parse(*file, 1);
|
String name = attribute.parse(*file, 1);
|
||||||
file->d->tag->addAttribute(name, attribute);
|
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.clear();
|
||||||
data.append(ByteVector::fromShort(attributeData.size(), false));
|
data.append(ByteVector::fromShort(attributeData.size(), false));
|
||||||
data.append(attributeData.toByteVector(""));
|
data.append(attributeData.toByteVector(""));
|
||||||
return BaseObject::render(file);
|
return BaseObject::render(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector ASF::File::FilePrivate::MetadataLibraryObject::guid() const
|
ByteVector ASF::File::FilePrivate::MetadataLibraryObject::guid() const {
|
||||||
{
|
|
||||||
return metadataLibraryGuid;
|
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);
|
int count = readWORD(file);
|
||||||
while(count--) {
|
while (count--) {
|
||||||
ASF::Attribute attribute;
|
ASF::Attribute attribute;
|
||||||
String name = attribute.parse(*file, 2);
|
String name = attribute.parse(*file, 2);
|
||||||
file->d->tag->addAttribute(name, attribute);
|
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.clear();
|
||||||
data.append(ByteVector::fromShort(attributeData.size(), false));
|
data.append(ByteVector::fromShort(attributeData.size(), false));
|
||||||
data.append(attributeData.toByteVector(""));
|
data.append(attributeData.toByteVector(""));
|
||||||
return BaseObject::render(file);
|
return BaseObject::render(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASF::File::FilePrivate::HeaderExtensionObject::HeaderExtensionObject()
|
ASF::File::FilePrivate::HeaderExtensionObject::HeaderExtensionObject() {
|
||||||
{
|
|
||||||
objects.setAutoDelete(true);
|
objects.setAutoDelete(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector ASF::File::FilePrivate::HeaderExtensionObject::guid() const
|
ByteVector ASF::File::FilePrivate::HeaderExtensionObject::guid() const {
|
||||||
{
|
|
||||||
return headerExtensionGuid;
|
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);
|
file->seek(18, File::Current);
|
||||||
long long dataSize = readDWORD(file);
|
long long dataSize = readDWORD(file);
|
||||||
long long dataPos = 0;
|
long long dataPos = 0;
|
||||||
while(dataPos < dataSize) {
|
while (dataPos < dataSize) {
|
||||||
ByteVector guid = file->readBlock(16);
|
ByteVector guid = file->readBlock(16);
|
||||||
if(guid.size() != 16) {
|
if (guid.size() != 16) {
|
||||||
file->setValid(false);
|
file->setValid(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
bool ok;
|
bool ok;
|
||||||
long long size = readQWORD(file, &ok);
|
long long size = readQWORD(file, &ok);
|
||||||
if(!ok) {
|
if (!ok) {
|
||||||
file->setValid(false);
|
file->setValid(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
BaseObject *obj;
|
BaseObject *obj;
|
||||||
if(guid == metadataGuid) {
|
if (guid == metadataGuid) {
|
||||||
file->d->metadataObject = new MetadataObject();
|
file->d->metadataObject = new MetadataObject();
|
||||||
obj = file->d->metadataObject;
|
obj = file->d->metadataObject;
|
||||||
}
|
}
|
||||||
else if(guid == metadataLibraryGuid) {
|
else if (guid == metadataLibraryGuid) {
|
||||||
file->d->metadataLibraryObject = new MetadataLibraryObject();
|
file->d->metadataLibraryObject = new MetadataLibraryObject();
|
||||||
obj = file->d->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();
|
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.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;
|
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);
|
return BaseObject::render(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector ASF::File::FilePrivate::CodecListObject::guid() const
|
ByteVector ASF::File::FilePrivate::CodecListObject::guid() const {
|
||||||
{
|
|
||||||
return codecListGuid;
|
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);
|
BaseObject::parse(file, size);
|
||||||
if(data.size() <= 20) {
|
if (data.size() <= 20) {
|
||||||
debug("ASF::File::FilePrivate::CodecListObject::parse() -- data is too short.");
|
debug("ASF::File::FilePrivate::CodecListObject::parse() -- data is too short.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -434,9 +393,9 @@ void ASF::File::FilePrivate::CodecListObject::parse(ASF::File *file, unsigned in
|
|||||||
const int count = data.toUInt(pos, false);
|
const int count = data.toUInt(pos, false);
|
||||||
pos += 4;
|
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;
|
break;
|
||||||
|
|
||||||
const CodecType type = static_cast<CodecType>(data.toUShort(pos, false));
|
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);
|
const int infoLength = data.toUShort(pos, false);
|
||||||
pos += 2 + infoLength * 2;
|
pos += 2 + infoLength * 2;
|
||||||
|
|
||||||
if(type == CodecListObject::Audio) {
|
if (type == CodecListObject::Audio) {
|
||||||
// First audio codec found.
|
// First audio codec found.
|
||||||
|
|
||||||
const String name(data.mid(namePos, nameLength * 2), String::UTF16LE);
|
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
|
// static members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
bool ASF::File::isSupported(IOStream *stream)
|
bool ASF::File::isSupported(IOStream *stream) {
|
||||||
{
|
|
||||||
// An ASF file has to start with the designated GUID.
|
// An ASF file has to start with the designated GUID.
|
||||||
|
|
||||||
const ByteVector id = Utils::readHeader(stream, 16, false);
|
const ByteVector id = Utils::readHeader(stream, 16, false);
|
||||||
@ -487,81 +445,70 @@ bool ASF::File::isSupported(IOStream *stream)
|
|||||||
// public members
|
// public members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ASF::File::File(FileName file, bool, Properties::ReadStyle) :
|
ASF::File::File(FileName file, bool, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file),
|
||||||
Strawberry_TagLib::TagLib::File(file),
|
d(new FilePrivate()) {
|
||||||
d(new FilePrivate())
|
if (isOpen())
|
||||||
{
|
|
||||||
if(isOpen())
|
|
||||||
read();
|
read();
|
||||||
}
|
}
|
||||||
|
|
||||||
ASF::File::File(IOStream *stream, bool, Properties::ReadStyle) :
|
ASF::File::File(IOStream *stream, bool, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(stream),
|
||||||
Strawberry_TagLib::TagLib::File(stream),
|
d(new FilePrivate()) {
|
||||||
d(new FilePrivate())
|
if (isOpen())
|
||||||
{
|
|
||||||
if(isOpen())
|
|
||||||
read();
|
read();
|
||||||
}
|
}
|
||||||
|
|
||||||
ASF::File::~File()
|
ASF::File::~File() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASF::Tag *ASF::File::tag() const
|
ASF::Tag *ASF::File::tag() const {
|
||||||
{
|
|
||||||
return d->tag;
|
return d->tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyMap ASF::File::properties() const
|
PropertyMap ASF::File::properties() const {
|
||||||
{
|
|
||||||
return d->tag->properties();
|
return d->tag->properties();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASF::File::removeUnsupportedProperties(const StringList &properties)
|
void ASF::File::removeUnsupportedProperties(const StringList &properties) {
|
||||||
{
|
|
||||||
d->tag->removeUnsupportedProperties(properties);
|
d->tag->removeUnsupportedProperties(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyMap ASF::File::setProperties(const PropertyMap &properties)
|
PropertyMap ASF::File::setProperties(const PropertyMap &properties) {
|
||||||
{
|
|
||||||
return d->tag->setProperties(properties);
|
return d->tag->setProperties(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASF::Properties *ASF::File::audioProperties() const
|
ASF::Properties *ASF::File::audioProperties() const {
|
||||||
{
|
|
||||||
return d->properties;
|
return d->properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ASF::File::save()
|
bool ASF::File::save() {
|
||||||
{
|
if (readOnly()) {
|
||||||
if(readOnly()) {
|
|
||||||
debug("ASF::File::save() -- File is read only.");
|
debug("ASF::File::save() -- File is read only.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!isValid()) {
|
if (!isValid()) {
|
||||||
debug("ASF::File::save() -- Trying to save invalid file.");
|
debug("ASF::File::save() -- Trying to save invalid file.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!d->contentDescriptionObject) {
|
if (!d->contentDescriptionObject) {
|
||||||
d->contentDescriptionObject = new FilePrivate::ContentDescriptionObject();
|
d->contentDescriptionObject = new FilePrivate::ContentDescriptionObject();
|
||||||
d->objects.append(d->contentDescriptionObject);
|
d->objects.append(d->contentDescriptionObject);
|
||||||
}
|
}
|
||||||
if(!d->extendedContentDescriptionObject) {
|
if (!d->extendedContentDescriptionObject) {
|
||||||
d->extendedContentDescriptionObject = new FilePrivate::ExtendedContentDescriptionObject();
|
d->extendedContentDescriptionObject = new FilePrivate::ExtendedContentDescriptionObject();
|
||||||
d->objects.append(d->extendedContentDescriptionObject);
|
d->objects.append(d->extendedContentDescriptionObject);
|
||||||
}
|
}
|
||||||
if(!d->headerExtensionObject) {
|
if (!d->headerExtensionObject) {
|
||||||
d->headerExtensionObject = new FilePrivate::HeaderExtensionObject();
|
d->headerExtensionObject = new FilePrivate::HeaderExtensionObject();
|
||||||
d->objects.append(d->headerExtensionObject);
|
d->objects.append(d->headerExtensionObject);
|
||||||
}
|
}
|
||||||
if(!d->metadataObject) {
|
if (!d->metadataObject) {
|
||||||
d->metadataObject = new FilePrivate::MetadataObject();
|
d->metadataObject = new FilePrivate::MetadataObject();
|
||||||
d->headerExtensionObject->objects.append(d->metadataObject);
|
d->headerExtensionObject->objects.append(d->metadataObject);
|
||||||
}
|
}
|
||||||
if(!d->metadataLibraryObject) {
|
if (!d->metadataLibraryObject) {
|
||||||
d->metadataLibraryObject = new FilePrivate::MetadataLibraryObject();
|
d->metadataLibraryObject = new FilePrivate::MetadataLibraryObject();
|
||||||
d->headerExtensionObject->objects.append(d->metadataLibraryObject);
|
d->headerExtensionObject->objects.append(d->metadataLibraryObject);
|
||||||
}
|
}
|
||||||
@ -572,7 +519,7 @@ bool ASF::File::save()
|
|||||||
|
|
||||||
const AttributeListMap allAttributes = d->tag->attributeListMap();
|
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 String &name = it->first;
|
||||||
const AttributeList &attributes = it->second;
|
const AttributeList &attributes = it->second;
|
||||||
@ -580,17 +527,17 @@ bool ASF::File::save()
|
|||||||
bool inExtendedContentDescriptionObject = false;
|
bool inExtendedContentDescriptionObject = false;
|
||||||
bool inMetadataObject = 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 Attribute &attribute = *jt;
|
||||||
const bool largeValue = (attribute.dataSize() > 65535);
|
const bool largeValue = (attribute.dataSize() > 65535);
|
||||||
const bool guid = (attribute.type() == Attribute::GuidType);
|
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));
|
d->extendedContentDescriptionObject->attributeData.append(attribute.render(name));
|
||||||
inExtendedContentDescriptionObject = true;
|
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));
|
d->metadataObject->attributeData.append(attribute.render(name, 1));
|
||||||
inMetadataObject = true;
|
inMetadataObject = true;
|
||||||
}
|
}
|
||||||
@ -601,7 +548,7 @@ bool ASF::File::save()
|
|||||||
}
|
}
|
||||||
|
|
||||||
ByteVector data;
|
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));
|
data.append((*it)->render(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -621,12 +568,11 @@ bool ASF::File::save()
|
|||||||
// private members
|
// private members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void ASF::File::read()
|
void ASF::File::read() {
|
||||||
{
|
if (!isValid())
|
||||||
if(!isValid())
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(readBlock(16) != headerGuid) {
|
if (readBlock(16) != headerGuid) {
|
||||||
debug("ASF::File::read(): Not an ASF file.");
|
debug("ASF::File::read(): Not an ASF file.");
|
||||||
setValid(false);
|
setValid(false);
|
||||||
return;
|
return;
|
||||||
@ -637,58 +583,58 @@ void ASF::File::read()
|
|||||||
|
|
||||||
bool ok;
|
bool ok;
|
||||||
d->headerSize = readQWORD(this, &ok);
|
d->headerSize = readQWORD(this, &ok);
|
||||||
if(!ok) {
|
if (!ok) {
|
||||||
setValid(false);
|
setValid(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
int numObjects = readDWORD(this, &ok);
|
int numObjects = readDWORD(this, &ok);
|
||||||
if(!ok) {
|
if (!ok) {
|
||||||
setValid(false);
|
setValid(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
seek(2, Current);
|
seek(2, Current);
|
||||||
|
|
||||||
FilePrivate::FilePropertiesObject *filePropertiesObject = 0;
|
FilePrivate::FilePropertiesObject *filePropertiesObject = 0;
|
||||||
FilePrivate::StreamPropertiesObject *streamPropertiesObject = 0;
|
FilePrivate::StreamPropertiesObject *streamPropertiesObject = 0;
|
||||||
for(int i = 0; i < numObjects; i++) {
|
for (int i = 0; i < numObjects; i++) {
|
||||||
const ByteVector guid = readBlock(16);
|
const ByteVector guid = readBlock(16);
|
||||||
if(guid.size() != 16) {
|
if (guid.size() != 16) {
|
||||||
setValid(false);
|
setValid(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
long size = (long)readQWORD(this, &ok);
|
long size = (long)readQWORD(this, &ok);
|
||||||
if(!ok) {
|
if (!ok) {
|
||||||
setValid(false);
|
setValid(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
FilePrivate::BaseObject *obj;
|
FilePrivate::BaseObject *obj;
|
||||||
if(guid == filePropertiesGuid) {
|
if (guid == filePropertiesGuid) {
|
||||||
filePropertiesObject = new FilePrivate::FilePropertiesObject();
|
filePropertiesObject = new FilePrivate::FilePropertiesObject();
|
||||||
obj = filePropertiesObject;
|
obj = filePropertiesObject;
|
||||||
}
|
}
|
||||||
else if(guid == streamPropertiesGuid) {
|
else if (guid == streamPropertiesGuid) {
|
||||||
streamPropertiesObject = new FilePrivate::StreamPropertiesObject();
|
streamPropertiesObject = new FilePrivate::StreamPropertiesObject();
|
||||||
obj = streamPropertiesObject;
|
obj = streamPropertiesObject;
|
||||||
}
|
}
|
||||||
else if(guid == contentDescriptionGuid) {
|
else if (guid == contentDescriptionGuid) {
|
||||||
d->contentDescriptionObject = new FilePrivate::ContentDescriptionObject();
|
d->contentDescriptionObject = new FilePrivate::ContentDescriptionObject();
|
||||||
obj = d->contentDescriptionObject;
|
obj = d->contentDescriptionObject;
|
||||||
}
|
}
|
||||||
else if(guid == extendedContentDescriptionGuid) {
|
else if (guid == extendedContentDescriptionGuid) {
|
||||||
d->extendedContentDescriptionObject = new FilePrivate::ExtendedContentDescriptionObject();
|
d->extendedContentDescriptionObject = new FilePrivate::ExtendedContentDescriptionObject();
|
||||||
obj = d->extendedContentDescriptionObject;
|
obj = d->extendedContentDescriptionObject;
|
||||||
}
|
}
|
||||||
else if(guid == headerExtensionGuid) {
|
else if (guid == headerExtensionGuid) {
|
||||||
d->headerExtensionObject = new FilePrivate::HeaderExtensionObject();
|
d->headerExtensionObject = new FilePrivate::HeaderExtensionObject();
|
||||||
obj = d->headerExtensionObject;
|
obj = d->headerExtensionObject;
|
||||||
}
|
}
|
||||||
else if(guid == codecListGuid) {
|
else if (guid == codecListGuid) {
|
||||||
obj = new FilePrivate::CodecListObject();
|
obj = new FilePrivate::CodecListObject();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(guid == contentEncryptionGuid ||
|
if (guid == contentEncryptionGuid ||
|
||||||
guid == extendedContentEncryptionGuid ||
|
guid == extendedContentEncryptionGuid ||
|
||||||
guid == advancedContentEncryptionGuid) {
|
guid == advancedContentEncryptionGuid) {
|
||||||
d->properties->setEncrypted(true);
|
d->properties->setEncrypted(true);
|
||||||
}
|
}
|
||||||
obj = new FilePrivate::UnknownObject(guid);
|
obj = new FilePrivate::UnknownObject(guid);
|
||||||
@ -697,7 +643,7 @@ void ASF::File::read()
|
|||||||
d->objects.append(obj);
|
d->objects.append(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!filePropertiesObject || !streamPropertiesObject) {
|
if (!filePropertiesObject || !streamPropertiesObject) {
|
||||||
debug("ASF::File::read(): Missing mandatory header objects.");
|
debug("ASF::File::read(): Missing mandatory header objects.");
|
||||||
setValid(false);
|
setValid(false);
|
||||||
return;
|
return;
|
||||||
|
72
3rdparty/taglib/asf/asffile.h
vendored
72
3rdparty/taglib/asf/asffile.h
vendored
@ -35,30 +35,28 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
//! An implementation of ASF (WMA) metadata
|
//! An implementation of ASF (WMA) metadata
|
||||||
namespace ASF {
|
namespace ASF {
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* This implements and provides an interface for ASF files to the
|
* This implements and provides an interface for ASF files to the
|
||||||
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
|
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
|
||||||
* the abstract TagLib::File API as well as providing some additional
|
* the abstract TagLib::File API as well as providing some additional
|
||||||
* information specific to ASF files.
|
* information specific to ASF files.
|
||||||
*/
|
*/
|
||||||
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File
|
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File {
|
||||||
{
|
public:
|
||||||
public:
|
/*!
|
||||||
|
|
||||||
/*!
|
|
||||||
* Constructs an ASF file from \a file.
|
* Constructs an ASF file from \a file.
|
||||||
*
|
*
|
||||||
* \note In the current implementation, both \a readProperties and
|
* \note In the current implementation, both \a readProperties and
|
||||||
* \a propertiesStyle are ignored. The audio properties are always
|
* \a propertiesStyle are ignored. The audio properties are always
|
||||||
* read.
|
* read.
|
||||||
*/
|
*/
|
||||||
File(FileName file, bool readProperties = true,
|
File(FileName file, bool readProperties = true,
|
||||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs an ASF file from \a stream.
|
* Constructs an ASF file from \a stream.
|
||||||
*
|
*
|
||||||
* \note In the current implementation, both \a readProperties and
|
* \note In the current implementation, both \a readProperties and
|
||||||
@ -68,15 +66,15 @@ namespace TagLib {
|
|||||||
* \note TagLib will *not* take ownership of the stream, the caller is
|
* \note TagLib will *not* take ownership of the stream, the caller is
|
||||||
* responsible for deleting it after the File object.
|
* responsible for deleting it after the File object.
|
||||||
*/
|
*/
|
||||||
File(IOStream *stream, bool readProperties = true,
|
File(IOStream *stream, bool readProperties = true,
|
||||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys this instance of the File.
|
* Destroys this instance of the File.
|
||||||
*/
|
*/
|
||||||
virtual ~File();
|
virtual ~File();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns a pointer to the ASF tag of the file.
|
* Returns a pointer to the ASF tag of the file.
|
||||||
*
|
*
|
||||||
* ASF::Tag implements the tag interface, so this serves as the
|
* ASF::Tag implements the tag interface, so this serves as the
|
||||||
@ -86,55 +84,55 @@ namespace TagLib {
|
|||||||
* deleted by the user. It will be deleted when the file (object) is
|
* deleted by the user. It will be deleted when the file (object) is
|
||||||
* destroyed.
|
* destroyed.
|
||||||
*/
|
*/
|
||||||
virtual Tag *tag() const;
|
virtual Tag *tag() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Implements the unified property interface -- export function.
|
* Implements the unified property interface -- export function.
|
||||||
*/
|
*/
|
||||||
PropertyMap properties() const;
|
PropertyMap properties() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Removes unsupported properties. Forwards to the actual Tag's
|
* Removes unsupported properties. Forwards to the actual Tag's
|
||||||
* removeUnsupportedProperties() function.
|
* removeUnsupportedProperties() function.
|
||||||
*/
|
*/
|
||||||
void removeUnsupportedProperties(const StringList &properties);
|
void removeUnsupportedProperties(const StringList &properties);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Implements the unified property interface -- import function.
|
* Implements the unified property interface -- import function.
|
||||||
*/
|
*/
|
||||||
PropertyMap setProperties(const PropertyMap &);
|
PropertyMap setProperties(const PropertyMap &);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the ASF audio properties for this file.
|
* Returns the ASF audio properties for this file.
|
||||||
*/
|
*/
|
||||||
virtual Properties *audioProperties() const;
|
virtual Properties *audioProperties() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Save the file.
|
* Save the file.
|
||||||
*
|
*
|
||||||
* This returns true if the save was successful.
|
* This returns true if the save was successful.
|
||||||
*/
|
*/
|
||||||
virtual bool save();
|
virtual bool save();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns whether or not the given \a stream can be opened as an ASF
|
* Returns whether or not the given \a stream can be opened as an ASF
|
||||||
* file.
|
* file.
|
||||||
*
|
*
|
||||||
* \note This method is designed to do a quick check. The result may
|
* \note This method is designed to do a quick check. The result may
|
||||||
* not necessarily be correct.
|
* not necessarily be correct.
|
||||||
*/
|
*/
|
||||||
static bool isSupported(IOStream *stream);
|
static bool isSupported(IOStream *stream);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void read();
|
void read();
|
||||||
|
|
||||||
class FilePrivate;
|
class FilePrivate;
|
||||||
FilePrivate *d;
|
FilePrivate *d;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace ASF
|
||||||
|
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
89
3rdparty/taglib/asf/asfpicture.cpp
vendored
89
3rdparty/taglib/asf/asfpicture.cpp
vendored
@ -34,9 +34,8 @@
|
|||||||
|
|
||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
class ASF::Picture::PicturePrivate : public RefCounter
|
class ASF::Picture::PicturePrivate : public RefCounter {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
bool valid;
|
bool valid;
|
||||||
Type type;
|
Type type;
|
||||||
String mimeType;
|
String mimeType;
|
||||||
@ -48,126 +47,107 @@ public:
|
|||||||
// Picture class members
|
// Picture class members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ASF::Picture::Picture() :
|
ASF::Picture::Picture() : d(new PicturePrivate()) {
|
||||||
d(new PicturePrivate())
|
|
||||||
{
|
|
||||||
d->valid = true;
|
d->valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASF::Picture::Picture(const Picture& other) :
|
ASF::Picture::Picture(const Picture& other) : d(other.d) {
|
||||||
d(other.d)
|
|
||||||
{
|
|
||||||
d->ref();
|
d->ref();
|
||||||
}
|
}
|
||||||
|
|
||||||
ASF::Picture::~Picture()
|
ASF::Picture::~Picture() {
|
||||||
{
|
if (d->deref())
|
||||||
if(d->deref())
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ASF::Picture::isValid() const
|
bool ASF::Picture::isValid() const {
|
||||||
{
|
|
||||||
return d->valid;
|
return d->valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
String ASF::Picture::mimeType() const
|
String ASF::Picture::mimeType() const {
|
||||||
{
|
|
||||||
return d->mimeType;
|
return d->mimeType;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASF::Picture::setMimeType(const String &value)
|
void ASF::Picture::setMimeType(const String& value) {
|
||||||
{
|
|
||||||
d->mimeType = value;
|
d->mimeType = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASF::Picture::Type ASF::Picture::type() const
|
ASF::Picture::Type ASF::Picture::type() const {
|
||||||
{
|
|
||||||
return d->type;
|
return d->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASF::Picture::setType(const ASF::Picture::Type& t)
|
void ASF::Picture::setType(const ASF::Picture::Type& t) {
|
||||||
{
|
|
||||||
d->type = t;
|
d->type = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
String ASF::Picture::description() const
|
String ASF::Picture::description() const {
|
||||||
{
|
|
||||||
return d->description;
|
return d->description;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASF::Picture::setDescription(const String &desc)
|
void ASF::Picture::setDescription(const String& desc) {
|
||||||
{
|
|
||||||
d->description = desc;
|
d->description = desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector ASF::Picture::picture() const
|
ByteVector ASF::Picture::picture() const {
|
||||||
{
|
|
||||||
return d->picture;
|
return d->picture;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASF::Picture::setPicture(const ByteVector &p)
|
void ASF::Picture::setPicture(const ByteVector& p) {
|
||||||
{
|
|
||||||
d->picture = p;
|
d->picture = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ASF::Picture::dataSize() const
|
int ASF::Picture::dataSize() const {
|
||||||
{
|
return 9 + (d->mimeType.length() + d->description.length()) * 2 +
|
||||||
return
|
|
||||||
9 + (d->mimeType.length() + d->description.length()) * 2 +
|
|
||||||
d->picture.size();
|
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);
|
Picture(other).swap(*this);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASF::Picture::swap(Picture &other)
|
void ASF::Picture::swap(Picture& other) {
|
||||||
{
|
|
||||||
using std::swap;
|
using std::swap;
|
||||||
|
|
||||||
swap(d, other.d);
|
swap(d, other.d);
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector ASF::Picture::render() const
|
ByteVector ASF::Picture::render() const {
|
||||||
{
|
if (!isValid())
|
||||||
if(!isValid())
|
|
||||||
return ByteVector();
|
return ByteVector();
|
||||||
|
|
||||||
return
|
return ByteVector((char)d->type) +
|
||||||
ByteVector((char)d->type) +
|
|
||||||
ByteVector::fromUInt(d->picture.size(), false) +
|
ByteVector::fromUInt(d->picture.size(), false) +
|
||||||
renderString(d->mimeType) +
|
renderString(d->mimeType) +
|
||||||
renderString(d->description) +
|
renderString(d->description) +
|
||||||
d->picture;
|
d->picture;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASF::Picture::parse(const ByteVector& bytes)
|
void ASF::Picture::parse(const ByteVector& bytes) {
|
||||||
{
|
|
||||||
d->valid = false;
|
d->valid = false;
|
||||||
if(bytes.size() < 9)
|
if (bytes.size() < 9)
|
||||||
return;
|
return;
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
d->type = (Type)bytes[0]; ++pos;
|
d->type = (Type)bytes[0];
|
||||||
const unsigned int dataLen = bytes.toUInt(pos, false); pos+=4;
|
++pos;
|
||||||
|
const unsigned int dataLen = bytes.toUInt(pos, false);
|
||||||
|
pos += 4;
|
||||||
|
|
||||||
const ByteVector nullStringTerminator(2, 0);
|
const ByteVector nullStringTerminator(2, 0);
|
||||||
|
|
||||||
int endPos = bytes.find(nullStringTerminator, pos, 2);
|
int endPos = bytes.find(nullStringTerminator, pos, 2);
|
||||||
if(endPos < 0)
|
if (endPos < 0)
|
||||||
return;
|
return;
|
||||||
d->mimeType = String(bytes.mid(pos, endPos - pos), String::UTF16LE);
|
d->mimeType = String(bytes.mid(pos, endPos - pos), String::UTF16LE);
|
||||||
pos = endPos+2;
|
pos = endPos + 2;
|
||||||
|
|
||||||
endPos = bytes.find(nullStringTerminator, pos, 2);
|
endPos = bytes.find(nullStringTerminator, pos, 2);
|
||||||
if(endPos < 0)
|
if (endPos < 0)
|
||||||
return;
|
return;
|
||||||
d->description = String(bytes.mid(pos, endPos - pos), String::UTF16LE);
|
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;
|
return;
|
||||||
|
|
||||||
d->picture = bytes.mid(pos, dataLen);
|
d->picture = bytes.mid(pos, dataLen);
|
||||||
@ -175,8 +155,7 @@ void ASF::Picture::parse(const ByteVector& bytes)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASF::Picture ASF::Picture::fromInvalid()
|
ASF::Picture ASF::Picture::fromInvalid() {
|
||||||
{
|
|
||||||
Picture ret;
|
Picture ret;
|
||||||
ret.d->valid = false;
|
ret.d->valid = false;
|
||||||
return ret;
|
return ret;
|
||||||
|
191
3rdparty/taglib/asf/asfpicture.h
vendored
191
3rdparty/taglib/asf/asfpicture.h
vendored
@ -32,14 +32,12 @@
|
|||||||
#include "attachedpictureframe.h"
|
#include "attachedpictureframe.h"
|
||||||
|
|
||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib
|
namespace TagLib {
|
||||||
{
|
namespace ASF {
|
||||||
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
|
* 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
|
* 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
|
* attribute in a single tag). These pictures are usually in either JPEG or
|
||||||
@ -47,136 +45,135 @@ namespace TagLib
|
|||||||
* \see Attribute::toPicture()
|
* \see Attribute::toPicture()
|
||||||
* \see Attribute::Attribute(const Picture& picture)
|
* \see Attribute::Attribute(const Picture& picture)
|
||||||
*/
|
*/
|
||||||
class TAGLIB_EXPORT Picture {
|
class TAGLIB_EXPORT Picture {
|
||||||
public:
|
public:
|
||||||
|
/*!
|
||||||
/*!
|
|
||||||
* This describes the function or content of the picture.
|
* This describes the function or content of the picture.
|
||||||
*/
|
*/
|
||||||
enum Type {
|
enum Type {
|
||||||
//! A type not enumerated below
|
//! A type not enumerated below
|
||||||
Other = 0x00,
|
Other = 0x00,
|
||||||
//! 32x32 PNG image that should be used as the file icon
|
//! 32x32 PNG image that should be used as the file icon
|
||||||
FileIcon = 0x01,
|
FileIcon = 0x01,
|
||||||
//! File icon of a different size or format
|
//! File icon of a different size or format
|
||||||
OtherFileIcon = 0x02,
|
OtherFileIcon = 0x02,
|
||||||
//! Front cover image of the album
|
//! Front cover image of the album
|
||||||
FrontCover = 0x03,
|
FrontCover = 0x03,
|
||||||
//! Back cover image of the album
|
//! Back cover image of the album
|
||||||
BackCover = 0x04,
|
BackCover = 0x04,
|
||||||
//! Inside leaflet page of the album
|
//! Inside leaflet page of the album
|
||||||
LeafletPage = 0x05,
|
LeafletPage = 0x05,
|
||||||
//! Image from the album itself
|
//! Image from the album itself
|
||||||
Media = 0x06,
|
Media = 0x06,
|
||||||
//! Picture of the lead artist or soloist
|
//! Picture of the lead artist or soloist
|
||||||
LeadArtist = 0x07,
|
LeadArtist = 0x07,
|
||||||
//! Picture of the artist or performer
|
//! Picture of the artist or performer
|
||||||
Artist = 0x08,
|
Artist = 0x08,
|
||||||
//! Picture of the conductor
|
//! Picture of the conductor
|
||||||
Conductor = 0x09,
|
Conductor = 0x09,
|
||||||
//! Picture of the band or orchestra
|
//! Picture of the band or orchestra
|
||||||
Band = 0x0A,
|
Band = 0x0A,
|
||||||
//! Picture of the composer
|
//! Picture of the composer
|
||||||
Composer = 0x0B,
|
Composer = 0x0B,
|
||||||
//! Picture of the lyricist or text writer
|
//! Picture of the lyricist or text writer
|
||||||
Lyricist = 0x0C,
|
Lyricist = 0x0C,
|
||||||
//! Picture of the recording location or studio
|
//! Picture of the recording location or studio
|
||||||
RecordingLocation = 0x0D,
|
RecordingLocation = 0x0D,
|
||||||
//! Picture of the artists during recording
|
//! Picture of the artists during recording
|
||||||
DuringRecording = 0x0E,
|
DuringRecording = 0x0E,
|
||||||
//! Picture of the artists during performance
|
//! Picture of the artists during performance
|
||||||
DuringPerformance = 0x0F,
|
DuringPerformance = 0x0F,
|
||||||
//! Picture from a movie or video related to the track
|
//! Picture from a movie or video related to the track
|
||||||
MovieScreenCapture = 0x10,
|
MovieScreenCapture = 0x10,
|
||||||
//! Picture of a large, coloured fish
|
//! Picture of a large, coloured fish
|
||||||
ColouredFish = 0x11,
|
ColouredFish = 0x11,
|
||||||
//! Illustration related to the track
|
//! Illustration related to the track
|
||||||
Illustration = 0x12,
|
Illustration = 0x12,
|
||||||
//! Logo of the band or performer
|
//! Logo of the band or performer
|
||||||
BandLogo = 0x13,
|
BandLogo = 0x13,
|
||||||
//! Logo of the publisher (record company)
|
//! Logo of the publisher (record company)
|
||||||
PublisherLogo = 0x14
|
PublisherLogo = 0x14
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs an empty picture.
|
* Constructs an empty picture.
|
||||||
*/
|
*/
|
||||||
Picture();
|
Picture();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Construct an picture as a copy of \a other.
|
* Construct an picture as a copy of \a other.
|
||||||
*/
|
*/
|
||||||
Picture(const Picture& other);
|
Picture(const Picture& other);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys the picture.
|
* Destroys the picture.
|
||||||
*/
|
*/
|
||||||
virtual ~Picture();
|
virtual ~Picture();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Copies the contents of \a other into this picture.
|
* Copies the contents of \a other into this picture.
|
||||||
*/
|
*/
|
||||||
Picture& operator=(const Picture& other);
|
Picture& operator=(const Picture& other);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Exchanges the content of the Picture by the content of \a other.
|
* 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
|
* Returns true if Picture stores valid picture
|
||||||
*/
|
*/
|
||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the mime type of the image. This should in most cases be
|
* Returns the mime type of the image. This should in most cases be
|
||||||
* "image/png" or "image/jpeg".
|
* "image/png" or "image/jpeg".
|
||||||
* \see setMimeType(const String &)
|
* \see setMimeType(const String &)
|
||||||
* \see picture()
|
* \see picture()
|
||||||
* \see setPicture(const ByteArray&)
|
* \see setPicture(const ByteArray&)
|
||||||
*/
|
*/
|
||||||
String mimeType() const;
|
String mimeType() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the mime type of the image. This should in most cases be
|
* Sets the mime type of the image. This should in most cases be
|
||||||
* "image/png" or "image/jpeg".
|
* "image/png" or "image/jpeg".
|
||||||
* \see setMimeType(const String &)
|
* \see setMimeType(const String &)
|
||||||
* \see picture()
|
* \see picture()
|
||||||
* \see setPicture(const ByteArray&)
|
* \see setPicture(const ByteArray&)
|
||||||
*/
|
*/
|
||||||
void setMimeType(const String &value);
|
void setMimeType(const String& value);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the type of the image.
|
* Returns the type of the image.
|
||||||
*
|
*
|
||||||
* \see Type
|
* \see Type
|
||||||
* \see setType()
|
* \see setType()
|
||||||
*/
|
*/
|
||||||
Type type() const;
|
Type type() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the type for the image.
|
* Sets the type for the image.
|
||||||
*
|
*
|
||||||
* \see Type
|
* \see Type
|
||||||
* \see type()
|
* \see type()
|
||||||
*/
|
*/
|
||||||
void setType(const ASF::Picture::Type& t);
|
void setType(const ASF::Picture::Type& t);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns a text description of the image.
|
* Returns a text description of the image.
|
||||||
*
|
*
|
||||||
* \see setDescription()
|
* \see setDescription()
|
||||||
*/
|
*/
|
||||||
String description() const;
|
String description() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets a textual description of the image to \a desc.
|
* Sets a textual description of the image to \a desc.
|
||||||
*
|
*
|
||||||
* \see description()
|
* \see description()
|
||||||
*/
|
*/
|
||||||
void setDescription(const String &desc);
|
void setDescription(const String& desc);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the image data as a ByteVector.
|
* Returns the image data as a ByteVector.
|
||||||
*
|
*
|
||||||
* \note ByteVector has a data() method that returns a const char * which
|
* \note ByteVector has a data() method that returns a const char * which
|
||||||
@ -185,9 +182,9 @@ namespace TagLib
|
|||||||
* \see setPicture()
|
* \see setPicture()
|
||||||
* \see mimeType()
|
* \see mimeType()
|
||||||
*/
|
*/
|
||||||
ByteVector picture() const;
|
ByteVector picture() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the image data to \a p. \a p should be of the type specified in
|
* Sets the image data to \a p. \a p should be of the type specified in
|
||||||
* this frame's mime-type specification.
|
* this frame's mime-type specification.
|
||||||
*
|
*
|
||||||
@ -195,30 +192,30 @@ namespace TagLib
|
|||||||
* \see mimeType()
|
* \see mimeType()
|
||||||
* \see setMimeType()
|
* \see setMimeType()
|
||||||
*/
|
*/
|
||||||
void setPicture(const ByteVector &p);
|
void setPicture(const ByteVector& p);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns picture as binary raw data \a value
|
* Returns picture as binary raw data \a value
|
||||||
*/
|
*/
|
||||||
ByteVector render() const;
|
ByteVector render() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns picture as binary raw data \a value
|
* Returns picture as binary raw data \a value
|
||||||
*/
|
*/
|
||||||
int dataSize() const;
|
int dataSize() const;
|
||||||
|
|
||||||
#ifndef DO_NOT_DOCUMENT
|
#ifndef DO_NOT_DOCUMENT
|
||||||
/* THIS IS PRIVATE, DON'T TOUCH IT! */
|
/* THIS IS PRIVATE, DON'T TOUCH IT! */
|
||||||
void parse(const ByteVector& );
|
void parse(const ByteVector&);
|
||||||
static Picture fromInvalid();
|
static Picture fromInvalid();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class PicturePrivate;
|
class PicturePrivate;
|
||||||
PicturePrivate *d;
|
PicturePrivate* d;
|
||||||
};
|
};
|
||||||
}
|
} // namespace ASF
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif // ASFPICTURE_H
|
#endif // ASFPICTURE_H
|
||||||
|
125
3rdparty/taglib/asf/asfproperties.cpp
vendored
125
3rdparty/taglib/asf/asfproperties.cpp
vendored
@ -29,17 +29,15 @@
|
|||||||
|
|
||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
class ASF::Properties::PropertiesPrivate
|
class ASF::Properties::PropertiesPrivate {
|
||||||
{
|
public:
|
||||||
public:
|
PropertiesPrivate() : length(0),
|
||||||
PropertiesPrivate() :
|
bitrate(0),
|
||||||
length(0),
|
sampleRate(0),
|
||||||
bitrate(0),
|
channels(0),
|
||||||
sampleRate(0),
|
bitsPerSample(0),
|
||||||
channels(0),
|
codec(ASF::Properties::Unknown),
|
||||||
bitsPerSample(0),
|
encrypted(false) {}
|
||||||
codec(ASF::Properties::Unknown),
|
|
||||||
encrypted(false) {}
|
|
||||||
|
|
||||||
int length;
|
int length;
|
||||||
int bitrate;
|
int bitrate;
|
||||||
@ -56,69 +54,55 @@ public:
|
|||||||
// public members
|
// public members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ASF::Properties::Properties() :
|
ASF::Properties::Properties() : AudioProperties(AudioProperties::Average),
|
||||||
AudioProperties(AudioProperties::Average),
|
d(new PropertiesPrivate()) {
|
||||||
d(new PropertiesPrivate())
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ASF::Properties::~Properties()
|
ASF::Properties::~Properties() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ASF::Properties::length() const
|
int ASF::Properties::length() const {
|
||||||
{
|
|
||||||
return lengthInSeconds();
|
return lengthInSeconds();
|
||||||
}
|
}
|
||||||
|
|
||||||
int ASF::Properties::lengthInSeconds() const
|
int ASF::Properties::lengthInSeconds() const {
|
||||||
{
|
|
||||||
return d->length / 1000;
|
return d->length / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ASF::Properties::lengthInMilliseconds() const
|
int ASF::Properties::lengthInMilliseconds() const {
|
||||||
{
|
|
||||||
return d->length;
|
return d->length;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ASF::Properties::bitrate() const
|
int ASF::Properties::bitrate() const {
|
||||||
{
|
|
||||||
return d->bitrate;
|
return d->bitrate;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ASF::Properties::sampleRate() const
|
int ASF::Properties::sampleRate() const {
|
||||||
{
|
|
||||||
return d->sampleRate;
|
return d->sampleRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ASF::Properties::channels() const
|
int ASF::Properties::channels() const {
|
||||||
{
|
|
||||||
return d->channels;
|
return d->channels;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ASF::Properties::bitsPerSample() const
|
int ASF::Properties::bitsPerSample() const {
|
||||||
{
|
|
||||||
return d->bitsPerSample;
|
return d->bitsPerSample;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASF::Properties::Codec ASF::Properties::codec() const
|
ASF::Properties::Codec ASF::Properties::codec() const {
|
||||||
{
|
|
||||||
return d->codec;
|
return d->codec;
|
||||||
}
|
}
|
||||||
|
|
||||||
String ASF::Properties::codecName() const
|
String ASF::Properties::codecName() const {
|
||||||
{
|
|
||||||
return d->codecName;
|
return d->codecName;
|
||||||
}
|
}
|
||||||
|
|
||||||
String ASF::Properties::codecDescription() const
|
String ASF::Properties::codecDescription() const {
|
||||||
{
|
|
||||||
return d->codecDescription;
|
return d->codecDescription;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ASF::Properties::isEncrypted() const
|
bool ASF::Properties::isEncrypted() const {
|
||||||
{
|
|
||||||
return d->encrypted;
|
return d->encrypted;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,69 +110,58 @@ bool ASF::Properties::isEncrypted() const
|
|||||||
// private members
|
// 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.");
|
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;
|
d->length = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASF::Properties::setBitrate(int value)
|
void ASF::Properties::setBitrate(int value) {
|
||||||
{
|
|
||||||
d->bitrate = value;
|
d->bitrate = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASF::Properties::setSampleRate(int value)
|
void ASF::Properties::setSampleRate(int value) {
|
||||||
{
|
|
||||||
d->sampleRate = value;
|
d->sampleRate = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASF::Properties::setChannels(int value)
|
void ASF::Properties::setChannels(int value) {
|
||||||
{
|
|
||||||
d->channels = value;
|
d->channels = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASF::Properties::setBitsPerSample(int value)
|
void ASF::Properties::setBitsPerSample(int value) {
|
||||||
{
|
|
||||||
d->bitsPerSample = value;
|
d->bitsPerSample = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASF::Properties::setCodec(int value)
|
void ASF::Properties::setCodec(int value) {
|
||||||
{
|
switch (value) {
|
||||||
switch(value)
|
case 0x0160:
|
||||||
{
|
d->codec = WMA1;
|
||||||
case 0x0160:
|
break;
|
||||||
d->codec = WMA1;
|
case 0x0161:
|
||||||
break;
|
d->codec = WMA2;
|
||||||
case 0x0161:
|
break;
|
||||||
d->codec = WMA2;
|
case 0x0162:
|
||||||
break;
|
d->codec = WMA9Pro;
|
||||||
case 0x0162:
|
break;
|
||||||
d->codec = WMA9Pro;
|
case 0x0163:
|
||||||
break;
|
d->codec = WMA9Lossless;
|
||||||
case 0x0163:
|
break;
|
||||||
d->codec = WMA9Lossless;
|
default:
|
||||||
break;
|
d->codec = Unknown;
|
||||||
default:
|
break;
|
||||||
d->codec = Unknown;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASF::Properties::setCodecName(const String &value)
|
void ASF::Properties::setCodecName(const String &value) {
|
||||||
{
|
|
||||||
d->codecName = value;
|
d->codecName = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASF::Properties::setCodecDescription(const String &value)
|
void ASF::Properties::setCodecDescription(const String &value) {
|
||||||
{
|
|
||||||
d->codecDescription = value;
|
d->codecDescription = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASF::Properties::setEncrypted(bool value)
|
void ASF::Properties::setEncrypted(bool value) {
|
||||||
{
|
|
||||||
d->encrypted = value;
|
d->encrypted = value;
|
||||||
}
|
}
|
||||||
|
129
3rdparty/taglib/asf/asfproperties.h
vendored
129
3rdparty/taglib/asf/asfproperties.h
vendored
@ -33,55 +33,52 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
namespace ASF {
|
namespace ASF {
|
||||||
|
|
||||||
//! An implementation of ASF audio properties
|
//! An implementation of ASF audio properties
|
||||||
class TAGLIB_EXPORT Properties : public AudioProperties
|
class TAGLIB_EXPORT Properties : public AudioProperties {
|
||||||
{
|
public:
|
||||||
public:
|
/*!
|
||||||
|
|
||||||
/*!
|
|
||||||
* Audio codec types can be used in ASF file.
|
* Audio codec types can be used in ASF file.
|
||||||
*/
|
*/
|
||||||
enum Codec
|
enum Codec {
|
||||||
{
|
/*!
|
||||||
/*!
|
|
||||||
* Couldn't detect the codec.
|
* Couldn't detect the codec.
|
||||||
*/
|
*/
|
||||||
Unknown = 0,
|
Unknown = 0,
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Windows Media Audio 1
|
* Windows Media Audio 1
|
||||||
*/
|
*/
|
||||||
WMA1,
|
WMA1,
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Windows Media Audio 2 or above
|
* Windows Media Audio 2 or above
|
||||||
*/
|
*/
|
||||||
WMA2,
|
WMA2,
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Windows Media Audio 9 Professional
|
* Windows Media Audio 9 Professional
|
||||||
*/
|
*/
|
||||||
WMA9Pro,
|
WMA9Pro,
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Windows Media Audio 9 Lossless
|
* Windows Media Audio 9 Lossless
|
||||||
*/
|
*/
|
||||||
WMA9Lossless,
|
WMA9Lossless,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Creates an instance of ASF::Properties.
|
* Creates an instance of ASF::Properties.
|
||||||
*/
|
*/
|
||||||
Properties();
|
Properties();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys this ASF::Properties instance.
|
* Destroys this ASF::Properties instance.
|
||||||
*/
|
*/
|
||||||
virtual ~Properties();
|
virtual ~Properties();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the length of the file in seconds. The length is rounded down to
|
* Returns the length of the file in seconds. The length is rounded down to
|
||||||
* the nearest whole second.
|
* the nearest whole second.
|
||||||
*
|
*
|
||||||
@ -89,63 +86,63 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \deprecated
|
* \deprecated
|
||||||
*/
|
*/
|
||||||
virtual int length() const;
|
virtual int length() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the length of the file in seconds. The length is rounded down to
|
* Returns the length of the file in seconds. The length is rounded down to
|
||||||
* the nearest whole second.
|
* the nearest whole second.
|
||||||
*
|
*
|
||||||
* \see lengthInMilliseconds()
|
* \see lengthInMilliseconds()
|
||||||
*/
|
*/
|
||||||
// BIC: make virtual
|
// BIC: make virtual
|
||||||
int lengthInSeconds() const;
|
int lengthInSeconds() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the length of the file in milliseconds.
|
* Returns the length of the file in milliseconds.
|
||||||
*
|
*
|
||||||
* \see lengthInSeconds()
|
* \see lengthInSeconds()
|
||||||
*/
|
*/
|
||||||
// BIC: make virtual
|
// BIC: make virtual
|
||||||
int lengthInMilliseconds() const;
|
int lengthInMilliseconds() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the average bit rate of the file in kb/s.
|
* Returns the average bit rate of the file in kb/s.
|
||||||
*/
|
*/
|
||||||
virtual int bitrate() const;
|
virtual int bitrate() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the sample rate in Hz.
|
* Returns the sample rate in Hz.
|
||||||
*/
|
*/
|
||||||
virtual int sampleRate() const;
|
virtual int sampleRate() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the number of audio channels.
|
* Returns the number of audio channels.
|
||||||
*/
|
*/
|
||||||
virtual int channels() const;
|
virtual int channels() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the number of bits per audio sample.
|
* Returns the number of bits per audio sample.
|
||||||
*/
|
*/
|
||||||
int bitsPerSample() const;
|
int bitsPerSample() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the codec used in the file.
|
* Returns the codec used in the file.
|
||||||
*
|
*
|
||||||
* \see codecName()
|
* \see codecName()
|
||||||
* \see codecDescription()
|
* \see codecDescription()
|
||||||
*/
|
*/
|
||||||
Codec codec() const;
|
Codec codec() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the concrete codec name, for example "Windows Media Audio 9.1"
|
* Returns the concrete codec name, for example "Windows Media Audio 9.1"
|
||||||
* used in the file if available, otherwise an empty string.
|
* used in the file if available, otherwise an empty string.
|
||||||
*
|
*
|
||||||
* \see codec()
|
* \see codec()
|
||||||
* \see codecDescription()
|
* \see codecDescription()
|
||||||
*/
|
*/
|
||||||
String codecName() const;
|
String codecName() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the codec description, typically contains the encoder settings,
|
* Returns the codec description, typically contains the encoder settings,
|
||||||
* for example "VBR Quality 50, 44kHz, stereo 1-pass VBR" if available,
|
* for example "VBR Quality 50, 44kHz, stereo 1-pass VBR" if available,
|
||||||
* otherwise an empty string.
|
* otherwise an empty string.
|
||||||
@ -153,36 +150,36 @@ namespace TagLib {
|
|||||||
* \see codec()
|
* \see codec()
|
||||||
* \see codecName()
|
* \see codecName()
|
||||||
*/
|
*/
|
||||||
String codecDescription() const;
|
String codecDescription() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns whether or not the file is encrypted.
|
* Returns whether or not the file is encrypted.
|
||||||
*/
|
*/
|
||||||
bool isEncrypted() const;
|
bool isEncrypted() const;
|
||||||
|
|
||||||
#ifndef DO_NOT_DOCUMENT
|
#ifndef DO_NOT_DOCUMENT
|
||||||
// deprecated
|
// deprecated
|
||||||
void setLength(int value);
|
void setLength(int value);
|
||||||
|
|
||||||
void setLengthInMilliseconds(int value);
|
void setLengthInMilliseconds(int value);
|
||||||
void setBitrate(int value);
|
void setBitrate(int value);
|
||||||
void setSampleRate(int value);
|
void setSampleRate(int value);
|
||||||
void setChannels(int value);
|
void setChannels(int value);
|
||||||
void setBitsPerSample(int value);
|
void setBitsPerSample(int value);
|
||||||
void setCodec(int value);
|
void setCodec(int value);
|
||||||
void setCodecName(const String &value);
|
void setCodecName(const String &value);
|
||||||
void setCodecDescription(const String &value);
|
void setCodecDescription(const String &value);
|
||||||
void setEncrypted(bool value);
|
void setEncrypted(bool value);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class PropertiesPrivate;
|
class PropertiesPrivate;
|
||||||
PropertiesPrivate *d;
|
PropertiesPrivate *d;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace ASF
|
||||||
|
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
278
3rdparty/taglib/asf/asftag.cpp
vendored
278
3rdparty/taglib/asf/asftag.cpp
vendored
@ -28,9 +28,8 @@
|
|||||||
|
|
||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
class ASF::Tag::TagPrivate
|
class ASF::Tag::TagPrivate {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
String title;
|
String title;
|
||||||
String artist;
|
String artist;
|
||||||
String copyright;
|
String copyright;
|
||||||
@ -39,162 +38,133 @@ public:
|
|||||||
AttributeListMap attributeListMap;
|
AttributeListMap attributeListMap;
|
||||||
};
|
};
|
||||||
|
|
||||||
ASF::Tag::Tag() :
|
ASF::Tag::Tag() : Strawberry_TagLib::TagLib::Tag(),
|
||||||
Strawberry_TagLib::TagLib::Tag(),
|
d(new TagPrivate()) {
|
||||||
d(new TagPrivate())
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ASF::Tag::~Tag()
|
ASF::Tag::~Tag() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
String ASF::Tag::title() const
|
String ASF::Tag::title() const {
|
||||||
{
|
|
||||||
return d->title;
|
return d->title;
|
||||||
}
|
}
|
||||||
|
|
||||||
String ASF::Tag::artist() const
|
String ASF::Tag::artist() const {
|
||||||
{
|
|
||||||
return d->artist;
|
return d->artist;
|
||||||
}
|
}
|
||||||
|
|
||||||
String ASF::Tag::album() const
|
String ASF::Tag::album() const {
|
||||||
{
|
if (d->attributeListMap.contains("WM/AlbumTitle"))
|
||||||
if(d->attributeListMap.contains("WM/AlbumTitle"))
|
|
||||||
return d->attributeListMap["WM/AlbumTitle"][0].toString();
|
return d->attributeListMap["WM/AlbumTitle"][0].toString();
|
||||||
return String();
|
return String();
|
||||||
}
|
}
|
||||||
|
|
||||||
String ASF::Tag::copyright() const
|
String ASF::Tag::copyright() const {
|
||||||
{
|
|
||||||
return d->copyright;
|
return d->copyright;
|
||||||
}
|
}
|
||||||
|
|
||||||
String ASF::Tag::comment() const
|
String ASF::Tag::comment() const {
|
||||||
{
|
|
||||||
return d->comment;
|
return d->comment;
|
||||||
}
|
}
|
||||||
|
|
||||||
String ASF::Tag::rating() const
|
String ASF::Tag::rating() const {
|
||||||
{
|
|
||||||
return d->rating;
|
return d->rating;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int ASF::Tag::year() const
|
unsigned int ASF::Tag::year() const {
|
||||||
{
|
if (d->attributeListMap.contains("WM/Year"))
|
||||||
if(d->attributeListMap.contains("WM/Year"))
|
|
||||||
return d->attributeListMap["WM/Year"][0].toString().toInt();
|
return d->attributeListMap["WM/Year"][0].toString().toInt();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int ASF::Tag::track() const
|
unsigned int ASF::Tag::track() const {
|
||||||
{
|
if (d->attributeListMap.contains("WM/TrackNumber")) {
|
||||||
if(d->attributeListMap.contains("WM/TrackNumber")) {
|
|
||||||
const ASF::Attribute attr = d->attributeListMap["WM/TrackNumber"][0];
|
const ASF::Attribute attr = d->attributeListMap["WM/TrackNumber"][0];
|
||||||
if(attr.type() == ASF::Attribute::DWordType)
|
if (attr.type() == ASF::Attribute::DWordType)
|
||||||
return attr.toUInt();
|
return attr.toUInt();
|
||||||
else
|
else
|
||||||
return attr.toString().toInt();
|
return attr.toString().toInt();
|
||||||
}
|
}
|
||||||
if(d->attributeListMap.contains("WM/Track"))
|
if (d->attributeListMap.contains("WM/Track"))
|
||||||
return d->attributeListMap["WM/Track"][0].toUInt();
|
return d->attributeListMap["WM/Track"][0].toUInt();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
String ASF::Tag::genre() const
|
String ASF::Tag::genre() const {
|
||||||
{
|
if (d->attributeListMap.contains("WM/Genre"))
|
||||||
if(d->attributeListMap.contains("WM/Genre"))
|
|
||||||
return d->attributeListMap["WM/Genre"][0].toString();
|
return d->attributeListMap["WM/Genre"][0].toString();
|
||||||
return String();
|
return String();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASF::Tag::setTitle(const String &value)
|
void ASF::Tag::setTitle(const String &value) {
|
||||||
{
|
|
||||||
d->title = value;
|
d->title = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASF::Tag::setArtist(const String &value)
|
void ASF::Tag::setArtist(const String &value) {
|
||||||
{
|
|
||||||
d->artist = value;
|
d->artist = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASF::Tag::setCopyright(const String &value)
|
void ASF::Tag::setCopyright(const String &value) {
|
||||||
{
|
|
||||||
d->copyright = value;
|
d->copyright = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASF::Tag::setComment(const String &value)
|
void ASF::Tag::setComment(const String &value) {
|
||||||
{
|
|
||||||
d->comment = value;
|
d->comment = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASF::Tag::setRating(const String &value)
|
void ASF::Tag::setRating(const String &value) {
|
||||||
{
|
|
||||||
d->rating = value;
|
d->rating = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASF::Tag::setAlbum(const String &value)
|
void ASF::Tag::setAlbum(const String &value) {
|
||||||
{
|
|
||||||
setAttribute("WM/AlbumTitle", value);
|
setAttribute("WM/AlbumTitle", value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASF::Tag::setGenre(const String &value)
|
void ASF::Tag::setGenre(const String &value) {
|
||||||
{
|
|
||||||
setAttribute("WM/Genre", 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));
|
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));
|
setAttribute("WM/TrackNumber", String::number(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
ASF::AttributeListMap& ASF::Tag::attributeListMap()
|
ASF::AttributeListMap &ASF::Tag::attributeListMap() {
|
||||||
{
|
|
||||||
return d->attributeListMap;
|
return d->attributeListMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ASF::AttributeListMap &ASF::Tag::attributeListMap() const
|
const ASF::AttributeListMap &ASF::Tag::attributeListMap() const {
|
||||||
{
|
|
||||||
return d->attributeListMap;
|
return d->attributeListMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ASF::Tag::contains(const String &key) const
|
bool ASF::Tag::contains(const String &key) const {
|
||||||
{
|
|
||||||
return d->attributeListMap.contains(key);
|
return d->attributeListMap.contains(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASF::Tag::removeItem(const String &key)
|
void ASF::Tag::removeItem(const String &key) {
|
||||||
{
|
|
||||||
d->attributeListMap.erase(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];
|
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;
|
AttributeList value;
|
||||||
value.append(attribute);
|
value.append(attribute);
|
||||||
d->attributeListMap.insert(name, value);
|
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);
|
d->attributeListMap.insert(name, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASF::Tag::addAttribute(const String &name, const Attribute &attribute)
|
void ASF::Tag::addAttribute(const String &name, const Attribute &attribute) {
|
||||||
{
|
if (d->attributeListMap.contains(name)) {
|
||||||
if(d->attributeListMap.contains(name)) {
|
|
||||||
d->attributeListMap[name].append(attribute);
|
d->attributeListMap[name].append(attribute);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -202,95 +172,91 @@ 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() &&
|
return Strawberry_TagLib::TagLib::Tag::isEmpty() &&
|
||||||
copyright().isEmpty() &&
|
copyright().isEmpty() &&
|
||||||
rating().isEmpty() &&
|
rating().isEmpty() &&
|
||||||
d->attributeListMap.isEmpty();
|
d->attributeListMap.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace
|
namespace {
|
||||||
{
|
const char *keyTranslation[][2] = {
|
||||||
const char *keyTranslation[][2] = {
|
{ "WM/AlbumTitle", "ALBUM" },
|
||||||
{ "WM/AlbumTitle", "ALBUM" },
|
{ "WM/AlbumArtist", "ALBUMARTIST" },
|
||||||
{ "WM/AlbumArtist", "ALBUMARTIST" },
|
{ "WM/Composer", "COMPOSER" },
|
||||||
{ "WM/Composer", "COMPOSER" },
|
{ "WM/Writer", "WRITER" },
|
||||||
{ "WM/Writer", "WRITER" },
|
{ "WM/Conductor", "CONDUCTOR" },
|
||||||
{ "WM/Conductor", "CONDUCTOR" },
|
{ "WM/ModifiedBy", "REMIXER" },
|
||||||
{ "WM/ModifiedBy", "REMIXER" },
|
{ "WM/Year", "DATE" },
|
||||||
{ "WM/Year", "DATE" },
|
{ "WM/OriginalReleaseYear", "ORIGINALDATE" },
|
||||||
{ "WM/OriginalReleaseYear", "ORIGINALDATE" },
|
{ "WM/Producer", "PRODUCER" },
|
||||||
{ "WM/Producer", "PRODUCER" },
|
{ "WM/ContentGroupDescription", "GROUPING" },
|
||||||
{ "WM/ContentGroupDescription", "GROUPING" },
|
{ "WM/SubTitle", "SUBTITLE" },
|
||||||
{ "WM/SubTitle", "SUBTITLE" },
|
{ "WM/SetSubTitle", "DISCSUBTITLE" },
|
||||||
{ "WM/SetSubTitle", "DISCSUBTITLE" },
|
{ "WM/TrackNumber", "TRACKNUMBER" },
|
||||||
{ "WM/TrackNumber", "TRACKNUMBER" },
|
{ "WM/PartOfSet", "DISCNUMBER" },
|
||||||
{ "WM/PartOfSet", "DISCNUMBER" },
|
{ "WM/Genre", "GENRE" },
|
||||||
{ "WM/Genre", "GENRE" },
|
{ "WM/BeatsPerMinute", "BPM" },
|
||||||
{ "WM/BeatsPerMinute", "BPM" },
|
{ "WM/Mood", "MOOD" },
|
||||||
{ "WM/Mood", "MOOD" },
|
{ "WM/ISRC", "ISRC" },
|
||||||
{ "WM/ISRC", "ISRC" },
|
{ "WM/Lyrics", "LYRICS" },
|
||||||
{ "WM/Lyrics", "LYRICS" },
|
{ "WM/Media", "MEDIA" },
|
||||||
{ "WM/Media", "MEDIA" },
|
{ "WM/Publisher", "LABEL" },
|
||||||
{ "WM/Publisher", "LABEL" },
|
{ "WM/CatalogNo", "CATALOGNUMBER" },
|
||||||
{ "WM/CatalogNo", "CATALOGNUMBER" },
|
{ "WM/Barcode", "BARCODE" },
|
||||||
{ "WM/Barcode", "BARCODE" },
|
{ "WM/EncodedBy", "ENCODEDBY" },
|
||||||
{ "WM/EncodedBy", "ENCODEDBY" },
|
{ "WM/AlbumSortOrder", "ALBUMSORT" },
|
||||||
{ "WM/AlbumSortOrder", "ALBUMSORT" },
|
{ "WM/AlbumArtistSortOrder", "ALBUMARTISTSORT" },
|
||||||
{ "WM/AlbumArtistSortOrder", "ALBUMARTISTSORT" },
|
{ "WM/ArtistSortOrder", "ARTISTSORT" },
|
||||||
{ "WM/ArtistSortOrder", "ARTISTSORT" },
|
{ "WM/TitleSortOrder", "TITLESORT" },
|
||||||
{ "WM/TitleSortOrder", "TITLESORT" },
|
{ "WM/Script", "SCRIPT" },
|
||||||
{ "WM/Script", "SCRIPT" },
|
{ "WM/Language", "LANGUAGE" },
|
||||||
{ "WM/Language", "LANGUAGE" },
|
{ "MusicBrainz/Track Id", "MUSICBRAINZ_TRACKID" },
|
||||||
{ "MusicBrainz/Track Id", "MUSICBRAINZ_TRACKID" },
|
{ "MusicBrainz/Artist Id", "MUSICBRAINZ_ARTISTID" },
|
||||||
{ "MusicBrainz/Artist Id", "MUSICBRAINZ_ARTISTID" },
|
{ "MusicBrainz/Album Id", "MUSICBRAINZ_ALBUMID" },
|
||||||
{ "MusicBrainz/Album Id", "MUSICBRAINZ_ALBUMID" },
|
{ "MusicBrainz/Album Artist Id", "MUSICBRAINZ_ALBUMARTISTID" },
|
||||||
{ "MusicBrainz/Album Artist Id", "MUSICBRAINZ_ALBUMARTISTID" },
|
{ "MusicBrainz/Release Group Id", "MUSICBRAINZ_RELEASEGROUPID" },
|
||||||
{ "MusicBrainz/Release Group Id", "MUSICBRAINZ_RELEASEGROUPID" },
|
{ "MusicBrainz/Work Id", "MUSICBRAINZ_WORKID" },
|
||||||
{ "MusicBrainz/Work Id", "MUSICBRAINZ_WORKID" },
|
{ "MusicIP/PUID", "MUSICIP_PUID" },
|
||||||
{ "MusicIP/PUID", "MUSICIP_PUID" },
|
{ "Acoustid/Id", "ACOUSTID_ID" },
|
||||||
{ "Acoustid/Id", "ACOUSTID_ID" },
|
{ "Acoustid/Fingerprint", "ACOUSTID_FINGERPRINT" },
|
||||||
{ "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)
|
String translateKey(const String &key) {
|
||||||
{
|
for (size_t i = 0; i < keyTranslationSize; ++i) {
|
||||||
for(size_t i = 0; i < keyTranslationSize; ++i) {
|
if (key == keyTranslation[i][0])
|
||||||
if(key == keyTranslation[i][0])
|
return keyTranslation[i][1];
|
||||||
return keyTranslation[i][1];
|
|
||||||
}
|
|
||||||
|
|
||||||
return String();
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
PropertyMap ASF::Tag::properties() const
|
return String();
|
||||||
{
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
PropertyMap ASF::Tag::properties() const {
|
||||||
PropertyMap props;
|
PropertyMap props;
|
||||||
|
|
||||||
if(!d->title.isEmpty()) {
|
if (!d->title.isEmpty()) {
|
||||||
props["TITLE"] = d->title;
|
props["TITLE"] = d->title;
|
||||||
}
|
}
|
||||||
if(!d->artist.isEmpty()) {
|
if (!d->artist.isEmpty()) {
|
||||||
props["ARTIST"] = d->artist;
|
props["ARTIST"] = d->artist;
|
||||||
}
|
}
|
||||||
if(!d->copyright.isEmpty()) {
|
if (!d->copyright.isEmpty()) {
|
||||||
props["COPYRIGHT"] = d->copyright;
|
props["COPYRIGHT"] = d->copyright;
|
||||||
}
|
}
|
||||||
if(!d->comment.isEmpty()) {
|
if (!d->comment.isEmpty()) {
|
||||||
props["COMMENT"] = d->comment;
|
props["COMMENT"] = d->comment;
|
||||||
}
|
}
|
||||||
|
|
||||||
ASF::AttributeListMap::ConstIterator it = d->attributeListMap.begin();
|
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);
|
const String key = translateKey(it->first);
|
||||||
if(!key.isEmpty()) {
|
if (!key.isEmpty()) {
|
||||||
AttributeList::ConstIterator it2 = it->second.begin();
|
AttributeList::ConstIterator it2 = it->second.begin();
|
||||||
for(; it2 != it->second.end(); ++it2) {
|
for (; it2 != it->second.end(); ++it2) {
|
||||||
if(key == "TRACKNUMBER") {
|
if (key == "TRACKNUMBER") {
|
||||||
if(it2->type() == ASF::Attribute::DWordType)
|
if (it2->type() == ASF::Attribute::DWordType)
|
||||||
props.insert(key, String::number(it2->toUInt()));
|
props.insert(key, String::number(it2->toUInt()));
|
||||||
else
|
else
|
||||||
props.insert(key, it2->toString());
|
props.insert(key, it2->toString());
|
||||||
@ -307,37 +273,35 @@ PropertyMap ASF::Tag::properties() const
|
|||||||
return props;
|
return props;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ASF::Tag::removeUnsupportedProperties(const StringList &props)
|
void ASF::Tag::removeUnsupportedProperties(const StringList &props) {
|
||||||
{
|
|
||||||
StringList::ConstIterator it = props.begin();
|
StringList::ConstIterator it = props.begin();
|
||||||
for(; it != props.end(); ++it)
|
for (; it != props.end(); ++it)
|
||||||
d->attributeListMap.erase(*it);
|
d->attributeListMap.erase(*it);
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyMap ASF::Tag::setProperties(const PropertyMap &props)
|
PropertyMap ASF::Tag::setProperties(const PropertyMap &props) {
|
||||||
{
|
|
||||||
static Map<String, String> reverseKeyMap;
|
static Map<String, String> reverseKeyMap;
|
||||||
if(reverseKeyMap.isEmpty()) {
|
if (reverseKeyMap.isEmpty()) {
|
||||||
int numKeys = sizeof(keyTranslation) / sizeof(keyTranslation[0]);
|
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];
|
reverseKeyMap[keyTranslation[i][1]] = keyTranslation[i][0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyMap origProps = properties();
|
PropertyMap origProps = properties();
|
||||||
PropertyMap::ConstIterator it = origProps.begin();
|
PropertyMap::ConstIterator it = origProps.begin();
|
||||||
for(; it != origProps.end(); ++it) {
|
for (; it != origProps.end(); ++it) {
|
||||||
if(!props.contains(it->first) || props[it->first].isEmpty()) {
|
if (!props.contains(it->first) || props[it->first].isEmpty()) {
|
||||||
if(it->first == "TITLE") {
|
if (it->first == "TITLE") {
|
||||||
d->title.clear();
|
d->title.clear();
|
||||||
}
|
}
|
||||||
else if(it->first == "ARTIST") {
|
else if (it->first == "ARTIST") {
|
||||||
d->artist.clear();
|
d->artist.clear();
|
||||||
}
|
}
|
||||||
else if(it->first == "COMMENT") {
|
else if (it->first == "COMMENT") {
|
||||||
d->comment.clear();
|
d->comment.clear();
|
||||||
}
|
}
|
||||||
else if(it->first == "COPYRIGHT") {
|
else if (it->first == "COPYRIGHT") {
|
||||||
d->copyright.clear();
|
d->copyright.clear();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -348,25 +312,25 @@ PropertyMap ASF::Tag::setProperties(const PropertyMap &props)
|
|||||||
|
|
||||||
PropertyMap ignoredProps;
|
PropertyMap ignoredProps;
|
||||||
it = props.begin();
|
it = props.begin();
|
||||||
for(; it != props.end(); ++it) {
|
for (; it != props.end(); ++it) {
|
||||||
if(reverseKeyMap.contains(it->first)) {
|
if (reverseKeyMap.contains(it->first)) {
|
||||||
String name = reverseKeyMap[it->first];
|
String name = reverseKeyMap[it->first];
|
||||||
removeItem(name);
|
removeItem(name);
|
||||||
StringList::ConstIterator it2 = it->second.begin();
|
StringList::ConstIterator it2 = it->second.begin();
|
||||||
for(; it2 != it->second.end(); ++it2) {
|
for (; it2 != it->second.end(); ++it2) {
|
||||||
addAttribute(name, *it2);
|
addAttribute(name, *it2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(it->first == "TITLE") {
|
else if (it->first == "TITLE") {
|
||||||
d->title = it->second.toString();
|
d->title = it->second.toString();
|
||||||
}
|
}
|
||||||
else if(it->first == "ARTIST") {
|
else if (it->first == "ARTIST") {
|
||||||
d->artist = it->second.toString();
|
d->artist = it->second.toString();
|
||||||
}
|
}
|
||||||
else if(it->first == "COMMENT") {
|
else if (it->first == "COMMENT") {
|
||||||
d->comment = it->second.toString();
|
d->comment = it->second.toString();
|
||||||
}
|
}
|
||||||
else if(it->first == "COPYRIGHT") {
|
else if (it->first == "COPYRIGHT") {
|
||||||
d->copyright = it->second.toString();
|
d->copyright = it->second.toString();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
148
3rdparty/taglib/asf/asftag.h
vendored
148
3rdparty/taglib/asf/asftag.h
vendored
@ -35,178 +35,176 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
namespace ASF {
|
namespace ASF {
|
||||||
|
|
||||||
typedef List<Attribute> AttributeList;
|
typedef List<Attribute> AttributeList;
|
||||||
typedef Map<String, AttributeList> AttributeListMap;
|
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;
|
friend class File;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
Tag();
|
||||||
|
|
||||||
Tag();
|
virtual ~Tag();
|
||||||
|
|
||||||
virtual ~Tag();
|
/*!
|
||||||
|
|
||||||
/*!
|
|
||||||
* Returns the track name.
|
* Returns the track name.
|
||||||
*/
|
*/
|
||||||
virtual String title() const;
|
virtual String title() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the artist name.
|
* Returns the artist name.
|
||||||
*/
|
*/
|
||||||
virtual String artist() const;
|
virtual String artist() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the album name; if no album name is present in the tag
|
* Returns the album name; if no album name is present in the tag
|
||||||
* String::null will be returned.
|
* String::null will be returned.
|
||||||
*/
|
*/
|
||||||
virtual String album() const;
|
virtual String album() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the track comment.
|
* Returns the track comment.
|
||||||
*/
|
*/
|
||||||
virtual String comment() const;
|
virtual String comment() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the genre name; if no genre is present in the tag String::null
|
* Returns the genre name; if no genre is present in the tag String::null
|
||||||
* will be returned.
|
* will be returned.
|
||||||
*/
|
*/
|
||||||
virtual String genre() const;
|
virtual String genre() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the rating.
|
* Returns the rating.
|
||||||
*/
|
*/
|
||||||
virtual String rating() const;
|
virtual String rating() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the genre name; if no genre is present in the tag String::null
|
* Returns the genre name; if no genre is present in the tag String::null
|
||||||
* will be returned.
|
* will be returned.
|
||||||
*/
|
*/
|
||||||
virtual String copyright() const;
|
virtual String copyright() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the year; if there is no year set, this will return 0.
|
* Returns the year; if there is no year set, this will return 0.
|
||||||
*/
|
*/
|
||||||
virtual unsigned int year() const;
|
virtual unsigned int year() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the track number; if there is no track number set, this will
|
* Returns the track number; if there is no track number set, this will
|
||||||
* return 0.
|
* return 0.
|
||||||
*/
|
*/
|
||||||
virtual unsigned int track() const;
|
virtual unsigned int track() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the title to \a s.
|
* Sets the title to \a s.
|
||||||
*/
|
*/
|
||||||
virtual void setTitle(const String &s);
|
virtual void setTitle(const String &s);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the artist to \a s.
|
* Sets the artist to \a s.
|
||||||
*/
|
*/
|
||||||
virtual void setArtist(const String &s);
|
virtual void setArtist(const String &s);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the album to \a s. If \a s is String::null then this value will be
|
* Sets the album to \a s. If \a s is String::null then this value will be
|
||||||
* cleared.
|
* cleared.
|
||||||
*/
|
*/
|
||||||
virtual void setAlbum(const String &s);
|
virtual void setAlbum(const String &s);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the comment to \a s.
|
* Sets the comment to \a s.
|
||||||
*/
|
*/
|
||||||
virtual void setComment(const String &s);
|
virtual void setComment(const String &s);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the rating to \a s.
|
* Sets the rating to \a s.
|
||||||
*/
|
*/
|
||||||
virtual void setRating(const String &s);
|
virtual void setRating(const String &s);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the copyright to \a s.
|
* Sets the copyright to \a s.
|
||||||
*/
|
*/
|
||||||
virtual void setCopyright(const String &s);
|
virtual void setCopyright(const String &s);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the genre to \a s.
|
* Sets the genre to \a s.
|
||||||
*/
|
*/
|
||||||
virtual void setGenre(const String &s);
|
virtual void setGenre(const String &s);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the year to \a i. If \a s is 0 then this value will be cleared.
|
* Sets the year to \a i. If \a s is 0 then this value will be cleared.
|
||||||
*/
|
*/
|
||||||
virtual void setYear(unsigned int i);
|
virtual void setYear(unsigned int i);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the track to \a i. If \a s is 0 then this value will be cleared.
|
* Sets the track to \a i. If \a s is 0 then this value will be cleared.
|
||||||
*/
|
*/
|
||||||
virtual void setTrack(unsigned int i);
|
virtual void setTrack(unsigned int i);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns true if the tag does not contain any data. This should be
|
* Returns true if the tag does not contain any data. This should be
|
||||||
* reimplemented in subclasses that provide more than the basic tagging
|
* reimplemented in subclasses that provide more than the basic tagging
|
||||||
* abilities in this class.
|
* abilities in this class.
|
||||||
*/
|
*/
|
||||||
virtual bool isEmpty() const;
|
virtual bool isEmpty() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \deprecated
|
* \deprecated
|
||||||
*/
|
*/
|
||||||
AttributeListMap &attributeListMap();
|
AttributeListMap &attributeListMap();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns a reference to the item list map. This is an AttributeListMap of
|
* Returns a reference to the item list map. This is an AttributeListMap of
|
||||||
* all of the items in the tag.
|
* all of the items in the tag.
|
||||||
*/
|
*/
|
||||||
// BIC: return by value
|
// BIC: return by value
|
||||||
const AttributeListMap &attributeListMap() const;
|
const AttributeListMap &attributeListMap() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \return True if a value for \a attribute is currently set.
|
* \return True if a value for \a attribute is currently set.
|
||||||
*/
|
*/
|
||||||
bool contains(const String &name) const;
|
bool contains(const String &name) const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Removes the \a key attribute from the tag
|
* Removes the \a key attribute from the tag
|
||||||
*/
|
*/
|
||||||
void removeItem(const String &name);
|
void removeItem(const String &name);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \return The list of values for the key \a name, or an empty list if no
|
* \return The list of values for the key \a name, or an empty list if no
|
||||||
* values have been set.
|
* values have been set.
|
||||||
*/
|
*/
|
||||||
AttributeList attribute(const String &name) const;
|
AttributeList attribute(const String &name) const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the \a key attribute to the value of \a attribute. If an attribute
|
* Sets the \a key attribute to the value of \a attribute. If an attribute
|
||||||
* with the \a key is already present, it will be replaced.
|
* with the \a key is already present, it will be replaced.
|
||||||
*/
|
*/
|
||||||
void setAttribute(const String &name, const Attribute &attribute);
|
void setAttribute(const String &name, const Attribute &attribute);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets multiple \a values to the key \a name.
|
* Sets multiple \a values to the key \a name.
|
||||||
*/
|
*/
|
||||||
void setAttribute(const String &name, const AttributeList &values);
|
void setAttribute(const String &name, const AttributeList &values);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the \a key attribute to the value of \a attribute. If an attribute
|
* Sets the \a key attribute to the value of \a attribute. If an attribute
|
||||||
* with the \a key is already present, it will be added to the list.
|
* with the \a key is already present, it will be added to the list.
|
||||||
*/
|
*/
|
||||||
void addAttribute(const String &name, const Attribute &attribute);
|
void addAttribute(const String &name, const Attribute &attribute);
|
||||||
|
|
||||||
PropertyMap properties() const;
|
PropertyMap properties() const;
|
||||||
void removeUnsupportedProperties(const StringList& properties);
|
void removeUnsupportedProperties(const StringList &properties);
|
||||||
PropertyMap setProperties(const PropertyMap &properties);
|
PropertyMap setProperties(const PropertyMap &properties);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
class TagPrivate;
|
||||||
class TagPrivate;
|
TagPrivate *d;
|
||||||
TagPrivate *d;
|
};
|
||||||
};
|
} // namespace ASF
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
122
3rdparty/taglib/asf/asfutils.h
vendored
122
3rdparty/taglib/asf/asfutils.h
vendored
@ -31,76 +31,68 @@
|
|||||||
#ifndef DO_NOT_DOCUMENT // tell Doxygen not to document this header
|
#ifndef DO_NOT_DOCUMENT // tell Doxygen not to document this header
|
||||||
|
|
||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib
|
namespace TagLib {
|
||||||
{
|
namespace ASF {
|
||||||
namespace ASF
|
namespace {
|
||||||
{
|
|
||||||
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);
|
||||||
const ByteVector v = file->readBlock(2);
|
if (v.size() != 2) {
|
||||||
if(v.size() != 2) {
|
if (ok) *ok = false;
|
||||||
if(ok) *ok = false;
|
return 0;
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if(ok) *ok = true;
|
|
||||||
return v.toUShort(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline unsigned int readDWORD(File *file, bool *ok = 0)
|
|
||||||
{
|
|
||||||
const ByteVector v = file->readBlock(4);
|
|
||||||
if(v.size() != 4) {
|
|
||||||
if(ok) *ok = false;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if(ok) *ok = true;
|
|
||||||
return v.toUInt(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline long long readQWORD(File *file, bool *ok = 0)
|
|
||||||
{
|
|
||||||
const ByteVector v = file->readBlock(8);
|
|
||||||
if(v.size() != 8) {
|
|
||||||
if(ok) *ok = false;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if(ok) *ok = true;
|
|
||||||
return v.toLongLong(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
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') {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
size -= 2;
|
|
||||||
}
|
|
||||||
if(size != data.size()) {
|
|
||||||
data.resize(size);
|
|
||||||
}
|
|
||||||
return String(data, String::UTF16LE);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline ByteVector renderString(const String &str, bool includeLength = false)
|
|
||||||
{
|
|
||||||
ByteVector data = str.data(String::UTF16LE) + ByteVector::fromShort(0, false);
|
|
||||||
if(includeLength) {
|
|
||||||
data = ByteVector::fromShort(data.size(), false) + data;
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (ok) *ok = true;
|
||||||
|
return v.toUShort(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline unsigned int readDWORD(File *file, bool *ok = 0) {
|
||||||
|
const ByteVector v = file->readBlock(4);
|
||||||
|
if (v.size() != 4) {
|
||||||
|
if (ok) *ok = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (ok) *ok = true;
|
||||||
|
return v.toUInt(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline long long readQWORD(File *file, bool *ok = 0) {
|
||||||
|
const ByteVector v = file->readBlock(8);
|
||||||
|
if (v.size() != 8) {
|
||||||
|
if (ok) *ok = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (ok) *ok = true;
|
||||||
|
return v.toLongLong(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
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') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
size -= 2;
|
||||||
|
}
|
||||||
|
if (size != data.size()) {
|
||||||
|
data.resize(size);
|
||||||
|
}
|
||||||
|
return String(data, String::UTF16LE);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ByteVector renderString(const String &str, bool includeLength = false) {
|
||||||
|
ByteVector data = str.data(String::UTF16LE) + ByteVector::fromShort(0, false);
|
||||||
|
if (includeLength) {
|
||||||
|
data = ByteVector::fromShort(data.size(), false) + data;
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
} // namespace ASF
|
||||||
|
} // namespace TagLib
|
||||||
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
83
3rdparty/taglib/audioproperties.cpp
vendored
83
3rdparty/taglib/audioproperties.cpp
vendored
@ -48,61 +48,55 @@ using namespace Strawberry_TagLib::TagLib;
|
|||||||
// This macro is a workaround for the fact that we can't add virtual functions.
|
// This macro is a workaround for the fact that we can't add virtual functions.
|
||||||
// Should be true virtual functions in taglib2.
|
// Should be true virtual functions in taglib2.
|
||||||
|
|
||||||
#define VIRTUAL_FUNCTION_WORKAROUND(function_name, default_value) \
|
#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(); \
|
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(); \
|
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(); \
|
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(); \
|
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(); \
|
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(); \
|
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(); \
|
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(); \
|
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(); \
|
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(); \
|
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(); \
|
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(); \
|
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(); \
|
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(); \
|
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(); \
|
return dynamic_cast<const DSDIFF::Properties*>(this)->function_name(); \
|
||||||
else \
|
else \
|
||||||
return (default_value);
|
return (default_value);
|
||||||
|
|
||||||
class AudioProperties::AudioPropertiesPrivate
|
class AudioProperties::AudioPropertiesPrivate {
|
||||||
{
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// public methods
|
// public methods
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
AudioProperties::~AudioProperties()
|
AudioProperties::~AudioProperties() {
|
||||||
{
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int AudioProperties::lengthInSeconds() const
|
int AudioProperties::lengthInSeconds() const {
|
||||||
{
|
|
||||||
VIRTUAL_FUNCTION_WORKAROUND(lengthInSeconds, 0)
|
VIRTUAL_FUNCTION_WORKAROUND(lengthInSeconds, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
int AudioProperties::lengthInMilliseconds() const
|
int AudioProperties::lengthInMilliseconds() const {
|
||||||
{
|
|
||||||
VIRTUAL_FUNCTION_WORKAROUND(lengthInMilliseconds, 0)
|
VIRTUAL_FUNCTION_WORKAROUND(lengthInMilliseconds, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,8 +104,5 @@ int AudioProperties::lengthInMilliseconds() const
|
|||||||
// protected methods
|
// protected methods
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
AudioProperties::AudioProperties(ReadStyle) :
|
AudioProperties::AudioProperties(ReadStyle) : d(0) {
|
||||||
d(0)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
83
3rdparty/taglib/audioproperties.h
vendored
83
3rdparty/taglib/audioproperties.h
vendored
@ -31,99 +31,96 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace 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
|
* 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
|
* dependent values, please see see the subclasses APIs. This is meant to
|
||||||
* compliment the TagLib::File and TagLib::Tag APIs in providing a simple
|
* compliment the TagLib::File and TagLib::Tag APIs in providing a simple
|
||||||
* interface that is sufficient for most applications.
|
* interface that is sufficient for most applications.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class TAGLIB_EXPORT AudioProperties
|
class TAGLIB_EXPORT AudioProperties {
|
||||||
{
|
public:
|
||||||
public:
|
/*!
|
||||||
|
|
||||||
/*!
|
|
||||||
* Reading audio properties from a file can sometimes be very time consuming
|
* Reading audio properties from a file can sometimes be very time consuming
|
||||||
* and for the most accurate results can often involve reading the entire
|
* and for the most accurate results can often involve reading the entire
|
||||||
* file. Because in many situations speed is critical or the accuracy of the
|
* file. Because in many situations speed is critical or the accuracy of the
|
||||||
* values is not particularly important this allows the level of desired
|
* values is not particularly important this allows the level of desired
|
||||||
* accuracy to be set.
|
* accuracy to be set.
|
||||||
*/
|
*/
|
||||||
enum ReadStyle {
|
enum ReadStyle {
|
||||||
//! Read as little of the file as possible
|
//! Read as little of the file as possible
|
||||||
Fast,
|
Fast,
|
||||||
//! Read more of the file and make better values guesses
|
//! Read more of the file and make better values guesses
|
||||||
Average,
|
Average,
|
||||||
//! Read as much of the file as needed to report accurate values
|
//! Read as much of the file as needed to report accurate values
|
||||||
Accurate
|
Accurate
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys this AudioProperties instance.
|
* Destroys this AudioProperties instance.
|
||||||
*/
|
*/
|
||||||
virtual ~AudioProperties();
|
virtual ~AudioProperties();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the length of the file in seconds.
|
* Returns the length of the file in seconds.
|
||||||
*/
|
*/
|
||||||
virtual int length() const = 0;
|
virtual int length() const = 0;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the length of the file in seconds. The length is rounded down to
|
* Returns the length of the file in seconds. The length is rounded down to
|
||||||
* the nearest whole second.
|
* the nearest whole second.
|
||||||
*
|
*
|
||||||
* \see lengthInMilliseconds()
|
* \see lengthInMilliseconds()
|
||||||
*/
|
*/
|
||||||
// BIC: make virtual
|
// BIC: make virtual
|
||||||
int lengthInSeconds() const;
|
int lengthInSeconds() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the length of the file in milliseconds.
|
* Returns the length of the file in milliseconds.
|
||||||
*
|
*
|
||||||
* \see lengthInSeconds()
|
* \see lengthInSeconds()
|
||||||
*/
|
*/
|
||||||
// BIC: make virtual
|
// BIC: make virtual
|
||||||
int lengthInMilliseconds() const;
|
int lengthInMilliseconds() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the most appropriate bit rate for the file in kb/s. For constant
|
* Returns the most appropriate bit rate for the file in kb/s. For constant
|
||||||
* bitrate formats this is simply the bitrate of the file. For variable
|
* bitrate formats this is simply the bitrate of the file. For variable
|
||||||
* bitrate formats this is either the average or nominal bitrate.
|
* bitrate formats this is either the average or nominal bitrate.
|
||||||
*/
|
*/
|
||||||
virtual int bitrate() const = 0;
|
virtual int bitrate() const = 0;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the sample rate in Hz.
|
* Returns the sample rate in Hz.
|
||||||
*/
|
*/
|
||||||
virtual int sampleRate() const = 0;
|
virtual int sampleRate() const = 0;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the number of audio channels.
|
* Returns the number of audio channels.
|
||||||
*/
|
*/
|
||||||
virtual int channels() const = 0;
|
virtual int channels() const = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
/*!
|
||||||
/*!
|
|
||||||
* Construct an audio properties instance. This is protected as this class
|
* Construct an audio properties instance. This is protected as this class
|
||||||
* should not be instantiated directly, but should be instantiated via its
|
* should not be instantiated directly, but should be instantiated via its
|
||||||
* subclasses and can be fetched from the FileRef or File APIs.
|
* subclasses and can be fetched from the FileRef or File APIs.
|
||||||
*
|
*
|
||||||
* \see ReadStyle
|
* \see ReadStyle
|
||||||
*/
|
*/
|
||||||
AudioProperties(ReadStyle style);
|
AudioProperties(ReadStyle style);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AudioProperties(const AudioProperties &);
|
AudioProperties(const AudioProperties &);
|
||||||
AudioProperties &operator=(const AudioProperties &);
|
AudioProperties &operator=(const AudioProperties &);
|
||||||
|
|
||||||
class AudioPropertiesPrivate;
|
class AudioPropertiesPrivate;
|
||||||
AudioPropertiesPrivate *d;
|
AudioPropertiesPrivate *d;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#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 Strawberry_TagLib::TagLib;
|
||||||
using namespace DSDIFF::DIIN;
|
using namespace DSDIFF::DIIN;
|
||||||
|
|
||||||
class DSDIFF::DIIN::Tag::TagPrivate
|
class DSDIFF::DIIN::Tag::TagPrivate {
|
||||||
{
|
public:
|
||||||
public:
|
TagPrivate() {
|
||||||
TagPrivate()
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String title;
|
String title;
|
||||||
String artist;
|
String artist;
|
||||||
};
|
};
|
||||||
|
|
||||||
DSDIFF::DIIN::Tag::Tag() : Strawberry_TagLib::TagLib::Tag()
|
DSDIFF::DIIN::Tag::Tag() : Strawberry_TagLib::TagLib::Tag() {
|
||||||
{
|
|
||||||
d = new TagPrivate;
|
d = new TagPrivate;
|
||||||
}
|
}
|
||||||
|
|
||||||
DSDIFF::DIIN::Tag::~Tag()
|
DSDIFF::DIIN::Tag::~Tag() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
String DSDIFF::DIIN::Tag::title() const
|
String DSDIFF::DIIN::Tag::title() const {
|
||||||
{
|
|
||||||
return d->title;
|
return d->title;
|
||||||
}
|
}
|
||||||
|
|
||||||
String DSDIFF::DIIN::Tag::artist() const
|
String DSDIFF::DIIN::Tag::artist() const {
|
||||||
{
|
|
||||||
return d->artist;
|
return d->artist;
|
||||||
}
|
}
|
||||||
|
|
||||||
String DSDIFF::DIIN::Tag::album() const
|
String DSDIFF::DIIN::Tag::album() const {
|
||||||
{
|
|
||||||
return String();
|
return String();
|
||||||
}
|
}
|
||||||
|
|
||||||
String DSDIFF::DIIN::Tag::comment() const
|
String DSDIFF::DIIN::Tag::comment() const {
|
||||||
{
|
|
||||||
return String();
|
return String();
|
||||||
}
|
}
|
||||||
|
|
||||||
String DSDIFF::DIIN::Tag::genre() const
|
String DSDIFF::DIIN::Tag::genre() const {
|
||||||
{
|
|
||||||
return String();
|
return String();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int DSDIFF::DIIN::Tag::year() const
|
unsigned int DSDIFF::DIIN::Tag::year() const {
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int DSDIFF::DIIN::Tag::track() const
|
unsigned int DSDIFF::DIIN::Tag::track() const {
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSDIFF::DIIN::Tag::setTitle(const String &title)
|
void DSDIFF::DIIN::Tag::setTitle(const String &title) {
|
||||||
{
|
if (title.isNull() || title.isEmpty())
|
||||||
if(title.isNull() || title.isEmpty())
|
|
||||||
d->title = String();
|
d->title = String();
|
||||||
else
|
else
|
||||||
d->title = title;
|
d->title = title;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSDIFF::DIIN::Tag::setArtist(const String &artist)
|
void DSDIFF::DIIN::Tag::setArtist(const String &artist) {
|
||||||
{
|
if (artist.isNull() || artist.isEmpty())
|
||||||
if(artist.isNull() || artist.isEmpty())
|
|
||||||
d->artist = String();
|
d->artist = String();
|
||||||
else
|
else
|
||||||
d->artist = artist;
|
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;
|
PropertyMap properties;
|
||||||
properties["TITLE"] = d->title;
|
properties["TITLE"] = d->title;
|
||||||
properties["ARTIST"] = d->artist;
|
properties["ARTIST"] = d->artist;
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyMap DSDIFF::DIIN::Tag::setProperties(const PropertyMap &origProps)
|
PropertyMap DSDIFF::DIIN::Tag::setProperties(const PropertyMap &origProps) {
|
||||||
{
|
|
||||||
PropertyMap properties(origProps);
|
PropertyMap properties(origProps);
|
||||||
properties.removeEmpty();
|
properties.removeEmpty();
|
||||||
StringList oneValueSet;
|
StringList oneValueSet;
|
||||||
|
|
||||||
if(properties.contains("TITLE")) {
|
if (properties.contains("TITLE")) {
|
||||||
d->title = properties["TITLE"].front();
|
d->title = properties["TITLE"].front();
|
||||||
oneValueSet.append("TITLE");
|
oneValueSet.append("TITLE");
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
d->title = String();
|
d->title = String();
|
||||||
|
|
||||||
if(properties.contains("ARTIST")) {
|
if (properties.contains("ARTIST")) {
|
||||||
d->artist = properties["ARTIST"].front();
|
d->artist = properties["ARTIST"].front();
|
||||||
oneValueSet.append("ARTIST");
|
oneValueSet.append("ARTIST");
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
d->artist = String();
|
d->artist = String();
|
||||||
|
|
||||||
// for each tag that has been set above, remove the first entry in the corresponding
|
// 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.
|
// value list. The others will be returned as unsupported by this format.
|
||||||
for(StringList::Iterator it = oneValueSet.begin(); it != oneValueSet.end(); ++it) {
|
for (StringList::Iterator it = oneValueSet.begin(); it != oneValueSet.end(); ++it) {
|
||||||
if(properties[*it].size() == 1)
|
if (properties[*it].size() == 1)
|
||||||
properties.erase(*it);
|
properties.erase(*it);
|
||||||
else
|
else
|
||||||
properties[*it].erase(properties[*it].begin());
|
properties[*it].erase(properties[*it].begin());
|
||||||
@ -159,4 +141,3 @@ PropertyMap DSDIFF::DIIN::Tag::setProperties(const PropertyMap &origProps)
|
|||||||
|
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
100
3rdparty/taglib/dsdiff/dsdiffdiintag.h
vendored
100
3rdparty/taglib/dsdiff/dsdiffdiintag.h
vendored
@ -31,102 +31,101 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
namespace DSDIFF {
|
namespace DSDIFF {
|
||||||
|
|
||||||
namespace DIIN {
|
namespace DIIN {
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Tags from the Edited Master Chunk Info
|
* Tags from the Edited Master Chunk Info
|
||||||
*
|
*
|
||||||
* Only Title and Artist tags are supported
|
* 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:
|
||||||
public:
|
Tag();
|
||||||
Tag();
|
virtual ~Tag();
|
||||||
virtual ~Tag();
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the track name; if no track name is present in the tag
|
* Returns the track name; if no track name is present in the tag
|
||||||
* String() will be returned.
|
* String() will be returned.
|
||||||
*/
|
*/
|
||||||
String title() const;
|
String title() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the artist name; if no artist name is present in the tag
|
* Returns the artist name; if no artist name is present in the tag
|
||||||
* String() will be returned.
|
* String() will be returned.
|
||||||
*/
|
*/
|
||||||
String artist() const;
|
String artist() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Not supported. Therefore always returns String().
|
* Not supported. Therefore always returns String().
|
||||||
*/
|
*/
|
||||||
String album() const;
|
String album() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Not supported. Therefore always returns String().
|
* Not supported. Therefore always returns String().
|
||||||
*/
|
*/
|
||||||
String comment() const;
|
String comment() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Not supported. Therefore always returns String().
|
* Not supported. Therefore always returns String().
|
||||||
*/
|
*/
|
||||||
String genre() const;
|
String genre() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Not supported. Therefore always returns 0.
|
* Not supported. Therefore always returns 0.
|
||||||
*/
|
*/
|
||||||
unsigned int year() const;
|
unsigned int year() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Not supported. Therefore always returns 0.
|
* Not supported. Therefore always returns 0.
|
||||||
*/
|
*/
|
||||||
unsigned int track() const;
|
unsigned int track() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the title to \a title. If \a title is String() then this
|
* Sets the title to \a title. If \a title is String() then this
|
||||||
* value will be cleared.
|
* value will be cleared.
|
||||||
*/
|
*/
|
||||||
void setTitle(const String &title);
|
void setTitle(const String &title);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the artist to \a artist. If \a artist is String() then this
|
* Sets the artist to \a artist. If \a artist is String() then this
|
||||||
* value will be cleared.
|
* value will be cleared.
|
||||||
*/
|
*/
|
||||||
void setArtist(const String &artist);
|
void setArtist(const String &artist);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Not supported and therefore ignored.
|
* Not supported and therefore ignored.
|
||||||
*/
|
*/
|
||||||
void setAlbum(const String &album);
|
void setAlbum(const String &album);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Not supported and therefore ignored.
|
* Not supported and therefore ignored.
|
||||||
*/
|
*/
|
||||||
void setComment(const String &comment);
|
void setComment(const String &comment);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Not supported and therefore ignored.
|
* Not supported and therefore ignored.
|
||||||
*/
|
*/
|
||||||
void setGenre(const String &genre);
|
void setGenre(const String &genre);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Not supported and therefore ignored.
|
* Not supported and therefore ignored.
|
||||||
*/
|
*/
|
||||||
void setYear(unsigned int year);
|
void setYear(unsigned int year);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Not supported and therefore ignored.
|
* Not supported and therefore ignored.
|
||||||
*/
|
*/
|
||||||
void setTrack(unsigned int track);
|
void setTrack(unsigned int track);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Implements the unified property interface -- export function.
|
* Implements the unified property interface -- export function.
|
||||||
* Since the DIIN tag is very limited, the exported map is as well.
|
* Since the DIIN tag is very limited, the exported map is as well.
|
||||||
*/
|
*/
|
||||||
PropertyMap properties() const;
|
PropertyMap properties() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Implements the unified property interface -- import function.
|
* Implements the unified property interface -- import function.
|
||||||
* Because of the limitations of the DIIN file tag, any tags besides
|
* Because of the limitations of the DIIN file tag, any tags besides
|
||||||
* TITLE and ARTIST, will be
|
* TITLE and ARTIST, will be
|
||||||
@ -134,19 +133,18 @@ namespace TagLib {
|
|||||||
* all but the first will be contained in the returned map of unsupported
|
* all but the first will be contained in the returned map of unsupported
|
||||||
* properties.
|
* properties.
|
||||||
*/
|
*/
|
||||||
PropertyMap setProperties(const PropertyMap &);
|
PropertyMap setProperties(const PropertyMap &);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Tag(const Tag &);
|
Tag(const Tag &);
|
||||||
Tag &operator=(const Tag &);
|
Tag &operator=(const Tag &);
|
||||||
|
|
||||||
class TagPrivate;
|
class TagPrivate;
|
||||||
TagPrivate *d;
|
TagPrivate *d;
|
||||||
};
|
};
|
||||||
}
|
} // namespace DIIN
|
||||||
}
|
} // namespace DSDIFF
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
508
3rdparty/taglib/dsdiff/dsdifffile.cpp
vendored
508
3rdparty/taglib/dsdiff/dsdifffile.cpp
vendored
@ -37,70 +37,62 @@
|
|||||||
|
|
||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
namespace
|
namespace {
|
||||||
{
|
struct Chunk64 {
|
||||||
struct Chunk64
|
ByteVector name;
|
||||||
{
|
unsigned long long offset;
|
||||||
ByteVector name;
|
unsigned long long size;
|
||||||
unsigned long long offset;
|
char padding;
|
||||||
unsigned long long size;
|
};
|
||||||
char padding;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::vector<Chunk64> ChunkList;
|
typedef std::vector<Chunk64> ChunkList;
|
||||||
|
|
||||||
int chunkIndex(const ChunkList &chunks, const ByteVector &id)
|
int chunkIndex(const ChunkList &chunks, const ByteVector &id) {
|
||||||
{
|
for (unsigned long int i = 0; i < chunks.size(); i++) {
|
||||||
for (unsigned long int i = 0 ; i < chunks.size() ; i++) {
|
if (chunks[i].name == id)
|
||||||
if(chunks[i].name == id)
|
return i;
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isValidChunkID(const ByteVector &name)
|
return -1;
|
||||||
{
|
|
||||||
if(name.size() != 4)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
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
|
bool isValidChunkID(const ByteVector &name) {
|
||||||
{
|
if (name.size() != 4)
|
||||||
public:
|
return false;
|
||||||
FilePrivate() :
|
|
||||||
endianness(BigEndian),
|
for (int i = 0; i < 4; i++) {
|
||||||
size(0),
|
if (name[i] < 32)
|
||||||
isID3InPropChunk(false),
|
return false;
|
||||||
duplicateID3V2chunkIndex(-1),
|
}
|
||||||
properties(0),
|
|
||||||
id3v2TagChunkID("ID3 "),
|
return true;
|
||||||
hasID3v2(false),
|
}
|
||||||
hasDiin(false)
|
|
||||||
{
|
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) {
|
||||||
childChunkIndex[ID3v2Index] = -1;
|
childChunkIndex[ID3v2Index] = -1;
|
||||||
childChunkIndex[DIINIndex] = -1;
|
childChunkIndex[DIINIndex] = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
~FilePrivate()
|
~FilePrivate() {
|
||||||
{
|
|
||||||
delete properties;
|
delete properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,12 +127,11 @@ public:
|
|||||||
// static members
|
// static members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
bool DSDIFF::File::isSupported(IOStream *stream)
|
bool DSDIFF::File::isSupported(IOStream *stream) {
|
||||||
{
|
// A DSDIFF file has to start with "FRM8????????DSD ".
|
||||||
// A DSDIFF file has to start with "FRM8????????DSD ".
|
|
||||||
|
|
||||||
const ByteVector id = Utils::readHeader(stream, 16, false);
|
const ByteVector id = Utils::readHeader(stream, 16, false);
|
||||||
return (id.startsWith("FRM8") && id.containsAt("DSD ", 12));
|
return (id.startsWith("FRM8") && id.containsAt("DSD ", 12));
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -148,107 +139,93 @@ bool DSDIFF::File::isSupported(IOStream *stream)
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
DSDIFF::File::File(FileName file, bool readProperties,
|
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 = new FilePrivate;
|
||||||
d->endianness = BigEndian;
|
d->endianness = BigEndian;
|
||||||
if(isOpen())
|
if (isOpen())
|
||||||
read(readProperties, propertiesStyle);
|
read(readProperties, propertiesStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
DSDIFF::File::File(IOStream *stream, bool readProperties,
|
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 = new FilePrivate;
|
||||||
d->endianness = BigEndian;
|
d->endianness = BigEndian;
|
||||||
if(isOpen())
|
if (isOpen())
|
||||||
read(readProperties, propertiesStyle);
|
read(readProperties, propertiesStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
DSDIFF::File::~File()
|
DSDIFF::File::~File() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
Strawberry_TagLib::TagLib::Tag *DSDIFF::File::tag() const
|
Strawberry_TagLib::TagLib::Tag *DSDIFF::File::tag() const {
|
||||||
{
|
|
||||||
return &d->tag;
|
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);
|
return d->tag.access<ID3v2::Tag>(ID3v2Index, create);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DSDIFF::File::hasID3v2Tag() const
|
bool DSDIFF::File::hasID3v2Tag() const {
|
||||||
{
|
|
||||||
return d->hasID3v2;
|
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);
|
return d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, create);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DSDIFF::File::hasDIINTag() const
|
bool DSDIFF::File::hasDIINTag() const {
|
||||||
{
|
|
||||||
return d->hasDiin;
|
return d->hasDiin;
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyMap DSDIFF::File::properties() const
|
PropertyMap DSDIFF::File::properties() const {
|
||||||
{
|
if (d->hasID3v2)
|
||||||
if(d->hasID3v2)
|
|
||||||
return d->tag.access<ID3v2::Tag>(ID3v2Index, false)->properties();
|
return d->tag.access<ID3v2::Tag>(ID3v2Index, false)->properties();
|
||||||
|
|
||||||
return PropertyMap();
|
return PropertyMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSDIFF::File::removeUnsupportedProperties(const StringList &unsupported)
|
void DSDIFF::File::removeUnsupportedProperties(const StringList &unsupported) {
|
||||||
{
|
if (d->hasID3v2)
|
||||||
if(d->hasID3v2)
|
|
||||||
d->tag.access<ID3v2::Tag>(ID3v2Index, false)->removeUnsupportedProperties(unsupported);
|
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);
|
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);
|
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;
|
return d->properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DSDIFF::File::save()
|
bool DSDIFF::File::save() {
|
||||||
{
|
|
||||||
return save(AllTags);
|
return save(AllTags);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DSDIFF::File::save(TagTypes tags, StripTags, ID3v2::Version version)
|
bool DSDIFF::File::save(TagTypes tags, StripTags, ID3v2::Version version) {
|
||||||
{
|
if (readOnly()) {
|
||||||
if(readOnly()) {
|
|
||||||
debug("DSDIFF::File::save() -- File is read only.");
|
debug("DSDIFF::File::save() -- File is read only.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!isValid()) {
|
if (!isValid()) {
|
||||||
debug("DSDIFF::File::save() -- Trying to save invalid file.");
|
debug("DSDIFF::File::save() -- Trying to save invalid file.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//if(strip == StripOthers || strip == StripAll)
|
//if(strip == StripOthers || strip == StripAll)
|
||||||
//File::strip(static_cast<TagTypes>(AllTags & ~tags));
|
//File::strip(static_cast<TagTypes>(AllTags & ~tags));
|
||||||
|
|
||||||
// First: save ID3V2 chunk
|
// First: save ID3V2 chunk
|
||||||
|
|
||||||
ID3v2::Tag *id3v2Tag = d->tag.access<ID3v2::Tag>(ID3v2Index, false);
|
ID3v2::Tag *id3v2Tag = d->tag.access<ID3v2::Tag>(ID3v2Index, false);
|
||||||
|
|
||||||
if(tags & ID3v2 && id3v2Tag) {
|
if (tags & ID3v2 && id3v2Tag) {
|
||||||
if(d->isID3InPropChunk) {
|
if (d->isID3InPropChunk) {
|
||||||
if(id3v2Tag && !id3v2Tag->isEmpty()) {
|
if (id3v2Tag && !id3v2Tag->isEmpty()) {
|
||||||
setChildChunkData(d->id3v2TagChunkID, id3v2Tag->render(version), PROPChunk);
|
setChildChunkData(d->id3v2TagChunkID, id3v2Tag->render(version), PROPChunk);
|
||||||
d->hasID3v2 = true;
|
d->hasID3v2 = true;
|
||||||
}
|
}
|
||||||
@ -259,7 +236,7 @@ bool DSDIFF::File::save(TagTypes tags, StripTags, ID3v2::Version version)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(id3v2Tag && !id3v2Tag->isEmpty()) {
|
if (id3v2Tag && !id3v2Tag->isEmpty()) {
|
||||||
setRootChunkData(d->id3v2TagChunkID, id3v2Tag->render(version));
|
setRootChunkData(d->id3v2TagChunkID, id3v2Tag->render(version));
|
||||||
d->hasID3v2 = true;
|
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);
|
DSDIFF::DIIN::Tag *diinTag = d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, false);
|
||||||
|
|
||||||
if(tags & DIIN && diinTag) {
|
if (tags & DIIN && diinTag) {
|
||||||
if(!diinTag->title().isEmpty()) {
|
if (!diinTag->title().isEmpty()) {
|
||||||
ByteVector diinTitle;
|
ByteVector diinTitle;
|
||||||
diinTitle.append(ByteVector::fromUInt(diinTag->title().size(), d->endianness == BigEndian));
|
diinTitle.append(ByteVector::fromUInt(diinTag->title().size(), d->endianness == BigEndian));
|
||||||
diinTitle.append(ByteVector::fromCString(diinTag->title().toCString()));
|
diinTitle.append(ByteVector::fromCString(diinTag->title().toCString()));
|
||||||
@ -285,7 +262,7 @@ bool DSDIFF::File::save(TagTypes tags, StripTags, ID3v2::Version version)
|
|||||||
else
|
else
|
||||||
setChildChunkData("DITI", ByteVector(), DIINChunk);
|
setChildChunkData("DITI", ByteVector(), DIINChunk);
|
||||||
|
|
||||||
if(!diinTag->artist().isEmpty()) {
|
if (!diinTag->artist().isEmpty()) {
|
||||||
ByteVector diinArtist;
|
ByteVector diinArtist;
|
||||||
diinArtist.append(ByteVector::fromUInt(diinTag->artist().size(), d->endianness == BigEndian));
|
diinArtist.append(ByteVector::fromUInt(diinTag->artist().size(), d->endianness == BigEndian));
|
||||||
diinArtist.append(ByteVector::fromCString(diinTag->artist().toCString()));
|
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
|
// Third: remove the duplicate ID3V2 chunk (inside PROP chunk) if any
|
||||||
if(d->duplicateID3V2chunkIndex>=0) {
|
if (d->duplicateID3V2chunkIndex >= 0) {
|
||||||
setChildChunkData(d->duplicateID3V2chunkIndex, ByteVector(), PROPChunk);
|
setChildChunkData(d->duplicateID3V2chunkIndex, ByteVector(), PROPChunk);
|
||||||
d->duplicateID3V2chunkIndex = -1;
|
d->duplicateID3V2chunkIndex = -1;
|
||||||
}
|
}
|
||||||
@ -304,9 +281,8 @@ bool DSDIFF::File::save(TagTypes tags, StripTags, ID3v2::Version version)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSDIFF::File::strip(TagTypes tags)
|
void DSDIFF::File::strip(TagTypes tags) {
|
||||||
{
|
if (tags & ID3v2) {
|
||||||
if(tags & ID3v2) {
|
|
||||||
removeRootChunk("ID3 ");
|
removeRootChunk("ID3 ");
|
||||||
removeRootChunk("id3 ");
|
removeRootChunk("id3 ");
|
||||||
d->hasID3v2 = false;
|
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
|
/// TODO: needs to also account for ID3v2 tags under the PROP chunk
|
||||||
}
|
}
|
||||||
if(tags & DIIN) {
|
if (tags & DIIN) {
|
||||||
removeRootChunk("DITI");
|
removeRootChunk("DITI");
|
||||||
removeRootChunk("DIAR");
|
removeRootChunk("DIAR");
|
||||||
d->hasDiin = false;
|
d->hasDiin = false;
|
||||||
@ -326,35 +302,31 @@ void DSDIFF::File::strip(TagTypes tags)
|
|||||||
// private members
|
// 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;
|
||||||
unsigned long long chunkSize = d->chunks[i].size + d->chunks[i].padding + 12;
|
|
||||||
|
|
||||||
d->size -= chunkSize;
|
d->size -= chunkSize;
|
||||||
insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8);
|
insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8);
|
||||||
|
|
||||||
removeBlock(d->chunks[i].offset - 12, chunkSize);
|
removeBlock(d->chunks[i].offset - 12, chunkSize);
|
||||||
|
|
||||||
// Update the internal offsets
|
// Update the internal offsets
|
||||||
|
|
||||||
for(unsigned long r = i + 1; r < d->chunks.size(); r++)
|
for (unsigned long r = i + 1; r < d->chunks.size(); r++)
|
||||||
d->chunks[r].offset = d->chunks[r - 1].offset + 12
|
d->chunks[r].offset = d->chunks[r - 1].offset + 12 + d->chunks[r - 1].size + d->chunks[r - 1].padding;
|
||||||
+ d->chunks[r - 1].size + d->chunks[r - 1].padding;
|
|
||||||
|
|
||||||
d->chunks.erase(d->chunks.begin() + i);
|
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);
|
int i = chunkIndex(d->chunks, id);
|
||||||
|
|
||||||
if(i >= 0)
|
if (i >= 0)
|
||||||
removeRootChunk(i);
|
removeRootChunk(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSDIFF::File::setRootChunkData(unsigned int i, const ByteVector &data)
|
void DSDIFF::File::setRootChunkData(unsigned int i, const ByteVector &data) {
|
||||||
{
|
if (data.isEmpty()) {
|
||||||
if(data.isEmpty()) {
|
|
||||||
removeRootChunk(i);
|
removeRootChunk(i);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -368,9 +340,9 @@ void DSDIFF::File::setRootChunkData(unsigned int i, const ByteVector &data)
|
|||||||
// Now update the specific chunk
|
// Now update the specific chunk
|
||||||
|
|
||||||
writeChunk(d->chunks[i].name,
|
writeChunk(d->chunks[i].name,
|
||||||
data,
|
data,
|
||||||
d->chunks[i].offset - 12,
|
d->chunks[i].offset - 12,
|
||||||
d->chunks[i].size + d->chunks[i].padding + 12);
|
d->chunks[i].size + d->chunks[i].padding + 12);
|
||||||
|
|
||||||
d->chunks[i].size = data.size();
|
d->chunks[i].size = data.size();
|
||||||
d->chunks[i].padding = (data.size() & 0x01) ? 1 : 0;
|
d->chunks[i].padding = (data.size() & 0x01) ? 1 : 0;
|
||||||
@ -380,16 +352,15 @@ void DSDIFF::File::setRootChunkData(unsigned int i, const ByteVector &data)
|
|||||||
updateRootChunksStructure(i + 1);
|
updateRootChunksStructure(i + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSDIFF::File::setRootChunkData(const ByteVector &name, const ByteVector &data)
|
void DSDIFF::File::setRootChunkData(const ByteVector &name, const ByteVector &data) {
|
||||||
{
|
if (d->chunks.size() == 0) {
|
||||||
if(d->chunks.size() == 0) {
|
|
||||||
debug("DSDIFF::File::setPropChunkData - No valid chunks found.");
|
debug("DSDIFF::File::setPropChunkData - No valid chunks found.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int i = chunkIndex(d->chunks, name);
|
int i = chunkIndex(d->chunks, name);
|
||||||
|
|
||||||
if(i >= 0) {
|
if (i >= 0) {
|
||||||
setRootChunkData(i, data);
|
setRootChunkData(i, data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -404,10 +375,10 @@ void DSDIFF::File::setRootChunkData(const ByteVector &name, const ByteVector &da
|
|||||||
|
|
||||||
// Now add the chunk to the file
|
// Now add the chunk to the file
|
||||||
writeChunk(name,
|
writeChunk(name,
|
||||||
data,
|
data,
|
||||||
offset,
|
offset,
|
||||||
std::max<unsigned long long>(0, length() - offset),
|
std::max<unsigned long long>(0, length() - offset),
|
||||||
(offset & 1) ? 1 : 0);
|
(offset & 1) ? 1 : 0);
|
||||||
|
|
||||||
Chunk64 chunk;
|
Chunk64 chunk;
|
||||||
chunk.name = name;
|
chunk.name = name;
|
||||||
@ -418,53 +389,49 @@ void DSDIFF::File::setRootChunkData(const ByteVector &name, const ByteVector &da
|
|||||||
d->chunks.push_back(chunk);
|
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];
|
||||||
ChunkList &childChunks = d->childChunks[childChunkNum];
|
|
||||||
|
|
||||||
// Update global size
|
// Update global size
|
||||||
|
|
||||||
unsigned long long removedChunkTotalSize = childChunks[i].size + childChunks[i].padding + 12;
|
unsigned long long removedChunkTotalSize = childChunks[i].size + childChunks[i].padding + 12;
|
||||||
d->size -= removedChunkTotalSize;
|
d->size -= removedChunkTotalSize;
|
||||||
insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8);
|
insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8);
|
||||||
|
|
||||||
// Update child chunk size
|
// Update child chunk size
|
||||||
|
|
||||||
d->chunks[d->childChunkIndex[childChunkNum]].size -= removedChunkTotalSize;
|
d->chunks[d->childChunkIndex[childChunkNum]].size -= removedChunkTotalSize;
|
||||||
insert(ByteVector::fromLongLong(d->chunks[d->childChunkIndex[childChunkNum]].size,
|
insert(ByteVector::fromLongLong(d->chunks[d->childChunkIndex[childChunkNum]].size,
|
||||||
d->endianness == BigEndian),
|
d->endianness == BigEndian),
|
||||||
d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8);
|
d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8);
|
||||||
// Remove the chunk
|
// Remove the chunk
|
||||||
|
|
||||||
removeBlock(childChunks[i].offset - 12, removedChunkTotalSize);
|
removeBlock(childChunks[i].offset - 12, removedChunkTotalSize);
|
||||||
|
|
||||||
// Update the internal offsets
|
// Update the internal offsets
|
||||||
// For child chunks
|
// For child chunks
|
||||||
|
|
||||||
if((i + 1) < childChunks.size()) {
|
if ((i + 1) < childChunks.size()) {
|
||||||
childChunks[i + 1].offset = childChunks[i].offset;
|
childChunks[i + 1].offset = childChunks[i].offset;
|
||||||
i++;
|
i++;
|
||||||
for(i++; i < childChunks.size(); i++)
|
for (i++; i < childChunks.size(); i++)
|
||||||
childChunks[i].offset = childChunks[i - 1].offset + 12
|
childChunks[i].offset = childChunks[i - 1].offset + 12 + childChunks[i - 1].size + childChunks[i - 1].padding;
|
||||||
+ childChunks[i - 1].size + childChunks[i - 1].padding;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// And for root chunks
|
// And for root chunks
|
||||||
|
|
||||||
for(i = d->childChunkIndex[childChunkNum] + 1; i < d->chunks.size(); i++)
|
for (i = d->childChunkIndex[childChunkNum] + 1; i < d->chunks.size(); i++)
|
||||||
d->chunks[i].offset = d->chunks[i - 1].offset + 12
|
d->chunks[i].offset = d->chunks[i - 1].offset + 12 + d->chunks[i - 1].size + d->chunks[i - 1].padding;
|
||||||
+ d->chunks[i - 1].size + d->chunks[i - 1].padding;
|
|
||||||
|
|
||||||
childChunks.erase(childChunks.begin() + i);
|
childChunks.erase(childChunks.begin() + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSDIFF::File::setChildChunkData(unsigned int i,
|
void DSDIFF::File::setChildChunkData(unsigned int i,
|
||||||
const ByteVector &data,
|
const ByteVector &data,
|
||||||
unsigned int childChunkNum)
|
unsigned int childChunkNum) {
|
||||||
{
|
|
||||||
ChunkList &childChunks = d->childChunks[childChunkNum];
|
ChunkList &childChunks = d->childChunks[childChunkNum];
|
||||||
|
|
||||||
if(data.isEmpty()) {
|
if (data.isEmpty()) {
|
||||||
removeChildChunk(i, childChunkNum);
|
removeChildChunk(i, childChunkNum);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -481,42 +448,40 @@ void DSDIFF::File::setChildChunkData(unsigned int i,
|
|||||||
d->chunks[d->childChunkIndex[childChunkNum]].size +=
|
d->chunks[d->childChunkIndex[childChunkNum]].size +=
|
||||||
((data.size() + 1) & ~1) - (childChunks[i].size + childChunks[i].padding);
|
((data.size() + 1) & ~1) - (childChunks[i].size + childChunks[i].padding);
|
||||||
insert(ByteVector::fromLongLong(d->chunks[d->childChunkIndex[childChunkNum]].size,
|
insert(ByteVector::fromLongLong(d->chunks[d->childChunkIndex[childChunkNum]].size,
|
||||||
d->endianness == BigEndian),
|
d->endianness == BigEndian),
|
||||||
d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8);
|
d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8);
|
||||||
|
|
||||||
// Now update the specific chunk
|
// Now update the specific chunk
|
||||||
|
|
||||||
writeChunk(childChunks[i].name,
|
writeChunk(childChunks[i].name,
|
||||||
data,
|
data,
|
||||||
childChunks[i].offset - 12,
|
childChunks[i].offset - 12,
|
||||||
childChunks[i].size + childChunks[i].padding + 12);
|
childChunks[i].size + childChunks[i].padding + 12);
|
||||||
|
|
||||||
childChunks[i].size = data.size();
|
childChunks[i].size = data.size();
|
||||||
childChunks[i].padding = (data.size() & 0x01) ? 1 : 0;
|
childChunks[i].padding = (data.size() & 0x01) ? 1 : 0;
|
||||||
|
|
||||||
// Now update the internal offsets
|
// Now update the internal offsets
|
||||||
// For child Chunks
|
// For child Chunks
|
||||||
for(i++; i < childChunks.size(); i++)
|
for (i++; i < childChunks.size(); i++)
|
||||||
childChunks[i].offset = childChunks[i - 1].offset + 12
|
childChunks[i].offset = childChunks[i - 1].offset + 12 + childChunks[i - 1].size + childChunks[i - 1].padding;
|
||||||
+ childChunks[i - 1].size + childChunks[i - 1].padding;
|
|
||||||
|
|
||||||
// And for root chunks
|
// And for root chunks
|
||||||
updateRootChunksStructure(d->childChunkIndex[childChunkNum] + 1);
|
updateRootChunksStructure(d->childChunkIndex[childChunkNum] + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSDIFF::File::setChildChunkData(const ByteVector &name,
|
void DSDIFF::File::setChildChunkData(const ByteVector &name,
|
||||||
const ByteVector &data,
|
const ByteVector &data,
|
||||||
unsigned int childChunkNum)
|
unsigned int childChunkNum) {
|
||||||
{
|
|
||||||
ChunkList &childChunks = d->childChunks[childChunkNum];
|
ChunkList &childChunks = d->childChunks[childChunkNum];
|
||||||
|
|
||||||
if(childChunks.size() == 0) {
|
if (childChunks.size() == 0) {
|
||||||
debug("DSDIFF::File::setPropChunkData - No valid chunks found.");
|
debug("DSDIFF::File::setPropChunkData - No valid chunks found.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned int i = 0; i < childChunks.size(); i++) {
|
for (unsigned int i = 0; i < childChunks.size(); i++) {
|
||||||
if(childChunks[i].name == name) {
|
if (childChunks[i].name == name) {
|
||||||
setChildChunkData(i, data, childChunkNum);
|
setChildChunkData(i, data, childChunkNum);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -524,7 +489,7 @@ void DSDIFF::File::setChildChunkData(const ByteVector &name,
|
|||||||
|
|
||||||
// Do not attempt to remove a non existing chunk
|
// Do not attempt to remove a non existing chunk
|
||||||
|
|
||||||
if(data.isEmpty())
|
if (data.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Couldn't find an existing chunk, so let's create a new one.
|
// Couldn't find an existing chunk, so let's create a new one.
|
||||||
@ -539,21 +504,20 @@ void DSDIFF::File::setChildChunkData(const ByteVector &name,
|
|||||||
|
|
||||||
// And the child chunk size
|
// And the child chunk size
|
||||||
|
|
||||||
d->chunks[d->childChunkIndex[childChunkNum]].size += (offset & 1)
|
d->chunks[d->childChunkIndex[childChunkNum]].size += (offset & 1) + ((data.size() + 1) & ~1) + 12;
|
||||||
+ ((data.size() + 1) & ~1) + 12;
|
|
||||||
insert(ByteVector::fromLongLong(d->chunks[d->childChunkIndex[childChunkNum]].size,
|
insert(ByteVector::fromLongLong(d->chunks[d->childChunkIndex[childChunkNum]].size,
|
||||||
d->endianness == BigEndian),
|
d->endianness == BigEndian),
|
||||||
d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8);
|
d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8);
|
||||||
|
|
||||||
// Now add the chunk to the file
|
// Now add the chunk to the file
|
||||||
|
|
||||||
unsigned long long nextRootChunkIdx = length();
|
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;
|
nextRootChunkIdx = d->chunks[d->childChunkIndex[childChunkNum] + 1].offset - 12;
|
||||||
|
|
||||||
writeChunk(name, data, offset,
|
writeChunk(name, data, offset,
|
||||||
std::max<unsigned long long>(0, nextRootChunkIdx - offset),
|
std::max<unsigned long long>(0, nextRootChunkIdx - offset),
|
||||||
(offset & 1) ? 1 : 0);
|
(offset & 1) ? 1 : 0);
|
||||||
|
|
||||||
// For root chunks
|
// For root chunks
|
||||||
|
|
||||||
@ -568,37 +532,31 @@ void DSDIFF::File::setChildChunkData(const ByteVector &name,
|
|||||||
childChunks.push_back(chunk);
|
childChunks.push_back(chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSDIFF::File::updateRootChunksStructure(unsigned int startingChunk)
|
void DSDIFF::File::updateRootChunksStructure(unsigned int startingChunk) {
|
||||||
{
|
for (unsigned int i = startingChunk; i < d->chunks.size(); i++)
|
||||||
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;
|
||||||
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
|
// 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];
|
ChunkList &childChunksToUpdate = d->childChunks[PROPChunk];
|
||||||
if(childChunksToUpdate.size() > 0) {
|
if (childChunksToUpdate.size() > 0) {
|
||||||
childChunksToUpdate[0].offset = d->chunks[d->childChunkIndex[PROPChunk]].offset + 12;
|
childChunksToUpdate[0].offset = d->chunks[d->childChunkIndex[PROPChunk]].offset + 12;
|
||||||
for(unsigned int i = 1; i < childChunksToUpdate.size(); i++)
|
for (unsigned int i = 1; i < childChunksToUpdate.size(); i++)
|
||||||
childChunksToUpdate[i].offset = childChunksToUpdate[i - 1].offset + 12
|
childChunksToUpdate[i].offset = childChunksToUpdate[i - 1].offset + 12 + childChunksToUpdate[i - 1].size + childChunksToUpdate[i - 1].padding;
|
||||||
+ 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];
|
ChunkList &childChunksToUpdate = d->childChunks[DIINChunk];
|
||||||
if(childChunksToUpdate.size() > 0) {
|
if (childChunksToUpdate.size() > 0) {
|
||||||
childChunksToUpdate[0].offset = d->chunks[d->childChunkIndex[DIINChunk]].offset + 12;
|
childChunksToUpdate[0].offset = d->chunks[d->childChunkIndex[DIINChunk]].offset + 12;
|
||||||
for(unsigned int i = 1; i < childChunksToUpdate.size(); i++)
|
for (unsigned int i = 1; i < childChunksToUpdate.size(); i++)
|
||||||
childChunksToUpdate[i].offset = childChunksToUpdate[i - 1].offset + 12
|
childChunksToUpdate[i].offset = childChunksToUpdate[i - 1].offset + 12 + childChunksToUpdate[i - 1].size + childChunksToUpdate[i - 1].padding;
|
||||||
+ 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);
|
bool bigEndian = (d->endianness == BigEndian);
|
||||||
|
|
||||||
d->type = readBlock(4);
|
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
|
// + 12: chunk header at least, fix for additional junk bytes
|
||||||
|
|
||||||
while(tell() + 12 <= length()) {
|
while (tell() + 12 <= length()) {
|
||||||
ByteVector chunkName = readBlock(4);
|
ByteVector chunkName = readBlock(4);
|
||||||
unsigned long long chunkSize = readBlock(8).toLongLong(bigEndian);
|
unsigned long long chunkSize = readBlock(8).toLongLong(bigEndian);
|
||||||
|
|
||||||
if(!isValidChunkID(chunkName)) {
|
if (!isValidChunkID(chunkName)) {
|
||||||
debug("DSDIFF::File::read() -- Chunk '" + chunkName + "' has invalid ID");
|
debug("DSDIFF::File::read() -- Chunk '" + chunkName + "' has invalid ID");
|
||||||
setValid(false);
|
setValid(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(static_cast<unsigned long long>(tell()) + chunkSize >
|
if (static_cast<unsigned long long>(tell()) + chunkSize >
|
||||||
static_cast<unsigned long long>(length())) {
|
static_cast<unsigned long long>(length())) {
|
||||||
debug("DSDIFF::File::read() -- Chunk '" + chunkName
|
debug("DSDIFF::File::read() -- Chunk '" + chunkName + "' has invalid size (larger than the file size)");
|
||||||
+ "' has invalid size (larger than the file size)");
|
|
||||||
setValid(false);
|
setValid(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -636,9 +593,9 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
|
|||||||
|
|
||||||
chunk.padding = 0;
|
chunk.padding = 0;
|
||||||
long uPosNotPadded = tell();
|
long uPosNotPadded = tell();
|
||||||
if((uPosNotPadded & 0x01) != 0) {
|
if ((uPosNotPadded & 0x01) != 0) {
|
||||||
ByteVector iByte = readBlock(1);
|
ByteVector iByte = readBlock(1);
|
||||||
if((iByte.size() != 1) || (iByte[0] != 0))
|
if ((iByte.size() != 1) || (iByte[0] != 0))
|
||||||
// Not well formed, re-seek
|
// Not well formed, re-seek
|
||||||
seek(uPosNotPadded, Beginning);
|
seek(uPosNotPadded, Beginning);
|
||||||
else
|
else
|
||||||
@ -656,36 +613,35 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
|
|||||||
// For DST compressed frames
|
// For DST compressed frames
|
||||||
unsigned short dstFrameRate = 0;
|
unsigned short dstFrameRate = 0;
|
||||||
|
|
||||||
for(unsigned int i = 0; i < d->chunks.size(); i++) {
|
for (unsigned int i = 0; i < d->chunks.size(); i++) {
|
||||||
if(d->chunks[i].name == "DSD ") {
|
if (d->chunks[i].name == "DSD ") {
|
||||||
lengthDSDSamplesTimeChannels = d->chunks[i].size * 8;
|
lengthDSDSamplesTimeChannels = d->chunks[i].size * 8;
|
||||||
audioDataSizeinBytes = d->chunks[i].size;
|
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
|
// 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;
|
long long dstChunkEnd = d->chunks[i].offset + d->chunks[i].size;
|
||||||
seek(d->chunks[i].offset);
|
seek(d->chunks[i].offset);
|
||||||
|
|
||||||
audioDataSizeinBytes = d->chunks[i].size;
|
audioDataSizeinBytes = d->chunks[i].size;
|
||||||
|
|
||||||
while(tell() + 12 <= dstChunkEnd) {
|
while (tell() + 12 <= dstChunkEnd) {
|
||||||
ByteVector dstChunkName = readBlock(4);
|
ByteVector dstChunkName = readBlock(4);
|
||||||
long long dstChunkSize = readBlock(8).toLongLong(bigEndian);
|
long long dstChunkSize = readBlock(8).toLongLong(bigEndian);
|
||||||
|
|
||||||
if(!isValidChunkID(dstChunkName)) {
|
if (!isValidChunkID(dstChunkName)) {
|
||||||
debug("DSDIFF::File::read() -- DST Chunk '" + dstChunkName + "' has invalid ID");
|
debug("DSDIFF::File::read() -- DST Chunk '" + dstChunkName + "' has invalid ID");
|
||||||
setValid(false);
|
setValid(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(static_cast<long long>(tell()) + dstChunkSize > dstChunkEnd) {
|
if (static_cast<long long>(tell()) + dstChunkSize > dstChunkEnd) {
|
||||||
debug("DSDIFF::File::read() -- DST Chunk '" + dstChunkName
|
debug("DSDIFF::File::read() -- DST Chunk '" + dstChunkName + "' has invalid size (larger than the DST chunk)");
|
||||||
+ "' has invalid size (larger than the DST chunk)");
|
|
||||||
setValid(false);
|
setValid(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dstChunkName == "FRTE") {
|
if (dstChunkName == "FRTE") {
|
||||||
// Found the DST frame information chunk
|
// Found the DST frame information chunk
|
||||||
dstNumFrames = readBlock(4).toUInt(bigEndian);
|
dstNumFrames = readBlock(4).toUInt(bigEndian);
|
||||||
dstFrameRate = readBlock(2).toUShort(bigEndian);
|
dstFrameRate = readBlock(2).toUShort(bigEndian);
|
||||||
@ -697,33 +653,32 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
|
|||||||
|
|
||||||
// Check padding
|
// Check padding
|
||||||
long uPosNotPadded = tell();
|
long uPosNotPadded = tell();
|
||||||
if((uPosNotPadded & 0x01) != 0) {
|
if ((uPosNotPadded & 0x01) != 0) {
|
||||||
ByteVector iByte = readBlock(1);
|
ByteVector iByte = readBlock(1);
|
||||||
if((iByte.size() != 1) || (iByte[0] != 0))
|
if ((iByte.size() != 1) || (iByte[0] != 0))
|
||||||
// Not well formed, re-seek
|
// Not well formed, re-seek
|
||||||
seek(uPosNotPadded, Beginning);
|
seek(uPosNotPadded, Beginning);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(d->chunks[i].name == "PROP") {
|
else if (d->chunks[i].name == "PROP") {
|
||||||
d->childChunkIndex[PROPChunk] = i;
|
d->childChunkIndex[PROPChunk] = i;
|
||||||
// Now decodes the chunks inside the PROP chunk
|
// Now decodes the chunks inside the PROP chunk
|
||||||
long long propChunkEnd = d->chunks[i].offset + d->chunks[i].size;
|
long long propChunkEnd = d->chunks[i].offset + d->chunks[i].size;
|
||||||
// +4 to remove the 'SND ' marker at beginning of 'PROP' chunk
|
// +4 to remove the 'SND ' marker at beginning of 'PROP' chunk
|
||||||
seek(d->chunks[i].offset + 4);
|
seek(d->chunks[i].offset + 4);
|
||||||
while(tell() + 12 <= propChunkEnd) {
|
while (tell() + 12 <= propChunkEnd) {
|
||||||
ByteVector propChunkName = readBlock(4);
|
ByteVector propChunkName = readBlock(4);
|
||||||
long long propChunkSize = readBlock(8).toLongLong(bigEndian);
|
long long propChunkSize = readBlock(8).toLongLong(bigEndian);
|
||||||
|
|
||||||
if(!isValidChunkID(propChunkName)) {
|
if (!isValidChunkID(propChunkName)) {
|
||||||
debug("DSDIFF::File::read() -- PROP Chunk '" + propChunkName + "' has invalid ID");
|
debug("DSDIFF::File::read() -- PROP Chunk '" + propChunkName + "' has invalid ID");
|
||||||
setValid(false);
|
setValid(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(static_cast<long long>(tell()) + propChunkSize > propChunkEnd) {
|
if (static_cast<long long>(tell()) + propChunkSize > propChunkEnd) {
|
||||||
debug("DSDIFF::File::read() -- PROP Chunk '" + propChunkName
|
debug("DSDIFF::File::read() -- PROP Chunk '" + propChunkName + "' has invalid size (larger than the PROP chunk)");
|
||||||
+ "' has invalid size (larger than the PROP chunk)");
|
|
||||||
setValid(false);
|
setValid(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -738,9 +693,9 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
|
|||||||
// Check padding
|
// Check padding
|
||||||
chunk.padding = 0;
|
chunk.padding = 0;
|
||||||
long uPosNotPadded = tell();
|
long uPosNotPadded = tell();
|
||||||
if((uPosNotPadded & 0x01) != 0) {
|
if ((uPosNotPadded & 0x01) != 0) {
|
||||||
ByteVector iByte = readBlock(1);
|
ByteVector iByte = readBlock(1);
|
||||||
if((iByte.size() != 1) || (iByte[0] != 0))
|
if ((iByte.size() != 1) || (iByte[0] != 0))
|
||||||
// Not well formed, re-seek
|
// Not well formed, re-seek
|
||||||
seek(uPosNotPadded, Beginning);
|
seek(uPosNotPadded, Beginning);
|
||||||
else
|
else
|
||||||
@ -749,7 +704,7 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
|
|||||||
d->childChunks[PROPChunk].push_back(chunk);
|
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->childChunkIndex[DIINChunk] = i;
|
||||||
d->hasDiin = true;
|
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;
|
long long diinChunkEnd = d->chunks[i].offset + d->chunks[i].size;
|
||||||
seek(d->chunks[i].offset);
|
seek(d->chunks[i].offset);
|
||||||
|
|
||||||
while(tell() + 12 <= diinChunkEnd) {
|
while (tell() + 12 <= diinChunkEnd) {
|
||||||
ByteVector diinChunkName = readBlock(4);
|
ByteVector diinChunkName = readBlock(4);
|
||||||
long long diinChunkSize = readBlock(8).toLongLong(bigEndian);
|
long long diinChunkSize = readBlock(8).toLongLong(bigEndian);
|
||||||
|
|
||||||
if(!isValidChunkID(diinChunkName)) {
|
if (!isValidChunkID(diinChunkName)) {
|
||||||
debug("DSDIFF::File::read() -- DIIN Chunk '" + diinChunkName + "' has invalid ID");
|
debug("DSDIFF::File::read() -- DIIN Chunk '" + diinChunkName + "' has invalid ID");
|
||||||
setValid(false);
|
setValid(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(static_cast<long long>(tell()) + diinChunkSize > diinChunkEnd) {
|
if (static_cast<long long>(tell()) + diinChunkSize > diinChunkEnd) {
|
||||||
debug("DSDIFF::File::read() -- DIIN Chunk '" + diinChunkName
|
debug("DSDIFF::File::read() -- DIIN Chunk '" + diinChunkName + "' has invalid size (larger than the DIIN chunk)");
|
||||||
+ "' has invalid size (larger than the DIIN chunk)");
|
|
||||||
setValid(false);
|
setValid(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -787,9 +741,9 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
|
|||||||
chunk.padding = 0;
|
chunk.padding = 0;
|
||||||
long uPosNotPadded = tell();
|
long uPosNotPadded = tell();
|
||||||
|
|
||||||
if((uPosNotPadded & 0x01) != 0) {
|
if ((uPosNotPadded & 0x01) != 0) {
|
||||||
ByteVector iByte = readBlock(1);
|
ByteVector iByte = readBlock(1);
|
||||||
if((iByte.size() != 1) || (iByte[0] != 0))
|
if ((iByte.size() != 1) || (iByte[0] != 0))
|
||||||
// Not well formed, re-seek
|
// Not well formed, re-seek
|
||||||
seek(uPosNotPadded, Beginning);
|
seek(uPosNotPadded, Beginning);
|
||||||
else
|
else
|
||||||
@ -798,7 +752,7 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
|
|||||||
d->childChunks[DIINChunk].push_back(chunk);
|
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->id3v2TagChunkID = d->chunks[i].name;
|
||||||
d->tag.set(ID3v2Index, new ID3v2::Tag(this, d->chunks[i].offset));
|
d->tag.set(ID3v2Index, new ID3v2::Tag(this, d->chunks[i].offset));
|
||||||
d->isID3InPropChunk = false;
|
d->isID3InPropChunk = false;
|
||||||
@ -806,10 +760,10 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!isValid())
|
if (!isValid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(d->childChunkIndex[PROPChunk] < 0) {
|
if (d->childChunkIndex[PROPChunk] < 0) {
|
||||||
debug("DSDIFF::File::read() -- no PROP chunk found");
|
debug("DSDIFF::File::read() -- no PROP chunk found");
|
||||||
setValid(false);
|
setValid(false);
|
||||||
return;
|
return;
|
||||||
@ -817,13 +771,13 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
|
|||||||
|
|
||||||
// Read properties
|
// Read properties
|
||||||
|
|
||||||
unsigned int sampleRate=0;
|
unsigned int sampleRate = 0;
|
||||||
unsigned short channels=0;
|
unsigned short channels = 0;
|
||||||
|
|
||||||
for(unsigned int i = 0; i < d->childChunks[PROPChunk].size(); i++) {
|
for (unsigned int i = 0; i < d->childChunks[PROPChunk].size(); i++) {
|
||||||
if(d->childChunks[PROPChunk][i].name == "ID3 " ||
|
if (d->childChunks[PROPChunk][i].name == "ID3 " ||
|
||||||
d->childChunks[PROPChunk][i].name == "id3 ") {
|
d->childChunks[PROPChunk][i].name == "id3 ") {
|
||||||
if(d->hasID3v2) {
|
if (d->hasID3v2) {
|
||||||
d->duplicateID3V2chunkIndex = i;
|
d->duplicateID3V2chunkIndex = i;
|
||||||
// ID3V2 tag has already been found at root level
|
// ID3V2 tag has already been found at root level
|
||||||
continue;
|
continue;
|
||||||
@ -833,12 +787,12 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
|
|||||||
d->isID3InPropChunk = true;
|
d->isID3InPropChunk = true;
|
||||||
d->hasID3v2 = true;
|
d->hasID3v2 = true;
|
||||||
}
|
}
|
||||||
else if(d->childChunks[PROPChunk][i].name == "FS ") {
|
else if (d->childChunks[PROPChunk][i].name == "FS ") {
|
||||||
// Sample rate
|
// Sample rate
|
||||||
seek(d->childChunks[PROPChunk][i].offset);
|
seek(d->childChunks[PROPChunk][i].offset);
|
||||||
sampleRate = readBlock(4).toUInt(0, 4, bigEndian);
|
sampleRate = readBlock(4).toUInt(0, 4, bigEndian);
|
||||||
}
|
}
|
||||||
else if(d->childChunks[PROPChunk][i].name == "CHNL") {
|
else if (d->childChunks[PROPChunk][i].name == "CHNL") {
|
||||||
// Channels
|
// Channels
|
||||||
seek(d->childChunks[PROPChunk][i].offset);
|
seek(d->childChunks[PROPChunk][i].offset);
|
||||||
channels = readBlock(2).toShort(0, bigEndian);
|
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);
|
d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, true);
|
||||||
|
|
||||||
if(d->hasDiin) {
|
if (d->hasDiin) {
|
||||||
for(unsigned int i = 0; i < d->childChunks[DIINChunk].size(); i++) {
|
for (unsigned int i = 0; i < d->childChunks[DIINChunk].size(); i++) {
|
||||||
if(d->childChunks[DIINChunk][i].name == "DITI") {
|
if (d->childChunks[DIINChunk][i].name == "DITI") {
|
||||||
seek(d->childChunks[DIINChunk][i].offset);
|
seek(d->childChunks[DIINChunk][i].offset);
|
||||||
unsigned int titleStrLength = readBlock(4).toUInt(0, 4, bigEndian);
|
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);
|
ByteVector titleStr = readBlock(titleStrLength);
|
||||||
d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, false)->setTitle(titleStr);
|
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);
|
seek(d->childChunks[DIINChunk][i].offset);
|
||||||
unsigned int artistStrLength = readBlock(4).toUInt(0, 4, bigEndian);
|
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);
|
ByteVector artistStr = readBlock(artistStrLength);
|
||||||
d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, false)->setArtist(artistStr);
|
d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, false)->setArtist(artistStr);
|
||||||
}
|
}
|
||||||
@ -870,33 +824,33 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(readProperties) {
|
if (readProperties) {
|
||||||
if(lengthDSDSamplesTimeChannels == 0) {
|
if (lengthDSDSamplesTimeChannels == 0) {
|
||||||
// DST compressed signal : need to compute length of DSD uncompressed frames
|
// DST compressed signal : need to compute length of DSD uncompressed frames
|
||||||
if(dstFrameRate > 0)
|
if (dstFrameRate > 0)
|
||||||
lengthDSDSamplesTimeChannels = (unsigned long long) dstNumFrames *
|
lengthDSDSamplesTimeChannels = (unsigned long long)dstNumFrames *
|
||||||
(unsigned long long) sampleRate /
|
(unsigned long long)sampleRate /
|
||||||
(unsigned long long) dstFrameRate;
|
(unsigned long long)dstFrameRate;
|
||||||
else
|
else
|
||||||
lengthDSDSamplesTimeChannels = 0;
|
lengthDSDSamplesTimeChannels = 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// In DSD uncompressed files, the read number of samples is the total for each channel
|
// In DSD uncompressed files, the read number of samples is the total for each channel
|
||||||
if(channels > 0)
|
if (channels > 0)
|
||||||
lengthDSDSamplesTimeChannels /= channels;
|
lengthDSDSamplesTimeChannels /= channels;
|
||||||
}
|
}
|
||||||
int bitrate = 0;
|
int bitrate = 0;
|
||||||
if(lengthDSDSamplesTimeChannels > 0)
|
if (lengthDSDSamplesTimeChannels > 0)
|
||||||
bitrate = (audioDataSizeinBytes * 8 * sampleRate) / lengthDSDSamplesTimeChannels / 1000;
|
bitrate = (audioDataSizeinBytes * 8 * sampleRate) / lengthDSDSamplesTimeChannels / 1000;
|
||||||
|
|
||||||
d->properties = new Properties(sampleRate,
|
d->properties = new Properties(sampleRate,
|
||||||
channels,
|
channels,
|
||||||
lengthDSDSamplesTimeChannels,
|
lengthDSDSamplesTimeChannels,
|
||||||
bitrate,
|
bitrate,
|
||||||
propertiesStyle);
|
propertiesStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!ID3v2Tag()) {
|
if (!ID3v2Tag()) {
|
||||||
d->tag.access<ID3v2::Tag>(ID3v2Index, true);
|
d->tag.access<ID3v2::Tag>(ID3v2Index, true);
|
||||||
// By default, ID3 chunk is at root level
|
// By default, ID3 chunk is at root level
|
||||||
d->isID3InPropChunk = false;
|
d->isID3InPropChunk = false;
|
||||||
@ -905,19 +859,17 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DSDIFF::File::writeChunk(const ByteVector &name, const ByteVector &data,
|
void DSDIFF::File::writeChunk(const ByteVector &name, const ByteVector &data,
|
||||||
unsigned long long offset, unsigned long replace,
|
unsigned long long offset, unsigned long replace,
|
||||||
unsigned int leadingPadding)
|
unsigned int leadingPadding) {
|
||||||
{
|
|
||||||
ByteVector combined;
|
ByteVector combined;
|
||||||
if(leadingPadding)
|
if (leadingPadding)
|
||||||
combined.append(ByteVector(leadingPadding, '\x00'));
|
combined.append(ByteVector(leadingPadding, '\x00'));
|
||||||
|
|
||||||
combined.append(name);
|
combined.append(name);
|
||||||
combined.append(ByteVector::fromLongLong(data.size(), d->endianness == BigEndian));
|
combined.append(ByteVector::fromLongLong(data.size(), d->endianness == BigEndian));
|
||||||
combined.append(data);
|
combined.append(data);
|
||||||
if((data.size() & 0x01) != 0)
|
if ((data.size() & 0x01) != 0)
|
||||||
combined.append('\x00');
|
combined.append('\x00');
|
||||||
|
|
||||||
insert(combined, offset, replace);
|
insert(combined, offset, replace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
168
3rdparty/taglib/dsdiff/dsdifffile.h
vendored
168
3rdparty/taglib/dsdiff/dsdifffile.h
vendored
@ -34,9 +34,9 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
//! An implementation of DSDIFF metadata
|
//! An implementation of DSDIFF metadata
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* This is implementation of DSDIFF metadata.
|
* This is implementation of DSDIFF metadata.
|
||||||
*
|
*
|
||||||
* This supports an ID3v2 tag as well as reading stream from the ID3 RIFF
|
* This supports an ID3v2 tag as well as reading stream from the ID3 RIFF
|
||||||
@ -48,46 +48,44 @@ namespace TagLib {
|
|||||||
* In addition, title and artist info are stored as part of the standard
|
* 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
|
* This implements and provides an interface for DSDIFF files to the
|
||||||
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
|
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
|
||||||
* the abstract TagLib::File API as well as providing some additional
|
* the abstract TagLib::File API as well as providing some additional
|
||||||
* information specific to DSDIFF files.
|
* information specific to DSDIFF files.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File
|
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File {
|
||||||
{
|
public:
|
||||||
public:
|
/*!
|
||||||
|
|
||||||
/*!
|
|
||||||
* This set of flags is used for various operations and is suitable for
|
* This set of flags is used for various operations and is suitable for
|
||||||
* being OR-ed together.
|
* being OR-ed together.
|
||||||
*/
|
*/
|
||||||
enum TagTypes {
|
enum TagTypes {
|
||||||
//! Empty set. Matches no tag types.
|
//! Empty set. Matches no tag types.
|
||||||
NoTags = 0x0000,
|
NoTags = 0x0000,
|
||||||
//! Matches DIIN tags.
|
//! Matches DIIN tags.
|
||||||
DIIN = 0x0002,
|
DIIN = 0x0002,
|
||||||
//! Matches ID3v1 tags.
|
//! Matches ID3v1 tags.
|
||||||
ID3v2 = 0x0002,
|
ID3v2 = 0x0002,
|
||||||
//! Matches all tag types.
|
//! Matches all tag types.
|
||||||
AllTags = 0xffff
|
AllTags = 0xffff
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs an DSDIFF file from \a file. If \a readProperties is true
|
* Constructs an DSDIFF file from \a file. If \a readProperties is true
|
||||||
* the file's audio properties will also be read.
|
* the file's audio properties will also be read.
|
||||||
*
|
*
|
||||||
* \note In the current implementation, \a propertiesStyle is ignored.
|
* \note In the current implementation, \a propertiesStyle is ignored.
|
||||||
*/
|
*/
|
||||||
File(FileName file, bool readProperties = true,
|
File(FileName file, bool readProperties = true,
|
||||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs an DSDIFF file from \a stream. If \a readProperties is true
|
* Constructs an DSDIFF file from \a stream. If \a readProperties is true
|
||||||
* the file's audio properties will also be read.
|
* the file's audio properties will also be read.
|
||||||
*
|
*
|
||||||
@ -96,15 +94,15 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \note In the current implementation, \a propertiesStyle is ignored.
|
* \note In the current implementation, \a propertiesStyle is ignored.
|
||||||
*/
|
*/
|
||||||
File(IOStream *stream, bool readProperties = true,
|
File(IOStream *stream, bool readProperties = true,
|
||||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys this instance of the File.
|
* Destroys this instance of the File.
|
||||||
*/
|
*/
|
||||||
virtual ~File();
|
virtual ~File();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns a pointer to a tag that is the union of the ID3v2 and DIIN
|
* Returns a pointer to a tag that is the union of the ID3v2 and DIIN
|
||||||
* tags. The ID3v2 tag is given priority in reading the information -- if
|
* tags. The ID3v2 tag is given priority in reading the information -- if
|
||||||
* requested information exists in both the ID3v2 tag and the ID3v1 tag,
|
* requested information exists in both the ID3v2 tag and the ID3v1 tag,
|
||||||
@ -120,9 +118,9 @@ namespace TagLib {
|
|||||||
* \see ID3v2Tag()
|
* \see ID3v2Tag()
|
||||||
* \see DIINTag()
|
* \see DIINTag()
|
||||||
*/
|
*/
|
||||||
virtual Tag *tag() const;
|
virtual Tag *tag() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the ID3V2 Tag for this file.
|
* Returns the ID3V2 Tag for this file.
|
||||||
*
|
*
|
||||||
* \note This always returns a valid pointer regardless of whether or not
|
* \note This always returns a valid pointer regardless of whether or not
|
||||||
@ -131,35 +129,35 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \see hasID3v2Tag()
|
* \see hasID3v2Tag()
|
||||||
*/
|
*/
|
||||||
ID3v2::Tag *ID3v2Tag(bool create = false) const;
|
ID3v2::Tag *ID3v2Tag(bool create = false) const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the DSDIFF DIIN Tag for this file
|
* Returns the DSDIFF DIIN Tag for this file
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
DSDIFF::DIIN::Tag *DIINTag(bool create = false) const;
|
DSDIFF::DIIN::Tag *DIINTag(bool create = false) const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Implements the unified property interface -- export function.
|
* Implements the unified property interface -- export function.
|
||||||
* This method forwards to ID3v2::Tag::properties().
|
* This method forwards to ID3v2::Tag::properties().
|
||||||
*/
|
*/
|
||||||
PropertyMap properties() const;
|
PropertyMap properties() const;
|
||||||
|
|
||||||
void removeUnsupportedProperties(const StringList &properties);
|
void removeUnsupportedProperties(const StringList &properties);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Implements the unified property interface -- import function.
|
* Implements the unified property interface -- import function.
|
||||||
* This method forwards to ID3v2::Tag::setProperties().
|
* This method forwards to ID3v2::Tag::setProperties().
|
||||||
*/
|
*/
|
||||||
PropertyMap setProperties(const PropertyMap &);
|
PropertyMap setProperties(const PropertyMap &);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the AIFF::Properties for this file. If no audio properties
|
* Returns the AIFF::Properties for this file. If no audio properties
|
||||||
* were read then this will return a null pointer.
|
* were read then this will return a null pointer.
|
||||||
*/
|
*/
|
||||||
virtual Properties *audioProperties() const;
|
virtual Properties *audioProperties() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Save the file. If at least one tag -- ID3v1 or DIIN -- exists this
|
* Save the file. If at least one tag -- ID3v1 or DIIN -- exists this
|
||||||
* will duplicate its content into the other tag. This returns true
|
* will duplicate its content into the other tag. This returns true
|
||||||
* if saving was successful.
|
* if saving was successful.
|
||||||
@ -174,71 +172,72 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \see save(int tags)
|
* \see save(int tags)
|
||||||
*/
|
*/
|
||||||
virtual bool save();
|
virtual bool save();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Save the file. If \a strip is specified, it is possible to choose if
|
* Save the file. If \a strip is specified, it is possible to choose if
|
||||||
* tags not specified in \a tags should be stripped from the file or
|
* tags not specified in \a tags should be stripped from the file or
|
||||||
* retained. With \a version, it is possible to specify whether ID3v2.4
|
* retained. With \a version, it is possible to specify whether ID3v2.4
|
||||||
* or ID3v2.3 should be used.
|
* or ID3v2.3 should be used.
|
||||||
*/
|
*/
|
||||||
bool save(TagTypes tags, StripTags strip = StripOthers, ID3v2::Version version = ID3v2::v4);
|
bool save(TagTypes tags, StripTags strip = StripOthers, ID3v2::Version version = ID3v2::v4);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* This will strip the tags that match the OR-ed together TagTypes from the
|
* This will strip the tags that match the OR-ed together TagTypes from the
|
||||||
* file. By default it strips all tags. It returns true if the tags are
|
* file. By default it strips all tags. It returns true if the tags are
|
||||||
* successfully stripped.
|
* successfully stripped.
|
||||||
*
|
*
|
||||||
* \note This will update the file immediately.
|
* \note This will update the file immediately.
|
||||||
*/
|
*/
|
||||||
void strip(TagTypes tags = AllTags);
|
void strip(TagTypes tags = AllTags);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns whether or not the file on disk actually has an ID3v2 tag.
|
* Returns whether or not the file on disk actually has an ID3v2 tag.
|
||||||
*
|
*
|
||||||
* \see ID3v2Tag()
|
* \see ID3v2Tag()
|
||||||
*/
|
*/
|
||||||
bool hasID3v2Tag() const;
|
bool hasID3v2Tag() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns whether or not the file on disk actually has the DSDIFF
|
* Returns whether or not the file on disk actually has the DSDIFF
|
||||||
* title and artist tags.
|
* title and artist tags.
|
||||||
*
|
*
|
||||||
* \see DIINTag()
|
* \see DIINTag()
|
||||||
*/
|
*/
|
||||||
bool hasDIINTag() const;
|
bool hasDIINTag() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns whether or not the given \a stream can be opened as a DSDIFF
|
* Returns whether or not the given \a stream can be opened as a DSDIFF
|
||||||
* file.
|
* file.
|
||||||
*
|
*
|
||||||
* \note This method is designed to do a quick check. The result may
|
* \note This method is designed to do a quick check. The result may
|
||||||
* not necessarily be correct.
|
* not necessarily be correct.
|
||||||
*/
|
*/
|
||||||
static bool isSupported(IOStream *stream);
|
static bool isSupported(IOStream *stream);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
enum Endianness { BigEndian, LittleEndian };
|
enum Endianness { BigEndian,
|
||||||
|
LittleEndian };
|
||||||
|
|
||||||
File(FileName file, Endianness endianness);
|
File(FileName file, Endianness endianness);
|
||||||
File(IOStream *stream, Endianness endianness);
|
File(IOStream *stream, Endianness endianness);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
File(const File &);
|
File(const File &);
|
||||||
File &operator=(const File &);
|
File &operator=(const File &);
|
||||||
|
|
||||||
void removeRootChunk(const ByteVector &id);
|
void removeRootChunk(const ByteVector &id);
|
||||||
void removeRootChunk(unsigned int chunk);
|
void removeRootChunk(unsigned int chunk);
|
||||||
void removeChildChunk(unsigned int i, unsigned int chunk);
|
void removeChildChunk(unsigned int i, unsigned int chunk);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the data for the the specified chunk at root level to \a data.
|
* Sets the data for the the specified chunk at root level to \a data.
|
||||||
*
|
*
|
||||||
* \warning This will update the file immediately.
|
* \warning This will update the file immediately.
|
||||||
*/
|
*/
|
||||||
void setRootChunkData(unsigned int i, const ByteVector &data);
|
void setRootChunkData(unsigned int i, const ByteVector &data);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the data for the root-level chunk \a name to \a data.
|
* Sets the data for the root-level chunk \a name to \a data.
|
||||||
* If a root-level chunk with the given name already exists
|
* If a root-level chunk with the given name already exists
|
||||||
* it will be overwritten, otherwise it will be
|
* it will be overwritten, otherwise it will be
|
||||||
@ -246,19 +245,19 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \warning This will update the file immediately.
|
* \warning This will update the file immediately.
|
||||||
*/
|
*/
|
||||||
void setRootChunkData(const ByteVector &name, const ByteVector &data);
|
void setRootChunkData(const ByteVector &name, const ByteVector &data);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the data for the the specified child chunk to \a data.
|
* Sets the data for the the specified child chunk to \a data.
|
||||||
*
|
*
|
||||||
* If data is null, then remove the chunk
|
* If data is null, then remove the chunk
|
||||||
*
|
*
|
||||||
* \warning This will update the file immediately.
|
* \warning This will update the file immediately.
|
||||||
*/
|
*/
|
||||||
void setChildChunkData(unsigned int i, const ByteVector &data,
|
void setChildChunkData(unsigned int i, const ByteVector &data,
|
||||||
unsigned int childChunkNum);
|
unsigned int childChunkNum);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the data for the child chunk \a name to \a data. If a chunk with
|
* Sets the data for the child chunk \a name to \a data. If a chunk with
|
||||||
* the given name already exists it will be overwritten, otherwise it will
|
* the given name already exists it will be overwritten, otherwise it will
|
||||||
* be created after the existing chunks inside child chunk.
|
* be created after the existing chunks inside child chunk.
|
||||||
@ -267,22 +266,21 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \warning This will update the file immediately.
|
* \warning This will update the file immediately.
|
||||||
*/
|
*/
|
||||||
void setChildChunkData(const ByteVector &name, const ByteVector &data,
|
void setChildChunkData(const ByteVector &name, const ByteVector &data,
|
||||||
unsigned int childChunkNum);
|
unsigned int childChunkNum);
|
||||||
|
|
||||||
void updateRootChunksStructure(unsigned int startingChunk);
|
void updateRootChunksStructure(unsigned int startingChunk);
|
||||||
|
|
||||||
void read(bool readProperties, Properties::ReadStyle propertiesStyle);
|
void read(bool readProperties, Properties::ReadStyle propertiesStyle);
|
||||||
void writeChunk(const ByteVector &name, const ByteVector &data,
|
void writeChunk(const ByteVector &name, const ByteVector &data,
|
||||||
unsigned long long offset, unsigned long replace = 0,
|
unsigned long long offset, unsigned long replace = 0,
|
||||||
unsigned int leadingPadding = 0);
|
unsigned int leadingPadding = 0);
|
||||||
|
|
||||||
class FilePrivate;
|
class FilePrivate;
|
||||||
FilePrivate *d;
|
FilePrivate *d;
|
||||||
};
|
};
|
||||||
}
|
} // namespace DSDIFF
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
66
3rdparty/taglib/dsdiff/dsdiffproperties.cpp
vendored
66
3rdparty/taglib/dsdiff/dsdiffproperties.cpp
vendored
@ -30,17 +30,14 @@
|
|||||||
|
|
||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
class DSDIFF::Properties::PropertiesPrivate
|
class DSDIFF::Properties::PropertiesPrivate {
|
||||||
{
|
public:
|
||||||
public:
|
PropertiesPrivate() : length(0),
|
||||||
PropertiesPrivate() :
|
bitrate(0),
|
||||||
length(0),
|
sampleRate(0),
|
||||||
bitrate(0),
|
channels(0),
|
||||||
sampleRate(0),
|
sampleWidth(0),
|
||||||
channels(0),
|
sampleCount(0) {
|
||||||
sampleWidth(0),
|
|
||||||
sampleCount(0)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int length;
|
int length;
|
||||||
@ -56,65 +53,52 @@ public:
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
DSDIFF::Properties::Properties(const unsigned int sampleRate,
|
DSDIFF::Properties::Properties(const unsigned int sampleRate,
|
||||||
const unsigned short channels,
|
const unsigned short channels,
|
||||||
const unsigned long long samplesCount,
|
const unsigned long long samplesCount,
|
||||||
const int bitrate,
|
const int bitrate,
|
||||||
ReadStyle style) : AudioProperties(style)
|
ReadStyle style) : AudioProperties(style) {
|
||||||
{
|
|
||||||
d = new PropertiesPrivate;
|
d = new PropertiesPrivate;
|
||||||
|
|
||||||
d->channels = channels;
|
d->channels = channels;
|
||||||
d->sampleCount = samplesCount;
|
d->sampleCount = samplesCount;
|
||||||
d->sampleWidth = 1;
|
d->sampleWidth = 1;
|
||||||
d->sampleRate = sampleRate;
|
d->sampleRate = sampleRate;
|
||||||
d->bitrate = bitrate;
|
d->bitrate = bitrate;
|
||||||
d->length = d->sampleRate > 0
|
d->length = d->sampleRate > 0 ? static_cast<int>((d->sampleCount * 1000.0) / d->sampleRate + 0.5) : 0;
|
||||||
? static_cast<int>((d->sampleCount * 1000.0) / d->sampleRate + 0.5)
|
|
||||||
: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DSDIFF::Properties::~Properties()
|
DSDIFF::Properties::~Properties() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DSDIFF::Properties::length() const
|
int DSDIFF::Properties::length() const {
|
||||||
{
|
|
||||||
return lengthInSeconds();
|
return lengthInSeconds();
|
||||||
}
|
}
|
||||||
|
|
||||||
int DSDIFF::Properties::lengthInSeconds() const
|
int DSDIFF::Properties::lengthInSeconds() const {
|
||||||
{
|
|
||||||
return d->length / 1000;
|
return d->length / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DSDIFF::Properties::lengthInMilliseconds() const
|
int DSDIFF::Properties::lengthInMilliseconds() const {
|
||||||
{
|
|
||||||
return d->length;
|
return d->length;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DSDIFF::Properties::bitrate() const
|
int DSDIFF::Properties::bitrate() const {
|
||||||
{
|
|
||||||
return d->bitrate;
|
return d->bitrate;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DSDIFF::Properties::sampleRate() const
|
int DSDIFF::Properties::sampleRate() const {
|
||||||
{
|
|
||||||
return d->sampleRate;
|
return d->sampleRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DSDIFF::Properties::channels() const
|
int DSDIFF::Properties::channels() const {
|
||||||
{
|
|
||||||
return d->channels;
|
return d->channels;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DSDIFF::Properties::bitsPerSample() const
|
int DSDIFF::Properties::bitsPerSample() const {
|
||||||
{
|
|
||||||
return d->sampleWidth;
|
return d->sampleWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
long long DSDIFF::Properties::sampleCount() const
|
long long DSDIFF::Properties::sampleCount() const {
|
||||||
{
|
|
||||||
return d->sampleCount;
|
return d->sampleCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
62
3rdparty/taglib/dsdiff/dsdiffproperties.h
vendored
62
3rdparty/taglib/dsdiff/dsdiffproperties.h
vendored
@ -31,55 +31,53 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace 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
|
* This reads the data from an DSDIFF stream found in the AudioProperties
|
||||||
* API.
|
* API.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class TAGLIB_EXPORT Properties : public AudioProperties
|
class TAGLIB_EXPORT Properties : public AudioProperties {
|
||||||
{
|
public:
|
||||||
public:
|
/*!
|
||||||
/*!
|
|
||||||
* Create an instance of DSDIFF::Properties with the data read from the
|
* Create an instance of DSDIFF::Properties with the data read from the
|
||||||
* ByteVector \a data.
|
* ByteVector \a data.
|
||||||
*/
|
*/
|
||||||
Properties(const unsigned int sampleRate, const unsigned short channels,
|
Properties(const unsigned int sampleRate, const unsigned short channels,
|
||||||
const unsigned long long samplesCount, const int bitrate,
|
const unsigned long long samplesCount, const int bitrate,
|
||||||
ReadStyle style);
|
ReadStyle style);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys this DSDIFF::Properties instance.
|
* Destroys this DSDIFF::Properties instance.
|
||||||
*/
|
*/
|
||||||
virtual ~Properties();
|
virtual ~Properties();
|
||||||
|
|
||||||
// Reimplementations.
|
// Reimplementations.
|
||||||
|
|
||||||
virtual int length() const;
|
virtual int length() const;
|
||||||
virtual int lengthInSeconds() const;
|
virtual int lengthInSeconds() const;
|
||||||
virtual int lengthInMilliseconds() const;
|
virtual int lengthInMilliseconds() const;
|
||||||
virtual int bitrate() const;
|
virtual int bitrate() const;
|
||||||
virtual int sampleRate() const;
|
virtual int sampleRate() const;
|
||||||
virtual int channels() const;
|
virtual int channels() const;
|
||||||
|
|
||||||
int bitsPerSample() const;
|
int bitsPerSample() const;
|
||||||
long long sampleCount() const;
|
long long sampleCount() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Properties(const Properties &);
|
Properties(const Properties &);
|
||||||
Properties &operator=(const Properties &);
|
Properties &operator=(const Properties &);
|
||||||
|
|
||||||
class PropertiesPrivate;
|
class PropertiesPrivate;
|
||||||
PropertiesPrivate *d;
|
PropertiesPrivate *d;
|
||||||
};
|
};
|
||||||
}
|
} // namespace DSDIFF
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
91
3rdparty/taglib/dsf/dsffile.cpp
vendored
91
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
|
// The DSF specification is located at http://dsd-guide.com/sites/default/files/white-papers/DSFFileFormatSpec_E.pdf
|
||||||
|
|
||||||
class DSF::File::FilePrivate
|
class DSF::File::FilePrivate {
|
||||||
{
|
public:
|
||||||
public:
|
FilePrivate() : fileSize(0),
|
||||||
FilePrivate() :
|
metadataOffset(0),
|
||||||
fileSize(0),
|
properties(nullptr),
|
||||||
metadataOffset(0),
|
tag(nullptr) {
|
||||||
properties(nullptr),
|
|
||||||
tag(nullptr)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~FilePrivate()
|
~FilePrivate() {
|
||||||
{
|
|
||||||
delete properties;
|
delete properties;
|
||||||
delete tag;
|
delete tag;
|
||||||
}
|
}
|
||||||
@ -63,11 +59,10 @@ public:
|
|||||||
// static members
|
// static members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
bool DSF::File::isSupported(IOStream *stream)
|
bool DSF::File::isSupported(IOStream *stream) {
|
||||||
{
|
// A DSF file has to start with "DSD "
|
||||||
// A DSF file has to start with "DSD "
|
const ByteVector id = Utils::readHeader(stream, 4, false);
|
||||||
const ByteVector id = Utils::readHeader(stream, 4, false);
|
return id.startsWith("DSD ");
|
||||||
return id.startsWith("DSD ");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -75,73 +70,63 @@ bool DSF::File::isSupported(IOStream *stream)
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
DSF::File::File(FileName file, bool readProperties,
|
DSF::File::File(FileName file, bool readProperties,
|
||||||
Properties::ReadStyle propertiesStyle) :
|
Properties::ReadStyle propertiesStyle) : Strawberry_TagLib::TagLib::File(file),
|
||||||
Strawberry_TagLib::TagLib::File(file),
|
d(new FilePrivate()) {
|
||||||
d(new FilePrivate())
|
if (isOpen())
|
||||||
{
|
|
||||||
if(isOpen())
|
|
||||||
read(readProperties, propertiesStyle);
|
read(readProperties, propertiesStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
DSF::File::File(IOStream *stream, bool readProperties,
|
DSF::File::File(IOStream *stream, bool readProperties,
|
||||||
Properties::ReadStyle propertiesStyle) :
|
Properties::ReadStyle propertiesStyle) : Strawberry_TagLib::TagLib::File(stream),
|
||||||
Strawberry_TagLib::TagLib::File(stream),
|
d(new FilePrivate()) {
|
||||||
d(new FilePrivate())
|
if (isOpen())
|
||||||
{
|
|
||||||
if(isOpen())
|
|
||||||
read(readProperties, propertiesStyle);
|
read(readProperties, propertiesStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
DSF::File::~File()
|
DSF::File::~File() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
ID3v2::Tag *DSF::File::tag() const
|
ID3v2::Tag *DSF::File::tag() const {
|
||||||
{
|
|
||||||
return d->tag;
|
return d->tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyMap DSF::File::properties() const
|
PropertyMap DSF::File::properties() const {
|
||||||
{
|
|
||||||
return d->tag->properties();
|
return d->tag->properties();
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyMap DSF::File::setProperties(const PropertyMap &properties)
|
PropertyMap DSF::File::setProperties(const PropertyMap &properties) {
|
||||||
{
|
|
||||||
return d->tag->setProperties(properties);
|
return d->tag->setProperties(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
DSF::Properties *DSF::File::audioProperties() const
|
DSF::Properties *DSF::File::audioProperties() const {
|
||||||
{
|
|
||||||
return d->properties;
|
return d->properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DSF::File::save()
|
bool DSF::File::save() {
|
||||||
{
|
if (readOnly()) {
|
||||||
if(readOnly()) {
|
|
||||||
debug("DSF::File::save() -- File is read only.");
|
debug("DSF::File::save() -- File is read only.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!isValid()) {
|
if (!isValid()) {
|
||||||
debug("DSF::File::save() -- Trying to save invalid file.");
|
debug("DSF::File::save() -- Trying to save invalid file.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Three things must be updated: the file size, the tag data, and the metadata offset
|
// 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;
|
long long newFileSize = d->metadataOffset ? d->metadataOffset : d->fileSize;
|
||||||
|
|
||||||
// Update the file size
|
// Update the file size
|
||||||
if(d->fileSize != newFileSize) {
|
if (d->fileSize != newFileSize) {
|
||||||
insert(ByteVector::fromLongLong(newFileSize, false), 12, 8);
|
insert(ByteVector::fromLongLong(newFileSize, false), 12, 8);
|
||||||
d->fileSize = newFileSize;
|
d->fileSize = newFileSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the metadata offset to 0 since there is no longer a tag
|
// 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);
|
insert(ByteVector::fromLongLong(0ULL, false), 20, 8);
|
||||||
d->metadataOffset = 0;
|
d->metadataOffset = 0;
|
||||||
}
|
}
|
||||||
@ -157,13 +142,13 @@ bool DSF::File::save()
|
|||||||
long long oldTagSize = d->fileSize - newMetadataOffset;
|
long long oldTagSize = d->fileSize - newMetadataOffset;
|
||||||
|
|
||||||
// Update the file size
|
// Update the file size
|
||||||
if(d->fileSize != newFileSize) {
|
if (d->fileSize != newFileSize) {
|
||||||
insert(ByteVector::fromLongLong(newFileSize, false), 12, 8);
|
insert(ByteVector::fromLongLong(newFileSize, false), 12, 8);
|
||||||
d->fileSize = newFileSize;
|
d->fileSize = newFileSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the metadata offset
|
// Update the metadata offset
|
||||||
if(d->metadataOffset != newMetadataOffset) {
|
if (d->metadataOffset != newMetadataOffset) {
|
||||||
insert(ByteVector::fromLongLong(newMetadataOffset, false), 20, 8);
|
insert(ByteVector::fromLongLong(newMetadataOffset, false), 20, 8);
|
||||||
d->metadataOffset = newMetadataOffset;
|
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
|
// 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
|
// The file format is not chunked in the sense of a RIFF File, though
|
||||||
|
|
||||||
// DSD chunk
|
// DSD chunk
|
||||||
ByteVector chunkName = readBlock(4);
|
ByteVector chunkName = readBlock(4);
|
||||||
if(chunkName != "DSD ") {
|
if (chunkName != "DSD ") {
|
||||||
debug("DSF::File::read() -- Not a DSF file.");
|
debug("DSF::File::read() -- Not a DSF file.");
|
||||||
setValid(false);
|
setValid(false);
|
||||||
return;
|
return;
|
||||||
@ -196,7 +180,7 @@ void DSF::File::read(bool, Properties::ReadStyle propertiesStyle)
|
|||||||
long long chunkSize = readBlock(8).toLongLong(false);
|
long long chunkSize = readBlock(8).toLongLong(false);
|
||||||
|
|
||||||
// Integrity check
|
// Integrity check
|
||||||
if(28 != chunkSize) {
|
if (28 != chunkSize) {
|
||||||
debug("DSF::File::read() -- File is corrupted, wrong chunk size");
|
debug("DSF::File::read() -- File is corrupted, wrong chunk size");
|
||||||
setValid(false);
|
setValid(false);
|
||||||
return;
|
return;
|
||||||
@ -205,7 +189,7 @@ void DSF::File::read(bool, Properties::ReadStyle propertiesStyle)
|
|||||||
d->fileSize = readBlock(8).toLongLong(false);
|
d->fileSize = readBlock(8).toLongLong(false);
|
||||||
|
|
||||||
// File is malformed or corrupted
|
// File is malformed or corrupted
|
||||||
if(d->fileSize != length()) {
|
if (d->fileSize != length()) {
|
||||||
debug("DSF::File::read() -- File is corrupted wrong length");
|
debug("DSF::File::read() -- File is corrupted wrong length");
|
||||||
setValid(false);
|
setValid(false);
|
||||||
return;
|
return;
|
||||||
@ -214,7 +198,7 @@ void DSF::File::read(bool, Properties::ReadStyle propertiesStyle)
|
|||||||
d->metadataOffset = readBlock(8).toLongLong(false);
|
d->metadataOffset = readBlock(8).toLongLong(false);
|
||||||
|
|
||||||
// File is malformed or corrupted
|
// File is malformed or corrupted
|
||||||
if(d->metadataOffset > d->fileSize) {
|
if (d->metadataOffset > d->fileSize) {
|
||||||
debug("DSF::File::read() -- Invalid metadata offset.");
|
debug("DSF::File::read() -- Invalid metadata offset.");
|
||||||
setValid(false);
|
setValid(false);
|
||||||
return;
|
return;
|
||||||
@ -222,7 +206,7 @@ void DSF::File::read(bool, Properties::ReadStyle propertiesStyle)
|
|||||||
|
|
||||||
// Format chunk
|
// Format chunk
|
||||||
chunkName = readBlock(4);
|
chunkName = readBlock(4);
|
||||||
if(chunkName != "fmt ") {
|
if (chunkName != "fmt ") {
|
||||||
debug("DSF::File::read() -- Missing 'fmt ' chunk.");
|
debug("DSF::File::read() -- Missing 'fmt ' chunk.");
|
||||||
setValid(false);
|
setValid(false);
|
||||||
return;
|
return;
|
||||||
@ -235,9 +219,8 @@ void DSF::File::read(bool, Properties::ReadStyle propertiesStyle)
|
|||||||
// Skip the data chunk
|
// Skip the data chunk
|
||||||
|
|
||||||
// A metadata offset of 0 indicates the absence of an ID3v2 tag
|
// 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();
|
d->tag = new ID3v2::Tag();
|
||||||
else
|
else
|
||||||
d->tag = new ID3v2::Tag(this, d->metadataOffset);
|
d->tag = new ID3v2::Tag(this, d->metadataOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
76
3rdparty/taglib/dsf/dsffile.h
vendored
76
3rdparty/taglib/dsf/dsffile.h
vendored
@ -33,98 +33,96 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
//! An implementation of DSF metadata
|
//! An implementation of DSF metadata
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* This is implementation of DSF metadata.
|
* This is implementation of DSF metadata.
|
||||||
*
|
*
|
||||||
* This supports an ID3v2 tag as well as properties from the file.
|
* 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
|
* 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
|
* 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
|
* the abstract Strawberry_TagLib::TagLib::File API as well as providing some additional
|
||||||
* information specific to DSF files.
|
* information specific to DSF files.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File
|
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File {
|
||||||
{
|
public:
|
||||||
public:
|
/*!
|
||||||
/*!
|
|
||||||
* Constructs an DSF file from \a file. If \a readProperties is true the
|
* Constructs an DSF file from \a file. If \a readProperties is true the
|
||||||
* file's audio properties will also be read using \a propertiesStyle. If
|
* file's audio properties will also be read using \a propertiesStyle. If
|
||||||
* false, \a propertiesStyle is ignored.
|
* false, \a propertiesStyle is ignored.
|
||||||
*/
|
*/
|
||||||
File(FileName file, bool readProperties = true,
|
File(FileName file, bool readProperties = true,
|
||||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs an DSF file from \a file. If \a readProperties is true the
|
* Constructs an DSF file from \a file. If \a readProperties is true the
|
||||||
* file's audio properties will also be read using \a propertiesStyle. If
|
* file's audio properties will also be read using \a propertiesStyle. If
|
||||||
* false, \a propertiesStyle is ignored.
|
* false, \a propertiesStyle is ignored.
|
||||||
*/
|
*/
|
||||||
File(IOStream *stream, bool readProperties = true,
|
File(IOStream *stream, bool readProperties = true,
|
||||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys this instance of the File.
|
* Destroys this instance of the File.
|
||||||
*/
|
*/
|
||||||
virtual ~File();
|
virtual ~File();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the Tag for this file.
|
* Returns the Tag for this file.
|
||||||
*/
|
*/
|
||||||
ID3v2::Tag *tag() const;
|
ID3v2::Tag *tag() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Implements the unified property interface -- export function.
|
* Implements the unified property interface -- export function.
|
||||||
* This method forwards to ID3v2::Tag::properties().
|
* This method forwards to ID3v2::Tag::properties().
|
||||||
*/
|
*/
|
||||||
PropertyMap properties() const;
|
PropertyMap properties() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Implements the unified property interface -- import function.
|
* Implements the unified property interface -- import function.
|
||||||
* This method forwards to ID3v2::Tag::setProperties().
|
* This method forwards to ID3v2::Tag::setProperties().
|
||||||
*/
|
*/
|
||||||
PropertyMap setProperties(const PropertyMap &);
|
PropertyMap setProperties(const PropertyMap &);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the DSF::AudioProperties for this file. If no audio properties
|
* Returns the DSF::AudioProperties for this file. If no audio properties
|
||||||
* were read then this will return a null pointer.
|
* were read then this will return a null pointer.
|
||||||
*/
|
*/
|
||||||
virtual Properties *audioProperties() const;
|
virtual Properties *audioProperties() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Saves the file.
|
* Saves the file.
|
||||||
*/
|
*/
|
||||||
virtual bool save();
|
virtual bool save();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns whether or not the given \a stream can be opened as a DSF
|
* Returns whether or not the given \a stream can be opened as a DSF
|
||||||
* file.
|
* file.
|
||||||
*
|
*
|
||||||
* \note This method is designed to do a quick check. The result may
|
* \note This method is designed to do a quick check. The result may
|
||||||
* not necessarily be correct.
|
* not necessarily be correct.
|
||||||
*/
|
*/
|
||||||
static bool isSupported(IOStream *stream);
|
static bool isSupported(IOStream *stream);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
File(const File &);
|
File(const File &);
|
||||||
File &operator=(const File &);
|
File &operator=(const File &);
|
||||||
|
|
||||||
void read(bool readProperties, Properties::ReadStyle propertiesStyle);
|
void read(bool readProperties, Properties::ReadStyle propertiesStyle);
|
||||||
|
|
||||||
class FilePrivate;
|
class FilePrivate;
|
||||||
FilePrivate *d;
|
FilePrivate *d;
|
||||||
};
|
};
|
||||||
}
|
} // namespace DSF
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
95
3rdparty/taglib/dsf/dsfproperties.cpp
vendored
95
3rdparty/taglib/dsf/dsfproperties.cpp
vendored
@ -30,21 +30,18 @@
|
|||||||
|
|
||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
class DSF::Properties::PropertiesPrivate
|
class DSF::Properties::PropertiesPrivate {
|
||||||
{
|
public:
|
||||||
public:
|
PropertiesPrivate() : formatVersion(0),
|
||||||
PropertiesPrivate() :
|
formatID(0),
|
||||||
formatVersion(0),
|
channelType(0),
|
||||||
formatID(0),
|
channelNum(0),
|
||||||
channelType(0),
|
samplingFrequency(0),
|
||||||
channelNum(0),
|
bitsPerSample(0),
|
||||||
samplingFrequency(0),
|
sampleCount(0),
|
||||||
bitsPerSample(0),
|
blockSizePerChannel(0),
|
||||||
sampleCount(0),
|
bitrate(0),
|
||||||
blockSizePerChannel(0),
|
length(0) {
|
||||||
bitrate(0),
|
|
||||||
length(0)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nomenclature is from DSF file format specification
|
// Nomenclature is from DSF file format specification
|
||||||
@ -66,75 +63,61 @@ public:
|
|||||||
// public members
|
// 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;
|
d = new PropertiesPrivate;
|
||||||
read(data);
|
read(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
DSF::Properties::~Properties()
|
DSF::Properties::~Properties() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DSF::Properties::length() const
|
int DSF::Properties::length() const {
|
||||||
{
|
|
||||||
return lengthInSeconds();
|
return lengthInSeconds();
|
||||||
}
|
}
|
||||||
|
|
||||||
int DSF::Properties::lengthInSeconds() const
|
int DSF::Properties::lengthInSeconds() const {
|
||||||
{
|
|
||||||
return d->length / 1000;
|
return d->length / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DSF::Properties::lengthInMilliseconds() const
|
int DSF::Properties::lengthInMilliseconds() const {
|
||||||
{
|
|
||||||
return d->length;
|
return d->length;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DSF::Properties::bitrate() const
|
int DSF::Properties::bitrate() const {
|
||||||
{
|
|
||||||
return d->bitrate;
|
return d->bitrate;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DSF::Properties::sampleRate() const
|
int DSF::Properties::sampleRate() const {
|
||||||
{
|
|
||||||
return d->samplingFrequency;
|
return d->samplingFrequency;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DSF::Properties::channels() const
|
int DSF::Properties::channels() const {
|
||||||
{
|
|
||||||
return d->channelNum;
|
return d->channelNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
// DSF specific
|
// DSF specific
|
||||||
int DSF::Properties::formatVersion() const
|
int DSF::Properties::formatVersion() const {
|
||||||
{
|
|
||||||
return d->formatVersion;
|
return d->formatVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DSF::Properties::formatID() const
|
int DSF::Properties::formatID() const {
|
||||||
{
|
|
||||||
return d->formatID;
|
return d->formatID;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DSF::Properties::channelType() const
|
int DSF::Properties::channelType() const {
|
||||||
{
|
|
||||||
return d->channelType;
|
return d->channelType;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DSF::Properties::bitsPerSample() const
|
int DSF::Properties::bitsPerSample() const {
|
||||||
{
|
|
||||||
return d->bitsPerSample;
|
return d->bitsPerSample;
|
||||||
}
|
}
|
||||||
|
|
||||||
long long DSF::Properties::sampleCount() const
|
long long DSF::Properties::sampleCount() const {
|
||||||
{
|
|
||||||
return d->sampleCount;
|
return d->sampleCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DSF::Properties::blockSizePerChannel() const
|
int DSF::Properties::blockSizePerChannel() const {
|
||||||
{
|
|
||||||
return d->blockSizePerChannel;
|
return d->blockSizePerChannel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,20 +125,16 @@ int DSF::Properties::blockSizePerChannel() const
|
|||||||
// private members
|
// private members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void DSF::Properties::read(const ByteVector &data)
|
void DSF::Properties::read(const ByteVector &data) {
|
||||||
{
|
d->formatVersion = data.toUInt(0U, false);
|
||||||
d->formatVersion = data.toUInt(0U,false);
|
d->formatID = data.toUInt(4U, false);
|
||||||
d->formatID = data.toUInt(4U,false);
|
d->channelType = data.toUInt(8U, false);
|
||||||
d->channelType = data.toUInt(8U,false);
|
d->channelNum = data.toUInt(12U, false);
|
||||||
d->channelNum = data.toUInt(12U,false);
|
d->samplingFrequency = data.toUInt(16U, false);
|
||||||
d->samplingFrequency = data.toUInt(16U,false);
|
d->bitsPerSample = data.toUInt(20U, false);
|
||||||
d->bitsPerSample = data.toUInt(20U,false);
|
d->sampleCount = data.toLongLong(24U, false);
|
||||||
d->sampleCount = data.toLongLong(24U,false);
|
d->blockSizePerChannel = data.toUInt(32U, false);
|
||||||
d->blockSizePerChannel = data.toUInt(32U,false);
|
|
||||||
|
|
||||||
d->bitrate
|
d->bitrate = static_cast<unsigned int>((d->samplingFrequency * d->bitsPerSample * d->channelNum) / 1000.0 + 0.5);
|
||||||
= 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->length
|
|
||||||
= d->samplingFrequency > 0 ? static_cast<unsigned int>(d->sampleCount * 1000.0 / d->samplingFrequency + 0.5) : 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
70
3rdparty/taglib/dsf/dsfproperties.h
vendored
70
3rdparty/taglib/dsf/dsfproperties.h
vendored
@ -31,64 +31,62 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace 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
|
* This reads the data from a DSF stream found in the AudioProperties
|
||||||
* API.
|
* API.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class TAGLIB_EXPORT Properties : public Strawberry_TagLib::TagLib::AudioProperties
|
class TAGLIB_EXPORT Properties : public Strawberry_TagLib::TagLib::AudioProperties {
|
||||||
{
|
public:
|
||||||
public:
|
/*!
|
||||||
/*!
|
|
||||||
* Create an instance of DSF::AudioProperties with the data read from the
|
* Create an instance of DSF::AudioProperties with the data read from the
|
||||||
* ByteVector \a data.
|
* ByteVector \a data.
|
||||||
*/
|
*/
|
||||||
Properties(const ByteVector &data, ReadStyle style);
|
Properties(const ByteVector &data, ReadStyle style);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys this DSF::AudioProperties instance.
|
* Destroys this DSF::AudioProperties instance.
|
||||||
*/
|
*/
|
||||||
virtual ~Properties();
|
virtual ~Properties();
|
||||||
|
|
||||||
// Reimplementations.
|
// Reimplementations.
|
||||||
|
|
||||||
virtual int length() const;
|
virtual int length() const;
|
||||||
virtual int lengthInSeconds() const;
|
virtual int lengthInSeconds() const;
|
||||||
virtual int lengthInMilliseconds() const;
|
virtual int lengthInMilliseconds() const;
|
||||||
virtual int bitrate() const;
|
virtual int bitrate() const;
|
||||||
virtual int sampleRate() const;
|
virtual int sampleRate() const;
|
||||||
virtual int channels() const;
|
virtual int channels() const;
|
||||||
|
|
||||||
int formatVersion() const;
|
int formatVersion() const;
|
||||||
int formatID() const;
|
int formatID() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Channel type values: 1 = mono, 2 = stereo, 3 = 3 channels,
|
* Channel type values: 1 = mono, 2 = stereo, 3 = 3 channels,
|
||||||
* 4 = quad, 5 = 4 channels, 6 = 5 channels, 7 = 5.1 channels
|
* 4 = quad, 5 = 4 channels, 6 = 5 channels, 7 = 5.1 channels
|
||||||
*/
|
*/
|
||||||
int channelType() const;
|
int channelType() const;
|
||||||
int bitsPerSample() const;
|
int bitsPerSample() const;
|
||||||
long long sampleCount() const;
|
long long sampleCount() const;
|
||||||
int blockSizePerChannel() const;
|
int blockSizePerChannel() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Properties(const Properties &);
|
Properties(const Properties &);
|
||||||
Properties &operator=(const Properties &);
|
Properties &operator=(const Properties &);
|
||||||
|
|
||||||
void read(const ByteVector &data);
|
void read(const ByteVector &data);
|
||||||
|
|
||||||
class PropertiesPrivate;
|
class PropertiesPrivate;
|
||||||
PropertiesPrivate *d;
|
PropertiesPrivate *d;
|
||||||
};
|
};
|
||||||
}
|
} // namespace DSF
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
518
3rdparty/taglib/fileref.cpp
vendored
518
3rdparty/taglib/fileref.cpp
vendored
@ -57,237 +57,230 @@
|
|||||||
|
|
||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
namespace
|
namespace {
|
||||||
{
|
typedef List<const FileRef::FileTypeResolver *> ResolverList;
|
||||||
typedef List<const FileRef::FileTypeResolver *> ResolverList;
|
ResolverList fileTypeResolvers;
|
||||||
ResolverList fileTypeResolvers;
|
|
||||||
|
|
||||||
// Detect the file type by user-defined resolvers.
|
// Detect the file type by user-defined resolvers.
|
||||||
|
|
||||||
File *detectByResolvers(FileName fileName, bool readAudioProperties,
|
File *detectByResolvers(FileName fileName, bool readAudioProperties,
|
||||||
AudioProperties::ReadStyle audioPropertiesStyle)
|
AudioProperties::ReadStyle audioPropertiesStyle) {
|
||||||
{
|
ResolverList::ConstIterator it = fileTypeResolvers.begin();
|
||||||
ResolverList::ConstIterator it = fileTypeResolvers.begin();
|
for (; it != fileTypeResolvers.end(); ++it) {
|
||||||
for(; it != fileTypeResolvers.end(); ++it) {
|
File *file = (*it)->createFile(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
File *file = (*it)->createFile(fileName, readAudioProperties, audioPropertiesStyle);
|
if (file)
|
||||||
if(file)
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Detect the file type based on the file extension.
|
|
||||||
|
|
||||||
File* detectByExtension(IOStream *stream, bool readAudioProperties,
|
|
||||||
AudioProperties::ReadStyle audioPropertiesStyle)
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
const String s = stream->name().toString();
|
|
||||||
#else
|
|
||||||
const String s(stream->name());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
String ext;
|
|
||||||
const int pos = s.rfind(".");
|
|
||||||
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())
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
// .oga can be any audio in the Ogg container. So leave it to content-based detection.
|
|
||||||
|
|
||||||
if(ext == "MP3")
|
|
||||||
return new MPEG::File(stream, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(ext == "OGG")
|
|
||||||
return new Ogg::Vorbis::File(stream, readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(ext == "FLAC")
|
|
||||||
return new FLAC::File(stream, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(ext == "MPC")
|
|
||||||
return new MPC::File(stream, readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(ext == "WV")
|
|
||||||
return new WavPack::File(stream, readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(ext == "SPX")
|
|
||||||
return new Ogg::Speex::File(stream, readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(ext == "OPUS")
|
|
||||||
return new Ogg::Opus::File(stream, readAudioProperties, audioPropertiesStyle);
|
|
||||||
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")
|
|
||||||
return new MP4::File(stream, readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(ext == "WMA" || ext == "ASF")
|
|
||||||
return new ASF::File(stream, readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(ext == "AIF" || ext == "AIFF" || ext == "AFC" || ext == "AIFC")
|
|
||||||
return new RIFF::AIFF::File(stream, readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(ext == "WAV")
|
|
||||||
return new RIFF::WAV::File(stream, readAudioProperties, audioPropertiesStyle);
|
|
||||||
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")
|
|
||||||
return new Mod::File(stream, readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(ext == "S3M")
|
|
||||||
return new S3M::File(stream, readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(ext == "IT")
|
|
||||||
return new IT::File(stream, readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(ext == "XM")
|
|
||||||
return new XM::File(stream, readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(ext == "DFF" || ext == "DSDIFF")
|
|
||||||
return new DSDIFF::File(stream, readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(ext == "DSF")
|
|
||||||
return new DSF::File(stream, readAudioProperties, audioPropertiesStyle);
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Detect the file type based on the actual content of the stream.
|
|
||||||
|
|
||||||
File *detectByContent(IOStream *stream, bool readAudioProperties,
|
|
||||||
AudioProperties::ReadStyle audioPropertiesStyle)
|
|
||||||
{
|
|
||||||
File *file = 0;
|
|
||||||
|
|
||||||
if(MPEG::File::isSupported(stream))
|
|
||||||
file = new MPEG::File(stream, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
|
|
||||||
else if(Ogg::Vorbis::File::isSupported(stream))
|
|
||||||
file = new Ogg::Vorbis::File(stream, readAudioProperties, audioPropertiesStyle);
|
|
||||||
else if(Ogg::FLAC::File::isSupported(stream))
|
|
||||||
file = new Ogg::FLAC::File(stream, readAudioProperties, audioPropertiesStyle);
|
|
||||||
else if(FLAC::File::isSupported(stream))
|
|
||||||
file = new FLAC::File(stream, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
|
|
||||||
else if(MPC::File::isSupported(stream))
|
|
||||||
file = new MPC::File(stream, readAudioProperties, audioPropertiesStyle);
|
|
||||||
else if(WavPack::File::isSupported(stream))
|
|
||||||
file = new WavPack::File(stream, readAudioProperties, audioPropertiesStyle);
|
|
||||||
else if(Ogg::Speex::File::isSupported(stream))
|
|
||||||
file = new Ogg::Speex::File(stream, readAudioProperties, audioPropertiesStyle);
|
|
||||||
else if(Ogg::Opus::File::isSupported(stream))
|
|
||||||
file = new Ogg::Opus::File(stream, readAudioProperties, audioPropertiesStyle);
|
|
||||||
else if(TrueAudio::File::isSupported(stream))
|
|
||||||
file = new TrueAudio::File(stream, readAudioProperties, audioPropertiesStyle);
|
|
||||||
else if(MP4::File::isSupported(stream))
|
|
||||||
file = new MP4::File(stream, readAudioProperties, audioPropertiesStyle);
|
|
||||||
else if(ASF::File::isSupported(stream))
|
|
||||||
file = new ASF::File(stream, readAudioProperties, audioPropertiesStyle);
|
|
||||||
else if(RIFF::AIFF::File::isSupported(stream))
|
|
||||||
file = new RIFF::AIFF::File(stream, readAudioProperties, audioPropertiesStyle);
|
|
||||||
else if(RIFF::WAV::File::isSupported(stream))
|
|
||||||
file = new RIFF::WAV::File(stream, readAudioProperties, audioPropertiesStyle);
|
|
||||||
else if(APE::File::isSupported(stream))
|
|
||||||
file = new APE::File(stream, readAudioProperties, audioPropertiesStyle);
|
|
||||||
else if(DSDIFF::File::isSupported(stream))
|
|
||||||
file = new DSDIFF::File(stream, readAudioProperties, audioPropertiesStyle);
|
|
||||||
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())
|
|
||||||
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().
|
|
||||||
|
|
||||||
File* createInternal(FileName fileName, bool readAudioProperties,
|
|
||||||
AudioProperties::ReadStyle audioPropertiesStyle)
|
|
||||||
{
|
|
||||||
File *file = detectByResolvers(fileName, readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(file)
|
|
||||||
return file;
|
return file;
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
const String s = fileName.toString();
|
|
||||||
#else
|
|
||||||
const String s(fileName);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
String ext;
|
|
||||||
const int pos = s.rfind(".");
|
|
||||||
if(pos != -1)
|
|
||||||
ext = s.substr(pos + 1).upper();
|
|
||||||
|
|
||||||
if(ext.isEmpty())
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
if(ext == "MP3")
|
|
||||||
return new MPEG::File(fileName, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(ext == "OGG")
|
|
||||||
return new Ogg::Vorbis::File(fileName, readAudioProperties, audioPropertiesStyle);
|
|
||||||
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())
|
|
||||||
return file_flac;
|
|
||||||
delete file_flac;
|
|
||||||
return new Ogg::Vorbis::File(fileName, readAudioProperties, audioPropertiesStyle);
|
|
||||||
}
|
|
||||||
if(ext == "FLAC")
|
|
||||||
return new FLAC::File(fileName, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(ext == "MPC")
|
|
||||||
return new MPC::File(fileName, readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(ext == "WV")
|
|
||||||
return new WavPack::File(fileName, readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(ext == "SPX")
|
|
||||||
return new Ogg::Speex::File(fileName, readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(ext == "OPUS")
|
|
||||||
return new Ogg::Opus::File(fileName, readAudioProperties, audioPropertiesStyle);
|
|
||||||
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")
|
|
||||||
return new MP4::File(fileName, readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(ext == "WMA" || ext == "ASF")
|
|
||||||
return new ASF::File(fileName, readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(ext == "AIF" || ext == "AIFF" || ext == "AFC" || ext == "AIFC")
|
|
||||||
return new RIFF::AIFF::File(fileName, readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(ext == "WAV")
|
|
||||||
return new RIFF::WAV::File(fileName, readAudioProperties, audioPropertiesStyle);
|
|
||||||
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")
|
|
||||||
return new Mod::File(fileName, readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(ext == "S3M")
|
|
||||||
return new S3M::File(fileName, readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(ext == "IT")
|
|
||||||
return new IT::File(fileName, readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(ext == "XM")
|
|
||||||
return new XM::File(fileName, readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(ext == "DFF" || ext == "DSDIFF")
|
|
||||||
return new DSDIFF::File(fileName, readAudioProperties, audioPropertiesStyle);
|
|
||||||
if(ext == "DSF")
|
|
||||||
return new DSF::File(fileName, readAudioProperties, audioPropertiesStyle);
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
class FileRef::FileRefPrivate : public RefCounter
|
// Detect the file type based on the file extension.
|
||||||
{
|
|
||||||
public:
|
File *detectByExtension(IOStream *stream, bool readAudioProperties,
|
||||||
FileRefPrivate() :
|
AudioProperties::ReadStyle audioPropertiesStyle) {
|
||||||
RefCounter(),
|
#ifdef _WIN32
|
||||||
file(0),
|
const String s = stream->name().toString();
|
||||||
stream(0) {}
|
#else
|
||||||
|
const String s(stream->name());
|
||||||
|
#endif
|
||||||
|
|
||||||
|
String ext;
|
||||||
|
const int pos = s.rfind(".");
|
||||||
|
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())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
// .oga can be any audio in the Ogg container. So leave it to content-based detection.
|
||||||
|
|
||||||
|
if (ext == "MP3")
|
||||||
|
return new MPEG::File(stream, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
|
||||||
|
if (ext == "OGG")
|
||||||
|
return new Ogg::Vorbis::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
|
if (ext == "FLAC")
|
||||||
|
return new FLAC::File(stream, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
|
||||||
|
if (ext == "MPC")
|
||||||
|
return new MPC::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
|
if (ext == "WV")
|
||||||
|
return new WavPack::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
|
if (ext == "SPX")
|
||||||
|
return new Ogg::Speex::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
|
if (ext == "OPUS")
|
||||||
|
return new Ogg::Opus::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
|
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")
|
||||||
|
return new MP4::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
|
if (ext == "WMA" || ext == "ASF")
|
||||||
|
return new ASF::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
|
if (ext == "AIF" || ext == "AIFF" || ext == "AFC" || ext == "AIFC")
|
||||||
|
return new RIFF::AIFF::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
|
if (ext == "WAV")
|
||||||
|
return new RIFF::WAV::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
|
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")
|
||||||
|
return new Mod::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
|
if (ext == "S3M")
|
||||||
|
return new S3M::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
|
if (ext == "IT")
|
||||||
|
return new IT::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
|
if (ext == "XM")
|
||||||
|
return new XM::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
|
if (ext == "DFF" || ext == "DSDIFF")
|
||||||
|
return new DSDIFF::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
|
if (ext == "DSF")
|
||||||
|
return new DSF::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Detect the file type based on the actual content of the stream.
|
||||||
|
|
||||||
|
File *detectByContent(IOStream *stream, bool readAudioProperties,
|
||||||
|
AudioProperties::ReadStyle audioPropertiesStyle) {
|
||||||
|
File *file = 0;
|
||||||
|
|
||||||
|
if (MPEG::File::isSupported(stream))
|
||||||
|
file = new MPEG::File(stream, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
|
||||||
|
else if (Ogg::Vorbis::File::isSupported(stream))
|
||||||
|
file = new Ogg::Vorbis::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
|
else if (Ogg::FLAC::File::isSupported(stream))
|
||||||
|
file = new Ogg::FLAC::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
|
else if (FLAC::File::isSupported(stream))
|
||||||
|
file = new FLAC::File(stream, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
|
||||||
|
else if (MPC::File::isSupported(stream))
|
||||||
|
file = new MPC::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
|
else if (WavPack::File::isSupported(stream))
|
||||||
|
file = new WavPack::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
|
else if (Ogg::Speex::File::isSupported(stream))
|
||||||
|
file = new Ogg::Speex::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
|
else if (Ogg::Opus::File::isSupported(stream))
|
||||||
|
file = new Ogg::Opus::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
|
else if (TrueAudio::File::isSupported(stream))
|
||||||
|
file = new TrueAudio::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
|
else if (MP4::File::isSupported(stream))
|
||||||
|
file = new MP4::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
|
else if (ASF::File::isSupported(stream))
|
||||||
|
file = new ASF::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
|
else if (RIFF::AIFF::File::isSupported(stream))
|
||||||
|
file = new RIFF::AIFF::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
|
else if (RIFF::WAV::File::isSupported(stream))
|
||||||
|
file = new RIFF::WAV::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
|
else if (APE::File::isSupported(stream))
|
||||||
|
file = new APE::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
|
else if (DSDIFF::File::isSupported(stream))
|
||||||
|
file = new DSDIFF::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
|
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())
|
||||||
|
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().
|
||||||
|
|
||||||
|
File *createInternal(FileName fileName, bool readAudioProperties,
|
||||||
|
AudioProperties::ReadStyle audioPropertiesStyle) {
|
||||||
|
File *file = detectByResolvers(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
|
if (file)
|
||||||
|
return file;
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
const String s = fileName.toString();
|
||||||
|
#else
|
||||||
|
const String s(fileName);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
String ext;
|
||||||
|
const int pos = s.rfind(".");
|
||||||
|
if (pos != -1)
|
||||||
|
ext = s.substr(pos + 1).upper();
|
||||||
|
|
||||||
|
if (ext.isEmpty())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (ext == "MP3")
|
||||||
|
return new MPEG::File(fileName, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
|
||||||
|
if (ext == "OGG")
|
||||||
|
return new Ogg::Vorbis::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
|
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())
|
||||||
|
return file_flac;
|
||||||
|
delete file_flac;
|
||||||
|
return new Ogg::Vorbis::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
|
}
|
||||||
|
if (ext == "FLAC")
|
||||||
|
return new FLAC::File(fileName, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
|
||||||
|
if (ext == "MPC")
|
||||||
|
return new MPC::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
|
if (ext == "WV")
|
||||||
|
return new WavPack::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
|
if (ext == "SPX")
|
||||||
|
return new Ogg::Speex::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
|
if (ext == "OPUS")
|
||||||
|
return new Ogg::Opus::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
|
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")
|
||||||
|
return new MP4::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
|
if (ext == "WMA" || ext == "ASF")
|
||||||
|
return new ASF::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
|
if (ext == "AIF" || ext == "AIFF" || ext == "AFC" || ext == "AIFC")
|
||||||
|
return new RIFF::AIFF::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
|
if (ext == "WAV")
|
||||||
|
return new RIFF::WAV::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
|
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")
|
||||||
|
return new Mod::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
|
if (ext == "S3M")
|
||||||
|
return new S3M::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
|
if (ext == "IT")
|
||||||
|
return new IT::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
|
if (ext == "XM")
|
||||||
|
return new XM::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
|
if (ext == "DFF" || ext == "DSDIFF")
|
||||||
|
return new DSDIFF::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
|
if (ext == "DSF")
|
||||||
|
return new DSF::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
class FileRef::FileRefPrivate : public RefCounter {
|
||||||
|
public:
|
||||||
|
FileRefPrivate() : RefCounter(),
|
||||||
|
file(0),
|
||||||
|
stream(0) {}
|
||||||
|
|
||||||
~FileRefPrivate() {
|
~FileRefPrivate() {
|
||||||
delete file;
|
delete file;
|
||||||
delete stream;
|
delete stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
File *file;
|
File *file;
|
||||||
IOStream *stream;
|
IOStream *stream;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -295,82 +288,66 @@ public:
|
|||||||
// public members
|
// public members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
FileRef::FileRef() :
|
FileRef::FileRef() : d(new FileRefPrivate()) {
|
||||||
d(new FileRefPrivate())
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FileRef::FileRef(FileName fileName, bool readAudioProperties,
|
FileRef::FileRef(FileName fileName, bool readAudioProperties,
|
||||||
AudioProperties::ReadStyle audioPropertiesStyle) :
|
AudioProperties::ReadStyle audioPropertiesStyle) : d(new FileRefPrivate()) {
|
||||||
d(new FileRefPrivate())
|
|
||||||
{
|
|
||||||
parse(fileName, readAudioProperties, audioPropertiesStyle);
|
parse(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
FileRef::FileRef(IOStream* stream, bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle) :
|
FileRef::FileRef(IOStream *stream, bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle) : d(new FileRefPrivate()) {
|
||||||
d(new FileRefPrivate())
|
|
||||||
{
|
|
||||||
parse(stream, readAudioProperties, audioPropertiesStyle);
|
parse(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
}
|
}
|
||||||
|
|
||||||
FileRef::FileRef(File *file) :
|
FileRef::FileRef(File *file) : d(new FileRefPrivate()) {
|
||||||
d(new FileRefPrivate())
|
|
||||||
{
|
|
||||||
d->file = file;
|
d->file = file;
|
||||||
}
|
}
|
||||||
|
|
||||||
FileRef::FileRef(const FileRef &ref) :
|
FileRef::FileRef(const FileRef &ref) : d(ref.d) {
|
||||||
d(ref.d)
|
|
||||||
{
|
|
||||||
d->ref();
|
d->ref();
|
||||||
}
|
}
|
||||||
|
|
||||||
FileRef::~FileRef()
|
FileRef::~FileRef() {
|
||||||
{
|
if (d->deref())
|
||||||
if(d->deref())
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
Tag *FileRef::tag() const
|
Tag *FileRef::tag() const {
|
||||||
{
|
if (isNull()) {
|
||||||
if(isNull()) {
|
|
||||||
debug("FileRef::tag() - Called without a valid file.");
|
debug("FileRef::tag() - Called without a valid file.");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return d->file->tag();
|
return d->file->tag();
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioProperties *FileRef::audioProperties() const
|
AudioProperties *FileRef::audioProperties() const {
|
||||||
{
|
if (isNull()) {
|
||||||
if(isNull()) {
|
|
||||||
debug("FileRef::audioProperties() - Called without a valid file.");
|
debug("FileRef::audioProperties() - Called without a valid file.");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return d->file->audioProperties();
|
return d->file->audioProperties();
|
||||||
}
|
}
|
||||||
|
|
||||||
File *FileRef::file() const
|
File *FileRef::file() const {
|
||||||
{
|
|
||||||
return d->file;
|
return d->file;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileRef::save()
|
bool FileRef::save() {
|
||||||
{
|
if (isNull()) {
|
||||||
if(isNull()) {
|
|
||||||
debug("FileRef::save() - Called without a valid file.");
|
debug("FileRef::save() - Called without a valid file.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return d->file->save();
|
return d->file->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
const FileRef::FileTypeResolver *FileRef::addFileTypeResolver(const FileRef::FileTypeResolver *resolver) // static
|
const FileRef::FileTypeResolver *FileRef::addFileTypeResolver(const FileRef::FileTypeResolver *resolver) // static
|
||||||
{
|
{
|
||||||
fileTypeResolvers.prepend(resolver);
|
fileTypeResolvers.prepend(resolver);
|
||||||
return resolver;
|
return resolver;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringList FileRef::defaultFileExtensions()
|
StringList FileRef::defaultFileExtensions() {
|
||||||
{
|
|
||||||
StringList l;
|
StringList l;
|
||||||
|
|
||||||
l.append("ogg");
|
l.append("ogg");
|
||||||
@ -395,49 +372,44 @@ StringList FileRef::defaultFileExtensions()
|
|||||||
l.append("wav");
|
l.append("wav");
|
||||||
l.append("ape");
|
l.append("ape");
|
||||||
l.append("mod");
|
l.append("mod");
|
||||||
l.append("module"); // alias for "mod"
|
l.append("module"); // alias for "mod"
|
||||||
l.append("nst"); // alias for "mod"
|
l.append("nst"); // alias for "mod"
|
||||||
l.append("wow"); // alias for "mod"
|
l.append("wow"); // alias for "mod"
|
||||||
l.append("s3m");
|
l.append("s3m");
|
||||||
l.append("it");
|
l.append("it");
|
||||||
l.append("xm");
|
l.append("xm");
|
||||||
l.append("dsf");
|
l.append("dsf");
|
||||||
l.append("dff");
|
l.append("dff");
|
||||||
l.append("dsdiff"); // alias for "dff"
|
l.append("dsdiff"); // alias for "dff"
|
||||||
|
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileRef::isNull() const
|
bool FileRef::isNull() const {
|
||||||
{
|
|
||||||
return (!d->file || !d->file->isValid());
|
return (!d->file || !d->file->isValid());
|
||||||
}
|
}
|
||||||
|
|
||||||
FileRef &FileRef::operator=(const FileRef &ref)
|
FileRef &FileRef::operator=(const FileRef &ref) {
|
||||||
{
|
|
||||||
FileRef(ref).swap(*this);
|
FileRef(ref).swap(*this);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileRef::swap(FileRef &ref)
|
void FileRef::swap(FileRef &ref) {
|
||||||
{
|
|
||||||
using std::swap;
|
using std::swap;
|
||||||
|
|
||||||
swap(d, ref.d);
|
swap(d, ref.d);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileRef::operator==(const FileRef &ref) const
|
bool FileRef::operator==(const FileRef &ref) const {
|
||||||
{
|
|
||||||
return (ref.d->file == d->file);
|
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);
|
return (ref.d->file != d->file);
|
||||||
}
|
}
|
||||||
|
|
||||||
File *FileRef::create(FileName fileName, bool readAudioProperties,
|
File *FileRef::create(FileName fileName, bool readAudioProperties,
|
||||||
AudioProperties::ReadStyle audioPropertiesStyle) // static
|
AudioProperties::ReadStyle audioPropertiesStyle) // static
|
||||||
{
|
{
|
||||||
return createInternal(fileName, readAudioProperties, audioPropertiesStyle);
|
return createInternal(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
}
|
}
|
||||||
@ -447,25 +419,24 @@ File *FileRef::create(FileName fileName, bool readAudioProperties,
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void FileRef::parse(FileName fileName, bool readAudioProperties,
|
void FileRef::parse(FileName fileName, bool readAudioProperties,
|
||||||
AudioProperties::ReadStyle audioPropertiesStyle)
|
AudioProperties::ReadStyle audioPropertiesStyle) {
|
||||||
{
|
|
||||||
// Try user-defined resolvers.
|
// Try user-defined resolvers.
|
||||||
|
|
||||||
d->file = detectByResolvers(fileName, readAudioProperties, audioPropertiesStyle);
|
d->file = detectByResolvers(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
if(d->file)
|
if (d->file)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Try to resolve file types based on the file extension.
|
// Try to resolve file types based on the file extension.
|
||||||
|
|
||||||
d->stream = new FileStream(fileName);
|
d->stream = new FileStream(fileName);
|
||||||
d->file = detectByExtension(d->stream, readAudioProperties, audioPropertiesStyle);
|
d->file = detectByExtension(d->stream, readAudioProperties, audioPropertiesStyle);
|
||||||
if(d->file)
|
if (d->file)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// At last, try to resolve file types based on the actual content.
|
// At last, try to resolve file types based on the actual content.
|
||||||
|
|
||||||
d->file = detectByContent(d->stream, readAudioProperties, audioPropertiesStyle);
|
d->file = detectByContent(d->stream, readAudioProperties, audioPropertiesStyle);
|
||||||
if(d->file)
|
if (d->file)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Stream have to be closed here if failed to resolve file types.
|
// 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,
|
void FileRef::parse(IOStream *stream, bool readAudioProperties,
|
||||||
AudioProperties::ReadStyle audioPropertiesStyle)
|
AudioProperties::ReadStyle audioPropertiesStyle) {
|
||||||
{
|
|
||||||
// User-defined resolvers won't work with a stream.
|
// User-defined resolvers won't work with a stream.
|
||||||
|
|
||||||
// Try to resolve file types based on the file extension.
|
// Try to resolve file types based on the file extension.
|
||||||
|
|
||||||
d->file = detectByExtension(stream, readAudioProperties, audioPropertiesStyle);
|
d->file = detectByExtension(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
if(d->file)
|
if (d->file)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// At last, try to resolve file types based on the actual content of the file.
|
// At last, try to resolve file types based on the actual content of the file.
|
||||||
|
135
3rdparty/taglib/fileref.h
vendored
135
3rdparty/taglib/fileref.h
vendored
@ -35,11 +35,11 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace 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
|
* 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
|
* 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
|
* pass-by-value use. This hides some of the uglier details of TagLib::File
|
||||||
@ -57,10 +57,8 @@ namespace TagLib {
|
|||||||
* \see addFileTypeResolver()
|
* \see addFileTypeResolver()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class TAGLIB_EXPORT FileRef
|
class TAGLIB_EXPORT FileRef {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
|
|
||||||
//! A class for pluggable file type resolution.
|
//! A class for pluggable file type resolution.
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -90,11 +88,10 @@ namespace TagLib {
|
|||||||
* to TagLib.
|
* to TagLib.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class TAGLIB_EXPORT FileTypeResolver
|
class TAGLIB_EXPORT FileTypeResolver {
|
||||||
{
|
public:
|
||||||
public:
|
virtual ~FileTypeResolver();
|
||||||
virtual ~FileTypeResolver();
|
/*!
|
||||||
/*!
|
|
||||||
* This method must be overridden to provide an additional file type
|
* This method must be overridden to provide an additional file type
|
||||||
* resolver. If the resolver is able to determine the file type it should
|
* resolver. If the resolver is able to determine the file type it should
|
||||||
* return a valid File object; if not it should return 0.
|
* return a valid File object; if not it should return 0.
|
||||||
@ -103,18 +100,18 @@ namespace TagLib {
|
|||||||
* deleted. Deletion will happen automatically when the FileRef passes
|
* deleted. Deletion will happen automatically when the FileRef passes
|
||||||
* out of scope.
|
* out of scope.
|
||||||
*/
|
*/
|
||||||
virtual File *createFile(FileName fileName,
|
virtual File *createFile(FileName fileName,
|
||||||
bool readAudioProperties = true,
|
bool readAudioProperties = true,
|
||||||
AudioProperties::ReadStyle
|
AudioProperties::ReadStyle
|
||||||
audioPropertiesStyle = AudioProperties::Average) const = 0;
|
audioPropertiesStyle = AudioProperties::Average) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Creates a null FileRef.
|
* Creates a null FileRef.
|
||||||
*/
|
*/
|
||||||
FileRef();
|
FileRef();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Create a FileRef from \a fileName. If \a readAudioProperties is true then
|
* Create a FileRef from \a fileName. If \a readAudioProperties is true then
|
||||||
* the audio properties will be read using \a audioPropertiesStyle. If
|
* the audio properties will be read using \a audioPropertiesStyle. If
|
||||||
* \a readAudioProperties is false then \a audioPropertiesStyle will be
|
* \a readAudioProperties is false then \a audioPropertiesStyle will be
|
||||||
@ -123,12 +120,12 @@ namespace TagLib {
|
|||||||
* Also see the note in the class documentation about why you may not want to
|
* Also see the note in the class documentation about why you may not want to
|
||||||
* use this method in your application.
|
* use this method in your application.
|
||||||
*/
|
*/
|
||||||
explicit FileRef(FileName fileName,
|
explicit FileRef(FileName fileName,
|
||||||
bool readAudioProperties = true,
|
bool readAudioProperties = true,
|
||||||
AudioProperties::ReadStyle
|
AudioProperties::ReadStyle
|
||||||
audioPropertiesStyle = AudioProperties::Average);
|
audioPropertiesStyle = AudioProperties::Average);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Construct a FileRef from an opened \a IOStream. If \a readAudioProperties
|
* Construct a FileRef from an opened \a IOStream. If \a readAudioProperties
|
||||||
* is true then the audio properties will be read using \a audioPropertiesStyle.
|
* is true then the audio properties will be read using \a audioPropertiesStyle.
|
||||||
* If \a readAudioProperties is false then \a audioPropertiesStyle will be
|
* If \a readAudioProperties is false then \a audioPropertiesStyle will be
|
||||||
@ -140,28 +137,28 @@ namespace TagLib {
|
|||||||
* \note TagLib will *not* take ownership of the stream, the caller is
|
* \note TagLib will *not* take ownership of the stream, the caller is
|
||||||
* responsible for deleting it after the File object.
|
* responsible for deleting it after the File object.
|
||||||
*/
|
*/
|
||||||
explicit FileRef(IOStream* stream,
|
explicit FileRef(IOStream *stream,
|
||||||
bool readAudioProperties = true,
|
bool readAudioProperties = true,
|
||||||
AudioProperties::ReadStyle
|
AudioProperties::ReadStyle
|
||||||
audioPropertiesStyle = AudioProperties::Average);
|
audioPropertiesStyle = AudioProperties::Average);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Construct a FileRef using \a file. The FileRef now takes ownership of the
|
* Construct a FileRef using \a file. The FileRef now takes ownership of the
|
||||||
* pointer and will delete the File when it passes out of scope.
|
* pointer and will delete the File when it passes out of scope.
|
||||||
*/
|
*/
|
||||||
explicit FileRef(File *file);
|
explicit FileRef(File *file);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Make a copy of \a ref.
|
* Make a copy of \a ref.
|
||||||
*/
|
*/
|
||||||
FileRef(const FileRef &ref);
|
FileRef(const FileRef &ref);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys this FileRef instance.
|
* Destroys this FileRef instance.
|
||||||
*/
|
*/
|
||||||
virtual ~FileRef();
|
virtual ~FileRef();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns a pointer to represented file's tag.
|
* Returns a pointer to represented file's tag.
|
||||||
*
|
*
|
||||||
* \warning This pointer will become invalid when this FileRef and all
|
* \warning This pointer will become invalid when this FileRef and all
|
||||||
@ -172,15 +169,15 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \see File::tag()
|
* \see File::tag()
|
||||||
*/
|
*/
|
||||||
Tag *tag() const;
|
Tag *tag() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the audio properties for this FileRef. If no audio properties
|
* Returns the audio properties for this FileRef. If no audio properties
|
||||||
* were read then this will returns a null pointer.
|
* were read then this will returns a null pointer.
|
||||||
*/
|
*/
|
||||||
AudioProperties *audioProperties() const;
|
AudioProperties *audioProperties() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns a pointer to the file represented by this handler class.
|
* Returns a pointer to the file represented by this handler class.
|
||||||
*
|
*
|
||||||
* As a general rule this call should be avoided since if you need to work
|
* As a general rule this call should be avoided since if you need to work
|
||||||
@ -195,14 +192,14 @@ namespace TagLib {
|
|||||||
* \warning This pointer will become invalid when this FileRef and all
|
* \warning This pointer will become invalid when this FileRef and all
|
||||||
* copies pass out of scope.
|
* copies pass out of scope.
|
||||||
*/
|
*/
|
||||||
File *file() const;
|
File *file() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Saves the file. Returns true on success.
|
* Saves the file. Returns true on success.
|
||||||
*/
|
*/
|
||||||
bool save();
|
bool save();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Adds a FileTypeResolver to the list of those used by TagLib. Each
|
* Adds a FileTypeResolver to the list of those used by TagLib. Each
|
||||||
* additional FileTypeResolver is added to the front of a list of resolvers
|
* additional FileTypeResolver is added to the front of a list of resolvers
|
||||||
* that are tried. If the FileTypeResolver returns zero the next resolver
|
* that are tried. If the FileTypeResolver returns zero the next resolver
|
||||||
@ -214,9 +211,9 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \see FileTypeResolver
|
* \see FileTypeResolver
|
||||||
*/
|
*/
|
||||||
static const FileTypeResolver *addFileTypeResolver(const FileTypeResolver *resolver);
|
static const FileTypeResolver *addFileTypeResolver(const FileTypeResolver *resolver);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* As is mentioned elsewhere in this class's documentation, the default file
|
* As is mentioned elsewhere in this class's documentation, the default file
|
||||||
* type resolution code provided by TagLib only works by comparing file
|
* type resolution code provided by TagLib only works by comparing file
|
||||||
* extensions.
|
* extensions.
|
||||||
@ -232,35 +229,35 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \see FileTypeResolver
|
* \see FileTypeResolver
|
||||||
*/
|
*/
|
||||||
static StringList defaultFileExtensions();
|
static StringList defaultFileExtensions();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns true if the file (and as such other pointers) are null.
|
* Returns true if the file (and as such other pointers) are null.
|
||||||
*/
|
*/
|
||||||
bool isNull() const;
|
bool isNull() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Assign the file pointed to by \a ref to this FileRef.
|
* Assign the file pointed to by \a ref to this FileRef.
|
||||||
*/
|
*/
|
||||||
FileRef &operator=(const FileRef &ref);
|
FileRef &operator=(const FileRef &ref);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Exchanges the content of the FileRef by the content of \a ref.
|
* Exchanges the content of the FileRef by the content of \a ref.
|
||||||
*/
|
*/
|
||||||
void swap(FileRef &ref);
|
void swap(FileRef &ref);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns true if this FileRef and \a ref point to the same File object.
|
* Returns true if this FileRef and \a ref point to the same File object.
|
||||||
*/
|
*/
|
||||||
bool operator==(const FileRef &ref) const;
|
bool operator==(const FileRef &ref) const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns true if this FileRef and \a ref do not point to the same File
|
* Returns true if this FileRef and \a ref do not point to the same File
|
||||||
* object.
|
* object.
|
||||||
*/
|
*/
|
||||||
bool operator!=(const FileRef &ref) const;
|
bool operator!=(const FileRef &ref) const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* A simple implementation of file type guessing. If \a readAudioProperties
|
* A simple implementation of file type guessing. If \a readAudioProperties
|
||||||
* is true then the audio properties will be read using
|
* is true then the audio properties will be read using
|
||||||
* \a audioPropertiesStyle. If \a readAudioProperties is false then
|
* \a audioPropertiesStyle. If \a readAudioProperties is false then
|
||||||
@ -271,19 +268,19 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \deprecated
|
* \deprecated
|
||||||
*/
|
*/
|
||||||
static File *create(FileName fileName,
|
static File *create(FileName fileName,
|
||||||
bool readAudioProperties = true,
|
bool readAudioProperties = true,
|
||||||
AudioProperties::ReadStyle audioPropertiesStyle = AudioProperties::Average);
|
AudioProperties::ReadStyle audioPropertiesStyle = AudioProperties::Average);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void parse(FileName fileName, bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle);
|
void parse(FileName fileName, bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle);
|
||||||
void parse(IOStream *stream, bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle);
|
void parse(IOStream *stream, bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle);
|
||||||
|
|
||||||
class FileRefPrivate;
|
class FileRefPrivate;
|
||||||
FileRefPrivate *d;
|
FileRefPrivate *d;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace TagLib
|
||||||
} // namespace Strawberry_TagLib::TagLib
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif // TAGLIB_FILEREF_H
|
#endif // TAGLIB_FILEREF_H
|
||||||
|
243
3rdparty/taglib/flac/flacfile.cpp
vendored
243
3rdparty/taglib/flac/flacfile.cpp
vendored
@ -43,38 +43,35 @@
|
|||||||
|
|
||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
namespace
|
namespace {
|
||||||
{
|
typedef List<FLAC::MetadataBlock *> BlockList;
|
||||||
typedef List<FLAC::MetadataBlock *> BlockList;
|
typedef BlockList::Iterator BlockIterator;
|
||||||
typedef BlockList::Iterator BlockIterator;
|
typedef BlockList::Iterator BlockConstIterator;
|
||||||
typedef BlockList::Iterator BlockConstIterator;
|
|
||||||
|
|
||||||
enum { FlacXiphIndex = 0, FlacID3v2Index = 1, FlacID3v1Index = 2 };
|
enum { FlacXiphIndex = 0,
|
||||||
|
FlacID3v2Index = 1,
|
||||||
|
FlacID3v1Index = 2 };
|
||||||
|
|
||||||
const long MinPaddingLength = 4096;
|
const long MinPaddingLength = 4096;
|
||||||
const long MaxPaddingLegnth = 1024 * 1024;
|
const long MaxPaddingLegnth = 1024 * 1024;
|
||||||
|
|
||||||
const char LastBlockFlag = '\x80';
|
const char LastBlockFlag = '\x80';
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
class FLAC::File::FilePrivate
|
class FLAC::File::FilePrivate {
|
||||||
{
|
public:
|
||||||
public:
|
explicit FilePrivate(const ID3v2::FrameFactory *frameFactory = ID3v2::FrameFactory::instance()) : ID3v2FrameFactory(frameFactory),
|
||||||
explicit FilePrivate(const ID3v2::FrameFactory *frameFactory = ID3v2::FrameFactory::instance()) :
|
ID3v2Location(-1),
|
||||||
ID3v2FrameFactory(frameFactory),
|
ID3v2OriginalSize(0),
|
||||||
ID3v2Location(-1),
|
ID3v1Location(-1),
|
||||||
ID3v2OriginalSize(0),
|
properties(0),
|
||||||
ID3v1Location(-1),
|
flacStart(0),
|
||||||
properties(0),
|
streamStart(0),
|
||||||
flacStart(0),
|
scanned(false) {
|
||||||
streamStart(0),
|
|
||||||
scanned(false)
|
|
||||||
{
|
|
||||||
blocks.setAutoDelete(true);
|
blocks.setAutoDelete(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
~FilePrivate()
|
~FilePrivate() {
|
||||||
{
|
|
||||||
delete properties;
|
delete properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,8 +96,7 @@ public:
|
|||||||
// static members
|
// 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.
|
// A FLAC file has an ID "fLaC" somewhere. An ID3v2 tag may precede.
|
||||||
|
|
||||||
const ByteVector buffer = Utils::readHeader(stream, bufferSize(), true);
|
const ByteVector buffer = Utils::readHeader(stream, bufferSize(), true);
|
||||||
@ -111,84 +107,71 @@ bool FLAC::File::isSupported(IOStream *stream)
|
|||||||
// public members
|
// public members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
FLAC::File::File(FileName file, bool readProperties, Properties::ReadStyle) :
|
FLAC::File::File(FileName file, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file),
|
||||||
Strawberry_TagLib::TagLib::File(file),
|
d(new FilePrivate()) {
|
||||||
d(new FilePrivate())
|
if (isOpen())
|
||||||
{
|
|
||||||
if(isOpen())
|
|
||||||
read(readProperties);
|
read(readProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
FLAC::File::File(FileName file, ID3v2::FrameFactory *frameFactory,
|
FLAC::File::File(FileName file, ID3v2::FrameFactory *frameFactory,
|
||||||
bool readProperties, Properties::ReadStyle) :
|
bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file),
|
||||||
Strawberry_TagLib::TagLib::File(file),
|
d(new FilePrivate(frameFactory)) {
|
||||||
d(new FilePrivate(frameFactory))
|
if (isOpen())
|
||||||
{
|
|
||||||
if(isOpen())
|
|
||||||
read(readProperties);
|
read(readProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
FLAC::File::File(IOStream *stream, ID3v2::FrameFactory *frameFactory,
|
FLAC::File::File(IOStream *stream, ID3v2::FrameFactory *frameFactory,
|
||||||
bool readProperties, Properties::ReadStyle) :
|
bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(stream),
|
||||||
Strawberry_TagLib::TagLib::File(stream),
|
d(new FilePrivate(frameFactory)) {
|
||||||
d(new FilePrivate(frameFactory))
|
if (isOpen())
|
||||||
{
|
|
||||||
if(isOpen())
|
|
||||||
read(readProperties);
|
read(readProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
FLAC::File::~File()
|
FLAC::File::~File() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
Strawberry_TagLib::TagLib::Tag *FLAC::File::tag() const
|
Strawberry_TagLib::TagLib::Tag *FLAC::File::tag() const {
|
||||||
{
|
|
||||||
return &d->tag;
|
return &d->tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyMap FLAC::File::properties() const
|
PropertyMap FLAC::File::properties() const {
|
||||||
{
|
|
||||||
return d->tag.properties();
|
return d->tag.properties();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FLAC::File::removeUnsupportedProperties(const StringList &unsupported)
|
void FLAC::File::removeUnsupportedProperties(const StringList &unsupported) {
|
||||||
{
|
|
||||||
d->tag.removeUnsupportedProperties(unsupported);
|
d->tag.removeUnsupportedProperties(unsupported);
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyMap FLAC::File::setProperties(const PropertyMap &properties)
|
PropertyMap FLAC::File::setProperties(const PropertyMap &properties) {
|
||||||
{
|
|
||||||
return xiphComment(true)->setProperties(properties);
|
return xiphComment(true)->setProperties(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
FLAC::Properties *FLAC::File::audioProperties() const
|
FLAC::Properties *FLAC::File::audioProperties() const {
|
||||||
{
|
|
||||||
return d->properties;
|
return d->properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FLAC::File::save()
|
bool FLAC::File::save() {
|
||||||
{
|
if (readOnly()) {
|
||||||
if(readOnly()) {
|
|
||||||
debug("FLAC::File::save() - Cannot save to a read only file.");
|
debug("FLAC::File::save() - Cannot save to a read only file.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!isValid()) {
|
if (!isValid()) {
|
||||||
debug("FLAC::File::save() -- Trying to save invalid file.");
|
debug("FLAC::File::save() -- Trying to save invalid file.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create new vorbis comments
|
// Create new vorbis comments
|
||||||
if(!hasXiphComment())
|
if (!hasXiphComment())
|
||||||
Tag::duplicate(&d->tag, xiphComment(true), false);
|
Tag::duplicate(&d->tag, xiphComment(true), false);
|
||||||
|
|
||||||
d->xiphCommentData = xiphComment()->render(false);
|
d->xiphCommentData = xiphComment()->render(false);
|
||||||
|
|
||||||
// Replace metadata blocks
|
// Replace metadata blocks
|
||||||
|
|
||||||
for(BlockIterator it = d->blocks.begin(); it != d->blocks.end(); ++it) {
|
for (BlockIterator it = d->blocks.begin(); it != d->blocks.end(); ++it) {
|
||||||
if((*it)->code() == MetadataBlock::VorbisComment) {
|
if ((*it)->code() == MetadataBlock::VorbisComment) {
|
||||||
// Set the new Vorbis Comment block
|
// Set the new Vorbis Comment block
|
||||||
delete *it;
|
delete *it;
|
||||||
d->blocks.erase(it);
|
d->blocks.erase(it);
|
||||||
@ -201,7 +184,7 @@ bool FLAC::File::save()
|
|||||||
// Render data for the metadata blocks
|
// Render data for the metadata blocks
|
||||||
|
|
||||||
ByteVector data;
|
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 blockData = (*it)->render();
|
||||||
ByteVector blockHeader = ByteVector::fromUInt(blockData.size());
|
ByteVector blockHeader = ByteVector::fromUInt(blockData.size());
|
||||||
blockHeader[0] = (*it)->code();
|
blockHeader[0] = (*it)->code();
|
||||||
@ -214,7 +197,7 @@ bool FLAC::File::save()
|
|||||||
long originalLength = d->streamStart - d->flacStart;
|
long originalLength = d->streamStart - d->flacStart;
|
||||||
long paddingLength = originalLength - data.size() - 4;
|
long paddingLength = originalLength - data.size() - 4;
|
||||||
|
|
||||||
if(paddingLength <= 0) {
|
if (paddingLength <= 0) {
|
||||||
paddingLength = MinPaddingLength;
|
paddingLength = MinPaddingLength;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -224,7 +207,7 @@ bool FLAC::File::save()
|
|||||||
threshold = std::max(threshold, MinPaddingLength);
|
threshold = std::max(threshold, MinPaddingLength);
|
||||||
threshold = std::min(threshold, MaxPaddingLegnth);
|
threshold = std::min(threshold, MaxPaddingLegnth);
|
||||||
|
|
||||||
if(paddingLength > threshold)
|
if (paddingLength > threshold)
|
||||||
paddingLength = MinPaddingLength;
|
paddingLength = MinPaddingLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,25 +222,25 @@ bool FLAC::File::save()
|
|||||||
|
|
||||||
d->streamStart += (static_cast<long>(data.size()) - originalLength);
|
d->streamStart += (static_cast<long>(data.size()) - originalLength);
|
||||||
|
|
||||||
if(d->ID3v1Location >= 0)
|
if (d->ID3v1Location >= 0)
|
||||||
d->ID3v1Location += (static_cast<long>(data.size()) - originalLength);
|
d->ID3v1Location += (static_cast<long>(data.size()) - originalLength);
|
||||||
|
|
||||||
// Update ID3 tags
|
// 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.
|
// 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;
|
d->ID3v2Location = 0;
|
||||||
|
|
||||||
data = ID3v2Tag()->render();
|
data = ID3v2Tag()->render();
|
||||||
insert(data, d->ID3v2Location, d->ID3v2OriginalSize);
|
insert(data, d->ID3v2Location, d->ID3v2OriginalSize);
|
||||||
|
|
||||||
d->flacStart += (static_cast<long>(data.size()) - d->ID3v2OriginalSize);
|
d->flacStart += (static_cast<long>(data.size()) - d->ID3v2OriginalSize);
|
||||||
d->streamStart += (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->ID3v1Location += (static_cast<long>(data.size()) - d->ID3v2OriginalSize);
|
||||||
|
|
||||||
d->ID3v2OriginalSize = data.size();
|
d->ID3v2OriginalSize = data.size();
|
||||||
@ -266,13 +249,13 @@ bool FLAC::File::save()
|
|||||||
|
|
||||||
// ID3v2 tag is empty. Remove the old one.
|
// ID3v2 tag is empty. Remove the old one.
|
||||||
|
|
||||||
if(d->ID3v2Location >= 0) {
|
if (d->ID3v2Location >= 0) {
|
||||||
removeBlock(d->ID3v2Location, d->ID3v2OriginalSize);
|
removeBlock(d->ID3v2Location, d->ID3v2OriginalSize);
|
||||||
|
|
||||||
d->flacStart -= d->ID3v2OriginalSize;
|
d->flacStart -= d->ID3v2OriginalSize;
|
||||||
d->streamStart -= d->ID3v2OriginalSize;
|
d->streamStart -= d->ID3v2OriginalSize;
|
||||||
|
|
||||||
if(d->ID3v1Location >= 0)
|
if (d->ID3v1Location >= 0)
|
||||||
d->ID3v1Location -= d->ID3v2OriginalSize;
|
d->ID3v1Location -= d->ID3v2OriginalSize;
|
||||||
|
|
||||||
d->ID3v2Location = -1;
|
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.
|
// 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);
|
seek(d->ID3v1Location);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -298,7 +281,7 @@ bool FLAC::File::save()
|
|||||||
|
|
||||||
// ID3v1 tag is empty. Remove the old one.
|
// ID3v1 tag is empty. Remove the old one.
|
||||||
|
|
||||||
if(d->ID3v1Location >= 0) {
|
if (d->ID3v1Location >= 0) {
|
||||||
truncate(d->ID3v1Location);
|
truncate(d->ID3v1Location);
|
||||||
d->ID3v1Location = -1;
|
d->ID3v1Location = -1;
|
||||||
}
|
}
|
||||||
@ -307,69 +290,59 @@ bool FLAC::File::save()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ID3v2::Tag *FLAC::File::ID3v2Tag(bool create)
|
ID3v2::Tag *FLAC::File::ID3v2Tag(bool create) {
|
||||||
{
|
|
||||||
return d->tag.access<ID3v2::Tag>(FlacID3v2Index, 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);
|
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);
|
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;
|
d->ID3v2FrameFactory = factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector FLAC::File::streamInfoData()
|
ByteVector FLAC::File::streamInfoData() {
|
||||||
{
|
|
||||||
debug("FLAC::File::streamInfoData() -- This function is obsolete. Returning an empty ByteVector.");
|
debug("FLAC::File::streamInfoData() -- This function is obsolete. Returning an empty ByteVector.");
|
||||||
return ByteVector();
|
return ByteVector();
|
||||||
}
|
}
|
||||||
|
|
||||||
long FLAC::File::streamLength()
|
long FLAC::File::streamLength() {
|
||||||
{
|
|
||||||
debug("FLAC::File::streamLength() -- This function is obsolete. Returning zero.");
|
debug("FLAC::File::streamLength() -- This function is obsolete. Returning zero.");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<FLAC::Picture *> FLAC::File::pictureList()
|
List<FLAC::Picture *> FLAC::File::pictureList() {
|
||||||
{
|
|
||||||
List<Picture *> pictures;
|
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);
|
Picture *picture = dynamic_cast<Picture *>(*it);
|
||||||
if(picture) {
|
if (picture) {
|
||||||
pictures.append(picture);
|
pictures.append(picture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pictures;
|
return pictures;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FLAC::File::addPicture(Picture *picture)
|
void FLAC::File::addPicture(Picture *picture) {
|
||||||
{
|
|
||||||
d->blocks.append(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);
|
BlockIterator it = d->blocks.find(picture);
|
||||||
if(it != d->blocks.end())
|
if (it != d->blocks.end())
|
||||||
d->blocks.erase(it);
|
d->blocks.erase(it);
|
||||||
|
|
||||||
if(del)
|
if (del)
|
||||||
delete picture;
|
delete picture;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FLAC::File::removePictures()
|
void FLAC::File::removePictures() {
|
||||||
{
|
for (BlockIterator it = d->blocks.begin(); it != d->blocks.end();) {
|
||||||
for(BlockIterator it = d->blocks.begin(); it != d->blocks.end(); ) {
|
if (dynamic_cast<Picture *>(*it)) {
|
||||||
if(dynamic_cast<Picture *>(*it)) {
|
|
||||||
delete *it;
|
delete *it;
|
||||||
it = d->blocks.erase(it);
|
it = d->blocks.erase(it);
|
||||||
}
|
}
|
||||||
@ -379,32 +352,28 @@ void FLAC::File::removePictures()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FLAC::File::strip(int tags)
|
void FLAC::File::strip(int tags) {
|
||||||
{
|
if (tags & ID3v1)
|
||||||
if(tags & ID3v1)
|
|
||||||
d->tag.set(FlacID3v1Index, 0);
|
d->tag.set(FlacID3v1Index, 0);
|
||||||
|
|
||||||
if(tags & ID3v2)
|
if (tags & ID3v2)
|
||||||
d->tag.set(FlacID3v2Index, 0);
|
d->tag.set(FlacID3v2Index, 0);
|
||||||
|
|
||||||
if(tags & XiphComment) {
|
if (tags & XiphComment) {
|
||||||
xiphComment()->removeAllFields();
|
xiphComment()->removeAllFields();
|
||||||
xiphComment()->removeAllPictures();
|
xiphComment()->removeAllPictures();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FLAC::File::hasXiphComment() const
|
bool FLAC::File::hasXiphComment() const {
|
||||||
{
|
|
||||||
return !d->xiphCommentData.isEmpty();
|
return !d->xiphCommentData.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FLAC::File::hasID3v1Tag() const
|
bool FLAC::File::hasID3v1Tag() const {
|
||||||
{
|
|
||||||
return (d->ID3v1Location >= 0);
|
return (d->ID3v1Location >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FLAC::File::hasID3v2Tag() const
|
bool FLAC::File::hasID3v2Tag() const {
|
||||||
{
|
|
||||||
return (d->ID3v2Location >= 0);
|
return (d->ID3v2Location >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -412,13 +381,12 @@ bool FLAC::File::hasID3v2Tag() const
|
|||||||
// private members
|
// private members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void FLAC::File::read(bool readProperties)
|
void FLAC::File::read(bool readProperties) {
|
||||||
{
|
|
||||||
// Look for an ID3v2 tag
|
// Look for an ID3v2 tag
|
||||||
|
|
||||||
d->ID3v2Location = Utils::findID3v2(this);
|
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->tag.set(FlacID3v2Index, new ID3v2::Tag(this, d->ID3v2Location, d->ID3v2FrameFactory));
|
||||||
d->ID3v2OriginalSize = ID3v2Tag()->header()->completeTagSize();
|
d->ID3v2OriginalSize = ID3v2Tag()->header()->completeTagSize();
|
||||||
}
|
}
|
||||||
@ -427,22 +395,22 @@ void FLAC::File::read(bool readProperties)
|
|||||||
|
|
||||||
d->ID3v1Location = Utils::findID3v1(this);
|
d->ID3v1Location = Utils::findID3v1(this);
|
||||||
|
|
||||||
if(d->ID3v1Location >= 0)
|
if (d->ID3v1Location >= 0)
|
||||||
d->tag.set(FlacID3v1Index, new ID3v1::Tag(this, d->ID3v1Location));
|
d->tag.set(FlacID3v1Index, new ID3v1::Tag(this, d->ID3v1Location));
|
||||||
|
|
||||||
// Look for FLAC metadata, including vorbis comments
|
// Look for FLAC metadata, including vorbis comments
|
||||||
|
|
||||||
scan();
|
scan();
|
||||||
|
|
||||||
if(!isValid())
|
if (!isValid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(!d->xiphCommentData.isEmpty())
|
if (!d->xiphCommentData.isEmpty())
|
||||||
d->tag.set(FlacXiphIndex, new Ogg::XiphComment(d->xiphCommentData));
|
d->tag.set(FlacXiphIndex, new Ogg::XiphComment(d->xiphCommentData));
|
||||||
else
|
else
|
||||||
d->tag.set(FlacXiphIndex, new Ogg::XiphComment());
|
d->tag.set(FlacXiphIndex, new Ogg::XiphComment());
|
||||||
|
|
||||||
if(readProperties) {
|
if (readProperties) {
|
||||||
|
|
||||||
// First block should be the stream_info metadata
|
// First block should be the stream_info metadata
|
||||||
|
|
||||||
@ -450,7 +418,7 @@ void FLAC::File::read(bool readProperties)
|
|||||||
|
|
||||||
long streamLength;
|
long streamLength;
|
||||||
|
|
||||||
if(d->ID3v1Location >= 0)
|
if (d->ID3v1Location >= 0)
|
||||||
streamLength = d->ID3v1Location - d->streamStart;
|
streamLength = d->ID3v1Location - d->streamStart;
|
||||||
else
|
else
|
||||||
streamLength = length() - d->streamStart;
|
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
|
// Scan the metadata pages
|
||||||
|
|
||||||
if(d->scanned)
|
if (d->scanned)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(!isValid())
|
if (!isValid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
long nextBlockOffset;
|
long nextBlockOffset;
|
||||||
|
|
||||||
if(d->ID3v2Location >= 0)
|
if (d->ID3v2Location >= 0)
|
||||||
nextBlockOffset = find("fLaC", d->ID3v2Location + d->ID3v2OriginalSize);
|
nextBlockOffset = find("fLaC", d->ID3v2Location + d->ID3v2OriginalSize);
|
||||||
else
|
else
|
||||||
nextBlockOffset = find("fLaC");
|
nextBlockOffset = find("fLaC");
|
||||||
|
|
||||||
if(nextBlockOffset < 0) {
|
if (nextBlockOffset < 0) {
|
||||||
debug("FLAC::File::scan() -- FLAC stream not found");
|
debug("FLAC::File::scan() -- FLAC stream not found");
|
||||||
setValid(false);
|
setValid(false);
|
||||||
return;
|
return;
|
||||||
@ -485,7 +452,7 @@ void FLAC::File::scan()
|
|||||||
nextBlockOffset += 4;
|
nextBlockOffset += 4;
|
||||||
d->flacStart = nextBlockOffset;
|
d->flacStart = nextBlockOffset;
|
||||||
|
|
||||||
while(true) {
|
while (true) {
|
||||||
|
|
||||||
seek(nextBlockOffset);
|
seek(nextBlockOffset);
|
||||||
const ByteVector header = readBlock(4);
|
const ByteVector header = readBlock(4);
|
||||||
@ -508,22 +475,20 @@ void FLAC::File::scan()
|
|||||||
|
|
||||||
// First block should be the stream_info metadata
|
// 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");
|
debug("FLAC::File::scan() -- First block should be the stream_info metadata");
|
||||||
setValid(false);
|
setValid(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(blockLength == 0
|
if (blockLength == 0 && blockType != MetadataBlock::Padding && blockType != MetadataBlock::SeekTable) {
|
||||||
&& blockType != MetadataBlock::Padding && blockType != MetadataBlock::SeekTable)
|
|
||||||
{
|
|
||||||
debug("FLAC::File::scan() -- Zero-sized metadata block found");
|
debug("FLAC::File::scan() -- Zero-sized metadata block found");
|
||||||
setValid(false);
|
setValid(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ByteVector data = readBlock(blockLength);
|
const ByteVector data = readBlock(blockLength);
|
||||||
if(data.size() != blockLength) {
|
if (data.size() != blockLength) {
|
||||||
debug("FLAC::File::scan() -- Failed to read a metadata block");
|
debug("FLAC::File::scan() -- Failed to read a metadata block");
|
||||||
setValid(false);
|
setValid(false);
|
||||||
return;
|
return;
|
||||||
@ -532,8 +497,8 @@ void FLAC::File::scan()
|
|||||||
MetadataBlock *block = 0;
|
MetadataBlock *block = 0;
|
||||||
|
|
||||||
// Found the vorbis-comment
|
// Found the vorbis-comment
|
||||||
if(blockType == MetadataBlock::VorbisComment) {
|
if (blockType == MetadataBlock::VorbisComment) {
|
||||||
if(d->xiphCommentData.isEmpty()) {
|
if (d->xiphCommentData.isEmpty()) {
|
||||||
d->xiphCommentData = data;
|
d->xiphCommentData = data;
|
||||||
block = new UnknownMetadataBlock(MetadataBlock::VorbisComment, 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");
|
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();
|
FLAC::Picture *picture = new FLAC::Picture();
|
||||||
if(picture->parse(data)) {
|
if (picture->parse(data)) {
|
||||||
block = picture;
|
block = picture;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -551,19 +516,19 @@ void FLAC::File::scan()
|
|||||||
delete picture;
|
delete picture;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(blockType == MetadataBlock::Padding) {
|
else if (blockType == MetadataBlock::Padding) {
|
||||||
// Skip all padding blocks.
|
// Skip all padding blocks.
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
block = new UnknownMetadataBlock(blockType, data);
|
block = new UnknownMetadataBlock(blockType, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(block)
|
if (block)
|
||||||
d->blocks.append(block);
|
d->blocks.append(block);
|
||||||
|
|
||||||
nextBlockOffset += blockLength + 4;
|
nextBlockOffset += blockLength + 4;
|
||||||
|
|
||||||
if(isLastBlock)
|
if (isLastBlock)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
190
3rdparty/taglib/flac/flacfile.h
vendored
190
3rdparty/taglib/flac/flacfile.h
vendored
@ -37,14 +37,21 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
class Tag;
|
class Tag;
|
||||||
namespace ID3v2 { class FrameFactory; class Tag; }
|
namespace ID3v2 {
|
||||||
namespace ID3v1 { class Tag; }
|
class FrameFactory;
|
||||||
namespace Ogg { class XiphComment; }
|
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
|
* 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
|
* point when Ogg / FLAC is more common there will be a similar implementation
|
||||||
* under the Ogg hierarchy.
|
* under the Ogg hierarchy.
|
||||||
@ -53,38 +60,37 @@ namespace TagLib {
|
|||||||
* properties from the file.
|
* 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
|
* This implements and provides an interface for FLAC files to the
|
||||||
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
|
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
|
||||||
* the abstract TagLib::File API as well as providing some additional
|
* the abstract TagLib::File API as well as providing some additional
|
||||||
* information specific to FLAC files.
|
* information specific to FLAC files.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File
|
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File {
|
||||||
{
|
public:
|
||||||
public:
|
/*!
|
||||||
/*!
|
|
||||||
* This set of flags is used for various operations and is suitable for
|
* This set of flags is used for various operations and is suitable for
|
||||||
* being OR-ed together.
|
* being OR-ed together.
|
||||||
*/
|
*/
|
||||||
enum TagTypes {
|
enum TagTypes {
|
||||||
//! Empty set. Matches no tag types.
|
//! Empty set. Matches no tag types.
|
||||||
NoTags = 0x0000,
|
NoTags = 0x0000,
|
||||||
//! Matches Vorbis comments.
|
//! Matches Vorbis comments.
|
||||||
XiphComment = 0x0001,
|
XiphComment = 0x0001,
|
||||||
//! Matches ID3v1 tags.
|
//! Matches ID3v1 tags.
|
||||||
ID3v1 = 0x0002,
|
ID3v1 = 0x0002,
|
||||||
//! Matches ID3v2 tags.
|
//! Matches ID3v2 tags.
|
||||||
ID3v2 = 0x0004,
|
ID3v2 = 0x0004,
|
||||||
//! Matches all tag types.
|
//! Matches all tag types.
|
||||||
AllTags = 0xffff
|
AllTags = 0xffff
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs a FLAC file from \a file. If \a readProperties is true the
|
* Constructs a FLAC file from \a file. If \a readProperties is true the
|
||||||
* file's audio properties will also be read.
|
* file's audio properties will also be read.
|
||||||
*
|
*
|
||||||
@ -93,10 +99,10 @@ namespace TagLib {
|
|||||||
* \deprecated This constructor will be dropped in favor of the one below
|
* \deprecated This constructor will be dropped in favor of the one below
|
||||||
* in a future version.
|
* in a future version.
|
||||||
*/
|
*/
|
||||||
File(FileName file, bool readProperties = true,
|
File(FileName file, bool readProperties = true,
|
||||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs an FLAC file from \a file. If \a readProperties is true the
|
* Constructs an FLAC file from \a file. If \a readProperties is true the
|
||||||
* file's audio properties will also be read.
|
* file's audio properties will also be read.
|
||||||
*
|
*
|
||||||
@ -105,12 +111,12 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \note In the current implementation, \a propertiesStyle is ignored.
|
* \note In the current implementation, \a propertiesStyle is ignored.
|
||||||
*/
|
*/
|
||||||
// BIC: merge with the above constructor
|
// BIC: merge with the above constructor
|
||||||
File(FileName file, ID3v2::FrameFactory *frameFactory,
|
File(FileName file, ID3v2::FrameFactory *frameFactory,
|
||||||
bool readProperties = true,
|
bool readProperties = true,
|
||||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs a FLAC file from \a stream. If \a readProperties is true the
|
* Constructs a FLAC file from \a stream. If \a readProperties is true the
|
||||||
* file's audio properties will also be read.
|
* file's audio properties will also be read.
|
||||||
*
|
*
|
||||||
@ -122,17 +128,17 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \note In the current implementation, \a propertiesStyle is ignored.
|
* \note In the current implementation, \a propertiesStyle is ignored.
|
||||||
*/
|
*/
|
||||||
// BIC: merge with the above constructor
|
// BIC: merge with the above constructor
|
||||||
File(IOStream *stream, ID3v2::FrameFactory *frameFactory,
|
File(IOStream *stream, ID3v2::FrameFactory *frameFactory,
|
||||||
bool readProperties = true,
|
bool readProperties = true,
|
||||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys this instance of the File.
|
* Destroys this instance of the File.
|
||||||
*/
|
*/
|
||||||
virtual ~File();
|
virtual ~File();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the Tag for this file. This will be a union of XiphComment,
|
* Returns the Tag for this file. This will be a union of XiphComment,
|
||||||
* ID3v1 and ID3v2 tags.
|
* ID3v1 and ID3v2 tags.
|
||||||
*
|
*
|
||||||
@ -140,43 +146,43 @@ namespace TagLib {
|
|||||||
* \see ID3v1Tag()
|
* \see ID3v1Tag()
|
||||||
* \see XiphComment()
|
* \see XiphComment()
|
||||||
*/
|
*/
|
||||||
virtual Strawberry_TagLib::TagLib::Tag *tag() const;
|
virtual Strawberry_TagLib::TagLib::Tag *tag() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Implements the unified property interface -- export function.
|
* Implements the unified property interface -- export function.
|
||||||
* If the file contains more than one tag (e.g. XiphComment and ID3v1),
|
* If the file contains more than one tag (e.g. XiphComment and ID3v1),
|
||||||
* only the first one (in the order XiphComment, ID3v2, ID3v1) will be
|
* only the first one (in the order XiphComment, ID3v2, ID3v1) will be
|
||||||
* converted to the PropertyMap.
|
* converted to the PropertyMap.
|
||||||
*/
|
*/
|
||||||
PropertyMap properties() const;
|
PropertyMap properties() const;
|
||||||
|
|
||||||
void removeUnsupportedProperties(const StringList &);
|
void removeUnsupportedProperties(const StringList &);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Implements the unified property interface -- import function.
|
* Implements the unified property interface -- import function.
|
||||||
* This always creates a Xiph comment, if none exists. The return value
|
* This always creates a Xiph comment, if none exists. The return value
|
||||||
* relates to the Xiph comment only.
|
* relates to the Xiph comment only.
|
||||||
* Ignores any changes to ID3v1 or ID3v2 comments since they are not allowed
|
* Ignores any changes to ID3v1 or ID3v2 comments since they are not allowed
|
||||||
* in the FLAC specification.
|
* in the FLAC specification.
|
||||||
*/
|
*/
|
||||||
PropertyMap setProperties(const PropertyMap &);
|
PropertyMap setProperties(const PropertyMap &);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the FLAC::Properties for this file. If no audio properties
|
* Returns the FLAC::Properties for this file. If no audio properties
|
||||||
* were read then this will return a null pointer.
|
* were read then this will return a null pointer.
|
||||||
*/
|
*/
|
||||||
virtual Properties *audioProperties() const;
|
virtual Properties *audioProperties() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Save the file. This will primarily save the XiphComment, but
|
* Save the file. This will primarily save the XiphComment, but
|
||||||
* will also keep any old ID3-tags up to date. If the file
|
* will also keep any old ID3-tags up to date. If the file
|
||||||
* has no XiphComment, one will be constructed from the ID3-tags.
|
* has no XiphComment, one will be constructed from the ID3-tags.
|
||||||
*
|
*
|
||||||
* This returns true if the save was successful.
|
* This returns true if the save was successful.
|
||||||
*/
|
*/
|
||||||
virtual bool save();
|
virtual bool save();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns a pointer to the ID3v2 tag of the file.
|
* Returns a pointer to the ID3v2 tag of the file.
|
||||||
*
|
*
|
||||||
* If \a create is false (the default) this returns a null pointer
|
* If \a create is false (the default) this returns a null pointer
|
||||||
@ -193,9 +199,9 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \see hasID3v2Tag()
|
* \see hasID3v2Tag()
|
||||||
*/
|
*/
|
||||||
ID3v2::Tag *ID3v2Tag(bool create = false);
|
ID3v2::Tag *ID3v2Tag(bool create = false);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns a pointer to the ID3v1 tag of the file.
|
* Returns a pointer to the ID3v1 tag of the file.
|
||||||
*
|
*
|
||||||
* If \a create is false (the default) this returns a null pointer
|
* If \a create is false (the default) this returns a null pointer
|
||||||
@ -212,9 +218,9 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \see hasID3v1Tag()
|
* \see hasID3v1Tag()
|
||||||
*/
|
*/
|
||||||
ID3v1::Tag *ID3v1Tag(bool create = false);
|
ID3v1::Tag *ID3v1Tag(bool create = false);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns a pointer to the XiphComment for the file.
|
* Returns a pointer to the XiphComment for the file.
|
||||||
*
|
*
|
||||||
* If \a create is false (the default) this returns a null pointer
|
* If \a create is false (the default) this returns a null pointer
|
||||||
@ -231,9 +237,9 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \see hasXiphComment()
|
* \see hasXiphComment()
|
||||||
*/
|
*/
|
||||||
Ogg::XiphComment *xiphComment(bool create = false);
|
Ogg::XiphComment *xiphComment(bool create = false);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Set the ID3v2::FrameFactory to something other than the default. This
|
* Set the ID3v2::FrameFactory to something other than the default. This
|
||||||
* can be used to specify the way that ID3v2 frames will be interpreted
|
* can be used to specify the way that ID3v2 frames will be interpreted
|
||||||
* when
|
* when
|
||||||
@ -241,49 +247,49 @@ namespace TagLib {
|
|||||||
* \see ID3v2FrameFactory
|
* \see ID3v2FrameFactory
|
||||||
* \deprecated This value should be passed in via the constructor
|
* \deprecated This value should be passed in via the constructor
|
||||||
*/
|
*/
|
||||||
TAGLIB_DEPRECATED void setID3v2FrameFactory(const ID3v2::FrameFactory *factory);
|
TAGLIB_DEPRECATED void setID3v2FrameFactory(const ID3v2::FrameFactory *factory);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the block of data used by FLAC::Properties for parsing the
|
* Returns the block of data used by FLAC::Properties for parsing the
|
||||||
* stream properties.
|
* stream properties.
|
||||||
*
|
*
|
||||||
* \deprecated Always returns an empty vector.
|
* \deprecated Always returns an empty vector.
|
||||||
*/
|
*/
|
||||||
TAGLIB_DEPRECATED ByteVector streamInfoData(); // BIC: remove
|
TAGLIB_DEPRECATED ByteVector streamInfoData(); // BIC: remove
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the length of the audio-stream, used by FLAC::Properties for
|
* Returns the length of the audio-stream, used by FLAC::Properties for
|
||||||
* calculating the bitrate.
|
* calculating the bitrate.
|
||||||
*
|
*
|
||||||
* \deprecated Always returns zero.
|
* \deprecated Always returns zero.
|
||||||
*/
|
*/
|
||||||
TAGLIB_DEPRECATED long streamLength(); // BIC: remove
|
TAGLIB_DEPRECATED long streamLength(); // BIC: remove
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns a list of pictures attached to the FLAC file.
|
* Returns a list of pictures attached to the FLAC file.
|
||||||
*/
|
*/
|
||||||
List<Picture *> pictureList();
|
List<Picture *> pictureList();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Removes an attached picture. If \a del is true the picture's memory
|
* Removes an attached picture. If \a del is true the picture's memory
|
||||||
* will be freed; if it is false, it must be deleted by the user.
|
* will be freed; if it is false, it must be deleted by the user.
|
||||||
*/
|
*/
|
||||||
void removePicture(Picture *picture, bool del = true);
|
void removePicture(Picture *picture, bool del = true);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Remove all attached images.
|
* Remove all attached images.
|
||||||
*/
|
*/
|
||||||
void removePictures();
|
void removePictures();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Add a new picture to the file. The file takes ownership of the
|
* Add a new picture to the file. The file takes ownership of the
|
||||||
* picture and will handle freeing its memory.
|
* picture and will handle freeing its memory.
|
||||||
*
|
*
|
||||||
* \note The file will be saved only after calling save().
|
* \note The file will be saved only after calling save().
|
||||||
*/
|
*/
|
||||||
void addPicture(Picture *picture);
|
void addPicture(Picture *picture);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* This will remove the tags that match the OR-ed together TagTypes from
|
* This will remove the tags that match the OR-ed together TagTypes from
|
||||||
* the file. By default it removes all tags.
|
* the file. By default it removes all tags.
|
||||||
*
|
*
|
||||||
@ -296,50 +302,50 @@ namespace TagLib {
|
|||||||
* \note This won't remove the Vorbis comment block completely. The
|
* \note This won't remove the Vorbis comment block completely. The
|
||||||
* vendor ID will be preserved.
|
* vendor ID will be preserved.
|
||||||
*/
|
*/
|
||||||
void strip(int tags = AllTags);
|
void strip(int tags = AllTags);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns whether or not the file on disk actually has a XiphComment.
|
* Returns whether or not the file on disk actually has a XiphComment.
|
||||||
*
|
*
|
||||||
* \see xiphComment()
|
* \see xiphComment()
|
||||||
*/
|
*/
|
||||||
bool hasXiphComment() const;
|
bool hasXiphComment() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns whether or not the file on disk actually has an ID3v1 tag.
|
* Returns whether or not the file on disk actually has an ID3v1 tag.
|
||||||
*
|
*
|
||||||
* \see ID3v1Tag()
|
* \see ID3v1Tag()
|
||||||
*/
|
*/
|
||||||
bool hasID3v1Tag() const;
|
bool hasID3v1Tag() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns whether or not the file on disk actually has an ID3v2 tag.
|
* Returns whether or not the file on disk actually has an ID3v2 tag.
|
||||||
*
|
*
|
||||||
* \see ID3v2Tag()
|
* \see ID3v2Tag()
|
||||||
*/
|
*/
|
||||||
bool hasID3v2Tag() const;
|
bool hasID3v2Tag() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns whether or not the given \a stream can be opened as a FLAC
|
* Returns whether or not the given \a stream can be opened as a FLAC
|
||||||
* file.
|
* file.
|
||||||
*
|
*
|
||||||
* \note This method is designed to do a quick check. The result may
|
* \note This method is designed to do a quick check. The result may
|
||||||
* not necessarily be correct.
|
* not necessarily be correct.
|
||||||
*/
|
*/
|
||||||
static bool isSupported(IOStream *stream);
|
static bool isSupported(IOStream *stream);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
File(const File &);
|
File(const File &);
|
||||||
File &operator=(const File &);
|
File &operator=(const File &);
|
||||||
|
|
||||||
void read(bool readProperties);
|
void read(bool readProperties);
|
||||||
void scan();
|
void scan();
|
||||||
|
|
||||||
class FilePrivate;
|
class FilePrivate;
|
||||||
FilePrivate *d;
|
FilePrivate *d;
|
||||||
};
|
};
|
||||||
}
|
} // namespace FLAC
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
13
3rdparty/taglib/flac/flacmetadatablock.cpp
vendored
13
3rdparty/taglib/flac/flacmetadatablock.cpp
vendored
@ -29,19 +29,14 @@
|
|||||||
|
|
||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
class FLAC::MetadataBlock::MetadataBlockPrivate
|
class FLAC::MetadataBlock::MetadataBlockPrivate {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
MetadataBlockPrivate() {}
|
MetadataBlockPrivate() {}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
FLAC::MetadataBlock::MetadataBlock()
|
FLAC::MetadataBlock::MetadataBlock() {
|
||||||
{
|
|
||||||
d = 0;
|
d = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
FLAC::MetadataBlock::~MetadataBlock()
|
FLAC::MetadataBlock::~MetadataBlock() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
55
3rdparty/taglib/flac/flacmetadatablock.h
vendored
55
3rdparty/taglib/flac/flacmetadatablock.h
vendored
@ -33,45 +33,44 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
namespace FLAC {
|
namespace FLAC {
|
||||||
|
|
||||||
class TAGLIB_EXPORT MetadataBlock
|
class TAGLIB_EXPORT MetadataBlock {
|
||||||
{
|
public:
|
||||||
public:
|
MetadataBlock();
|
||||||
MetadataBlock();
|
virtual ~MetadataBlock();
|
||||||
virtual ~MetadataBlock();
|
|
||||||
|
|
||||||
enum BlockType {
|
enum BlockType {
|
||||||
StreamInfo = 0,
|
StreamInfo = 0,
|
||||||
Padding,
|
Padding,
|
||||||
Application,
|
Application,
|
||||||
SeekTable,
|
SeekTable,
|
||||||
VorbisComment,
|
VorbisComment,
|
||||||
CueSheet,
|
CueSheet,
|
||||||
Picture
|
Picture
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the FLAC metadata block type.
|
* Returns the FLAC metadata block type.
|
||||||
*/
|
*/
|
||||||
virtual int code() const = 0;
|
virtual int code() const = 0;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Render the content of the block.
|
* Render the content of the block.
|
||||||
*/
|
*/
|
||||||
virtual ByteVector render() const = 0;
|
virtual ByteVector render() const = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MetadataBlock(const MetadataBlock &item);
|
MetadataBlock(const MetadataBlock &item);
|
||||||
MetadataBlock &operator=(const MetadataBlock &item);
|
MetadataBlock &operator=(const MetadataBlock &item);
|
||||||
|
|
||||||
class MetadataBlockPrivate;
|
class MetadataBlockPrivate;
|
||||||
MetadataBlockPrivate *d;
|
MetadataBlockPrivate *d;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace FLAC
|
||||||
|
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
95
3rdparty/taglib/flac/flacpicture.cpp
vendored
95
3rdparty/taglib/flac/flacpicture.cpp
vendored
@ -29,16 +29,14 @@
|
|||||||
|
|
||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
class FLAC::Picture::PicturePrivate
|
class FLAC::Picture::PicturePrivate {
|
||||||
{
|
public:
|
||||||
public:
|
PicturePrivate() : type(FLAC::Picture::Other),
|
||||||
PicturePrivate() :
|
width(0),
|
||||||
type(FLAC::Picture::Other),
|
height(0),
|
||||||
width(0),
|
colorDepth(0),
|
||||||
height(0),
|
numColors(0) {
|
||||||
colorDepth(0),
|
}
|
||||||
numColors(0)
|
|
||||||
{}
|
|
||||||
|
|
||||||
Type type;
|
Type type;
|
||||||
String mimeType;
|
String mimeType;
|
||||||
@ -50,30 +48,23 @@ public:
|
|||||||
ByteVector data;
|
ByteVector data;
|
||||||
};
|
};
|
||||||
|
|
||||||
FLAC::Picture::Picture() :
|
FLAC::Picture::Picture() : d(new PicturePrivate()) {
|
||||||
d(new PicturePrivate())
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FLAC::Picture::Picture(const ByteVector &data) :
|
FLAC::Picture::Picture(const ByteVector &data) : d(new PicturePrivate()) {
|
||||||
d(new PicturePrivate())
|
|
||||||
{
|
|
||||||
parse(data);
|
parse(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
FLAC::Picture::~Picture()
|
FLAC::Picture::~Picture() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
int FLAC::Picture::code() const
|
int FLAC::Picture::code() const {
|
||||||
{
|
|
||||||
return FLAC::MetadataBlock::Picture;
|
return FLAC::MetadataBlock::Picture;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FLAC::Picture::parse(const ByteVector &data)
|
bool FLAC::Picture::parse(const ByteVector &data) {
|
||||||
{
|
if (data.size() < 32) {
|
||||||
if(data.size() < 32) {
|
|
||||||
debug("A picture block must contain at least 5 bytes.");
|
debug("A picture block must contain at least 5 bytes.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -83,7 +74,7 @@ bool FLAC::Picture::parse(const ByteVector &data)
|
|||||||
pos += 4;
|
pos += 4;
|
||||||
unsigned int mimeTypeLength = data.toUInt(pos);
|
unsigned int mimeTypeLength = data.toUInt(pos);
|
||||||
pos += 4;
|
pos += 4;
|
||||||
if(pos + mimeTypeLength + 24 > data.size()) {
|
if (pos + mimeTypeLength + 24 > data.size()) {
|
||||||
debug("Invalid picture block.");
|
debug("Invalid picture block.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -91,7 +82,7 @@ bool FLAC::Picture::parse(const ByteVector &data)
|
|||||||
pos += mimeTypeLength;
|
pos += mimeTypeLength;
|
||||||
unsigned int descriptionLength = data.toUInt(pos);
|
unsigned int descriptionLength = data.toUInt(pos);
|
||||||
pos += 4;
|
pos += 4;
|
||||||
if(pos + descriptionLength + 20 > data.size()) {
|
if (pos + descriptionLength + 20 > data.size()) {
|
||||||
debug("Invalid picture block.");
|
debug("Invalid picture block.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -107,7 +98,7 @@ bool FLAC::Picture::parse(const ByteVector &data)
|
|||||||
pos += 4;
|
pos += 4;
|
||||||
unsigned int dataLength = data.toUInt(pos);
|
unsigned int dataLength = data.toUInt(pos);
|
||||||
pos += 4;
|
pos += 4;
|
||||||
if(pos + dataLength > data.size()) {
|
if (pos + dataLength > data.size()) {
|
||||||
debug("Invalid picture block.");
|
debug("Invalid picture block.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -116,8 +107,7 @@ bool FLAC::Picture::parse(const ByteVector &data)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector FLAC::Picture::render() const
|
ByteVector FLAC::Picture::render() const {
|
||||||
{
|
|
||||||
ByteVector result;
|
ByteVector result;
|
||||||
result.append(ByteVector::fromUInt(d->type));
|
result.append(ByteVector::fromUInt(d->type));
|
||||||
ByteVector mimeTypeData = d->mimeType.data(String::UTF8);
|
ByteVector mimeTypeData = d->mimeType.data(String::UTF8);
|
||||||
@ -135,83 +125,66 @@ ByteVector FLAC::Picture::render() const
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
FLAC::Picture::Type FLAC::Picture::type() const
|
FLAC::Picture::Type FLAC::Picture::type() const {
|
||||||
{
|
|
||||||
return d->type;
|
return d->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FLAC::Picture::setType(FLAC::Picture::Type type)
|
void FLAC::Picture::setType(FLAC::Picture::Type type) {
|
||||||
{
|
|
||||||
d->type = type;
|
d->type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
String FLAC::Picture::mimeType() const
|
String FLAC::Picture::mimeType() const {
|
||||||
{
|
|
||||||
return d->mimeType;
|
return d->mimeType;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FLAC::Picture::setMimeType(const String &mimeType)
|
void FLAC::Picture::setMimeType(const String &mimeType) {
|
||||||
{
|
|
||||||
d->mimeType = mimeType;
|
d->mimeType = mimeType;
|
||||||
}
|
}
|
||||||
|
|
||||||
String FLAC::Picture::description() const
|
String FLAC::Picture::description() const {
|
||||||
{
|
|
||||||
return d->description;
|
return d->description;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FLAC::Picture::setDescription(const String &description)
|
void FLAC::Picture::setDescription(const String &description) {
|
||||||
{
|
|
||||||
d->description = description;
|
d->description = description;
|
||||||
}
|
}
|
||||||
|
|
||||||
int FLAC::Picture::width() const
|
int FLAC::Picture::width() const {
|
||||||
{
|
|
||||||
return d->width;
|
return d->width;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FLAC::Picture::setWidth(int width)
|
void FLAC::Picture::setWidth(int width) {
|
||||||
{
|
|
||||||
d->width = width;
|
d->width = width;
|
||||||
}
|
}
|
||||||
|
|
||||||
int FLAC::Picture::height() const
|
int FLAC::Picture::height() const {
|
||||||
{
|
|
||||||
return d->height;
|
return d->height;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FLAC::Picture::setHeight(int height)
|
void FLAC::Picture::setHeight(int height) {
|
||||||
{
|
|
||||||
d->height = height;
|
d->height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
int FLAC::Picture::colorDepth() const
|
int FLAC::Picture::colorDepth() const {
|
||||||
{
|
|
||||||
return d->colorDepth;
|
return d->colorDepth;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FLAC::Picture::setColorDepth(int colorDepth)
|
void FLAC::Picture::setColorDepth(int colorDepth) {
|
||||||
{
|
|
||||||
d->colorDepth = colorDepth;
|
d->colorDepth = colorDepth;
|
||||||
}
|
}
|
||||||
|
|
||||||
int FLAC::Picture::numColors() const
|
int FLAC::Picture::numColors() const {
|
||||||
{
|
|
||||||
return d->numColors;
|
return d->numColors;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FLAC::Picture::setNumColors(int numColors)
|
void FLAC::Picture::setNumColors(int numColors) {
|
||||||
{
|
|
||||||
d->numColors = numColors;
|
d->numColors = numColors;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector FLAC::Picture::data() const
|
ByteVector FLAC::Picture::data() const {
|
||||||
{
|
|
||||||
return d->data;
|
return d->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FLAC::Picture::setData(const ByteVector &data)
|
void FLAC::Picture::setData(const ByteVector &data) {
|
||||||
{
|
|
||||||
d->data = data;
|
d->data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
200
3rdparty/taglib/flac/flacpicture.h
vendored
200
3rdparty/taglib/flac/flacpicture.h
vendored
@ -35,176 +35,174 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
namespace FLAC {
|
namespace FLAC {
|
||||||
|
|
||||||
class TAGLIB_EXPORT Picture : public MetadataBlock
|
class TAGLIB_EXPORT Picture : public MetadataBlock {
|
||||||
{
|
public:
|
||||||
public:
|
/*!
|
||||||
|
|
||||||
/*!
|
|
||||||
* This describes the function or content of the picture.
|
* This describes the function or content of the picture.
|
||||||
*/
|
*/
|
||||||
enum Type {
|
enum Type {
|
||||||
//! A type not enumerated below
|
//! A type not enumerated below
|
||||||
Other = 0x00,
|
Other = 0x00,
|
||||||
//! 32x32 PNG image that should be used as the file icon
|
//! 32x32 PNG image that should be used as the file icon
|
||||||
FileIcon = 0x01,
|
FileIcon = 0x01,
|
||||||
//! File icon of a different size or format
|
//! File icon of a different size or format
|
||||||
OtherFileIcon = 0x02,
|
OtherFileIcon = 0x02,
|
||||||
//! Front cover image of the album
|
//! Front cover image of the album
|
||||||
FrontCover = 0x03,
|
FrontCover = 0x03,
|
||||||
//! Back cover image of the album
|
//! Back cover image of the album
|
||||||
BackCover = 0x04,
|
BackCover = 0x04,
|
||||||
//! Inside leaflet page of the album
|
//! Inside leaflet page of the album
|
||||||
LeafletPage = 0x05,
|
LeafletPage = 0x05,
|
||||||
//! Image from the album itself
|
//! Image from the album itself
|
||||||
Media = 0x06,
|
Media = 0x06,
|
||||||
//! Picture of the lead artist or soloist
|
//! Picture of the lead artist or soloist
|
||||||
LeadArtist = 0x07,
|
LeadArtist = 0x07,
|
||||||
//! Picture of the artist or performer
|
//! Picture of the artist or performer
|
||||||
Artist = 0x08,
|
Artist = 0x08,
|
||||||
//! Picture of the conductor
|
//! Picture of the conductor
|
||||||
Conductor = 0x09,
|
Conductor = 0x09,
|
||||||
//! Picture of the band or orchestra
|
//! Picture of the band or orchestra
|
||||||
Band = 0x0A,
|
Band = 0x0A,
|
||||||
//! Picture of the composer
|
//! Picture of the composer
|
||||||
Composer = 0x0B,
|
Composer = 0x0B,
|
||||||
//! Picture of the lyricist or text writer
|
//! Picture of the lyricist or text writer
|
||||||
Lyricist = 0x0C,
|
Lyricist = 0x0C,
|
||||||
//! Picture of the recording location or studio
|
//! Picture of the recording location or studio
|
||||||
RecordingLocation = 0x0D,
|
RecordingLocation = 0x0D,
|
||||||
//! Picture of the artists during recording
|
//! Picture of the artists during recording
|
||||||
DuringRecording = 0x0E,
|
DuringRecording = 0x0E,
|
||||||
//! Picture of the artists during performance
|
//! Picture of the artists during performance
|
||||||
DuringPerformance = 0x0F,
|
DuringPerformance = 0x0F,
|
||||||
//! Picture from a movie or video related to the track
|
//! Picture from a movie or video related to the track
|
||||||
MovieScreenCapture = 0x10,
|
MovieScreenCapture = 0x10,
|
||||||
//! Picture of a large, coloured fish
|
//! Picture of a large, coloured fish
|
||||||
ColouredFish = 0x11,
|
ColouredFish = 0x11,
|
||||||
//! Illustration related to the track
|
//! Illustration related to the track
|
||||||
Illustration = 0x12,
|
Illustration = 0x12,
|
||||||
//! Logo of the band or performer
|
//! Logo of the band or performer
|
||||||
BandLogo = 0x13,
|
BandLogo = 0x13,
|
||||||
//! Logo of the publisher (record company)
|
//! Logo of the publisher (record company)
|
||||||
PublisherLogo = 0x14
|
PublisherLogo = 0x14
|
||||||
};
|
};
|
||||||
|
|
||||||
Picture();
|
Picture();
|
||||||
Picture(const ByteVector &data);
|
Picture(const ByteVector &data);
|
||||||
~Picture();
|
~Picture();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the type of the image.
|
* Returns the type of the image.
|
||||||
*/
|
*/
|
||||||
Type type() const;
|
Type type() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the type of the image.
|
* Sets the type of the image.
|
||||||
*/
|
*/
|
||||||
void setType(Type type);
|
void setType(Type type);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the mime type of the image. This should in most cases be
|
* Returns the mime type of the image. This should in most cases be
|
||||||
* "image/png" or "image/jpeg".
|
* "image/png" or "image/jpeg".
|
||||||
*/
|
*/
|
||||||
String mimeType() const;
|
String mimeType() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the mime type of the image. This should in most cases be
|
* Sets the mime type of the image. This should in most cases be
|
||||||
* "image/png" or "image/jpeg".
|
* "image/png" or "image/jpeg".
|
||||||
*/
|
*/
|
||||||
void setMimeType(const String &m);
|
void setMimeType(const String &m);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns a text description of the image.
|
* Returns a text description of the image.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
String description() const;
|
String description() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets a textual description of the image to \a desc.
|
* Sets a textual description of the image to \a desc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void setDescription(const String &desc);
|
void setDescription(const String &desc);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the width of the image.
|
* Returns the width of the image.
|
||||||
*/
|
*/
|
||||||
int width() const;
|
int width() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the width of the image.
|
* Sets the width of the image.
|
||||||
*/
|
*/
|
||||||
void setWidth(int w);
|
void setWidth(int w);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the height of the image.
|
* Returns the height of the image.
|
||||||
*/
|
*/
|
||||||
int height() const;
|
int height() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the height of the image.
|
* Sets the height of the image.
|
||||||
*/
|
*/
|
||||||
void setHeight(int h);
|
void setHeight(int h);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the color depth (in bits-per-pixel) of the image.
|
* Returns the color depth (in bits-per-pixel) of the image.
|
||||||
*/
|
*/
|
||||||
int colorDepth() const;
|
int colorDepth() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the color depth (in bits-per-pixel) of the image.
|
* Sets the color depth (in bits-per-pixel) of the image.
|
||||||
*/
|
*/
|
||||||
void setColorDepth(int depth);
|
void setColorDepth(int depth);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the number of colors used on the image..
|
* Returns the number of colors used on the image..
|
||||||
*/
|
*/
|
||||||
int numColors() const;
|
int numColors() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the number of colors used on the image (for indexed images).
|
* Sets the number of colors used on the image (for indexed images).
|
||||||
*/
|
*/
|
||||||
void setNumColors(int numColors);
|
void setNumColors(int numColors);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the image data.
|
* Returns the image data.
|
||||||
*/
|
*/
|
||||||
ByteVector data() const;
|
ByteVector data() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the image data.
|
* Sets the image data.
|
||||||
*/
|
*/
|
||||||
void setData(const ByteVector &data);
|
void setData(const ByteVector &data);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the FLAC metadata block type.
|
* Returns the FLAC metadata block type.
|
||||||
*/
|
*/
|
||||||
int code() const;
|
int code() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Render the content to the FLAC picture block format.
|
* Render the content to the FLAC picture block format.
|
||||||
*/
|
*/
|
||||||
ByteVector render() const;
|
ByteVector render() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Parse the picture data in the FLAC picture block format.
|
* Parse the picture data in the FLAC picture block format.
|
||||||
*/
|
*/
|
||||||
bool parse(const ByteVector &rawData);
|
bool parse(const ByteVector &rawData);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Picture(const Picture &item);
|
Picture(const Picture &item);
|
||||||
Picture &operator=(const Picture &item);
|
Picture &operator=(const Picture &item);
|
||||||
|
|
||||||
class PicturePrivate;
|
class PicturePrivate;
|
||||||
PicturePrivate *d;
|
PicturePrivate *d;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef List<Picture> PictureList;
|
typedef List<Picture> PictureList;
|
||||||
|
|
||||||
}
|
} // namespace FLAC
|
||||||
|
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
78
3rdparty/taglib/flac/flacproperties.cpp
vendored
78
3rdparty/taglib/flac/flacproperties.cpp
vendored
@ -31,16 +31,14 @@
|
|||||||
|
|
||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
class FLAC::Properties::PropertiesPrivate
|
class FLAC::Properties::PropertiesPrivate {
|
||||||
{
|
public:
|
||||||
public:
|
PropertiesPrivate() : length(0),
|
||||||
PropertiesPrivate() :
|
bitrate(0),
|
||||||
length(0),
|
sampleRate(0),
|
||||||
bitrate(0),
|
bitsPerSample(0),
|
||||||
sampleRate(0),
|
channels(0),
|
||||||
bitsPerSample(0),
|
sampleFrames(0) {}
|
||||||
channels(0),
|
|
||||||
sampleFrames(0) {}
|
|
||||||
|
|
||||||
int length;
|
int length;
|
||||||
int bitrate;
|
int bitrate;
|
||||||
@ -55,72 +53,57 @@ public:
|
|||||||
// public members
|
// public members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
FLAC::Properties::Properties(ByteVector data, long streamLength, ReadStyle style) :
|
FLAC::Properties::Properties(ByteVector data, long streamLength, ReadStyle style) : AudioProperties(style),
|
||||||
AudioProperties(style),
|
d(new PropertiesPrivate()) {
|
||||||
d(new PropertiesPrivate())
|
|
||||||
{
|
|
||||||
read(data, streamLength);
|
read(data, streamLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
FLAC::Properties::Properties(File *, ReadStyle style) :
|
FLAC::Properties::Properties(File *, ReadStyle style) : AudioProperties(style),
|
||||||
AudioProperties(style),
|
d(new PropertiesPrivate()) {
|
||||||
d(new PropertiesPrivate())
|
|
||||||
{
|
|
||||||
debug("FLAC::Properties::Properties() - This constructor is no longer used.");
|
debug("FLAC::Properties::Properties() - This constructor is no longer used.");
|
||||||
}
|
}
|
||||||
|
|
||||||
FLAC::Properties::~Properties()
|
FLAC::Properties::~Properties() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
int FLAC::Properties::length() const
|
int FLAC::Properties::length() const {
|
||||||
{
|
|
||||||
return lengthInSeconds();
|
return lengthInSeconds();
|
||||||
}
|
}
|
||||||
|
|
||||||
int FLAC::Properties::lengthInSeconds() const
|
int FLAC::Properties::lengthInSeconds() const {
|
||||||
{
|
|
||||||
return d->length / 1000;
|
return d->length / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
int FLAC::Properties::lengthInMilliseconds() const
|
int FLAC::Properties::lengthInMilliseconds() const {
|
||||||
{
|
|
||||||
return d->length;
|
return d->length;
|
||||||
}
|
}
|
||||||
|
|
||||||
int FLAC::Properties::bitrate() const
|
int FLAC::Properties::bitrate() const {
|
||||||
{
|
|
||||||
return d->bitrate;
|
return d->bitrate;
|
||||||
}
|
}
|
||||||
|
|
||||||
int FLAC::Properties::sampleRate() const
|
int FLAC::Properties::sampleRate() const {
|
||||||
{
|
|
||||||
return d->sampleRate;
|
return d->sampleRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
int FLAC::Properties::bitsPerSample() const
|
int FLAC::Properties::bitsPerSample() const {
|
||||||
{
|
|
||||||
return d->bitsPerSample;
|
return d->bitsPerSample;
|
||||||
}
|
}
|
||||||
|
|
||||||
int FLAC::Properties::sampleWidth() const
|
int FLAC::Properties::sampleWidth() const {
|
||||||
{
|
|
||||||
return bitsPerSample();
|
return bitsPerSample();
|
||||||
}
|
}
|
||||||
|
|
||||||
int FLAC::Properties::channels() const
|
int FLAC::Properties::channels() const {
|
||||||
{
|
|
||||||
return d->channels;
|
return d->channels;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long long FLAC::Properties::sampleFrames() const
|
unsigned long long FLAC::Properties::sampleFrames() const {
|
||||||
{
|
|
||||||
return d->sampleFrames;
|
return d->sampleFrames;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector FLAC::Properties::signature() const
|
ByteVector FLAC::Properties::signature() const {
|
||||||
{
|
|
||||||
return d->signature;
|
return d->signature;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,9 +111,8 @@ ByteVector FLAC::Properties::signature() const
|
|||||||
// private members
|
// private members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void FLAC::Properties::read(const ByteVector &data, long streamLength)
|
void FLAC::Properties::read(const ByteVector &data, long streamLength) {
|
||||||
{
|
if (data.size() < 18) {
|
||||||
if(data.size() < 18) {
|
|
||||||
debug("FLAC::Properties::read() - FLAC properties must contain at least 18 bytes.");
|
debug("FLAC::Properties::read() - FLAC properties must contain at least 18 bytes.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -152,8 +134,8 @@ void FLAC::Properties::read(const ByteVector &data, long streamLength)
|
|||||||
const unsigned int flags = data.toUInt(pos, true);
|
const unsigned int flags = data.toUInt(pos, true);
|
||||||
pos += 4;
|
pos += 4;
|
||||||
|
|
||||||
d->sampleRate = flags >> 12;
|
d->sampleRate = flags >> 12;
|
||||||
d->channels = ((flags >> 9) & 7) + 1;
|
d->channels = ((flags >> 9) & 7) + 1;
|
||||||
d->bitsPerSample = ((flags >> 4) & 31) + 1;
|
d->bitsPerSample = ((flags >> 4) & 31) + 1;
|
||||||
|
|
||||||
// The last 4 bits are the most significant 4 bits for the 36 bit
|
// The last 4 bits are the most significant 4 bits for the 36 bit
|
||||||
@ -165,12 +147,12 @@ void FLAC::Properties::read(const ByteVector &data, long streamLength)
|
|||||||
|
|
||||||
d->sampleFrames = (hi << 32) | lo;
|
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;
|
const double length = d->sampleFrames * 1000.0 / d->sampleRate;
|
||||||
d->length = static_cast<int>(length + 0.5);
|
d->length = static_cast<int>(length + 0.5);
|
||||||
d->bitrate = static_cast<int>(streamLength * 8.0 / 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);
|
d->signature = data.mid(pos, 16);
|
||||||
}
|
}
|
||||||
|
93
3rdparty/taglib/flac/flacproperties.h
vendored
93
3rdparty/taglib/flac/flacproperties.h
vendored
@ -32,40 +32,39 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace 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
|
* This reads the data from an FLAC stream found in the AudioProperties
|
||||||
* API.
|
* API.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class TAGLIB_EXPORT Properties : public AudioProperties
|
class TAGLIB_EXPORT Properties : public AudioProperties {
|
||||||
{
|
public:
|
||||||
public:
|
/*!
|
||||||
/*!
|
|
||||||
* Create an instance of FLAC::Properties with the data read from the
|
* Create an instance of FLAC::Properties with the data read from the
|
||||||
* ByteVector \a data.
|
* ByteVector \a data.
|
||||||
*/
|
*/
|
||||||
// BIC: switch to const reference
|
// BIC: switch to const reference
|
||||||
Properties(ByteVector data, long streamLength, ReadStyle style = Average);
|
Properties(ByteVector data, long streamLength, ReadStyle style = Average);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Create an instance of FLAC::Properties with the data read from the
|
* Create an instance of FLAC::Properties with the data read from the
|
||||||
* FLAC::File \a file.
|
* FLAC::File \a file.
|
||||||
*/
|
*/
|
||||||
// BIC: remove
|
// BIC: remove
|
||||||
Properties(File *file, ReadStyle style = Average);
|
Properties(File *file, ReadStyle style = Average);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys this FLAC::Properties instance.
|
* Destroys this FLAC::Properties instance.
|
||||||
*/
|
*/
|
||||||
virtual ~Properties();
|
virtual ~Properties();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the length of the file in seconds. The length is rounded down to
|
* Returns the length of the file in seconds. The length is rounded down to
|
||||||
* the nearest whole second.
|
* the nearest whole second.
|
||||||
*
|
*
|
||||||
@ -73,47 +72,47 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \deprecated
|
* \deprecated
|
||||||
*/
|
*/
|
||||||
TAGLIB_DEPRECATED virtual int length() const;
|
TAGLIB_DEPRECATED virtual int length() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the length of the file in seconds. The length is rounded down to
|
* Returns the length of the file in seconds. The length is rounded down to
|
||||||
* the nearest whole second.
|
* the nearest whole second.
|
||||||
*
|
*
|
||||||
* \see lengthInMilliseconds()
|
* \see lengthInMilliseconds()
|
||||||
*/
|
*/
|
||||||
// BIC: make virtual
|
// BIC: make virtual
|
||||||
int lengthInSeconds() const;
|
int lengthInSeconds() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the length of the file in milliseconds.
|
* Returns the length of the file in milliseconds.
|
||||||
*
|
*
|
||||||
* \see lengthInSeconds()
|
* \see lengthInSeconds()
|
||||||
*/
|
*/
|
||||||
// BIC: make virtual
|
// BIC: make virtual
|
||||||
int lengthInMilliseconds() const;
|
int lengthInMilliseconds() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the average bit rate of the file in kb/s.
|
* Returns the average bit rate of the file in kb/s.
|
||||||
*/
|
*/
|
||||||
virtual int bitrate() const;
|
virtual int bitrate() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the sample rate in Hz.
|
* Returns the sample rate in Hz.
|
||||||
*/
|
*/
|
||||||
virtual int sampleRate() const;
|
virtual int sampleRate() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the number of audio channels.
|
* Returns the number of audio channels.
|
||||||
*/
|
*/
|
||||||
virtual int channels() const;
|
virtual int channels() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the number of bits per audio sample as read from the FLAC
|
* Returns the number of bits per audio sample as read from the FLAC
|
||||||
* identification header.
|
* identification header.
|
||||||
*/
|
*/
|
||||||
int bitsPerSample() const;
|
int bitsPerSample() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the sample width as read from the FLAC identification
|
* Returns the sample width as read from the FLAC identification
|
||||||
* header.
|
* header.
|
||||||
*
|
*
|
||||||
@ -121,30 +120,30 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \deprecated
|
* \deprecated
|
||||||
*/
|
*/
|
||||||
TAGLIB_DEPRECATED int sampleWidth() const;
|
TAGLIB_DEPRECATED int sampleWidth() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Return the number of sample frames.
|
* Return the number of sample frames.
|
||||||
*/
|
*/
|
||||||
unsigned long long sampleFrames() const;
|
unsigned long long sampleFrames() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the MD5 signature of the uncompressed audio stream as read
|
* Returns the MD5 signature of the uncompressed audio stream as read
|
||||||
* from the stream info header.
|
* from the stream info header.
|
||||||
*/
|
*/
|
||||||
ByteVector signature() const;
|
ByteVector signature() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Properties(const Properties &);
|
Properties(const Properties &);
|
||||||
Properties &operator=(const Properties &);
|
Properties &operator=(const Properties &);
|
||||||
|
|
||||||
void read(const ByteVector &data, long streamLength);
|
void read(const ByteVector &data, long streamLength);
|
||||||
|
|
||||||
class PropertiesPrivate;
|
class PropertiesPrivate;
|
||||||
PropertiesPrivate *d;
|
PropertiesPrivate *d;
|
||||||
};
|
};
|
||||||
}
|
} // namespace FLAC
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -30,49 +30,39 @@
|
|||||||
|
|
||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
class FLAC::UnknownMetadataBlock::UnknownMetadataBlockPrivate
|
class FLAC::UnknownMetadataBlock::UnknownMetadataBlockPrivate {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
UnknownMetadataBlockPrivate() : code(0) {}
|
UnknownMetadataBlockPrivate() : code(0) {}
|
||||||
|
|
||||||
int code;
|
int code;
|
||||||
ByteVector data;
|
ByteVector data;
|
||||||
};
|
};
|
||||||
|
|
||||||
FLAC::UnknownMetadataBlock::UnknownMetadataBlock(int code, const ByteVector &data) :
|
FLAC::UnknownMetadataBlock::UnknownMetadataBlock(int code, const ByteVector &data) : d(new UnknownMetadataBlockPrivate()) {
|
||||||
d(new UnknownMetadataBlockPrivate())
|
|
||||||
{
|
|
||||||
d->code = code;
|
d->code = code;
|
||||||
d->data = data;
|
d->data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
FLAC::UnknownMetadataBlock::~UnknownMetadataBlock()
|
FLAC::UnknownMetadataBlock::~UnknownMetadataBlock() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
int FLAC::UnknownMetadataBlock::code() const
|
int FLAC::UnknownMetadataBlock::code() const {
|
||||||
{
|
|
||||||
return d->code;
|
return d->code;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FLAC::UnknownMetadataBlock::setCode(int code)
|
void FLAC::UnknownMetadataBlock::setCode(int code) {
|
||||||
{
|
|
||||||
d->code = code;
|
d->code = code;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector FLAC::UnknownMetadataBlock::data() const
|
ByteVector FLAC::UnknownMetadataBlock::data() const {
|
||||||
{
|
|
||||||
return d->data;
|
return d->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FLAC::UnknownMetadataBlock::setData(const ByteVector &data)
|
void FLAC::UnknownMetadataBlock::setData(const ByteVector &data) {
|
||||||
{
|
|
||||||
d->data = data;
|
d->data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector FLAC::UnknownMetadataBlock::render() const
|
ByteVector FLAC::UnknownMetadataBlock::render() const {
|
||||||
{
|
|
||||||
return d->data;
|
return d->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
49
3rdparty/taglib/flac/flacunknownmetadatablock.h
vendored
49
3rdparty/taglib/flac/flacunknownmetadatablock.h
vendored
@ -34,50 +34,49 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
namespace FLAC {
|
namespace FLAC {
|
||||||
|
|
||||||
class TAGLIB_EXPORT UnknownMetadataBlock : public MetadataBlock
|
class TAGLIB_EXPORT UnknownMetadataBlock : public MetadataBlock {
|
||||||
{
|
public:
|
||||||
public:
|
UnknownMetadataBlock(int blockType, const ByteVector &data);
|
||||||
UnknownMetadataBlock(int blockType, const ByteVector &data);
|
~UnknownMetadataBlock();
|
||||||
~UnknownMetadataBlock();
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the FLAC metadata block type.
|
* Returns the FLAC metadata block type.
|
||||||
*/
|
*/
|
||||||
int code() const;
|
int code() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the FLAC metadata block type.
|
* Sets the FLAC metadata block type.
|
||||||
*/
|
*/
|
||||||
void setCode(int code);
|
void setCode(int code);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the FLAC metadata block type.
|
* Returns the FLAC metadata block type.
|
||||||
*/
|
*/
|
||||||
ByteVector data() const;
|
ByteVector data() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the FLAC metadata block type.
|
* Sets the FLAC metadata block type.
|
||||||
*/
|
*/
|
||||||
void setData(const ByteVector &data);
|
void setData(const ByteVector &data);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Render the content of the block.
|
* Render the content of the block.
|
||||||
*/
|
*/
|
||||||
ByteVector render() const;
|
ByteVector render() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UnknownMetadataBlock(const MetadataBlock &item);
|
UnknownMetadataBlock(const MetadataBlock &item);
|
||||||
UnknownMetadataBlock &operator=(const MetadataBlock &item);
|
UnknownMetadataBlock &operator=(const MetadataBlock &item);
|
||||||
|
|
||||||
class UnknownMetadataBlockPrivate;
|
class UnknownMetadataBlockPrivate;
|
||||||
UnknownMetadataBlockPrivate *d;
|
UnknownMetadataBlockPrivate *d;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace FLAC
|
||||||
|
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
111
3rdparty/taglib/it/itfile.cpp
vendored
111
3rdparty/taglib/it/itfile.cpp
vendored
@ -33,65 +33,52 @@
|
|||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
using namespace IT;
|
using namespace IT;
|
||||||
|
|
||||||
class IT::File::FilePrivate
|
class IT::File::FilePrivate {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
explicit FilePrivate(AudioProperties::ReadStyle propertiesStyle)
|
explicit FilePrivate(AudioProperties::ReadStyle propertiesStyle)
|
||||||
: tag(), properties(propertiesStyle)
|
: tag(), properties(propertiesStyle) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Mod::Tag tag;
|
Mod::Tag tag;
|
||||||
IT::Properties properties;
|
IT::Properties properties;
|
||||||
};
|
};
|
||||||
|
|
||||||
IT::File::File(FileName file, bool readProperties,
|
IT::File::File(FileName file, bool readProperties,
|
||||||
AudioProperties::ReadStyle propertiesStyle) :
|
AudioProperties::ReadStyle propertiesStyle) : Mod::FileBase(file),
|
||||||
Mod::FileBase(file),
|
d(new FilePrivate(propertiesStyle)) {
|
||||||
d(new FilePrivate(propertiesStyle))
|
if (isOpen())
|
||||||
{
|
|
||||||
if(isOpen())
|
|
||||||
read(readProperties);
|
read(readProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
IT::File::File(IOStream *stream, bool readProperties,
|
IT::File::File(IOStream *stream, bool readProperties,
|
||||||
AudioProperties::ReadStyle propertiesStyle) :
|
AudioProperties::ReadStyle propertiesStyle) : Mod::FileBase(stream),
|
||||||
Mod::FileBase(stream),
|
d(new FilePrivate(propertiesStyle)) {
|
||||||
d(new FilePrivate(propertiesStyle))
|
if (isOpen())
|
||||||
{
|
|
||||||
if(isOpen())
|
|
||||||
read(readProperties);
|
read(readProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
IT::File::~File()
|
IT::File::~File() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
Mod::Tag *IT::File::tag() const
|
Mod::Tag *IT::File::tag() const {
|
||||||
{
|
|
||||||
return &d->tag;
|
return &d->tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyMap IT::File::properties() const
|
PropertyMap IT::File::properties() const {
|
||||||
{
|
|
||||||
return d->tag.properties();
|
return d->tag.properties();
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyMap IT::File::setProperties(const PropertyMap &properties)
|
PropertyMap IT::File::setProperties(const PropertyMap &properties) {
|
||||||
{
|
|
||||||
return d->tag.setProperties(properties);
|
return d->tag.setProperties(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
IT::Properties *IT::File::audioProperties() const
|
IT::Properties *IT::File::audioProperties() const {
|
||||||
{
|
|
||||||
return &d->properties;
|
return &d->properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IT::File::save()
|
bool IT::File::save() {
|
||||||
{
|
if (readOnly()) {
|
||||||
if(readOnly())
|
|
||||||
{
|
|
||||||
debug("IT::File::save() - Cannot save to a read only file.");
|
debug("IT::File::save() - Cannot save to a read only file.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -105,37 +92,37 @@ bool IT::File::save()
|
|||||||
unsigned short instrumentCount = 0;
|
unsigned short instrumentCount = 0;
|
||||||
unsigned short sampleCount = 0;
|
unsigned short sampleCount = 0;
|
||||||
|
|
||||||
if(!readU16L(length) || !readU16L(instrumentCount) || !readU16L(sampleCount))
|
if (!readU16L(length) || !readU16L(instrumentCount) || !readU16L(sampleCount))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
seek(15, Current);
|
seek(15, Current);
|
||||||
|
|
||||||
// write comment as instrument and sample names:
|
// write comment as instrument and sample names:
|
||||||
StringList lines = d->tag.comment().split("\n");
|
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));
|
seek(192L + length + ((long)i << 2));
|
||||||
unsigned long instrumentOffset = 0;
|
unsigned long instrumentOffset = 0;
|
||||||
if(!readU32L(instrumentOffset))
|
if (!readU32L(instrumentOffset))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
seek(instrumentOffset + 32);
|
seek(instrumentOffset + 32);
|
||||||
|
|
||||||
if(i < lines.size())
|
if (i < lines.size())
|
||||||
writeString(lines[i], 25);
|
writeString(lines[i], 25);
|
||||||
else
|
else
|
||||||
writeString(String(), 25);
|
writeString(String(), 25);
|
||||||
writeByte(0);
|
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));
|
seek(192L + length + ((long)instrumentCount << 2) + ((long)i << 2));
|
||||||
unsigned long sampleOffset = 0;
|
unsigned long sampleOffset = 0;
|
||||||
if(!readU32L(sampleOffset))
|
if (!readU32L(sampleOffset))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
seek(sampleOffset + 20);
|
seek(sampleOffset + 20);
|
||||||
|
|
||||||
if((unsigned int)(i + instrumentCount) < lines.size())
|
if ((unsigned int)(i + instrumentCount) < lines.size())
|
||||||
writeString(lines[i + instrumentCount], 25);
|
writeString(lines[i + instrumentCount], 25);
|
||||||
else
|
else
|
||||||
writeString(String(), 25);
|
writeString(String(), 25);
|
||||||
@ -144,41 +131,40 @@ bool IT::File::save()
|
|||||||
|
|
||||||
// write rest as message:
|
// write rest as message:
|
||||||
StringList messageLines;
|
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]);
|
messageLines.append(lines[i]);
|
||||||
ByteVector message = messageLines.toString("\r").data(String::Latin1);
|
ByteVector message = messageLines.toString("\r").data(String::Latin1);
|
||||||
|
|
||||||
// it's actually not really stated if the message needs a
|
// it's actually not really stated if the message needs a
|
||||||
// terminating NUL but it does not hurt to add one:
|
// terminating NUL but it does not hurt to add one:
|
||||||
if(message.size() > 7999)
|
if (message.size() > 7999)
|
||||||
message.resize(7999);
|
message.resize(7999);
|
||||||
message.append((char)0);
|
message.append((char)0);
|
||||||
|
|
||||||
unsigned short special = 0;
|
unsigned short special = 0;
|
||||||
unsigned short messageLength = 0;
|
unsigned short messageLength = 0;
|
||||||
unsigned long messageOffset = 0;
|
unsigned long messageOffset = 0;
|
||||||
|
|
||||||
seek(46);
|
seek(46);
|
||||||
if(!readU16L(special))
|
if (!readU16L(special))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
unsigned long fileSize = File::length();
|
unsigned long fileSize = File::length();
|
||||||
if(special & Properties::MessageAttached) {
|
if (special & Properties::MessageAttached) {
|
||||||
seek(54);
|
seek(54);
|
||||||
if(!readU16L(messageLength) || !readU32L(messageOffset))
|
if (!readU16L(messageLength) || !readU32L(messageOffset))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(messageLength == 0)
|
if (messageLength == 0)
|
||||||
messageOffset = fileSize;
|
messageOffset = fileSize;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
{
|
|
||||||
messageOffset = fileSize;
|
messageOffset = fileSize;
|
||||||
seek(46);
|
seek(46);
|
||||||
writeU16L(special | 0x1);
|
writeU16L(special | 0x1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(messageOffset + messageLength >= fileSize) {
|
if (messageOffset + messageLength >= fileSize) {
|
||||||
// append new message
|
// append new message
|
||||||
seek(54);
|
seek(54);
|
||||||
writeU16L(message.size());
|
writeU16L(message.size());
|
||||||
@ -199,9 +185,8 @@ bool IT::File::save()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IT::File::read(bool)
|
void IT::File::read(bool) {
|
||||||
{
|
if (!isOpen())
|
||||||
if(!isOpen())
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
seek(0);
|
seek(0);
|
||||||
@ -233,14 +218,14 @@ void IT::File::read(bool)
|
|||||||
// sample/instrument names are abused as comments so
|
// sample/instrument names are abused as comments so
|
||||||
// I just add all together.
|
// I just add all together.
|
||||||
String message;
|
String message;
|
||||||
if(special & Properties::MessageAttached) {
|
if (special & Properties::MessageAttached) {
|
||||||
READ_U16L_AS(messageLength);
|
READ_U16L_AS(messageLength);
|
||||||
READ_U32L_AS(messageOffset);
|
READ_U32L_AS(messageOffset);
|
||||||
seek(messageOffset);
|
seek(messageOffset);
|
||||||
ByteVector messageBytes = readBlock(messageLength);
|
ByteVector messageBytes = readBlock(messageLength);
|
||||||
READ_ASSERT(messageBytes.size() == messageLength);
|
READ_ASSERT(messageBytes.size() == messageLength);
|
||||||
int index = messageBytes.find((char) 0);
|
int index = messageBytes.find((char)0);
|
||||||
if(index > -1)
|
if (index > -1)
|
||||||
messageBytes.resize(index, 0);
|
messageBytes.resize(index, 0);
|
||||||
messageBytes.replace('\r', '\n');
|
messageBytes.replace('\r', '\n');
|
||||||
message = messageBytes;
|
message = messageBytes;
|
||||||
@ -249,26 +234,26 @@ void IT::File::read(bool)
|
|||||||
seek(64);
|
seek(64);
|
||||||
|
|
||||||
ByteVector pannings = readBlock(64);
|
ByteVector pannings = readBlock(64);
|
||||||
ByteVector volumes = readBlock(64);
|
ByteVector volumes = readBlock(64);
|
||||||
READ_ASSERT(pannings.size() == 64 && volumes.size() == 64);
|
READ_ASSERT(pannings.size() == 64 && volumes.size() == 64);
|
||||||
int channels = 0;
|
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
|
// Strictly speaking an IT file has always 64 channels, but
|
||||||
// I don't count disabled and muted channels.
|
// I don't count disabled and muted channels.
|
||||||
// But this always gives 64 channels for all my files anyway.
|
// But this always gives 64 channels for all my files anyway.
|
||||||
// Strangely VLC does report other values. I wonder how VLC
|
// Strangely VLC does report other values. I wonder how VLC
|
||||||
// gets it's values.
|
// gets it's values.
|
||||||
if((unsigned char) pannings[i] < 128 && volumes[i] > 0)
|
if ((unsigned char)pannings[i] < 128 && volumes[i] > 0)
|
||||||
++channels;
|
++channels;
|
||||||
}
|
}
|
||||||
d->properties.setChannels(channels);
|
d->properties.setChannels(channels);
|
||||||
|
|
||||||
// real length might be shorter because of skips and terminator
|
// real length might be shorter because of skips and terminator
|
||||||
unsigned short realLength = 0;
|
unsigned short realLength = 0;
|
||||||
for(unsigned short i = 0; i < length; ++ i) {
|
for (unsigned short i = 0; i < length; ++i) {
|
||||||
READ_BYTE_AS(order);
|
READ_BYTE_AS(order);
|
||||||
if(order == 255) break;
|
if (order == 255) break;
|
||||||
if(order != 254) ++ realLength;
|
if (order != 254) ++realLength;
|
||||||
}
|
}
|
||||||
d->properties.setLengthInPatterns(realLength);
|
d->properties.setLengthInPatterns(realLength);
|
||||||
|
|
||||||
@ -279,7 +264,7 @@ void IT::File::read(bool)
|
|||||||
// Currently I just discard anything after a nil, but
|
// Currently I just discard anything after a nil, but
|
||||||
// e.g. VLC seems to interpret a nil as a space. I
|
// e.g. VLC seems to interpret a nil as a space. I
|
||||||
// don't know what is the proper behaviour.
|
// 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));
|
seek(192L + length + ((long)i << 2));
|
||||||
READ_U32L_AS(instrumentOffset);
|
READ_U32L_AS(instrumentOffset);
|
||||||
seek(instrumentOffset);
|
seek(instrumentOffset);
|
||||||
@ -295,7 +280,7 @@ void IT::File::read(bool)
|
|||||||
comment.append(instrumentName);
|
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));
|
seek(192L + length + ((long)instrumentCount << 2) + ((long)i << 2));
|
||||||
READ_U32L_AS(sampleOffset);
|
READ_U32L_AS(sampleOffset);
|
||||||
|
|
||||||
@ -328,7 +313,7 @@ void IT::File::read(bool)
|
|||||||
comment.append(sampleName);
|
comment.append(sampleName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(message.size() > 0)
|
if (message.size() > 0)
|
||||||
comment.append(message);
|
comment.append(message);
|
||||||
d->tag.setComment(comment.toString("\n"));
|
d->tag.setComment(comment.toString("\n"));
|
||||||
d->tag.setTrackerName("Impulse Tracker");
|
d->tag.setTrackerName("Impulse Tracker");
|
||||||
|
64
3rdparty/taglib/it/itfile.h
vendored
64
3rdparty/taglib/it/itfile.h
vendored
@ -32,22 +32,22 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
namespace IT {
|
namespace IT {
|
||||||
|
|
||||||
class TAGLIB_EXPORT File : public Mod::FileBase {
|
class TAGLIB_EXPORT File : public Mod::FileBase {
|
||||||
public:
|
public:
|
||||||
/*!
|
/*!
|
||||||
* Constructs a Impulse Tracker file from \a file.
|
* Constructs a Impulse Tracker file from \a file.
|
||||||
*
|
*
|
||||||
* \note In the current implementation, both \a readProperties and
|
* \note In the current implementation, both \a readProperties and
|
||||||
* \a propertiesStyle are ignored. The audio properties are always
|
* \a propertiesStyle are ignored. The audio properties are always
|
||||||
* read.
|
* read.
|
||||||
*/
|
*/
|
||||||
File(FileName file, bool readProperties = true,
|
File(FileName file, bool readProperties = true,
|
||||||
AudioProperties::ReadStyle propertiesStyle =
|
AudioProperties::ReadStyle propertiesStyle =
|
||||||
AudioProperties::Average);
|
AudioProperties::Average);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs a Impulse Tracker file from \a stream.
|
* Constructs a Impulse Tracker file from \a stream.
|
||||||
*
|
*
|
||||||
* \note In the current implementation, both \a readProperties and
|
* \note In the current implementation, both \a readProperties and
|
||||||
@ -57,55 +57,55 @@ namespace TagLib {
|
|||||||
* \note TagLib will *not* take ownership of the stream, the caller is
|
* \note TagLib will *not* take ownership of the stream, the caller is
|
||||||
* responsible for deleting it after the File object.
|
* responsible for deleting it after the File object.
|
||||||
*/
|
*/
|
||||||
File(IOStream *stream, bool readProperties = true,
|
File(IOStream *stream, bool readProperties = true,
|
||||||
AudioProperties::ReadStyle propertiesStyle =
|
AudioProperties::ReadStyle propertiesStyle =
|
||||||
AudioProperties::Average);
|
AudioProperties::Average);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys this instance of the File.
|
* Destroys this instance of the File.
|
||||||
*/
|
*/
|
||||||
virtual ~File();
|
virtual ~File();
|
||||||
|
|
||||||
Mod::Tag *tag() const;
|
Mod::Tag *tag() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Forwards to Mod::Tag::properties().
|
* Forwards to Mod::Tag::properties().
|
||||||
* BIC: will be removed once File::toDict() is made virtual
|
* BIC: will be removed once File::toDict() is made virtual
|
||||||
*/
|
*/
|
||||||
PropertyMap properties() const;
|
PropertyMap properties() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Forwards to Mod::Tag::setProperties().
|
* Forwards to Mod::Tag::setProperties().
|
||||||
* BIC: will be removed once File::setProperties() is made virtual
|
* BIC: will be removed once File::setProperties() is made virtual
|
||||||
*/
|
*/
|
||||||
PropertyMap setProperties(const PropertyMap &);
|
PropertyMap setProperties(const PropertyMap &);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the IT::Properties for this file. If no audio properties
|
* Returns the IT::Properties for this file. If no audio properties
|
||||||
* were read then this will return a null pointer.
|
* were read then this will return a null pointer.
|
||||||
*/
|
*/
|
||||||
IT::Properties *audioProperties() const;
|
IT::Properties *audioProperties() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Save the file.
|
* Save the file.
|
||||||
* This is the same as calling save(AllTags);
|
* This is the same as calling save(AllTags);
|
||||||
*
|
*
|
||||||
* \note Saving Impulse Tracker tags is not supported.
|
* \note Saving Impulse Tracker tags is not supported.
|
||||||
*/
|
*/
|
||||||
bool save();
|
bool save();
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
File(const File &);
|
File(const File &);
|
||||||
File &operator=(const File &);
|
File &operator=(const File &);
|
||||||
|
|
||||||
void read(bool readProperties);
|
void read(bool readProperties);
|
||||||
|
|
||||||
class FilePrivate;
|
class FilePrivate;
|
||||||
FilePrivate *d;
|
FilePrivate *d;
|
||||||
};
|
};
|
||||||
}
|
} // namespace IT
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
168
3rdparty/taglib/it/itproperties.cpp
vendored
168
3rdparty/taglib/it/itproperties.cpp
vendored
@ -29,29 +29,26 @@
|
|||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
using namespace IT;
|
using namespace IT;
|
||||||
|
|
||||||
class IT::Properties::PropertiesPrivate
|
class IT::Properties::PropertiesPrivate {
|
||||||
{
|
public:
|
||||||
public:
|
PropertiesPrivate() : channels(0),
|
||||||
PropertiesPrivate() :
|
lengthInPatterns(0),
|
||||||
channels(0),
|
instrumentCount(0),
|
||||||
lengthInPatterns(0),
|
sampleCount(0),
|
||||||
instrumentCount(0),
|
patternCount(0),
|
||||||
sampleCount(0),
|
version(0),
|
||||||
patternCount(0),
|
compatibleVersion(0),
|
||||||
version(0),
|
flags(0),
|
||||||
compatibleVersion(0),
|
special(0),
|
||||||
flags(0),
|
globalVolume(0),
|
||||||
special(0),
|
mixVolume(0),
|
||||||
globalVolume(0),
|
tempo(0),
|
||||||
mixVolume(0),
|
bpmSpeed(0),
|
||||||
tempo(0),
|
panningSeparation(0),
|
||||||
bpmSpeed(0),
|
pitchWheelDepth(0) {
|
||||||
panningSeparation(0),
|
|
||||||
pitchWheelDepth(0)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int channels;
|
int channels;
|
||||||
unsigned short lengthInPatterns;
|
unsigned short lengthInPatterns;
|
||||||
unsigned short instrumentCount;
|
unsigned short instrumentCount;
|
||||||
unsigned short sampleCount;
|
unsigned short sampleCount;
|
||||||
@ -60,201 +57,162 @@ public:
|
|||||||
unsigned short compatibleVersion;
|
unsigned short compatibleVersion;
|
||||||
unsigned short flags;
|
unsigned short flags;
|
||||||
unsigned short special;
|
unsigned short special;
|
||||||
unsigned char globalVolume;
|
unsigned char globalVolume;
|
||||||
unsigned char mixVolume;
|
unsigned char mixVolume;
|
||||||
unsigned char tempo;
|
unsigned char tempo;
|
||||||
unsigned char bpmSpeed;
|
unsigned char bpmSpeed;
|
||||||
unsigned char panningSeparation;
|
unsigned char panningSeparation;
|
||||||
unsigned char pitchWheelDepth;
|
unsigned char pitchWheelDepth;
|
||||||
};
|
};
|
||||||
|
|
||||||
IT::Properties::Properties(AudioProperties::ReadStyle propertiesStyle) :
|
IT::Properties::Properties(AudioProperties::ReadStyle propertiesStyle) : AudioProperties(propertiesStyle),
|
||||||
AudioProperties(propertiesStyle),
|
d(new PropertiesPrivate()) {
|
||||||
d(new PropertiesPrivate())
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IT::Properties::~Properties()
|
IT::Properties::~Properties() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
int IT::Properties::length() const
|
int IT::Properties::length() const {
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int IT::Properties::lengthInSeconds() const
|
int IT::Properties::lengthInSeconds() const {
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int IT::Properties::lengthInMilliseconds() const
|
int IT::Properties::lengthInMilliseconds() const {
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int IT::Properties::bitrate() const
|
int IT::Properties::bitrate() const {
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int IT::Properties::sampleRate() const
|
int IT::Properties::sampleRate() const {
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int IT::Properties::channels() const
|
int IT::Properties::channels() const {
|
||||||
{
|
|
||||||
return d->channels;
|
return d->channels;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned short IT::Properties::lengthInPatterns() const
|
unsigned short IT::Properties::lengthInPatterns() const {
|
||||||
{
|
|
||||||
return d->lengthInPatterns;
|
return d->lengthInPatterns;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IT::Properties::stereo() const
|
bool IT::Properties::stereo() const {
|
||||||
{
|
|
||||||
return d->flags & Stereo;
|
return d->flags & Stereo;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned short IT::Properties::instrumentCount() const
|
unsigned short IT::Properties::instrumentCount() const {
|
||||||
{
|
|
||||||
return d->instrumentCount;
|
return d->instrumentCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned short IT::Properties::sampleCount() const
|
unsigned short IT::Properties::sampleCount() const {
|
||||||
{
|
|
||||||
return d->sampleCount;
|
return d->sampleCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned short IT::Properties::patternCount() const
|
unsigned short IT::Properties::patternCount() const {
|
||||||
{
|
|
||||||
return d->patternCount;
|
return d->patternCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned short IT::Properties::version() const
|
unsigned short IT::Properties::version() const {
|
||||||
{
|
|
||||||
return d->version;
|
return d->version;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned short IT::Properties::compatibleVersion() const
|
unsigned short IT::Properties::compatibleVersion() const {
|
||||||
{
|
|
||||||
return d->compatibleVersion;
|
return d->compatibleVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned short IT::Properties::flags() const
|
unsigned short IT::Properties::flags() const {
|
||||||
{
|
|
||||||
return d->flags;
|
return d->flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned short IT::Properties::special() const
|
unsigned short IT::Properties::special() const {
|
||||||
{
|
|
||||||
return d->special;
|
return d->special;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char IT::Properties::globalVolume() const
|
unsigned char IT::Properties::globalVolume() const {
|
||||||
{
|
|
||||||
return d->globalVolume;
|
return d->globalVolume;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char IT::Properties::mixVolume() const
|
unsigned char IT::Properties::mixVolume() const {
|
||||||
{
|
|
||||||
return d->mixVolume;
|
return d->mixVolume;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char IT::Properties::tempo() const
|
unsigned char IT::Properties::tempo() const {
|
||||||
{
|
|
||||||
return d->tempo;
|
return d->tempo;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char IT::Properties::bpmSpeed() const
|
unsigned char IT::Properties::bpmSpeed() const {
|
||||||
{
|
|
||||||
return d->bpmSpeed;
|
return d->bpmSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char IT::Properties::panningSeparation() const
|
unsigned char IT::Properties::panningSeparation() const {
|
||||||
{
|
|
||||||
return d->panningSeparation;
|
return d->panningSeparation;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char IT::Properties::pitchWheelDepth() const
|
unsigned char IT::Properties::pitchWheelDepth() const {
|
||||||
{
|
|
||||||
return d->pitchWheelDepth;
|
return d->pitchWheelDepth;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IT::Properties::setChannels(int channels)
|
void IT::Properties::setChannels(int channels) {
|
||||||
{
|
|
||||||
d->channels = channels;
|
d->channels = channels;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IT::Properties::setLengthInPatterns(unsigned short lengthInPatterns)
|
void IT::Properties::setLengthInPatterns(unsigned short lengthInPatterns) {
|
||||||
{
|
|
||||||
d->lengthInPatterns = lengthInPatterns;
|
d->lengthInPatterns = lengthInPatterns;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IT::Properties::setInstrumentCount(unsigned short instrumentCount)
|
void IT::Properties::setInstrumentCount(unsigned short instrumentCount) {
|
||||||
{
|
|
||||||
d->instrumentCount = instrumentCount;
|
d->instrumentCount = instrumentCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IT::Properties::setSampleCount(unsigned short sampleCount)
|
void IT::Properties::setSampleCount(unsigned short sampleCount) {
|
||||||
{
|
|
||||||
d->sampleCount = sampleCount;
|
d->sampleCount = sampleCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IT::Properties::setPatternCount(unsigned short patternCount)
|
void IT::Properties::setPatternCount(unsigned short patternCount) {
|
||||||
{
|
|
||||||
d->patternCount = patternCount;
|
d->patternCount = patternCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IT::Properties::setFlags(unsigned short flags)
|
void IT::Properties::setFlags(unsigned short flags) {
|
||||||
{
|
|
||||||
d->flags = flags;
|
d->flags = flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IT::Properties::setSpecial(unsigned short special)
|
void IT::Properties::setSpecial(unsigned short special) {
|
||||||
{
|
|
||||||
d->special = special;
|
d->special = special;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IT::Properties::setCompatibleVersion(unsigned short compatibleVersion)
|
void IT::Properties::setCompatibleVersion(unsigned short compatibleVersion) {
|
||||||
{
|
|
||||||
d->compatibleVersion = compatibleVersion;
|
d->compatibleVersion = compatibleVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IT::Properties::setVersion(unsigned short version)
|
void IT::Properties::setVersion(unsigned short version) {
|
||||||
{
|
|
||||||
d->version = version;
|
d->version = version;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IT::Properties::setGlobalVolume(unsigned char globalVolume)
|
void IT::Properties::setGlobalVolume(unsigned char globalVolume) {
|
||||||
{
|
|
||||||
d->globalVolume = globalVolume;
|
d->globalVolume = globalVolume;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IT::Properties::setMixVolume(unsigned char mixVolume)
|
void IT::Properties::setMixVolume(unsigned char mixVolume) {
|
||||||
{
|
|
||||||
d->mixVolume = mixVolume;
|
d->mixVolume = mixVolume;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IT::Properties::setTempo(unsigned char tempo)
|
void IT::Properties::setTempo(unsigned char tempo) {
|
||||||
{
|
|
||||||
d->tempo = tempo;
|
d->tempo = tempo;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IT::Properties::setBpmSpeed(unsigned char bpmSpeed)
|
void IT::Properties::setBpmSpeed(unsigned char bpmSpeed) {
|
||||||
{
|
|
||||||
d->bpmSpeed = bpmSpeed;
|
d->bpmSpeed = bpmSpeed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IT::Properties::setPanningSeparation(unsigned char panningSeparation)
|
void IT::Properties::setPanningSeparation(unsigned char panningSeparation) {
|
||||||
{
|
|
||||||
d->panningSeparation = panningSeparation;
|
d->panningSeparation = panningSeparation;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IT::Properties::setPitchWheelDepth(unsigned char pitchWheelDepth)
|
void IT::Properties::setPitchWheelDepth(unsigned char pitchWheelDepth) {
|
||||||
{
|
|
||||||
d->pitchWheelDepth = pitchWheelDepth;
|
d->pitchWheelDepth = pitchWheelDepth;
|
||||||
}
|
}
|
||||||
|
135
3rdparty/taglib/it/itproperties.h
vendored
135
3rdparty/taglib/it/itproperties.h
vendored
@ -31,79 +31,80 @@
|
|||||||
|
|
||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
namespace IT {
|
namespace IT {
|
||||||
class TAGLIB_EXPORT Properties : public AudioProperties {
|
class TAGLIB_EXPORT Properties : public AudioProperties {
|
||||||
friend class File;
|
friend class File;
|
||||||
public:
|
|
||||||
/*! Flag bits. */
|
|
||||||
enum {
|
|
||||||
Stereo = 1,
|
|
||||||
Vol0MixOptimizations = 2,
|
|
||||||
UseInstruments = 4,
|
|
||||||
LinearSlides = 8,
|
|
||||||
OldEffects = 16,
|
|
||||||
LinkEffects = 32,
|
|
||||||
UseMidiPitchController = 64,
|
|
||||||
RequestEmbeddedMidiConf = 128
|
|
||||||
};
|
|
||||||
|
|
||||||
/*! Special bits. */
|
public:
|
||||||
enum {
|
/*! Flag bits. */
|
||||||
MessageAttached = 1,
|
enum {
|
||||||
MidiConfEmbedded = 8
|
Stereo = 1,
|
||||||
};
|
Vol0MixOptimizations = 2,
|
||||||
|
UseInstruments = 4,
|
||||||
|
LinearSlides = 8,
|
||||||
|
OldEffects = 16,
|
||||||
|
LinkEffects = 32,
|
||||||
|
UseMidiPitchController = 64,
|
||||||
|
RequestEmbeddedMidiConf = 128
|
||||||
|
};
|
||||||
|
|
||||||
Properties(AudioProperties::ReadStyle propertiesStyle);
|
/*! Special bits. */
|
||||||
virtual ~Properties();
|
enum {
|
||||||
|
MessageAttached = 1,
|
||||||
|
MidiConfEmbedded = 8
|
||||||
|
};
|
||||||
|
|
||||||
int length() const;
|
Properties(AudioProperties::ReadStyle propertiesStyle);
|
||||||
int lengthInSeconds() const;
|
virtual ~Properties();
|
||||||
int lengthInMilliseconds() const;
|
|
||||||
int bitrate() const;
|
|
||||||
int sampleRate() const;
|
|
||||||
int channels() const;
|
|
||||||
|
|
||||||
unsigned short lengthInPatterns() const;
|
int length() const;
|
||||||
bool stereo() const;
|
int lengthInSeconds() const;
|
||||||
unsigned short instrumentCount() const;
|
int lengthInMilliseconds() const;
|
||||||
unsigned short sampleCount() const;
|
int bitrate() const;
|
||||||
unsigned short patternCount() const;
|
int sampleRate() const;
|
||||||
unsigned short version() const;
|
int channels() const;
|
||||||
unsigned short compatibleVersion() const;
|
|
||||||
unsigned short flags() const;
|
|
||||||
unsigned short special() const;
|
|
||||||
unsigned char globalVolume() const;
|
|
||||||
unsigned char mixVolume() const;
|
|
||||||
unsigned char tempo() const;
|
|
||||||
unsigned char bpmSpeed() const;
|
|
||||||
unsigned char panningSeparation() const;
|
|
||||||
unsigned char pitchWheelDepth() const;
|
|
||||||
|
|
||||||
void setChannels(int channels);
|
unsigned short lengthInPatterns() const;
|
||||||
void setLengthInPatterns(unsigned short lengthInPatterns);
|
bool stereo() const;
|
||||||
void setInstrumentCount(unsigned short instrumentCount);
|
unsigned short instrumentCount() const;
|
||||||
void setSampleCount (unsigned short sampleCount);
|
unsigned short sampleCount() const;
|
||||||
void setPatternCount(unsigned short patternCount);
|
unsigned short patternCount() const;
|
||||||
void setVersion (unsigned short version);
|
unsigned short version() const;
|
||||||
void setCompatibleVersion(unsigned short compatibleVersion);
|
unsigned short compatibleVersion() const;
|
||||||
void setFlags (unsigned short flags);
|
unsigned short flags() const;
|
||||||
void setSpecial (unsigned short special);
|
unsigned short special() const;
|
||||||
void setGlobalVolume(unsigned char globalVolume);
|
unsigned char globalVolume() const;
|
||||||
void setMixVolume (unsigned char mixVolume);
|
unsigned char mixVolume() const;
|
||||||
void setTempo (unsigned char tempo);
|
unsigned char tempo() const;
|
||||||
void setBpmSpeed (unsigned char bpmSpeed);
|
unsigned char bpmSpeed() const;
|
||||||
void setPanningSeparation(unsigned char panningSeparation);
|
unsigned char panningSeparation() const;
|
||||||
void setPitchWheelDepth (unsigned char pitchWheelDepth);
|
unsigned char pitchWheelDepth() const;
|
||||||
|
|
||||||
private:
|
void setChannels(int channels);
|
||||||
Properties(const Properties&);
|
void setLengthInPatterns(unsigned short lengthInPatterns);
|
||||||
Properties &operator=(const Properties&);
|
void setInstrumentCount(unsigned short instrumentCount);
|
||||||
|
void setSampleCount(unsigned short sampleCount);
|
||||||
|
void setPatternCount(unsigned short patternCount);
|
||||||
|
void setVersion(unsigned short version);
|
||||||
|
void setCompatibleVersion(unsigned short compatibleVersion);
|
||||||
|
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 setPanningSeparation(unsigned char panningSeparation);
|
||||||
|
void setPitchWheelDepth(unsigned char pitchWheelDepth);
|
||||||
|
|
||||||
class PropertiesPrivate;
|
private:
|
||||||
PropertiesPrivate *d;
|
Properties(const Properties &);
|
||||||
};
|
Properties &operator=(const Properties &);
|
||||||
}
|
|
||||||
}
|
class PropertiesPrivate;
|
||||||
}
|
PropertiesPrivate *d;
|
||||||
|
};
|
||||||
|
} // namespace IT
|
||||||
|
} // namespace TagLib
|
||||||
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
77
3rdparty/taglib/mod/modfile.cpp
vendored
77
3rdparty/taglib/mod/modfile.cpp
vendored
@ -33,64 +33,52 @@
|
|||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
using namespace Mod;
|
using namespace Mod;
|
||||||
|
|
||||||
class Mod::File::FilePrivate
|
class Mod::File::FilePrivate {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
explicit FilePrivate(AudioProperties::ReadStyle propertiesStyle)
|
explicit FilePrivate(AudioProperties::ReadStyle propertiesStyle)
|
||||||
: properties(propertiesStyle)
|
: properties(propertiesStyle) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Mod::Tag tag;
|
Mod::Tag tag;
|
||||||
Mod::Properties properties;
|
Mod::Properties properties;
|
||||||
};
|
};
|
||||||
|
|
||||||
Mod::File::File(FileName file, bool readProperties,
|
Mod::File::File(FileName file, bool readProperties,
|
||||||
AudioProperties::ReadStyle propertiesStyle) :
|
AudioProperties::ReadStyle propertiesStyle) : Mod::FileBase(file),
|
||||||
Mod::FileBase(file),
|
d(new FilePrivate(propertiesStyle)) {
|
||||||
d(new FilePrivate(propertiesStyle))
|
if (isOpen())
|
||||||
{
|
|
||||||
if(isOpen())
|
|
||||||
read(readProperties);
|
read(readProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
Mod::File::File(IOStream *stream, bool readProperties,
|
Mod::File::File(IOStream *stream, bool readProperties,
|
||||||
AudioProperties::ReadStyle propertiesStyle) :
|
AudioProperties::ReadStyle propertiesStyle) : Mod::FileBase(stream),
|
||||||
Mod::FileBase(stream),
|
d(new FilePrivate(propertiesStyle)) {
|
||||||
d(new FilePrivate(propertiesStyle))
|
if (isOpen())
|
||||||
{
|
|
||||||
if(isOpen())
|
|
||||||
read(readProperties);
|
read(readProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
Mod::File::~File()
|
Mod::File::~File() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
Mod::Tag *Mod::File::tag() const
|
Mod::Tag *Mod::File::tag() const {
|
||||||
{
|
|
||||||
return &d->tag;
|
return &d->tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
Mod::Properties *Mod::File::audioProperties() const
|
Mod::Properties *Mod::File::audioProperties() const {
|
||||||
{
|
|
||||||
return &d->properties;
|
return &d->properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyMap Mod::File::properties() const
|
PropertyMap Mod::File::properties() const {
|
||||||
{
|
|
||||||
return d->tag.properties();
|
return d->tag.properties();
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyMap Mod::File::setProperties(const PropertyMap &properties)
|
PropertyMap Mod::File::setProperties(const PropertyMap &properties) {
|
||||||
{
|
|
||||||
return d->tag.setProperties(properties);
|
return d->tag.setProperties(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mod::File::save()
|
bool Mod::File::save() {
|
||||||
{
|
if (readOnly()) {
|
||||||
if(readOnly()) {
|
|
||||||
debug("Mod::File::save() - Cannot save to a read only file.");
|
debug("Mod::File::save() - Cannot save to a read only file.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -98,50 +86,49 @@ bool Mod::File::save()
|
|||||||
writeString(d->tag.title(), 20);
|
writeString(d->tag.title(), 20);
|
||||||
StringList lines = d->tag.comment().split("\n");
|
StringList lines = d->tag.comment().split("\n");
|
||||||
unsigned int n = std::min(lines.size(), d->properties.instrumentCount());
|
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);
|
writeString(lines[i], 22);
|
||||||
seek(8, Current);
|
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);
|
writeString(String(), 22);
|
||||||
seek(8, Current);
|
seek(8, Current);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mod::File::read(bool)
|
void Mod::File::read(bool) {
|
||||||
{
|
if (!isOpen())
|
||||||
if(!isOpen())
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
seek(1080);
|
seek(1080);
|
||||||
ByteVector modId = readBlock(4);
|
ByteVector modId = readBlock(4);
|
||||||
READ_ASSERT(modId.size() == 4);
|
READ_ASSERT(modId.size() == 4);
|
||||||
|
|
||||||
int channels = 4;
|
int channels = 4;
|
||||||
unsigned int instruments = 31;
|
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");
|
d->tag.setTrackerName("ProTracker");
|
||||||
channels = 4;
|
channels = 4;
|
||||||
}
|
}
|
||||||
else if(modId.startsWith("FLT") || modId.startsWith("TDZ")) {
|
else if (modId.startsWith("FLT") || modId.startsWith("TDZ")) {
|
||||||
d->tag.setTrackerName("StarTrekker");
|
d->tag.setTrackerName("StarTrekker");
|
||||||
char digit = modId[3];
|
char digit = modId[3];
|
||||||
READ_ASSERT(digit >= '0' && digit <= '9');
|
READ_ASSERT(digit >= '0' && digit <= '9');
|
||||||
channels = digit - '0';
|
channels = digit - '0';
|
||||||
}
|
}
|
||||||
else if(modId.endsWith("CHN")) {
|
else if (modId.endsWith("CHN")) {
|
||||||
d->tag.setTrackerName("StarTrekker");
|
d->tag.setTrackerName("StarTrekker");
|
||||||
char digit = modId[0];
|
char digit = modId[0];
|
||||||
READ_ASSERT(digit >= '0' && digit <= '9');
|
READ_ASSERT(digit >= '0' && digit <= '9');
|
||||||
channels = digit - '0';
|
channels = digit - '0';
|
||||||
}
|
}
|
||||||
else if(modId == "CD81" || modId == "OKTA") {
|
else if (modId == "CD81" || modId == "OKTA") {
|
||||||
d->tag.setTrackerName("Atari Oktalyzer");
|
d->tag.setTrackerName("Atari Oktalyzer");
|
||||||
channels = 8;
|
channels = 8;
|
||||||
}
|
}
|
||||||
else if(modId.endsWith("CH") || modId.endsWith("CN")) {
|
else if (modId.endsWith("CH") || modId.endsWith("CN")) {
|
||||||
d->tag.setTrackerName("TakeTracker");
|
d->tag.setTrackerName("TakeTracker");
|
||||||
char digit = modId[0];
|
char digit = modId[0];
|
||||||
READ_ASSERT(digit >= '0' && digit <= '9');
|
READ_ASSERT(digit >= '0' && digit <= '9');
|
||||||
@ -153,8 +140,8 @@ void Mod::File::read(bool)
|
|||||||
else {
|
else {
|
||||||
// Not sure if this is correct. I'd need a file
|
// Not sure if this is correct. I'd need a file
|
||||||
// created with NoiseTracker to check this.
|
// created with NoiseTracker to check this.
|
||||||
d->tag.setTrackerName("NoiseTracker"); // probably
|
d->tag.setTrackerName("NoiseTracker"); // probably
|
||||||
channels = 4;
|
channels = 4;
|
||||||
instruments = 15;
|
instruments = 15;
|
||||||
}
|
}
|
||||||
d->properties.setChannels(channels);
|
d->properties.setChannels(channels);
|
||||||
@ -164,7 +151,7 @@ void Mod::File::read(bool)
|
|||||||
READ_STRING(d->tag.setTitle, 20);
|
READ_STRING(d->tag.setTitle, 20);
|
||||||
|
|
||||||
StringList comment;
|
StringList comment;
|
||||||
for(unsigned int i = 0; i < instruments; ++ i) {
|
for (unsigned int i = 0; i < instruments; ++i) {
|
||||||
READ_STRING_AS(instrumentName, 22);
|
READ_STRING_AS(instrumentName, 22);
|
||||||
// value in words, * 2 (<< 1) for bytes:
|
// value in words, * 2 (<< 1) for bytes:
|
||||||
READ_U16B_AS(sampleLength);
|
READ_U16B_AS(sampleLength);
|
||||||
@ -172,10 +159,10 @@ void Mod::File::read(bool)
|
|||||||
READ_BYTE_AS(fineTuneByte);
|
READ_BYTE_AS(fineTuneByte);
|
||||||
int fineTune = fineTuneByte & 0xF;
|
int fineTune = fineTuneByte & 0xF;
|
||||||
// > 7 means negative value
|
// > 7 means negative value
|
||||||
if(fineTune > 7) fineTune -= 16;
|
if (fineTune > 7) fineTune -= 16;
|
||||||
|
|
||||||
READ_BYTE_AS(volume);
|
READ_BYTE_AS(volume);
|
||||||
if(volume > 64) volume = 64;
|
if (volume > 64) volume = 64;
|
||||||
// volume in decibels: 20 * log10(volume / 64)
|
// volume in decibels: 20 * log10(volume / 64)
|
||||||
|
|
||||||
// value in words, * 2 (<< 1) for bytes:
|
// value in words, * 2 (<< 1) for bytes:
|
||||||
|
65
3rdparty/taglib/mod/modfile.h
vendored
65
3rdparty/taglib/mod/modfile.h
vendored
@ -36,23 +36,22 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace 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:
|
||||||
public:
|
/*!
|
||||||
/*!
|
|
||||||
* Constructs a Protracker file from \a file.
|
* Constructs a Protracker file from \a file.
|
||||||
*
|
*
|
||||||
* \note In the current implementation, both \a readProperties and
|
* \note In the current implementation, both \a readProperties and
|
||||||
* \a propertiesStyle are ignored. The audio properties are always
|
* \a propertiesStyle are ignored. The audio properties are always
|
||||||
* read.
|
* read.
|
||||||
*/
|
*/
|
||||||
File(FileName file, bool readProperties = true,
|
File(FileName file, bool readProperties = true,
|
||||||
AudioProperties::ReadStyle propertiesStyle =
|
AudioProperties::ReadStyle propertiesStyle =
|
||||||
AudioProperties::Average);
|
AudioProperties::Average);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs a Protracker file from \a stream.
|
* Constructs a Protracker file from \a stream.
|
||||||
*
|
*
|
||||||
* \note In the current implementation, both \a readProperties and
|
* \note In the current implementation, both \a readProperties and
|
||||||
@ -62,55 +61,55 @@ namespace TagLib {
|
|||||||
* \note TagLib will *not* take ownership of the stream, the caller is
|
* \note TagLib will *not* take ownership of the stream, the caller is
|
||||||
* responsible for deleting it after the File object.
|
* responsible for deleting it after the File object.
|
||||||
*/
|
*/
|
||||||
File(IOStream *stream, bool readProperties = true,
|
File(IOStream *stream, bool readProperties = true,
|
||||||
AudioProperties::ReadStyle propertiesStyle =
|
AudioProperties::ReadStyle propertiesStyle =
|
||||||
AudioProperties::Average);
|
AudioProperties::Average);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys this instance of the File.
|
* Destroys this instance of the File.
|
||||||
*/
|
*/
|
||||||
virtual ~File();
|
virtual ~File();
|
||||||
|
|
||||||
Mod::Tag *tag() const;
|
Mod::Tag *tag() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Implements the unified property interface -- export function.
|
* Implements the unified property interface -- export function.
|
||||||
* Forwards to Mod::Tag::properties().
|
* Forwards to Mod::Tag::properties().
|
||||||
*/
|
*/
|
||||||
PropertyMap properties() const;
|
PropertyMap properties() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Implements the unified property interface -- import function.
|
* Implements the unified property interface -- import function.
|
||||||
* Forwards to Mod::Tag::setProperties().
|
* Forwards to Mod::Tag::setProperties().
|
||||||
*/
|
*/
|
||||||
PropertyMap setProperties(const PropertyMap &);
|
PropertyMap setProperties(const PropertyMap &);
|
||||||
/*!
|
/*!
|
||||||
* Returns the Mod::Properties for this file. If no audio properties
|
* Returns the Mod::Properties for this file. If no audio properties
|
||||||
* were read then this will return a null pointer.
|
* were read then this will return a null pointer.
|
||||||
*/
|
*/
|
||||||
Mod::Properties *audioProperties() const;
|
Mod::Properties *audioProperties() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Save the file.
|
* Save the file.
|
||||||
* This is the same as calling save(AllTags);
|
* This is the same as calling save(AllTags);
|
||||||
*
|
*
|
||||||
* \note Saving Protracker tags is not supported.
|
* \note Saving Protracker tags is not supported.
|
||||||
*/
|
*/
|
||||||
bool save();
|
bool save();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
File(const File &);
|
File(const File &);
|
||||||
File &operator=(const File &);
|
File &operator=(const File &);
|
||||||
|
|
||||||
void read(bool readProperties);
|
void read(bool readProperties);
|
||||||
|
|
||||||
class FilePrivate;
|
class FilePrivate;
|
||||||
FilePrivate *d;
|
FilePrivate *d;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace Mod
|
||||||
|
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#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 Strawberry_TagLib::TagLib;
|
||||||
using namespace Mod;
|
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));
|
ByteVector data(s.data(String::Latin1));
|
||||||
data.resize(size, padding);
|
data.resize(size, padding);
|
||||||
writeBlock(data);
|
writeBlock(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mod::FileBase::readString(String &s, unsigned long size)
|
bool Mod::FileBase::readString(String &s, unsigned long size) {
|
||||||
{
|
|
||||||
ByteVector data(readBlock(size));
|
ByteVector data(readBlock(size));
|
||||||
if(data.size() < size) return false;
|
if (data.size() < size) return false;
|
||||||
int index = data.find((char) 0);
|
int index = data.find((char)0);
|
||||||
if(index > -1)
|
if (index > -1) {
|
||||||
{
|
|
||||||
data.resize(index);
|
data.resize(index);
|
||||||
}
|
}
|
||||||
data.replace('\xff', ' ');
|
data.replace('\xff', ' ');
|
||||||
@ -60,66 +55,58 @@ bool Mod::FileBase::readString(String &s, unsigned long size)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mod::FileBase::writeByte(unsigned char _byte)
|
void Mod::FileBase::writeByte(unsigned char _byte) {
|
||||||
{
|
|
||||||
ByteVector data(1, _byte);
|
ByteVector data(1, _byte);
|
||||||
writeBlock(data);
|
writeBlock(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mod::FileBase::writeU16L(unsigned short number)
|
void Mod::FileBase::writeU16L(unsigned short number) {
|
||||||
{
|
|
||||||
writeBlock(ByteVector::fromShort(number, false));
|
writeBlock(ByteVector::fromShort(number, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mod::FileBase::writeU32L(unsigned long number)
|
void Mod::FileBase::writeU32L(unsigned long number) {
|
||||||
{
|
|
||||||
writeBlock(ByteVector::fromUInt(number, false));
|
writeBlock(ByteVector::fromUInt(number, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mod::FileBase::writeU16B(unsigned short number)
|
void Mod::FileBase::writeU16B(unsigned short number) {
|
||||||
{
|
|
||||||
writeBlock(ByteVector::fromShort(number, true));
|
writeBlock(ByteVector::fromShort(number, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mod::FileBase::writeU32B(unsigned long number)
|
void Mod::FileBase::writeU32B(unsigned long number) {
|
||||||
{
|
|
||||||
writeBlock(ByteVector::fromUInt(number, true));
|
writeBlock(ByteVector::fromUInt(number, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mod::FileBase::readByte(unsigned char &_byte)
|
bool Mod::FileBase::readByte(unsigned char &_byte) {
|
||||||
{
|
|
||||||
ByteVector data(readBlock(1));
|
ByteVector data(readBlock(1));
|
||||||
if(data.size() < 1) return false;
|
if (data.size() < 1) return false;
|
||||||
_byte = data[0];
|
_byte = data[0];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mod::FileBase::readU16L(unsigned short &number)
|
bool Mod::FileBase::readU16L(unsigned short &number) {
|
||||||
{
|
|
||||||
ByteVector data(readBlock(2));
|
ByteVector data(readBlock(2));
|
||||||
if(data.size() < 2) return false;
|
if (data.size() < 2) return false;
|
||||||
number = data.toUShort(false);
|
number = data.toUShort(false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mod::FileBase::readU32L(unsigned long &number) {
|
bool Mod::FileBase::readU32L(unsigned long &number) {
|
||||||
ByteVector data(readBlock(4));
|
ByteVector data(readBlock(4));
|
||||||
if(data.size() < 4) return false;
|
if (data.size() < 4) return false;
|
||||||
number = data.toUInt(false);
|
number = data.toUInt(false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mod::FileBase::readU16B(unsigned short &number)
|
bool Mod::FileBase::readU16B(unsigned short &number) {
|
||||||
{
|
|
||||||
ByteVector data(readBlock(2));
|
ByteVector data(readBlock(2));
|
||||||
if(data.size() < 2) return false;
|
if (data.size() < 2) return false;
|
||||||
number = data.toUShort(true);
|
number = data.toUShort(true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mod::FileBase::readU32B(unsigned long &number) {
|
bool Mod::FileBase::readU32B(unsigned long &number) {
|
||||||
ByteVector data(readBlock(4));
|
ByteVector data(readBlock(4));
|
||||||
if(data.size() < 4) return false;
|
if (data.size() < 4) return false;
|
||||||
number = data.toUInt(true);
|
number = data.toUInt(true);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
43
3rdparty/taglib/mod/modfilebase.h
vendored
43
3rdparty/taglib/mod/modfilebase.h
vendored
@ -37,32 +37,31 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace 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:
|
||||||
protected:
|
FileBase(FileName file);
|
||||||
FileBase(FileName file);
|
FileBase(IOStream *stream);
|
||||||
FileBase(IOStream *stream);
|
|
||||||
|
|
||||||
void writeString(const String &s, unsigned long size, char padding = 0);
|
void writeString(const String &s, unsigned long size, char padding = 0);
|
||||||
void writeByte(unsigned char byte);
|
void writeByte(unsigned char byte);
|
||||||
void writeU16L(unsigned short number);
|
void writeU16L(unsigned short number);
|
||||||
void writeU32L(unsigned long number);
|
void writeU32L(unsigned long number);
|
||||||
void writeU16B(unsigned short number);
|
void writeU16B(unsigned short number);
|
||||||
void writeU32B(unsigned long number);
|
void writeU32B(unsigned long number);
|
||||||
|
|
||||||
bool readString(String &s, unsigned long size);
|
bool readString(String &s, unsigned long size);
|
||||||
bool readByte(unsigned char &byte);
|
bool readByte(unsigned char &byte);
|
||||||
bool readU16L(unsigned short &number);
|
bool readU16L(unsigned short &number);
|
||||||
bool readU32L(unsigned long &number);
|
bool readU32L(unsigned long &number);
|
||||||
bool readU16B(unsigned short &number);
|
bool readU16B(unsigned short &number);
|
||||||
bool readU32B(unsigned long &number);
|
bool readU32B(unsigned long &number);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace Mod
|
||||||
|
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
53
3rdparty/taglib/mod/modfileprivate.h
vendored
53
3rdparty/taglib/mod/modfileprivate.h
vendored
@ -24,44 +24,43 @@
|
|||||||
|
|
||||||
// some helper-macros only used internally by (s3m|it|xm)file.cpp
|
// some helper-macros only used internally by (s3m|it|xm)file.cpp
|
||||||
#define READ_ASSERT(cond) \
|
#define READ_ASSERT(cond) \
|
||||||
if(!(cond)) \
|
if (!(cond)) { \
|
||||||
{ \
|
setValid(false); \
|
||||||
setValid(false); \
|
return; \
|
||||||
return; \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define READ(setter,type,read) \
|
#define READ(setter, type, read) \
|
||||||
{ \
|
{ \
|
||||||
type number; \
|
type number; \
|
||||||
READ_ASSERT(read(number)); \
|
READ_ASSERT(read(number)); \
|
||||||
setter(number); \
|
setter(number); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define READ_BYTE(setter) READ(setter,unsigned char,readByte)
|
#define READ_BYTE(setter) READ(setter, unsigned char, readByte)
|
||||||
#define READ_U16L(setter) READ(setter,unsigned short,readU16L)
|
#define READ_U16L(setter) READ(setter, unsigned short, readU16L)
|
||||||
#define READ_U32L(setter) READ(setter,unsigned long,readU32L)
|
#define READ_U32L(setter) READ(setter, unsigned long, readU32L)
|
||||||
#define READ_U16B(setter) READ(setter,unsigned short,readU16B)
|
#define READ_U16B(setter) READ(setter, unsigned short, readU16B)
|
||||||
#define READ_U32B(setter) READ(setter,unsigned long,readU32B)
|
#define READ_U32B(setter) READ(setter, unsigned long, readU32B)
|
||||||
|
|
||||||
#define READ_STRING(setter,size) \
|
#define READ_STRING(setter, size) \
|
||||||
{ \
|
{ \
|
||||||
String s; \
|
String s; \
|
||||||
READ_ASSERT(readString(s, size)); \
|
READ_ASSERT(readString(s, size)); \
|
||||||
setter(s); \
|
setter(s); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define READ_AS(type,name,read) \
|
#define READ_AS(type, name, read) \
|
||||||
type name = 0; \
|
type name = 0; \
|
||||||
READ_ASSERT(read(name));
|
READ_ASSERT(read(name));
|
||||||
|
|
||||||
#define READ_BYTE_AS(name) READ_AS(unsigned char,name,readByte)
|
#define READ_BYTE_AS(name) READ_AS(unsigned char, name, readByte)
|
||||||
#define READ_U16L_AS(name) READ_AS(unsigned short,name,readU16L)
|
#define READ_U16L_AS(name) READ_AS(unsigned short, name, readU16L)
|
||||||
#define READ_U32L_AS(name) READ_AS(unsigned long,name,readU32L)
|
#define READ_U32L_AS(name) READ_AS(unsigned long, name, readU32L)
|
||||||
#define READ_U16B_AS(name) READ_AS(unsigned short,name,readU16B)
|
#define READ_U16B_AS(name) READ_AS(unsigned short, name, readU16B)
|
||||||
#define READ_U32B_AS(name) READ_AS(unsigned long,name,readU32B)
|
#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; \
|
String name; \
|
||||||
READ_ASSERT(readString(name, size));
|
READ_ASSERT(readString(name, size));
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
59
3rdparty/taglib/mod/modproperties.cpp
vendored
59
3rdparty/taglib/mod/modproperties.cpp
vendored
@ -29,83 +29,66 @@
|
|||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
using namespace Mod;
|
using namespace Mod;
|
||||||
|
|
||||||
class Mod::Properties::PropertiesPrivate
|
class Mod::Properties::PropertiesPrivate {
|
||||||
{
|
public:
|
||||||
public:
|
PropertiesPrivate() : channels(0),
|
||||||
PropertiesPrivate() :
|
instrumentCount(0),
|
||||||
channels(0),
|
lengthInPatterns(0) {
|
||||||
instrumentCount(0),
|
|
||||||
lengthInPatterns(0)
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int channels;
|
int channels;
|
||||||
unsigned int instrumentCount;
|
unsigned int instrumentCount;
|
||||||
unsigned char lengthInPatterns;
|
unsigned char lengthInPatterns;
|
||||||
};
|
};
|
||||||
|
|
||||||
Mod::Properties::Properties(AudioProperties::ReadStyle propertiesStyle) :
|
Mod::Properties::Properties(AudioProperties::ReadStyle propertiesStyle) : AudioProperties(propertiesStyle),
|
||||||
AudioProperties(propertiesStyle),
|
d(new PropertiesPrivate()) {
|
||||||
d(new PropertiesPrivate())
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Mod::Properties::~Properties()
|
Mod::Properties::~Properties() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Mod::Properties::length() const
|
int Mod::Properties::length() const {
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Mod::Properties::lengthInSeconds() const
|
int Mod::Properties::lengthInSeconds() const {
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Mod::Properties::lengthInMilliseconds() const
|
int Mod::Properties::lengthInMilliseconds() const {
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Mod::Properties::bitrate() const
|
int Mod::Properties::bitrate() const {
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Mod::Properties::sampleRate() const
|
int Mod::Properties::sampleRate() const {
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Mod::Properties::channels() const
|
int Mod::Properties::channels() const {
|
||||||
{
|
|
||||||
return d->channels;
|
return d->channels;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int Mod::Properties::instrumentCount() const
|
unsigned int Mod::Properties::instrumentCount() const {
|
||||||
{
|
|
||||||
return d->instrumentCount;
|
return d->instrumentCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char Mod::Properties::lengthInPatterns() const
|
unsigned char Mod::Properties::lengthInPatterns() const {
|
||||||
{
|
|
||||||
return d->lengthInPatterns;
|
return d->lengthInPatterns;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mod::Properties::setChannels(int channels)
|
void Mod::Properties::setChannels(int channels) {
|
||||||
{
|
|
||||||
d->channels = channels;
|
d->channels = channels;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mod::Properties::setInstrumentCount(unsigned int instrumentCount)
|
void Mod::Properties::setInstrumentCount(unsigned int instrumentCount) {
|
||||||
{
|
|
||||||
d->instrumentCount = instrumentCount;
|
d->instrumentCount = instrumentCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mod::Properties::setLengthInPatterns(unsigned char lengthInPatterns)
|
void Mod::Properties::setLengthInPatterns(unsigned char lengthInPatterns) {
|
||||||
{
|
|
||||||
d->lengthInPatterns = lengthInPatterns;
|
d->lengthInPatterns = lengthInPatterns;
|
||||||
}
|
}
|
||||||
|
53
3rdparty/taglib/mod/modproperties.h
vendored
53
3rdparty/taglib/mod/modproperties.h
vendored
@ -32,42 +32,41 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
namespace Mod {
|
namespace Mod {
|
||||||
|
|
||||||
class TAGLIB_EXPORT Properties : public AudioProperties
|
class TAGLIB_EXPORT Properties : public AudioProperties {
|
||||||
{
|
public:
|
||||||
public:
|
Properties(AudioProperties::ReadStyle propertiesStyle);
|
||||||
Properties(AudioProperties::ReadStyle propertiesStyle);
|
virtual ~Properties();
|
||||||
virtual ~Properties();
|
|
||||||
|
|
||||||
int length() const;
|
int length() const;
|
||||||
int lengthInSeconds() const;
|
int lengthInSeconds() const;
|
||||||
int lengthInMilliseconds() const;
|
int lengthInMilliseconds() const;
|
||||||
int bitrate() const;
|
int bitrate() const;
|
||||||
int sampleRate() const;
|
int sampleRate() const;
|
||||||
int channels() const;
|
int channels() const;
|
||||||
|
|
||||||
unsigned int instrumentCount() const;
|
unsigned int instrumentCount() const;
|
||||||
unsigned char lengthInPatterns() const;
|
unsigned char lengthInPatterns() const;
|
||||||
|
|
||||||
void setChannels(int channels);
|
void setChannels(int channels);
|
||||||
|
|
||||||
void setInstrumentCount(unsigned int sampleCount);
|
void setInstrumentCount(unsigned int sampleCount);
|
||||||
void setLengthInPatterns(unsigned char lengthInPatterns);
|
void setLengthInPatterns(unsigned char lengthInPatterns);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class File;
|
friend class File;
|
||||||
|
|
||||||
Properties(const Properties&);
|
Properties(const Properties &);
|
||||||
Properties &operator=(const Properties&);
|
Properties &operator=(const Properties &);
|
||||||
|
|
||||||
class PropertiesPrivate;
|
class PropertiesPrivate;
|
||||||
PropertiesPrivate *d;
|
PropertiesPrivate *d;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace Mod
|
||||||
|
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#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 Strawberry_TagLib::TagLib;
|
||||||
using namespace Mod;
|
using namespace Mod;
|
||||||
|
|
||||||
class Mod::Tag::TagPrivate
|
class Mod::Tag::TagPrivate {
|
||||||
{
|
public:
|
||||||
public:
|
TagPrivate() {
|
||||||
TagPrivate()
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String title;
|
String title;
|
||||||
@ -43,132 +41,114 @@ public:
|
|||||||
String trackerName;
|
String trackerName;
|
||||||
};
|
};
|
||||||
|
|
||||||
Mod::Tag::Tag() :
|
Mod::Tag::Tag() : Strawberry_TagLib::TagLib::Tag(),
|
||||||
Strawberry_TagLib::TagLib::Tag(),
|
d(new TagPrivate()) {
|
||||||
d(new TagPrivate())
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Mod::Tag::~Tag()
|
Mod::Tag::~Tag() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
String Mod::Tag::title() const
|
String Mod::Tag::title() const {
|
||||||
{
|
|
||||||
return d->title;
|
return d->title;
|
||||||
}
|
}
|
||||||
|
|
||||||
String Mod::Tag::artist() const
|
String Mod::Tag::artist() const {
|
||||||
{
|
|
||||||
return String();
|
return String();
|
||||||
}
|
}
|
||||||
|
|
||||||
String Mod::Tag::album() const
|
String Mod::Tag::album() const {
|
||||||
{
|
|
||||||
return String();
|
return String();
|
||||||
}
|
}
|
||||||
|
|
||||||
String Mod::Tag::comment() const
|
String Mod::Tag::comment() const {
|
||||||
{
|
|
||||||
return d->comment;
|
return d->comment;
|
||||||
}
|
}
|
||||||
|
|
||||||
String Mod::Tag::genre() const
|
String Mod::Tag::genre() const {
|
||||||
{
|
|
||||||
return String();
|
return String();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int Mod::Tag::year() const
|
unsigned int Mod::Tag::year() const {
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int Mod::Tag::track() const
|
unsigned int Mod::Tag::track() const {
|
||||||
{
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
String Mod::Tag::trackerName() const
|
String Mod::Tag::trackerName() const {
|
||||||
{
|
|
||||||
return d->trackerName;
|
return d->trackerName;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mod::Tag::setTitle(const String &title)
|
void Mod::Tag::setTitle(const String &title) {
|
||||||
{
|
|
||||||
d->title = 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;
|
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;
|
d->trackerName = trackerName;
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyMap Mod::Tag::properties() const
|
PropertyMap Mod::Tag::properties() const {
|
||||||
{
|
|
||||||
PropertyMap properties;
|
PropertyMap properties;
|
||||||
properties["TITLE"] = d->title;
|
properties["TITLE"] = d->title;
|
||||||
properties["COMMENT"] = d->comment;
|
properties["COMMENT"] = d->comment;
|
||||||
if(!(d->trackerName.isEmpty()))
|
if (!(d->trackerName.isEmpty()))
|
||||||
properties["TRACKERNAME"] = d->trackerName;
|
properties["TRACKERNAME"] = d->trackerName;
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyMap Mod::Tag::setProperties(const PropertyMap &origProps)
|
PropertyMap Mod::Tag::setProperties(const PropertyMap &origProps) {
|
||||||
{
|
|
||||||
PropertyMap properties(origProps);
|
PropertyMap properties(origProps);
|
||||||
properties.removeEmpty();
|
properties.removeEmpty();
|
||||||
StringList oneValueSet;
|
StringList oneValueSet;
|
||||||
if(properties.contains("TITLE")) {
|
if (properties.contains("TITLE")) {
|
||||||
d->title = properties["TITLE"].front();
|
d->title = properties["TITLE"].front();
|
||||||
oneValueSet.append("TITLE");
|
oneValueSet.append("TITLE");
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
d->title.clear();
|
d->title.clear();
|
||||||
|
|
||||||
if(properties.contains("COMMENT")) {
|
if (properties.contains("COMMENT")) {
|
||||||
d->comment = properties["COMMENT"].front();
|
d->comment = properties["COMMENT"].front();
|
||||||
oneValueSet.append("COMMENT");
|
oneValueSet.append("COMMENT");
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
d->comment.clear();
|
d->comment.clear();
|
||||||
|
|
||||||
if(properties.contains("TRACKERNAME")) {
|
if (properties.contains("TRACKERNAME")) {
|
||||||
d->trackerName = properties["TRACKERNAME"].front();
|
d->trackerName = properties["TRACKERNAME"].front();
|
||||||
oneValueSet.append("TRACKERNAME");
|
oneValueSet.append("TRACKERNAME");
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
d->trackerName.clear();
|
d->trackerName.clear();
|
||||||
|
|
||||||
// for each tag that has been set above, remove the first entry in the corresponding
|
// 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.
|
// value list. The others will be returned as unsupported by this format.
|
||||||
for(StringList::ConstIterator it = oneValueSet.begin(); it != oneValueSet.end(); ++it) {
|
for (StringList::ConstIterator it = oneValueSet.begin(); it != oneValueSet.end(); ++it) {
|
||||||
if(properties[*it].size() == 1)
|
if (properties[*it].size() == 1)
|
||||||
properties.erase(*it);
|
properties.erase(*it);
|
||||||
else
|
else
|
||||||
properties[*it].erase( properties[*it].begin() );
|
properties[*it].erase(properties[*it].begin());
|
||||||
}
|
}
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
103
3rdparty/taglib/mod/modtag.h
vendored
103
3rdparty/taglib/mod/modtag.h
vendored
@ -31,9 +31,9 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
namespace Mod {
|
namespace Mod {
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Tags for module files (Mod, S3M, IT, XM).
|
* Tags for module files (Mod, S3M, IT, XM).
|
||||||
*
|
*
|
||||||
* Note that only the \a title is supported as such by most
|
* Note that only the \a title is supported as such by most
|
||||||
@ -45,60 +45,59 @@ namespace TagLib {
|
|||||||
* but it is common practice to abuse instrument/sample/pattern
|
* but it is common practice to abuse instrument/sample/pattern
|
||||||
* names as multiline comments. TagLib does so as well.
|
* 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:
|
||||||
public:
|
Tag();
|
||||||
Tag();
|
virtual ~Tag();
|
||||||
virtual ~Tag();
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the track name; if no track name is present in the tag
|
* Returns the track name; if no track name is present in the tag
|
||||||
* String::null will be returned.
|
* String::null will be returned.
|
||||||
*/
|
*/
|
||||||
virtual String title() const;
|
virtual String title() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Not supported by module files. Therefore always returns String::null.
|
* Not supported by module files. Therefore always returns String::null.
|
||||||
*/
|
*/
|
||||||
virtual String artist() const;
|
virtual String artist() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Not supported by module files. Therefore always returns String::null.
|
* Not supported by module files. Therefore always returns String::null.
|
||||||
*/
|
*/
|
||||||
virtual String album() const;
|
virtual String album() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the track comment derived from the instrument/sample/pattern
|
* Returns the track comment derived from the instrument/sample/pattern
|
||||||
* names; if no comment is present in the tag String::null will be
|
* names; if no comment is present in the tag String::null will be
|
||||||
* returned.
|
* returned.
|
||||||
*/
|
*/
|
||||||
virtual String comment() const;
|
virtual String comment() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Not supported by module files. Therefore always returns String::null.
|
* Not supported by module files. Therefore always returns String::null.
|
||||||
*/
|
*/
|
||||||
virtual String genre() const;
|
virtual String genre() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Not supported by module files. Therefore always returns 0.
|
* Not supported by module files. Therefore always returns 0.
|
||||||
*/
|
*/
|
||||||
virtual unsigned int year() const;
|
virtual unsigned int year() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Not supported by module files. Therefore always returns 0.
|
* Not supported by module files. Therefore always returns 0.
|
||||||
*/
|
*/
|
||||||
virtual unsigned int track() const;
|
virtual unsigned int track() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the name of the tracker used to create/edit the module file.
|
* Returns the name of the tracker used to create/edit the module file.
|
||||||
* Only XM files store this tag to the file as such, for other formats
|
* Only XM files store this tag to the file as such, for other formats
|
||||||
* (Mod, S3M, IT) this is derived from the file type or the flavour of
|
* (Mod, S3M, IT) this is derived from the file type or the flavour of
|
||||||
* the file type. Therefore only XM files might have an empty
|
* the file type. Therefore only XM files might have an empty
|
||||||
* (String::null) tracker name.
|
* (String::null) tracker name.
|
||||||
*/
|
*/
|
||||||
String trackerName() const;
|
String trackerName() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the title to \a title. If \a title is String::null then this
|
* Sets the title to \a title. If \a title is String::null then this
|
||||||
* value will be cleared.
|
* value will be cleared.
|
||||||
*
|
*
|
||||||
@ -106,19 +105,19 @@ namespace TagLib {
|
|||||||
* Mod 20 characters, S3M 27 characters, IT 25 characters and XM 20
|
* Mod 20 characters, S3M 27 characters, IT 25 characters and XM 20
|
||||||
* characters.
|
* characters.
|
||||||
*/
|
*/
|
||||||
virtual void setTitle(const String &title);
|
virtual void setTitle(const String &title);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Not supported by module files and therefore ignored.
|
* Not supported by module files and therefore ignored.
|
||||||
*/
|
*/
|
||||||
virtual void setArtist(const String &artist);
|
virtual void setArtist(const String &artist);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Not supported by module files and therefore ignored.
|
* Not supported by module files and therefore ignored.
|
||||||
*/
|
*/
|
||||||
virtual void setAlbum(const String &album);
|
virtual void setAlbum(const String &album);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the comment to \a comment. If \a comment is String::null then
|
* Sets the comment to \a comment. If \a comment is String::null then
|
||||||
* this value will be cleared.
|
* this value will be cleared.
|
||||||
*
|
*
|
||||||
@ -135,24 +134,24 @@ namespace TagLib {
|
|||||||
* Mod 22 characters, S3M 27 characters, IT 25 characters and XM 22
|
* Mod 22 characters, S3M 27 characters, IT 25 characters and XM 22
|
||||||
* characters.
|
* characters.
|
||||||
*/
|
*/
|
||||||
virtual void setComment(const String &comment);
|
virtual void setComment(const String &comment);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Not supported by module files and therefore ignored.
|
* Not supported by module files and therefore ignored.
|
||||||
*/
|
*/
|
||||||
virtual void setGenre(const String &genre);
|
virtual void setGenre(const String &genre);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Not supported by module files and therefore ignored.
|
* Not supported by module files and therefore ignored.
|
||||||
*/
|
*/
|
||||||
virtual void setYear(unsigned int year);
|
virtual void setYear(unsigned int year);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Not supported by module files and therefore ignored.
|
* Not supported by module files and therefore ignored.
|
||||||
*/
|
*/
|
||||||
virtual void setTrack(unsigned int track);
|
virtual void setTrack(unsigned int track);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the tracker name to \a trackerName. If \a trackerName is
|
* Sets the tracker name to \a trackerName. If \a trackerName is
|
||||||
* String::null then this value will be cleared.
|
* String::null then this value will be cleared.
|
||||||
*
|
*
|
||||||
@ -162,15 +161,15 @@ namespace TagLib {
|
|||||||
* The length of this tag is limited to 20 characters (1 character
|
* The length of this tag is limited to 20 characters (1 character
|
||||||
* = 1 byte).
|
* = 1 byte).
|
||||||
*/
|
*/
|
||||||
void setTrackerName(const String &trackerName);
|
void setTrackerName(const String &trackerName);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Implements the unified property interface -- export function.
|
* Implements the unified property interface -- export function.
|
||||||
* Since the module tag is very limited, the exported map is as well.
|
* Since the module tag is very limited, the exported map is as well.
|
||||||
*/
|
*/
|
||||||
PropertyMap properties() const;
|
PropertyMap properties() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Implements the unified property interface -- import function.
|
* Implements the unified property interface -- import function.
|
||||||
* Because of the limitations of the module file tag, any tags besides
|
* Because of the limitations of the module file tag, any tags besides
|
||||||
* COMMENT, TITLE and, if it is an XM file, TRACKERNAME, will be
|
* COMMENT, TITLE and, if it is an XM file, TRACKERNAME, will be
|
||||||
@ -178,19 +177,19 @@ namespace TagLib {
|
|||||||
* all but the first will be contained in the returned map of unsupported
|
* all but the first will be contained in the returned map of unsupported
|
||||||
* properties.
|
* properties.
|
||||||
*/
|
*/
|
||||||
PropertyMap setProperties(const PropertyMap &);
|
PropertyMap setProperties(const PropertyMap &);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Tag(const Tag &);
|
Tag(const Tag &);
|
||||||
Tag &operator=(const Tag &);
|
Tag &operator=(const Tag &);
|
||||||
|
|
||||||
class TagPrivate;
|
class TagPrivate;
|
||||||
TagPrivate *d;
|
TagPrivate *d;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace Mod
|
||||||
|
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
86
3rdparty/taglib/mp4/mp4atom.cpp
vendored
86
3rdparty/taglib/mp4/mp4atom.cpp
vendored
@ -32,18 +32,17 @@
|
|||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
const char *MP4::Atom::containers[11] = {
|
const char *MP4::Atom::containers[11] = {
|
||||||
"moov", "udta", "mdia", "meta", "ilst",
|
"moov", "udta", "mdia", "meta", "ilst",
|
||||||
"stbl", "minf", "moof", "traf", "trak",
|
"stbl", "minf", "moof", "traf", "trak",
|
||||||
"stsd"
|
"stsd"
|
||||||
};
|
};
|
||||||
|
|
||||||
MP4::Atom::Atom(File *file)
|
MP4::Atom::Atom(File *file) {
|
||||||
{
|
|
||||||
children.setAutoDelete(true);
|
children.setAutoDelete(true);
|
||||||
|
|
||||||
offset = file->tell();
|
offset = file->tell();
|
||||||
ByteVector header = file->readBlock(8);
|
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
|
// The atom header must be 8 bytes long, otherwise there is either
|
||||||
// trailing garbage or the file is truncated
|
// trailing garbage or the file is truncated
|
||||||
debug("MP4: Couldn't read 8 bytes of data for atom header");
|
debug("MP4: Couldn't read 8 bytes of data for atom header");
|
||||||
@ -54,14 +53,14 @@ MP4::Atom::Atom(File *file)
|
|||||||
|
|
||||||
length = header.toUInt();
|
length = header.toUInt();
|
||||||
|
|
||||||
if(length == 0) {
|
if (length == 0) {
|
||||||
// The last atom which extends to the end of the file.
|
// The last atom which extends to the end of the file.
|
||||||
length = file->length() - offset;
|
length = file->length() - offset;
|
||||||
}
|
}
|
||||||
else if(length == 1) {
|
else if (length == 1) {
|
||||||
// The atom has a 64-bit length.
|
// The atom has a 64-bit length.
|
||||||
const long long longLength = file->readBlock(8).toLongLong();
|
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.
|
// The actual length fits in long. That's always the case if long is 64-bit.
|
||||||
length = static_cast<long>(longLength);
|
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");
|
debug("MP4: Invalid atom size");
|
||||||
length = 0;
|
length = 0;
|
||||||
file->seek(0, File::End);
|
file->seek(0, File::End);
|
||||||
@ -82,18 +81,18 @@ MP4::Atom::Atom(File *file)
|
|||||||
|
|
||||||
name = header.mid(4, 4);
|
name = header.mid(4, 4);
|
||||||
|
|
||||||
for(int i = 0; i < numContainers; i++) {
|
for (int i = 0; i < numContainers; i++) {
|
||||||
if(name == containers[i]) {
|
if (name == containers[i]) {
|
||||||
if(name == "meta") {
|
if (name == "meta") {
|
||||||
file->seek(4, File::Current);
|
file->seek(4, File::Current);
|
||||||
}
|
}
|
||||||
else if(name == "stsd") {
|
else if (name == "stsd") {
|
||||||
file->seek(8, File::Current);
|
file->seek(8, File::Current);
|
||||||
}
|
}
|
||||||
while(file->tell() < offset + length) {
|
while (file->tell() < offset + length) {
|
||||||
MP4::Atom *child = new MP4::Atom(file);
|
MP4::Atom *child = new MP4::Atom(file);
|
||||||
children.append(child);
|
children.append(child);
|
||||||
if(child->length == 0)
|
if (child->length == 0)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -103,18 +102,16 @@ MP4::Atom::Atom(File *file)
|
|||||||
file->seek(offset + length);
|
file->seek(offset + length);
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::Atom::~Atom()
|
MP4::Atom::~Atom() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::Atom *
|
MP4::Atom *
|
||||||
MP4::Atom::find(const char *name1, const char *name2, const char *name3, const char *name4)
|
MP4::Atom::find(const char *name1, const char *name2, const char *name3, const char *name4) {
|
||||||
{
|
if (name1 == 0) {
|
||||||
if(name1 == 0) {
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
for(AtomList::ConstIterator it = children.begin(); it != children.end(); ++it) {
|
for (AtomList::ConstIterator it = children.begin(); it != children.end(); ++it) {
|
||||||
if((*it)->name == name1) {
|
if ((*it)->name == name1) {
|
||||||
return (*it)->find(name2, name3, name4);
|
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::AtomList
|
||||||
MP4::Atom::findall(const char *_name, bool recursive)
|
MP4::Atom::findall(const char *_name, bool recursive) {
|
||||||
{
|
|
||||||
MP4::AtomList result;
|
MP4::AtomList result;
|
||||||
for(AtomList::ConstIterator it = children.begin(); it != children.end(); ++it) {
|
for (AtomList::ConstIterator it = children.begin(); it != children.end(); ++it) {
|
||||||
if((*it)->name == _name) {
|
if ((*it)->name == _name) {
|
||||||
result.append(*it);
|
result.append(*it);
|
||||||
}
|
}
|
||||||
if(recursive) {
|
if (recursive) {
|
||||||
result.append((*it)->findall(_name, recursive));
|
result.append((*it)->findall(_name, recursive));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool MP4::Atom::path(MP4::AtomList &path, const char *name1, const char *name2, const char *name3) {
|
||||||
MP4::Atom::path(MP4::AtomList &path, const char *name1, const char *name2, const char *name3)
|
|
||||||
{
|
|
||||||
path.append(this);
|
path.append(this);
|
||||||
if(name1 == 0) {
|
if (name1 == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
for(AtomList::ConstIterator it = children.begin(); it != children.end(); ++it) {
|
for (AtomList::ConstIterator it = children.begin(); it != children.end(); ++it) {
|
||||||
if((*it)->name == name1) {
|
if ((*it)->name == name1) {
|
||||||
return (*it)->path(path, name2, name3);
|
return (*it)->path(path, name2, name3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::Atoms::Atoms(File *file)
|
MP4::Atoms::Atoms(File *file) {
|
||||||
{
|
|
||||||
atoms.setAutoDelete(true);
|
atoms.setAutoDelete(true);
|
||||||
|
|
||||||
file->seek(0, File::End);
|
file->seek(0, File::End);
|
||||||
long end = file->tell();
|
long end = file->tell();
|
||||||
file->seek(0);
|
file->seek(0);
|
||||||
while(file->tell() + 8 <= end) {
|
while (file->tell() + 8 <= end) {
|
||||||
MP4::Atom *atom = new MP4::Atom(file);
|
MP4::Atom *atom = new MP4::Atom(file);
|
||||||
atoms.append(atom);
|
atoms.append(atom);
|
||||||
if (atom->length == 0)
|
if (atom->length == 0)
|
||||||
@ -166,15 +159,13 @@ MP4::Atoms::Atoms(File *file)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::Atoms::~Atoms()
|
MP4::Atoms::~Atoms() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::Atom *
|
MP4::Atom *
|
||||||
MP4::Atoms::find(const char *name1, const char *name2, const char *name3, const char *name4)
|
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) {
|
||||||
for(AtomList::ConstIterator it = atoms.begin(); it != atoms.end(); ++it) {
|
if ((*it)->name == name1) {
|
||||||
if((*it)->name == name1) {
|
|
||||||
return (*it)->find(name2, name3, name4);
|
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::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;
|
MP4::AtomList path;
|
||||||
for(AtomList::ConstIterator it = atoms.begin(); it != atoms.end(); ++it) {
|
for (AtomList::ConstIterator it = atoms.begin(); it != atoms.end(); ++it) {
|
||||||
if((*it)->name == name1) {
|
if ((*it)->name == name1) {
|
||||||
if(!(*it)->path(path, name2, name3, name4)) {
|
if (!(*it)->path(path, name2, name3, name4)) {
|
||||||
path.clear();
|
path.clear();
|
||||||
}
|
}
|
||||||
return path;
|
return path;
|
||||||
|
136
3rdparty/taglib/mp4/mp4atom.h
vendored
136
3rdparty/taglib/mp4/mp4atom.h
vendored
@ -27,87 +27,85 @@
|
|||||||
|
|
||||||
#ifndef DO_NOT_DOCUMENT
|
#ifndef DO_NOT_DOCUMENT
|
||||||
|
|
||||||
#ifndef TAGLIB_MP4ATOM_H
|
# ifndef TAGLIB_MP4ATOM_H
|
||||||
#define TAGLIB_MP4ATOM_H
|
# define TAGLIB_MP4ATOM_H
|
||||||
|
|
||||||
#include "tfile.h"
|
# include "tfile.h"
|
||||||
#include "tlist.h"
|
# include "tlist.h"
|
||||||
|
|
||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
namespace MP4 {
|
namespace MP4 {
|
||||||
|
|
||||||
class Atom;
|
class Atom;
|
||||||
typedef Strawberry_TagLib::TagLib::List<Atom *> AtomList;
|
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
|
||||||
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
|
||||||
TypeUTF8 = 1, // without any count or null terminator
|
TypeUTF16 = 2, // also known as UTF-16BE
|
||||||
TypeUTF16 = 2, // also known as UTF-16BE
|
TypeSJIS = 3, // deprecated unless it is needed for special Japanese characters
|
||||||
TypeSJIS = 3, // deprecated unless it is needed for special Japanese characters
|
TypeHTML = 6, // the HTML file header specifies which HTML version
|
||||||
TypeHTML = 6, // the HTML file header specifies which HTML version
|
TypeXML = 7, // the XML header must identify the DTD or schemas
|
||||||
TypeXML = 7, // the XML header must identify the DTD or schemas
|
TypeUUID = 8, // also known as GUID; stored as 16 bytes in binary (valid as an ID)
|
||||||
TypeUUID = 8, // also known as GUID; stored as 16 bytes in binary (valid as an ID)
|
TypeISRC = 9, // stored as UTF-8 text (valid as an ID)
|
||||||
TypeISRC = 9, // stored as UTF-8 text (valid as an ID)
|
TypeMI3P = 10, // stored as UTF-8 text (valid as an ID)
|
||||||
TypeMI3P = 10, // stored as UTF-8 text (valid as an ID)
|
TypeGIF = 12, // (deprecated) a GIF image
|
||||||
TypeGIF = 12, // (deprecated) a GIF image
|
TypeJPEG = 13, // a JPEG image
|
||||||
TypeJPEG = 13, // a JPEG image
|
TypePNG = 14, // a PNG image
|
||||||
TypePNG = 14, // a PNG image
|
TypeURL = 15, // absolute, in UTF-8 characters
|
||||||
TypeURL = 15, // absolute, in UTF-8 characters
|
TypeDuration = 16, // in milliseconds, 32-bit integer
|
||||||
TypeDuration = 16, // in milliseconds, 32-bit integer
|
TypeDateTime = 17, // in UTC, counting seconds since midnight, January 1, 1904; 32 or 64-bits
|
||||||
TypeDateTime = 17, // in UTC, counting seconds since midnight, January 1, 1904; 32 or 64-bits
|
TypeGenred = 18, // a list of enumerated values
|
||||||
TypeGenred = 18, // a list of enumerated values
|
TypeInteger = 21, // a signed big-endian integer with length one of { 1,2,3,4,8 } bytes
|
||||||
TypeInteger = 21, // a signed big-endian integer with length one of { 1,2,3,4,8 } bytes
|
TypeRIAAPA = 24, // RIAA parental advisory; { -1=no, 1=yes, 0=unspecified }, 8-bit integer
|
||||||
TypeRIAAPA = 24, // RIAA parental advisory; { -1=no, 1=yes, 0=unspecified }, 8-bit integer
|
TypeUPC = 25, // Universal Product Code, in text UTF-8 format (valid as an ID)
|
||||||
TypeUPC = 25, // Universal Product Code, in text UTF-8 format (valid as an ID)
|
TypeBMP = 27, // Windows bitmap image
|
||||||
TypeBMP = 27, // Windows bitmap image
|
TypeUndefined = 255 // undefined
|
||||||
TypeUndefined = 255 // undefined
|
};
|
||||||
};
|
|
||||||
|
|
||||||
struct AtomData {
|
struct AtomData {
|
||||||
AtomData(AtomDataType _type, ByteVector _data) : type(_type), locale(0), data(_data) {}
|
AtomData(AtomDataType _type, ByteVector _data) : type(_type), locale(0), data(_data) {}
|
||||||
AtomDataType type;
|
AtomDataType type;
|
||||||
int locale;
|
int locale;
|
||||||
ByteVector data;
|
ByteVector data;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef Strawberry_TagLib::TagLib::List<AtomData> AtomDataList;
|
typedef Strawberry_TagLib::TagLib::List<AtomData> AtomDataList;
|
||||||
|
|
||||||
class Atom
|
class Atom {
|
||||||
{
|
public:
|
||||||
public:
|
Atom(File *file);
|
||||||
Atom(File *file);
|
~Atom();
|
||||||
~Atom();
|
Atom *find(const char *name1, const char *name2 = 0, const char *name3 = 0, const char *name4 = 0);
|
||||||
Atom *find(const char *name1, const char *name2 = 0, const char *name3 = 0, const char *name4 = 0);
|
bool path(AtomList &path, const char *name1, const char *name2 = 0, const char *name3 = 0);
|
||||||
bool path(AtomList &path, const char *name1, const char *name2 = 0, const char *name3 = 0);
|
AtomList findall(const char *name, bool recursive = false);
|
||||||
AtomList findall(const char *name, bool recursive = false);
|
long offset;
|
||||||
long offset;
|
long length;
|
||||||
long length;
|
Strawberry_TagLib::TagLib::ByteVector name;
|
||||||
Strawberry_TagLib::TagLib::ByteVector name;
|
AtomList children;
|
||||||
AtomList children;
|
|
||||||
private:
|
|
||||||
static const int numContainers = 11;
|
|
||||||
static const char *containers[11];
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Root-level atoms
|
private:
|
||||||
class Atoms
|
static const int numContainers = 11;
|
||||||
{
|
static const char *containers[11];
|
||||||
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;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
//! 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
|
||||||
}
|
|
||||||
|
} // namespace TagLib
|
||||||
#endif
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
|
# endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
36
3rdparty/taglib/mp4/mp4coverart.cpp
vendored
36
3rdparty/taglib/mp4/mp4coverart.cpp
vendored
@ -30,12 +30,10 @@
|
|||||||
|
|
||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
class MP4::CoverArt::CoverArtPrivate : public RefCounter
|
class MP4::CoverArt::CoverArtPrivate : public RefCounter {
|
||||||
{
|
public:
|
||||||
public:
|
CoverArtPrivate() : RefCounter(),
|
||||||
CoverArtPrivate() :
|
format(MP4::CoverArt::JPEG) {}
|
||||||
RefCounter(),
|
|
||||||
format(MP4::CoverArt::JPEG) {}
|
|
||||||
|
|
||||||
Format format;
|
Format format;
|
||||||
ByteVector data;
|
ByteVector data;
|
||||||
@ -45,49 +43,39 @@ public:
|
|||||||
// public members
|
// public members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
MP4::CoverArt::CoverArt(Format format, const ByteVector &data) :
|
MP4::CoverArt::CoverArt(Format format, const ByteVector &data) : d(new CoverArtPrivate()) {
|
||||||
d(new CoverArtPrivate())
|
|
||||||
{
|
|
||||||
d->format = format;
|
d->format = format;
|
||||||
d->data = data;
|
d->data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::CoverArt::CoverArt(const CoverArt &item) :
|
MP4::CoverArt::CoverArt(const CoverArt &item) : d(item.d) {
|
||||||
d(item.d)
|
|
||||||
{
|
|
||||||
d->ref();
|
d->ref();
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::CoverArt &
|
MP4::CoverArt &
|
||||||
MP4::CoverArt::operator=(const CoverArt &item)
|
MP4::CoverArt::operator=(const CoverArt &item) {
|
||||||
{
|
|
||||||
CoverArt(item).swap(*this);
|
CoverArt(item).swap(*this);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void MP4::CoverArt::swap(CoverArt &item) {
|
||||||
MP4::CoverArt::swap(CoverArt &item)
|
|
||||||
{
|
|
||||||
using std::swap;
|
using std::swap;
|
||||||
|
|
||||||
swap(d, item.d);
|
swap(d, item.d);
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::CoverArt::~CoverArt()
|
MP4::CoverArt::~CoverArt() {
|
||||||
{
|
if (d->deref()) {
|
||||||
if(d->deref()) {
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::CoverArt::Format
|
MP4::CoverArt::Format
|
||||||
MP4::CoverArt::format() const
|
MP4::CoverArt::format() const {
|
||||||
{
|
|
||||||
return d->format;
|
return d->format;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector
|
ByteVector
|
||||||
MP4::CoverArt::data() const
|
MP4::CoverArt::data() const {
|
||||||
{
|
|
||||||
return d->data;
|
return d->data;
|
||||||
}
|
}
|
||||||
|
61
3rdparty/taglib/mp4/mp4coverart.h
vendored
61
3rdparty/taglib/mp4/mp4coverart.h
vendored
@ -34,53 +34,52 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
namespace MP4 {
|
namespace MP4 {
|
||||||
|
|
||||||
class TAGLIB_EXPORT CoverArt
|
class TAGLIB_EXPORT CoverArt {
|
||||||
{
|
public:
|
||||||
public:
|
/*!
|
||||||
/*!
|
|
||||||
* This describes the image type.
|
* This describes the image type.
|
||||||
*/
|
*/
|
||||||
enum Format {
|
enum Format {
|
||||||
JPEG = TypeJPEG,
|
JPEG = TypeJPEG,
|
||||||
PNG = TypePNG,
|
PNG = TypePNG,
|
||||||
BMP = TypeBMP,
|
BMP = TypeBMP,
|
||||||
GIF = TypeGIF,
|
GIF = TypeGIF,
|
||||||
Unknown = TypeImplicit,
|
Unknown = TypeImplicit,
|
||||||
};
|
};
|
||||||
|
|
||||||
CoverArt(Format format, const ByteVector &data);
|
CoverArt(Format format, const ByteVector &data);
|
||||||
~CoverArt();
|
~CoverArt();
|
||||||
|
|
||||||
CoverArt(const CoverArt &item);
|
CoverArt(const CoverArt &item);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Copies the contents of \a item into this CoverArt.
|
* Copies the contents of \a item into this CoverArt.
|
||||||
*/
|
*/
|
||||||
CoverArt &operator=(const CoverArt &item);
|
CoverArt &operator=(const CoverArt &item);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Exchanges the content of the CoverArt by the content of \a item.
|
* Exchanges the content of the CoverArt by the content of \a item.
|
||||||
*/
|
*/
|
||||||
void swap(CoverArt &item);
|
void swap(CoverArt &item);
|
||||||
|
|
||||||
//! Format of the image
|
//! Format of the image
|
||||||
Format format() const;
|
Format format() const;
|
||||||
|
|
||||||
//! The image data
|
//! The image data
|
||||||
ByteVector data() const;
|
ByteVector data() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class CoverArtPrivate;
|
class CoverArtPrivate;
|
||||||
CoverArtPrivate *d;
|
CoverArtPrivate *d;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef List<CoverArt> CoverArtList;
|
typedef List<CoverArt> CoverArtList;
|
||||||
|
|
||||||
}
|
} // namespace MP4
|
||||||
|
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
102
3rdparty/taglib/mp4/mp4file.cpp
vendored
102
3rdparty/taglib/mp4/mp4file.cpp
vendored
@ -34,40 +34,35 @@
|
|||||||
|
|
||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
namespace
|
namespace {
|
||||||
{
|
bool checkValid(const MP4::AtomList &list) {
|
||||||
bool checkValid(const MP4::AtomList &list)
|
for (MP4::AtomList::ConstIterator it = list.begin(); it != list.end(); ++it) {
|
||||||
{
|
|
||||||
for(MP4::AtomList::ConstIterator it = list.begin(); it != list.end(); ++it) {
|
|
||||||
|
|
||||||
if((*it)->length == 0)
|
if ((*it)->length == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(!checkValid((*it)->children))
|
if (!checkValid((*it)->children))
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
class MP4::File::FilePrivate
|
class MP4::File::FilePrivate {
|
||||||
{
|
public:
|
||||||
public:
|
FilePrivate() : tag(0),
|
||||||
FilePrivate() :
|
atoms(0),
|
||||||
tag(0),
|
properties(0) {}
|
||||||
atoms(0),
|
|
||||||
properties(0) {}
|
|
||||||
|
|
||||||
~FilePrivate()
|
~FilePrivate() {
|
||||||
{
|
|
||||||
delete atoms;
|
delete atoms;
|
||||||
delete tag;
|
delete tag;
|
||||||
delete properties;
|
delete properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::Tag *tag;
|
MP4::Tag *tag;
|
||||||
MP4::Atoms *atoms;
|
MP4::Atoms *atoms;
|
||||||
MP4::Properties *properties;
|
MP4::Properties *properties;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -75,8 +70,7 @@ public:
|
|||||||
// static members
|
// static members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
bool MP4::File::isSupported(IOStream *stream)
|
bool MP4::File::isSupported(IOStream *stream) {
|
||||||
{
|
|
||||||
// An MP4 file has to have an "ftyp" box first.
|
// An MP4 file has to have an "ftyp" box first.
|
||||||
|
|
||||||
const ByteVector id = Utils::readHeader(stream, 8, false);
|
const ByteVector id = Utils::readHeader(stream, 8, false);
|
||||||
@ -87,87 +81,73 @@ bool MP4::File::isSupported(IOStream *stream)
|
|||||||
// public members
|
// public members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
MP4::File::File(FileName file, bool readProperties, AudioProperties::ReadStyle) :
|
MP4::File::File(FileName file, bool readProperties, AudioProperties::ReadStyle) : Strawberry_TagLib::TagLib::File(file),
|
||||||
Strawberry_TagLib::TagLib::File(file),
|
d(new FilePrivate()) {
|
||||||
d(new FilePrivate())
|
if (isOpen())
|
||||||
{
|
|
||||||
if(isOpen())
|
|
||||||
read(readProperties);
|
read(readProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::File::File(IOStream *stream, bool readProperties, AudioProperties::ReadStyle) :
|
MP4::File::File(IOStream *stream, bool readProperties, AudioProperties::ReadStyle) : Strawberry_TagLib::TagLib::File(stream),
|
||||||
Strawberry_TagLib::TagLib::File(stream),
|
d(new FilePrivate()) {
|
||||||
d(new FilePrivate())
|
if (isOpen())
|
||||||
{
|
|
||||||
if(isOpen())
|
|
||||||
read(readProperties);
|
read(readProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::File::~File()
|
MP4::File::~File() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::Tag *
|
MP4::Tag *
|
||||||
MP4::File::tag() const
|
MP4::File::tag() const {
|
||||||
{
|
|
||||||
return d->tag;
|
return d->tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyMap MP4::File::properties() const
|
PropertyMap MP4::File::properties() const {
|
||||||
{
|
|
||||||
return d->tag->properties();
|
return d->tag->properties();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MP4::File::removeUnsupportedProperties(const StringList &properties)
|
void MP4::File::removeUnsupportedProperties(const StringList &properties) {
|
||||||
{
|
|
||||||
d->tag->removeUnsupportedProperties(properties);
|
d->tag->removeUnsupportedProperties(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyMap MP4::File::setProperties(const PropertyMap &properties)
|
PropertyMap MP4::File::setProperties(const PropertyMap &properties) {
|
||||||
{
|
|
||||||
return d->tag->setProperties(properties);
|
return d->tag->setProperties(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::Properties *
|
MP4::Properties *
|
||||||
MP4::File::audioProperties() const
|
MP4::File::audioProperties() const {
|
||||||
{
|
|
||||||
return d->properties;
|
return d->properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void MP4::File::read(bool readProperties) {
|
||||||
MP4::File::read(bool readProperties)
|
if (!isValid())
|
||||||
{
|
|
||||||
if(!isValid())
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
d->atoms = new Atoms(this);
|
d->atoms = new Atoms(this);
|
||||||
if(!checkValid(d->atoms->atoms)) {
|
if (!checkValid(d->atoms->atoms)) {
|
||||||
setValid(false);
|
setValid(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// must have a moov atom, otherwise consider it invalid
|
// must have a moov atom, otherwise consider it invalid
|
||||||
if(!d->atoms->find("moov")) {
|
if (!d->atoms->find("moov")) {
|
||||||
setValid(false);
|
setValid(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->tag = new Tag(this, d->atoms);
|
d->tag = new Tag(this, d->atoms);
|
||||||
if(readProperties) {
|
if (readProperties) {
|
||||||
d->properties = new Properties(this, d->atoms);
|
d->properties = new Properties(this, d->atoms);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool MP4::File::save() {
|
||||||
MP4::File::save()
|
if (readOnly()) {
|
||||||
{
|
|
||||||
if(readOnly()) {
|
|
||||||
debug("MP4::File::save() -- File is read only.");
|
debug("MP4::File::save() -- File is read only.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!isValid()) {
|
if (!isValid()) {
|
||||||
debug("MP4::File::save() -- Trying to save invalid file.");
|
debug("MP4::File::save() -- Trying to save invalid file.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -175,8 +155,6 @@ MP4::File::save()
|
|||||||
return d->tag->save();
|
return d->tag->save();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool MP4::File::hasMP4Tag() const {
|
||||||
MP4::File::hasMP4Tag() const
|
|
||||||
{
|
|
||||||
return (d->atoms->find("moov", "udta", "meta", "ilst") != 0);
|
return (d->atoms->find("moov", "udta", "meta", "ilst") != 0);
|
||||||
}
|
}
|
||||||
|
77
3rdparty/taglib/mp4/mp4file.h
vendored
77
3rdparty/taglib/mp4/mp4file.h
vendored
@ -35,30 +35,29 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
//! An implementation of MP4 (AAC, ALAC, ...) metadata
|
//! An implementation of MP4 (AAC, ALAC, ...) metadata
|
||||||
namespace MP4 {
|
namespace MP4 {
|
||||||
|
|
||||||
class Atoms;
|
class Atoms;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* This implements and provides an interface for MP4 files to the
|
* This implements and provides an interface for MP4 files to the
|
||||||
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
|
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
|
||||||
* the abstract TagLib::File API as well as providing some additional
|
* the abstract TagLib::File API as well as providing some additional
|
||||||
* information specific to MP4 files.
|
* information specific to MP4 files.
|
||||||
*/
|
*/
|
||||||
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File
|
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File {
|
||||||
{
|
public:
|
||||||
public:
|
/*!
|
||||||
/*!
|
|
||||||
* Constructs an MP4 file from \a file. If \a readProperties is true the
|
* Constructs an MP4 file from \a file. If \a readProperties is true the
|
||||||
* file's audio properties will also be read.
|
* file's audio properties will also be read.
|
||||||
*
|
*
|
||||||
* \note In the current implementation, \a propertiesStyle is ignored.
|
* \note In the current implementation, \a propertiesStyle is ignored.
|
||||||
*/
|
*/
|
||||||
File(FileName file, bool readProperties = true,
|
File(FileName file, bool readProperties = true,
|
||||||
Properties::ReadStyle audioPropertiesStyle = Properties::Average);
|
Properties::ReadStyle audioPropertiesStyle = Properties::Average);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs an MP4 file from \a stream. If \a readProperties is true the
|
* Constructs an MP4 file from \a stream. If \a readProperties is true the
|
||||||
* file's audio properties will also be read.
|
* file's audio properties will also be read.
|
||||||
*
|
*
|
||||||
@ -67,15 +66,15 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \note In the current implementation, \a propertiesStyle is ignored.
|
* \note In the current implementation, \a propertiesStyle is ignored.
|
||||||
*/
|
*/
|
||||||
File(IOStream *stream, bool readProperties = true,
|
File(IOStream *stream, bool readProperties = true,
|
||||||
Properties::ReadStyle audioPropertiesStyle = Properties::Average);
|
Properties::ReadStyle audioPropertiesStyle = Properties::Average);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys this instance of the File.
|
* Destroys this instance of the File.
|
||||||
*/
|
*/
|
||||||
virtual ~File();
|
virtual ~File();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns a pointer to the MP4 tag of the file.
|
* Returns a pointer to the MP4 tag of the file.
|
||||||
*
|
*
|
||||||
* MP4::Tag implements the tag interface, so this serves as the
|
* MP4::Tag implements the tag interface, so this serves as the
|
||||||
@ -85,61 +84,61 @@ namespace TagLib {
|
|||||||
* deleted by the user. It will be deleted when the file (object) is
|
* deleted by the user. It will be deleted when the file (object) is
|
||||||
* destroyed.
|
* destroyed.
|
||||||
*/
|
*/
|
||||||
Tag *tag() const;
|
Tag *tag() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Implements the unified property interface -- export function.
|
* Implements the unified property interface -- export function.
|
||||||
*/
|
*/
|
||||||
PropertyMap properties() const;
|
PropertyMap properties() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Removes unsupported properties. Forwards to the actual Tag's
|
* Removes unsupported properties. Forwards to the actual Tag's
|
||||||
* removeUnsupportedProperties() function.
|
* removeUnsupportedProperties() function.
|
||||||
*/
|
*/
|
||||||
void removeUnsupportedProperties(const StringList &properties);
|
void removeUnsupportedProperties(const StringList &properties);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Implements the unified property interface -- import function.
|
* Implements the unified property interface -- import function.
|
||||||
*/
|
*/
|
||||||
PropertyMap setProperties(const PropertyMap &);
|
PropertyMap setProperties(const PropertyMap &);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the MP4 audio properties for this file.
|
* Returns the MP4 audio properties for this file.
|
||||||
*/
|
*/
|
||||||
Properties *audioProperties() const;
|
Properties *audioProperties() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Save the file.
|
* Save the file.
|
||||||
*
|
*
|
||||||
* This returns true if the save was successful.
|
* This returns true if the save was successful.
|
||||||
*/
|
*/
|
||||||
bool save();
|
bool save();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns whether or not the file on disk actually has an MP4 tag, or the
|
* Returns whether or not the file on disk actually has an MP4 tag, or the
|
||||||
* file has a Metadata Item List (ilst) atom.
|
* file has a Metadata Item List (ilst) atom.
|
||||||
*/
|
*/
|
||||||
bool hasMP4Tag() const;
|
bool hasMP4Tag() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns whether or not the given \a stream can be opened as an ASF
|
* Returns whether or not the given \a stream can be opened as an ASF
|
||||||
* file.
|
* file.
|
||||||
*
|
*
|
||||||
* \note This method is designed to do a quick check. The result may
|
* \note This method is designed to do a quick check. The result may
|
||||||
* not necessarily be correct.
|
* not necessarily be correct.
|
||||||
*/
|
*/
|
||||||
static bool isSupported(IOStream *stream);
|
static bool isSupported(IOStream *stream);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void read(bool readProperties);
|
void read(bool readProperties);
|
||||||
|
|
||||||
class FilePrivate;
|
class FilePrivate;
|
||||||
FilePrivate *d;
|
FilePrivate *d;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace MP4
|
||||||
|
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
107
3rdparty/taglib/mp4/mp4item.cpp
vendored
107
3rdparty/taglib/mp4/mp4item.cpp
vendored
@ -30,13 +30,11 @@
|
|||||||
|
|
||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
class MP4::Item::ItemPrivate : public RefCounter
|
class MP4::Item::ItemPrivate : public RefCounter {
|
||||||
{
|
public:
|
||||||
public:
|
ItemPrivate() : RefCounter(),
|
||||||
ItemPrivate() :
|
valid(true),
|
||||||
RefCounter(),
|
atomDataType(TypeUndefined) {}
|
||||||
valid(true),
|
|
||||||
atomDataType(TypeUndefined) {}
|
|
||||||
|
|
||||||
bool valid;
|
bool valid;
|
||||||
AtomDataType atomDataType;
|
AtomDataType atomDataType;
|
||||||
@ -53,160 +51,119 @@ public:
|
|||||||
MP4::CoverArtList m_coverArtList;
|
MP4::CoverArtList m_coverArtList;
|
||||||
};
|
};
|
||||||
|
|
||||||
MP4::Item::Item() :
|
MP4::Item::Item() : d(new ItemPrivate()) {
|
||||||
d(new ItemPrivate())
|
|
||||||
{
|
|
||||||
d->valid = false;
|
d->valid = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::Item::Item(const Item &item) :
|
MP4::Item::Item(const Item &item) : d(item.d) {
|
||||||
d(item.d)
|
|
||||||
{
|
|
||||||
d->ref();
|
d->ref();
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::Item &
|
MP4::Item &
|
||||||
MP4::Item::operator=(const Item &item)
|
MP4::Item::operator=(const Item &item) {
|
||||||
{
|
|
||||||
Item(item).swap(*this);
|
Item(item).swap(*this);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void MP4::Item::swap(Item &item) {
|
||||||
MP4::Item::swap(Item &item)
|
|
||||||
{
|
|
||||||
using std::swap;
|
using std::swap;
|
||||||
|
|
||||||
swap(d, item.d);
|
swap(d, item.d);
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::Item::~Item()
|
MP4::Item::~Item() {
|
||||||
{
|
if (d->deref())
|
||||||
if(d->deref())
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::Item::Item(bool value) :
|
MP4::Item::Item(bool value) : d(new ItemPrivate()) {
|
||||||
d(new ItemPrivate())
|
|
||||||
{
|
|
||||||
d->m_bool = value;
|
d->m_bool = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::Item::Item(int value) :
|
MP4::Item::Item(int value) : d(new ItemPrivate()) {
|
||||||
d(new ItemPrivate())
|
|
||||||
{
|
|
||||||
d->m_int = value;
|
d->m_int = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::Item::Item(unsigned char value) :
|
MP4::Item::Item(unsigned char value) : d(new ItemPrivate()) {
|
||||||
d(new ItemPrivate())
|
|
||||||
{
|
|
||||||
d->m_byte = value;
|
d->m_byte = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::Item::Item(unsigned int value) :
|
MP4::Item::Item(unsigned int value) : d(new ItemPrivate()) {
|
||||||
d(new ItemPrivate())
|
|
||||||
{
|
|
||||||
d->m_uint = value;
|
d->m_uint = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::Item::Item(long long value) :
|
MP4::Item::Item(long long value) : d(new ItemPrivate()) {
|
||||||
d(new ItemPrivate())
|
|
||||||
{
|
|
||||||
d->m_longlong = value;
|
d->m_longlong = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::Item::Item(int value1, int value2) :
|
MP4::Item::Item(int value1, int value2) : d(new ItemPrivate()) {
|
||||||
d(new ItemPrivate())
|
|
||||||
{
|
|
||||||
d->m_intPair.first = value1;
|
d->m_intPair.first = value1;
|
||||||
d->m_intPair.second = value2;
|
d->m_intPair.second = value2;
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::Item::Item(const ByteVectorList &value) :
|
MP4::Item::Item(const ByteVectorList &value) : d(new ItemPrivate()) {
|
||||||
d(new ItemPrivate())
|
|
||||||
{
|
|
||||||
d->m_byteVectorList = value;
|
d->m_byteVectorList = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::Item::Item(const StringList &value) :
|
MP4::Item::Item(const StringList &value) : d(new ItemPrivate()) {
|
||||||
d(new ItemPrivate())
|
|
||||||
{
|
|
||||||
d->m_stringList = value;
|
d->m_stringList = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::Item::Item(const MP4::CoverArtList &value) :
|
MP4::Item::Item(const MP4::CoverArtList &value) : d(new ItemPrivate()) {
|
||||||
d(new ItemPrivate())
|
|
||||||
{
|
|
||||||
d->m_coverArtList = value;
|
d->m_coverArtList = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MP4::Item::setAtomDataType(MP4::AtomDataType type)
|
void MP4::Item::setAtomDataType(MP4::AtomDataType type) {
|
||||||
{
|
|
||||||
d->atomDataType = type;
|
d->atomDataType = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::AtomDataType MP4::Item::atomDataType() const
|
MP4::AtomDataType MP4::Item::atomDataType() const {
|
||||||
{
|
|
||||||
return d->atomDataType;
|
return d->atomDataType;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool MP4::Item::toBool() const {
|
||||||
MP4::Item::toBool() const
|
|
||||||
{
|
|
||||||
return d->m_bool;
|
return d->m_bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int MP4::Item::toInt() const {
|
||||||
MP4::Item::toInt() const
|
|
||||||
{
|
|
||||||
return d->m_int;
|
return d->m_int;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char
|
unsigned char
|
||||||
MP4::Item::toByte() const
|
MP4::Item::toByte() const {
|
||||||
{
|
|
||||||
return d->m_byte;
|
return d->m_byte;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int
|
unsigned int
|
||||||
MP4::Item::toUInt() const
|
MP4::Item::toUInt() const {
|
||||||
{
|
|
||||||
return d->m_uint;
|
return d->m_uint;
|
||||||
}
|
}
|
||||||
|
|
||||||
long long
|
long long
|
||||||
MP4::Item::toLongLong() const
|
MP4::Item::toLongLong() const {
|
||||||
{
|
|
||||||
return d->m_longlong;
|
return d->m_longlong;
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::Item::IntPair
|
MP4::Item::IntPair
|
||||||
MP4::Item::toIntPair() const
|
MP4::Item::toIntPair() const {
|
||||||
{
|
|
||||||
return d->m_intPair;
|
return d->m_intPair;
|
||||||
}
|
}
|
||||||
|
|
||||||
StringList
|
StringList
|
||||||
MP4::Item::toStringList() const
|
MP4::Item::toStringList() const {
|
||||||
{
|
|
||||||
return d->m_stringList;
|
return d->m_stringList;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVectorList
|
ByteVectorList
|
||||||
MP4::Item::toByteVectorList() const
|
MP4::Item::toByteVectorList() const {
|
||||||
{
|
|
||||||
return d->m_byteVectorList;
|
return d->m_byteVectorList;
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::CoverArtList
|
MP4::CoverArtList
|
||||||
MP4::Item::toCoverArtList() const
|
MP4::Item::toCoverArtList() const {
|
||||||
{
|
|
||||||
return d->m_coverArtList;
|
return d->m_coverArtList;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool MP4::Item::isValid() const {
|
||||||
MP4::Item::isValid() const
|
|
||||||
{
|
|
||||||
return d->valid;
|
return d->valid;
|
||||||
}
|
}
|
||||||
|
83
3rdparty/taglib/mp4/mp4item.h
vendored
83
3rdparty/taglib/mp4/mp4item.h
vendored
@ -33,63 +33,62 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
namespace MP4 {
|
namespace MP4 {
|
||||||
|
|
||||||
class TAGLIB_EXPORT Item
|
class TAGLIB_EXPORT Item {
|
||||||
{
|
public:
|
||||||
public:
|
struct IntPair {
|
||||||
struct IntPair {
|
int first, second;
|
||||||
int first, second;
|
};
|
||||||
};
|
|
||||||
|
|
||||||
Item();
|
Item();
|
||||||
Item(const Item &item);
|
Item(const Item &item);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Copies the contents of \a item into this Item.
|
* Copies the contents of \a item into this Item.
|
||||||
*/
|
*/
|
||||||
Item &operator=(const Item &item);
|
Item &operator=(const Item &item);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Exchanges the content of the Item by the content of \a item.
|
* Exchanges the content of the Item by the content of \a item.
|
||||||
*/
|
*/
|
||||||
void swap(Item &item);
|
void swap(Item &item);
|
||||||
|
|
||||||
~Item();
|
~Item();
|
||||||
|
|
||||||
Item(int value);
|
Item(int value);
|
||||||
Item(unsigned char value);
|
Item(unsigned char value);
|
||||||
Item(unsigned int value);
|
Item(unsigned int value);
|
||||||
Item(long long value);
|
Item(long long value);
|
||||||
Item(bool value);
|
Item(bool value);
|
||||||
Item(int first, int second);
|
Item(int first, int second);
|
||||||
Item(const StringList &value);
|
Item(const StringList &value);
|
||||||
Item(const ByteVectorList &value);
|
Item(const ByteVectorList &value);
|
||||||
Item(const CoverArtList &value);
|
Item(const CoverArtList &value);
|
||||||
|
|
||||||
void setAtomDataType(AtomDataType type);
|
void setAtomDataType(AtomDataType type);
|
||||||
AtomDataType atomDataType() const;
|
AtomDataType atomDataType() const;
|
||||||
|
|
||||||
int toInt() const;
|
int toInt() const;
|
||||||
unsigned char toByte() const;
|
unsigned char toByte() const;
|
||||||
unsigned int toUInt() const;
|
unsigned int toUInt() const;
|
||||||
long long toLongLong() const;
|
long long toLongLong() const;
|
||||||
bool toBool() const;
|
bool toBool() const;
|
||||||
IntPair toIntPair() const;
|
IntPair toIntPair() const;
|
||||||
StringList toStringList() const;
|
StringList toStringList() const;
|
||||||
ByteVectorList toByteVectorList() const;
|
ByteVectorList toByteVectorList() const;
|
||||||
CoverArtList toCoverArtList() const;
|
CoverArtList toCoverArtList() const;
|
||||||
|
|
||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class ItemPrivate;
|
class ItemPrivate;
|
||||||
ItemPrivate *d;
|
ItemPrivate *d;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace MP4
|
||||||
|
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
124
3rdparty/taglib/mp4/mp4properties.cpp
vendored
124
3rdparty/taglib/mp4/mp4properties.cpp
vendored
@ -31,17 +31,15 @@
|
|||||||
|
|
||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
class MP4::Properties::PropertiesPrivate
|
class MP4::Properties::PropertiesPrivate {
|
||||||
{
|
public:
|
||||||
public:
|
PropertiesPrivate() : length(0),
|
||||||
PropertiesPrivate() :
|
bitrate(0),
|
||||||
length(0),
|
sampleRate(0),
|
||||||
bitrate(0),
|
channels(0),
|
||||||
sampleRate(0),
|
bitsPerSample(0),
|
||||||
channels(0),
|
encrypted(false),
|
||||||
bitsPerSample(0),
|
codec(MP4::Properties::Unknown) {}
|
||||||
encrypted(false),
|
|
||||||
codec(MP4::Properties::Unknown) {}
|
|
||||||
|
|
||||||
int length;
|
int length;
|
||||||
int bitrate;
|
int bitrate;
|
||||||
@ -56,69 +54,49 @@ public:
|
|||||||
// public members
|
// public members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
MP4::Properties::Properties(File *file, MP4::Atoms *atoms, ReadStyle style) :
|
MP4::Properties::Properties(File *file, MP4::Atoms *atoms, ReadStyle style) : AudioProperties(style),
|
||||||
AudioProperties(style),
|
d(new PropertiesPrivate()) {
|
||||||
d(new PropertiesPrivate())
|
|
||||||
{
|
|
||||||
read(file, atoms);
|
read(file, atoms);
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::Properties::~Properties()
|
MP4::Properties::~Properties() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int MP4::Properties::channels() const {
|
||||||
MP4::Properties::channels() const
|
|
||||||
{
|
|
||||||
return d->channels;
|
return d->channels;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int MP4::Properties::sampleRate() const {
|
||||||
MP4::Properties::sampleRate() const
|
|
||||||
{
|
|
||||||
return d->sampleRate;
|
return d->sampleRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int MP4::Properties::length() const {
|
||||||
MP4::Properties::length() const
|
|
||||||
{
|
|
||||||
return lengthInSeconds();
|
return lengthInSeconds();
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int MP4::Properties::lengthInSeconds() const {
|
||||||
MP4::Properties::lengthInSeconds() const
|
|
||||||
{
|
|
||||||
return d->length / 1000;
|
return d->length / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int MP4::Properties::lengthInMilliseconds() const {
|
||||||
MP4::Properties::lengthInMilliseconds() const
|
|
||||||
{
|
|
||||||
return d->length;
|
return d->length;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int MP4::Properties::bitrate() const {
|
||||||
MP4::Properties::bitrate() const
|
|
||||||
{
|
|
||||||
return d->bitrate;
|
return d->bitrate;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int MP4::Properties::bitsPerSample() const {
|
||||||
MP4::Properties::bitsPerSample() const
|
|
||||||
{
|
|
||||||
return d->bitsPerSample;
|
return d->bitsPerSample;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool MP4::Properties::isEncrypted() const {
|
||||||
MP4::Properties::isEncrypted() const
|
|
||||||
{
|
|
||||||
return d->encrypted;
|
return d->encrypted;
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::Properties::Codec
|
MP4::Properties::Codec
|
||||||
MP4::Properties::codec() const
|
MP4::Properties::codec() const {
|
||||||
{
|
|
||||||
return d->codec;
|
return d->codec;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,11 +104,9 @@ MP4::Properties::codec() const
|
|||||||
// private members
|
// private members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void
|
void MP4::Properties::read(File *file, Atoms *atoms) {
|
||||||
MP4::Properties::read(File *file, Atoms *atoms)
|
|
||||||
{
|
|
||||||
MP4::Atom *moov = atoms->find("moov");
|
MP4::Atom *moov = atoms->find("moov");
|
||||||
if(!moov) {
|
if (!moov) {
|
||||||
debug("MP4: Atom 'moov' not found");
|
debug("MP4: Atom 'moov' not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -139,27 +115,27 @@ MP4::Properties::read(File *file, Atoms *atoms)
|
|||||||
ByteVector data;
|
ByteVector data;
|
||||||
|
|
||||||
const MP4::AtomList trakList = moov->findall("trak");
|
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;
|
trak = *it;
|
||||||
MP4::Atom *hdlr = trak->find("mdia", "hdlr");
|
MP4::Atom *hdlr = trak->find("mdia", "hdlr");
|
||||||
if(!hdlr) {
|
if (!hdlr) {
|
||||||
debug("MP4: Atom 'trak.mdia.hdlr' not found");
|
debug("MP4: Atom 'trak.mdia.hdlr' not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
file->seek(hdlr->offset);
|
file->seek(hdlr->offset);
|
||||||
data = file->readBlock(hdlr->length);
|
data = file->readBlock(hdlr->length);
|
||||||
if(data.containsAt("soun", 16)) {
|
if (data.containsAt("soun", 16)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
trak = 0;
|
trak = 0;
|
||||||
}
|
}
|
||||||
if(!trak) {
|
if (!trak) {
|
||||||
debug("MP4: No audio tracks");
|
debug("MP4: No audio tracks");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::Atom *mdhd = trak->find("mdia", "mdhd");
|
MP4::Atom *mdhd = trak->find("mdia", "mdhd");
|
||||||
if(!mdhd) {
|
if (!mdhd) {
|
||||||
debug("MP4: Atom 'trak.mdia.mdhd' not found");
|
debug("MP4: Atom 'trak.mdia.mdhd' not found");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -170,46 +146,46 @@ MP4::Properties::read(File *file, Atoms *atoms)
|
|||||||
const unsigned int version = data[8];
|
const unsigned int version = data[8];
|
||||||
long long unit;
|
long long unit;
|
||||||
long long length;
|
long long length;
|
||||||
if(version == 1) {
|
if (version == 1) {
|
||||||
if(data.size() < 36 + 8) {
|
if (data.size() < 36 + 8) {
|
||||||
debug("MP4: Atom 'trak.mdia.mdhd' is smaller than expected");
|
debug("MP4: Atom 'trak.mdia.mdhd' is smaller than expected");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
unit = data.toUInt(28U);
|
unit = data.toUInt(28U);
|
||||||
length = data.toLongLong(32U);
|
length = data.toLongLong(32U);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if(data.size() < 24 + 8) {
|
if (data.size() < 24 + 8) {
|
||||||
debug("MP4: Atom 'trak.mdia.mdhd' is smaller than expected");
|
debug("MP4: Atom 'trak.mdia.mdhd' is smaller than expected");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
unit = data.toUInt(20U);
|
unit = data.toUInt(20U);
|
||||||
length = data.toUInt(24U);
|
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);
|
d->length = static_cast<int>(length * 1000.0 / unit + 0.5);
|
||||||
|
|
||||||
MP4::Atom *atom = trak->find("mdia", "minf", "stbl", "stsd");
|
MP4::Atom *atom = trak->find("mdia", "minf", "stbl", "stsd");
|
||||||
if(!atom) {
|
if (!atom) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
file->seek(atom->offset);
|
file->seek(atom->offset);
|
||||||
data = file->readBlock(atom->length);
|
data = file->readBlock(atom->length);
|
||||||
if(data.containsAt("mp4a", 20)) {
|
if (data.containsAt("mp4a", 20)) {
|
||||||
d->codec = AAC;
|
d->codec = AAC;
|
||||||
d->channels = data.toShort(40U);
|
d->channels = data.toShort(40U);
|
||||||
d->bitsPerSample = data.toShort(42U);
|
d->bitsPerSample = data.toShort(42U);
|
||||||
d->sampleRate = data.toUInt(46U);
|
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;
|
unsigned int pos = 65;
|
||||||
if(data.containsAt("\x80\x80\x80", pos)) {
|
if (data.containsAt("\x80\x80\x80", pos)) {
|
||||||
pos += 3;
|
pos += 3;
|
||||||
}
|
}
|
||||||
pos += 4;
|
pos += 4;
|
||||||
if(data[pos] == 0x04) {
|
if (data[pos] == 0x04) {
|
||||||
pos += 1;
|
pos += 1;
|
||||||
if(data.containsAt("\x80\x80\x80", pos)) {
|
if (data.containsAt("\x80\x80\x80", pos)) {
|
||||||
pos += 3;
|
pos += 3;
|
||||||
}
|
}
|
||||||
pos += 10;
|
pos += 10;
|
||||||
@ -217,18 +193,18 @@ MP4::Properties::read(File *file, Atoms *atoms)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(data.containsAt("alac", 20)) {
|
else if (data.containsAt("alac", 20)) {
|
||||||
if(atom->length == 88 && data.containsAt("alac", 56)) {
|
if (atom->length == 88 && data.containsAt("alac", 56)) {
|
||||||
d->codec = ALAC;
|
d->codec = ALAC;
|
||||||
d->bitsPerSample = data.at(69);
|
d->bitsPerSample = data.at(69);
|
||||||
d->channels = data.at(73);
|
d->channels = data.at(73);
|
||||||
d->bitrate = static_cast<int>(data.toUInt(80U) / 1000.0 + 0.5);
|
d->bitrate = static_cast<int>(data.toUInt(80U) / 1000.0 + 0.5);
|
||||||
d->sampleRate = data.toUInt(84U);
|
d->sampleRate = data.toUInt(84U);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MP4::Atom *drms = atom->find("drms");
|
MP4::Atom *drms = atom->find("drms");
|
||||||
if(drms) {
|
if (drms) {
|
||||||
d->encrypted = true;
|
d->encrypted = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
83
3rdparty/taglib/mp4/mp4properties.h
vendored
83
3rdparty/taglib/mp4/mp4properties.h
vendored
@ -32,25 +32,24 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
namespace MP4 {
|
namespace MP4 {
|
||||||
|
|
||||||
class Atoms;
|
class Atoms;
|
||||||
class File;
|
class File;
|
||||||
|
|
||||||
//! An implementation of MP4 audio properties
|
//! An implementation of MP4 audio properties
|
||||||
class TAGLIB_EXPORT Properties : public AudioProperties
|
class TAGLIB_EXPORT Properties : public AudioProperties {
|
||||||
{
|
public:
|
||||||
public:
|
enum Codec {
|
||||||
enum Codec {
|
Unknown = 0,
|
||||||
Unknown = 0,
|
AAC,
|
||||||
AAC,
|
ALAC
|
||||||
ALAC
|
};
|
||||||
};
|
|
||||||
|
|
||||||
Properties(File *file, Atoms *atoms, ReadStyle style = Average);
|
Properties(File *file, Atoms *atoms, ReadStyle style = Average);
|
||||||
virtual ~Properties();
|
virtual ~Properties();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the length of the file in seconds. The length is rounded down to
|
* Returns the length of the file in seconds. The length is rounded down to
|
||||||
* the nearest whole second.
|
* the nearest whole second.
|
||||||
*
|
*
|
||||||
@ -58,65 +57,65 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \deprecated
|
* \deprecated
|
||||||
*/
|
*/
|
||||||
TAGLIB_DEPRECATED virtual int length() const;
|
TAGLIB_DEPRECATED virtual int length() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the length of the file in seconds. The length is rounded down to
|
* Returns the length of the file in seconds. The length is rounded down to
|
||||||
* the nearest whole second.
|
* the nearest whole second.
|
||||||
*
|
*
|
||||||
* \see lengthInMilliseconds()
|
* \see lengthInMilliseconds()
|
||||||
*/
|
*/
|
||||||
// BIC: make virtual
|
// BIC: make virtual
|
||||||
int lengthInSeconds() const;
|
int lengthInSeconds() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the length of the file in milliseconds.
|
* Returns the length of the file in milliseconds.
|
||||||
*
|
*
|
||||||
* \see lengthInSeconds()
|
* \see lengthInSeconds()
|
||||||
*/
|
*/
|
||||||
// BIC: make virtual
|
// BIC: make virtual
|
||||||
int lengthInMilliseconds() const;
|
int lengthInMilliseconds() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the average bit rate of the file in kb/s.
|
* Returns the average bit rate of the file in kb/s.
|
||||||
*/
|
*/
|
||||||
virtual int bitrate() const;
|
virtual int bitrate() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the sample rate in Hz.
|
* Returns the sample rate in Hz.
|
||||||
*/
|
*/
|
||||||
virtual int sampleRate() const;
|
virtual int sampleRate() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the number of audio channels.
|
* Returns the number of audio channels.
|
||||||
*/
|
*/
|
||||||
virtual int channels() const;
|
virtual int channels() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the number of bits per audio sample.
|
* Returns the number of bits per audio sample.
|
||||||
*/
|
*/
|
||||||
virtual int bitsPerSample() const;
|
virtual int bitsPerSample() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns whether or not the file is encrypted.
|
* Returns whether or not the file is encrypted.
|
||||||
*/
|
*/
|
||||||
bool isEncrypted() const;
|
bool isEncrypted() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the codec used in the file.
|
* Returns the codec used in the file.
|
||||||
*/
|
*/
|
||||||
Codec codec() const;
|
Codec codec() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void read(File *file, Atoms *atoms);
|
void read(File *file, Atoms *atoms);
|
||||||
|
|
||||||
class PropertiesPrivate;
|
class PropertiesPrivate;
|
||||||
PropertiesPrivate *d;
|
PropertiesPrivate *d;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace MP4
|
||||||
|
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
616
3rdparty/taglib/mp4/mp4tag.cpp
vendored
616
3rdparty/taglib/mp4/mp4tag.cpp
vendored
File diff suppressed because it is too large
Load Diff
163
3rdparty/taglib/mp4/mp4tag.h
vendored
163
3rdparty/taglib/mp4/mp4tag.h
vendored
@ -38,122 +38,121 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
namespace MP4 {
|
namespace MP4 {
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \deprecated
|
* \deprecated
|
||||||
*/
|
*/
|
||||||
TAGLIB_DEPRECATED typedef Strawberry_TagLib::TagLib::Map<String, Item> ItemListMap;
|
TAGLIB_DEPRECATED typedef Strawberry_TagLib::TagLib::Map<String, Item> ItemListMap;
|
||||||
typedef Strawberry_TagLib::TagLib::Map<String, Item> ItemMap;
|
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:
|
||||||
public:
|
Tag();
|
||||||
Tag();
|
Tag(Strawberry_TagLib::TagLib::File *file, Atoms *atoms);
|
||||||
Tag(Strawberry_TagLib::TagLib::File *file, Atoms *atoms);
|
virtual ~Tag();
|
||||||
virtual ~Tag();
|
bool save();
|
||||||
bool save();
|
|
||||||
|
|
||||||
virtual String title() const;
|
virtual String title() const;
|
||||||
virtual String artist() const;
|
virtual String artist() const;
|
||||||
virtual String album() const;
|
virtual String album() const;
|
||||||
virtual String comment() const;
|
virtual String comment() const;
|
||||||
virtual String genre() const;
|
virtual String genre() const;
|
||||||
virtual unsigned int year() const;
|
virtual unsigned int year() const;
|
||||||
virtual unsigned int track() const;
|
virtual unsigned int track() const;
|
||||||
|
|
||||||
virtual void setTitle(const String &value);
|
virtual void setTitle(const String &value);
|
||||||
virtual void setArtist(const String &value);
|
virtual void setArtist(const String &value);
|
||||||
virtual void setAlbum(const String &value);
|
virtual void setAlbum(const String &value);
|
||||||
virtual void setComment(const String &value);
|
virtual void setComment(const String &value);
|
||||||
virtual void setGenre(const String &value);
|
virtual void setGenre(const String &value);
|
||||||
virtual void setYear(unsigned int value);
|
virtual void setYear(unsigned int value);
|
||||||
virtual void setTrack(unsigned int value);
|
virtual void setTrack(unsigned int value);
|
||||||
|
|
||||||
virtual bool isEmpty() const;
|
virtual bool isEmpty() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \deprecated Use the item() and setItem() API instead
|
* \deprecated Use the item() and setItem() API instead
|
||||||
*/
|
*/
|
||||||
TAGLIB_DEPRECATED ItemMap &itemListMap();
|
TAGLIB_DEPRECATED ItemMap &itemListMap();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns a string-keyed map of the MP4::Items for this tag.
|
* Returns a string-keyed map of the MP4::Items for this tag.
|
||||||
*/
|
*/
|
||||||
const ItemMap &itemMap() const;
|
const ItemMap &itemMap() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \return The item, if any, corresponding to \a key.
|
* \return The item, if any, corresponding to \a key.
|
||||||
*/
|
*/
|
||||||
Item item(const String &key) const;
|
Item item(const String &key) const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the value of \a key to \a value, overwriting any previous value.
|
* Sets the value of \a key to \a value, overwriting any previous value.
|
||||||
*/
|
*/
|
||||||
void setItem(const String &key, const Item &value);
|
void setItem(const String &key, const Item &value);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Removes the entry with \a key from the tag, or does nothing if it does
|
* Removes the entry with \a key from the tag, or does nothing if it does
|
||||||
* not exist.
|
* not exist.
|
||||||
*/
|
*/
|
||||||
void removeItem(const String &key);
|
void removeItem(const String &key);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \return True if the tag contains an entry for \a key.
|
* \return True if the tag contains an entry for \a key.
|
||||||
*/
|
*/
|
||||||
bool contains(const String &key) const;
|
bool contains(const String &key) const;
|
||||||
|
|
||||||
PropertyMap properties() const;
|
PropertyMap properties() const;
|
||||||
void removeUnsupportedProperties(const StringList& properties);
|
void removeUnsupportedProperties(const StringList &properties);
|
||||||
PropertyMap setProperties(const PropertyMap &properties);
|
PropertyMap setProperties(const PropertyMap &properties);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AtomDataList parseData2(const Atom *atom, int expectedFlags = -1,
|
AtomDataList parseData2(const Atom *atom, int expectedFlags = -1,
|
||||||
bool freeForm = false);
|
bool freeForm = false);
|
||||||
ByteVectorList parseData(const Atom *atom, int expectedFlags = -1,
|
ByteVectorList parseData(const Atom *atom, int expectedFlags = -1,
|
||||||
bool freeForm = false);
|
bool freeForm = false);
|
||||||
void parseText(const Atom *atom, int expectedFlags = 1);
|
void parseText(const Atom *atom, int expectedFlags = 1);
|
||||||
void parseFreeForm(const Atom *atom);
|
void parseFreeForm(const Atom *atom);
|
||||||
void parseInt(const Atom *atom);
|
void parseInt(const Atom *atom);
|
||||||
void parseByte(const Atom *atom);
|
void parseByte(const Atom *atom);
|
||||||
void parseUInt(const Atom *atom);
|
void parseUInt(const Atom *atom);
|
||||||
void parseLongLong(const Atom *atom);
|
void parseLongLong(const Atom *atom);
|
||||||
void parseGnre(const Atom *atom);
|
void parseGnre(const Atom *atom);
|
||||||
void parseIntPair(const Atom *atom);
|
void parseIntPair(const Atom *atom);
|
||||||
void parseBool(const Atom *atom);
|
void parseBool(const Atom *atom);
|
||||||
void parseCovr(const Atom *atom);
|
void parseCovr(const Atom *atom);
|
||||||
|
|
||||||
ByteVector padIlst(const ByteVector &data, int length = -1) const;
|
ByteVector padIlst(const ByteVector &data, int length = -1) const;
|
||||||
ByteVector renderAtom(const ByteVector &name, const ByteVector &data) const;
|
ByteVector renderAtom(const ByteVector &name, const ByteVector &data) const;
|
||||||
ByteVector renderData(const ByteVector &name, int flags,
|
ByteVector renderData(const ByteVector &name, int flags,
|
||||||
const ByteVectorList &data) const;
|
const ByteVectorList &data) const;
|
||||||
ByteVector renderText(const ByteVector &name, const Item &item,
|
ByteVector renderText(const ByteVector &name, const Item &item,
|
||||||
int flags = TypeUTF8) const;
|
int flags = TypeUTF8) const;
|
||||||
ByteVector renderFreeForm(const String &name, const Item &item) const;
|
ByteVector renderFreeForm(const String &name, const Item &item) const;
|
||||||
ByteVector renderBool(const ByteVector &name, const Item &item) const;
|
ByteVector renderBool(const ByteVector &name, const Item &item) const;
|
||||||
ByteVector renderInt(const ByteVector &name, const Item &item) const;
|
ByteVector renderInt(const ByteVector &name, const Item &item) const;
|
||||||
ByteVector renderByte(const ByteVector &name, const Item &item) const;
|
ByteVector renderByte(const ByteVector &name, const Item &item) const;
|
||||||
ByteVector renderUInt(const ByteVector &name, const Item &item) const;
|
ByteVector renderUInt(const ByteVector &name, const Item &item) const;
|
||||||
ByteVector renderLongLong(const ByteVector &name, const Item &item) const;
|
ByteVector renderLongLong(const ByteVector &name, const Item &item) const;
|
||||||
ByteVector renderIntPair(const ByteVector &name, const Item &item) const;
|
ByteVector renderIntPair(const ByteVector &name, const Item &item) const;
|
||||||
ByteVector renderIntPairNoTrailing(const ByteVector &name, const Item &item) const;
|
ByteVector renderIntPairNoTrailing(const ByteVector &name, const Item &item) const;
|
||||||
ByteVector renderCovr(const ByteVector &name, const Item &item) const;
|
ByteVector renderCovr(const ByteVector &name, const Item &item) const;
|
||||||
|
|
||||||
void updateParents(const AtomList &path, long delta, int ignore = 0);
|
void updateParents(const AtomList &path, long delta, int ignore = 0);
|
||||||
void updateOffsets(long delta, long offset);
|
void updateOffsets(long delta, long offset);
|
||||||
|
|
||||||
void saveNew(ByteVector data);
|
void saveNew(ByteVector data);
|
||||||
void saveExisting(ByteVector data, const AtomList &path);
|
void saveExisting(ByteVector data, const AtomList &path);
|
||||||
|
|
||||||
void addItem(const String &name, const Item &value);
|
void addItem(const String &name, const Item &value);
|
||||||
|
|
||||||
class TagPrivate;
|
class TagPrivate;
|
||||||
TagPrivate *d;
|
TagPrivate *d;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace MP4
|
||||||
|
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
142
3rdparty/taglib/mpc/mpcfile.cpp
vendored
142
3rdparty/taglib/mpc/mpcfile.cpp
vendored
@ -38,25 +38,22 @@
|
|||||||
|
|
||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
namespace
|
namespace {
|
||||||
{
|
enum { MPCAPEIndex = 0,
|
||||||
enum { MPCAPEIndex = 0, MPCID3v1Index = 1 };
|
MPCID3v1Index = 1 };
|
||||||
}
|
}
|
||||||
|
|
||||||
class MPC::File::FilePrivate
|
class MPC::File::FilePrivate {
|
||||||
{
|
public:
|
||||||
public:
|
FilePrivate() : APELocation(-1),
|
||||||
FilePrivate() :
|
APESize(0),
|
||||||
APELocation(-1),
|
ID3v1Location(-1),
|
||||||
APESize(0),
|
ID3v2Header(0),
|
||||||
ID3v1Location(-1),
|
ID3v2Location(-1),
|
||||||
ID3v2Header(0),
|
ID3v2Size(0),
|
||||||
ID3v2Location(-1),
|
properties(0) {}
|
||||||
ID3v2Size(0),
|
|
||||||
properties(0) {}
|
|
||||||
|
|
||||||
~FilePrivate()
|
~FilePrivate() {
|
||||||
{
|
|
||||||
delete ID3v2Header;
|
delete ID3v2Header;
|
||||||
delete properties;
|
delete properties;
|
||||||
}
|
}
|
||||||
@ -79,8 +76,7 @@ public:
|
|||||||
// static members
|
// 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
|
// A newer MPC file has to start with "MPCK" or "MP+", but older files don't
|
||||||
// have keys to do a quick check.
|
// have keys to do a quick check.
|
||||||
|
|
||||||
@ -92,71 +88,60 @@ bool MPC::File::isSupported(IOStream *stream)
|
|||||||
// public members
|
// public members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
MPC::File::File(FileName file, bool readProperties, Properties::ReadStyle) :
|
MPC::File::File(FileName file, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file),
|
||||||
Strawberry_TagLib::TagLib::File(file),
|
d(new FilePrivate()) {
|
||||||
d(new FilePrivate())
|
if (isOpen())
|
||||||
{
|
|
||||||
if(isOpen())
|
|
||||||
read(readProperties);
|
read(readProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
MPC::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) :
|
MPC::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(stream),
|
||||||
Strawberry_TagLib::TagLib::File(stream),
|
d(new FilePrivate()) {
|
||||||
d(new FilePrivate())
|
if (isOpen())
|
||||||
{
|
|
||||||
if(isOpen())
|
|
||||||
read(readProperties);
|
read(readProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
MPC::File::~File()
|
MPC::File::~File() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
Strawberry_TagLib::TagLib::Tag *MPC::File::tag() const
|
Strawberry_TagLib::TagLib::Tag *MPC::File::tag() const {
|
||||||
{
|
|
||||||
return &d->tag;
|
return &d->tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyMap MPC::File::properties() const
|
PropertyMap MPC::File::properties() const {
|
||||||
{
|
|
||||||
return d->tag.properties();
|
return d->tag.properties();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MPC::File::removeUnsupportedProperties(const StringList &properties)
|
void MPC::File::removeUnsupportedProperties(const StringList &properties) {
|
||||||
{
|
|
||||||
d->tag.removeUnsupportedProperties(properties);
|
d->tag.removeUnsupportedProperties(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyMap MPC::File::setProperties(const PropertyMap &properties)
|
PropertyMap MPC::File::setProperties(const PropertyMap &properties) {
|
||||||
{
|
if (ID3v1Tag())
|
||||||
if(ID3v1Tag())
|
|
||||||
ID3v1Tag()->setProperties(properties);
|
ID3v1Tag()->setProperties(properties);
|
||||||
|
|
||||||
return APETag(true)->setProperties(properties);
|
return APETag(true)->setProperties(properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
MPC::Properties *MPC::File::audioProperties() const
|
MPC::Properties *MPC::File::audioProperties() const {
|
||||||
{
|
|
||||||
return d->properties;
|
return d->properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MPC::File::save()
|
bool MPC::File::save() {
|
||||||
{
|
if (readOnly()) {
|
||||||
if(readOnly()) {
|
|
||||||
debug("MPC::File::save() -- File is read only.");
|
debug("MPC::File::save() -- File is read only.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Possibly strip ID3v2 tag
|
// Possibly strip ID3v2 tag
|
||||||
|
|
||||||
if(!d->ID3v2Header && d->ID3v2Location >= 0) {
|
if (!d->ID3v2Header && d->ID3v2Location >= 0) {
|
||||||
removeBlock(d->ID3v2Location, d->ID3v2Size);
|
removeBlock(d->ID3v2Location, d->ID3v2Size);
|
||||||
|
|
||||||
if(d->APELocation >= 0)
|
if (d->APELocation >= 0)
|
||||||
d->APELocation -= d->ID3v2Size;
|
d->APELocation -= d->ID3v2Size;
|
||||||
|
|
||||||
if(d->ID3v1Location >= 0)
|
if (d->ID3v1Location >= 0)
|
||||||
d->ID3v1Location -= d->ID3v2Size;
|
d->ID3v1Location -= d->ID3v2Size;
|
||||||
|
|
||||||
d->ID3v2Location = -1;
|
d->ID3v2Location = -1;
|
||||||
@ -165,11 +150,11 @@ bool MPC::File::save()
|
|||||||
|
|
||||||
// Update ID3v1 tag
|
// 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.
|
// 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);
|
seek(d->ID3v1Location);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -183,7 +168,7 @@ bool MPC::File::save()
|
|||||||
|
|
||||||
// ID3v1 tag is empty. Remove the old one.
|
// ID3v1 tag is empty. Remove the old one.
|
||||||
|
|
||||||
if(d->ID3v1Location >= 0) {
|
if (d->ID3v1Location >= 0) {
|
||||||
truncate(d->ID3v1Location);
|
truncate(d->ID3v1Location);
|
||||||
d->ID3v1Location = -1;
|
d->ID3v1Location = -1;
|
||||||
}
|
}
|
||||||
@ -191,12 +176,12 @@ bool MPC::File::save()
|
|||||||
|
|
||||||
// Update APE tag
|
// 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.
|
// APE tag is not empty. Update the old one or create a new one.
|
||||||
|
|
||||||
if(d->APELocation < 0) {
|
if (d->APELocation < 0) {
|
||||||
if(d->ID3v1Location >= 0)
|
if (d->ID3v1Location >= 0)
|
||||||
d->APELocation = d->ID3v1Location;
|
d->APELocation = d->ID3v1Location;
|
||||||
else
|
else
|
||||||
d->APELocation = length();
|
d->APELocation = length();
|
||||||
@ -205,7 +190,7 @@ bool MPC::File::save()
|
|||||||
const ByteVector data = APETag()->render();
|
const ByteVector data = APETag()->render();
|
||||||
insert(data, d->APELocation, d->APESize);
|
insert(data, d->APELocation, d->APESize);
|
||||||
|
|
||||||
if(d->ID3v1Location >= 0)
|
if (d->ID3v1Location >= 0)
|
||||||
d->ID3v1Location += (static_cast<long>(data.size()) - d->APESize);
|
d->ID3v1Location += (static_cast<long>(data.size()) - d->APESize);
|
||||||
|
|
||||||
d->APESize = data.size();
|
d->APESize = data.size();
|
||||||
@ -214,10 +199,10 @@ bool MPC::File::save()
|
|||||||
|
|
||||||
// APE tag is empty. Remove the old one.
|
// APE tag is empty. Remove the old one.
|
||||||
|
|
||||||
if(d->APELocation >= 0) {
|
if (d->APELocation >= 0) {
|
||||||
removeBlock(d->APELocation, d->APESize);
|
removeBlock(d->APELocation, d->APESize);
|
||||||
|
|
||||||
if(d->ID3v1Location >= 0)
|
if (d->ID3v1Location >= 0)
|
||||||
d->ID3v1Location -= d->APESize;
|
d->ID3v1Location -= d->APESize;
|
||||||
|
|
||||||
d->APELocation = -1;
|
d->APELocation = -1;
|
||||||
@ -228,45 +213,39 @@ bool MPC::File::save()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ID3v1::Tag *MPC::File::ID3v1Tag(bool create)
|
ID3v1::Tag *MPC::File::ID3v1Tag(bool create) {
|
||||||
{
|
|
||||||
return d->tag.access<ID3v1::Tag>(MPCID3v1Index, 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);
|
return d->tag.access<APE::Tag>(MPCAPEIndex, create);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MPC::File::strip(int tags)
|
void MPC::File::strip(int tags) {
|
||||||
{
|
if (tags & ID3v1)
|
||||||
if(tags & ID3v1)
|
|
||||||
d->tag.set(MPCID3v1Index, 0);
|
d->tag.set(MPCID3v1Index, 0);
|
||||||
|
|
||||||
if(tags & APE)
|
if (tags & APE)
|
||||||
d->tag.set(MPCAPEIndex, 0);
|
d->tag.set(MPCAPEIndex, 0);
|
||||||
|
|
||||||
if(!ID3v1Tag())
|
if (!ID3v1Tag())
|
||||||
APETag(true);
|
APETag(true);
|
||||||
|
|
||||||
if(tags & ID3v2) {
|
if (tags & ID3v2) {
|
||||||
delete d->ID3v2Header;
|
delete d->ID3v2Header;
|
||||||
d->ID3v2Header = 0;
|
d->ID3v2Header = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MPC::File::remove(int tags)
|
void MPC::File::remove(int tags) {
|
||||||
{
|
|
||||||
strip(tags);
|
strip(tags);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MPC::File::hasID3v1Tag() const
|
bool MPC::File::hasID3v1Tag() const {
|
||||||
{
|
|
||||||
return (d->ID3v1Location >= 0);
|
return (d->ID3v1Location >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MPC::File::hasAPETag() const
|
bool MPC::File::hasAPETag() const {
|
||||||
{
|
|
||||||
return (d->APELocation >= 0);
|
return (d->APELocation >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -274,13 +253,12 @@ bool MPC::File::hasAPETag() const
|
|||||||
// private members
|
// private members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void MPC::File::read(bool readProperties)
|
void MPC::File::read(bool readProperties) {
|
||||||
{
|
|
||||||
// Look for an ID3v2 tag
|
// Look for an ID3v2 tag
|
||||||
|
|
||||||
d->ID3v2Location = Utils::findID3v2(this);
|
d->ID3v2Location = Utils::findID3v2(this);
|
||||||
|
|
||||||
if(d->ID3v2Location >= 0) {
|
if (d->ID3v2Location >= 0) {
|
||||||
seek(d->ID3v2Location);
|
seek(d->ID3v2Location);
|
||||||
d->ID3v2Header = new ID3v2::Header(readBlock(ID3v2::Header::size()));
|
d->ID3v2Header = new ID3v2::Header(readBlock(ID3v2::Header::size()));
|
||||||
d->ID3v2Size = d->ID3v2Header->completeTagSize();
|
d->ID3v2Size = d->ID3v2Header->completeTagSize();
|
||||||
@ -290,36 +268,36 @@ void MPC::File::read(bool readProperties)
|
|||||||
|
|
||||||
d->ID3v1Location = Utils::findID3v1(this);
|
d->ID3v1Location = Utils::findID3v1(this);
|
||||||
|
|
||||||
if(d->ID3v1Location >= 0)
|
if (d->ID3v1Location >= 0)
|
||||||
d->tag.set(MPCID3v1Index, new ID3v1::Tag(this, d->ID3v1Location));
|
d->tag.set(MPCID3v1Index, new ID3v1::Tag(this, d->ID3v1Location));
|
||||||
|
|
||||||
// Look for an APE tag
|
// Look for an APE tag
|
||||||
|
|
||||||
d->APELocation = Utils::findAPE(this, d->ID3v1Location);
|
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->tag.set(MPCAPEIndex, new APE::Tag(this, d->APELocation));
|
||||||
d->APESize = APETag()->footer()->completeTagSize();
|
d->APESize = APETag()->footer()->completeTagSize();
|
||||||
d->APELocation = d->APELocation + APE::Footer::size() - d->APESize;
|
d->APELocation = d->APELocation + APE::Footer::size() - d->APESize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(d->ID3v1Location < 0)
|
if (d->ID3v1Location < 0)
|
||||||
APETag(true);
|
APETag(true);
|
||||||
|
|
||||||
// Look for MPC metadata
|
// Look for MPC metadata
|
||||||
|
|
||||||
if(readProperties) {
|
if (readProperties) {
|
||||||
|
|
||||||
long streamLength;
|
long streamLength;
|
||||||
|
|
||||||
if(d->APELocation >= 0)
|
if (d->APELocation >= 0)
|
||||||
streamLength = d->APELocation;
|
streamLength = d->APELocation;
|
||||||
else if(d->ID3v1Location >= 0)
|
else if (d->ID3v1Location >= 0)
|
||||||
streamLength = d->ID3v1Location;
|
streamLength = d->ID3v1Location;
|
||||||
else
|
else
|
||||||
streamLength = length();
|
streamLength = length();
|
||||||
|
|
||||||
if(d->ID3v2Location >= 0) {
|
if (d->ID3v2Location >= 0) {
|
||||||
seek(d->ID3v2Location + d->ID3v2Size);
|
seek(d->ID3v2Location + d->ID3v2Size);
|
||||||
streamLength -= (d->ID3v2Location + d->ID3v2Size);
|
streamLength -= (d->ID3v2Location + d->ID3v2Size);
|
||||||
}
|
}
|
||||||
|
137
3rdparty/taglib/mpc/mpcfile.h
vendored
137
3rdparty/taglib/mpc/mpcfile.h
vendored
@ -37,14 +37,18 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
class Tag;
|
class Tag;
|
||||||
|
|
||||||
namespace ID3v1 { class Tag; }
|
namespace ID3v1 {
|
||||||
namespace APE { class Tag; }
|
class Tag;
|
||||||
|
}
|
||||||
|
namespace APE {
|
||||||
|
class Tag;
|
||||||
|
}
|
||||||
|
|
||||||
//! An implementation of MPC metadata
|
//! An implementation of MPC metadata
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* This is 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
|
* This supports ID3v1 and APE (v1 and v2) style comments as well as reading stream
|
||||||
@ -52,11 +56,11 @@ namespace TagLib {
|
|||||||
* and ignored.
|
* 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
|
* This implements and provides an interface for MPC files to the
|
||||||
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
|
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
|
||||||
* the abstract TagLib::File API as well as providing some additional
|
* the abstract TagLib::File API as well as providing some additional
|
||||||
@ -64,36 +68,35 @@ namespace TagLib {
|
|||||||
* The only invalid tag combination supported is an ID3v1 tag after an APE tag.
|
* 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:
|
||||||
public:
|
/*!
|
||||||
/*!
|
|
||||||
* This set of flags is used for various operations and is suitable for
|
* This set of flags is used for various operations and is suitable for
|
||||||
* being OR-ed together.
|
* being OR-ed together.
|
||||||
*/
|
*/
|
||||||
enum TagTypes {
|
enum TagTypes {
|
||||||
//! Empty set. Matches no tag types.
|
//! Empty set. Matches no tag types.
|
||||||
NoTags = 0x0000,
|
NoTags = 0x0000,
|
||||||
//! Matches ID3v1 tags.
|
//! Matches ID3v1 tags.
|
||||||
ID3v1 = 0x0001,
|
ID3v1 = 0x0001,
|
||||||
//! Matches ID3v2 tags.
|
//! Matches ID3v2 tags.
|
||||||
ID3v2 = 0x0002,
|
ID3v2 = 0x0002,
|
||||||
//! Matches APE tags.
|
//! Matches APE tags.
|
||||||
APE = 0x0004,
|
APE = 0x0004,
|
||||||
//! Matches all tag types.
|
//! Matches all tag types.
|
||||||
AllTags = 0xffff
|
AllTags = 0xffff
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs an MPC file from \a file. If \a readProperties is true the
|
* Constructs an MPC file from \a file. If \a readProperties is true the
|
||||||
* file's audio properties will also be read.
|
* file's audio properties will also be read.
|
||||||
*
|
*
|
||||||
* \note In the current implementation, \a propertiesStyle is ignored.
|
* \note In the current implementation, \a propertiesStyle is ignored.
|
||||||
*/
|
*/
|
||||||
File(FileName file, bool readProperties = true,
|
File(FileName file, bool readProperties = true,
|
||||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs an MPC file from \a stream. If \a readProperties is true the
|
* Constructs an MPC file from \a stream. If \a readProperties is true the
|
||||||
* file's audio properties will also be read.
|
* file's audio properties will also be read.
|
||||||
*
|
*
|
||||||
@ -102,50 +105,50 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \note In the current implementation, \a propertiesStyle is ignored.
|
* \note In the current implementation, \a propertiesStyle is ignored.
|
||||||
*/
|
*/
|
||||||
File(IOStream *stream, bool readProperties = true,
|
File(IOStream *stream, bool readProperties = true,
|
||||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys this instance of the File.
|
* Destroys this instance of the File.
|
||||||
*/
|
*/
|
||||||
virtual ~File();
|
virtual ~File();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the Tag for this file. This will be an APE tag, an ID3v1 tag
|
* Returns the Tag for this file. This will be an APE tag, an ID3v1 tag
|
||||||
* or a combination of the two.
|
* or a combination of the two.
|
||||||
*/
|
*/
|
||||||
virtual Strawberry_TagLib::TagLib::Tag *tag() const;
|
virtual Strawberry_TagLib::TagLib::Tag *tag() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Implements the unified property interface -- export function.
|
* Implements the unified property interface -- export function.
|
||||||
* If the file contains both an APE and an ID3v1 tag, only the APE
|
* If the file contains both an APE and an ID3v1 tag, only the APE
|
||||||
* tag will be converted to the PropertyMap.
|
* tag will be converted to the PropertyMap.
|
||||||
*/
|
*/
|
||||||
PropertyMap properties() const;
|
PropertyMap properties() const;
|
||||||
|
|
||||||
void removeUnsupportedProperties(const StringList &properties);
|
void removeUnsupportedProperties(const StringList &properties);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Implements the unified property interface -- import function.
|
* Implements the unified property interface -- import function.
|
||||||
* Affects only the APEv2 tag which will be created if necessary.
|
* Affects only the APEv2 tag which will be created if necessary.
|
||||||
* If an ID3v1 tag exists, it will be updated as well.
|
* If an ID3v1 tag exists, it will be updated as well.
|
||||||
*/
|
*/
|
||||||
PropertyMap setProperties(const PropertyMap &);
|
PropertyMap setProperties(const PropertyMap &);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the MPC::Properties for this file. If no audio properties
|
* Returns the MPC::Properties for this file. If no audio properties
|
||||||
* were read then this will return a null pointer.
|
* were read then this will return a null pointer.
|
||||||
*/
|
*/
|
||||||
virtual Properties *audioProperties() const;
|
virtual Properties *audioProperties() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Saves the file.
|
* Saves the file.
|
||||||
*
|
*
|
||||||
* This returns true if the save was successful.
|
* This returns true if the save was successful.
|
||||||
*/
|
*/
|
||||||
virtual bool save();
|
virtual bool save();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns a pointer to the ID3v1 tag of the file.
|
* Returns a pointer to the ID3v1 tag of the file.
|
||||||
*
|
*
|
||||||
* If \a create is false (the default) this returns a null pointer
|
* If \a create is false (the default) this returns a null pointer
|
||||||
@ -162,9 +165,9 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \see hasID3v1Tag()
|
* \see hasID3v1Tag()
|
||||||
*/
|
*/
|
||||||
ID3v1::Tag *ID3v1Tag(bool create = false);
|
ID3v1::Tag *ID3v1Tag(bool create = false);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns a pointer to the APE tag of the file.
|
* Returns a pointer to the APE tag of the file.
|
||||||
*
|
*
|
||||||
* If \a create is false (the default) this may return a null pointer
|
* If \a create is false (the default) this may return a null pointer
|
||||||
@ -182,9 +185,9 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \see hasAPETag()
|
* \see hasAPETag()
|
||||||
*/
|
*/
|
||||||
APE::Tag *APETag(bool create = false);
|
APE::Tag *APETag(bool create = false);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* This will remove the tags that match the OR-ed together TagTypes from the
|
* This will remove the tags that match the OR-ed together TagTypes from the
|
||||||
* file. By default it removes all tags.
|
* file. By default it removes all tags.
|
||||||
*
|
*
|
||||||
@ -193,48 +196,48 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \note In order to make the removal permanent save() still needs to be called.
|
* \note In order to make the removal permanent save() still needs to be called.
|
||||||
*/
|
*/
|
||||||
void strip(int tags = AllTags);
|
void strip(int tags = AllTags);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \deprecated
|
* \deprecated
|
||||||
* \see strip
|
* \see strip
|
||||||
*/
|
*/
|
||||||
TAGLIB_DEPRECATED void remove(int tags = AllTags);
|
TAGLIB_DEPRECATED void remove(int tags = AllTags);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns whether or not the file on disk actually has an ID3v1 tag.
|
* Returns whether or not the file on disk actually has an ID3v1 tag.
|
||||||
*
|
*
|
||||||
* \see ID3v1Tag()
|
* \see ID3v1Tag()
|
||||||
*/
|
*/
|
||||||
bool hasID3v1Tag() const;
|
bool hasID3v1Tag() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns whether or not the file on disk actually has an APE tag.
|
* Returns whether or not the file on disk actually has an APE tag.
|
||||||
*
|
*
|
||||||
* \see APETag()
|
* \see APETag()
|
||||||
*/
|
*/
|
||||||
bool hasAPETag() const;
|
bool hasAPETag() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns whether or not the given \a stream can be opened as an MPC
|
* Returns whether or not the given \a stream can be opened as an MPC
|
||||||
* file.
|
* file.
|
||||||
*
|
*
|
||||||
* \note This method is designed to do a quick check. The result may
|
* \note This method is designed to do a quick check. The result may
|
||||||
* not necessarily be correct.
|
* not necessarily be correct.
|
||||||
*/
|
*/
|
||||||
static bool isSupported(IOStream *stream);
|
static bool isSupported(IOStream *stream);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
File(const File &);
|
File(const File &);
|
||||||
File &operator=(const File &);
|
File &operator=(const File &);
|
||||||
|
|
||||||
void read(bool readProperties);
|
void read(bool readProperties);
|
||||||
|
|
||||||
class FilePrivate;
|
class FilePrivate;
|
||||||
FilePrivate *d;
|
FilePrivate *d;
|
||||||
};
|
};
|
||||||
}
|
} // namespace MPC
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
213
3rdparty/taglib/mpc/mpcproperties.cpp
vendored
213
3rdparty/taglib/mpc/mpcproperties.cpp
vendored
@ -33,21 +33,19 @@
|
|||||||
|
|
||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
class MPC::Properties::PropertiesPrivate
|
class MPC::Properties::PropertiesPrivate {
|
||||||
{
|
public:
|
||||||
public:
|
PropertiesPrivate() : version(0),
|
||||||
PropertiesPrivate() :
|
length(0),
|
||||||
version(0),
|
bitrate(0),
|
||||||
length(0),
|
sampleRate(0),
|
||||||
bitrate(0),
|
channels(0),
|
||||||
sampleRate(0),
|
totalFrames(0),
|
||||||
channels(0),
|
sampleFrames(0),
|
||||||
totalFrames(0),
|
trackGain(0),
|
||||||
sampleFrames(0),
|
trackPeak(0),
|
||||||
trackGain(0),
|
albumGain(0),
|
||||||
trackPeak(0),
|
albumPeak(0) {}
|
||||||
albumGain(0),
|
|
||||||
albumPeak(0) {}
|
|
||||||
|
|
||||||
int version;
|
int version;
|
||||||
int length;
|
int length;
|
||||||
@ -66,19 +64,15 @@ public:
|
|||||||
// public members
|
// public members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
MPC::Properties::Properties(const ByteVector &data, long streamLength, ReadStyle style) :
|
MPC::Properties::Properties(const ByteVector &data, long streamLength, ReadStyle style) : AudioProperties(style),
|
||||||
AudioProperties(style),
|
d(new PropertiesPrivate()) {
|
||||||
d(new PropertiesPrivate())
|
|
||||||
{
|
|
||||||
readSV7(data, streamLength);
|
readSV7(data, streamLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
MPC::Properties::Properties(File *file, long streamLength, ReadStyle style) :
|
MPC::Properties::Properties(File *file, long streamLength, ReadStyle style) : AudioProperties(style),
|
||||||
AudioProperties(style),
|
d(new PropertiesPrivate()) {
|
||||||
d(new PropertiesPrivate())
|
|
||||||
{
|
|
||||||
ByteVector magic = file->readBlock(4);
|
ByteVector magic = file->readBlock(4);
|
||||||
if(magic == "MPCK") {
|
if (magic == "MPCK") {
|
||||||
// Musepack version 8
|
// Musepack version 8
|
||||||
readSV8(file, streamLength);
|
readSV8(file, streamLength);
|
||||||
}
|
}
|
||||||
@ -88,73 +82,59 @@ MPC::Properties::Properties(File *file, long streamLength, ReadStyle style) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MPC::Properties::~Properties()
|
MPC::Properties::~Properties() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MPC::Properties::length() const
|
int MPC::Properties::length() const {
|
||||||
{
|
|
||||||
return lengthInSeconds();
|
return lengthInSeconds();
|
||||||
}
|
}
|
||||||
|
|
||||||
int MPC::Properties::lengthInSeconds() const
|
int MPC::Properties::lengthInSeconds() const {
|
||||||
{
|
|
||||||
return d->length / 1000;
|
return d->length / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MPC::Properties::lengthInMilliseconds() const
|
int MPC::Properties::lengthInMilliseconds() const {
|
||||||
{
|
|
||||||
return d->length;
|
return d->length;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MPC::Properties::bitrate() const
|
int MPC::Properties::bitrate() const {
|
||||||
{
|
|
||||||
return d->bitrate;
|
return d->bitrate;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MPC::Properties::sampleRate() const
|
int MPC::Properties::sampleRate() const {
|
||||||
{
|
|
||||||
return d->sampleRate;
|
return d->sampleRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MPC::Properties::channels() const
|
int MPC::Properties::channels() const {
|
||||||
{
|
|
||||||
return d->channels;
|
return d->channels;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MPC::Properties::mpcVersion() const
|
int MPC::Properties::mpcVersion() const {
|
||||||
{
|
|
||||||
return d->version;
|
return d->version;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int MPC::Properties::totalFrames() const
|
unsigned int MPC::Properties::totalFrames() const {
|
||||||
{
|
|
||||||
return d->totalFrames;
|
return d->totalFrames;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int MPC::Properties::sampleFrames() const
|
unsigned int MPC::Properties::sampleFrames() const {
|
||||||
{
|
|
||||||
return d->sampleFrames;
|
return d->sampleFrames;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MPC::Properties::trackGain() const
|
int MPC::Properties::trackGain() const {
|
||||||
{
|
|
||||||
return d->trackGain;
|
return d->trackGain;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MPC::Properties::trackPeak() const
|
int MPC::Properties::trackPeak() const {
|
||||||
{
|
|
||||||
return d->trackPeak;
|
return d->trackPeak;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MPC::Properties::albumGain() const
|
int MPC::Properties::albumGain() const {
|
||||||
{
|
|
||||||
return d->albumGain;
|
return d->albumGain;
|
||||||
}
|
}
|
||||||
|
|
||||||
int MPC::Properties::albumPeak() const
|
int MPC::Properties::albumPeak() const {
|
||||||
{
|
|
||||||
return d->albumPeak;
|
return d->albumPeak;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -162,58 +142,54 @@ int MPC::Properties::albumPeak() const
|
|||||||
// private members
|
// private members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
namespace
|
namespace {
|
||||||
{
|
unsigned long readSize(File *file, unsigned int &sizeLength, bool &eof) {
|
||||||
unsigned long readSize(File *file, unsigned int &sizeLength, bool &eof)
|
sizeLength = 0;
|
||||||
{
|
eof = false;
|
||||||
sizeLength = 0;
|
|
||||||
eof = false;
|
|
||||||
|
|
||||||
unsigned char tmp;
|
unsigned char tmp;
|
||||||
unsigned long size = 0;
|
unsigned long size = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
const ByteVector b = file->readBlock(1);
|
const ByteVector b = file->readBlock(1);
|
||||||
if(b.isEmpty()) {
|
if (b.isEmpty()) {
|
||||||
eof = true;
|
eof = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp = b[0];
|
tmp = b[0];
|
||||||
size = (size << 7) | (tmp & 0x7F);
|
size = (size << 7) | (tmp & 0x7F);
|
||||||
sizeLength++;
|
sizeLength++;
|
||||||
} while((tmp & 0x80));
|
} while ((tmp & 0x80));
|
||||||
return size;
|
return size;
|
||||||
}
|
|
||||||
|
|
||||||
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()));
|
|
||||||
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)
|
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()));
|
||||||
|
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 };
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
void MPC::Properties::readSV8(File *file, long streamLength) {
|
||||||
bool readSH = false, readRG = false;
|
bool readSH = false, readRG = false;
|
||||||
|
|
||||||
while(!readSH && !readRG) {
|
while (!readSH && !readRG) {
|
||||||
const ByteVector packetType = file->readBlock(2);
|
const ByteVector packetType = file->readBlock(2);
|
||||||
|
|
||||||
unsigned int packetSizeLength;
|
unsigned int packetSizeLength;
|
||||||
bool eof;
|
bool eof;
|
||||||
const unsigned long packetSize = readSize(file, packetSizeLength, eof);
|
const unsigned long packetSize = readSize(file, packetSizeLength, eof);
|
||||||
if(eof) {
|
if (eof) {
|
||||||
debug("MPC::Properties::readSV8() - Reached to EOF.");
|
debug("MPC::Properties::readSV8() - Reached to EOF.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -221,16 +197,16 @@ void MPC::Properties::readSV8(File *file, long streamLength)
|
|||||||
const unsigned long dataSize = packetSize - 2 - packetSizeLength;
|
const unsigned long dataSize = packetSize - 2 - packetSizeLength;
|
||||||
|
|
||||||
const ByteVector data = file->readBlock(dataSize);
|
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.");
|
debug("MPC::Properties::readSV8() - dataSize doesn't match the actual data size.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(packetType == "SH") {
|
if (packetType == "SH") {
|
||||||
// Stream Header
|
// Stream Header
|
||||||
// http://trac.musepack.net/wiki/SV8Specification#StreamHeaderPacket
|
// http://trac.musepack.net/wiki/SV8Specification#StreamHeaderPacket
|
||||||
|
|
||||||
if(dataSize <= 5) {
|
if (dataSize <= 5) {
|
||||||
debug("MPC::Properties::readSV8() - \"SH\" packet is too short to parse.");
|
debug("MPC::Properties::readSV8() - \"SH\" packet is too short to parse.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -241,13 +217,13 @@ void MPC::Properties::readSV8(File *file, long streamLength)
|
|||||||
d->version = data[pos];
|
d->version = data[pos];
|
||||||
pos += 1;
|
pos += 1;
|
||||||
d->sampleFrames = readSize(data, pos);
|
d->sampleFrames = readSize(data, pos);
|
||||||
if(pos > dataSize - 3) {
|
if (pos > dataSize - 3) {
|
||||||
debug("MPC::Properties::readSV8() - \"SH\" packet is corrupt.");
|
debug("MPC::Properties::readSV8() - \"SH\" packet is corrupt.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const unsigned long begSilence = readSize(data, pos);
|
const unsigned long begSilence = readSize(data, pos);
|
||||||
if(pos > dataSize - 2) {
|
if (pos > dataSize - 2) {
|
||||||
debug("MPC::Properties::readSV8() - \"SH\" packet is corrupt.");
|
debug("MPC::Properties::readSV8() - \"SH\" packet is corrupt.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -256,12 +232,12 @@ void MPC::Properties::readSV8(File *file, long streamLength)
|
|||||||
pos += 2;
|
pos += 2;
|
||||||
|
|
||||||
d->sampleRate = sftable[(flags >> 13) & 0x07];
|
d->sampleRate = sftable[(flags >> 13) & 0x07];
|
||||||
d->channels = ((flags >> 4) & 0x0F) + 1;
|
d->channels = ((flags >> 4) & 0x0F) + 1;
|
||||||
|
|
||||||
const unsigned int frameCount = d->sampleFrames - begSilence;
|
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;
|
const double length = frameCount * 1000.0 / d->sampleRate;
|
||||||
d->length = static_cast<int>(length + 0.5);
|
d->length = static_cast<int>(length + 0.5);
|
||||||
d->bitrate = static_cast<int>(streamLength * 8.0 / 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
|
// Replay Gain
|
||||||
// http://trac.musepack.net/wiki/SV8Specification#ReplaygainPacket
|
// http://trac.musepack.net/wiki/SV8Specification#ReplaygainPacket
|
||||||
|
|
||||||
if(dataSize <= 9) {
|
if (dataSize <= 9) {
|
||||||
debug("MPC::Properties::readSV8() - \"RG\" packet is too short to parse.");
|
debug("MPC::Properties::readSV8() - \"RG\" packet is too short to parse.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -277,7 +253,7 @@ void MPC::Properties::readSV8(File *file, long streamLength)
|
|||||||
readRG = true;
|
readRG = true;
|
||||||
|
|
||||||
const int replayGainVersion = data[0];
|
const int replayGainVersion = data[0];
|
||||||
if(replayGainVersion == 1) {
|
if (replayGainVersion == 1) {
|
||||||
d->trackGain = data.toShort(1, true);
|
d->trackGain = data.toShort(1, true);
|
||||||
d->trackPeak = data.toShort(3, true);
|
d->trackPeak = data.toShort(3, true);
|
||||||
d->albumGain = data.toShort(5, 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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -295,18 +271,17 @@ void MPC::Properties::readSV8(File *file, long streamLength)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MPC::Properties::readSV7(const ByteVector &data, long streamLength)
|
void MPC::Properties::readSV7(const ByteVector &data, long streamLength) {
|
||||||
{
|
if (data.startsWith("MP+")) {
|
||||||
if(data.startsWith("MP+")) {
|
|
||||||
d->version = data[3] & 15;
|
d->version = data[3] & 15;
|
||||||
if(d->version < 7)
|
if (d->version < 7)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
d->totalFrames = data.toUInt(4, false);
|
d->totalFrames = data.toUInt(4, false);
|
||||||
|
|
||||||
const unsigned int flags = data.toUInt(8, false);
|
const unsigned int flags = data.toUInt(8, false);
|
||||||
d->sampleRate = sftable[(flags >> 16) & 0x03];
|
d->sampleRate = sftable[(flags >> 16) & 0x03];
|
||||||
d->channels = 2;
|
d->channels = 2;
|
||||||
|
|
||||||
const unsigned int gapless = data.toUInt(5, false);
|
const unsigned int gapless = data.toUInt(5, false);
|
||||||
|
|
||||||
@ -316,15 +291,15 @@ void MPC::Properties::readSV7(const ByteVector &data, long streamLength)
|
|||||||
d->albumPeak = data.toUShort(16, false);
|
d->albumPeak = data.toUShort(16, false);
|
||||||
|
|
||||||
// convert gain info
|
// convert gain info
|
||||||
if(d->trackGain != 0) {
|
if (d->trackGain != 0) {
|
||||||
int tmp = (int)((64.82 - (short)d->trackGain / 100.) * 256. + .5);
|
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;
|
d->trackGain = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(d->albumGain != 0) {
|
if (d->albumGain != 0) {
|
||||||
int tmp = (int)((64.82 - d->albumGain / 100.) * 256. + .5);
|
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;
|
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);
|
d->albumPeak = (int)(log10((double)d->albumPeak) * 20 * 256 + .5);
|
||||||
|
|
||||||
bool trueGapless = (gapless >> 31) & 0x0001;
|
bool trueGapless = (gapless >> 31) & 0x0001;
|
||||||
if(trueGapless) {
|
if (trueGapless) {
|
||||||
unsigned int lastFrameSamples = (gapless >> 20) & 0x07FF;
|
unsigned int lastFrameSamples = (gapless >> 20) & 0x07FF;
|
||||||
d->sampleFrames = d->totalFrames * 1152 - lastFrameSamples;
|
d->sampleFrames = d->totalFrames * 1152 - lastFrameSamples;
|
||||||
}
|
}
|
||||||
@ -345,12 +320,12 @@ void MPC::Properties::readSV7(const ByteVector &data, long streamLength)
|
|||||||
else {
|
else {
|
||||||
const unsigned int headerData = data.toUInt(0, false);
|
const unsigned int headerData = data.toUInt(0, false);
|
||||||
|
|
||||||
d->bitrate = (headerData >> 23) & 0x01ff;
|
d->bitrate = (headerData >> 23) & 0x01ff;
|
||||||
d->version = (headerData >> 11) & 0x03ff;
|
d->version = (headerData >> 11) & 0x03ff;
|
||||||
d->sampleRate = 44100;
|
d->sampleRate = 44100;
|
||||||
d->channels = 2;
|
d->channels = 2;
|
||||||
|
|
||||||
if(d->version >= 5)
|
if (d->version >= 5)
|
||||||
d->totalFrames = data.toUInt(4, false);
|
d->totalFrames = data.toUInt(4, false);
|
||||||
else
|
else
|
||||||
d->totalFrames = data.toUShort(6, false);
|
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;
|
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;
|
const double length = d->sampleFrames * 1000.0 / d->sampleRate;
|
||||||
d->length = static_cast<int>(length + 0.5);
|
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);
|
d->bitrate = static_cast<int>(streamLength * 8.0 / length + 0.5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
101
3rdparty/taglib/mpc/mpcproperties.h
vendored
101
3rdparty/taglib/mpc/mpcproperties.h
vendored
@ -32,42 +32,41 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace 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
|
* This reads the data from an MPC stream found in the AudioProperties
|
||||||
* API.
|
* API.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class TAGLIB_EXPORT Properties : public AudioProperties
|
class TAGLIB_EXPORT Properties : public AudioProperties {
|
||||||
{
|
public:
|
||||||
public:
|
/*!
|
||||||
/*!
|
|
||||||
* Create an instance of MPC::Properties with the data read from the
|
* Create an instance of MPC::Properties with the data read from the
|
||||||
* ByteVector \a data.
|
* ByteVector \a data.
|
||||||
*
|
*
|
||||||
* This constructor is deprecated. It only works for MPC version up to 7.
|
* This constructor is deprecated. It only works for MPC version up to 7.
|
||||||
*/
|
*/
|
||||||
Properties(const ByteVector &data, long streamLength, ReadStyle style = Average);
|
Properties(const ByteVector &data, long streamLength, ReadStyle style = Average);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Create an instance of MPC::Properties with the data read directly
|
* Create an instance of MPC::Properties with the data read directly
|
||||||
* from a MPC::File.
|
* from a MPC::File.
|
||||||
*/
|
*/
|
||||||
Properties(File *file, long streamLength, ReadStyle style = Average);
|
Properties(File *file, long streamLength, ReadStyle style = Average);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys this MPC::Properties instance.
|
* Destroys this MPC::Properties instance.
|
||||||
*/
|
*/
|
||||||
virtual ~Properties();
|
virtual ~Properties();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the length of the file in seconds. The length is rounded down to
|
* Returns the length of the file in seconds. The length is rounded down to
|
||||||
* the nearest whole second.
|
* the nearest whole second.
|
||||||
*
|
*
|
||||||
@ -75,86 +74,86 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \deprecated
|
* \deprecated
|
||||||
*/
|
*/
|
||||||
TAGLIB_DEPRECATED virtual int length() const;
|
TAGLIB_DEPRECATED virtual int length() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the length of the file in seconds. The length is rounded down to
|
* Returns the length of the file in seconds. The length is rounded down to
|
||||||
* the nearest whole second.
|
* the nearest whole second.
|
||||||
*
|
*
|
||||||
* \see lengthInMilliseconds()
|
* \see lengthInMilliseconds()
|
||||||
*/
|
*/
|
||||||
// BIC: make virtual
|
// BIC: make virtual
|
||||||
int lengthInSeconds() const;
|
int lengthInSeconds() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the length of the file in milliseconds.
|
* Returns the length of the file in milliseconds.
|
||||||
*
|
*
|
||||||
* \see lengthInSeconds()
|
* \see lengthInSeconds()
|
||||||
*/
|
*/
|
||||||
// BIC: make virtual
|
// BIC: make virtual
|
||||||
int lengthInMilliseconds() const;
|
int lengthInMilliseconds() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the average bit rate of the file in kb/s.
|
* Returns the average bit rate of the file in kb/s.
|
||||||
*/
|
*/
|
||||||
virtual int bitrate() const;
|
virtual int bitrate() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the sample rate in Hz.
|
* Returns the sample rate in Hz.
|
||||||
*/
|
*/
|
||||||
virtual int sampleRate() const;
|
virtual int sampleRate() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the number of audio channels.
|
* Returns the number of audio channels.
|
||||||
*/
|
*/
|
||||||
virtual int channels() const;
|
virtual int channels() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the version of the bitstream (SV4-SV8)
|
* Returns the version of the bitstream (SV4-SV8)
|
||||||
*/
|
*/
|
||||||
int mpcVersion() const;
|
int mpcVersion() const;
|
||||||
|
|
||||||
unsigned int totalFrames() const;
|
unsigned int totalFrames() const;
|
||||||
unsigned int sampleFrames() const;
|
unsigned int sampleFrames() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the track gain as an integer value,
|
* Returns the track gain as an integer value,
|
||||||
* to convert to dB: trackGain in dB = 64.82 - (trackGain / 256)
|
* to convert to dB: trackGain in dB = 64.82 - (trackGain / 256)
|
||||||
*/
|
*/
|
||||||
int trackGain() const;
|
int trackGain() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the track peak as an integer value,
|
* Returns the track peak as an integer value,
|
||||||
* to convert to dB: trackPeak in dB = trackPeak / 256
|
* to convert to dB: trackPeak in dB = trackPeak / 256
|
||||||
* to convert to floating [-1..1]: trackPeak = 10^(trackPeak / 256 / 20)/32768
|
* to convert to floating [-1..1]: trackPeak = 10^(trackPeak / 256 / 20)/32768
|
||||||
*/
|
*/
|
||||||
int trackPeak() const;
|
int trackPeak() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the album gain as an integer value,
|
* Returns the album gain as an integer value,
|
||||||
* to convert to dB: albumGain in dB = 64.82 - (albumGain / 256)
|
* to convert to dB: albumGain in dB = 64.82 - (albumGain / 256)
|
||||||
*/
|
*/
|
||||||
int albumGain() const;
|
int albumGain() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the album peak as an integer value,
|
* Returns the album peak as an integer value,
|
||||||
* to convert to dB: albumPeak in dB = albumPeak / 256
|
* to convert to dB: albumPeak in dB = albumPeak / 256
|
||||||
* to convert to floating [-1..1]: albumPeak = 10^(albumPeak / 256 / 20)/32768
|
* to convert to floating [-1..1]: albumPeak = 10^(albumPeak / 256 / 20)/32768
|
||||||
*/
|
*/
|
||||||
int albumPeak() const;
|
int albumPeak() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Properties(const Properties &);
|
Properties(const Properties &);
|
||||||
Properties &operator=(const Properties &);
|
Properties &operator=(const Properties &);
|
||||||
|
|
||||||
void readSV7(const ByteVector &data, long streamLength);
|
void readSV7(const ByteVector &data, long streamLength);
|
||||||
void readSV8(File *file, long streamLength);
|
void readSV8(File *file, long streamLength);
|
||||||
|
|
||||||
class PropertiesPrivate;
|
class PropertiesPrivate;
|
||||||
PropertiesPrivate *d;
|
PropertiesPrivate *d;
|
||||||
};
|
};
|
||||||
}
|
} // namespace MPC
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
419
3rdparty/taglib/mpeg/id3v1/id3v1genres.cpp
vendored
419
3rdparty/taglib/mpeg/id3v1/id3v1genres.cpp
vendored
@ -27,237 +27,232 @@
|
|||||||
|
|
||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
namespace
|
namespace {
|
||||||
{
|
const wchar_t *genres[] = {
|
||||||
const wchar_t *genres[] = {
|
L"Blues",
|
||||||
L"Blues",
|
L"Classic Rock",
|
||||||
L"Classic Rock",
|
L"Country",
|
||||||
L"Country",
|
L"Dance",
|
||||||
L"Dance",
|
L"Disco",
|
||||||
L"Disco",
|
L"Funk",
|
||||||
L"Funk",
|
L"Grunge",
|
||||||
L"Grunge",
|
L"Hip-Hop",
|
||||||
L"Hip-Hop",
|
L"Jazz",
|
||||||
L"Jazz",
|
L"Metal",
|
||||||
L"Metal",
|
L"New Age",
|
||||||
L"New Age",
|
L"Oldies",
|
||||||
L"Oldies",
|
L"Other",
|
||||||
L"Other",
|
L"Pop",
|
||||||
L"Pop",
|
L"R&B",
|
||||||
L"R&B",
|
L"Rap",
|
||||||
L"Rap",
|
L"Reggae",
|
||||||
L"Reggae",
|
L"Rock",
|
||||||
L"Rock",
|
L"Techno",
|
||||||
L"Techno",
|
L"Industrial",
|
||||||
L"Industrial",
|
L"Alternative",
|
||||||
L"Alternative",
|
L"Ska",
|
||||||
L"Ska",
|
L"Death Metal",
|
||||||
L"Death Metal",
|
L"Pranks",
|
||||||
L"Pranks",
|
L"Soundtrack",
|
||||||
L"Soundtrack",
|
L"Euro-Techno",
|
||||||
L"Euro-Techno",
|
L"Ambient",
|
||||||
L"Ambient",
|
L"Trip-Hop",
|
||||||
L"Trip-Hop",
|
L"Vocal",
|
||||||
L"Vocal",
|
L"Jazz+Funk",
|
||||||
L"Jazz+Funk",
|
L"Fusion",
|
||||||
L"Fusion",
|
L"Trance",
|
||||||
L"Trance",
|
L"Classical",
|
||||||
L"Classical",
|
L"Instrumental",
|
||||||
L"Instrumental",
|
L"Acid",
|
||||||
L"Acid",
|
L"House",
|
||||||
L"House",
|
L"Game",
|
||||||
L"Game",
|
L"Sound Clip",
|
||||||
L"Sound Clip",
|
L"Gospel",
|
||||||
L"Gospel",
|
L"Noise",
|
||||||
L"Noise",
|
L"Alternative Rock",
|
||||||
L"Alternative Rock",
|
L"Bass",
|
||||||
L"Bass",
|
L"Soul",
|
||||||
L"Soul",
|
L"Punk",
|
||||||
L"Punk",
|
L"Space",
|
||||||
L"Space",
|
L"Meditative",
|
||||||
L"Meditative",
|
L"Instrumental Pop",
|
||||||
L"Instrumental Pop",
|
L"Instrumental Rock",
|
||||||
L"Instrumental Rock",
|
L"Ethnic",
|
||||||
L"Ethnic",
|
L"Gothic",
|
||||||
L"Gothic",
|
L"Darkwave",
|
||||||
L"Darkwave",
|
L"Techno-Industrial",
|
||||||
L"Techno-Industrial",
|
L"Electronic",
|
||||||
L"Electronic",
|
L"Pop-Folk",
|
||||||
L"Pop-Folk",
|
L"Eurodance",
|
||||||
L"Eurodance",
|
L"Dream",
|
||||||
L"Dream",
|
L"Southern Rock",
|
||||||
L"Southern Rock",
|
L"Comedy",
|
||||||
L"Comedy",
|
L"Cult",
|
||||||
L"Cult",
|
L"Gangsta",
|
||||||
L"Gangsta",
|
L"Top 40",
|
||||||
L"Top 40",
|
L"Christian Rap",
|
||||||
L"Christian Rap",
|
L"Pop/Funk",
|
||||||
L"Pop/Funk",
|
L"Jungle",
|
||||||
L"Jungle",
|
L"Native American",
|
||||||
L"Native American",
|
L"Cabaret",
|
||||||
L"Cabaret",
|
L"New Wave",
|
||||||
L"New Wave",
|
L"Psychedelic",
|
||||||
L"Psychedelic",
|
L"Rave",
|
||||||
L"Rave",
|
L"Showtunes",
|
||||||
L"Showtunes",
|
L"Trailer",
|
||||||
L"Trailer",
|
L"Lo-Fi",
|
||||||
L"Lo-Fi",
|
L"Tribal",
|
||||||
L"Tribal",
|
L"Acid Punk",
|
||||||
L"Acid Punk",
|
L"Acid Jazz",
|
||||||
L"Acid Jazz",
|
L"Polka",
|
||||||
L"Polka",
|
L"Retro",
|
||||||
L"Retro",
|
L"Musical",
|
||||||
L"Musical",
|
L"Rock & Roll",
|
||||||
L"Rock & Roll",
|
L"Hard Rock",
|
||||||
L"Hard Rock",
|
L"Folk",
|
||||||
L"Folk",
|
L"Folk/Rock",
|
||||||
L"Folk/Rock",
|
L"National Folk",
|
||||||
L"National Folk",
|
L"Swing",
|
||||||
L"Swing",
|
L"Fusion",
|
||||||
L"Fusion",
|
L"Bebob",
|
||||||
L"Bebob",
|
L"Latin",
|
||||||
L"Latin",
|
L"Revival",
|
||||||
L"Revival",
|
L"Celtic",
|
||||||
L"Celtic",
|
L"Bluegrass",
|
||||||
L"Bluegrass",
|
L"Avantgarde",
|
||||||
L"Avantgarde",
|
L"Gothic Rock",
|
||||||
L"Gothic Rock",
|
L"Progressive Rock",
|
||||||
L"Progressive Rock",
|
L"Psychedelic Rock",
|
||||||
L"Psychedelic Rock",
|
L"Symphonic Rock",
|
||||||
L"Symphonic Rock",
|
L"Slow Rock",
|
||||||
L"Slow Rock",
|
L"Big Band",
|
||||||
L"Big Band",
|
L"Chorus",
|
||||||
L"Chorus",
|
L"Easy Listening",
|
||||||
L"Easy Listening",
|
L"Acoustic",
|
||||||
L"Acoustic",
|
L"Humour",
|
||||||
L"Humour",
|
L"Speech",
|
||||||
L"Speech",
|
L"Chanson",
|
||||||
L"Chanson",
|
L"Opera",
|
||||||
L"Opera",
|
L"Chamber Music",
|
||||||
L"Chamber Music",
|
L"Sonata",
|
||||||
L"Sonata",
|
L"Symphony",
|
||||||
L"Symphony",
|
L"Booty Bass",
|
||||||
L"Booty Bass",
|
L"Primus",
|
||||||
L"Primus",
|
L"Porn Groove",
|
||||||
L"Porn Groove",
|
L"Satire",
|
||||||
L"Satire",
|
L"Slow Jam",
|
||||||
L"Slow Jam",
|
L"Club",
|
||||||
L"Club",
|
L"Tango",
|
||||||
L"Tango",
|
L"Samba",
|
||||||
L"Samba",
|
L"Folklore",
|
||||||
L"Folklore",
|
L"Ballad",
|
||||||
L"Ballad",
|
L"Power Ballad",
|
||||||
L"Power Ballad",
|
L"Rhythmic Soul",
|
||||||
L"Rhythmic Soul",
|
L"Freestyle",
|
||||||
L"Freestyle",
|
L"Duet",
|
||||||
L"Duet",
|
L"Punk Rock",
|
||||||
L"Punk Rock",
|
L"Drum Solo",
|
||||||
L"Drum Solo",
|
L"A Cappella",
|
||||||
L"A Cappella",
|
L"Euro-House",
|
||||||
L"Euro-House",
|
L"Dance Hall",
|
||||||
L"Dance Hall",
|
L"Goa",
|
||||||
L"Goa",
|
L"Drum & Bass",
|
||||||
L"Drum & Bass",
|
L"Club-House",
|
||||||
L"Club-House",
|
L"Hardcore",
|
||||||
L"Hardcore",
|
L"Terror",
|
||||||
L"Terror",
|
L"Indie",
|
||||||
L"Indie",
|
L"BritPop",
|
||||||
L"BritPop",
|
L"Negerpunk",
|
||||||
L"Negerpunk",
|
L"Polsk Punk",
|
||||||
L"Polsk Punk",
|
L"Beat",
|
||||||
L"Beat",
|
L"Christian Gangsta Rap",
|
||||||
L"Christian Gangsta Rap",
|
L"Heavy Metal",
|
||||||
L"Heavy Metal",
|
L"Black Metal",
|
||||||
L"Black Metal",
|
L"Crossover",
|
||||||
L"Crossover",
|
L"Contemporary Christian",
|
||||||
L"Contemporary Christian",
|
L"Christian Rock",
|
||||||
L"Christian Rock",
|
L"Merengue",
|
||||||
L"Merengue",
|
L"Salsa",
|
||||||
L"Salsa",
|
L"Thrash Metal",
|
||||||
L"Thrash Metal",
|
L"Anime",
|
||||||
L"Anime",
|
L"Jpop",
|
||||||
L"Jpop",
|
L"Synthpop",
|
||||||
L"Synthpop",
|
L"Abstract",
|
||||||
L"Abstract",
|
L"Art Rock",
|
||||||
L"Art Rock",
|
L"Baroque",
|
||||||
L"Baroque",
|
L"Bhangra",
|
||||||
L"Bhangra",
|
L"Big Beat",
|
||||||
L"Big Beat",
|
L"Breakbeat",
|
||||||
L"Breakbeat",
|
L"Chillout",
|
||||||
L"Chillout",
|
L"Downtempo",
|
||||||
L"Downtempo",
|
L"Dub",
|
||||||
L"Dub",
|
L"EBM",
|
||||||
L"EBM",
|
L"Eclectic",
|
||||||
L"Eclectic",
|
L"Electro",
|
||||||
L"Electro",
|
L"Electroclash",
|
||||||
L"Electroclash",
|
L"Emo",
|
||||||
L"Emo",
|
L"Experimental",
|
||||||
L"Experimental",
|
L"Garage",
|
||||||
L"Garage",
|
L"Global",
|
||||||
L"Global",
|
L"IDM",
|
||||||
L"IDM",
|
L"Illbient",
|
||||||
L"Illbient",
|
L"Industro-Goth",
|
||||||
L"Industro-Goth",
|
L"Jam Band",
|
||||||
L"Jam Band",
|
L"Krautrock",
|
||||||
L"Krautrock",
|
L"Leftfield",
|
||||||
L"Leftfield",
|
L"Lounge",
|
||||||
L"Lounge",
|
L"Math Rock",
|
||||||
L"Math Rock",
|
L"New Romantic",
|
||||||
L"New Romantic",
|
L"Nu-Breakz",
|
||||||
L"Nu-Breakz",
|
L"Post-Punk",
|
||||||
L"Post-Punk",
|
L"Post-Rock",
|
||||||
L"Post-Rock",
|
L"Psytrance",
|
||||||
L"Psytrance",
|
L"Shoegaze",
|
||||||
L"Shoegaze",
|
L"Space Rock",
|
||||||
L"Space Rock",
|
L"Trop Rock",
|
||||||
L"Trop Rock",
|
L"World Music",
|
||||||
L"World Music",
|
L"Neoclassical",
|
||||||
L"Neoclassical",
|
L"Audiobook",
|
||||||
L"Audiobook",
|
L"Audio Theatre",
|
||||||
L"Audio Theatre",
|
L"Neue Deutsche Welle",
|
||||||
L"Neue Deutsche Welle",
|
L"Podcast",
|
||||||
L"Podcast",
|
L"Indie Rock",
|
||||||
L"Indie Rock",
|
L"G-Funk",
|
||||||
L"G-Funk",
|
L"Dubstep",
|
||||||
L"Dubstep",
|
L"Garage Rock",
|
||||||
L"Garage Rock",
|
L"Psybient"
|
||||||
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;
|
StringList l;
|
||||||
for(int i = 0; i < genresSize; i++) {
|
for (int i = 0; i < genresSize; i++) {
|
||||||
l.append(genres[i]);
|
l.append(genres[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return l;
|
return l;
|
||||||
}
|
}
|
||||||
|
|
||||||
ID3v1::GenreMap ID3v1::genreMap()
|
ID3v1::GenreMap ID3v1::genreMap() {
|
||||||
{
|
|
||||||
GenreMap m;
|
GenreMap m;
|
||||||
for(int i = 0; i < genresSize; i++) {
|
for (int i = 0; i < genresSize; i++) {
|
||||||
m.insert(genres[i], i);
|
m.insert(genres[i], i);
|
||||||
}
|
}
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
String ID3v1::genre(int i)
|
String ID3v1::genre(int i) {
|
||||||
{
|
if (i >= 0 && i < genresSize)
|
||||||
if(i >= 0 && i < genresSize)
|
return String(genres[i]); // always make a copy
|
||||||
return String(genres[i]); // always make a copy
|
|
||||||
else
|
else
|
||||||
return String();
|
return String();
|
||||||
}
|
}
|
||||||
|
|
||||||
int ID3v1::genreIndex(const String &name)
|
int ID3v1::genreIndex(const String &name) {
|
||||||
{
|
for (int i = 0; i < genresSize; ++i) {
|
||||||
for(int i = 0; i < genresSize; ++i) {
|
if (name == genres[i])
|
||||||
if(name == genres[i])
|
|
||||||
return 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 Strawberry_TagLib {
|
||||||
namespace 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
|
* Returns the list of canonical ID3v1 genre names in the order that they
|
||||||
* are listed in the standard.
|
* 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
|
* A "reverse mapping" that goes from the canonical ID3v1 genre name to the
|
||||||
* respective genre number. genreMap()["Rock"] ==
|
* 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
|
* 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
|
* \a index is out of range -- less than zero or greater than 191 -- a null
|
||||||
* string will be returned.
|
* 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
|
* 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)
|
* genre is not in the list 255 (which signifies an unknown genre in ID3v1)
|
||||||
* will be returned.
|
* 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
|
#endif
|
||||||
|
122
3rdparty/taglib/mpeg/id3v1/id3v1tag.cpp
vendored
122
3rdparty/taglib/mpeg/id3v1/id3v1tag.cpp
vendored
@ -32,20 +32,17 @@
|
|||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
using namespace ID3v1;
|
using namespace ID3v1;
|
||||||
|
|
||||||
namespace
|
namespace {
|
||||||
{
|
const ID3v1::StringHandler defaultStringHandler;
|
||||||
const ID3v1::StringHandler defaultStringHandler;
|
const ID3v1::StringHandler *stringHandler = &defaultStringHandler;
|
||||||
const ID3v1::StringHandler *stringHandler = &defaultStringHandler;
|
} // namespace
|
||||||
}
|
|
||||||
|
|
||||||
class ID3v1::Tag::TagPrivate
|
class ID3v1::Tag::TagPrivate {
|
||||||
{
|
public:
|
||||||
public:
|
TagPrivate() : file(0),
|
||||||
TagPrivate() :
|
tagOffset(0),
|
||||||
file(0),
|
track(0),
|
||||||
tagOffset(0),
|
genre(255) {}
|
||||||
track(0),
|
|
||||||
genre(255) {}
|
|
||||||
|
|
||||||
File *file;
|
File *file;
|
||||||
long tagOffset;
|
long tagOffset;
|
||||||
@ -63,18 +60,15 @@ public:
|
|||||||
// StringHandler implementation
|
// 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();
|
return String(data, String::Latin1).stripWhiteSpace();
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector ID3v1::StringHandler::render(const String &s) const
|
ByteVector ID3v1::StringHandler::render(const String &s) const {
|
||||||
{
|
if (s.isLatin1())
|
||||||
if(s.isLatin1())
|
|
||||||
return s.data(String::Latin1);
|
return s.data(String::Latin1);
|
||||||
else
|
else
|
||||||
return ByteVector();
|
return ByteVector();
|
||||||
@ -84,29 +78,23 @@ ByteVector ID3v1::StringHandler::render(const String &s) const
|
|||||||
// public methods
|
// public methods
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ID3v1::Tag::Tag() :
|
ID3v1::Tag::Tag() : Strawberry_TagLib::TagLib::Tag(),
|
||||||
Strawberry_TagLib::TagLib::Tag(),
|
d(new TagPrivate()) {
|
||||||
d(new TagPrivate())
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ID3v1::Tag::Tag(File *file, long tagOffset) :
|
ID3v1::Tag::Tag(File *file, long tagOffset) : Strawberry_TagLib::TagLib::Tag(),
|
||||||
Strawberry_TagLib::TagLib::Tag(),
|
d(new TagPrivate()) {
|
||||||
d(new TagPrivate())
|
|
||||||
{
|
|
||||||
d->file = file;
|
d->file = file;
|
||||||
d->tagOffset = tagOffset;
|
d->tagOffset = tagOffset;
|
||||||
|
|
||||||
read();
|
read();
|
||||||
}
|
}
|
||||||
|
|
||||||
ID3v1::Tag::~Tag()
|
ID3v1::Tag::~Tag() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector ID3v1::Tag::render() const
|
ByteVector ID3v1::Tag::render() const {
|
||||||
{
|
|
||||||
ByteVector data;
|
ByteVector data;
|
||||||
|
|
||||||
data.append(fileIdentifier());
|
data.append(fileIdentifier());
|
||||||
@ -122,94 +110,76 @@ ByteVector ID3v1::Tag::render() const
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector ID3v1::Tag::fileIdentifier()
|
ByteVector ID3v1::Tag::fileIdentifier() {
|
||||||
{
|
|
||||||
return ByteVector::fromCString("TAG");
|
return ByteVector::fromCString("TAG");
|
||||||
}
|
}
|
||||||
|
|
||||||
String ID3v1::Tag::title() const
|
String ID3v1::Tag::title() const {
|
||||||
{
|
|
||||||
return d->title;
|
return d->title;
|
||||||
}
|
}
|
||||||
|
|
||||||
String ID3v1::Tag::artist() const
|
String ID3v1::Tag::artist() const {
|
||||||
{
|
|
||||||
return d->artist;
|
return d->artist;
|
||||||
}
|
}
|
||||||
|
|
||||||
String ID3v1::Tag::album() const
|
String ID3v1::Tag::album() const {
|
||||||
{
|
|
||||||
return d->album;
|
return d->album;
|
||||||
}
|
}
|
||||||
|
|
||||||
String ID3v1::Tag::comment() const
|
String ID3v1::Tag::comment() const {
|
||||||
{
|
|
||||||
return d->comment;
|
return d->comment;
|
||||||
}
|
}
|
||||||
|
|
||||||
String ID3v1::Tag::genre() const
|
String ID3v1::Tag::genre() const {
|
||||||
{
|
|
||||||
return ID3v1::genre(d->genre);
|
return ID3v1::genre(d->genre);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int ID3v1::Tag::year() const
|
unsigned int ID3v1::Tag::year() const {
|
||||||
{
|
|
||||||
return d->year.toInt();
|
return d->year.toInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int ID3v1::Tag::track() const
|
unsigned int ID3v1::Tag::track() const {
|
||||||
{
|
|
||||||
return d->track;
|
return d->track;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ID3v1::Tag::setTitle(const String &s)
|
void ID3v1::Tag::setTitle(const String &s) {
|
||||||
{
|
|
||||||
d->title = s;
|
d->title = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ID3v1::Tag::setArtist(const String &s)
|
void ID3v1::Tag::setArtist(const String &s) {
|
||||||
{
|
|
||||||
d->artist = s;
|
d->artist = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ID3v1::Tag::setAlbum(const String &s)
|
void ID3v1::Tag::setAlbum(const String &s) {
|
||||||
{
|
|
||||||
d->album = s;
|
d->album = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ID3v1::Tag::setComment(const String &s)
|
void ID3v1::Tag::setComment(const String &s) {
|
||||||
{
|
|
||||||
d->comment = s;
|
d->comment = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ID3v1::Tag::setGenre(const String &s)
|
void ID3v1::Tag::setGenre(const String &s) {
|
||||||
{
|
|
||||||
d->genre = ID3v1::genreIndex(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();
|
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;
|
d->track = i < 256 ? i : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int ID3v1::Tag::genreNumber() const
|
unsigned int ID3v1::Tag::genreNumber() const {
|
||||||
{
|
|
||||||
return d->genre;
|
return d->genre;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ID3v1::Tag::setGenreNumber(unsigned int i)
|
void ID3v1::Tag::setGenreNumber(unsigned int i) {
|
||||||
{
|
|
||||||
d->genre = i < 256 ? i : 255;
|
d->genre = i < 256 ? i : 255;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ID3v1::Tag::setStringHandler(const StringHandler *handler)
|
void ID3v1::Tag::setStringHandler(const StringHandler *handler) {
|
||||||
{
|
if (handler)
|
||||||
if(handler)
|
|
||||||
stringHandler = handler;
|
stringHandler = handler;
|
||||||
else
|
else
|
||||||
stringHandler = &defaultStringHandler;
|
stringHandler = &defaultStringHandler;
|
||||||
@ -219,23 +189,21 @@ void ID3v1::Tag::setStringHandler(const StringHandler *handler)
|
|||||||
// protected methods
|
// protected methods
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void ID3v1::Tag::read()
|
void ID3v1::Tag::read() {
|
||||||
{
|
if (d->file && d->file->isValid()) {
|
||||||
if(d->file && d->file->isValid()) {
|
|
||||||
d->file->seek(d->tagOffset);
|
d->file->seek(d->tagOffset);
|
||||||
// read the tag -- always 128 bytes
|
// read the tag -- always 128 bytes
|
||||||
const ByteVector data = d->file->readBlock(128);
|
const ByteVector data = d->file->readBlock(128);
|
||||||
|
|
||||||
// some initial sanity checking
|
// some initial sanity checking
|
||||||
if(data.size() == 128 && data.startsWith("TAG"))
|
if (data.size() == 128 && data.startsWith("TAG"))
|
||||||
parse(data);
|
parse(data);
|
||||||
else
|
else
|
||||||
debug("ID3v1 tag is not valid or could not be read at the specified offset.");
|
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;
|
int offset = 3;
|
||||||
|
|
||||||
d->title = stringHandler->parse(data.mid(offset, 30));
|
d->title = stringHandler->parse(data.mid(offset, 30));
|
||||||
@ -255,11 +223,11 @@ void ID3v1::Tag::parse(const ByteVector &data)
|
|||||||
// indicate the end of a C-String, specifically the comment string, a value of
|
// indicate the end of a C-String, specifically the comment string, a value of
|
||||||
// zero must be assumed to be just that.
|
// 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
|
// ID3v1.1 detected
|
||||||
|
|
||||||
d->comment = stringHandler->parse(data.mid(offset, 28));
|
d->comment = stringHandler->parse(data.mid(offset, 28));
|
||||||
d->track = static_cast<unsigned char>(data[offset + 29]);
|
d->track = static_cast<unsigned char>(data[offset + 29]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
d->comment = data.mid(offset, 30);
|
d->comment = data.mid(offset, 30);
|
||||||
|
130
3rdparty/taglib/mpeg/id3v1/id3v1tag.h
vendored
130
3rdparty/taglib/mpeg/id3v1/id3v1tag.h
vendored
@ -33,15 +33,15 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace 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
|
* 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
|
* practice it does not. TagLib by default only supports ISO-8859-1 data
|
||||||
* in ID3v1 tags.
|
* in ID3v1 tags.
|
||||||
@ -58,20 +58,19 @@ namespace TagLib {
|
|||||||
* \see ID3v1::Tag::setStringHandler()
|
* \see ID3v1::Tag::setStringHandler()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class TAGLIB_EXPORT StringHandler
|
class TAGLIB_EXPORT StringHandler {
|
||||||
{
|
TAGLIB_IGNORE_MISSING_DESTRUCTOR
|
||||||
TAGLIB_IGNORE_MISSING_DESTRUCTOR
|
public:
|
||||||
public:
|
// BIC: Add virtual destructor.
|
||||||
// BIC: Add virtual destructor.
|
StringHandler();
|
||||||
StringHandler();
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Decode a string from \a data. The default implementation assumes that
|
* Decode a string from \a data. The default implementation assumes that
|
||||||
* \a data is an ISO-8859-1 (Latin1) character array.
|
* \a data is an ISO-8859-1 (Latin1) character array.
|
||||||
*/
|
*/
|
||||||
virtual String parse(const ByteVector &data) const;
|
virtual String parse(const ByteVector &data) const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Encode a ByteVector with the data from \a s. The default implementation
|
* Encode a ByteVector with the data from \a s. The default implementation
|
||||||
* assumes that \a s is an ISO-8859-1 (Latin1) string. If the string is
|
* assumes that \a s is an ISO-8859-1 (Latin1) string. If the string is
|
||||||
* does not conform to ISO-8859-1, no value is written.
|
* does not conform to ISO-8859-1, no value is written.
|
||||||
@ -80,12 +79,12 @@ namespace TagLib {
|
|||||||
* instead do not write an ID3v1 tag in the case that the data is not
|
* instead do not write an ID3v1 tag in the case that the data is not
|
||||||
* ISO-8859-1.
|
* ISO-8859-1.
|
||||||
*/
|
*/
|
||||||
virtual ByteVector render(const String &s) const;
|
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
|
* 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
|
* and most common of tag formats but is rather limited. Because of its
|
||||||
* pervasiveness and the way that applications have been written around the
|
* pervasiveness and the way that applications have been written around the
|
||||||
@ -103,71 +102,70 @@ namespace TagLib {
|
|||||||
* truncation happens automatically when the tag is rendered.
|
* 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:
|
||||||
public:
|
/*!
|
||||||
/*!
|
|
||||||
* Create an ID3v1 tag with default values.
|
* Create an ID3v1 tag with default values.
|
||||||
*/
|
*/
|
||||||
Tag();
|
Tag();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Create an ID3v1 tag and parse the data in \a file starting at
|
* Create an ID3v1 tag and parse the data in \a file starting at
|
||||||
* \a tagOffset.
|
* \a tagOffset.
|
||||||
*/
|
*/
|
||||||
Tag(File *file, long tagOffset);
|
Tag(File *file, long tagOffset);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys this Tag instance.
|
* Destroys this Tag instance.
|
||||||
*/
|
*/
|
||||||
virtual ~Tag();
|
virtual ~Tag();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Renders the in memory values to a ByteVector suitable for writing to
|
* Renders the in memory values to a ByteVector suitable for writing to
|
||||||
* the file.
|
* the file.
|
||||||
*/
|
*/
|
||||||
ByteVector render() const;
|
ByteVector render() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the string "TAG" suitable for usage in locating the tag in a
|
* Returns the string "TAG" suitable for usage in locating the tag in a
|
||||||
* file.
|
* file.
|
||||||
*/
|
*/
|
||||||
static ByteVector fileIdentifier();
|
static ByteVector fileIdentifier();
|
||||||
|
|
||||||
// Reimplementations.
|
// Reimplementations.
|
||||||
|
|
||||||
virtual String title() const;
|
virtual String title() const;
|
||||||
virtual String artist() const;
|
virtual String artist() const;
|
||||||
virtual String album() const;
|
virtual String album() const;
|
||||||
virtual String comment() const;
|
virtual String comment() const;
|
||||||
virtual String genre() const;
|
virtual String genre() const;
|
||||||
virtual unsigned int year() const;
|
virtual unsigned int year() const;
|
||||||
virtual unsigned int track() const;
|
virtual unsigned int track() const;
|
||||||
|
|
||||||
virtual void setTitle(const String &s);
|
virtual void setTitle(const String &s);
|
||||||
virtual void setArtist(const String &s);
|
virtual void setArtist(const String &s);
|
||||||
virtual void setAlbum(const String &s);
|
virtual void setAlbum(const String &s);
|
||||||
virtual void setComment(const String &s);
|
virtual void setComment(const String &s);
|
||||||
virtual void setGenre(const String &s);
|
virtual void setGenre(const String &s);
|
||||||
virtual void setYear(unsigned int i);
|
virtual void setYear(unsigned int i);
|
||||||
virtual void setTrack(unsigned int i);
|
virtual void setTrack(unsigned int i);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the genre in number.
|
* Returns the genre in number.
|
||||||
*
|
*
|
||||||
* \note Normally 255 indicates that this tag contains no genre.
|
* \note Normally 255 indicates that this tag contains no genre.
|
||||||
*/
|
*/
|
||||||
unsigned int genreNumber() const;
|
unsigned int genreNumber() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the genre in number to \a i.
|
* Sets the genre in number to \a i.
|
||||||
*
|
*
|
||||||
* \note Valid value is from 0 up to 255. Normally 255 indicates that
|
* \note Valid value is from 0 up to 255. Normally 255 indicates that
|
||||||
* this tag contains no genre.
|
* this tag contains no genre.
|
||||||
*/
|
*/
|
||||||
void setGenreNumber(unsigned int i);
|
void setGenreNumber(unsigned int i);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the string handler that decides how the ID3v1 data will be
|
* Sets the string handler that decides how the ID3v1 data will be
|
||||||
* converted to and from binary data.
|
* converted to and from binary data.
|
||||||
* If the parameter \a handler is null, the previous handler is
|
* If the parameter \a handler is null, the previous handler is
|
||||||
@ -178,27 +176,27 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \see StringHandler
|
* \see StringHandler
|
||||||
*/
|
*/
|
||||||
static void setStringHandler(const StringHandler *handler);
|
static void setStringHandler(const StringHandler *handler);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/*!
|
/*!
|
||||||
* Reads from the file specified in the constructor.
|
* Reads from the file specified in the constructor.
|
||||||
*/
|
*/
|
||||||
void read();
|
void read();
|
||||||
/*!
|
/*!
|
||||||
* Pareses the body of the tag in \a data.
|
* Pareses the body of the tag in \a data.
|
||||||
*/
|
*/
|
||||||
void parse(const ByteVector &data);
|
void parse(const ByteVector &data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Tag(const Tag &);
|
Tag(const Tag &);
|
||||||
Tag &operator=(const Tag &);
|
Tag &operator=(const Tag &);
|
||||||
|
|
||||||
class TagPrivate;
|
class TagPrivate;
|
||||||
TagPrivate *d;
|
TagPrivate *d;
|
||||||
};
|
};
|
||||||
}
|
} // namespace ID3v1
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,9 +31,8 @@
|
|||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
using namespace ID3v2;
|
using namespace ID3v2;
|
||||||
|
|
||||||
class AttachedPictureFrame::AttachedPictureFramePrivate
|
class AttachedPictureFrame::AttachedPictureFramePrivate {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
AttachedPictureFramePrivate() : textEncoding(String::Latin1),
|
AttachedPictureFramePrivate() : textEncoding(String::Latin1),
|
||||||
type(AttachedPictureFrame::Other) {}
|
type(AttachedPictureFrame::Other) {}
|
||||||
|
|
||||||
@ -48,77 +47,61 @@ public:
|
|||||||
// public members
|
// public members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
AttachedPictureFrame::AttachedPictureFrame() :
|
AttachedPictureFrame::AttachedPictureFrame() : Frame("APIC"),
|
||||||
Frame("APIC"),
|
d(new AttachedPictureFramePrivate()) {
|
||||||
d(new AttachedPictureFramePrivate())
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data) :
|
AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data) : Frame(data),
|
||||||
Frame(data),
|
d(new AttachedPictureFramePrivate()) {
|
||||||
d(new AttachedPictureFramePrivate())
|
|
||||||
{
|
|
||||||
setData(data);
|
setData(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
AttachedPictureFrame::~AttachedPictureFrame()
|
AttachedPictureFrame::~AttachedPictureFrame() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
String AttachedPictureFrame::toString() const
|
String AttachedPictureFrame::toString() const {
|
||||||
{
|
|
||||||
String s = "[" + d->mimeType + "]";
|
String s = "[" + d->mimeType + "]";
|
||||||
return d->description.isEmpty() ? s : d->description + " " + s;
|
return d->description.isEmpty() ? s : d->description + " " + s;
|
||||||
}
|
}
|
||||||
|
|
||||||
String::Type AttachedPictureFrame::textEncoding() const
|
String::Type AttachedPictureFrame::textEncoding() const {
|
||||||
{
|
|
||||||
return d->textEncoding;
|
return d->textEncoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AttachedPictureFrame::setTextEncoding(String::Type t)
|
void AttachedPictureFrame::setTextEncoding(String::Type t) {
|
||||||
{
|
|
||||||
d->textEncoding = t;
|
d->textEncoding = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
String AttachedPictureFrame::mimeType() const
|
String AttachedPictureFrame::mimeType() const {
|
||||||
{
|
|
||||||
return d->mimeType;
|
return d->mimeType;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AttachedPictureFrame::setMimeType(const String &m)
|
void AttachedPictureFrame::setMimeType(const String &m) {
|
||||||
{
|
|
||||||
d->mimeType = m;
|
d->mimeType = m;
|
||||||
}
|
}
|
||||||
|
|
||||||
AttachedPictureFrame::Type AttachedPictureFrame::type() const
|
AttachedPictureFrame::Type AttachedPictureFrame::type() const {
|
||||||
{
|
|
||||||
return d->type;
|
return d->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AttachedPictureFrame::setType(Type t)
|
void AttachedPictureFrame::setType(Type t) {
|
||||||
{
|
|
||||||
d->type = t;
|
d->type = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
String AttachedPictureFrame::description() const
|
String AttachedPictureFrame::description() const {
|
||||||
{
|
|
||||||
return d->description;
|
return d->description;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AttachedPictureFrame::setDescription(const String &desc)
|
void AttachedPictureFrame::setDescription(const String &desc) {
|
||||||
{
|
|
||||||
d->description = desc;
|
d->description = desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector AttachedPictureFrame::picture() const
|
ByteVector AttachedPictureFrame::picture() const {
|
||||||
{
|
|
||||||
return d->data;
|
return d->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AttachedPictureFrame::setPicture(const ByteVector &p)
|
void AttachedPictureFrame::setPicture(const ByteVector &p) {
|
||||||
{
|
|
||||||
d->data = p;
|
d->data = p;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,9 +109,8 @@ void AttachedPictureFrame::setPicture(const ByteVector &p)
|
|||||||
// protected members
|
// protected members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void AttachedPictureFrame::parseFields(const ByteVector &data)
|
void AttachedPictureFrame::parseFields(const ByteVector &data) {
|
||||||
{
|
if (data.size() < 5) {
|
||||||
if(data.size() < 5) {
|
|
||||||
debug("A picture frame must contain at least 5 bytes.");
|
debug("A picture frame must contain at least 5 bytes.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -139,7 +121,7 @@ void AttachedPictureFrame::parseFields(const ByteVector &data)
|
|||||||
|
|
||||||
d->mimeType = readStringField(data, String::Latin1, &pos);
|
d->mimeType = readStringField(data, String::Latin1, &pos);
|
||||||
/* Now we need at least two more bytes available */
|
/* 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.");
|
debug("Truncated picture frame.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -150,8 +132,7 @@ void AttachedPictureFrame::parseFields(const ByteVector &data)
|
|||||||
d->data = data.mid(pos);
|
d->data = data.mid(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector AttachedPictureFrame::renderFields() const
|
ByteVector AttachedPictureFrame::renderFields() const {
|
||||||
{
|
|
||||||
ByteVector data;
|
ByteVector data;
|
||||||
|
|
||||||
String::Type encoding = checkTextEncoding(d->description, d->textEncoding);
|
String::Type encoding = checkTextEncoding(d->description, d->textEncoding);
|
||||||
@ -171,10 +152,8 @@ ByteVector AttachedPictureFrame::renderFields() const
|
|||||||
// private members
|
// private members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data, Header *h) :
|
AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data, Header *h) : Frame(h),
|
||||||
Frame(h),
|
d(new AttachedPictureFramePrivate()) {
|
||||||
d(new AttachedPictureFramePrivate())
|
|
||||||
{
|
|
||||||
parseFields(fieldData(data));
|
parseFields(fieldData(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,9 +161,8 @@ AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data, Header *h) :
|
|||||||
// support for ID3v2.2 PIC frames
|
// support for ID3v2.2 PIC frames
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void AttachedPictureFrameV22::parseFields(const ByteVector &data)
|
void AttachedPictureFrameV22::parseFields(const ByteVector &data) {
|
||||||
{
|
if (data.size() < 5) {
|
||||||
if(data.size() < 5) {
|
|
||||||
debug("A picture frame must contain at least 5 bytes.");
|
debug("A picture frame must contain at least 5 bytes.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -198,9 +176,11 @@ void AttachedPictureFrameV22::parseFields(const ByteVector &data)
|
|||||||
// convert fixed string image type to mime string
|
// convert fixed string image type to mime string
|
||||||
if (fixedString.upper() == "JPG") {
|
if (fixedString.upper() == "JPG") {
|
||||||
d->mimeType = "image/jpeg";
|
d->mimeType = "image/jpeg";
|
||||||
} else if (fixedString.upper() == "PNG") {
|
}
|
||||||
|
else if (fixedString.upper() == "PNG") {
|
||||||
d->mimeType = "image/png";
|
d->mimeType = "image/png";
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
debug("probably unsupported image type");
|
debug("probably unsupported image type");
|
||||||
d->mimeType = "image/" + fixedString;
|
d->mimeType = "image/" + fixedString;
|
||||||
}
|
}
|
||||||
@ -211,8 +191,7 @@ void AttachedPictureFrameV22::parseFields(const ByteVector &data)
|
|||||||
d->data = data.mid(pos);
|
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
|
// set v2.2 header to make fieldData work correctly
|
||||||
setHeader(h, true);
|
setHeader(h, true);
|
||||||
|
|
||||||
|
@ -33,136 +33,134 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace 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
|
* This is an implementation of ID3v2 attached pictures. Pictures may be
|
||||||
* included in tags, one per APIC frame (but there may be multiple APIC
|
* 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
|
* frames in a single tag). These pictures are usually in either JPEG or
|
||||||
* PNG format.
|
* PNG format.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class TAGLIB_EXPORT AttachedPictureFrame : public Frame
|
class TAGLIB_EXPORT AttachedPictureFrame : public Frame {
|
||||||
{
|
friend class FrameFactory;
|
||||||
friend class FrameFactory;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/*!
|
||||||
/*!
|
|
||||||
* This describes the function or content of the picture.
|
* This describes the function or content of the picture.
|
||||||
*/
|
*/
|
||||||
enum Type {
|
enum Type {
|
||||||
//! A type not enumerated below
|
//! A type not enumerated below
|
||||||
Other = 0x00,
|
Other = 0x00,
|
||||||
//! 32x32 PNG image that should be used as the file icon
|
//! 32x32 PNG image that should be used as the file icon
|
||||||
FileIcon = 0x01,
|
FileIcon = 0x01,
|
||||||
//! File icon of a different size or format
|
//! File icon of a different size or format
|
||||||
OtherFileIcon = 0x02,
|
OtherFileIcon = 0x02,
|
||||||
//! Front cover image of the album
|
//! Front cover image of the album
|
||||||
FrontCover = 0x03,
|
FrontCover = 0x03,
|
||||||
//! Back cover image of the album
|
//! Back cover image of the album
|
||||||
BackCover = 0x04,
|
BackCover = 0x04,
|
||||||
//! Inside leaflet page of the album
|
//! Inside leaflet page of the album
|
||||||
LeafletPage = 0x05,
|
LeafletPage = 0x05,
|
||||||
//! Image from the album itself
|
//! Image from the album itself
|
||||||
Media = 0x06,
|
Media = 0x06,
|
||||||
//! Picture of the lead artist or soloist
|
//! Picture of the lead artist or soloist
|
||||||
LeadArtist = 0x07,
|
LeadArtist = 0x07,
|
||||||
//! Picture of the artist or performer
|
//! Picture of the artist or performer
|
||||||
Artist = 0x08,
|
Artist = 0x08,
|
||||||
//! Picture of the conductor
|
//! Picture of the conductor
|
||||||
Conductor = 0x09,
|
Conductor = 0x09,
|
||||||
//! Picture of the band or orchestra
|
//! Picture of the band or orchestra
|
||||||
Band = 0x0A,
|
Band = 0x0A,
|
||||||
//! Picture of the composer
|
//! Picture of the composer
|
||||||
Composer = 0x0B,
|
Composer = 0x0B,
|
||||||
//! Picture of the lyricist or text writer
|
//! Picture of the lyricist or text writer
|
||||||
Lyricist = 0x0C,
|
Lyricist = 0x0C,
|
||||||
//! Picture of the recording location or studio
|
//! Picture of the recording location or studio
|
||||||
RecordingLocation = 0x0D,
|
RecordingLocation = 0x0D,
|
||||||
//! Picture of the artists during recording
|
//! Picture of the artists during recording
|
||||||
DuringRecording = 0x0E,
|
DuringRecording = 0x0E,
|
||||||
//! Picture of the artists during performance
|
//! Picture of the artists during performance
|
||||||
DuringPerformance = 0x0F,
|
DuringPerformance = 0x0F,
|
||||||
//! Picture from a movie or video related to the track
|
//! Picture from a movie or video related to the track
|
||||||
MovieScreenCapture = 0x10,
|
MovieScreenCapture = 0x10,
|
||||||
//! Picture of a large, coloured fish
|
//! Picture of a large, coloured fish
|
||||||
ColouredFish = 0x11,
|
ColouredFish = 0x11,
|
||||||
//! Illustration related to the track
|
//! Illustration related to the track
|
||||||
Illustration = 0x12,
|
Illustration = 0x12,
|
||||||
//! Logo of the band or performer
|
//! Logo of the band or performer
|
||||||
BandLogo = 0x13,
|
BandLogo = 0x13,
|
||||||
//! Logo of the publisher (record company)
|
//! Logo of the publisher (record company)
|
||||||
PublisherLogo = 0x14
|
PublisherLogo = 0x14
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs an empty picture frame. The description, content and text
|
* Constructs an empty picture frame. The description, content and text
|
||||||
* encoding should be set manually.
|
* encoding should be set manually.
|
||||||
*/
|
*/
|
||||||
AttachedPictureFrame();
|
AttachedPictureFrame();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs an AttachedPicture frame based on \a data.
|
* Constructs an AttachedPicture frame based on \a data.
|
||||||
*/
|
*/
|
||||||
explicit AttachedPictureFrame(const ByteVector &data);
|
explicit AttachedPictureFrame(const ByteVector &data);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys the AttahcedPictureFrame instance.
|
* Destroys the AttahcedPictureFrame instance.
|
||||||
*/
|
*/
|
||||||
virtual ~AttachedPictureFrame();
|
virtual ~AttachedPictureFrame();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns a string containing the description and mime-type
|
* Returns a string containing the description and mime-type
|
||||||
*/
|
*/
|
||||||
virtual String toString() const;
|
virtual String toString() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the text encoding used for the description.
|
* Returns the text encoding used for the description.
|
||||||
*
|
*
|
||||||
* \see setTextEncoding()
|
* \see setTextEncoding()
|
||||||
* \see description()
|
* \see description()
|
||||||
*/
|
*/
|
||||||
String::Type textEncoding() const;
|
String::Type textEncoding() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Set the text encoding used for the description.
|
* Set the text encoding used for the description.
|
||||||
*
|
*
|
||||||
* \see description()
|
* \see description()
|
||||||
*/
|
*/
|
||||||
void setTextEncoding(String::Type t);
|
void setTextEncoding(String::Type t);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the mime type of the image. This should in most cases be
|
* Returns the mime type of the image. This should in most cases be
|
||||||
* "image/png" or "image/jpeg".
|
* "image/png" or "image/jpeg".
|
||||||
*/
|
*/
|
||||||
String mimeType() const;
|
String mimeType() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the mime type of the image. This should in most cases be
|
* Sets the mime type of the image. This should in most cases be
|
||||||
* "image/png" or "image/jpeg".
|
* "image/png" or "image/jpeg".
|
||||||
*/
|
*/
|
||||||
void setMimeType(const String &m);
|
void setMimeType(const String &m);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the type of the image.
|
* Returns the type of the image.
|
||||||
*
|
*
|
||||||
* \see Type
|
* \see Type
|
||||||
* \see setType()
|
* \see setType()
|
||||||
*/
|
*/
|
||||||
Type type() const;
|
Type type() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the type for the image.
|
* Sets the type for the image.
|
||||||
*
|
*
|
||||||
* \see Type
|
* \see Type
|
||||||
* \see type()
|
* \see type()
|
||||||
*/
|
*/
|
||||||
void setType(Type t);
|
void setType(Type t);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns a text description of the image.
|
* Returns a text description of the image.
|
||||||
*
|
*
|
||||||
* \see setDescription()
|
* \see setDescription()
|
||||||
@ -170,9 +168,9 @@ namespace TagLib {
|
|||||||
* \see setTextEncoding()
|
* \see setTextEncoding()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
String description() const;
|
String description() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets a textual description of the image to \a desc.
|
* Sets a textual description of the image to \a desc.
|
||||||
*
|
*
|
||||||
* \see description()
|
* \see description()
|
||||||
@ -180,9 +178,9 @@ namespace TagLib {
|
|||||||
* \see setTextEncoding()
|
* \see setTextEncoding()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void setDescription(const String &desc);
|
void setDescription(const String &desc);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the image data as a ByteVector.
|
* Returns the image data as a ByteVector.
|
||||||
*
|
*
|
||||||
* \note ByteVector has a data() method that returns a const char * which
|
* \note ByteVector has a data() method that returns a const char * which
|
||||||
@ -191,9 +189,9 @@ namespace TagLib {
|
|||||||
* \see setPicture()
|
* \see setPicture()
|
||||||
* \see mimeType()
|
* \see mimeType()
|
||||||
*/
|
*/
|
||||||
ByteVector picture() const;
|
ByteVector picture() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the image data to \a p. \a p should be of the type specified in
|
* Sets the image data to \a p. \a p should be of the type specified in
|
||||||
* this frame's mime-type specification.
|
* this frame's mime-type specification.
|
||||||
*
|
*
|
||||||
@ -201,32 +199,31 @@ namespace TagLib {
|
|||||||
* \see mimeType()
|
* \see mimeType()
|
||||||
* \see setMimeType()
|
* \see setMimeType()
|
||||||
*/
|
*/
|
||||||
void setPicture(const ByteVector &p);
|
void setPicture(const ByteVector &p);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void parseFields(const ByteVector &data);
|
virtual void parseFields(const ByteVector &data);
|
||||||
virtual ByteVector renderFields() const;
|
virtual ByteVector renderFields() const;
|
||||||
class AttachedPictureFramePrivate;
|
class AttachedPictureFramePrivate;
|
||||||
AttachedPictureFramePrivate *d;
|
AttachedPictureFramePrivate *d;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AttachedPictureFrame(const AttachedPictureFrame &);
|
AttachedPictureFrame(const AttachedPictureFrame &);
|
||||||
AttachedPictureFrame &operator=(const AttachedPictureFrame &);
|
AttachedPictureFrame &operator=(const AttachedPictureFrame &);
|
||||||
AttachedPictureFrame(const ByteVector &data, Header *h);
|
AttachedPictureFrame(const ByteVector &data, Header *h);
|
||||||
|
};
|
||||||
|
|
||||||
};
|
//! support for ID3v2.2 PIC frames
|
||||||
|
class TAGLIB_EXPORT AttachedPictureFrameV22 : public AttachedPictureFrame {
|
||||||
|
protected:
|
||||||
|
virtual void parseFields(const ByteVector &data);
|
||||||
|
|
||||||
//! support for ID3v2.2 PIC frames
|
private:
|
||||||
class TAGLIB_EXPORT AttachedPictureFrameV22 : public AttachedPictureFrame
|
AttachedPictureFrameV22(const ByteVector &data, Header *h);
|
||||||
{
|
friend class FrameFactory;
|
||||||
protected:
|
};
|
||||||
virtual void parseFields(const ByteVector &data);
|
} // namespace ID3v2
|
||||||
private:
|
} // namespace TagLib
|
||||||
AttachedPictureFrameV22(const ByteVector &data, Header *h);
|
} // namespace Strawberry_TagLib
|
||||||
friend class FrameFactory;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
151
3rdparty/taglib/mpeg/id3v2/frames/chapterframe.cpp
vendored
151
3rdparty/taglib/mpeg/id3v2/frames/chapterframe.cpp
vendored
@ -33,16 +33,13 @@
|
|||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
using namespace ID3v2;
|
using namespace ID3v2;
|
||||||
|
|
||||||
class ChapterFrame::ChapterFramePrivate
|
class ChapterFrame::ChapterFramePrivate {
|
||||||
{
|
public:
|
||||||
public:
|
ChapterFramePrivate() : tagHeader(0),
|
||||||
ChapterFramePrivate() :
|
startTime(0),
|
||||||
tagHeader(0),
|
endTime(0),
|
||||||
startTime(0),
|
startOffset(0),
|
||||||
endTime(0),
|
endOffset(0) {
|
||||||
startOffset(0),
|
|
||||||
endOffset(0)
|
|
||||||
{
|
|
||||||
embeddedFrameList.setAutoDelete(true);
|
embeddedFrameList.setAutoDelete(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,21 +57,17 @@ public:
|
|||||||
// public methods
|
// public methods
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ChapterFrame::ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data) :
|
ChapterFrame::ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data) : ID3v2::Frame(data),
|
||||||
ID3v2::Frame(data),
|
d(new ChapterFramePrivate()) {
|
||||||
d(new ChapterFramePrivate())
|
|
||||||
{
|
|
||||||
d->tagHeader = tagHeader;
|
d->tagHeader = tagHeader;
|
||||||
setData(data);
|
setData(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
ChapterFrame::ChapterFrame(const ByteVector &elementID,
|
ChapterFrame::ChapterFrame(const ByteVector &elementID,
|
||||||
unsigned int startTime, unsigned int endTime,
|
unsigned int startTime, unsigned int endTime,
|
||||||
unsigned int startOffset, unsigned int endOffset,
|
unsigned int startOffset, unsigned int endOffset,
|
||||||
const FrameList &embeddedFrames) :
|
const FrameList &embeddedFrames) : ID3v2::Frame("CHAP"),
|
||||||
ID3v2::Frame("CHAP"),
|
d(new ChapterFramePrivate()) {
|
||||||
d(new ChapterFramePrivate())
|
|
||||||
{
|
|
||||||
// setElementID has a workaround for a previously silly API where you had to
|
// setElementID has a workaround for a previously silly API where you had to
|
||||||
// specifically include the null byte.
|
// specifically include the null byte.
|
||||||
|
|
||||||
@ -85,92 +78,77 @@ ChapterFrame::ChapterFrame(const ByteVector &elementID,
|
|||||||
d->startOffset = startOffset;
|
d->startOffset = startOffset;
|
||||||
d->endOffset = endOffset;
|
d->endOffset = endOffset;
|
||||||
|
|
||||||
for(FrameList::ConstIterator it = embeddedFrames.begin();
|
for (FrameList::ConstIterator it = embeddedFrames.begin();
|
||||||
it != embeddedFrames.end(); ++it)
|
it != embeddedFrames.end();
|
||||||
|
++it)
|
||||||
addEmbeddedFrame(*it);
|
addEmbeddedFrame(*it);
|
||||||
}
|
}
|
||||||
|
|
||||||
ChapterFrame::~ChapterFrame()
|
ChapterFrame::~ChapterFrame() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector ChapterFrame::elementID() const
|
ByteVector ChapterFrame::elementID() const {
|
||||||
{
|
|
||||||
return d->elementID;
|
return d->elementID;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int ChapterFrame::startTime() const
|
unsigned int ChapterFrame::startTime() const {
|
||||||
{
|
|
||||||
return d->startTime;
|
return d->startTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int ChapterFrame::endTime() const
|
unsigned int ChapterFrame::endTime() const {
|
||||||
{
|
|
||||||
return d->endTime;
|
return d->endTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int ChapterFrame::startOffset() const
|
unsigned int ChapterFrame::startOffset() const {
|
||||||
{
|
|
||||||
return d->startOffset;
|
return d->startOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int ChapterFrame::endOffset() const
|
unsigned int ChapterFrame::endOffset() const {
|
||||||
{
|
|
||||||
return d->endOffset;
|
return d->endOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChapterFrame::setElementID(const ByteVector &eID)
|
void ChapterFrame::setElementID(const ByteVector &eID) {
|
||||||
{
|
|
||||||
d->elementID = 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);
|
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;
|
d->startTime = sT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChapterFrame::setEndTime(const unsigned int &eT)
|
void ChapterFrame::setEndTime(const unsigned int &eT) {
|
||||||
{
|
|
||||||
d->endTime = eT;
|
d->endTime = eT;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChapterFrame::setStartOffset(const unsigned int &sO)
|
void ChapterFrame::setStartOffset(const unsigned int &sO) {
|
||||||
{
|
|
||||||
d->startOffset = sO;
|
d->startOffset = sO;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChapterFrame::setEndOffset(const unsigned int &eO)
|
void ChapterFrame::setEndOffset(const unsigned int &eO) {
|
||||||
{
|
|
||||||
d->endOffset = eO;
|
d->endOffset = eO;
|
||||||
}
|
}
|
||||||
|
|
||||||
const FrameListMap &ChapterFrame::embeddedFrameListMap() const
|
const FrameListMap &ChapterFrame::embeddedFrameListMap() const {
|
||||||
{
|
|
||||||
return d->embeddedFrameListMap;
|
return d->embeddedFrameListMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
const FrameList &ChapterFrame::embeddedFrameList() const
|
const FrameList &ChapterFrame::embeddedFrameList() const {
|
||||||
{
|
|
||||||
return d->embeddedFrameList;
|
return d->embeddedFrameList;
|
||||||
}
|
}
|
||||||
|
|
||||||
const FrameList &ChapterFrame::embeddedFrameList(const ByteVector &frameID) const
|
const FrameList &ChapterFrame::embeddedFrameList(const ByteVector &frameID) const {
|
||||||
{
|
|
||||||
return d->embeddedFrameListMap[frameID];
|
return d->embeddedFrameListMap[frameID];
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChapterFrame::addEmbeddedFrame(Frame *frame)
|
void ChapterFrame::addEmbeddedFrame(Frame *frame) {
|
||||||
{
|
|
||||||
d->embeddedFrameList.append(frame);
|
d->embeddedFrameList.append(frame);
|
||||||
d->embeddedFrameListMap[frame->frameID()].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
|
// remove the frame from the frame list
|
||||||
FrameList::Iterator it = d->embeddedFrameList.find(frame);
|
FrameList::Iterator it = d->embeddedFrameList.find(frame);
|
||||||
d->embeddedFrameList.erase(it);
|
d->embeddedFrameList.erase(it);
|
||||||
@ -180,33 +158,32 @@ void ChapterFrame::removeEmbeddedFrame(Frame *frame, bool del)
|
|||||||
d->embeddedFrameListMap[frame->frameID()].erase(it);
|
d->embeddedFrameListMap[frame->frameID()].erase(it);
|
||||||
|
|
||||||
// ...and delete as desired
|
// ...and delete as desired
|
||||||
if(del)
|
if (del)
|
||||||
delete frame;
|
delete frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChapterFrame::removeEmbeddedFrames(const ByteVector &id)
|
void ChapterFrame::removeEmbeddedFrames(const ByteVector &id) {
|
||||||
{
|
|
||||||
FrameList l = d->embeddedFrameListMap[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);
|
removeEmbeddedFrame(*it, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
String ChapterFrame::toString() const
|
String ChapterFrame::toString() const {
|
||||||
{
|
|
||||||
String s = String(d->elementID) +
|
String s = String(d->elementID) +
|
||||||
": start time: " + String::number(d->startTime) +
|
": start time: " + String::number(d->startTime) +
|
||||||
", end time: " + String::number(d->endTime);
|
", end time: " + String::number(d->endTime);
|
||||||
|
|
||||||
if(d->startOffset != 0xFFFFFFFF)
|
if (d->startOffset != 0xFFFFFFFF)
|
||||||
s += ", start offset: " + String::number(d->startOffset);
|
s += ", start offset: " + String::number(d->startOffset);
|
||||||
|
|
||||||
if(d->endOffset != 0xFFFFFFFF)
|
if (d->endOffset != 0xFFFFFFFF)
|
||||||
s += ", end offset: " + String::number(d->endOffset);
|
s += ", end offset: " + String::number(d->endOffset);
|
||||||
|
|
||||||
if(!d->embeddedFrameList.isEmpty()) {
|
if (!d->embeddedFrameList.isEmpty()) {
|
||||||
StringList frameIDs;
|
StringList frameIDs;
|
||||||
for(FrameList::ConstIterator it = d->embeddedFrameList.begin();
|
for (FrameList::ConstIterator it = d->embeddedFrameList.begin();
|
||||||
it != d->embeddedFrameList.end(); ++it)
|
it != d->embeddedFrameList.end();
|
||||||
|
++it)
|
||||||
frameIDs.append((*it)->frameID());
|
frameIDs.append((*it)->frameID());
|
||||||
s += ", sub-frames: [ " + frameIDs.toString(", ") + " ]";
|
s += ", sub-frames: [ " + frameIDs.toString(", ") + " ]";
|
||||||
}
|
}
|
||||||
@ -214,8 +191,7 @@ String ChapterFrame::toString() const
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyMap ChapterFrame::asProperties() const
|
PropertyMap ChapterFrame::asProperties() const {
|
||||||
{
|
|
||||||
PropertyMap map;
|
PropertyMap map;
|
||||||
|
|
||||||
map.unsupportedData().append(frameID() + String("/") + d->elementID);
|
map.unsupportedData().append(frameID() + String("/") + d->elementID);
|
||||||
@ -223,26 +199,24 @@ PropertyMap ChapterFrame::asProperties() const
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChapterFrame *ChapterFrame::findByElementID(const ID3v2::Tag *tag, const ByteVector &eID) // static
|
ChapterFrame *ChapterFrame::findByElementID(const ID3v2::Tag *tag, const ByteVector &eID) // static
|
||||||
{
|
{
|
||||||
ID3v2::FrameList comments = tag->frameList("CHAP");
|
ID3v2::FrameList comments = tag->frameList("CHAP");
|
||||||
|
|
||||||
for(ID3v2::FrameList::ConstIterator it = comments.begin();
|
for (ID3v2::FrameList::ConstIterator it = comments.begin();
|
||||||
it != comments.end();
|
it != comments.end();
|
||||||
++it)
|
++it) {
|
||||||
{
|
|
||||||
ChapterFrame *frame = dynamic_cast<ChapterFrame *>(*it);
|
ChapterFrame *frame = dynamic_cast<ChapterFrame *>(*it);
|
||||||
if(frame && frame->elementID() == eID)
|
if (frame && frame->elementID() == eID)
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ChapterFrame::parseFields(const ByteVector &data)
|
void ChapterFrame::parseFields(const ByteVector &data) {
|
||||||
{
|
|
||||||
unsigned int size = data.size();
|
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 "
|
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).");
|
"terminated by null and 4x4 bytes for start and end time and offset).");
|
||||||
return;
|
return;
|
||||||
@ -263,17 +237,17 @@ void ChapterFrame::parseFields(const ByteVector &data)
|
|||||||
|
|
||||||
// Embedded frames are optional
|
// Embedded frames are optional
|
||||||
|
|
||||||
if(size < header()->size())
|
if (size < header()->size())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
while(embPos < size - header()->size()) {
|
while (embPos < size - header()->size()) {
|
||||||
Frame *frame = FrameFactory::instance()->createFrame(data.mid(pos + embPos), d->tagHeader);
|
Frame *frame = FrameFactory::instance()->createFrame(data.mid(pos + embPos), d->tagHeader);
|
||||||
|
|
||||||
if(!frame)
|
if (!frame)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Checks to make sure that frame parsed correctly.
|
// Checks to make sure that frame parsed correctly.
|
||||||
if(frame->size() <= 0) {
|
if (frame->size() <= 0) {
|
||||||
delete frame;
|
delete frame;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -283,8 +257,7 @@ void ChapterFrame::parseFields(const ByteVector &data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector ChapterFrame::renderFields() const
|
ByteVector ChapterFrame::renderFields() const {
|
||||||
{
|
|
||||||
ByteVector data;
|
ByteVector data;
|
||||||
|
|
||||||
data.append(d->elementID);
|
data.append(d->elementID);
|
||||||
@ -294,16 +267,14 @@ ByteVector ChapterFrame::renderFields() const
|
|||||||
data.append(ByteVector::fromUInt(d->startOffset, true));
|
data.append(ByteVector::fromUInt(d->startOffset, true));
|
||||||
data.append(ByteVector::fromUInt(d->endOffset, true));
|
data.append(ByteVector::fromUInt(d->endOffset, true));
|
||||||
FrameList l = d->embeddedFrameList;
|
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());
|
data.append((*it)->render());
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChapterFrame::ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data, Header *h) :
|
ChapterFrame::ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data, Header *h) : Frame(h),
|
||||||
Frame(h),
|
d(new ChapterFramePrivate()) {
|
||||||
d(new ChapterFramePrivate())
|
|
||||||
{
|
|
||||||
d->tagHeader = tagHeader;
|
d->tagHeader = tagHeader;
|
||||||
parseFields(fieldData(data));
|
parseFields(fieldData(data));
|
||||||
}
|
}
|
||||||
|
129
3rdparty/taglib/mpeg/id3v2/frames/chapterframe.h
vendored
129
3rdparty/taglib/mpeg/id3v2/frames/chapterframe.h
vendored
@ -33,27 +33,26 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
namespace ID3v2 {
|
namespace ID3v2 {
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* This is an implementation of ID3v2 chapter frames. The purpose of this
|
* This is an implementation of ID3v2 chapter frames. The purpose of this
|
||||||
* frame is to describe a single chapter within an audio file.
|
* 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;
|
||||||
friend class FrameFactory;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/*!
|
/*!
|
||||||
* Creates a chapter frame based on \a data. \a tagHeader is required as
|
* Creates a chapter frame based on \a data. \a tagHeader is required as
|
||||||
* the internal frames are parsed based on the tag version.
|
* the internal frames are parsed based on the tag version.
|
||||||
*/
|
*/
|
||||||
ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data);
|
ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Creates a chapter frame with the element ID \a elementID, start time
|
* Creates a chapter frame with the element ID \a elementID, start time
|
||||||
* \a startTime, end time \a endTime, start offset \a startOffset,
|
* \a startTime, end time \a endTime, start offset \a startOffset,
|
||||||
* end offset \a endOffset and optionally a list of embedded frames,
|
* end offset \a endOffset and optionally a list of embedded frames,
|
||||||
@ -62,95 +61,95 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* All times are in milliseconds.
|
* All times are in milliseconds.
|
||||||
*/
|
*/
|
||||||
ChapterFrame(const ByteVector &elementID,
|
ChapterFrame(const ByteVector &elementID,
|
||||||
unsigned int startTime, unsigned int endTime,
|
unsigned int startTime, unsigned int endTime,
|
||||||
unsigned int startOffset, unsigned int endOffset,
|
unsigned int startOffset, unsigned int endOffset,
|
||||||
const FrameList &embeddedFrames = FrameList());
|
const FrameList &embeddedFrames = FrameList());
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys the frame.
|
* Destroys the frame.
|
||||||
*/
|
*/
|
||||||
virtual ~ChapterFrame();
|
virtual ~ChapterFrame();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the element ID of the frame. Element ID
|
* Returns the element ID of the frame. Element ID
|
||||||
* is a null terminated string, however it's not human-readable.
|
* is a null terminated string, however it's not human-readable.
|
||||||
*
|
*
|
||||||
* \see setElementID()
|
* \see setElementID()
|
||||||
*/
|
*/
|
||||||
ByteVector elementID() const;
|
ByteVector elementID() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns time of chapter's start (in milliseconds).
|
* Returns time of chapter's start (in milliseconds).
|
||||||
*
|
*
|
||||||
* \see setStartTime()
|
* \see setStartTime()
|
||||||
*/
|
*/
|
||||||
unsigned int startTime() const;
|
unsigned int startTime() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns time of chapter's end (in milliseconds).
|
* Returns time of chapter's end (in milliseconds).
|
||||||
*
|
*
|
||||||
* \see setEndTime()
|
* \see setEndTime()
|
||||||
*/
|
*/
|
||||||
unsigned int endTime() const;
|
unsigned int endTime() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns zero based byte offset (count of bytes from the beginning
|
* Returns zero based byte offset (count of bytes from the beginning
|
||||||
* of the audio file) of chapter's start.
|
* of the audio file) of chapter's start.
|
||||||
*
|
*
|
||||||
* \note If returned value is 0xFFFFFFFF, start time should be used instead.
|
* \note If returned value is 0xFFFFFFFF, start time should be used instead.
|
||||||
* \see setStartOffset()
|
* \see setStartOffset()
|
||||||
*/
|
*/
|
||||||
unsigned int startOffset() const;
|
unsigned int startOffset() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns zero based byte offset (count of bytes from the beginning
|
* Returns zero based byte offset (count of bytes from the beginning
|
||||||
* of the audio file) of chapter's end.
|
* of the audio file) of chapter's end.
|
||||||
*
|
*
|
||||||
* \note If returned value is 0xFFFFFFFF, end time should be used instead.
|
* \note If returned value is 0xFFFFFFFF, end time should be used instead.
|
||||||
* \see setEndOffset()
|
* \see setEndOffset()
|
||||||
*/
|
*/
|
||||||
unsigned int endOffset() const;
|
unsigned int endOffset() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the element ID of the frame to \a eID. If \a eID isn't
|
* Sets the element ID of the frame to \a eID. If \a eID isn't
|
||||||
* null terminated, a null char is appended automatically.
|
* null terminated, a null char is appended automatically.
|
||||||
*
|
*
|
||||||
* \see elementID()
|
* \see elementID()
|
||||||
*/
|
*/
|
||||||
void setElementID(const ByteVector &eID);
|
void setElementID(const ByteVector &eID);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets time of chapter's start (in milliseconds) to \a sT.
|
* Sets time of chapter's start (in milliseconds) to \a sT.
|
||||||
*
|
*
|
||||||
* \see startTime()
|
* \see startTime()
|
||||||
*/
|
*/
|
||||||
void setStartTime(const unsigned int &sT);
|
void setStartTime(const unsigned int &sT);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets time of chapter's end (in milliseconds) to \a eT.
|
* Sets time of chapter's end (in milliseconds) to \a eT.
|
||||||
*
|
*
|
||||||
* \see endTime()
|
* \see endTime()
|
||||||
*/
|
*/
|
||||||
void setEndTime(const unsigned int &eT);
|
void setEndTime(const unsigned int &eT);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets zero based byte offset (count of bytes from the beginning
|
* Sets zero based byte offset (count of bytes from the beginning
|
||||||
* of the audio file) of chapter's start to \a sO.
|
* of the audio file) of chapter's start to \a sO.
|
||||||
*
|
*
|
||||||
* \see startOffset()
|
* \see startOffset()
|
||||||
*/
|
*/
|
||||||
void setStartOffset(const unsigned int &sO);
|
void setStartOffset(const unsigned int &sO);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets zero based byte offset (count of bytes from the beginning
|
* Sets zero based byte offset (count of bytes from the beginning
|
||||||
* of the audio file) of chapter's end to \a eO.
|
* of the audio file) of chapter's end to \a eO.
|
||||||
*
|
*
|
||||||
* \see endOffset()
|
* \see endOffset()
|
||||||
*/
|
*/
|
||||||
void setEndOffset(const unsigned int &eO);
|
void setEndOffset(const unsigned int &eO);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns a reference to the frame list map. This is an FrameListMap of
|
* Returns a reference to the frame list map. This is an FrameListMap of
|
||||||
* all of the frames embedded in the CHAP frame.
|
* all of the frames embedded in the CHAP frame.
|
||||||
*
|
*
|
||||||
@ -164,9 +163,9 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \see embeddedFrameList()
|
* \see embeddedFrameList()
|
||||||
*/
|
*/
|
||||||
const FrameListMap &embeddedFrameListMap() const;
|
const FrameListMap &embeddedFrameListMap() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns a reference to the embedded frame list. This is an FrameList
|
* Returns a reference to the embedded frame list. This is an FrameList
|
||||||
* of all of the frames embedded in the CHAP frame in the order that they
|
* of all of the frames embedded in the CHAP frame in the order that they
|
||||||
* were parsed.
|
* were parsed.
|
||||||
@ -177,9 +176,9 @@ namespace TagLib {
|
|||||||
* \warning You should not modify this data structure directly, instead
|
* \warning You should not modify this data structure directly, instead
|
||||||
* use addEmbeddedFrame() and removeEmbeddedFrame().
|
* use addEmbeddedFrame() and removeEmbeddedFrame().
|
||||||
*/
|
*/
|
||||||
const FrameList &embeddedFrameList() const;
|
const FrameList &embeddedFrameList() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the embedded frame list for frames with the id \a frameID
|
* Returns the embedded frame list for frames with the id \a frameID
|
||||||
* or an empty list if there are no embedded frames of that type. This
|
* or an empty list if there are no embedded frames of that type. This
|
||||||
* is just a convenience and is equivalent to:
|
* is just a convenience and is equivalent to:
|
||||||
@ -190,62 +189,62 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \see embeddedFrameListMap()
|
* \see embeddedFrameListMap()
|
||||||
*/
|
*/
|
||||||
const FrameList &embeddedFrameList(const ByteVector &frameID) const;
|
const FrameList &embeddedFrameList(const ByteVector &frameID) const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Add an embedded frame to the CHAP frame. At this point the CHAP frame
|
* Add an embedded frame to the CHAP frame. At this point the CHAP frame
|
||||||
* takes ownership of the embedded frame and will handle freeing its memory.
|
* takes ownership of the embedded frame and will handle freeing its memory.
|
||||||
*
|
*
|
||||||
* \note Using this method will invalidate any pointers on the list
|
* \note Using this method will invalidate any pointers on the list
|
||||||
* returned by embeddedFrameList()
|
* returned by embeddedFrameList()
|
||||||
*/
|
*/
|
||||||
void addEmbeddedFrame(Frame *frame);
|
void addEmbeddedFrame(Frame *frame);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Remove an embedded frame from the CHAP frame. If \a del is true the frame's
|
* Remove an embedded frame from the CHAP frame. If \a del is true the frame's
|
||||||
* memory will be freed; if it is false, it must be deleted by the user.
|
* memory will be freed; if it is false, it must be deleted by the user.
|
||||||
*
|
*
|
||||||
* \note Using this method will invalidate any pointers on the list
|
* \note Using this method will invalidate any pointers on the list
|
||||||
* returned by embeddedFrameList()
|
* returned by embeddedFrameList()
|
||||||
*/
|
*/
|
||||||
void removeEmbeddedFrame(Frame *frame, bool del = true);
|
void removeEmbeddedFrame(Frame *frame, bool del = true);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Remove all embedded frames of type \a id from the CHAP frame and free their
|
* Remove all embedded frames of type \a id from the CHAP frame and free their
|
||||||
* memory.
|
* memory.
|
||||||
*
|
*
|
||||||
* \note Using this method will invalidate any pointers on the list
|
* \note Using this method will invalidate any pointers on the list
|
||||||
* returned by embeddedFrameList()
|
* returned by embeddedFrameList()
|
||||||
*/
|
*/
|
||||||
void removeEmbeddedFrames(const ByteVector &id);
|
void removeEmbeddedFrames(const ByteVector &id);
|
||||||
|
|
||||||
virtual String toString() const;
|
virtual String toString() const;
|
||||||
|
|
||||||
PropertyMap asProperties() const;
|
PropertyMap asProperties() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* CHAP frames each have a unique element ID. This searches for a CHAP
|
* CHAP frames each have a unique element ID. This searches for a CHAP
|
||||||
* frame with the element ID \a eID and returns a pointer to it. This
|
* frame with the element ID \a eID and returns a pointer to it. This
|
||||||
* can be used to link CTOC and CHAP frames together.
|
* can be used to link CTOC and CHAP frames together.
|
||||||
*
|
*
|
||||||
* \see elementID()
|
* \see elementID()
|
||||||
*/
|
*/
|
||||||
static ChapterFrame *findByElementID(const Tag *tag, const ByteVector &eID);
|
static ChapterFrame *findByElementID(const Tag *tag, const ByteVector &eID);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void parseFields(const ByteVector &data);
|
virtual void parseFields(const ByteVector &data);
|
||||||
virtual ByteVector renderFields() const;
|
virtual ByteVector renderFields() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data, Header *h);
|
ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data, Header *h);
|
||||||
ChapterFrame(const ChapterFrame &);
|
ChapterFrame(const ChapterFrame &);
|
||||||
ChapterFrame &operator=(const ChapterFrame &);
|
ChapterFrame &operator=(const ChapterFrame &);
|
||||||
|
|
||||||
class ChapterFramePrivate;
|
class ChapterFramePrivate;
|
||||||
ChapterFramePrivate *d;
|
ChapterFramePrivate *d;
|
||||||
};
|
};
|
||||||
}
|
} // namespace ID3v2
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -34,9 +34,8 @@
|
|||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
using namespace ID3v2;
|
using namespace ID3v2;
|
||||||
|
|
||||||
class CommentsFrame::CommentsFramePrivate
|
class CommentsFrame::CommentsFramePrivate {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
CommentsFramePrivate() : textEncoding(String::Latin1) {}
|
CommentsFramePrivate() : textEncoding(String::Latin1) {}
|
||||||
String::Type textEncoding;
|
String::Type textEncoding;
|
||||||
ByteVector language;
|
ByteVector language;
|
||||||
@ -48,91 +47,75 @@ public:
|
|||||||
// public members
|
// public members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
CommentsFrame::CommentsFrame(String::Type encoding) :
|
CommentsFrame::CommentsFrame(String::Type encoding) : Frame("COMM"),
|
||||||
Frame("COMM"),
|
d(new CommentsFramePrivate()) {
|
||||||
d(new CommentsFramePrivate())
|
|
||||||
{
|
|
||||||
d->textEncoding = encoding;
|
d->textEncoding = encoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
CommentsFrame::CommentsFrame(const ByteVector &data) :
|
CommentsFrame::CommentsFrame(const ByteVector &data) : Frame(data),
|
||||||
Frame(data),
|
d(new CommentsFramePrivate()) {
|
||||||
d(new CommentsFramePrivate())
|
|
||||||
{
|
|
||||||
setData(data);
|
setData(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
CommentsFrame::~CommentsFrame()
|
CommentsFrame::~CommentsFrame() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
String CommentsFrame::toString() const
|
String CommentsFrame::toString() const {
|
||||||
{
|
|
||||||
return d->text;
|
return d->text;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector CommentsFrame::language() const
|
ByteVector CommentsFrame::language() const {
|
||||||
{
|
|
||||||
return d->language;
|
return d->language;
|
||||||
}
|
}
|
||||||
|
|
||||||
String CommentsFrame::description() const
|
String CommentsFrame::description() const {
|
||||||
{
|
|
||||||
return d->description;
|
return d->description;
|
||||||
}
|
}
|
||||||
|
|
||||||
String CommentsFrame::text() const
|
String CommentsFrame::text() const {
|
||||||
{
|
|
||||||
return d->text;
|
return d->text;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommentsFrame::setLanguage(const ByteVector &languageEncoding)
|
void CommentsFrame::setLanguage(const ByteVector &languageEncoding) {
|
||||||
{
|
|
||||||
d->language = languageEncoding.mid(0, 3);
|
d->language = languageEncoding.mid(0, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommentsFrame::setDescription(const String &s)
|
void CommentsFrame::setDescription(const String &s) {
|
||||||
{
|
|
||||||
d->description = s;
|
d->description = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommentsFrame::setText(const String &s)
|
void CommentsFrame::setText(const String &s) {
|
||||||
{
|
|
||||||
d->text = s;
|
d->text = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
String::Type CommentsFrame::textEncoding() const
|
String::Type CommentsFrame::textEncoding() const {
|
||||||
{
|
|
||||||
return d->textEncoding;
|
return d->textEncoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommentsFrame::setTextEncoding(String::Type encoding)
|
void CommentsFrame::setTextEncoding(String::Type encoding) {
|
||||||
{
|
|
||||||
d->textEncoding = encoding;
|
d->textEncoding = encoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
PropertyMap CommentsFrame::asProperties() const
|
PropertyMap CommentsFrame::asProperties() const {
|
||||||
{
|
|
||||||
String key = description().upper();
|
String key = description().upper();
|
||||||
PropertyMap map;
|
PropertyMap map;
|
||||||
if(key.isEmpty() || key == "COMMENT")
|
if (key.isEmpty() || key == "COMMENT")
|
||||||
map.insert("COMMENT", text());
|
map.insert("COMMENT", text());
|
||||||
else
|
else
|
||||||
map.insert("COMMENT:" + key, text());
|
map.insert("COMMENT:" + key, text());
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
CommentsFrame *CommentsFrame::findByDescription(const ID3v2::Tag *tag, const String &d) // static
|
CommentsFrame *CommentsFrame::findByDescription(const ID3v2::Tag *tag, const String &d) // static
|
||||||
{
|
{
|
||||||
ID3v2::FrameList comments = tag->frameList("COMM");
|
ID3v2::FrameList comments = tag->frameList("COMM");
|
||||||
|
|
||||||
for(ID3v2::FrameList::ConstIterator it = comments.begin();
|
for (ID3v2::FrameList::ConstIterator it = comments.begin();
|
||||||
it != comments.end();
|
it != comments.end();
|
||||||
++it)
|
++it) {
|
||||||
{
|
|
||||||
CommentsFrame *frame = dynamic_cast<CommentsFrame *>(*it);
|
CommentsFrame *frame = dynamic_cast<CommentsFrame *>(*it);
|
||||||
if(frame && frame->description() == d)
|
if (frame && frame->description() == d)
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -143,9 +126,8 @@ CommentsFrame *CommentsFrame::findByDescription(const ID3v2::Tag *tag, const Str
|
|||||||
// protected members
|
// protected members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void CommentsFrame::parseFields(const ByteVector &data)
|
void CommentsFrame::parseFields(const ByteVector &data) {
|
||||||
{
|
if (data.size() < 5) {
|
||||||
if(data.size() < 5) {
|
|
||||||
debug("A comment frame must contain at least 5 bytes.");
|
debug("A comment frame must contain at least 5 bytes.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -157,19 +139,19 @@ void CommentsFrame::parseFields(const ByteVector &data)
|
|||||||
|
|
||||||
ByteVectorList l = ByteVectorList::split(data.mid(4), textDelimiter(d->textEncoding), byteAlign, 2);
|
ByteVectorList l = ByteVectorList::split(data.mid(4), textDelimiter(d->textEncoding), byteAlign, 2);
|
||||||
|
|
||||||
if(l.size() == 2) {
|
if (l.size() == 2) {
|
||||||
if(d->textEncoding == String::Latin1) {
|
if (d->textEncoding == String::Latin1) {
|
||||||
d->description = Tag::latin1StringHandler()->parse(l.front());
|
d->description = Tag::latin1StringHandler()->parse(l.front());
|
||||||
d->text = Tag::latin1StringHandler()->parse(l.back());
|
d->text = Tag::latin1StringHandler()->parse(l.back());
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
d->description = String(l.front(), d->textEncoding);
|
d->description = String(l.front(), d->textEncoding);
|
||||||
d->text = String(l.back(), d->textEncoding);
|
d->text = String(l.back(), d->textEncoding);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector CommentsFrame::renderFields() const
|
ByteVector CommentsFrame::renderFields() const {
|
||||||
{
|
|
||||||
ByteVector v;
|
ByteVector v;
|
||||||
|
|
||||||
String::Type encoding = d->textEncoding;
|
String::Type encoding = d->textEncoding;
|
||||||
@ -190,9 +172,7 @@ ByteVector CommentsFrame::renderFields() const
|
|||||||
// private members
|
// private members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
CommentsFrame::CommentsFrame(const ByteVector &data, Header *h) :
|
CommentsFrame::CommentsFrame(const ByteVector &data, Header *h) : Frame(h),
|
||||||
Frame(h),
|
d(new CommentsFramePrivate()) {
|
||||||
d(new CommentsFramePrivate())
|
|
||||||
{
|
|
||||||
parseFields(fieldData(data));
|
parseFields(fieldData(data));
|
||||||
}
|
}
|
||||||
|
@ -32,44 +32,43 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace 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
|
* This implements the ID3v2 comment format. An ID3v2 comment consists of
|
||||||
* a language encoding, a description and a single text field.
|
* 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;
|
||||||
friend class FrameFactory;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/*!
|
/*!
|
||||||
* Construct an empty comment frame that will use the text encoding
|
* Construct an empty comment frame that will use the text encoding
|
||||||
* \a encoding.
|
* \a encoding.
|
||||||
*/
|
*/
|
||||||
explicit CommentsFrame(String::Type encoding = String::Latin1);
|
explicit CommentsFrame(String::Type encoding = String::Latin1);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Construct a comment based on the data in \a data.
|
* Construct a comment based on the data in \a data.
|
||||||
*/
|
*/
|
||||||
explicit CommentsFrame(const ByteVector &data);
|
explicit CommentsFrame(const ByteVector &data);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys this CommentFrame instance.
|
* Destroys this CommentFrame instance.
|
||||||
*/
|
*/
|
||||||
virtual ~CommentsFrame();
|
virtual ~CommentsFrame();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the text of this comment.
|
* Returns the text of this comment.
|
||||||
*
|
*
|
||||||
* \see text()
|
* \see text()
|
||||||
*/
|
*/
|
||||||
virtual String toString() const;
|
virtual String toString() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the language encoding as a 3 byte encoding as specified by
|
* Returns the language encoding as a 3 byte encoding as specified by
|
||||||
* <a href="http://en.wikipedia.org/wiki/ISO_639">ISO-639-2</a>.
|
* <a href="http://en.wikipedia.org/wiki/ISO_639">ISO-639-2</a>.
|
||||||
*
|
*
|
||||||
@ -77,48 +76,48 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \see setLanguage()
|
* \see setLanguage()
|
||||||
*/
|
*/
|
||||||
ByteVector language() const;
|
ByteVector language() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the description of this comment.
|
* Returns the description of this comment.
|
||||||
*
|
*
|
||||||
* \note Most taggers simply ignore this value.
|
* \note Most taggers simply ignore this value.
|
||||||
*
|
*
|
||||||
* \see setDescription()
|
* \see setDescription()
|
||||||
*/
|
*/
|
||||||
String description() const;
|
String description() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the text of this comment.
|
* Returns the text of this comment.
|
||||||
*
|
*
|
||||||
* \see setText()
|
* \see setText()
|
||||||
*/
|
*/
|
||||||
String text() const;
|
String text() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Set the language using the 3 byte language code from
|
* Set the language using the 3 byte language code from
|
||||||
* <a href="http://en.wikipedia.org/wiki/ISO_639">ISO-639-2</a> to
|
* <a href="http://en.wikipedia.org/wiki/ISO_639">ISO-639-2</a> to
|
||||||
* \a languageCode.
|
* \a languageCode.
|
||||||
*
|
*
|
||||||
* \see language()
|
* \see language()
|
||||||
*/
|
*/
|
||||||
void setLanguage(const ByteVector &languageCode);
|
void setLanguage(const ByteVector &languageCode);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the description of the comment to \a s.
|
* Sets the description of the comment to \a s.
|
||||||
*
|
*
|
||||||
* \see description()
|
* \see description()
|
||||||
*/
|
*/
|
||||||
void setDescription(const String &s);
|
void setDescription(const String &s);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the text portion of the comment to \a s.
|
* Sets the text portion of the comment to \a s.
|
||||||
*
|
*
|
||||||
* \see text()
|
* \see text()
|
||||||
*/
|
*/
|
||||||
virtual void setText(const String &s);
|
virtual void setText(const String &s);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the text encoding that will be used in rendering this frame.
|
* Returns the text encoding that will be used in rendering this frame.
|
||||||
* This defaults to the type that was either specified in the constructor
|
* This defaults to the type that was either specified in the constructor
|
||||||
* or read from the frame when parsed.
|
* or read from the frame when parsed.
|
||||||
@ -126,18 +125,18 @@ namespace TagLib {
|
|||||||
* \see setTextEncoding()
|
* \see setTextEncoding()
|
||||||
* \see render()
|
* \see render()
|
||||||
*/
|
*/
|
||||||
String::Type textEncoding() const;
|
String::Type textEncoding() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the text encoding to be used when rendering this frame to
|
* Sets the text encoding to be used when rendering this frame to
|
||||||
* \a encoding.
|
* \a encoding.
|
||||||
*
|
*
|
||||||
* \see textEncoding()
|
* \see textEncoding()
|
||||||
* \see render()
|
* \see render()
|
||||||
*/
|
*/
|
||||||
void setTextEncoding(String::Type encoding);
|
void setTextEncoding(String::Type encoding);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Parses this frame as PropertyMap with a single key.
|
* Parses this frame as PropertyMap with a single key.
|
||||||
* - if description() is empty or "COMMENT", the key will be "COMMENT"
|
* - if description() is empty or "COMMENT", the key will be "COMMENT"
|
||||||
* - if description() is not a valid PropertyMap key, the frame will be
|
* - if description() is not a valid PropertyMap key, the frame will be
|
||||||
@ -146,36 +145,36 @@ namespace TagLib {
|
|||||||
* - otherwise, the key will be "COMMENT:<description>"
|
* - otherwise, the key will be "COMMENT:<description>"
|
||||||
* - The single value will be the frame's text().
|
* - The single value will be the frame's text().
|
||||||
*/
|
*/
|
||||||
PropertyMap asProperties() const;
|
PropertyMap asProperties() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Comments each have a unique description. This searches for a comment
|
* Comments each have a unique description. This searches for a comment
|
||||||
* frame with the description \a d and returns a pointer to it. If no
|
* frame with the description \a d and returns a pointer to it. If no
|
||||||
* frame is found that matches the given description null is returned.
|
* frame is found that matches the given description null is returned.
|
||||||
*
|
*
|
||||||
* \see description()
|
* \see description()
|
||||||
*/
|
*/
|
||||||
static CommentsFrame *findByDescription(const Tag *tag, const String &d);
|
static CommentsFrame *findByDescription(const Tag *tag, const String &d);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Reimplementations.
|
// Reimplementations.
|
||||||
|
|
||||||
virtual void parseFields(const ByteVector &data);
|
virtual void parseFields(const ByteVector &data);
|
||||||
virtual ByteVector renderFields() const;
|
virtual ByteVector renderFields() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*!
|
/*!
|
||||||
* The constructor used by the FrameFactory.
|
* The constructor used by the FrameFactory.
|
||||||
*/
|
*/
|
||||||
CommentsFrame(const ByteVector &data, Header *h);
|
CommentsFrame(const ByteVector &data, Header *h);
|
||||||
CommentsFrame(const CommentsFrame &);
|
CommentsFrame(const CommentsFrame &);
|
||||||
CommentsFrame &operator=(const CommentsFrame &);
|
CommentsFrame &operator=(const CommentsFrame &);
|
||||||
|
|
||||||
class CommentsFramePrivate;
|
class CommentsFramePrivate;
|
||||||
CommentsFramePrivate *d;
|
CommentsFramePrivate *d;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace ID3v2
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
#endif
|
#endif
|
||||||
|
@ -32,11 +32,9 @@
|
|||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
using namespace ID3v2;
|
using namespace ID3v2;
|
||||||
|
|
||||||
class EventTimingCodesFrame::EventTimingCodesFramePrivate
|
class EventTimingCodesFrame::EventTimingCodesFramePrivate {
|
||||||
{
|
public:
|
||||||
public:
|
EventTimingCodesFramePrivate() : timestampFormat(EventTimingCodesFrame::AbsoluteMilliseconds) {}
|
||||||
EventTimingCodesFramePrivate() :
|
|
||||||
timestampFormat(EventTimingCodesFrame::AbsoluteMilliseconds) {}
|
|
||||||
EventTimingCodesFrame::TimestampFormat timestampFormat;
|
EventTimingCodesFrame::TimestampFormat timestampFormat;
|
||||||
EventTimingCodesFrame::SynchedEventList synchedEvents;
|
EventTimingCodesFrame::SynchedEventList synchedEvents;
|
||||||
};
|
};
|
||||||
@ -45,50 +43,40 @@ public:
|
|||||||
// public members
|
// public members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
EventTimingCodesFrame::EventTimingCodesFrame() :
|
EventTimingCodesFrame::EventTimingCodesFrame() : Frame("ETCO"),
|
||||||
Frame("ETCO"),
|
d(new EventTimingCodesFramePrivate()) {
|
||||||
d(new EventTimingCodesFramePrivate())
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
EventTimingCodesFrame::EventTimingCodesFrame(const ByteVector &data) :
|
EventTimingCodesFrame::EventTimingCodesFrame(const ByteVector &data) : Frame(data),
|
||||||
Frame(data),
|
d(new EventTimingCodesFramePrivate()) {
|
||||||
d(new EventTimingCodesFramePrivate())
|
|
||||||
{
|
|
||||||
setData(data);
|
setData(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
EventTimingCodesFrame::~EventTimingCodesFrame()
|
EventTimingCodesFrame::~EventTimingCodesFrame() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
String EventTimingCodesFrame::toString() const
|
String EventTimingCodesFrame::toString() const {
|
||||||
{
|
|
||||||
return String();
|
return String();
|
||||||
}
|
}
|
||||||
|
|
||||||
EventTimingCodesFrame::TimestampFormat
|
EventTimingCodesFrame::TimestampFormat
|
||||||
EventTimingCodesFrame::timestampFormat() const
|
EventTimingCodesFrame::timestampFormat() const {
|
||||||
{
|
|
||||||
return d->timestampFormat;
|
return d->timestampFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
EventTimingCodesFrame::SynchedEventList
|
EventTimingCodesFrame::SynchedEventList
|
||||||
EventTimingCodesFrame::synchedEvents() const
|
EventTimingCodesFrame::synchedEvents() const {
|
||||||
{
|
|
||||||
return d->synchedEvents;
|
return d->synchedEvents;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventTimingCodesFrame::setTimestampFormat(
|
void EventTimingCodesFrame::setTimestampFormat(
|
||||||
EventTimingCodesFrame::TimestampFormat f)
|
EventTimingCodesFrame::TimestampFormat f) {
|
||||||
{
|
|
||||||
d->timestampFormat = f;
|
d->timestampFormat = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EventTimingCodesFrame::setSynchedEvents(
|
void EventTimingCodesFrame::setSynchedEvents(
|
||||||
const EventTimingCodesFrame::SynchedEventList &e)
|
const EventTimingCodesFrame::SynchedEventList &e) {
|
||||||
{
|
|
||||||
d->synchedEvents = e;
|
d->synchedEvents = e;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,10 +84,9 @@ void EventTimingCodesFrame::setSynchedEvents(
|
|||||||
// protected members
|
// protected members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void EventTimingCodesFrame::parseFields(const ByteVector &data)
|
void EventTimingCodesFrame::parseFields(const ByteVector &data) {
|
||||||
{
|
|
||||||
const int end = data.size();
|
const int end = data.size();
|
||||||
if(end < 1) {
|
if (end < 1) {
|
||||||
debug("An event timing codes frame must contain at least 1 byte.");
|
debug("An event timing codes frame must contain at least 1 byte.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -108,7 +95,7 @@ void EventTimingCodesFrame::parseFields(const ByteVector &data)
|
|||||||
|
|
||||||
int pos = 1;
|
int pos = 1;
|
||||||
d->synchedEvents.clear();
|
d->synchedEvents.clear();
|
||||||
while(pos + 4 < end) {
|
while (pos + 4 < end) {
|
||||||
EventType type = static_cast<EventType>(static_cast<unsigned char>(data[pos++]));
|
EventType type = static_cast<EventType>(static_cast<unsigned char>(data[pos++]));
|
||||||
unsigned int time = data.toUInt(pos, true);
|
unsigned int time = data.toUInt(pos, true);
|
||||||
pos += 4;
|
pos += 4;
|
||||||
@ -116,14 +103,13 @@ void EventTimingCodesFrame::parseFields(const ByteVector &data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector EventTimingCodesFrame::renderFields() const
|
ByteVector EventTimingCodesFrame::renderFields() const {
|
||||||
{
|
|
||||||
ByteVector v;
|
ByteVector v;
|
||||||
|
|
||||||
v.append(char(d->timestampFormat));
|
v.append(char(d->timestampFormat));
|
||||||
for(SynchedEventList::ConstIterator it = d->synchedEvents.begin();
|
for (SynchedEventList::ConstIterator it = d->synchedEvents.begin();
|
||||||
it != d->synchedEvents.end();
|
it != d->synchedEvents.end();
|
||||||
++it) {
|
++it) {
|
||||||
const SynchedEvent &entry = *it;
|
const SynchedEvent &entry = *it;
|
||||||
v.append(char(entry.type));
|
v.append(char(entry.type));
|
||||||
v.append(ByteVector::fromUInt(entry.time));
|
v.append(ByteVector::fromUInt(entry.time));
|
||||||
@ -136,9 +122,7 @@ ByteVector EventTimingCodesFrame::renderFields() const
|
|||||||
// private members
|
// private members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
EventTimingCodesFrame::EventTimingCodesFrame(const ByteVector &data, Header *h) :
|
EventTimingCodesFrame::EventTimingCodesFrame(const ByteVector &data, Header *h) : Frame(h),
|
||||||
Frame(h),
|
d(new EventTimingCodesFramePrivate()) {
|
||||||
d(new EventTimingCodesFramePrivate())
|
|
||||||
{
|
|
||||||
parseFields(fieldData(data));
|
parseFields(fieldData(data));
|
||||||
}
|
}
|
||||||
|
@ -32,156 +32,154 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
namespace ID3v2 {
|
namespace ID3v2 {
|
||||||
|
|
||||||
//! ID3v2 event timing codes frame
|
//! ID3v2 event timing codes frame
|
||||||
/*!
|
/*!
|
||||||
* An implementation of ID3v2 event timing codes.
|
* An implementation of ID3v2 event timing codes.
|
||||||
*/
|
*/
|
||||||
class TAGLIB_EXPORT EventTimingCodesFrame : public Frame
|
class TAGLIB_EXPORT EventTimingCodesFrame : public Frame {
|
||||||
{
|
friend class FrameFactory;
|
||||||
friend class FrameFactory;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/*!
|
||||||
/*!
|
|
||||||
* Specifies the timestamp format used.
|
* Specifies the timestamp format used.
|
||||||
*/
|
*/
|
||||||
enum TimestampFormat {
|
enum TimestampFormat {
|
||||||
//! The timestamp is of unknown format.
|
//! The timestamp is of unknown format.
|
||||||
Unknown = 0x00,
|
Unknown = 0x00,
|
||||||
//! The timestamp represents the number of MPEG frames since
|
//! The timestamp represents the number of MPEG frames since
|
||||||
//! the beginning of the audio stream.
|
//! the beginning of the audio stream.
|
||||||
AbsoluteMpegFrames = 0x01,
|
AbsoluteMpegFrames = 0x01,
|
||||||
//! The timestamp represents the number of milliseconds since
|
//! The timestamp represents the number of milliseconds since
|
||||||
//! the beginning of the audio stream.
|
//! the beginning of the audio stream.
|
||||||
AbsoluteMilliseconds = 0x02
|
AbsoluteMilliseconds = 0x02
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Event types defined in id3v2.4.0-frames.txt 4.5. Event timing codes.
|
* Event types defined in id3v2.4.0-frames.txt 4.5. Event timing codes.
|
||||||
*/
|
*/
|
||||||
enum EventType {
|
enum EventType {
|
||||||
Padding = 0x00,
|
Padding = 0x00,
|
||||||
EndOfInitialSilence = 0x01,
|
EndOfInitialSilence = 0x01,
|
||||||
IntroStart = 0x02,
|
IntroStart = 0x02,
|
||||||
MainPartStart = 0x03,
|
MainPartStart = 0x03,
|
||||||
OutroStart = 0x04,
|
OutroStart = 0x04,
|
||||||
OutroEnd = 0x05,
|
OutroEnd = 0x05,
|
||||||
VerseStart = 0x06,
|
VerseStart = 0x06,
|
||||||
RefrainStart = 0x07,
|
RefrainStart = 0x07,
|
||||||
InterludeStart = 0x08,
|
InterludeStart = 0x08,
|
||||||
ThemeStart = 0x09,
|
ThemeStart = 0x09,
|
||||||
VariationStart = 0x0a,
|
VariationStart = 0x0a,
|
||||||
KeyChange = 0x0b,
|
KeyChange = 0x0b,
|
||||||
TimeChange = 0x0c,
|
TimeChange = 0x0c,
|
||||||
MomentaryUnwantedNoise = 0x0d,
|
MomentaryUnwantedNoise = 0x0d,
|
||||||
SustainedNoise = 0x0e,
|
SustainedNoise = 0x0e,
|
||||||
SustainedNoiseEnd = 0x0f,
|
SustainedNoiseEnd = 0x0f,
|
||||||
IntroEnd = 0x10,
|
IntroEnd = 0x10,
|
||||||
MainPartEnd = 0x11,
|
MainPartEnd = 0x11,
|
||||||
VerseEnd = 0x12,
|
VerseEnd = 0x12,
|
||||||
RefrainEnd = 0x13,
|
RefrainEnd = 0x13,
|
||||||
ThemeEnd = 0x14,
|
ThemeEnd = 0x14,
|
||||||
Profanity = 0x15,
|
Profanity = 0x15,
|
||||||
ProfanityEnd = 0x16,
|
ProfanityEnd = 0x16,
|
||||||
NotPredefinedSynch0 = 0xe0,
|
NotPredefinedSynch0 = 0xe0,
|
||||||
NotPredefinedSynch1 = 0xe1,
|
NotPredefinedSynch1 = 0xe1,
|
||||||
NotPredefinedSynch2 = 0xe2,
|
NotPredefinedSynch2 = 0xe2,
|
||||||
NotPredefinedSynch3 = 0xe3,
|
NotPredefinedSynch3 = 0xe3,
|
||||||
NotPredefinedSynch4 = 0xe4,
|
NotPredefinedSynch4 = 0xe4,
|
||||||
NotPredefinedSynch5 = 0xe5,
|
NotPredefinedSynch5 = 0xe5,
|
||||||
NotPredefinedSynch6 = 0xe6,
|
NotPredefinedSynch6 = 0xe6,
|
||||||
NotPredefinedSynch7 = 0xe7,
|
NotPredefinedSynch7 = 0xe7,
|
||||||
NotPredefinedSynch8 = 0xe8,
|
NotPredefinedSynch8 = 0xe8,
|
||||||
NotPredefinedSynch9 = 0xe9,
|
NotPredefinedSynch9 = 0xe9,
|
||||||
NotPredefinedSynchA = 0xea,
|
NotPredefinedSynchA = 0xea,
|
||||||
NotPredefinedSynchB = 0xeb,
|
NotPredefinedSynchB = 0xeb,
|
||||||
NotPredefinedSynchC = 0xec,
|
NotPredefinedSynchC = 0xec,
|
||||||
NotPredefinedSynchD = 0xed,
|
NotPredefinedSynchD = 0xed,
|
||||||
NotPredefinedSynchE = 0xee,
|
NotPredefinedSynchE = 0xee,
|
||||||
NotPredefinedSynchF = 0xef,
|
NotPredefinedSynchF = 0xef,
|
||||||
AudioEnd = 0xfd,
|
AudioEnd = 0xfd,
|
||||||
AudioFileEnds = 0xfe
|
AudioFileEnds = 0xfe
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Single entry of time stamp and event.
|
* Single entry of time stamp and event.
|
||||||
*/
|
*/
|
||||||
struct SynchedEvent {
|
struct SynchedEvent {
|
||||||
SynchedEvent(unsigned int ms, EventType t) : time(ms), type(t) {}
|
SynchedEvent(unsigned int ms, EventType t) : time(ms), type(t) {}
|
||||||
unsigned int time;
|
unsigned int time;
|
||||||
EventType type;
|
EventType type;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* List of synchronized events.
|
* List of synchronized events.
|
||||||
*/
|
*/
|
||||||
typedef Strawberry_TagLib::TagLib::List<SynchedEvent> SynchedEventList;
|
typedef Strawberry_TagLib::TagLib::List<SynchedEvent> SynchedEventList;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Construct an empty event timing codes frame.
|
* Construct an empty event timing codes frame.
|
||||||
*/
|
*/
|
||||||
explicit EventTimingCodesFrame();
|
explicit EventTimingCodesFrame();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Construct a event timing codes frame based on the data in \a data.
|
* Construct a event timing codes frame based on the data in \a data.
|
||||||
*/
|
*/
|
||||||
explicit EventTimingCodesFrame(const ByteVector &data);
|
explicit EventTimingCodesFrame(const ByteVector &data);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys this EventTimingCodesFrame instance.
|
* Destroys this EventTimingCodesFrame instance.
|
||||||
*/
|
*/
|
||||||
virtual ~EventTimingCodesFrame();
|
virtual ~EventTimingCodesFrame();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns a null string.
|
* Returns a null string.
|
||||||
*/
|
*/
|
||||||
virtual String toString() const;
|
virtual String toString() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the timestamp format.
|
* Returns the timestamp format.
|
||||||
*/
|
*/
|
||||||
TimestampFormat timestampFormat() const;
|
TimestampFormat timestampFormat() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the events with the time stamps.
|
* Returns the events with the time stamps.
|
||||||
*/
|
*/
|
||||||
SynchedEventList synchedEvents() const;
|
SynchedEventList synchedEvents() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Set the timestamp format.
|
* Set the timestamp format.
|
||||||
*
|
*
|
||||||
* \see timestampFormat()
|
* \see timestampFormat()
|
||||||
*/
|
*/
|
||||||
void setTimestampFormat(TimestampFormat f);
|
void setTimestampFormat(TimestampFormat f);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the text with the time stamps.
|
* Sets the text with the time stamps.
|
||||||
*
|
*
|
||||||
* \see text()
|
* \see text()
|
||||||
*/
|
*/
|
||||||
void setSynchedEvents(const SynchedEventList &e);
|
void setSynchedEvents(const SynchedEventList &e);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Reimplementations.
|
// Reimplementations.
|
||||||
|
|
||||||
virtual void parseFields(const ByteVector &data);
|
virtual void parseFields(const ByteVector &data);
|
||||||
virtual ByteVector renderFields() const;
|
virtual ByteVector renderFields() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*!
|
/*!
|
||||||
* The constructor used by the FrameFactory.
|
* The constructor used by the FrameFactory.
|
||||||
*/
|
*/
|
||||||
EventTimingCodesFrame(const ByteVector &data, Header *h);
|
EventTimingCodesFrame(const ByteVector &data, Header *h);
|
||||||
EventTimingCodesFrame(const EventTimingCodesFrame &);
|
EventTimingCodesFrame(const EventTimingCodesFrame &);
|
||||||
EventTimingCodesFrame &operator=(const EventTimingCodesFrame &);
|
EventTimingCodesFrame &operator=(const EventTimingCodesFrame &);
|
||||||
|
|
||||||
class EventTimingCodesFramePrivate;
|
class EventTimingCodesFramePrivate;
|
||||||
EventTimingCodesFramePrivate *d;
|
EventTimingCodesFramePrivate *d;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace ID3v2
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
#endif
|
#endif
|
||||||
|
@ -34,9 +34,8 @@
|
|||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
using namespace ID3v2;
|
using namespace ID3v2;
|
||||||
|
|
||||||
class GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFramePrivate
|
class GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFramePrivate {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
GeneralEncapsulatedObjectFramePrivate() : textEncoding(String::Latin1) {}
|
GeneralEncapsulatedObjectFramePrivate() : textEncoding(String::Latin1) {}
|
||||||
|
|
||||||
String::Type textEncoding;
|
String::Type textEncoding;
|
||||||
@ -50,84 +49,68 @@ public:
|
|||||||
// public members
|
// public members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame() :
|
GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame() : Frame("GEOB"),
|
||||||
Frame("GEOB"),
|
d(new GeneralEncapsulatedObjectFramePrivate()) {
|
||||||
d(new GeneralEncapsulatedObjectFramePrivate())
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame(const ByteVector &data) :
|
GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame(const ByteVector &data) : Frame(data),
|
||||||
Frame(data),
|
d(new GeneralEncapsulatedObjectFramePrivate()) {
|
||||||
d(new GeneralEncapsulatedObjectFramePrivate())
|
|
||||||
{
|
|
||||||
setData(data);
|
setData(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
GeneralEncapsulatedObjectFrame::~GeneralEncapsulatedObjectFrame()
|
GeneralEncapsulatedObjectFrame::~GeneralEncapsulatedObjectFrame() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
String GeneralEncapsulatedObjectFrame::toString() const
|
String GeneralEncapsulatedObjectFrame::toString() const {
|
||||||
{
|
|
||||||
String text = "[" + d->mimeType + "]";
|
String text = "[" + d->mimeType + "]";
|
||||||
|
|
||||||
if(!d->fileName.isEmpty())
|
if (!d->fileName.isEmpty())
|
||||||
text += " " + d->fileName;
|
text += " " + d->fileName;
|
||||||
|
|
||||||
if(!d->description.isEmpty())
|
if (!d->description.isEmpty())
|
||||||
text += " \"" + d->description + "\"";
|
text += " \"" + d->description + "\"";
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
String::Type GeneralEncapsulatedObjectFrame::textEncoding() const
|
String::Type GeneralEncapsulatedObjectFrame::textEncoding() const {
|
||||||
{
|
|
||||||
return d->textEncoding;
|
return d->textEncoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeneralEncapsulatedObjectFrame::setTextEncoding(String::Type encoding)
|
void GeneralEncapsulatedObjectFrame::setTextEncoding(String::Type encoding) {
|
||||||
{
|
|
||||||
d->textEncoding = encoding;
|
d->textEncoding = encoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
String GeneralEncapsulatedObjectFrame::mimeType() const
|
String GeneralEncapsulatedObjectFrame::mimeType() const {
|
||||||
{
|
|
||||||
return d->mimeType;
|
return d->mimeType;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeneralEncapsulatedObjectFrame::setMimeType(const String &type)
|
void GeneralEncapsulatedObjectFrame::setMimeType(const String &type) {
|
||||||
{
|
|
||||||
d->mimeType = type;
|
d->mimeType = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
String GeneralEncapsulatedObjectFrame::fileName() const
|
String GeneralEncapsulatedObjectFrame::fileName() const {
|
||||||
{
|
|
||||||
return d->fileName;
|
return d->fileName;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeneralEncapsulatedObjectFrame::setFileName(const String &name)
|
void GeneralEncapsulatedObjectFrame::setFileName(const String &name) {
|
||||||
{
|
|
||||||
d->fileName = name;
|
d->fileName = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
String GeneralEncapsulatedObjectFrame::description() const
|
String GeneralEncapsulatedObjectFrame::description() const {
|
||||||
{
|
|
||||||
return d->description;
|
return d->description;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeneralEncapsulatedObjectFrame::setDescription(const String &desc)
|
void GeneralEncapsulatedObjectFrame::setDescription(const String &desc) {
|
||||||
{
|
|
||||||
d->description = desc;
|
d->description = desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector GeneralEncapsulatedObjectFrame::object() const
|
ByteVector GeneralEncapsulatedObjectFrame::object() const {
|
||||||
{
|
|
||||||
return d->data;
|
return d->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeneralEncapsulatedObjectFrame::setObject(const ByteVector &data)
|
void GeneralEncapsulatedObjectFrame::setObject(const ByteVector &data) {
|
||||||
{
|
|
||||||
d->data = data;
|
d->data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,9 +118,8 @@ void GeneralEncapsulatedObjectFrame::setObject(const ByteVector &data)
|
|||||||
// protected members
|
// protected members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void GeneralEncapsulatedObjectFrame::parseFields(const ByteVector &data)
|
void GeneralEncapsulatedObjectFrame::parseFields(const ByteVector &data) {
|
||||||
{
|
if (data.size() < 4) {
|
||||||
if(data.size() < 4) {
|
|
||||||
debug("An object frame must contain at least 4 bytes.");
|
debug("An object frame must contain at least 4 bytes.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -153,8 +135,7 @@ void GeneralEncapsulatedObjectFrame::parseFields(const ByteVector &data)
|
|||||||
d->data = data.mid(pos);
|
d->data = data.mid(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector GeneralEncapsulatedObjectFrame::renderFields() const
|
ByteVector GeneralEncapsulatedObjectFrame::renderFields() const {
|
||||||
{
|
|
||||||
StringList sl;
|
StringList sl;
|
||||||
sl.append(d->fileName);
|
sl.append(d->fileName);
|
||||||
sl.append(d->description);
|
sl.append(d->description);
|
||||||
@ -179,9 +160,7 @@ ByteVector GeneralEncapsulatedObjectFrame::renderFields() const
|
|||||||
// private members
|
// private members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame(const ByteVector &data, Header *h) :
|
GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame(const ByteVector &data, Header *h) : Frame(h),
|
||||||
Frame(h),
|
d(new GeneralEncapsulatedObjectFramePrivate()) {
|
||||||
d(new GeneralEncapsulatedObjectFramePrivate())
|
|
||||||
{
|
|
||||||
parseFields(fieldData(data));
|
parseFields(fieldData(data));
|
||||||
}
|
}
|
||||||
|
@ -36,11 +36,11 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace 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.
|
* This is an implementation of ID3v2 general encapsulated objects.
|
||||||
* Arbitrary binary data may be included in tags, stored in GEOB frames.
|
* 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
|
* There may be multiple GEOB frames in a single tag. Each GEOB it
|
||||||
@ -49,79 +49,77 @@ namespace TagLib {
|
|||||||
* uniquely identifies the GEOB frame in the tag.
|
* uniquely identifies the GEOB frame in the tag.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class TAGLIB_EXPORT GeneralEncapsulatedObjectFrame : public Frame
|
class TAGLIB_EXPORT GeneralEncapsulatedObjectFrame : public Frame {
|
||||||
{
|
friend class FrameFactory;
|
||||||
friend class FrameFactory;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/*!
|
||||||
/*!
|
|
||||||
* Constructs an empty object frame. The description, file name and text
|
* Constructs an empty object frame. The description, file name and text
|
||||||
* encoding should be set manually.
|
* encoding should be set manually.
|
||||||
*/
|
*/
|
||||||
GeneralEncapsulatedObjectFrame();
|
GeneralEncapsulatedObjectFrame();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs a GeneralEncapsulatedObjectFrame frame based on \a data.
|
* Constructs a GeneralEncapsulatedObjectFrame frame based on \a data.
|
||||||
*
|
*
|
||||||
* \warning This is \em not data for the encapsulated object, for that use
|
* \warning This is \em not data for the encapsulated object, for that use
|
||||||
* setObject(). This constructor is used when reading the frame from the
|
* setObject(). This constructor is used when reading the frame from the
|
||||||
* disk.
|
* disk.
|
||||||
*/
|
*/
|
||||||
explicit GeneralEncapsulatedObjectFrame(const ByteVector &data);
|
explicit GeneralEncapsulatedObjectFrame(const ByteVector &data);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys the GeneralEncapsulatedObjectFrame instance.
|
* Destroys the GeneralEncapsulatedObjectFrame instance.
|
||||||
*/
|
*/
|
||||||
virtual ~GeneralEncapsulatedObjectFrame();
|
virtual ~GeneralEncapsulatedObjectFrame();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns a string containing the description, file name and mime-type
|
* Returns a string containing the description, file name and mime-type
|
||||||
*/
|
*/
|
||||||
virtual String toString() const;
|
virtual String toString() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the text encoding used for the description and file name.
|
* Returns the text encoding used for the description and file name.
|
||||||
*
|
*
|
||||||
* \see setTextEncoding()
|
* \see setTextEncoding()
|
||||||
* \see description()
|
* \see description()
|
||||||
* \see fileName()
|
* \see fileName()
|
||||||
*/
|
*/
|
||||||
String::Type textEncoding() const;
|
String::Type textEncoding() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Set the text encoding used for the description and file name.
|
* Set the text encoding used for the description and file name.
|
||||||
*
|
*
|
||||||
* \see description()
|
* \see description()
|
||||||
* \see fileName()
|
* \see fileName()
|
||||||
*/
|
*/
|
||||||
void setTextEncoding(String::Type encoding);
|
void setTextEncoding(String::Type encoding);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the mime type of the object.
|
* Returns the mime type of the object.
|
||||||
*/
|
*/
|
||||||
String mimeType() const;
|
String mimeType() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the mime type of the object.
|
* Sets the mime type of the object.
|
||||||
*/
|
*/
|
||||||
void setMimeType(const String &type);
|
void setMimeType(const String &type);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the file name of the object.
|
* Returns the file name of the object.
|
||||||
*
|
*
|
||||||
* \see setFileName()
|
* \see setFileName()
|
||||||
*/
|
*/
|
||||||
String fileName() const;
|
String fileName() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the file name for the object.
|
* Sets the file name for the object.
|
||||||
*
|
*
|
||||||
* \see fileName()
|
* \see fileName()
|
||||||
*/
|
*/
|
||||||
void setFileName(const String &name);
|
void setFileName(const String &name);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the content description of the object.
|
* Returns the content description of the object.
|
||||||
*
|
*
|
||||||
* \see setDescription()
|
* \see setDescription()
|
||||||
@ -129,9 +127,9 @@ namespace TagLib {
|
|||||||
* \see setTextEncoding()
|
* \see setTextEncoding()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
String description() const;
|
String description() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the content description of the object to \a desc.
|
* Sets the content description of the object to \a desc.
|
||||||
*
|
*
|
||||||
* \see description()
|
* \see description()
|
||||||
@ -139,9 +137,9 @@ namespace TagLib {
|
|||||||
* \see setTextEncoding()
|
* \see setTextEncoding()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void setDescription(const String &desc);
|
void setDescription(const String &desc);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the object data as a ByteVector.
|
* Returns the object data as a ByteVector.
|
||||||
*
|
*
|
||||||
* \note ByteVector has a data() method that returns a const char * which
|
* \note ByteVector has a data() method that returns a const char * which
|
||||||
@ -150,9 +148,9 @@ namespace TagLib {
|
|||||||
* \see setObject()
|
* \see setObject()
|
||||||
* \see mimeType()
|
* \see mimeType()
|
||||||
*/
|
*/
|
||||||
ByteVector object() const;
|
ByteVector object() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the object data to \a data. \a data should be of the type specified in
|
* Sets the object data to \a data. \a data should be of the type specified in
|
||||||
* this frame's mime-type specification.
|
* this frame's mime-type specification.
|
||||||
*
|
*
|
||||||
@ -160,22 +158,22 @@ namespace TagLib {
|
|||||||
* \see mimeType()
|
* \see mimeType()
|
||||||
* \see setMimeType()
|
* \see setMimeType()
|
||||||
*/
|
*/
|
||||||
void setObject(const ByteVector &object);
|
void setObject(const ByteVector &object);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void parseFields(const ByteVector &data);
|
virtual void parseFields(const ByteVector &data);
|
||||||
virtual ByteVector renderFields() const;
|
virtual ByteVector renderFields() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GeneralEncapsulatedObjectFrame(const ByteVector &data, Header *h);
|
GeneralEncapsulatedObjectFrame(const ByteVector &data, Header *h);
|
||||||
GeneralEncapsulatedObjectFrame(const GeneralEncapsulatedObjectFrame &);
|
GeneralEncapsulatedObjectFrame(const GeneralEncapsulatedObjectFrame &);
|
||||||
GeneralEncapsulatedObjectFrame &operator=(const GeneralEncapsulatedObjectFrame &);
|
GeneralEncapsulatedObjectFrame &operator=(const GeneralEncapsulatedObjectFrame &);
|
||||||
|
|
||||||
class GeneralEncapsulatedObjectFramePrivate;
|
class GeneralEncapsulatedObjectFramePrivate;
|
||||||
GeneralEncapsulatedObjectFramePrivate *d;
|
GeneralEncapsulatedObjectFramePrivate *d;
|
||||||
};
|
};
|
||||||
}
|
} // namespace ID3v2
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -32,9 +32,8 @@
|
|||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
using namespace ID3v2;
|
using namespace ID3v2;
|
||||||
|
|
||||||
class OwnershipFrame::OwnershipFramePrivate
|
class OwnershipFrame::OwnershipFramePrivate {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
String pricePaid;
|
String pricePaid;
|
||||||
String datePurchased;
|
String datePurchased;
|
||||||
String seller;
|
String seller;
|
||||||
@ -45,67 +44,53 @@ public:
|
|||||||
// public members
|
// public members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
OwnershipFrame::OwnershipFrame(String::Type encoding) :
|
OwnershipFrame::OwnershipFrame(String::Type encoding) : Frame("OWNE"),
|
||||||
Frame("OWNE"),
|
d(new OwnershipFramePrivate()) {
|
||||||
d(new OwnershipFramePrivate())
|
|
||||||
{
|
|
||||||
d->textEncoding = encoding;
|
d->textEncoding = encoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
OwnershipFrame::OwnershipFrame(const ByteVector &data) :
|
OwnershipFrame::OwnershipFrame(const ByteVector &data) : Frame(data),
|
||||||
Frame(data),
|
d(new OwnershipFramePrivate()) {
|
||||||
d(new OwnershipFramePrivate())
|
|
||||||
{
|
|
||||||
setData(data);
|
setData(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
OwnershipFrame::~OwnershipFrame()
|
OwnershipFrame::~OwnershipFrame() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
String OwnershipFrame::toString() const
|
String OwnershipFrame::toString() const {
|
||||||
{
|
|
||||||
return "pricePaid=" + d->pricePaid + " datePurchased=" + d->datePurchased + " seller=" + d->seller;
|
return "pricePaid=" + d->pricePaid + " datePurchased=" + d->datePurchased + " seller=" + d->seller;
|
||||||
}
|
}
|
||||||
|
|
||||||
String OwnershipFrame::pricePaid() const
|
String OwnershipFrame::pricePaid() const {
|
||||||
{
|
|
||||||
return d->pricePaid;
|
return d->pricePaid;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OwnershipFrame::setPricePaid(const String &s)
|
void OwnershipFrame::setPricePaid(const String &s) {
|
||||||
{
|
|
||||||
d->pricePaid = s;
|
d->pricePaid = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
String OwnershipFrame::datePurchased() const
|
String OwnershipFrame::datePurchased() const {
|
||||||
{
|
|
||||||
return d->datePurchased;
|
return d->datePurchased;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OwnershipFrame::setDatePurchased(const String &s)
|
void OwnershipFrame::setDatePurchased(const String &s) {
|
||||||
{
|
|
||||||
d->datePurchased = s;
|
d->datePurchased = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
String OwnershipFrame::seller() const
|
String OwnershipFrame::seller() const {
|
||||||
{
|
|
||||||
return d->seller;
|
return d->seller;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OwnershipFrame::setSeller(const String &s)
|
void OwnershipFrame::setSeller(const String &s) {
|
||||||
{
|
|
||||||
d->seller = s;
|
d->seller = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
String::Type OwnershipFrame::textEncoding() const
|
String::Type OwnershipFrame::textEncoding() const {
|
||||||
{
|
|
||||||
return d->textEncoding;
|
return d->textEncoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OwnershipFrame::setTextEncoding(String::Type encoding)
|
void OwnershipFrame::setTextEncoding(String::Type encoding) {
|
||||||
{
|
|
||||||
d->textEncoding = encoding;
|
d->textEncoding = encoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -113,8 +98,7 @@ void OwnershipFrame::setTextEncoding(String::Type encoding)
|
|||||||
// protected members
|
// protected members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void OwnershipFrame::parseFields(const ByteVector &data)
|
void OwnershipFrame::parseFields(const ByteVector &data) {
|
||||||
{
|
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
|
|
||||||
// Get the text encoding
|
// 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
|
// If we don't have at least 8 bytes left then don't parse the rest of the
|
||||||
// data
|
// data
|
||||||
if(data.size() - pos < 8) {
|
if (data.size() - pos < 8) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,14 +119,13 @@ void OwnershipFrame::parseFields(const ByteVector &data)
|
|||||||
pos += 8;
|
pos += 8;
|
||||||
|
|
||||||
// Read the seller
|
// Read the seller
|
||||||
if(d->textEncoding == String::Latin1)
|
if (d->textEncoding == String::Latin1)
|
||||||
d->seller = Tag::latin1StringHandler()->parse(data.mid(pos));
|
d->seller = Tag::latin1StringHandler()->parse(data.mid(pos));
|
||||||
else
|
else
|
||||||
d->seller = String(data.mid(pos), d->textEncoding);
|
d->seller = String(data.mid(pos), d->textEncoding);
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector OwnershipFrame::renderFields() const
|
ByteVector OwnershipFrame::renderFields() const {
|
||||||
{
|
|
||||||
StringList sl;
|
StringList sl;
|
||||||
sl.append(d->seller);
|
sl.append(d->seller);
|
||||||
|
|
||||||
@ -163,9 +146,7 @@ ByteVector OwnershipFrame::renderFields() const
|
|||||||
// private members
|
// private members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
OwnershipFrame::OwnershipFrame(const ByteVector &data, Header *h) :
|
OwnershipFrame::OwnershipFrame(const ByteVector &data, Header *h) : Frame(h),
|
||||||
Frame(h),
|
d(new OwnershipFramePrivate()) {
|
||||||
d(new OwnershipFramePrivate())
|
|
||||||
{
|
|
||||||
parseFields(fieldData(data));
|
parseFields(fieldData(data));
|
||||||
}
|
}
|
||||||
|
@ -32,85 +32,84 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace 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
|
* This implements the ID3v2 ownership (OWNE frame). It consists of
|
||||||
* a price paid, a date purchased (YYYYMMDD) and the name of the seller.
|
* 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;
|
||||||
friend class FrameFactory;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/*!
|
/*!
|
||||||
* Construct an empty ownership frame.
|
* Construct an empty ownership frame.
|
||||||
*/
|
*/
|
||||||
explicit OwnershipFrame(String::Type encoding = String::Latin1);
|
explicit OwnershipFrame(String::Type encoding = String::Latin1);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Construct a ownership based on the data in \a data.
|
* Construct a ownership based on the data in \a data.
|
||||||
*/
|
*/
|
||||||
explicit OwnershipFrame(const ByteVector &data);
|
explicit OwnershipFrame(const ByteVector &data);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys this OwnershipFrame instance.
|
* Destroys this OwnershipFrame instance.
|
||||||
*/
|
*/
|
||||||
virtual ~OwnershipFrame();
|
virtual ~OwnershipFrame();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the text of this popularimeter.
|
* Returns the text of this popularimeter.
|
||||||
*
|
*
|
||||||
* \see text()
|
* \see text()
|
||||||
*/
|
*/
|
||||||
virtual String toString() const;
|
virtual String toString() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the date purchased.
|
* Returns the date purchased.
|
||||||
*
|
*
|
||||||
* \see setDatePurchased()
|
* \see setDatePurchased()
|
||||||
*/
|
*/
|
||||||
String datePurchased() const;
|
String datePurchased() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Set the date purchased.
|
* Set the date purchased.
|
||||||
*
|
*
|
||||||
* \see datePurchased()
|
* \see datePurchased()
|
||||||
*/
|
*/
|
||||||
void setDatePurchased(const String &datePurchased);
|
void setDatePurchased(const String &datePurchased);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the price paid.
|
* Returns the price paid.
|
||||||
*
|
*
|
||||||
* \see setPricePaid()
|
* \see setPricePaid()
|
||||||
*/
|
*/
|
||||||
String pricePaid() const;
|
String pricePaid() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Set the price paid.
|
* Set the price paid.
|
||||||
*
|
*
|
||||||
* \see pricePaid()
|
* \see pricePaid()
|
||||||
*/
|
*/
|
||||||
void setPricePaid(const String &pricePaid);
|
void setPricePaid(const String &pricePaid);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the seller.
|
* Returns the seller.
|
||||||
*
|
*
|
||||||
* \see setSeller()
|
* \see setSeller()
|
||||||
*/
|
*/
|
||||||
String seller() const;
|
String seller() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Set the seller.
|
* Set the seller.
|
||||||
*
|
*
|
||||||
* \see seller()
|
* \see seller()
|
||||||
*/
|
*/
|
||||||
void setSeller(const String &seller);
|
void setSeller(const String &seller);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the text encoding that will be used in rendering this frame.
|
* Returns the text encoding that will be used in rendering this frame.
|
||||||
* This defaults to the type that was either specified in the constructor
|
* This defaults to the type that was either specified in the constructor
|
||||||
* or read from the frame when parsed.
|
* or read from the frame when parsed.
|
||||||
@ -118,36 +117,36 @@ namespace TagLib {
|
|||||||
* \see setTextEncoding()
|
* \see setTextEncoding()
|
||||||
* \see render()
|
* \see render()
|
||||||
*/
|
*/
|
||||||
String::Type textEncoding() const;
|
String::Type textEncoding() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the text encoding to be used when rendering this frame to
|
* Sets the text encoding to be used when rendering this frame to
|
||||||
* \a encoding.
|
* \a encoding.
|
||||||
*
|
*
|
||||||
* \see textEncoding()
|
* \see textEncoding()
|
||||||
* \see render()
|
* \see render()
|
||||||
*/
|
*/
|
||||||
void setTextEncoding(String::Type encoding);
|
void setTextEncoding(String::Type encoding);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Reimplementations.
|
// Reimplementations.
|
||||||
|
|
||||||
virtual void parseFields(const ByteVector &data);
|
virtual void parseFields(const ByteVector &data);
|
||||||
virtual ByteVector renderFields() const;
|
virtual ByteVector renderFields() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*!
|
/*!
|
||||||
* The constructor used by the FrameFactory.
|
* The constructor used by the FrameFactory.
|
||||||
*/
|
*/
|
||||||
OwnershipFrame(const ByteVector &data, Header *h);
|
OwnershipFrame(const ByteVector &data, Header *h);
|
||||||
OwnershipFrame(const OwnershipFrame &);
|
OwnershipFrame(const OwnershipFrame &);
|
||||||
OwnershipFrame &operator=(const OwnershipFrame &);
|
OwnershipFrame &operator=(const OwnershipFrame &);
|
||||||
|
|
||||||
class OwnershipFramePrivate;
|
class OwnershipFramePrivate;
|
||||||
OwnershipFramePrivate *d;
|
OwnershipFramePrivate *d;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace ID3v2
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
#endif
|
#endif
|
||||||
|
@ -28,9 +28,8 @@
|
|||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
using namespace ID3v2;
|
using namespace ID3v2;
|
||||||
|
|
||||||
class PodcastFrame::PodcastFramePrivate
|
class PodcastFrame::PodcastFramePrivate {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
ByteVector fieldData;
|
ByteVector fieldData;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -38,20 +37,16 @@ public:
|
|||||||
// public members
|
// public members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
PodcastFrame::PodcastFrame() :
|
PodcastFrame::PodcastFrame() : Frame("PCST"),
|
||||||
Frame("PCST"),
|
d(new PodcastFramePrivate()) {
|
||||||
d(new PodcastFramePrivate())
|
|
||||||
{
|
|
||||||
d->fieldData = ByteVector(4, '\0');
|
d->fieldData = ByteVector(4, '\0');
|
||||||
}
|
}
|
||||||
|
|
||||||
PodcastFrame::~PodcastFrame()
|
PodcastFrame::~PodcastFrame() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
String PodcastFrame::toString() const
|
String PodcastFrame::toString() const {
|
||||||
{
|
|
||||||
return String();
|
return String();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,13 +54,11 @@ String PodcastFrame::toString() const
|
|||||||
// protected members
|
// protected members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void PodcastFrame::parseFields(const ByteVector &data)
|
void PodcastFrame::parseFields(const ByteVector &data) {
|
||||||
{
|
|
||||||
d->fieldData = data;
|
d->fieldData = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector PodcastFrame::renderFields() const
|
ByteVector PodcastFrame::renderFields() const {
|
||||||
{
|
|
||||||
return d->fieldData;
|
return d->fieldData;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,9 +66,7 @@ ByteVector PodcastFrame::renderFields() const
|
|||||||
// private members
|
// private members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
PodcastFrame::PodcastFrame(const ByteVector &data, Header *h) :
|
PodcastFrame::PodcastFrame(const ByteVector &data, Header *h) : Frame(h),
|
||||||
Frame(h),
|
d(new PodcastFramePrivate()) {
|
||||||
d(new PodcastFramePrivate())
|
|
||||||
{
|
|
||||||
parseFields(fieldData(data));
|
parseFields(fieldData(data));
|
||||||
}
|
}
|
||||||
|
55
3rdparty/taglib/mpeg/id3v2/frames/podcastframe.h
vendored
55
3rdparty/taglib/mpeg/id3v2/frames/podcastframe.h
vendored
@ -32,51 +32,50 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace 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.
|
* 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;
|
||||||
friend class FrameFactory;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/*!
|
/*!
|
||||||
* Construct a podcast frame.
|
* Construct a podcast frame.
|
||||||
*/
|
*/
|
||||||
PodcastFrame();
|
PodcastFrame();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys this PodcastFrame instance.
|
* Destroys this PodcastFrame instance.
|
||||||
*/
|
*/
|
||||||
virtual ~PodcastFrame();
|
virtual ~PodcastFrame();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns a null string.
|
* Returns a null string.
|
||||||
*/
|
*/
|
||||||
virtual String toString() const;
|
virtual String toString() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Reimplementations.
|
// Reimplementations.
|
||||||
|
|
||||||
virtual void parseFields(const ByteVector &data);
|
virtual void parseFields(const ByteVector &data);
|
||||||
virtual ByteVector renderFields() const;
|
virtual ByteVector renderFields() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*!
|
/*!
|
||||||
* The constructor used by the FrameFactory.
|
* The constructor used by the FrameFactory.
|
||||||
*/
|
*/
|
||||||
PodcastFrame(const ByteVector &data, Header *h);
|
PodcastFrame(const ByteVector &data, Header *h);
|
||||||
PodcastFrame(const PodcastFrame &);
|
PodcastFrame(const PodcastFrame &);
|
||||||
PodcastFrame &operator=(const PodcastFrame &);
|
PodcastFrame &operator=(const PodcastFrame &);
|
||||||
|
|
||||||
class PodcastFramePrivate;
|
class PodcastFramePrivate;
|
||||||
PodcastFramePrivate *d;
|
PodcastFramePrivate *d;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace ID3v2
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
#endif
|
#endif
|
||||||
|
@ -30,9 +30,8 @@
|
|||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
using namespace ID3v2;
|
using namespace ID3v2;
|
||||||
|
|
||||||
class PopularimeterFrame::PopularimeterFramePrivate
|
class PopularimeterFrame::PopularimeterFramePrivate {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
PopularimeterFramePrivate() : rating(0), counter(0) {}
|
PopularimeterFramePrivate() : rating(0), counter(0) {}
|
||||||
String email;
|
String email;
|
||||||
int rating;
|
int rating;
|
||||||
@ -43,56 +42,44 @@ public:
|
|||||||
// public members
|
// public members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
PopularimeterFrame::PopularimeterFrame() :
|
PopularimeterFrame::PopularimeterFrame() : Frame("POPM"),
|
||||||
Frame("POPM"),
|
d(new PopularimeterFramePrivate()) {
|
||||||
d(new PopularimeterFramePrivate())
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PopularimeterFrame::PopularimeterFrame(const ByteVector &data) :
|
PopularimeterFrame::PopularimeterFrame(const ByteVector &data) : Frame(data),
|
||||||
Frame(data),
|
d(new PopularimeterFramePrivate()) {
|
||||||
d(new PopularimeterFramePrivate())
|
|
||||||
{
|
|
||||||
setData(data);
|
setData(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
PopularimeterFrame::~PopularimeterFrame()
|
PopularimeterFrame::~PopularimeterFrame() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
String PopularimeterFrame::toString() const
|
String PopularimeterFrame::toString() const {
|
||||||
{
|
|
||||||
return d->email + " rating=" + String::number(d->rating) + " counter=" + String::number(d->counter);
|
return d->email + " rating=" + String::number(d->rating) + " counter=" + String::number(d->counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
String PopularimeterFrame::email() const
|
String PopularimeterFrame::email() const {
|
||||||
{
|
|
||||||
return d->email;
|
return d->email;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PopularimeterFrame::setEmail(const String &s)
|
void PopularimeterFrame::setEmail(const String &s) {
|
||||||
{
|
|
||||||
d->email = s;
|
d->email = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
int PopularimeterFrame::rating() const
|
int PopularimeterFrame::rating() const {
|
||||||
{
|
|
||||||
return d->rating;
|
return d->rating;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PopularimeterFrame::setRating(int s)
|
void PopularimeterFrame::setRating(int s) {
|
||||||
{
|
|
||||||
d->rating = s;
|
d->rating = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int PopularimeterFrame::counter() const
|
unsigned int PopularimeterFrame::counter() const {
|
||||||
{
|
|
||||||
return d->counter;
|
return d->counter;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PopularimeterFrame::setCounter(unsigned int s)
|
void PopularimeterFrame::setCounter(unsigned int s) {
|
||||||
{
|
|
||||||
d->counter = s;
|
d->counter = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,24 +87,22 @@ void PopularimeterFrame::setCounter(unsigned int s)
|
|||||||
// protected members
|
// protected members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void PopularimeterFrame::parseFields(const ByteVector &data)
|
void PopularimeterFrame::parseFields(const ByteVector &data) {
|
||||||
{
|
|
||||||
int pos = 0, size = int(data.size());
|
int pos = 0, size = int(data.size());
|
||||||
|
|
||||||
d->email = readStringField(data, String::Latin1, &pos);
|
d->email = readStringField(data, String::Latin1, &pos);
|
||||||
|
|
||||||
d->rating = 0;
|
d->rating = 0;
|
||||||
d->counter = 0;
|
d->counter = 0;
|
||||||
if(pos < size) {
|
if (pos < size) {
|
||||||
d->rating = (unsigned char)(data[pos++]);
|
d->rating = (unsigned char)(data[pos++]);
|
||||||
if(pos < size) {
|
if (pos < size) {
|
||||||
d->counter = data.toUInt(static_cast<unsigned int>(pos));
|
d->counter = data.toUInt(static_cast<unsigned int>(pos));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector PopularimeterFrame::renderFields() const
|
ByteVector PopularimeterFrame::renderFields() const {
|
||||||
{
|
|
||||||
ByteVector data;
|
ByteVector data;
|
||||||
|
|
||||||
data.append(d->email.data(String::Latin1));
|
data.append(d->email.data(String::Latin1));
|
||||||
@ -132,9 +117,7 @@ ByteVector PopularimeterFrame::renderFields() const
|
|||||||
// private members
|
// private members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
PopularimeterFrame::PopularimeterFrame(const ByteVector &data, Header *h) :
|
PopularimeterFrame::PopularimeterFrame(const ByteVector &data, Header *h) : Frame(h),
|
||||||
Frame(h),
|
d(new PopularimeterFramePrivate()) {
|
||||||
d(new PopularimeterFramePrivate())
|
|
||||||
{
|
|
||||||
parseFields(fieldData(data));
|
parseFields(fieldData(data));
|
||||||
}
|
}
|
||||||
|
@ -32,103 +32,102 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace 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
|
* This implements the ID3v2 popularimeter (POPM frame). It consists of
|
||||||
* an email, a rating and an optional counter.
|
* an email, a rating and an optional counter.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class TAGLIB_EXPORT PopularimeterFrame : public Frame
|
class TAGLIB_EXPORT PopularimeterFrame : public Frame {
|
||||||
{
|
friend class FrameFactory;
|
||||||
friend class FrameFactory;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/*!
|
/*!
|
||||||
* Construct an empty popularimeter frame.
|
* Construct an empty popularimeter frame.
|
||||||
*/
|
*/
|
||||||
explicit PopularimeterFrame();
|
explicit PopularimeterFrame();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Construct a popularimeter based on the data in \a data.
|
* Construct a popularimeter based on the data in \a data.
|
||||||
*/
|
*/
|
||||||
explicit PopularimeterFrame(const ByteVector &data);
|
explicit PopularimeterFrame(const ByteVector &data);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys this PopularimeterFrame instance.
|
* Destroys this PopularimeterFrame instance.
|
||||||
*/
|
*/
|
||||||
virtual ~PopularimeterFrame();
|
virtual ~PopularimeterFrame();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the text of this popularimeter.
|
* Returns the text of this popularimeter.
|
||||||
*
|
*
|
||||||
* \see text()
|
* \see text()
|
||||||
*/
|
*/
|
||||||
virtual String toString() const;
|
virtual String toString() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the email.
|
* Returns the email.
|
||||||
*
|
*
|
||||||
* \see setEmail()
|
* \see setEmail()
|
||||||
*/
|
*/
|
||||||
String email() const;
|
String email() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Set the email.
|
* Set the email.
|
||||||
*
|
*
|
||||||
* \see email()
|
* \see email()
|
||||||
*/
|
*/
|
||||||
void setEmail(const String &email);
|
void setEmail(const String &email);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the rating.
|
* Returns the rating.
|
||||||
*
|
*
|
||||||
* \see setRating()
|
* \see setRating()
|
||||||
*/
|
*/
|
||||||
int rating() const;
|
int rating() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Set the rating.
|
* Set the rating.
|
||||||
*
|
*
|
||||||
* \see rating()
|
* \see rating()
|
||||||
*/
|
*/
|
||||||
void setRating(int rating);
|
void setRating(int rating);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the counter.
|
* Returns the counter.
|
||||||
*
|
*
|
||||||
* \see setCounter()
|
* \see setCounter()
|
||||||
*/
|
*/
|
||||||
unsigned int counter() const;
|
unsigned int counter() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Set the counter.
|
* Set the counter.
|
||||||
*
|
*
|
||||||
* \see counter()
|
* \see counter()
|
||||||
*/
|
*/
|
||||||
void setCounter(unsigned int counter);
|
void setCounter(unsigned int counter);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Reimplementations.
|
// Reimplementations.
|
||||||
|
|
||||||
virtual void parseFields(const ByteVector &data);
|
virtual void parseFields(const ByteVector &data);
|
||||||
virtual ByteVector renderFields() const;
|
virtual ByteVector renderFields() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*!
|
/*!
|
||||||
* The constructor used by the FrameFactory.
|
* The constructor used by the FrameFactory.
|
||||||
*/
|
*/
|
||||||
PopularimeterFrame(const ByteVector &data, Header *h);
|
PopularimeterFrame(const ByteVector &data, Header *h);
|
||||||
PopularimeterFrame(const PopularimeterFrame &);
|
PopularimeterFrame(const PopularimeterFrame &);
|
||||||
PopularimeterFrame &operator=(const PopularimeterFrame &);
|
PopularimeterFrame &operator=(const PopularimeterFrame &);
|
||||||
|
|
||||||
class PopularimeterFramePrivate;
|
class PopularimeterFramePrivate;
|
||||||
PopularimeterFramePrivate *d;
|
PopularimeterFramePrivate *d;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace ID3v2
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
#endif
|
#endif
|
||||||
|
@ -34,9 +34,8 @@ using namespace Strawberry_TagLib::TagLib;
|
|||||||
using namespace ID3v2;
|
using namespace ID3v2;
|
||||||
|
|
||||||
|
|
||||||
class PrivateFrame::PrivateFramePrivate
|
class PrivateFrame::PrivateFramePrivate {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
ByteVector data;
|
ByteVector data;
|
||||||
String owner;
|
String owner;
|
||||||
};
|
};
|
||||||
@ -45,46 +44,36 @@ public:
|
|||||||
// public members
|
// public members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
PrivateFrame::PrivateFrame() :
|
PrivateFrame::PrivateFrame() : Frame("PRIV"),
|
||||||
Frame("PRIV"),
|
d(new PrivateFramePrivate()) {
|
||||||
d(new PrivateFramePrivate())
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PrivateFrame::PrivateFrame(const ByteVector &data) :
|
PrivateFrame::PrivateFrame(const ByteVector &data) : Frame(data),
|
||||||
Frame(data),
|
d(new PrivateFramePrivate()) {
|
||||||
d(new PrivateFramePrivate())
|
|
||||||
{
|
|
||||||
setData(data);
|
setData(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
PrivateFrame::~PrivateFrame()
|
PrivateFrame::~PrivateFrame() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
String PrivateFrame::toString() const
|
String PrivateFrame::toString() const {
|
||||||
{
|
|
||||||
return d->owner;
|
return d->owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
String PrivateFrame::owner() const
|
String PrivateFrame::owner() const {
|
||||||
{
|
|
||||||
return d->owner;
|
return d->owner;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector PrivateFrame::data() const
|
ByteVector PrivateFrame::data() const {
|
||||||
{
|
|
||||||
return d->data;
|
return d->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrivateFrame::setOwner(const String &s)
|
void PrivateFrame::setOwner(const String &s) {
|
||||||
{
|
|
||||||
d->owner = s;
|
d->owner = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PrivateFrame::setData(const ByteVector & data)
|
void PrivateFrame::setData(const ByteVector &data) {
|
||||||
{
|
|
||||||
d->data = data;
|
d->data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,24 +81,22 @@ void PrivateFrame::setData(const ByteVector & data)
|
|||||||
// protected members
|
// protected members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void PrivateFrame::parseFields(const ByteVector &data)
|
void PrivateFrame::parseFields(const ByteVector &data) {
|
||||||
{
|
if (data.size() < 2) {
|
||||||
if(data.size() < 2) {
|
|
||||||
debug("A private frame must contain at least 2 bytes.");
|
debug("A private frame must contain at least 2 bytes.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Owner identifier is assumed to be Latin1
|
// Owner identifier is assumed to be Latin1
|
||||||
|
|
||||||
const int byteAlign = 1;
|
const int byteAlign = 1;
|
||||||
const int endOfOwner = data.find(textDelimiter(String::Latin1), 0, byteAlign);
|
const int endOfOwner = data.find(textDelimiter(String::Latin1), 0, byteAlign);
|
||||||
|
|
||||||
d->owner = String(data.mid(0, endOfOwner));
|
d->owner = String(data.mid(0, endOfOwner));
|
||||||
d->data = data.mid(endOfOwner + 1);
|
d->data = data.mid(endOfOwner + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector PrivateFrame::renderFields() const
|
ByteVector PrivateFrame::renderFields() const {
|
||||||
{
|
|
||||||
ByteVector v;
|
ByteVector v;
|
||||||
|
|
||||||
v.append(d->owner.data(String::Latin1));
|
v.append(d->owner.data(String::Latin1));
|
||||||
@ -123,9 +110,7 @@ ByteVector PrivateFrame::renderFields() const
|
|||||||
// private members
|
// private members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
PrivateFrame::PrivateFrame(const ByteVector &data, Header *h) :
|
PrivateFrame::PrivateFrame(const ByteVector &data, Header *h) : Frame(h),
|
||||||
Frame(h),
|
d(new PrivateFramePrivate()) {
|
||||||
d(new PrivateFramePrivate())
|
|
||||||
{
|
|
||||||
parseFields(fieldData(data));
|
parseFields(fieldData(data));
|
||||||
}
|
}
|
||||||
|
73
3rdparty/taglib/mpeg/id3v2/frames/privateframe.h
vendored
73
3rdparty/taglib/mpeg/id3v2/frames/privateframe.h
vendored
@ -33,81 +33,80 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace 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;
|
||||||
friend class FrameFactory;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/*!
|
/*!
|
||||||
* Construct an empty private frame.
|
* Construct an empty private frame.
|
||||||
*/
|
*/
|
||||||
PrivateFrame();
|
PrivateFrame();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Construct a private frame based on the data in \a data.
|
* Construct a private frame based on the data in \a data.
|
||||||
*
|
*
|
||||||
* \note This is the constructor used when parsing the frame from a file.
|
* \note This is the constructor used when parsing the frame from a file.
|
||||||
*/
|
*/
|
||||||
explicit PrivateFrame(const ByteVector &data);
|
explicit PrivateFrame(const ByteVector &data);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys this private frame instance.
|
* Destroys this private frame instance.
|
||||||
*/
|
*/
|
||||||
virtual ~PrivateFrame();
|
virtual ~PrivateFrame();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the text of this private frame, currently just the owner.
|
* Returns the text of this private frame, currently just the owner.
|
||||||
*
|
*
|
||||||
* \see text()
|
* \see text()
|
||||||
*/
|
*/
|
||||||
virtual String toString() const;
|
virtual String toString() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \return The owner of the private frame.
|
* \return The owner of the private frame.
|
||||||
* \note This should contain an email address or link to a website.
|
* \note This should contain an email address or link to a website.
|
||||||
*/
|
*/
|
||||||
String owner() const;
|
String owner() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
ByteVector data() const;
|
ByteVector data() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the owner of the frame to \a s.
|
* Sets the owner of the frame to \a s.
|
||||||
* \note This should contain an email address or link to a website.
|
* \note This should contain an email address or link to a website.
|
||||||
*/
|
*/
|
||||||
void setOwner(const String &s);
|
void setOwner(const String &s);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
void setData(const ByteVector &v);
|
void setData(const ByteVector &v);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Reimplementations.
|
// Reimplementations.
|
||||||
|
|
||||||
virtual void parseFields(const ByteVector &data);
|
virtual void parseFields(const ByteVector &data);
|
||||||
virtual ByteVector renderFields() const;
|
virtual ByteVector renderFields() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*!
|
/*!
|
||||||
* The constructor used by the FrameFactory.
|
* The constructor used by the FrameFactory.
|
||||||
*/
|
*/
|
||||||
PrivateFrame(const ByteVector &data, Header *h);
|
PrivateFrame(const ByteVector &data, Header *h);
|
||||||
|
|
||||||
PrivateFrame(const PrivateFrame &);
|
PrivateFrame(const PrivateFrame &);
|
||||||
PrivateFrame &operator=(const PrivateFrame &);
|
PrivateFrame &operator=(const PrivateFrame &);
|
||||||
|
|
||||||
class PrivateFramePrivate;
|
class PrivateFramePrivate;
|
||||||
PrivateFramePrivate *d;
|
PrivateFramePrivate *d;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace ID3v2
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
#endif
|
#endif
|
||||||
|
@ -31,8 +31,7 @@
|
|||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
using namespace ID3v2;
|
using namespace ID3v2;
|
||||||
|
|
||||||
struct ChannelData
|
struct ChannelData {
|
||||||
{
|
|
||||||
ChannelData() : channelType(RelativeVolumeFrame::Other), volumeAdjustment(0) {}
|
ChannelData() : channelType(RelativeVolumeFrame::Other), volumeAdjustment(0) {}
|
||||||
|
|
||||||
RelativeVolumeFrame::ChannelType channelType;
|
RelativeVolumeFrame::ChannelType channelType;
|
||||||
@ -40,9 +39,8 @@ struct ChannelData
|
|||||||
RelativeVolumeFrame::PeakVolume peakVolume;
|
RelativeVolumeFrame::PeakVolume peakVolume;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RelativeVolumeFrame::RelativeVolumeFramePrivate
|
class RelativeVolumeFrame::RelativeVolumeFramePrivate {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
String identification;
|
String identification;
|
||||||
Map<ChannelType, ChannelData> channels;
|
Map<ChannelType, ChannelData> channels;
|
||||||
};
|
};
|
||||||
@ -51,35 +49,28 @@ public:
|
|||||||
// public members
|
// public members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
RelativeVolumeFrame::RelativeVolumeFrame() :
|
RelativeVolumeFrame::RelativeVolumeFrame() : Frame("RVA2"),
|
||||||
Frame("RVA2"),
|
d(new RelativeVolumeFramePrivate()) {
|
||||||
d(new RelativeVolumeFramePrivate())
|
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RelativeVolumeFrame::RelativeVolumeFrame(const ByteVector &data) :
|
RelativeVolumeFrame::RelativeVolumeFrame(const ByteVector &data) : Frame(data),
|
||||||
Frame(data),
|
d(new RelativeVolumeFramePrivate()) {
|
||||||
d(new RelativeVolumeFramePrivate())
|
|
||||||
{
|
|
||||||
setData(data);
|
setData(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
RelativeVolumeFrame::~RelativeVolumeFrame()
|
RelativeVolumeFrame::~RelativeVolumeFrame() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
String RelativeVolumeFrame::toString() const
|
String RelativeVolumeFrame::toString() const {
|
||||||
{
|
|
||||||
return d->identification;
|
return d->identification;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<RelativeVolumeFrame::ChannelType> RelativeVolumeFrame::channels() const
|
List<RelativeVolumeFrame::ChannelType> RelativeVolumeFrame::channels() const {
|
||||||
{
|
|
||||||
List<ChannelType> l;
|
List<ChannelType> l;
|
||||||
|
|
||||||
Map<ChannelType, ChannelData>::ConstIterator it = d->channels.begin();
|
Map<ChannelType, ChannelData>::ConstIterator it = d->channels.begin();
|
||||||
for(; it != d->channels.end(); ++it)
|
for (; it != d->channels.end(); ++it)
|
||||||
l.append((*it).first);
|
l.append((*it).first);
|
||||||
|
|
||||||
return l;
|
return l;
|
||||||
@ -87,85 +78,68 @@ List<RelativeVolumeFrame::ChannelType> RelativeVolumeFrame::channels() const
|
|||||||
|
|
||||||
// deprecated
|
// deprecated
|
||||||
|
|
||||||
RelativeVolumeFrame::ChannelType RelativeVolumeFrame::channelType() const
|
RelativeVolumeFrame::ChannelType RelativeVolumeFrame::channelType() const {
|
||||||
{
|
|
||||||
return MasterVolume;
|
return MasterVolume;
|
||||||
}
|
}
|
||||||
|
|
||||||
// deprecated
|
// 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;
|
return d->channels.contains(type) ? d->channels[type].volumeAdjustment : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
short RelativeVolumeFrame::volumeAdjustmentIndex() const
|
short RelativeVolumeFrame::volumeAdjustmentIndex() const {
|
||||||
{
|
|
||||||
return volumeAdjustmentIndex(MasterVolume);
|
return volumeAdjustmentIndex(MasterVolume);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RelativeVolumeFrame::setVolumeAdjustmentIndex(short index, ChannelType type)
|
void RelativeVolumeFrame::setVolumeAdjustmentIndex(short index, ChannelType type) {
|
||||||
{
|
|
||||||
d->channels[type].volumeAdjustment = index;
|
d->channels[type].volumeAdjustment = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RelativeVolumeFrame::setVolumeAdjustmentIndex(short index)
|
void RelativeVolumeFrame::setVolumeAdjustmentIndex(short index) {
|
||||||
{
|
|
||||||
setVolumeAdjustmentIndex(index, MasterVolume);
|
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;
|
return d->channels.contains(type) ? float(d->channels[type].volumeAdjustment) / float(512) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
float RelativeVolumeFrame::volumeAdjustment() const
|
float RelativeVolumeFrame::volumeAdjustment() const {
|
||||||
{
|
|
||||||
return volumeAdjustment(MasterVolume);
|
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));
|
d->channels[type].volumeAdjustment = short(adjustment * float(512));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RelativeVolumeFrame::setVolumeAdjustment(float adjustment)
|
void RelativeVolumeFrame::setVolumeAdjustment(float adjustment) {
|
||||||
{
|
|
||||||
setVolumeAdjustment(adjustment, MasterVolume);
|
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();
|
return d->channels.contains(type) ? d->channels[type].peakVolume : PeakVolume();
|
||||||
}
|
}
|
||||||
|
|
||||||
RelativeVolumeFrame::PeakVolume RelativeVolumeFrame::peakVolume() const
|
RelativeVolumeFrame::PeakVolume RelativeVolumeFrame::peakVolume() const {
|
||||||
{
|
|
||||||
return peakVolume(MasterVolume);
|
return peakVolume(MasterVolume);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RelativeVolumeFrame::setPeakVolume(const PeakVolume &peak, ChannelType type)
|
void RelativeVolumeFrame::setPeakVolume(const PeakVolume &peak, ChannelType type) {
|
||||||
{
|
|
||||||
d->channels[type].peakVolume = peak;
|
d->channels[type].peakVolume = peak;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RelativeVolumeFrame::setPeakVolume(const PeakVolume &peak)
|
void RelativeVolumeFrame::setPeakVolume(const PeakVolume &peak) {
|
||||||
{
|
|
||||||
setPeakVolume(peak, MasterVolume);
|
setPeakVolume(peak, MasterVolume);
|
||||||
}
|
}
|
||||||
|
|
||||||
String RelativeVolumeFrame::identification() const
|
String RelativeVolumeFrame::identification() const {
|
||||||
{
|
|
||||||
return d->identification;
|
return d->identification;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RelativeVolumeFrame::setIdentification(const String &s)
|
void RelativeVolumeFrame::setIdentification(const String &s) {
|
||||||
{
|
|
||||||
d->identification = s;
|
d->identification = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,14 +147,13 @@ void RelativeVolumeFrame::setIdentification(const String &s)
|
|||||||
// protected members
|
// protected members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void RelativeVolumeFrame::parseFields(const ByteVector &data)
|
void RelativeVolumeFrame::parseFields(const ByteVector &data) {
|
||||||
{
|
|
||||||
int pos = 0;
|
int pos = 0;
|
||||||
d->identification = readStringField(data, String::Latin1, &pos);
|
d->identification = readStringField(data, String::Latin1, &pos);
|
||||||
|
|
||||||
// Each channel is at least 4 bytes.
|
// Each channel is at least 4 bytes.
|
||||||
|
|
||||||
while(pos <= (int)data.size() - 4) {
|
while (pos <= (int)data.size() - 4) {
|
||||||
|
|
||||||
ChannelType type = ChannelType(data[pos]);
|
ChannelType type = ChannelType(data[pos]);
|
||||||
pos += 1;
|
pos += 1;
|
||||||
@ -199,8 +172,7 @@ void RelativeVolumeFrame::parseFields(const ByteVector &data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector RelativeVolumeFrame::renderFields() const
|
ByteVector RelativeVolumeFrame::renderFields() const {
|
||||||
{
|
|
||||||
ByteVector data;
|
ByteVector data;
|
||||||
|
|
||||||
data.append(d->identification.data(String::Latin1));
|
data.append(d->identification.data(String::Latin1));
|
||||||
@ -208,7 +180,7 @@ ByteVector RelativeVolumeFrame::renderFields() const
|
|||||||
|
|
||||||
Map<ChannelType, ChannelData>::ConstIterator it = d->channels.begin();
|
Map<ChannelType, ChannelData>::ConstIterator it = d->channels.begin();
|
||||||
|
|
||||||
for(; it != d->channels.end(); ++it) {
|
for (; it != d->channels.end(); ++it) {
|
||||||
ChannelType type = (*it).first;
|
ChannelType type = (*it).first;
|
||||||
const ChannelData &channel = (*it).second;
|
const ChannelData &channel = (*it).second;
|
||||||
|
|
||||||
@ -225,9 +197,7 @@ ByteVector RelativeVolumeFrame::renderFields() const
|
|||||||
// private members
|
// private members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
RelativeVolumeFrame::RelativeVolumeFrame(const ByteVector &data, Header *h) :
|
RelativeVolumeFrame::RelativeVolumeFrame(const ByteVector &data, Header *h) : Frame(h),
|
||||||
Frame(h),
|
d(new RelativeVolumeFramePrivate()) {
|
||||||
d(new RelativeVolumeFramePrivate())
|
|
||||||
{
|
|
||||||
parseFields(fieldData(data));
|
parseFields(fieldData(data));
|
||||||
}
|
}
|
||||||
|
@ -33,11 +33,11 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace 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
|
* This is an implementation of ID3v2 relative volume adjustment. The
|
||||||
* presence of this frame makes it possible to specify an increase in volume
|
* presence of this frame makes it possible to specify an increase in volume
|
||||||
* for an audio file or specific audio tracks in that file.
|
* for an audio file or specific audio tracks in that file.
|
||||||
@ -47,99 +47,96 @@ namespace TagLib {
|
|||||||
* different channel types.
|
* different channel types.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class TAGLIB_EXPORT RelativeVolumeFrame : public Frame
|
class TAGLIB_EXPORT RelativeVolumeFrame : public Frame {
|
||||||
{
|
friend class FrameFactory;
|
||||||
friend class FrameFactory;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/*!
|
||||||
/*!
|
|
||||||
* This indicates the type of volume adjustment that should be applied.
|
* This indicates the type of volume adjustment that should be applied.
|
||||||
*/
|
*/
|
||||||
enum ChannelType {
|
enum ChannelType {
|
||||||
//! A type not enumerated below
|
//! A type not enumerated below
|
||||||
Other = 0x00,
|
Other = 0x00,
|
||||||
//! The master volume for the track
|
//! The master volume for the track
|
||||||
MasterVolume = 0x01,
|
MasterVolume = 0x01,
|
||||||
//! The front right audio channel
|
//! The front right audio channel
|
||||||
FrontRight = 0x02,
|
FrontRight = 0x02,
|
||||||
//! The front left audio channel
|
//! The front left audio channel
|
||||||
FrontLeft = 0x03,
|
FrontLeft = 0x03,
|
||||||
//! The back right audio channel
|
//! The back right audio channel
|
||||||
BackRight = 0x04,
|
BackRight = 0x04,
|
||||||
//! The back left audio channel
|
//! The back left audio channel
|
||||||
BackLeft = 0x05,
|
BackLeft = 0x05,
|
||||||
//! The front center audio channel
|
//! The front center audio channel
|
||||||
FrontCentre = 0x06,
|
FrontCentre = 0x06,
|
||||||
//! The back center audio channel
|
//! The back center audio channel
|
||||||
BackCentre = 0x07,
|
BackCentre = 0x07,
|
||||||
//! The subwoofer audio channel
|
//! The subwoofer audio channel
|
||||||
Subwoofer = 0x08
|
Subwoofer = 0x08
|
||||||
};
|
};
|
||||||
|
|
||||||
//! Struct that stores the relevant values for ID3v2 peak volume
|
//! Struct that stores the relevant values for ID3v2 peak volume
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* The peak volume is described as a series of bits that is padded to fill
|
* 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.
|
* a block of bytes. These two values should always be updated in tandem.
|
||||||
*/
|
*/
|
||||||
struct PeakVolume
|
struct PeakVolume {
|
||||||
{
|
/*!
|
||||||
/*!
|
|
||||||
* Constructs an empty peak volume description.
|
* Constructs an empty peak volume description.
|
||||||
*/
|
*/
|
||||||
PeakVolume() : bitsRepresentingPeak(0) {}
|
PeakVolume() : bitsRepresentingPeak(0) {}
|
||||||
/*!
|
/*!
|
||||||
* The number of bits (in the range of 0 to 255) used to describe the
|
* The number of bits (in the range of 0 to 255) used to describe the
|
||||||
* peak volume.
|
* peak volume.
|
||||||
*/
|
*/
|
||||||
unsigned char bitsRepresentingPeak;
|
unsigned char bitsRepresentingPeak;
|
||||||
/*!
|
/*!
|
||||||
* The array of bits (represented as a series of bytes) used to describe
|
* The array of bits (represented as a series of bytes) used to describe
|
||||||
* the peak volume.
|
* the peak volume.
|
||||||
*/
|
*/
|
||||||
ByteVector peakVolume;
|
ByteVector peakVolume;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs a RelativeVolumeFrame. The relevant data should be set
|
* Constructs a RelativeVolumeFrame. The relevant data should be set
|
||||||
* manually.
|
* manually.
|
||||||
*/
|
*/
|
||||||
RelativeVolumeFrame();
|
RelativeVolumeFrame();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs a RelativeVolumeFrame based on the contents of \a data.
|
* Constructs a RelativeVolumeFrame based on the contents of \a data.
|
||||||
*/
|
*/
|
||||||
RelativeVolumeFrame(const ByteVector &data);
|
RelativeVolumeFrame(const ByteVector &data);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys the RelativeVolumeFrame instance.
|
* Destroys the RelativeVolumeFrame instance.
|
||||||
*/
|
*/
|
||||||
virtual ~RelativeVolumeFrame();
|
virtual ~RelativeVolumeFrame();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the frame's identification.
|
* Returns the frame's identification.
|
||||||
*
|
*
|
||||||
* \see identification()
|
* \see identification()
|
||||||
*/
|
*/
|
||||||
virtual String toString() const;
|
virtual String toString() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns a list of channels with information currently in the frame.
|
* Returns a list of channels with information currently in the frame.
|
||||||
*/
|
*/
|
||||||
List<ChannelType> channels() const;
|
List<ChannelType> channels() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \deprecated Always returns master volume.
|
* \deprecated Always returns master volume.
|
||||||
*/
|
*/
|
||||||
TAGLIB_DEPRECATED ChannelType channelType() const;
|
TAGLIB_DEPRECATED ChannelType channelType() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \deprecated This method no longer has any effect.
|
* \deprecated This method no longer has any effect.
|
||||||
*/
|
*/
|
||||||
TAGLIB_DEPRECATED void setChannelType(ChannelType t);
|
TAGLIB_DEPRECATED void setChannelType(ChannelType t);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There was a terrible API goof here, and while this can't be changed to
|
* There was a terrible API goof here, and while this can't be changed to
|
||||||
* the way it appears below for binary compatibility reasons, let's at
|
* the way it appears below for binary compatibility reasons, let's at
|
||||||
* least pretend that it looks clean.
|
* least pretend that it looks clean.
|
||||||
@ -147,7 +144,7 @@ namespace TagLib {
|
|||||||
|
|
||||||
#ifdef DOXYGEN
|
#ifdef DOXYGEN
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the relative volume adjustment "index". As indicated by the
|
* Returns the relative volume adjustment "index". As indicated by the
|
||||||
* ID3v2 standard this is a 16-bit signed integer that reflects the
|
* ID3v2 standard this is a 16-bit signed integer that reflects the
|
||||||
* decibels of adjustment when divided by 512.
|
* decibels of adjustment when divided by 512.
|
||||||
@ -158,9 +155,9 @@ namespace TagLib {
|
|||||||
* \see setVolumeAdjustmentIndex()
|
* \see setVolumeAdjustmentIndex()
|
||||||
* \see volumeAjustment()
|
* \see volumeAjustment()
|
||||||
*/
|
*/
|
||||||
short volumeAdjustmentIndex(ChannelType type = MasterVolume) const;
|
short volumeAdjustmentIndex(ChannelType type = MasterVolume) const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Set the volume adjustment to \a index. As indicated by the ID3v2
|
* Set the volume adjustment to \a index. As indicated by the ID3v2
|
||||||
* standard this is a 16-bit signed integer that reflects the decibels of
|
* standard this is a 16-bit signed integer that reflects the decibels of
|
||||||
* adjustment when divided by 512.
|
* adjustment when divided by 512.
|
||||||
@ -170,9 +167,9 @@ namespace TagLib {
|
|||||||
* \see volumeAdjustmentIndex()
|
* \see volumeAdjustmentIndex()
|
||||||
* \see setVolumeAjustment()
|
* \see setVolumeAjustment()
|
||||||
*/
|
*/
|
||||||
void setVolumeAdjustmentIndex(short index, ChannelType type = MasterVolume);
|
void setVolumeAdjustmentIndex(short index, ChannelType type = MasterVolume);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the relative volume adjustment in decibels.
|
* Returns the relative volume adjustment in decibels.
|
||||||
*
|
*
|
||||||
* \note Because this is actually stored internally as an "index" to this
|
* \note Because this is actually stored internally as an "index" to this
|
||||||
@ -185,9 +182,9 @@ namespace TagLib {
|
|||||||
* \see setVolumeAdjustment()
|
* \see setVolumeAdjustment()
|
||||||
* \see volumeAdjustmentIndex()
|
* \see volumeAdjustmentIndex()
|
||||||
*/
|
*/
|
||||||
float volumeAdjustment(ChannelType type = MasterVolume) const;
|
float volumeAdjustment(ChannelType type = MasterVolume) const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Set the relative volume adjustment in decibels to \a adjustment.
|
* Set the relative volume adjustment in decibels to \a adjustment.
|
||||||
*
|
*
|
||||||
* By default this sets the value for the master volume.
|
* By default this sets the value for the master volume.
|
||||||
@ -199,9 +196,9 @@ namespace TagLib {
|
|||||||
* \see setVolumeAdjustment()
|
* \see setVolumeAdjustment()
|
||||||
* \see volumeAdjustmentIndex()
|
* \see volumeAdjustmentIndex()
|
||||||
*/
|
*/
|
||||||
void setVolumeAdjustment(float adjustment, ChannelType type = MasterVolume);
|
void setVolumeAdjustment(float adjustment, ChannelType type = MasterVolume);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the peak volume (represented as a length and a string of bits).
|
* Returns the peak volume (represented as a length and a string of bits).
|
||||||
*
|
*
|
||||||
* This defaults to returning the value for the master volume channel if
|
* This defaults to returning the value for the master volume channel if
|
||||||
@ -209,68 +206,68 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \see setPeakVolume()
|
* \see setPeakVolume()
|
||||||
*/
|
*/
|
||||||
PeakVolume peakVolume(ChannelType type = MasterVolume) const;
|
PeakVolume peakVolume(ChannelType type = MasterVolume) const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the peak volume to \a peak.
|
* Sets the peak volume to \a peak.
|
||||||
*
|
*
|
||||||
* By default this sets the value for the master volume.
|
* By default this sets the value for the master volume.
|
||||||
*
|
*
|
||||||
* \see peakVolume()
|
* \see peakVolume()
|
||||||
*/
|
*/
|
||||||
void setPeakVolume(const PeakVolume &peak, ChannelType type = MasterVolume);
|
void setPeakVolume(const PeakVolume &peak, ChannelType type = MasterVolume);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
// BIC: Combine each of the following pairs of functions (or maybe just
|
// BIC: Combine each of the following pairs of functions (or maybe just
|
||||||
// rework this junk altogether).
|
// rework this junk altogether).
|
||||||
|
|
||||||
short volumeAdjustmentIndex(ChannelType type) const;
|
short volumeAdjustmentIndex(ChannelType type) const;
|
||||||
short volumeAdjustmentIndex() const;
|
short volumeAdjustmentIndex() const;
|
||||||
|
|
||||||
void setVolumeAdjustmentIndex(short index, ChannelType type);
|
void setVolumeAdjustmentIndex(short index, ChannelType type);
|
||||||
void setVolumeAdjustmentIndex(short index);
|
void setVolumeAdjustmentIndex(short index);
|
||||||
|
|
||||||
float volumeAdjustment(ChannelType type) const;
|
float volumeAdjustment(ChannelType type) const;
|
||||||
float volumeAdjustment() const;
|
float volumeAdjustment() const;
|
||||||
|
|
||||||
void setVolumeAdjustment(float adjustment, ChannelType type);
|
void setVolumeAdjustment(float adjustment, ChannelType type);
|
||||||
void setVolumeAdjustment(float adjustment);
|
void setVolumeAdjustment(float adjustment);
|
||||||
|
|
||||||
PeakVolume peakVolume(ChannelType type) const;
|
PeakVolume peakVolume(ChannelType type) const;
|
||||||
PeakVolume peakVolume() const;
|
PeakVolume peakVolume() const;
|
||||||
|
|
||||||
void setPeakVolume(const PeakVolume &peak, ChannelType type);
|
void setPeakVolume(const PeakVolume &peak, ChannelType type);
|
||||||
void setPeakVolume(const PeakVolume &peak);
|
void setPeakVolume(const PeakVolume &peak);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the identification for this frame.
|
* Returns the identification for this frame.
|
||||||
*/
|
*/
|
||||||
String identification() const;
|
String identification() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the identification of the frame to \a s. The string
|
* Sets the identification of the frame to \a s. The string
|
||||||
* is used to identify the situation and/or device where this
|
* is used to identify the situation and/or device where this
|
||||||
* adjustment should apply.
|
* adjustment should apply.
|
||||||
*/
|
*/
|
||||||
void setIdentification(const String &s);
|
void setIdentification(const String &s);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void parseFields(const ByteVector &data);
|
virtual void parseFields(const ByteVector &data);
|
||||||
virtual ByteVector renderFields() const;
|
virtual ByteVector renderFields() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RelativeVolumeFrame(const ByteVector &data, Header *h);
|
RelativeVolumeFrame(const ByteVector &data, Header *h);
|
||||||
RelativeVolumeFrame(const RelativeVolumeFrame &);
|
RelativeVolumeFrame(const RelativeVolumeFrame &);
|
||||||
RelativeVolumeFrame &operator=(const RelativeVolumeFrame &);
|
RelativeVolumeFrame &operator=(const RelativeVolumeFrame &);
|
||||||
|
|
||||||
class RelativeVolumeFramePrivate;
|
class RelativeVolumeFramePrivate;
|
||||||
RelativeVolumeFramePrivate *d;
|
RelativeVolumeFramePrivate *d;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace ID3v2
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
#endif
|
#endif
|
||||||
|
@ -32,13 +32,11 @@
|
|||||||
using namespace Strawberry_TagLib::TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
using namespace ID3v2;
|
using namespace ID3v2;
|
||||||
|
|
||||||
class SynchronizedLyricsFrame::SynchronizedLyricsFramePrivate
|
class SynchronizedLyricsFrame::SynchronizedLyricsFramePrivate {
|
||||||
{
|
public:
|
||||||
public:
|
SynchronizedLyricsFramePrivate() : textEncoding(String::Latin1),
|
||||||
SynchronizedLyricsFramePrivate() :
|
timestampFormat(SynchronizedLyricsFrame::AbsoluteMilliseconds),
|
||||||
textEncoding(String::Latin1),
|
type(SynchronizedLyricsFrame::Lyrics) {}
|
||||||
timestampFormat(SynchronizedLyricsFrame::AbsoluteMilliseconds),
|
|
||||||
type(SynchronizedLyricsFrame::Lyrics) {}
|
|
||||||
String::Type textEncoding;
|
String::Type textEncoding;
|
||||||
ByteVector language;
|
ByteVector language;
|
||||||
SynchronizedLyricsFrame::TimestampFormat timestampFormat;
|
SynchronizedLyricsFrame::TimestampFormat timestampFormat;
|
||||||
@ -51,90 +49,72 @@ public:
|
|||||||
// public members
|
// public members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
SynchronizedLyricsFrame::SynchronizedLyricsFrame(String::Type encoding) :
|
SynchronizedLyricsFrame::SynchronizedLyricsFrame(String::Type encoding) : Frame("SYLT"),
|
||||||
Frame("SYLT"),
|
d(new SynchronizedLyricsFramePrivate()) {
|
||||||
d(new SynchronizedLyricsFramePrivate())
|
|
||||||
{
|
|
||||||
d->textEncoding = encoding;
|
d->textEncoding = encoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
SynchronizedLyricsFrame::SynchronizedLyricsFrame(const ByteVector &data) :
|
SynchronizedLyricsFrame::SynchronizedLyricsFrame(const ByteVector &data) : Frame(data),
|
||||||
Frame(data),
|
d(new SynchronizedLyricsFramePrivate()) {
|
||||||
d(new SynchronizedLyricsFramePrivate())
|
|
||||||
{
|
|
||||||
setData(data);
|
setData(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
SynchronizedLyricsFrame::~SynchronizedLyricsFrame()
|
SynchronizedLyricsFrame::~SynchronizedLyricsFrame() {
|
||||||
{
|
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
String SynchronizedLyricsFrame::toString() const
|
String SynchronizedLyricsFrame::toString() const {
|
||||||
{
|
|
||||||
return d->description;
|
return d->description;
|
||||||
}
|
}
|
||||||
|
|
||||||
String::Type SynchronizedLyricsFrame::textEncoding() const
|
String::Type SynchronizedLyricsFrame::textEncoding() const {
|
||||||
{
|
|
||||||
return d->textEncoding;
|
return d->textEncoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector SynchronizedLyricsFrame::language() const
|
ByteVector SynchronizedLyricsFrame::language() const {
|
||||||
{
|
|
||||||
return d->language;
|
return d->language;
|
||||||
}
|
}
|
||||||
|
|
||||||
SynchronizedLyricsFrame::TimestampFormat
|
SynchronizedLyricsFrame::TimestampFormat
|
||||||
SynchronizedLyricsFrame::timestampFormat() const
|
SynchronizedLyricsFrame::timestampFormat() const {
|
||||||
{
|
|
||||||
return d->timestampFormat;
|
return d->timestampFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
SynchronizedLyricsFrame::Type SynchronizedLyricsFrame::type() const
|
SynchronizedLyricsFrame::Type SynchronizedLyricsFrame::type() const {
|
||||||
{
|
|
||||||
return d->type;
|
return d->type;
|
||||||
}
|
}
|
||||||
|
|
||||||
String SynchronizedLyricsFrame::description() const
|
String SynchronizedLyricsFrame::description() const {
|
||||||
{
|
|
||||||
return d->description;
|
return d->description;
|
||||||
}
|
}
|
||||||
|
|
||||||
SynchronizedLyricsFrame::SynchedTextList
|
SynchronizedLyricsFrame::SynchedTextList
|
||||||
SynchronizedLyricsFrame::synchedText() const
|
SynchronizedLyricsFrame::synchedText() const {
|
||||||
{
|
|
||||||
return d->synchedText;
|
return d->synchedText;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SynchronizedLyricsFrame::setTextEncoding(String::Type encoding)
|
void SynchronizedLyricsFrame::setTextEncoding(String::Type encoding) {
|
||||||
{
|
|
||||||
d->textEncoding = encoding;
|
d->textEncoding = encoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SynchronizedLyricsFrame::setLanguage(const ByteVector &languageEncoding)
|
void SynchronizedLyricsFrame::setLanguage(const ByteVector &languageEncoding) {
|
||||||
{
|
|
||||||
d->language = languageEncoding.mid(0, 3);
|
d->language = languageEncoding.mid(0, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SynchronizedLyricsFrame::setTimestampFormat(SynchronizedLyricsFrame::TimestampFormat f)
|
void SynchronizedLyricsFrame::setTimestampFormat(SynchronizedLyricsFrame::TimestampFormat f) {
|
||||||
{
|
|
||||||
d->timestampFormat = f;
|
d->timestampFormat = f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SynchronizedLyricsFrame::setType(SynchronizedLyricsFrame::Type t)
|
void SynchronizedLyricsFrame::setType(SynchronizedLyricsFrame::Type t) {
|
||||||
{
|
|
||||||
d->type = t;
|
d->type = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SynchronizedLyricsFrame::setDescription(const String &s)
|
void SynchronizedLyricsFrame::setDescription(const String &s) {
|
||||||
{
|
|
||||||
d->description = s;
|
d->description = s;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SynchronizedLyricsFrame::setSynchedText(
|
void SynchronizedLyricsFrame::setSynchedText(
|
||||||
const SynchronizedLyricsFrame::SynchedTextList &t)
|
const SynchronizedLyricsFrame::SynchedTextList &t) {
|
||||||
{
|
|
||||||
d->synchedText = t;
|
d->synchedText = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,10 +122,9 @@ void SynchronizedLyricsFrame::setSynchedText(
|
|||||||
// protected members
|
// protected members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void SynchronizedLyricsFrame::parseFields(const ByteVector &data)
|
void SynchronizedLyricsFrame::parseFields(const ByteVector &data) {
|
||||||
{
|
|
||||||
const int end = data.size();
|
const int end = data.size();
|
||||||
if(end < 7) {
|
if (end < 7) {
|
||||||
debug("A synchronized lyrics frame must contain at least 7 bytes.");
|
debug("A synchronized lyrics frame must contain at least 7 bytes.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -158,7 +137,7 @@ void SynchronizedLyricsFrame::parseFields(const ByteVector &data)
|
|||||||
int pos = 6;
|
int pos = 6;
|
||||||
|
|
||||||
d->description = readStringField(data, d->textEncoding, &pos);
|
d->description = readStringField(data, d->textEncoding, &pos);
|
||||||
if(pos == 6)
|
if (pos == 6)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -169,27 +148,28 @@ void SynchronizedLyricsFrame::parseFields(const ByteVector &data)
|
|||||||
* case of strings without BOM so that readStringField() will work.
|
* case of strings without BOM so that readStringField() will work.
|
||||||
*/
|
*/
|
||||||
String::Type encWithEndianness = d->textEncoding;
|
String::Type encWithEndianness = d->textEncoding;
|
||||||
if(d->textEncoding == String::UTF16) {
|
if (d->textEncoding == String::UTF16) {
|
||||||
unsigned short bom = data.toUShort(6, true);
|
unsigned short bom = data.toUShort(6, true);
|
||||||
if(bom == 0xfffe) {
|
if (bom == 0xfffe) {
|
||||||
encWithEndianness = String::UTF16LE;
|
encWithEndianness = String::UTF16LE;
|
||||||
} else if(bom == 0xfeff) {
|
}
|
||||||
|
else if (bom == 0xfeff) {
|
||||||
encWithEndianness = String::UTF16BE;
|
encWithEndianness = String::UTF16BE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
d->synchedText.clear();
|
d->synchedText.clear();
|
||||||
while(pos < end) {
|
while (pos < end) {
|
||||||
String::Type enc = d->textEncoding;
|
String::Type enc = d->textEncoding;
|
||||||
// If a UTF16 string has no BOM, use the encoding found above.
|
// 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);
|
unsigned short bom = data.toUShort(pos, true);
|
||||||
if(bom != 0xfffe && bom != 0xfeff) {
|
if (bom != 0xfffe && bom != 0xfeff) {
|
||||||
enc = encWithEndianness;
|
enc = encWithEndianness;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
String text = readStringField(data, enc, &pos);
|
String text = readStringField(data, enc, &pos);
|
||||||
if(pos + 4 > end)
|
if (pos + 4 > end)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
unsigned int time = data.toUInt(pos, true);
|
unsigned int time = data.toUInt(pos, true);
|
||||||
@ -199,16 +179,15 @@ void SynchronizedLyricsFrame::parseFields(const ByteVector &data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteVector SynchronizedLyricsFrame::renderFields() const
|
ByteVector SynchronizedLyricsFrame::renderFields() const {
|
||||||
{
|
|
||||||
ByteVector v;
|
ByteVector v;
|
||||||
|
|
||||||
String::Type encoding = d->textEncoding;
|
String::Type encoding = d->textEncoding;
|
||||||
|
|
||||||
encoding = checkTextEncoding(d->description, encoding);
|
encoding = checkTextEncoding(d->description, encoding);
|
||||||
for(SynchedTextList::ConstIterator it = d->synchedText.begin();
|
for (SynchedTextList::ConstIterator it = d->synchedText.begin();
|
||||||
it != d->synchedText.end();
|
it != d->synchedText.end();
|
||||||
++it) {
|
++it) {
|
||||||
encoding = checkTextEncoding(it->text, encoding);
|
encoding = checkTextEncoding(it->text, encoding);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -218,9 +197,9 @@ ByteVector SynchronizedLyricsFrame::renderFields() const
|
|||||||
v.append(char(d->type));
|
v.append(char(d->type));
|
||||||
v.append(d->description.data(encoding));
|
v.append(d->description.data(encoding));
|
||||||
v.append(textDelimiter(encoding));
|
v.append(textDelimiter(encoding));
|
||||||
for(SynchedTextList::ConstIterator it = d->synchedText.begin();
|
for (SynchedTextList::ConstIterator it = d->synchedText.begin();
|
||||||
it != d->synchedText.end();
|
it != d->synchedText.end();
|
||||||
++it) {
|
++it) {
|
||||||
const SynchedText &entry = *it;
|
const SynchedText &entry = *it;
|
||||||
v.append(entry.text.data(encoding));
|
v.append(entry.text.data(encoding));
|
||||||
v.append(textDelimiter(encoding));
|
v.append(textDelimiter(encoding));
|
||||||
@ -234,9 +213,7 @@ ByteVector SynchronizedLyricsFrame::renderFields() const
|
|||||||
// private members
|
// private members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
SynchronizedLyricsFrame::SynchronizedLyricsFrame(const ByteVector &data, Header *h) :
|
SynchronizedLyricsFrame::SynchronizedLyricsFrame(const ByteVector &data, Header *h) : Frame(h),
|
||||||
Frame(h),
|
d(new SynchronizedLyricsFramePrivate()) {
|
||||||
d(new SynchronizedLyricsFramePrivate())
|
|
||||||
{
|
|
||||||
parseFields(fieldData(data));
|
parseFields(fieldData(data));
|
||||||
}
|
}
|
||||||
|
@ -32,94 +32,92 @@
|
|||||||
namespace Strawberry_TagLib {
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
namespace ID3v2 {
|
namespace ID3v2 {
|
||||||
|
|
||||||
//! ID3v2 synchronized lyrics frame
|
//! ID3v2 synchronized lyrics frame
|
||||||
/*!
|
/*!
|
||||||
* An implementation of ID3v2 synchronized lyrics.
|
* An implementation of ID3v2 synchronized lyrics.
|
||||||
*/
|
*/
|
||||||
class TAGLIB_EXPORT SynchronizedLyricsFrame : public Frame
|
class TAGLIB_EXPORT SynchronizedLyricsFrame : public Frame {
|
||||||
{
|
friend class FrameFactory;
|
||||||
friend class FrameFactory;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
/*!
|
||||||
/*!
|
|
||||||
* Specifies the timestamp format used.
|
* Specifies the timestamp format used.
|
||||||
*/
|
*/
|
||||||
enum TimestampFormat {
|
enum TimestampFormat {
|
||||||
//! The timestamp is of unknown format.
|
//! The timestamp is of unknown format.
|
||||||
Unknown = 0x00,
|
Unknown = 0x00,
|
||||||
//! The timestamp represents the number of MPEG frames since
|
//! The timestamp represents the number of MPEG frames since
|
||||||
//! the beginning of the audio stream.
|
//! the beginning of the audio stream.
|
||||||
AbsoluteMpegFrames = 0x01,
|
AbsoluteMpegFrames = 0x01,
|
||||||
//! The timestamp represents the number of milliseconds since
|
//! The timestamp represents the number of milliseconds since
|
||||||
//! the beginning of the audio stream.
|
//! the beginning of the audio stream.
|
||||||
AbsoluteMilliseconds = 0x02
|
AbsoluteMilliseconds = 0x02
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Specifies the type of text contained.
|
* Specifies the type of text contained.
|
||||||
*/
|
*/
|
||||||
enum Type {
|
enum Type {
|
||||||
//! The text is some other type of text.
|
//! The text is some other type of text.
|
||||||
Other = 0x00,
|
Other = 0x00,
|
||||||
//! The text contains lyrical data.
|
//! The text contains lyrical data.
|
||||||
Lyrics = 0x01,
|
Lyrics = 0x01,
|
||||||
//! The text contains a transcription.
|
//! The text contains a transcription.
|
||||||
TextTranscription = 0x02,
|
TextTranscription = 0x02,
|
||||||
//! The text lists the movements in the piece.
|
//! The text lists the movements in the piece.
|
||||||
Movement = 0x03,
|
Movement = 0x03,
|
||||||
//! The text describes events that occur.
|
//! The text describes events that occur.
|
||||||
Events = 0x04,
|
Events = 0x04,
|
||||||
//! The text contains chord changes that occur in the music.
|
//! The text contains chord changes that occur in the music.
|
||||||
Chord = 0x05,
|
Chord = 0x05,
|
||||||
//! The text contains trivia or "pop up" information about the media.
|
//! The text contains trivia or "pop up" information about the media.
|
||||||
Trivia = 0x06,
|
Trivia = 0x06,
|
||||||
//! The text contains URLs for relevant webpages.
|
//! The text contains URLs for relevant webpages.
|
||||||
WebpageUrls = 0x07,
|
WebpageUrls = 0x07,
|
||||||
//! The text contains URLs for relevant images.
|
//! The text contains URLs for relevant images.
|
||||||
ImageUrls = 0x08
|
ImageUrls = 0x08
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Single entry of time stamp and lyrics text.
|
* Single entry of time stamp and lyrics text.
|
||||||
*/
|
*/
|
||||||
struct SynchedText {
|
struct SynchedText {
|
||||||
SynchedText(unsigned int ms, String str) : time(ms), text(str) {}
|
SynchedText(unsigned int ms, String str) : time(ms), text(str) {}
|
||||||
unsigned int time;
|
unsigned int time;
|
||||||
String text;
|
String text;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* List of synchronized lyrics.
|
* List of synchronized lyrics.
|
||||||
*/
|
*/
|
||||||
typedef Strawberry_TagLib::TagLib::List<SynchedText> SynchedTextList;
|
typedef Strawberry_TagLib::TagLib::List<SynchedText> SynchedTextList;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Construct an empty synchronized lyrics frame that will use the text
|
* Construct an empty synchronized lyrics frame that will use the text
|
||||||
* encoding \a encoding.
|
* encoding \a encoding.
|
||||||
*/
|
*/
|
||||||
explicit SynchronizedLyricsFrame(String::Type encoding = String::Latin1);
|
explicit SynchronizedLyricsFrame(String::Type encoding = String::Latin1);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Construct a synchronized lyrics frame based on the data in \a data.
|
* Construct a synchronized lyrics frame based on the data in \a data.
|
||||||
*/
|
*/
|
||||||
explicit SynchronizedLyricsFrame(const ByteVector &data);
|
explicit SynchronizedLyricsFrame(const ByteVector &data);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys this SynchronizedLyricsFrame instance.
|
* Destroys this SynchronizedLyricsFrame instance.
|
||||||
*/
|
*/
|
||||||
virtual ~SynchronizedLyricsFrame();
|
virtual ~SynchronizedLyricsFrame();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the description of this synchronized lyrics frame.
|
* Returns the description of this synchronized lyrics frame.
|
||||||
*
|
*
|
||||||
* \see description()
|
* \see description()
|
||||||
*/
|
*/
|
||||||
virtual String toString() const;
|
virtual String toString() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the text encoding that will be used in rendering this frame.
|
* Returns the text encoding that will be used in rendering this frame.
|
||||||
* This defaults to the type that was either specified in the constructor
|
* This defaults to the type that was either specified in the constructor
|
||||||
* or read from the frame when parsed.
|
* or read from the frame when parsed.
|
||||||
@ -127,9 +125,9 @@ namespace TagLib {
|
|||||||
* \see setTextEncoding()
|
* \see setTextEncoding()
|
||||||
* \see render()
|
* \see render()
|
||||||
*/
|
*/
|
||||||
String::Type textEncoding() const;
|
String::Type textEncoding() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the language encoding as a 3 byte encoding as specified by
|
* Returns the language encoding as a 3 byte encoding as specified by
|
||||||
* <a href="http://en.wikipedia.org/wiki/ISO_639">ISO-639-2</a>.
|
* <a href="http://en.wikipedia.org/wiki/ISO_639">ISO-639-2</a>.
|
||||||
*
|
*
|
||||||
@ -137,97 +135,97 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \see setLanguage()
|
* \see setLanguage()
|
||||||
*/
|
*/
|
||||||
ByteVector language() const;
|
ByteVector language() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the timestamp format.
|
* Returns the timestamp format.
|
||||||
*/
|
*/
|
||||||
TimestampFormat timestampFormat() const;
|
TimestampFormat timestampFormat() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the type of text contained.
|
* Returns the type of text contained.
|
||||||
*/
|
*/
|
||||||
Type type() const;
|
Type type() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the description of this synchronized lyrics frame.
|
* Returns the description of this synchronized lyrics frame.
|
||||||
*
|
*
|
||||||
* \note Most taggers simply ignore this value.
|
* \note Most taggers simply ignore this value.
|
||||||
*
|
*
|
||||||
* \see setDescription()
|
* \see setDescription()
|
||||||
*/
|
*/
|
||||||
String description() const;
|
String description() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the text with the time stamps.
|
* Returns the text with the time stamps.
|
||||||
*/
|
*/
|
||||||
SynchedTextList synchedText() const;
|
SynchedTextList synchedText() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the text encoding to be used when rendering this frame to
|
* Sets the text encoding to be used when rendering this frame to
|
||||||
* \a encoding.
|
* \a encoding.
|
||||||
*
|
*
|
||||||
* \see textEncoding()
|
* \see textEncoding()
|
||||||
* \see render()
|
* \see render()
|
||||||
*/
|
*/
|
||||||
void setTextEncoding(String::Type encoding);
|
void setTextEncoding(String::Type encoding);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Set the language using the 3 byte language code from
|
* Set the language using the 3 byte language code from
|
||||||
* <a href="http://en.wikipedia.org/wiki/ISO_639">ISO-639-2</a> to
|
* <a href="http://en.wikipedia.org/wiki/ISO_639">ISO-639-2</a> to
|
||||||
* \a languageCode.
|
* \a languageCode.
|
||||||
*
|
*
|
||||||
* \see language()
|
* \see language()
|
||||||
*/
|
*/
|
||||||
void setLanguage(const ByteVector &languageCode);
|
void setLanguage(const ByteVector &languageCode);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Set the timestamp format.
|
* Set the timestamp format.
|
||||||
*
|
*
|
||||||
* \see timestampFormat()
|
* \see timestampFormat()
|
||||||
*/
|
*/
|
||||||
void setTimestampFormat(TimestampFormat f);
|
void setTimestampFormat(TimestampFormat f);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Set the type of text contained.
|
* Set the type of text contained.
|
||||||
*
|
*
|
||||||
* \see type()
|
* \see type()
|
||||||
*/
|
*/
|
||||||
void setType(Type t);
|
void setType(Type t);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the description of the synchronized lyrics frame to \a s.
|
* Sets the description of the synchronized lyrics frame to \a s.
|
||||||
*
|
*
|
||||||
* \see description()
|
* \see description()
|
||||||
*/
|
*/
|
||||||
void setDescription(const String &s);
|
void setDescription(const String &s);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the text with the time stamps.
|
* Sets the text with the time stamps.
|
||||||
*
|
*
|
||||||
* \see text()
|
* \see text()
|
||||||
*/
|
*/
|
||||||
void setSynchedText(const SynchedTextList &t);
|
void setSynchedText(const SynchedTextList &t);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Reimplementations.
|
// Reimplementations.
|
||||||
|
|
||||||
virtual void parseFields(const ByteVector &data);
|
virtual void parseFields(const ByteVector &data);
|
||||||
virtual ByteVector renderFields() const;
|
virtual ByteVector renderFields() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*!
|
/*!
|
||||||
* The constructor used by the FrameFactory.
|
* The constructor used by the FrameFactory.
|
||||||
*/
|
*/
|
||||||
SynchronizedLyricsFrame(const ByteVector &data, Header *h);
|
SynchronizedLyricsFrame(const ByteVector &data, Header *h);
|
||||||
SynchronizedLyricsFrame(const SynchronizedLyricsFrame &);
|
SynchronizedLyricsFrame(const SynchronizedLyricsFrame &);
|
||||||
SynchronizedLyricsFrame &operator=(const SynchronizedLyricsFrame &);
|
SynchronizedLyricsFrame &operator=(const SynchronizedLyricsFrame &);
|
||||||
|
|
||||||
class SynchronizedLyricsFramePrivate;
|
class SynchronizedLyricsFramePrivate;
|
||||||
SynchronizedLyricsFramePrivate *d;
|
SynchronizedLyricsFramePrivate *d;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
} // namespace ID3v2
|
||||||
}
|
} // namespace TagLib
|
||||||
}
|
} // namespace Strawberry_TagLib
|
||||||
#endif
|
#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