Additional manual formatting to taglib sources

This commit is contained in:
Jonas Kvinge
2020-06-14 17:01:05 +02:00
parent 577b7d8ec8
commit ef34dce4dc
217 changed files with 7367 additions and 8204 deletions

View File

@@ -36,9 +36,7 @@ using namespace Strawberry_TagLib::TagLib;
class RIFF::AIFF::File::FilePrivate {
public:
FilePrivate() : properties(0),
tag(0),
hasID3v2(false) {}
FilePrivate() : properties(nullptr), tag(nullptr), hasID3v2(false) {}
~FilePrivate() {
delete properties;
@@ -56,24 +54,26 @@ class RIFF::AIFF::File::FilePrivate {
////////////////////////////////////////////////////////////////////////////////
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
////////////////////////////////////////////////////////////////////////////////
RIFF::AIFF::File::File(FileName file, bool readProperties, Properties::ReadStyle) : RIFF::File(file, BigEndian),
d(new FilePrivate()) {
RIFF::AIFF::File::File(FileName file, bool readProperties, Properties::ReadStyle) : RIFF::File(file, BigEndian), d(new FilePrivate()) {
if (isOpen())
read(readProperties);
}
RIFF::AIFF::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : RIFF::File(stream, BigEndian),
d(new FilePrivate()) {
RIFF::AIFF::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : RIFF::File(stream, BigEndian), d(new FilePrivate()) {
if (isOpen())
read(readProperties);
}
@@ -107,6 +107,7 @@ bool RIFF::AIFF::File::save() {
}
bool RIFF::AIFF::File::save(ID3v2::Version version) {
if (readOnly()) {
debug("RIFF::AIFF::File::save() -- File is read only.");
return false;
@@ -129,6 +130,7 @@ bool RIFF::AIFF::File::save(ID3v2::Version version) {
}
return true;
}
bool RIFF::AIFF::File::hasID3v2Tag() const {
@@ -140,6 +142,7 @@ bool RIFF::AIFF::File::hasID3v2Tag() const {
////////////////////////////////////////////////////////////////////////////////
void RIFF::AIFF::File::read(bool readProperties) {
for (unsigned int i = 0; i < chunkCount(); ++i) {
const ByteVector name = chunkName(i);
if (name == "ID3 " || name == "id3 ") {
@@ -158,4 +161,5 @@ void RIFF::AIFF::File::read(bool readProperties) {
if (readProperties)
d->properties = new Properties(this, Properties::Average);
}

View File

@@ -32,111 +32,109 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace RIFF {
//! An implementation of AIFF metadata
/*!
* This is implementation of AIFF metadata.
*
* This supports an ID3v2 tag as well as reading stream from the ID3 RIFF
* chunk as well as properties from the file.
*/
* This is implementation of AIFF metadata.
*
* This supports an ID3v2 tag as well as reading stream from the ID3 RIFF
* chunk as well as properties from the file.
*/
namespace AIFF {
//! An implementation of TagLib::File with AIFF specific methods
/*!
* This implements and provides an interface for AIFF files to the
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
* the abstract TagLib::File API as well as providing some additional
* information specific to AIFF files.
*/
* This implements and provides an interface for AIFF files to the
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
* the abstract TagLib::File API as well as providing some additional
* information specific to AIFF files.
*/
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::RIFF::File {
public:
/*!
* Constructs an AIFF file from \a file. If \a readProperties is true the
* file's audio properties will also be read.
*
* \note In the current implementation, \a propertiesStyle is ignored.
*/
* Constructs an AIFF file from \a file.
* If \a readProperties is true the file's audio properties will also be read.
*
* \note In the current implementation, \a propertiesStyle is ignored.
*/
File(FileName file, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
/*!
* Constructs an AIFF file from \a stream. If \a readProperties is true the
* file's audio properties will also be read.
*
* \note TagLib will *not* take ownership of the stream, the caller is
* responsible for deleting it after the File object.
*
* \note In the current implementation, \a propertiesStyle is ignored.
*/
* Constructs an AIFF file from \a stream.
* If \a readProperties is true the file's audio properties will also be read.
*
* \note TagLib will *not* take ownership of the stream, the caller is
* responsible for deleting it after the File object.
*
* \note In the current implementation, \a propertiesStyle is ignored.
*/
File(IOStream *stream, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
/*!
* Destroys this instance of the File.
*/
* Destroys this instance of the File.
*/
virtual ~File();
/*!
* Returns the Tag for this file.
*
* \note This always returns a valid pointer regardless of whether or not
* the file on disk has an ID3v2 tag. Use hasID3v2Tag() to check if the file
* on disk actually has an ID3v2 tag.
*
* \see hasID3v2Tag()
*/
* Returns the Tag for this file.
*
* \note This always returns a valid pointer regardless of whether or not the file on disk has an ID3v2 tag.
* Use hasID3v2Tag() to check if the file on disk actually has an ID3v2 tag.
*
* \see hasID3v2Tag()
*/
virtual ID3v2::Tag *tag() const;
/*!
* Implements the unified property interface -- export function.
* This method forwards to ID3v2::Tag::properties().
*/
* Implements the unified property interface -- export function.
* This method forwards to ID3v2::Tag::properties().
*/
PropertyMap properties() const;
void removeUnsupportedProperties(const StringList &properties);
/*!
* Implements the unified property interface -- import function.
* This method forwards to ID3v2::Tag::setProperties().
*/
* Implements the unified property interface -- import function.
* This method forwards to ID3v2::Tag::setProperties().
*/
PropertyMap setProperties(const PropertyMap &);
/*!
* Returns the AIFF::Properties for this file. If no audio properties
* were read then this will return a null pointer.
*/
* Returns the AIFF::Properties for this file.
* If no audio properties were read then this will return a null pointer.
*/
virtual Properties *audioProperties() const;
/*!
* Saves the file.
*/
* Saves the file.
*/
virtual bool save();
/*!
* Save using a specific ID3v2 version (e.g. v3)
*/
* Save using a specific ID3v2 version (e.g. v3)
*/
bool save(ID3v2::Version version);
/*!
* Returns whether or not the file on disk actually has an ID3v2 tag.
*
* \see ID3v2Tag()
*/
* Returns whether or not the file on disk actually has an ID3v2 tag.
*
* \see ID3v2Tag()
*/
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.
*/
* 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:
@@ -150,6 +148,7 @@ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::RIFF::File {
class FilePrivate;
FilePrivate *d;
};
} // namespace AIFF
} // namespace RIFF
} // namespace TagLib

View File

@@ -55,13 +55,7 @@ class RIFF::AIFF::Properties::PropertiesPrivate {
// public members
////////////////////////////////////////////////////////////////////////////////
RIFF::AIFF::Properties::Properties(const ByteVector &, ReadStyle style) : AudioProperties(style),
d(new PropertiesPrivate()) {
debug("RIFF::AIFF::Properties::Properties() - This constructor is no longer used.");
}
RIFF::AIFF::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style),
d(new PropertiesPrivate()) {
RIFF::AIFF::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style), d(new PropertiesPrivate()) {
read(file);
}
@@ -69,10 +63,6 @@ RIFF::AIFF::Properties::~Properties() {
delete d;
}
int RIFF::AIFF::Properties::length() const {
return lengthInSeconds();
}
int RIFF::AIFF::Properties::lengthInSeconds() const {
return d->length / 1000;
}
@@ -97,10 +87,6 @@ int RIFF::AIFF::Properties::bitsPerSample() const {
return d->bitsPerSample;
}
int RIFF::AIFF::Properties::sampleWidth() const {
return bitsPerSample();
}
unsigned int RIFF::AIFF::Properties::sampleFrames() const {
return d->sampleFrames;
}
@@ -122,6 +108,7 @@ String RIFF::AIFF::Properties::compressionName() const {
////////////////////////////////////////////////////////////////////////////////
void RIFF::AIFF::Properties::read(File *file) {
ByteVector data;
unsigned int streamLength = 0;
for (unsigned int i = 0; i < file->chunkCount(); i++) {
@@ -168,4 +155,5 @@ void RIFF::AIFF::Properties::read(File *file) {
d->compressionType = data.mid(18, 4);
d->compressionName = String(data.mid(23, static_cast<unsigned char>(data[22])), String::Latin1);
}
}

View File

@@ -30,9 +30,7 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace RIFF {
namespace AIFF {
class File;
@@ -40,114 +38,84 @@ class File;
//! An implementation of audio property reading for AIFF
/*!
* This reads the data from an AIFF stream found in the AudioProperties
* API.
*/
* This reads the data from an AIFF stream found in the AudioProperties API.
*/
class TAGLIB_EXPORT Properties : public AudioProperties {
public:
/*!
* Create an instance of AIFF::Properties with the data read from the
* ByteVector \a data.
*
* \deprecated
*/
TAGLIB_DEPRECATED Properties(const ByteVector &data, ReadStyle style);
/*!
* Create an instance of AIFF::Properties with the data read from the
* AIFF::File \a file.
*/
* Create an instance of AIFF::Properties with the data read from the AIFF::File \a file.
*/
Properties(File *file, ReadStyle style);
/*!
* Destroys this AIFF::Properties instance.
*/
* Destroys this AIFF::Properties instance.
*/
virtual ~Properties();
/*!
* Returns the length of the file in seconds. The length is rounded down to
* the nearest whole second.
*
* \note This method is just an alias of lengthInSeconds().
*
* \deprecated
*/
TAGLIB_DEPRECATED virtual int length() const;
/*!
* Returns the length of the file in seconds. The length is rounded down to
* the nearest whole second.
*
* \see lengthInMilliseconds()
*/
* Returns the length of the file in seconds. The length is rounded down to the nearest whole second.
*
* \see lengthInMilliseconds()
*/
// BIC: make virtual
int lengthInSeconds() const;
/*!
* Returns the length of the file in milliseconds.
*
* \see lengthInSeconds()
*/
* Returns the length of the file in milliseconds.
*
* \see lengthInSeconds()
*/
// BIC: make virtual
int lengthInMilliseconds() const;
/*!
* Returns the average bit rate of the file in kb/s.
*/
* Returns the average bit rate of the file in kb/s.
*/
virtual int bitrate() const;
/*!
* Returns the sample rate in Hz.
*/
* Returns the sample rate in Hz.
*/
virtual int sampleRate() const;
/*!
* Returns the number of audio channels.
*/
* Returns the number of audio channels.
*/
virtual int channels() const;
/*!
* Returns the number of bits per audio sample.
*/
* Returns the number of bits per audio sample.
*/
int bitsPerSample() const;
/*!
* Returns the number of bits per audio sample.
*
* \note This method is just an alias of bitsPerSample().
*
* \deprecated
*/
TAGLIB_DEPRECATED int sampleWidth() const;
/*!
* Returns the number of sample frames
*/
* Returns the number of sample frames
*/
unsigned int sampleFrames() const;
/*!
* Returns true if the file is in AIFF-C format, false if AIFF format.
*/
* Returns true if the file is in AIFF-C format, false if AIFF format.
*/
bool isAiffC() const;
/*!
* Returns the compression type of the AIFF-C file. For example, "NONE" for
* not compressed, "ACE2" for ACE 2-to-1.
*
* If the file is in AIFF format, always returns an empty vector.
*
* \see isAiffC()
*/
* Returns the compression type of the AIFF-C file. For example, "NONE" for not compressed, "ACE2" for ACE 2-to-1.
*
* If the file is in AIFF format, always returns an empty vector.
*
* \see isAiffC()
*/
ByteVector compressionType() const;
/*!
* Returns the concrete compression name of the AIFF-C file.
*
* If the file is in AIFF format, always returns an empty string.
*
* \see isAiffC()
*/
* Returns the concrete compression name of the AIFF-C file.
*
* If the file is in AIFF format, always returns an empty string.
*
* \see isAiffC()
*/
String compressionName() const;
private:

View File

@@ -44,9 +44,7 @@ struct Chunk {
class RIFF::File::FilePrivate {
public:
explicit FilePrivate(Endianness _endianness) : endianness(_endianness),
size(0),
sizeOffset(0) {}
explicit FilePrivate(Endianness _endianness) : endianness(_endianness), size(0), sizeOffset(0) {}
const Endianness endianness;
@@ -68,14 +66,12 @@ RIFF::File::~File() {
// protected members
////////////////////////////////////////////////////////////////////////////////
RIFF::File::File(FileName file, Endianness endianness) : Strawberry_TagLib::TagLib::File(file),
d(new FilePrivate(endianness)) {
RIFF::File::File(FileName file, Endianness endianness) : Strawberry_TagLib::TagLib::File(file), d(new FilePrivate(endianness)) {
if (isOpen())
read();
}
RIFF::File::File(IOStream *stream, Endianness endianness) : Strawberry_TagLib::TagLib::File(stream),
d(new FilePrivate(endianness)) {
RIFF::File::File(IOStream *stream, Endianness endianness) : Strawberry_TagLib::TagLib::File(stream), d(new FilePrivate(endianness)) {
if (isOpen())
read();
}
@@ -89,42 +85,51 @@ unsigned int RIFF::File::chunkCount() const {
}
unsigned int RIFF::File::chunkDataSize(unsigned int i) const {
if (i >= d->chunks.size()) {
debug("RIFF::File::chunkDataSize() - Index out of range. Returning 0.");
return 0;
}
return d->chunks[i].size;
}
unsigned int RIFF::File::chunkOffset(unsigned int i) const {
if (i >= d->chunks.size()) {
debug("RIFF::File::chunkOffset() - Index out of range. Returning 0.");
return 0;
}
return d->chunks[i].offset;
}
unsigned int RIFF::File::chunkPadding(unsigned int i) const {
if (i >= d->chunks.size()) {
debug("RIFF::File::chunkPadding() - Index out of range. Returning 0.");
return 0;
}
return d->chunks[i].padding;
}
ByteVector RIFF::File::chunkName(unsigned int i) const {
if (i >= d->chunks.size()) {
debug("RIFF::File::chunkName() - Index out of range. Returning an empty vector.");
return ByteVector();
}
return d->chunks[i].name;
}
ByteVector RIFF::File::chunkData(unsigned int i) {
if (i >= d->chunks.size()) {
debug("RIFF::File::chunkData() - Index out of range. Returning an empty vector.");
return ByteVector();
@@ -132,9 +137,11 @@ ByteVector RIFF::File::chunkData(unsigned int i) {
seek(d->chunks[i].offset);
return readBlock(d->chunks[i].size);
}
void RIFF::File::setChunkData(unsigned int i, const ByteVector &data) {
if (i >= d->chunks.size()) {
debug("RIFF::File::setChunkData() - Index out of range.");
return;
@@ -162,6 +169,7 @@ void RIFF::File::setChunkData(unsigned int i, const ByteVector &data) {
// Update the global size.
updateGlobalSize();
}
void RIFF::File::setChunkData(const ByteVector &name, const ByteVector &data) {
@@ -169,6 +177,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.empty()) {
debug("RIFF::File::setChunkData - No valid chunks found.");
return;
@@ -225,9 +234,11 @@ void RIFF::File::setChunkData(const ByteVector &name, const ByteVector &data, bo
// Update the global size.
updateGlobalSize();
}
void RIFF::File::removeChunk(unsigned int i) {
if (i >= d->chunks.size()) {
debug("RIFF::File::removeChunk() - Index out of range.");
return;
@@ -246,13 +257,16 @@ void RIFF::File::removeChunk(unsigned int i) {
// Update the global size.
updateGlobalSize();
}
void RIFF::File::removeChunk(const ByteVector &name) {
for (int i = static_cast<int>(d->chunks.size()) - 1; i >= 0; --i) {
if (d->chunks[i].name == name)
removeChunk(i);
}
}
////////////////////////////////////////////////////////////////////////////////
@@ -260,6 +274,7 @@ void RIFF::File::removeChunk(const ByteVector &name) {
////////////////////////////////////////////////////////////////////////////////
void RIFF::File::read() {
const bool bigEndian = (d->endianness == BigEndian);
long offset = tell();
@@ -323,10 +338,11 @@ void RIFF::File::read() {
d->chunks.push_back(chunk);
}
}
void RIFF::File::writeChunk(const ByteVector &name, const ByteVector &data,
unsigned long offset, unsigned long replace) {
void RIFF::File::writeChunk(const ByteVector &name, const ByteVector &data, unsigned long offset, unsigned long replace) {
ByteVector combined;
combined.append(name);
@@ -337,13 +353,16 @@ void RIFF::File::writeChunk(const ByteVector &name, const ByteVector &data,
combined.resize(combined.size() + 1, '\0');
insert(combined, offset, replace);
}
void RIFF::File::updateGlobalSize() {
const Chunk first = d->chunks.front();
const Chunk last = d->chunks.back();
d->size = last.offset + last.size + last.padding - first.offset + 12;
const ByteVector data = ByteVector::fromUInt(d->size, d->endianness == BigEndian);
insert(data, d->sizeOffset, 4);
}

View File

@@ -39,16 +39,16 @@ namespace RIFF {
//! An RIFF file class with some useful methods specific to RIFF
/*!
* This implements the generic TagLib::File API and additionally provides
* access to properties that are distinct to RIFF files, notably access
* to the different ID3 tags.
*/
* This implements the generic TagLib::File API and additionally provides
* access to properties that are distinct to RIFF files, notably access
* to the different ID3 tags.
*/
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File {
public:
/*!
* Destroys this instance of the File.
*/
* Destroys this instance of the File.
*/
virtual ~File();
protected:
@@ -59,84 +59,82 @@ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File {
File(IOStream *stream, Endianness endianness);
/*!
* \return The size of the main RIFF chunk.
*/
* \return The size of the main RIFF chunk.
*/
unsigned int riffSize() const;
/*!
* \return The number of chunks in the file.
*/
* \return The number of chunks in the file.
*/
unsigned int chunkCount() const;
/*!
* \return The offset within the file for the selected chunk number.
*/
* \return The offset within the file for the selected chunk number.
*/
unsigned int chunkOffset(unsigned int i) const;
/*!
* \return The size of the chunk data.
*/
* \return The size of the chunk data.
*/
unsigned int chunkDataSize(unsigned int i) const;
/*!
* \return The size of the padding after the chunk (can be either 0 or 1).
*/
* \return The size of the padding after the chunk (can be either 0 or 1).
*/
unsigned int chunkPadding(unsigned int i) const;
/*!
* \return The name of the specified chunk, for instance, "COMM" or "ID3 "
*/
* \return The name of the specified chunk, for instance, "COMM" or "ID3 "
*/
ByteVector chunkName(unsigned int i) const;
/*!
* Reads the chunk data from the file and returns it.
*
* \note This \e will move the read pointer for the file.
*/
* Reads the chunk data from the file and returns it.
*
* \note This \e will move the read pointer for the file.
*/
ByteVector chunkData(unsigned int i);
/*!
* Sets the data for the specified chunk to \a data.
*
* \warning This will update the file immediately.
*/
* Sets the data for the specified chunk to \a data.
*
* \warning This will update the file immediately.
*/
void setChunkData(unsigned int i, const ByteVector &data);
/*!
* Sets the data for the chunk \a name to \a data. If a chunk with the
* given name already exists it will be overwritten, otherwise it will be
* created after the existing chunks.
*
* \warning This will update the file immediately.
*/
* Sets the data for the chunk \a name to \a data.
* If a chunk with the given name already exists it will be overwritten, otherwise it will be created after the existing chunks.
*
* \warning This will update the file immediately.
*/
void setChunkData(const ByteVector &name, const ByteVector &data);
/*!
* Sets the data for the chunk \a name to \a data. If a chunk with the
* given name already exists it will be overwritten, otherwise it will be
* created after the existing chunks.
*
* \note If \a alwaysCreate is true, a new chunk is created regardless of
* whether or not the chunk \a name exists. It should only be used for
* "LIST" chunks.
*
* \warning This will update the file immediately.
*/
* Sets the data for the chunk \a name to \a data.
* If a chunk with the given name already exists it will be overwritten, otherwise it will be created after the existing chunks.
*
* \note If \a alwaysCreate is true, a new chunk is created regardless of
* whether or not the chunk \a name exists. It should only be used for
* "LIST" chunks.
*
* \warning This will update the file immediately.
*/
void setChunkData(const ByteVector &name, const ByteVector &data, bool alwaysCreate);
/*!
* Removes the specified chunk.
*
* \warning This will update the file immediately.
*/
* Removes the specified chunk.
*
* \warning This will update the file immediately.
*/
void removeChunk(unsigned int i);
/*!
* Removes the chunk \a name.
*
* \warning This will update the file immediately.
* \warning This removes all the chunks with the given name.
*/
* Removes the chunk \a name.
*
* \warning This will update the file immediately.
* \warning This removes all the chunks with the given name.
*/
void removeChunk(const ByteVector &name);
private:
@@ -148,13 +146,14 @@ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File {
unsigned long offset, unsigned long replace = 0);
/*!
* Update the global RIFF size based on the current internal structure.
*/
* Update the global RIFF size based on the current internal structure.
*/
void updateGlobalSize();
class FilePrivate;
FilePrivate *d;
};
} // namespace RIFF
} // namespace TagLib
} // namespace Strawberry_TagLib

View File

@@ -36,6 +36,7 @@ namespace RIFF {
namespace {
inline bool isValidChunkName(const ByteVector &name) {
if (name.size() != 4)
return false;
@@ -46,6 +47,7 @@ inline bool isValidChunkName(const ByteVector &name) {
}
return true;
}
} // namespace

View File

@@ -46,11 +46,9 @@ class RIFF::Info::Tag::TagPrivate {
// StringHandler implementation
////////////////////////////////////////////////////////////////////////////////
StringHandler::StringHandler() {
}
StringHandler::StringHandler() {}
StringHandler::~StringHandler() {
}
StringHandler::~StringHandler() {}
String RIFF::Info::StringHandler::parse(const ByteVector &data) const {
return String(data, String::UTF8);
@@ -64,14 +62,11 @@ ByteVector RIFF::Info::StringHandler::render(const String &s) const {
// public members
////////////////////////////////////////////////////////////////////////////////
RIFF::Info::Tag::Tag(const ByteVector &data) : Strawberry_TagLib::TagLib::Tag(),
d(new TagPrivate()) {
RIFF::Info::Tag::Tag(const ByteVector &data) : Strawberry_TagLib::TagLib::Tag(), d(new TagPrivate()) {
parse(data);
}
RIFF::Info::Tag::Tag() : Strawberry_TagLib::TagLib::Tag(),
d(new TagPrivate()) {
}
RIFF::Info::Tag::Tag() : Strawberry_TagLib::TagLib::Tag(), d(new TagPrivate()) {}
RIFF::Info::Tag::~Tag() {
delete d;
@@ -148,13 +143,16 @@ FieldListMap RIFF::Info::Tag::fieldListMap() const {
}
String RIFF::Info::Tag::fieldText(const ByteVector &id) const {
if (d->fieldListMap.contains(id))
return String(d->fieldListMap[id]);
else
return String();
}
void RIFF::Info::Tag::setFieldText(const ByteVector &id, const String &s) {
// id must be four-byte long pure ascii string.
if (!isValidChunkName(id))
return;
@@ -163,14 +161,18 @@ void RIFF::Info::Tag::setFieldText(const ByteVector &id, const String &s) {
d->fieldListMap[id] = s;
else
removeField(id);
}
void RIFF::Info::Tag::removeField(const ByteVector &id) {
if (d->fieldListMap.contains(id))
d->fieldListMap.erase(id);
}
ByteVector RIFF::Info::Tag::render() const {
ByteVector data("INFO");
FieldListMap::ConstIterator it = d->fieldListMap.begin();
@@ -192,13 +194,16 @@ ByteVector RIFF::Info::Tag::render() const {
return ByteVector();
else
return data;
}
void RIFF::Info::Tag::setStringHandler(const StringHandler *handler) {
if (handler)
stringHandler = handler;
else
stringHandler = &defaultStringHandler;
}
////////////////////////////////////////////////////////////////////////////////
@@ -206,6 +211,7 @@ void RIFF::Info::Tag::setStringHandler(const StringHandler *handler) {
////////////////////////////////////////////////////////////////////////////////
void RIFF::Info::Tag::parse(const ByteVector &data) {
unsigned int p = 4;
while (p < data.size()) {
const unsigned int size = data.toUInt(p + 4, false);
@@ -220,4 +226,5 @@ void RIFF::Info::Tag::parse(const ByteVector &data) {
p += ((size + 1) & ~1) + 8;
}
}

View File

@@ -47,16 +47,14 @@ typedef Map<ByteVector, String> FieldListMap;
//! A abstraction for the string to data encoding in Info tags.
/*!
* RIFF INFO tag has no clear definitions about character encodings.
* In practice, local encoding of each system is largely used and UTF-8 is
* popular too.
*
* Here is an option to read and write tags in your preferred encoding
* by subclassing this class, reimplementing parse() and render() and setting
* your reimplementation as the default with Info::Tag::setStringHandler().
*
* \see ID3v1::Tag::setStringHandler()
*/
* RIFF INFO tag has no clear definitions about character encodings.
* In practice, local encoding of each system is largely used and UTF-8 is popular too.
*
* Here is an option to read and write tags in your preferred encoding by subclassing this class,
* reimplementing parse() and render() and setting your reimplementation as the default with Info::Tag::setStringHandler().
*
* \see ID3v1::Tag::setStringHandler()
*/
class TAGLIB_EXPORT StringHandler {
public:
@@ -64,37 +62,38 @@ class TAGLIB_EXPORT StringHandler {
~StringHandler();
/*!
* Decode a string from \a data. The default implementation assumes that
* \a data is an UTF-8 character array.
*/
* Decode a string from \a data.
* The default implementation assumes that \a data is an UTF-8 character array.
*/
virtual String parse(const ByteVector &data) const;
/*!
* Encode a ByteVector with the data from \a s. The default implementation
* assumes that \a s is an UTF-8 string.
*/
* Encode a ByteVector with the data from \a s.
* The default implementation assumes that \a s is an UTF-8 string.
*/
virtual ByteVector render(const String &s) const;
};
//! The main class in the ID3v2 implementation
/*!
* This is the main class in the INFO tag implementation. RIFF INFO tag is a
* metadata format found in WAV audio and AVI video files. Though it is a part
* of Microsoft/IBM's RIFF specification, the author could not find the official
* documents about it. So, this implementation is referring to unofficial documents
* online and some applications' behaviors especially Windows Explorer.
*/
* This is the main class in the INFO tag implementation.
* RIFF INFO tag is a metadata format found in WAV audio and AVI video files.
* Though it is a part of Microsoft/IBM's RIFF specification,
* the author could not find the official documents about it.
* So, this implementation is referring to unofficial documents online and some applications'
* behaviors especially Windows Explorer.
*/
class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag {
public:
/*!
* Constructs an empty INFO tag.
*/
* Constructs an empty INFO tag.
*/
Tag();
/*!
* Constructs an INFO tag read from \a data which is contents of "LIST" chunk.
*/
* Constructs an INFO tag read from \a data which is contents of "LIST" chunk.
*/
Tag(const ByteVector &data);
virtual ~Tag();
@@ -120,61 +119,59 @@ class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag {
virtual bool isEmpty() const;
/*!
* Returns a copy of the internal fields of the tag. The returned map directly
* reflects the contents of the "INFO" chunk.
*
* \note Modifying this map does not affect the tag's internal data.
* Use setFieldText() and removeField() instead.
*
* \see setFieldText()
* \see removeField()
*/
* Returns a copy of the internal fields of the tag.
* The returned map directly reflects the contents of the "INFO" chunk.
*
* \note Modifying this map does not affect the tag's internal data.
* Use setFieldText() and removeField() instead.
*
* \see setFieldText()
* \see removeField()
*/
FieldListMap fieldListMap() const;
/*
* Gets the value of the field with the ID \a id.
*/
* Gets the value of the field with the ID \a id.
*/
String fieldText(const ByteVector &id) const;
/*
* Sets the value of the field with the ID \a id to \a s.
* If the field does not exist, it is created.
* If \s is empty, the field is removed.
*
* \note fieldId must be four-byte long pure ASCII string. This function
* performs nothing if fieldId is invalid.
*/
* Sets the value of the field with the ID \a id to \a s.
* If the field does not exist, it is created.
* If \s is empty, the field is removed.
*
* \note fieldId must be four-byte long pure ASCII string.
* This function performs nothing if fieldId is invalid.
*/
void setFieldText(const ByteVector &id, const String &s);
/*
* Removes the field with the ID \a id.
*/
* Removes the field with the ID \a id.
*/
void removeField(const ByteVector &id);
/*!
* Render the tag back to binary data, suitable to be written to disk.
*
* \note Returns empty ByteVector is the tag contains no fields.
*/
* Render the tag back to binary data, suitable to be written to disk.
*
* \note Returns empty ByteVector is the tag contains no fields.
*/
ByteVector render() const;
/*!
* Sets the string handler that decides how the text data will be
* converted to and from binary data.
* If the parameter \a handler is null, the previous handler is
* released and default UTF-8 handler is restored.
*
* \note The caller is responsible for deleting the previous handler
* as needed after it is released.
*
* \see StringHandler
*/
* Sets the string handler that decides how the text data will be
* converted to and from binary data.
* If the parameter \a handler is null, the previous handler is released and default UTF-8 handler is restored.
*
* \note The caller is responsible for deleting the previous handler as needed after it is released.
*
* \see StringHandler
*/
static void setStringHandler(const StringHandler *handler);
protected:
/*!
* Pareses the body of the tag in \a data.
*/
* Pareses the body of the tag in \a data.
*/
void parse(const ByteVector &data);
@@ -185,6 +182,7 @@ class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag {
class TagPrivate;
TagPrivate *d;
};
} // namespace Info
} // namespace RIFF
} // namespace TagLib

View File

@@ -37,15 +37,15 @@
using namespace Strawberry_TagLib::TagLib;
namespace {
enum { ID3v2Index = 0,
InfoIndex = 1 };
enum {
ID3v2Index = 0,
InfoIndex = 1
};
}
class RIFF::WAV::File::FilePrivate {
public:
FilePrivate() : properties(0),
hasID3v2(false),
hasInfo(false) {}
FilePrivate() : properties(nullptr), hasID3v2(false), hasInfo(false) {}
~FilePrivate() {
delete properties;
@@ -63,26 +63,30 @@ class RIFF::WAV::File::FilePrivate {
////////////////////////////////////////////////////////////////////////////////
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
////////////////////////////////////////////////////////////////////////////////
RIFF::WAV::File::File(FileName file, bool readProperties, Properties::ReadStyle) : RIFF::File(file, LittleEndian),
d(new FilePrivate()) {
RIFF::WAV::File::File(FileName file, bool readProperties, Properties::ReadStyle) : RIFF::File(file, LittleEndian), d(new FilePrivate()) {
if (isOpen())
read(readProperties);
}
RIFF::WAV::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : RIFF::File(stream, LittleEndian),
d(new FilePrivate()) {
RIFF::WAV::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : RIFF::File(stream, LittleEndian), d(new FilePrivate()) {
if (isOpen())
read(readProperties);
}
RIFF::WAV::File::~File() {
@@ -102,6 +106,7 @@ RIFF::Info::Tag *RIFF::WAV::File::InfoTag() const {
}
void RIFF::WAV::File::strip(TagTypes tags) {
removeTagChunks(tags);
if (tags & ID3v2)
@@ -109,6 +114,7 @@ void RIFF::WAV::File::strip(TagTypes tags) {
if (tags & Info)
d->tag.set(InfoIndex, new RIFF::Info::Tag());
}
PropertyMap RIFF::WAV::File::properties() const {
@@ -120,8 +126,10 @@ void RIFF::WAV::File::removeUnsupportedProperties(const StringList &unsupported)
}
PropertyMap RIFF::WAV::File::setProperties(const PropertyMap &properties) {
InfoTag()->setProperties(properties);
return ID3v2Tag()->setProperties(properties);
}
RIFF::WAV::Properties *RIFF::WAV::File::audioProperties() const {
@@ -132,13 +140,8 @@ bool RIFF::WAV::File::save() {
return RIFF::WAV::File::save(AllTags);
}
bool RIFF::WAV::File::save(TagTypes tags, bool stripOthers, int id3v2Version) {
return save(tags,
stripOthers ? StripOthers : StripNone,
id3v2Version == 3 ? ID3v2::v3 : ID3v2::v4);
}
bool RIFF::WAV::File::save(TagTypes tags, StripTags strip, ID3v2::Version version) {
if (readOnly()) {
debug("RIFF::WAV::File::save() -- File is read only.");
return false;
@@ -171,6 +174,7 @@ bool RIFF::WAV::File::save(TagTypes tags, StripTags strip, ID3v2::Version versio
}
return true;
}
bool RIFF::WAV::File::hasID3v2Tag() const {
@@ -186,6 +190,7 @@ bool RIFF::WAV::File::hasInfoTag() const {
////////////////////////////////////////////////////////////////////////////////
void RIFF::WAV::File::read(bool readProperties) {
for (unsigned int i = 0; i < chunkCount(); ++i) {
const ByteVector name = chunkName(i);
if (name == "ID3 " || name == "id3 ") {
@@ -222,6 +227,7 @@ void RIFF::WAV::File::read(bool readProperties) {
}
void RIFF::WAV::File::removeTagChunks(TagTypes tags) {
if ((tags & ID3v2) && d->hasID3v2) {
removeChunk("ID3 ");
removeChunk("id3 ");
@@ -237,4 +243,5 @@ void RIFF::WAV::File::removeTagChunks(TagTypes tags) {
d->hasInfo = false;
}
}

View File

@@ -39,22 +39,22 @@ namespace RIFF {
//! An implementation of WAV metadata
/*!
* This is implementation of WAV metadata.
*
* This supports an ID3v2 tag as well as reading stream from the ID3 RIFF
* chunk as well as properties from the file.
*/
* This is implementation of WAV metadata.
*
* This supports an ID3v2 tag as well as reading stream from the ID3 RIFF
* chunk as well as properties from the file.
*/
namespace WAV {
//! An implementation of TagLib::File with WAV specific methods
/*!
* This implements and provides an interface for WAV files to the
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
* the abstract TagLib::File API as well as providing some additional
* information specific to WAV files.
*/
* This implements and provides an interface for WAV files to the
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
* the abstract TagLib::File API as well as providing some additional
* information specific to WAV files.
*/
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::RIFF::File {
public:
@@ -70,130 +70,114 @@ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::RIFF::File {
};
/*!
* Constructs a WAV file from \a file. If \a readProperties is true the
* file's audio properties will also be read.
*
* \note In the current implementation, \a propertiesStyle is ignored.
*/
File(FileName file, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
* Constructs a WAV file from \a file.
* If \a readProperties is true the file's audio properties will also be read.
*
* \note In the current implementation, \a propertiesStyle is ignored.
*/
File(FileName file, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average);
/*!
* Constructs a WAV file from \a stream. If \a readProperties is true the
* file's audio properties will also be read.
*
* \note TagLib will *not* take ownership of the stream, the caller is
* responsible for deleting it after the File object.
*
* \note In the current implementation, \a propertiesStyle is ignored.
*/
File(IOStream *stream, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
* Constructs a WAV file from \a stream.
* If \a readProperties is true the file's audio properties will also be read.
*
* \note TagLib will *not* take ownership of the stream, the caller is responsible for deleting it after the File object.
*
* \note In the current implementation, \a propertiesStyle is ignored.
*/
File(IOStream *stream, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average);
/*!
* Destroys this instance of the File.
*/
* Destroys this instance of the File.
*/
virtual ~File();
/*!
* Returns the ID3v2 Tag for this file.
*
* \note This method does not return all the tags for this file for
* backward compatibility. Will be fixed in TagLib 2.0.
*/
* Returns the ID3v2 Tag for this file.
*
* \note This method does not return all the tags for this file for backward compatibility. Will be fixed in TagLib 2.0.
*/
ID3v2::Tag *tag() const;
/*!
* Returns the ID3v2 Tag for this file.
*
* \note This always returns a valid pointer regardless of whether or not
* the file on disk has an ID3v2 tag. Use hasID3v2Tag() to check if the
* file on disk actually has an ID3v2 tag.
*
* \see hasID3v2Tag()
*/
* Returns the ID3v2 Tag for this file.
*
* \note This always returns a valid pointer regardless of whether or not the file on disk has an ID3v2 tag.
* Use hasID3v2Tag() to check if the file on disk actually has an ID3v2 tag.
*
* \see hasID3v2Tag()
*/
ID3v2::Tag *ID3v2Tag() const;
/*!
* Returns the RIFF INFO Tag for this file.
*
* \note This always returns a valid pointer regardless of whether or not
* the file on disk has a RIFF INFO tag. Use hasInfoTag() to check if the
* file on disk actually has a RIFF INFO tag.
*
* \see hasInfoTag()
*/
* Returns the RIFF INFO Tag for this file.
*
* \note This always returns a valid pointer regardless of whether or not the file on disk has a RIFF INFO tag.
* Use hasInfoTag() to check if the file on disk actually has a RIFF INFO tag.
*
* \see hasInfoTag()
*/
Info::Tag *InfoTag() const;
/*!
* This will strip the tags that match the OR-ed together TagTypes from the
* file. By default it strips all tags. It returns true if the tags are
* successfully stripped.
*
* \note This will update the file immediately.
*/
* This will strip the tags that match the OR-ed together TagTypes from the file.
* By default it strips all tags. It returns true if the tags are successfully stripped.
*
* \note This will update the file immediately.
*/
void strip(TagTypes tags = AllTags);
/*!
* Implements the unified property interface -- export function.
* This method forwards to ID3v2::Tag::properties().
*/
* Implements the unified property interface -- export function.
* This method forwards to ID3v2::Tag::properties().
*/
PropertyMap properties() const;
void removeUnsupportedProperties(const StringList &properties);
/*!
* Implements the unified property interface -- import function.
* This method forwards to ID3v2::Tag::setProperties().
*/
* Implements the unified property interface -- import function.
* This method forwards to ID3v2::Tag::setProperties().
*/
PropertyMap setProperties(const PropertyMap &);
/*!
* Returns the WAV::Properties for this file. If no audio properties
* were read then this will return a null pointer.
*/
* Returns the WAV::Properties for this file. If no audio properties
* were read then this will return a null pointer.
*/
virtual Properties *audioProperties() const;
/*!
* Saves the file.
*/
* Saves the file.
*/
virtual bool save();
/*!
* \deprecated
*/
TAGLIB_DEPRECATED bool save(TagTypes tags, bool stripOthers, int id3v2Version = 4);
* Save the file.
* If \a strip is specified, it is possible to choose if tags not specified in \a tags should be stripped from the file or retained.
* With \a version, it is possible to specify whether ID3v2.4 or ID3v2.3 should be used.
*/
bool save(TagTypes tags, StripTags strip = StripOthers, ID3v2::Version version = ID3v2::v4);
/*!
* Save the file. If \a strip is specified, it is possible to choose if
* tags not specified in \a tags should be stripped from the file or
* retained. With \a version, it is possible to specify whether ID3v2.4
* or ID3v2.3 should be used.
*/
bool save(TagTypes tags, StripTags strip = StripOthers,
ID3v2::Version version = ID3v2::v4);
/*!
* Returns whether or not the file on disk actually has an ID3v2 tag.
*
* \see ID3v2Tag()
*/
* Returns whether or not the file on disk actually has an ID3v2 tag.
*
* \see ID3v2Tag()
*/
bool hasID3v2Tag() const;
/*!
* Returns whether or not the file on disk actually has a RIFF INFO tag.
*
* \see InfoTag()
*/
* Returns whether or not the file on disk actually has a RIFF INFO tag.
*
* \see InfoTag()
*/
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.
*/
* 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:
@@ -208,6 +192,7 @@ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::RIFF::File {
class FilePrivate;
FilePrivate *d;
};
} // namespace WAV
} // namespace RIFF
} // namespace TagLib

View File

@@ -60,18 +60,7 @@ class RIFF::WAV::Properties::PropertiesPrivate {
// public members
////////////////////////////////////////////////////////////////////////////////
RIFF::WAV::Properties::Properties(const ByteVector &, ReadStyle style) : AudioProperties(style),
d(new PropertiesPrivate()) {
debug("RIFF::WAV::Properties::Properties() -- This constructor is no longer used.");
}
RIFF::WAV::Properties::Properties(const ByteVector &, unsigned int, ReadStyle style) : AudioProperties(style),
d(new PropertiesPrivate()) {
debug("RIFF::WAV::Properties::Properties() -- This constructor is no longer used.");
}
Strawberry_TagLib::TagLib::RIFF::WAV::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style),
d(new PropertiesPrivate()) {
Strawberry_TagLib::TagLib::RIFF::WAV::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style),d(new PropertiesPrivate()) {
read(file);
}
@@ -79,10 +68,6 @@ RIFF::WAV::Properties::~Properties() {
delete d;
}
int RIFF::WAV::Properties::length() const {
return lengthInSeconds();
}
int RIFF::WAV::Properties::lengthInSeconds() const {
return d->length / 1000;
}
@@ -107,10 +92,6 @@ int RIFF::WAV::Properties::bitsPerSample() const {
return d->bitsPerSample;
}
int RIFF::WAV::Properties::sampleWidth() const {
return bitsPerSample();
}
unsigned int RIFF::WAV::Properties::sampleFrames() const {
return d->sampleFrames;
}
@@ -124,6 +105,7 @@ int RIFF::WAV::Properties::format() const {
////////////////////////////////////////////////////////////////////////////////
void RIFF::WAV::Properties::read(File *file) {
ByteVector data;
unsigned int streamLength = 0;
unsigned int totalSamples = 0;
@@ -187,4 +169,5 @@ void RIFF::WAV::Properties::read(File *file) {
d->bitrate = static_cast<int>(byteRate * 8.0 / 1000.0 + 0.5);
}
}
}

View File

@@ -35,7 +35,6 @@ namespace TagLib {
class ByteVector;
namespace RIFF {
namespace WAV {
class File;
@@ -43,108 +42,70 @@ class File;
//! An implementation of audio property reading for WAV
/*!
* This reads the data from an WAV stream found in the AudioProperties
* API.
*/
* This reads the data from an WAV stream found in the AudioProperties
* API.
*/
class TAGLIB_EXPORT Properties : public AudioProperties {
public:
/*!
* Create an instance of WAV::Properties with the data read from the
* ByteVector \a data.
*
* \deprecated
*/
TAGLIB_DEPRECATED Properties(const ByteVector &data, ReadStyle style);
/*!
* Create an instance of WAV::Properties with the data read from the
* ByteVector \a data and the length calculated using \a streamLength.
*
* \deprecated
*/
TAGLIB_DEPRECATED Properties(const ByteVector &data, unsigned int streamLength, ReadStyle style);
/*!
* Create an instance of WAV::Properties with the data read from the
* WAV::File \a file.
*/
* Create an instance of WAV::Properties with the data read from the WAV::File \a file.
*/
Properties(File *file, ReadStyle style);
/*!
* Destroys this WAV::Properties instance.
*/
* Destroys this WAV::Properties instance.
*/
virtual ~Properties();
/*!
* Returns the length of the file in seconds. The length is rounded down to
* the nearest whole second.
*
* \note This method is just an alias of lengthInSeconds().
*
* \deprecated
*/
TAGLIB_DEPRECATED virtual int length() const;
/*!
* Returns the length of the file in seconds. The length is rounded down to
* the nearest whole second.
*
* \see lengthInMilliseconds()
*/
* Returns the length of the file in seconds.
* The length is rounded down to the nearest whole second.
*
* \see lengthInMilliseconds()
*/
// BIC: make virtual
int lengthInSeconds() const;
/*!
* Returns the length of the file in milliseconds.
*
* \see lengthInSeconds()
*/
* Returns the length of the file in milliseconds.
*
* \see lengthInSeconds()
*/
// BIC: make virtual
int lengthInMilliseconds() const;
/*!
* Returns the average bit rate of the file in kb/s.
*/
* Returns the average bit rate of the file in kb/s.
*/
virtual int bitrate() const;
/*!
* Returns the sample rate in Hz.
*/
* Returns the sample rate in Hz.
*/
virtual int sampleRate() const;
/*!
* Returns the number of audio channels.
*/
* Returns the number of audio channels.
*/
virtual int channels() const;
/*!
* Returns the number of bits per audio sample.
*/
* Returns the number of bits per audio sample.
*/
int bitsPerSample() const;
/*!
* Returns the number of bits per audio sample.
*
* \note This method is just an alias of bitsPerSample().
*
* \deprecated
*/
TAGLIB_DEPRECATED int sampleWidth() const;
/*!
* Returns the number of sample frames.
*/
* Returns the number of sample frames.
*/
unsigned int sampleFrames() const;
/*!
* Returns the format ID of the file.
* 0 for unknown, 1 for PCM, 2 for ADPCM, 3 for 32/64-bit IEEE754, and
* so forth.
*
* \note For further information, refer to the WAVE Form Registration
* Numbers in RFC 2361.
*/
* Returns the format ID of the file.
* 0 for unknown, 1 for PCM, 2 for ADPCM, 3 for 32/64-bit IEEE754, and so forth.
*
* \note For further information, refer to the WAVE Form Registration Numbers in RFC 2361.
*/
int format() const;
private:
@@ -156,6 +117,7 @@ class TAGLIB_EXPORT Properties : public AudioProperties {
class PropertiesPrivate;
PropertiesPrivate *d;
};
} // namespace WAV
} // namespace RIFF
} // namespace TagLib