commit
d20c2244a8
25
3rdparty/taglib/CMakeLists.txt
vendored
25
3rdparty/taglib/CMakeLists.txt
vendored
@ -1,3 +1,5 @@
|
||||
cmake_minimum_required(VERSION 2.8.11)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-delete-non-virtual-dtor")
|
||||
|
||||
set(TAGLIB_SOVERSION_CURRENT 17)
|
||||
@ -45,6 +47,7 @@ include_directories(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/s3m
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/it
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/xm
|
||||
${CMAKE_SOURCE_DIR}/3rdparty
|
||||
)
|
||||
|
||||
if(ZLIB_FOUND)
|
||||
@ -53,10 +56,6 @@ elseif(HAVE_ZLIB_SOURCE)
|
||||
include_directories(${ZLIB_SOURCE})
|
||||
endif()
|
||||
|
||||
if(HAVE_BOOST_BYTESWAP OR HAVE_BOOST_ATOMIC OR HAVE_BOOST_ZLIB)
|
||||
include_directories(${Boost_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
set(tag_HDRS
|
||||
tag.h
|
||||
fileref.h
|
||||
@ -333,12 +332,6 @@ set(toolkit_SRCS
|
||||
toolkit/tzlib.cpp
|
||||
)
|
||||
|
||||
if(NOT WIN32)
|
||||
set(unicode_SRCS
|
||||
toolkit/unicode.cpp
|
||||
)
|
||||
endif()
|
||||
|
||||
if(HAVE_ZLIB_SOURCE)
|
||||
set(zlib_SRCS
|
||||
${ZLIB_SOURCE}/adler32.c
|
||||
@ -355,7 +348,7 @@ set(tag_LIB_SRCS
|
||||
${vorbis_SRCS} ${oggflacs_SRCS} ${mpc_SRCS} ${ape_SRCS} ${toolkit_SRCS} ${flacs_SRCS}
|
||||
${wavpack_SRCS} ${speex_SRCS} ${trueaudio_SRCS} ${riff_SRCS} ${aiff_SRCS} ${wav_SRCS}
|
||||
${asf_SRCS} ${mp4_SRCS} ${mod_SRCS} ${s3m_SRCS} ${it_SRCS} ${xm_SRCS} ${opus_SRCS}
|
||||
${unicode_SRCS} ${zlib_SRCS}
|
||||
${zlib_SRCS}
|
||||
tag.cpp
|
||||
tagunion.cpp
|
||||
fileref.cpp
|
||||
@ -365,18 +358,10 @@ set(tag_LIB_SRCS
|
||||
|
||||
add_library(tag STATIC ${tag_LIB_SRCS} ${tag_HDRS})
|
||||
|
||||
if(ZLIB_FOUND)
|
||||
if(HAVE_ZLIB AND NOT HAVE_ZLIB_SOURCE)
|
||||
target_link_libraries(tag ${ZLIB_LIBRARIES})
|
||||
endif()
|
||||
|
||||
if(HAVE_BOOST_ATOMIC)
|
||||
target_link_libraries(tag ${Boost_ATOMIC_LIBRARY})
|
||||
endif()
|
||||
|
||||
if(HAVE_BOOST_ZLIB)
|
||||
target_link_libraries(tag ${Boost_IOSTREAMS_LIBRARY} ${Boost_ZLIB_LIBRARY})
|
||||
endif()
|
||||
|
||||
set_target_properties(tag PROPERTIES
|
||||
VERSION ${TAGLIB_SOVERSION_MAJOR}.${TAGLIB_SOVERSION_MINOR}.${TAGLIB_SOVERSION_PATCH}
|
||||
SOVERSION ${TAGLIB_SOVERSION_MAJOR}
|
||||
|
12
3rdparty/taglib/ape/apefile.cpp
vendored
12
3rdparty/taglib/ape/apefile.cpp
vendored
@ -83,6 +83,18 @@ public:
|
||||
Properties *properties;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// static members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool APE::File::isSupported(IOStream *stream)
|
||||
{
|
||||
// An APE file has an ID "MAC " somewhere. An ID3v2 tag may precede.
|
||||
|
||||
const ByteVector buffer = Utils::readHeader(stream, bufferSize(), true);
|
||||
return (buffer.find("MAC ") >= 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
9
3rdparty/taglib/ape/apefile.h
vendored
9
3rdparty/taglib/ape/apefile.h
vendored
@ -211,6 +211,15 @@ namespace TagLib {
|
||||
*/
|
||||
bool hasID3v1Tag() const;
|
||||
|
||||
/*!
|
||||
* Returns whether or not the given \a stream can be opened as an APE
|
||||
* file.
|
||||
*
|
||||
* \note This method is designed to do a quick check. The result may
|
||||
* not necessarily be correct.
|
||||
*/
|
||||
static bool isSupported(IOStream *stream);
|
||||
|
||||
private:
|
||||
File(const File &);
|
||||
File &operator=(const File &);
|
||||
|
29
3rdparty/taglib/ape/apetag.cpp
vendored
29
3rdparty/taglib/ape/apetag.cpp
vendored
@ -47,23 +47,24 @@ using namespace APE;
|
||||
|
||||
namespace
|
||||
{
|
||||
bool isKeyValid(const char *key, size_t length)
|
||||
const unsigned int MinKeyLength = 2;
|
||||
const unsigned int MaxKeyLength = 255;
|
||||
|
||||
bool isKeyValid(const ByteVector &key)
|
||||
{
|
||||
const char *invalidKeys[] = { "ID3", "TAG", "OGGS", "MP+", 0 };
|
||||
|
||||
if(length < 2 || length > 255)
|
||||
return false;
|
||||
|
||||
// only allow printable ASCII including space (32..126)
|
||||
|
||||
for(const char *p = key; p < key + length; ++p) {
|
||||
const int c = static_cast<unsigned char>(*p);
|
||||
for(ByteVector::ConstIterator it = key.begin(); it != key.end(); ++it) {
|
||||
const int c = static_cast<unsigned char>(*it);
|
||||
if(c < 32 || c > 126)
|
||||
return false;
|
||||
}
|
||||
|
||||
const String upperKey = String(key).upper();
|
||||
for(size_t i = 0; invalidKeys[i] != 0; ++i) {
|
||||
if(Utils::equalsIgnoreCase(key, invalidKeys[i]))
|
||||
if(upperKey == invalidKeys[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -191,7 +192,7 @@ void APE::Tag::setGenre(const String &s)
|
||||
|
||||
void APE::Tag::setYear(unsigned int i)
|
||||
{
|
||||
if(i <= 0)
|
||||
if(i == 0)
|
||||
removeItem("YEAR");
|
||||
else
|
||||
addValue("YEAR", String::number(i), true);
|
||||
@ -199,7 +200,7 @@ void APE::Tag::setYear(unsigned int i)
|
||||
|
||||
void APE::Tag::setTrack(unsigned int i)
|
||||
{
|
||||
if(i <= 0)
|
||||
if(i == 0)
|
||||
removeItem("TRACK");
|
||||
else
|
||||
addValue("TRACK", String::number(i), true);
|
||||
@ -296,11 +297,10 @@ PropertyMap APE::Tag::setProperties(const PropertyMap &origProps)
|
||||
|
||||
bool APE::Tag::checkKey(const String &key)
|
||||
{
|
||||
if(!key.isLatin1())
|
||||
if(key.size() < MinKeyLength || key.size() > MaxKeyLength)
|
||||
return false;
|
||||
|
||||
const std::string data = key.to8Bit(false);
|
||||
return isKeyValid(data.c_str(), data.size());
|
||||
return isKeyValid(key.data(String::UTF8));
|
||||
}
|
||||
|
||||
APE::Footer *APE::Tag::footer() const
|
||||
@ -419,7 +419,10 @@ void APE::Tag::parse(const ByteVector &data)
|
||||
const unsigned int keyLength = nullPos - pos - 8;
|
||||
const unsigned int valLegnth = data.toUInt(pos, false);
|
||||
|
||||
if(isKeyValid(&data[pos + 8], keyLength)){
|
||||
if(keyLength >= MinKeyLength
|
||||
&& keyLength <= MaxKeyLength
|
||||
&& isKeyValid(data.mid(pos + 8, keyLength)))
|
||||
{
|
||||
APE::Item item;
|
||||
item.parse(data.mid(pos));
|
||||
|
||||
|
52
3rdparty/taglib/asf/asfattribute.cpp
vendored
52
3rdparty/taglib/asf/asfattribute.cpp
vendored
@ -36,20 +36,16 @@ using namespace TagLib;
|
||||
class ASF::Attribute::AttributePrivate : public RefCounter
|
||||
{
|
||||
public:
|
||||
AttributePrivate()
|
||||
: pictureValue(ASF::Picture::fromInvalid()),
|
||||
stream(0),
|
||||
language(0) {}
|
||||
AttributePrivate() :
|
||||
pictureValue(ASF::Picture::fromInvalid()),
|
||||
numericValue(0),
|
||||
stream(0),
|
||||
language(0) {}
|
||||
AttributeTypes type;
|
||||
String stringValue;
|
||||
ByteVector byteVectorValue;
|
||||
ASF::Picture pictureValue;
|
||||
union {
|
||||
unsigned int intValue;
|
||||
unsigned short shortValue;
|
||||
unsigned long long longLongValue;
|
||||
bool boolValue;
|
||||
};
|
||||
unsigned long long numericValue;
|
||||
int stream;
|
||||
int language;
|
||||
};
|
||||
@ -95,28 +91,28 @@ ASF::Attribute::Attribute(unsigned int value) :
|
||||
d(new AttributePrivate())
|
||||
{
|
||||
d->type = DWordType;
|
||||
d->intValue = value;
|
||||
d->numericValue = value;
|
||||
}
|
||||
|
||||
ASF::Attribute::Attribute(unsigned long long value) :
|
||||
d(new AttributePrivate())
|
||||
{
|
||||
d->type = QWordType;
|
||||
d->longLongValue = value;
|
||||
d->numericValue = value;
|
||||
}
|
||||
|
||||
ASF::Attribute::Attribute(unsigned short value) :
|
||||
d(new AttributePrivate())
|
||||
{
|
||||
d->type = WordType;
|
||||
d->shortValue = value;
|
||||
d->numericValue = value;
|
||||
}
|
||||
|
||||
ASF::Attribute::Attribute(bool value) :
|
||||
d(new AttributePrivate())
|
||||
{
|
||||
d->type = BoolType;
|
||||
d->boolValue = value;
|
||||
d->numericValue = value;
|
||||
}
|
||||
|
||||
ASF::Attribute &ASF::Attribute::operator=(const ASF::Attribute &other)
|
||||
@ -157,22 +153,22 @@ ByteVector ASF::Attribute::toByteVector() const
|
||||
|
||||
unsigned short ASF::Attribute::toBool() const
|
||||
{
|
||||
return d->shortValue;
|
||||
return d->numericValue ? 1 : 0;
|
||||
}
|
||||
|
||||
unsigned short ASF::Attribute::toUShort() const
|
||||
{
|
||||
return d->shortValue;
|
||||
return static_cast<unsigned short>(d->numericValue);
|
||||
}
|
||||
|
||||
unsigned int ASF::Attribute::toUInt() const
|
||||
{
|
||||
return d->intValue;
|
||||
return static_cast<unsigned int>(d->numericValue);
|
||||
}
|
||||
|
||||
unsigned long long ASF::Attribute::toULongLong() const
|
||||
{
|
||||
return d->longLongValue;
|
||||
return static_cast<unsigned long long>(d->numericValue);
|
||||
}
|
||||
|
||||
ASF::Picture ASF::Attribute::toPicture() const
|
||||
@ -212,24 +208,24 @@ String ASF::Attribute::parse(ASF::File &f, int kind)
|
||||
|
||||
switch(d->type) {
|
||||
case WordType:
|
||||
d->shortValue = readWORD(&f);
|
||||
d->numericValue = readWORD(&f);
|
||||
break;
|
||||
|
||||
case BoolType:
|
||||
if(kind == 0) {
|
||||
d->boolValue = (readDWORD(&f) == 1);
|
||||
d->numericValue = (readDWORD(&f) != 0);
|
||||
}
|
||||
else {
|
||||
d->boolValue = (readWORD(&f) == 1);
|
||||
d->numericValue = (readWORD(&f) != 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case DWordType:
|
||||
d->intValue = readDWORD(&f);
|
||||
d->numericValue = readDWORD(&f);
|
||||
break;
|
||||
|
||||
case QWordType:
|
||||
d->longLongValue = readQWORD(&f);
|
||||
d->numericValue = readQWORD(&f);
|
||||
break;
|
||||
|
||||
case UnicodeType:
|
||||
@ -280,24 +276,24 @@ ByteVector ASF::Attribute::render(const String &name, int kind) const
|
||||
|
||||
switch (d->type) {
|
||||
case WordType:
|
||||
data.append(ByteVector::fromShort(d->shortValue, false));
|
||||
data.append(ByteVector::fromShort(toUShort(), false));
|
||||
break;
|
||||
|
||||
case BoolType:
|
||||
if(kind == 0) {
|
||||
data.append(ByteVector::fromUInt(d->boolValue ? 1 : 0, false));
|
||||
data.append(ByteVector::fromUInt(toBool(), false));
|
||||
}
|
||||
else {
|
||||
data.append(ByteVector::fromShort(d->boolValue ? 1 : 0, false));
|
||||
data.append(ByteVector::fromShort(toBool(), false));
|
||||
}
|
||||
break;
|
||||
|
||||
case DWordType:
|
||||
data.append(ByteVector::fromUInt(d->intValue, false));
|
||||
data.append(ByteVector::fromUInt(toUInt(), false));
|
||||
break;
|
||||
|
||||
case QWordType:
|
||||
data.append(ByteVector::fromLongLong(d->longLongValue, false));
|
||||
data.append(ByteVector::fromLongLong(toULongLong(), false));
|
||||
break;
|
||||
|
||||
case UnicodeType:
|
||||
|
2
3rdparty/taglib/asf/asfattribute.h
vendored
2
3rdparty/taglib/asf/asfattribute.h
vendored
@ -113,7 +113,7 @@ namespace TagLib
|
||||
/*!
|
||||
* Copies the contents of \a other into this item.
|
||||
*/
|
||||
ASF::Attribute &operator=(const Attribute &other);
|
||||
Attribute &operator=(const Attribute &other);
|
||||
|
||||
/*!
|
||||
* Exchanges the content of the Attribute by the content of \a other.
|
||||
|
54
3rdparty/taglib/asf/asffile.cpp
vendored
54
3rdparty/taglib/asf/asffile.cpp
vendored
@ -27,6 +27,7 @@
|
||||
#include <tbytevectorlist.h>
|
||||
#include <tpropertymap.h>
|
||||
#include <tstring.h>
|
||||
#include <tagutils.h>
|
||||
|
||||
#include "asffile.h"
|
||||
#include "asftag.h"
|
||||
@ -258,7 +259,6 @@ ByteVector ASF::File::FilePrivate::ContentDescriptionObject::guid() const
|
||||
|
||||
void ASF::File::FilePrivate::ContentDescriptionObject::parse(ASF::File *file, unsigned int /*size*/)
|
||||
{
|
||||
file->d->contentDescriptionObject = this;
|
||||
const int titleLength = readWORD(file);
|
||||
const int artistLength = readWORD(file);
|
||||
const int copyrightLength = readWORD(file);
|
||||
@ -299,7 +299,6 @@ ByteVector ASF::File::FilePrivate::ExtendedContentDescriptionObject::guid() cons
|
||||
|
||||
void ASF::File::FilePrivate::ExtendedContentDescriptionObject::parse(ASF::File *file, unsigned int /*size*/)
|
||||
{
|
||||
file->d->extendedContentDescriptionObject = this;
|
||||
int count = readWORD(file);
|
||||
while(count--) {
|
||||
ASF::Attribute attribute;
|
||||
@ -323,7 +322,6 @@ ByteVector ASF::File::FilePrivate::MetadataObject::guid() const
|
||||
|
||||
void ASF::File::FilePrivate::MetadataObject::parse(ASF::File *file, unsigned int /*size*/)
|
||||
{
|
||||
file->d->metadataObject = this;
|
||||
int count = readWORD(file);
|
||||
while(count--) {
|
||||
ASF::Attribute attribute;
|
||||
@ -347,7 +345,6 @@ ByteVector ASF::File::FilePrivate::MetadataLibraryObject::guid() const
|
||||
|
||||
void ASF::File::FilePrivate::MetadataLibraryObject::parse(ASF::File *file, unsigned int /*size*/)
|
||||
{
|
||||
file->d->metadataLibraryObject = this;
|
||||
int count = readWORD(file);
|
||||
while(count--) {
|
||||
ASF::Attribute attribute;
|
||||
@ -376,7 +373,6 @@ ByteVector ASF::File::FilePrivate::HeaderExtensionObject::guid() const
|
||||
|
||||
void ASF::File::FilePrivate::HeaderExtensionObject::parse(ASF::File *file, unsigned int /*size*/)
|
||||
{
|
||||
file->d->headerExtensionObject = this;
|
||||
file->seek(18, File::Current);
|
||||
long long dataSize = readDWORD(file);
|
||||
long long dataPos = 0;
|
||||
@ -394,10 +390,12 @@ void ASF::File::FilePrivate::HeaderExtensionObject::parse(ASF::File *file, unsig
|
||||
}
|
||||
BaseObject *obj;
|
||||
if(guid == metadataGuid) {
|
||||
obj = new MetadataObject();
|
||||
file->d->metadataObject = new MetadataObject();
|
||||
obj = file->d->metadataObject;
|
||||
}
|
||||
else if(guid == metadataLibraryGuid) {
|
||||
obj = new MetadataLibraryObject();
|
||||
file->d->metadataLibraryObject = new MetadataLibraryObject();
|
||||
obj = file->d->metadataLibraryObject;
|
||||
}
|
||||
else {
|
||||
obj = new UnknownObject(guid);
|
||||
@ -473,6 +471,18 @@ void ASF::File::FilePrivate::CodecListObject::parse(ASF::File *file, unsigned in
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// static members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool ASF::File::isSupported(IOStream *stream)
|
||||
{
|
||||
// An ASF file has to start with the designated GUID.
|
||||
|
||||
const ByteVector id = Utils::readHeader(stream, 16, false);
|
||||
return (id == headerGuid);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -616,9 +626,8 @@ void ASF::File::read()
|
||||
if(!isValid())
|
||||
return;
|
||||
|
||||
ByteVector guid = readBlock(16);
|
||||
if(guid != headerGuid) {
|
||||
debug("ASF: Not an ASF file.");
|
||||
if(readBlock(16) != headerGuid) {
|
||||
debug("ASF::File::read(): Not an ASF file.");
|
||||
setValid(false);
|
||||
return;
|
||||
}
|
||||
@ -639,8 +648,10 @@ void ASF::File::read()
|
||||
}
|
||||
seek(2, Current);
|
||||
|
||||
FilePrivate::FilePropertiesObject *filePropertiesObject = 0;
|
||||
FilePrivate::StreamPropertiesObject *streamPropertiesObject = 0;
|
||||
for(int i = 0; i < numObjects; i++) {
|
||||
guid = readBlock(16);
|
||||
const ByteVector guid = readBlock(16);
|
||||
if(guid.size() != 16) {
|
||||
setValid(false);
|
||||
break;
|
||||
@ -652,19 +663,24 @@ void ASF::File::read()
|
||||
}
|
||||
FilePrivate::BaseObject *obj;
|
||||
if(guid == filePropertiesGuid) {
|
||||
obj = new FilePrivate::FilePropertiesObject();
|
||||
filePropertiesObject = new FilePrivate::FilePropertiesObject();
|
||||
obj = filePropertiesObject;
|
||||
}
|
||||
else if(guid == streamPropertiesGuid) {
|
||||
obj = new FilePrivate::StreamPropertiesObject();
|
||||
streamPropertiesObject = new FilePrivate::StreamPropertiesObject();
|
||||
obj = streamPropertiesObject;
|
||||
}
|
||||
else if(guid == contentDescriptionGuid) {
|
||||
obj = new FilePrivate::ContentDescriptionObject();
|
||||
d->contentDescriptionObject = new FilePrivate::ContentDescriptionObject();
|
||||
obj = d->contentDescriptionObject;
|
||||
}
|
||||
else if(guid == extendedContentDescriptionGuid) {
|
||||
obj = new FilePrivate::ExtendedContentDescriptionObject();
|
||||
d->extendedContentDescriptionObject = new FilePrivate::ExtendedContentDescriptionObject();
|
||||
obj = d->extendedContentDescriptionObject;
|
||||
}
|
||||
else if(guid == headerExtensionGuid) {
|
||||
obj = new FilePrivate::HeaderExtensionObject();
|
||||
d->headerExtensionObject = new FilePrivate::HeaderExtensionObject();
|
||||
obj = d->headerExtensionObject;
|
||||
}
|
||||
else if(guid == codecListGuid) {
|
||||
obj = new FilePrivate::CodecListObject();
|
||||
@ -680,4 +696,10 @@ void ASF::File::read()
|
||||
obj->parse(this, size);
|
||||
d->objects.append(obj);
|
||||
}
|
||||
|
||||
if(!filePropertiesObject || !streamPropertiesObject) {
|
||||
debug("ASF::File::read(): Missing mandatory header objects.");
|
||||
setValid(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
9
3rdparty/taglib/asf/asffile.h
vendored
9
3rdparty/taglib/asf/asffile.h
vendored
@ -115,6 +115,15 @@ namespace TagLib {
|
||||
*/
|
||||
virtual bool save();
|
||||
|
||||
/*!
|
||||
* Returns whether or not the given \a stream can be opened as an ASF
|
||||
* file.
|
||||
*
|
||||
* \note This method is designed to do a quick check. The result may
|
||||
* not necessarily be correct.
|
||||
*/
|
||||
static bool isSupported(IOStream *stream);
|
||||
|
||||
private:
|
||||
void read();
|
||||
|
||||
|
6
3rdparty/taglib/asf/asftag.cpp
vendored
6
3rdparty/taglib/asf/asftag.cpp
vendored
@ -39,10 +39,10 @@ public:
|
||||
AttributeListMap attributeListMap;
|
||||
};
|
||||
|
||||
ASF::Tag::Tag()
|
||||
: TagLib::Tag()
|
||||
ASF::Tag::Tag() :
|
||||
TagLib::Tag(),
|
||||
d(new TagPrivate())
|
||||
{
|
||||
d = new TagPrivate;
|
||||
}
|
||||
|
||||
ASF::Tag::~Tag()
|
||||
|
123
3rdparty/taglib/audioproperties.cpp
vendored
123
3rdparty/taglib/audioproperties.cpp
vendored
@ -43,6 +43,39 @@
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
// This macro is a workaround for the fact that we can't add virtual functions.
|
||||
// Should be true virtual functions in taglib2.
|
||||
|
||||
#define VIRTUAL_FUNCTION_WORKAROUND(function_name, default_value) \
|
||||
if(dynamic_cast<const APE::Properties*>(this)) \
|
||||
return dynamic_cast<const APE::Properties*>(this)->function_name(); \
|
||||
else if(dynamic_cast<const ASF::Properties*>(this)) \
|
||||
return dynamic_cast<const ASF::Properties*>(this)->function_name(); \
|
||||
else if(dynamic_cast<const FLAC::Properties*>(this)) \
|
||||
return dynamic_cast<const FLAC::Properties*>(this)->function_name(); \
|
||||
else if(dynamic_cast<const MP4::Properties*>(this)) \
|
||||
return dynamic_cast<const MP4::Properties*>(this)->function_name(); \
|
||||
else if(dynamic_cast<const MPC::Properties*>(this)) \
|
||||
return dynamic_cast<const MPC::Properties*>(this)->function_name(); \
|
||||
else if(dynamic_cast<const MPEG::Properties*>(this)) \
|
||||
return dynamic_cast<const MPEG::Properties*>(this)->function_name(); \
|
||||
else if(dynamic_cast<const Ogg::Opus::Properties*>(this)) \
|
||||
return dynamic_cast<const Ogg::Opus::Properties*>(this)->function_name(); \
|
||||
else if(dynamic_cast<const Ogg::Speex::Properties*>(this)) \
|
||||
return dynamic_cast<const Ogg::Speex::Properties*>(this)->function_name(); \
|
||||
else if(dynamic_cast<const TrueAudio::Properties*>(this)) \
|
||||
return dynamic_cast<const TrueAudio::Properties*>(this)->function_name(); \
|
||||
else if(dynamic_cast<const RIFF::AIFF::Properties*>(this)) \
|
||||
return dynamic_cast<const RIFF::AIFF::Properties*>(this)->function_name(); \
|
||||
else if(dynamic_cast<const RIFF::WAV::Properties*>(this)) \
|
||||
return dynamic_cast<const RIFF::WAV::Properties*>(this)->function_name(); \
|
||||
else if(dynamic_cast<const Vorbis::Properties*>(this)) \
|
||||
return dynamic_cast<const Vorbis::Properties*>(this)->function_name(); \
|
||||
else if(dynamic_cast<const WavPack::Properties*>(this)) \
|
||||
return dynamic_cast<const WavPack::Properties*>(this)->function_name(); \
|
||||
else \
|
||||
return (default_value);
|
||||
|
||||
class AudioProperties::AudioPropertiesPrivate
|
||||
{
|
||||
|
||||
@ -59,98 +92,12 @@ AudioProperties::~AudioProperties()
|
||||
|
||||
int AudioProperties::lengthInSeconds() const
|
||||
{
|
||||
// This is an ugly workaround but we can't add a virtual function.
|
||||
// Should be virtual in taglib2.
|
||||
|
||||
if(dynamic_cast<const APE::Properties*>(this))
|
||||
return dynamic_cast<const APE::Properties*>(this)->lengthInSeconds();
|
||||
|
||||
else if(dynamic_cast<const ASF::Properties*>(this))
|
||||
return dynamic_cast<const ASF::Properties*>(this)->lengthInSeconds();
|
||||
|
||||
else if(dynamic_cast<const FLAC::Properties*>(this))
|
||||
return dynamic_cast<const FLAC::Properties*>(this)->lengthInSeconds();
|
||||
|
||||
else if(dynamic_cast<const MP4::Properties*>(this))
|
||||
return dynamic_cast<const MP4::Properties*>(this)->lengthInSeconds();
|
||||
|
||||
else if(dynamic_cast<const MPC::Properties*>(this))
|
||||
return dynamic_cast<const MPC::Properties*>(this)->lengthInSeconds();
|
||||
|
||||
else if(dynamic_cast<const MPEG::Properties*>(this))
|
||||
return dynamic_cast<const MPEG::Properties*>(this)->lengthInSeconds();
|
||||
|
||||
else if(dynamic_cast<const Ogg::Opus::Properties*>(this))
|
||||
return dynamic_cast<const Ogg::Opus::Properties*>(this)->lengthInSeconds();
|
||||
|
||||
else if(dynamic_cast<const Ogg::Speex::Properties*>(this))
|
||||
return dynamic_cast<const Ogg::Speex::Properties*>(this)->lengthInSeconds();
|
||||
|
||||
else if(dynamic_cast<const TrueAudio::Properties*>(this))
|
||||
return dynamic_cast<const TrueAudio::Properties*>(this)->lengthInSeconds();
|
||||
|
||||
else if (dynamic_cast<const RIFF::AIFF::Properties*>(this))
|
||||
return dynamic_cast<const RIFF::AIFF::Properties*>(this)->lengthInSeconds();
|
||||
|
||||
else if(dynamic_cast<const RIFF::WAV::Properties*>(this))
|
||||
return dynamic_cast<const RIFF::WAV::Properties*>(this)->lengthInSeconds();
|
||||
|
||||
else if(dynamic_cast<const Vorbis::Properties*>(this))
|
||||
return dynamic_cast<const Vorbis::Properties*>(this)->lengthInSeconds();
|
||||
|
||||
else if(dynamic_cast<const WavPack::Properties*>(this))
|
||||
return dynamic_cast<const WavPack::Properties*>(this)->lengthInSeconds();
|
||||
|
||||
else
|
||||
return 0;
|
||||
VIRTUAL_FUNCTION_WORKAROUND(lengthInSeconds, 0)
|
||||
}
|
||||
|
||||
int AudioProperties::lengthInMilliseconds() const
|
||||
{
|
||||
// This is an ugly workaround but we can't add a virtual function.
|
||||
// Should be virtual in taglib2.
|
||||
|
||||
if(dynamic_cast<const APE::Properties*>(this))
|
||||
return dynamic_cast<const APE::Properties*>(this)->lengthInMilliseconds();
|
||||
|
||||
else if(dynamic_cast<const ASF::Properties*>(this))
|
||||
return dynamic_cast<const ASF::Properties*>(this)->lengthInMilliseconds();
|
||||
|
||||
else if(dynamic_cast<const FLAC::Properties*>(this))
|
||||
return dynamic_cast<const FLAC::Properties*>(this)->lengthInMilliseconds();
|
||||
|
||||
else if(dynamic_cast<const MP4::Properties*>(this))
|
||||
return dynamic_cast<const MP4::Properties*>(this)->lengthInMilliseconds();
|
||||
|
||||
else if(dynamic_cast<const MPC::Properties*>(this))
|
||||
return dynamic_cast<const MPC::Properties*>(this)->lengthInMilliseconds();
|
||||
|
||||
else if(dynamic_cast<const MPEG::Properties*>(this))
|
||||
return dynamic_cast<const MPEG::Properties*>(this)->lengthInMilliseconds();
|
||||
|
||||
else if(dynamic_cast<const Ogg::Opus::Properties*>(this))
|
||||
return dynamic_cast<const Ogg::Opus::Properties*>(this)->lengthInMilliseconds();
|
||||
|
||||
else if(dynamic_cast<const Ogg::Speex::Properties*>(this))
|
||||
return dynamic_cast<const Ogg::Speex::Properties*>(this)->lengthInMilliseconds();
|
||||
|
||||
else if(dynamic_cast<const TrueAudio::Properties*>(this))
|
||||
return dynamic_cast<const TrueAudio::Properties*>(this)->lengthInMilliseconds();
|
||||
|
||||
else if(dynamic_cast<const RIFF::AIFF::Properties*>(this))
|
||||
return dynamic_cast<const RIFF::AIFF::Properties*>(this)->lengthInMilliseconds();
|
||||
|
||||
else if(dynamic_cast<const RIFF::WAV::Properties*>(this))
|
||||
return dynamic_cast<const RIFF::WAV::Properties*>(this)->lengthInMilliseconds();
|
||||
|
||||
else if(dynamic_cast<const Vorbis::Properties*>(this))
|
||||
return dynamic_cast<const Vorbis::Properties*>(this)->lengthInMilliseconds();
|
||||
|
||||
else if(dynamic_cast<const WavPack::Properties*>(this))
|
||||
return dynamic_cast<const WavPack::Properties*>(this)->lengthInMilliseconds();
|
||||
|
||||
else
|
||||
return 0;
|
||||
VIRTUAL_FUNCTION_WORKAROUND(lengthInMilliseconds, 0)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
279
3rdparty/taglib/fileref.cpp
vendored
279
3rdparty/taglib/fileref.cpp
vendored
@ -28,6 +28,7 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include <tfile.h>
|
||||
#include <tfilestream.h>
|
||||
#include <tstring.h>
|
||||
#include <tdebug.h>
|
||||
#include <trefcounter.h>
|
||||
@ -59,49 +60,14 @@ namespace
|
||||
typedef List<const FileRef::FileTypeResolver *> ResolverList;
|
||||
ResolverList fileTypeResolvers;
|
||||
|
||||
// Templatized internal functions. T should be String or IOStream*.
|
||||
// Detect the file type by user-defined resolvers.
|
||||
|
||||
template <typename T>
|
||||
FileName toFileName(T arg)
|
||||
{
|
||||
debug("FileRef::toFileName<T>(): This version should never be called.");
|
||||
return FileName(L"");
|
||||
}
|
||||
|
||||
template <>
|
||||
FileName toFileName<IOStream *>(IOStream *arg)
|
||||
{
|
||||
return arg->name();
|
||||
}
|
||||
|
||||
template <>
|
||||
FileName toFileName<FileName>(FileName arg)
|
||||
{
|
||||
return arg;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
File *resolveFileType(T arg, bool readProperties,
|
||||
AudioProperties::ReadStyle style)
|
||||
{
|
||||
debug("FileRef::resolveFileType<T>(): This version should never be called.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <>
|
||||
File *resolveFileType<IOStream *>(IOStream *arg, bool readProperties,
|
||||
AudioProperties::ReadStyle style)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <>
|
||||
File *resolveFileType<FileName>(FileName arg, bool readProperties,
|
||||
AudioProperties::ReadStyle style)
|
||||
File *detectByResolvers(FileName fileName, bool readAudioProperties,
|
||||
AudioProperties::ReadStyle audioPropertiesStyle)
|
||||
{
|
||||
ResolverList::ConstIterator it = fileTypeResolvers.begin();
|
||||
for(; it != fileTypeResolvers.end(); ++it) {
|
||||
File *file = (*it)->createFile(arg, readProperties, style);
|
||||
File *file = (*it)->createFile(fileName, readAudioProperties, audioPropertiesStyle);
|
||||
if(file)
|
||||
return file;
|
||||
}
|
||||
@ -109,18 +75,15 @@ namespace
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
File* createInternal(T arg, bool readAudioProperties,
|
||||
AudioProperties::ReadStyle audioPropertiesStyle)
|
||||
{
|
||||
File *file = resolveFileType(arg, readAudioProperties, audioPropertiesStyle);
|
||||
if(file)
|
||||
return file;
|
||||
// Detect the file type based on the file extension.
|
||||
|
||||
File* detectByExtension(IOStream *stream, bool readAudioProperties,
|
||||
AudioProperties::ReadStyle audioPropertiesStyle)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
const String s = toFileName(arg).toString();
|
||||
const String s = stream->name().toString();
|
||||
#else
|
||||
const String s(toFileName(arg));
|
||||
const String s(stream->name());
|
||||
#endif
|
||||
|
||||
String ext;
|
||||
@ -135,49 +98,163 @@ namespace
|
||||
if(ext.isEmpty())
|
||||
return 0;
|
||||
|
||||
// .oga can be any audio in the Ogg container. So leave it to content-based detection.
|
||||
|
||||
if(ext == "MP3")
|
||||
return new MPEG::File(arg, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
|
||||
return new MPEG::File(stream, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "OGG")
|
||||
return new Ogg::Vorbis::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
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);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
// isSupported() only does a quick check, so double check the file here.
|
||||
|
||||
if(file) {
|
||||
if(file->isValid())
|
||||
return file;
|
||||
else
|
||||
delete file;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 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 0;
|
||||
|
||||
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 = new Ogg::FLAC::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
File *file = new Ogg::FLAC::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||
if(file->isValid())
|
||||
return file;
|
||||
delete file;
|
||||
return new Ogg::Vorbis::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
return new Ogg::Vorbis::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||
}
|
||||
if(ext == "FLAC")
|
||||
return new FLAC::File(arg, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
|
||||
return new FLAC::File(fileName, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "MPC")
|
||||
return new MPC::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
return new MPC::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "WV")
|
||||
return new WavPack::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
return new WavPack::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "SPX")
|
||||
return new Ogg::Speex::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
return new Ogg::Speex::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "OPUS")
|
||||
return new Ogg::Opus::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
return new Ogg::Opus::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "TTA")
|
||||
return new TrueAudio::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
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(arg, readAudioProperties, audioPropertiesStyle);
|
||||
return new MP4::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "WMA" || ext == "ASF")
|
||||
return new ASF::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
return new ASF::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "AIF" || ext == "AIFF" || ext == "AFC" || ext == "AIFC")
|
||||
return new RIFF::AIFF::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
return new RIFF::AIFF::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "WAV")
|
||||
return new RIFF::WAV::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
return new RIFF::WAV::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "APE")
|
||||
return new APE::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
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(arg, readAudioProperties, audioPropertiesStyle);
|
||||
return new Mod::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "S3M")
|
||||
return new S3M::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
return new S3M::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "IT")
|
||||
return new IT::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
return new IT::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||
if(ext == "XM")
|
||||
return new XM::File(arg, readAudioProperties, audioPropertiesStyle);
|
||||
return new XM::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -186,15 +263,18 @@ namespace
|
||||
class FileRef::FileRefPrivate : public RefCounter
|
||||
{
|
||||
public:
|
||||
FileRefPrivate(File *f) :
|
||||
FileRefPrivate() :
|
||||
RefCounter(),
|
||||
file(f) {}
|
||||
file(0),
|
||||
stream(0) {}
|
||||
|
||||
~FileRefPrivate() {
|
||||
delete file;
|
||||
delete stream;
|
||||
}
|
||||
|
||||
File *file;
|
||||
File *file;
|
||||
IOStream *stream;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -202,24 +282,27 @@ public:
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FileRef::FileRef() :
|
||||
d(new FileRefPrivate(0))
|
||||
d(new FileRefPrivate())
|
||||
{
|
||||
}
|
||||
|
||||
FileRef::FileRef(FileName fileName, bool readAudioProperties,
|
||||
AudioProperties::ReadStyle audioPropertiesStyle) :
|
||||
d(new FileRefPrivate(createInternal(fileName, readAudioProperties, audioPropertiesStyle)))
|
||||
d(new FileRefPrivate())
|
||||
{
|
||||
parse(fileName, readAudioProperties, audioPropertiesStyle);
|
||||
}
|
||||
|
||||
FileRef::FileRef(IOStream* stream, bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle) :
|
||||
d(new FileRefPrivate(createInternal(stream, readAudioProperties, audioPropertiesStyle)))
|
||||
d(new FileRefPrivate())
|
||||
{
|
||||
parse(stream, readAudioProperties, audioPropertiesStyle);
|
||||
}
|
||||
|
||||
FileRef::FileRef(File *file) :
|
||||
d(new FileRefPrivate(file))
|
||||
d(new FileRefPrivate())
|
||||
{
|
||||
d->file = file;
|
||||
}
|
||||
|
||||
FileRef::FileRef(const FileRef &ref) :
|
||||
@ -341,3 +424,51 @@ File *FileRef::create(FileName fileName, bool readAudioProperties,
|
||||
{
|
||||
return createInternal(fileName, readAudioProperties, audioPropertiesStyle);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void FileRef::parse(FileName fileName, bool readAudioProperties,
|
||||
AudioProperties::ReadStyle audioPropertiesStyle)
|
||||
{
|
||||
// Try user-defined resolvers.
|
||||
|
||||
d->file = detectByResolvers(fileName, readAudioProperties, audioPropertiesStyle);
|
||||
if(d->file)
|
||||
return;
|
||||
|
||||
// Try to resolve file types based on the file extension.
|
||||
|
||||
d->stream = new FileStream(fileName);
|
||||
d->file = detectByExtension(d->stream, readAudioProperties, audioPropertiesStyle);
|
||||
if(d->file)
|
||||
return;
|
||||
|
||||
// At last, try to resolve file types based on the actual content.
|
||||
|
||||
d->file = detectByContent(d->stream, readAudioProperties, audioPropertiesStyle);
|
||||
if(d->file)
|
||||
return;
|
||||
|
||||
// Stream have to be closed here if failed to resolve file types.
|
||||
|
||||
delete d->stream;
|
||||
d->stream = 0;
|
||||
}
|
||||
|
||||
void FileRef::parse(IOStream *stream, bool readAudioProperties,
|
||||
AudioProperties::ReadStyle audioPropertiesStyle)
|
||||
{
|
||||
// User-defined resolvers won't work with a stream.
|
||||
|
||||
// Try to resolve file types based on the file extension.
|
||||
|
||||
d->file = detectByExtension(stream, readAudioProperties, audioPropertiesStyle);
|
||||
if(d->file)
|
||||
return;
|
||||
|
||||
// At last, try to resolve file types based on the actual content of the file.
|
||||
|
||||
d->file = detectByContent(stream, readAudioProperties, audioPropertiesStyle);
|
||||
}
|
||||
|
4
3rdparty/taglib/fileref.h
vendored
4
3rdparty/taglib/fileref.h
vendored
@ -274,8 +274,10 @@ namespace TagLib {
|
||||
bool readAudioProperties = true,
|
||||
AudioProperties::ReadStyle audioPropertiesStyle = AudioProperties::Average);
|
||||
|
||||
|
||||
private:
|
||||
void parse(FileName fileName, bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle);
|
||||
void parse(IOStream *stream, bool readAudioProperties, AudioProperties::ReadStyle audioPropertiesStyle);
|
||||
|
||||
class FileRefPrivate;
|
||||
FileRefPrivate *d;
|
||||
};
|
||||
|
27
3rdparty/taglib/flac/flacfile.cpp
vendored
27
3rdparty/taglib/flac/flacfile.cpp
vendored
@ -95,6 +95,18 @@ public:
|
||||
bool scanned;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// static members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool FLAC::File::isSupported(IOStream *stream)
|
||||
{
|
||||
// A FLAC file has an ID "fLaC" somewhere. An ID3v2 tag may precede.
|
||||
|
||||
const ByteVector buffer = Utils::readHeader(stream, bufferSize(), true);
|
||||
return (buffer.find("fLaC") >= 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -168,8 +180,8 @@ bool FLAC::File::save()
|
||||
}
|
||||
|
||||
// Create new vorbis comments
|
||||
|
||||
Tag::duplicate(&d->tag, xiphComment(true), false);
|
||||
if(!hasXiphComment())
|
||||
Tag::duplicate(&d->tag, xiphComment(true), false);
|
||||
|
||||
d->xiphCommentData = xiphComment()->render(false);
|
||||
|
||||
@ -198,7 +210,6 @@ bool FLAC::File::save()
|
||||
}
|
||||
|
||||
// Compute the amount of padding, and append that to data.
|
||||
// TODO: Should be calculated in offset_t in taglib2.
|
||||
|
||||
long originalLength = d->streamStart - d->flacStart;
|
||||
long paddingLength = originalLength - data.size() - 4;
|
||||
@ -298,11 +309,7 @@ bool FLAC::File::save()
|
||||
|
||||
ID3v2::Tag *FLAC::File::ID3v2Tag(bool create)
|
||||
{
|
||||
if(!create || d->tag[FlacID3v2Index])
|
||||
return static_cast<ID3v2::Tag *>(d->tag[FlacID3v2Index]);
|
||||
|
||||
d->tag.set(FlacID3v2Index, new ID3v2::Tag);
|
||||
return static_cast<ID3v2::Tag *>(d->tag[FlacID3v2Index]);
|
||||
return d->tag.access<ID3v2::Tag>(FlacID3v2Index, create);
|
||||
}
|
||||
|
||||
ID3v1::Tag *FLAC::File::ID3v1Tag(bool create)
|
||||
@ -507,7 +514,9 @@ void FLAC::File::scan()
|
||||
return;
|
||||
}
|
||||
|
||||
if(blockLength == 0 && blockType != MetadataBlock::Padding) {
|
||||
if(blockLength == 0
|
||||
&& blockType != MetadataBlock::Padding && blockType != MetadataBlock::SeekTable)
|
||||
{
|
||||
debug("FLAC::File::scan() -- Zero-sized metadata block found");
|
||||
setValid(false);
|
||||
return;
|
||||
|
9
3rdparty/taglib/flac/flacfile.h
vendored
9
3rdparty/taglib/flac/flacfile.h
vendored
@ -318,6 +318,15 @@ namespace TagLib {
|
||||
*/
|
||||
bool hasID3v2Tag() const;
|
||||
|
||||
/*!
|
||||
* Returns whether or not the given \a stream can be opened as a FLAC
|
||||
* file.
|
||||
*
|
||||
* \note This method is designed to do a quick check. The result may
|
||||
* not necessarily be correct.
|
||||
*/
|
||||
static bool isSupported(IOStream *stream);
|
||||
|
||||
private:
|
||||
File(const File &);
|
||||
File &operator=(const File &);
|
||||
|
8
3rdparty/taglib/flac/flacpicture.cpp
vendored
8
3rdparty/taglib/flac/flacpicture.cpp
vendored
@ -50,14 +50,14 @@ public:
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -39,11 +39,10 @@ public:
|
||||
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;
|
||||
//debug(String(data.toHex()));
|
||||
d->data = data;
|
||||
}
|
||||
|
||||
|
2
3rdparty/taglib/it/itproperties.cpp
vendored
2
3rdparty/taglib/it/itproperties.cpp
vendored
@ -70,7 +70,7 @@ public:
|
||||
|
||||
IT::Properties::Properties(AudioProperties::ReadStyle propertiesStyle) :
|
||||
AudioProperties(propertiesStyle),
|
||||
d(new PropertiesPrivate)
|
||||
d(new PropertiesPrivate())
|
||||
{
|
||||
}
|
||||
|
||||
|
2
3rdparty/taglib/mod/modproperties.cpp
vendored
2
3rdparty/taglib/mod/modproperties.cpp
vendored
@ -46,7 +46,7 @@ public:
|
||||
|
||||
Mod::Properties::Properties(AudioProperties::ReadStyle propertiesStyle) :
|
||||
AudioProperties(propertiesStyle),
|
||||
d(new PropertiesPrivate)
|
||||
d(new PropertiesPrivate())
|
||||
{
|
||||
}
|
||||
|
||||
|
5
3rdparty/taglib/mod/modtag.cpp
vendored
5
3rdparty/taglib/mod/modtag.cpp
vendored
@ -43,9 +43,10 @@ public:
|
||||
String trackerName;
|
||||
};
|
||||
|
||||
Mod::Tag::Tag() : TagLib::Tag()
|
||||
Mod::Tag::Tag() :
|
||||
TagLib::Tag(),
|
||||
d(new TagPrivate())
|
||||
{
|
||||
d = new TagPrivate;
|
||||
}
|
||||
|
||||
Mod::Tag::~Tag()
|
||||
|
25
3rdparty/taglib/mp4/mp4atom.cpp
vendored
25
3rdparty/taglib/mp4/mp4atom.cpp
vendored
@ -54,24 +54,25 @@ MP4::Atom::Atom(File *file)
|
||||
|
||||
length = header.toUInt();
|
||||
|
||||
if(length == 1) {
|
||||
if(length == 0) {
|
||||
// The last atom which extends to the end of the file.
|
||||
length = file->length() - offset;
|
||||
}
|
||||
else if(length == 1) {
|
||||
// The atom has a 64-bit length.
|
||||
const long long longLength = file->readBlock(8).toLongLong();
|
||||
if(sizeof(long) == sizeof(long long)) {
|
||||
if(longLength <= LONG_MAX) {
|
||||
// The actual length fits in long. That's always the case if long is 64-bit.
|
||||
length = static_cast<long>(longLength);
|
||||
}
|
||||
else {
|
||||
if(longLength <= LONG_MAX) {
|
||||
// The atom has a 64-bit length, but it's actually a 31-bit value
|
||||
length = static_cast<long>(longLength);
|
||||
}
|
||||
else {
|
||||
debug("MP4: 64-bit atoms are not supported");
|
||||
length = 0;
|
||||
file->seek(0, File::End);
|
||||
return;
|
||||
}
|
||||
debug("MP4: 64-bit atoms are not supported");
|
||||
length = 0;
|
||||
file->seek(0, File::End);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(length < 8) {
|
||||
debug("MP4: Invalid atom size");
|
||||
length = 0;
|
||||
|
18
3rdparty/taglib/mp4/mp4file.cpp
vendored
18
3rdparty/taglib/mp4/mp4file.cpp
vendored
@ -26,6 +26,8 @@
|
||||
#include <tdebug.h>
|
||||
#include <tstring.h>
|
||||
#include <tpropertymap.h>
|
||||
#include <tagutils.h>
|
||||
|
||||
#include "mp4atom.h"
|
||||
#include "mp4tag.h"
|
||||
#include "mp4file.h"
|
||||
@ -69,6 +71,22 @@ public:
|
||||
MP4::Properties *properties;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// static members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool MP4::File::isSupported(IOStream *stream)
|
||||
{
|
||||
// An MP4 file has to have an "ftyp" box first.
|
||||
|
||||
const ByteVector id = Utils::readHeader(stream, 8, false);
|
||||
return id.containsAt("ftyp", 4);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
MP4::File::File(FileName file, bool readProperties, AudioProperties::ReadStyle) :
|
||||
TagLib::File(file),
|
||||
d(new FilePrivate())
|
||||
|
9
3rdparty/taglib/mp4/mp4file.h
vendored
9
3rdparty/taglib/mp4/mp4file.h
vendored
@ -120,6 +120,15 @@ namespace TagLib {
|
||||
*/
|
||||
bool hasMP4Tag() const;
|
||||
|
||||
/*!
|
||||
* Returns whether or not the given \a stream can be opened as an ASF
|
||||
* file.
|
||||
*
|
||||
* \note This method is designed to do a quick check. The result may
|
||||
* not necessarily be correct.
|
||||
*/
|
||||
static bool isSupported(IOStream *stream);
|
||||
|
||||
private:
|
||||
void read(bool readProperties);
|
||||
|
||||
|
38
3rdparty/taglib/mp4/mp4tag.cpp
vendored
38
3rdparty/taglib/mp4/mp4tag.cpp
vendored
@ -71,14 +71,15 @@ MP4::Tag::Tag(TagLib::File *file, MP4::Atoms *atoms) :
|
||||
parseIntPair(atom);
|
||||
}
|
||||
else if(atom->name == "cpil" || atom->name == "pgap" || atom->name == "pcst" ||
|
||||
atom->name == "hdvd") {
|
||||
atom->name == "hdvd" || atom->name == "shwm") {
|
||||
parseBool(atom);
|
||||
}
|
||||
else if(atom->name == "tmpo") {
|
||||
else if(atom->name == "tmpo" || atom->name == "rate" || atom->name == "\251mvi" || atom->name == "\251mvc") {
|
||||
parseInt(atom);
|
||||
}
|
||||
else if(atom->name == "tvsn" || atom->name == "tves" || atom->name == "cnID" ||
|
||||
atom->name == "sfID" || atom->name == "atID" || atom->name == "geID") {
|
||||
atom->name == "sfID" || atom->name == "atID" || atom->name == "geID" ||
|
||||
atom->name == "cmID") {
|
||||
parseUInt(atom);
|
||||
}
|
||||
else if(atom->name == "plID") {
|
||||
@ -93,6 +94,9 @@ MP4::Tag::Tag(TagLib::File *file, MP4::Atoms *atoms) :
|
||||
else if(atom->name == "covr") {
|
||||
parseCovr(atom);
|
||||
}
|
||||
else if(atom->name == "purl" || atom->name == "egid") {
|
||||
parseText(atom, -1);
|
||||
}
|
||||
else {
|
||||
parseText(atom);
|
||||
}
|
||||
@ -472,14 +476,16 @@ MP4::Tag::save()
|
||||
else if(name == "disk") {
|
||||
data.append(renderIntPairNoTrailing(name.data(String::Latin1), it->second));
|
||||
}
|
||||
else if(name == "cpil" || name == "pgap" || name == "pcst" || name == "hdvd") {
|
||||
else if(name == "cpil" || name == "pgap" || name == "pcst" || name == "hdvd" ||
|
||||
name == "shwm") {
|
||||
data.append(renderBool(name.data(String::Latin1), it->second));
|
||||
}
|
||||
else if(name == "tmpo") {
|
||||
else if(name == "tmpo" || name == "rate" || name == "\251mvi" || name == "\251mvc") {
|
||||
data.append(renderInt(name.data(String::Latin1), it->second));
|
||||
}
|
||||
else if(name == "tvsn" || name == "tves" || name == "cnID" ||
|
||||
name == "sfID" || name == "atID" || name == "geID") {
|
||||
name == "sfID" || name == "atID" || name == "geID" ||
|
||||
name == "cmID") {
|
||||
data.append(renderUInt(name.data(String::Latin1), it->second));
|
||||
}
|
||||
else if(name == "plID") {
|
||||
@ -491,6 +497,9 @@ MP4::Tag::save()
|
||||
else if(name == "covr") {
|
||||
data.append(renderCovr(name.data(String::Latin1), it->second));
|
||||
}
|
||||
else if(name == "purl" || name == "egid") {
|
||||
data.append(renderText(name.data(String::Latin1), it->second, TypeImplicit));
|
||||
}
|
||||
else if(name.size() == 4){
|
||||
data.append(renderText(name.data(String::Latin1), it->second));
|
||||
}
|
||||
@ -844,6 +853,11 @@ namespace
|
||||
{ "sonm", "TITLESORT" },
|
||||
{ "soco", "COMPOSERSORT" },
|
||||
{ "sosn", "SHOWSORT" },
|
||||
{ "shwm", "SHOWWORKMOVEMENT" },
|
||||
{ "\251wrk", "WORK" },
|
||||
{ "\251mvn", "MOVEMENTNAME" },
|
||||
{ "\251mvi", "MOVEMENTNUMBER" },
|
||||
{ "\251mvc", "MOVEMENTCOUNT" },
|
||||
{ "----:com.apple.iTunes:MusicBrainz Track Id", "MUSICBRAINZ_TRACKID" },
|
||||
{ "----:com.apple.iTunes:MusicBrainz Artist Id", "MUSICBRAINZ_ARTISTID" },
|
||||
{ "----:com.apple.iTunes:MusicBrainz Album Id", "MUSICBRAINZ_ALBUMID" },
|
||||
@ -897,10 +911,10 @@ PropertyMap MP4::Tag::properties() const
|
||||
}
|
||||
props[key] = value;
|
||||
}
|
||||
else if(key == "BPM") {
|
||||
else if(key == "BPM" || key == "MOVEMENTNUMBER" || key == "MOVEMENTCOUNT") {
|
||||
props[key] = String::number(it->second.toInt());
|
||||
}
|
||||
else if(key == "COMPILATION") {
|
||||
else if(key == "COMPILATION" || key == "SHOWWORKMOVEMENT") {
|
||||
props[key] = String::number(it->second.toBool());
|
||||
}
|
||||
else {
|
||||
@ -942,21 +956,21 @@ PropertyMap MP4::Tag::setProperties(const PropertyMap &props)
|
||||
if(reverseKeyMap.contains(it->first)) {
|
||||
String name = reverseKeyMap[it->first];
|
||||
if((it->first == "TRACKNUMBER" || it->first == "DISCNUMBER") && !it->second.isEmpty()) {
|
||||
int first = 0, second = 0;
|
||||
StringList parts = StringList::split(it->second.front(), "/");
|
||||
if(!parts.isEmpty()) {
|
||||
first = parts[0].toInt();
|
||||
int first = parts[0].toInt();
|
||||
int second = 0;
|
||||
if(parts.size() > 1) {
|
||||
second = parts[1].toInt();
|
||||
}
|
||||
d->items[name] = MP4::Item(first, second);
|
||||
}
|
||||
}
|
||||
else if(it->first == "BPM" && !it->second.isEmpty()) {
|
||||
else if((it->first == "BPM" || it->first == "MOVEMENTNUMBER" || it->first == "MOVEMENTCOUNT") && !it->second.isEmpty()) {
|
||||
int value = it->second.front().toInt();
|
||||
d->items[name] = MP4::Item(value);
|
||||
}
|
||||
else if(it->first == "COMPILATION" && !it->second.isEmpty()) {
|
||||
else if((it->first == "COMPILATION" || it->first == "SHOWWORKMOVEMENT") && !it->second.isEmpty()) {
|
||||
bool value = (it->second.front().toInt() != 0);
|
||||
d->items[name] = MP4::Item(value);
|
||||
}
|
||||
|
13
3rdparty/taglib/mpc/mpcfile.cpp
vendored
13
3rdparty/taglib/mpc/mpcfile.cpp
vendored
@ -75,6 +75,19 @@ public:
|
||||
Properties *properties;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// static members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool MPC::File::isSupported(IOStream *stream)
|
||||
{
|
||||
// A newer MPC file has to start with "MPCK" or "MP+", but older files don't
|
||||
// have keys to do a quick check.
|
||||
|
||||
const ByteVector id = Utils::readHeader(stream, 4, false);
|
||||
return (id == "MPCK" || id.startsWith("MP+"));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
9
3rdparty/taglib/mpc/mpcfile.h
vendored
9
3rdparty/taglib/mpc/mpcfile.h
vendored
@ -214,6 +214,15 @@ namespace TagLib {
|
||||
*/
|
||||
bool hasAPETag() const;
|
||||
|
||||
/*!
|
||||
* Returns whether or not the given \a stream can be opened as an MPC
|
||||
* file.
|
||||
*
|
||||
* \note This method is designed to do a quick check. The result may
|
||||
* not necessarily be correct.
|
||||
*/
|
||||
static bool isSupported(IOStream *stream);
|
||||
|
||||
private:
|
||||
File(const File &);
|
||||
File &operator=(const File &);
|
||||
|
@ -48,14 +48,16 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AttachedPictureFrame::AttachedPictureFrame() : Frame("APIC")
|
||||
AttachedPictureFrame::AttachedPictureFrame() :
|
||||
Frame("APIC"),
|
||||
d(new AttachedPictureFramePrivate())
|
||||
{
|
||||
d = new AttachedPictureFramePrivate;
|
||||
}
|
||||
|
||||
AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data) : Frame(data)
|
||||
AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data) :
|
||||
Frame(data),
|
||||
d(new AttachedPictureFramePrivate())
|
||||
{
|
||||
d = new AttachedPictureFramePrivate;
|
||||
setData(data);
|
||||
}
|
||||
|
||||
@ -169,9 +171,10 @@ ByteVector AttachedPictureFrame::renderFields() const
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data, Header *h) : Frame(h)
|
||||
AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data, Header *h) :
|
||||
Frame(h),
|
||||
d(new AttachedPictureFramePrivate())
|
||||
{
|
||||
d = new AttachedPictureFramePrivate;
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,11 @@ class ChapterFrame::ChapterFramePrivate
|
||||
{
|
||||
public:
|
||||
ChapterFramePrivate() :
|
||||
tagHeader(0)
|
||||
tagHeader(0),
|
||||
startTime(0),
|
||||
endTime(0),
|
||||
startOffset(0),
|
||||
endOffset(0)
|
||||
{
|
||||
embeddedFrameList.setAutoDelete(true);
|
||||
}
|
||||
@ -57,9 +61,9 @@ public:
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ChapterFrame::ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data) :
|
||||
ID3v2::Frame(data)
|
||||
ID3v2::Frame(data),
|
||||
d(new ChapterFramePrivate())
|
||||
{
|
||||
d = new ChapterFramePrivate;
|
||||
d->tagHeader = tagHeader;
|
||||
setData(data);
|
||||
}
|
||||
@ -68,10 +72,9 @@ ChapterFrame::ChapterFrame(const ByteVector &elementID,
|
||||
unsigned int startTime, unsigned int endTime,
|
||||
unsigned int startOffset, unsigned int endOffset,
|
||||
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
|
||||
// specifically include the null byte.
|
||||
|
||||
@ -198,7 +201,7 @@ String ChapterFrame::toString() const
|
||||
s += ", start offset: " + String::number(d->startOffset);
|
||||
|
||||
if(d->endOffset != 0xFFFFFFFF)
|
||||
s += ", start offset: " + String::number(d->endOffset);
|
||||
s += ", end offset: " + String::number(d->endOffset);
|
||||
|
||||
if(!d->embeddedFrameList.isEmpty()) {
|
||||
StringList frameIDs;
|
||||
@ -298,9 +301,9 @@ ByteVector ChapterFrame::renderFields() const
|
||||
}
|
||||
|
||||
ChapterFrame::ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data, Header *h) :
|
||||
Frame(h)
|
||||
Frame(h),
|
||||
d(new ChapterFramePrivate())
|
||||
{
|
||||
d = new ChapterFramePrivate;
|
||||
d->tagHeader = tagHeader;
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
@ -48,15 +48,17 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CommentsFrame::CommentsFrame(String::Type encoding) : Frame("COMM")
|
||||
CommentsFrame::CommentsFrame(String::Type encoding) :
|
||||
Frame("COMM"),
|
||||
d(new CommentsFramePrivate())
|
||||
{
|
||||
d = new CommentsFramePrivate;
|
||||
d->textEncoding = encoding;
|
||||
}
|
||||
|
||||
CommentsFrame::CommentsFrame(const ByteVector &data) : Frame(data)
|
||||
CommentsFrame::CommentsFrame(const ByteVector &data) :
|
||||
Frame(data),
|
||||
d(new CommentsFramePrivate())
|
||||
{
|
||||
d = new CommentsFramePrivate;
|
||||
setData(data);
|
||||
}
|
||||
|
||||
@ -188,8 +190,9 @@ ByteVector CommentsFrame::renderFields() const
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CommentsFrame::CommentsFrame(const ByteVector &data, Header *h) : Frame(h)
|
||||
CommentsFrame::CommentsFrame(const ByteVector &data, Header *h) :
|
||||
Frame(h),
|
||||
d(new CommentsFramePrivate())
|
||||
{
|
||||
d = new CommentsFramePrivate();
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
@ -46,15 +46,15 @@ public:
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
EventTimingCodesFrame::EventTimingCodesFrame() :
|
||||
Frame("ETCO")
|
||||
Frame("ETCO"),
|
||||
d(new EventTimingCodesFramePrivate())
|
||||
{
|
||||
d = new EventTimingCodesFramePrivate;
|
||||
}
|
||||
|
||||
EventTimingCodesFrame::EventTimingCodesFrame(const ByteVector &data) :
|
||||
Frame(data)
|
||||
Frame(data),
|
||||
d(new EventTimingCodesFramePrivate())
|
||||
{
|
||||
d = new EventTimingCodesFramePrivate;
|
||||
setData(data);
|
||||
}
|
||||
|
||||
@ -136,9 +136,9 @@ ByteVector EventTimingCodesFrame::renderFields() const
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
EventTimingCodesFrame::EventTimingCodesFrame(const ByteVector &data, Header *h)
|
||||
: Frame(h)
|
||||
EventTimingCodesFrame::EventTimingCodesFrame(const ByteVector &data, Header *h) :
|
||||
Frame(h),
|
||||
d(new EventTimingCodesFramePrivate())
|
||||
{
|
||||
d = new EventTimingCodesFramePrivate();
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
@ -50,14 +50,16 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame() : Frame("GEOB")
|
||||
GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame() :
|
||||
Frame("GEOB"),
|
||||
d(new GeneralEncapsulatedObjectFramePrivate())
|
||||
{
|
||||
d = new GeneralEncapsulatedObjectFramePrivate;
|
||||
}
|
||||
|
||||
GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame(const ByteVector &data) : Frame(data)
|
||||
GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame(const ByteVector &data) :
|
||||
Frame(data),
|
||||
d(new GeneralEncapsulatedObjectFramePrivate())
|
||||
{
|
||||
d = new GeneralEncapsulatedObjectFramePrivate;
|
||||
setData(data);
|
||||
}
|
||||
|
||||
@ -177,8 +179,9 @@ ByteVector GeneralEncapsulatedObjectFrame::renderFields() const
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame(const ByteVector &data, Header *h) : Frame(h)
|
||||
GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame(const ByteVector &data, Header *h) :
|
||||
Frame(h),
|
||||
d(new GeneralEncapsulatedObjectFramePrivate())
|
||||
{
|
||||
d = new GeneralEncapsulatedObjectFramePrivate;
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
@ -45,15 +45,17 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
OwnershipFrame::OwnershipFrame(String::Type encoding) : Frame("OWNE")
|
||||
OwnershipFrame::OwnershipFrame(String::Type encoding) :
|
||||
Frame("OWNE"),
|
||||
d(new OwnershipFramePrivate())
|
||||
{
|
||||
d = new OwnershipFramePrivate;
|
||||
d->textEncoding = encoding;
|
||||
}
|
||||
|
||||
OwnershipFrame::OwnershipFrame(const ByteVector &data) : Frame(data)
|
||||
OwnershipFrame::OwnershipFrame(const ByteVector &data) :
|
||||
Frame(data),
|
||||
d(new OwnershipFramePrivate())
|
||||
{
|
||||
d = new OwnershipFramePrivate;
|
||||
setData(data);
|
||||
}
|
||||
|
||||
@ -161,8 +163,9 @@ ByteVector OwnershipFrame::renderFields() const
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
OwnershipFrame::OwnershipFrame(const ByteVector &data, Header *h) : Frame(h)
|
||||
OwnershipFrame::OwnershipFrame(const ByteVector &data, Header *h) :
|
||||
Frame(h),
|
||||
d(new OwnershipFramePrivate())
|
||||
{
|
||||
d = new OwnershipFramePrivate;
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
@ -38,9 +38,10 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PodcastFrame::PodcastFrame() : Frame("PCST")
|
||||
PodcastFrame::PodcastFrame() :
|
||||
Frame("PCST"),
|
||||
d(new PodcastFramePrivate())
|
||||
{
|
||||
d = new PodcastFramePrivate;
|
||||
d->fieldData = ByteVector(4, '\0');
|
||||
}
|
||||
|
||||
@ -72,8 +73,9 @@ ByteVector PodcastFrame::renderFields() const
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PodcastFrame::PodcastFrame(const ByteVector &data, Header *h) : Frame(h)
|
||||
PodcastFrame::PodcastFrame(const ByteVector &data, Header *h) :
|
||||
Frame(h),
|
||||
d(new PodcastFramePrivate())
|
||||
{
|
||||
d = new PodcastFramePrivate;
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
@ -43,14 +43,16 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PopularimeterFrame::PopularimeterFrame() : Frame("POPM")
|
||||
PopularimeterFrame::PopularimeterFrame() :
|
||||
Frame("POPM"),
|
||||
d(new PopularimeterFramePrivate())
|
||||
{
|
||||
d = new PopularimeterFramePrivate;
|
||||
}
|
||||
|
||||
PopularimeterFrame::PopularimeterFrame(const ByteVector &data) : Frame(data)
|
||||
PopularimeterFrame::PopularimeterFrame(const ByteVector &data) :
|
||||
Frame(data),
|
||||
d(new PopularimeterFramePrivate())
|
||||
{
|
||||
d = new PopularimeterFramePrivate;
|
||||
setData(data);
|
||||
}
|
||||
|
||||
@ -130,8 +132,9 @@ ByteVector PopularimeterFrame::renderFields() const
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PopularimeterFrame::PopularimeterFrame(const ByteVector &data, Header *h) : Frame(h)
|
||||
PopularimeterFrame::PopularimeterFrame(const ByteVector &data, Header *h) :
|
||||
Frame(h),
|
||||
d(new PopularimeterFramePrivate())
|
||||
{
|
||||
d = new PopularimeterFramePrivate;
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
@ -45,14 +45,16 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PrivateFrame::PrivateFrame() : Frame("PRIV")
|
||||
PrivateFrame::PrivateFrame() :
|
||||
Frame("PRIV"),
|
||||
d(new PrivateFramePrivate())
|
||||
{
|
||||
d = new PrivateFramePrivate;
|
||||
}
|
||||
|
||||
PrivateFrame::PrivateFrame(const ByteVector &data) : Frame(data)
|
||||
PrivateFrame::PrivateFrame(const ByteVector &data) :
|
||||
Frame(data),
|
||||
d(new PrivateFramePrivate())
|
||||
{
|
||||
d = new PrivateFramePrivate;
|
||||
setData(data);
|
||||
}
|
||||
|
||||
@ -121,8 +123,9 @@ ByteVector PrivateFrame::renderFields() const
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PrivateFrame::PrivateFrame(const ByteVector &data, Header *h) : Frame(h)
|
||||
PrivateFrame::PrivateFrame(const ByteVector &data, Header *h) :
|
||||
Frame(h),
|
||||
d(new PrivateFramePrivate())
|
||||
{
|
||||
d = new PrivateFramePrivate();
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
@ -51,14 +51,16 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
RelativeVolumeFrame::RelativeVolumeFrame() : Frame("RVA2")
|
||||
RelativeVolumeFrame::RelativeVolumeFrame() :
|
||||
Frame("RVA2"),
|
||||
d(new RelativeVolumeFramePrivate())
|
||||
{
|
||||
d = new RelativeVolumeFramePrivate;
|
||||
}
|
||||
|
||||
RelativeVolumeFrame::RelativeVolumeFrame(const ByteVector &data) : Frame(data)
|
||||
RelativeVolumeFrame::RelativeVolumeFrame(const ByteVector &data) :
|
||||
Frame(data),
|
||||
d(new RelativeVolumeFramePrivate())
|
||||
{
|
||||
d = new RelativeVolumeFramePrivate;
|
||||
setData(data);
|
||||
}
|
||||
|
||||
@ -223,8 +225,9 @@ ByteVector RelativeVolumeFrame::renderFields() const
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
RelativeVolumeFrame::RelativeVolumeFrame(const ByteVector &data, Header *h) : Frame(h)
|
||||
RelativeVolumeFrame::RelativeVolumeFrame(const ByteVector &data, Header *h) :
|
||||
Frame(h),
|
||||
d(new RelativeVolumeFramePrivate())
|
||||
{
|
||||
d = new RelativeVolumeFramePrivate;
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
@ -52,16 +52,16 @@ public:
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SynchronizedLyricsFrame::SynchronizedLyricsFrame(String::Type encoding) :
|
||||
Frame("SYLT")
|
||||
Frame("SYLT"),
|
||||
d(new SynchronizedLyricsFramePrivate())
|
||||
{
|
||||
d = new SynchronizedLyricsFramePrivate;
|
||||
d->textEncoding = encoding;
|
||||
}
|
||||
|
||||
SynchronizedLyricsFrame::SynchronizedLyricsFrame(const ByteVector &data) :
|
||||
Frame(data)
|
||||
Frame(data),
|
||||
d(new SynchronizedLyricsFramePrivate())
|
||||
{
|
||||
d = new SynchronizedLyricsFramePrivate;
|
||||
setData(data);
|
||||
}
|
||||
|
||||
@ -189,7 +189,7 @@ void SynchronizedLyricsFrame::parseFields(const ByteVector &data)
|
||||
}
|
||||
}
|
||||
String text = readStringField(data, enc, &pos);
|
||||
if(text.isEmpty() || pos + 4 > end)
|
||||
if(pos + 4 > end)
|
||||
return;
|
||||
|
||||
unsigned int time = data.toUInt(pos, true);
|
||||
@ -234,9 +234,9 @@ ByteVector SynchronizedLyricsFrame::renderFields() const
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SynchronizedLyricsFrame::SynchronizedLyricsFrame(const ByteVector &data, Header *h)
|
||||
: Frame(h)
|
||||
SynchronizedLyricsFrame::SynchronizedLyricsFrame(const ByteVector &data, Header *h) :
|
||||
Frame(h),
|
||||
d(new SynchronizedLyricsFramePrivate())
|
||||
{
|
||||
d = new SynchronizedLyricsFramePrivate();
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
@ -36,7 +36,9 @@ class TableOfContentsFrame::TableOfContentsFramePrivate
|
||||
{
|
||||
public:
|
||||
TableOfContentsFramePrivate() :
|
||||
tagHeader(0)
|
||||
tagHeader(0),
|
||||
isTopLevel(false),
|
||||
isOrdered(false)
|
||||
{
|
||||
embeddedFrameList.setAutoDelete(true);
|
||||
}
|
||||
@ -80,9 +82,9 @@ namespace {
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TableOfContentsFrame::TableOfContentsFrame(const ID3v2::Header *tagHeader, const ByteVector &data) :
|
||||
ID3v2::Frame(data)
|
||||
ID3v2::Frame(data),
|
||||
d(new TableOfContentsFramePrivate())
|
||||
{
|
||||
d = new TableOfContentsFramePrivate;
|
||||
d->tagHeader = tagHeader;
|
||||
setData(data);
|
||||
}
|
||||
@ -90,9 +92,9 @@ TableOfContentsFrame::TableOfContentsFrame(const ID3v2::Header *tagHeader, const
|
||||
TableOfContentsFrame::TableOfContentsFrame(const ByteVector &elementID,
|
||||
const ByteVectorList &children,
|
||||
const FrameList &embeddedFrames) :
|
||||
ID3v2::Frame("CTOC")
|
||||
ID3v2::Frame("CTOC"),
|
||||
d(new TableOfContentsFramePrivate())
|
||||
{
|
||||
d = new TableOfContentsFramePrivate;
|
||||
d->elementID = elementID;
|
||||
strip(d->elementID);
|
||||
d->childElements = children;
|
||||
@ -272,9 +274,9 @@ void TableOfContentsFrame::parseFields(const ByteVector &data)
|
||||
int pos = 0;
|
||||
unsigned int embPos = 0;
|
||||
d->elementID = readStringField(data, String::Latin1, &pos).data(String::Latin1);
|
||||
d->isTopLevel = (data.at(pos) & 2) > 0;
|
||||
d->isOrdered = (data.at(pos++) & 1) > 0;
|
||||
unsigned int entryCount = data.at(pos++);
|
||||
d->isTopLevel = (data.at(pos) & 2) != 0;
|
||||
d->isOrdered = (data.at(pos++) & 1) != 0;
|
||||
unsigned int entryCount = static_cast<unsigned char>(data.at(pos++));
|
||||
for(unsigned int i = 0; i < entryCount; i++) {
|
||||
ByteVector childElementID = readStringField(data, String::Latin1, &pos).data(String::Latin1);
|
||||
d->childElements.append(childElementID);
|
||||
@ -330,9 +332,9 @@ ByteVector TableOfContentsFrame::renderFields() const
|
||||
|
||||
TableOfContentsFrame::TableOfContentsFrame(const ID3v2::Header *tagHeader,
|
||||
const ByteVector &data, Header *h) :
|
||||
Frame(h)
|
||||
Frame(h),
|
||||
d(new TableOfContentsFramePrivate())
|
||||
{
|
||||
d = new TableOfContentsFramePrivate;
|
||||
d->tagHeader = tagHeader;
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
@ -29,6 +29,8 @@
|
||||
#include "id3v2tag.h"
|
||||
#include "id3v2frame.h"
|
||||
|
||||
#include "tbytevectorlist.h"
|
||||
|
||||
namespace TagLib {
|
||||
|
||||
namespace ID3v2 {
|
||||
|
@ -45,16 +45,16 @@ public:
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TextIdentificationFrame::TextIdentificationFrame(const ByteVector &type, String::Type encoding) :
|
||||
Frame(type)
|
||||
Frame(type),
|
||||
d(new TextIdentificationFramePrivate())
|
||||
{
|
||||
d = new TextIdentificationFramePrivate;
|
||||
d->textEncoding = encoding;
|
||||
}
|
||||
|
||||
TextIdentificationFrame::TextIdentificationFrame(const ByteVector &data) :
|
||||
Frame(data)
|
||||
Frame(data),
|
||||
d(new TextIdentificationFramePrivate())
|
||||
{
|
||||
d = new TextIdentificationFramePrivate;
|
||||
setData(data);
|
||||
}
|
||||
|
||||
@ -252,9 +252,10 @@ ByteVector TextIdentificationFrame::renderFields() const
|
||||
// TextIdentificationFrame private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TextIdentificationFrame::TextIdentificationFrame(const ByteVector &data, Header *h) : Frame(h)
|
||||
TextIdentificationFrame::TextIdentificationFrame(const ByteVector &data, Header *h) :
|
||||
Frame(h),
|
||||
d(new TextIdentificationFramePrivate())
|
||||
{
|
||||
d = new TextIdentificationFramePrivate;
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
||||
|
@ -45,16 +45,16 @@ public:
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
UniqueFileIdentifierFrame::UniqueFileIdentifierFrame(const ByteVector &data) :
|
||||
ID3v2::Frame(data)
|
||||
ID3v2::Frame(data),
|
||||
d(new UniqueFileIdentifierFramePrivate())
|
||||
{
|
||||
d = new UniqueFileIdentifierFramePrivate;
|
||||
setData(data);
|
||||
}
|
||||
|
||||
UniqueFileIdentifierFrame::UniqueFileIdentifierFrame(const String &owner, const ByteVector &id) :
|
||||
ID3v2::Frame("UFID")
|
||||
ID3v2::Frame("UFID"),
|
||||
d(new UniqueFileIdentifierFramePrivate())
|
||||
{
|
||||
d = new UniqueFileIdentifierFramePrivate;
|
||||
d->owner = owner;
|
||||
d->identifier = id;
|
||||
}
|
||||
@ -141,8 +141,8 @@ ByteVector UniqueFileIdentifierFrame::renderFields() const
|
||||
}
|
||||
|
||||
UniqueFileIdentifierFrame::UniqueFileIdentifierFrame(const ByteVector &data, Header *h) :
|
||||
Frame(h)
|
||||
Frame(h),
|
||||
d(new UniqueFileIdentifierFramePrivate())
|
||||
{
|
||||
d = new UniqueFileIdentifierFramePrivate;
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
@ -38,9 +38,10 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
UnknownFrame::UnknownFrame(const ByteVector &data) : Frame(data)
|
||||
UnknownFrame::UnknownFrame(const ByteVector &data) :
|
||||
Frame(data),
|
||||
d(new UnknownFramePrivate())
|
||||
{
|
||||
d = new UnknownFramePrivate;
|
||||
setData(data);
|
||||
}
|
||||
|
||||
@ -77,8 +78,9 @@ ByteVector UnknownFrame::renderFields() const
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
UnknownFrame::UnknownFrame(const ByteVector &data, Header *h) : Frame(h)
|
||||
UnknownFrame::UnknownFrame(const ByteVector &data, Header *h) :
|
||||
Frame(h),
|
||||
d(new UnknownFramePrivate())
|
||||
{
|
||||
d = new UnknownFramePrivate;
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
@ -50,16 +50,16 @@ public:
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
UnsynchronizedLyricsFrame::UnsynchronizedLyricsFrame(String::Type encoding) :
|
||||
Frame("USLT")
|
||||
Frame("USLT"),
|
||||
d(new UnsynchronizedLyricsFramePrivate())
|
||||
{
|
||||
d = new UnsynchronizedLyricsFramePrivate;
|
||||
d->textEncoding = encoding;
|
||||
}
|
||||
|
||||
UnsynchronizedLyricsFrame::UnsynchronizedLyricsFrame(const ByteVector &data) :
|
||||
Frame(data)
|
||||
Frame(data),
|
||||
d(new UnsynchronizedLyricsFramePrivate())
|
||||
{
|
||||
d = new UnsynchronizedLyricsFramePrivate;
|
||||
setData(data);
|
||||
}
|
||||
|
||||
@ -118,7 +118,7 @@ PropertyMap UnsynchronizedLyricsFrame::asProperties() const
|
||||
{
|
||||
PropertyMap map;
|
||||
String key = description().upper();
|
||||
if(key.isEmpty() || key.upper() == "LYRICS")
|
||||
if(key.isEmpty() || key == "LYRICS")
|
||||
map.insert("LYRICS", text());
|
||||
else
|
||||
map.insert("LYRICS:" + key, text());
|
||||
@ -190,9 +190,9 @@ ByteVector UnsynchronizedLyricsFrame::renderFields() const
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
UnsynchronizedLyricsFrame::UnsynchronizedLyricsFrame(const ByteVector &data, Header *h)
|
||||
: Frame(h)
|
||||
UnsynchronizedLyricsFrame::UnsynchronizedLyricsFrame(const ByteVector &data, Header *h) :
|
||||
Frame(h),
|
||||
d(new UnsynchronizedLyricsFramePrivate())
|
||||
{
|
||||
d = new UnsynchronizedLyricsFramePrivate();
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
@ -49,10 +49,14 @@ public:
|
||||
String description;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// UrlLinkFrame public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
UrlLinkFrame::UrlLinkFrame(const ByteVector &data) :
|
||||
Frame(data)
|
||||
Frame(data),
|
||||
d(new UrlLinkFramePrivate())
|
||||
{
|
||||
d = new UrlLinkFramePrivate;
|
||||
setData(data);
|
||||
}
|
||||
|
||||
@ -93,6 +97,10 @@ PropertyMap UrlLinkFrame::asProperties() const
|
||||
return map;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// UrlLinkFrame protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void UrlLinkFrame::parseFields(const ByteVector &data)
|
||||
{
|
||||
d->url = String(data);
|
||||
@ -103,24 +111,28 @@ ByteVector UrlLinkFrame::renderFields() const
|
||||
return d->url.data(String::Latin1);
|
||||
}
|
||||
|
||||
UrlLinkFrame::UrlLinkFrame(const ByteVector &data, Header *h) : Frame(h)
|
||||
UrlLinkFrame::UrlLinkFrame(const ByteVector &data, Header *h) :
|
||||
Frame(h),
|
||||
d(new UrlLinkFramePrivate())
|
||||
{
|
||||
d = new UrlLinkFramePrivate;
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// UserUrlLinkFrame public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
UserUrlLinkFrame::UserUrlLinkFrame(String::Type encoding) :
|
||||
UrlLinkFrame("WXXX")
|
||||
UrlLinkFrame("WXXX"),
|
||||
d(new UserUrlLinkFramePrivate())
|
||||
{
|
||||
d = new UserUrlLinkFramePrivate;
|
||||
d->textEncoding = encoding;
|
||||
}
|
||||
|
||||
UserUrlLinkFrame::UserUrlLinkFrame(const ByteVector &data) :
|
||||
UrlLinkFrame(data)
|
||||
UrlLinkFrame(data),
|
||||
d(new UserUrlLinkFramePrivate())
|
||||
{
|
||||
d = new UserUrlLinkFramePrivate;
|
||||
setData(data);
|
||||
}
|
||||
|
||||
@ -158,7 +170,7 @@ PropertyMap UserUrlLinkFrame::asProperties() const
|
||||
{
|
||||
PropertyMap map;
|
||||
String key = description().upper();
|
||||
if(key.isEmpty() || key.upper() == "URL")
|
||||
if(key.isEmpty() || key == "URL")
|
||||
map.insert("URL", url());
|
||||
else
|
||||
map.insert("URL:" + key, url());
|
||||
@ -176,6 +188,10 @@ UserUrlLinkFrame *UserUrlLinkFrame::find(ID3v2::Tag *tag, const String &descript
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// UserUrlLinkFrame protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void UserUrlLinkFrame::parseFields(const ByteVector &data)
|
||||
{
|
||||
if(data.size() < 2) {
|
||||
@ -222,8 +238,9 @@ ByteVector UserUrlLinkFrame::renderFields() const
|
||||
return v;
|
||||
}
|
||||
|
||||
UserUrlLinkFrame::UserUrlLinkFrame(const ByteVector &data, Header *h) : UrlLinkFrame(data, h)
|
||||
UserUrlLinkFrame::UserUrlLinkFrame(const ByteVector &data, Header *h) :
|
||||
UrlLinkFrame(data, h),
|
||||
d(new UserUrlLinkFramePrivate())
|
||||
{
|
||||
d = new UserUrlLinkFramePrivate;
|
||||
parseFields(fieldData(data));
|
||||
}
|
||||
|
@ -41,9 +41,9 @@ public:
|
||||
// public methods
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExtendedHeader::ExtendedHeader()
|
||||
ExtendedHeader::ExtendedHeader() :
|
||||
d(new ExtendedHeaderPrivate())
|
||||
{
|
||||
d = new ExtendedHeaderPrivate();
|
||||
}
|
||||
|
||||
ExtendedHeader::~ExtendedHeader()
|
||||
|
26
3rdparty/taglib/mpeg/id3v2/id3v2frame.cpp
vendored
26
3rdparty/taglib/mpeg/id3v2/id3v2frame.cpp
vendored
@ -111,8 +111,8 @@ Frame *Frame::createTextualFrame(const String &key, const StringList &values) //
|
||||
// check if the key is contained in the key<=>frameID mapping
|
||||
ByteVector frameID = keyToFrameID(key);
|
||||
if(!frameID.isEmpty()) {
|
||||
// Apple proprietary WFED (Podcast URL) is in fact a text frame.
|
||||
if(frameID[0] == 'T' || frameID == "WFED"){ // text frame
|
||||
// Apple proprietary WFED (Podcast URL), MVNM (Movement Name), MVIN (Movement Number) are in fact text frames.
|
||||
if(frameID[0] == 'T' || frameID == "WFED" || frameID == "MVNM" || frameID == "MVIN"){ // text frame
|
||||
TextIdentificationFrame *frame = new TextIdentificationFrame(frameID, String::UTF8);
|
||||
frame->setText(values);
|
||||
return frame;
|
||||
@ -198,15 +198,15 @@ ByteVector Frame::render() const
|
||||
// protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Frame::Frame(const ByteVector &data)
|
||||
Frame::Frame(const ByteVector &data) :
|
||||
d(new FramePrivate())
|
||||
{
|
||||
d = new FramePrivate;
|
||||
d->header = new Header(data);
|
||||
}
|
||||
|
||||
Frame::Frame(Header *h)
|
||||
Frame::Frame(Header *h) :
|
||||
d(new FramePrivate())
|
||||
{
|
||||
d = new FramePrivate;
|
||||
d->header = h;
|
||||
}
|
||||
|
||||
@ -392,6 +392,8 @@ namespace
|
||||
{ "TDES", "PODCASTDESC" },
|
||||
{ "TGID", "PODCASTID" },
|
||||
{ "WFED", "PODCASTURL" },
|
||||
{ "MVNM", "MOVEMENTNAME" },
|
||||
{ "MVIN", "MOVEMENTNUMBER" },
|
||||
};
|
||||
const size_t frameTranslationSize = sizeof(frameTranslation) / sizeof(frameTranslation[0]);
|
||||
|
||||
@ -474,8 +476,8 @@ PropertyMap Frame::asProperties() const
|
||||
// workaround until this function is virtual
|
||||
if(id == "TXXX")
|
||||
return dynamic_cast< const UserTextIdentificationFrame* >(this)->asProperties();
|
||||
// Apple proprietary WFED (Podcast URL) is in fact a text frame.
|
||||
else if(id[0] == 'T' || id == "WFED")
|
||||
// Apple proprietary WFED (Podcast URL), MVNM (Movement Name), MVIN (Movement Number) are in fact text frames.
|
||||
else if(id[0] == 'T' || id == "WFED" || id == "MVNM" || id == "MVIN")
|
||||
return dynamic_cast< const TextIdentificationFrame* >(this)->asProperties();
|
||||
else if(id == "WXXX")
|
||||
return dynamic_cast< const UserUrlLinkFrame* >(this)->asProperties();
|
||||
@ -571,15 +573,15 @@ unsigned int Frame::Header::size(unsigned int version)
|
||||
// public members (Frame::Header)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Frame::Header::Header(const ByteVector &data, bool synchSafeInts)
|
||||
Frame::Header::Header(const ByteVector &data, bool synchSafeInts) :
|
||||
d(new HeaderPrivate())
|
||||
{
|
||||
d = new HeaderPrivate;
|
||||
setData(data, synchSafeInts);
|
||||
}
|
||||
|
||||
Frame::Header::Header(const ByteVector &data, unsigned int version)
|
||||
Frame::Header::Header(const ByteVector &data, unsigned int version) :
|
||||
d(new HeaderPrivate())
|
||||
{
|
||||
d = new HeaderPrivate;
|
||||
setData(data, version);
|
||||
}
|
||||
|
||||
|
11
3rdparty/taglib/mpeg/id3v2/id3v2framefactory.cpp
vendored
11
3rdparty/taglib/mpeg/id3v2/id3v2framefactory.cpp
vendored
@ -198,8 +198,8 @@ Frame *FrameFactory::createFrame(const ByteVector &origData, Header *tagHeader)
|
||||
|
||||
// Text Identification (frames 4.2)
|
||||
|
||||
// Apple proprietary WFED (Podcast URL) is in fact a text frame.
|
||||
if(frameID.startsWith("T") || frameID == "WFED") {
|
||||
// Apple proprietary WFED (Podcast URL), MVNM (Movement Name), MVIN (Movement Number) are in fact text frames.
|
||||
if(frameID.startsWith("T") || frameID == "WFED" || frameID == "MVNM" || frameID == "MVIN") {
|
||||
|
||||
TextIdentificationFrame *f = frameID != "TXXX"
|
||||
? new TextIdentificationFrame(data, header)
|
||||
@ -334,10 +334,11 @@ void FrameFactory::rebuildAggregateFrames(ID3v2::Tag *tag) const
|
||||
tag->frameList("TDAT").size() == 1)
|
||||
{
|
||||
TextIdentificationFrame *tdrc =
|
||||
static_cast<TextIdentificationFrame *>(tag->frameList("TDRC").front());
|
||||
dynamic_cast<TextIdentificationFrame *>(tag->frameList("TDRC").front());
|
||||
UnknownFrame *tdat = static_cast<UnknownFrame *>(tag->frameList("TDAT").front());
|
||||
|
||||
if(tdrc->fieldList().size() == 1 &&
|
||||
if(tdrc &&
|
||||
tdrc->fieldList().size() == 1 &&
|
||||
tdrc->fieldList().front().size() == 4 &&
|
||||
tdat->data().size() >= 5)
|
||||
{
|
||||
@ -456,6 +457,8 @@ namespace
|
||||
{ "TDS", "TDES" },
|
||||
{ "TID", "TGID" },
|
||||
{ "WFD", "WFED" },
|
||||
{ "MVN", "MVNM" },
|
||||
{ "MVI", "MVIN" },
|
||||
};
|
||||
const size_t frameConversion2Size = sizeof(frameConversion2) / sizeof(frameConversion2[0]);
|
||||
|
||||
|
8
3rdparty/taglib/mpeg/id3v2/id3v2tag.cpp
vendored
8
3rdparty/taglib/mpeg/id3v2/id3v2tag.cpp
vendored
@ -60,6 +60,7 @@ class ID3v2::Tag::TagPrivate
|
||||
{
|
||||
public:
|
||||
TagPrivate() :
|
||||
factory(0),
|
||||
file(0),
|
||||
tagOffset(0),
|
||||
extendedHeader(0),
|
||||
@ -286,7 +287,7 @@ void ID3v2::Tag::setGenre(const String &s)
|
||||
|
||||
void ID3v2::Tag::setYear(unsigned int i)
|
||||
{
|
||||
if(i <= 0) {
|
||||
if(i == 0) {
|
||||
removeFrames("TDRC");
|
||||
return;
|
||||
}
|
||||
@ -295,7 +296,7 @@ void ID3v2::Tag::setYear(unsigned int i)
|
||||
|
||||
void ID3v2::Tag::setTrack(unsigned int i)
|
||||
{
|
||||
if(i <= 0) {
|
||||
if(i == 0) {
|
||||
removeFrames("TRCK");
|
||||
return;
|
||||
}
|
||||
@ -618,7 +619,6 @@ ByteVector ID3v2::Tag::render(int version) const
|
||||
}
|
||||
|
||||
// Compute the amount of padding, and append that to tagData.
|
||||
// TODO: Should be calculated in long long in taglib2.
|
||||
|
||||
long originalSize = d->header.tagSize();
|
||||
long paddingSize = originalSize - (tagData.size() - Header::size());
|
||||
@ -723,7 +723,7 @@ void ID3v2::Tag::parse(const ByteVector &origData)
|
||||
|
||||
if(d->header.extendedHeader()) {
|
||||
if(!d->extendedHeader)
|
||||
d->extendedHeader = new ExtendedHeader;
|
||||
d->extendedHeader = new ExtendedHeader();
|
||||
d->extendedHeader->setData(data);
|
||||
if(d->extendedHeader->size() <= data.size()) {
|
||||
frameDataPosition += d->extendedHeader->size();
|
||||
|
156
3rdparty/taglib/mpeg/mpegfile.cpp
vendored
156
3rdparty/taglib/mpeg/mpegfile.cpp
vendored
@ -76,6 +76,58 @@ public:
|
||||
Properties *properties;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// static members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace
|
||||
{
|
||||
// Dummy file class to make a stream work with MPEG::Header.
|
||||
|
||||
class AdapterFile : public TagLib::File
|
||||
{
|
||||
public:
|
||||
AdapterFile(IOStream *stream) : File(stream) {}
|
||||
|
||||
Tag *tag() const { return 0; }
|
||||
AudioProperties *audioProperties() const { return 0; }
|
||||
bool save() { return false; }
|
||||
};
|
||||
}
|
||||
|
||||
bool MPEG::File::isSupported(IOStream *stream)
|
||||
{
|
||||
if(!stream || !stream->isOpen())
|
||||
return false;
|
||||
|
||||
// An MPEG file has MPEG frame headers. An ID3v2 tag may precede.
|
||||
|
||||
// MPEG frame headers are really confusing with irrelevant binary data.
|
||||
// So we check if a frame header is really valid.
|
||||
|
||||
long headerOffset;
|
||||
const ByteVector buffer = Utils::readHeader(stream, bufferSize(), true, &headerOffset);
|
||||
|
||||
if(buffer.isEmpty())
|
||||
return false;
|
||||
|
||||
const long originalPosition = stream->tell();
|
||||
AdapterFile file(stream);
|
||||
|
||||
for(unsigned int i = 0; i < buffer.size() - 1; ++i) {
|
||||
if(isFrameSync(buffer, i)) {
|
||||
const Header header(&file, headerOffset + i, true);
|
||||
if(header.isValid()) {
|
||||
stream->seek(originalPosition);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stream->seek(originalPosition);
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -346,55 +398,50 @@ void MPEG::File::setID3v2FrameFactory(const ID3v2::FrameFactory *factory)
|
||||
|
||||
long MPEG::File::nextFrameOffset(long position)
|
||||
{
|
||||
bool foundLastSyncPattern = false;
|
||||
|
||||
ByteVector buffer;
|
||||
ByteVector frameSyncBytes(2, '\0');
|
||||
|
||||
while(true) {
|
||||
seek(position);
|
||||
buffer = readBlock(bufferSize());
|
||||
|
||||
if(buffer.size() <= 0)
|
||||
const ByteVector buffer = readBlock(bufferSize());
|
||||
if(buffer.isEmpty())
|
||||
return -1;
|
||||
|
||||
if(foundLastSyncPattern && secondSynchByte(buffer[0]))
|
||||
return position - 1;
|
||||
|
||||
for(unsigned int i = 0; i < buffer.size() - 1; i++) {
|
||||
if(firstSyncByte(buffer[i]) && secondSynchByte(buffer[i + 1]))
|
||||
return position + i;
|
||||
for(unsigned int i = 0; i < buffer.size(); ++i) {
|
||||
frameSyncBytes[0] = frameSyncBytes[1];
|
||||
frameSyncBytes[1] = buffer[i];
|
||||
if(isFrameSync(frameSyncBytes)) {
|
||||
const Header header(this, position + i - 1, true);
|
||||
if(header.isValid())
|
||||
return position + i - 1;
|
||||
}
|
||||
}
|
||||
|
||||
foundLastSyncPattern = firstSyncByte(buffer[buffer.size() - 1]);
|
||||
position += buffer.size();
|
||||
position += bufferSize();
|
||||
}
|
||||
}
|
||||
|
||||
long MPEG::File::previousFrameOffset(long position)
|
||||
{
|
||||
bool foundFirstSyncPattern = false;
|
||||
ByteVector buffer;
|
||||
ByteVector frameSyncBytes(2, '\0');
|
||||
|
||||
while (position > 0) {
|
||||
long size = std::min<long>(position, bufferSize());
|
||||
position -= size;
|
||||
while(position > 0) {
|
||||
const long bufferLength = std::min<long>(position, bufferSize());
|
||||
position -= bufferLength;
|
||||
|
||||
seek(position);
|
||||
buffer = readBlock(size);
|
||||
const ByteVector buffer = readBlock(bufferLength);
|
||||
|
||||
if(buffer.size() <= 0)
|
||||
break;
|
||||
|
||||
if(foundFirstSyncPattern && firstSyncByte(buffer[buffer.size() - 1]))
|
||||
return position + buffer.size() - 1;
|
||||
|
||||
for(int i = buffer.size() - 2; i >= 0; i--) {
|
||||
if(firstSyncByte(buffer[i]) && secondSynchByte(buffer[i + 1]))
|
||||
return position + i;
|
||||
for(int i = buffer.size() - 1; i >= 0; --i) {
|
||||
frameSyncBytes[1] = frameSyncBytes[0];
|
||||
frameSyncBytes[0] = buffer[i];
|
||||
if(isFrameSync(frameSyncBytes)) {
|
||||
const Header header(this, position + i, true);
|
||||
if(header.isValid())
|
||||
return position + i + header.frameLength();
|
||||
}
|
||||
}
|
||||
|
||||
foundFirstSyncPattern = secondSynchByte(buffer[0]);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -488,28 +535,41 @@ long MPEG::File::findID3v2()
|
||||
const ByteVector headerID = ID3v2::Header::fileIdentifier();
|
||||
|
||||
seek(0);
|
||||
|
||||
const ByteVector data = readBlock(headerID.size());
|
||||
if(data.size() < headerID.size())
|
||||
return -1;
|
||||
|
||||
if(data == headerID)
|
||||
if(readBlock(headerID.size()) == headerID)
|
||||
return 0;
|
||||
|
||||
if(firstSyncByte(data[0]) && secondSynchByte(data[1]))
|
||||
const Header firstHeader(this, 0, true);
|
||||
if(firstHeader.isValid())
|
||||
return -1;
|
||||
|
||||
// Look for the entire file, if neither an MEPG frame or ID3v2 tag was found
|
||||
// at the beginning of the file.
|
||||
// We don't care about the inefficiency of the code, since this is a seldom case.
|
||||
// Look for an ID3v2 tag until reaching the first valid MPEG frame.
|
||||
|
||||
const long tagOffset = find(headerID);
|
||||
if(tagOffset < 0)
|
||||
return -1;
|
||||
ByteVector frameSyncBytes(2, '\0');
|
||||
ByteVector tagHeaderBytes(3, '\0');
|
||||
long position = 0;
|
||||
|
||||
const long frameOffset = firstFrameOffset();
|
||||
if(frameOffset < tagOffset)
|
||||
return -1;
|
||||
while(true) {
|
||||
seek(position);
|
||||
const ByteVector buffer = readBlock(bufferSize());
|
||||
if(buffer.isEmpty())
|
||||
return -1;
|
||||
|
||||
return tagOffset;
|
||||
for(unsigned int i = 0; i < buffer.size(); ++i) {
|
||||
frameSyncBytes[0] = frameSyncBytes[1];
|
||||
frameSyncBytes[1] = buffer[i];
|
||||
if(isFrameSync(frameSyncBytes)) {
|
||||
const Header header(this, position + i - 1, true);
|
||||
if(header.isValid())
|
||||
return -1;
|
||||
}
|
||||
|
||||
tagHeaderBytes[0] = tagHeaderBytes[1];
|
||||
tagHeaderBytes[1] = tagHeaderBytes[2];
|
||||
tagHeaderBytes[2] = buffer[i];
|
||||
if(tagHeaderBytes == headerID)
|
||||
return position + i - 2;
|
||||
}
|
||||
|
||||
position += bufferSize();
|
||||
}
|
||||
}
|
||||
|
9
3rdparty/taglib/mpeg/mpegfile.h
vendored
9
3rdparty/taglib/mpeg/mpegfile.h
vendored
@ -370,6 +370,15 @@ namespace TagLib {
|
||||
*/
|
||||
bool hasAPETag() const;
|
||||
|
||||
/*!
|
||||
* Returns whether or not the given \a stream can be opened as an MPEG
|
||||
* file.
|
||||
*
|
||||
* \note This method is designed to do a quick check. The result may
|
||||
* not necessarily be correct.
|
||||
*/
|
||||
static bool isSupported(IOStream *stream);
|
||||
|
||||
private:
|
||||
File(const File &);
|
||||
File &operator=(const File &);
|
||||
|
23
3rdparty/taglib/mpeg/mpegheader.cpp
vendored
23
3rdparty/taglib/mpeg/mpegheader.cpp
vendored
@ -182,7 +182,7 @@ void MPEG::Header::parse(File *file, long offset, bool checkLength)
|
||||
|
||||
// Check for the MPEG synch bytes.
|
||||
|
||||
if(!firstSyncByte(data[0]) || !secondSynchByte(data[1])) {
|
||||
if(!isFrameSync(data)) {
|
||||
debug("MPEG::Header::parse() -- MPEG header did not match MPEG synch.");
|
||||
return;
|
||||
}
|
||||
@ -197,10 +197,8 @@ void MPEG::Header::parse(File *file, long offset, bool checkLength)
|
||||
d->version = Version2;
|
||||
else if(versionBits == 3)
|
||||
d->version = Version1;
|
||||
else {
|
||||
debug("MPEG::Header::parse() -- Invalid MPEG version bits.");
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the MPEG layer
|
||||
|
||||
@ -212,10 +210,8 @@ void MPEG::Header::parse(File *file, long offset, bool checkLength)
|
||||
d->layer = 2;
|
||||
else if(layerBits == 3)
|
||||
d->layer = 1;
|
||||
else {
|
||||
debug("MPEG::Header::parse() -- Invalid MPEG layer bits.");
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
d->protectionEnabled = (static_cast<unsigned char>(data[1] & 0x01) == 0);
|
||||
|
||||
@ -244,10 +240,8 @@ void MPEG::Header::parse(File *file, long offset, bool checkLength)
|
||||
|
||||
d->bitrate = bitrates[versionIndex][layerIndex][bitrateIndex];
|
||||
|
||||
if(d->bitrate == 0) {
|
||||
debug("MPEG::Header::parse() -- Invalid bit rate.");
|
||||
if(d->bitrate == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the sample rate
|
||||
|
||||
@ -264,7 +258,6 @@ void MPEG::Header::parse(File *file, long offset, bool checkLength)
|
||||
d->sampleRate = sampleRates[d->version][samplerateIndex];
|
||||
|
||||
if(d->sampleRate == 0) {
|
||||
debug("MPEG::Header::parse() -- Invalid sample rate.");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -311,20 +304,16 @@ void MPEG::Header::parse(File *file, long offset, bool checkLength)
|
||||
file->seek(offset + d->frameLength);
|
||||
const ByteVector nextData = file->readBlock(4);
|
||||
|
||||
if(nextData.size() < 4) {
|
||||
debug("MPEG::Header::parse() -- Could not read the next frame header.");
|
||||
if(nextData.size() < 4)
|
||||
return;
|
||||
}
|
||||
|
||||
const unsigned int HeaderMask = 0xfffe0c00;
|
||||
|
||||
const unsigned int header = data.toUInt(0, true) & HeaderMask;
|
||||
const unsigned int nextHeader = nextData.toUInt(0, true) & HeaderMask;
|
||||
|
||||
if(header != nextHeader) {
|
||||
debug("MPEG::Header::parse() -- The next frame was not consistent with this frame.");
|
||||
if(header != nextHeader)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Now that we're done parsing, set this to be a valid frame.
|
||||
|
29
3rdparty/taglib/mpeg/mpegproperties.cpp
vendored
29
3rdparty/taglib/mpeg/mpegproperties.cpp
vendored
@ -157,23 +157,13 @@ void MPEG::Properties::read(File *file)
|
||||
{
|
||||
// Only the first valid frame is required if we have a VBR header.
|
||||
|
||||
long firstFrameOffset = file->firstFrameOffset();
|
||||
const long firstFrameOffset = file->firstFrameOffset();
|
||||
if(firstFrameOffset < 0) {
|
||||
debug("MPEG::Properties::read() -- Could not find an MPEG frame in the stream.");
|
||||
return;
|
||||
}
|
||||
|
||||
Header firstHeader(file, firstFrameOffset);
|
||||
|
||||
while(!firstHeader.isValid()) {
|
||||
firstFrameOffset = file->nextFrameOffset(firstFrameOffset + 1);
|
||||
if(firstFrameOffset < 0) {
|
||||
debug("MPEG::Properties::read() -- Could not find a valid first MPEG frame in the stream.");
|
||||
return;
|
||||
}
|
||||
|
||||
firstHeader = Header(file, firstFrameOffset);
|
||||
}
|
||||
const Header firstHeader(file, firstFrameOffset, false);
|
||||
|
||||
// Check for a VBR header that will help us in gathering information about a
|
||||
// VBR stream.
|
||||
@ -207,24 +197,13 @@ void MPEG::Properties::read(File *file)
|
||||
|
||||
// Look for the last MPEG audio frame to calculate the stream length.
|
||||
|
||||
long lastFrameOffset = file->lastFrameOffset();
|
||||
const long lastFrameOffset = file->lastFrameOffset();
|
||||
if(lastFrameOffset < 0) {
|
||||
debug("MPEG::Properties::read() -- Could not find an MPEG frame in the stream.");
|
||||
return;
|
||||
}
|
||||
|
||||
Header lastHeader(file, lastFrameOffset, false);
|
||||
|
||||
while(!lastHeader.isValid()) {
|
||||
lastFrameOffset = file->previousFrameOffset(lastFrameOffset);
|
||||
if(lastFrameOffset < 0) {
|
||||
debug("MPEG::Properties::read() -- Could not find a valid last MPEG frame in the stream.");
|
||||
return;
|
||||
}
|
||||
|
||||
lastHeader = Header(file, lastFrameOffset, false);
|
||||
}
|
||||
|
||||
const Header lastHeader(file, lastFrameOffset, false);
|
||||
const long streamLength = lastFrameOffset - firstFrameOffset + lastHeader.frameLength();
|
||||
if(streamLength > 0)
|
||||
d->length = static_cast<int>(streamLength * 8.0 / d->bitrate + 0.5);
|
||||
|
16
3rdparty/taglib/mpeg/mpegutils.h
vendored
16
3rdparty/taglib/mpeg/mpegutils.h
vendored
@ -41,17 +41,17 @@ namespace TagLib
|
||||
* MPEG frames can be recognized by the bit pattern 11111111 111, so the
|
||||
* first byte is easy to check for, however checking to see if the second byte
|
||||
* starts with \e 111 is a bit more tricky, hence these functions.
|
||||
*
|
||||
* \note This does not check the length of the vector, since this is an
|
||||
* internal utility function.
|
||||
*/
|
||||
inline bool firstSyncByte(unsigned char byte)
|
||||
inline bool isFrameSync(const ByteVector &bytes, unsigned int offset = 0)
|
||||
{
|
||||
return (byte == 0xFF);
|
||||
}
|
||||
// 0xFF in the second byte is possible in theory, but it's very unlikely.
|
||||
|
||||
inline bool secondSynchByte(unsigned char byte)
|
||||
{
|
||||
// 0xFF is possible in theory, but it's very unlikely be a header.
|
||||
|
||||
return (byte != 0xFF && ((byte & 0xE0) == 0xE0));
|
||||
const unsigned char b1 = bytes[offset + 0];
|
||||
const unsigned char b2 = bytes[offset + 1];
|
||||
return (b1 == 0xFF && b2 != 0xFF && (b2 & 0xE0) == 0xE0);
|
||||
}
|
||||
|
||||
}
|
||||
|
25
3rdparty/taglib/ogg/flac/oggflacfile.cpp
vendored
25
3rdparty/taglib/ogg/flac/oggflacfile.cpp
vendored
@ -27,6 +27,7 @@
|
||||
#include <tstring.h>
|
||||
#include <tdebug.h>
|
||||
#include <tpropertymap.h>
|
||||
#include <tagutils.h>
|
||||
|
||||
#include <xiphcomment.h>
|
||||
#include "oggflacfile.h"
|
||||
@ -65,22 +66,36 @@ public:
|
||||
int commentPacket;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// static members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool Ogg::FLAC::File::isSupported(IOStream *stream)
|
||||
{
|
||||
// An Ogg FLAC file has IDs "OggS" and "fLaC" somewhere.
|
||||
|
||||
const ByteVector buffer = Utils::readHeader(stream, bufferSize(), false);
|
||||
return (buffer.find("OggS") >= 0 && buffer.find("fLaC") >= 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Ogg::FLAC::File::File(FileName file, bool readProperties,
|
||||
Properties::ReadStyle propertiesStyle) : Ogg::File(file)
|
||||
Properties::ReadStyle propertiesStyle) :
|
||||
Ogg::File(file),
|
||||
d(new FilePrivate())
|
||||
{
|
||||
d = new FilePrivate;
|
||||
if(isOpen())
|
||||
read(readProperties, propertiesStyle);
|
||||
}
|
||||
|
||||
Ogg::FLAC::File::File(IOStream *stream, bool readProperties,
|
||||
Properties::ReadStyle propertiesStyle) : Ogg::File(stream)
|
||||
Properties::ReadStyle propertiesStyle) :
|
||||
Ogg::File(stream),
|
||||
d(new FilePrivate())
|
||||
{
|
||||
d = new FilePrivate;
|
||||
if(isOpen())
|
||||
read(readProperties, propertiesStyle);
|
||||
}
|
||||
@ -172,7 +187,7 @@ void Ogg::FLAC::File::read(bool readProperties, Properties::ReadStyle properties
|
||||
if(d->hasXiphComment)
|
||||
d->comment = new Ogg::XiphComment(xiphCommentData());
|
||||
else
|
||||
d->comment = new Ogg::XiphComment;
|
||||
d->comment = new Ogg::XiphComment();
|
||||
|
||||
|
||||
if(readProperties)
|
||||
|
11
3rdparty/taglib/ogg/flac/oggflacfile.h
vendored
11
3rdparty/taglib/ogg/flac/oggflacfile.h
vendored
@ -127,9 +127,6 @@ namespace TagLib {
|
||||
/*!
|
||||
* Save the file. This will primarily save and update the XiphComment.
|
||||
* Returns true if the save is successful.
|
||||
*
|
||||
* \warning In the current implementation, it's dangerous to call save()
|
||||
* repeatedly. It leads to a segfault.
|
||||
*/
|
||||
virtual bool save();
|
||||
|
||||
@ -146,6 +143,14 @@ namespace TagLib {
|
||||
*/
|
||||
bool hasXiphComment() const;
|
||||
|
||||
/*!
|
||||
* Check if the given \a stream can be opened as an Ogg FLAC file.
|
||||
*
|
||||
* \note This method is designed to do a quick check. The result may
|
||||
* not necessarily be correct.
|
||||
*/
|
||||
static bool isSupported(IOStream *stream);
|
||||
|
||||
private:
|
||||
File(const File &);
|
||||
File &operator=(const File &);
|
||||
|
2
3rdparty/taglib/ogg/oggfile.cpp
vendored
2
3rdparty/taglib/ogg/oggfile.cpp
vendored
@ -253,7 +253,7 @@ void Ogg::File::writePacket(unsigned int i, const ByteVector &packet)
|
||||
ByteVectorList packets = firstPage->packets();
|
||||
packets[i - firstPage->firstPacketIndex()] = packet;
|
||||
|
||||
if(firstPage != lastPage && lastPage->packetCount() > 2) {
|
||||
if(firstPage != lastPage && lastPage->packetCount() > 1) {
|
||||
ByteVectorList lastPagePackets = lastPage->packets();
|
||||
lastPagePackets.erase(lastPagePackets.begin());
|
||||
packets.append(lastPagePackets);
|
||||
|
8
3rdparty/taglib/ogg/oggpage.cpp
vendored
8
3rdparty/taglib/ogg/oggpage.cpp
vendored
@ -208,15 +208,15 @@ List<Ogg::Page *> Ogg::Page::paginate(const ByteVectorList &packets,
|
||||
|
||||
static const unsigned int SplitSize = 32 * 255;
|
||||
|
||||
// Force repagination if the packets are too large for a page.
|
||||
// Force repagination if the segment table will exceed the size limit.
|
||||
|
||||
if(strategy != Repaginate) {
|
||||
|
||||
size_t totalSize = packets.size();
|
||||
size_t tableSize = 0;
|
||||
for(ByteVectorList::ConstIterator it = packets.begin(); it != packets.end(); ++it)
|
||||
totalSize += it->size();
|
||||
tableSize += it->size() / 255 + 1;
|
||||
|
||||
if(totalSize > 255 * 255)
|
||||
if(tableSize > 255)
|
||||
strategy = Repaginate;
|
||||
}
|
||||
|
||||
|
15
3rdparty/taglib/ogg/opus/opusfile.cpp
vendored
15
3rdparty/taglib/ogg/opus/opusfile.cpp
vendored
@ -30,6 +30,7 @@
|
||||
#include <tstring.h>
|
||||
#include <tdebug.h>
|
||||
#include <tpropertymap.h>
|
||||
#include <tagutils.h>
|
||||
|
||||
#include "opusfile.h"
|
||||
|
||||
@ -53,6 +54,18 @@ public:
|
||||
Properties *properties;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// static members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool Ogg::Opus::File::isSupported(IOStream *stream)
|
||||
{
|
||||
// An Opus file has IDs "OggS" and "OpusHead" somewhere.
|
||||
|
||||
const ByteVector buffer = Utils::readHeader(stream, bufferSize(), false);
|
||||
return (buffer.find("OggS") >= 0 && buffer.find("OpusHead") >= 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -101,7 +114,7 @@ Opus::Properties *Opus::File::audioProperties() const
|
||||
bool Opus::File::save()
|
||||
{
|
||||
if(!d->comment)
|
||||
d->comment = new Ogg::XiphComment;
|
||||
d->comment = new Ogg::XiphComment();
|
||||
|
||||
setPacket(1, ByteVector("OpusTags", 8) + d->comment->render(false));
|
||||
|
||||
|
12
3rdparty/taglib/ogg/opus/opusfile.h
vendored
12
3rdparty/taglib/ogg/opus/opusfile.h
vendored
@ -110,12 +110,18 @@ namespace TagLib {
|
||||
* Save the file.
|
||||
*
|
||||
* This returns true if the save was successful.
|
||||
*
|
||||
* \warning In the current implementation, it's dangerous to call save()
|
||||
* repeatedly. It leads to a segfault.
|
||||
*/
|
||||
virtual bool save();
|
||||
|
||||
/*!
|
||||
* Returns whether or not the given \a stream can be opened as an Opus
|
||||
* file.
|
||||
*
|
||||
* \note This method is designed to do a quick check. The result may
|
||||
* not necessarily be correct.
|
||||
*/
|
||||
static bool isSupported(IOStream *stream);
|
||||
|
||||
private:
|
||||
File(const File &);
|
||||
File &operator=(const File &);
|
||||
|
15
3rdparty/taglib/ogg/speex/speexfile.cpp
vendored
15
3rdparty/taglib/ogg/speex/speexfile.cpp
vendored
@ -30,6 +30,7 @@
|
||||
#include <tstring.h>
|
||||
#include <tdebug.h>
|
||||
#include <tpropertymap.h>
|
||||
#include <tagutils.h>
|
||||
|
||||
#include "speexfile.h"
|
||||
|
||||
@ -53,6 +54,18 @@ public:
|
||||
Properties *properties;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// static members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool Ogg::Speex::File::isSupported(IOStream *stream)
|
||||
{
|
||||
// A Speex file has IDs "OggS" and "Speex " somewhere.
|
||||
|
||||
const ByteVector buffer = Utils::readHeader(stream, bufferSize(), false);
|
||||
return (buffer.find("OggS") >= 0 && buffer.find("Speex ") >= 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -101,7 +114,7 @@ Speex::Properties *Speex::File::audioProperties() const
|
||||
bool Speex::File::save()
|
||||
{
|
||||
if(!d->comment)
|
||||
d->comment = new Ogg::XiphComment;
|
||||
d->comment = new Ogg::XiphComment();
|
||||
|
||||
setPacket(1, d->comment->render());
|
||||
|
||||
|
12
3rdparty/taglib/ogg/speex/speexfile.h
vendored
12
3rdparty/taglib/ogg/speex/speexfile.h
vendored
@ -110,12 +110,18 @@ namespace TagLib {
|
||||
* Save the file.
|
||||
*
|
||||
* This returns true if the save was successful.
|
||||
*
|
||||
* \warning In the current implementation, it's dangerous to call save()
|
||||
* repeatedly. It leads to a segfault.
|
||||
*/
|
||||
virtual bool save();
|
||||
|
||||
/*!
|
||||
* Returns whether or not the given \a stream can be opened as a Speex
|
||||
* file.
|
||||
*
|
||||
* \note This method is designed to do a quick check. The result may
|
||||
* not necessarily be correct.
|
||||
*/
|
||||
static bool isSupported(IOStream *stream);
|
||||
|
||||
private:
|
||||
File(const File &);
|
||||
File &operator=(const File &);
|
||||
|
16
3rdparty/taglib/ogg/vorbis/vorbisfile.cpp
vendored
16
3rdparty/taglib/ogg/vorbis/vorbisfile.cpp
vendored
@ -28,10 +28,10 @@
|
||||
#include <tstring.h>
|
||||
#include <tdebug.h>
|
||||
#include <tpropertymap.h>
|
||||
#include <tagutils.h>
|
||||
|
||||
#include "vorbisfile.h"
|
||||
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
class Vorbis::File::FilePrivate
|
||||
@ -59,6 +59,18 @@ namespace TagLib {
|
||||
static const char vorbisCommentHeaderID[] = { 0x03, 'v', 'o', 'r', 'b', 'i', 's', 0 };
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// static members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool Vorbis::File::isSupported(IOStream *stream)
|
||||
{
|
||||
// An Ogg Vorbis file has IDs "OggS" and "\x01vorbis" somewhere.
|
||||
|
||||
const ByteVector buffer = Utils::readHeader(stream, bufferSize(), false);
|
||||
return (buffer.find("OggS") >= 0 && buffer.find("\x01vorbis") >= 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
@ -109,7 +121,7 @@ bool Vorbis::File::save()
|
||||
ByteVector v(vorbisCommentHeaderID);
|
||||
|
||||
if(!d->comment)
|
||||
d->comment = new Ogg::XiphComment;
|
||||
d->comment = new Ogg::XiphComment();
|
||||
v.append(d->comment->render());
|
||||
|
||||
setPacket(1, v);
|
||||
|
11
3rdparty/taglib/ogg/vorbis/vorbisfile.h
vendored
11
3rdparty/taglib/ogg/vorbis/vorbisfile.h
vendored
@ -118,12 +118,17 @@ namespace TagLib {
|
||||
* Save the file.
|
||||
*
|
||||
* This returns true if the save was successful.
|
||||
*
|
||||
* \warning In the current implementation, it's dangerous to call save()
|
||||
* repeatedly. It leads to a segfault.
|
||||
*/
|
||||
virtual bool save();
|
||||
|
||||
/*!
|
||||
* Check if the given \a stream can be opened as an Ogg Vorbis file.
|
||||
*
|
||||
* \note This method is designed to do a quick check. The result may
|
||||
* not necessarily be correct.
|
||||
*/
|
||||
static bool isSupported(IOStream *stream);
|
||||
|
||||
private:
|
||||
File(const File &);
|
||||
File &operator=(const File &);
|
||||
|
143
3rdparty/taglib/ogg/xiphcomment.cpp
vendored
143
3rdparty/taglib/ogg/xiphcomment.cpp
vendored
@ -261,10 +261,14 @@ bool Ogg::XiphComment::checkKey(const String &key)
|
||||
{
|
||||
if(key.size() < 1)
|
||||
return false;
|
||||
for(String::ConstIterator it = key.begin(); it != key.end(); it++)
|
||||
// forbid non-printable, non-ascii, '=' (#61) and '~' (#126)
|
||||
if (*it < 32 || *it >= 128 || *it == 61 || *it == 126)
|
||||
|
||||
// A key may consist of ASCII 0x20 through 0x7D, 0x3D ('=') excluded.
|
||||
|
||||
for(String::ConstIterator it = key.begin(); it != key.end(); it++) {
|
||||
if(*it < 0x20 || *it > 0x7D || *it == 0x3D)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -275,11 +279,18 @@ String Ogg::XiphComment::vendorID() const
|
||||
|
||||
void Ogg::XiphComment::addField(const String &key, const String &value, bool replace)
|
||||
{
|
||||
if(!checkKey(key)) {
|
||||
debug("Ogg::XiphComment::addField() - Invalid key. Field not added.");
|
||||
return;
|
||||
}
|
||||
|
||||
const String upperKey = key.upper();
|
||||
|
||||
if(replace)
|
||||
removeFields(key.upper());
|
||||
removeFields(upperKey);
|
||||
|
||||
if(!key.isEmpty() && !value.isEmpty())
|
||||
d->fieldListMap[key.upper()].append(value);
|
||||
d->fieldListMap[upperKey].append(value);
|
||||
}
|
||||
|
||||
void Ogg::XiphComment::removeField(const String &key, const String &value)
|
||||
@ -436,85 +447,69 @@ void Ogg::XiphComment::parse(const ByteVector &data)
|
||||
const unsigned int commentLength = data.toUInt(pos, false);
|
||||
pos += 4;
|
||||
|
||||
ByteVector entry = data.mid(pos, commentLength);
|
||||
|
||||
const ByteVector entry = data.mid(pos, commentLength);
|
||||
pos += commentLength;
|
||||
|
||||
// Don't go past data end
|
||||
|
||||
if(pos > data.size())
|
||||
break;
|
||||
|
||||
// Handle Pictures separately
|
||||
if(entry.startsWith("METADATA_BLOCK_PICTURE=")) {
|
||||
|
||||
// We need base64 encoded data including padding
|
||||
if((entry.size() - 23) > 3 && ((entry.size() - 23) % 4) == 0) {
|
||||
|
||||
// Decode base64 picture data
|
||||
ByteVector picturedata = ByteVector::fromBase64(entry.mid(23));
|
||||
if(picturedata.size()) {
|
||||
|
||||
// Decode Flac Picture
|
||||
FLAC::Picture * picture = new FLAC::Picture();
|
||||
if(picture->parse(picturedata)) {
|
||||
|
||||
d->pictureList.append(picture);
|
||||
|
||||
// continue to next field
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
delete picture;
|
||||
debug("Failed to decode FlacPicture block");
|
||||
}
|
||||
}
|
||||
else {
|
||||
debug("Failed to decode base64 encoded data");
|
||||
}
|
||||
}
|
||||
else {
|
||||
debug("Invalid base64 encoded data");
|
||||
}
|
||||
}
|
||||
|
||||
// Handle old picture standard
|
||||
if(entry.startsWith("COVERART=")) {
|
||||
|
||||
if((entry.size() - 9) > 3 && ((entry.size() - 9) % 4) == 0) {
|
||||
|
||||
// Decode base64 picture data
|
||||
ByteVector picturedata = ByteVector::fromBase64(entry.mid(9));
|
||||
if (picturedata.size()) {
|
||||
|
||||
// Assume it's some type of image file
|
||||
FLAC::Picture * picture = new FLAC::Picture();
|
||||
picture->setData(picturedata);
|
||||
picture->setMimeType("image/");
|
||||
picture->setType(FLAC::Picture::Other);
|
||||
d->pictureList.append(picture);
|
||||
|
||||
// continue to next field
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
debug("Failed to decode base64 encoded data");
|
||||
}
|
||||
}
|
||||
else {
|
||||
debug("Invalid base64 encoded data");
|
||||
}
|
||||
}
|
||||
|
||||
// Check for field separator
|
||||
int sep = entry.find('=');
|
||||
|
||||
const int sep = entry.find('=');
|
||||
if(sep < 1) {
|
||||
debug("Discarding invalid comment field.");
|
||||
debug("Ogg::XiphComment::parse() - Discarding a field. Separator not found.");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Parse key and value
|
||||
String key = String(entry.mid(0, sep), String::UTF8);
|
||||
String value = String(entry.mid(sep + 1), String::UTF8);
|
||||
addField(key, value, false);
|
||||
// Parse the key
|
||||
|
||||
const String key = String(entry.mid(0, sep), String::UTF8).upper();
|
||||
if(!checkKey(key)) {
|
||||
debug("Ogg::XiphComment::parse() - Discarding a field. Invalid key.");
|
||||
continue;
|
||||
}
|
||||
|
||||
if(key == "METADATA_BLOCK_PICTURE" || key == "COVERART") {
|
||||
|
||||
// Handle Pictures separately
|
||||
|
||||
const ByteVector picturedata = ByteVector::fromBase64(entry.mid(sep + 1));
|
||||
if(picturedata.isEmpty()) {
|
||||
debug("Ogg::XiphComment::parse() - Discarding a field. Invalid base64 data");
|
||||
continue;
|
||||
}
|
||||
|
||||
if(key[0] == L'M') {
|
||||
|
||||
// Decode FLAC Picture
|
||||
|
||||
FLAC::Picture * picture = new FLAC::Picture();
|
||||
if(picture->parse(picturedata)) {
|
||||
d->pictureList.append(picture);
|
||||
}
|
||||
else {
|
||||
delete picture;
|
||||
debug("Ogg::XiphComment::parse() - Failed to decode FLAC Picture block");
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
// Assume it's some type of image file
|
||||
|
||||
FLAC::Picture * picture = new FLAC::Picture();
|
||||
picture->setData(picturedata);
|
||||
picture->setMimeType("image/");
|
||||
picture->setType(FLAC::Picture::Other);
|
||||
d->pictureList.append(picture);
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
// Parse the text
|
||||
|
||||
addField(key, String(entry.mid(sep + 1), String::UTF8), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
13
3rdparty/taglib/riff/aiff/aifffile.cpp
vendored
13
3rdparty/taglib/riff/aiff/aifffile.cpp
vendored
@ -28,6 +28,7 @@
|
||||
#include <id3v2tag.h>
|
||||
#include <tstringlist.h>
|
||||
#include <tpropertymap.h>
|
||||
#include <tagutils.h>
|
||||
|
||||
#include "aifffile.h"
|
||||
|
||||
@ -53,6 +54,18 @@ public:
|
||||
bool hasID3v2;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// static members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool RIFF::AIFF::File::isSupported(IOStream *stream)
|
||||
{
|
||||
// An AIFF file has to start with "FORM????AIFF" or "FORM????AIFC".
|
||||
|
||||
const ByteVector id = Utils::readHeader(stream, 12, false);
|
||||
return (id.startsWith("FORM") && (id.containsAt("AIFF", 8) || id.containsAt("AIFC", 8)));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
8
3rdparty/taglib/riff/aiff/aifffile.h
vendored
8
3rdparty/taglib/riff/aiff/aifffile.h
vendored
@ -126,6 +126,14 @@ namespace TagLib {
|
||||
*/
|
||||
bool hasID3v2Tag() const;
|
||||
|
||||
/*!
|
||||
* Check if the given \a stream can be opened as an AIFF file.
|
||||
*
|
||||
* \note This method is designed to do a quick check. The result may
|
||||
* not necessarily be correct.
|
||||
*/
|
||||
static bool isSupported(IOStream *stream);
|
||||
|
||||
private:
|
||||
File(const File &);
|
||||
File &operator=(const File &);
|
||||
|
37
3rdparty/taglib/riff/rifffile.cpp
vendored
37
3rdparty/taglib/riff/rifffile.cpp
vendored
@ -95,13 +95,13 @@ unsigned int RIFF::File::riffSize() const
|
||||
|
||||
unsigned int RIFF::File::chunkCount() const
|
||||
{
|
||||
return d->chunks.size();
|
||||
return static_cast<unsigned int>(d->chunks.size());
|
||||
}
|
||||
|
||||
unsigned int RIFF::File::chunkDataSize(unsigned int i) const
|
||||
{
|
||||
if(i >= d->chunks.size()) {
|
||||
debug("RIFF::File::chunkPadding() - Index out of range. Returning 0.");
|
||||
debug("RIFF::File::chunkDataSize() - Index out of range. Returning 0.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -111,7 +111,7 @@ unsigned int RIFF::File::chunkDataSize(unsigned int i) const
|
||||
unsigned int RIFF::File::chunkOffset(unsigned int i) const
|
||||
{
|
||||
if(i >= d->chunks.size()) {
|
||||
debug("RIFF::File::chunkPadding() - Index out of range. Returning 0.");
|
||||
debug("RIFF::File::chunkOffset() - Index out of range. Returning 0.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -161,19 +161,19 @@ void RIFF::File::setChunkData(unsigned int i, const ByteVector &data)
|
||||
std::vector<Chunk>::iterator it = d->chunks.begin();
|
||||
std::advance(it, i);
|
||||
|
||||
const int originalSize = it->size + it->padding;
|
||||
const long long originalSize = static_cast<long long>(it->size) + it->padding;
|
||||
|
||||
writeChunk(it->name, data, it->offset - 8, it->size + it->padding + 8);
|
||||
|
||||
it->size = data.size();
|
||||
it->padding = data.size() % 1;
|
||||
it->padding = data.size() % 2;
|
||||
|
||||
const int diff = it->size + it->padding - originalSize;
|
||||
const long long diff = static_cast<long long>(it->size) + it->padding - originalSize;
|
||||
|
||||
// Now update the internal offsets
|
||||
|
||||
for(++it; it != d->chunks.end(); ++it)
|
||||
it->offset += diff;
|
||||
it->offset += static_cast<int>(diff);
|
||||
|
||||
// Update the global size.
|
||||
|
||||
@ -187,7 +187,7 @@ void RIFF::File::setChunkData(const ByteVector &name, const ByteVector &data)
|
||||
|
||||
void RIFF::File::setChunkData(const ByteVector &name, const ByteVector &data, bool alwaysCreate)
|
||||
{
|
||||
if(d->chunks.size() == 0) {
|
||||
if(d->chunks.empty()) {
|
||||
debug("RIFF::File::setChunkData - No valid chunks found.");
|
||||
return;
|
||||
}
|
||||
@ -269,7 +269,7 @@ void RIFF::File::removeChunk(unsigned int i)
|
||||
|
||||
void RIFF::File::removeChunk(const ByteVector &name)
|
||||
{
|
||||
for(int i = d->chunks.size() - 1; i >= 0; --i) {
|
||||
for(int i = static_cast<int>(d->chunks.size()) - 1; i >= 0; --i) {
|
||||
if(d->chunks[i].name == name)
|
||||
removeChunk(i);
|
||||
}
|
||||
@ -292,7 +292,6 @@ void RIFF::File::read()
|
||||
d->size = readBlock(4).toUInt(bigEndian);
|
||||
|
||||
offset += 8;
|
||||
seek(offset);
|
||||
|
||||
// + 8: chunk header at least, fix for additional junk bytes
|
||||
while(offset + 8 <= length()) {
|
||||
@ -307,28 +306,24 @@ void RIFF::File::read()
|
||||
break;
|
||||
}
|
||||
|
||||
if(static_cast<long long>(tell()) + chunkSize > length()) {
|
||||
if(static_cast<long long>(offset) + 8 + chunkSize > length()) {
|
||||
debug("RIFF::File::read() -- Chunk '" + chunkName + "' has invalid size (larger than the file size)");
|
||||
setValid(false);
|
||||
break;
|
||||
}
|
||||
|
||||
offset += 8;
|
||||
|
||||
Chunk chunk;
|
||||
chunk.name = chunkName;
|
||||
chunk.size = chunkSize;
|
||||
chunk.offset = offset;
|
||||
chunk.name = chunkName;
|
||||
chunk.size = chunkSize;
|
||||
chunk.offset = offset + 8;
|
||||
chunk.padding = 0;
|
||||
|
||||
offset += chunk.size;
|
||||
|
||||
seek(offset);
|
||||
offset = chunk.offset + chunk.size;
|
||||
|
||||
// Check padding
|
||||
|
||||
chunk.padding = 0;
|
||||
|
||||
if(offset & 1) {
|
||||
seek(offset);
|
||||
const ByteVector iByte = readBlock(1);
|
||||
if(iByte.size() == 1 && iByte[0] == '\0') {
|
||||
chunk.padding = 1;
|
||||
|
21
3rdparty/taglib/riff/wav/wavfile.cpp
vendored
21
3rdparty/taglib/riff/wav/wavfile.cpp
vendored
@ -23,10 +23,11 @@
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#include "tbytevector.h"
|
||||
#include "tdebug.h"
|
||||
#include "tstringlist.h"
|
||||
#include "tpropertymap.h"
|
||||
#include <tbytevector.h>
|
||||
#include <tdebug.h>
|
||||
#include <tstringlist.h>
|
||||
#include <tpropertymap.h>
|
||||
#include <tagutils.h>
|
||||
|
||||
#include "wavfile.h"
|
||||
#include "id3v2tag.h"
|
||||
@ -60,6 +61,18 @@ public:
|
||||
bool hasInfo;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// static members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool RIFF::WAV::File::isSupported(IOStream *stream)
|
||||
{
|
||||
// A WAV file has to start with "RIFF????WAVE".
|
||||
|
||||
const ByteVector id = Utils::readHeader(stream, 12, false);
|
||||
return (id.startsWith("RIFF") && id.containsAt("WAVE", 8));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
9
3rdparty/taglib/riff/wav/wavfile.h
vendored
9
3rdparty/taglib/riff/wav/wavfile.h
vendored
@ -175,6 +175,15 @@ namespace TagLib {
|
||||
*/
|
||||
bool hasInfoTag() const;
|
||||
|
||||
/*!
|
||||
* Returns whether or not the given \a stream can be opened as a WAV
|
||||
* file.
|
||||
*
|
||||
* \note This method is designed to do a quick check. The result may
|
||||
* not necessarily be correct.
|
||||
*/
|
||||
static bool isSupported(IOStream *stream);
|
||||
|
||||
private:
|
||||
File(const File &);
|
||||
File &operator=(const File &);
|
||||
|
2
3rdparty/taglib/s3m/s3mproperties.cpp
vendored
2
3rdparty/taglib/s3m/s3mproperties.cpp
vendored
@ -64,7 +64,7 @@ public:
|
||||
|
||||
S3M::Properties::Properties(AudioProperties::ReadStyle propertiesStyle) :
|
||||
AudioProperties(propertiesStyle),
|
||||
d(new PropertiesPrivate)
|
||||
d(new PropertiesPrivate())
|
||||
{
|
||||
}
|
||||
|
||||
|
5
3rdparty/taglib/taglib_config.h.cmake
vendored
5
3rdparty/taglib/taglib_config.h.cmake
vendored
@ -1,6 +1,11 @@
|
||||
/* taglib_config.h. Generated by cmake from taglib_config.h.cmake */
|
||||
|
||||
#ifndef TAGLIB_TAGLIB_CONFIG_H
|
||||
#define TAGLIB_TAGLIB_CONFIG_H
|
||||
|
||||
/* These values are no longer used. This file is present only for compatibility reasons. */
|
||||
|
||||
#define TAGLIB_WITH_ASF 1
|
||||
#define TAGLIB_WITH_MP4 1
|
||||
|
||||
#endif
|
||||
|
5
3rdparty/taglib/tagunion.cpp
vendored
5
3rdparty/taglib/tagunion.cpp
vendored
@ -79,10 +79,9 @@ public:
|
||||
std::vector<Tag *> tags;
|
||||
};
|
||||
|
||||
TagUnion::TagUnion(Tag *first, Tag *second, Tag *third)
|
||||
TagUnion::TagUnion(Tag *first, Tag *second, Tag *third) :
|
||||
d(new TagUnionPrivate())
|
||||
{
|
||||
d = new TagUnionPrivate;
|
||||
|
||||
d->tags[0] = first;
|
||||
d->tags[1] = second;
|
||||
d->tags[2] = third;
|
||||
|
26
3rdparty/taglib/tagutils.cpp
vendored
26
3rdparty/taglib/tagutils.cpp
vendored
@ -77,3 +77,29 @@ long Utils::findAPE(File *file, long id3v1Location)
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
ByteVector TagLib::Utils::readHeader(IOStream *stream, unsigned int length,
|
||||
bool skipID3v2, long *headerOffset)
|
||||
{
|
||||
if(!stream || !stream->isOpen())
|
||||
return ByteVector();
|
||||
|
||||
const long originalPosition = stream->tell();
|
||||
long bufferOffset = 0;
|
||||
|
||||
if(skipID3v2) {
|
||||
stream->seek(0);
|
||||
const ByteVector data = stream->readBlock(ID3v2::Header::size());
|
||||
if(data.startsWith(ID3v2::Header::fileIdentifier()))
|
||||
bufferOffset = ID3v2::Header(data).completeTagSize();
|
||||
}
|
||||
|
||||
stream->seek(bufferOffset);
|
||||
const ByteVector header = stream->readBlock(length);
|
||||
stream->seek(originalPosition);
|
||||
|
||||
if(headerOffset)
|
||||
*headerOffset = bufferOffset;
|
||||
|
||||
return header;
|
||||
}
|
||||
|
6
3rdparty/taglib/tagutils.h
vendored
6
3rdparty/taglib/tagutils.h
vendored
@ -30,9 +30,12 @@
|
||||
|
||||
#ifndef DO_NOT_DOCUMENT // tell Doxygen not to document this header
|
||||
|
||||
#include <tbytevector.h>
|
||||
|
||||
namespace TagLib {
|
||||
|
||||
class File;
|
||||
class IOStream;
|
||||
|
||||
namespace Utils {
|
||||
|
||||
@ -41,6 +44,9 @@ namespace TagLib {
|
||||
long findID3v2(File *file);
|
||||
|
||||
long findAPE(File *file, long id3v1Location);
|
||||
|
||||
ByteVector readHeader(IOStream *stream, unsigned int length, bool skipID3v2,
|
||||
long *headerOffset = 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
9
3rdparty/taglib/toolkit/taglib.h
vendored
9
3rdparty/taglib/toolkit/taglib.h
vendored
@ -30,7 +30,7 @@
|
||||
|
||||
#define TAGLIB_MAJOR_VERSION 1
|
||||
#define TAGLIB_MINOR_VERSION 11
|
||||
#define TAGLIB_PATCH_VERSION 0
|
||||
#define TAGLIB_PATCH_VERSION 1
|
||||
|
||||
#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 1)) || defined(__clang__)
|
||||
#define TAGLIB_IGNORE_MISSING_DESTRUCTOR _Pragma("GCC diagnostic ignored \"-Wnon-virtual-dtor\"")
|
||||
@ -115,7 +115,7 @@ namespace TagLib {
|
||||
*
|
||||
* \section installing Installing TagLib
|
||||
*
|
||||
* Please see the <a href="http://developer.kde.org/~wheeler/taglib.html">TagLib website</a> for the latest
|
||||
* Please see the <a href="http://taglib.org/">TagLib website</a> for the latest
|
||||
* downloads.
|
||||
*
|
||||
* TagLib can be built using the CMake build system. TagLib installs a taglib-config and pkg-config file to
|
||||
@ -160,11 +160,10 @@ namespace TagLib {
|
||||
*
|
||||
* Questions about TagLib should be directed to the TagLib mailing list, not directly to the author.
|
||||
*
|
||||
* - <a href="http://developer.kde.org/~wheeler/taglib/">TagLib Homepage</a>
|
||||
* - <a href="http://taglib.org/">TagLib Homepage</a>
|
||||
* - <a href="https://mail.kde.org/mailman/listinfo/taglib-devel">TagLib Mailing List (taglib-devel@kde.org)</a>
|
||||
*
|
||||
* \author Scott Wheeler <wheeler@kde.org> et al.
|
||||
*
|
||||
* \author <a href="https://github.com/taglib/taglib/blob/master/AUTHORS">TagLib authors</a>.
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
93
3rdparty/taglib/toolkit/tbytevector.cpp
vendored
93
3rdparty/taglib/toolkit/tbytevector.cpp
vendored
@ -29,7 +29,6 @@
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <cstddef>
|
||||
|
||||
#include <tstring.h>
|
||||
#include <tdebug.h>
|
||||
@ -63,7 +62,7 @@ int findChar(
|
||||
|
||||
for(TIterator it = dataBegin + offset; it < dataEnd; it += byteAlign) {
|
||||
if(*it == c)
|
||||
return (it - dataBegin);
|
||||
return static_cast<int>(it - dataBegin);
|
||||
}
|
||||
|
||||
return -1;
|
||||
@ -105,7 +104,7 @@ int findVector(
|
||||
++itPattern;
|
||||
|
||||
if(itPattern == patternEnd)
|
||||
return (it - dataBegin);
|
||||
return static_cast<int>(it - dataBegin);
|
||||
}
|
||||
}
|
||||
|
||||
@ -125,7 +124,7 @@ T toNumber(const ByteVector &v, size_t offset, size_t length, bool mostSignifica
|
||||
T sum = 0;
|
||||
for(size_t i = 0; i < length; i++) {
|
||||
const size_t shift = (mostSignificantByteFirst ? length - 1 - i : i) * 8;
|
||||
sum |= static_cast<T>(static_cast<unsigned char>(v[offset + i])) << shift;
|
||||
sum |= static_cast<T>(static_cast<unsigned char>(v[static_cast<int>(offset + i)])) << shift;
|
||||
}
|
||||
|
||||
return sum;
|
||||
@ -176,7 +175,7 @@ TFloat toFloat(const ByteVector &v, size_t offset)
|
||||
} tmp;
|
||||
::memcpy(&tmp, v.data() + offset, sizeof(TInt));
|
||||
|
||||
if(ENDIAN != Utils::floatByteOrder())
|
||||
if(ENDIAN != Utils::systemByteOrder())
|
||||
tmp.i = Utils::byteSwap(tmp.i);
|
||||
|
||||
return tmp.f;
|
||||
@ -191,7 +190,7 @@ ByteVector fromFloat(TFloat value)
|
||||
} tmp;
|
||||
tmp.f = value;
|
||||
|
||||
if(ENDIAN != Utils::floatByteOrder())
|
||||
if(ENDIAN != Utils::systemByteOrder())
|
||||
tmp.i = Utils::byteSwap(tmp.i);
|
||||
|
||||
return ByteVector(reinterpret_cast<char *>(&tmp), sizeof(TInt));
|
||||
@ -300,7 +299,7 @@ ByteVector ByteVector::null;
|
||||
ByteVector ByteVector::fromCString(const char *s, unsigned int length)
|
||||
{
|
||||
if(length == 0xffffffff)
|
||||
return ByteVector(s, ::strlen(s));
|
||||
return ByteVector(s, static_cast<unsigned int>(::strlen(s)));
|
||||
else
|
||||
return ByteVector(s, length);
|
||||
}
|
||||
@ -375,7 +374,7 @@ ByteVector::ByteVector(const char *data, unsigned int length) :
|
||||
}
|
||||
|
||||
ByteVector::ByteVector(const char *data) :
|
||||
d(new ByteVectorPrivate(data, ::strlen(data)))
|
||||
d(new ByteVectorPrivate(data, static_cast<unsigned int>(::strlen(data))))
|
||||
{
|
||||
}
|
||||
|
||||
@ -485,46 +484,60 @@ ByteVector &ByteVector::replace(char oldByte, char newByte)
|
||||
|
||||
ByteVector &ByteVector::replace(const ByteVector &pattern, const ByteVector &with)
|
||||
{
|
||||
// TODO: This takes O(n!) time in the worst case. Rewrite it to run in O(n) time.
|
||||
|
||||
if(pattern.size() == 0 || pattern.size() > size())
|
||||
return *this;
|
||||
|
||||
if(pattern.size() == 1 && with.size() == 1)
|
||||
return replace(pattern[0], with[0]);
|
||||
|
||||
const size_t withSize = with.size();
|
||||
const size_t patternSize = pattern.size();
|
||||
const ptrdiff_t diff = withSize - patternSize;
|
||||
// Check if there is at least one occurrence of the pattern.
|
||||
|
||||
size_t offset = 0;
|
||||
while (true) {
|
||||
offset = find(pattern, offset);
|
||||
if(offset == static_cast<size_t>(-1)) // Use npos in taglib2.
|
||||
break;
|
||||
int offset = find(pattern, 0);
|
||||
if(offset == -1)
|
||||
return *this;
|
||||
|
||||
if(pattern.size() == with.size()) {
|
||||
|
||||
// We think this case might be common enough to optimize it.
|
||||
|
||||
detach();
|
||||
do
|
||||
{
|
||||
::memcpy(data() + offset, with.data(), with.size());
|
||||
offset = find(pattern, offset + pattern.size());
|
||||
} while(offset != -1);
|
||||
}
|
||||
else {
|
||||
|
||||
if(diff < 0) {
|
||||
::memmove(
|
||||
data() + offset + withSize,
|
||||
data() + offset + patternSize,
|
||||
size() - offset - patternSize);
|
||||
resize(size() + diff);
|
||||
}
|
||||
else if(diff > 0) {
|
||||
resize(size() + diff);
|
||||
::memmove(
|
||||
data() + offset + withSize,
|
||||
data() + offset + patternSize,
|
||||
size() - diff - offset - patternSize);
|
||||
// Loop once to calculate the result size.
|
||||
|
||||
unsigned int dstSize = size();
|
||||
do
|
||||
{
|
||||
dstSize += with.size() - pattern.size();
|
||||
offset = find(pattern, offset + pattern.size());
|
||||
} while(offset != -1);
|
||||
|
||||
// Loop again to copy modified data to the new vector.
|
||||
|
||||
ByteVector dst(dstSize);
|
||||
int dstOffset = 0;
|
||||
|
||||
offset = 0;
|
||||
while(true) {
|
||||
const int next = find(pattern, offset);
|
||||
if(next == -1) {
|
||||
::memcpy(dst.data() + dstOffset, data() + offset, size() - offset);
|
||||
break;
|
||||
}
|
||||
|
||||
::memcpy(dst.data() + dstOffset, data() + offset, next - offset);
|
||||
dstOffset += next - offset;
|
||||
|
||||
::memcpy(dst.data() + dstOffset, with.data(), with.size());
|
||||
dstOffset += with.size();
|
||||
|
||||
offset = next + pattern.size();
|
||||
}
|
||||
|
||||
::memcpy(data() + offset, with.data(), with.size());
|
||||
|
||||
offset += withSize;
|
||||
if(offset > size() - patternSize)
|
||||
break;
|
||||
swap(dst);
|
||||
}
|
||||
|
||||
return *this;
|
||||
@ -963,7 +976,7 @@ ByteVector ByteVector::fromBase64(const ByteVector & input)
|
||||
|
||||
// Only return output if we processed all bytes
|
||||
if(len == 0) {
|
||||
output.resize(dst - (unsigned char*) output.data());
|
||||
output.resize(static_cast<unsigned int>(dst - (unsigned char*) output.data()));
|
||||
return output;
|
||||
}
|
||||
return ByteVector();
|
||||
|
@ -53,9 +53,9 @@ ByteVectorStream::ByteVectorStreamPrivate::ByteVectorStreamPrivate(const ByteVec
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ByteVectorStream::ByteVectorStream(const ByteVector &data)
|
||||
ByteVectorStream::ByteVectorStream(const ByteVector &data) :
|
||||
d(new ByteVectorStreamPrivate(data))
|
||||
{
|
||||
d = new ByteVectorStreamPrivate(data);
|
||||
}
|
||||
|
||||
ByteVectorStream::~ByteVectorStream()
|
||||
@ -137,7 +137,7 @@ void ByteVectorStream::seek(long offset, Position p)
|
||||
d->position += offset;
|
||||
break;
|
||||
case End:
|
||||
d->position = length() - offset;
|
||||
d->position = length() + offset; // offset is expected to be negative
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
21
3rdparty/taglib/toolkit/tdebug.cpp
vendored
21
3rdparty/taglib/toolkit/tdebug.cpp
vendored
@ -27,6 +27,8 @@
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#if !defined(NDEBUG) || defined(TRACE_IN_RELEASE)
|
||||
|
||||
#include "tdebug.h"
|
||||
#include "tstring.h"
|
||||
#include "tdebuglistener.h"
|
||||
@ -43,27 +45,20 @@ namespace TagLib
|
||||
|
||||
void debug(const String &s)
|
||||
{
|
||||
#if !defined(NDEBUG) || defined(TRACE_IN_RELEASE)
|
||||
|
||||
debugListener->printMessage("TagLib: " + s + "\n");
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void debugData(const ByteVector &v)
|
||||
{
|
||||
#if !defined(NDEBUG) || defined(TRACE_IN_RELEASE)
|
||||
|
||||
for(size_t i = 0; i < v.size(); ++i)
|
||||
{
|
||||
std::string bits = std::bitset<8>(v[i]).to_string();
|
||||
String msg = Utils::formatString(
|
||||
"*** [%d] - char '%c' - int %d, 0x%02x, 0b%s\n",
|
||||
for(unsigned int i = 0; i < v.size(); ++i) {
|
||||
const std::string bits = std::bitset<8>(v[i]).to_string();
|
||||
const String msg = Utils::formatString(
|
||||
"*** [%u] - char '%c' - int %d, 0x%02x, 0b%s\n",
|
||||
i, v[i], v[i], v[i], bits.c_str());
|
||||
|
||||
debugListener->printMessage(msg);
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
14
3rdparty/taglib/toolkit/tdebug.h
vendored
14
3rdparty/taglib/toolkit/tdebug.h
vendored
@ -32,10 +32,11 @@ namespace TagLib {
|
||||
class ByteVector;
|
||||
|
||||
#ifndef DO_NOT_DOCUMENT
|
||||
#if !defined(NDEBUG) || defined(TRACE_IN_RELEASE)
|
||||
|
||||
/*!
|
||||
* A simple function that outputs the debug messages to the listener.
|
||||
* The default listener redirects the messages to \a stderr when NDEBUG is
|
||||
* A simple function that outputs the debug messages to the listener.
|
||||
* The default listener redirects the messages to \a stderr when NDEBUG is
|
||||
* not defined.
|
||||
*
|
||||
* \warning Do not use this outside of TagLib, it could lead to undefined
|
||||
@ -45,7 +46,7 @@ namespace TagLib {
|
||||
* \internal
|
||||
*/
|
||||
void debug(const String &s);
|
||||
|
||||
|
||||
/*!
|
||||
* For debugging binary data.
|
||||
*
|
||||
@ -56,6 +57,13 @@ namespace TagLib {
|
||||
* \internal
|
||||
*/
|
||||
void debugData(const ByteVector &v);
|
||||
|
||||
#else
|
||||
|
||||
#define debug(x) ((void)0)
|
||||
#define debugData(x) ((void)0)
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
29
3rdparty/taglib/toolkit/tfile.cpp
vendored
29
3rdparty/taglib/toolkit/tfile.cpp
vendored
@ -69,39 +69,38 @@ using namespace TagLib;
|
||||
class File::FilePrivate
|
||||
{
|
||||
public:
|
||||
FilePrivate(IOStream *stream, bool owner);
|
||||
FilePrivate(IOStream *stream, bool owner) :
|
||||
stream(stream),
|
||||
streamOwner(owner),
|
||||
valid(true) {}
|
||||
|
||||
~FilePrivate()
|
||||
{
|
||||
if(streamOwner)
|
||||
delete stream;
|
||||
}
|
||||
|
||||
IOStream *stream;
|
||||
bool streamOwner;
|
||||
bool valid;
|
||||
};
|
||||
|
||||
File::FilePrivate::FilePrivate(IOStream *stream, bool owner) :
|
||||
stream(stream),
|
||||
streamOwner(owner),
|
||||
valid(true)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
File::File(FileName fileName)
|
||||
File::File(FileName fileName) :
|
||||
d(new FilePrivate(new FileStream(fileName), true))
|
||||
{
|
||||
IOStream *stream = new FileStream(fileName);
|
||||
d = new FilePrivate(stream, true);
|
||||
}
|
||||
|
||||
File::File(IOStream *stream)
|
||||
File::File(IOStream *stream) :
|
||||
d(new FilePrivate(stream, false))
|
||||
{
|
||||
d = new FilePrivate(stream, false);
|
||||
}
|
||||
|
||||
File::~File()
|
||||
{
|
||||
if(d->stream && d->streamOwner)
|
||||
delete d->stream;
|
||||
delete d;
|
||||
}
|
||||
|
||||
|
2
3rdparty/taglib/toolkit/tfile.h
vendored
2
3rdparty/taglib/toolkit/tfile.h
vendored
@ -86,7 +86,7 @@ namespace TagLib {
|
||||
* format, the returned map's unsupportedData() list will contain one entry identifying
|
||||
* that object (e.g. the frame type for ID3v2 tags). Use removeUnsupportedProperties()
|
||||
* to remove (a subset of) them.
|
||||
* For files that contain more than one tag (e.g. an MP3 with both an ID3v2 and an ID3v2
|
||||
* For files that contain more than one tag (e.g. an MP3 with both an ID3v1 and an ID3v2
|
||||
* tag) only the most "modern" one will be exported (ID3v2 in this case).
|
||||
* BIC: Will be made virtual in future releases.
|
||||
*/
|
||||
|
59
3rdparty/taglib/toolkit/tfilestream.cpp
vendored
59
3rdparty/taglib/toolkit/tfilestream.cpp
vendored
@ -51,12 +51,11 @@ namespace
|
||||
{
|
||||
const DWORD access = readOnly ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE);
|
||||
|
||||
if(!path.wstr().empty())
|
||||
return CreateFileW(path.wstr().c_str(), access, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
else if(!path.str().empty())
|
||||
return CreateFileA(path.str().c_str(), access, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
else
|
||||
return InvalidFileHandle;
|
||||
#if defined (PLATFORM_WINRT)
|
||||
return CreateFile2(path.wstr().c_str(), access, FILE_SHARE_READ, OPEN_EXISTING, NULL);
|
||||
#else
|
||||
return CreateFileW(path.wstr().c_str(), access, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void closeFile(FileHandle file)
|
||||
@ -262,7 +261,7 @@ void FileStream::insert(const ByteVector &data, unsigned long start, unsigned lo
|
||||
// to overwrite. Appropriately increment the readPosition.
|
||||
|
||||
seek(readPosition);
|
||||
const size_t bytesRead = readFile(d->file, aboutToOverwrite);
|
||||
const unsigned int bytesRead = static_cast<unsigned int>(readFile(d->file, aboutToOverwrite));
|
||||
aboutToOverwrite.resize(bytesRead);
|
||||
readPosition += bufferLength;
|
||||
|
||||
@ -305,10 +304,10 @@ void FileStream::removeBlock(unsigned long start, unsigned long length)
|
||||
|
||||
ByteVector buffer(static_cast<unsigned int>(bufferLength));
|
||||
|
||||
for(size_t bytesRead = -1; bytesRead != 0;)
|
||||
for(unsigned int bytesRead = -1; bytesRead != 0;)
|
||||
{
|
||||
seek(readPosition);
|
||||
bytesRead = readFile(d->file, buffer);
|
||||
bytesRead = static_cast<unsigned int>(readFile(d->file, buffer));
|
||||
readPosition += bytesRead;
|
||||
|
||||
// Check to see if we just read the last block. We need to call clear()
|
||||
@ -347,28 +346,17 @@ void FileStream::seek(long offset, Position p)
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
DWORD whence;
|
||||
switch(p) {
|
||||
case Beginning:
|
||||
whence = FILE_BEGIN;
|
||||
break;
|
||||
case Current:
|
||||
whence = FILE_CURRENT;
|
||||
break;
|
||||
case End:
|
||||
whence = FILE_END;
|
||||
break;
|
||||
default:
|
||||
if(p != Beginning && p != Current && p != End) {
|
||||
debug("FileStream::seek() -- Invalid Position value.");
|
||||
return;
|
||||
}
|
||||
|
||||
SetLastError(NO_ERROR);
|
||||
SetFilePointer(d->file, offset, NULL, whence);
|
||||
LARGE_INTEGER liOffset;
|
||||
liOffset.QuadPart = offset;
|
||||
|
||||
const int lastError = GetLastError();
|
||||
if(lastError != NO_ERROR && lastError != ERROR_NEGATIVE_SEEK)
|
||||
if(!SetFilePointerEx(d->file, liOffset, NULL, static_cast<DWORD>(p))) {
|
||||
debug("FileStream::seek() -- Failed to set the file pointer.");
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
@ -410,10 +398,11 @@ long FileStream::tell() const
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
SetLastError(NO_ERROR);
|
||||
const DWORD position = SetFilePointer(d->file, 0, NULL, FILE_CURRENT);
|
||||
if(GetLastError() == NO_ERROR) {
|
||||
return static_cast<long>(position);
|
||||
const LARGE_INTEGER zero = {};
|
||||
LARGE_INTEGER position;
|
||||
|
||||
if(SetFilePointerEx(d->file, zero, &position, FILE_CURRENT) && position.QuadPart <= LONG_MAX) {
|
||||
return static_cast<long>(position.QuadPart);
|
||||
}
|
||||
else {
|
||||
debug("FileStream::tell() -- Failed to get the file pointer.");
|
||||
@ -436,10 +425,10 @@ long FileStream::length()
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
SetLastError(NO_ERROR);
|
||||
const DWORD fileSize = GetFileSize(d->file, NULL);
|
||||
if(GetLastError() == NO_ERROR) {
|
||||
return static_cast<long>(fileSize);
|
||||
LARGE_INTEGER fileSize;
|
||||
|
||||
if(GetFileSizeEx(d->file, &fileSize) && fileSize.QuadPart <= LONG_MAX) {
|
||||
return static_cast<long>(fileSize.QuadPart);
|
||||
}
|
||||
else {
|
||||
debug("FileStream::length() -- Failed to get the file size.");
|
||||
@ -472,9 +461,7 @@ void FileStream::truncate(long length)
|
||||
|
||||
seek(length);
|
||||
|
||||
SetLastError(NO_ERROR);
|
||||
SetEndOfFile(d->file);
|
||||
if(GetLastError() != NO_ERROR) {
|
||||
if(!SetEndOfFile(d->file)) {
|
||||
debug("FileStream::truncate() -- Failed to truncate the file.");
|
||||
}
|
||||
|
||||
|
84
3rdparty/taglib/toolkit/tiostream.cpp
vendored
84
3rdparty/taglib/toolkit/tiostream.cpp
vendored
@ -23,73 +23,49 @@
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <windows.h>
|
||||
# include <tstring.h>
|
||||
#endif
|
||||
|
||||
#include "tiostream.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
# include "tstring.h"
|
||||
# include "tdebug.h"
|
||||
# include <windows.h>
|
||||
|
||||
namespace
|
||||
{
|
||||
// Check if the running system has CreateFileW() function.
|
||||
// Windows9x systems don't have CreateFileW() or can't accept Unicode file names.
|
||||
|
||||
bool supportsUnicode()
|
||||
std::wstring ansiToUnicode(const char *str)
|
||||
{
|
||||
#ifdef UNICODE
|
||||
return true;
|
||||
#else
|
||||
const FARPROC p = GetProcAddress(GetModuleHandleA("kernel32"), "CreateFileW");
|
||||
return (p != NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Indicates whether the system supports Unicode file names.
|
||||
|
||||
const bool SystemSupportsUnicode = supportsUnicode();
|
||||
|
||||
// Converts a UTF-16 string into a local encoding.
|
||||
// This function should only be used in Windows9x systems which don't support
|
||||
// Unicode file names.
|
||||
|
||||
std::string unicodeToAnsi(const wchar_t *wstr)
|
||||
{
|
||||
if(SystemSupportsUnicode) {
|
||||
debug("unicodeToAnsi() - Should not be used on WinNT systems.");
|
||||
}
|
||||
|
||||
const int len = WideCharToMultiByte(CP_ACP, 0, wstr, -1, NULL, 0, NULL, NULL);
|
||||
const int len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
|
||||
if(len == 0)
|
||||
return std::string();
|
||||
return std::wstring();
|
||||
|
||||
std::string str(len, '\0');
|
||||
WideCharToMultiByte(CP_ACP, 0, wstr, -1, &str[0], len, NULL, NULL);
|
||||
std::wstring wstr(len - 1, L'\0');
|
||||
MultiByteToWideChar(CP_ACP, 0, str, -1, &wstr[0], len);
|
||||
|
||||
return str;
|
||||
return wstr;
|
||||
}
|
||||
}
|
||||
|
||||
// If WinNT, stores a Unicode string into m_wname directly.
|
||||
// If Win9x, converts and stores it into m_name to avoid calling Unicode version functions.
|
||||
// m_name is no longer used, but kept for backward compatibility.
|
||||
|
||||
FileName::FileName(const wchar_t *name)
|
||||
: m_name (SystemSupportsUnicode ? "" : unicodeToAnsi(name))
|
||||
, m_wname(SystemSupportsUnicode ? name : L"")
|
||||
FileName::FileName(const wchar_t *name) :
|
||||
m_name(),
|
||||
m_wname(name)
|
||||
{
|
||||
}
|
||||
|
||||
FileName::FileName(const char *name)
|
||||
: m_name(name)
|
||||
FileName::FileName(const char *name) :
|
||||
m_name(),
|
||||
m_wname(ansiToUnicode(name))
|
||||
{
|
||||
}
|
||||
|
||||
FileName::FileName(const FileName &name)
|
||||
: m_name (name.m_name)
|
||||
, m_wname(name.m_wname)
|
||||
FileName::FileName(const FileName &name) :
|
||||
m_name(),
|
||||
m_wname(name.m_wname)
|
||||
{
|
||||
}
|
||||
|
||||
@ -115,25 +91,9 @@ const std::string &FileName::str() const
|
||||
|
||||
String FileName::toString() const
|
||||
{
|
||||
if(!m_wname.empty()) {
|
||||
return String(m_wname);
|
||||
}
|
||||
else if(!m_name.empty()) {
|
||||
const int len = MultiByteToWideChar(CP_ACP, 0, m_name.c_str(), -1, NULL, 0);
|
||||
if(len == 0)
|
||||
return String();
|
||||
|
||||
std::vector<wchar_t> buf(len);
|
||||
MultiByteToWideChar(CP_ACP, 0, m_name.c_str(), -1, &buf[0], len);
|
||||
|
||||
return String(&buf[0]);
|
||||
}
|
||||
else {
|
||||
return String();
|
||||
}
|
||||
return String(m_wname.c_str());
|
||||
}
|
||||
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
5
3rdparty/taglib/toolkit/tlist.h
vendored
5
3rdparty/taglib/toolkit/tlist.h
vendored
@ -229,6 +229,11 @@ namespace TagLib {
|
||||
*/
|
||||
List<T> &operator=(const List<T> &l);
|
||||
|
||||
/*!
|
||||
* Exchanges the content of this list by the content of \a l.
|
||||
*/
|
||||
void swap(List<T> &l);
|
||||
|
||||
/*!
|
||||
* Compares this list with \a l and returns true if all of the elements are
|
||||
* the same.
|
||||
|
22
3rdparty/taglib/toolkit/tlist.tcc
vendored
22
3rdparty/taglib/toolkit/tlist.tcc
vendored
@ -89,9 +89,9 @@ public:
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class T>
|
||||
List<T>::List()
|
||||
List<T>::List() :
|
||||
d(new ListPrivate<T>())
|
||||
{
|
||||
d = new ListPrivate<T>;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
@ -196,7 +196,7 @@ List<T> &List<T>::clear()
|
||||
template <class T>
|
||||
unsigned int List<T>::size() const
|
||||
{
|
||||
return d->list.size();
|
||||
return static_cast<unsigned int>(d->list.size());
|
||||
}
|
||||
|
||||
template <class T>
|
||||
@ -283,16 +283,18 @@ const T &List<T>::operator[](unsigned int i) const
|
||||
template <class T>
|
||||
List<T> &List<T>::operator=(const List<T> &l)
|
||||
{
|
||||
if(&l == this)
|
||||
return *this;
|
||||
|
||||
if(d->deref())
|
||||
delete d;
|
||||
d = l.d;
|
||||
d->ref();
|
||||
List<T>(l).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
void List<T>::swap(List<T> &l)
|
||||
{
|
||||
using std::swap;
|
||||
|
||||
swap(d, l.d);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool List<T>::operator==(const List<T> &l) const
|
||||
{
|
||||
|
5
3rdparty/taglib/toolkit/tmap.h
vendored
5
3rdparty/taglib/toolkit/tmap.h
vendored
@ -174,6 +174,11 @@ namespace TagLib {
|
||||
*/
|
||||
Map<Key, T> &operator=(const Map<Key, T> &m);
|
||||
|
||||
/*!
|
||||
* Exchanges the content of this map by the content of \a m.
|
||||
*/
|
||||
void swap(Map<Key, T> &m);
|
||||
|
||||
protected:
|
||||
/*
|
||||
* If this List is being shared via implicit sharing, do a deep copy of the
|
||||
|
22
3rdparty/taglib/toolkit/tmap.tcc
vendored
22
3rdparty/taglib/toolkit/tmap.tcc
vendored
@ -48,9 +48,9 @@ public:
|
||||
};
|
||||
|
||||
template <class Key, class T>
|
||||
Map<Key, T>::Map()
|
||||
Map<Key, T>::Map() :
|
||||
d(new MapPrivate<Key, T>())
|
||||
{
|
||||
d = new MapPrivate<Key, T>;
|
||||
}
|
||||
|
||||
template <class Key, class T>
|
||||
@ -152,7 +152,7 @@ Map<Key, T> &Map<Key,T>::erase(const Key &key)
|
||||
template <class Key, class T>
|
||||
unsigned int Map<Key, T>::size() const
|
||||
{
|
||||
return d->map.size();
|
||||
return static_cast<unsigned int>(d->map.size());
|
||||
}
|
||||
|
||||
template <class Key, class T>
|
||||
@ -171,16 +171,18 @@ T &Map<Key, T>::operator[](const Key &key)
|
||||
template <class Key, class T>
|
||||
Map<Key, T> &Map<Key, T>::operator=(const Map<Key, T> &m)
|
||||
{
|
||||
if(&m == this)
|
||||
return *this;
|
||||
|
||||
if(d->deref())
|
||||
delete(d);
|
||||
d = m.d;
|
||||
d->ref();
|
||||
Map<Key, T>(m).swap(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Key, class T>
|
||||
void Map<Key, T>::swap(Map<Key, T> &m)
|
||||
{
|
||||
using std::swap;
|
||||
|
||||
swap(d, m.d);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
11
3rdparty/taglib/toolkit/trefcounter.cpp
vendored
11
3rdparty/taglib/toolkit/trefcounter.cpp
vendored
@ -31,14 +31,9 @@
|
||||
|
||||
#if defined(HAVE_STD_ATOMIC)
|
||||
# include <atomic>
|
||||
# define ATOMIC_INT std::atomic<unsigned int>
|
||||
# define ATOMIC_INC(x) x.fetch_add(1)
|
||||
# define ATOMIC_DEC(x) (x.fetch_sub(1) - 1)
|
||||
#elif defined(HAVE_BOOST_ATOMIC)
|
||||
# include <boost/atomic.hpp>
|
||||
# define ATOMIC_INT boost::atomic<unsigned int>
|
||||
# define ATOMIC_INC(x) x.fetch_add(1)
|
||||
# define ATOMIC_DEC(x) (x.fetch_sub(1) - 1)
|
||||
# define ATOMIC_INT std::atomic_int
|
||||
# define ATOMIC_INC(x) (++x)
|
||||
# define ATOMIC_DEC(x) (--x)
|
||||
#elif defined(HAVE_GCC_ATOMIC)
|
||||
# define ATOMIC_INT int
|
||||
# define ATOMIC_INC(x) __sync_add_and_fetch(&x, 1)
|
||||
|
1
3rdparty/taglib/toolkit/trefcounter.h
vendored
1
3rdparty/taglib/toolkit/trefcounter.h
vendored
@ -30,6 +30,7 @@
|
||||
#include "taglib.h"
|
||||
|
||||
#ifdef __APPLE__
|
||||
# define OSATOMIC_DEPRECATED 0
|
||||
# include <libkern/OSAtomic.h>
|
||||
# define TAGLIB_ATOMIC_MAC
|
||||
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
|
||||
|
255
3rdparty/taglib/toolkit/tstring.cpp
vendored
255
3rdparty/taglib/toolkit/tstring.cpp
vendored
@ -23,19 +23,10 @@
|
||||
* http://www.mozilla.org/MPL/ *
|
||||
***************************************************************************/
|
||||
|
||||
// This class assumes that std::basic_string<T> has a contiguous and null-terminated buffer.
|
||||
|
||||
#include <iostream>
|
||||
#include <cerrno>
|
||||
#include <climits>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#ifdef _WIN32
|
||||
# include <windows.h>
|
||||
#else
|
||||
# include "unicode.h"
|
||||
#endif
|
||||
#include <utf8-cpp/checked.h>
|
||||
|
||||
#include <tdebug.h>
|
||||
#include <tstringlist.h>
|
||||
@ -48,70 +39,6 @@ namespace
|
||||
{
|
||||
using namespace TagLib;
|
||||
|
||||
size_t UTF16toUTF8(const wchar_t *src, size_t srcLength, char *dst, size_t dstLength)
|
||||
{
|
||||
size_t len = 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
len = ::WideCharToMultiByte(CP_UTF8, 0, src, srcLength, dst, dstLength, NULL, NULL);
|
||||
|
||||
#else
|
||||
|
||||
using namespace Unicode;
|
||||
|
||||
const UTF16 *srcBegin = src;
|
||||
const UTF16 *srcEnd = srcBegin + srcLength;
|
||||
|
||||
UTF8 *dstBegin = reinterpret_cast<UTF8*>(dst);
|
||||
UTF8 *dstEnd = dstBegin + dstLength;
|
||||
|
||||
ConversionResult result = ConvertUTF16toUTF8(
|
||||
&srcBegin, srcEnd, &dstBegin, dstEnd, lenientConversion);
|
||||
|
||||
if(result == conversionOK)
|
||||
len = dstBegin - reinterpret_cast<UTF8*>(dst);
|
||||
|
||||
#endif
|
||||
|
||||
if(len == 0)
|
||||
debug("String::UTF16toUTF8() - Unicode conversion error.");
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
size_t UTF8toUTF16(const char *src, size_t srcLength, wchar_t *dst, size_t dstLength)
|
||||
{
|
||||
size_t len = 0;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
len = ::MultiByteToWideChar(CP_UTF8, 0, src, srcLength, dst, dstLength);
|
||||
|
||||
#else
|
||||
|
||||
using namespace Unicode;
|
||||
|
||||
const UTF8 *srcBegin = reinterpret_cast<const UTF8*>(src);
|
||||
const UTF8 *srcEnd = srcBegin + srcLength;
|
||||
|
||||
UTF16 *dstBegin = dst;
|
||||
UTF16 *dstEnd = dstBegin + dstLength;
|
||||
|
||||
ConversionResult result = ConvertUTF8toUTF16(
|
||||
&srcBegin, srcEnd, &dstBegin, dstEnd, lenientConversion);
|
||||
|
||||
if(result == conversionOK)
|
||||
len = dstBegin - dst;
|
||||
|
||||
#endif
|
||||
|
||||
if(len == 0)
|
||||
debug("String::UTF8toUTF16() - Unicode conversion error.");
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
// Returns the native format of std::wstring.
|
||||
String::Type wcharByteOrder()
|
||||
{
|
||||
@ -137,28 +64,61 @@ namespace
|
||||
{
|
||||
data.resize(length);
|
||||
|
||||
if(length > 0) {
|
||||
const size_t len = UTF8toUTF16(s, length, &data[0], data.size());
|
||||
data.resize(len);
|
||||
try {
|
||||
const std::wstring::iterator dstEnd = utf8::utf8to16(s, s + length, data.begin());
|
||||
data.resize(dstEnd - data.begin());
|
||||
}
|
||||
catch(const utf8::exception &e) {
|
||||
const String message(e.what());
|
||||
debug("String::copyFromUTF8() - UTF8-CPP error: " + message);
|
||||
data.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// Helper functions to read a UTF-16 character from an array.
|
||||
template <typename T>
|
||||
unsigned short nextUTF16(const T **p);
|
||||
|
||||
template <>
|
||||
unsigned short nextUTF16<wchar_t>(const wchar_t **p)
|
||||
{
|
||||
return static_cast<unsigned short>(*(*p)++);
|
||||
}
|
||||
|
||||
template <>
|
||||
unsigned short nextUTF16<char>(const char **p)
|
||||
{
|
||||
union {
|
||||
unsigned short w;
|
||||
char c[2];
|
||||
} u;
|
||||
u.c[0] = *(*p)++;
|
||||
u.c[1] = *(*p)++;
|
||||
return u.w;
|
||||
}
|
||||
|
||||
// Converts a UTF-16 (with BOM), UTF-16LE or UTF16-BE string into
|
||||
// UTF-16(without BOM/CPU byte order) and copies it to the internal buffer.
|
||||
void copyFromUTF16(std::wstring &data, const wchar_t *s, size_t length, String::Type t)
|
||||
template <typename T>
|
||||
void copyFromUTF16(std::wstring &data, const T *s, size_t length, String::Type t)
|
||||
{
|
||||
bool swap;
|
||||
if(t == String::UTF16) {
|
||||
if(length >= 1 && s[0] == 0xfeff)
|
||||
swap = false; // Same as CPU endian. No need to swap bytes.
|
||||
else if(length >= 1 && s[0] == 0xfffe)
|
||||
swap = true; // Not same as CPU endian. Need to swap bytes.
|
||||
else {
|
||||
debug("String::copyFromUTF16() - Invalid UTF16 string.");
|
||||
if(length < 1) {
|
||||
debug("String::copyFromUTF16() - Invalid UTF16 string. Too short to have a BOM.");
|
||||
return;
|
||||
}
|
||||
|
||||
const unsigned short bom = nextUTF16(&s);
|
||||
if(bom == 0xfeff)
|
||||
swap = false; // Same as CPU endian. No need to swap bytes.
|
||||
else if(bom == 0xfffe)
|
||||
swap = true; // Not same as CPU endian. Need to swap bytes.
|
||||
else {
|
||||
debug("String::copyFromUTF16() - Invalid UTF16 string. BOM is broken.");
|
||||
return;
|
||||
}
|
||||
|
||||
s++;
|
||||
length--;
|
||||
}
|
||||
else {
|
||||
@ -166,57 +126,12 @@ namespace
|
||||
}
|
||||
|
||||
data.resize(length);
|
||||
if(length > 0) {
|
||||
if(swap) {
|
||||
for(size_t i = 0; i < length; ++i)
|
||||
data[i] = Utils::byteSwap(static_cast<unsigned short>(s[i]));
|
||||
}
|
||||
else {
|
||||
::wmemcpy(&data[0], s, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Converts a UTF-16 (with BOM), UTF-16LE or UTF16-BE string into
|
||||
// UTF-16(without BOM/CPU byte order) and copies it to the internal buffer.
|
||||
void copyFromUTF16(std::wstring &data, const char *s, size_t length, String::Type t)
|
||||
{
|
||||
bool swap;
|
||||
if(t == String::UTF16) {
|
||||
if(length < 2) {
|
||||
debug("String::copyFromUTF16() - Invalid UTF16 string.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Uses memcpy instead of reinterpret_cast to avoid an alignment exception.
|
||||
unsigned short bom;
|
||||
::memcpy(&bom, s, 2);
|
||||
|
||||
if(bom == 0xfeff)
|
||||
swap = false; // Same as CPU endian. No need to swap bytes.
|
||||
else if(bom == 0xfffe)
|
||||
swap = true; // Not same as CPU endian. Need to swap bytes.
|
||||
else {
|
||||
debug("String::copyFromUTF16() - Invalid UTF16 string.");
|
||||
return;
|
||||
}
|
||||
|
||||
s += 2;
|
||||
length -= 2;
|
||||
}
|
||||
else {
|
||||
swap = (t != wcharByteOrder());
|
||||
}
|
||||
|
||||
data.resize(length / 2);
|
||||
for(size_t i = 0; i < length / 2; ++i) {
|
||||
unsigned short c;
|
||||
::memcpy(&c, s, 2);
|
||||
for(size_t i = 0; i < length; ++i) {
|
||||
const unsigned short c = nextUTF16(&s);
|
||||
if(swap)
|
||||
c = Utils::byteSwap(c);
|
||||
|
||||
data[i] = static_cast<wchar_t>(c);
|
||||
s += 2;
|
||||
data[i] = Utils::byteSwap(c);
|
||||
else
|
||||
data[i] = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -229,10 +144,6 @@ public:
|
||||
StringPrivate() :
|
||||
RefCounter() {}
|
||||
|
||||
StringPrivate(unsigned int n, wchar_t c) :
|
||||
RefCounter(),
|
||||
data(static_cast<size_t>(n), c) {}
|
||||
|
||||
/*!
|
||||
* Stores string in UTF-16. The byte order depends on the CPU endian.
|
||||
*/
|
||||
@ -332,9 +243,13 @@ String::String(wchar_t c, Type t) :
|
||||
}
|
||||
|
||||
String::String(char c, Type t) :
|
||||
d(new StringPrivate(1, static_cast<unsigned char>(c)))
|
||||
d(new StringPrivate())
|
||||
{
|
||||
if(t != Latin1 && t != UTF8) {
|
||||
if(t == Latin1)
|
||||
copyFromLatin1(d->data, &c, 1);
|
||||
else if(t == String::UTF8)
|
||||
copyFromUTF8(d->data, &c, 1);
|
||||
else {
|
||||
debug("String::String() -- char should not contain UTF16.");
|
||||
}
|
||||
}
|
||||
@ -350,7 +265,7 @@ String::String(const ByteVector &v, Type t) :
|
||||
else if(t == UTF8)
|
||||
copyFromUTF8(d->data, v.data(), v.size());
|
||||
else
|
||||
copyFromUTF16(d->data, v.data(), v.size(), t);
|
||||
copyFromUTF16(d->data, v.data(), v.size() / 2, t);
|
||||
|
||||
// If we hit a null in the ByteVector, shrink the string again.
|
||||
d->data.resize(::wcslen(d->data.c_str()));
|
||||
@ -410,12 +325,12 @@ String::ConstIterator String::end() const
|
||||
|
||||
int String::find(const String &s, int offset) const
|
||||
{
|
||||
return d->data.find(s.d->data, offset);
|
||||
return static_cast<int>(d->data.find(s.d->data, offset));
|
||||
}
|
||||
|
||||
int String::rfind(const String &s, int offset) const
|
||||
{
|
||||
return d->data.rfind(s.d->data, offset);
|
||||
return static_cast<int>(d->data.rfind(s.d->data, offset));
|
||||
}
|
||||
|
||||
StringList String::split(const String &separator) const
|
||||
@ -445,7 +360,10 @@ bool String::startsWith(const String &s) const
|
||||
|
||||
String String::substr(unsigned int position, unsigned int n) const
|
||||
{
|
||||
return String(d->data.substr(position, n));
|
||||
if(position == 0 && n >= size())
|
||||
return *this;
|
||||
else
|
||||
return String(d->data.substr(position, n));
|
||||
}
|
||||
|
||||
String &String::append(const String &s)
|
||||
@ -464,12 +382,11 @@ String & String::clear()
|
||||
String String::upper() const
|
||||
{
|
||||
String s;
|
||||
s.d->data.reserve(size());
|
||||
|
||||
static int shift = 'A' - 'a';
|
||||
|
||||
for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); ++it) {
|
||||
for(ConstIterator it = begin(); it != end(); ++it) {
|
||||
if(*it >= 'a' && *it <= 'z')
|
||||
s.d->data.push_back(*it + shift);
|
||||
s.d->data.push_back(*it + 'A' - 'a');
|
||||
else
|
||||
s.d->data.push_back(*it);
|
||||
}
|
||||
@ -479,7 +396,7 @@ String String::upper() const
|
||||
|
||||
unsigned int String::size() const
|
||||
{
|
||||
return d->data.size();
|
||||
return static_cast<unsigned int>(d->data.size());
|
||||
}
|
||||
|
||||
unsigned int String::length() const
|
||||
@ -506,25 +423,27 @@ ByteVector String::data(Type t) const
|
||||
ByteVector v(size(), 0);
|
||||
char *p = v.data();
|
||||
|
||||
for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++)
|
||||
for(ConstIterator it = begin(); it != end(); ++it)
|
||||
*p++ = static_cast<char>(*it);
|
||||
|
||||
return v;
|
||||
}
|
||||
case UTF8:
|
||||
if(!d->data.empty())
|
||||
{
|
||||
ByteVector v(size() * 4 + 1, 0);
|
||||
ByteVector v(size() * 4, 0);
|
||||
|
||||
const size_t len = UTF16toUTF8(
|
||||
d->data.c_str(), d->data.size(), v.data(), v.size());
|
||||
v.resize(len);
|
||||
try {
|
||||
const ByteVector::Iterator dstEnd = utf8::utf16to8(begin(), end(), v.begin());
|
||||
v.resize(static_cast<unsigned int>(dstEnd - v.begin()));
|
||||
}
|
||||
catch(const utf8::exception &e) {
|
||||
const String message(e.what());
|
||||
debug("String::data() - UTF8-CPP error: " + message);
|
||||
v.clear();
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
else {
|
||||
return ByteVector();
|
||||
}
|
||||
case UTF16:
|
||||
{
|
||||
ByteVector v(2 + size() * 2, 0);
|
||||
@ -535,7 +454,7 @@ ByteVector String::data(Type t) const
|
||||
*p++ = '\xff';
|
||||
*p++ = '\xfe';
|
||||
|
||||
for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) {
|
||||
for(ConstIterator it = begin(); it != end(); ++it) {
|
||||
*p++ = static_cast<char>(*it & 0xff);
|
||||
*p++ = static_cast<char>(*it >> 8);
|
||||
}
|
||||
@ -547,7 +466,7 @@ ByteVector String::data(Type t) const
|
||||
ByteVector v(size() * 2, 0);
|
||||
char *p = v.data();
|
||||
|
||||
for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) {
|
||||
for(ConstIterator it = begin(); it != end(); ++it) {
|
||||
*p++ = static_cast<char>(*it >> 8);
|
||||
*p++ = static_cast<char>(*it & 0xff);
|
||||
}
|
||||
@ -559,7 +478,7 @@ ByteVector String::data(Type t) const
|
||||
ByteVector v(size() * 2, 0);
|
||||
char *p = v.data();
|
||||
|
||||
for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) {
|
||||
for(ConstIterator it = begin(); it != end(); ++it) {
|
||||
*p++ = static_cast<char>(*it & 0xff);
|
||||
*p++ = static_cast<char>(*it >> 8);
|
||||
}
|
||||
@ -604,12 +523,12 @@ String String::stripWhiteSpace() const
|
||||
return String();
|
||||
|
||||
const size_t pos2 = d->data.find_last_not_of(WhiteSpaceChars);
|
||||
return substr(pos1, pos2 - pos1 + 1);
|
||||
return substr(static_cast<unsigned int>(pos1), static_cast<unsigned int>(pos2 - pos1 + 1));
|
||||
}
|
||||
|
||||
bool String::isLatin1() const
|
||||
{
|
||||
for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) {
|
||||
for(ConstIterator it = begin(); it != end(); ++it) {
|
||||
if(*it >= 256)
|
||||
return false;
|
||||
}
|
||||
@ -618,7 +537,7 @@ bool String::isLatin1() const
|
||||
|
||||
bool String::isAscii() const
|
||||
{
|
||||
for(wstring::const_iterator it = d->data.begin(); it != d->data.end(); it++) {
|
||||
for(ConstIterator it = begin(); it != end(); ++it) {
|
||||
if(*it >= 128)
|
||||
return false;
|
||||
}
|
||||
@ -787,6 +706,12 @@ void String::detach()
|
||||
if(d->count() > 1)
|
||||
String(d->data.c_str()).swap(*this);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const String::Type String::WCharByteOrder = wcharByteOrder();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
7
3rdparty/taglib/toolkit/tstring.h
vendored
7
3rdparty/taglib/toolkit/tstring.h
vendored
@ -536,6 +536,13 @@ namespace TagLib {
|
||||
void detach();
|
||||
|
||||
private:
|
||||
/*!
|
||||
* \deprecated This variable is no longer used, but NEVER remove this. It
|
||||
* may lead to a linkage error.
|
||||
*/
|
||||
// BIC: remove
|
||||
static const Type WCharByteOrder;
|
||||
|
||||
class StringPrivate;
|
||||
StringPrivate *d;
|
||||
};
|
||||
|
61
3rdparty/taglib/toolkit/tutils.h
vendored
61
3rdparty/taglib/toolkit/tutils.h
vendored
@ -34,9 +34,7 @@
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_BOOST_BYTESWAP)
|
||||
# include <boost/endian/conversion.hpp>
|
||||
#elif defined(HAVE_MSC_BYTESWAP)
|
||||
#if defined(HAVE_MSC_BYTESWAP)
|
||||
# include <stdlib.h>
|
||||
#elif defined(HAVE_GLIBC_BYTESWAP)
|
||||
# include <byteswap.h>
|
||||
@ -63,11 +61,7 @@ namespace TagLib
|
||||
*/
|
||||
inline unsigned short byteSwap(unsigned short x)
|
||||
{
|
||||
#if defined(HAVE_BOOST_BYTESWAP)
|
||||
|
||||
return boost::endian::endian_reverse(static_cast<uint16_t>(x));
|
||||
|
||||
#elif defined(HAVE_GCC_BYTESWAP)
|
||||
#if defined(HAVE_GCC_BYTESWAP)
|
||||
|
||||
return __builtin_bswap16(x);
|
||||
|
||||
@ -99,11 +93,7 @@ namespace TagLib
|
||||
*/
|
||||
inline unsigned int byteSwap(unsigned int x)
|
||||
{
|
||||
#if defined(HAVE_BOOST_BYTESWAP)
|
||||
|
||||
return boost::endian::endian_reverse(static_cast<uint32_t>(x));
|
||||
|
||||
#elif defined(HAVE_GCC_BYTESWAP)
|
||||
#if defined(HAVE_GCC_BYTESWAP)
|
||||
|
||||
return __builtin_bswap32(x);
|
||||
|
||||
@ -138,11 +128,7 @@ namespace TagLib
|
||||
*/
|
||||
inline unsigned long long byteSwap(unsigned long long x)
|
||||
{
|
||||
#if defined(HAVE_BOOST_BYTESWAP)
|
||||
|
||||
return boost::endian::endian_reverse(static_cast<uint64_t>(x));
|
||||
|
||||
#elif defined(HAVE_GCC_BYTESWAP)
|
||||
#if defined(HAVE_GCC_BYTESWAP)
|
||||
|
||||
return __builtin_bswap64(x);
|
||||
|
||||
@ -221,23 +207,6 @@ namespace TagLib
|
||||
return String();
|
||||
}
|
||||
|
||||
/*!
|
||||
* Returns whether the two strings s1 and s2 are equal, ignoring the case of
|
||||
* the characters.
|
||||
*
|
||||
* We took the trouble to define this one here, since there are some
|
||||
* incompatible variations of case insensitive strcmp().
|
||||
*/
|
||||
inline bool equalsIgnoreCase(const char *s1, const char *s2)
|
||||
{
|
||||
while(*s1 != '\0' && *s2 != '\0' && ::tolower(*s1) == ::tolower(*s2)) {
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
|
||||
return (*s1 == '\0' && *s2 == '\0');
|
||||
}
|
||||
|
||||
/*!
|
||||
* The types of byte order of the running system.
|
||||
*/
|
||||
@ -250,7 +219,7 @@ namespace TagLib
|
||||
};
|
||||
|
||||
/*!
|
||||
* Returns the integer byte order of the system.
|
||||
* Returns the byte order of the system.
|
||||
*/
|
||||
inline ByteOrder systemByteOrder()
|
||||
{
|
||||
@ -265,26 +234,6 @@ namespace TagLib
|
||||
else
|
||||
return BigEndian;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Returns the IEEE754 byte order of the system.
|
||||
*/
|
||||
inline ByteOrder floatByteOrder()
|
||||
{
|
||||
union {
|
||||
double d;
|
||||
char c;
|
||||
} u;
|
||||
|
||||
// 1.0 is stored in memory like 0x3FF0000000000000 in canonical form.
|
||||
// So the first byte is zero if little endian.
|
||||
|
||||
u.d = 1.0;
|
||||
if(u.c == 0)
|
||||
return LittleEndian;
|
||||
else
|
||||
return BigEndian;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
46
3rdparty/taglib/toolkit/tzlib.cpp
vendored
46
3rdparty/taglib/toolkit/tzlib.cpp
vendored
@ -27,23 +27,19 @@
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_ZLIB)
|
||||
#ifdef HAVE_ZLIB
|
||||
# include <zlib.h>
|
||||
#elif defined(HAVE_BOOST_ZLIB)
|
||||
# include <boost/iostreams/filtering_streambuf.hpp>
|
||||
# include <boost/iostreams/filter/zlib.hpp>
|
||||
# include <tstring.h>
|
||||
# include <tdebug.h>
|
||||
#endif
|
||||
|
||||
#include <tstring.h>
|
||||
#include <tdebug.h>
|
||||
|
||||
#include "tzlib.h"
|
||||
|
||||
using namespace TagLib;
|
||||
|
||||
bool zlib::isAvailable()
|
||||
{
|
||||
#if defined(HAVE_ZLIB) || defined(HAVE_BOOST_ZLIB)
|
||||
#ifdef HAVE_ZLIB
|
||||
|
||||
return true;
|
||||
|
||||
@ -56,7 +52,7 @@ bool zlib::isAvailable()
|
||||
|
||||
ByteVector zlib::decompress(const ByteVector &data)
|
||||
{
|
||||
#if defined(HAVE_ZLIB)
|
||||
#ifdef HAVE_ZLIB
|
||||
|
||||
z_stream stream = {};
|
||||
|
||||
@ -102,38 +98,6 @@ ByteVector zlib::decompress(const ByteVector &data)
|
||||
|
||||
return outData;
|
||||
|
||||
#elif defined(HAVE_BOOST_ZLIB)
|
||||
|
||||
using namespace boost::iostreams;
|
||||
|
||||
struct : public sink
|
||||
{
|
||||
ByteVector data;
|
||||
|
||||
typedef char char_type;
|
||||
typedef sink_tag category;
|
||||
|
||||
std::streamsize write(char const* s, std::streamsize n)
|
||||
{
|
||||
const unsigned int originalSize = data.size();
|
||||
|
||||
data.resize(static_cast<unsigned int>(originalSize + n));
|
||||
::memcpy(data.data() + originalSize, s, static_cast<size_t>(n));
|
||||
|
||||
return n;
|
||||
}
|
||||
} sink;
|
||||
|
||||
try {
|
||||
zlib_decompressor().write(sink, data.data(), data.size());
|
||||
}
|
||||
catch(const zlib_error &) {
|
||||
debug("zlib::decompress() - Error reading compressed stream.");
|
||||
return ByteVector();
|
||||
}
|
||||
|
||||
return sink.data;
|
||||
|
||||
#else
|
||||
|
||||
return ByteVector();
|
||||
|
303
3rdparty/taglib/toolkit/unicode.cpp
vendored
303
3rdparty/taglib/toolkit/unicode.cpp
vendored
@ -1,303 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* THIS FILE IS INCLUDED IN TAGLIB, BUT IS NOT COPYRIGHTED BY THE TAGLIB *
|
||||
* AUTHORS, NOT PART OF THE TAGLIB API AND COULD GO AWAY AT ANY POINT IN TIME. *
|
||||
* AS SUCH IT SHOULD BE CONSIERED FOR INTERNAL USE ONLY. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
/*
|
||||
* Copyright 2001 Unicode, Inc.
|
||||
*
|
||||
* Disclaimer
|
||||
*
|
||||
* This source code is provided as is by Unicode, Inc. No claims are
|
||||
* made as to fitness for any particular purpose. No warranties of any
|
||||
* kind are expressed or implied. The recipient agrees to determine
|
||||
* applicability of information provided. If this file has been
|
||||
* purchased on magnetic or optical media from Unicode, Inc., the
|
||||
* sole remedy for any claim will be exchange of defective media
|
||||
* within 90 days of receipt.
|
||||
*
|
||||
* Limitations on Rights to Redistribute This Code
|
||||
*
|
||||
* Unicode, Inc. hereby grants the right to freely use the information
|
||||
* supplied in this file in the creation of products supporting the
|
||||
* Unicode Standard, and to make copies of this file in any form
|
||||
* for internal or external distribution as long as this notice
|
||||
* remains attached.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file has been modified by Scott Wheeler <wheeler@kde.org> to remove
|
||||
* the UTF32 conversion functions and to place the appropriate functions
|
||||
* in their own C++ namespace.
|
||||
*/
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
|
||||
Conversions between UTF32, UTF-16, and UTF-8. Source code file.
|
||||
Author: Mark E. Davis, 1994.
|
||||
Rev History: Rick McGowan, fixes & updates May 2001.
|
||||
Sept 2001: fixed const & error conditions per
|
||||
mods suggested by S. Parent & A. Lillich.
|
||||
|
||||
See the header file "ConvertUTF.h" for complete documentation.
|
||||
|
||||
------------------------------------------------------------------------ */
|
||||
|
||||
|
||||
#include "unicode.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#define UNI_SUR_HIGH_START (UTF32)0xD800
|
||||
#define UNI_SUR_HIGH_END (UTF32)0xDBFF
|
||||
#define UNI_SUR_LOW_START (UTF32)0xDC00
|
||||
#define UNI_SUR_LOW_END (UTF32)0xDFFF
|
||||
#define false 0
|
||||
#define true 1
|
||||
|
||||
namespace Unicode {
|
||||
|
||||
static const int halfShift = 10; /* used for shifting by 10 bits */
|
||||
|
||||
static const UTF32 halfBase = 0x0010000UL;
|
||||
static const UTF32 halfMask = 0x3FFUL;
|
||||
|
||||
/*
|
||||
* Index into the table below with the first byte of a UTF-8 sequence to
|
||||
* get the number of trailing bytes that are supposed to follow it.
|
||||
*/
|
||||
static const char trailingBytesForUTF8[256] = {
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
|
||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5
|
||||
};
|
||||
|
||||
/*
|
||||
* Magic values subtracted from a buffer value during UTF8 conversion.
|
||||
* This table contains as many values as there might be trailing bytes
|
||||
* in a UTF-8 sequence.
|
||||
*/
|
||||
static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
|
||||
0x03C82080UL, 0xFA082080UL, 0x82082080UL };
|
||||
|
||||
/*
|
||||
* Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
|
||||
* into the first byte, depending on how many bytes follow. There are
|
||||
* as many entries in this table as there are UTF-8 sequence types.
|
||||
* (I.e., one byte sequence, two byte... six byte sequence.)
|
||||
*/
|
||||
static const UTF8 firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/* The interface converts a whole buffer to avoid function-call overhead.
|
||||
* Constants have been gathered. Loops & conditionals have been removed as
|
||||
* much as possible for efficiency, in favor of drop-through switches.
|
||||
* (See "Note A" at the bottom of the file for equivalent code.)
|
||||
* If your compiler supports it, the "isLegalUTF8" call can be turned
|
||||
* into an inline function.
|
||||
*/
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
ConversionResult ConvertUTF16toUTF8 (
|
||||
const UTF16** sourceStart, const UTF16* sourceEnd,
|
||||
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
|
||||
ConversionResult result = conversionOK;
|
||||
const UTF16* source = *sourceStart;
|
||||
UTF8* target = *targetStart;
|
||||
while (source < sourceEnd) {
|
||||
UTF32 ch;
|
||||
unsigned short bytesToWrite = 0;
|
||||
const UTF32 byteMask = 0xBF;
|
||||
const UTF32 byteMark = 0x80;
|
||||
const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
|
||||
ch = *source++;
|
||||
/* If we have a surrogate pair, convert to UTF32 first. */
|
||||
if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END && source < sourceEnd) {
|
||||
UTF32 ch2 = *source;
|
||||
if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
|
||||
ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
|
||||
+ (ch2 - UNI_SUR_LOW_START) + halfBase;
|
||||
++source;
|
||||
} else if (flags == strictConversion) { /* it's an unpaired high surrogate */
|
||||
--source; /* return to the illegal value itself */
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
}
|
||||
} else if ((flags == strictConversion) && (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END)) {
|
||||
--source; /* return to the illegal value itself */
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
}
|
||||
/* Figure out how many bytes the result will require */
|
||||
if (ch < (UTF32)0x80) { bytesToWrite = 1;
|
||||
} else if (ch < (UTF32)0x800) { bytesToWrite = 2;
|
||||
} else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
|
||||
} else if (ch < (UTF32)0x200000) { bytesToWrite = 4;
|
||||
} else { bytesToWrite = 2;
|
||||
ch = UNI_REPLACEMENT_CHAR;
|
||||
}
|
||||
// printf("bytes to write = %i\n", bytesToWrite);
|
||||
target += bytesToWrite;
|
||||
if (target > targetEnd) {
|
||||
source = oldSource; /* Back up source pointer! */
|
||||
target -= bytesToWrite; result = targetExhausted; break;
|
||||
}
|
||||
switch (bytesToWrite) { /* note: everything falls through. */
|
||||
case 4: *--target = (ch | byteMark) & byteMask; ch >>= 6;
|
||||
case 3: *--target = (ch | byteMark) & byteMask; ch >>= 6;
|
||||
case 2: *--target = (ch | byteMark) & byteMask; ch >>= 6;
|
||||
case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]);
|
||||
}
|
||||
target += bytesToWrite;
|
||||
}
|
||||
*sourceStart = source;
|
||||
*targetStart = target;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Utility routine to tell whether a sequence of bytes is legal UTF-8.
|
||||
* This must be called with the length pre-determined by the first byte.
|
||||
* If not calling this from ConvertUTF8to*, then the length can be set by:
|
||||
* length = trailingBytesForUTF8[*source]+1;
|
||||
* and the sequence is illegal right away if there aren't that many bytes
|
||||
* available.
|
||||
* If presented with a length > 4, this returns false. The Unicode
|
||||
* definition of UTF-8 goes up to 4-byte sequences.
|
||||
*/
|
||||
|
||||
static Boolean isLegalUTF8(const UTF8 *source, int length) {
|
||||
UTF8 a;
|
||||
const UTF8 *srcptr = source+length;
|
||||
switch (length) {
|
||||
default: return false;
|
||||
/* Everything else falls through when "true"... */
|
||||
case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
|
||||
case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
|
||||
case 2: if ((a = (*--srcptr)) > 0xBF) return false;
|
||||
switch (*source) {
|
||||
/* no fall-through in this inner switch */
|
||||
case 0xE0: if (a < 0xA0) return false; break;
|
||||
case 0xF0: if (a < 0x90) return false; break;
|
||||
case 0xF4: if (a > 0x8F) return false; break;
|
||||
default: if (a < 0x80) return false;
|
||||
}
|
||||
case 1: if (*source >= 0x80 && *source < 0xC2) return false;
|
||||
if (*source > 0xF4) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Exported function to return whether a UTF-8 sequence is legal or not.
|
||||
* This is not used here; it's just exported.
|
||||
*/
|
||||
Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) {
|
||||
int length = trailingBytesForUTF8[*source]+1;
|
||||
if (source+length > sourceEnd) {
|
||||
return false;
|
||||
}
|
||||
return isLegalUTF8(source, length);
|
||||
}
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
ConversionResult ConvertUTF8toUTF16 (
|
||||
const UTF8** sourceStart, const UTF8* sourceEnd,
|
||||
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
|
||||
ConversionResult result = conversionOK;
|
||||
const UTF8* source = *sourceStart;
|
||||
UTF16* target = *targetStart;
|
||||
while (source < sourceEnd) {
|
||||
UTF32 ch = 0;
|
||||
unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
|
||||
if (source + extraBytesToRead >= sourceEnd) {
|
||||
result = sourceExhausted; break;
|
||||
}
|
||||
/* Do this check whether lenient or strict */
|
||||
if (! isLegalUTF8(source, extraBytesToRead+1)) {
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* The cases all fall through. See "Note A" below.
|
||||
*/
|
||||
switch (extraBytesToRead) {
|
||||
case 3: ch += *source++; ch <<= 6;
|
||||
case 2: ch += *source++; ch <<= 6;
|
||||
case 1: ch += *source++; ch <<= 6;
|
||||
case 0: ch += *source++;
|
||||
}
|
||||
ch -= offsetsFromUTF8[extraBytesToRead];
|
||||
|
||||
if (target >= targetEnd) {
|
||||
source -= (extraBytesToRead+1); /* Back up source pointer! */
|
||||
result = targetExhausted; break;
|
||||
}
|
||||
if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
|
||||
if ((flags == strictConversion) && (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END)) {
|
||||
source -= (extraBytesToRead+1); /* return to the illegal value itself */
|
||||
result = sourceIllegal;
|
||||
break;
|
||||
} else {
|
||||
*target++ = (UTF16)ch; /* normal case */
|
||||
}
|
||||
} else if (ch > UNI_MAX_UTF16) {
|
||||
if (flags == strictConversion) {
|
||||
result = sourceIllegal;
|
||||
source -= (extraBytesToRead+1); /* return to the start */
|
||||
break; /* Bail out; shouldn't continue */
|
||||
} else {
|
||||
*target++ = UNI_REPLACEMENT_CHAR;
|
||||
}
|
||||
} else {
|
||||
/* target is a character in range 0xFFFF - 0x10FFFF. */
|
||||
if (target + 1 >= targetEnd) {
|
||||
source -= (extraBytesToRead+1); /* Back up source pointer! */
|
||||
result = targetExhausted; break;
|
||||
}
|
||||
ch -= halfBase;
|
||||
*target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
|
||||
*target++ = (ch & halfMask) + UNI_SUR_LOW_START;
|
||||
}
|
||||
}
|
||||
*sourceStart = source;
|
||||
*targetStart = target;
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
|
||||
Note A.
|
||||
The fall-through switches in UTF-8 reading code save a
|
||||
temp variable, some decrements & conditionals. The switches
|
||||
are equivalent to the following loop:
|
||||
{
|
||||
int tmpBytesToRead = extraBytesToRead+1;
|
||||
do {
|
||||
ch += *source++;
|
||||
--tmpBytesToRead;
|
||||
if (tmpBytesToRead) ch <<= 6;
|
||||
} while (tmpBytesToRead > 0);
|
||||
}
|
||||
In UTF-8 writing code, the switches on "bytesToWrite" are
|
||||
similarly unrolled loops.
|
||||
|
||||
--------------------------------------------------------------------- */
|
||||
|
||||
|
149
3rdparty/taglib/toolkit/unicode.h
vendored
149
3rdparty/taglib/toolkit/unicode.h
vendored
@ -1,149 +0,0 @@
|
||||
#ifndef TAGLIB_UNICODE_H
|
||||
#define TAGLIB_UNICODE_H
|
||||
|
||||
/*******************************************************************************
|
||||
* *
|
||||
* THIS FILE IS INCLUDED IN TAGLIB, BUT IS NOT COPYRIGHTED BY THE TAGLIB *
|
||||
* AUTHORS, NOT PART OF THE TAGLIB API AND COULD GO AWAY AT ANY POINT IN TIME. *
|
||||
* AS SUCH IT SHOULD BE CONSIERED FOR INTERNAL USE ONLY. *
|
||||
* *
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef DO_NOT_DOCUMENT // tell Doxygen not to document this header
|
||||
|
||||
/*
|
||||
* Copyright 2001 Unicode, Inc.
|
||||
*
|
||||
* Disclaimer
|
||||
*
|
||||
* This source code is provided as is by Unicode, Inc. No claims are
|
||||
* made as to fitness for any particular purpose. No warranties of any
|
||||
* kind are expressed or implied. The recipient agrees to determine
|
||||
* applicability of information provided. If this file has been
|
||||
* purchased on magnetic or optical media from Unicode, Inc., the
|
||||
* sole remedy for any claim will be exchange of defective media
|
||||
* within 90 days of receipt.
|
||||
*
|
||||
* Limitations on Rights to Redistribute This Code
|
||||
*
|
||||
* Unicode, Inc. hereby grants the right to freely use the information
|
||||
* supplied in this file in the creation of products supporting the
|
||||
* Unicode Standard, and to make copies of this file in any form
|
||||
* for internal or external distribution as long as this notice
|
||||
* remains attached.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file has been modified by Scott Wheeler <wheeler@kde.org> to remove
|
||||
* the UTF32 conversion functions and to place the appropriate functions
|
||||
* in their own C++ namespace.
|
||||
*/
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
|
||||
Conversions between UTF32, UTF-16, and UTF-8. Header file.
|
||||
|
||||
Several functions are included here, forming a complete set of
|
||||
conversions between the three formats. UTF-7 is not included
|
||||
here, but is handled in a separate source file.
|
||||
|
||||
Each of these routines takes pointers to input buffers and output
|
||||
buffers. The input buffers are const.
|
||||
|
||||
Each routine converts the text between *sourceStart and sourceEnd,
|
||||
putting the result into the buffer between *targetStart and
|
||||
targetEnd. Note: the end pointers are *after* the last item: e.g.
|
||||
*(sourceEnd - 1) is the last item.
|
||||
|
||||
The return result indicates whether the conversion was successful,
|
||||
and if not, whether the problem was in the source or target buffers.
|
||||
(Only the first encountered problem is indicated.)
|
||||
|
||||
After the conversion, *sourceStart and *targetStart are both
|
||||
updated to point to the end of last text successfully converted in
|
||||
the respective buffers.
|
||||
|
||||
Input parameters:
|
||||
sourceStart - pointer to a pointer to the source buffer.
|
||||
The contents of this are modified on return so that
|
||||
it points at the next thing to be converted.
|
||||
targetStart - similarly, pointer to pointer to the target buffer.
|
||||
sourceEnd, targetEnd - respectively pointers to the ends of the
|
||||
two buffers, for overflow checking only.
|
||||
|
||||
These conversion functions take a ConversionFlags argument. When this
|
||||
flag is set to strict, both irregular sequences and isolated surrogates
|
||||
will cause an error. When the flag is set to lenient, both irregular
|
||||
sequences and isolated surrogates are converted.
|
||||
|
||||
Whether the flag is strict or lenient, all illegal sequences will cause
|
||||
an error return. This includes sequences such as: <F4 90 80 80>, <C0 80>,
|
||||
or <A0> in UTF-8, and values above 0x10FFFF in UTF-32. Conformant code
|
||||
must check for illegal sequences.
|
||||
|
||||
When the flag is set to lenient, characters over 0x10FFFF are converted
|
||||
to the replacement character; otherwise (when the flag is set to strict)
|
||||
they constitute an error.
|
||||
|
||||
Output parameters:
|
||||
The value "sourceIllegal" is returned from some routines if the input
|
||||
sequence is malformed. When "sourceIllegal" is returned, the source
|
||||
value will point to the illegal value that caused the problem. E.g.,
|
||||
in UTF-8 when a sequence is malformed, it points to the start of the
|
||||
malformed sequence.
|
||||
|
||||
Author: Mark E. Davis, 1994.
|
||||
Rev History: Rick McGowan, fixes & updates May 2001.
|
||||
Fixes & updates, Sept 2001.
|
||||
|
||||
------------------------------------------------------------------------ */
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
The following 4 definitions are compiler-specific.
|
||||
The C standard does not guarantee that wchar_t has at least
|
||||
16 bits, so wchar_t is no less portable than unsigned short!
|
||||
All should be unsigned values to avoid sign extension during
|
||||
bit mask & shift operations.
|
||||
------------------------------------------------------------------------ */
|
||||
|
||||
/* Some fundamental constants */
|
||||
#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
|
||||
#define UNI_MAX_BMP (UTF32)0x0000FFFF
|
||||
#define UNI_MAX_UTF16 (UTF32)0x0010FFFF
|
||||
#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF
|
||||
|
||||
namespace Unicode {
|
||||
|
||||
typedef unsigned long UTF32; /* at least 32 bits */
|
||||
typedef wchar_t UTF16; /* TagLib assumes that wchar_t is sufficient for UTF-16. */
|
||||
typedef unsigned char UTF8; /* typically 8 bits */
|
||||
typedef unsigned char Boolean; /* 0 or 1 */
|
||||
|
||||
typedef enum {
|
||||
conversionOK = 0, /* conversion successful */
|
||||
sourceExhausted = 1, /* partial character in source, but hit end */
|
||||
targetExhausted = 2, /* insuff. room in target for conversion */
|
||||
sourceIllegal = 3 /* source sequence is illegal/malformed */
|
||||
} ConversionResult;
|
||||
|
||||
typedef enum {
|
||||
strictConversion = 0,
|
||||
lenientConversion
|
||||
} ConversionFlags;
|
||||
|
||||
ConversionResult ConvertUTF8toUTF16 (
|
||||
const UTF8** sourceStart, const UTF8* sourceEnd,
|
||||
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
|
||||
|
||||
ConversionResult ConvertUTF16toUTF8 (
|
||||
const UTF16** sourceStart, const UTF16* sourceEnd,
|
||||
UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
|
||||
|
||||
Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd);
|
||||
|
||||
} // namespace Unicode
|
||||
|
||||
/* --------------------------------------------------------------------- */
|
||||
|
||||
#endif
|
||||
#endif
|
12
3rdparty/taglib/trueaudio/trueaudiofile.cpp
vendored
12
3rdparty/taglib/trueaudio/trueaudiofile.cpp
vendored
@ -73,6 +73,18 @@ public:
|
||||
Properties *properties;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// static members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool TrueAudio::File::isSupported(IOStream *stream)
|
||||
{
|
||||
// A TrueAudio file has to start with "TTA". An ID3v2 tag may precede.
|
||||
|
||||
const ByteVector id = Utils::readHeader(stream, 3, true);
|
||||
return (id == "TTA");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
9
3rdparty/taglib/trueaudio/trueaudiofile.h
vendored
9
3rdparty/taglib/trueaudio/trueaudiofile.h
vendored
@ -235,6 +235,15 @@ namespace TagLib {
|
||||
*/
|
||||
bool hasID3v2Tag() const;
|
||||
|
||||
/*!
|
||||
* Returns whether or not the given \a stream can be opened as a TrueAudio
|
||||
* file.
|
||||
*
|
||||
* \note This method is designed to do a quick check. The result may
|
||||
* not necessarily be correct.
|
||||
*/
|
||||
static bool isSupported(IOStream *stream);
|
||||
|
||||
private:
|
||||
File(const File &);
|
||||
File &operator=(const File &);
|
||||
|
12
3rdparty/taglib/wavpack/wavpackfile.cpp
vendored
12
3rdparty/taglib/wavpack/wavpackfile.cpp
vendored
@ -71,6 +71,18 @@ public:
|
||||
Properties *properties;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// static members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool WavPack::File::isSupported(IOStream *stream)
|
||||
{
|
||||
// A WavPack file has to start with "wvpk".
|
||||
|
||||
const ByteVector id = Utils::readHeader(stream, 4, false);
|
||||
return (id == "wvpk");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
8
3rdparty/taglib/wavpack/wavpackfile.h
vendored
8
3rdparty/taglib/wavpack/wavpackfile.h
vendored
@ -200,6 +200,14 @@ namespace TagLib {
|
||||
*/
|
||||
bool hasAPETag() const;
|
||||
|
||||
/*!
|
||||
* Check if the given \a stream can be opened as a WavPack file.
|
||||
*
|
||||
* \note This method is designed to do a quick check. The result may
|
||||
* not necessarily be correct.
|
||||
*/
|
||||
static bool isSupported(IOStream *stream);
|
||||
|
||||
private:
|
||||
File(const File &);
|
||||
File &operator=(const File &);
|
||||
|
2
3rdparty/taglib/xm/xmfile.cpp
vendored
2
3rdparty/taglib/xm/xmfile.cpp
vendored
@ -586,9 +586,9 @@ void XM::File::read(bool)
|
||||
unsigned int count = 4 + instrument.read(*this, instrumentHeaderSize - 4U);
|
||||
READ_ASSERT(count == std::min(instrumentHeaderSize, (unsigned long)instrument.size() + 4));
|
||||
|
||||
unsigned long sampleHeaderSize = 0;
|
||||
long offset = 0;
|
||||
if(sampleCount > 0) {
|
||||
unsigned long sampleHeaderSize = 0;
|
||||
sumSampleCount += sampleCount;
|
||||
// wouldn't know which header size to assume otherwise:
|
||||
READ_ASSERT(instrumentHeaderSize >= count + 4 && readU32L(sampleHeaderSize));
|
||||
|
2
3rdparty/taglib/xm/xmproperties.cpp
vendored
2
3rdparty/taglib/xm/xmproperties.cpp
vendored
@ -60,7 +60,7 @@ public:
|
||||
|
||||
XM::Properties::Properties(AudioProperties::ReadStyle propertiesStyle) :
|
||||
AudioProperties(propertiesStyle),
|
||||
d(new PropertiesPrivate)
|
||||
d(new PropertiesPrivate())
|
||||
{
|
||||
}
|
||||
|
||||
|
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