Format taglib sources
This commit is contained in:
118
3rdparty/taglib/ogg/flac/oggflacfile.cpp
vendored
118
3rdparty/taglib/ogg/flac/oggflacfile.cpp
vendored
@@ -35,20 +35,17 @@
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
using Strawberry_TagLib::TagLib::FLAC::Properties;
|
||||
|
||||
class Ogg::FLAC::File::FilePrivate
|
||||
{
|
||||
public:
|
||||
FilePrivate() :
|
||||
comment(0),
|
||||
properties(0),
|
||||
streamStart(0),
|
||||
streamLength(0),
|
||||
scanned(false),
|
||||
hasXiphComment(false),
|
||||
commentPacket(0) {}
|
||||
class Ogg::FLAC::File::FilePrivate {
|
||||
public:
|
||||
FilePrivate() : comment(0),
|
||||
properties(0),
|
||||
streamStart(0),
|
||||
streamLength(0),
|
||||
scanned(false),
|
||||
hasXiphComment(false),
|
||||
commentPacket(0) {}
|
||||
|
||||
~FilePrivate()
|
||||
{
|
||||
~FilePrivate() {
|
||||
delete comment;
|
||||
delete properties;
|
||||
}
|
||||
@@ -70,8 +67,7 @@ public:
|
||||
// static members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool Ogg::FLAC::File::isSupported(IOStream *stream)
|
||||
{
|
||||
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);
|
||||
@@ -83,51 +79,41 @@ bool Ogg::FLAC::File::isSupported(IOStream *stream)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Ogg::FLAC::File::File(FileName file, bool readProperties,
|
||||
Properties::ReadStyle propertiesStyle) :
|
||||
Ogg::File(file),
|
||||
d(new FilePrivate())
|
||||
{
|
||||
if(isOpen())
|
||||
Properties::ReadStyle propertiesStyle) : Ogg::File(file),
|
||||
d(new FilePrivate()) {
|
||||
if (isOpen())
|
||||
read(readProperties, propertiesStyle);
|
||||
}
|
||||
|
||||
Ogg::FLAC::File::File(IOStream *stream, bool readProperties,
|
||||
Properties::ReadStyle propertiesStyle) :
|
||||
Ogg::File(stream),
|
||||
d(new FilePrivate())
|
||||
{
|
||||
if(isOpen())
|
||||
Properties::ReadStyle propertiesStyle) : Ogg::File(stream),
|
||||
d(new FilePrivate()) {
|
||||
if (isOpen())
|
||||
read(readProperties, propertiesStyle);
|
||||
}
|
||||
|
||||
Ogg::FLAC::File::~File()
|
||||
{
|
||||
Ogg::FLAC::File::~File() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
Ogg::XiphComment *Ogg::FLAC::File::tag() const
|
||||
{
|
||||
Ogg::XiphComment *Ogg::FLAC::File::tag() const {
|
||||
return d->comment;
|
||||
}
|
||||
|
||||
PropertyMap Ogg::FLAC::File::properties() const
|
||||
{
|
||||
PropertyMap Ogg::FLAC::File::properties() const {
|
||||
return d->comment->properties();
|
||||
}
|
||||
|
||||
PropertyMap Ogg::FLAC::File::setProperties(const PropertyMap &properties)
|
||||
{
|
||||
PropertyMap Ogg::FLAC::File::setProperties(const PropertyMap &properties) {
|
||||
return d->comment->setProperties(properties);
|
||||
}
|
||||
|
||||
Properties *Ogg::FLAC::File::audioProperties() const
|
||||
{
|
||||
Properties *Ogg::FLAC::File::audioProperties() const {
|
||||
return d->properties;
|
||||
}
|
||||
|
||||
|
||||
bool Ogg::FLAC::File::save()
|
||||
{
|
||||
bool Ogg::FLAC::File::save() {
|
||||
d->xiphCommentData = d->comment->render(false);
|
||||
|
||||
// Create FLAC metadata-block:
|
||||
@@ -152,8 +138,7 @@ bool Ogg::FLAC::File::save()
|
||||
return Ogg::File::save();
|
||||
}
|
||||
|
||||
bool Ogg::FLAC::File::hasXiphComment() const
|
||||
{
|
||||
bool Ogg::FLAC::File::hasXiphComment() const {
|
||||
return d->hasXiphComment;
|
||||
}
|
||||
|
||||
@@ -161,11 +146,10 @@ bool Ogg::FLAC::File::hasXiphComment() const
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Ogg::FLAC::File::read(bool readProperties, Properties::ReadStyle propertiesStyle)
|
||||
{
|
||||
void Ogg::FLAC::File::read(bool readProperties, Properties::ReadStyle propertiesStyle) {
|
||||
// Sanity: Check if we really have an Ogg/FLAC file
|
||||
|
||||
/*
|
||||
/*
|
||||
ByteVector oggHeader = packet(0);
|
||||
|
||||
if (oggHeader.mid(28,4) != "fLaC") {
|
||||
@@ -184,67 +168,63 @@ void Ogg::FLAC::File::read(bool readProperties, Properties::ReadStyle properties
|
||||
}
|
||||
|
||||
|
||||
if(d->hasXiphComment)
|
||||
if (d->hasXiphComment)
|
||||
d->comment = new Ogg::XiphComment(xiphCommentData());
|
||||
else
|
||||
d->comment = new Ogg::XiphComment();
|
||||
|
||||
|
||||
if(readProperties)
|
||||
if (readProperties)
|
||||
d->properties = new Properties(streamInfoData(), streamLength(), propertiesStyle);
|
||||
}
|
||||
|
||||
ByteVector Ogg::FLAC::File::streamInfoData()
|
||||
{
|
||||
ByteVector Ogg::FLAC::File::streamInfoData() {
|
||||
scan();
|
||||
return d->streamInfoData;
|
||||
}
|
||||
|
||||
ByteVector Ogg::FLAC::File::xiphCommentData()
|
||||
{
|
||||
ByteVector Ogg::FLAC::File::xiphCommentData() {
|
||||
scan();
|
||||
return d->xiphCommentData;
|
||||
}
|
||||
|
||||
long Ogg::FLAC::File::streamLength()
|
||||
{
|
||||
long Ogg::FLAC::File::streamLength() {
|
||||
scan();
|
||||
return d->streamLength;
|
||||
}
|
||||
|
||||
void Ogg::FLAC::File::scan()
|
||||
{
|
||||
void Ogg::FLAC::File::scan() {
|
||||
// Scan the metadata pages
|
||||
|
||||
if(d->scanned)
|
||||
if (d->scanned)
|
||||
return;
|
||||
|
||||
if(!isValid())
|
||||
if (!isValid())
|
||||
return;
|
||||
|
||||
int ipacket = 0;
|
||||
long overhead = 0;
|
||||
|
||||
ByteVector metadataHeader = packet(ipacket);
|
||||
if(metadataHeader.isEmpty())
|
||||
if (metadataHeader.isEmpty())
|
||||
return;
|
||||
|
||||
if(!metadataHeader.startsWith("fLaC")) {
|
||||
if (!metadataHeader.startsWith("fLaC")) {
|
||||
// FLAC 1.1.2+
|
||||
// See https://xiph.org/flac/ogg_mapping.html for the header specification.
|
||||
if(metadataHeader.size() < 13)
|
||||
if (metadataHeader.size() < 13)
|
||||
return;
|
||||
|
||||
if(metadataHeader[0] != 0x7f)
|
||||
if (metadataHeader[0] != 0x7f)
|
||||
return;
|
||||
|
||||
if(metadataHeader.mid(1, 4) != "FLAC")
|
||||
if (metadataHeader.mid(1, 4) != "FLAC")
|
||||
return;
|
||||
|
||||
if(metadataHeader[5] != 1 && metadataHeader[6] != 0)
|
||||
return; // not version 1.0
|
||||
if (metadataHeader[5] != 1 && metadataHeader[6] != 0)
|
||||
return; // not version 1.0
|
||||
|
||||
if(metadataHeader.mid(9, 4) != "fLaC")
|
||||
if (metadataHeader.mid(9, 4) != "fLaC")
|
||||
return;
|
||||
|
||||
metadataHeader = metadataHeader.mid(13);
|
||||
@@ -255,7 +235,7 @@ void Ogg::FLAC::File::scan()
|
||||
}
|
||||
|
||||
ByteVector header = metadataHeader.mid(0, 4);
|
||||
if(header.size() != 4) {
|
||||
if (header.size() != 4) {
|
||||
debug("Ogg::FLAC::File::scan() -- Invalid Ogg/FLAC metadata header");
|
||||
return;
|
||||
}
|
||||
@@ -277,7 +257,7 @@ void Ogg::FLAC::File::scan()
|
||||
|
||||
// Sanity: First block should be the stream_info metadata
|
||||
|
||||
if(blockType != 0) {
|
||||
if (blockType != 0) {
|
||||
debug("Ogg::FLAC::File::scan() -- Invalid Ogg/FLAC stream");
|
||||
return;
|
||||
}
|
||||
@@ -286,10 +266,10 @@ void Ogg::FLAC::File::scan()
|
||||
|
||||
// Search through the remaining metadata
|
||||
|
||||
while(!lastBlock) {
|
||||
while (!lastBlock) {
|
||||
metadataHeader = packet(++ipacket);
|
||||
header = metadataHeader.mid(0, 4);
|
||||
if(header.size() != 4) {
|
||||
if (header.size() != 4) {
|
||||
debug("Ogg::FLAC::File::scan() -- Invalid Ogg/FLAC metadata header");
|
||||
return;
|
||||
}
|
||||
@@ -299,16 +279,16 @@ void Ogg::FLAC::File::scan()
|
||||
length = header.toUInt(1, 3, true);
|
||||
overhead += length;
|
||||
|
||||
if(blockType == 1) {
|
||||
if (blockType == 1) {
|
||||
// debug("Ogg::FLAC::File::scan() -- Padding found");
|
||||
}
|
||||
else if(blockType == 4) {
|
||||
else if (blockType == 4) {
|
||||
// debug("Ogg::FLAC::File::scan() -- Vorbis-comments found");
|
||||
d->xiphCommentData = metadataHeader.mid(4, length);
|
||||
d->hasXiphComment = true;
|
||||
d->commentPacket = ipacket;
|
||||
}
|
||||
else if(blockType > 5) {
|
||||
else if (blockType > 5) {
|
||||
debug("Ogg::FLAC::File::scan() -- Unknown metadata block");
|
||||
}
|
||||
}
|
||||
|
||||
97
3rdparty/taglib/ogg/flac/oggflacfile.h
vendored
97
3rdparty/taglib/ogg/flac/oggflacfile.h
vendored
@@ -35,45 +35,44 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
class Tag;
|
||||
class Tag;
|
||||
|
||||
namespace Ogg {
|
||||
namespace Ogg {
|
||||
|
||||
//! An implementation of Ogg FLAC metadata
|
||||
//! An implementation of Ogg FLAC metadata
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This is implementation of FLAC metadata for Ogg FLAC files. For "pure"
|
||||
* FLAC files look under the FLAC hierarchy.
|
||||
*
|
||||
* Unlike "pure" FLAC-files, Ogg FLAC only supports Xiph-comments,
|
||||
* while the audio-properties are the same.
|
||||
*/
|
||||
namespace FLAC {
|
||||
namespace FLAC {
|
||||
|
||||
using Strawberry_TagLib::TagLib::FLAC::Properties;
|
||||
using Strawberry_TagLib::TagLib::FLAC::Properties;
|
||||
|
||||
//! An implementation of TagLib::File with Ogg/FLAC specific methods
|
||||
//! An implementation of TagLib::File with Ogg/FLAC specific methods
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This implements and provides an interface for Ogg/FLAC files to the
|
||||
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
|
||||
* the abstract TagLib::File API as well as providing some additional
|
||||
* information specific to Ogg FLAC files.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT File : public Ogg::File
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
class TAGLIB_EXPORT File : public Ogg::File {
|
||||
public:
|
||||
/*!
|
||||
* Constructs an Ogg/FLAC 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);
|
||||
File(FileName file, bool readProperties = true,
|
||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Constructs an Ogg/FLAC file from \a stream. If \a readProperties is true
|
||||
* the file's audio properties will also be read.
|
||||
*
|
||||
@@ -82,15 +81,15 @@ namespace TagLib {
|
||||
*
|
||||
* \note In the current implementation, \a propertiesStyle is ignored.
|
||||
*/
|
||||
File(IOStream *stream, bool readProperties = true,
|
||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||
File(IOStream *stream, bool readProperties = true,
|
||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys this instance of the File.
|
||||
*/
|
||||
virtual ~File();
|
||||
virtual ~File();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the Tag for this file. This will always be a XiphComment.
|
||||
*
|
||||
* \note This always returns a valid pointer regardless of whether or not
|
||||
@@ -103,70 +102,70 @@ namespace TagLib {
|
||||
*
|
||||
* \see hasXiphComment()
|
||||
*/
|
||||
virtual XiphComment *tag() const;
|
||||
virtual XiphComment *tag() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the FLAC::Properties for this file. If no audio properties
|
||||
* were read then this will return a null pointer.
|
||||
*/
|
||||
virtual Properties *audioProperties() const;
|
||||
virtual Properties *audioProperties() const;
|
||||
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Implements the unified property interface -- export function.
|
||||
* This forwards directly to XiphComment::properties().
|
||||
*/
|
||||
PropertyMap properties() const;
|
||||
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 &);
|
||||
PropertyMap setProperties(const PropertyMap &);
|
||||
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Save the file. This will primarily save and update the XiphComment.
|
||||
* Returns true if the save is successful.
|
||||
*/
|
||||
virtual bool save();
|
||||
virtual bool save();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the length of the audio-stream, used by FLAC::Properties for
|
||||
* calculating the bitrate.
|
||||
*/
|
||||
long streamLength();
|
||||
long streamLength();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns whether or not the file on disk actually has a XiphComment.
|
||||
*
|
||||
* \see tag()
|
||||
*/
|
||||
bool hasXiphComment() const;
|
||||
bool hasXiphComment() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Check if the given \a stream can be opened as an Ogg FLAC file.
|
||||
*
|
||||
* \note This method is designed to do a quick check. The result may
|
||||
* not necessarily be correct.
|
||||
*/
|
||||
static bool isSupported(IOStream *stream);
|
||||
static bool isSupported(IOStream *stream);
|
||||
|
||||
private:
|
||||
File(const File &);
|
||||
File &operator=(const File &);
|
||||
private:
|
||||
File(const File &);
|
||||
File &operator=(const File &);
|
||||
|
||||
void read(bool readProperties, Properties::ReadStyle propertiesStyle);
|
||||
void scan();
|
||||
ByteVector streamInfoData();
|
||||
ByteVector xiphCommentData();
|
||||
void read(bool readProperties, Properties::ReadStyle propertiesStyle);
|
||||
void scan();
|
||||
ByteVector streamInfoData();
|
||||
ByteVector xiphCommentData();
|
||||
|
||||
class FilePrivate;
|
||||
FilePrivate *d;
|
||||
};
|
||||
} // namespace FLAC
|
||||
} // namespace Ogg
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
class FilePrivate;
|
||||
FilePrivate *d;
|
||||
};
|
||||
} // namespace FLAC
|
||||
} // namespace Ogg
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
|
||||
#endif
|
||||
|
||||
135
3rdparty/taglib/ogg/oggfile.cpp
vendored
135
3rdparty/taglib/ogg/oggfile.cpp
vendored
@@ -34,31 +34,25 @@
|
||||
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
|
||||
namespace
|
||||
{
|
||||
// Returns the first packet index of the right next page to the given one.
|
||||
unsigned int nextPacketIndex(const Ogg::Page *page)
|
||||
{
|
||||
if(page->header()->lastPacketCompleted())
|
||||
return page->firstPacketIndex() + page->packetCount();
|
||||
else
|
||||
return page->firstPacketIndex() + page->packetCount() - 1;
|
||||
}
|
||||
namespace {
|
||||
// Returns the first packet index of the right next page to the given one.
|
||||
unsigned int nextPacketIndex(const Ogg::Page *page) {
|
||||
if (page->header()->lastPacketCompleted())
|
||||
return page->firstPacketIndex() + page->packetCount();
|
||||
else
|
||||
return page->firstPacketIndex() + page->packetCount() - 1;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
class Ogg::File::FilePrivate
|
||||
{
|
||||
public:
|
||||
FilePrivate() :
|
||||
streamSerialNumber(0),
|
||||
firstPageHeader(0),
|
||||
lastPageHeader(0)
|
||||
{
|
||||
class Ogg::File::FilePrivate {
|
||||
public:
|
||||
FilePrivate() : streamSerialNumber(0),
|
||||
firstPageHeader(0),
|
||||
lastPageHeader(0) {
|
||||
pages.setAutoDelete(true);
|
||||
}
|
||||
|
||||
~FilePrivate()
|
||||
{
|
||||
~FilePrivate() {
|
||||
delete firstPageHeader;
|
||||
delete lastPageHeader;
|
||||
}
|
||||
@@ -74,23 +68,21 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Ogg::File::~File()
|
||||
{
|
||||
Ogg::File::~File() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
ByteVector Ogg::File::packet(unsigned int i)
|
||||
{
|
||||
ByteVector Ogg::File::packet(unsigned int i) {
|
||||
// Check to see if we're called setPacket() for this packet since the last
|
||||
// save:
|
||||
|
||||
if(d->dirtyPackets.contains(i))
|
||||
if (d->dirtyPackets.contains(i))
|
||||
return d->dirtyPackets[i];
|
||||
|
||||
// If we haven't indexed the page where the packet we're interested in starts,
|
||||
// begin reading pages until we have.
|
||||
|
||||
if(!readPages(i)) {
|
||||
if (!readPages(i)) {
|
||||
debug("Ogg::File::packet() -- Could not find the requested packet.");
|
||||
return ByteVector();
|
||||
}
|
||||
@@ -98,7 +90,7 @@ ByteVector Ogg::File::packet(unsigned int i)
|
||||
// Look for the first page in which the requested packet starts.
|
||||
|
||||
List<Page *>::ConstIterator it = d->pages.begin();
|
||||
while((*it)->containsPacket(i) == Page::DoesNotContainPacket)
|
||||
while ((*it)->containsPacket(i) == Page::DoesNotContainPacket)
|
||||
++it;
|
||||
|
||||
// If the packet is completely contained in the first page that it's in.
|
||||
@@ -110,7 +102,7 @@ ByteVector Ogg::File::packet(unsigned int i)
|
||||
|
||||
ByteVector packet = (*it)->packets()[i - (*it)->firstPacketIndex()];
|
||||
|
||||
while(nextPacketIndex(*it) <= i) {
|
||||
while (nextPacketIndex(*it) <= i) {
|
||||
++it;
|
||||
packet.append((*it)->packets().front());
|
||||
}
|
||||
@@ -118,9 +110,8 @@ ByteVector Ogg::File::packet(unsigned int i)
|
||||
return packet;
|
||||
}
|
||||
|
||||
void Ogg::File::setPacket(unsigned int i, const ByteVector &p)
|
||||
{
|
||||
if(!readPages(i)) {
|
||||
void Ogg::File::setPacket(unsigned int i, const ByteVector &p) {
|
||||
if (!readPages(i)) {
|
||||
debug("Ogg::File::setPacket() -- Could not set the requested packet.");
|
||||
return;
|
||||
}
|
||||
@@ -128,11 +119,10 @@ void Ogg::File::setPacket(unsigned int i, const ByteVector &p)
|
||||
d->dirtyPackets[i] = p;
|
||||
}
|
||||
|
||||
const Ogg::PageHeader *Ogg::File::firstPageHeader()
|
||||
{
|
||||
if(!d->firstPageHeader) {
|
||||
const Ogg::PageHeader *Ogg::File::firstPageHeader() {
|
||||
if (!d->firstPageHeader) {
|
||||
const long firstPageHeaderOffset = find("OggS");
|
||||
if(firstPageHeaderOffset < 0)
|
||||
if (firstPageHeaderOffset < 0)
|
||||
return 0;
|
||||
|
||||
d->firstPageHeader = new PageHeader(this, firstPageHeaderOffset);
|
||||
@@ -141,11 +131,10 @@ const Ogg::PageHeader *Ogg::File::firstPageHeader()
|
||||
return d->firstPageHeader->isValid() ? d->firstPageHeader : 0;
|
||||
}
|
||||
|
||||
const Ogg::PageHeader *Ogg::File::lastPageHeader()
|
||||
{
|
||||
if(!d->lastPageHeader) {
|
||||
const Ogg::PageHeader *Ogg::File::lastPageHeader() {
|
||||
if (!d->lastPageHeader) {
|
||||
const long lastPageHeaderOffset = rfind("OggS");
|
||||
if(lastPageHeaderOffset < 0)
|
||||
if (lastPageHeaderOffset < 0)
|
||||
return 0;
|
||||
|
||||
d->lastPageHeader = new PageHeader(this, lastPageHeaderOffset);
|
||||
@@ -154,15 +143,14 @@ const Ogg::PageHeader *Ogg::File::lastPageHeader()
|
||||
return d->lastPageHeader->isValid() ? d->lastPageHeader : 0;
|
||||
}
|
||||
|
||||
bool Ogg::File::save()
|
||||
{
|
||||
if(readOnly()) {
|
||||
bool Ogg::File::save() {
|
||||
if (readOnly()) {
|
||||
debug("Ogg::File::save() - Cannot save to a read only file.");
|
||||
return false;
|
||||
}
|
||||
|
||||
Map<unsigned int, ByteVector>::ConstIterator it;
|
||||
for(it = d->dirtyPackets.begin(); it != d->dirtyPackets.end(); ++it)
|
||||
for (it = d->dirtyPackets.begin(); it != d->dirtyPackets.end(); ++it)
|
||||
writePacket(it->first, it->second);
|
||||
|
||||
d->dirtyPackets.clear();
|
||||
@@ -174,32 +162,27 @@ bool Ogg::File::save()
|
||||
// protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Ogg::File::File(FileName file) :
|
||||
Strawberry_TagLib::TagLib::File(file),
|
||||
d(new FilePrivate())
|
||||
{
|
||||
Ogg::File::File(FileName file) : Strawberry_TagLib::TagLib::File(file),
|
||||
d(new FilePrivate()) {
|
||||
}
|
||||
|
||||
Ogg::File::File(IOStream *stream) :
|
||||
Strawberry_TagLib::TagLib::File(stream),
|
||||
d(new FilePrivate())
|
||||
{
|
||||
Ogg::File::File(IOStream *stream) : Strawberry_TagLib::TagLib::File(stream),
|
||||
d(new FilePrivate()) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool Ogg::File::readPages(unsigned int i)
|
||||
{
|
||||
while(true) {
|
||||
bool Ogg::File::readPages(unsigned int i) {
|
||||
while (true) {
|
||||
unsigned int packetIndex;
|
||||
long offset;
|
||||
|
||||
if(d->pages.isEmpty()) {
|
||||
if (d->pages.isEmpty()) {
|
||||
packetIndex = 0;
|
||||
offset = find("OggS");
|
||||
if(offset < 0)
|
||||
if (offset < 0)
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
@@ -210,13 +193,13 @@ bool Ogg::File::readPages(unsigned int i)
|
||||
|
||||
// Enough pages have been fetched.
|
||||
|
||||
if(packetIndex > i)
|
||||
if (packetIndex > i)
|
||||
return true;
|
||||
|
||||
// Read the next page and add it to the page list.
|
||||
|
||||
Page *nextPage = new Page(this, offset);
|
||||
if(!nextPage->header()->isValid()) {
|
||||
if (!nextPage->header()->isValid()) {
|
||||
delete nextPage;
|
||||
return false;
|
||||
}
|
||||
@@ -224,14 +207,13 @@ bool Ogg::File::readPages(unsigned int i)
|
||||
nextPage->setFirstPacketIndex(packetIndex);
|
||||
d->pages.append(nextPage);
|
||||
|
||||
if(nextPage->header()->lastPageOfStream())
|
||||
if (nextPage->header()->lastPageOfStream())
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void Ogg::File::writePacket(unsigned int i, const ByteVector &packet)
|
||||
{
|
||||
if(!readPages(i)) {
|
||||
void Ogg::File::writePacket(unsigned int i, const ByteVector &packet) {
|
||||
if (!readPages(i)) {
|
||||
debug("Ogg::File::writePacket() -- Could not find the requested packet.");
|
||||
return;
|
||||
}
|
||||
@@ -239,12 +221,12 @@ void Ogg::File::writePacket(unsigned int i, const ByteVector &packet)
|
||||
// Look for the pages where the requested packet should belong to.
|
||||
|
||||
List<Page *>::ConstIterator it = d->pages.begin();
|
||||
while((*it)->containsPacket(i) == Page::DoesNotContainPacket)
|
||||
while ((*it)->containsPacket(i) == Page::DoesNotContainPacket)
|
||||
++it;
|
||||
|
||||
const Page *firstPage = *it;
|
||||
|
||||
while(nextPacketIndex(*it) <= i)
|
||||
while (nextPacketIndex(*it) <= i)
|
||||
++it;
|
||||
|
||||
const Page *lastPage = *it;
|
||||
@@ -254,7 +236,7 @@ void Ogg::File::writePacket(unsigned int i, const ByteVector &packet)
|
||||
ByteVectorList packets = firstPage->packets();
|
||||
packets[i - firstPage->firstPacketIndex()] = packet;
|
||||
|
||||
if(firstPage != lastPage && lastPage->packetCount() > 1) {
|
||||
if (firstPage != lastPage && lastPage->packetCount() > 1) {
|
||||
ByteVectorList lastPagePackets = lastPage->packets();
|
||||
lastPagePackets.erase(lastPagePackets.begin());
|
||||
packets.append(lastPagePackets);
|
||||
@@ -264,17 +246,17 @@ void Ogg::File::writePacket(unsigned int i, const ByteVector &packet)
|
||||
// This should account for real possibilities like non-aligned packets and such.
|
||||
|
||||
List<Page *> pages = Page::paginate(packets,
|
||||
Page::SinglePagePerGroup,
|
||||
firstPage->header()->streamSerialNumber(),
|
||||
firstPage->pageSequenceNumber(),
|
||||
firstPage->header()->firstPacketContinued(),
|
||||
lastPage->header()->lastPacketCompleted());
|
||||
Page::SinglePagePerGroup,
|
||||
firstPage->header()->streamSerialNumber(),
|
||||
firstPage->pageSequenceNumber(),
|
||||
firstPage->header()->firstPacketContinued(),
|
||||
lastPage->header()->lastPacketCompleted());
|
||||
pages.setAutoDelete(true);
|
||||
|
||||
// Write the pages.
|
||||
|
||||
ByteVector data;
|
||||
for(it = pages.begin(); it != pages.end(); ++it)
|
||||
for (it = pages.begin(); it != pages.end(); ++it)
|
||||
data.append((*it)->render());
|
||||
|
||||
const unsigned long originalOffset = firstPage->fileOffset();
|
||||
@@ -284,15 +266,14 @@ void Ogg::File::writePacket(unsigned int i, const ByteVector &packet)
|
||||
|
||||
// Renumber the following pages if the pages have been split or merged.
|
||||
|
||||
const int numberOfNewPages
|
||||
= pages.back()->pageSequenceNumber() - lastPage->pageSequenceNumber();
|
||||
const int numberOfNewPages = pages.back()->pageSequenceNumber() - lastPage->pageSequenceNumber();
|
||||
|
||||
if(numberOfNewPages != 0) {
|
||||
if (numberOfNewPages != 0) {
|
||||
long pageOffset = originalOffset + data.size();
|
||||
|
||||
while(true) {
|
||||
while (true) {
|
||||
Page page(this, pageOffset);
|
||||
if(!page.header()->isValid())
|
||||
if (!page.header()->isValid())
|
||||
break;
|
||||
|
||||
page.setPageSequenceNumber(page.pageSequenceNumber() + numberOfNewPages);
|
||||
@@ -301,7 +282,7 @@ void Ogg::File::writePacket(unsigned int i, const ByteVector &packet)
|
||||
seek(pageOffset + 18);
|
||||
writeBlock(data2.mid(18, 8));
|
||||
|
||||
if(page.header()->lastPageOfStream())
|
||||
if (page.header()->lastPageOfStream())
|
||||
break;
|
||||
|
||||
pageOffset += page.size();
|
||||
|
||||
73
3rdparty/taglib/ogg/oggfile.h
vendored
73
3rdparty/taglib/ogg/oggfile.h
vendored
@@ -28,70 +28,69 @@
|
||||
#include "tbytevectorlist.h"
|
||||
|
||||
#ifndef TAGLIB_OGGFILE_H
|
||||
#define TAGLIB_OGGFILE_H
|
||||
# define TAGLIB_OGGFILE_H
|
||||
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
//! A namespace for the classes used by Ogg-based metadata files
|
||||
//! A namespace for the classes used by Ogg-based metadata files
|
||||
|
||||
namespace Ogg {
|
||||
namespace Ogg {
|
||||
|
||||
class PageHeader;
|
||||
class PageHeader;
|
||||
|
||||
//! An implementation of Strawberry_TagLib::TagLib::File with some helpers for Ogg based formats
|
||||
//! An implementation of Strawberry_TagLib::TagLib::File with some helpers for Ogg based formats
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This is an implementation of Ogg file page and packet rendering and is of
|
||||
* use to Ogg based formats. While the API is small this handles the
|
||||
* non-trivial details of breaking up an Ogg stream into packets and makes
|
||||
* these available (via subclassing) to the codec meta data implementations.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File
|
||||
{
|
||||
public:
|
||||
virtual ~File();
|
||||
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File {
|
||||
public:
|
||||
virtual ~File();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the packet contents for the i-th packet (starting from zero)
|
||||
* in the Ogg bitstream.
|
||||
*
|
||||
* \warning This requires reading at least the packet header for every page
|
||||
* up to the requested page.
|
||||
*/
|
||||
ByteVector packet(unsigned int i);
|
||||
ByteVector packet(unsigned int i);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the packet with index \a i to the value \a p.
|
||||
*/
|
||||
void setPacket(unsigned int i, const ByteVector &p);
|
||||
void setPacket(unsigned int i, const ByteVector &p);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a pointer to the PageHeader for the first page in the stream or
|
||||
* null if the page could not be found.
|
||||
*/
|
||||
const PageHeader *firstPageHeader();
|
||||
const PageHeader *firstPageHeader();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a pointer to the PageHeader for the last page in the stream or
|
||||
* null if the page could not be found.
|
||||
*/
|
||||
const PageHeader *lastPageHeader();
|
||||
const PageHeader *lastPageHeader();
|
||||
|
||||
virtual bool save();
|
||||
virtual bool save();
|
||||
|
||||
protected:
|
||||
/*!
|
||||
protected:
|
||||
/*!
|
||||
* Constructs an Ogg file from \a file.
|
||||
*
|
||||
* \note This constructor is protected since Ogg::File shouldn't be
|
||||
* instantiated directly but rather should be used through the codec
|
||||
* specific subclasses.
|
||||
*/
|
||||
File(FileName file);
|
||||
File(FileName file);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Constructs an Ogg file from \a stream.
|
||||
*
|
||||
* \note This constructor is protected since Ogg::File shouldn't be
|
||||
@@ -101,29 +100,29 @@ namespace TagLib {
|
||||
* \note TagLib will *not* take ownership of the stream, the caller is
|
||||
* responsible for deleting it after the File object.
|
||||
*/
|
||||
File(IOStream *stream);
|
||||
File(IOStream *stream);
|
||||
|
||||
private:
|
||||
File(const File &);
|
||||
File &operator=(const File &);
|
||||
private:
|
||||
File(const File &);
|
||||
File &operator=(const File &);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Reads the pages from the beginning of the file until enough to compose
|
||||
* the requested packet.
|
||||
*/
|
||||
bool readPages(unsigned int i);
|
||||
bool readPages(unsigned int i);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Writes the requested packet to the file.
|
||||
*/
|
||||
void writePacket(unsigned int i, const ByteVector &packet);
|
||||
void writePacket(unsigned int i, const ByteVector &packet);
|
||||
|
||||
class FilePrivate;
|
||||
FilePrivate *d;
|
||||
};
|
||||
class FilePrivate;
|
||||
FilePrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace Ogg
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
|
||||
#endif
|
||||
|
||||
150
3rdparty/taglib/ogg/oggpage.cpp
vendored
150
3rdparty/taglib/ogg/oggpage.cpp
vendored
@@ -34,14 +34,12 @@
|
||||
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
|
||||
class Ogg::Page::PagePrivate
|
||||
{
|
||||
public:
|
||||
PagePrivate(File *f = 0, long pageOffset = -1) :
|
||||
file(f),
|
||||
fileOffset(pageOffset),
|
||||
header(f, pageOffset),
|
||||
firstPacketIndex(-1) {}
|
||||
class Ogg::Page::PagePrivate {
|
||||
public:
|
||||
PagePrivate(File *f = 0, long pageOffset = -1) : file(f),
|
||||
fileOffset(pageOffset),
|
||||
header(f, pageOffset),
|
||||
firstPacketIndex(-1) {}
|
||||
|
||||
File *file;
|
||||
long fileOffset;
|
||||
@@ -54,66 +52,55 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Ogg::Page::Page(Ogg::File *file, long pageOffset) :
|
||||
d(new PagePrivate(file, pageOffset))
|
||||
{
|
||||
Ogg::Page::Page(Ogg::File *file, long pageOffset) : d(new PagePrivate(file, pageOffset)) {
|
||||
}
|
||||
|
||||
Ogg::Page::~Page()
|
||||
{
|
||||
Ogg::Page::~Page() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
long Ogg::Page::fileOffset() const
|
||||
{
|
||||
long Ogg::Page::fileOffset() const {
|
||||
return d->fileOffset;
|
||||
}
|
||||
|
||||
const Ogg::PageHeader *Ogg::Page::header() const
|
||||
{
|
||||
const Ogg::PageHeader *Ogg::Page::header() const {
|
||||
return &d->header;
|
||||
}
|
||||
|
||||
int Ogg::Page::pageSequenceNumber() const
|
||||
{
|
||||
int Ogg::Page::pageSequenceNumber() const {
|
||||
return d->header.pageSequenceNumber();
|
||||
}
|
||||
|
||||
void Ogg::Page::setPageSequenceNumber(int sequenceNumber)
|
||||
{
|
||||
void Ogg::Page::setPageSequenceNumber(int sequenceNumber) {
|
||||
d->header.setPageSequenceNumber(sequenceNumber);
|
||||
}
|
||||
|
||||
int Ogg::Page::firstPacketIndex() const
|
||||
{
|
||||
int Ogg::Page::firstPacketIndex() const {
|
||||
return d->firstPacketIndex;
|
||||
}
|
||||
|
||||
void Ogg::Page::setFirstPacketIndex(int index)
|
||||
{
|
||||
void Ogg::Page::setFirstPacketIndex(int index) {
|
||||
d->firstPacketIndex = index;
|
||||
}
|
||||
|
||||
Ogg::Page::ContainsPacketFlags Ogg::Page::containsPacket(int index) const
|
||||
{
|
||||
Ogg::Page::ContainsPacketFlags Ogg::Page::containsPacket(int index) const {
|
||||
const int lastPacketIndex = d->firstPacketIndex + packetCount() - 1;
|
||||
if(index < d->firstPacketIndex || index > lastPacketIndex)
|
||||
if (index < d->firstPacketIndex || index > lastPacketIndex)
|
||||
return DoesNotContainPacket;
|
||||
|
||||
ContainsPacketFlags flags = DoesNotContainPacket;
|
||||
|
||||
if(index == d->firstPacketIndex)
|
||||
if (index == d->firstPacketIndex)
|
||||
flags = ContainsPacketFlags(flags | BeginsWithPacket);
|
||||
|
||||
if(index == lastPacketIndex)
|
||||
if (index == lastPacketIndex)
|
||||
flags = ContainsPacketFlags(flags | EndsWithPacket);
|
||||
|
||||
// If there's only one page and it's complete:
|
||||
|
||||
if(packetCount() == 1 &&
|
||||
!d->header.firstPacketContinued() &&
|
||||
d->header.lastPacketCompleted())
|
||||
{
|
||||
if (packetCount() == 1 &&
|
||||
!d->header.firstPacketContinued() &&
|
||||
d->header.lastPacketCompleted()) {
|
||||
flags = ContainsPacketFlags(flags | CompletePacket);
|
||||
}
|
||||
|
||||
@@ -121,37 +108,34 @@ Ogg::Page::ContainsPacketFlags Ogg::Page::containsPacket(int index) const
|
||||
// (a) the first page and it's complete or
|
||||
// (b) the last page and it's complete or
|
||||
// (c) a page in the middle.
|
||||
else if(packetCount() > 1 &&
|
||||
((flags & BeginsWithPacket && !d->header.firstPacketContinued()) ||
|
||||
(flags & EndsWithPacket && d->header.lastPacketCompleted()) ||
|
||||
(!(flags & BeginsWithPacket) && !(flags & EndsWithPacket))))
|
||||
{
|
||||
else if (packetCount() > 1 &&
|
||||
((flags & BeginsWithPacket && !d->header.firstPacketContinued()) ||
|
||||
(flags & EndsWithPacket && d->header.lastPacketCompleted()) ||
|
||||
(!(flags & BeginsWithPacket) && !(flags & EndsWithPacket)))) {
|
||||
flags = ContainsPacketFlags(flags | CompletePacket);
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
unsigned int Ogg::Page::packetCount() const
|
||||
{
|
||||
unsigned int Ogg::Page::packetCount() const {
|
||||
return d->header.packetSizes().size();
|
||||
}
|
||||
|
||||
ByteVectorList Ogg::Page::packets() const
|
||||
{
|
||||
if(!d->packets.isEmpty())
|
||||
ByteVectorList Ogg::Page::packets() const {
|
||||
if (!d->packets.isEmpty())
|
||||
return d->packets;
|
||||
|
||||
ByteVectorList l;
|
||||
|
||||
if(d->file && d->header.isValid()) {
|
||||
if (d->file && d->header.isValid()) {
|
||||
|
||||
d->file->seek(d->fileOffset + d->header.size());
|
||||
|
||||
List<int> packetSizes = d->header.packetSizes();
|
||||
|
||||
List<int>::ConstIterator it = packetSizes.begin();
|
||||
for(; it != packetSizes.end(); ++it)
|
||||
for (; it != packetSizes.end(); ++it)
|
||||
l.append(d->file->readBlock(*it));
|
||||
}
|
||||
else
|
||||
@@ -160,19 +144,17 @@ ByteVectorList Ogg::Page::packets() const
|
||||
return l;
|
||||
}
|
||||
|
||||
int Ogg::Page::size() const
|
||||
{
|
||||
int Ogg::Page::size() const {
|
||||
return d->header.size() + d->header.dataSize();
|
||||
}
|
||||
|
||||
ByteVector Ogg::Page::render() const
|
||||
{
|
||||
ByteVector Ogg::Page::render() const {
|
||||
ByteVector data;
|
||||
|
||||
data.append(d->header.render());
|
||||
|
||||
if(d->packets.isEmpty()) {
|
||||
if(d->file) {
|
||||
if (d->packets.isEmpty()) {
|
||||
if (d->file) {
|
||||
d->file->seek(d->fileOffset + d->header.size());
|
||||
data.append(d->file->readBlock(d->header.dataSize()));
|
||||
}
|
||||
@@ -181,7 +163,7 @@ ByteVector Ogg::Page::render() const
|
||||
}
|
||||
else {
|
||||
ByteVectorList::ConstIterator it = d->packets.begin();
|
||||
for(; it != d->packets.end(); ++it)
|
||||
for (; it != d->packets.end(); ++it)
|
||||
data.append(*it);
|
||||
}
|
||||
|
||||
@@ -196,13 +178,12 @@ ByteVector Ogg::Page::render() const
|
||||
}
|
||||
|
||||
List<Ogg::Page *> Ogg::Page::paginate(const ByteVectorList &packets,
|
||||
PaginationStrategy strategy,
|
||||
unsigned int streamSerialNumber,
|
||||
int firstPage,
|
||||
bool firstPacketContinued,
|
||||
bool lastPacketCompleted,
|
||||
bool containsLastPacket)
|
||||
{
|
||||
PaginationStrategy strategy,
|
||||
unsigned int streamSerialNumber,
|
||||
int firstPage,
|
||||
bool firstPacketContinued,
|
||||
bool lastPacketCompleted,
|
||||
bool containsLastPacket) {
|
||||
// SplitSize must be a multiple of 255 in order to get the lacing values right
|
||||
// create pages of about 8KB each
|
||||
|
||||
@@ -210,13 +191,13 @@ List<Ogg::Page *> Ogg::Page::paginate(const ByteVectorList &packets,
|
||||
|
||||
// Force repagination if the segment table will exceed the size limit.
|
||||
|
||||
if(strategy != Repaginate) {
|
||||
if (strategy != Repaginate) {
|
||||
|
||||
size_t tableSize = 0;
|
||||
for(ByteVectorList::ConstIterator it = packets.begin(); it != packets.end(); ++it)
|
||||
for (ByteVectorList::ConstIterator it = packets.begin(); it != packets.end(); ++it)
|
||||
tableSize += it->size() / 255 + 1;
|
||||
|
||||
if(tableSize > 255)
|
||||
if (tableSize > 255)
|
||||
strategy = Repaginate;
|
||||
}
|
||||
|
||||
@@ -224,11 +205,11 @@ List<Ogg::Page *> Ogg::Page::paginate(const ByteVectorList &packets,
|
||||
|
||||
// Handle creation of multiple pages with appropriate pagination.
|
||||
|
||||
if(strategy == Repaginate) {
|
||||
if (strategy == Repaginate) {
|
||||
|
||||
int pageIndex = firstPage;
|
||||
|
||||
for(ByteVectorList::ConstIterator it = packets.begin(); it != packets.end(); ++it) {
|
||||
for (ByteVectorList::ConstIterator it = packets.begin(); it != packets.end(); ++it) {
|
||||
|
||||
const bool lastPacketInList = (it == --packets.end());
|
||||
|
||||
@@ -237,7 +218,7 @@ List<Ogg::Page *> Ogg::Page::paginate(const ByteVectorList &packets,
|
||||
bool continued = (firstPacketContinued && it == packets.begin());
|
||||
unsigned int pos = 0;
|
||||
|
||||
while(pos < it->size()) {
|
||||
while (pos < it->size()) {
|
||||
|
||||
const bool lastSplit = (pos + SplitSize >= it->size());
|
||||
|
||||
@@ -245,11 +226,11 @@ List<Ogg::Page *> Ogg::Page::paginate(const ByteVectorList &packets,
|
||||
packetList.append(it->mid(pos, SplitSize));
|
||||
|
||||
l.append(new Page(packetList,
|
||||
streamSerialNumber,
|
||||
pageIndex,
|
||||
continued,
|
||||
lastSplit && (lastPacketInList ? lastPacketCompleted : true),
|
||||
lastSplit && (containsLastPacket && lastPacketInList)));
|
||||
streamSerialNumber,
|
||||
pageIndex,
|
||||
continued,
|
||||
lastSplit && (lastPacketInList ? lastPacketCompleted : true),
|
||||
lastSplit && (containsLastPacket && lastPacketInList)));
|
||||
pageIndex++;
|
||||
continued = true;
|
||||
|
||||
@@ -259,18 +240,17 @@ List<Ogg::Page *> Ogg::Page::paginate(const ByteVectorList &packets,
|
||||
}
|
||||
else {
|
||||
l.append(new Page(packets,
|
||||
streamSerialNumber,
|
||||
firstPage,
|
||||
firstPacketContinued,
|
||||
lastPacketCompleted,
|
||||
containsLastPacket));
|
||||
streamSerialNumber,
|
||||
firstPage,
|
||||
firstPacketContinued,
|
||||
lastPacketCompleted,
|
||||
containsLastPacket));
|
||||
}
|
||||
|
||||
return l;
|
||||
}
|
||||
|
||||
Ogg::Page* Ogg::Page::getCopyWithNewPageSequenceNumber(int /*sequenceNumber*/)
|
||||
{
|
||||
Ogg::Page *Ogg::Page::getCopyWithNewPageSequenceNumber(int /*sequenceNumber*/) {
|
||||
debug("Ogg::Page::getCopyWithNewPageSequenceNumber() -- This function is obsolete. Returning null.");
|
||||
return nullptr;
|
||||
}
|
||||
@@ -280,13 +260,11 @@ Ogg::Page* Ogg::Page::getCopyWithNewPageSequenceNumber(int /*sequenceNumber*/)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Ogg::Page::Page(const ByteVectorList &packets,
|
||||
unsigned int streamSerialNumber,
|
||||
int pageNumber,
|
||||
bool firstPacketContinued,
|
||||
bool lastPacketCompleted,
|
||||
bool containsLastPacket) :
|
||||
d(new PagePrivate())
|
||||
{
|
||||
unsigned int streamSerialNumber,
|
||||
int pageNumber,
|
||||
bool firstPacketContinued,
|
||||
bool lastPacketCompleted,
|
||||
bool containsLastPacket) : d(new PagePrivate()) {
|
||||
d->header.setFirstPageOfStream(pageNumber == 0 && !firstPacketContinued);
|
||||
d->header.setLastPageOfStream(containsLastPacket);
|
||||
d->header.setFirstPacketContinued(firstPacketContinued);
|
||||
@@ -299,7 +277,7 @@ Ogg::Page::Page(const ByteVectorList &packets,
|
||||
ByteVector data;
|
||||
List<int> packetSizes;
|
||||
|
||||
for(ByteVectorList::ConstIterator it = packets.begin(); it != packets.end(); ++it) {
|
||||
for (ByteVectorList::ConstIterator it = packets.begin(); it != packets.end(); ++it) {
|
||||
packetSizes.append((*it).size());
|
||||
data.append(*it);
|
||||
}
|
||||
|
||||
153
3rdparty/taglib/ogg/oggpage.h
vendored
153
3rdparty/taglib/ogg/oggpage.h
vendored
@@ -32,14 +32,14 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
namespace Ogg {
|
||||
namespace Ogg {
|
||||
|
||||
class File;
|
||||
class PageHeader;
|
||||
class File;
|
||||
class PageHeader;
|
||||
|
||||
//! An implementation of Ogg pages
|
||||
//! An implementation of Ogg pages
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This is an implementation of the pages that make up an Ogg stream.
|
||||
* This handles parsing pages and breaking them down into packets and handles
|
||||
* the details of packets spanning multiple pages and pages that contain
|
||||
@@ -50,43 +50,42 @@ namespace TagLib {
|
||||
* could potentially be useful for non-meta data purposes.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT Page
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
class TAGLIB_EXPORT Page {
|
||||
public:
|
||||
/*!
|
||||
* Read an Ogg page from the \a file at the position \a pageOffset.
|
||||
*/
|
||||
Page(File *file, long pageOffset);
|
||||
Page(File *file, long pageOffset);
|
||||
|
||||
virtual ~Page();
|
||||
virtual ~Page();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the page's position within the file (in bytes).
|
||||
*/
|
||||
long fileOffset() const;
|
||||
long fileOffset() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a pointer to the header for this page. This pointer will become
|
||||
* invalid when the page is deleted.
|
||||
*/
|
||||
const PageHeader *header() const;
|
||||
const PageHeader *header() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the index of the page within the Ogg stream. This helps make it
|
||||
* possible to determine if pages have been lost.
|
||||
*
|
||||
* \see setPageSequenceNumber()
|
||||
*/
|
||||
int pageSequenceNumber() const;
|
||||
int pageSequenceNumber() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the page's position in the stream to \a sequenceNumber.
|
||||
*
|
||||
* \see pageSequenceNumber()
|
||||
*/
|
||||
void setPageSequenceNumber(int sequenceNumber);
|
||||
void setPageSequenceNumber(int sequenceNumber);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a copy of the page with \a sequenceNumber set as sequence number.
|
||||
*
|
||||
* \see header()
|
||||
@@ -94,91 +93,91 @@ namespace TagLib {
|
||||
*
|
||||
* \deprecated Always returns null.
|
||||
*/
|
||||
TAGLIB_DEPRECATED Page *getCopyWithNewPageSequenceNumber(int sequenceNumber);
|
||||
TAGLIB_DEPRECATED Page *getCopyWithNewPageSequenceNumber(int sequenceNumber);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the index of the first packet wholly or partially contained in
|
||||
* this page.
|
||||
*
|
||||
* \see setFirstPacketIndex()
|
||||
*/
|
||||
int firstPacketIndex() const;
|
||||
int firstPacketIndex() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the index of the first packet in the page.
|
||||
*
|
||||
* \see firstPacketIndex()
|
||||
*/
|
||||
void setFirstPacketIndex(int index);
|
||||
void setFirstPacketIndex(int index);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* When checking to see if a page contains a given packet this set of flags
|
||||
* represents the possible values for that packets status in the page.
|
||||
*
|
||||
* \see containsPacket()
|
||||
*/
|
||||
enum ContainsPacketFlags {
|
||||
//! No part of the packet is contained in the page
|
||||
DoesNotContainPacket = 0x0000,
|
||||
//! The packet is wholly contained in the page
|
||||
CompletePacket = 0x0001,
|
||||
//! The page starts with the given packet
|
||||
BeginsWithPacket = 0x0002,
|
||||
//! The page ends with the given packet
|
||||
EndsWithPacket = 0x0004
|
||||
};
|
||||
enum ContainsPacketFlags {
|
||||
//! No part of the packet is contained in the page
|
||||
DoesNotContainPacket = 0x0000,
|
||||
//! The packet is wholly contained in the page
|
||||
CompletePacket = 0x0001,
|
||||
//! The page starts with the given packet
|
||||
BeginsWithPacket = 0x0002,
|
||||
//! The page ends with the given packet
|
||||
EndsWithPacket = 0x0004
|
||||
};
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Checks to see if the specified \a packet is contained in the current
|
||||
* page.
|
||||
*
|
||||
* \see ContainsPacketFlags
|
||||
*/
|
||||
ContainsPacketFlags containsPacket(int index) const;
|
||||
ContainsPacketFlags containsPacket(int index) const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the number of packets (whole or partial) in this page.
|
||||
*/
|
||||
unsigned int packetCount() const;
|
||||
unsigned int packetCount() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a list of the packets in this page.
|
||||
*
|
||||
* \note Either or both the first and last packets may be only partial.
|
||||
* \see PageHeader::firstPacketContinued()
|
||||
*/
|
||||
ByteVectorList packets() const;
|
||||
ByteVectorList packets() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the size of the page in bytes.
|
||||
*/
|
||||
int size() const;
|
||||
int size() const;
|
||||
|
||||
ByteVector render() const;
|
||||
ByteVector render() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Defines a strategy for pagination, or grouping pages into Ogg packets,
|
||||
* for use with pagination methods.
|
||||
*
|
||||
* \note Yes, I'm aware that this is not a canonical "Strategy Pattern",
|
||||
* the term was simply convenient.
|
||||
*/
|
||||
enum PaginationStrategy {
|
||||
/*!
|
||||
enum PaginationStrategy {
|
||||
/*!
|
||||
* Attempt to put the specified set of packets into a single Ogg packet.
|
||||
* If the sum of the packet data is greater than will fit into a single
|
||||
* Ogg page -- 65280 bytes -- this will fall back to repagination using
|
||||
* the recommended page sizes.
|
||||
*/
|
||||
SinglePagePerGroup,
|
||||
/*!
|
||||
SinglePagePerGroup,
|
||||
/*!
|
||||
* Split the packet or group of packets into pages that conform to the
|
||||
* sizes recommended in the Ogg standard.
|
||||
*/
|
||||
Repaginate
|
||||
};
|
||||
Repaginate
|
||||
};
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Pack \a packets into Ogg pages using the \a strategy for pagination.
|
||||
* The page number indicator inside of the rendered packets will start
|
||||
* with \a firstPage and be incremented for each page rendered.
|
||||
@@ -197,34 +196,34 @@ namespace TagLib {
|
||||
* \see PaginationStrategy
|
||||
* \see List::setAutoDelete()
|
||||
*/
|
||||
static List<Page *> paginate(const ByteVectorList &packets,
|
||||
PaginationStrategy strategy,
|
||||
unsigned int streamSerialNumber,
|
||||
int firstPage,
|
||||
bool firstPacketContinued = false,
|
||||
bool lastPacketCompleted = true,
|
||||
bool containsLastPacket = false);
|
||||
static List<Page *> paginate(const ByteVectorList &packets,
|
||||
PaginationStrategy strategy,
|
||||
unsigned int streamSerialNumber,
|
||||
int firstPage,
|
||||
bool firstPacketContinued = false,
|
||||
bool lastPacketCompleted = true,
|
||||
bool containsLastPacket = false);
|
||||
|
||||
protected:
|
||||
/*!
|
||||
protected:
|
||||
/*!
|
||||
* Creates an Ogg packet based on the data in \a packets. The page number
|
||||
* for each page will be set to \a pageNumber.
|
||||
*/
|
||||
Page(const ByteVectorList &packets,
|
||||
unsigned int streamSerialNumber,
|
||||
int pageNumber,
|
||||
bool firstPacketContinued = false,
|
||||
bool lastPacketCompleted = true,
|
||||
bool containsLastPacket = false);
|
||||
Page(const ByteVectorList &packets,
|
||||
unsigned int streamSerialNumber,
|
||||
int pageNumber,
|
||||
bool firstPacketContinued = false,
|
||||
bool lastPacketCompleted = true,
|
||||
bool containsLastPacket = false);
|
||||
|
||||
private:
|
||||
Page(const Page &);
|
||||
Page &operator=(const Page &);
|
||||
private:
|
||||
Page(const Page &);
|
||||
Page &operator=(const Page &);
|
||||
|
||||
class PagePrivate;
|
||||
PagePrivate *d;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
class PagePrivate;
|
||||
PagePrivate *d;
|
||||
};
|
||||
} // namespace Ogg
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
#endif
|
||||
|
||||
119
3rdparty/taglib/ogg/oggpageheader.cpp
vendored
119
3rdparty/taglib/ogg/oggpageheader.cpp
vendored
@@ -34,20 +34,18 @@
|
||||
|
||||
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) {}
|
||||
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) {}
|
||||
|
||||
bool isValid;
|
||||
List<int> packetSizes;
|
||||
@@ -66,115 +64,92 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Ogg::PageHeader::PageHeader(Ogg::File *file, long pageOffset) :
|
||||
d(new PageHeaderPrivate())
|
||||
{
|
||||
if(file && pageOffset >= 0)
|
||||
Ogg::PageHeader::PageHeader(Ogg::File *file, long pageOffset) : d(new PageHeaderPrivate()) {
|
||||
if (file && pageOffset >= 0)
|
||||
read(file, pageOffset);
|
||||
}
|
||||
|
||||
Ogg::PageHeader::~PageHeader()
|
||||
{
|
||||
Ogg::PageHeader::~PageHeader() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
bool Ogg::PageHeader::isValid() const
|
||||
{
|
||||
bool Ogg::PageHeader::isValid() const {
|
||||
return d->isValid;
|
||||
}
|
||||
|
||||
List<int> Ogg::PageHeader::packetSizes() const
|
||||
{
|
||||
List<int> Ogg::PageHeader::packetSizes() const {
|
||||
return d->packetSizes;
|
||||
}
|
||||
|
||||
void Ogg::PageHeader::setPacketSizes(const List<int> &sizes)
|
||||
{
|
||||
void Ogg::PageHeader::setPacketSizes(const List<int> &sizes) {
|
||||
d->packetSizes = sizes;
|
||||
}
|
||||
|
||||
bool Ogg::PageHeader::firstPacketContinued() const
|
||||
{
|
||||
bool Ogg::PageHeader::firstPacketContinued() const {
|
||||
return d->firstPacketContinued;
|
||||
}
|
||||
|
||||
void Ogg::PageHeader::setFirstPacketContinued(bool continued)
|
||||
{
|
||||
void Ogg::PageHeader::setFirstPacketContinued(bool continued) {
|
||||
d->firstPacketContinued = continued;
|
||||
}
|
||||
|
||||
bool Ogg::PageHeader::lastPacketCompleted() const
|
||||
{
|
||||
bool Ogg::PageHeader::lastPacketCompleted() const {
|
||||
return d->lastPacketCompleted;
|
||||
}
|
||||
|
||||
void Ogg::PageHeader::setLastPacketCompleted(bool completed)
|
||||
{
|
||||
void Ogg::PageHeader::setLastPacketCompleted(bool completed) {
|
||||
d->lastPacketCompleted = completed;
|
||||
}
|
||||
|
||||
bool Ogg::PageHeader::firstPageOfStream() const
|
||||
{
|
||||
bool Ogg::PageHeader::firstPageOfStream() const {
|
||||
return d->firstPageOfStream;
|
||||
}
|
||||
|
||||
void Ogg::PageHeader::setFirstPageOfStream(bool first)
|
||||
{
|
||||
void Ogg::PageHeader::setFirstPageOfStream(bool first) {
|
||||
d->firstPageOfStream = first;
|
||||
}
|
||||
|
||||
bool Ogg::PageHeader::lastPageOfStream() const
|
||||
{
|
||||
bool Ogg::PageHeader::lastPageOfStream() const {
|
||||
return d->lastPageOfStream;
|
||||
}
|
||||
|
||||
void Ogg::PageHeader::setLastPageOfStream(bool last)
|
||||
{
|
||||
void Ogg::PageHeader::setLastPageOfStream(bool last) {
|
||||
d->lastPageOfStream = last;
|
||||
}
|
||||
|
||||
long long Ogg::PageHeader::absoluteGranularPosition() const
|
||||
{
|
||||
long long Ogg::PageHeader::absoluteGranularPosition() const {
|
||||
return d->absoluteGranularPosition;
|
||||
}
|
||||
|
||||
void Ogg::PageHeader::setAbsoluteGranularPosition(long long agp)
|
||||
{
|
||||
void Ogg::PageHeader::setAbsoluteGranularPosition(long long agp) {
|
||||
d->absoluteGranularPosition = agp;
|
||||
}
|
||||
|
||||
int Ogg::PageHeader::pageSequenceNumber() const
|
||||
{
|
||||
int Ogg::PageHeader::pageSequenceNumber() const {
|
||||
return d->pageSequenceNumber;
|
||||
}
|
||||
|
||||
void Ogg::PageHeader::setPageSequenceNumber(int sequenceNumber)
|
||||
{
|
||||
void Ogg::PageHeader::setPageSequenceNumber(int sequenceNumber) {
|
||||
d->pageSequenceNumber = sequenceNumber;
|
||||
}
|
||||
|
||||
unsigned int Ogg::PageHeader::streamSerialNumber() const
|
||||
{
|
||||
unsigned int Ogg::PageHeader::streamSerialNumber() const {
|
||||
return d->streamSerialNumber;
|
||||
}
|
||||
|
||||
void Ogg::PageHeader::setStreamSerialNumber(unsigned int n)
|
||||
{
|
||||
void Ogg::PageHeader::setStreamSerialNumber(unsigned int n) {
|
||||
d->streamSerialNumber = n;
|
||||
}
|
||||
|
||||
int Ogg::PageHeader::size() const
|
||||
{
|
||||
int Ogg::PageHeader::size() const {
|
||||
return d->size;
|
||||
}
|
||||
|
||||
int Ogg::PageHeader::dataSize() const
|
||||
{
|
||||
int Ogg::PageHeader::dataSize() const {
|
||||
return d->dataSize;
|
||||
}
|
||||
|
||||
ByteVector Ogg::PageHeader::render() const
|
||||
{
|
||||
ByteVector Ogg::PageHeader::render() const {
|
||||
ByteVector data;
|
||||
|
||||
// capture pattern
|
||||
@@ -225,8 +200,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 pageOffset) {
|
||||
file->seek(pageOffset);
|
||||
|
||||
// An Ogg page header is at least 27 bytes, so we'll go ahead and read that
|
||||
@@ -237,7 +211,7 @@ void Ogg::PageHeader::read(Ogg::File *file, long pageOffset)
|
||||
// Sanity check -- make sure that we were in fact able to read as much data as
|
||||
// we asked for and that the page begins with "OggS".
|
||||
|
||||
if(data.size() != 27 || !data.startsWith("OggS")) {
|
||||
if (data.size() != 27 || !data.startsWith("OggS")) {
|
||||
debug("Ogg::PageHeader::read() -- error reading page header");
|
||||
return;
|
||||
}
|
||||
@@ -245,8 +219,8 @@ void Ogg::PageHeader::read(Ogg::File *file, long pageOffset)
|
||||
const std::bitset<8> flags(data[5]);
|
||||
|
||||
d->firstPacketContinued = flags.test(0);
|
||||
d->firstPageOfStream = flags.test(1);
|
||||
d->lastPageOfStream = flags.test(2);
|
||||
d->firstPageOfStream = flags.test(1);
|
||||
d->lastPageOfStream = flags.test(2);
|
||||
|
||||
d->absoluteGranularPosition = data.toLongLong(6, false);
|
||||
d->streamSerialNumber = data.toUInt(14, false);
|
||||
@@ -262,7 +236,7 @@ void Ogg::PageHeader::read(Ogg::File *file, long pageOffset)
|
||||
|
||||
// Another sanity check.
|
||||
|
||||
if(pageSegmentCount < 1 || int(pageSegments.size()) != pageSegmentCount)
|
||||
if (pageSegmentCount < 1 || int(pageSegments.size()) != pageSegmentCount)
|
||||
return;
|
||||
|
||||
// The base size of an Ogg page 27 bytes plus the number of lacing values.
|
||||
@@ -271,17 +245,17 @@ void Ogg::PageHeader::read(Ogg::File *file, long pageOffset)
|
||||
|
||||
int packetSize = 0;
|
||||
|
||||
for(int i = 0; i < pageSegmentCount; i++) {
|
||||
for (int i = 0; i < pageSegmentCount; i++) {
|
||||
d->dataSize += static_cast<unsigned char>(pageSegments[i]);
|
||||
packetSize += static_cast<unsigned char>(pageSegments[i]);
|
||||
|
||||
if(static_cast<unsigned char>(pageSegments[i]) < 255) {
|
||||
if (static_cast<unsigned char>(pageSegments[i]) < 255) {
|
||||
d->packetSizes.append(packetSize);
|
||||
packetSize = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(packetSize > 0) {
|
||||
if (packetSize > 0) {
|
||||
d->packetSizes.append(packetSize);
|
||||
d->lastPacketCompleted = false;
|
||||
}
|
||||
@@ -291,11 +265,10 @@ void Ogg::PageHeader::read(Ogg::File *file, long pageOffset)
|
||||
d->isValid = true;
|
||||
}
|
||||
|
||||
ByteVector Ogg::PageHeader::lacingValues() const
|
||||
{
|
||||
ByteVector Ogg::PageHeader::lacingValues() const {
|
||||
ByteVector data;
|
||||
|
||||
for(List<int>::ConstIterator it = d->packetSizes.begin(); it != d->packetSizes.end(); ++it) {
|
||||
for (List<int>::ConstIterator it = d->packetSizes.begin(); it != d->packetSizes.end(); ++it) {
|
||||
|
||||
// The size of a packet in an Ogg page is indicated by a series of "lacing
|
||||
// values" where the sum of the values is the packet size in bytes. Each of
|
||||
@@ -304,7 +277,7 @@ ByteVector Ogg::PageHeader::lacingValues() const
|
||||
|
||||
data.resize(data.size() + (*it / 255), '\xff');
|
||||
|
||||
if(it != --d->packetSizes.end() || d->lastPacketCompleted)
|
||||
if (it != --d->packetSizes.end() || d->lastPacketCompleted)
|
||||
data.append(static_cast<unsigned char>(*it % 255));
|
||||
}
|
||||
|
||||
|
||||
123
3rdparty/taglib/ogg/oggpageheader.h
vendored
123
3rdparty/taglib/ogg/oggpageheader.h
vendored
@@ -33,56 +33,55 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
namespace Ogg {
|
||||
namespace Ogg {
|
||||
|
||||
class File;
|
||||
class File;
|
||||
|
||||
//! An implementation of the page headers associated with each Ogg::Page
|
||||
//! An implementation of the page headers associated with each Ogg::Page
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This class implements Ogg page headers which contain the information
|
||||
* about Ogg pages needed to break them into packets which can be passed on
|
||||
* to the codecs.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT PageHeader
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
class TAGLIB_EXPORT PageHeader {
|
||||
public:
|
||||
/*!
|
||||
* 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.
|
||||
*/
|
||||
PageHeader(File *file = 0, long pageOffset = -1);
|
||||
PageHeader(File *file = 0, long pageOffset = -1);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Deletes this instance of the PageHeader.
|
||||
*/
|
||||
virtual ~PageHeader();
|
||||
virtual ~PageHeader();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns true if the header parsed properly and is valid.
|
||||
*/
|
||||
bool isValid() const;
|
||||
bool isValid() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Ogg pages contain a list of packets (which are used by the contained
|
||||
* codecs). The sizes of these pages is encoded in the page header. This
|
||||
* returns a list of the packet sizes in bytes.
|
||||
*
|
||||
* \see setPacketSizes()
|
||||
*/
|
||||
List<int> packetSizes() const;
|
||||
List<int> packetSizes() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the sizes of the packets in this page to \a sizes. Internally this
|
||||
* updates the lacing values in the header.
|
||||
*
|
||||
* \see packetSizes()
|
||||
*/
|
||||
void setPacketSizes(const List<int> &sizes);
|
||||
void setPacketSizes(const List<int> &sizes);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Some packets can be <i>continued</i> across multiple pages. If the
|
||||
* first packet in the current page is a continuation this will return
|
||||
* true. If this is page starts with a new packet this will return false.
|
||||
@@ -90,89 +89,89 @@ namespace TagLib {
|
||||
* \see lastPacketCompleted()
|
||||
* \see setFirstPacketContinued()
|
||||
*/
|
||||
bool firstPacketContinued() const;
|
||||
bool firstPacketContinued() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the internal flag indicating if the first packet in this page is
|
||||
* continued to \a continued.
|
||||
*
|
||||
* \see firstPacketContinued()
|
||||
*/
|
||||
void setFirstPacketContinued(bool continued);
|
||||
void setFirstPacketContinued(bool continued);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns true if the last packet of this page is completely contained in
|
||||
* this page.
|
||||
*
|
||||
* \see firstPacketContinued()
|
||||
* \see setLastPacketCompleted()
|
||||
*/
|
||||
bool lastPacketCompleted() const;
|
||||
bool lastPacketCompleted() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the internal flag indicating if the last packet in this page is
|
||||
* complete to \a completed.
|
||||
*
|
||||
* \see lastPacketCompleted()
|
||||
*/
|
||||
void setLastPacketCompleted(bool completed);
|
||||
void setLastPacketCompleted(bool completed);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This returns true if this is the first page of the Ogg (logical) stream.
|
||||
*
|
||||
* \see setFirstPageOfStream()
|
||||
*/
|
||||
bool firstPageOfStream() const;
|
||||
bool firstPageOfStream() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Marks this page as the first page of the Ogg stream.
|
||||
*
|
||||
* \see firstPageOfStream()
|
||||
*/
|
||||
void setFirstPageOfStream(bool first);
|
||||
void setFirstPageOfStream(bool first);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This returns true if this is the last page of the Ogg (logical) stream.
|
||||
*
|
||||
* \see setLastPageOfStream()
|
||||
*/
|
||||
bool lastPageOfStream() const;
|
||||
bool lastPageOfStream() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Marks this page as the last page of the Ogg stream.
|
||||
*
|
||||
* \see lastPageOfStream()
|
||||
*/
|
||||
void setLastPageOfStream(bool last);
|
||||
void setLastPageOfStream(bool last);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* A special value of containing the position of the packet to be
|
||||
* interpreted by the codec. In the case of Vorbis this contains the PCM
|
||||
* value and is used to calculate the length of the stream.
|
||||
*
|
||||
* \see setAbsoluteGranularPosition()
|
||||
*/
|
||||
long long absoluteGranularPosition() const;
|
||||
long long absoluteGranularPosition() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* A special value of containing the position of the packet to be
|
||||
* interpreted by the codec. It is only supported here so that it may be
|
||||
* copied from one page to another.
|
||||
*
|
||||
* \see absoluteGranularPosition()
|
||||
*/
|
||||
void setAbsoluteGranularPosition(long long agp);
|
||||
void setAbsoluteGranularPosition(long long agp);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Every Ogg logical stream is given a random serial number which is common
|
||||
* to every page in that logical stream. This returns the serial number of
|
||||
* the stream associated with this packet.
|
||||
*
|
||||
* \see setStreamSerialNumber()
|
||||
*/
|
||||
unsigned int streamSerialNumber() const;
|
||||
unsigned int streamSerialNumber() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Every Ogg logical stream is given a random serial number which is common
|
||||
* to every page in that logical stream. This sets this pages serial
|
||||
* number. This method should be used when adding new pages to a logical
|
||||
@@ -180,55 +179,55 @@ namespace TagLib {
|
||||
*
|
||||
* \see streamSerialNumber()
|
||||
*/
|
||||
void setStreamSerialNumber(unsigned int n);
|
||||
void setStreamSerialNumber(unsigned int n);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the index of the page within the Ogg stream. This helps make it
|
||||
* possible to determine if pages have been lost.
|
||||
*
|
||||
* \see setPageSequenceNumber()
|
||||
*/
|
||||
int pageSequenceNumber() const;
|
||||
int pageSequenceNumber() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Sets the page's position in the stream to \a sequenceNumber.
|
||||
*
|
||||
* \see pageSequenceNumber()
|
||||
*/
|
||||
void setPageSequenceNumber(int sequenceNumber);
|
||||
void setPageSequenceNumber(int sequenceNumber);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the complete header size.
|
||||
*/
|
||||
int size() const;
|
||||
int size() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the size of the data portion of the page -- i.e. the size of the
|
||||
* page less the header size.
|
||||
*/
|
||||
int dataSize() const;
|
||||
int dataSize() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Render the page header to binary data.
|
||||
*
|
||||
* \note The checksum -- bytes 22 - 25 -- will be left empty and must be
|
||||
* filled in when rendering the entire page.
|
||||
*/
|
||||
ByteVector render() const;
|
||||
ByteVector render() const;
|
||||
|
||||
private:
|
||||
PageHeader(const PageHeader &);
|
||||
PageHeader &operator=(const PageHeader &);
|
||||
private:
|
||||
PageHeader(const PageHeader &);
|
||||
PageHeader &operator=(const PageHeader &);
|
||||
|
||||
void read(Ogg::File *file, long pageOffset);
|
||||
ByteVector lacingValues() const;
|
||||
void read(Ogg::File *file, long pageOffset);
|
||||
ByteVector lacingValues() const;
|
||||
|
||||
class PageHeaderPrivate;
|
||||
PageHeaderPrivate *d;
|
||||
};
|
||||
class PageHeaderPrivate;
|
||||
PageHeaderPrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace Ogg
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
|
||||
#endif
|
||||
|
||||
61
3rdparty/taglib/ogg/opus/opusfile.cpp
vendored
61
3rdparty/taglib/ogg/opus/opusfile.cpp
vendored
@@ -37,15 +37,12 @@
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
using namespace Strawberry_TagLib::TagLib::Ogg;
|
||||
|
||||
class Opus::File::FilePrivate
|
||||
{
|
||||
public:
|
||||
FilePrivate() :
|
||||
comment(0),
|
||||
properties(0) {}
|
||||
class Opus::File::FilePrivate {
|
||||
public:
|
||||
FilePrivate() : comment(0),
|
||||
properties(0) {}
|
||||
|
||||
~FilePrivate()
|
||||
{
|
||||
~FilePrivate() {
|
||||
delete comment;
|
||||
delete properties;
|
||||
}
|
||||
@@ -58,8 +55,7 @@ public:
|
||||
// static members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool Ogg::Opus::File::isSupported(IOStream *stream)
|
||||
{
|
||||
bool Ogg::Opus::File::isSupported(IOStream *stream) {
|
||||
// An Opus file has IDs "OggS" and "OpusHead" somewhere.
|
||||
|
||||
const ByteVector buffer = Utils::readHeader(stream, bufferSize(), false);
|
||||
@@ -70,50 +66,40 @@ bool Ogg::Opus::File::isSupported(IOStream *stream)
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Opus::File::File(FileName file, bool readProperties, Properties::ReadStyle) :
|
||||
Ogg::File(file),
|
||||
d(new FilePrivate())
|
||||
{
|
||||
if(isOpen())
|
||||
Opus::File::File(FileName file, bool readProperties, Properties::ReadStyle) : Ogg::File(file),
|
||||
d(new FilePrivate()) {
|
||||
if (isOpen())
|
||||
read(readProperties);
|
||||
}
|
||||
|
||||
Opus::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) :
|
||||
Ogg::File(stream),
|
||||
d(new FilePrivate())
|
||||
{
|
||||
if(isOpen())
|
||||
Opus::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : Ogg::File(stream),
|
||||
d(new FilePrivate()) {
|
||||
if (isOpen())
|
||||
read(readProperties);
|
||||
}
|
||||
|
||||
Opus::File::~File()
|
||||
{
|
||||
Opus::File::~File() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
Ogg::XiphComment *Opus::File::tag() const
|
||||
{
|
||||
Ogg::XiphComment *Opus::File::tag() const {
|
||||
return d->comment;
|
||||
}
|
||||
|
||||
PropertyMap Opus::File::properties() const
|
||||
{
|
||||
PropertyMap Opus::File::properties() const {
|
||||
return d->comment->properties();
|
||||
}
|
||||
|
||||
PropertyMap Opus::File::setProperties(const PropertyMap &properties)
|
||||
{
|
||||
PropertyMap Opus::File::setProperties(const PropertyMap &properties) {
|
||||
return d->comment->setProperties(properties);
|
||||
}
|
||||
|
||||
Opus::Properties *Opus::File::audioProperties() const
|
||||
{
|
||||
Opus::Properties *Opus::File::audioProperties() const {
|
||||
return d->properties;
|
||||
}
|
||||
|
||||
bool Opus::File::save()
|
||||
{
|
||||
if(!d->comment)
|
||||
bool Opus::File::save() {
|
||||
if (!d->comment)
|
||||
d->comment = new Ogg::XiphComment();
|
||||
|
||||
setPacket(1, ByteVector("OpusTags", 8) + d->comment->render(false));
|
||||
@@ -125,11 +111,10 @@ bool Opus::File::save()
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Opus::File::read(bool readProperties)
|
||||
{
|
||||
void Opus::File::read(bool readProperties) {
|
||||
ByteVector opusHeaderData = packet(0);
|
||||
|
||||
if(!opusHeaderData.startsWith("OpusHead")) {
|
||||
if (!opusHeaderData.startsWith("OpusHead")) {
|
||||
setValid(false);
|
||||
debug("Opus::File::read() -- invalid Opus identification header");
|
||||
return;
|
||||
@@ -137,7 +122,7 @@ void Opus::File::read(bool readProperties)
|
||||
|
||||
ByteVector commentHeaderData = packet(1);
|
||||
|
||||
if(!commentHeaderData.startsWith("OpusTags")) {
|
||||
if (!commentHeaderData.startsWith("OpusTags")) {
|
||||
setValid(false);
|
||||
debug("Opus::File::read() -- invalid Opus tags header");
|
||||
return;
|
||||
@@ -145,6 +130,6 @@ void Opus::File::read(bool readProperties)
|
||||
|
||||
d->comment = new Ogg::XiphComment(commentHeaderData.mid(8));
|
||||
|
||||
if(readProperties)
|
||||
if (readProperties)
|
||||
d->properties = new Properties(this);
|
||||
}
|
||||
|
||||
77
3rdparty/taglib/ogg/opus/opusfile.h
vendored
77
3rdparty/taglib/ogg/opus/opusfile.h
vendored
@@ -38,34 +38,33 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
namespace Ogg {
|
||||
namespace Ogg {
|
||||
|
||||
//! A namespace containing classes for Opus metadata
|
||||
//! A namespace containing classes for Opus metadata
|
||||
|
||||
namespace Opus {
|
||||
namespace Opus {
|
||||
|
||||
//! An implementation of Ogg::File with Opus specific methods
|
||||
//! An implementation of Ogg::File with Opus specific methods
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This is the central class in the Ogg Opus metadata processing collection
|
||||
* of classes. It's built upon Ogg::File which handles processing of the Ogg
|
||||
* logical bitstream and breaking it down into pages which are handled by
|
||||
* the codec implementations, in this case Opus specifically.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT File : public Ogg::File
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
class TAGLIB_EXPORT File : public Ogg::File {
|
||||
public:
|
||||
/*!
|
||||
* Constructs an Opus 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);
|
||||
File(FileName file, bool readProperties = true,
|
||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Constructs an Opus file from \a stream. If \a readProperties is true the
|
||||
* file's audio properties will also be read.
|
||||
*
|
||||
@@ -74,67 +73,67 @@ namespace TagLib {
|
||||
*
|
||||
* \note In the current implementation, \a propertiesStyle is ignored.
|
||||
*/
|
||||
File(IOStream *stream, bool readProperties = true,
|
||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||
File(IOStream *stream, bool readProperties = true,
|
||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys this instance of the File.
|
||||
*/
|
||||
virtual ~File();
|
||||
virtual ~File();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* 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;
|
||||
virtual Ogg::XiphComment *tag() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Implements the unified property interface -- export function.
|
||||
* This forwards directly to XiphComment::properties().
|
||||
*/
|
||||
PropertyMap properties() const;
|
||||
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 &);
|
||||
PropertyMap setProperties(const PropertyMap &);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the Opus::Properties for this file. If no audio properties
|
||||
* were read then this will return a null pointer.
|
||||
*/
|
||||
virtual Properties *audioProperties() const;
|
||||
virtual Properties *audioProperties() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Save the file.
|
||||
*
|
||||
* This returns true if the save was successful.
|
||||
*/
|
||||
virtual bool save();
|
||||
virtual bool save();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns whether or not the given \a stream can be opened as an Opus
|
||||
* file.
|
||||
*
|
||||
* \note This method is designed to do a quick check. The result may
|
||||
* not necessarily be correct.
|
||||
*/
|
||||
static bool isSupported(IOStream *stream);
|
||||
static bool isSupported(IOStream *stream);
|
||||
|
||||
private:
|
||||
File(const File &);
|
||||
File &operator=(const File &);
|
||||
private:
|
||||
File(const File &);
|
||||
File &operator=(const File &);
|
||||
|
||||
void read(bool readProperties);
|
||||
void read(bool readProperties);
|
||||
|
||||
class FilePrivate;
|
||||
FilePrivate *d;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
class FilePrivate;
|
||||
FilePrivate *d;
|
||||
};
|
||||
} // namespace Opus
|
||||
} // namespace Ogg
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
|
||||
#endif
|
||||
|
||||
64
3rdparty/taglib/ogg/opus/opusproperties.cpp
vendored
64
3rdparty/taglib/ogg/opus/opusproperties.cpp
vendored
@@ -38,15 +38,13 @@
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
using namespace Strawberry_TagLib::TagLib::Ogg;
|
||||
|
||||
class Opus::Properties::PropertiesPrivate
|
||||
{
|
||||
public:
|
||||
PropertiesPrivate() :
|
||||
length(0),
|
||||
bitrate(0),
|
||||
inputSampleRate(0),
|
||||
channels(0),
|
||||
opusVersion(0) {}
|
||||
class Opus::Properties::PropertiesPrivate {
|
||||
public:
|
||||
PropertiesPrivate() : length(0),
|
||||
bitrate(0),
|
||||
inputSampleRate(0),
|
||||
channels(0),
|
||||
opusVersion(0) {}
|
||||
|
||||
int length;
|
||||
int bitrate;
|
||||
@@ -59,58 +57,47 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Opus::Properties::Properties(File *file, ReadStyle style) :
|
||||
AudioProperties(style),
|
||||
d(new PropertiesPrivate())
|
||||
{
|
||||
Opus::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style),
|
||||
d(new PropertiesPrivate()) {
|
||||
read(file);
|
||||
}
|
||||
|
||||
Opus::Properties::~Properties()
|
||||
{
|
||||
Opus::Properties::~Properties() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
int Opus::Properties::length() const
|
||||
{
|
||||
int Opus::Properties::length() const {
|
||||
return lengthInSeconds();
|
||||
}
|
||||
|
||||
int Ogg::Opus::Properties::lengthInSeconds() const
|
||||
{
|
||||
int Ogg::Opus::Properties::lengthInSeconds() const {
|
||||
return d->length / 1000;
|
||||
}
|
||||
|
||||
int Ogg::Opus::Properties::lengthInMilliseconds() const
|
||||
{
|
||||
int Ogg::Opus::Properties::lengthInMilliseconds() const {
|
||||
return d->length;
|
||||
}
|
||||
|
||||
int Opus::Properties::bitrate() const
|
||||
{
|
||||
int Opus::Properties::bitrate() const {
|
||||
return d->bitrate;
|
||||
}
|
||||
|
||||
int Opus::Properties::sampleRate() const
|
||||
{
|
||||
int Opus::Properties::sampleRate() const {
|
||||
// Opus can decode any stream at a sample rate of 8, 12, 16, 24, or 48 kHz,
|
||||
// so there is no single sample rate. Let's assume it's the highest
|
||||
// possible.
|
||||
return 48000;
|
||||
}
|
||||
|
||||
int Opus::Properties::channels() const
|
||||
{
|
||||
int Opus::Properties::channels() const {
|
||||
return d->channels;
|
||||
}
|
||||
|
||||
int Opus::Properties::inputSampleRate() const
|
||||
{
|
||||
int Opus::Properties::inputSampleRate() const {
|
||||
return d->inputSampleRate;
|
||||
}
|
||||
|
||||
int Opus::Properties::opusVersion() const
|
||||
{
|
||||
int Opus::Properties::opusVersion() const {
|
||||
return d->opusVersion;
|
||||
}
|
||||
|
||||
@@ -118,8 +105,7 @@ int Opus::Properties::opusVersion() const
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Opus::Properties::read(File *file)
|
||||
{
|
||||
void Opus::Properties::read(File *file) {
|
||||
// Get the identification header from the Ogg implementation.
|
||||
|
||||
// http://tools.ietf.org/html/draft-terriberry-oggopus-01#section-5.1
|
||||
@@ -152,16 +138,16 @@ void Opus::Properties::read(File *file)
|
||||
pos += 1;
|
||||
|
||||
const Ogg::PageHeader *first = file->firstPageHeader();
|
||||
const Ogg::PageHeader *last = file->lastPageHeader();
|
||||
const Ogg::PageHeader *last = file->lastPageHeader();
|
||||
|
||||
if(first && last) {
|
||||
if (first && last) {
|
||||
const long long start = first->absoluteGranularPosition();
|
||||
const long long end = last->absoluteGranularPosition();
|
||||
const long long end = last->absoluteGranularPosition();
|
||||
|
||||
if(start >= 0 && end >= 0) {
|
||||
if (start >= 0 && end >= 0) {
|
||||
const long long frameCount = (end - start - preSkip);
|
||||
|
||||
if(frameCount > 0) {
|
||||
if (frameCount > 0) {
|
||||
const double length = frameCount * 1000.0 / 48000.0;
|
||||
long fileLengthWithoutOverhead = file->length();
|
||||
// Ignore the two mandatory header packets, see "3. Packet Organization"
|
||||
@@ -169,7 +155,7 @@ void Opus::Properties::read(File *file)
|
||||
for (unsigned int i = 0; i < 2; ++i) {
|
||||
fileLengthWithoutOverhead -= file->packet(i).size();
|
||||
}
|
||||
d->length = static_cast<int>(length + 0.5);
|
||||
d->length = static_cast<int>(length + 0.5);
|
||||
d->bitrate = static_cast<int>(fileLengthWithoutOverhead * 8.0 / length + 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
81
3rdparty/taglib/ogg/opus/opusproperties.h
vendored
81
3rdparty/taglib/ogg/opus/opusproperties.h
vendored
@@ -35,34 +35,33 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
namespace Ogg {
|
||||
namespace Ogg {
|
||||
|
||||
namespace Opus {
|
||||
namespace Opus {
|
||||
|
||||
class File;
|
||||
class File;
|
||||
|
||||
//! An implementation of audio property reading for Ogg Opus
|
||||
//! An implementation of audio property reading for Ogg Opus
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This reads the data from an Ogg Opus stream found in the AudioProperties
|
||||
* API.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT Properties : public AudioProperties
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
class TAGLIB_EXPORT Properties : public AudioProperties {
|
||||
public:
|
||||
/*!
|
||||
* Create an instance of Opus::Properties with the data read from the
|
||||
* Opus::File \a file.
|
||||
*/
|
||||
Properties(File *file, ReadStyle style = Average);
|
||||
Properties(File *file, ReadStyle style = Average);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys this Opus::Properties instance.
|
||||
*/
|
||||
virtual ~Properties();
|
||||
virtual ~Properties();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the length of the file in seconds. The length is rounded down to
|
||||
* the nearest whole second.
|
||||
*
|
||||
@@ -70,67 +69,67 @@ namespace TagLib {
|
||||
*
|
||||
* \deprecated
|
||||
*/
|
||||
TAGLIB_DEPRECATED virtual int length() const;
|
||||
TAGLIB_DEPRECATED virtual int length() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the length of the file in seconds. The length is rounded down to
|
||||
* the nearest whole second.
|
||||
*
|
||||
* \see lengthInMilliseconds()
|
||||
*/
|
||||
// BIC: make virtual
|
||||
int lengthInSeconds() const;
|
||||
// BIC: make virtual
|
||||
int lengthInSeconds() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the length of the file in milliseconds.
|
||||
*
|
||||
* \see lengthInSeconds()
|
||||
*/
|
||||
// BIC: make virtual
|
||||
int lengthInMilliseconds() const;
|
||||
// BIC: make virtual
|
||||
int lengthInMilliseconds() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the average bit rate of the file in kb/s.
|
||||
*/
|
||||
virtual int bitrate() const;
|
||||
virtual int bitrate() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the sample rate in Hz.
|
||||
*
|
||||
* \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;
|
||||
virtual int sampleRate() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the number of audio channels.
|
||||
*/
|
||||
virtual int channels() const;
|
||||
virtual int channels() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* The Opus codec supports decoding at multiple sample rates, there is no
|
||||
* single sample rate of the encoded stream. This returns the sample rate
|
||||
* of the original audio stream.
|
||||
*/
|
||||
int inputSampleRate() const;
|
||||
int inputSampleRate() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the Opus version, in the range 0...255.
|
||||
*/
|
||||
int opusVersion() const;
|
||||
int opusVersion() const;
|
||||
|
||||
private:
|
||||
Properties(const Properties &);
|
||||
Properties &operator=(const Properties &);
|
||||
private:
|
||||
Properties(const Properties &);
|
||||
Properties &operator=(const Properties &);
|
||||
|
||||
void read(File *file);
|
||||
void read(File *file);
|
||||
|
||||
class PropertiesPrivate;
|
||||
PropertiesPrivate *d;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
class PropertiesPrivate;
|
||||
PropertiesPrivate *d;
|
||||
};
|
||||
} // namespace Opus
|
||||
} // namespace Ogg
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
|
||||
#endif
|
||||
|
||||
59
3rdparty/taglib/ogg/speex/speexfile.cpp
vendored
59
3rdparty/taglib/ogg/speex/speexfile.cpp
vendored
@@ -37,15 +37,12 @@
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
using namespace Strawberry_TagLib::TagLib::Ogg;
|
||||
|
||||
class Speex::File::FilePrivate
|
||||
{
|
||||
public:
|
||||
FilePrivate() :
|
||||
comment(0),
|
||||
properties(0) {}
|
||||
class Speex::File::FilePrivate {
|
||||
public:
|
||||
FilePrivate() : comment(0),
|
||||
properties(0) {}
|
||||
|
||||
~FilePrivate()
|
||||
{
|
||||
~FilePrivate() {
|
||||
delete comment;
|
||||
delete properties;
|
||||
}
|
||||
@@ -58,8 +55,7 @@ public:
|
||||
// static members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool Ogg::Speex::File::isSupported(IOStream *stream)
|
||||
{
|
||||
bool Ogg::Speex::File::isSupported(IOStream *stream) {
|
||||
// A Speex file has IDs "OggS" and "Speex " somewhere.
|
||||
|
||||
const ByteVector buffer = Utils::readHeader(stream, bufferSize(), false);
|
||||
@@ -70,50 +66,40 @@ bool Ogg::Speex::File::isSupported(IOStream *stream)
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Speex::File::File(FileName file, bool readProperties, Properties::ReadStyle) :
|
||||
Ogg::File(file),
|
||||
d(new FilePrivate())
|
||||
{
|
||||
if(isOpen())
|
||||
Speex::File::File(FileName file, bool readProperties, Properties::ReadStyle) : Ogg::File(file),
|
||||
d(new FilePrivate()) {
|
||||
if (isOpen())
|
||||
read(readProperties);
|
||||
}
|
||||
|
||||
Speex::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) :
|
||||
Ogg::File(stream),
|
||||
d(new FilePrivate())
|
||||
{
|
||||
if(isOpen())
|
||||
Speex::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : Ogg::File(stream),
|
||||
d(new FilePrivate()) {
|
||||
if (isOpen())
|
||||
read(readProperties);
|
||||
}
|
||||
|
||||
Speex::File::~File()
|
||||
{
|
||||
Speex::File::~File() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
Ogg::XiphComment *Speex::File::tag() const
|
||||
{
|
||||
Ogg::XiphComment *Speex::File::tag() const {
|
||||
return d->comment;
|
||||
}
|
||||
|
||||
PropertyMap Speex::File::properties() const
|
||||
{
|
||||
PropertyMap Speex::File::properties() const {
|
||||
return d->comment->properties();
|
||||
}
|
||||
|
||||
PropertyMap Speex::File::setProperties(const PropertyMap &properties)
|
||||
{
|
||||
PropertyMap Speex::File::setProperties(const PropertyMap &properties) {
|
||||
return d->comment->setProperties(properties);
|
||||
}
|
||||
|
||||
Speex::Properties *Speex::File::audioProperties() const
|
||||
{
|
||||
Speex::Properties *Speex::File::audioProperties() const {
|
||||
return d->properties;
|
||||
}
|
||||
|
||||
bool Speex::File::save()
|
||||
{
|
||||
if(!d->comment)
|
||||
bool Speex::File::save() {
|
||||
if (!d->comment)
|
||||
d->comment = new Ogg::XiphComment();
|
||||
|
||||
setPacket(1, d->comment->render());
|
||||
@@ -125,11 +111,10 @@ bool Speex::File::save()
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Speex::File::read(bool readProperties)
|
||||
{
|
||||
void Speex::File::read(bool readProperties) {
|
||||
ByteVector speexHeaderData = packet(0);
|
||||
|
||||
if(!speexHeaderData.startsWith("Speex ")) {
|
||||
if (!speexHeaderData.startsWith("Speex ")) {
|
||||
debug("Speex::File::read() -- invalid Speex identification header");
|
||||
setValid(false);
|
||||
return;
|
||||
@@ -139,6 +124,6 @@ void Speex::File::read(bool readProperties)
|
||||
|
||||
d->comment = new Ogg::XiphComment(commentHeaderData);
|
||||
|
||||
if(readProperties)
|
||||
if (readProperties)
|
||||
d->properties = new Properties(this);
|
||||
}
|
||||
|
||||
77
3rdparty/taglib/ogg/speex/speexfile.h
vendored
77
3rdparty/taglib/ogg/speex/speexfile.h
vendored
@@ -38,34 +38,33 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
namespace Ogg {
|
||||
namespace Ogg {
|
||||
|
||||
//! A namespace containing classes for Speex metadata
|
||||
//! A namespace containing classes for Speex metadata
|
||||
|
||||
namespace Speex {
|
||||
namespace Speex {
|
||||
|
||||
//! An implementation of Ogg::File with Speex specific methods
|
||||
//! An implementation of Ogg::File with Speex specific methods
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This is the central class in the Ogg Speex metadata processing collection
|
||||
* of classes. It's built upon Ogg::File which handles processing of the Ogg
|
||||
* logical bitstream and breaking it down into pages which are handled by
|
||||
* the codec implementations, in this case Speex specifically.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT File : public Ogg::File
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
class TAGLIB_EXPORT File : public Ogg::File {
|
||||
public:
|
||||
/*!
|
||||
* Constructs a Speex 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);
|
||||
File(FileName file, bool readProperties = true,
|
||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Constructs a Speex file from \a stream. If \a readProperties is true the
|
||||
* file's audio properties will also be read.
|
||||
*
|
||||
@@ -74,67 +73,67 @@ namespace TagLib {
|
||||
*
|
||||
* \note In the current implementation, \a propertiesStyle is ignored.
|
||||
*/
|
||||
File(IOStream *stream, bool readProperties = true,
|
||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||
File(IOStream *stream, bool readProperties = true,
|
||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys this instance of the File.
|
||||
*/
|
||||
virtual ~File();
|
||||
virtual ~File();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* 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;
|
||||
virtual Ogg::XiphComment *tag() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Implements the unified property interface -- export function.
|
||||
* This forwards directly to XiphComment::properties().
|
||||
*/
|
||||
PropertyMap properties() const;
|
||||
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 &);
|
||||
PropertyMap setProperties(const PropertyMap &);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the Speex::Properties for this file. If no audio properties
|
||||
* were read then this will return a null pointer.
|
||||
*/
|
||||
virtual Properties *audioProperties() const;
|
||||
virtual Properties *audioProperties() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Save the file.
|
||||
*
|
||||
* This returns true if the save was successful.
|
||||
*/
|
||||
virtual bool save();
|
||||
virtual bool save();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns whether or not the given \a stream can be opened as a Speex
|
||||
* file.
|
||||
*
|
||||
* \note This method is designed to do a quick check. The result may
|
||||
* not necessarily be correct.
|
||||
*/
|
||||
static bool isSupported(IOStream *stream);
|
||||
static bool isSupported(IOStream *stream);
|
||||
|
||||
private:
|
||||
File(const File &);
|
||||
File &operator=(const File &);
|
||||
private:
|
||||
File(const File &);
|
||||
File &operator=(const File &);
|
||||
|
||||
void read(bool readProperties);
|
||||
void read(bool readProperties);
|
||||
|
||||
class FilePrivate;
|
||||
FilePrivate *d;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
class FilePrivate;
|
||||
FilePrivate *d;
|
||||
};
|
||||
} // namespace Speex
|
||||
} // namespace Ogg
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
|
||||
#endif
|
||||
|
||||
74
3rdparty/taglib/ogg/speex/speexproperties.cpp
vendored
74
3rdparty/taglib/ogg/speex/speexproperties.cpp
vendored
@@ -38,18 +38,16 @@
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
using namespace Strawberry_TagLib::TagLib::Ogg;
|
||||
|
||||
class Speex::Properties::PropertiesPrivate
|
||||
{
|
||||
public:
|
||||
PropertiesPrivate() :
|
||||
length(0),
|
||||
bitrate(0),
|
||||
bitrateNominal(0),
|
||||
sampleRate(0),
|
||||
channels(0),
|
||||
speexVersion(0),
|
||||
vbr(false),
|
||||
mode(0) {}
|
||||
class Speex::Properties::PropertiesPrivate {
|
||||
public:
|
||||
PropertiesPrivate() : length(0),
|
||||
bitrate(0),
|
||||
bitrateNominal(0),
|
||||
sampleRate(0),
|
||||
channels(0),
|
||||
speexVersion(0),
|
||||
vbr(false),
|
||||
mode(0) {}
|
||||
|
||||
int length;
|
||||
int bitrate;
|
||||
@@ -65,55 +63,44 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Speex::Properties::Properties(File *file, ReadStyle style) :
|
||||
AudioProperties(style),
|
||||
d(new PropertiesPrivate())
|
||||
{
|
||||
Speex::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style),
|
||||
d(new PropertiesPrivate()) {
|
||||
read(file);
|
||||
}
|
||||
|
||||
Speex::Properties::~Properties()
|
||||
{
|
||||
Speex::Properties::~Properties() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
int Speex::Properties::length() const
|
||||
{
|
||||
int Speex::Properties::length() const {
|
||||
return lengthInSeconds();
|
||||
}
|
||||
|
||||
int Speex::Properties::lengthInSeconds() const
|
||||
{
|
||||
int Speex::Properties::lengthInSeconds() const {
|
||||
return d->length / 1000;
|
||||
}
|
||||
|
||||
int Speex::Properties::lengthInMilliseconds() const
|
||||
{
|
||||
int Speex::Properties::lengthInMilliseconds() const {
|
||||
return d->length;
|
||||
}
|
||||
|
||||
int Speex::Properties::bitrate() const
|
||||
{
|
||||
int Speex::Properties::bitrate() const {
|
||||
return d->bitrate;
|
||||
}
|
||||
|
||||
int Speex::Properties::bitrateNominal() const
|
||||
{
|
||||
int Speex::Properties::bitrateNominal() const {
|
||||
return d->bitrateNominal;
|
||||
}
|
||||
|
||||
int Speex::Properties::sampleRate() const
|
||||
{
|
||||
int Speex::Properties::sampleRate() const {
|
||||
return d->sampleRate;
|
||||
}
|
||||
|
||||
int Speex::Properties::channels() const
|
||||
{
|
||||
int Speex::Properties::channels() const {
|
||||
return d->channels;
|
||||
}
|
||||
|
||||
int Speex::Properties::speexVersion() const
|
||||
{
|
||||
int Speex::Properties::speexVersion() const {
|
||||
return d->speexVersion;
|
||||
}
|
||||
|
||||
@@ -121,12 +108,11 @@ int Speex::Properties::speexVersion() const
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Speex::Properties::read(File *file)
|
||||
{
|
||||
void Speex::Properties::read(File *file) {
|
||||
// Get the identification header from the Ogg implementation.
|
||||
|
||||
const ByteVector data = file->packet(0);
|
||||
if(data.size() < 64) {
|
||||
if (data.size() < 64) {
|
||||
debug("Speex::Properties::read() -- data is too short.");
|
||||
return;
|
||||
}
|
||||
@@ -171,16 +157,16 @@ void Speex::Properties::read(File *file)
|
||||
// unsigned int framesPerPacket = data.mid(pos, 4).toUInt(false);
|
||||
|
||||
const Ogg::PageHeader *first = file->firstPageHeader();
|
||||
const Ogg::PageHeader *last = file->lastPageHeader();
|
||||
const Ogg::PageHeader *last = file->lastPageHeader();
|
||||
|
||||
if(first && last) {
|
||||
if (first && last) {
|
||||
const long long start = first->absoluteGranularPosition();
|
||||
const long long end = last->absoluteGranularPosition();
|
||||
const long long end = last->absoluteGranularPosition();
|
||||
|
||||
if(start >= 0 && end >= 0 && d->sampleRate > 0) {
|
||||
if (start >= 0 && end >= 0 && d->sampleRate > 0) {
|
||||
const long long frameCount = end - start;
|
||||
|
||||
if(frameCount > 0) {
|
||||
if (frameCount > 0) {
|
||||
const double length = frameCount * 1000.0 / d->sampleRate;
|
||||
long fileLengthWithoutOverhead = file->length();
|
||||
// Ignore the two header packets, see "Ogg file format" in
|
||||
@@ -188,7 +174,7 @@ void Speex::Properties::read(File *file)
|
||||
for (unsigned int i = 0; i < 2; ++i) {
|
||||
fileLengthWithoutOverhead -= file->packet(i).size();
|
||||
}
|
||||
d->length = static_cast<int>(length + 0.5);
|
||||
d->length = static_cast<int>(length + 0.5);
|
||||
d->bitrate = static_cast<int>(fileLengthWithoutOverhead * 8.0 / length + 0.5);
|
||||
}
|
||||
}
|
||||
@@ -202,6 +188,6 @@ void Speex::Properties::read(File *file)
|
||||
|
||||
// Alternative to the actual average bitrate.
|
||||
|
||||
if(d->bitrate == 0 && d->bitrateNominal > 0)
|
||||
if (d->bitrate == 0 && d->bitrateNominal > 0)
|
||||
d->bitrate = static_cast<int>(d->bitrateNominal / 1000.0 + 0.5);
|
||||
}
|
||||
|
||||
81
3rdparty/taglib/ogg/speex/speexproperties.h
vendored
81
3rdparty/taglib/ogg/speex/speexproperties.h
vendored
@@ -35,34 +35,33 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
namespace Ogg {
|
||||
namespace Ogg {
|
||||
|
||||
namespace Speex {
|
||||
namespace Speex {
|
||||
|
||||
class File;
|
||||
class File;
|
||||
|
||||
//! An implementation of audio property reading for Ogg Speex
|
||||
//! An implementation of audio property reading for Ogg Speex
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This reads the data from an Ogg Speex stream found in the AudioProperties
|
||||
* API.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT Properties : public AudioProperties
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
class TAGLIB_EXPORT Properties : public AudioProperties {
|
||||
public:
|
||||
/*!
|
||||
* Create an instance of Speex::Properties with the data read from the
|
||||
* Speex::File \a file.
|
||||
*/
|
||||
Properties(File *file, ReadStyle style = Average);
|
||||
Properties(File *file, ReadStyle style = Average);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys this Speex::Properties instance.
|
||||
*/
|
||||
virtual ~Properties();
|
||||
virtual ~Properties();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the length of the file in seconds. The length is rounded down to
|
||||
* the nearest whole second.
|
||||
*
|
||||
@@ -70,62 +69,62 @@ namespace TagLib {
|
||||
*
|
||||
* \deprecated
|
||||
*/
|
||||
TAGLIB_DEPRECATED virtual int length() const;
|
||||
TAGLIB_DEPRECATED virtual int length() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the length of the file in seconds. The length is rounded down to
|
||||
* the nearest whole second.
|
||||
*
|
||||
* \see lengthInMilliseconds()
|
||||
*/
|
||||
// BIC: make virtual
|
||||
int lengthInSeconds() const;
|
||||
// BIC: make virtual
|
||||
int lengthInSeconds() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the length of the file in milliseconds.
|
||||
*
|
||||
* \see lengthInSeconds()
|
||||
*/
|
||||
// BIC: make virtual
|
||||
int lengthInMilliseconds() const;
|
||||
// BIC: make virtual
|
||||
int lengthInMilliseconds() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the average bit rate of the file in kb/s.
|
||||
*/
|
||||
virtual int bitrate() const;
|
||||
virtual int bitrate() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the nominal bit rate as read from the Speex header in kb/s.
|
||||
*/
|
||||
int bitrateNominal() const;
|
||||
int bitrateNominal() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the sample rate in Hz.
|
||||
*/
|
||||
virtual int sampleRate() const;
|
||||
virtual int sampleRate() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the number of audio channels.
|
||||
*/
|
||||
virtual int channels() const;
|
||||
virtual int channels() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the Speex version, currently "0" (as specified by the spec).
|
||||
*/
|
||||
int speexVersion() const;
|
||||
int speexVersion() const;
|
||||
|
||||
private:
|
||||
Properties(const Properties &);
|
||||
Properties &operator=(const Properties &);
|
||||
private:
|
||||
Properties(const Properties &);
|
||||
Properties &operator=(const Properties &);
|
||||
|
||||
void read(File *file);
|
||||
void read(File *file);
|
||||
|
||||
class PropertiesPrivate;
|
||||
PropertiesPrivate *d;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
class PropertiesPrivate;
|
||||
PropertiesPrivate *d;
|
||||
};
|
||||
} // namespace Speex
|
||||
} // namespace Ogg
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
|
||||
#endif
|
||||
|
||||
67
3rdparty/taglib/ogg/vorbis/vorbisfile.cpp
vendored
67
3rdparty/taglib/ogg/vorbis/vorbisfile.cpp
vendored
@@ -34,15 +34,12 @@
|
||||
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
|
||||
class Vorbis::File::FilePrivate
|
||||
{
|
||||
public:
|
||||
FilePrivate() :
|
||||
comment(0),
|
||||
properties(0) {}
|
||||
class Vorbis::File::FilePrivate {
|
||||
public:
|
||||
FilePrivate() : comment(0),
|
||||
properties(0) {}
|
||||
|
||||
~FilePrivate()
|
||||
{
|
||||
~FilePrivate() {
|
||||
delete comment;
|
||||
delete properties;
|
||||
}
|
||||
@@ -53,20 +50,19 @@ public:
|
||||
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
/*!
|
||||
/*!
|
||||
* Vorbis headers can be found with one type ID byte and the string "vorbis" in
|
||||
* an Ogg stream. 0x03 indicates the comment header.
|
||||
*/
|
||||
static const char vorbisCommentHeaderID[] = { 0x03, 'v', 'o', 'r', 'b', 'i', 's', 0 };
|
||||
}
|
||||
}
|
||||
static const char vorbisCommentHeaderID[] = { 0x03, 'v', 'o', 'r', 'b', 'i', 's', 0 };
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// static members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool Vorbis::File::isSupported(IOStream *stream)
|
||||
{
|
||||
bool Vorbis::File::isSupported(IOStream *stream) {
|
||||
// An Ogg Vorbis file has IDs "OggS" and "\x01vorbis" somewhere.
|
||||
|
||||
const ByteVector buffer = Utils::readHeader(stream, bufferSize(), false);
|
||||
@@ -77,52 +73,42 @@ bool Vorbis::File::isSupported(IOStream *stream)
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Vorbis::File::File(FileName file, bool readProperties, Properties::ReadStyle) :
|
||||
Ogg::File(file),
|
||||
d(new FilePrivate())
|
||||
{
|
||||
if(isOpen())
|
||||
Vorbis::File::File(FileName file, bool readProperties, Properties::ReadStyle) : Ogg::File(file),
|
||||
d(new FilePrivate()) {
|
||||
if (isOpen())
|
||||
read(readProperties);
|
||||
}
|
||||
|
||||
Vorbis::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) :
|
||||
Ogg::File(stream),
|
||||
d(new FilePrivate())
|
||||
{
|
||||
if(isOpen())
|
||||
Vorbis::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : Ogg::File(stream),
|
||||
d(new FilePrivate()) {
|
||||
if (isOpen())
|
||||
read(readProperties);
|
||||
}
|
||||
|
||||
Vorbis::File::~File()
|
||||
{
|
||||
Vorbis::File::~File() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
Ogg::XiphComment *Vorbis::File::tag() const
|
||||
{
|
||||
Ogg::XiphComment *Vorbis::File::tag() const {
|
||||
return d->comment;
|
||||
}
|
||||
|
||||
PropertyMap Vorbis::File::properties() const
|
||||
{
|
||||
PropertyMap Vorbis::File::properties() const {
|
||||
return d->comment->properties();
|
||||
}
|
||||
|
||||
PropertyMap Vorbis::File::setProperties(const PropertyMap &properties)
|
||||
{
|
||||
PropertyMap Vorbis::File::setProperties(const PropertyMap &properties) {
|
||||
return d->comment->setProperties(properties);
|
||||
}
|
||||
|
||||
Vorbis::Properties *Vorbis::File::audioProperties() const
|
||||
{
|
||||
Vorbis::Properties *Vorbis::File::audioProperties() const {
|
||||
return d->properties;
|
||||
}
|
||||
|
||||
bool Vorbis::File::save()
|
||||
{
|
||||
bool Vorbis::File::save() {
|
||||
ByteVector v(vorbisCommentHeaderID);
|
||||
|
||||
if(!d->comment)
|
||||
if (!d->comment)
|
||||
d->comment = new Ogg::XiphComment();
|
||||
v.append(d->comment->render());
|
||||
|
||||
@@ -135,11 +121,10 @@ bool Vorbis::File::save()
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Vorbis::File::read(bool readProperties)
|
||||
{
|
||||
void Vorbis::File::read(bool readProperties) {
|
||||
ByteVector commentHeaderData = packet(1);
|
||||
|
||||
if(commentHeaderData.mid(0, 7) != vorbisCommentHeaderID) {
|
||||
if (commentHeaderData.mid(0, 7) != vorbisCommentHeaderID) {
|
||||
debug("Vorbis::File::read() - Could not find the Vorbis comment header.");
|
||||
setValid(false);
|
||||
return;
|
||||
@@ -147,6 +132,6 @@ void Vorbis::File::read(bool readProperties)
|
||||
|
||||
d->comment = new Ogg::XiphComment(commentHeaderData.mid(7));
|
||||
|
||||
if(readProperties)
|
||||
if (readProperties)
|
||||
d->properties = new Properties(this);
|
||||
}
|
||||
|
||||
83
3rdparty/taglib/ogg/vorbis/vorbisfile.h
vendored
83
3rdparty/taglib/ogg/vorbis/vorbisfile.h
vendored
@@ -43,36 +43,35 @@ namespace TagLib {
|
||||
*/
|
||||
|
||||
#ifdef DOXYGEN
|
||||
namespace Ogg {
|
||||
namespace Ogg {
|
||||
#endif
|
||||
|
||||
//! A namespace containing classes for Vorbis metadata
|
||||
//! A namespace containing classes for Vorbis metadata
|
||||
|
||||
namespace Vorbis {
|
||||
namespace Vorbis {
|
||||
|
||||
|
||||
//! An implementation of Ogg::File with Vorbis specific methods
|
||||
//! An implementation of Ogg::File with Vorbis specific methods
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This is the central class in the Ogg Vorbis metadata processing collection
|
||||
* of classes. It's built upon Ogg::File which handles processing of the Ogg
|
||||
* logical bitstream and breaking it down into pages which are handled by
|
||||
* the codec implementations, in this case Vorbis specifically.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT File : public Ogg::File
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
class TAGLIB_EXPORT File : public Ogg::File {
|
||||
public:
|
||||
/*!
|
||||
* Constructs a Vorbis 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);
|
||||
File(FileName file, bool readProperties = true,
|
||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Constructs a Vorbis file from \a stream. If \a readProperties is true the
|
||||
* file's audio properties will also be read.
|
||||
*
|
||||
@@ -81,65 +80,65 @@ namespace TagLib {
|
||||
*
|
||||
* \note In the current implementation, \a propertiesStyle is ignored.
|
||||
*/
|
||||
File(IOStream *stream, bool readProperties = true,
|
||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||
File(IOStream *stream, bool readProperties = true,
|
||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys this instance of the File.
|
||||
*/
|
||||
virtual ~File();
|
||||
virtual ~File();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* 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;
|
||||
virtual Ogg::XiphComment *tag() const;
|
||||
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Implements the unified property interface -- export function.
|
||||
* This forwards directly to XiphComment::properties().
|
||||
*/
|
||||
PropertyMap properties() const;
|
||||
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 &);
|
||||
PropertyMap setProperties(const PropertyMap &);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the Vorbis::Properties for this file. If no audio properties
|
||||
* were read then this will return a null pointer.
|
||||
*/
|
||||
virtual Properties *audioProperties() const;
|
||||
virtual Properties *audioProperties() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Save the file.
|
||||
*
|
||||
* This returns true if the save was successful.
|
||||
*/
|
||||
virtual bool save();
|
||||
virtual bool save();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Check if the given \a stream can be opened as an Ogg Vorbis file.
|
||||
*
|
||||
* \note This method is designed to do a quick check. The result may
|
||||
* not necessarily be correct.
|
||||
*/
|
||||
static bool isSupported(IOStream *stream);
|
||||
static bool isSupported(IOStream *stream);
|
||||
|
||||
private:
|
||||
File(const File &);
|
||||
File &operator=(const File &);
|
||||
private:
|
||||
File(const File &);
|
||||
File &operator=(const File &);
|
||||
|
||||
void read(bool readProperties);
|
||||
void read(bool readProperties);
|
||||
|
||||
class FilePrivate;
|
||||
FilePrivate *d;
|
||||
};
|
||||
}
|
||||
class FilePrivate;
|
||||
FilePrivate *d;
|
||||
};
|
||||
} // namespace Vorbis
|
||||
|
||||
/*
|
||||
* To keep compatibility with the current version put Vorbis in the Ogg namespace
|
||||
@@ -148,12 +147,16 @@ namespace TagLib {
|
||||
*/
|
||||
|
||||
#ifdef DOXYGEN
|
||||
}
|
||||
}
|
||||
#else
|
||||
namespace Ogg { namespace Vorbis { typedef Strawberry_TagLib::TagLib::Vorbis::File File; } }
|
||||
namespace Ogg {
|
||||
namespace Vorbis {
|
||||
typedef Strawberry_TagLib::TagLib::Vorbis::File File;
|
||||
}
|
||||
} // namespace Ogg
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
|
||||
#endif
|
||||
|
||||
90
3rdparty/taglib/ogg/vorbis/vorbisproperties.cpp
vendored
90
3rdparty/taglib/ogg/vorbis/vorbisproperties.cpp
vendored
@@ -33,18 +33,16 @@
|
||||
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
|
||||
class Vorbis::Properties::PropertiesPrivate
|
||||
{
|
||||
public:
|
||||
PropertiesPrivate() :
|
||||
length(0),
|
||||
bitrate(0),
|
||||
sampleRate(0),
|
||||
channels(0),
|
||||
vorbisVersion(0),
|
||||
bitrateMaximum(0),
|
||||
bitrateNominal(0),
|
||||
bitrateMinimum(0) {}
|
||||
class Vorbis::Properties::PropertiesPrivate {
|
||||
public:
|
||||
PropertiesPrivate() : length(0),
|
||||
bitrate(0),
|
||||
sampleRate(0),
|
||||
channels(0),
|
||||
vorbisVersion(0),
|
||||
bitrateMaximum(0),
|
||||
bitrateNominal(0),
|
||||
bitrateMinimum(0) {}
|
||||
|
||||
int length;
|
||||
int bitrate;
|
||||
@@ -58,77 +56,64 @@ public:
|
||||
|
||||
namespace Strawberry_TagLib {
|
||||
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 };
|
||||
}
|
||||
}
|
||||
static const char vorbisSetupHeaderID[] = { 0x01, 'v', 'o', 'r', 'b', 'i', 's', 0 };
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Vorbis::Properties::Properties(File *file, ReadStyle style) :
|
||||
AudioProperties(style),
|
||||
d(new PropertiesPrivate())
|
||||
{
|
||||
Vorbis::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style),
|
||||
d(new PropertiesPrivate()) {
|
||||
read(file);
|
||||
}
|
||||
|
||||
Vorbis::Properties::~Properties()
|
||||
{
|
||||
Vorbis::Properties::~Properties() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
int Vorbis::Properties::length() const
|
||||
{
|
||||
int Vorbis::Properties::length() const {
|
||||
return lengthInSeconds();
|
||||
}
|
||||
|
||||
int Vorbis::Properties::lengthInSeconds() const
|
||||
{
|
||||
int Vorbis::Properties::lengthInSeconds() const {
|
||||
return d->length / 1000;
|
||||
}
|
||||
|
||||
int Vorbis::Properties::lengthInMilliseconds() const
|
||||
{
|
||||
int Vorbis::Properties::lengthInMilliseconds() const {
|
||||
return d->length;
|
||||
}
|
||||
|
||||
int Vorbis::Properties::bitrate() const
|
||||
{
|
||||
int Vorbis::Properties::bitrate() const {
|
||||
return d->bitrate;
|
||||
}
|
||||
|
||||
int Vorbis::Properties::sampleRate() const
|
||||
{
|
||||
int Vorbis::Properties::sampleRate() const {
|
||||
return d->sampleRate;
|
||||
}
|
||||
|
||||
int Vorbis::Properties::channels() const
|
||||
{
|
||||
int Vorbis::Properties::channels() const {
|
||||
return d->channels;
|
||||
}
|
||||
|
||||
int Vorbis::Properties::vorbisVersion() const
|
||||
{
|
||||
int Vorbis::Properties::vorbisVersion() const {
|
||||
return d->vorbisVersion;
|
||||
}
|
||||
|
||||
int Vorbis::Properties::bitrateMaximum() const
|
||||
{
|
||||
int Vorbis::Properties::bitrateMaximum() const {
|
||||
return d->bitrateMaximum;
|
||||
}
|
||||
|
||||
int Vorbis::Properties::bitrateNominal() const
|
||||
{
|
||||
int Vorbis::Properties::bitrateNominal() const {
|
||||
return d->bitrateNominal;
|
||||
}
|
||||
|
||||
int Vorbis::Properties::bitrateMinimum() const
|
||||
{
|
||||
int Vorbis::Properties::bitrateMinimum() const {
|
||||
return d->bitrateMinimum;
|
||||
}
|
||||
|
||||
@@ -136,19 +121,18 @@ int Vorbis::Properties::bitrateMinimum() const
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Vorbis::Properties::read(File *file)
|
||||
{
|
||||
void Vorbis::Properties::read(File *file) {
|
||||
// Get the identification header from the Ogg implementation.
|
||||
|
||||
const ByteVector data = file->packet(0);
|
||||
if(data.size() < 28) {
|
||||
if (data.size() < 28) {
|
||||
debug("Vorbis::Properties::read() -- data is too short.");
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned int pos = 0;
|
||||
|
||||
if(data.mid(pos, 7) != vorbisSetupHeaderID) {
|
||||
if (data.mid(pos, 7) != vorbisSetupHeaderID) {
|
||||
debug("Vorbis::Properties::read() -- invalid Vorbis identification header");
|
||||
return;
|
||||
}
|
||||
@@ -177,16 +161,16 @@ void Vorbis::Properties::read(File *file)
|
||||
// for my notes on the topic.
|
||||
|
||||
const Ogg::PageHeader *first = file->firstPageHeader();
|
||||
const Ogg::PageHeader *last = file->lastPageHeader();
|
||||
const Ogg::PageHeader *last = file->lastPageHeader();
|
||||
|
||||
if(first && last) {
|
||||
if (first && last) {
|
||||
const long long start = first->absoluteGranularPosition();
|
||||
const long long end = last->absoluteGranularPosition();
|
||||
const long long end = last->absoluteGranularPosition();
|
||||
|
||||
if(start >= 0 && end >= 0 && d->sampleRate > 0) {
|
||||
if (start >= 0 && end >= 0 && d->sampleRate > 0) {
|
||||
const long long frameCount = end - start;
|
||||
|
||||
if(frameCount > 0) {
|
||||
if (frameCount > 0) {
|
||||
const double length = frameCount * 1000.0 / d->sampleRate;
|
||||
long fileLengthWithoutOverhead = file->length();
|
||||
// Ignore the three initial header packets, see "1.3.1. Decode Setup" in
|
||||
@@ -194,7 +178,7 @@ void Vorbis::Properties::read(File *file)
|
||||
for (unsigned int i = 0; i < 3; ++i) {
|
||||
fileLengthWithoutOverhead -= file->packet(i).size();
|
||||
}
|
||||
d->length = static_cast<int>(length + 0.5);
|
||||
d->length = static_cast<int>(length + 0.5);
|
||||
d->bitrate = static_cast<int>(fileLengthWithoutOverhead * 8.0 / length + 0.5);
|
||||
}
|
||||
}
|
||||
@@ -208,6 +192,6 @@ void Vorbis::Properties::read(File *file)
|
||||
|
||||
// Alternative to the actual average bitrate.
|
||||
|
||||
if(d->bitrate == 0 && d->bitrateNominal > 0)
|
||||
if (d->bitrate == 0 && d->bitrateNominal > 0)
|
||||
d->bitrate = static_cast<int>(d->bitrateNominal / 1000.0 + 0.5);
|
||||
}
|
||||
|
||||
95
3rdparty/taglib/ogg/vorbis/vorbisproperties.h
vendored
95
3rdparty/taglib/ogg/vorbis/vorbisproperties.h
vendored
@@ -40,35 +40,34 @@ namespace TagLib {
|
||||
*/
|
||||
|
||||
#ifdef DOXYGEN
|
||||
namespace Ogg {
|
||||
namespace Ogg {
|
||||
#endif
|
||||
|
||||
namespace Vorbis {
|
||||
namespace Vorbis {
|
||||
|
||||
class File;
|
||||
class File;
|
||||
|
||||
//! An implementation of audio property reading for Ogg Vorbis
|
||||
//! An implementation of audio property reading for Ogg Vorbis
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This reads the data from an Ogg Vorbis stream found in the AudioProperties
|
||||
* API.
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT Properties : public AudioProperties
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
class TAGLIB_EXPORT Properties : public AudioProperties {
|
||||
public:
|
||||
/*!
|
||||
* Create an instance of Vorbis::Properties with the data read from the
|
||||
* Vorbis::File \a file.
|
||||
*/
|
||||
Properties(File *file, ReadStyle style = Average);
|
||||
Properties(File *file, ReadStyle style = Average);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys this VorbisProperties instance.
|
||||
*/
|
||||
virtual ~Properties();
|
||||
virtual ~Properties();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the length of the file in seconds. The length is rounded down to
|
||||
* the nearest whole second.
|
||||
*
|
||||
@@ -76,73 +75,73 @@ namespace TagLib {
|
||||
*
|
||||
* \deprecated
|
||||
*/
|
||||
TAGLIB_DEPRECATED virtual int length() const;
|
||||
TAGLIB_DEPRECATED virtual int length() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the length of the file in seconds. The length is rounded down to
|
||||
* the nearest whole second.
|
||||
*
|
||||
* \see lengthInMilliseconds()
|
||||
*/
|
||||
// BIC: make virtual
|
||||
int lengthInSeconds() const;
|
||||
// BIC: make virtual
|
||||
int lengthInSeconds() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the length of the file in milliseconds.
|
||||
*
|
||||
* \see lengthInSeconds()
|
||||
*/
|
||||
// BIC: make virtual
|
||||
int lengthInMilliseconds() const;
|
||||
// BIC: make virtual
|
||||
int lengthInMilliseconds() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the average bit rate of the file in kb/s.
|
||||
*/
|
||||
virtual int bitrate() const;
|
||||
virtual int bitrate() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the sample rate in Hz.
|
||||
*/
|
||||
virtual int sampleRate() const;
|
||||
virtual int sampleRate() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the number of audio channels.
|
||||
*/
|
||||
virtual int channels() const;
|
||||
virtual int channels() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the Vorbis version, currently "0" (as specified by the spec).
|
||||
*/
|
||||
int vorbisVersion() const;
|
||||
int vorbisVersion() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the maximum bitrate as read from the Vorbis identification
|
||||
* header.
|
||||
*/
|
||||
int bitrateMaximum() const;
|
||||
int bitrateMaximum() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the nominal bitrate as read from the Vorbis identification
|
||||
* header.
|
||||
*/
|
||||
int bitrateNominal() const;
|
||||
int bitrateNominal() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the minimum bitrate as read from the Vorbis identification
|
||||
* header.
|
||||
*/
|
||||
int bitrateMinimum() const;
|
||||
int bitrateMinimum() const;
|
||||
|
||||
private:
|
||||
Properties(const Properties &);
|
||||
Properties &operator=(const Properties &);
|
||||
private:
|
||||
Properties(const Properties &);
|
||||
Properties &operator=(const Properties &);
|
||||
|
||||
void read(File *file);
|
||||
void read(File *file);
|
||||
|
||||
class PropertiesPrivate;
|
||||
PropertiesPrivate *d;
|
||||
};
|
||||
}
|
||||
class PropertiesPrivate;
|
||||
PropertiesPrivate *d;
|
||||
};
|
||||
} // namespace Vorbis
|
||||
|
||||
/*
|
||||
* To keep compatibility with the current version put Vorbis in the Ogg namespace
|
||||
@@ -151,12 +150,16 @@ namespace TagLib {
|
||||
*/
|
||||
|
||||
#ifdef DOXYGEN
|
||||
}
|
||||
}
|
||||
#else
|
||||
namespace Ogg { namespace Vorbis { typedef Strawberry_TagLib::TagLib::AudioProperties AudioProperties; } }
|
||||
namespace Ogg {
|
||||
namespace Vorbis {
|
||||
typedef Strawberry_TagLib::TagLib::AudioProperties AudioProperties;
|
||||
}
|
||||
} // namespace Ogg
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
|
||||
#endif
|
||||
|
||||
243
3rdparty/taglib/ogg/xiphcomment.cpp
vendored
243
3rdparty/taglib/ogg/xiphcomment.cpp
vendored
@@ -32,21 +32,18 @@
|
||||
|
||||
using namespace Strawberry_TagLib::TagLib;
|
||||
|
||||
namespace
|
||||
{
|
||||
typedef Ogg::FieldListMap::Iterator FieldIterator;
|
||||
typedef Ogg::FieldListMap::ConstIterator FieldConstIterator;
|
||||
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 *> PictureList;
|
||||
typedef PictureList::Iterator PictureIterator;
|
||||
typedef PictureList::Iterator PictureConstIterator;
|
||||
} // namespace
|
||||
|
||||
class Ogg::XiphComment::XiphCommentPrivate
|
||||
{
|
||||
public:
|
||||
XiphCommentPrivate()
|
||||
{
|
||||
class Ogg::XiphComment::XiphCommentPrivate {
|
||||
public:
|
||||
XiphCommentPrivate() {
|
||||
pictureList.setAutoDelete(true);
|
||||
}
|
||||
|
||||
@@ -60,53 +57,44 @@ public:
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Ogg::XiphComment::XiphComment() :
|
||||
Strawberry_TagLib::TagLib::Tag(),
|
||||
d(new XiphCommentPrivate())
|
||||
{
|
||||
Ogg::XiphComment::XiphComment() : Strawberry_TagLib::TagLib::Tag(),
|
||||
d(new XiphCommentPrivate()) {
|
||||
}
|
||||
|
||||
Ogg::XiphComment::XiphComment(const ByteVector &data) :
|
||||
Strawberry_TagLib::TagLib::Tag(),
|
||||
d(new XiphCommentPrivate())
|
||||
{
|
||||
Ogg::XiphComment::XiphComment(const ByteVector &data) : Strawberry_TagLib::TagLib::Tag(),
|
||||
d(new XiphCommentPrivate()) {
|
||||
parse(data);
|
||||
}
|
||||
|
||||
Ogg::XiphComment::~XiphComment()
|
||||
{
|
||||
Ogg::XiphComment::~XiphComment() {
|
||||
delete d;
|
||||
}
|
||||
|
||||
String Ogg::XiphComment::title() const
|
||||
{
|
||||
if(d->fieldListMap["TITLE"].isEmpty())
|
||||
String Ogg::XiphComment::title() const {
|
||||
if (d->fieldListMap["TITLE"].isEmpty())
|
||||
return String();
|
||||
return d->fieldListMap["TITLE"].toString();
|
||||
}
|
||||
|
||||
String Ogg::XiphComment::artist() const
|
||||
{
|
||||
if(d->fieldListMap["ARTIST"].isEmpty())
|
||||
String Ogg::XiphComment::artist() const {
|
||||
if (d->fieldListMap["ARTIST"].isEmpty())
|
||||
return String();
|
||||
return d->fieldListMap["ARTIST"].toString();
|
||||
}
|
||||
|
||||
String Ogg::XiphComment::album() const
|
||||
{
|
||||
if(d->fieldListMap["ALBUM"].isEmpty())
|
||||
String Ogg::XiphComment::album() const {
|
||||
if (d->fieldListMap["ALBUM"].isEmpty())
|
||||
return String();
|
||||
return d->fieldListMap["ALBUM"].toString();
|
||||
}
|
||||
|
||||
String Ogg::XiphComment::comment() const
|
||||
{
|
||||
if(!d->fieldListMap["DESCRIPTION"].isEmpty()) {
|
||||
String Ogg::XiphComment::comment() const {
|
||||
if (!d->fieldListMap["DESCRIPTION"].isEmpty()) {
|
||||
d->commentField = "DESCRIPTION";
|
||||
return d->fieldListMap["DESCRIPTION"].toString();
|
||||
}
|
||||
|
||||
if(!d->fieldListMap["COMMENT"].isEmpty()) {
|
||||
if (!d->fieldListMap["COMMENT"].isEmpty()) {
|
||||
d->commentField = "COMMENT";
|
||||
return d->fieldListMap["COMMENT"].toString();
|
||||
}
|
||||
@@ -114,50 +102,43 @@ String Ogg::XiphComment::comment() const
|
||||
return String();
|
||||
}
|
||||
|
||||
String Ogg::XiphComment::genre() const
|
||||
{
|
||||
if(d->fieldListMap["GENRE"].isEmpty())
|
||||
String Ogg::XiphComment::genre() const {
|
||||
if (d->fieldListMap["GENRE"].isEmpty())
|
||||
return String();
|
||||
return d->fieldListMap["GENRE"].toString();
|
||||
}
|
||||
|
||||
unsigned int Ogg::XiphComment::year() const
|
||||
{
|
||||
if(!d->fieldListMap["DATE"].isEmpty())
|
||||
unsigned int Ogg::XiphComment::year() const {
|
||||
if (!d->fieldListMap["DATE"].isEmpty())
|
||||
return d->fieldListMap["DATE"].front().toInt();
|
||||
if(!d->fieldListMap["YEAR"].isEmpty())
|
||||
if (!d->fieldListMap["YEAR"].isEmpty())
|
||||
return d->fieldListMap["YEAR"].front().toInt();
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned int Ogg::XiphComment::track() const
|
||||
{
|
||||
if(!d->fieldListMap["TRACKNUMBER"].isEmpty())
|
||||
unsigned int Ogg::XiphComment::track() const {
|
||||
if (!d->fieldListMap["TRACKNUMBER"].isEmpty())
|
||||
return d->fieldListMap["TRACKNUMBER"].front().toInt();
|
||||
if(!d->fieldListMap["TRACKNUM"].isEmpty())
|
||||
if (!d->fieldListMap["TRACKNUM"].isEmpty())
|
||||
return d->fieldListMap["TRACKNUM"].front().toInt();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Ogg::XiphComment::setTitle(const String &s)
|
||||
{
|
||||
void Ogg::XiphComment::setTitle(const String &s) {
|
||||
addField("TITLE", s);
|
||||
}
|
||||
|
||||
void Ogg::XiphComment::setArtist(const String &s)
|
||||
{
|
||||
void Ogg::XiphComment::setArtist(const String &s) {
|
||||
addField("ARTIST", s);
|
||||
}
|
||||
|
||||
void Ogg::XiphComment::setAlbum(const String &s)
|
||||
{
|
||||
void Ogg::XiphComment::setAlbum(const String &s) {
|
||||
addField("ALBUM", s);
|
||||
}
|
||||
|
||||
void Ogg::XiphComment::setComment(const String &s)
|
||||
{
|
||||
if(d->commentField.isEmpty()) {
|
||||
if(!d->fieldListMap["DESCRIPTION"].isEmpty())
|
||||
void Ogg::XiphComment::setComment(const String &s) {
|
||||
if (d->commentField.isEmpty()) {
|
||||
if (!d->fieldListMap["DESCRIPTION"].isEmpty())
|
||||
d->commentField = "DESCRIPTION";
|
||||
else
|
||||
d->commentField = "COMMENT";
|
||||
@@ -166,44 +147,39 @@ void Ogg::XiphComment::setComment(const String &s)
|
||||
addField(d->commentField, s);
|
||||
}
|
||||
|
||||
void Ogg::XiphComment::setGenre(const String &s)
|
||||
{
|
||||
void Ogg::XiphComment::setGenre(const String &s) {
|
||||
addField("GENRE", s);
|
||||
}
|
||||
|
||||
void Ogg::XiphComment::setYear(unsigned int i)
|
||||
{
|
||||
void Ogg::XiphComment::setYear(unsigned int i) {
|
||||
removeFields("YEAR");
|
||||
if(i == 0)
|
||||
if (i == 0)
|
||||
removeFields("DATE");
|
||||
else
|
||||
addField("DATE", String::number(i));
|
||||
}
|
||||
|
||||
void Ogg::XiphComment::setTrack(unsigned int i)
|
||||
{
|
||||
void Ogg::XiphComment::setTrack(unsigned int i) {
|
||||
removeFields("TRACKNUM");
|
||||
if(i == 0)
|
||||
if (i == 0)
|
||||
removeFields("TRACKNUMBER");
|
||||
else
|
||||
addField("TRACKNUMBER", String::number(i));
|
||||
}
|
||||
|
||||
bool Ogg::XiphComment::isEmpty() const
|
||||
{
|
||||
for(FieldConstIterator it = d->fieldListMap.begin(); it != d->fieldListMap.end(); ++it) {
|
||||
if(!(*it).second.isEmpty())
|
||||
bool Ogg::XiphComment::isEmpty() const {
|
||||
for (FieldConstIterator it = d->fieldListMap.begin(); it != d->fieldListMap.end(); ++it) {
|
||||
if (!(*it).second.isEmpty())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned int Ogg::XiphComment::fieldCount() const
|
||||
{
|
||||
unsigned int Ogg::XiphComment::fieldCount() const {
|
||||
unsigned int count = 0;
|
||||
|
||||
for(FieldConstIterator it = d->fieldListMap.begin(); it != d->fieldListMap.end(); ++it)
|
||||
for (FieldConstIterator it = d->fieldListMap.begin(); it != d->fieldListMap.end(); ++it)
|
||||
count += (*it).second.size();
|
||||
|
||||
count += d->pictureList.size();
|
||||
@@ -211,37 +187,33 @@ unsigned int Ogg::XiphComment::fieldCount() const
|
||||
return count;
|
||||
}
|
||||
|
||||
const Ogg::FieldListMap &Ogg::XiphComment::fieldListMap() const
|
||||
{
|
||||
const Ogg::FieldListMap &Ogg::XiphComment::fieldListMap() const {
|
||||
return d->fieldListMap;
|
||||
}
|
||||
|
||||
PropertyMap Ogg::XiphComment::properties() const
|
||||
{
|
||||
PropertyMap Ogg::XiphComment::properties() const {
|
||||
return d->fieldListMap;
|
||||
}
|
||||
|
||||
PropertyMap Ogg::XiphComment::setProperties(const PropertyMap &properties)
|
||||
{
|
||||
PropertyMap Ogg::XiphComment::setProperties(const PropertyMap &properties) {
|
||||
// check which keys are to be deleted
|
||||
StringList toRemove;
|
||||
for(FieldConstIterator it = d->fieldListMap.begin(); it != d->fieldListMap.end(); ++it)
|
||||
for (FieldConstIterator it = d->fieldListMap.begin(); it != d->fieldListMap.end(); ++it)
|
||||
if (!properties.contains(it->first))
|
||||
toRemove.append(it->first);
|
||||
|
||||
for(StringList::ConstIterator it = toRemove.begin(); it != toRemove.end(); ++it)
|
||||
removeFields(*it);
|
||||
for (StringList::ConstIterator it = toRemove.begin(); it != toRemove.end(); ++it)
|
||||
removeFields(*it);
|
||||
|
||||
// now go through keys in \a properties and check that the values match those in the xiph comment
|
||||
PropertyMap invalid;
|
||||
PropertyMap::ConstIterator it = properties.begin();
|
||||
for(; it != properties.end(); ++it)
|
||||
{
|
||||
if(!checkKey(it->first))
|
||||
for (; it != properties.end(); ++it) {
|
||||
if (!checkKey(it->first))
|
||||
invalid.insert(it->first, it->second);
|
||||
else if(!d->fieldListMap.contains(it->first) || !(it->second == d->fieldListMap[it->first])) {
|
||||
else if (!d->fieldListMap.contains(it->first) || !(it->second == d->fieldListMap[it->first])) {
|
||||
const StringList &sl = it->second;
|
||||
if(sl.isEmpty())
|
||||
if (sl.isEmpty())
|
||||
// zero size string list -> remove the tag with all values
|
||||
removeFields(it->first);
|
||||
else {
|
||||
@@ -249,7 +221,7 @@ PropertyMap Ogg::XiphComment::setProperties(const PropertyMap &properties)
|
||||
StringList::ConstIterator valueIterator = sl.begin();
|
||||
addField(it->first, *valueIterator, true);
|
||||
++valueIterator;
|
||||
for(; valueIterator != sl.end(); ++valueIterator)
|
||||
for (; valueIterator != sl.end(); ++valueIterator)
|
||||
addField(it->first, *valueIterator, false);
|
||||
}
|
||||
}
|
||||
@@ -257,108 +229,94 @@ PropertyMap Ogg::XiphComment::setProperties(const PropertyMap &properties)
|
||||
return invalid;
|
||||
}
|
||||
|
||||
bool Ogg::XiphComment::checkKey(const String &key)
|
||||
{
|
||||
if(key.size() < 1)
|
||||
bool Ogg::XiphComment::checkKey(const String &key) {
|
||||
if (key.size() < 1)
|
||||
return false;
|
||||
|
||||
// A key may consist of ASCII 0x20 through 0x7D, 0x3D ('=') excluded.
|
||||
|
||||
for(String::ConstIterator it = key.begin(); it != key.end(); it++) {
|
||||
if(*it < 0x20 || *it > 0x7D || *it == 0x3D)
|
||||
return false;
|
||||
for (String::ConstIterator it = key.begin(); it != key.end(); it++) {
|
||||
if (*it < 0x20 || *it > 0x7D || *it == 0x3D)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
String Ogg::XiphComment::vendorID() const
|
||||
{
|
||||
String Ogg::XiphComment::vendorID() const {
|
||||
return d->vendorID;
|
||||
}
|
||||
|
||||
void Ogg::XiphComment::addField(const String &key, const String &value, bool replace)
|
||||
{
|
||||
if(!checkKey(key)) {
|
||||
void Ogg::XiphComment::addField(const String &key, const String &value, bool replace) {
|
||||
if (!checkKey(key)) {
|
||||
debug("Ogg::XiphComment::addField() - Invalid key. Field not added.");
|
||||
return;
|
||||
}
|
||||
|
||||
const String upperKey = key.upper();
|
||||
|
||||
if(replace)
|
||||
if (replace)
|
||||
removeFields(upperKey);
|
||||
|
||||
if(!key.isEmpty() && !value.isEmpty())
|
||||
if (!key.isEmpty() && !value.isEmpty())
|
||||
d->fieldListMap[upperKey].append(value);
|
||||
}
|
||||
|
||||
void Ogg::XiphComment::removeField(const String &key, const String &value)
|
||||
{
|
||||
if(!value.isNull())
|
||||
void Ogg::XiphComment::removeField(const String &key, const String &value) {
|
||||
if (!value.isNull())
|
||||
removeFields(key, value);
|
||||
else
|
||||
removeFields(key);
|
||||
}
|
||||
|
||||
void Ogg::XiphComment::removeFields(const String &key)
|
||||
{
|
||||
void Ogg::XiphComment::removeFields(const String &key) {
|
||||
d->fieldListMap.erase(key.upper());
|
||||
}
|
||||
|
||||
void Ogg::XiphComment::removeFields(const String &key, const String &value)
|
||||
{
|
||||
void Ogg::XiphComment::removeFields(const String &key, const String &value) {
|
||||
StringList &fields = d->fieldListMap[key.upper()];
|
||||
for(StringList::Iterator it = fields.begin(); it != fields.end(); ) {
|
||||
if(*it == value)
|
||||
for (StringList::Iterator it = fields.begin(); it != fields.end();) {
|
||||
if (*it == value)
|
||||
it = fields.erase(it);
|
||||
else
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
void Ogg::XiphComment::removeAllFields()
|
||||
{
|
||||
void Ogg::XiphComment::removeAllFields() {
|
||||
d->fieldListMap.clear();
|
||||
}
|
||||
|
||||
bool Ogg::XiphComment::contains(const String &key) const
|
||||
{
|
||||
bool Ogg::XiphComment::contains(const String &key) const {
|
||||
return !d->fieldListMap[key.upper()].isEmpty();
|
||||
}
|
||||
|
||||
void Ogg::XiphComment::removePicture(FLAC::Picture *picture, bool del)
|
||||
{
|
||||
void Ogg::XiphComment::removePicture(FLAC::Picture *picture, bool del) {
|
||||
PictureIterator it = d->pictureList.find(picture);
|
||||
if(it != d->pictureList.end())
|
||||
if (it != d->pictureList.end())
|
||||
d->pictureList.erase(it);
|
||||
|
||||
if(del)
|
||||
if (del)
|
||||
delete picture;
|
||||
}
|
||||
|
||||
void Ogg::XiphComment::removeAllPictures()
|
||||
{
|
||||
void Ogg::XiphComment::removeAllPictures() {
|
||||
d->pictureList.clear();
|
||||
}
|
||||
|
||||
void Ogg::XiphComment::addPicture(FLAC::Picture * picture)
|
||||
{
|
||||
void Ogg::XiphComment::addPicture(FLAC::Picture *picture) {
|
||||
d->pictureList.append(picture);
|
||||
}
|
||||
|
||||
List<FLAC::Picture *> Ogg::XiphComment::pictureList()
|
||||
{
|
||||
List<FLAC::Picture *> Ogg::XiphComment::pictureList() {
|
||||
return d->pictureList;
|
||||
}
|
||||
|
||||
ByteVector Ogg::XiphComment::render() const
|
||||
{
|
||||
ByteVector Ogg::XiphComment::render() const {
|
||||
return render(true);
|
||||
}
|
||||
|
||||
ByteVector Ogg::XiphComment::render(bool addFramingBit) const
|
||||
{
|
||||
ByteVector Ogg::XiphComment::render(bool addFramingBit) const {
|
||||
ByteVector data;
|
||||
|
||||
// Add the vendor ID length and the vendor ID. It's important to use the
|
||||
@@ -379,7 +337,7 @@ ByteVector Ogg::XiphComment::render(bool addFramingBit) const
|
||||
// std::pair<String, StringList> where the first String is the field name and
|
||||
// the StringList is the values associated with that field.
|
||||
|
||||
for(FieldListMap::ConstIterator it = d->fieldListMap.begin() ; it != d->fieldListMap.end() ; ++it) {
|
||||
for (FieldListMap::ConstIterator it = d->fieldListMap.begin(); it != d->fieldListMap.end(); ++it) {
|
||||
|
||||
// And now iterate over the values of the current list.
|
||||
|
||||
@@ -387,7 +345,7 @@ ByteVector Ogg::XiphComment::render(bool addFramingBit) const
|
||||
StringList values = (*it).second;
|
||||
|
||||
StringList::ConstIterator valuesIt = values.begin();
|
||||
for(; valuesIt != values.end(); ++valuesIt) {
|
||||
for (; valuesIt != values.end(); ++valuesIt) {
|
||||
ByteVector fieldData = fieldName.data(String::UTF8);
|
||||
fieldData.append('=');
|
||||
fieldData.append((*valuesIt).data(String::UTF8));
|
||||
@@ -406,7 +364,7 @@ ByteVector Ogg::XiphComment::render(bool addFramingBit) const
|
||||
|
||||
// Append the "framing bit".
|
||||
|
||||
if(addFramingBit)
|
||||
if (addFramingBit)
|
||||
data.append(char(1));
|
||||
|
||||
return data;
|
||||
@@ -416,8 +374,7 @@ ByteVector Ogg::XiphComment::render(bool addFramingBit) const
|
||||
// protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Ogg::XiphComment::parse(const ByteVector &data)
|
||||
{
|
||||
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.
|
||||
|
||||
@@ -434,11 +391,11 @@ void Ogg::XiphComment::parse(const ByteVector &data)
|
||||
const unsigned int commentFields = data.toUInt(pos, false);
|
||||
pos += 4;
|
||||
|
||||
if(commentFields > (data.size() - 8) / 4) {
|
||||
if (commentFields > (data.size() - 8) / 4) {
|
||||
return;
|
||||
}
|
||||
|
||||
for(unsigned int i = 0; i < commentFields; i++) {
|
||||
for (unsigned int i = 0; i < commentFields; i++) {
|
||||
|
||||
// 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.
|
||||
@@ -451,13 +408,13 @@ void Ogg::XiphComment::parse(const ByteVector &data)
|
||||
|
||||
// Don't go past data end
|
||||
|
||||
if(pos > data.size())
|
||||
if (pos > data.size())
|
||||
break;
|
||||
|
||||
// Check for field separator
|
||||
|
||||
const int sep = entry.find('=');
|
||||
if(sep < 1) {
|
||||
if (sep < 1) {
|
||||
debug("Ogg::XiphComment::parse() - Discarding a field. Separator not found.");
|
||||
continue;
|
||||
}
|
||||
@@ -465,27 +422,27 @@ void Ogg::XiphComment::parse(const ByteVector &data)
|
||||
// Parse the key
|
||||
|
||||
const String key = String(entry.mid(0, sep), String::UTF8).upper();
|
||||
if(!checkKey(key)) {
|
||||
if (!checkKey(key)) {
|
||||
debug("Ogg::XiphComment::parse() - Discarding a field. Invalid key.");
|
||||
continue;
|
||||
}
|
||||
|
||||
if(key == "METADATA_BLOCK_PICTURE" || key == "COVERART") {
|
||||
if (key == "METADATA_BLOCK_PICTURE" || key == "COVERART") {
|
||||
|
||||
// Handle Pictures separately
|
||||
|
||||
const ByteVector picturedata = ByteVector::fromBase64(entry.mid(sep + 1));
|
||||
if(picturedata.isEmpty()) {
|
||||
if (picturedata.isEmpty()) {
|
||||
debug("Ogg::XiphComment::parse() - Discarding a field. Invalid base64 data");
|
||||
continue;
|
||||
}
|
||||
|
||||
if(key[0] == L'M') {
|
||||
if (key[0] == L'M') {
|
||||
|
||||
// Decode FLAC Picture
|
||||
|
||||
FLAC::Picture * picture = new FLAC::Picture();
|
||||
if(picture->parse(picturedata)) {
|
||||
FLAC::Picture *picture = new FLAC::Picture();
|
||||
if (picture->parse(picturedata)) {
|
||||
d->pictureList.append(picture);
|
||||
}
|
||||
else {
|
||||
@@ -497,7 +454,7 @@ void Ogg::XiphComment::parse(const ByteVector &data)
|
||||
|
||||
// Assume it's some type of image file
|
||||
|
||||
FLAC::Picture * picture = new FLAC::Picture();
|
||||
FLAC::Picture *picture = new FLAC::Picture();
|
||||
picture->setData(picturedata);
|
||||
picture->setMimeType("image/");
|
||||
picture->setType(FLAC::Picture::Other);
|
||||
|
||||
155
3rdparty/taglib/ogg/xiphcomment.h
vendored
155
3rdparty/taglib/ogg/xiphcomment.h
vendored
@@ -38,19 +38,19 @@
|
||||
namespace Strawberry_TagLib {
|
||||
namespace TagLib {
|
||||
|
||||
namespace Ogg {
|
||||
namespace Ogg {
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* A mapping between a list of field names, or keys, and a list of values
|
||||
* associated with that field.
|
||||
*
|
||||
* \see XiphComment::fieldListMap()
|
||||
*/
|
||||
typedef Map<String, StringList> FieldListMap;
|
||||
typedef Map<String, StringList> FieldListMap;
|
||||
|
||||
//! Ogg Vorbis comment implementation
|
||||
//! Ogg Vorbis comment implementation
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* This class is an implementation of the Ogg Vorbis comment specification,
|
||||
* to be found in section 5 of the Ogg Vorbis specification. Because this
|
||||
* format is also used in other (currently unsupported) Xiph.org formats, it
|
||||
@@ -63,48 +63,47 @@ namespace TagLib {
|
||||
* \see fieldListMap()
|
||||
*/
|
||||
|
||||
class TAGLIB_EXPORT XiphComment : public Strawberry_TagLib::TagLib::Tag
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
class TAGLIB_EXPORT XiphComment : public Strawberry_TagLib::TagLib::Tag {
|
||||
public:
|
||||
/*!
|
||||
* Constructs an empty Vorbis comment.
|
||||
*/
|
||||
XiphComment();
|
||||
XiphComment();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Constructs a Vorbis comment from \a data.
|
||||
*/
|
||||
XiphComment(const ByteVector &data);
|
||||
XiphComment(const ByteVector &data);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Destroys this instance of the XiphComment.
|
||||
*/
|
||||
virtual ~XiphComment();
|
||||
virtual ~XiphComment();
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
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);
|
||||
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);
|
||||
|
||||
virtual bool isEmpty() const;
|
||||
virtual bool isEmpty() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the number of fields present in the comment.
|
||||
*/
|
||||
unsigned int fieldCount() const;
|
||||
unsigned int fieldCount() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a reference to the map of field lists. Because Xiph comments
|
||||
* support multiple fields with the same key, a pure Map would not work.
|
||||
* As such this is a Map of string lists, keyed on the comment field name.
|
||||
@@ -140,138 +139,138 @@ namespace TagLib {
|
||||
* \warning You should not modify this data structure directly, instead
|
||||
* use addField() and removeField().
|
||||
*/
|
||||
const FieldListMap &fieldListMap() const;
|
||||
const FieldListMap &fieldListMap() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Implements the unified property interface -- export function.
|
||||
* The result is a one-to-one match of the Xiph comment, 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;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Implements the unified property interface -- import function.
|
||||
* The tags from the given map will be stored one-to-one in the file,
|
||||
* 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 &);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Check if the given String is a valid Xiph comment key.
|
||||
*/
|
||||
static bool checkKey(const String&);
|
||||
static bool checkKey(const String &);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns the vendor ID of the Ogg Vorbis encoder. libvorbis 1.0 as the
|
||||
* most common case always returns "Xiph.Org libVorbis I 20020717".
|
||||
*/
|
||||
String vendorID() const;
|
||||
String vendorID() const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Add the field specified by \a key with the data \a value. If \a replace
|
||||
* is true, then all of the other fields with the same key will be removed
|
||||
* first.
|
||||
*
|
||||
* If the field value is empty, the field will be removed.
|
||||
*/
|
||||
void addField(const String &key, const String &value, bool replace = true);
|
||||
void addField(const String &key, const String &value, bool replace = true);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Remove the field specified by \a key with the data \a value. If
|
||||
* \a value is null, all of the fields with the given key will be removed.
|
||||
*
|
||||
* \deprecated Using this method may lead to a linkage error.
|
||||
*/
|
||||
// BIC: remove and merge with below
|
||||
TAGLIB_DEPRECATED void removeField(const String &key, const String &value = String());
|
||||
// BIC: remove and merge with below
|
||||
TAGLIB_DEPRECATED void removeField(const String &key, const String &value = String());
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Remove all the fields specified by \a key.
|
||||
*
|
||||
* \see removeAllFields()
|
||||
*/
|
||||
void removeFields(const String &key);
|
||||
void removeFields(const String &key);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Remove all the fields specified by \a key with the data \a value.
|
||||
*
|
||||
* \see removeAllFields()
|
||||
*/
|
||||
void removeFields(const String &key, const String &value);
|
||||
void removeFields(const String &key, const String &value);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Remove all the fields in the comment.
|
||||
*
|
||||
* \see removeFields()
|
||||
*/
|
||||
void removeAllFields();
|
||||
void removeAllFields();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns true if the field is contained within the comment.
|
||||
*
|
||||
* \note This is safer than checking for membership in the FieldListMap.
|
||||
*/
|
||||
bool contains(const String &key) const;
|
||||
bool contains(const String &key) const;
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Renders the comment to a ByteVector suitable for inserting into a file.
|
||||
*/
|
||||
ByteVector render() const; // BIC: remove and merge with below
|
||||
ByteVector render() const; // BIC: remove and merge with below
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Renders the comment to a ByteVector suitable for inserting into a file.
|
||||
*
|
||||
* If \a addFramingBit is true the standard Vorbis comment framing bit will
|
||||
* be appended. However some formats (notably FLAC) do not work with this
|
||||
* in place.
|
||||
*/
|
||||
ByteVector render(bool addFramingBit) const;
|
||||
ByteVector render(bool addFramingBit) const;
|
||||
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Returns a list of pictures attached to the xiph comment.
|
||||
*/
|
||||
List<FLAC::Picture *> pictureList();
|
||||
List<FLAC::Picture *> pictureList();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Removes an picture. If \a del is true the picture's memory
|
||||
* will be freed; if it is false, it must be deleted by the user.
|
||||
*/
|
||||
void removePicture(FLAC::Picture *picture, bool del = true);
|
||||
void removePicture(FLAC::Picture *picture, bool del = true);
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Remove all pictures.
|
||||
*/
|
||||
void removeAllPictures();
|
||||
void removeAllPictures();
|
||||
|
||||
/*!
|
||||
/*!
|
||||
* Add a new picture to the comment block. The comment block takes ownership of the
|
||||
* picture and will handle freeing its memory.
|
||||
*
|
||||
* \note The file will be saved only after calling save().
|
||||
*/
|
||||
void addPicture(FLAC::Picture *picture);
|
||||
void addPicture(FLAC::Picture *picture);
|
||||
|
||||
protected:
|
||||
/*!
|
||||
protected:
|
||||
/*!
|
||||
* Reads the tag from the file specified in the constructor and fills the
|
||||
* FieldListMap.
|
||||
*/
|
||||
void parse(const ByteVector &data);
|
||||
void parse(const ByteVector &data);
|
||||
|
||||
private:
|
||||
XiphComment(const XiphComment &);
|
||||
XiphComment &operator=(const XiphComment &);
|
||||
private:
|
||||
XiphComment(const XiphComment &);
|
||||
XiphComment &operator=(const XiphComment &);
|
||||
|
||||
class XiphCommentPrivate;
|
||||
XiphCommentPrivate *d;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
class XiphCommentPrivate;
|
||||
XiphCommentPrivate *d;
|
||||
};
|
||||
} // namespace Ogg
|
||||
} // namespace TagLib
|
||||
} // namespace Strawberry_TagLib
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user