Adapt most changes from taglib2

This commit is contained in:
Jonas Kvinge
2020-06-26 23:30:30 +02:00
parent 08882639e0
commit 5f71a558b9
374 changed files with 13708 additions and 4418 deletions

View File

@@ -23,11 +23,11 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include <tbytevector.h>
#include <tstring.h>
#include <tdebug.h>
#include <tpropertymap.h>
#include <tagutils.h>
#include "tbytevector.h"
#include "tstring.h"
#include "tdebug.h"
#include "tpropertymap.h"
#include "tagutils.h"
#include <xiphcomment.h>
#include "oggflacfile.h"
@@ -37,13 +37,13 @@ using Strawberry_TagLib::TagLib::FLAC::AudioProperties;
class Ogg::FLAC::File::FilePrivate {
public:
FilePrivate() : comment(nullptr),
properties(nullptr),
streamStart(0),
streamLength(0),
scanned(false),
hasXiphComment(false),
commentPacket(0) {}
explicit FilePrivate() : comment(nullptr),
properties(nullptr),
streamStart(0),
streamLength(0),
scanned(false),
hasXiphComment(false),
commentPacket(0) {}
~FilePrivate() {
delete comment;
@@ -55,8 +55,8 @@ class Ogg::FLAC::File::FilePrivate {
AudioProperties *properties;
ByteVector streamInfoData;
ByteVector xiphCommentData;
long streamStart;
long streamLength;
long long streamStart;
long long streamLength;
bool scanned;
bool hasXiphComment;
@@ -71,7 +71,7 @@ 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);
return (buffer.find("OggS") != ByteVector::npos() && buffer.find("fLaC") != ByteVector::npos());
}
////////////////////////////////////////////////////////////////////////////////
@@ -100,14 +100,6 @@ Ogg::XiphComment *Ogg::FLAC::File::tag() const {
return d->comment;
}
PropertyMap Ogg::FLAC::File::properties() const {
return d->comment->properties();
}
PropertyMap Ogg::FLAC::File::setProperties(const PropertyMap &properties) {
return d->comment->setProperties(properties);
}
FLAC::AudioProperties *Ogg::FLAC::File::audioProperties() const {
return d->properties;
}
@@ -121,7 +113,7 @@ bool Ogg::FLAC::File::save() {
// Put the size in the first 32 bit (I assume no more than 24 bit are used)
ByteVector v = ByteVector::fromUInt(d->xiphCommentData.size());
ByteVector v = ByteVector::fromUInt32BE(d->xiphCommentData.size());
// Set the type of the metadata-block to be a Xiph / Vorbis comment
@@ -192,7 +184,7 @@ ByteVector Ogg::FLAC::File::xiphCommentData() {
return d->xiphCommentData;
}
long Ogg::FLAC::File::streamLength() {
long long Ogg::FLAC::File::streamLength() {
scan();
return d->streamLength;
}
@@ -208,7 +200,7 @@ void Ogg::FLAC::File::scan() {
return;
int ipacket = 0;
long overhead = 0;
long long overhead = 0;
ByteVector metadataHeader = packet(ipacket);
if (metadataHeader.isEmpty())
@@ -257,7 +249,7 @@ void Ogg::FLAC::File::scan() {
char blockType = header[0] & 0x7f;
bool lastBlock = (header[0] & 0x80) != 0;
unsigned int length = header.toUInt(1, 3, true);
unsigned int length = header.toUInt24BE(1);
overhead += length;
// Sanity: First block should be the stream_info metadata
@@ -281,7 +273,7 @@ void Ogg::FLAC::File::scan() {
blockType = header[0] & 0x7f;
lastBlock = (header[0] & 0x80) != 0;
length = header.toUInt(1, 3, true);
length = header.toUInt24BE(1);
overhead += length;
if (blockType == 1) {

View File

@@ -84,7 +84,7 @@ class TAGLIB_EXPORT File : public Ogg::File {
/*!
* Destroys this instance of the File.
*/
virtual ~File();
~File() override;
/*!
* Returns the Tag for this file. This will always be a XiphComment.
@@ -97,38 +97,24 @@ class TAGLIB_EXPORT File : public Ogg::File {
*
* \see hasXiphComment()
*/
virtual XiphComment *tag() const;
XiphComment *tag() const override;
/*!
* Returns the FLAC::AudioProperties for this file.
* If no audio properties were read then this will return a null pointer.
*/
virtual AudioProperties *audioProperties() const;
/*!
* Implements the unified property interface -- export function.
* This forwards directly to XiphComment::properties().
*/
PropertyMap properties() const;
/*!
* Implements the unified tag dictionary interface -- import function.
* Like properties(), this is a forwarder to the file's XiphComment.
*/
PropertyMap setProperties(const PropertyMap &);
AudioProperties *audioProperties() const override;
/*!
* Save the file. This will primarily save and update the XiphComment.
* Returns true if the save is successful.
*/
virtual bool save();
bool save() override;
/*!
* Returns the length of the audio-stream, used by FLAC::AudioProperties for calculating the bitrate.
*/
long streamLength();
long long streamLength();
/*!
* Returns whether or not the file on disk actually has a XiphComment.
@@ -145,7 +131,7 @@ class TAGLIB_EXPORT File : public Ogg::File {
static bool isSupported(IOStream *stream);
private:
explicit File(const File&);
File(const File&);
File &operator=(const File&);
void read(bool readProperties, AudioProperties::ReadStyle propertiesStyle);

View File

@@ -23,10 +23,10 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include <tbytevectorlist.h>
#include <tmap.h>
#include <tstring.h>
#include <tdebug.h>
#include "tbytevectorlist.h"
#include "tmap.h"
#include "tstring.h"
#include "tdebug.h"
#include "oggfile.h"
#include "oggpage.h"
@@ -48,7 +48,7 @@ unsigned int nextPacketIndex(const Ogg::Page *page) {
class Ogg::File::FilePrivate {
public:
FilePrivate() : streamSerialNumber(0), firstPageHeader(nullptr), lastPageHeader(nullptr) {
explicit FilePrivate() : streamSerialNumber(0), firstPageHeader(nullptr), lastPageHeader(nullptr) {
pages.setAutoDelete(true);
}
@@ -74,8 +74,7 @@ Ogg::File::~File() {
ByteVector Ogg::File::packet(unsigned int i) {
// Check to see if we're called setPacket() for this packet since the last
// save:
// Check to see if we're called setPacket() for this packet since the last save:
if (d->dirtyPackets.contains(i))
return d->dirtyPackets[i];
@@ -126,7 +125,7 @@ void Ogg::File::setPacket(unsigned int i, const ByteVector &p) {
const Ogg::PageHeader *Ogg::File::firstPageHeader() {
if (!d->firstPageHeader) {
const long firstPageHeaderOffset = find("OggS");
const long long firstPageHeaderOffset = find("OggS");
if (firstPageHeaderOffset < 0)
return nullptr;
@@ -140,7 +139,7 @@ const Ogg::PageHeader *Ogg::File::firstPageHeader() {
const Ogg::PageHeader *Ogg::File::lastPageHeader() {
if (!d->lastPageHeader) {
const long lastPageHeaderOffset = rfind("OggS");
const long long lastPageHeaderOffset = rfind("OggS");
if (lastPageHeaderOffset < 0)
return nullptr;
@@ -184,7 +183,7 @@ bool Ogg::File::readPages(unsigned int i) {
while (true) {
unsigned int packetIndex;
long offset;
long long offset;
if (d->pages.isEmpty()) {
packetIndex = 0;
@@ -268,8 +267,8 @@ void Ogg::File::writePacket(unsigned int i, const ByteVector &packet) {
for (it = pages.begin(); it != pages.end(); ++it)
data.append((*it)->render());
const unsigned long originalOffset = firstPage->fileOffset();
const unsigned long originalLength = lastPage->fileOffset() + lastPage->size() - originalOffset;
const long long originalOffset = firstPage->fileOffset();
const long long originalLength = lastPage->fileOffset() + lastPage->size() - originalOffset;
insert(data, originalOffset, originalLength);
@@ -278,7 +277,7 @@ void Ogg::File::writePacket(unsigned int i, const ByteVector &packet) {
const int numberOfNewPages = pages.back()->pageSequenceNumber() - lastPage->pageSequenceNumber();
if (numberOfNewPages != 0) {
long pageOffset = originalOffset + data.size();
long long pageOffset = originalOffset + data.size();
while (true) {
Page page(this, pageOffset);

View File

@@ -49,7 +49,7 @@ class PageHeader;
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File {
public:
virtual ~File();
~File() override;
/*!
* Returns the packet contents for the i-th packet (starting from zero) in the Ogg bitstream.
@@ -73,7 +73,7 @@ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File {
*/
const PageHeader *lastPageHeader();
virtual bool save();
bool save() override;
protected:
/*!
@@ -90,10 +90,10 @@ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File {
*
* \note TagLib will *not* take ownership of the stream, the caller is responsible for deleting it after the File object.
*/
File(IOStream *stream);
explicit File(IOStream *stream);
private:
explicit File(const File &);
File(const File &);
File &operator=(const File &);
/*!

View File

@@ -25,8 +25,8 @@
#include <algorithm>
#include <tstring.h>
#include <tdebug.h>
#include "tstring.h"
#include "tdebug.h"
#include "oggpage.h"
#include "oggpageheader.h"
@@ -86,16 +86,16 @@ ByteVector checksum(const ByteVector &v) {
for (ByteVector::ConstIterator it = v.begin(); it != v.end(); ++it)
sum = (sum << 8) ^ crcTable[((sum >> 24) & 0xff) ^ static_cast<unsigned char>(*it)];
return ByteVector::fromUInt(sum);
return ByteVector::fromUInt32LE(sum);
}
} // namespace
class Ogg::Page::PagePrivate {
public:
PagePrivate(File *f = nullptr, long pageOffset = -1) : file(f), fileOffset(pageOffset), header(f, pageOffset), firstPacketIndex(-1) {}
explicit PagePrivate(File *f = nullptr, long long pageOffset = -1) : file(f), fileOffset(pageOffset), header(f, pageOffset), firstPacketIndex(-1) {}
File *file;
long fileOffset;
long long fileOffset;
PageHeader header;
int firstPacketIndex;
ByteVectorList packets;
@@ -105,13 +105,13 @@ class Ogg::Page::PagePrivate {
// public members
////////////////////////////////////////////////////////////////////////////////
Ogg::Page::Page(Ogg::File *file, long pageOffset) : d(new PagePrivate(file, pageOffset)) {}
Ogg::Page::Page(Ogg::File *file, long long pageOffset) : d(new PagePrivate(file, pageOffset)) {}
Ogg::Page::~Page() {
delete d;
}
long Ogg::Page::fileOffset() const {
long long Ogg::Page::fileOffset() const {
return d->fileOffset;
}

View File

@@ -54,14 +54,14 @@ class TAGLIB_EXPORT Page {
/*!
* Read an Ogg page from the \a file at the position \a pageOffset.
*/
explicit Page(File *file, long pageOffset);
explicit Page(File *file, long long pageOffset);
virtual ~Page();
/*!
* Returns the page's position within the file (in bytes).
*/
long fileOffset() const;
long long fileOffset() const;
/*!
* Returns a pointer to the header for this page. This pointer will become invalid when the page is deleted.
@@ -193,7 +193,7 @@ class TAGLIB_EXPORT Page {
bool containsLastPacket = false);
private:
explicit Page(const Page &);
Page(const Page &);
Page &operator=(const Page &);
class PagePrivate;

View File

@@ -25,9 +25,9 @@
#include <bitset>
#include <tstring.h>
#include <tdebug.h>
#include <taglib.h>
#include "tstring.h"
#include "tdebug.h"
#include "taglib.h"
#include "oggpageheader.h"
#include "oggfile.h"
@@ -36,16 +36,16 @@ using namespace Strawberry_TagLib::TagLib;
class Ogg::PageHeader::PageHeaderPrivate {
public:
PageHeaderPrivate() : isValid(false),
firstPacketContinued(false),
lastPacketCompleted(false),
firstPageOfStream(false),
lastPageOfStream(false),
absoluteGranularPosition(0),
streamSerialNumber(0),
pageSequenceNumber(-1),
size(0),
dataSize(0) {}
explicit PageHeaderPrivate() : isValid(false),
firstPacketContinued(false),
lastPacketCompleted(false),
firstPageOfStream(false),
lastPageOfStream(false),
absoluteGranularPosition(0),
streamSerialNumber(0),
pageSequenceNumber(-1),
size(0),
dataSize(0) {}
bool isValid;
List<int> packetSizes;
@@ -64,7 +64,7 @@ class Ogg::PageHeader::PageHeaderPrivate {
// public members
////////////////////////////////////////////////////////////////////////////////
Ogg::PageHeader::PageHeader(Ogg::File *file, long pageOffset) : d(new PageHeaderPrivate()) {
Ogg::PageHeader::PageHeader(Ogg::File *file, long long pageOffset) : d(new PageHeaderPrivate()) {
if (file && pageOffset >= 0)
read(file, pageOffset);
@@ -174,15 +174,15 @@ ByteVector Ogg::PageHeader::render() const {
// absolute granular position
data.append(ByteVector::fromLongLong(d->absoluteGranularPosition, false));
data.append(ByteVector::fromUInt64LE(d->absoluteGranularPosition));
// stream serial number
data.append(ByteVector::fromUInt(d->streamSerialNumber, false));
data.append(ByteVector::fromUInt32LE(d->streamSerialNumber));
// page sequence number
data.append(ByteVector::fromUInt(d->pageSequenceNumber, false));
data.append(ByteVector::fromUInt32LE(d->pageSequenceNumber));
// checksum -- this is left empty and should be filled in by the Ogg::Page
// class
@@ -204,7 +204,7 @@ ByteVector Ogg::PageHeader::render() const {
// private members
////////////////////////////////////////////////////////////////////////////////
void Ogg::PageHeader::read(Ogg::File *file, long pageOffset) {
void Ogg::PageHeader::read(Ogg::File *file, long long pageOffset) {
file->seek(pageOffset);
@@ -227,9 +227,9 @@ void Ogg::PageHeader::read(Ogg::File *file, long pageOffset) {
d->firstPageOfStream = flags.test(1);
d->lastPageOfStream = flags.test(2);
d->absoluteGranularPosition = data.toLongLong(6, false);
d->streamSerialNumber = data.toUInt(14, false);
d->pageSequenceNumber = data.toUInt(18, false);
d->absoluteGranularPosition = data.toInt64LE(6);
d->streamSerialNumber = data.toUInt32LE(14);
d->pageSequenceNumber = data.toUInt32LE(18);
// Byte number 27 is the number of page segments, which is the only variable
// length portion of the page header. After reading the number of page

View File

@@ -48,7 +48,7 @@ class TAGLIB_EXPORT PageHeader {
* Reads a PageHeader from \a file starting at \a pageOffset.
* The defaults create a page with no (and as such, invalid) data that must be set later.
*/
explicit PageHeader(File *file = 0, long pageOffset = -1);
explicit PageHeader(File *file = nullptr, long long pageOffset = -1);
/*!
* Deletes this instance of the PageHeader.
@@ -200,10 +200,10 @@ class TAGLIB_EXPORT PageHeader {
ByteVector render() const;
private:
explicit PageHeader(const PageHeader&);
PageHeader(const PageHeader&);
PageHeader &operator=(const PageHeader&);
void read(Ogg::File *file, long pageOffset);
void read(Ogg::File *file, long long pageOffset);
ByteVector lacingValues() const;
class PageHeaderPrivate;

View File

@@ -27,10 +27,10 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include <tstring.h>
#include <tdebug.h>
#include <tpropertymap.h>
#include <tagutils.h>
#include "tstring.h"
#include "tdebug.h"
#include "tpropertymap.h"
#include "tagutils.h"
#include "opusfile.h"
@@ -39,7 +39,7 @@ using namespace Strawberry_TagLib::TagLib::Ogg;
class Opus::File::FilePrivate {
public:
FilePrivate() : comment(nullptr), properties(nullptr) {}
explicit FilePrivate() : comment(nullptr), properties(nullptr) {}
~FilePrivate() {
delete comment;
@@ -59,7 +59,7 @@ 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);
return (buffer.find("OggS") != ByteVector::npos() && buffer.find("OpusHead") != ByteVector::npos());
}
@@ -89,14 +89,6 @@ Ogg::XiphComment *Opus::File::tag() const {
return d->comment;
}
PropertyMap Opus::File::properties() const {
return d->comment->properties();
}
PropertyMap Opus::File::setProperties(const PropertyMap &properties) {
return d->comment->setProperties(properties);
}
Opus::AudioProperties *Opus::File::audioProperties() const {
return d->properties;
}

View File

@@ -76,38 +76,26 @@ class TAGLIB_EXPORT File : public Ogg::File {
/*!
* Destroys this instance of the File.
*/
virtual ~File();
~File() override;
/*!
* Returns the XiphComment for this file.
* XiphComment implements the tag interface, so this serves as the reimplementation of TagLib::File::tag().
*/
virtual Ogg::XiphComment *tag() const;
/*!
* Implements the unified property interface -- export function.
* This forwards directly to XiphComment::properties().
*/
PropertyMap properties() const;
/*!
* Implements the unified tag dictionary interface -- import function.
* Like properties(), this is a forwarder to the file's XiphComment.
*/
PropertyMap setProperties(const PropertyMap &);
Ogg::XiphComment *tag() const override;
/*!
* Returns the Opus::AudioProperties for this file.
* If no audio properties were read then this will return a null pointer.
*/
virtual AudioProperties *audioProperties() const;
AudioProperties *audioProperties() const override;
/*!
* Save the file.
*
* This returns true if the save was successful.
*/
virtual bool save();
bool save() override;
/*!
* Returns whether or not the given \a stream can be opened as an Opus file.
@@ -117,7 +105,7 @@ class TAGLIB_EXPORT File : public Ogg::File {
static bool isSupported(IOStream *stream);
private:
explicit File(const File&);
File(const File&);
File &operator=(const File&);
void read(bool readProperties);

View File

@@ -27,8 +27,8 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include <tstring.h>
#include <tdebug.h>
#include "tstring.h"
#include "tdebug.h"
#include <oggpageheader.h>
@@ -40,11 +40,11 @@ using namespace Strawberry_TagLib::TagLib::Ogg;
class Opus::AudioProperties::AudioPropertiesPrivate {
public:
AudioPropertiesPrivate() : length(0),
bitrate(0),
inputSampleRate(0),
channels(0),
opusVersion(0) {}
explicit AudioPropertiesPrivate() : length(0),
bitrate(0),
inputSampleRate(0),
channels(0),
opusVersion(0) {}
int length;
int bitrate;
@@ -57,7 +57,7 @@ class Opus::AudioProperties::AudioPropertiesPrivate {
// public members
////////////////////////////////////////////////////////////////////////////////
Opus::AudioProperties::AudioProperties(File *file, ReadStyle style) : Strawberry_TagLib::TagLib::AudioProperties(style), d(new AudioPropertiesPrivate()) {
Opus::AudioProperties::AudioProperties(File *file, ReadStyle) : Strawberry_TagLib::TagLib::AudioProperties(), d(new AudioPropertiesPrivate()) {
read(file);
}
@@ -65,11 +65,11 @@ Opus::AudioProperties::~AudioProperties() {
delete d;
}
int Ogg::Opus::AudioProperties::lengthInSeconds() const {
int Opus::AudioProperties::lengthInSeconds() const {
return d->length / 1000;
}
int Ogg::Opus::AudioProperties::lengthInMilliseconds() const {
int Opus::AudioProperties::lengthInMilliseconds() const {
return d->length;
}
@@ -111,7 +111,7 @@ void Opus::AudioProperties::read(File *file) {
const ByteVector data = file->packet(0);
// *Magic Signature*
unsigned int pos = 8;
size_t pos = 8;
// *Version* (8 bits, unsigned)
d->opusVersion = static_cast<unsigned char>(data.at(pos));
@@ -122,11 +122,11 @@ void Opus::AudioProperties::read(File *file) {
pos += 1;
// *Pre-skip* (16 bits, unsigned, little endian)
const unsigned short preSkip = data.toUShort(pos, false);
const unsigned short preSkip = data.toUInt16LE(pos);
pos += 2;
// *Input Sample Rate* (32 bits, unsigned, little endian)
d->inputSampleRate = data.toUInt(pos, false);
d->inputSampleRate = data.toUInt32LE(pos);
pos += 4;
// *Output Gain* (16 bits, signed, little endian)
@@ -147,14 +147,15 @@ void Opus::AudioProperties::read(File *file) {
if (frameCount > 0) {
const double length = frameCount * 1000.0 / 48000.0;
long fileLengthWithoutOverhead = file->length();
//long fileLengthWithoutOverhead = file->length();
// Ignore the two mandatory header packets, see "3. Packet Organization"
// in https://tools.ietf.org/html/rfc7845.html
for (unsigned int i = 0; i < 2; ++i) {
fileLengthWithoutOverhead -= file->packet(i).size();
}
//for (unsigned int i = 0; i < 2; ++i) {
//fileLengthWithoutOverhead -= file->packet(i).size();
//}
d->length = static_cast<int>(length + 0.5);
d->bitrate = static_cast<int>(fileLengthWithoutOverhead * 8.0 / length + 0.5);
//d->bitrate = static_cast<int>(fileLengthWithoutOverhead * 8.0 / length + 0.5);
d->bitrate = static_cast<int>(file->length() * 8.0 / length + 0.5);
}
}
else {

View File

@@ -58,38 +58,38 @@ class TAGLIB_EXPORT AudioProperties : public Strawberry_TagLib::TagLib::AudioPro
/*!
* Destroys this Opus::AudioProperties instance.
*/
virtual ~AudioProperties();
~AudioProperties() override;
/*!
* Returns the length of the file in seconds. The length is rounded down to the nearest whole second.
*
* \see lengthInMilliseconds()
*/
virtual int lengthInSeconds() const;
int lengthInSeconds() const override;
/*!
* Returns the length of the file in milliseconds.
*
* \see lengthInSeconds()
*/
virtual int lengthInMilliseconds() const;
int lengthInMilliseconds() const override;
/*!
* Returns the average bit rate of the file in kb/s.
*/
virtual int bitrate() const;
int bitrate() const override;
/*!
* Returns the sample rate in Hz.
*
* \note Always returns 48000, because Opus can decode any stream at a sample rate of 8, 12, 16, 24, or 48 kHz,
*/
virtual int sampleRate() const;
int sampleRate() const override;
/*!
* Returns the number of audio channels.
*/
virtual int channels() const;
int channels() const override;
/*!
* The Opus codec supports decoding at multiple sample rates, there is no single sample rate of the encoded stream.
@@ -103,9 +103,6 @@ class TAGLIB_EXPORT AudioProperties : public Strawberry_TagLib::TagLib::AudioPro
int opusVersion() const;
private:
explicit AudioProperties(const AudioProperties&);
AudioProperties &operator=(const AudioProperties&);
void read(File *file);
class AudioPropertiesPrivate;

View File

@@ -27,10 +27,10 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include <tstring.h>
#include <tdebug.h>
#include <tpropertymap.h>
#include <tagutils.h>
#include "tstring.h"
#include "tdebug.h"
#include "tpropertymap.h"
#include "tagutils.h"
#include "speexfile.h"
@@ -39,7 +39,7 @@ using namespace Strawberry_TagLib::TagLib::Ogg;
class Speex::File::FilePrivate {
public:
FilePrivate() : comment(nullptr), properties(nullptr) {}
explicit FilePrivate() : comment(nullptr), properties(nullptr) {}
~FilePrivate() {
delete comment;
@@ -59,7 +59,7 @@ 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);
return (buffer.find("OggS") != ByteVector::npos() && buffer.find("Speex ") != ByteVector::npos());
}
@@ -85,14 +85,6 @@ Ogg::XiphComment *Speex::File::tag() const {
return d->comment;
}
PropertyMap Speex::File::properties() const {
return d->comment->properties();
}
PropertyMap Speex::File::setProperties(const PropertyMap &properties) {
return d->comment->setProperties(properties);
}
Speex::AudioProperties *Speex::File::audioProperties() const {
return d->properties;
}

View File

@@ -77,37 +77,25 @@ class TAGLIB_EXPORT File : public Ogg::File {
/*!
* Destroys this instance of the File.
*/
virtual ~File();
~File() override;
/*!
* Returns the XiphComment for this file. XiphComment implements the tag interface, so this serves as the reimplementation of TagLib::File::tag().
*/
virtual Ogg::XiphComment *tag() const;
/*!
* Implements the unified property interface -- export function.
* This forwards directly to XiphComment::properties().
*/
PropertyMap properties() const;
/*!
* Implements the unified tag dictionary interface -- import function.
* Like properties(), this is a forwarder to the file's XiphComment.
*/
PropertyMap setProperties(const PropertyMap &);
Ogg::XiphComment *tag() const override;
/*!
* Returns the Speex::AudioProperties for this file.
* If no audio properties were read then this will return a null pointer.
*/
virtual AudioProperties *audioProperties() const;
AudioProperties *audioProperties() const override;
/*!
* Save the file.
*
* This returns true if the save was successful.
*/
virtual bool save();
bool save() override;
/*!
* Returns whether or not the given \a stream can be opened as a Speex file.
@@ -117,7 +105,7 @@ class TAGLIB_EXPORT File : public Ogg::File {
static bool isSupported(IOStream *stream);
private:
explicit File(const File&);
File(const File&);
File &operator=(const File&);
void read(bool readProperties);

View File

@@ -27,10 +27,10 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include <tstring.h>
#include <tdebug.h>
#include "tstring.h"
#include "tdebug.h"
#include <oggpageheader.h>
#include "oggpageheader.h"
#include "speexproperties.h"
#include "speexfile.h"
@@ -40,14 +40,14 @@ using namespace Strawberry_TagLib::TagLib::Ogg;
class Speex::AudioProperties::AudioPropertiesPrivate {
public:
AudioPropertiesPrivate() : length(0),
bitrate(0),
bitrateNominal(0),
sampleRate(0),
channels(0),
speexVersion(0),
vbr(false),
mode(0) {}
explicit AudioPropertiesPrivate() : length(0),
bitrate(0),
bitrateNominal(0),
sampleRate(0),
channels(0),
speexVersion(0),
vbr(false),
mode(0) {}
int length;
int bitrate;
@@ -63,7 +63,7 @@ class Speex::AudioProperties::AudioPropertiesPrivate {
// public members
////////////////////////////////////////////////////////////////////////////////
Speex::AudioProperties::AudioProperties(File *file, ReadStyle style) : Strawberry_TagLib::TagLib::AudioProperties(style), d(new AudioPropertiesPrivate()) {
Speex::AudioProperties::AudioProperties(File *file, ReadStyle) : Strawberry_TagLib::TagLib::AudioProperties(), d(new AudioPropertiesPrivate()) {
read(file);
}
@@ -113,32 +113,32 @@ void Speex::AudioProperties::read(File *file) {
return;
}
unsigned int pos = 28;
size_t pos = 28;
// speex_version_id; /**< Version for Speex (for checking compatibility) */
d->speexVersion = data.toUInt(pos, false);
d->speexVersion = data.toUInt32LE(pos);
pos += 4;
// header_size; /**< Total size of the header ( sizeof(SpeexHeader) ) */
pos += 4;
// rate; /**< Sampling rate used */
d->sampleRate = data.toUInt(pos, false);
d->sampleRate = data.toUInt32LE(pos);
pos += 4;
// mode; /**< Mode used (0 for narrowband, 1 for wideband) */
d->mode = data.toUInt(pos, false);
d->mode = data.toUInt32LE(pos);
pos += 4;
// mode_bitstream_version; /**< Version ID of the bit-stream */
pos += 4;
// nb_channels; /**< Number of channels encoded */
d->channels = data.toUInt(pos, false);
d->channels = data.toUInt32LE(pos);
pos += 4;
// bitrate; /**< Bit-rate used */
d->bitrateNominal = data.toUInt(pos, false);
d->bitrateNominal = data.toUInt32LE(pos);
pos += 4;
// frame_size; /**< Size of frames */
@@ -146,7 +146,7 @@ void Speex::AudioProperties::read(File *file) {
pos += 4;
// vbr; /**< 1 for a VBR encoding, 0 otherwise */
d->vbr = data.toUInt(pos, false) == 1;
d->vbr = data.toUInt32LE(pos) == 1;
pos += 4;
// frames_per_packet; /**< Number of frames stored per Ogg packet */

View File

@@ -52,26 +52,26 @@ class TAGLIB_EXPORT AudioProperties : public Strawberry_TagLib::TagLib::AudioPro
/*!
* Destroys this Speex::AudioProperties instance.
*/
virtual ~AudioProperties();
~AudioProperties() override;
/*!
* Returns the length of the file in seconds. The length is rounded down to the nearest whole second.
*
* \see lengthInMilliseconds()
*/
virtual int lengthInSeconds() const;
int lengthInSeconds() const override;
/*!
* Returns the length of the file in milliseconds.
*
* \see lengthInSeconds()
*/
virtual int lengthInMilliseconds() const;
int lengthInMilliseconds() const override;
/*!
* Returns the average bit rate of the file in kb/s.
*/
virtual int bitrate() const;
int bitrate() const override;
/*!
* Returns the nominal bit rate as read from the Speex header in kb/s.
@@ -81,12 +81,12 @@ class TAGLIB_EXPORT AudioProperties : public Strawberry_TagLib::TagLib::AudioPro
/*!
* Returns the sample rate in Hz.
*/
virtual int sampleRate() const;
int sampleRate() const override;
/*!
* Returns the number of audio channels.
*/
virtual int channels() const;
int channels() const override;
/*!
* Returns the Speex version, currently "0" (as specified by the spec).
@@ -94,9 +94,6 @@ class TAGLIB_EXPORT AudioProperties : public Strawberry_TagLib::TagLib::AudioPro
int speexVersion() const;
private:
explicit AudioProperties(const AudioProperties&);
AudioProperties &operator=(const AudioProperties&);
void read(File *file);
class AudioPropertiesPrivate;

View File

@@ -25,18 +25,18 @@
#include <bitset>
#include <tstring.h>
#include <tdebug.h>
#include <tpropertymap.h>
#include <tagutils.h>
#include "tstring.h"
#include "tdebug.h"
#include "tpropertymap.h"
#include "tagutils.h"
#include "vorbisfile.h"
using namespace Strawberry_TagLib::TagLib;
class Vorbis::File::FilePrivate {
class Ogg::Vorbis::File::FilePrivate {
public:
FilePrivate() : comment(nullptr), properties(nullptr) {}
explicit FilePrivate() : comment(nullptr), properties(nullptr) {}
~FilePrivate() {
delete comment;
@@ -61,50 +61,43 @@ static const char vorbisCommentHeaderID[] = { 0x03, 'v', 'o', 'r', 'b', 'i', 's'
// static members
////////////////////////////////////////////////////////////////////////////////
bool Vorbis::File::isSupported(IOStream *stream) {
bool Ogg::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);
return (buffer.find("OggS") != ByteVector::npos() && buffer.find("\x01vorbis") != ByteVector::npos());
}
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
Vorbis::File::File(FileName file, bool readProperties, Strawberry_TagLib::TagLib::AudioProperties::ReadStyle) : Ogg::File(file),
Ogg::Vorbis::File::File(FileName file, bool readProperties, Strawberry_TagLib::TagLib::AudioProperties::ReadStyle) : Ogg::File(file),
d(new FilePrivate()) {
if (isOpen())
read(readProperties);
}
Vorbis::File::File(IOStream *stream, bool readProperties, Strawberry_TagLib::TagLib::AudioProperties::ReadStyle) : Ogg::File(stream),
Ogg::Vorbis::File::File(IOStream *stream, bool readProperties, Strawberry_TagLib::TagLib::AudioProperties::ReadStyle) : Ogg::File(stream),
d(new FilePrivate()) {
if (isOpen())
read(readProperties);
}
Vorbis::File::~File() {
Ogg::Vorbis::File::~File() {
delete d;
}
Ogg::XiphComment *Vorbis::File::tag() const {
Ogg::XiphComment *Ogg::Vorbis::File::tag() const {
return d->comment;
}
PropertyMap Vorbis::File::properties() const {
return d->comment->properties();
}
PropertyMap Vorbis::File::setProperties(const PropertyMap &properties) {
return d->comment->setProperties(properties);
}
Vorbis::AudioProperties *Vorbis::File::audioProperties() const {
Ogg::Vorbis::AudioProperties *Ogg::Vorbis::File::audioProperties() const {
return d->properties;
}
bool Vorbis::File::save() {
bool Ogg::Vorbis::File::save() {
ByteVector v(vorbisCommentHeaderID);
@@ -122,12 +115,12 @@ bool Vorbis::File::save() {
// private members
////////////////////////////////////////////////////////////////////////////////
void Vorbis::File::read(bool readProperties) {
void Ogg::Vorbis::File::read(bool readProperties) {
ByteVector commentHeaderData = packet(1);
if (commentHeaderData.mid(0, 7) != vorbisCommentHeaderID) {
debug("Vorbis::File::read() - Could not find the Vorbis comment header.");
debug("Ogg::Vorbis::File::read() - Could not find the Vorbis comment header.");
setValid(false);
return;
}

View File

@@ -34,16 +34,7 @@
namespace Strawberry_TagLib {
namespace TagLib {
/*
* This is just to make this appear to be in the Ogg namespace in the documentation.
* The typedef below will make this work with the current code.
* In the next BIC version of TagLib this will be really moved into the Ogg namespace.
*/
#ifdef DOXYGEN
namespace Ogg {
#endif
//! A namespace containing classes for Vorbis metadata
@@ -79,38 +70,25 @@ class TAGLIB_EXPORT File : public Ogg::File {
/*!
* Destroys this instance of the File.
*/
virtual ~File();
~File() override;
/*!
* Returns the XiphComment for this file.
* XiphComment implements the tag interface, so this serves as the reimplementation of TagLib::File::tag().
*/
virtual Ogg::XiphComment *tag() const;
/*!
* Implements the unified property interface -- export function.
* This forwards directly to XiphComment::properties().
*/
PropertyMap properties() const;
/*!
* Implements the unified tag dictionary interface -- import function.
* Like properties(), this is a forwarder to the file's XiphComment.
*/
PropertyMap setProperties(const PropertyMap &);
Ogg::XiphComment *tag() const override;
/*!
* Returns the Vorbis::AudioProperties for this file. If no audio properties were read then this will return a null pointer.
*/
virtual AudioProperties *audioProperties() const;
AudioProperties *audioProperties() const override;
/*!
* Save the file.
*
* This returns true if the save was successful.
*/
virtual bool save();
bool save() override;
/*!
* Check if the given \a stream can be opened as an Ogg Vorbis file.
@@ -120,7 +98,7 @@ class TAGLIB_EXPORT File : public Ogg::File {
static bool isSupported(IOStream *stream);
private:
explicit File(const File&);
File(const File&);
File &operator=(const File&);
void read(bool readProperties);
@@ -128,23 +106,9 @@ class TAGLIB_EXPORT File : public Ogg::File {
class FilePrivate;
FilePrivate *d;
};
} // namespace Vorbis
/*
* To keep compatibility with the current version put Vorbis in the Ogg namespace only in the docs and provide a typedef to make it work.
* In the next BIC version this will be removed and it will only exist in the Ogg namespace.
*/
#ifdef DOXYGEN
}
#else
namespace Ogg {
namespace Vorbis {
typedef Strawberry_TagLib::TagLib::Vorbis::File File;
}
} // namespace Ogg
#endif
} // namespace TagLib
} // namespace Strawberry_TagLib

View File

@@ -23,26 +23,26 @@
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include <tstring.h>
#include <tdebug.h>
#include "tstring.h"
#include "tdebug.h"
#include <oggpageheader.h>
#include "oggpageheader.h"
#include "vorbisproperties.h"
#include "vorbisfile.h"
using namespace Strawberry_TagLib::TagLib;
class Vorbis::AudioProperties::AudioPropertiesPrivate {
class Ogg::Vorbis::AudioProperties::AudioPropertiesPrivate {
public:
AudioPropertiesPrivate() : length(0),
bitrate(0),
sampleRate(0),
channels(0),
vorbisVersion(0),
bitrateMaximum(0),
bitrateNominal(0),
bitrateMinimum(0) {}
explicit AudioPropertiesPrivate() : length(0),
bitrate(0),
sampleRate(0),
channels(0),
vorbisVersion(0),
bitrateMaximum(0),
bitrateNominal(0),
bitrateMinimum(0) {}
int length;
int bitrate;
@@ -60,7 +60,7 @@ namespace TagLib {
* Vorbis headers can be found with one type ID byte and the string "vorbis" in
* an Ogg stream. 0x01 indicates the setup header.
*/
static const char vorbisSetupHeaderID[] = { 0x01, 'v', 'o', 'r', 'b', 'i', 's', 0 };
const char vorbisSetupHeaderID[] = { 0x01, 'v', 'o', 'r', 'b', 'i', 's', 0 };
} // namespace TagLib
} // namespace Strawberry_TagLib
@@ -68,89 +68,99 @@ static const char vorbisSetupHeaderID[] = { 0x01, 'v', 'o', 'r', 'b', 'i', 's',
// public members
////////////////////////////////////////////////////////////////////////////////
Vorbis::AudioProperties::AudioProperties(File *file, ReadStyle style) : Strawberry_TagLib::TagLib::AudioProperties(style), d(new AudioPropertiesPrivate()) {
Ogg::Vorbis::AudioProperties::AudioProperties(File *file, ReadStyle) : Strawberry_TagLib::TagLib::AudioProperties(), d(new AudioPropertiesPrivate()) {
read(file);
}
Vorbis::AudioProperties::~AudioProperties() {
Ogg::Vorbis::AudioProperties::~AudioProperties() {
delete d;
}
int Vorbis::AudioProperties::lengthInSeconds() const {
int Ogg::Vorbis::AudioProperties::lengthInSeconds() const {
return d->length / 1000;
}
int Vorbis::AudioProperties::lengthInMilliseconds() const {
int Ogg::Vorbis::AudioProperties::lengthInMilliseconds() const {
return d->length;
}
int Vorbis::AudioProperties::bitrate() const {
int Ogg::Vorbis::AudioProperties::bitrate() const {
return d->bitrate;
}
int Vorbis::AudioProperties::sampleRate() const {
int Ogg::Vorbis::AudioProperties::sampleRate() const {
return d->sampleRate;
}
int Vorbis::AudioProperties::channels() const {
int Ogg::Vorbis::AudioProperties::channels() const {
return d->channels;
}
int Vorbis::AudioProperties::vorbisVersion() const {
int Ogg::Vorbis::AudioProperties::vorbisVersion() const {
return d->vorbisVersion;
}
int Vorbis::AudioProperties::bitrateMaximum() const {
int Ogg::Vorbis::AudioProperties::bitrateMaximum() const {
return d->bitrateMaximum;
}
int Vorbis::AudioProperties::bitrateNominal() const {
int Ogg::Vorbis::AudioProperties::bitrateNominal() const {
return d->bitrateNominal;
}
int Vorbis::AudioProperties::bitrateMinimum() const {
int Ogg::Vorbis::AudioProperties::bitrateMinimum() const {
return d->bitrateMinimum;
}
String Ogg::Vorbis::AudioProperties::toString() const {
StringList desc;
desc.append("Ogg Vorbis audio (version " + String::number(vorbisVersion()) + ")");
desc.append(String::number(lengthInSeconds()) + " seconds");
desc.append(String::number(bitrate()) + " kbps");
return desc.toString(", ");
}
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
void Vorbis::AudioProperties::read(File *file) {
void Ogg::Vorbis::AudioProperties::read(File *file) {
// Get the identification header from the Ogg implementation.
const ByteVector data = file->packet(0);
if (data.size() < 28) {
debug("Vorbis::AudioProperties::read() -- data is too short.");
debug("Ogg::Vorbis::AudioProperties::read() -- data is too short.");
return;
}
unsigned int pos = 0;
size_t pos = 0;
if (data.mid(pos, 7) != vorbisSetupHeaderID) {
debug("Vorbis::AudioProperties::read() -- invalid Vorbis identification header");
debug("Ogg::Vorbis::AudioProperties::read() -- invalid Vorbis identification header");
return;
}
pos += 7;
d->vorbisVersion = data.toUInt(pos, false);
d->vorbisVersion = data.toUInt32LE(pos);
pos += 4;
d->channels = static_cast<unsigned char>(data[pos]);
pos += 1;
d->sampleRate = data.toUInt(pos, false);
d->sampleRate = data.toUInt32LE(pos);
pos += 4;
d->bitrateMaximum = data.toUInt(pos, false);
d->bitrateMaximum = data.toUInt32LE(pos);
pos += 4;
d->bitrateNominal = data.toUInt(pos, false);
d->bitrateNominal = data.toUInt32LE(pos);
pos += 4;
d->bitrateMinimum = data.toUInt(pos, false);
d->bitrateMinimum = data.toUInt32LE(pos);
pos += 4;
// Find the length of the file. See http://wiki.xiph.org/VorbisStreamLength/
@@ -168,23 +178,24 @@ void Vorbis::AudioProperties::read(File *file) {
if (frameCount > 0) {
const double length = frameCount * 1000.0 / d->sampleRate;
long fileLengthWithoutOverhead = file->length();
//long fileLengthWithoutOverhead = file->length();
// Ignore the three initial header packets, see "1.3.1. Decode Setup" in
// https://xiph.org/vorbis/doc/Vorbis_I_spec.html
for (unsigned int i = 0; i < 3; ++i) {
fileLengthWithoutOverhead -= file->packet(i).size();
}
//for (unsigned int i = 0; i < 3; ++i) {
//fileLengthWithoutOverhead -= file->packet(i).size();
//}
d->length = static_cast<int>(length + 0.5);
d->bitrate = static_cast<int>(fileLengthWithoutOverhead * 8.0 / length + 0.5);
//d->bitrate = static_cast<int>(fileLengthWithoutOverhead * 8.0 / length + 0.5);
d->bitrate = static_cast<int>(file->length() * 8.0 / length + 0.5);
}
}
else {
debug("Vorbis::AudioProperties::read() -- Either the PCM values for the start or "
debug("Ogg::Vorbis::AudioProperties::read() -- Either the PCM values for the start or "
"end of this file was incorrect or the sample rate is zero.");
}
}
else
debug("Vorbis::AudioProperties::read() -- Could not find valid first and last Ogg pages.");
debug("Ogg::Vorbis::AudioProperties::read() -- Could not find valid first and last Ogg pages.");
// Alternative to the actual average bitrate.

View File

@@ -31,16 +31,7 @@
namespace Strawberry_TagLib {
namespace TagLib {
/*
* This is just to make this appear to be in the Ogg namespace in the documentation.
* The typedef below will make this work with the current code.
* In the next BIC version of TagLib this will be really moved into the Ogg namespace.
*/
#ifdef DOXYGEN
namespace Ogg {
#endif
namespace Vorbis {
@@ -62,36 +53,38 @@ class TAGLIB_EXPORT AudioProperties : public Strawberry_TagLib::TagLib::AudioPro
/*!
* Destroys this VorbisProperties instance.
*/
virtual ~AudioProperties();
~AudioProperties() override;
/*!
* Returns the length of the file in seconds. The length is rounded down to the nearest whole second.
*
* \see lengthInMilliseconds()
*/
virtual int lengthInSeconds() const;
int lengthInSeconds() const override;
/*!
* Returns the length of the file in milliseconds.
*
* \see lengthInSeconds()
*/
virtual int lengthInMilliseconds() const;
int lengthInMilliseconds() const override;
/*!
* Returns the average bit rate of the file in kb/s.
*/
virtual int bitrate() const;
int bitrate() const override;
/*!
* Returns the sample rate in Hz.
*/
virtual int sampleRate() const;
int sampleRate() const override;
/*!
* Returns the number of audio channels.
*/
virtual int channels() const;
int channels() const override;
String toString() const override;
/*!
* Returns the Vorbis version, currently "0" (as specified by the spec).
@@ -114,31 +107,14 @@ class TAGLIB_EXPORT AudioProperties : public Strawberry_TagLib::TagLib::AudioPro
int bitrateMinimum() const;
private:
explicit AudioProperties(const AudioProperties &);
AudioProperties &operator=(const AudioProperties &);
void read(File *file);
class AudioPropertiesPrivate;
AudioPropertiesPrivate *d;
};
} // namespace Vorbis
/*
* To keep compatibility with the current version put Vorbis in the Ogg namespace only in the docs and provide a typedef to make it work.
* In the next BIC version this will be removed and it will only exist in the Ogg namespace.
*/
#ifdef DOXYGEN
}
#else
namespace Ogg {
namespace Vorbis {
typedef Strawberry_TagLib::TagLib::AudioProperties AudioProperties;
}
} // namespace Ogg
#endif
} // namespace TagLib
} // namespace Strawberry_TagLib

View File

@@ -26,9 +26,10 @@
#include <tbytevector.h>
#include <tdebug.h>
#include <flacpicture.h>
#include <xiphcomment.h>
#include <tpropertymap.h>
#include "flacpicture.h"
#include "xiphcomment.h"
#include "tpicturemap.h"
#include "tpropertymap.h"
using namespace Strawberry_TagLib::TagLib;
@@ -36,21 +37,21 @@ namespace {
typedef Ogg::FieldListMap::Iterator FieldIterator;
typedef Ogg::FieldListMap::ConstIterator FieldConstIterator;
typedef List<FLAC::Picture *> PictureList;
typedef PictureList::Iterator PictureIterator;
typedef PictureList::Iterator PictureConstIterator;
typedef List<FLAC::Picture *> XiphPictureList;
typedef XiphPictureList::Iterator PictureIterator;
typedef XiphPictureList::Iterator PictureConstIterator;
} // namespace
class Ogg::XiphComment::XiphCommentPrivate {
public:
XiphCommentPrivate() {
explicit XiphCommentPrivate() {
pictureList.setAutoDelete(true);
}
FieldListMap fieldListMap;
String vendorID;
String commentField;
PictureList pictureList;
XiphPictureList pictureList;
};
////////////////////////////////////////////////////////////////////////////////
@@ -131,10 +132,15 @@ unsigned int Ogg::XiphComment::track() const {
return d->fieldListMap["TRACKNUMBER"].front().toInt();
if (!d->fieldListMap["TRACKNUM"].isEmpty())
return d->fieldListMap["TRACKNUM"].front().toInt();
return 0;
}
Strawberry_TagLib::TagLib::PictureMap Ogg::XiphComment::pictures() const {
return PictureMap();
}
void Ogg::XiphComment::setTitle(const String &s) {
addField("TITLE", s);
}
@@ -184,6 +190,8 @@ void Ogg::XiphComment::setTrack(unsigned int i) {
}
void Ogg::XiphComment::setPictures(const PictureMap&) {}
bool Ogg::XiphComment::isEmpty() const {
for (FieldConstIterator it = d->fieldListMap.begin(); it != d->fieldListMap.end(); ++it) {
@@ -197,7 +205,7 @@ bool Ogg::XiphComment::isEmpty() const {
unsigned int Ogg::XiphComment::fieldCount() const {
unsigned int count = 0;
size_t count = 0;
for (FieldConstIterator it = d->fieldListMap.begin(); it != d->fieldListMap.end(); ++it)
count += (*it).second.size();
@@ -347,12 +355,12 @@ ByteVector Ogg::XiphComment::render(bool addFramingBit) const {
ByteVector vendorData = d->vendorID.data(String::UTF8);
data.append(ByteVector::fromUInt(vendorData.size(), false));
data.append(ByteVector::fromUInt32LE(vendorData.size()));
data.append(vendorData);
// Add the number of fields.
data.append(ByteVector::fromUInt(fieldCount(), false));
data.append(ByteVector::fromUInt32LE(fieldCount()));
// Iterate over the the field lists. Our iterator returns a
// std::pair<String, StringList> where the first String is the field name and
@@ -371,14 +379,14 @@ ByteVector Ogg::XiphComment::render(bool addFramingBit) const {
fieldData.append('=');
fieldData.append((*valuesIt).data(String::UTF8));
data.append(ByteVector::fromUInt(fieldData.size(), false));
data.append(ByteVector::fromUInt32LE(fieldData.size()));
data.append(fieldData);
}
}
for (PictureConstIterator it = d->pictureList.begin(); it != d->pictureList.end(); ++it) {
ByteVector picture = (*it)->render().toBase64();
data.append(ByteVector::fromUInt(picture.size() + 23, false));
data.append(ByteVector::fromUInt32LE(picture.size() + 23));
data.append("METADATA_BLOCK_PICTURE=");
data.append(picture);
}
@@ -392,6 +400,18 @@ ByteVector Ogg::XiphComment::render(bool addFramingBit) const {
}
String Ogg::XiphComment::toString() const {
StringList desc;
for (FieldListMap::ConstIterator i = d->fieldListMap.begin(); i != d->fieldListMap.end(); i++) {
for (StringList::ConstIterator j = i->second.begin(); j != i->second.end(); j++) {
desc.append(i->first + "=" + *j);
}
}
return desc.toString("\n");
}
////////////////////////////////////////////////////////////////////////////////
// protected members
////////////////////////////////////////////////////////////////////////////////
@@ -401,9 +421,9 @@ void Ogg::XiphComment::parse(const ByteVector &data) {
// The first thing in the comment data is the vendor ID length, followed by a
// UTF8 string with the vendor ID.
unsigned int pos = 0;
size_t pos = 0;
const unsigned int vendorLength = data.toUInt(0, false);
const unsigned int vendorLength = data.toUInt32LE(0);
pos += 4;
d->vendorID = String(data.mid(pos, vendorLength), String::UTF8);
@@ -411,7 +431,7 @@ void Ogg::XiphComment::parse(const ByteVector &data) {
// Next the number of fields in the comment vector.
const unsigned int commentFields = data.toUInt(pos, false);
const unsigned int commentFields = data.toUInt32LE(pos);
pos += 4;
if (commentFields > (data.size() - 8) / 4) {
@@ -423,7 +443,7 @@ void Ogg::XiphComment::parse(const ByteVector &data) {
// Each comment field is in the format "KEY=value" in a UTF8 string and has
// 4 bytes before the text starts that gives the length.
const unsigned int commentLength = data.toUInt(pos, false);
const unsigned int commentLength = data.toUInt32LE(pos);
pos += 4;
const ByteVector entry = data.mid(pos, commentLength);
@@ -436,8 +456,8 @@ void Ogg::XiphComment::parse(const ByteVector &data) {
// Check for field separator
const int sep = entry.find('=');
if (sep < 1) {
const size_t sep = entry.find('=');
if (sep == 0 || sep == ByteVector::npos()) {
debug("Ogg::XiphComment::parse() - Discarding a field. Separator not found.");
continue;
}

View File

@@ -37,7 +37,6 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace Ogg {
/*!
@@ -76,25 +75,28 @@ class TAGLIB_EXPORT XiphComment : public Strawberry_TagLib::TagLib::Tag {
/*!
* Destroys this instance of the XiphComment.
*/
virtual ~XiphComment();
~XiphComment() override;
virtual String title() const;
virtual String artist() const;
virtual String album() const;
virtual String comment() const;
virtual String genre() const;
virtual unsigned int year() const;
virtual unsigned int track() const;
String title() const override;
String artist() const override;
String album() const override;
String comment() const override;
String genre() const override;
unsigned int year() const override;
unsigned int track() const override;
PictureMap pictures() const override;
virtual void setTitle(const String &s);
virtual void setArtist(const String &s);
virtual void setAlbum(const String &s);
virtual void setComment(const String &s);
virtual void setGenre(const String &s);
virtual void setYear(unsigned int i);
virtual void setTrack(unsigned int i);
void setTitle(const String &s) override;
void setArtist(const String &s) override;
void setAlbum(const String &s) override;
void setComment(const String &s) override;
void setGenre(const String &s) override;
void setYear(unsigned int i) override;
void setTrack(unsigned int i) override;
void setPictures(const PictureMap&) override;
virtual bool isEmpty() const;
bool isEmpty() const override;
String toString() const override;
/*!
* Returns the number of fields present in the comment.
@@ -142,7 +144,7 @@ class TAGLIB_EXPORT XiphComment : public Strawberry_TagLib::TagLib::Tag {
* since it is completely compatible with the property interface
* (in fact, a Xiph comment is nothing more than a map from tag names to list of values, as is the dict interface).
*/
PropertyMap properties() const;
PropertyMap properties() const override;
/*!
* Implements the unified property interface -- import function.
@@ -150,7 +152,7 @@ class TAGLIB_EXPORT XiphComment : public Strawberry_TagLib::TagLib::Tag {
* except for invalid keys (less than one character, non-ASCII,
* or containing '=' or '~') in which case the according values will be contained in the returned PropertyMap.
*/
PropertyMap setProperties(const PropertyMap &);
PropertyMap setProperties(const PropertyMap&) override;
/*!
* Check if the given String is a valid Xiph comment key.
@@ -238,7 +240,7 @@ class TAGLIB_EXPORT XiphComment : public Strawberry_TagLib::TagLib::Tag {
void parse(const ByteVector &data);
private:
explicit XiphComment(const XiphComment&);
XiphComment(const XiphComment&);
XiphComment &operator=(const XiphComment&);
class XiphCommentPrivate;