Additional manual formatting to taglib sources

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

View File

@@ -37,8 +37,8 @@ using Strawberry_TagLib::TagLib::FLAC::Properties;
class Ogg::FLAC::File::FilePrivate {
public:
FilePrivate() : comment(0),
properties(0),
FilePrivate() : comment(nullptr),
properties(nullptr),
streamStart(0),
streamLength(0),
scanned(false),
@@ -78,18 +78,18 @@ bool Ogg::FLAC::File::isSupported(IOStream *stream) {
// public members
////////////////////////////////////////////////////////////////////////////////
Ogg::FLAC::File::File(FileName file, bool readProperties,
Properties::ReadStyle propertiesStyle) : Ogg::File(file),
d(new FilePrivate()) {
Ogg::FLAC::File::File(FileName file, bool readProperties, 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()) {
Ogg::FLAC::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle propertiesStyle) : Ogg::File(stream), d(new FilePrivate()) {
if (isOpen())
read(readProperties, propertiesStyle);
}
Ogg::FLAC::File::~File() {
@@ -114,6 +114,7 @@ Properties *Ogg::FLAC::File::audioProperties() const {
bool Ogg::FLAC::File::save() {
d->xiphCommentData = d->comment->render(false);
// Create FLAC metadata-block:
@@ -136,6 +137,7 @@ bool Ogg::FLAC::File::save() {
setPacket(d->commentPacket, v);
return Ogg::File::save();
}
bool Ogg::FLAC::File::hasXiphComment() const {
@@ -147,6 +149,7 @@ bool Ogg::FLAC::File::hasXiphComment() const {
////////////////////////////////////////////////////////////////////////////////
void Ogg::FLAC::File::read(bool readProperties, Properties::ReadStyle propertiesStyle) {
// Sanity: Check if we really have an Ogg/FLAC file
/*
@@ -176,6 +179,7 @@ void Ogg::FLAC::File::read(bool readProperties, Properties::ReadStyle properties
if (readProperties)
d->properties = new Properties(streamInfoData(), streamLength(), propertiesStyle);
}
ByteVector Ogg::FLAC::File::streamInfoData() {
@@ -194,6 +198,7 @@ long Ogg::FLAC::File::streamLength() {
}
void Ogg::FLAC::File::scan() {
// Scan the metadata pages
if (d->scanned)
@@ -298,4 +303,5 @@ void Ogg::FLAC::File::scan() {
d->streamLength = File::length() - d->streamStart;
d->scanned = true;
}

View File

@@ -55,100 +55,93 @@ using Strawberry_TagLib::TagLib::FLAC::Properties;
//! 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.
*/
* 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:
/*!
* 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);
* 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);
/*!
* Constructs an Ogg/FLAC file from \a stream. If \a readProperties is true
* the file's audio properties will also be read.
*
* \note TagLib will *not* take ownership of the stream, the caller is
* responsible for deleting it after the File object.
*
* \note In the current implementation, \a propertiesStyle is ignored.
*/
File(IOStream *stream, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
* Constructs an Ogg/FLAC file from \a stream.
* If \a readProperties is true the file's audio properties will also be read.
*
* \note TagLib will *not* take ownership of the stream, the caller is responsible for deleting it after the File object.
*
* \note In the current implementation, \a propertiesStyle is ignored.
*/
File(IOStream *stream, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average);
/*!
* Destroys this instance of the File.
*/
* Destroys this instance of the File.
*/
virtual ~File();
/*!
* Returns the Tag for this file. This will always be a XiphComment.
*
* \note This always returns a valid pointer regardless of whether or not
* the file on disk has a XiphComment. Use hasXiphComment() to check if
* the file on disk actually has a XiphComment.
*
* \note The Tag <b>is still</b> owned by the FLAC::File and should not be
* deleted by the user. It will be deleted when the file (object) is
* destroyed.
*
* \see hasXiphComment()
*/
* Returns the Tag for this file. This will always be a XiphComment.
*
* \note This always returns a valid pointer regardless of whether or not the file on disk has a XiphComment.
* Use hasXiphComment() to check if the file on disk actually has a XiphComment.
*
* \note The Tag <b>is still</b> owned by the FLAC::File and should not be deleted by the user.
* It will be deleted when the file (object) is destroyed.
*
* \see hasXiphComment()
*/
virtual XiphComment *tag() const;
/*!
* Returns the FLAC::Properties for this file. If no audio properties
* were read then this will return a null pointer.
*/
* Returns the FLAC::Properties for this file.
* If no audio properties were read then this will return a null pointer.
*/
virtual Properties *audioProperties() const;
/*!
* Implements the unified property interface -- export function.
* This forwards directly to XiphComment::properties().
*/
* Implements the unified property interface -- export function.
* This forwards directly to XiphComment::properties().
*/
PropertyMap properties() const;
/*!
* Implements the unified tag dictionary interface -- import function.
* Like properties(), this is a forwarder to the file's XiphComment.
*/
* Implements the unified tag dictionary interface -- import function.
* Like properties(), this is a forwarder to the file's XiphComment.
*/
PropertyMap setProperties(const PropertyMap &);
/*!
* Save the file. This will primarily save and update the XiphComment.
* Returns true if the save is successful.
*/
* Save the file. This will primarily save and update the XiphComment.
* Returns true if the save is successful.
*/
virtual bool save();
/*!
* Returns the length of the audio-stream, used by FLAC::Properties for
* calculating the bitrate.
*/
* Returns the length of the audio-stream, used by FLAC::Properties for calculating the bitrate.
*/
long streamLength();
/*!
* Returns whether or not the file on disk actually has a XiphComment.
*
* \see tag()
*/
* Returns whether or not the file on disk actually has a XiphComment.
*
* \see tag()
*/
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.
*/
* Check if the given \a stream can be opened as an Ogg FLAC file.
*
* \note This method is designed to do a quick check. The result may not necessarily be correct.
*/
static bool isSupported(IOStream *stream);
private:
@@ -163,6 +156,7 @@ class TAGLIB_EXPORT File : public Ogg::File {
class FilePrivate;
FilePrivate *d;
};
} // namespace FLAC
} // namespace Ogg
} // namespace TagLib

View File

@@ -37,18 +37,18 @@ 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
class Ogg::File::FilePrivate {
public:
FilePrivate() : streamSerialNumber(0),
firstPageHeader(0),
lastPageHeader(0) {
FilePrivate() : streamSerialNumber(0), firstPageHeader(nullptr), lastPageHeader(nullptr) {
pages.setAutoDelete(true);
}
@@ -58,7 +58,7 @@ class Ogg::File::FilePrivate {
}
unsigned int streamSerialNumber;
List<Page *> pages;
List<Page*> pages;
PageHeader *firstPageHeader;
PageHeader *lastPageHeader;
Map<unsigned int, ByteVector> dirtyPackets;
@@ -73,6 +73,7 @@ Ogg::File::~File() {
}
ByteVector Ogg::File::packet(unsigned int i) {
// Check to see if we're called setPacket() for this packet since the last
// save:
@@ -108,42 +109,50 @@ ByteVector Ogg::File::packet(unsigned int i) {
}
return packet;
}
void Ogg::File::setPacket(unsigned int i, const ByteVector &p) {
if (!readPages(i)) {
debug("Ogg::File::setPacket() -- Could not set the requested packet.");
return;
}
d->dirtyPackets[i] = p;
}
const Ogg::PageHeader *Ogg::File::firstPageHeader() {
if (!d->firstPageHeader) {
const long firstPageHeaderOffset = find("OggS");
if (firstPageHeaderOffset < 0)
return 0;
return nullptr;
d->firstPageHeader = new PageHeader(this, firstPageHeaderOffset);
}
return d->firstPageHeader->isValid() ? d->firstPageHeader : 0;
return d->firstPageHeader->isValid() ? d->firstPageHeader : nullptr;
}
const Ogg::PageHeader *Ogg::File::lastPageHeader() {
if (!d->lastPageHeader) {
const long lastPageHeaderOffset = rfind("OggS");
if (lastPageHeaderOffset < 0)
return 0;
return nullptr;
d->lastPageHeader = new PageHeader(this, lastPageHeaderOffset);
}
return d->lastPageHeader->isValid() ? d->lastPageHeader : 0;
return d->lastPageHeader->isValid() ? d->lastPageHeader : nullptr;
}
bool Ogg::File::save() {
if (readOnly()) {
debug("Ogg::File::save() - Cannot save to a read only file.");
return false;
@@ -156,25 +165,23 @@ bool Ogg::File::save() {
d->dirtyPackets.clear();
return true;
}
////////////////////////////////////////////////////////////////////////////////
// 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) {
unsigned int packetIndex;
long offset;
@@ -210,9 +217,11 @@ bool Ogg::File::readPages(unsigned int i) {
if (nextPage->header()->lastPageOfStream())
return false;
}
}
void Ogg::File::writePacket(unsigned int i, const ByteVector &packet) {
if (!readPages(i)) {
debug("Ogg::File::writePacket() -- Could not find the requested packet.");
return;
@@ -292,4 +301,5 @@ void Ogg::File::writePacket(unsigned int i, const ByteVector &packet) {
// Discard all the pages to keep them up-to-date by fetching them again.
d->pages.clear();
}

View File

@@ -28,7 +28,7 @@
#include "tbytevectorlist.h"
#ifndef TAGLIB_OGGFILE_H
# define TAGLIB_OGGFILE_H
#define TAGLIB_OGGFILE_H
namespace Strawberry_TagLib {
namespace TagLib {
@@ -42,64 +42,54 @@ class PageHeader;
//! 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.
*/
* 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();
/*!
* 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.
*/
* 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);
/*!
* Sets the packet with index \a i to the value \a p.
*/
* Sets the packet with index \a i to the value \a 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.
*/
* 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();
/*!
* Returns a pointer to the PageHeader for the last page in the stream or
* null if the page could not be found.
*/
* 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();
virtual bool save();
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.
*/
* 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);
/*!
* Constructs an Ogg file from \a stream.
*
* \note This constructor is protected since Ogg::File shouldn't be
* instantiated directly but rather should be used through the codec
* specific subclasses.
*
* \note TagLib will *not* take ownership of the stream, the caller is
* responsible for deleting it after the File object.
*/
* Constructs an Ogg file from \a stream.
*
* \note This constructor is protected since Ogg::File shouldn't be instantiated directly but rather should be used through the codec specific subclasses.
*
* \note TagLib will *not* take ownership of the stream, the caller is responsible for deleting it after the File object.
*/
File(IOStream *stream);
private:
@@ -107,14 +97,14 @@ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File {
File &operator=(const File &);
/*!
* Reads the pages from the beginning of the file until enough to compose
* the requested packet.
*/
* Reads the pages from the beginning of the file until enough to compose
* the requested packet.
*/
bool readPages(unsigned int i);
/*!
* Writes the requested packet to the file.
*/
* Writes the requested packet to the file.
*/
void writePacket(unsigned int i, const ByteVector &packet);
class FilePrivate;

View File

@@ -36,10 +36,7 @@ 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) {}
PagePrivate(File *f = nullptr, long pageOffset = -1) : file(f), fileOffset(pageOffset), header(f, pageOffset), firstPacketIndex(-1) {}
File *file;
long fileOffset;
@@ -52,8 +49,7 @@ class Ogg::Page::PagePrivate {
// public members
////////////////////////////////////////////////////////////////////////////////
Ogg::Page::Page(Ogg::File *file, long pageOffset) : d(new PagePrivate(file, pageOffset)) {
}
Ogg::Page::Page(Ogg::File *file, long pageOffset) : d(new PagePrivate(file, pageOffset)) {}
Ogg::Page::~Page() {
delete d;
@@ -84,6 +80,7 @@ void Ogg::Page::setFirstPacketIndex(int index) {
}
Ogg::Page::ContainsPacketFlags Ogg::Page::containsPacket(int index) const {
const int lastPacketIndex = d->firstPacketIndex + packetCount() - 1;
if (index < d->firstPacketIndex || index > lastPacketIndex)
return DoesNotContainPacket;
@@ -116,6 +113,7 @@ Ogg::Page::ContainsPacketFlags Ogg::Page::containsPacket(int index) const {
}
return flags;
}
unsigned int Ogg::Page::packetCount() const {
@@ -123,6 +121,7 @@ unsigned int Ogg::Page::packetCount() const {
}
ByteVectorList Ogg::Page::packets() const {
if (!d->packets.isEmpty())
return d->packets;
@@ -142,6 +141,7 @@ ByteVectorList Ogg::Page::packets() const {
debug("Ogg::Page::packets() -- attempting to read packets from an invalid page.");
return l;
}
int Ogg::Page::size() const {
@@ -149,6 +149,7 @@ int Ogg::Page::size() const {
}
ByteVector Ogg::Page::render() const {
ByteVector data;
data.append(d->header.render());
@@ -175,15 +176,11 @@ ByteVector Ogg::Page::render() const {
std::copy(checksum.begin(), checksum.end(), data.begin() + 22);
return data;
}
List<Ogg::Page *> Ogg::Page::paginate(const ByteVectorList &packets,
PaginationStrategy strategy,
unsigned int streamSerialNumber,
int firstPage,
bool firstPacketContinued,
bool lastPacketCompleted,
bool containsLastPacket) {
List<Ogg::Page *> Ogg::Page::paginate(const ByteVectorList &packets, 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
@@ -248,23 +245,15 @@ List<Ogg::Page *> Ogg::Page::paginate(const ByteVectorList &packets,
}
return l;
}
Ogg::Page *Ogg::Page::getCopyWithNewPageSequenceNumber(int /*sequenceNumber*/) {
debug("Ogg::Page::getCopyWithNewPageSequenceNumber() -- This function is obsolete. Returning null.");
return nullptr;
}
////////////////////////////////////////////////////////////////////////////////
// protected members
////////////////////////////////////////////////////////////////////////////////
Ogg::Page::Page(const ByteVectorList &packets,
unsigned int streamSerialNumber,
int pageNumber,
bool firstPacketContinued,
bool lastPacketCompleted,
bool containsLastPacket) : d(new PagePrivate()) {
Ogg::Page::Page(const ByteVectorList &packets, 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);
@@ -283,4 +272,5 @@ Ogg::Page::Page(const ByteVectorList &packets,
}
d->packets = packets;
d->header.setPacketSizes(packetSizes);
}

View File

@@ -40,82 +40,67 @@ class PageHeader;
//! 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
* multiple packets.
*
* In most Xiph.org formats the comments are found in the first few packets,
* this however is a reasonably complete implementation of Ogg pages that
* could potentially be useful for non-meta data purposes.
*/
* 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 multiple packets.
*
* In most Xiph.org formats the comments are found in the first few packets,
* this however is a reasonably complete implementation of Ogg pages that
* could potentially be useful for non-meta data purposes.
*/
class TAGLIB_EXPORT Page {
public:
/*!
* Read an Ogg page from the \a file at the position \a pageOffset.
*/
* Read an Ogg page from the \a file at the position \a pageOffset.
*/
Page(File *file, long pageOffset);
virtual ~Page();
/*!
* Returns the page's position within the file (in bytes).
*/
* Returns the page's position within the file (in bytes).
*/
long fileOffset() const;
/*!
* Returns a pointer to the header for this page. This pointer will become
* invalid when the page is deleted.
*/
* Returns a pointer to the header for this page. This pointer will become invalid when the page is deleted.
*/
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()
*/
* 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;
/*!
* Sets the page's position in the stream to \a sequenceNumber.
*
* \see pageSequenceNumber()
*/
* Sets the page's position in the stream to \a sequenceNumber.
*
* \see pageSequenceNumber()
*/
void setPageSequenceNumber(int sequenceNumber);
/*!
* Returns a copy of the page with \a sequenceNumber set as sequence number.
*
* \see header()
* \see PageHeader::setPageSequenceNumber()
*
* \deprecated Always returns null.
*/
TAGLIB_DEPRECATED Page *getCopyWithNewPageSequenceNumber(int sequenceNumber);
/*!
* Returns the index of the first packet wholly or partially contained in
* this page.
*
* \see setFirstPacketIndex()
*/
* Returns the index of the first packet wholly or partially contained in this page.
*
* \see setFirstPacketIndex()
*/
int firstPacketIndex() const;
/*!
* Sets the index of the first packet in the page.
*
* \see firstPacketIndex()
*/
* Sets the index of the first packet in the page.
*
* \see firstPacketIndex()
*/
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()
*/
* 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,
@@ -128,74 +113,66 @@ class TAGLIB_EXPORT Page {
};
/*!
* Checks to see if the specified \a packet is contained in the current
* page.
*
* \see ContainsPacketFlags
*/
* Checks to see if the specified \a packet is contained in the current page.
*
* \see ContainsPacketFlags
*/
ContainsPacketFlags containsPacket(int index) const;
/*!
* Returns the number of packets (whole or partial) in this page.
*/
* Returns the number of packets (whole or partial) in this page.
*/
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()
*/
* 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;
/*!
* Returns the size of the page in bytes.
*/
* Returns the size of the page in bytes.
*/
int size() 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.
*/
* 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 {
/*!
* 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.
*/
* 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,
/*!
* Split the packet or group of packets into pages that conform to the
* sizes recommended in the Ogg standard.
*/
* Split the packet or group of packets into pages that conform to the sizes recommended in the Ogg standard.
*/
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.
* \a containsLastPacket should be set to true if \a packets contains the
* last page in the stream and will set the appropriate flag in the last
* rendered Ogg page's header. \a streamSerialNumber should be set to
* the serial number for this stream.
*
* \note The "absolute granule position" is currently always zeroed using
* this method as this suffices for the comment headers.
*
* \warning The pages returned by this method must be deleted by the user.
* You can use List<T>::setAutoDelete(true) to set these pages to be
* automatically deleted when this list passes out of scope.
*
* \see PaginationStrategy
* \see List::setAutoDelete()
*/
* 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.
* \a containsLastPacket should be set to true if \a packets contains the
* last page in the stream and will set the appropriate flag in the last rendered Ogg page's header.
* \a streamSerialNumber should be set to the serial number for this stream.
*
* \note The "absolute granule position" is currently always zeroed using this method as this suffices for the comment headers.
*
* \warning The pages returned by this method must be deleted by the user.
* You can use List<T>::setAutoDelete(true) to set these pages to be automatically deleted when this list passes out of scope.
*
* \see PaginationStrategy
* \see List::setAutoDelete()
*/
static List<Page *> paginate(const ByteVectorList &packets,
PaginationStrategy strategy,
unsigned int streamSerialNumber,
@@ -206,9 +183,8 @@ class TAGLIB_EXPORT Page {
protected:
/*!
* Creates an Ogg packet based on the data in \a packets. The page number
* for each page will be set to \a pageNumber.
*/
* 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,
@@ -223,7 +199,9 @@ class TAGLIB_EXPORT Page {
class PagePrivate;
PagePrivate *d;
};
} // namespace Ogg
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@@ -65,8 +65,10 @@ class Ogg::PageHeader::PageHeaderPrivate {
////////////////////////////////////////////////////////////////////////////////
Ogg::PageHeader::PageHeader(Ogg::File *file, long pageOffset) : d(new PageHeaderPrivate()) {
if (file && pageOffset >= 0)
read(file, pageOffset);
}
Ogg::PageHeader::~PageHeader() {
@@ -150,6 +152,7 @@ int Ogg::PageHeader::dataSize() const {
}
ByteVector Ogg::PageHeader::render() const {
ByteVector data;
// capture pattern
@@ -194,6 +197,7 @@ ByteVector Ogg::PageHeader::render() const {
data.append(pageSegments);
return data;
}
////////////////////////////////////////////////////////////////////////////////
@@ -201,6 +205,7 @@ ByteVector Ogg::PageHeader::render() const {
////////////////////////////////////////////////////////////////////////////////
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
@@ -263,9 +268,11 @@ void Ogg::PageHeader::read(Ogg::File *file, long pageOffset) {
d->lastPacketCompleted = true;
d->isValid = true;
}
ByteVector Ogg::PageHeader::lacingValues() const {
ByteVector data;
for (List<int>::ConstIterator it = d->packetSizes.begin(); it != d->packetSizes.end(); ++it) {
@@ -282,4 +289,5 @@ ByteVector Ogg::PageHeader::lacingValues() const {
}
return data;
}

View File

@@ -32,7 +32,6 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace Ogg {
class File;
@@ -40,179 +39,164 @@ class File;
//! 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.
*/
* 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:
/*!
* 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.
*/
* 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);
/*!
* Deletes this instance of the PageHeader.
*/
* Deletes this instance of the PageHeader.
*/
virtual ~PageHeader();
/*!
* Returns true if the header parsed properly and is valid.
*/
* Returns true if the header parsed properly and is valid.
*/
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()
*/
* 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;
/*!
* Sets the sizes of the packets in this page to \a sizes. Internally this
* updates the lacing values in the header.
*
* \see packetSizes()
*/
* 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);
/*!
* 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.
*
* \see lastPacketCompleted()
* \see setFirstPacketContinued()
*/
* 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.
*
* \see lastPacketCompleted()
* \see setFirstPacketContinued()
*/
bool firstPacketContinued() const;
/*!
* Sets the internal flag indicating if the first packet in this page is
* continued to \a continued.
*
* \see firstPacketContinued()
*/
* Sets the internal flag indicating if the first packet in this page is continued to \a continued.
*
* \see firstPacketContinued()
*/
void setFirstPacketContinued(bool continued);
/*!
* Returns true if the last packet of this page is completely contained in
* this page.
*
* \see firstPacketContinued()
* \see setLastPacketCompleted()
*/
* Returns true if the last packet of this page is completely contained in this page.
*
* \see firstPacketContinued()
* \see setLastPacketCompleted()
*/
bool lastPacketCompleted() const;
/*!
* Sets the internal flag indicating if the last packet in this page is
* complete to \a completed.
*
* \see lastPacketCompleted()
*/
* Sets the internal flag indicating if the last packet in this page is complete to \a completed.
*
* \see lastPacketCompleted()
*/
void setLastPacketCompleted(bool completed);
/*!
* This returns true if this is the first page of the Ogg (logical) stream.
*
* \see setFirstPageOfStream()
*/
* This returns true if this is the first page of the Ogg (logical) stream.
*
* \see setFirstPageOfStream()
*/
bool firstPageOfStream() const;
/*!
* Marks this page as the first page of the Ogg stream.
*
* \see firstPageOfStream()
*/
* Marks this page as the first page of the Ogg stream.
*
* \see firstPageOfStream()
*/
void setFirstPageOfStream(bool first);
/*!
* This returns true if this is the last page of the Ogg (logical) stream.
*
* \see setLastPageOfStream()
*/
* This returns true if this is the last page of the Ogg (logical) stream.
*
* \see setLastPageOfStream()
*/
bool lastPageOfStream() const;
/*!
* Marks this page as the last page of the Ogg stream.
*
* \see lastPageOfStream()
*/
* Marks this page as the last page of the Ogg stream.
*
* \see lastPageOfStream()
*/
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()
*/
* 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;
/*!
* 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()
*/
* 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);
/*!
* 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()
*/
* 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;
/*!
* 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
* stream.
*
* \see streamSerialNumber()
*/
* 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 stream.
*
* \see streamSerialNumber()
*/
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()
*/
* 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;
/*!
* Sets the page's position in the stream to \a sequenceNumber.
*
* \see pageSequenceNumber()
*/
* Sets the page's position in the stream to \a sequenceNumber.
*
* \see pageSequenceNumber()
*/
void setPageSequenceNumber(int sequenceNumber);
/*!
* Returns the complete header size.
*/
* Returns the complete header size.
*/
int size() const;
/*!
* Returns the size of the data portion of the page -- i.e. the size of the
* page less the header size.
*/
* Returns the size of the data portion of the page -- i.e. the size of the page less the header size.
*/
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.
*/
* 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;
private:

View File

@@ -39,8 +39,7 @@ using namespace Strawberry_TagLib::TagLib::Ogg;
class Opus::File::FilePrivate {
public:
FilePrivate() : comment(0),
properties(0) {}
FilePrivate() : comment(nullptr), properties(nullptr) {}
~FilePrivate() {
delete comment;
@@ -56,26 +55,30 @@ class Opus::File::FilePrivate {
////////////////////////////////////////////////////////////////////////////////
bool Ogg::Opus::File::isSupported(IOStream *stream) {
// An Opus file has IDs "OggS" and "OpusHead" somewhere.
const ByteVector buffer = Utils::readHeader(stream, bufferSize(), false);
return (buffer.find("OggS") >= 0 && buffer.find("OpusHead") >= 0);
}
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
Opus::File::File(FileName file, bool readProperties, Properties::ReadStyle) : Ogg::File(file),
d(new FilePrivate()) {
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()) {
Opus::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : Ogg::File(stream), d(new FilePrivate()) {
if (isOpen())
read(readProperties);
}
Opus::File::~File() {
@@ -99,12 +102,14 @@ Opus::Properties *Opus::File::audioProperties() const {
}
bool Opus::File::save() {
if (!d->comment)
d->comment = new Ogg::XiphComment();
setPacket(1, ByteVector("OpusTags", 8) + d->comment->render(false));
return Ogg::File::save();
}
////////////////////////////////////////////////////////////////////////////////
@@ -112,6 +117,7 @@ bool Opus::File::save() {
////////////////////////////////////////////////////////////////////////////////
void Opus::File::read(bool readProperties) {
ByteVector opusHeaderData = packet(0);
if (!opusHeaderData.startsWith("OpusHead")) {
@@ -132,4 +138,5 @@ void Opus::File::read(bool readProperties) {
if (readProperties)
d->properties = new Properties(this);
}

View File

@@ -37,7 +37,6 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace Ogg {
//! A namespace containing classes for Opus metadata
@@ -47,79 +46,74 @@ namespace Opus {
//! 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.
*/
* 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:
/*!
* 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);
* 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);
/*!
* Constructs an Opus file from \a stream. If \a readProperties is true the
* file's audio properties will also be read.
*
* \note TagLib will *not* take ownership of the stream, the caller is
* responsible for deleting it after the File object.
*
* \note In the current implementation, \a propertiesStyle is ignored.
*/
File(IOStream *stream, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
* Constructs an Opus file from \a stream.
* If \a readProperties is true the file's audio properties will also be read.
*
* \note TagLib will *not* take ownership of the stream, the caller is responsible for deleting it after the File object.
*
* \note In the current implementation, \a propertiesStyle is ignored.
*/
File(IOStream *stream, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average);
/*!
* Destroys this instance of the File.
*/
* Destroys this instance of the File.
*/
virtual ~File();
/*!
* Returns the XiphComment for this file. XiphComment implements the tag
* interface, so this serves as the reimplementation of
* TagLib::File::tag().
*/
* Returns the XiphComment for this file.
* XiphComment implements the tag interface, so this serves as the reimplementation of TagLib::File::tag().
*/
virtual Ogg::XiphComment *tag() const;
/*!
* Implements the unified property interface -- export function.
* This forwards directly to XiphComment::properties().
*/
* Implements the unified property interface -- export function.
* This forwards directly to XiphComment::properties().
*/
PropertyMap properties() const;
/*!
* Implements the unified tag dictionary interface -- import function.
* Like properties(), this is a forwarder to the file's XiphComment.
*/
* Implements the unified tag dictionary interface -- import function.
* Like properties(), this is a forwarder to the file's XiphComment.
*/
PropertyMap setProperties(const PropertyMap &);
/*!
* Returns the Opus::Properties for this file. If no audio properties
* were read then this will return a null pointer.
*/
* Returns the Opus::Properties for this file.
* If no audio properties were read then this will return a null pointer.
*/
virtual Properties *audioProperties() const;
/*!
* Save the file.
*
* This returns true if the save was successful.
*/
* Save the file.
*
* This returns true if the save was successful.
*/
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.
*/
* Returns whether or not the given \a stream can be opened as an Opus file.
*
* \note This method is designed to do a quick check. The result may not necessarily be correct.
*/
static bool isSupported(IOStream *stream);
private:
@@ -131,6 +125,7 @@ class TAGLIB_EXPORT File : public Ogg::File {
class FilePrivate;
FilePrivate *d;
};
} // namespace Opus
} // namespace Ogg
} // namespace TagLib

View File

@@ -57,8 +57,7 @@ class Opus::Properties::PropertiesPrivate {
// 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);
}
@@ -66,10 +65,6 @@ Opus::Properties::~Properties() {
delete d;
}
int Opus::Properties::length() const {
return lengthInSeconds();
}
int Ogg::Opus::Properties::lengthInSeconds() const {
return d->length / 1000;
}
@@ -83,10 +78,12 @@ int Opus::Properties::bitrate() 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 {
@@ -106,6 +103,7 @@ int Opus::Properties::opusVersion() const {
////////////////////////////////////////////////////////////////////////////////
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
@@ -166,4 +164,5 @@ void Opus::Properties::read(File *file) {
}
else
debug("Opus::Properties::read() -- Could not find valid first and last Ogg pages.");
}

View File

@@ -44,78 +44,64 @@ class File;
//! An implementation of audio property reading for Ogg Opus
/*!
* This reads the data from an Ogg Opus stream found in the AudioProperties
* API.
*/
* This reads the data from an Ogg Opus stream found in the AudioProperties API.
*/
class TAGLIB_EXPORT Properties : public AudioProperties {
public:
/*!
* Create an instance of Opus::Properties with the data read from the
* Opus::File \a file.
*/
* Create an instance of Opus::Properties with the data read from the
* Opus::File \a file.
*/
Properties(File *file, ReadStyle style = Average);
/*!
* Destroys this Opus::Properties instance.
*/
* Destroys this Opus::Properties instance.
*/
virtual ~Properties();
/*!
* Returns the length of the file in seconds. The length is rounded down to
* the nearest whole second.
*
* \note This method is just an alias of lengthInSeconds().
*
* \deprecated
*/
TAGLIB_DEPRECATED virtual int length() const;
/*!
* Returns the length of the file in seconds. The length is rounded down to
* the nearest whole second.
*
* \see lengthInMilliseconds()
*/
* Returns the length of the file in seconds. The length is rounded down to the nearest whole second.
*
* \see lengthInMilliseconds()
*/
// BIC: make virtual
int lengthInSeconds() const;
/*!
* Returns the length of the file in milliseconds.
*
* \see lengthInSeconds()
*/
* Returns the length of the file in milliseconds.
*
* \see lengthInSeconds()
*/
// BIC: make virtual
int lengthInMilliseconds() const;
/*!
* Returns the average bit rate of the file in kb/s.
*/
* Returns the average bit rate of the file in kb/s.
*/
virtual int bitrate() const;
/*!
* Returns the sample rate in Hz.
*
* \note Always returns 48000, because Opus can decode any stream at a
* sample rate of 8, 12, 16, 24, or 48 kHz,
*/
* 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;
/*!
* Returns the number of audio channels.
*/
* Returns the number of audio channels.
*/
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.
*/
* 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;
/*!
* Returns the Opus version, in the range 0...255.
*/
* Returns the Opus version, in the range 0...255.
*/
int opusVersion() const;
private:
@@ -127,6 +113,7 @@ class TAGLIB_EXPORT Properties : public AudioProperties {
class PropertiesPrivate;
PropertiesPrivate *d;
};
} // namespace Opus
} // namespace Ogg
} // namespace TagLib

View File

@@ -39,8 +39,7 @@ using namespace Strawberry_TagLib::TagLib::Ogg;
class Speex::File::FilePrivate {
public:
FilePrivate() : comment(0),
properties(0) {}
FilePrivate() : comment(nullptr), properties(nullptr) {}
~FilePrivate() {
delete comment;
@@ -56,24 +55,24 @@ class Speex::File::FilePrivate {
////////////////////////////////////////////////////////////////////////////////
bool Ogg::Speex::File::isSupported(IOStream *stream) {
// A Speex file has IDs "OggS" and "Speex " somewhere.
const ByteVector buffer = Utils::readHeader(stream, bufferSize(), false);
return (buffer.find("OggS") >= 0 && buffer.find("Speex ") >= 0);
}
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
Speex::File::File(FileName file, bool readProperties, Properties::ReadStyle) : Ogg::File(file),
d(new FilePrivate()) {
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()) {
Speex::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) : Ogg::File(stream), d(new FilePrivate()) {
if (isOpen())
read(readProperties);
}
@@ -99,12 +98,14 @@ Speex::Properties *Speex::File::audioProperties() const {
}
bool Speex::File::save() {
if (!d->comment)
d->comment = new Ogg::XiphComment();
setPacket(1, d->comment->render());
return Ogg::File::save();
}
////////////////////////////////////////////////////////////////////////////////
@@ -112,6 +113,7 @@ bool Speex::File::save() {
////////////////////////////////////////////////////////////////////////////////
void Speex::File::read(bool readProperties) {
ByteVector speexHeaderData = packet(0);
if (!speexHeaderData.startsWith("Speex ")) {
@@ -126,4 +128,5 @@ void Speex::File::read(bool readProperties) {
if (readProperties)
d->properties = new Properties(this);
}

View File

@@ -47,79 +47,73 @@ namespace Speex {
//! 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.
*/
* 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:
/*!
* 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);
* 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);
/*!
* Constructs a Speex file from \a stream. If \a readProperties is true the
* file's audio properties will also be read.
*
* \note TagLib will *not* take ownership of the stream, the caller is
* responsible for deleting it after the File object.
*
* \note In the current implementation, \a propertiesStyle is ignored.
*/
File(IOStream *stream, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
* Constructs a Speex file from \a stream.
* If \a readProperties is true the file's audio properties will also be read.
*
* \note TagLib will *not* take ownership of the stream, the caller is responsible for deleting it after the File object.
*
* \note In the current implementation, \a propertiesStyle is ignored.
*/
File(IOStream *stream, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average);
/*!
* Destroys this instance of the File.
*/
* Destroys this instance of the File.
*/
virtual ~File();
/*!
* Returns the XiphComment for this file. XiphComment implements the tag
* interface, so this serves as the reimplementation of
* TagLib::File::tag().
*/
* Returns the XiphComment for this file. XiphComment implements the tag interface, so this serves as the reimplementation of TagLib::File::tag().
*/
virtual Ogg::XiphComment *tag() const;
/*!
* Implements the unified property interface -- export function.
* This forwards directly to XiphComment::properties().
*/
* Implements the unified property interface -- export function.
* This forwards directly to XiphComment::properties().
*/
PropertyMap properties() const;
/*!
* Implements the unified tag dictionary interface -- import function.
* Like properties(), this is a forwarder to the file's XiphComment.
*/
* Implements the unified tag dictionary interface -- import function.
* Like properties(), this is a forwarder to the file's XiphComment.
*/
PropertyMap setProperties(const PropertyMap &);
/*!
* Returns the Speex::Properties for this file. If no audio properties
* were read then this will return a null pointer.
*/
* Returns the Speex::Properties for this file.
* If no audio properties were read then this will return a null pointer.
*/
virtual Properties *audioProperties() const;
/*!
* Save the file.
*
* This returns true if the save was successful.
*/
* Save the file.
*
* This returns true if the save was successful.
*/
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.
*/
* Returns whether or not the given \a stream can be opened as a Speex file.
*
* \note This method is designed to do a quick check. The result may not necessarily be correct.
*/
static bool isSupported(IOStream *stream);
private:
@@ -131,6 +125,7 @@ class TAGLIB_EXPORT File : public Ogg::File {
class FilePrivate;
FilePrivate *d;
};
} // namespace Speex
} // namespace Ogg
} // namespace TagLib

View File

@@ -63,8 +63,7 @@ class Speex::Properties::PropertiesPrivate {
// 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);
}
@@ -72,10 +71,6 @@ Speex::Properties::~Properties() {
delete d;
}
int Speex::Properties::length() const {
return lengthInSeconds();
}
int Speex::Properties::lengthInSeconds() const {
return d->length / 1000;
}
@@ -109,6 +104,7 @@ int Speex::Properties::speexVersion() const {
////////////////////////////////////////////////////////////////////////////////
void Speex::Properties::read(File *file) {
// Get the identification header from the Ogg implementation.
const ByteVector data = file->packet(0);
@@ -190,4 +186,5 @@ void Speex::Properties::read(File *file) {
if (d->bitrate == 0 && d->bitrateNominal > 0)
d->bitrate = static_cast<int>(d->bitrateNominal / 1000.0 + 0.5);
}

View File

@@ -34,83 +34,65 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace Ogg {
namespace Speex {
class File;
//! An implementation of audio property reading for Ogg Speex
/*!
* This reads the data from an Ogg Speex stream found in the AudioProperties
* API.
*/
//! This reads the data from an Ogg Speex stream found in the AudioProperties API.
class TAGLIB_EXPORT Properties : public AudioProperties {
public:
/*!
* Create an instance of Speex::Properties with the data read from the
* Speex::File \a file.
*/
* Create an instance of Speex::Properties with the data read from the Speex::File \a file.
*/
Properties(File *file, ReadStyle style = Average);
/*!
* Destroys this Speex::Properties instance.
*/
* Destroys this Speex::Properties instance.
*/
virtual ~Properties();
/*!
* Returns the length of the file in seconds. The length is rounded down to
* the nearest whole second.
*
* \note This method is just an alias of lengthInSeconds().
*
* \deprecated
*/
TAGLIB_DEPRECATED virtual int length() const;
/*!
* Returns the length of the file in seconds. The length is rounded down to
* the nearest whole second.
*
* \see lengthInMilliseconds()
*/
* Returns the length of the file in seconds. The length is rounded down to the nearest whole second.
*
* \see lengthInMilliseconds()
*/
// BIC: make virtual
int lengthInSeconds() const;
/*!
* Returns the length of the file in milliseconds.
*
* \see lengthInSeconds()
*/
* Returns the length of the file in milliseconds.
*
* \see lengthInSeconds()
*/
// BIC: make virtual
int lengthInMilliseconds() const;
/*!
* Returns the average bit rate of the file in kb/s.
*/
* Returns the average bit rate of the file in kb/s.
*/
virtual int bitrate() const;
/*!
* Returns the nominal bit rate as read from the Speex header in kb/s.
*/
* Returns the nominal bit rate as read from the Speex header in kb/s.
*/
int bitrateNominal() const;
/*!
* Returns the sample rate in Hz.
*/
* Returns the sample rate in Hz.
*/
virtual int sampleRate() const;
/*!
* Returns the number of audio channels.
*/
* Returns the number of audio channels.
*/
virtual int channels() const;
/*!
* Returns the Speex version, currently "0" (as specified by the spec).
*/
* Returns the Speex version, currently "0" (as specified by the spec).
*/
int speexVersion() const;
private:
@@ -122,6 +104,7 @@ class TAGLIB_EXPORT Properties : public AudioProperties {
class PropertiesPrivate;
PropertiesPrivate *d;
};
} // namespace Speex
} // namespace Ogg
} // namespace TagLib

View File

@@ -36,8 +36,7 @@ using namespace Strawberry_TagLib::TagLib;
class Vorbis::File::FilePrivate {
public:
FilePrivate() : comment(0),
properties(0) {}
FilePrivate() : comment(nullptr), properties(nullptr) {}
~FilePrivate() {
delete comment;
@@ -106,6 +105,7 @@ Vorbis::Properties *Vorbis::File::audioProperties() const {
}
bool Vorbis::File::save() {
ByteVector v(vorbisCommentHeaderID);
if (!d->comment)
@@ -115,6 +115,7 @@ bool Vorbis::File::save() {
setPacket(1, v);
return Ogg::File::save();
}
////////////////////////////////////////////////////////////////////////////////
@@ -122,6 +123,7 @@ bool Vorbis::File::save() {
////////////////////////////////////////////////////////////////////////////////
void Vorbis::File::read(bool readProperties) {
ByteVector commentHeaderData = packet(1);
if (commentHeaderData.mid(0, 7) != vorbisCommentHeaderID) {
@@ -134,4 +136,5 @@ void Vorbis::File::read(bool readProperties) {
if (readProperties)
d->properties = new Properties(this);
}

View File

@@ -36,10 +36,9 @@ namespace Strawberry_TagLib {
namespace TagLib {
/*
* This is just to make this appear to be in the Ogg namespace in the
* documentation. The typedef below will make this work with the current code.
* In the next BIC version of TagLib this will be really moved into the Ogg
* namespace.
* This is just to make this appear to be in the Ogg namespace in the documentation.
* The typedef below will make this work with the current code.
* In the next BIC version of TagLib this will be really moved into the Ogg namespace.
*/
#ifdef DOXYGEN
@@ -50,83 +49,74 @@ namespace Ogg {
namespace Vorbis {
//! 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.
*/
* 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:
/*!
* 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);
* 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);
/*!
* Constructs a Vorbis file from \a stream. If \a readProperties is true the
* file's audio properties will also be read.
*
* \note TagLib will *not* take ownership of the stream, the caller is
* responsible for deleting it after the File object.
*
* \note In the current implementation, \a propertiesStyle is ignored.
*/
File(IOStream *stream, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
* Constructs a Vorbis file from \a stream.
* If \a readProperties is true the file's audio properties will also be read.
*
* \note TagLib will *not* take ownership of the stream, the caller is responsible for deleting it after the File object.
*
* \note In the current implementation, \a propertiesStyle is ignored.
*/
File(IOStream *stream, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average);
/*!
* Destroys this instance of the File.
*/
* Destroys this instance of the File.
*/
virtual ~File();
/*!
* Returns the XiphComment for this file. XiphComment implements the tag
* interface, so this serves as the reimplementation of
* TagLib::File::tag().
*/
* Returns the XiphComment for this file.
* XiphComment implements the tag interface, so this serves as the reimplementation of TagLib::File::tag().
*/
virtual Ogg::XiphComment *tag() const;
/*!
* Implements the unified property interface -- export function.
* This forwards directly to XiphComment::properties().
*/
* Implements the unified property interface -- export function.
* This forwards directly to XiphComment::properties().
*/
PropertyMap properties() const;
/*!
* Implements the unified tag dictionary interface -- import function.
* Like properties(), this is a forwarder to the file's XiphComment.
*/
* Implements the unified tag dictionary interface -- import function.
* Like properties(), this is a forwarder to the file's XiphComment.
*/
PropertyMap setProperties(const PropertyMap &);
/*!
* Returns the Vorbis::Properties for this file. If no audio properties
* were read then this will return a null pointer.
*/
* Returns the Vorbis::Properties for this file. If no audio properties were read then this will return a null pointer.
*/
virtual Properties *audioProperties() const;
/*!
* Save the file.
*
* This returns true if the save was successful.
*/
* Save the file.
*
* This returns true if the save was successful.
*/
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.
*/
* Check if the given \a stream can be opened as an Ogg Vorbis file.
*
* \note This method is designed to do a quick check. The result may not necessarily be correct.
*/
static bool isSupported(IOStream *stream);
private:
@@ -141,9 +131,8 @@ class TAGLIB_EXPORT File : public Ogg::File {
} // namespace Vorbis
/*
* To keep compatibility with the current version put Vorbis in the Ogg namespace
* only in the docs and provide a typedef to make it work. In the next BIC
* version this will be removed and it will only exist in the Ogg namespace.
* To keep compatibility with the current version put Vorbis in the Ogg namespace only in the docs and provide a typedef to make it work.
* In the next BIC version this will be removed and it will only exist in the Ogg namespace.
*/
#ifdef DOXYGEN

View File

@@ -68,8 +68,7 @@ static const char vorbisSetupHeaderID[] = { 0x01, 'v', 'o', 'r', 'b', 'i', 's',
// 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);
}
@@ -77,10 +76,6 @@ Vorbis::Properties::~Properties() {
delete d;
}
int Vorbis::Properties::length() const {
return lengthInSeconds();
}
int Vorbis::Properties::lengthInSeconds() const {
return d->length / 1000;
}
@@ -122,6 +117,7 @@ int Vorbis::Properties::bitrateMinimum() const {
////////////////////////////////////////////////////////////////////////////////
void Vorbis::Properties::read(File *file) {
// Get the identification header from the Ogg implementation.
const ByteVector data = file->packet(0);
@@ -194,4 +190,5 @@ void Vorbis::Properties::read(File *file) {
if (d->bitrate == 0 && d->bitrateNominal > 0)
d->bitrate = static_cast<int>(d->bitrateNominal / 1000.0 + 0.5);
}

View File

@@ -33,10 +33,9 @@ namespace Strawberry_TagLib {
namespace TagLib {
/*
* This is just to make this appear to be in the Ogg namespace in the
* documentation. The typedef below will make this work with the current code.
* In the next BIC version of TagLib this will be really moved into the Ogg
* namespace.
* This is just to make this appear to be in the Ogg namespace in the documentation.
* The typedef below will make this work with the current code.
* In the next BIC version of TagLib this will be really moved into the Ogg namespace.
*/
#ifdef DOXYGEN
@@ -50,86 +49,70 @@ class File;
//! An implementation of audio property reading for Ogg Vorbis
/*!
* This reads the data from an Ogg Vorbis stream found in the AudioProperties
* API.
*/
* This reads the data from an Ogg Vorbis stream found in the AudioProperties API.
*/
class TAGLIB_EXPORT Properties : public AudioProperties {
public:
/*!
* Create an instance of Vorbis::Properties with the data read from the
* Vorbis::File \a file.
*/
* Create an instance of Vorbis::Properties with the data read from the Vorbis::File \a file.
*/
Properties(File *file, ReadStyle style = Average);
/*!
* Destroys this VorbisProperties instance.
*/
* Destroys this VorbisProperties instance.
*/
virtual ~Properties();
/*!
* Returns the length of the file in seconds. The length is rounded down to
* the nearest whole second.
*
* \note This method is just an alias of lengthInSeconds().
*
* \deprecated
*/
TAGLIB_DEPRECATED virtual int length() const;
/*!
* Returns the length of the file in seconds. The length is rounded down to
* the nearest whole second.
*
* \see lengthInMilliseconds()
*/
* Returns the length of the file in seconds. The length is rounded down to the nearest whole second.
*
* \see lengthInMilliseconds()
*/
// BIC: make virtual
int lengthInSeconds() const;
/*!
* Returns the length of the file in milliseconds.
*
* \see lengthInSeconds()
*/
* Returns the length of the file in milliseconds.
*
* \see lengthInSeconds()
*/
// BIC: make virtual
int lengthInMilliseconds() const;
/*!
* Returns the average bit rate of the file in kb/s.
*/
* Returns the average bit rate of the file in kb/s.
*/
virtual int bitrate() const;
/*!
* Returns the sample rate in Hz.
*/
* Returns the sample rate in Hz.
*/
virtual int sampleRate() const;
/*!
* Returns the number of audio channels.
*/
* Returns the number of audio channels.
*/
virtual int channels() const;
/*!
* Returns the Vorbis version, currently "0" (as specified by the spec).
*/
* Returns the Vorbis version, currently "0" (as specified by the spec).
*/
int vorbisVersion() const;
/*!
* Returns the maximum bitrate as read from the Vorbis identification
* header.
*/
* Returns the maximum bitrate as read from the Vorbis identification header.
*/
int bitrateMaximum() const;
/*!
* Returns the nominal bitrate as read from the Vorbis identification
* header.
*/
* Returns the nominal bitrate as read from the Vorbis identification header.
*/
int bitrateNominal() const;
/*!
* Returns the minimum bitrate as read from the Vorbis identification
* header.
*/
* Returns the minimum bitrate as read from the Vorbis identification header.
*/
int bitrateMinimum() const;
private:
@@ -144,9 +127,8 @@ class TAGLIB_EXPORT Properties : public AudioProperties {
} // namespace Vorbis
/*
* To keep compatibility with the current version put Vorbis in the Ogg namespace
* only in the docs and provide a typedef to make it work. In the next BIC
* version this will be removed and it will only exist in the Ogg namespace.
* To keep compatibility with the current version put Vorbis in the Ogg namespace only in the docs and provide a typedef to make it work.
* In the next BIC version this will be removed and it will only exist in the Ogg namespace.
*/
#ifdef DOXYGEN

View File

@@ -57,12 +57,9 @@ class Ogg::XiphComment::XiphCommentPrivate {
// 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);
}
@@ -71,24 +68,31 @@ Ogg::XiphComment::~XiphComment() {
}
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())
return String();
return d->fieldListMap["ARTIST"].toString();
}
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()) {
d->commentField = "DESCRIPTION";
return d->fieldListMap["DESCRIPTION"].toString();
@@ -100,28 +104,35 @@ String Ogg::XiphComment::comment() const {
}
return String();
}
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())
return d->fieldListMap["DATE"].front().toInt();
if (!d->fieldListMap["YEAR"].isEmpty())
return d->fieldListMap["YEAR"].front().toInt();
return 0;
}
unsigned int Ogg::XiphComment::track() const {
if (!d->fieldListMap["TRACKNUMBER"].isEmpty())
return d->fieldListMap["TRACKNUMBER"].front().toInt();
if (!d->fieldListMap["TRACKNUM"].isEmpty())
return d->fieldListMap["TRACKNUM"].front().toInt();
return 0;
}
void Ogg::XiphComment::setTitle(const String &s) {
@@ -137,6 +148,7 @@ void Ogg::XiphComment::setAlbum(const String &s) {
}
void Ogg::XiphComment::setComment(const String &s) {
if (d->commentField.isEmpty()) {
if (!d->fieldListMap["DESCRIPTION"].isEmpty())
d->commentField = "DESCRIPTION";
@@ -145,6 +157,7 @@ void Ogg::XiphComment::setComment(const String &s) {
}
addField(d->commentField, s);
}
void Ogg::XiphComment::setGenre(const String &s) {
@@ -152,31 +165,38 @@ void Ogg::XiphComment::setGenre(const String &s) {
}
void Ogg::XiphComment::setYear(unsigned int i) {
removeFields("YEAR");
if (i == 0)
removeFields("DATE");
else
addField("DATE", String::number(i));
}
void Ogg::XiphComment::setTrack(unsigned int i) {
removeFields("TRACKNUM");
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())
return false;
}
return true;
}
unsigned int Ogg::XiphComment::fieldCount() const {
unsigned int count = 0;
for (FieldConstIterator it = d->fieldListMap.begin(); it != d->fieldListMap.end(); ++it)
@@ -185,6 +205,7 @@ unsigned int Ogg::XiphComment::fieldCount() const {
count += d->pictureList.size();
return count;
}
const Ogg::FieldListMap &Ogg::XiphComment::fieldListMap() const {
@@ -196,6 +217,7 @@ PropertyMap Ogg::XiphComment::properties() const {
}
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)
@@ -227,9 +249,11 @@ PropertyMap Ogg::XiphComment::setProperties(const PropertyMap &properties) {
}
}
return invalid;
}
bool Ogg::XiphComment::checkKey(const String &key) {
if (key.size() < 1)
return false;
@@ -241,6 +265,7 @@ bool Ogg::XiphComment::checkKey(const String &key) {
}
return true;
}
String Ogg::XiphComment::vendorID() const {
@@ -248,6 +273,7 @@ String Ogg::XiphComment::vendorID() const {
}
void Ogg::XiphComment::addField(const String &key, const String &value, bool replace) {
if (!checkKey(key)) {
debug("Ogg::XiphComment::addField() - Invalid key. Field not added.");
return;
@@ -260,13 +286,7 @@ void Ogg::XiphComment::addField(const String &key, const String &value, bool rep
if (!key.isEmpty() && !value.isEmpty())
d->fieldListMap[upperKey].append(value);
}
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) {
@@ -274,6 +294,7 @@ void Ogg::XiphComment::removeFields(const String &key) {
}
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)
@@ -281,6 +302,7 @@ void Ogg::XiphComment::removeFields(const String &key, const String &value) {
else
++it;
}
}
void Ogg::XiphComment::removeAllFields() {
@@ -292,12 +314,14 @@ bool Ogg::XiphComment::contains(const String &key) const {
}
void Ogg::XiphComment::removePicture(FLAC::Picture *picture, bool del) {
PictureIterator it = d->pictureList.find(picture);
if (it != d->pictureList.end())
d->pictureList.erase(it);
if (del)
delete picture;
}
void Ogg::XiphComment::removeAllPictures() {
@@ -317,6 +341,7 @@ ByteVector Ogg::XiphComment::render() 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
@@ -368,6 +393,7 @@ ByteVector Ogg::XiphComment::render(bool addFramingBit) const {
data.append(char(1));
return data;
}
////////////////////////////////////////////////////////////////////////////////
@@ -375,6 +401,7 @@ ByteVector Ogg::XiphComment::render(bool addFramingBit) const {
////////////////////////////////////////////////////////////////////////////////
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.
@@ -468,4 +495,5 @@ void Ogg::XiphComment::parse(const ByteVector &data) {
addField(key, String(entry.mid(sep + 1), String::UTF8), false);
}
}
}

View File

@@ -41,43 +41,41 @@ namespace TagLib {
namespace Ogg {
/*!
* A mapping between a list of field names, or keys, and a list of values
* associated with that field.
*
* \see XiphComment::fieldListMap()
*/
* 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;
//! 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
* has been made part of a generic implementation rather than being limited
* to strictly Vorbis.
*
* Vorbis comments are a simple vector of keys and values, called fields.
* Multiple values for a given key are supported.
*
* \see fieldListMap()
*/
* 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 has been made part of a generic implementation rather than being limited to strictly Vorbis.
*
* Vorbis comments are a simple vector of keys and values, called fields.
* Multiple values for a given key are supported.
*
* \see fieldListMap()
*/
class TAGLIB_EXPORT XiphComment : public Strawberry_TagLib::TagLib::Tag {
public:
/*!
* Constructs an empty Vorbis comment.
*/
* Constructs an empty Vorbis comment.
*/
XiphComment();
/*!
* Constructs a Vorbis comment from \a data.
*/
* Constructs a Vorbis comment from \a data.
*/
XiphComment(const ByteVector &data);
/*!
* Destroys this instance of the XiphComment.
*/
* Destroys this instance of the XiphComment.
*/
virtual ~XiphComment();
virtual String title() const;
@@ -99,167 +97,149 @@ class TAGLIB_EXPORT XiphComment : public Strawberry_TagLib::TagLib::Tag {
virtual bool isEmpty() const;
/*!
* Returns the number of fields present in the comment.
*/
* Returns the number of fields present in the comment.
*/
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.
*
* The standard set of Xiph/Vorbis fields (which may or may not be
* contained in any specific comment) is:
*
* <ul>
* <li>TITLE</li>
* <li>VERSION</li>
* <li>ALBUM</li>
* <li>ARTIST</li>
* <li>PERFORMER</li>
* <li>COPYRIGHT</li>
* <li>ORGANIZATION</li>
* <li>DESCRIPTION</li>
* <li>GENRE</li>
* <li>DATE</li>
* <li>LOCATION</li>
* <li>CONTACT</li>
* <li>ISRC</li>
* </ul>
*
* For a more detailed description of these fields, please see the Ogg
* Vorbis specification, section 5.2.2.1.
*
* \note The Ogg Vorbis comment specification does allow these key values
* to be either upper or lower case. However, it is conventional for them
* to be upper case. As such, TagLib, when parsing a Xiph/Vorbis comment,
* converts all fields to uppercase. When you are using this data
* structure, you will need to specify the field name in upper case.
*
* \warning You should not modify this data structure directly, instead
* use addField() and removeField().
*/
* 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.
*
* The standard set of Xiph/Vorbis fields (which may or may not be contained in any specific comment) is:
*
* <ul>
* <li>TITLE</li>
* <li>VERSION</li>
* <li>ALBUM</li>
* <li>ARTIST</li>
* <li>PERFORMER</li>
* <li>COPYRIGHT</li>
* <li>ORGANIZATION</li>
* <li>DESCRIPTION</li>
* <li>GENRE</li>
* <li>DATE</li>
* <li>LOCATION</li>
* <li>CONTACT</li>
* <li>ISRC</li>
* </ul>
*
* For a more detailed description of these fields, please see the Ogg
* Vorbis specification, section 5.2.2.1.
*
* \note The Ogg Vorbis comment specification does allow these key values to be either upper or lower case.
* However, it is conventional for them to be upper case.
* As such, TagLib, when parsing a Xiph/Vorbis comment, converts all fields to uppercase.
* When you are using this data structure, you will need to specify the field name in upper case.
*
* \warning You should not modify this data structure directly, instead use addField() and removeField().
*/
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).
*/
* 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;
/*!
* 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.
*/
* 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 &);
/*!
* Check if the given String is a valid Xiph comment key.
*/
* Check if the given String is a valid Xiph comment key.
*/
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".
*/
* 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;
/*!
* 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.
*/
* 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);
/*!
* 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());
/*!
* Remove all the fields specified by \a key.
*
* \see removeAllFields()
*/
* Remove all the fields specified by \a key.
*
* \see removeAllFields()
*/
void removeFields(const String &key);
/*!
* Remove all the fields specified by \a key with the data \a value.
*
* \see removeAllFields()
*/
* Remove all the fields specified by \a key with the data \a value.
*
* \see removeAllFields()
*/
void removeFields(const String &key, const String &value);
/*!
* Remove all the fields in the comment.
*
* \see removeFields()
*/
* Remove all the fields in the comment.
*
* \see removeFields()
*/
void removeAllFields();
/*!
* Returns true if the field is contained within the comment.
*
* \note This is safer than checking for membership in the FieldListMap.
*/
* 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;
/*!
* Renders the comment to a ByteVector suitable for inserting into a file.
*/
* Renders the comment to a ByteVector suitable for inserting into a file.
*/
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.
*/
* 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;
/*!
* Returns a list of pictures attached to the xiph comment.
*/
* Returns a list of pictures attached to the xiph comment.
*/
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.
*/
* 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);
/*!
* Remove all pictures.
*/
* Remove all pictures.
*/
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().
*/
* 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);
protected:
/*!
* Reads the tag from the file specified in the constructor and fills the
* FieldListMap.
*/
* Reads the tag from the file specified in the constructor and fills the FieldListMap.
*/
void parse(const ByteVector &data);
private: