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

@@ -226,35 +226,43 @@ const int genresSize = sizeof(genres) / sizeof(genres[0]);
} // namespace
StringList ID3v1::genreList() {
StringList l;
for (int i = 0; i < genresSize; i++) {
l.append(genres[i]);
}
return l;
}
ID3v1::GenreMap ID3v1::genreMap() {
GenreMap m;
for (int i = 0; i < genresSize; i++) {
m.insert(genres[i], i);
}
return m;
}
String ID3v1::genre(int i) {
if (i >= 0 && i < genresSize)
return String(genres[i]); // always make a copy
else
return String();
}
int ID3v1::genreIndex(const String &name) {
for (int i = 0; i < genresSize; ++i) {
if (name == genres[i])
return i;
}
return 255;
}

View File

@@ -37,29 +37,25 @@ namespace ID3v1 {
typedef Map<String, int> GenreMap;
/*!
* Returns the list of canonical ID3v1 genre names in the order that they
* are listed in the standard.
*/
* Returns the list of canonical ID3v1 genre names in the order that they are listed in the standard.
*/
StringList TAGLIB_EXPORT genreList();
/*!
* A "reverse mapping" that goes from the canonical ID3v1 genre name to the
* respective genre number. genreMap()["Rock"] ==
*/
* A "reverse mapping" that goes from the canonical ID3v1 genre name to the respective genre number. genreMap()["Rock"] ==
*/
GenreMap TAGLIB_EXPORT genreMap();
/*!
* Returns the name of the genre at \a index in the ID3v1 genre list. If
* \a index is out of range -- less than zero or greater than 191 -- a null
* string will be returned.
*/
* Returns the name of the genre at \a index in the ID3v1 genre list.
* If \a index is out of range -- less than zero or greater than 191 -- a null string will be returned.
*/
String TAGLIB_EXPORT genre(int index);
/*!
* Returns the genre index for the (case sensitive) genre \a name. If the
* genre is not in the list 255 (which signifies an unknown genre in ID3v1)
* will be returned.
*/
* Returns the genre index for the (case sensitive) genre \a name.
* If the genre is not in the list 255 (which signifies an unknown genre in ID3v1) will be returned.
*/
int TAGLIB_EXPORT genreIndex(const String &name);
} // namespace ID3v1
} // namespace TagLib

View File

@@ -39,7 +39,7 @@ const ID3v1::StringHandler *stringHandler = &defaultStringHandler;
class ID3v1::Tag::TagPrivate {
public:
TagPrivate() : file(0),
TagPrivate() : file(nullptr),
tagOffset(0),
track(0),
genre(255) {}
@@ -68,22 +68,22 @@ String ID3v1::StringHandler::parse(const ByteVector &data) const {
}
ByteVector ID3v1::StringHandler::render(const String &s) const {
if (s.isLatin1())
return s.data(String::Latin1);
else
return ByteVector();
}
////////////////////////////////////////////////////////////////////////////////
// public methods
////////////////////////////////////////////////////////////////////////////////
ID3v1::Tag::Tag() : Strawberry_TagLib::TagLib::Tag(),
d(new TagPrivate()) {
}
ID3v1::Tag::Tag() : Strawberry_TagLib::TagLib::Tag(), d(new TagPrivate()) {}
ID3v1::Tag::Tag(File *file, long tagOffset) : Strawberry_TagLib::TagLib::Tag(), d(new TagPrivate()) {
ID3v1::Tag::Tag(File *file, long tagOffset) : Strawberry_TagLib::TagLib::Tag(),
d(new TagPrivate()) {
d->file = file;
d->tagOffset = tagOffset;
@@ -95,6 +95,7 @@ ID3v1::Tag::~Tag() {
}
ByteVector ID3v1::Tag::render() const {
ByteVector data;
data.append(fileIdentifier());
@@ -108,6 +109,7 @@ ByteVector ID3v1::Tag::render() const {
data.append(char(d->genre));
return data;
}
ByteVector ID3v1::Tag::fileIdentifier() {
@@ -190,6 +192,7 @@ void ID3v1::Tag::setStringHandler(const StringHandler *handler) {
////////////////////////////////////////////////////////////////////////////////
void ID3v1::Tag::read() {
if (d->file && d->file->isValid()) {
d->file->seek(d->tagOffset);
// read the tag -- always 128 bytes
@@ -201,9 +204,11 @@ void ID3v1::Tag::read() {
else
debug("ID3v1 tag is not valid or could not be read at the specified offset.");
}
}
void ID3v1::Tag::parse(const ByteVector &data) {
int offset = 3;
d->title = stringHandler->parse(data.mid(offset, 30));
@@ -235,4 +240,5 @@ void ID3v1::Tag::parse(const ByteVector &data) {
offset += 30;
d->genre = static_cast<unsigned char>(data[offset]);
}

View File

@@ -42,94 +42,86 @@ namespace ID3v1 {
//! A abstraction for the string to data encoding in ID3v1 tags.
/*!
* ID3v1 should in theory always contain ISO-8859-1 (Latin1) data. In
* practice it does not. TagLib by default only supports ISO-8859-1 data
* in ID3v1 tags.
*
* However by subclassing this class and reimplementing parse() and render()
* and setting your reimplementation as the default with
* ID3v1::Tag::setStringHandler() you can define how you would like these
* transformations to be done.
*
* \warning It is advisable <b>not</b> to write non-ISO-8859-1 data to ID3v1
* tags. Please consider disabling the writing of ID3v1 tags in the case
* that the data is not ISO-8859-1.
*
* \see ID3v1::Tag::setStringHandler()
*/
* ID3v1 should in theory always contain ISO-8859-1 (Latin1) data. In practice it does not.
* TagLib by default only supports ISO-8859-1 data in ID3v1 tags.
*
* However by subclassing this class and reimplementing parse() and render() and setting your reimplementation as the default with
* ID3v1::Tag::setStringHandler() you can define how you would like these transformations to be done.
*
* \warning It is advisable <b>not</b> to write non-ISO-8859-1 data to ID3v1 tags.
* Please consider disabling the writing of ID3v1 tags in the case that the data is not ISO-8859-1.
*
* \see ID3v1::Tag::setStringHandler()
*/
class TAGLIB_EXPORT StringHandler {
TAGLIB_IGNORE_MISSING_DESTRUCTOR
public:
// BIC: Add virtual destructor.
StringHandler();
/*!
* Decode a string from \a data. The default implementation assumes that
* \a data is an ISO-8859-1 (Latin1) character array.
*/
* Decode a string from \a data.
* The default implementation assumes that \a data is an ISO-8859-1 (Latin1) character array.
*/
virtual String parse(const ByteVector &data) const;
/*!
* Encode a ByteVector with the data from \a s. The default implementation
* assumes that \a s is an ISO-8859-1 (Latin1) string. If the string is
* does not conform to ISO-8859-1, no value is written.
*
* \warning It is recommended that you <b>not</b> override this method, but
* instead do not write an ID3v1 tag in the case that the data is not
* ISO-8859-1.
*/
* Encode a ByteVector with the data from \a s.
* The default implementation assumes that \a s is an ISO-8859-1 (Latin1) string.
* If the string is does not conform to ISO-8859-1, no value is written.
*
* \warning It is recommended that you <b>not</b> override this method, but
* instead do not write an ID3v1 tag in the case that the data is not ISO-8859-1.
*/
virtual ByteVector render(const String &s) const;
};
//! The main class in the ID3v1 implementation
/*!
* This is an implementation of the ID3v1 format. ID3v1 is both the simplest
* and most common of tag formats but is rather limited. Because of its
* pervasiveness and the way that applications have been written around the
* fields that it provides, the generic TagLib::Tag API is a mirror of what is
* provided by ID3v1.
*
* ID3v1 tags should generally only contain Latin1 information. However because
* many applications do not follow this rule there is now support for overriding
* the ID3v1 string handling using the ID3v1::StringHandler class. Please see
* the documentation for that class for more information.
*
* \see StringHandler
*
* \note Most fields are truncated to a maximum of 28-30 bytes. The
* truncation happens automatically when the tag is rendered.
*/
* This is an implementation of the ID3v1 format.
* ID3v1 is both the simplest and most common of tag formats but is rather limited.
* Because of its pervasiveness and the way that applications have been written around the
* fields that it provides, the generic TagLib::Tag API is a mirror of what is provided by ID3v1.
*
* ID3v1 tags should generally only contain Latin1 information.
* However because many applications do not follow this rule there is now support for overriding
* the ID3v1 string handling using the ID3v1::StringHandler class.
* Please see the documentation for that class for more information.
*
* \see StringHandler
*
* \note Most fields are truncated to a maximum of 28-30 bytes.
* The truncation happens automatically when the tag is rendered.
*/
class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag {
public:
/*!
* Create an ID3v1 tag with default values.
*/
* Create an ID3v1 tag with default values.
*/
Tag();
/*!
* Create an ID3v1 tag and parse the data in \a file starting at
* \a tagOffset.
*/
* Create an ID3v1 tag and parse the data in \a file starting at \a tagOffset.
*/
Tag(File *file, long tagOffset);
/*!
* Destroys this Tag instance.
*/
* Destroys this Tag instance.
*/
virtual ~Tag();
/*!
* Renders the in memory values to a ByteVector suitable for writing to
* the file.
*/
* Renders the in memory values to a ByteVector suitable for writing to the file.
*/
ByteVector render() const;
/*!
* Returns the string "TAG" suitable for usage in locating the tag in a
* file.
*/
* Returns the string "TAG" suitable for usage in locating the tag in a file.
*/
static ByteVector fileIdentifier();
// Reimplementations.
@@ -151,41 +143,37 @@ class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag {
virtual void setTrack(unsigned int i);
/*!
* Returns the genre in number.
*
* \note Normally 255 indicates that this tag contains no genre.
*/
* Returns the genre in number.
*
* \note Normally 255 indicates that this tag contains no genre.
*/
unsigned int genreNumber() const;
/*!
* Sets the genre in number to \a i.
*
* \note Valid value is from 0 up to 255. Normally 255 indicates that
* this tag contains no genre.
*/
* Sets the genre in number to \a i.
*
* \note Valid value is from 0 up to 255. Normally 255 indicates that this tag contains no genre.
*/
void setGenreNumber(unsigned int i);
/*!
* Sets the string handler that decides how the ID3v1 data will be
* converted to and from binary data.
* If the parameter \a handler is null, the previous handler is
* released and default ISO-8859-1 handler is restored.
*
* \note The caller is responsible for deleting the previous handler
* as needed after it is released.
*
* \see StringHandler
*/
* Sets the string handler that decides how the ID3v1 data will be converted to and from binary data.
* If the parameter \a handler is null, the previous handler is released and default ISO-8859-1 handler is restored.
*
* \note The caller is responsible for deleting the previous handler as needed after it is released.
*
* \see StringHandler
*/
static void setStringHandler(const StringHandler *handler);
protected:
/*!
* Reads from the file specified in the constructor.
*/
* Reads from the file specified in the constructor.
*/
void read();
/*!
* Pareses the body of the tag in \a data.
*/
* Pareses the body of the tag in \a data.
*/
void parse(const ByteVector &data);
private:
@@ -195,6 +183,7 @@ class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag {
class TagPrivate;
TagPrivate *d;
};
} // namespace ID3v1
} // namespace TagLib
} // namespace Strawberry_TagLib

View File

@@ -33,8 +33,7 @@ using namespace ID3v2;
class AttachedPictureFrame::AttachedPictureFramePrivate {
public:
AttachedPictureFramePrivate() : textEncoding(String::Latin1),
type(AttachedPictureFrame::Other) {}
AttachedPictureFramePrivate() : textEncoding(String::Latin1), type(AttachedPictureFrame::Other) {}
String::Type textEncoding;
String mimeType;
@@ -47,12 +46,9 @@ class AttachedPictureFrame::AttachedPictureFramePrivate {
// public members
////////////////////////////////////////////////////////////////////////////////
AttachedPictureFrame::AttachedPictureFrame() : Frame("APIC"),
d(new AttachedPictureFramePrivate()) {
}
AttachedPictureFrame::AttachedPictureFrame() : Frame("APIC"), d(new AttachedPictureFramePrivate()) {}
AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data) : Frame(data),
d(new AttachedPictureFramePrivate()) {
AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data) : Frame(data), d(new AttachedPictureFramePrivate()) {
setData(data);
}
@@ -110,6 +106,7 @@ void AttachedPictureFrame::setPicture(const ByteVector &p) {
////////////////////////////////////////////////////////////////////////////////
void AttachedPictureFrame::parseFields(const ByteVector &data) {
if (data.size() < 5) {
debug("A picture frame must contain at least 5 bytes.");
return;
@@ -130,9 +127,11 @@ void AttachedPictureFrame::parseFields(const ByteVector &data) {
d->description = readStringField(data, d->textEncoding, &pos);
d->data = data.mid(pos);
}
ByteVector AttachedPictureFrame::renderFields() const {
ByteVector data;
String::Type encoding = checkTextEncoding(d->description, d->textEncoding);
@@ -146,14 +145,14 @@ ByteVector AttachedPictureFrame::renderFields() const {
data.append(d->data);
return data;
}
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data, Header *h) : Frame(h),
d(new AttachedPictureFramePrivate()) {
AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data, Header *h) : Frame(h), d(new AttachedPictureFramePrivate()) {
parseFields(fieldData(data));
}
@@ -162,6 +161,7 @@ AttachedPictureFrame::AttachedPictureFrame(const ByteVector &data, Header *h) :
////////////////////////////////////////////////////////////////////////////////
void AttachedPictureFrameV22::parseFields(const ByteVector &data) {
if (data.size() < 5) {
debug("A picture frame must contain at least 5 bytes.");
return;
@@ -189,9 +189,11 @@ void AttachedPictureFrameV22::parseFields(const ByteVector &data) {
d->description = readStringField(data, d->textEncoding, &pos);
d->data = data.mid(pos);
}
AttachedPictureFrameV22::AttachedPictureFrameV22(const ByteVector &data, Header *h) {
// set v2.2 header to make fieldData work correctly
setHeader(h, true);
@@ -201,4 +203,5 @@ AttachedPictureFrameV22::AttachedPictureFrameV22(const ByteVector &data, Header
Frame::Header *newHeader = new Frame::Header("APIC");
newHeader->setFrameSize(h->frameSize());
setHeader(newHeader, true);
}

View File

@@ -32,25 +32,23 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
//! An ID3v2 attached picture frame implementation
/*!
* This is an implementation of ID3v2 attached pictures. Pictures may be
* included in tags, one per APIC frame (but there may be multiple APIC
* frames in a single tag). These pictures are usually in either JPEG or
* PNG format.
*/
* This is an implementation of ID3v2 attached pictures.
* Pictures may be included in tags, one per APIC frame (but there may be multiple APIC frames in a single tag).
* These pictures are usually in either JPEG or PNG format.
*/
class TAGLIB_EXPORT AttachedPictureFrame : public Frame {
friend class FrameFactory;
public:
/*!
* This describes the function or content of the picture.
*/
* This describes the function or content of the picture.
*/
enum Type {
//! A type not enumerated below
Other = 0x00,
@@ -97,108 +95,106 @@ class TAGLIB_EXPORT AttachedPictureFrame : public Frame {
};
/*!
* Constructs an empty picture frame. The description, content and text
* encoding should be set manually.
*/
* Constructs an empty picture frame.
* The description, content and text encoding should be set manually.
*/
AttachedPictureFrame();
/*!
* Constructs an AttachedPicture frame based on \a data.
*/
* Constructs an AttachedPicture frame based on \a data.
*/
explicit AttachedPictureFrame(const ByteVector &data);
/*!
* Destroys the AttahcedPictureFrame instance.
*/
* Destroys the AttahcedPictureFrame instance.
*/
virtual ~AttachedPictureFrame();
/*!
* Returns a string containing the description and mime-type
*/
* Returns a string containing the description and mime-type
*/
virtual String toString() const;
/*!
* Returns the text encoding used for the description.
*
* \see setTextEncoding()
* \see description()
*/
* Returns the text encoding used for the description.
*
* \see setTextEncoding()
* \see description()
*/
String::Type textEncoding() const;
/*!
* Set the text encoding used for the description.
*
* \see description()
*/
* Set the text encoding used for the description.
*
* \see description()
*/
void setTextEncoding(String::Type t);
/*!
* Returns the mime type of the image. This should in most cases be
* "image/png" or "image/jpeg".
*/
* Returns the mime type of the image.
* This should in most cases be "image/png" or "image/jpeg".
*/
String mimeType() const;
/*!
* Sets the mime type of the image. This should in most cases be
* "image/png" or "image/jpeg".
*/
* Sets the mime type of the image.
* This should in most cases be "image/png" or "image/jpeg".
*/
void setMimeType(const String &m);
/*!
* Returns the type of the image.
*
* \see Type
* \see setType()
*/
* Returns the type of the image.
*
* \see Type
* \see setType()
*/
Type type() const;
/*!
* Sets the type for the image.
*
* \see Type
* \see type()
*/
* Sets the type for the image.
*
* \see Type
* \see type()
*/
void setType(Type t);
/*!
* Returns a text description of the image.
*
* \see setDescription()
* \see textEncoding()
* \see setTextEncoding()
*/
* Returns a text description of the image.
*
* \see setDescription()
* \see textEncoding()
* \see setTextEncoding()
*/
String description() const;
/*!
* Sets a textual description of the image to \a desc.
*
* \see description()
* \see textEncoding()
* \see setTextEncoding()
*/
* Sets a textual description of the image to \a desc.
*
* \see description()
* \see textEncoding()
* \see setTextEncoding()
*/
void setDescription(const String &desc);
/*!
* Returns the image data as a ByteVector.
*
* \note ByteVector has a data() method that returns a const char * which
* should make it easy to export this data to external programs.
*
* \see setPicture()
* \see mimeType()
*/
* Returns the image data as a ByteVector.
*
* \note ByteVector has a data() method that returns a const char * which should make it easy to export this data to external programs.
*
* \see setPicture()
* \see mimeType()
*/
ByteVector picture() const;
/*!
* Sets the image data to \a p. \a p should be of the type specified in
* this frame's mime-type specification.
*
* \see picture()
* \see mimeType()
* \see setMimeType()
*/
* Sets the image data to \a p. \a p should be of the type specified in this frame's mime-type specification.
*
* \see picture()
* \see mimeType()
* \see setMimeType()
*/
void setPicture(const ByteVector &p);
protected:
@@ -222,6 +218,7 @@ class TAGLIB_EXPORT AttachedPictureFrameV22 : public AttachedPictureFrame {
AttachedPictureFrameV22(const ByteVector &data, Header *h);
friend class FrameFactory;
};
} // namespace ID3v2
} // namespace TagLib
} // namespace Strawberry_TagLib

View File

@@ -35,7 +35,7 @@ using namespace ID3v2;
class ChapterFrame::ChapterFramePrivate {
public:
ChapterFramePrivate() : tagHeader(0),
ChapterFramePrivate() : tagHeader(nullptr),
startTime(0),
endTime(0),
startOffset(0),
@@ -57,19 +57,14 @@ class ChapterFrame::ChapterFramePrivate {
// public methods
////////////////////////////////////////////////////////////////////////////////
ChapterFrame::ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data) : ID3v2::Frame(data),
d(new ChapterFramePrivate()) {
ChapterFrame::ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data) : ID3v2::Frame(data), d(new ChapterFramePrivate()) {
d->tagHeader = tagHeader;
setData(data);
}
ChapterFrame::ChapterFrame(const ByteVector &elementID,
unsigned int startTime, unsigned int endTime,
unsigned int startOffset, unsigned int endOffset,
const FrameList &embeddedFrames) : ID3v2::Frame("CHAP"),
d(new ChapterFramePrivate()) {
// setElementID has a workaround for a previously silly API where you had to
// specifically include the null byte.
ChapterFrame::ChapterFrame(const ByteVector &elementID, unsigned int startTime, unsigned int endTime, unsigned int startOffset, unsigned int endOffset, const FrameList &embeddedFrames) : ID3v2::Frame("CHAP"), d(new ChapterFramePrivate()) {
// setElementID has a workaround for a previously silly API where you had to specifically include the null byte.
setElementID(elementID);
@@ -82,6 +77,7 @@ ChapterFrame::ChapterFrame(const ByteVector &elementID,
it != embeddedFrames.end();
++it)
addEmbeddedFrame(*it);
}
ChapterFrame::~ChapterFrame() {
@@ -109,10 +105,12 @@ unsigned int ChapterFrame::endOffset() const {
}
void ChapterFrame::setElementID(const ByteVector &eID) {
d->elementID = eID;
if (d->elementID.endsWith(char(0)))
d->elementID = d->elementID.mid(0, d->elementID.size() - 1);
}
void ChapterFrame::setStartTime(const unsigned int &sT) {
@@ -149,6 +147,7 @@ void ChapterFrame::addEmbeddedFrame(Frame *frame) {
}
void ChapterFrame::removeEmbeddedFrame(Frame *frame, bool del) {
// remove the frame from the frame list
FrameList::Iterator it = d->embeddedFrameList.find(frame);
d->embeddedFrameList.erase(it);
@@ -160,15 +159,19 @@ void ChapterFrame::removeEmbeddedFrame(Frame *frame, bool del) {
// ...and delete as desired
if (del)
delete frame;
}
void ChapterFrame::removeEmbeddedFrames(const ByteVector &id) {
FrameList l = d->embeddedFrameListMap[id];
for (FrameList::ConstIterator it = l.begin(); it != l.end(); ++it)
removeEmbeddedFrame(*it, true);
}
String ChapterFrame::toString() const {
String s = String(d->elementID) +
": start time: " + String::number(d->startTime) +
", end time: " + String::number(d->endTime);
@@ -189,18 +192,21 @@ String ChapterFrame::toString() const {
}
return s;
}
PropertyMap ChapterFrame::asProperties() const {
PropertyMap map;
map.unsupportedData().append(frameID() + String("/") + d->elementID);
return map;
}
ChapterFrame *ChapterFrame::findByElementID(const ID3v2::Tag *tag, const ByteVector &eID) // static
{
ChapterFrame *ChapterFrame::findByElementID(const ID3v2::Tag *tag, const ByteVector &eID) { // static
ID3v2::FrameList comments = tag->frameList("CHAP");
for (ID3v2::FrameList::ConstIterator it = comments.begin();
@@ -212,9 +218,11 @@ ChapterFrame *ChapterFrame::findByElementID(const ID3v2::Tag *tag, const ByteVec
}
return nullptr;
}
void ChapterFrame::parseFields(const ByteVector &data) {
unsigned int size = data.size();
if (size < 18) {
debug("A CHAP frame must contain at least 18 bytes (1 byte element ID "
@@ -255,9 +263,11 @@ void ChapterFrame::parseFields(const ByteVector &data) {
embPos += frame->size() + header()->size();
addEmbeddedFrame(frame);
}
}
ByteVector ChapterFrame::renderFields() const {
ByteVector data;
data.append(d->elementID);
@@ -271,10 +281,12 @@ ByteVector ChapterFrame::renderFields() const {
data.append((*it)->render());
return data;
}
ChapterFrame::ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data, Header *h) : Frame(h),
d(new ChapterFramePrivate()) {
ChapterFrame::ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data, Header *h) : Frame(h), d(new ChapterFramePrivate()) {
d->tagHeader = tagHeader;
parseFields(fieldData(data));
}

View File

@@ -32,13 +32,12 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
/*!
* This is an implementation of ID3v2 chapter frames. The purpose of this
* frame is to describe a single chapter within an audio file.
*/
* This is an implementation of ID3v2 chapter frames.
* The purpose of this frame is to describe a single chapter within an audio file.
*/
//! An implementation of ID3v2 chapter frames
@@ -47,175 +46,162 @@ class TAGLIB_EXPORT ChapterFrame : public ID3v2::Frame {
public:
/*!
* Creates a chapter frame based on \a data. \a tagHeader is required as
* the internal frames are parsed based on the tag version.
*/
* Creates a chapter frame based on \a data.
* \a tagHeader is required as the internal frames are parsed based on the tag version.
*/
ChapterFrame(const ID3v2::Header *tagHeader, const ByteVector &data);
/*!
* Creates a chapter frame with the element ID \a elementID, start time
* \a startTime, end time \a endTime, start offset \a startOffset,
* end offset \a endOffset and optionally a list of embedded frames,
* whose ownership will then be taken over by this Frame, in
* \a embeededFrames;
*
* All times are in milliseconds.
*/
* Creates a chapter frame with the element ID \a elementID,
* start time \a startTime, end time \a endTime, start offset \a startOffset,
* end offset \a endOffset and optionally a list of embedded frames,
* whose ownership will then be taken over by this Frame, in \a embeededFrames;
*
* All times are in milliseconds.
*/
ChapterFrame(const ByteVector &elementID,
unsigned int startTime, unsigned int endTime,
unsigned int startOffset, unsigned int endOffset,
const FrameList &embeddedFrames = FrameList());
/*!
* Destroys the frame.
*/
* Destroys the frame.
*/
virtual ~ChapterFrame();
/*!
* Returns the element ID of the frame. Element ID
* is a null terminated string, however it's not human-readable.
*
* \see setElementID()
*/
* Returns the element ID of the frame.
* Element ID is a null terminated string, however it's not human-readable.
*
* \see setElementID()
*/
ByteVector elementID() const;
/*!
* Returns time of chapter's start (in milliseconds).
*
* \see setStartTime()
*/
* Returns time of chapter's start (in milliseconds).
*
* \see setStartTime()
*/
unsigned int startTime() const;
/*!
* Returns time of chapter's end (in milliseconds).
*
* \see setEndTime()
*/
* Returns time of chapter's end (in milliseconds).
*
* \see setEndTime()
*/
unsigned int endTime() const;
/*!
* Returns zero based byte offset (count of bytes from the beginning
* of the audio file) of chapter's start.
*
* \note If returned value is 0xFFFFFFFF, start time should be used instead.
* \see setStartOffset()
*/
* Returns zero based byte offset (count of bytes from the beginning of the audio file) of chapter's start.
*
* \note If returned value is 0xFFFFFFFF, start time should be used instead.
* \see setStartOffset()
*/
unsigned int startOffset() const;
/*!
* Returns zero based byte offset (count of bytes from the beginning
* of the audio file) of chapter's end.
*
* \note If returned value is 0xFFFFFFFF, end time should be used instead.
* \see setEndOffset()
*/
* Returns zero based byte offset (count of bytes from the beginning of the audio file) of chapter's end.
*
* \note If returned value is 0xFFFFFFFF, end time should be used instead.
* \see setEndOffset()
*/
unsigned int endOffset() const;
/*!
* Sets the element ID of the frame to \a eID. If \a eID isn't
* null terminated, a null char is appended automatically.
*
* \see elementID()
*/
* Sets the element ID of the frame to \a eID. If \a eID isn't null terminated, a null char is appended automatically.
*
* \see elementID()
*/
void setElementID(const ByteVector &eID);
/*!
* Sets time of chapter's start (in milliseconds) to \a sT.
*
* \see startTime()
*/
* Sets time of chapter's start (in milliseconds) to \a sT.
*
* \see startTime()
*/
void setStartTime(const unsigned int &sT);
/*!
* Sets time of chapter's end (in milliseconds) to \a eT.
*
* \see endTime()
*/
* Sets time of chapter's end (in milliseconds) to \a eT.
*
* \see endTime()
*/
void setEndTime(const unsigned int &eT);
/*!
* Sets zero based byte offset (count of bytes from the beginning
* of the audio file) of chapter's start to \a sO.
*
* \see startOffset()
*/
* Sets zero based byte offset (count of bytes from the beginning of the audio file) of chapter's start to \a sO.
*
* \see startOffset()
*/
void setStartOffset(const unsigned int &sO);
/*!
* Sets zero based byte offset (count of bytes from the beginning
* of the audio file) of chapter's end to \a eO.
*
* \see endOffset()
*/
* Sets zero based byte offset (count of bytes from the beginning of the audio file) of chapter's end to \a eO.
*
* \see endOffset()
*/
void setEndOffset(const unsigned int &eO);
/*!
* Returns a reference to the frame list map. This is an FrameListMap of
* all of the frames embedded in the CHAP frame.
*
* This is the most convenient structure for accessing the CHAP frame's
* embedded frames. Many frame types allow multiple instances of the same
* frame type so this is a map of lists. In most cases however there will
* only be a single frame of a certain type.
*
* \warning You should not modify this data structure directly, instead
* use addEmbeddedFrame() and removeEmbeddedFrame().
*
* \see embeddedFrameList()
*/
* Returns a reference to the frame list map.
* This is an FrameListMap of all of the frames embedded in the CHAP frame.
*
* This is the most convenient structure for accessing the CHAP frame's embedded frames.
* Many frame types allow multiple instances of the same rame type so this is a map of lists.
* In most cases however there will only be a single frame of a certain type.
*
* \warning You should not modify this data structure directly, instead
* use addEmbeddedFrame() and removeEmbeddedFrame().
*
* \see embeddedFrameList()
*/
const FrameListMap &embeddedFrameListMap() const;
/*!
* Returns a reference to the embedded frame list. This is an FrameList
* of all of the frames embedded in the CHAP frame in the order that they
* were parsed.
*
* This can be useful if for example you want iterate over the CHAP frame's
* embedded frames in the order that they occur in the CHAP frame.
*
* \warning You should not modify this data structure directly, instead
* use addEmbeddedFrame() and removeEmbeddedFrame().
*/
* Returns a reference to the embedded frame list.
* This is an FrameList of all of the frames embedded in the CHAP frame in the order that they were parsed.
*
* This can be useful if for example you want iterate over the CHAP frame's
* embedded frames in the order that they occur in the CHAP frame.
*
* \warning You should not modify this data structure directly,
* instead use addEmbeddedFrame() and removeEmbeddedFrame().
*/
const FrameList &embeddedFrameList() const;
/*!
* Returns the embedded frame list for frames with the id \a frameID
* or an empty list if there are no embedded frames of that type. This
* is just a convenience and is equivalent to:
*
* \code
* embeddedFrameListMap()[frameID];
* \endcode
*
* \see embeddedFrameListMap()
*/
* Returns the embedded frame list for frames with the id \a frameID or an empty list if there are no embedded frames of that type.
* This is just a convenience and is equivalent to:
*
* \code
* embeddedFrameListMap()[frameID];
* \endcode
*
* \see embeddedFrameListMap()
*/
const FrameList &embeddedFrameList(const ByteVector &frameID) const;
/*!
* Add an embedded frame to the CHAP frame. At this point the CHAP frame
* takes ownership of the embedded frame and will handle freeing its memory.
*
* \note Using this method will invalidate any pointers on the list
* returned by embeddedFrameList()
*/
* Add an embedded frame to the CHAP frame.
* At this point the CHAP frame takes ownership of the embedded frame and will handle freeing its memory.
*
* \note Using this method will invalidate any pointers on the list returned by embeddedFrameList()
*/
void addEmbeddedFrame(Frame *frame);
/*!
* Remove an embedded frame from the CHAP frame. If \a del is true the frame's
* memory will be freed; if it is false, it must be deleted by the user.
*
* \note Using this method will invalidate any pointers on the list
* returned by embeddedFrameList()
*/
* Remove an embedded frame from the CHAP frame.
* If \a del is true the frame's memory will be freed; if it is false, it must be deleted by the user.
*
* \note Using this method will invalidate any pointers on the list returned by embeddedFrameList()
*/
void removeEmbeddedFrame(Frame *frame, bool del = true);
/*!
* Remove all embedded frames of type \a id from the CHAP frame and free their
* memory.
*
* \note Using this method will invalidate any pointers on the list
* returned by embeddedFrameList()
*/
* Remove all embedded frames of type \a id from the CHAP frame and free their memory.
*
* \note Using this method will invalidate any pointers on the list returned by embeddedFrameList()
*/
void removeEmbeddedFrames(const ByteVector &id);
virtual String toString() const;
@@ -223,12 +209,11 @@ class TAGLIB_EXPORT ChapterFrame : public ID3v2::Frame {
PropertyMap asProperties() const;
/*!
* CHAP frames each have a unique element ID. This searches for a CHAP
* frame with the element ID \a eID and returns a pointer to it. This
* can be used to link CTOC and CHAP frames together.
*
* \see elementID()
*/
* CHAP frames each have a unique element ID. This searches for a CHAP frame with the element ID \a eID and returns a pointer to it.
* This can be used to link CTOC and CHAP frames together.
*
* \see elementID()
*/
static ChapterFrame *findByElementID(const Tag *tag, const ByteVector &eID);
protected:
@@ -243,6 +228,7 @@ class TAGLIB_EXPORT ChapterFrame : public ID3v2::Frame {
class ChapterFramePrivate;
ChapterFramePrivate *d;
};
} // namespace ID3v2
} // namespace TagLib
} // namespace Strawberry_TagLib

View File

@@ -47,13 +47,11 @@ class CommentsFrame::CommentsFramePrivate {
// public members
////////////////////////////////////////////////////////////////////////////////
CommentsFrame::CommentsFrame(String::Type encoding) : Frame("COMM"),
d(new CommentsFramePrivate()) {
CommentsFrame::CommentsFrame(String::Type encoding) : Frame("COMM"), d(new CommentsFramePrivate()) {
d->textEncoding = encoding;
}
CommentsFrame::CommentsFrame(const ByteVector &data) : Frame(data),
d(new CommentsFramePrivate()) {
CommentsFrame::CommentsFrame(const ByteVector &data) : Frame(data), d(new CommentsFramePrivate()) {
setData(data);
}
@@ -98,6 +96,7 @@ void CommentsFrame::setTextEncoding(String::Type encoding) {
}
PropertyMap CommentsFrame::asProperties() const {
String key = description().upper();
PropertyMap map;
if (key.isEmpty() || key == "COMMENT")
@@ -105,10 +104,11 @@ PropertyMap CommentsFrame::asProperties() const {
else
map.insert("COMMENT:" + key, text());
return map;
}
CommentsFrame *CommentsFrame::findByDescription(const ID3v2::Tag *tag, const String &d) // static
{
CommentsFrame *CommentsFrame::findByDescription(const ID3v2::Tag *tag, const String &d) { // static
ID3v2::FrameList comments = tag->frameList("COMM");
for (ID3v2::FrameList::ConstIterator it = comments.begin();
@@ -120,6 +120,7 @@ CommentsFrame *CommentsFrame::findByDescription(const ID3v2::Tag *tag, const Str
}
return nullptr;
}
////////////////////////////////////////////////////////////////////////////////
@@ -127,6 +128,7 @@ CommentsFrame *CommentsFrame::findByDescription(const ID3v2::Tag *tag, const Str
////////////////////////////////////////////////////////////////////////////////
void CommentsFrame::parseFields(const ByteVector &data) {
if (data.size() < 5) {
debug("A comment frame must contain at least 5 bytes.");
return;
@@ -149,9 +151,11 @@ void CommentsFrame::parseFields(const ByteVector &data) {
d->text = String(l.back(), d->textEncoding);
}
}
}
ByteVector CommentsFrame::renderFields() const {
ByteVector v;
String::Type encoding = d->textEncoding;
@@ -166,13 +170,13 @@ ByteVector CommentsFrame::renderFields() const {
v.append(d->text.data(encoding));
return v;
}
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
CommentsFrame::CommentsFrame(const ByteVector &data, Header *h) : Frame(h),
d(new CommentsFramePrivate()) {
CommentsFrame::CommentsFrame(const ByteVector &data, Header *h) : Frame(h), d(new CommentsFramePrivate()) {
parseFields(fieldData(data));
}

View File

@@ -31,129 +31,124 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
//! An implementation of ID3v2 comments
/*!
* This implements the ID3v2 comment format. An ID3v2 comment consists of
* a language encoding, a description and a single text field.
*/
* This implements the ID3v2 comment format. An ID3v2 comment consists of
* a language encoding, a description and a single text field.
*/
class TAGLIB_EXPORT CommentsFrame : public Frame {
friend class FrameFactory;
public:
/*!
* Construct an empty comment frame that will use the text encoding
* \a encoding.
*/
* Construct an empty comment frame that will use the text encoding \a encoding.
*/
explicit CommentsFrame(String::Type encoding = String::Latin1);
/*!
* Construct a comment based on the data in \a data.
*/
* Construct a comment based on the data in \a data.
*/
explicit CommentsFrame(const ByteVector &data);
/*!
* Destroys this CommentFrame instance.
*/
* Destroys this CommentFrame instance.
*/
virtual ~CommentsFrame();
/*!
* Returns the text of this comment.
*
* \see text()
*/
* Returns the text of this comment.
*
* \see text()
*/
virtual String toString() const;
/*!
* Returns the language encoding as a 3 byte encoding as specified by
* <a href="http://en.wikipedia.org/wiki/ISO_639">ISO-639-2</a>.
*
* \note Most taggers simply ignore this value.
*
* \see setLanguage()
*/
* Returns the language encoding as a 3 byte encoding as specified by
* <a href="http://en.wikipedia.org/wiki/ISO_639">ISO-639-2</a>.
*
* \note Most taggers simply ignore this value.
*
* \see setLanguage()
*/
ByteVector language() const;
/*!
* Returns the description of this comment.
*
* \note Most taggers simply ignore this value.
*
* \see setDescription()
*/
* Returns the description of this comment.
*
* \note Most taggers simply ignore this value.
*
* \see setDescription()
*/
String description() const;
/*!
* Returns the text of this comment.
*
* \see setText()
*/
* Returns the text of this comment.
*
* \see setText()
*/
String text() const;
/*!
* Set the language using the 3 byte language code from
* <a href="http://en.wikipedia.org/wiki/ISO_639">ISO-639-2</a> to
* \a languageCode.
*
* \see language()
*/
* Set the language using the 3 byte language code from
* <a href="http://en.wikipedia.org/wiki/ISO_639">ISO-639-2</a> to \a languageCode.
*
* \see language()
*/
void setLanguage(const ByteVector &languageCode);
/*!
* Sets the description of the comment to \a s.
*
* \see description()
*/
* Sets the description of the comment to \a s.
*
* \see description()
*/
void setDescription(const String &s);
/*!
* Sets the text portion of the comment to \a s.
*
* \see text()
*/
* Sets the text portion of the comment to \a s.
*
* \see text()
*/
virtual void setText(const String &s);
/*!
* Returns the text encoding that will be used in rendering this frame.
* This defaults to the type that was either specified in the constructor
* or read from the frame when parsed.
*
* \see setTextEncoding()
* \see render()
*/
* Returns the text encoding that will be used in rendering this frame.
* This defaults to the type that was either specified in the constructor or read from the frame when parsed.
*
* \see setTextEncoding()
* \see render()
*/
String::Type textEncoding() const;
/*!
* Sets the text encoding to be used when rendering this frame to
* \a encoding.
*
* \see textEncoding()
* \see render()
*/
* Sets the text encoding to be used when rendering this frame to \a encoding.
*
* \see textEncoding()
* \see render()
*/
void setTextEncoding(String::Type encoding);
/*!
* Parses this frame as PropertyMap with a single key.
* - if description() is empty or "COMMENT", the key will be "COMMENT"
* - if description() is not a valid PropertyMap key, the frame will be
* marked unsupported by an entry "COMM/<description>" in the unsupportedData()
* attribute of the returned map.
* - otherwise, the key will be "COMMENT:<description>"
* - The single value will be the frame's text().
*/
* Parses this frame as PropertyMap with a single key.
* - if description() is empty or "COMMENT", the key will be "COMMENT"
* - if description() is not a valid PropertyMap key, the frame will be
* marked unsupported by an entry "COMM/<description>" in the unsupportedData()
* attribute of the returned map.
* - otherwise, the key will be "COMMENT:<description>"
* - The single value will be the frame's text().
*/
PropertyMap asProperties() const;
/*!
* Comments each have a unique description. This searches for a comment
* frame with the description \a d and returns a pointer to it. If no
* frame is found that matches the given description null is returned.
*
* \see description()
*/
* Comments each have a unique description.
* This searches for a comment frame with the description \a d and returns a pointer to it.
* If no frame is found that matches the given description null is returned.
*
* \see description()
*/
static CommentsFrame *findByDescription(const Tag *tag, const String &d);
protected:
@@ -164,8 +159,8 @@ class TAGLIB_EXPORT CommentsFrame : public Frame {
private:
/*!
* The constructor used by the FrameFactory.
*/
* The constructor used by the FrameFactory.
*/
CommentsFrame(const ByteVector &data, Header *h);
CommentsFrame(const CommentsFrame &);
CommentsFrame &operator=(const CommentsFrame &);
@@ -177,4 +172,5 @@ class TAGLIB_EXPORT CommentsFrame : public Frame {
} // namespace ID3v2
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@@ -43,12 +43,9 @@ class EventTimingCodesFrame::EventTimingCodesFramePrivate {
// public members
////////////////////////////////////////////////////////////////////////////////
EventTimingCodesFrame::EventTimingCodesFrame() : Frame("ETCO"),
d(new EventTimingCodesFramePrivate()) {
}
EventTimingCodesFrame::EventTimingCodesFrame() : Frame("ETCO"), d(new EventTimingCodesFramePrivate()) {}
EventTimingCodesFrame::EventTimingCodesFrame(const ByteVector &data) : Frame(data),
d(new EventTimingCodesFramePrivate()) {
EventTimingCodesFrame::EventTimingCodesFrame(const ByteVector &data) : Frame(data), d(new EventTimingCodesFramePrivate()) {
setData(data);
}
@@ -85,6 +82,7 @@ void EventTimingCodesFrame::setSynchedEvents(
////////////////////////////////////////////////////////////////////////////////
void EventTimingCodesFrame::parseFields(const ByteVector &data) {
const int end = data.size();
if (end < 1) {
debug("An event timing codes frame must contain at least 1 byte.");
@@ -101,28 +99,28 @@ void EventTimingCodesFrame::parseFields(const ByteVector &data) {
pos += 4;
d->synchedEvents.append(SynchedEvent(time, type));
}
}
ByteVector EventTimingCodesFrame::renderFields() const {
ByteVector v;
v.append(char(d->timestampFormat));
for (SynchedEventList::ConstIterator it = d->synchedEvents.begin();
it != d->synchedEvents.end();
++it) {
for (SynchedEventList::ConstIterator it = d->synchedEvents.begin(); it != d->synchedEvents.end(); ++it) {
const SynchedEvent &entry = *it;
v.append(char(entry.type));
v.append(ByteVector::fromUInt(entry.time));
}
return v;
}
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
EventTimingCodesFrame::EventTimingCodesFrame(const ByteVector &data, Header *h) : Frame(h),
d(new EventTimingCodesFramePrivate()) {
EventTimingCodesFrame::EventTimingCodesFrame(const ByteVector &data, Header *h) : Frame(h), d(new EventTimingCodesFramePrivate()) {
parseFields(fieldData(data));
}

View File

@@ -31,20 +31,19 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
//! ID3v2 event timing codes frame
/*!
* An implementation of ID3v2 event timing codes.
*/
* An implementation of ID3v2 event timing codes.
*/
class TAGLIB_EXPORT EventTimingCodesFrame : public Frame {
friend class FrameFactory;
public:
/*!
* Specifies the timestamp format used.
*/
* Specifies the timestamp format used.
*/
enum TimestampFormat {
//! The timestamp is of unknown format.
Unknown = 0x00,
@@ -57,8 +56,8 @@ class TAGLIB_EXPORT EventTimingCodesFrame : public Frame {
};
/*!
* Event types defined in id3v2.4.0-frames.txt 4.5. Event timing codes.
*/
* Event types defined in id3v2.4.0-frames.txt 4.5. Event timing codes.
*/
enum EventType {
Padding = 0x00,
EndOfInitialSilence = 0x01,
@@ -104,8 +103,8 @@ class TAGLIB_EXPORT EventTimingCodesFrame : public Frame {
};
/*!
* Single entry of time stamp and event.
*/
* Single entry of time stamp and event.
*/
struct SynchedEvent {
SynchedEvent(unsigned int ms, EventType t) : time(ms), type(t) {}
unsigned int time;
@@ -113,52 +112,52 @@ class TAGLIB_EXPORT EventTimingCodesFrame : public Frame {
};
/*!
* List of synchronized events.
*/
* List of synchronized events.
*/
typedef Strawberry_TagLib::TagLib::List<SynchedEvent> SynchedEventList;
/*!
* Construct an empty event timing codes frame.
*/
* Construct an empty event timing codes frame.
*/
explicit EventTimingCodesFrame();
/*!
* Construct a event timing codes frame based on the data in \a data.
*/
* Construct a event timing codes frame based on the data in \a data.
*/
explicit EventTimingCodesFrame(const ByteVector &data);
/*!
* Destroys this EventTimingCodesFrame instance.
*/
* Destroys this EventTimingCodesFrame instance.
*/
virtual ~EventTimingCodesFrame();
/*!
* Returns a null string.
*/
* Returns a null string.
*/
virtual String toString() const;
/*!
* Returns the timestamp format.
*/
* Returns the timestamp format.
*/
TimestampFormat timestampFormat() const;
/*!
* Returns the events with the time stamps.
*/
* Returns the events with the time stamps.
*/
SynchedEventList synchedEvents() const;
/*!
* Set the timestamp format.
*
* \see timestampFormat()
*/
* Set the timestamp format.
*
* \see timestampFormat()
*/
void setTimestampFormat(TimestampFormat f);
/*!
* Sets the text with the time stamps.
*
* \see text()
*/
* Sets the text with the time stamps.
*
* \see text()
*/
void setSynchedEvents(const SynchedEventList &e);
protected:
@@ -169,8 +168,8 @@ class TAGLIB_EXPORT EventTimingCodesFrame : public Frame {
private:
/*!
* The constructor used by the FrameFactory.
*/
* The constructor used by the FrameFactory.
*/
EventTimingCodesFrame(const ByteVector &data, Header *h);
EventTimingCodesFrame(const EventTimingCodesFrame &);
EventTimingCodesFrame &operator=(const EventTimingCodesFrame &);
@@ -182,4 +181,5 @@ class TAGLIB_EXPORT EventTimingCodesFrame : public Frame {
} // namespace ID3v2
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@@ -49,12 +49,9 @@ class GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFramePrivate {
// public members
////////////////////////////////////////////////////////////////////////////////
GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame() : Frame("GEOB"),
d(new GeneralEncapsulatedObjectFramePrivate()) {
}
GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame() : Frame("GEOB"), d(new GeneralEncapsulatedObjectFramePrivate()) {}
GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame(const ByteVector &data) : Frame(data),
d(new GeneralEncapsulatedObjectFramePrivate()) {
GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame(const ByteVector &data) : Frame(data), d(new GeneralEncapsulatedObjectFramePrivate()) {
setData(data);
}
@@ -63,6 +60,7 @@ GeneralEncapsulatedObjectFrame::~GeneralEncapsulatedObjectFrame() {
}
String GeneralEncapsulatedObjectFrame::toString() const {
String text = "[" + d->mimeType + "]";
if (!d->fileName.isEmpty())
@@ -72,6 +70,7 @@ String GeneralEncapsulatedObjectFrame::toString() const {
text += " \"" + d->description + "\"";
return text;
}
String::Type GeneralEncapsulatedObjectFrame::textEncoding() const {
@@ -119,6 +118,7 @@ void GeneralEncapsulatedObjectFrame::setObject(const ByteVector &data) {
////////////////////////////////////////////////////////////////////////////////
void GeneralEncapsulatedObjectFrame::parseFields(const ByteVector &data) {
if (data.size() < 4) {
debug("An object frame must contain at least 4 bytes.");
return;
@@ -133,9 +133,11 @@ void GeneralEncapsulatedObjectFrame::parseFields(const ByteVector &data) {
d->description = readStringField(data, d->textEncoding, &pos);
d->data = data.mid(pos);
}
ByteVector GeneralEncapsulatedObjectFrame::renderFields() const {
StringList sl;
sl.append(d->fileName);
sl.append(d->description);
@@ -154,13 +156,13 @@ ByteVector GeneralEncapsulatedObjectFrame::renderFields() const {
data.append(d->data);
return data;
}
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame(const ByteVector &data, Header *h) : Frame(h),
d(new GeneralEncapsulatedObjectFramePrivate()) {
GeneralEncapsulatedObjectFrame::GeneralEncapsulatedObjectFrame(const ByteVector &data, Header *h) : Frame(h), d(new GeneralEncapsulatedObjectFramePrivate()) {
parseFields(fieldData(data));
}

View File

@@ -35,129 +35,128 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
//! An ID3v2 general encapsulated object frame implementation
/*!
* This is an implementation of ID3v2 general encapsulated objects.
* Arbitrary binary data may be included in tags, stored in GEOB frames.
* There may be multiple GEOB frames in a single tag. Each GEOB it
* labelled with a content description (which may be blank), a required
* mime-type, and a file name (may be blank). The content description
* uniquely identifies the GEOB frame in the tag.
*/
* This is an implementation of ID3v2 general encapsulated objects.
* Arbitrary binary data may be included in tags, stored in GEOB frames.
* There may be multiple GEOB frames in a single tag.
* Each GEOB it labelled with a content description (which may be blank),
* a required mime-type, and a file name (may be blank).
* The content description uniquely identifies the GEOB frame in the tag.
*/
class TAGLIB_EXPORT GeneralEncapsulatedObjectFrame : public Frame {
friend class FrameFactory;
public:
/*!
* Constructs an empty object frame. The description, file name and text
* encoding should be set manually.
*/
* Constructs an empty object frame.
* The description, file name and text encoding should be set manually.
*/
GeneralEncapsulatedObjectFrame();
/*!
* Constructs a GeneralEncapsulatedObjectFrame frame based on \a data.
*
* \warning This is \em not data for the encapsulated object, for that use
* setObject(). This constructor is used when reading the frame from the
* disk.
*/
* Constructs a GeneralEncapsulatedObjectFrame frame based on \a data.
*
* \warning This is \em not data for the encapsulated object, for that use
* setObject().
* This constructor is used when reading the frame from the disk.
*/
explicit GeneralEncapsulatedObjectFrame(const ByteVector &data);
/*!
* Destroys the GeneralEncapsulatedObjectFrame instance.
*/
* Destroys the GeneralEncapsulatedObjectFrame instance.
*/
virtual ~GeneralEncapsulatedObjectFrame();
/*!
* Returns a string containing the description, file name and mime-type
*/
* Returns a string containing the description, file name and mime-type
*/
virtual String toString() const;
/*!
* Returns the text encoding used for the description and file name.
*
* \see setTextEncoding()
* \see description()
* \see fileName()
*/
* Returns the text encoding used for the description and file name.
*
* \see setTextEncoding()
* \see description()
* \see fileName()
*/
String::Type textEncoding() const;
/*!
* Set the text encoding used for the description and file name.
*
* \see description()
* \see fileName()
*/
* Set the text encoding used for the description and file name.
*
* \see description()
* \see fileName()
*/
void setTextEncoding(String::Type encoding);
/*!
* Returns the mime type of the object.
*/
* Returns the mime type of the object.
*/
String mimeType() const;
/*!
* Sets the mime type of the object.
*/
* Sets the mime type of the object.
*/
void setMimeType(const String &type);
/*!
* Returns the file name of the object.
*
* \see setFileName()
*/
* Returns the file name of the object.
*
* \see setFileName()
*/
String fileName() const;
/*!
* Sets the file name for the object.
*
* \see fileName()
*/
* Sets the file name for the object.
*
* \see fileName()
*/
void setFileName(const String &name);
/*!
* Returns the content description of the object.
*
* \see setDescription()
* \see textEncoding()
* \see setTextEncoding()
*/
* Returns the content description of the object.
*
* \see setDescription()
* \see textEncoding()
* \see setTextEncoding()
*/
String description() const;
/*!
* Sets the content description of the object to \a desc.
*
* \see description()
* \see textEncoding()
* \see setTextEncoding()
*/
* Sets the content description of the object to \a desc.
*
* \see description()
* \see textEncoding()
* \see setTextEncoding()
*/
void setDescription(const String &desc);
/*!
* Returns the object data as a ByteVector.
*
* \note ByteVector has a data() method that returns a const char * which
* should make it easy to export this data to external programs.
*
* \see setObject()
* \see mimeType()
*/
* Returns the object data as a ByteVector.
*
* \note ByteVector has a data() method that returns a const char * which
* should make it easy to export this data to external programs.
*
* \see setObject()
* \see mimeType()
*/
ByteVector object() const;
/*!
* Sets the object data to \a data. \a data should be of the type specified in
* this frame's mime-type specification.
*
* \see object()
* \see mimeType()
* \see setMimeType()
*/
* Sets the object data to \a data.
* \a data should be of the type specified in this frame's mime-type specification.
*
* \see object()
* \see mimeType()
* \see setMimeType()
*/
void setObject(const ByteVector &object);
protected:
@@ -172,6 +171,7 @@ class TAGLIB_EXPORT GeneralEncapsulatedObjectFrame : public Frame {
class GeneralEncapsulatedObjectFramePrivate;
GeneralEncapsulatedObjectFramePrivate *d;
};
} // namespace ID3v2
} // namespace TagLib
} // namespace Strawberry_TagLib

View File

@@ -44,13 +44,11 @@ class OwnershipFrame::OwnershipFramePrivate {
// public members
////////////////////////////////////////////////////////////////////////////////
OwnershipFrame::OwnershipFrame(String::Type encoding) : Frame("OWNE"),
d(new OwnershipFramePrivate()) {
OwnershipFrame::OwnershipFrame(String::Type encoding) : Frame("OWNE"),d(new OwnershipFramePrivate()) {
d->textEncoding = encoding;
}
OwnershipFrame::OwnershipFrame(const ByteVector &data) : Frame(data),
d(new OwnershipFramePrivate()) {
OwnershipFrame::OwnershipFrame(const ByteVector &data) : Frame(data),d(new OwnershipFramePrivate()) {
setData(data);
}
@@ -99,6 +97,7 @@ void OwnershipFrame::setTextEncoding(String::Type encoding) {
////////////////////////////////////////////////////////////////////////////////
void OwnershipFrame::parseFields(const ByteVector &data) {
int pos = 0;
// Get the text encoding
@@ -123,9 +122,11 @@ void OwnershipFrame::parseFields(const ByteVector &data) {
d->seller = Tag::latin1StringHandler()->parse(data.mid(pos));
else
d->seller = String(data.mid(pos), d->textEncoding);
}
ByteVector OwnershipFrame::renderFields() const {
StringList sl;
sl.append(d->seller);
@@ -140,13 +141,13 @@ ByteVector OwnershipFrame::renderFields() const {
v.append(d->seller.data(encoding));
return v;
}
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
OwnershipFrame::OwnershipFrame(const ByteVector &data, Header *h) : Frame(h),
d(new OwnershipFramePrivate()) {
OwnershipFrame::OwnershipFrame(const ByteVector &data, Header *h) : Frame(h), d(new OwnershipFramePrivate()) {
parseFields(fieldData(data));
}

View File

@@ -31,101 +31,98 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
//! An implementation of ID3v2 "ownership"
/*!
* This implements the ID3v2 ownership (OWNE frame). It consists of
* a price paid, a date purchased (YYYYMMDD) and the name of the seller.
*/
* This implements the ID3v2 ownership (OWNE frame).
* It consists of a price paid, a date purchased (YYYYMMDD) and the name of the seller.
*/
class TAGLIB_EXPORT OwnershipFrame : public Frame {
friend class FrameFactory;
public:
/*!
* Construct an empty ownership frame.
*/
* Construct an empty ownership frame.
*/
explicit OwnershipFrame(String::Type encoding = String::Latin1);
/*!
* Construct a ownership based on the data in \a data.
*/
* Construct a ownership based on the data in \a data.
*/
explicit OwnershipFrame(const ByteVector &data);
/*!
* Destroys this OwnershipFrame instance.
*/
* Destroys this OwnershipFrame instance.
*/
virtual ~OwnershipFrame();
/*!
* Returns the text of this popularimeter.
*
* \see text()
*/
* Returns the text of this popularimeter.
*
* \see text()
*/
virtual String toString() const;
/*!
* Returns the date purchased.
*
* \see setDatePurchased()
*/
* Returns the date purchased.
*
* \see setDatePurchased()
*/
String datePurchased() const;
/*!
* Set the date purchased.
*
* \see datePurchased()
*/
* Set the date purchased.
*
* \see datePurchased()
*/
void setDatePurchased(const String &datePurchased);
/*!
* Returns the price paid.
*
* \see setPricePaid()
*/
* Returns the price paid.
*
* \see setPricePaid()
*/
String pricePaid() const;
/*!
* Set the price paid.
*
* \see pricePaid()
*/
* Set the price paid.
*
* \see pricePaid()
*/
void setPricePaid(const String &pricePaid);
/*!
* Returns the seller.
*
* \see setSeller()
*/
* Returns the seller.
*
* \see setSeller()
*/
String seller() const;
/*!
* Set the seller.
*
* \see seller()
*/
* Set the seller.
*
* \see seller()
*/
void setSeller(const String &seller);
/*!
* Returns the text encoding that will be used in rendering this frame.
* This defaults to the type that was either specified in the constructor
* or read from the frame when parsed.
*
* \see setTextEncoding()
* \see render()
*/
* Returns the text encoding that will be used in rendering this frame.
* This defaults to the type that was either specified in the constructor or read from the frame when parsed.
*
* \see setTextEncoding()
* \see render()
*/
String::Type textEncoding() const;
/*!
* Sets the text encoding to be used when rendering this frame to
* \a encoding.
*
* \see textEncoding()
* \see render()
*/
* Sets the text encoding to be used when rendering this frame to \a encoding.
*
* \see textEncoding()
* \see render()
*/
void setTextEncoding(String::Type encoding);
protected:
@@ -136,8 +133,8 @@ class TAGLIB_EXPORT OwnershipFrame : public Frame {
private:
/*!
* The constructor used by the FrameFactory.
*/
* The constructor used by the FrameFactory.
*/
OwnershipFrame(const ByteVector &data, Header *h);
OwnershipFrame(const OwnershipFrame &);
OwnershipFrame &operator=(const OwnershipFrame &);
@@ -149,4 +146,5 @@ class TAGLIB_EXPORT OwnershipFrame : public Frame {
} // namespace ID3v2
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@@ -37,8 +37,7 @@ class PodcastFrame::PodcastFramePrivate {
// public members
////////////////////////////////////////////////////////////////////////////////
PodcastFrame::PodcastFrame() : Frame("PCST"),
d(new PodcastFramePrivate()) {
PodcastFrame::PodcastFrame() : Frame("PCST"), d(new PodcastFramePrivate()) {
d->fieldData = ByteVector(4, '\0');
}
@@ -66,7 +65,6 @@ ByteVector PodcastFrame::renderFields() const {
// private members
////////////////////////////////////////////////////////////////////////////////
PodcastFrame::PodcastFrame(const ByteVector &data, Header *h) : Frame(h),
d(new PodcastFramePrivate()) {
PodcastFrame::PodcastFrame(const ByteVector &data, Header *h) : Frame(h), d(new PodcastFramePrivate()) {
parseFields(fieldData(data));
}

View File

@@ -31,30 +31,29 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
//! ID3v2 podcast frame
/*!
* An implementation of ID3v2 podcast flag, a frame with four zero bytes.
*/
* An implementation of ID3v2 podcast flag, a frame with four zero bytes.
*/
class TAGLIB_EXPORT PodcastFrame : public Frame {
friend class FrameFactory;
public:
/*!
* Construct a podcast frame.
*/
* Construct a podcast frame.
*/
PodcastFrame();
/*!
* Destroys this PodcastFrame instance.
*/
* Destroys this PodcastFrame instance.
*/
virtual ~PodcastFrame();
/*!
* Returns a null string.
*/
* Returns a null string.
*/
virtual String toString() const;
protected:
@@ -65,8 +64,8 @@ class TAGLIB_EXPORT PodcastFrame : public Frame {
private:
/*!
* The constructor used by the FrameFactory.
*/
* The constructor used by the FrameFactory.
*/
PodcastFrame(const ByteVector &data, Header *h);
PodcastFrame(const PodcastFrame &);
PodcastFrame &operator=(const PodcastFrame &);
@@ -78,4 +77,5 @@ class TAGLIB_EXPORT PodcastFrame : public Frame {
} // namespace ID3v2
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@@ -42,12 +42,9 @@ class PopularimeterFrame::PopularimeterFramePrivate {
// public members
////////////////////////////////////////////////////////////////////////////////
PopularimeterFrame::PopularimeterFrame() : Frame("POPM"),
d(new PopularimeterFramePrivate()) {
}
PopularimeterFrame::PopularimeterFrame() : Frame("POPM"), d(new PopularimeterFramePrivate()) {}
PopularimeterFrame::PopularimeterFrame(const ByteVector &data) : Frame(data),
d(new PopularimeterFramePrivate()) {
PopularimeterFrame::PopularimeterFrame(const ByteVector &data) : Frame(data), d(new PopularimeterFramePrivate()) {
setData(data);
}
@@ -88,6 +85,7 @@ void PopularimeterFrame::setCounter(unsigned int s) {
////////////////////////////////////////////////////////////////////////////////
void PopularimeterFrame::parseFields(const ByteVector &data) {
int pos = 0, size = int(data.size());
d->email = readStringField(data, String::Latin1, &pos);
@@ -100,9 +98,11 @@ void PopularimeterFrame::parseFields(const ByteVector &data) {
d->counter = data.toUInt(static_cast<unsigned int>(pos));
}
}
}
ByteVector PopularimeterFrame::renderFields() const {
ByteVector data;
data.append(d->email.data(String::Latin1));
@@ -111,13 +111,13 @@ ByteVector PopularimeterFrame::renderFields() const {
data.append(ByteVector::fromUInt(d->counter));
return data;
}
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
PopularimeterFrame::PopularimeterFrame(const ByteVector &data, Header *h) : Frame(h),
d(new PopularimeterFramePrivate()) {
PopularimeterFrame::PopularimeterFrame(const ByteVector &data, Header *h) : Frame(h), d(new PopularimeterFramePrivate()) {
parseFields(fieldData(data));
}

View File

@@ -31,82 +31,81 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
//! An implementation of ID3v2 "popularimeter"
/*!
* This implements the ID3v2 popularimeter (POPM frame). It consists of
* an email, a rating and an optional counter.
*/
* This implements the ID3v2 popularimeter (POPM frame).
* It consists of an email, a rating and an optional counter.
*/
class TAGLIB_EXPORT PopularimeterFrame : public Frame {
friend class FrameFactory;
public:
/*!
* Construct an empty popularimeter frame.
*/
* Construct an empty popularimeter frame.
*/
explicit PopularimeterFrame();
/*!
* Construct a popularimeter based on the data in \a data.
*/
* Construct a popularimeter based on the data in \a data.
*/
explicit PopularimeterFrame(const ByteVector &data);
/*!
* Destroys this PopularimeterFrame instance.
*/
* Destroys this PopularimeterFrame instance.
*/
virtual ~PopularimeterFrame();
/*!
* Returns the text of this popularimeter.
*
* \see text()
*/
* Returns the text of this popularimeter.
*
* \see text()
*/
virtual String toString() const;
/*!
* Returns the email.
*
* \see setEmail()
*/
* Returns the email.
*
* \see setEmail()
*/
String email() const;
/*!
* Set the email.
*
* \see email()
*/
* Set the email.
*
* \see email()
*/
void setEmail(const String &email);
/*!
* Returns the rating.
*
* \see setRating()
*/
* Returns the rating.
*
* \see setRating()
*/
int rating() const;
/*!
* Set the rating.
*
* \see rating()
*/
* Set the rating.
*
* \see rating()
*/
void setRating(int rating);
/*!
* Returns the counter.
*
* \see setCounter()
*/
* Returns the counter.
*
* \see setCounter()
*/
unsigned int counter() const;
/*!
* Set the counter.
*
* \see counter()
*/
* Set the counter.
*
* \see counter()
*/
void setCounter(unsigned int counter);
protected:
@@ -117,8 +116,8 @@ class TAGLIB_EXPORT PopularimeterFrame : public Frame {
private:
/*!
* The constructor used by the FrameFactory.
*/
* The constructor used by the FrameFactory.
*/
PopularimeterFrame(const ByteVector &data, Header *h);
PopularimeterFrame(const PopularimeterFrame &);
PopularimeterFrame &operator=(const PopularimeterFrame &);
@@ -130,4 +129,5 @@ class TAGLIB_EXPORT PopularimeterFrame : public Frame {
} // namespace ID3v2
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@@ -44,12 +44,9 @@ class PrivateFrame::PrivateFramePrivate {
// public members
////////////////////////////////////////////////////////////////////////////////
PrivateFrame::PrivateFrame() : Frame("PRIV"),
d(new PrivateFramePrivate()) {
}
PrivateFrame::PrivateFrame() : Frame("PRIV"), d(new PrivateFramePrivate()) {}
PrivateFrame::PrivateFrame(const ByteVector &data) : Frame(data),
d(new PrivateFramePrivate()) {
PrivateFrame::PrivateFrame(const ByteVector &data) : Frame(data), d(new PrivateFramePrivate()) {
setData(data);
}
@@ -82,6 +79,7 @@ void PrivateFrame::setData(const ByteVector &data) {
////////////////////////////////////////////////////////////////////////////////
void PrivateFrame::parseFields(const ByteVector &data) {
if (data.size() < 2) {
debug("A private frame must contain at least 2 bytes.");
return;
@@ -94,9 +92,11 @@ void PrivateFrame::parseFields(const ByteVector &data) {
d->owner = String(data.mid(0, endOfOwner));
d->data = data.mid(endOfOwner + 1);
}
ByteVector PrivateFrame::renderFields() const {
ByteVector v;
v.append(d->owner.data(String::Latin1));
@@ -104,13 +104,13 @@ ByteVector PrivateFrame::renderFields() const {
v.append(d->data);
return v;
}
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
PrivateFrame::PrivateFrame(const ByteVector &data, Header *h) : Frame(h),
d(new PrivateFramePrivate()) {
PrivateFrame::PrivateFrame(const ByteVector &data, Header *h) : Frame(h), d(new PrivateFramePrivate()) {
parseFields(fieldData(data));
}

View File

@@ -32,7 +32,6 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
//! An implementation of ID3v2 privateframe
@@ -42,49 +41,49 @@ class TAGLIB_EXPORT PrivateFrame : public Frame {
public:
/*!
* Construct an empty private frame.
*/
* Construct an empty private frame.
*/
PrivateFrame();
/*!
* Construct a private frame based on the data in \a data.
*
* \note This is the constructor used when parsing the frame from a file.
*/
* Construct a private frame based on the data in \a data.
*
* \note This is the constructor used when parsing the frame from a file.
*/
explicit PrivateFrame(const ByteVector &data);
/*!
* Destroys this private frame instance.
*/
* Destroys this private frame instance.
*/
virtual ~PrivateFrame();
/*!
* Returns the text of this private frame, currently just the owner.
*
* \see text()
*/
* Returns the text of this private frame, currently just the owner.
*
* \see text()
*/
virtual String toString() const;
/*!
* \return The owner of the private frame.
* \note This should contain an email address or link to a website.
*/
* \return The owner of the private frame.
* \note This should contain an email address or link to a website.
*/
String owner() const;
/*!
*
*/
*
*/
ByteVector data() const;
/*!
* Sets the owner of the frame to \a s.
* \note This should contain an email address or link to a website.
*/
* Sets the owner of the frame to \a s.
* \note This should contain an email address or link to a website.
*/
void setOwner(const String &s);
/*!
*
*/
*
*/
void setData(const ByteVector &v);
protected:
@@ -95,8 +94,8 @@ class TAGLIB_EXPORT PrivateFrame : public Frame {
private:
/*!
* The constructor used by the FrameFactory.
*/
* The constructor used by the FrameFactory.
*/
PrivateFrame(const ByteVector &data, Header *h);
PrivateFrame(const PrivateFrame &);
@@ -109,4 +108,5 @@ class TAGLIB_EXPORT PrivateFrame : public Frame {
} // namespace ID3v2
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@@ -49,12 +49,9 @@ class RelativeVolumeFrame::RelativeVolumeFramePrivate {
// public members
////////////////////////////////////////////////////////////////////////////////
RelativeVolumeFrame::RelativeVolumeFrame() : Frame("RVA2"),
d(new RelativeVolumeFramePrivate()) {
}
RelativeVolumeFrame::RelativeVolumeFrame() : Frame("RVA2"), d(new RelativeVolumeFramePrivate()) {}
RelativeVolumeFrame::RelativeVolumeFrame(const ByteVector &data) : Frame(data),
d(new RelativeVolumeFramePrivate()) {
RelativeVolumeFrame::RelativeVolumeFrame(const ByteVector &data) : Frame(data), d(new RelativeVolumeFramePrivate()) {
setData(data);
}
@@ -67,6 +64,7 @@ String RelativeVolumeFrame::toString() const {
}
List<RelativeVolumeFrame::ChannelType> RelativeVolumeFrame::channels() const {
List<ChannelType> l;
Map<ChannelType, ChannelData>::ConstIterator it = d->channels.begin();
@@ -74,17 +72,7 @@ List<RelativeVolumeFrame::ChannelType> RelativeVolumeFrame::channels() const {
l.append((*it).first);
return l;
}
// deprecated
RelativeVolumeFrame::ChannelType RelativeVolumeFrame::channelType() const {
return MasterVolume;
}
// deprecated
void RelativeVolumeFrame::setChannelType(ChannelType) {
}
short RelativeVolumeFrame::volumeAdjustmentIndex(ChannelType type) const {
@@ -148,6 +136,7 @@ void RelativeVolumeFrame::setIdentification(const String &s) {
////////////////////////////////////////////////////////////////////////////////
void RelativeVolumeFrame::parseFields(const ByteVector &data) {
int pos = 0;
d->identification = readStringField(data, String::Latin1, &pos);
@@ -170,9 +159,11 @@ void RelativeVolumeFrame::parseFields(const ByteVector &data) {
channel.peakVolume.peakVolume = data.mid(pos, bytes);
pos += bytes;
}
}
ByteVector RelativeVolumeFrame::renderFields() const {
ByteVector data;
data.append(d->identification.data(String::Latin1));
@@ -191,13 +182,13 @@ ByteVector RelativeVolumeFrame::renderFields() const {
}
return data;
}
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
RelativeVolumeFrame::RelativeVolumeFrame(const ByteVector &data, Header *h) : Frame(h),
d(new RelativeVolumeFramePrivate()) {
RelativeVolumeFrame::RelativeVolumeFrame(const ByteVector &data, Header *h) : Frame(h), d(new RelativeVolumeFramePrivate()) {
parseFields(fieldData(data));
}

View File

@@ -32,28 +32,24 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
//! An ID3v2 relative volume adjustment frame implementation
/*!
* This is an implementation of ID3v2 relative volume adjustment. The
* presence of this frame makes it possible to specify an increase in volume
* for an audio file or specific audio tracks in that file.
*
* Multiple relative volume adjustment frames may be present in the tag
* each with a unique identification and describing volume adjustment for
* different channel types.
*/
* This is an implementation of ID3v2 relative volume adjustment.
* The presence of this frame makes it possible to specify an increase in volume for an audio file or specific audio tracks in that file.
*
* Multiple relative volume adjustment frames may be present in the tag each with a unique identification and describing volume adjustment for different channel types.
*/
class TAGLIB_EXPORT RelativeVolumeFrame : public Frame {
friend class FrameFactory;
public:
/*!
* This indicates the type of volume adjustment that should be applied.
*/
* This indicates the type of volume adjustment that should be applied.
*/
enum ChannelType {
//! A type not enumerated below
Other = 0x00,
@@ -78,149 +74,125 @@ class TAGLIB_EXPORT RelativeVolumeFrame : public Frame {
//! Struct that stores the relevant values for ID3v2 peak volume
/*!
* The peak volume is described as a series of bits that is padded to fill
* a block of bytes. These two values should always be updated in tandem.
*/
* The peak volume is described as a series of bits that is padded to fill a block of bytes.
* These two values should always be updated in tandem.
*/
struct PeakVolume {
/*!
* Constructs an empty peak volume description.
*/
* Constructs an empty peak volume description.
*/
PeakVolume() : bitsRepresentingPeak(0) {}
/*!
* The number of bits (in the range of 0 to 255) used to describe the
* peak volume.
*/
* The number of bits (in the range of 0 to 255) used to describe the peak volume.
*/
unsigned char bitsRepresentingPeak;
/*!
* The array of bits (represented as a series of bytes) used to describe
* the peak volume.
*/
* The array of bits (represented as a series of bytes) used to describe the peak volume.
*/
ByteVector peakVolume;
};
/*!
* Constructs a RelativeVolumeFrame. The relevant data should be set
* manually.
*/
* Constructs a RelativeVolumeFrame. The relevant data should be set manually.
*/
RelativeVolumeFrame();
/*!
* Constructs a RelativeVolumeFrame based on the contents of \a data.
*/
* Constructs a RelativeVolumeFrame based on the contents of \a data.
*/
RelativeVolumeFrame(const ByteVector &data);
/*!
* Destroys the RelativeVolumeFrame instance.
*/
* Destroys the RelativeVolumeFrame instance.
*/
virtual ~RelativeVolumeFrame();
/*!
* Returns the frame's identification.
*
* \see identification()
*/
* Returns the frame's identification.
*
* \see identification()
*/
virtual String toString() const;
/*!
* Returns a list of channels with information currently in the frame.
*/
* Returns a list of channels with information currently in the frame.
*/
List<ChannelType> channels() const;
/*!
* \deprecated Always returns master volume.
*/
TAGLIB_DEPRECATED ChannelType channelType() const;
/*!
* \deprecated This method no longer has any effect.
*/
TAGLIB_DEPRECATED void setChannelType(ChannelType t);
/*
* There was a terrible API goof here, and while this can't be changed to
* the way it appears below for binary compatibility reasons, let's at
* least pretend that it looks clean.
*/
* There was a terrible API goof here, and while this can't be changed to the way it appears below for binary compatibility reasons, let's at least pretend that it looks clean.
*/
#ifdef DOXYGEN
/*!
* Returns the relative volume adjustment "index". As indicated by the
* ID3v2 standard this is a 16-bit signed integer that reflects the
* decibels of adjustment when divided by 512.
*
* This defaults to returning the value for the master volume channel if
* available and returns 0 if the specified channel does not exist.
*
* \see setVolumeAdjustmentIndex()
* \see volumeAjustment()
*/
* Returns the relative volume adjustment "index".
* As indicated by the ID3v2 standard this is a 16-bit signed integer that reflects the decibels of adjustment when divided by 512.
*
* This defaults to returning the value for the master volume channel if available and returns 0 if the specified channel does not exist.
*
* \see setVolumeAdjustmentIndex()
* \see volumeAjustment()
*/
short volumeAdjustmentIndex(ChannelType type = MasterVolume) const;
/*!
* Set the volume adjustment to \a index. As indicated by the ID3v2
* standard this is a 16-bit signed integer that reflects the decibels of
* adjustment when divided by 512.
*
* By default this sets the value for the master volume.
*
* \see volumeAdjustmentIndex()
* \see setVolumeAjustment()
*/
* Set the volume adjustment to \a index.
* As indicated by the ID3v2 standard this is a 16-bit signed integer that reflects the decibels of adjustment when divided by 512.
*
* By default this sets the value for the master volume.
*
* \see volumeAdjustmentIndex()
* \see setVolumeAjustment()
*/
void setVolumeAdjustmentIndex(short index, ChannelType type = MasterVolume);
/*!
* Returns the relative volume adjustment in decibels.
*
* \note Because this is actually stored internally as an "index" to this
* value the value returned by this method may not be identical to the
* value set using setVolumeAdjustment().
*
* This defaults to returning the value for the master volume channel if
* available and returns 0 if the specified channel does not exist.
*
* \see setVolumeAdjustment()
* \see volumeAdjustmentIndex()
*/
* Returns the relative volume adjustment in decibels.
*
* \note Because this is actually stored internally as an "index" to this
* value the value returned by this method may not be identical to the value set using setVolumeAdjustment().
*
* This defaults to returning the value for the master volume channel if available and returns 0 if the specified channel does not exist.
*
* \see setVolumeAdjustment()
* \see volumeAdjustmentIndex()
*/
float volumeAdjustment(ChannelType type = MasterVolume) const;
/*!
* Set the relative volume adjustment in decibels to \a adjustment.
*
* By default this sets the value for the master volume.
*
* \note Because this is actually stored internally as an "index" to this
* value the value set by this method may not be identical to the one
* returned by volumeAdjustment().
*
* \see setVolumeAdjustment()
* \see volumeAdjustmentIndex()
*/
* Set the relative volume adjustment in decibels to \a adjustment.
*
* By default this sets the value for the master volume.
*
* \note Because this is actually stored internally as an "index" to this value the value set by this method may not be identical to the one returned by volumeAdjustment().
*
* \see setVolumeAdjustment()
* \see volumeAdjustmentIndex()
*/
void setVolumeAdjustment(float adjustment, ChannelType type = MasterVolume);
/*!
* Returns the peak volume (represented as a length and a string of bits).
*
* This defaults to returning the value for the master volume channel if
* available and returns 0 if the specified channel does not exist.
*
* \see setPeakVolume()
*/
* Returns the peak volume (represented as a length and a string of bits).
*
* This defaults to returning the value for the master volume channel if available and returns 0 if the specified channel does not exist.
*
* \see setPeakVolume()
*/
PeakVolume peakVolume(ChannelType type = MasterVolume) const;
/*!
* Sets the peak volume to \a peak.
*
* By default this sets the value for the master volume.
*
* \see peakVolume()
*/
* Sets the peak volume to \a peak.
*
* By default this sets the value for the master volume.
*
* \see peakVolume()
*/
void setPeakVolume(const PeakVolume &peak, ChannelType type = MasterVolume);
#else
// BIC: Combine each of the following pairs of functions (or maybe just
// rework this junk altogether).
// BIC: Combine each of the following pairs of functions (or maybe just rework this junk altogether).
short volumeAdjustmentIndex(ChannelType type) const;
short volumeAdjustmentIndex() const;
@@ -243,15 +215,14 @@ class TAGLIB_EXPORT RelativeVolumeFrame : public Frame {
#endif
/*!
* Returns the identification for this frame.
*/
* Returns the identification for this frame.
*/
String identification() const;
/*!
* Sets the identification of the frame to \a s. The string
* is used to identify the situation and/or device where this
* adjustment should apply.
*/
* Sets the identification of the frame to \a s.
* The string is used to identify the situation and/or device where this adjustment should apply.
*/
void setIdentification(const String &s);
protected:
@@ -270,4 +241,5 @@ class TAGLIB_EXPORT RelativeVolumeFrame : public Frame {
} // namespace ID3v2
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@@ -123,6 +123,7 @@ void SynchronizedLyricsFrame::setSynchedText(
////////////////////////////////////////////////////////////////////////////////
void SynchronizedLyricsFrame::parseFields(const ByteVector &data) {
const int end = data.size();
if (end < 7) {
debug("A synchronized lyrics frame must contain at least 7 bytes.");
@@ -177,9 +178,11 @@ void SynchronizedLyricsFrame::parseFields(const ByteVector &data) {
d->synchedText.append(SynchedText(time, text));
}
}
ByteVector SynchronizedLyricsFrame::renderFields() const {
ByteVector v;
String::Type encoding = d->textEncoding;
@@ -207,6 +210,7 @@ ByteVector SynchronizedLyricsFrame::renderFields() const {
}
return v;
}
////////////////////////////////////////////////////////////////////////////////

View File

@@ -31,20 +31,19 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
//! ID3v2 synchronized lyrics frame
/*!
* An implementation of ID3v2 synchronized lyrics.
*/
* An implementation of ID3v2 synchronized lyrics.
*/
class TAGLIB_EXPORT SynchronizedLyricsFrame : public Frame {
friend class FrameFactory;
public:
/*!
* Specifies the timestamp format used.
*/
* Specifies the timestamp format used.
*/
enum TimestampFormat {
//! The timestamp is of unknown format.
Unknown = 0x00,
@@ -57,8 +56,8 @@ class TAGLIB_EXPORT SynchronizedLyricsFrame : public Frame {
};
/*!
* Specifies the type of text contained.
*/
* Specifies the type of text contained.
*/
enum Type {
//! The text is some other type of text.
Other = 0x00,
@@ -81,8 +80,8 @@ class TAGLIB_EXPORT SynchronizedLyricsFrame : public Frame {
};
/*!
* Single entry of time stamp and lyrics text.
*/
* Single entry of time stamp and lyrics text.
*/
struct SynchedText {
SynchedText(unsigned int ms, String str) : time(ms), text(str) {}
unsigned int time;
@@ -90,121 +89,117 @@ class TAGLIB_EXPORT SynchronizedLyricsFrame : public Frame {
};
/*!
* List of synchronized lyrics.
*/
* List of synchronized lyrics.
*/
typedef Strawberry_TagLib::TagLib::List<SynchedText> SynchedTextList;
/*!
* Construct an empty synchronized lyrics frame that will use the text
* encoding \a encoding.
*/
* Construct an empty synchronized lyrics frame that will use the text encoding \a encoding.
*/
explicit SynchronizedLyricsFrame(String::Type encoding = String::Latin1);
/*!
* Construct a synchronized lyrics frame based on the data in \a data.
*/
* Construct a synchronized lyrics frame based on the data in \a data.
*/
explicit SynchronizedLyricsFrame(const ByteVector &data);
/*!
* Destroys this SynchronizedLyricsFrame instance.
*/
* Destroys this SynchronizedLyricsFrame instance.
*/
virtual ~SynchronizedLyricsFrame();
/*!
* Returns the description of this synchronized lyrics frame.
*
* \see description()
*/
* Returns the description of this synchronized lyrics frame.
*
* \see description()
*/
virtual String toString() const;
/*!
* Returns the text encoding that will be used in rendering this frame.
* This defaults to the type that was either specified in the constructor
* or read from the frame when parsed.
*
* \see setTextEncoding()
* \see render()
*/
* Returns the text encoding that will be used in rendering this frame.
* This defaults to the type that was either specified in the constructor or read from the frame when parsed.
*
* \see setTextEncoding()
* \see render()
*/
String::Type textEncoding() const;
/*!
* Returns the language encoding as a 3 byte encoding as specified by
* <a href="http://en.wikipedia.org/wiki/ISO_639">ISO-639-2</a>.
*
* \note Most taggers simply ignore this value.
*
* \see setLanguage()
*/
* Returns the language encoding as a 3 byte encoding as specified by
* <a href="http://en.wikipedia.org/wiki/ISO_639">ISO-639-2</a>.
*
* \note Most taggers simply ignore this value.
*
* \see setLanguage()
*/
ByteVector language() const;
/*!
* Returns the timestamp format.
*/
* Returns the timestamp format.
*/
TimestampFormat timestampFormat() const;
/*!
* Returns the type of text contained.
*/
* Returns the type of text contained.
*/
Type type() const;
/*!
* Returns the description of this synchronized lyrics frame.
*
* \note Most taggers simply ignore this value.
*
* \see setDescription()
*/
* Returns the description of this synchronized lyrics frame.
*
* \note Most taggers simply ignore this value.
*
* \see setDescription()
*/
String description() const;
/*!
* Returns the text with the time stamps.
*/
* Returns the text with the time stamps.
*/
SynchedTextList synchedText() const;
/*!
* Sets the text encoding to be used when rendering this frame to
* \a encoding.
*
* \see textEncoding()
* \see render()
*/
* Sets the text encoding to be used when rendering this frame to \a encoding.
*
* \see textEncoding()
* \see render()
*/
void setTextEncoding(String::Type encoding);
/*!
* Set the language using the 3 byte language code from
* <a href="http://en.wikipedia.org/wiki/ISO_639">ISO-639-2</a> to
* \a languageCode.
*
* \see language()
*/
* Set the language using the 3 byte language code from
* <a href="http://en.wikipedia.org/wiki/ISO_639">ISO-639-2</a> to \a languageCode.
*
* \see language()
*/
void setLanguage(const ByteVector &languageCode);
/*!
* Set the timestamp format.
*
* \see timestampFormat()
*/
* Set the timestamp format.
*
* \see timestampFormat()
*/
void setTimestampFormat(TimestampFormat f);
/*!
* Set the type of text contained.
*
* \see type()
*/
* Set the type of text contained.
*
* \see type()
*/
void setType(Type t);
/*!
* Sets the description of the synchronized lyrics frame to \a s.
*
* \see description()
*/
* Sets the description of the synchronized lyrics frame to \a s.
*
* \see description()
*/
void setDescription(const String &s);
/*!
* Sets the text with the time stamps.
*
* \see text()
*/
* Sets the text with the time stamps.
*
* \see text()
*/
void setSynchedText(const SynchedTextList &t);
protected:
@@ -215,8 +210,8 @@ class TAGLIB_EXPORT SynchronizedLyricsFrame : public Frame {
private:
/*!
* The constructor used by the FrameFactory.
*/
* The constructor used by the FrameFactory.
*/
SynchronizedLyricsFrame(const ByteVector &data, Header *h);
SynchronizedLyricsFrame(const SynchronizedLyricsFrame &);
SynchronizedLyricsFrame &operator=(const SynchronizedLyricsFrame &);
@@ -228,4 +223,5 @@ class TAGLIB_EXPORT SynchronizedLyricsFrame : public Frame {
} // namespace ID3v2
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@@ -34,9 +34,7 @@ using namespace ID3v2;
class TableOfContentsFrame::TableOfContentsFramePrivate {
public:
TableOfContentsFramePrivate() : tagHeader(0),
isTopLevel(false),
isOrdered(false) {
TableOfContentsFramePrivate() : tagHeader(nullptr), isTopLevel(false), isOrdered(false) {
embeddedFrameList.setAutoDelete(true);
}
@@ -69,6 +67,7 @@ ByteVectorList &strip(ByteVectorList &l) {
}
return l;
}
} // namespace
////////////////////////////////////////////////////////////////////////////////
@@ -81,16 +80,15 @@ TableOfContentsFrame::TableOfContentsFrame(const ID3v2::Header *tagHeader, const
setData(data);
}
TableOfContentsFrame::TableOfContentsFrame(const ByteVector &elementID,
const ByteVectorList &children,
const FrameList &embeddedFrames) : ID3v2::Frame("CTOC"),
d(new TableOfContentsFramePrivate()) {
TableOfContentsFrame::TableOfContentsFrame(const ByteVector &elementID, const ByteVectorList &children, const FrameList &embeddedFrames) : ID3v2::Frame("CTOC"), d(new TableOfContentsFramePrivate()) {
d->elementID = elementID;
strip(d->elementID);
d->childElements = children;
for (FrameList::ConstIterator it = embeddedFrames.begin(); it != embeddedFrames.end(); ++it)
addEmbeddedFrame(*it);
}
TableOfContentsFrame::~TableOfContentsFrame() {
@@ -167,6 +165,7 @@ void TableOfContentsFrame::addEmbeddedFrame(Frame *frame) {
}
void TableOfContentsFrame::removeEmbeddedFrame(Frame *frame, bool del) {
// remove the frame from the frame list
FrameList::Iterator it = d->embeddedFrameList.find(frame);
d->embeddedFrameList.erase(it);
@@ -178,15 +177,19 @@ void TableOfContentsFrame::removeEmbeddedFrame(Frame *frame, bool del) {
// ...and delete as desired
if (del)
delete frame;
}
void TableOfContentsFrame::removeEmbeddedFrames(const ByteVector &id) {
FrameList l = d->embeddedFrameListMap[id];
for (FrameList::ConstIterator it = l.begin(); it != l.end(); ++it)
removeEmbeddedFrame(*it, true);
}
String TableOfContentsFrame::toString() const {
String s = String(d->elementID) +
": top level: " + (d->isTopLevel ? "true" : "false") +
", ordered: " + (d->isOrdered ? "true" : "false");
@@ -205,19 +208,21 @@ String TableOfContentsFrame::toString() const {
}
return s;
}
PropertyMap TableOfContentsFrame::asProperties() const {
PropertyMap map;
map.unsupportedData().append(frameID() + String("/") + d->elementID);
return map;
}
TableOfContentsFrame *TableOfContentsFrame::findByElementID(const ID3v2::Tag *tag,
const ByteVector &eID) // static
{
TableOfContentsFrame *TableOfContentsFrame::findByElementID(const ID3v2::Tag *tag, const ByteVector &eID) { // static
ID3v2::FrameList tablesOfContents = tag->frameList("CTOC");
for (ID3v2::FrameList::ConstIterator it = tablesOfContents.begin();
@@ -229,10 +234,11 @@ TableOfContentsFrame *TableOfContentsFrame::findByElementID(const ID3v2::Tag *ta
}
return nullptr;
}
TableOfContentsFrame *TableOfContentsFrame::findTopLevel(const ID3v2::Tag *tag) // static
{
TableOfContentsFrame *TableOfContentsFrame::findTopLevel(const ID3v2::Tag *tag) { // static
ID3v2::FrameList tablesOfContents = tag->frameList("CTOC");
for (ID3v2::FrameList::ConstIterator it = tablesOfContents.begin();
@@ -244,9 +250,11 @@ TableOfContentsFrame *TableOfContentsFrame::findTopLevel(const ID3v2::Tag *tag)
}
return nullptr;
}
void TableOfContentsFrame::parseFields(const ByteVector &data) {
unsigned int size = data.size();
if (size < 6) {
debug("A CTOC frame must contain at least 6 bytes (1 byte element ID terminated by "
@@ -286,9 +294,11 @@ void TableOfContentsFrame::parseFields(const ByteVector &data) {
embPos += frame->size() + header()->size();
addEmbeddedFrame(frame);
}
}
ByteVector TableOfContentsFrame::renderFields() const {
ByteVector data;
data.append(d->elementID);
@@ -311,11 +321,10 @@ ByteVector TableOfContentsFrame::renderFields() const {
data.append((*it2)->render());
return data;
}
TableOfContentsFrame::TableOfContentsFrame(const ID3v2::Header *tagHeader,
const ByteVector &data, Header *h) : Frame(h),
d(new TableOfContentsFramePrivate()) {
TableOfContentsFrame::TableOfContentsFrame(const ID3v2::Header *tagHeader, const ByteVector &data, Header *h) : Frame(h), d(new TableOfContentsFramePrivate()) {
d->tagHeader = tagHeader;
parseFields(fieldData(data));
}

View File

@@ -33,13 +33,12 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
/*!
* This is an implementation of ID3v2 table of contents frames. Purpose
* of this frame is to allow a table of contents to be defined.
*/
* This is an implementation of ID3v2 table of contents frames.
* Purpose of this frame is to allow a table of contents to be defined.
*/
//! An implementation of ID3v2 table of contents frames
@@ -48,176 +47,159 @@ class TAGLIB_EXPORT TableOfContentsFrame : public ID3v2::Frame {
public:
/*!
* Creates a table of contents frame based on \a data. \a tagHeader is
* required as the internal frames are parsed based on the tag version.
*/
* Creates a table of contents frame based on \a data.
* \a tagHeader is required as the internal frames are parsed based on the tag version.
*/
TableOfContentsFrame(const ID3v2::Header *tagHeader, const ByteVector &data);
/*!
* Creates a table of contents frame with the element ID \a elementID,
* the child elements \a children and embedded frames, which become owned
* by this frame, in \a embeddedFrames.
*/
* Creates a table of contents frame with the element ID \a elementID,
* the child elements \a children and embedded frames, which become owned by this frame, in \a embeddedFrames.
*/
TableOfContentsFrame(const ByteVector &elementID,
const ByteVectorList &children = ByteVectorList(),
const FrameList &embeddedFrames = FrameList());
/*!
* Destroys the frame.
*/
* Destroys the frame.
*/
~TableOfContentsFrame();
/*!
* Returns the elementID of the frame. Element ID
* is a null terminated string, however it's not human-readable.
*
* \see setElementID()
*/
* Returns the elementID of the frame.
* Element ID is a null terminated string, however it's not human-readable.
*
* \see setElementID()
*/
ByteVector elementID() const;
/*!
* Returns true, if the frame is top-level (doesn't have
* any parent CTOC frame).
*
* \see setIsTopLevel()
*/
* Returns true, if the frame is top-level (doesn't have any parent CTOC frame).
*
* \see setIsTopLevel()
*/
bool isTopLevel() const;
/*!
* Returns true, if the child elements list entries
* are ordered.
*
* \see setIsOrdered()
*/
* Returns true, if the child elements list entries are ordered.
*
* \see setIsOrdered()
*/
bool isOrdered() const;
/*!
* Returns count of child elements of the frame. It always
* corresponds to size of child elements list.
*
* \see childElements()
*/
* Returns count of child elements of the frame. It always corresponds to size of child elements list.
*
* \see childElements()
*/
unsigned int entryCount() const;
/*!
* Returns list of child elements of the frame.
*
* \see setChildElements()
*/
* Returns list of child elements of the frame.
*
* \see setChildElements()
*/
ByteVectorList childElements() const;
/*!
* Sets the elementID of the frame to \a eID. If \a eID isn't
* null terminated, a null char is appended automatically.
*
* \see elementID()
*/
* Sets the elementID of the frame to \a eID. If \a eID isn't null terminated, a null char is appended automatically.
*
* \see elementID()
*/
void setElementID(const ByteVector &eID);
/*!
* Sets, if the frame is top-level (doesn't have
* any parent CTOC frame).
*
* \see isTopLevel()
*/
* Sets, if the frame is top-level (doesn't have any parent CTOC frame).
*
* \see isTopLevel()
*/
void setIsTopLevel(const bool &t);
/*!
* Sets, if the child elements list entries
* are ordered.
*
* \see isOrdered()
*/
* Sets, if the child elements list entries are ordered.
*
* \see isOrdered()
*/
void setIsOrdered(const bool &o);
/*!
* Sets list of child elements of the frame to \a l.
*
* \see childElements()
*/
* Sets list of child elements of the frame to \a l.
*
* \see childElements()
*/
void setChildElements(const ByteVectorList &l);
/*!
* Adds \a cE to list of child elements of the frame.
*
* \see childElements()
*/
* Adds \a cE to list of child elements of the frame.
*
* \see childElements()
*/
void addChildElement(const ByteVector &cE);
/*!
* Removes \a cE to list of child elements of the frame.
*
* \see childElements()
*/
* Removes \a cE to list of child elements of the frame.
*
* \see childElements()
*/
void removeChildElement(const ByteVector &cE);
/*!
* Returns a reference to the frame list map. This is an FrameListMap of
* all of the frames embedded in the CTOC frame.
*
* This is the most convenient structure for accessing the CTOC frame's
* embedded frames. Many frame types allow multiple instances of the same
* frame type so this is a map of lists. In most cases however there will
* only be a single frame of a certain type.
*
* \warning You should not modify this data structure directly, instead
* use addEmbeddedFrame() and removeEmbeddedFrame().
*
* \see embeddedFrameList()
*/
* Returns a reference to the frame list map.
* This is an FrameListMap of all of the frames embedded in the CTOC frame.
*
* This is the most convenient structure for accessing the CTOC frame's embedded frames.
* Many frame types allow multiple instances of the same frame type so this is a map of lists.
* In most cases however there will only be a single frame of a certain type.
*
* \warning You should not modify this data structure directly, instead use addEmbeddedFrame() and removeEmbeddedFrame().
*
* \see embeddedFrameList()
*/
const FrameListMap &embeddedFrameListMap() const;
/*!
* Returns a reference to the embedded frame list. This is an FrameList
* of all of the frames embedded in the CTOC frame in the order that they
* were parsed.
*
* This can be useful if for example you want iterate over the CTOC frame's
* embedded frames in the order that they occur in the CTOC frame.
*
* \warning You should not modify this data structure directly, instead
* use addEmbeddedFrame() and removeEmbeddedFrame().
*/
* Returns a reference to the embedded frame list.
* This is an FrameList of all of the frames embedded in the CTOC frame in the order that they were parsed.
*
* This can be useful if for example you want iterate over the CTOC frame's embedded frames in the order that they occur in the CTOC frame.
*
* \warning You should not modify this data structure directly, instead use addEmbeddedFrame() and removeEmbeddedFrame().
*/
const FrameList &embeddedFrameList() const;
/*!
* Returns the embedded frame list for frames with the id \a frameID
* or an empty list if there are no embedded frames of that type. This
* is just a convenience and is equivalent to:
*
* \code
* embeddedFrameListMap()[frameID];
* \endcode
*
* \see embeddedFrameListMap()
*/
* Returns the embedded frame list for frames with the id \a frameID or an empty list if there are no embedded frames of that type.
* This is just a convenience and is equivalent to:
*
* \code
* embeddedFrameListMap()[frameID];
* \endcode
*
* \see embeddedFrameListMap()
*/
const FrameList &embeddedFrameList(const ByteVector &frameID) const;
/*!
* Add an embedded frame to the CTOC frame. At this point the CTOC frame
* takes ownership of the embedded frame and will handle freeing its memory.
*
* \note Using this method will invalidate any pointers on the list
* returned by embeddedFrameList()
*/
* Add an embedded frame to the CTOC frame.
* At this point the CTOC frame takes ownership of the embedded frame and will handle freeing its memory.
*
* \note Using this method will invalidate any pointers on the list returned by embeddedFrameList()
*/
void addEmbeddedFrame(Frame *frame);
/*!
* Remove an embedded frame from the CTOC frame. If \a del is true the frame's
* memory will be freed; if it is false, it must be deleted by the user.
*
* \note Using this method will invalidate any pointers on the list
* returned by embeddedFrameList()
*/
* Remove an embedded frame from the CTOC frame.
* If \a del is true the frame's memory will be freed; if it is false, it must be deleted by the user.
*
* \note Using this method will invalidate any pointers on the list returned by embeddedFrameList()
*/
void removeEmbeddedFrame(Frame *frame, bool del = true);
/*!
* Remove all embedded frames of type \a id from the CTOC frame and free their
* memory.
*
* \note Using this method will invalidate any pointers on the list
* returned by embeddedFrameList()
*/
* Remove all embedded frames of type \a id from the CTOC frame and free their memory.
*
* \note Using this method will invalidate any pointers on the list returned by embeddedFrameList()
*/
void removeEmbeddedFrames(const ByteVector &id);
virtual String toString() const;
@@ -225,21 +207,21 @@ class TAGLIB_EXPORT TableOfContentsFrame : public ID3v2::Frame {
PropertyMap asProperties() const;
/*!
* CTOC frames each have a unique element ID. This searches for a CTOC
* frame with the element ID \a eID and returns a pointer to it. This
* can be used to link together parent and child CTOC frames.
*
* \see elementID()
*/
* CTOC frames each have a unique element ID.
* This searches for a CTOC frame with the element ID \a eID and returns a pointer to it.
* This can be used to link together parent and child CTOC frames.
*
* \see elementID()
*/
static TableOfContentsFrame *findByElementID(const Tag *tag, const ByteVector &eID);
/*!
* CTOC frames each contain a flag that indicates, if CTOC frame is top-level (there isn't
* any frame, which contains this frame in its child elements list). Only a single frame
* within tag can be top-level. This searches for a top-level CTOC frame.
*
* \see isTopLevel()
*/
* CTOC frames each contain a flag that indicates,
* if CTOC frame is top-level (there isn't any frame, which contains this frame in its child elements list).
* Only a single frame within tag can be top-level. This searches for a top-level CTOC frame.
*
* \see isTopLevel()
*/
static TableOfContentsFrame *findTopLevel(const Tag *tag);
protected:
@@ -254,6 +236,7 @@ class TAGLIB_EXPORT TableOfContentsFrame : public ID3v2::Frame {
class TableOfContentsFramePrivate;
TableOfContentsFramePrivate *d;
};
} // namespace ID3v2
} // namespace TagLib
} // namespace Strawberry_TagLib

View File

@@ -53,8 +53,8 @@ TextIdentificationFrame::TextIdentificationFrame(const ByteVector &data) : Frame
setData(data);
}
TextIdentificationFrame *TextIdentificationFrame::createTIPLFrame(const PropertyMap &properties) // static
{
TextIdentificationFrame *TextIdentificationFrame::createTIPLFrame(const PropertyMap &properties) { // static
TextIdentificationFrame *frame = new TextIdentificationFrame("TIPL");
StringList l;
for (PropertyMap::ConstIterator it = properties.begin(); it != properties.end(); ++it) {
@@ -63,10 +63,11 @@ TextIdentificationFrame *TextIdentificationFrame::createTIPLFrame(const Property
}
frame->setText(l);
return frame;
}
TextIdentificationFrame *TextIdentificationFrame::createTMCLFrame(const PropertyMap &properties) // static
{
TextIdentificationFrame *TextIdentificationFrame::createTMCLFrame(const PropertyMap &properties) { // static
TextIdentificationFrame *frame = new TextIdentificationFrame("TMCL");
StringList l;
for (PropertyMap::ConstIterator it = properties.begin(); it != properties.end(); ++it) {
@@ -77,6 +78,7 @@ TextIdentificationFrame *TextIdentificationFrame::createTMCLFrame(const Property
}
frame->setText(l);
return frame;
}
TextIdentificationFrame::~TextIdentificationFrame() {
@@ -119,17 +121,19 @@ const char *involvedPeople[][2] = {
const size_t involvedPeopleSize = sizeof(involvedPeople) / sizeof(involvedPeople[0]);
} // namespace
const KeyConversionMap &TextIdentificationFrame::involvedPeopleMap() // static
{
const KeyConversionMap &TextIdentificationFrame::involvedPeopleMap() { // static
static KeyConversionMap m;
if (m.isEmpty()) {
for (size_t i = 0; i < involvedPeopleSize; ++i)
m.insert(involvedPeople[i][1], involvedPeople[i][0]);
}
return m;
}
PropertyMap TextIdentificationFrame::asProperties() const {
if (frameID() == "TIPL")
return makeTIPLProperties();
if (frameID() == "TMCL")
@@ -163,6 +167,7 @@ PropertyMap TextIdentificationFrame::asProperties() const {
PropertyMap ret;
ret.insert(tagName, values);
return ret;
}
////////////////////////////////////////////////////////////////////////////////
@@ -170,6 +175,7 @@ PropertyMap TextIdentificationFrame::asProperties() const {
////////////////////////////////////////////////////////////////////////////////
void TextIdentificationFrame::parseFields(const ByteVector &data) {
// Don't try to parse invalid frames
if (data.size() < 2)
@@ -209,9 +215,11 @@ void TextIdentificationFrame::parseFields(const ByteVector &data) {
d->fieldList.append(String(*it, d->textEncoding));
}
}
}
ByteVector TextIdentificationFrame::renderFields() const {
String::Type encoding = checkTextEncoding(d->fieldList, d->textEncoding);
ByteVector v;
@@ -231,6 +239,7 @@ ByteVector TextIdentificationFrame::renderFields() const {
}
return v;
}
////////////////////////////////////////////////////////////////////////////////
@@ -243,6 +252,7 @@ TextIdentificationFrame::TextIdentificationFrame(const ByteVector &data, Header
}
PropertyMap TextIdentificationFrame::makeTIPLProperties() const {
PropertyMap map;
if (fieldList().size() % 2 != 0) {
// according to the ID3 spec, TIPL must contain an even number of entries
@@ -266,9 +276,11 @@ PropertyMap TextIdentificationFrame::makeTIPLProperties() const {
}
}
return map;
}
PropertyMap TextIdentificationFrame::makeTMCLProperties() const {
PropertyMap map;
if (fieldList().size() % 2 != 0) {
// according to the ID3 spec, TMCL must contain an even number of entries
@@ -287,14 +299,14 @@ PropertyMap TextIdentificationFrame::makeTMCLProperties() const {
map.insert(L"PERFORMER:" + instrument, (++it)->split(","));
}
return map;
}
////////////////////////////////////////////////////////////////////////////////
// UserTextIdentificationFrame public members
////////////////////////////////////////////////////////////////////////////////
UserTextIdentificationFrame::UserTextIdentificationFrame(String::Type encoding) : TextIdentificationFrame("TXXX", encoding),
d(0) {
UserTextIdentificationFrame::UserTextIdentificationFrame(String::Type encoding) : TextIdentificationFrame("TXXX", encoding), d(nullptr) {
StringList l;
l.append(String());
l.append(String());
@@ -306,13 +318,13 @@ UserTextIdentificationFrame::UserTextIdentificationFrame(const ByteVector &data)
checkFields();
}
UserTextIdentificationFrame::UserTextIdentificationFrame(const String &description, const StringList &values, String::Type encoding) : TextIdentificationFrame("TXXX", encoding),
d(0) {
UserTextIdentificationFrame::UserTextIdentificationFrame(const String &description, const StringList &values, String::Type encoding) : TextIdentificationFrame("TXXX", encoding), d(nullptr) {
setDescription(description);
setText(values);
}
String UserTextIdentificationFrame::toString() const {
// first entry is the description itself, drop from values list
StringList l = fieldList();
for (StringList::Iterator it = l.begin(); it != l.end(); ++it) {
@@ -320,6 +332,7 @@ String UserTextIdentificationFrame::toString() const {
break;
}
return "[" + description() + "] " + l.toString();
}
String UserTextIdentificationFrame::description() const {
@@ -347,6 +360,7 @@ void UserTextIdentificationFrame::setText(const StringList &fields) {
}
void UserTextIdentificationFrame::setDescription(const String &s) {
StringList l = fieldList();
if (l.isEmpty())
@@ -355,21 +369,22 @@ void UserTextIdentificationFrame::setDescription(const String &s) {
l[0] = s;
TextIdentificationFrame::setText(l);
}
PropertyMap UserTextIdentificationFrame::asProperties() const {
PropertyMap map;
String tagName = txxxToKey(description());
StringList v = fieldList();
for (StringList::ConstIterator it = v.begin(); it != v.end(); ++it)
if (it != v.begin())
map.insert(tagName, *it);
if (it != v.begin()) map.insert(tagName, *it);
return map;
}
UserTextIdentificationFrame *UserTextIdentificationFrame::find(
ID3v2::Tag *tag, const String &description) // static
{
UserTextIdentificationFrame *UserTextIdentificationFrame::find(ID3v2::Tag *tag, const String &description) { // static
FrameList l = tag->frameList("TXXX");
for (FrameList::ConstIterator it = l.begin(); it != l.end(); ++it) {
UserTextIdentificationFrame *f = dynamic_cast<UserTextIdentificationFrame *>(*it);
@@ -377,6 +392,7 @@ UserTextIdentificationFrame *UserTextIdentificationFrame::find(
return f;
}
return nullptr;
}
////////////////////////////////////////////////////////////////////////////////
@@ -388,10 +404,12 @@ UserTextIdentificationFrame::UserTextIdentificationFrame(const ByteVector &data,
}
void UserTextIdentificationFrame::checkFields() {
int fields = fieldList().size();
if (fields == 0)
setDescription(String());
if (fields <= 1)
setText(String());
}

View File

@@ -34,7 +34,6 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
class Tag;
@@ -43,117 +42,111 @@ typedef Map<String, String> KeyConversionMap;
//! An ID3v2 text identification frame implementation
/*!
* This is an implementation of the most common type of ID3v2 frame -- text
* identification frames. There are a number of variations on this. Those
* enumerated in the ID3v2.4 standard are:
*
* <ul>
* <li><b>TALB</b> Album/Movie/Show title</li>
* <li><b>TBPM</b> BPM (beats per minute)</li>
* <li><b>TCOM</b> Composer</li>
* <li><b>TCON</b> Content type</li>
* <li><b>TCOP</b> Copyright message</li>
* <li><b>TDEN</b> Encoding time</li>
* <li><b>TDLY</b> Playlist delay</li>
* <li><b>TDOR</b> Original release time</li>
* <li><b>TDRC</b> Recording time</li>
* <li><b>TDRL</b> Release time</li>
* <li><b>TDTG</b> Tagging time</li>
* <li><b>TENC</b> Encoded by</li>
* <li><b>TEXT</b> Lyricist/Text writer</li>
* <li><b>TFLT</b> File type</li>
* <li><b>TIPL</b> Involved people list</li>
* <li><b>TIT1</b> Content group description</li>
* <li><b>TIT2</b> Title/songname/content description</li>
* <li><b>TIT3</b> Subtitle/Description refinement</li>
* <li><b>TKEY</b> Initial key</li>
* <li><b>TLAN</b> Language(s)</li>
* <li><b>TLEN</b> Length</li>
* <li><b>TMCL</b> Musician credits list</li>
* <li><b>TMED</b> Media type</li>
* <li><b>TMOO</b> Mood</li>
* <li><b>TOAL</b> Original album/movie/show title</li>
* <li><b>TOFN</b> Original filename</li>
* <li><b>TOLY</b> Original lyricist(s)/text writer(s)</li>
* <li><b>TOPE</b> Original artist(s)/performer(s)</li>
* <li><b>TOWN</b> File owner/licensee</li>
* <li><b>TPE1</b> Lead performer(s)/Soloist(s)</li>
* <li><b>TPE2</b> Band/orchestra/accompaniment</li>
* <li><b>TPE3</b> Conductor/performer refinement</li>
* <li><b>TPE4</b> Interpreted, remixed, or otherwise modified by</li>
* <li><b>TPOS</b> Part of a set</li>
* <li><b>TPRO</b> Produced notice</li>
* <li><b>TPUB</b> Publisher</li>
* <li><b>TRCK</b> Track number/Position in set</li>
* <li><b>TRSN</b> Internet radio station name</li>
* <li><b>TRSO</b> Internet radio station owner</li>
* <li><b>TSOA</b> Album sort order</li>
* <li><b>TSOP</b> Performer sort order</li>
* <li><b>TSOT</b> Title sort order</li>
* <li><b>TSRC</b> ISRC (international standard recording code)</li>
* <li><b>TSSE</b> Software/Hardware and settings used for encoding</li>
* <li><b>TSST</b> Set subtitle</li>
* </ul>
*
* The ID3v2 Frames document gives a description of each of these formats
* and the expected order of strings in each. ID3v2::Header::frameID() can
* be used to determine the frame type.
*
* \note If non-Latin1 compatible strings are used with this class, even if
* the text encoding is set to Latin1, the frame will be written using UTF8
* (with the encoding flag appropriately set in the output).
*/
* This is an implementation of the most common type of ID3v2 frame -- text identification frames.
* There are a number of variations on this. Those enumerated in the ID3v2.4 standard are:
*
* <ul>
* <li><b>TALB</b> Album/Movie/Show title</li>
* <li><b>TBPM</b> BPM (beats per minute)</li>
* <li><b>TCOM</b> Composer</li>
* <li><b>TCON</b> Content type</li>
* <li><b>TCOP</b> Copyright message</li>
* <li><b>TDEN</b> Encoding time</li>
* <li><b>TDLY</b> Playlist delay</li>
* <li><b>TDOR</b> Original release time</li>
* <li><b>TDRC</b> Recording time</li>
* <li><b>TDRL</b> Release time</li>
* <li><b>TDTG</b> Tagging time</li>
* <li><b>TENC</b> Encoded by</li>
* <li><b>TEXT</b> Lyricist/Text writer</li>
* <li><b>TFLT</b> File type</li>
* <li><b>TIPL</b> Involved people list</li>
* <li><b>TIT1</b> Content group description</li>
* <li><b>TIT2</b> Title/songname/content description</li>
* <li><b>TIT3</b> Subtitle/Description refinement</li>
* <li><b>TKEY</b> Initial key</li>
* <li><b>TLAN</b> Language(s)</li>
* <li><b>TLEN</b> Length</li>
* <li><b>TMCL</b> Musician credits list</li>
* <li><b>TMED</b> Media type</li>
* <li><b>TMOO</b> Mood</li>
* <li><b>TOAL</b> Original album/movie/show title</li>
* <li><b>TOFN</b> Original filename</li>
* <li><b>TOLY</b> Original lyricist(s)/text writer(s)</li>
* <li><b>TOPE</b> Original artist(s)/performer(s)</li>
* <li><b>TOWN</b> File owner/licensee</li>
* <li><b>TPE1</b> Lead performer(s)/Soloist(s)</li>
* <li><b>TPE2</b> Band/orchestra/accompaniment</li>
* <li><b>TPE3</b> Conductor/performer refinement</li>
* <li><b>TPE4</b> Interpreted, remixed, or otherwise modified by</li>
* <li><b>TPOS</b> Part of a set</li>
* <li><b>TPRO</b> Produced notice</li>
* <li><b>TPUB</b> Publisher</li>
* <li><b>TRCK</b> Track number/Position in set</li>
* <li><b>TRSN</b> Internet radio station name</li>
* <li><b>TRSO</b> Internet radio station owner</li>
* <li><b>TSOA</b> Album sort order</li>
* <li><b>TSOP</b> Performer sort order</li>
* <li><b>TSOT</b> Title sort order</li>
* <li><b>TSRC</b> ISRC (international standard recording code)</li>
* <li><b>TSSE</b> Software/Hardware and settings used for encoding</li>
* <li><b>TSST</b> Set subtitle</li>
* </ul>
*
* The ID3v2 Frames document gives a description of each of these formats
* and the expected order of strings in each.
* ID3v2::Header::frameID() can be used to determine the frame type.
*
* \note If non-Latin1 compatible strings are used with this class,
* even if the text encoding is set to Latin1, the frame will be written using UTF8
* (with the encoding flag appropriately set in the output).
*/
class TAGLIB_EXPORT TextIdentificationFrame : public Frame {
friend class FrameFactory;
public:
/*!
* Construct an empty frame of type \a type. Uses \a encoding as the
* default text encoding.
*
* \note In this case you must specify the text encoding as it
* resolves the ambiguity between constructors.
*
* \note Please see the note in the class description regarding Latin1.
*/
* Construct an empty frame of type \a type.
* Uses \a encoding as the default text encoding.
*
* \note In this case you must specify the text encoding as it resolves the ambiguity between constructors.
*
* \note Please see the note in the class description regarding Latin1.
*/
TextIdentificationFrame(const ByteVector &type, String::Type encoding);
/*!
* This is a dual purpose constructor. \a data can either be binary data
* that should be parsed or (at a minimum) the frame ID.
*/
* This is a dual purpose constructor.
* \a data can either be binary data that should be parsed or (at a minimum) the frame ID.
*/
explicit TextIdentificationFrame(const ByteVector &data);
/*!
* This is a special factory method to create a TIPL (involved people list)
* frame from the given \a properties. Will parse key=[list of values] data
* into the TIPL format as specified in the ID3 standard.
*/
* This is a special factory method to create a TIPL (involved people list) frame from the given \a properties.
* Will parse key=[list of values] data into the TIPL format as specified in the ID3 standard.
*/
static TextIdentificationFrame *createTIPLFrame(const PropertyMap &properties);
/*!
* This is a special factory method to create a TMCL (musician credits list)
* frame from the given \a properties. Will parse key=[list of values] data
* into the TMCL format as specified in the ID3 standard, where key should be
* of the form instrumentPrefix:instrument.
*/
* This is a special factory method to create a TMCL (musician credits list) frame from the given \a properties.
* Will parse key=[list of values] data into the TMCL format as specified in the ID3 standard, where key should be of the form instrumentPrefix:instrument.
*/
static TextIdentificationFrame *createTMCLFrame(const PropertyMap &properties);
/*!
* Destroys this TextIdentificationFrame instance.
*/
* Destroys this TextIdentificationFrame instance.
*/
virtual ~TextIdentificationFrame();
/*!
* Text identification frames are a list of string fields.
*
* This function will accept either a StringList or a String (using the
* StringList constructor that accepts a single String).
*
* \note This will not change the text encoding of the frame even if the
* strings passed in are not of the same encoding. Please use
* setEncoding(s.type()) if you wish to change the encoding of the frame.
*/
* Text identification frames are a list of string fields.
*
* This function will accept either a StringList or a String (using the
* StringList constructor that accepts a single String).
*
* \note This will not change the text encoding of the frame even if the strings passed in are not of the same encoding.
* Please use setEncoding(s.type()) if you wish to change the encoding of the frame.
*/
void setText(const StringList &l);
// Reimplementations.
@@ -162,37 +155,34 @@ class TAGLIB_EXPORT TextIdentificationFrame : public Frame {
virtual String toString() const;
/*!
* Returns the text encoding that will be used in rendering this frame.
* This defaults to the type that was either specified in the constructor
* or read from the frame when parsed.
*
* \note Please see the note in the class description regarding Latin1.
*
* \see setTextEncoding()
* \see render()
*/
* Returns the text encoding that will be used in rendering this frame.
* This defaults to the type that was either specified in the constructor or read from the frame when parsed.
*
* \note Please see the note in the class description regarding Latin1.
*
* \see setTextEncoding()
* \see render()
*/
String::Type textEncoding() const;
/*!
* Sets the text encoding to be used when rendering this frame to
* \a encoding.
*
* \note Please see the note in the class description regarding Latin1.
*
* \see textEncoding()
* \see render()
*/
* Sets the text encoding to be used when rendering this frame to \a encoding.
*
* \note Please see the note in the class description regarding Latin1.
*
* \see textEncoding()
* \see render()
*/
void setTextEncoding(String::Type encoding);
/*!
* Returns a list of the strings in this frame.
*/
* Returns a list of the strings in this frame.
*/
StringList fieldList() const;
/*!
* Returns a KeyConversionMap mapping a role as it would be used in a PropertyMap
* to the corresponding key used in a TIPL ID3 frame to describe that role.
*/
* Returns a KeyConversionMap mapping a role as it would be used in a PropertyMap to the corresponding key used in a TIPL ID3 frame to describe that role.
*/
static const KeyConversionMap &involvedPeopleMap();
PropertyMap asProperties() const;
@@ -204,8 +194,8 @@ class TAGLIB_EXPORT TextIdentificationFrame : public Frame {
virtual ByteVector renderFields() const;
/*!
* The constructor used by the FrameFactory.
*/
* The constructor used by the FrameFactory.
*/
TextIdentificationFrame(const ByteVector &data, Header *h);
private:
@@ -213,26 +203,25 @@ class TAGLIB_EXPORT TextIdentificationFrame : public Frame {
TextIdentificationFrame &operator=(const TextIdentificationFrame &);
/*!
* Parses the special structure of a TIPL frame
* Only the whitelisted roles "ARRANGER", "ENGINEER", "PRODUCER",
* "DJMIXER" (ID3: "DJ-MIX") and "MIXER" (ID3: "MIX") are allowed.
*/
* Parses the special structure of a TIPL frame
* Only the whitelisted roles "ARRANGER", "ENGINEER", "PRODUCER",
* "DJMIXER" (ID3: "DJ-MIX") and "MIXER" (ID3: "MIX") are allowed.
*/
PropertyMap makeTIPLProperties() const;
/*!
* Parses the special structure of a TMCL frame.
*/
* Parses the special structure of a TMCL frame.
*/
PropertyMap makeTMCLProperties() const;
class TextIdentificationFramePrivate;
TextIdentificationFramePrivate *d;
};
/*!
* This is a specialization of text identification frames that allows for
* user defined entries. Each entry has a description in addition to the
* normal list of fields that a text identification frame has.
*
* This description identifies the frame and must be unique.
*/
* This is a specialization of text identification frames that allows for user defined entries.
* Each entry has a description in addition to the normal list of fields that a text identification frame has.
*
* This description identifies the frame and must be unique.
*/
//! An ID3v2 custom text identification frame implementation
@@ -241,34 +230,32 @@ class TAGLIB_EXPORT UserTextIdentificationFrame : public TextIdentificationFrame
public:
/*!
* Constructs an empty user defined text identification frame. For this to be
* a useful frame both a description and text must be set.
*/
* Constructs an empty user defined text identification frame.
* For this to be a useful frame both a description and text must be set.
*/
explicit UserTextIdentificationFrame(String::Type encoding = String::Latin1);
/*!
* Creates a frame based on \a data.
*/
* Creates a frame based on \a data.
*/
explicit UserTextIdentificationFrame(const ByteVector &data);
/*!
* Creates a user defined text identification frame with the given \a description
* and \a values.
*/
* Creates a user defined text identification frame with the given \a description and \a values.
*/
UserTextIdentificationFrame(const String &description, const StringList &values, String::Type encoding = String::UTF8);
virtual String toString() const;
/*!
* Returns the description for this frame.
*/
* Returns the description for this frame.
*/
String description() const;
/*!
* Sets the description of the frame to \a s. \a s must be unique. You can
* check for the presence of another user defined text frame of the same type
* using find() and testing for null.
*/
* Sets the description of the frame to \a s. \a s must be unique.
* You can check for the presence of another user defined text frame of the same type using find() and testing for null.
*/
void setDescription(const String &s);
StringList fieldList() const;
@@ -276,24 +263,19 @@ class TAGLIB_EXPORT UserTextIdentificationFrame : public TextIdentificationFrame
void setText(const StringList &fields);
/*!
* A UserTextIdentificationFrame is parsed into a PropertyMap as follows:
* - the key is the frame's description, uppercased
* - if the description contains '::', only the substring after that
* separator is considered as key (compatibility with exfalso)
* - if the above rules don't yield a valid key (e.g. containing non-ASCII
* characters), the returned map will contain an entry "TXXX/<description>"
* in its unsupportedData() list.
* - The values will be copies of the fieldList().
* - If the description() appears as value in fieldList(), it will be omitted
* in the value list, in order to be compatible with TagLib which copies
* the description() into the fieldList().
*/
* A UserTextIdentificationFrame is parsed into a PropertyMap as follows:
* - the key is the frame's description, uppercased
* - if the description contains '::', only the substring after that separator is considered as key (compatibility with exfalso)
* - if the above rules don't yield a valid key (e.g. containing non-ASCII characters), the returned map will contain an entry "TXXX/<description>" in its unsupportedData() list.
* - The values will be copies of the fieldList().
* - If the description() appears as value in fieldList(), it will be omitted in the value list, in order to be compatible with TagLib which copies the description() into the fieldList().
*/
PropertyMap asProperties() const;
/*!
* Searches for the user defined text frame with the description \a description
* in \a tag. This returns null if no matching frames were found.
*/
* Searches for the user defined text frame with the description \a description in \a tag.
* This returns null if no matching frames were found.
*/
static UserTextIdentificationFrame *find(Tag *tag, const String &description);
private:
@@ -310,4 +292,5 @@ class TAGLIB_EXPORT UserTextIdentificationFrame : public TextIdentificationFrame
} // namespace ID3v2
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@@ -89,8 +89,8 @@ PropertyMap UniqueFileIdentifierFrame::asProperties() const {
return map;
}
UniqueFileIdentifierFrame *UniqueFileIdentifierFrame::findByOwner(const ID3v2::Tag *tag, const String &o) // static
{
UniqueFileIdentifierFrame *UniqueFileIdentifierFrame::findByOwner(const ID3v2::Tag *tag, const String &o) { // static
ID3v2::FrameList comments = tag->frameList("UFID");
for (ID3v2::FrameList::ConstIterator it = comments.begin();
@@ -102,9 +102,11 @@ UniqueFileIdentifierFrame *UniqueFileIdentifierFrame::findByOwner(const ID3v2::T
}
return nullptr;
}
void UniqueFileIdentifierFrame::parseFields(const ByteVector &data) {
if (data.size() < 1) {
debug("An UFID frame must contain at least 1 byte.");
return;
@@ -113,9 +115,11 @@ void UniqueFileIdentifierFrame::parseFields(const ByteVector &data) {
int pos = 0;
d->owner = readStringField(data, String::Latin1, &pos);
d->identifier = data.mid(pos);
}
ByteVector UniqueFileIdentifierFrame::renderFields() const {
ByteVector data;
data.append(d->owner.data(String::Latin1));
@@ -123,6 +127,7 @@ ByteVector UniqueFileIdentifierFrame::renderFields() const {
data.append(d->identifier);
return data;
}
UniqueFileIdentifierFrame::UniqueFileIdentifierFrame(const ByteVector &data, Header *h) : Frame(h),

View File

@@ -30,14 +30,12 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
/*!
* This is an implementation of ID3v2 unique file identifier frames. This
* frame is used to identify the file in an arbitrary database identified
* by the owner field.
*/
* This is an implementation of ID3v2 unique file identifier frames.
* This frame is used to identify the file in an arbitrary database identified by the owner field.
*/
//! An implementation of ID3v2 unique identifier frames
@@ -46,50 +44,47 @@ class TAGLIB_EXPORT UniqueFileIdentifierFrame : public ID3v2::Frame {
public:
/*!
* Creates a unique file identifier frame based on \a data.
*/
* Creates a unique file identifier frame based on \a data.
*/
UniqueFileIdentifierFrame(const ByteVector &data);
/*!
* Creates a unique file identifier frame with the owner \a owner and
* the identification \a id.
*/
* Creates a unique file identifier frame with the owner \a owner and the identification \a id.
*/
UniqueFileIdentifierFrame(const String &owner, const ByteVector &id);
/*!
* Destroys the frame.
*/
* Destroys the frame.
*/
~UniqueFileIdentifierFrame();
/*!
* Returns the owner for the frame; essentially this is the key for
* determining which identification scheme this key belongs to. This
* will usually either be an email address or URL for the person or tool
* used to create the unique identifier.
*
* \see setOwner()
*/
* Returns the owner for the frame; essentially this is the key for determining which identification scheme this key belongs to.
* This will usually either be an email address or URL for the person or tool used to create the unique identifier.
*
* \see setOwner()
*/
String owner() const;
/*!
* Returns the unique identifier. Though sometimes this is a text string
* it also may be binary data and as much should be assumed when handling
* it.
*/
* Returns the unique identifier.
* Though sometimes this is a text string it also may be binary data and as much should be assumed when handling
* it.
*/
ByteVector identifier() const;
/*!
* Sets the owner of the identification scheme to \a s.
*
* \see owner()
*/
* Sets the owner of the identification scheme to \a s.
*
* \see owner()
*/
void setOwner(const String &s);
/*!
* Sets the unique file identifier to \a v.
*
* \see identifier()
*/
* Sets the unique file identifier to \a v.
*
* \see identifier()
*/
void setIdentifier(const ByteVector &v);
virtual String toString() const;
@@ -97,11 +92,10 @@ class TAGLIB_EXPORT UniqueFileIdentifierFrame : public ID3v2::Frame {
PropertyMap asProperties() const;
/*!
* UFID frames each have a unique owner. This searches for a UFID
* frame with the owner \a o and returns a pointer to it.
*
* \see owner()
*/
* UFID frames each have a unique owner. This searches for a UFID frame with the owner \a o and returns a pointer to it.
*
* \see owner()
*/
static UniqueFileIdentifierFrame *findByOwner(const Tag *tag, const String &o);
protected:
@@ -117,6 +111,7 @@ class TAGLIB_EXPORT UniqueFileIdentifierFrame : public ID3v2::Frame {
class UniqueFileIdentifierFramePrivate;
UniqueFileIdentifierFramePrivate *d;
};
} // namespace ID3v2
} // namespace TagLib
} // namespace Strawberry_TagLib

View File

@@ -31,21 +31,19 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
//! A frame type \e unknown to TagLib.
/*!
* This class represents a frame type not known (or more often simply
* unimplemented) in TagLib. This is here provide a basic API for
* manipulating the binary data of unknown frames and to provide a means
* of rendering such \e unknown frames.
*
* Please note that a cleaner way of handling frame types that TagLib
* does not understand is to subclass ID3v2::Frame and ID3v2::FrameFactory
* to have your frame type supported through the standard ID3v2 mechanism.
*/
* This class represents a frame type not known (or more often simply unimplemented) in TagLib.
* This is here provide a basic API for
* manipulating the binary data of unknown frames and to provide a means of rendering such \e unknown frames.
*
* Please note that a cleaner way of handling frame types that TagLib does
* not understand is to subclass ID3v2::Frame and ID3v2::FrameFactory to have
* your frame type supported through the standard ID3v2 mechanism.
*/
class TAGLIB_EXPORT UnknownFrame : public Frame {
friend class FrameFactory;
@@ -57,8 +55,8 @@ class TAGLIB_EXPORT UnknownFrame : public Frame {
virtual String toString() const;
/*!
* Returns the field data (everything but the header) for this frame.
*/
* Returns the field data (everything but the header) for this frame.
*/
ByteVector data() const;
protected:
@@ -77,4 +75,5 @@ class TAGLIB_EXPORT UnknownFrame : public Frame {
} // namespace ID3v2
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@@ -100,6 +100,7 @@ void UnsynchronizedLyricsFrame::setTextEncoding(String::Type encoding) {
}
PropertyMap UnsynchronizedLyricsFrame::asProperties() const {
PropertyMap map;
String key = description().upper();
if (key.isEmpty() || key == "LYRICS")
@@ -107,10 +108,11 @@ PropertyMap UnsynchronizedLyricsFrame::asProperties() const {
else
map.insert("LYRICS:" + key, text());
return map;
}
UnsynchronizedLyricsFrame *UnsynchronizedLyricsFrame::findByDescription(const ID3v2::Tag *tag, const String &d) // static
{
UnsynchronizedLyricsFrame *UnsynchronizedLyricsFrame::findByDescription(const ID3v2::Tag *tag, const String &d) { // static
ID3v2::FrameList lyrics = tag->frameList("USLT");
for (ID3v2::FrameList::ConstIterator it = lyrics.begin(); it != lyrics.end(); ++it) {
@@ -119,12 +121,14 @@ UnsynchronizedLyricsFrame *UnsynchronizedLyricsFrame::findByDescription(const ID
return frame;
}
return nullptr;
}
////////////////////////////////////////////////////////////////////////////////
// protected members
////////////////////////////////////////////////////////////////////////////////
void UnsynchronizedLyricsFrame::parseFields(const ByteVector &data) {
if (data.size() < 5) {
debug("An unsynchronized lyrics frame must contain at least 5 bytes.");
return;
@@ -148,9 +152,11 @@ void UnsynchronizedLyricsFrame::parseFields(const ByteVector &data) {
d->text = String(l.back(), d->textEncoding);
}
}
}
ByteVector UnsynchronizedLyricsFrame::renderFields() const {
StringList sl;
sl.append(d->description);
sl.append(d->text);
@@ -166,6 +172,7 @@ ByteVector UnsynchronizedLyricsFrame::renderFields() const {
v.append(d->text.data(encoding));
return v;
}
////////////////////////////////////////////////////////////////////////////////

View File

@@ -32,128 +32,123 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
//! ID3v2 unsynchronized lyrics frame
/*!
* An implementation of ID3v2 unsynchronized lyrics.
*/
* An implementation of ID3v2 unsynchronized lyrics.
*/
class TAGLIB_EXPORT UnsynchronizedLyricsFrame : public Frame {
friend class FrameFactory;
public:
/*!
* Construct an empty unsynchronized lyrics frame that will use the text encoding
* \a encoding.
*/
* Construct an empty unsynchronized lyrics frame that will use the text encoding \a encoding.
*/
explicit UnsynchronizedLyricsFrame(String::Type encoding = String::Latin1);
/*!
* Construct a unsynchronized lyrics frame based on the data in \a data.
*/
* Construct a unsynchronized lyrics frame based on the data in \a data.
*/
explicit UnsynchronizedLyricsFrame(const ByteVector &data);
/*!
* Destroys this UnsynchronizedLyricsFrame instance.
*/
* Destroys this UnsynchronizedLyricsFrame instance.
*/
virtual ~UnsynchronizedLyricsFrame();
/*!
* Returns the text of this unsynchronized lyrics frame.
*
* \see text()
*/
* Returns the text of this unsynchronized lyrics frame.
*
* \see text()
*/
virtual String toString() const;
/*!
* Returns the language encoding as a 3 byte encoding as specified by
* <a href="http://en.wikipedia.org/wiki/ISO_639">ISO-639-2</a>.
*
* \note Most taggers simply ignore this value.
*
* \see setLanguage()
*/
* Returns the language encoding as a 3 byte encoding as specified by
* <a href="http://en.wikipedia.org/wiki/ISO_639">ISO-639-2</a>.
*
* \note Most taggers simply ignore this value.
*
* \see setLanguage()
*/
ByteVector language() const;
/*!
* Returns the description of this unsynchronized lyrics frame.
*
* \note Most taggers simply ignore this value.
*
* \see setDescription()
*/
* Returns the description of this unsynchronized lyrics frame.
*
* \note Most taggers simply ignore this value.
*
* \see setDescription()
*/
String description() const;
/*!
* Returns the text of this unsynchronized lyrics frame.
*
* \see setText()
*/
* Returns the text of this unsynchronized lyrics frame.
*
* \see setText()
*/
String text() const;
/*!
* Set the language using the 3 byte language code from
* <a href="http://en.wikipedia.org/wiki/ISO_639">ISO-639-2</a> to
* \a languageCode.
*
* \see language()
*/
* Set the language using the 3 byte language code from
* <a href="http://en.wikipedia.org/wiki/ISO_639">ISO-639-2</a> to
* \a languageCode.
*
* \see language()
*/
void setLanguage(const ByteVector &languageCode);
/*!
* Sets the description of the unsynchronized lyrics frame to \a s.
*
* \see description()
*/
* Sets the description of the unsynchronized lyrics frame to \a s.
*
* \see description()
*/
void setDescription(const String &s);
/*!
* Sets the text portion of the unsynchronized lyrics frame to \a s.
*
* \see text()
*/
* Sets the text portion of the unsynchronized lyrics frame to \a s.
*
* \see text()
*/
virtual void setText(const String &s);
/*!
* Returns the text encoding that will be used in rendering this frame.
* This defaults to the type that was either specified in the constructor
* or read from the frame when parsed.
*
* \see setTextEncoding()
* \see render()
*/
* Returns the text encoding that will be used in rendering this frame.
* This defaults to the type that was either specified in the constructor or read from the frame when parsed.
*
* \see setTextEncoding()
* \see render()
*/
String::Type textEncoding() const;
/*!
* Sets the text encoding to be used when rendering this frame to
* \a encoding.
*
* \see textEncoding()
* \see render()
*/
* Sets the text encoding to be used when rendering this frame to
* \a encoding.
*
* \see textEncoding()
* \see render()
*/
void setTextEncoding(String::Type encoding);
/*! Parses this frame as PropertyMap with a single key.
* - if description() is empty or "LYRICS", the key will be "LYRICS"
* - if description() is not a valid PropertyMap key, the frame will be
* marked unsupported by an entry "USLT/<description>" in the unsupportedData()
* attribute of the returned map.
* - otherwise, the key will be "LYRICS:<description>"
* - The single value will be the frame's text().
* Note that currently the language() field is not supported by the PropertyMap
* interface.
*/
* - if description() is empty or "LYRICS", the key will be "LYRICS"
* - if description() is not a valid PropertyMap key,
* the frame will be marked unsupported by an entry "USLT/<description>" in the unsupportedData() attribute of the returned map.
* - otherwise, the key will be "LYRICS:<description>"
* - The single value will be the frame's text().
* Note that currently the language() field is not supported by the PropertyMap interface.
*/
PropertyMap asProperties() const;
/*!
* LyricsFrames each have a unique description. This searches for a lyrics
* frame with the description \a d and returns a pointer to it. If no
* frame is found that matches the given description null is returned.
*
* \see description()
*/
* LyricsFrames each have a unique description.
* This searches for a lyrics frame with the description \a d and returns a pointer to it.
* If no frame is found that matches the given description null is returned.
*
* \see description()
*/
static UnsynchronizedLyricsFrame *findByDescription(const Tag *tag, const String &d);
protected:
@@ -164,8 +159,8 @@ class TAGLIB_EXPORT UnsynchronizedLyricsFrame : public Frame {
private:
/*!
* The constructor used by the FrameFactory.
*/
* The constructor used by the FrameFactory.
*/
UnsynchronizedLyricsFrame(const ByteVector &data, Header *h);
UnsynchronizedLyricsFrame(const UnsynchronizedLyricsFrame &);
UnsynchronizedLyricsFrame &operator=(const UnsynchronizedLyricsFrame &);

View File

@@ -77,6 +77,7 @@ String UrlLinkFrame::toString() const {
}
PropertyMap UrlLinkFrame::asProperties() const {
String key = frameIDToKey(frameID());
PropertyMap map;
if (key.isEmpty())
@@ -85,6 +86,7 @@ PropertyMap UrlLinkFrame::asProperties() const {
else
map.insert(key, url());
return map;
}
////////////////////////////////////////////////////////////////////////////////
@@ -143,6 +145,7 @@ void UserUrlLinkFrame::setDescription(const String &s) {
}
PropertyMap UserUrlLinkFrame::asProperties() const {
PropertyMap map;
String key = description().upper();
if (key.isEmpty() || key == "URL")
@@ -150,10 +153,11 @@ PropertyMap UserUrlLinkFrame::asProperties() const {
else
map.insert("URL:" + key, url());
return map;
}
UserUrlLinkFrame *UserUrlLinkFrame::find(ID3v2::Tag *tag, const String &description) // static
{
UserUrlLinkFrame *UserUrlLinkFrame::find(ID3v2::Tag *tag, const String &description) { // static
FrameList l = tag->frameList("WXXX");
for (FrameList::ConstIterator it = l.begin(); it != l.end(); ++it) {
UserUrlLinkFrame *f = dynamic_cast<UserUrlLinkFrame *>(*it);
@@ -161,6 +165,7 @@ UserUrlLinkFrame *UserUrlLinkFrame::find(ID3v2::Tag *tag, const String &descript
return f;
}
return nullptr;
}
////////////////////////////////////////////////////////////////////////////////
@@ -168,6 +173,7 @@ UserUrlLinkFrame *UserUrlLinkFrame::find(ID3v2::Tag *tag, const String &descript
////////////////////////////////////////////////////////////////////////////////
void UserUrlLinkFrame::parseFields(const ByteVector &data) {
if (data.size() < 2) {
debug("A user URL link frame must contain at least 2 bytes.");
return;
@@ -196,9 +202,11 @@ void UserUrlLinkFrame::parseFields(const ByteVector &data) {
}
setUrl(String(data.mid(pos)));
}
ByteVector UserUrlLinkFrame::renderFields() const {
ByteVector v;
String::Type encoding = checkTextEncoding(d->description, d->textEncoding);
@@ -209,6 +217,7 @@ ByteVector UserUrlLinkFrame::renderFields() const {
v.append(url().data(String::Latin1));
return v;
}
UserUrlLinkFrame::UserUrlLinkFrame(const ByteVector &data, Header *h) : UrlLinkFrame(data, h),

View File

@@ -33,36 +33,35 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
//! ID3v2 URL frame
/*!
* An implementation of ID3v2 URL link frames.
*/
* An implementation of ID3v2 URL link frames.
*/
class TAGLIB_EXPORT UrlLinkFrame : public Frame {
friend class FrameFactory;
public:
/*!
* This is a dual purpose constructor. \a data can either be binary data
* that should be parsed or (at a minimum) the frame ID.
*/
* This is a dual purpose constructor. \a data can either be binary data
* that should be parsed or (at a minimum) the frame ID.
*/
explicit UrlLinkFrame(const ByteVector &data);
/*!
* Destroys this UrlLinkFrame instance.
*/
* Destroys this UrlLinkFrame instance.
*/
virtual ~UrlLinkFrame();
/*!
* Returns the URL.
*/
* Returns the URL.
*/
virtual String url() const;
/*!
* Sets the URL to \a s.
*/
* Sets the URL to \a s.
*/
virtual void setUrl(const String &s);
// Reimplementations.
@@ -76,8 +75,8 @@ class TAGLIB_EXPORT UrlLinkFrame : public Frame {
virtual ByteVector renderFields() const;
/*!
* The constructor used by the FrameFactory.
*/
* The constructor used by the FrameFactory.
*/
UrlLinkFrame(const ByteVector &data, Header *h);
private:
@@ -91,31 +90,30 @@ class TAGLIB_EXPORT UrlLinkFrame : public Frame {
//! ID3v2 User defined URL frame
/*!
* This is a specialization of URL link frames that allows for
* user defined entries. Each entry has a description in addition to the
* normal list of fields that a URL link frame has.
*
* This description identifies the frame and must be unique.
*/
* This is a specialization of URL link frames that allows for user defined entries.
* Each entry has a description in addition to the normal list of fields that a URL link frame has.
*
* This description identifies the frame and must be unique.
*/
class TAGLIB_EXPORT UserUrlLinkFrame : public UrlLinkFrame {
friend class FrameFactory;
public:
/*!
* Constructs an empty user defined URL link frame. For this to be
* a useful frame both a description and text must be set.
*/
* Constructs an empty user defined URL link frame.
* For this to be a useful frame both a description and text must be set.
*/
explicit UserUrlLinkFrame(String::Type encoding = String::Latin1);
/*!
* This is a dual purpose constructor. \a data can either be binary data
* that should be parsed or (at a minimum) the frame ID.
*/
* This is a dual purpose constructor.
* \a data can either be binary data that should be parsed or (at a minimum) the frame ID.
*/
explicit UserUrlLinkFrame(const ByteVector &data);
/*!
* Destroys this UserUrlLinkFrame instance.
*/
* Destroys this UserUrlLinkFrame instance.
*/
virtual ~UserUrlLinkFrame();
// Reimplementations.
@@ -123,48 +121,46 @@ class TAGLIB_EXPORT UserUrlLinkFrame : public UrlLinkFrame {
virtual String toString() const;
/*!
* Returns the text encoding that will be used in rendering this frame.
* This defaults to the type that was either specified in the constructor
* or read from the frame when parsed.
*
* \see setTextEncoding()
* \see render()
*/
* Returns the text encoding that will be used in rendering this frame.
* This defaults to the type that was either specified in the constructor or read from the frame when parsed.
*
* \see setTextEncoding()
* \see render()
*/
String::Type textEncoding() const;
/*!
* Sets the text encoding to be used when rendering this frame to
* \a encoding.
*
* \see textEncoding()
* \see render()
*/
* Sets the text encoding to be used when rendering this frame to \a encoding.
*
* \see textEncoding()
* \see render()
*/
void setTextEncoding(String::Type encoding);
/*!
* Returns the description for this frame.
*/
* Returns the description for this frame.
*/
String description() const;
/*!
* Sets the description of the frame to \a s. \a s must be unique.
*/
* Sets the description of the frame to \a s. \a s must be unique.
*/
void setDescription(const String &s);
/*!
* Parses the UserUrlLinkFrame as PropertyMap. The description() is taken as key,
* and the URL as single value.
* - if description() is empty, the key will be "URL".
* - otherwise, if description() is not a valid key (e.g. containing non-ASCII
* characters), the returned map will contain an entry "WXXX/<description>"
* in its unsupportedData() list.
*/
* Parses the UserUrlLinkFrame as PropertyMap. The description() is taken as key,
* and the URL as single value.
* - if description() is empty, the key will be "URL".
* - otherwise, if description() is not a valid key (e.g. containing non-ASCII
* characters), the returned map will contain an entry "WXXX/<description>"
* in its unsupportedData() list.
*/
PropertyMap asProperties() const;
/*!
* Searches for the user defined url frame with the description \a description
* in \a tag. This returns null if no matching frames were found.
*/
* Searches for the user defined url frame with the description \a description in \a tag.
* This returns null if no matching frames were found.
*/
static UserUrlLinkFrame *find(Tag *tag, const String &description);
protected:
@@ -172,8 +168,8 @@ class TAGLIB_EXPORT UserUrlLinkFrame : public UrlLinkFrame {
virtual ByteVector renderFields() const;
/*!
* The constructor used by the FrameFactory.
*/
* The constructor used by the FrameFactory.
*/
UserUrlLinkFrame(const ByteVector &data, Header *h);
private:
@@ -187,4 +183,5 @@ class TAGLIB_EXPORT UserUrlLinkFrame : public UrlLinkFrame {
} // namespace ID3v2
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@@ -19,6 +19,7 @@ enum Version {
v3 = 3, //<! ID3v2.3
v4 = 4 //<! ID3v2.4
};
} // namespace ID3v2
} // namespace TagLib
} // namespace Strawberry_TagLib

View File

@@ -40,8 +40,7 @@ class ExtendedHeader::ExtendedHeaderPrivate {
// public methods
////////////////////////////////////////////////////////////////////////////////
ExtendedHeader::ExtendedHeader() : d(new ExtendedHeaderPrivate()) {
}
ExtendedHeader::ExtendedHeader() : d(new ExtendedHeaderPrivate()) {}
ExtendedHeader::~ExtendedHeader() {
delete d;

View File

@@ -32,52 +32,49 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
//! ID3v2 extended header implementation
/*!
* This class implements ID3v2 extended headers. It attempts to follow,
* both semantically and programmatically, the structure specified in
* the ID3v2 standard. The API is based on the properties of ID3v2 extended
* headers specified there. If any of the terms used in this documentation
* are unclear please check the specification in the linked section.
* (Structure, <a href="id3v2-structure.html#3.2">3.2</a>)
*/
* This class implements ID3v2 extended headers.
* It attempts to follow, both semantically and programmatically,
* the structure specified in the ID3v2 standard.
* The API is based on the properties of ID3v2 extended headers specified there.
* If any of the terms used in this documentation are unclear please check the specification in the linked section.
* (Structure, <a href="id3v2-structure.html#3.2">3.2</a>)
*/
class TAGLIB_EXPORT ExtendedHeader {
public:
/*!
* Constructs an empty ID3v2 extended header.
*/
* Constructs an empty ID3v2 extended header.
*/
ExtendedHeader();
/*!
* Destroys the extended header.
*/
* Destroys the extended header.
*/
virtual ~ExtendedHeader();
/*!
* Returns the size of the extended header. This is variable for the
* extended header.
*/
* Returns the size of the extended header. This is variable for the extended header.
*/
unsigned int size() const;
/*!
* Sets the data that will be used as the extended header. Since the
* length is not known before the extended header has been parsed, this
* should just be a pointer to the first byte of the extended header. It
* will determine the length internally and make that available through
* size().
*/
* Sets the data that will be used as the extended header.
* Since the length is not known before the extended header has been parsed,
* this should just be a pointer to the first byte of the extended header.
* It will determine the length internally and make that available through size().
*/
void setData(const ByteVector &data);
protected:
/*!
* Called by setData() to parse the extended header data. It makes this
* information available through the public API.
*/
* Called by setData() to parse the extended header data.
* It makes this information available through the public API.
*/
void parse(const ByteVector &data);
private:
@@ -91,4 +88,5 @@ class TAGLIB_EXPORT ExtendedHeader {
} // namespace ID3v2
} // namespace TagLib
} // namespace Strawberry_TagLib
#endif

View File

@@ -29,14 +29,11 @@
using namespace Strawberry_TagLib::TagLib;
using namespace ID3v2;
class Footer::FooterPrivate {
};
class Footer::FooterPrivate {};
Footer::Footer() : d(0) {
}
Footer::Footer() : d(nullptr) {}
Footer::~Footer() {
}
Footer::~Footer() {}
unsigned int Footer::size() {
return 10;

View File

@@ -31,7 +31,6 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
class Header;
@@ -39,34 +38,33 @@ class Header;
//! ID3v2 footer implementation
/*!
* Per the ID3v2 specification, the tag's footer is just a copy of the
* information in the header. As such there is no API for reading the
* data from the header, it can just as easily be done from the header.
*
* In fact, at this point, TagLib does not even parse the footer since
* it is not useful internally. However, if the flag to include a footer
* has been set in the ID3v2::Tag, TagLib will render a footer.
*/
* Per the ID3v2 specification, the tag's footer is just a copy of the information in the header.
* As such there is no API for reading the data from the header,
* it can just as easily be done from the header.
*
* In fact, at this point, TagLib does not even parse the footer since it is not useful internally.
* However, if the flag to include a footer has been set in the ID3v2::Tag, TagLib will render a footer.
*/
class TAGLIB_EXPORT Footer {
public:
/*!
* Constructs an empty ID3v2 footer.
*/
* Constructs an empty ID3v2 footer.
*/
Footer();
/*!
* Destroys the footer.
*/
* Destroys the footer.
*/
virtual ~Footer();
/*!
* Returns the size of the footer. Presently this is always 10 bytes.
*/
* Returns the size of the footer. Presently this is always 10 bytes.
*/
static unsigned int size();
/*!
* Renders the footer based on the data in \a header.
*/
* Renders the footer based on the data in \a header.
*/
ByteVector render(const Header *header) const;
private:

View File

@@ -46,8 +46,7 @@ using namespace ID3v2;
class Frame::FramePrivate {
public:
FramePrivate() : header(0) {
}
FramePrivate() : header(nullptr) {}
~FramePrivate() {
delete header;
@@ -58,6 +57,7 @@ class Frame::FramePrivate {
namespace {
bool isValidFrameID(const ByteVector &frameID) {
if (frameID.size() != 4)
return false;
@@ -67,6 +67,7 @@ bool isValidFrameID(const ByteVector &frameID) {
}
}
return true;
}
} // namespace
@@ -98,8 +99,8 @@ const String Frame::urlPrefix("URL:");
// public members
////////////////////////////////////////////////////////////////////////////////
Frame *Frame::createTextualFrame(const String &key, const StringList &values) //static
{
Frame *Frame::createTextualFrame(const String &key, const StringList &values) { //static
// check if the key is contained in the key<=>frameID mapping
ByteVector frameID = keyToFrameID(key);
if (!frameID.isEmpty()) {
@@ -145,6 +146,7 @@ Frame *Frame::createTextualFrame(const String &key, const StringList &values) /
}
// if non of the above cases apply, we use a TXXX frame with the key as description
return new UserTextIdentificationFrame(keyToTXXX(key), values, String::UTF8);
}
Frame::~Frame() {
@@ -152,17 +154,21 @@ Frame::~Frame() {
}
ByteVector Frame::frameID() const {
if (d->header)
return d->header->frameID();
else
return ByteVector();
}
unsigned int Frame::size() const {
if (d->header)
return d->header->frameSize();
else
return 0;
}
void Frame::setData(const ByteVector &data) {
@@ -173,11 +179,13 @@ void Frame::setText(const String &) {
}
ByteVector Frame::render() const {
ByteVector fieldData = renderFields();
d->header->setFrameSize(fieldData.size());
ByteVector headerData = d->header->render();
return headerData + fieldData;
}
////////////////////////////////////////////////////////////////////////////////
@@ -213,6 +221,7 @@ void Frame::parse(const ByteVector &data) {
}
ByteVector Frame::fieldData(const ByteVector &frameData) const {
unsigned int headerSize = Header::size(d->header->version());
unsigned int frameDataOffset = headerSize;
@@ -238,9 +247,11 @@ ByteVector Frame::fieldData(const ByteVector &frameData) const {
}
return frameData.mid(frameDataOffset, frameDataLength);
}
String Frame::readStringField(const ByteVector &data, String::Type encoding, int *position) {
int start = 0;
if (!position)
@@ -262,15 +273,16 @@ String Frame::readStringField(const ByteVector &data, String::Type encoding, int
*position = end + delimiter.size();
return str;
}
String::Type Frame::checkEncoding(const StringList &fields, String::Type encoding) // static
{
String::Type Frame::checkEncoding(const StringList &fields, String::Type encoding) { // static
return checkEncoding(fields, encoding, 4);
}
String::Type Frame::checkEncoding(const StringList &fields, String::Type encoding, unsigned int version) // static
{
String::Type Frame::checkEncoding(const StringList &fields, String::Type encoding, unsigned int version) { // static
if ((encoding == String::UTF8 || encoding == String::UTF16BE) && version != 4)
return String::UTF16;
@@ -291,6 +303,7 @@ String::Type Frame::checkEncoding(const StringList &fields, String::Type encodin
}
return String::Latin1;
}
String::Type Frame::checkTextEncoding(const StringList &fields, String::Type encoding) const {
@@ -438,6 +451,7 @@ String Frame::keyToTXXX(const String &s) {
}
PropertyMap Frame::asProperties() const {
if (dynamic_cast<const UnknownFrame *>(this)) {
PropertyMap m;
m.unsupportedData().append("UNKNOWN/" + frameID());
@@ -463,10 +477,11 @@ PropertyMap Frame::asProperties() const {
PropertyMap m;
m.unsupportedData().append(id);
return m;
}
void Frame::splitProperties(const PropertyMap &original, PropertyMap &singleFrameProperties,
PropertyMap &tiplProperties, PropertyMap &tmclProperties) {
void Frame::splitProperties(const PropertyMap &original, PropertyMap &singleFrameProperties, PropertyMap &tiplProperties, PropertyMap &tmclProperties) {
singleFrameProperties.clear();
tiplProperties.clear();
tmclProperties.clear();
@@ -478,6 +493,7 @@ void Frame::splitProperties(const PropertyMap &original, PropertyMap &singleFram
else
singleFrameProperties.insert(it->first, it->second);
}
}
////////////////////////////////////////////////////////////////////////////////
@@ -539,10 +555,6 @@ unsigned int Frame::Header::size(unsigned int version) {
// public members (Frame::Header)
////////////////////////////////////////////////////////////////////////////////
Frame::Header::Header(const ByteVector &data, bool synchSafeInts) : d(new HeaderPrivate()) {
setData(data, synchSafeInts);
}
Frame::Header::Header(const ByteVector &data, unsigned int version) : d(new HeaderPrivate()) {
setData(data, version);
}
@@ -556,6 +568,7 @@ void Frame::Header::setData(const ByteVector &data, bool synchSafeInts) {
}
void Frame::Header::setData(const ByteVector &data, unsigned int version) {
d->version = version;
switch (version) {
@@ -680,6 +693,7 @@ void Frame::Header::setData(const ByteVector &data, unsigned int version) {
break;
}
}
}
ByteVector Frame::Header::frameID() const {
@@ -747,6 +761,7 @@ bool Frame::Header::dataLengthIndicator() const {
}
ByteVector Frame::Header::render() const {
ByteVector flags(2, char(0)); // just blank for the moment
ByteVector v = d->frameID +
@@ -754,8 +769,5 @@ ByteVector Frame::Header::render() const {
flags;
return v;
}
bool Frame::Header::frameAlterPreservation() const {
return fileAlterPreservation();
}

View File

@@ -44,13 +44,13 @@ class FrameFactory;
//! ID3v2 frame implementation
/*!
* This class is the main ID3v2 frame implementation. In ID3v2, a tag is
* split between a collection of frames (which are in turn split into fields
* (Structure, <a href="id3v2-structure.html#4">4</a>)
* (<a href="id3v2-frames.html">Frames</a>). This class provides an API for
* gathering information about and modifying ID3v2 frames. Funtionallity
* specific to a given frame type is handed in one of the many subclasses.
*/
* This class is the main ID3v2 frame implementation.
* In ID3v2, a tag is split between a collection of frames (which are in turn split into fields
* (Structure, <a href="id3v2-structure.html#4">4</a>)
* (<a href="id3v2-frames.html">Frames</a>).
* This class provides an API for gathering information about and modifying ID3v2 frames.
* Funtionallity specific to a given frame type is handed in one of the many subclasses.
*/
class TAGLIB_EXPORT Frame {
friend class Tag;
@@ -58,247 +58,217 @@ class TAGLIB_EXPORT Frame {
public:
/*!
* Creates a textual frame which corresponds to a single key in the PropertyMap
* interface. These are all (User)TextIdentificationFrames except TIPL and TMCL,
* all (User)URLLinkFrames, CommentsFrames, and UnsynchronizedLyricsFrame.
*/
* Creates a textual frame which corresponds to a single key in the PropertyMap interface.
* These are all (User)TextIdentificationFrames except TIPL and TMCL, all (User)URLLinkFrames, CommentsFrames, and UnsynchronizedLyricsFrame.
*/
static Frame *createTextualFrame(const String &key, const StringList &values);
/*!
* Destroys this Frame instance.
*/
* Destroys this Frame instance.
*/
virtual ~Frame();
/*!
* Returns the Frame ID (Structure, <a href="id3v2-structure.html#4">4</a>)
* (Frames, <a href="id3v2-frames.html#4">4</a>)
*/
* Returns the Frame ID (Structure, <a href="id3v2-structure.html#4">4</a>)
* (Frames, <a href="id3v2-frames.html#4">4</a>)
*/
ByteVector frameID() const;
/*!
* Returns the size of the frame.
*/
* Returns the size of the frame.
*/
unsigned int size() const;
/*!
* Returns the size of the frame header
*
* \deprecated This is only accurate for ID3v2.3 or ID3v2.4. Please use
* the call below which accepts an ID3v2 version number. In the next
* non-binary compatible release this will be made into a non-static
* member that checks the internal ID3v2 version.
*/
* Returns the size of the frame header
*
* \deprecated This is only accurate for ID3v2.3 or ID3v2.4.
* Please use the call below which accepts an ID3v2 version number.
* In the next non-binary compatible release this will be made into a non-static member that checks the internal ID3v2 version.
*/
static unsigned int headerSize(); // BIC: make non-static
/*!
* Returns the size of the frame header for the given ID3v2 version.
*
* \deprecated Please see the explanation above.
*/
* Returns the size of the frame header for the given ID3v2 version.
*
* \deprecated Please see the explanation above.
*/
// BIC: remove
static unsigned int headerSize(unsigned int version);
/*!
* Sets the data that will be used as the frame. Since the length is not
* known before the frame has been parsed, this should just be a pointer to
* the first byte of the frame. It will determine the length internally
* and make that available through size().
*/
* Sets the data that will be used as the frame.
* Since the length is not known before the frame has been parsed,
* this should just be a pointer to the first byte of the frame.
* It will determine the length internally and make that available through size().
*/
void setData(const ByteVector &data);
/*!
* Set the text of frame in the sanest way possible. This should only be
* reimplemented in frames where there is some logical mapping to text.
*
* \note If the frame type supports multiple text encodings, this will not
* change the text encoding of the frame; the string will be converted to
* that frame's encoding. Please use the specific APIs of the frame types
* to set the encoding if that is desired.
*/
* Set the text of frame in the sanest way possible.
* This should only be reimplemented in frames where there is some logical mapping to text.
*
* \note If the frame type supports multiple text encodings,
* this will not change the text encoding of the frame; the string will be converted to that frame's encoding.
* Please use the specific APIs of the frame types to set the encoding if that is desired.
*/
virtual void setText(const String &text);
/*!
* This returns the textual representation of the data in the frame.
* Subclasses must reimplement this method to provide a string
* representation of the frame's data.
*/
* This returns the textual representation of the data in the frame.
* Subclasses must reimplement this method to provide a string representation of the frame's data.
*/
virtual String toString() const = 0;
/*!
* Render the frame back to its binary format in a ByteVector.
*/
* Render the frame back to its binary format in a ByteVector.
*/
ByteVector render() const;
/*!
* Returns the text delimiter that is used between fields for the string
* type \a t.
*/
* Returns the text delimiter that is used between fields for the string type \a t.
*/
static ByteVector textDelimiter(String::Type t);
/*!
* The string with which an instrument name is prefixed to build a key in a PropertyMap;
* used to translate PropertyMaps to TMCL frames. In the current implementation, this
* is "PERFORMER:".
*/
* The string with which an instrument name is prefixed to build a key in a PropertyMap; used to translate PropertyMaps to TMCL frames.
* In the current implementation, this is "PERFORMER:".
*/
static const String instrumentPrefix;
/*!
* The PropertyMap key prefix which triggers the use of a COMM frame instead of a TXXX
* frame for a non-standard key. In the current implementation, this is "COMMENT:".
*/
* The PropertyMap key prefix which triggers the use of a COMM frame instead of a TXXX frame for a non-standard key.
* In the current implementation, this is "COMMENT:".
*/
static const String commentPrefix;
/*!
* The PropertyMap key prefix which triggers the use of a USLT frame instead of a TXXX
* frame for a non-standard key. In the current implementation, this is "LYRICS:".
*/
* The PropertyMap key prefix which triggers the use of a USLT frame instead of a TXXX frame for a non-standard key.
* In the current implementation, this is "LYRICS:".
*/
static const String lyricsPrefix;
/*!
* The PropertyMap key prefix which triggers the use of a WXXX frame instead of a TXX
* frame for a non-standard key. In the current implementation, this is "URL:".
*/
* The PropertyMap key prefix which triggers the use of a WXXX frame instead of a TXX frame for a non-standard key.
* In the current implementation, this is "URL:".
*/
static const String urlPrefix;
protected:
class Header;
/*!
* Constructs an ID3v2 frame using \a data to read the header information.
* All other processing of \a data should be handled in a subclass.
*
* \note This need not contain anything more than a frame ID, but
* \e must contain at least that.
*/
* Constructs an ID3v2 frame using \a data to read the header information.
* All other processing of \a data should be handled in a subclass.
*
* \note This need not contain anything more than a frame ID, but \e must contain at least that.
*/
explicit Frame(const ByteVector &data);
/*!
* This creates an Frame using the header \a h.
*
* The ownership of this header will be assigned to the frame and the
* header will be deleted when the frame is destroyed.
*/
* This creates an Frame using the header \a h.
*
* The ownership of this header will be assigned to the frame and the header will be deleted when the frame is destroyed.
*/
Frame(Header *h);
/*!
* Returns a pointer to the frame header.
*/
* Returns a pointer to the frame header.
*/
Header *header() const;
/*!
* Sets the header to \a h. If \a deleteCurrent is true, this will free
* the memory of the current header.
*
* The ownership of this header will be assigned to the frame and the
* header will be deleted when the frame is destroyed.
*/
* Sets the header to \a h. If \a deleteCurrent is true, this will free the memory of the current header.
*
* The ownership of this header will be assigned to the frame and the header will be deleted when the frame is destroyed.
*/
void setHeader(Header *h, bool deleteCurrent = true);
/*!
* Called by setData() to parse the frame data. It makes this information
* available through the public API.
*/
* Called by setData() to parse the frame data. It makes this information available through the public API.
*/
void parse(const ByteVector &data);
/*!
* Called by parse() to parse the field data. It makes this information
* available through the public API. This must be overridden by the
* subclasses.
*/
* Called by parse() to parse the field data.
* It makes this information available through the public API. This must be overridden by the subclasses.
*/
virtual void parseFields(const ByteVector &data) = 0;
/*!
* Render the field data back to a binary format in a ByteVector. This
* must be overridden by subclasses.
*/
* Render the field data back to a binary format in a ByteVector. This must be overridden by subclasses.
*/
virtual ByteVector renderFields() const = 0;
/*!
* Returns a ByteVector containing the field data given the frame data.
* This correctly adjusts for the header size plus any additional frame
* data that's specified in the frame header flags.
*/
* Returns a ByteVector containing the field data given the frame data.
* This correctly adjusts for the header size plus any additional frame data that's specified in the frame header flags.
*/
ByteVector fieldData(const ByteVector &frameData) const;
/*!
* Reads a String of type \a encoding from the ByteVector \a data. If \a
* position is passed in it is used both as the starting point and is
* updated to return the position just after the string that has been read.
* This is useful for reading strings sequentially.
*/
String readStringField(const ByteVector &data, String::Type encoding,
int *position = 0);
* Reads a String of type \a encoding from the ByteVector \a data.
* If \a position is passed in it is used both as the starting point and is updated to return the position just after the string that has been read.
* This is useful for reading strings sequentially.
*/
String readStringField(const ByteVector &data, String::Type encoding, int *position = 0);
/*!
* Checks a the list of string values to see if they can be used with the
* specified encoding and returns the recommended encoding.
*/
* Checks a the list of string values to see if they can be used with the specified encoding and returns the recommended encoding.
*/
// BIC: remove and make non-static
static String::Type checkEncoding(const StringList &fields,
String::Type encoding);
static String::Type checkEncoding(const StringList &fields, String::Type encoding);
/*!
* Checks a the list of string values to see if they can be used with the
* specified encoding and returns the recommended encoding. This method
* also checks the ID3v2 version and makes sure the encoding can be used
* in the specified version.
*/
* Checks a the list of string values to see if they can be used with the specified encoding and returns the recommended encoding.
* This method also checks the ID3v2 version and makes sure the encoding can be used in the specified version.
*/
// BIC: remove and make non-static
static String::Type checkEncoding(const StringList &fields,
String::Type encoding, unsigned int version);
static String::Type checkEncoding(const StringList &fields, String::Type encoding, unsigned int version);
/*!
* Checks a the list of string values to see if they can be used with the
* specified encoding and returns the recommended encoding. This method
* also checks the ID3v2 version and makes sure the encoding can be used
* in the version specified by the frame's header.
*/
String::Type checkTextEncoding(const StringList &fields,
String::Type encoding) const;
* Checks a the list of string values to see if they can be used with the specified encoding and returns the recommended encoding.
* This method also checks the ID3v2 version and makes sure the encoding can be used in the version specified by the frame's header.
*/
String::Type checkTextEncoding(const StringList &fields, String::Type encoding) const;
/*!
* Parses the contents of this frame as PropertyMap. If that fails, the returned
* PropertyMap will be empty, and its unsupportedData() will contain this frame's
* ID.
* BIC: Will be a virtual function in future releases.
*/
* Parses the contents of this frame as PropertyMap.
* If that fails, the returned PropertyMap will be empty, and its unsupportedData() will contain this frame's ID.
* BIC: Will be a virtual function in future releases.
*/
PropertyMap asProperties() const;
/*!
* Returns an appropriate ID3 frame ID for the given free-form tag key. This method
* will return an empty ByteVector if no specialized translation is found.
*/
* Returns an appropriate ID3 frame ID for the given free-form tag key. This method
* will return an empty ByteVector if no specialized translation is found.
*/
static ByteVector keyToFrameID(const String &);
/*!
* Returns a free-form tag name for the given ID3 frame ID. Note that this does not work
* for general frame IDs such as TXXX or WXXX; in such a case an empty string is returned.
*/
* Returns a free-form tag name for the given ID3 frame ID.
* Note that this does not work for general frame IDs such as TXXX or WXXX; in such a case an empty string is returned.
*/
static String frameIDToKey(const ByteVector &);
/*!
* Returns an appropriate TXXX frame description for the given free-form tag key.
*/
* Returns an appropriate TXXX frame description for the given free-form tag key.
*/
static String keyToTXXX(const String &);
/*!
* Returns a free-form tag name for the given ID3 frame description.
*/
* Returns a free-form tag name for the given ID3 frame description.
*/
static String txxxToKey(const String &);
/*!
* This helper function splits the PropertyMap \a original into three ProperytMaps
* \a singleFrameProperties, \a tiplProperties, and \a tmclProperties, such that:
* - \a singleFrameProperties contains only of keys which can be represented with
* exactly one ID3 frame per key. In the current implementation
* this is everything except for the fixed "involved people" keys and keys of the
* form "TextIdentificationFrame::instrumentPrefix" + "instrument", which are
* mapped to a TMCL frame.
* - \a tiplProperties will consist of those keys that are present in
* TextIdentificationFrame::involvedPeopleMap()
* - \a tmclProperties contains the "musician credits" keys which should be mapped
* to a TMCL frame
*/
static void splitProperties(const PropertyMap &original, PropertyMap &singleFrameProperties,
PropertyMap &tiplProperties, PropertyMap &tmclProperties);
* This helper function splits the PropertyMap \a original into three ProperytMaps
* \a singleFrameProperties, \a tiplProperties, and \a tmclProperties, such that:
* - \a singleFrameProperties contains only of keys which can be represented with exactly one ID3 frame per key.
* In the current implementation this is everything except for the fixed "involved people" keys and keys of the
* form "TextIdentificationFrame::instrumentPrefix" + "instrument", which are mapped to a TMCL frame.
* - \a tiplProperties will consist of those keys that are present in TextIdentificationFrame::involvedPeopleMap()
* - \a tmclProperties contains the "musician credits" keys which should be mapped to a TMCL frame
*/
static void splitProperties(const PropertyMap &original, PropertyMap &singleFrameProperties, PropertyMap &tiplProperties, PropertyMap &tmclProperties);
private:
Frame(const Frame &);
@@ -312,173 +282,157 @@ class TAGLIB_EXPORT Frame {
//! ID3v2 frame header implementation
/*!
* The ID3v2 Frame Header (Structure, <a href="id3v2-structure.html#4">4</a>)
*
* Every ID3v2::Frame has an associated header that gives some general
* properties of the frame and also makes it possible to identify the frame
* type.
*
* As such when reading an ID3v2 tag ID3v2::FrameFactory first creates the
* frame headers and then creates the appropriate Frame subclass based on
* the type and attaches the header.
*/
* The ID3v2 Frame Header (Structure, <a href="id3v2-structure.html#4">4</a>)
*
* Every ID3v2::Frame has an associated header that gives some general
* properties of the frame and also makes it possible to identify the frame type.
*
* As such when reading an ID3v2 tag ID3v2::FrameFactory first creates the
* frame headers and then creates the appropriate Frame subclass based on the type and attaches the header.
*/
class TAGLIB_EXPORT Frame::Header {
public:
/*!
* Construct a Frame Header based on \a data. \a data must at least
* contain a 4 byte frame ID, and optionally can contain flag data and the
* frame size. i.e. Just the frame id -- "TALB" -- is a valid value.
*
* \deprecated Please use the constructor below that accepts a version
* number.
*/
TAGLIB_DEPRECATED Header(const ByteVector &data, bool synchSafeInts);
/*!
* Construct a Frame Header based on \a data. \a data must at least
* contain a 4 byte frame ID, and optionally can contain flag data and the
* frame size. i.e. Just the frame id -- "TALB" -- is a valid value.
*
* \a version should be the ID3v2 version of the tag.
*/
* Construct a Frame Header based on \a data. \a data must at least
* contain a 4 byte frame ID, and optionally can contain flag data and the frame size.
* i.e. Just the frame id -- "TALB" -- is a valid value.
*
* \a version should be the ID3v2 version of the tag.
*/
explicit Header(const ByteVector &data, unsigned int version = 4);
/*!
* Destroys this Header instance.
*/
* Destroys this Header instance.
*/
virtual ~Header();
/*!
* Sets the data for the Header.
*
* \deprecated Please use the version below that accepts an ID3v2 version
* number.
*/
* Sets the data for the Header.
*
* \deprecated Please use the version below that accepts an ID3v2 version
* number.
*/
void setData(const ByteVector &data, bool synchSafeInts);
/*!
* Sets the data for the Header. \a version should indicate the ID3v2
* version number of the tag that this frame is contained in.
*/
* Sets the data for the Header.
* \a version should indicate the ID3v2 version number of the tag that this frame is contained in.
*/
void setData(const ByteVector &data, unsigned int version = 4);
/*!
* Returns the Frame ID (Structure, <a href="id3v2-structure.html#4">4</a>)
* (Frames, <a href="id3v2-frames.html#4">4</a>)
*/
* Returns the Frame ID (Structure, <a href="id3v2-structure.html#4">4</a>)
* (Frames, <a href="id3v2-frames.html#4">4</a>)
*/
ByteVector frameID() const;
/*!
* Sets the frame's ID to \a id. Only the first four bytes of \a id will
* be used.
*
* \warning This method should in general be avoided. It exists simply to
* provide a mechanism for transforming frames from a deprecated frame type
* to a newer one -- i.e. TYER to TDRC from ID3v2.3 to ID3v2.4.
*/
* Sets the frame's ID to \a id. Only the first four bytes of \a id will be used.
*
* \warning This method should in general be avoided. It exists simply to
* provide a mechanism for transforming frames from a deprecated frame type
* to a newer one -- i.e. TYER to TDRC from ID3v2.3 to ID3v2.4.
*/
void setFrameID(const ByteVector &id);
/*!
* Returns the size of the frame data portion, as set when setData() was
* called or set explicitly via setFrameSize().
*/
* Returns the size of the frame data portion, as set when setData() was called or set explicitly via setFrameSize().
*/
unsigned int frameSize() const;
/*!
* Sets the size of the frame data portion.
*/
* Sets the size of the frame data portion.
*/
void setFrameSize(unsigned int size);
/*!
* Returns the ID3v2 version of the header, as passed in from the
* construction of the header or set via setVersion().
*/
* Returns the ID3v2 version of the header, as passed in from the construction of the header or set via setVersion().
*/
unsigned int version() const;
/*!
* Sets the ID3v2 version of the header, changing has impact on the
* correct parsing/rendering of frame data.
*/
* Sets the ID3v2 version of the header, changing has impact on the correct parsing/rendering of frame data.
*/
void setVersion(unsigned int version);
/*!
* Returns the size of the frame header in bytes.
*
* \deprecated Please use the version of this method that accepts a
* version. This is only accurate for ID3v2.3 and ID3v2.4. This will be
* removed in the next binary incompatible release (2.0) and will be
* replaced with a non-static method that checks the frame version.
*/
* Returns the size of the frame header in bytes.
*
* \deprecated Please use the version of this method that accepts a
* version. This is only accurate for ID3v2.3 and ID3v2.4. This will be
* removed in the next binary incompatible release (2.0) and will be
* replaced with a non-static method that checks the frame version.
*/
// BIC: make non-static
static unsigned int size();
/*!
* Returns the size of the frame header in bytes for the ID3v2 version
* that's given.
*
* \deprecated Please see the explanation in the version above.
*/
* Returns the size of the frame header in bytes for the ID3v2 version
* that's given.
*
* \deprecated Please see the explanation in the version above.
*/
// BIC: remove
static unsigned int size(unsigned int version);
/*!
* Returns true if the flag for tag alter preservation is set.
*
* The semantics are a little backwards from what would seem natural
* (setting the preservation flag to throw away the frame), but this
* follows the ID3v2 standard.
*
* \see setTagAlterPreservation()
*/
* Returns true if the flag for tag alter preservation is set.
*
* The semantics are a little backwards from what would seem natural
* (setting the preservation flag to throw away the frame), but this
* follows the ID3v2 standard.
*
* \see setTagAlterPreservation()
*/
bool tagAlterPreservation() const;
/*!
* Sets the flag for preservation of this frame if the tag is set. If
* this is set to true the frame will not be written when the tag is
* saved.
*
* The semantics are a little backwards from what would seem natural
* (setting the preservation flag to throw away the frame), but this
* follows the ID3v2 standard.
*
* \see tagAlterPreservation()
*/
* Sets the flag for preservation of this frame if the tag is set. If
* this is set to true the frame will not be written when the tag is
* saved.
*
* The semantics are a little backwards from what would seem natural
* (setting the preservation flag to throw away the frame), but this
* follows the ID3v2 standard.
*
* \see tagAlterPreservation()
*/
void setTagAlterPreservation(bool discard);
/*!
* Returns true if the flag for file alter preservation is set.
*
* \note This flag is currently ignored internally in TagLib.
*/
* Returns true if the flag for file alter preservation is set.
*
* \note This flag is currently ignored internally in TagLib.
*/
bool fileAlterPreservation() const;
/*!
* Returns true if the frame is meant to be read only.
*
* \note This flag is currently ignored internally in TagLib.
*/
* Returns true if the frame is meant to be read only.
*
* \note This flag is currently ignored internally in TagLib.
*/
bool readOnly() const;
/*!
* Returns true if the flag for the grouping identity is set.
*
* \note This flag is currently ignored internally in TagLib.
*/
* Returns true if the flag for the grouping identity is set.
*
* \note This flag is currently ignored internally in TagLib.
*/
bool groupingIdentity() const;
/*!
* Returns true if compression is enabled for this frame.
*
* \note This flag is currently ignored internally in TagLib.
*/
* Returns true if compression is enabled for this frame.
*
* \note This flag is currently ignored internally in TagLib.
*/
bool compression() const;
/*!
* Returns true if encryption is enabled for this frame.
*
* \note This flag is currently ignored internally in TagLib.
*/
* Returns true if encryption is enabled for this frame.
*
* \note This flag is currently ignored internally in TagLib.
*/
bool encryption() const;
#ifndef DO_NOT_DOCUMENT
@@ -486,25 +440,20 @@ class TAGLIB_EXPORT Frame::Header {
#endif
/*!
* Returns true if unsynchronisation is enabled for this frame.
*/
* Returns true if unsynchronisation is enabled for this frame.
*/
bool unsynchronisation() const;
/*!
* Returns true if the flag for a data length indicator is set.
*/
* Returns true if the flag for a data length indicator is set.
*/
bool dataLengthIndicator() const;
/*!
* Render the Header back to binary format in a ByteVector.
*/
* Render the Header back to binary format in a ByteVector.
*/
ByteVector render() const;
/*!
* \deprecated
*/
TAGLIB_DEPRECATED bool frameAlterPreservation() const;
private:
Header(const Header &);
Header &operator=(const Header &);

View File

@@ -53,6 +53,7 @@ using namespace ID3v2;
namespace {
void updateGenre(TextIdentificationFrame *frame) {
StringList fields = frame->fieldList();
StringList newfields;
@@ -80,13 +81,13 @@ void updateGenre(TextIdentificationFrame *frame) {
fields.append(String());
frame->setText(newfields);
}
} // namespace
class FrameFactory::FrameFactoryPrivate {
public:
FrameFactoryPrivate() : defaultEncoding(String::Latin1),
useDefaultEncoding(false) {}
FrameFactoryPrivate() : defaultEncoding(String::Latin1), useDefaultEncoding(false) {}
String::Type defaultEncoding;
bool useDefaultEncoding;
@@ -107,21 +108,8 @@ FrameFactory *FrameFactory::instance() {
return &factory;
}
Frame *FrameFactory::createFrame(const ByteVector &data, bool synchSafeInts) const {
return createFrame(data, static_cast<unsigned int>(synchSafeInts ? 4 : 3));
}
Frame *FrameFactory::createFrame(const ByteVector &data, unsigned int version) const {
Header tagHeader;
tagHeader.setMajorVersion(version);
return createFrame(data, &tagHeader);
}
Frame *FrameFactory::createFrame(const ByteVector &origData, Header *tagHeader) const {
return createFrame(origData, const_cast<const Header *>(tagHeader));
}
Frame *FrameFactory::createFrame(const ByteVector &origData, const Header *tagHeader) const {
ByteVector data = origData;
unsigned int version = tagHeader->majorVersion();
Frame::Header *header = new Frame::Header(data, version);
@@ -317,9 +305,11 @@ Frame *FrameFactory::createFrame(const ByteVector &origData, const Header *tagHe
return new PodcastFrame(data, header);
return new UnknownFrame(data, header);
}
void FrameFactory::rebuildAggregateFrames(ID3v2::Tag *tag) const {
if (tag->header()->majorVersion() < 4 &&
tag->frameList("TDRC").size() == 1 &&
tag->frameList("TDAT").size() == 1) {
@@ -346,6 +336,7 @@ void FrameFactory::rebuildAggregateFrames(ID3v2::Tag *tag) const {
}
}
}
}
String::Type FrameFactory::defaultTextEncoding() const {
@@ -456,6 +447,7 @@ const size_t frameConversion3Size = sizeof(frameConversion3) / sizeof(frameConve
} // namespace
bool FrameFactory::updateFrame(Frame::Header *header) const {
const ByteVector frameID = header->frameID();
switch (header->version()) {
@@ -522,4 +514,5 @@ bool FrameFactory::updateFrame(Frame::Header *header) const {
}
return true;
}

View File

@@ -33,7 +33,6 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
class TextIdentificationFrame;
@@ -41,116 +40,79 @@ class TextIdentificationFrame;
//! A factory for creating ID3v2 frames during parsing
/*!
* This factory abstracts away the frame creation process and instantiates
* the appropriate ID3v2::Frame subclasses based on the contents of the
* data.
*
* Reimplementing this factory is the key to adding support for frame types
* not directly supported by TagLib to your application. To do so you would
* subclass this factory reimplement createFrame(). Then by setting your
* factory to be the default factory in ID3v2::Tag constructor you can
* implement behavior that will allow for new ID3v2::Frame subclasses (also
* provided by you) to be used.
*
* This implements both <i>abstract factory</i> and <i>singleton</i> patterns
* of which more information is available on the web and in software design
* textbooks (Notably <i>Design Patters</i>).
*
* \note You do not need to use this factory to create new frames to add to
* an ID3v2::Tag. You can instantiate frame subclasses directly (with new)
* and add them to a tag using ID3v2::Tag::addFrame()
*
* \see ID3v2::Tag::addFrame()
*/
* This factory abstracts away the frame creation process and instantiates
* the appropriate ID3v2::Frame subclasses based on the contents of the data.
*
* Reimplementing this factory is the key to adding support for frame types not directly supported by TagLib to your application.
* To do so you would subclass this factory reimplement createFrame().
* Then by setting your factory to be the default factory in ID3v2::Tag constructor you can
* implement behavior that will allow for new ID3v2::Frame subclasses (also provided by you) to be used.
*
* This implements both <i>abstract factory</i> and <i>singleton</i> patterns
* of which more information is available on the web and in software design textbooks (Notably <i>Design Patters</i>).
*
* \note You do not need to use this factory to create new frames to add to an ID3v2::Tag.
* You can instantiate frame subclasses directly (with new) and add them to a tag using ID3v2::Tag::addFrame()
*
* \see ID3v2::Tag::addFrame()
*/
class TAGLIB_EXPORT FrameFactory {
public:
static FrameFactory *instance();
/*!
* Create a frame based on \a data. \a synchSafeInts should only be set
* false if we are parsing an old tag (v2.3 or older) that does not support
* synchsafe ints.
*
* \deprecated Please use the method below that accepts a ID3v2::Header
* instance in new code.
*/
Frame *createFrame(const ByteVector &data, bool synchSafeInts) const;
/*!
* Create a frame based on \a data. \a version should indicate the ID3v2
* version of the tag. As ID3v2.4 is the most current version of the
* standard 4 is the default.
*
* \deprecated Please use the method below that accepts a ID3v2::Header
* instance in new code.
*/
Frame *createFrame(const ByteVector &data, unsigned int version = 4) const;
/*!
* \deprecated
*/
// BIC: remove
Frame *createFrame(const ByteVector &data, Header *tagHeader) const;
/*!
* Create a frame based on \a data. \a tagHeader should be a valid
* ID3v2::Header instance.
*/
* Create a frame based on \a data. \a tagHeader should be a valid ID3v2::Header instance.
*/
// BIC: make virtual
Frame *createFrame(const ByteVector &data, const Header *tagHeader) const;
/*!
* After a tag has been read, this tries to rebuild some of them
* information, most notably the recording date, from frames that
* have been deprecated and can't be upgraded directly.
*/
* After a tag has been read, this tries to rebuild some of them information,
* most notably the recording date, from frames that have been deprecated and can't be upgraded directly.
*/
// BIC: Make virtual
void rebuildAggregateFrames(ID3v2::Tag *tag) const;
/*!
* Returns the default text encoding for text frames. If setTextEncoding()
* has not been explicitly called this will only be used for new text
* frames. However, if this value has been set explicitly all frames will be
* converted to this type (unless it's explicitly set differently for the
* individual frame) when being rendered.
*
* \see setDefaultTextEncoding()
*/
* Returns the default text encoding for text frames.
* If setTextEncoding() has not been explicitly called this will only be used for new text frames.
* However, if this value has been set explicitly all frames will be converted to this type
* (unless it's explicitly set differently for the individual frame) when being rendered.
*
* \see setDefaultTextEncoding()
*/
String::Type defaultTextEncoding() const;
/*!
* Set the default text encoding for all text frames that are created to
* \a encoding. If no value is set the frames with either default to the
* encoding type that was parsed and new frames default to Latin1.
*
* Valid string types for ID3v2 tags are Latin1, UTF8, UTF16 and UTF16BE.
*
* \see defaultTextEncoding()
*/
* Set the default text encoding for all text frames that are created to \a encoding.
* If no value is set the frames with either default to the encoding type that was parsed and new frames default to Latin1.
*
* Valid string types for ID3v2 tags are Latin1, UTF8, UTF16 and UTF16BE.
*
* \see defaultTextEncoding()
*/
void setDefaultTextEncoding(String::Type encoding);
protected:
/*!
* Constructs a frame factory. Because this is a singleton this method is
* protected, but may be used for subclasses.
*/
* Constructs a frame factory. Because this is a singleton this method is protected, but may be used for subclasses.
*/
FrameFactory();
/*!
* Destroys the frame factory.
*/
* Destroys the frame factory.
*/
virtual ~FrameFactory();
/*!
* This method checks for compliance to the current ID3v2 standard (2.4)
* and does nothing in the common case. However if a frame is found that
* is not compatible with the current standard, this method either updates
* the frame or indicates that it should be discarded.
*
* This method with return true (with or without changes to the frame) if
* this frame should be kept or false if it should be discarded.
*
* See the id3v2.4.0-changes.txt document for further information.
*/
* This method checks for compliance to the current ID3v2 standard (2.4) and does nothing in the common case.
* However if a frame is found that is not compatible with the current standard,
* this method either updates the frame or indicates that it should be discarded.
*
* This method with return true (with or without changes to the frame) if this frame should be kept or false if it should be discarded.
*
* See the id3v2.4.0-changes.txt document for further information.
*/
virtual bool updateFrame(Frame::Header *header) const;
private:

View File

@@ -132,19 +132,18 @@ void Header::setData(const ByteVector &data) {
}
ByteVector Header::render() const {
ByteVector v;
// add the file identifier -- "ID3"
v.append(fileIdentifier());
// add the version number -- we always render a 2.4.0 tag regardless of what
// the tag originally was.
// add the version number -- we always render a 2.4.0 tag regardless of what the tag originally was.
v.append(char(majorVersion()));
v.append(char(0));
// Currently we don't actually support writing extended headers, footers or
// unsynchronized tags, make sure that the flags are set accordingly.
// Currently we don't actually support writing extended headers, footers or unsynchronized tags, make sure that the flags are set accordingly.
d->extendedHeader = false;
d->footerPresent = false;
@@ -164,6 +163,7 @@ ByteVector Header::render() const {
v.append(SynchData::fromUInt(d->tagSize));
return v;
}
////////////////////////////////////////////////////////////////////////////////
@@ -171,15 +171,14 @@ ByteVector Header::render() const {
////////////////////////////////////////////////////////////////////////////////
void Header::parse(const ByteVector &data) {
if (data.size() < size())
return;
// do some sanity checking -- even in ID3v2.3.0 and less the tag size is a
// synch-safe integer, so all bytes must be less than 128. If this is not
// true then this is an invalid tag.
// do some sanity checking -- even in ID3v2.3.0 and less the tag size is a synch-safe integer, so all bytes must be less than 128.
// If this is not true then this is an invalid tag.
// note that we're doing things a little out of order here -- the size is
// later in the bytestream than the version
// note that we're doing things a little out of order here -- the size is later in the bytestream than the version
ByteVector sizeData = data.mid(6, 4);
@@ -214,4 +213,5 @@ void Header::parse(const ByteVector &data) {
// Get the size from the remaining four bytes (read above)
d->tagSize = SynchData::toUInt(sizeData); // (structure 3.1 "size")
}

View File

@@ -32,134 +32,122 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
//! An implementation of ID3v2 headers
/*!
* This class implements ID3v2 headers. It attempts to follow, both
* semantically and programmatically, the structure specified in
* the ID3v2 standard. The API is based on the properties of ID3v2 headers
* specified there. If any of the terms used in this documentation are
* unclear please check the specification in the linked section.
* (Structure, <a href="id3v2-structure.html#3.1">3.1</a>)
*/
* This class implements ID3v2 headers.
* It attempts to follow, both semantically and programmatically, the structure specified in the ID3v2 standard.
* The API is based on the properties of ID3v2 headers specified there.
* If any of the terms used in this documentation are unclear please check the specification in the linked section.
* (Structure, <a href="id3v2-structure.html#3.1">3.1</a>)
*/
class TAGLIB_EXPORT Header {
public:
/*!
* Constructs an empty ID3v2 header.
*/
* Constructs an empty ID3v2 header.
*/
Header();
/*!
* Constructs an ID3v2 header based on \a data. parse() is called
* immediately.
*/
* Constructs an ID3v2 header based on \a data. parse() is called immediately.
*/
Header(const ByteVector &data);
/*!
* Destroys the header.
*/
* Destroys the header.
*/
virtual ~Header();
/*!
* Returns the major version number. (Note: This is the 4, not the 2 in
* ID3v2.4.0. The 2 is implied.)
*/
* Returns the major version number. (Note: This is the 4, not the 2 in ID3v2.4.0. The 2 is implied.)
*/
unsigned int majorVersion() const;
/*!
* Set the the major version number to \a version. (Note: This is
* the 4, not the 2 in ID3v2.4.0. The 2 is implied.)
* \see majorVersion()
*
* \note This is used by the internal parser; this will not change the
* version which is written and in general should not be called by API
* users.
*/
* Set the the major version number to \a version. (Note: This is the 4, not the 2 in ID3v2.4.0. The 2 is implied.)
* \see majorVersion()
*
* \note This is used by the internal parser; this will not change the version which is written and in general should not be called by API users.
*/
void setMajorVersion(unsigned int version);
/*!
* Returns the revision number. (Note: This is the 0, not the 4 in
* ID3v2.4.0. The 2 is implied.)
*/
* Returns the revision number. (Note: This is the 0, not the 4 in ID3v2.4.0. The 2 is implied.)
*/
unsigned int revisionNumber() const;
/*!
* Returns true if unsynchronisation has been applied to all frames.
*/
* Returns true if unsynchronisation has been applied to all frames.
*/
bool unsynchronisation() const;
/*!
* Returns true if an extended header is present in the tag.
*/
* Returns true if an extended header is present in the tag.
*/
bool extendedHeader() const;
/*!
* Returns true if the experimental indicator flag is set.
*/
* Returns true if the experimental indicator flag is set.
*/
bool experimentalIndicator() const;
/*!
* Returns true if a footer is present in the tag.
*/
* Returns true if a footer is present in the tag.
*/
bool footerPresent() const;
/*!
* Returns the tag size in bytes. This is the size of the frame content.
* The size of the \e entire tag will be this plus the header size (10
* bytes) and, if present, the footer size (potentially another 10 bytes).
*
* \note This is the value as read from the header to which TagLib attempts
* to provide an API to; it was not a design decision on the part of TagLib
* to not include the mentioned portions of the tag in the \e size.
*
* \see completeTagSize()
*/
* Returns the tag size in bytes.
* This is the size of the frame content.
* The size of the \e entire tag will be this plus the header size (10 bytes) and, if present, the footer size (potentially another 10 bytes).
*
* \note This is the value as read from the header to which TagLib attempts to provide an API to;
* it was not a design decision on the part of TagLib to not include the mentioned portions of the tag in the \e size.
*
* \see completeTagSize()
*/
unsigned int tagSize() const;
/*!
* Returns the tag size, including the header and, if present, the footer
* size.
*
* \see tagSize()
*/
* Returns the tag size, including the header and, if present, the footer size.
*
* \see tagSize()
*/
unsigned int completeTagSize() const;
/*!
* Set the tag size to \a s.
* \see tagSize()
*/
* Set the tag size to \a s.
* \see tagSize()
*/
void setTagSize(unsigned int s);
/*!
* Returns the size of the header. Presently this is always 10 bytes.
*/
* Returns the size of the header. Presently this is always 10 bytes.
*/
static unsigned int size();
/*!
* Returns the string used to identify and ID3v2 tag inside of a file.
* Presently this is always "ID3".
*/
* Returns the string used to identify and ID3v2 tag inside of a file.
* Presently this is always "ID3".
*/
static ByteVector fileIdentifier();
/*!
* Sets the data that will be used as the header. 10 bytes, starting from
* the beginning of \a data are used.
*/
* Sets the data that will be used as the header. 10 bytes, starting from the beginning of \a data are used.
*/
void setData(const ByteVector &data);
/*!
* Renders the Header back to binary format.
*/
* Renders the Header back to binary format.
*/
ByteVector render() const;
protected:
/*!
* Called by setData() to parse the header data. It makes this information
* available through the public API.
*/
* Called by setData() to parse the header data. It makes this information available through the public API.
*/
void parse(const ByteVector &data);
private:

View File

@@ -31,6 +31,7 @@ using namespace Strawberry_TagLib::TagLib;
using namespace ID3v2;
unsigned int SynchData::toUInt(const ByteVector &data) {
unsigned int sum = 0;
bool notSynchSafe = false;
int last = data.size() > 4 ? 3 : data.size() - 1;
@@ -46,8 +47,7 @@ unsigned int SynchData::toUInt(const ByteVector &data) {
if (notSynchSafe) {
// Invalid data; assume this was created by some buggy software that just
// put normal integers here rather than syncsafe ones, and try it that
// way.
// put normal integers here rather than syncsafe ones, and try it that way.
if (data.size() >= 4) {
sum = data.toUInt(0, true);
}
@@ -59,18 +59,22 @@ unsigned int SynchData::toUInt(const ByteVector &data) {
}
return sum;
}
ByteVector SynchData::fromUInt(unsigned int value) {
ByteVector v(4, 0);
for (int i = 0; i < 4; i++)
v[i] = static_cast<unsigned char>(value >> ((3 - i) * 7) & 0x7f);
return v;
}
ByteVector SynchData::decode(const ByteVector &data) {
// We have this optimized method instead of using ByteVector::replace(),
// since it makes a great difference when decoding huge unsynchronized frames.
@@ -92,4 +96,5 @@ ByteVector SynchData::decode(const ByteVector &data) {
result.resize(static_cast<unsigned int>(dst - result.begin()));
return result;
}

View File

@@ -31,36 +31,32 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace ID3v2 {
//! A few functions for ID3v2 synch safe integer conversion
/*!
* In the ID3v2.4 standard most integer values are encoded as "synch safe"
* integers which are encoded in such a way that they will not give false
* MPEG syncs and confuse MPEG decoders. This namespace provides some
* methods for converting to and from these values to ByteVectors for
* things rendering and parsing ID3v2 data.
*/
* In the ID3v2.4 standard most integer values are encoded as "synch safe"
* integers which are encoded in such a way that they will not give false MPEG syncs and confuse MPEG decoders.
* This namespace provides some methods for converting to and from these values to ByteVectors for things rendering and parsing ID3v2 data.
*/
namespace SynchData {
/*!
* This returns the unsigned integer value of \a data where \a data is a
* ByteVector that contains a \e synchsafe integer (Structure,
* <a href="id3v2-structure.html#6.2">6.2</a>). The default \a length of
* 4 is used if another value is not specified.
*/
* This returns the unsigned integer value of \a data where \a data is a ByteVector that contains a \e synchsafe integer (Structure,
* <a href="id3v2-structure.html#6.2">6.2</a>).
* The default \a length of 4 is used if another value is not specified.
*/
TAGLIB_EXPORT unsigned int toUInt(const ByteVector &data);
/*!
* Returns a 4 byte (32 bit) synchsafe integer based on \a value.
*/
* Returns a 4 byte (32 bit) synchsafe integer based on \a value.
*/
TAGLIB_EXPORT ByteVector fromUInt(unsigned int value);
/*!
* Convert the data from unsynchronized data to its original format.
*/
* Convert the data from unsynchronized data to its original format.
*/
TAGLIB_EXPORT ByteVector decode(const ByteVector &input);
} // namespace SynchData

View File

@@ -57,11 +57,11 @@ const long MaxPaddingSize = 1024 * 1024;
class ID3v2::Tag::TagPrivate {
public:
TagPrivate() : factory(0),
file(0),
TagPrivate() : factory(nullptr),
file(nullptr),
tagOffset(0),
extendedHeader(0),
footer(0) {
extendedHeader(nullptr),
footer(nullptr) {
frameList.setAutoDelete(true);
}
@@ -87,11 +87,9 @@ class ID3v2::Tag::TagPrivate {
// StringHandler implementation
////////////////////////////////////////////////////////////////////////////////
Latin1StringHandler::Latin1StringHandler() {
}
Latin1StringHandler::Latin1StringHandler() {}
Latin1StringHandler::~Latin1StringHandler() {
}
Latin1StringHandler::~Latin1StringHandler() {}
String Latin1StringHandler::parse(const ByteVector &data) const {
return String(data, String::Latin1);
@@ -101,13 +99,11 @@ String Latin1StringHandler::parse(const ByteVector &data) const {
// public members
////////////////////////////////////////////////////////////////////////////////
ID3v2::Tag::Tag() : Strawberry_TagLib::TagLib::Tag(),
d(new TagPrivate()) {
ID3v2::Tag::Tag() : Strawberry_TagLib::TagLib::Tag(), d(new TagPrivate()) {
d->factory = FrameFactory::instance();
}
ID3v2::Tag::Tag(File *file, long tagOffset, const FrameFactory *factory) : Strawberry_TagLib::TagLib::Tag(),
d(new TagPrivate()) {
ID3v2::Tag::Tag(File *file, long tagOffset, const FrameFactory *factory) : Strawberry_TagLib::TagLib::Tag(), d(new TagPrivate()) {
d->factory = factory;
d->file = file;
d->tagOffset = tagOffset;
@@ -138,6 +134,7 @@ String ID3v2::Tag::album() const {
}
String ID3v2::Tag::comment() const {
const FrameList &comments = d->frameListMap["COMM"];
if (comments.isEmpty())
@@ -151,9 +148,11 @@ String ID3v2::Tag::comment() const {
}
return comments.front()->toString();
}
String ID3v2::Tag::genre() const {
// TODO: In the next major version (TagLib 2.0) a list of multiple genres
// should be separated by " / " instead of " ". For the moment to keep
// the behavior the same as released versions it is being left with " ".
@@ -192,18 +191,23 @@ String ID3v2::Tag::genre() const {
}
return genres.toString();
}
unsigned int ID3v2::Tag::year() const {
if (!d->frameListMap["TDRC"].isEmpty())
return d->frameListMap["TDRC"].front()->toString().substr(0, 4).toInt();
return 0;
}
unsigned int ID3v2::Tag::track() const {
if (!d->frameListMap["TRCK"].isEmpty())
return d->frameListMap["TRCK"].front()->toString().toInt();
return 0;
}
void ID3v2::Tag::setTitle(const String &s) {
@@ -219,6 +223,7 @@ void ID3v2::Tag::setAlbum(const String &s) {
}
void ID3v2::Tag::setComment(const String &s) {
if (s.isEmpty()) {
removeFrames("COMM");
return;
@@ -231,9 +236,11 @@ void ID3v2::Tag::setComment(const String &s) {
addFrame(f);
f->setText(s);
}
}
void ID3v2::Tag::setGenre(const String &s) {
if (s.isEmpty()) {
removeFrames("TCON");
return;
@@ -256,6 +263,7 @@ void ID3v2::Tag::setGenre(const String &s) {
setTextFrame("TCON", s);
#endif
}
void ID3v2::Tag::setYear(unsigned int i) {
@@ -286,10 +294,6 @@ ExtendedHeader *ID3v2::Tag::extendedHeader() const {
return d->extendedHeader;
}
Footer *ID3v2::Tag::footer() const {
return d->footer;
}
const FrameListMap &ID3v2::Tag::frameListMap() const {
return d->frameListMap;
}
@@ -308,6 +312,7 @@ void ID3v2::Tag::addFrame(Frame *frame) {
}
void ID3v2::Tag::removeFrame(Frame *frame, bool del) {
// remove the frame from the frame list
FrameList::Iterator it = d->frameList.find(frame);
d->frameList.erase(it);
@@ -319,6 +324,7 @@ void ID3v2::Tag::removeFrame(Frame *frame, bool del) {
// ...and delete as desired
if (del)
delete frame;
}
void ID3v2::Tag::removeFrames(const ByteVector &id) {
@@ -337,6 +343,7 @@ PropertyMap ID3v2::Tag::properties() const {
}
void ID3v2::Tag::removeUnsupportedProperties(const StringList &properties) {
for (StringList::ConstIterator it = properties.begin(); it != properties.end(); ++it) {
if (it->startsWith("UNKNOWN/")) {
String frameID = it->substr(String("UNKNOWN/").size());
@@ -346,7 +353,7 @@ void ID3v2::Tag::removeUnsupportedProperties(const StringList &properties) {
// delete all unknown frames of given type
FrameList l = frameList(id);
for (FrameList::ConstIterator fit = l.begin(); fit != l.end(); fit++)
if (dynamic_cast<const UnknownFrame *>(*fit) != 0)
if (dynamic_cast<const UnknownFrame *>(*fit) != nullptr)
removeFrame(*fit);
}
else if (it->size() == 4) {
@@ -358,7 +365,7 @@ void ID3v2::Tag::removeUnsupportedProperties(const StringList &properties) {
if (it->size() <= 5)
continue; // invalid specification
String description = it->substr(5);
Frame *frame = 0;
Frame *frame = nullptr;
if (id == "TXXX")
frame = UserTextIdentificationFrame::find(this, description);
else if (id == "WXXX")
@@ -373,9 +380,11 @@ void ID3v2::Tag::removeUnsupportedProperties(const StringList &properties) {
removeFrame(frame);
}
}
}
PropertyMap ID3v2::Tag::setProperties(const PropertyMap &origProps) {
FrameList framesToDelete;
// we split up the PropertyMap into the "normal" keys and the "complicated" ones,
// which are those according to TIPL or TMCL frames.
@@ -418,6 +427,7 @@ PropertyMap ID3v2::Tag::setProperties(const PropertyMap &origProps) {
for (PropertyMap::ConstIterator it = properties.begin(); it != properties.end(); ++it)
addFrame(Frame::createTextualFrame(it->first, it->second));
return PropertyMap(); // ID3 implements the complete PropertyMap interface, so an empty map is returned
}
ByteVector ID3v2::Tag::render() const {
@@ -426,46 +436,40 @@ ByteVector ID3v2::Tag::render() const {
void ID3v2::Tag::downgradeFrames(FrameList *frames, FrameList *newFrames) const {
#ifdef NO_ITUNES_HACKS
const char *unsupportedFrames[] = {
"ASPI", "EQU2", "RVA2", "SEEK", "SIGN", "TDRL", "TDTG",
"TMOO", "TPRO", "TSOA", "TSOT", "TSST", "TSOP", 0
};
const char *unsupportedFrames[] = { "ASPI", "EQU2", "RVA2", "SEEK", "SIGN", "TDRL", "TDTG", "TMOO", "TPRO", "TSOA", "TSOT", "TSST", "TSOP", nullptr };
#else
// iTunes writes and reads TSOA, TSOT, TSOP to ID3v2.3.
const char *unsupportedFrames[] = {
"ASPI", "EQU2", "RVA2", "SEEK", "SIGN", "TDRL", "TDTG",
"TMOO", "TPRO", "TSST", 0
};
const char *unsupportedFrames[] = { "ASPI", "EQU2", "RVA2", "SEEK", "SIGN", "TDRL", "TDTG", "TMOO", "TPRO", "TSST", nullptr };
#endif
ID3v2::TextIdentificationFrame *frameTDOR = 0;
ID3v2::TextIdentificationFrame *frameTDRC = 0;
ID3v2::TextIdentificationFrame *frameTIPL = 0;
ID3v2::TextIdentificationFrame *frameTMCL = 0;
ID3v2::TextIdentificationFrame *frameTDOR = nullptr;
ID3v2::TextIdentificationFrame *frameTDRC = nullptr;
ID3v2::TextIdentificationFrame *frameTIPL = nullptr;
ID3v2::TextIdentificationFrame *frameTMCL = nullptr;
for (FrameList::ConstIterator it = d->frameList.begin(); it != d->frameList.end(); it++) {
ID3v2::Frame *frame = *it;
ByteVector frameID = frame->header()->frameID();
for (int i = 0; unsupportedFrames[i]; i++) {
if (frameID == unsupportedFrames[i]) {
debug("A frame that is not supported in ID3v2.3 \'" + String(frameID) + "\' has been discarded");
frame = 0;
frame = nullptr;
break;
}
}
if (frame && frameID == "TDOR") {
frameTDOR = dynamic_cast<ID3v2::TextIdentificationFrame *>(frame);
frame = 0;
frame = nullptr;
}
if (frame && frameID == "TDRC") {
frameTDRC = dynamic_cast<ID3v2::TextIdentificationFrame *>(frame);
frame = 0;
frame = nullptr;
}
if (frame && frameID == "TIPL") {
frameTIPL = dynamic_cast<ID3v2::TextIdentificationFrame *>(frame);
frame = 0;
frame = nullptr;
}
if (frame && frameID == "TMCL") {
frameTMCL = dynamic_cast<ID3v2::TextIdentificationFrame *>(frame);
frame = 0;
frame = nullptr;
}
if (frame) {
frames->append(frame);
@@ -522,13 +526,11 @@ void ID3v2::Tag::downgradeFrames(FrameList *frames, FrameList *newFrames) const
frames->append(frameIPLS);
newFrames->append(frameIPLS);
}
}
ByteVector ID3v2::Tag::render(int version) const {
return render(version == 3 ? v3 : v4);
}
ByteVector ID3v2::Tag::render(Version version) const {
// We need to render the "tag data" first so that we have to correct size to
// render in the tag's header. The "tag data" -- everything that is included
// in ID3v2::Header::tagSize() -- includes the extended header, frames and
@@ -601,6 +603,7 @@ ByteVector ID3v2::Tag::render(Version version) const {
std::copy(headerData.begin(), headerData.end(), tagData.begin());
return tagData;
}
Latin1StringHandler const *ID3v2::Tag::latin1StringHandler() {
@@ -619,6 +622,7 @@ void ID3v2::Tag::setLatin1StringHandler(const Latin1StringHandler *handler) {
////////////////////////////////////////////////////////////////////////////////
void ID3v2::Tag::read() {
if (!d->file)
return;
@@ -657,9 +661,11 @@ void ID3v2::Tag::read() {
debug("ID3v2::Tag::read() - Duplicate ID3v2 tags found.");
d->header.setTagSize(d->header.tagSize() + extraSize);
}
}
void ID3v2::Tag::parse(const ByteVector &origData) {
ByteVector data = origData;
if (d->header.unsynchronisation() && d->header.majorVersion() <= 3)
@@ -723,9 +729,11 @@ void ID3v2::Tag::parse(const ByteVector &origData) {
}
d->factory->rebuildAggregateFrames(this);
}
void ID3v2::Tag::setTextFrame(const ByteVector &id, const String &value) {
if (value.isEmpty()) {
removeFrames(id);
return;
@@ -739,4 +747,5 @@ void ID3v2::Tag::setTextFrame(const ByteVector &id, const String &value) {
addFrame(f);
f->setText(value);
}
}

View File

@@ -53,104 +53,92 @@ typedef Map<ByteVector, FrameList> FrameListMap;
//! An abstraction for the ISO-8859-1 string to data encoding in ID3v2 tags.
/*!
* ID3v2 tag can store strings in ISO-8859-1 (Latin1), and TagLib only
* supports genuine ISO-8859-1 by default. However, in practice, non
* ISO-8859-1 encodings are often used instead of ISO-8859-1, such as
* Windows-1252 for western languages, Shift_JIS for Japanese and so on.
*
* Here is an option to read such tags by subclassing this class,
* reimplementing parse() and setting your reimplementation as the default
* with ID3v2::Tag::setStringHandler().
*
* \note Writing non-ISO-8859-1 tags is not implemented intentionally.
* Use UTF-16 or UTF-8 instead.
*
* \see ID3v2::Tag::setStringHandler()
*/
* ID3v2 tag can store strings in ISO-8859-1 (Latin1), and TagLib only supports genuine ISO-8859-1 by default.
* However, in practice, non ISO-8859-1 encodings are often used instead of ISO-8859-1,
* such as Windows-1252 for western languages, Shift_JIS for Japanese and so on.
*
* Here is an option to read such tags by subclassing this class,
* reimplementing parse() and setting your reimplementation as the default
* with ID3v2::Tag::setStringHandler().
*
* \note Writing non-ISO-8859-1 tags is not implemented intentionally.
* Use UTF-16 or UTF-8 instead.
*
* \see ID3v2::Tag::setStringHandler()
*/
class TAGLIB_EXPORT Latin1StringHandler {
public:
Latin1StringHandler();
virtual ~Latin1StringHandler();
/*!
* Decode a string from \a data. The default implementation assumes that
* \a data is an ISO-8859-1 (Latin1) character array.
*/
* Decode a string from \a data. The default implementation assumes that
* \a data is an ISO-8859-1 (Latin1) character array.
*/
virtual String parse(const ByteVector &data) const;
};
//! The main class in the ID3v2 implementation
/*!
* This is the main class in the ID3v2 implementation. It serves two
* functions. This first, as is obvious from the public API, is to provide a
* container for the other ID3v2 related classes. In addition, through the
* read() and parse() protected methods, it provides the most basic level of
* parsing. In these methods the ID3v2 tag is extracted from the file and
* split into data components.
*
* ID3v2 tags have several parts, TagLib attempts to provide an interface
* for them all. header(), footer() and extendedHeader() correspond to those
* data structures in the ID3v2 standard and the APIs for the classes that
* they return attempt to reflect this.
*
* Also ID3v2 tags are built up from a list of frames, which are in turn
* have a header and a list of fields. TagLib provides two ways of accessing
* the list of frames that are in a given ID3v2 tag. The first is simply
* via the frameList() method. This is just a list of pointers to the frames.
* The second is a map from the frame type -- i.e. "COMM" for comments -- and
* a list of frames of that type. (In some cases ID3v2 allows for multiple
* frames of the same type, hence this being a map to a list rather than just
* a map to an individual frame.)
*
* More information on the structure of frames can be found in the ID3v2::Frame
* class.
*
* read() and parse() pass binary data to the other ID3v2 class structures,
* they do not handle parsing of flags or fields, for instance. Those are
* handled by similar functions within those classes.
*
* \note All pointers to data structures within the tag will become invalid
* when the tag is destroyed.
*
* \warning Dealing with the nasty details of ID3v2 is not for the faint of
* heart and should not be done without much meditation on the spec. It's
* rather long, but if you're planning on messing with this class and others
* that deal with the details of ID3v2 (rather than the nice, safe, abstract
* TagLib::Tag and friends), it's worth your time to familiarize yourself
* with said spec (which is distributed with the TagLib sources). TagLib
* tries to do most of the work, but with a little luck, you can still
* convince it to generate invalid ID3v2 tags. The APIs for ID3v2 assume a
* working knowledge of ID3v2 structure. You're been warned.
*/
* This is the main class in the ID3v2 implementation.
* It serves two functions.
* This first, as is obvious from the public API, is to provide a container for the other ID3v2 related classes.
* In addition, through the read() and parse() protected methods,
* it provides the most basic level of parsing.
* In these methods the ID3v2 tag is extracted from the file and split into data components.
*
* ID3v2 tags have several parts, TagLib attempts to provide an interface for them all.
* header(), footer() and extendedHeader() correspond to those data structures in
* the ID3v2 standard and the APIs for the classes that they return attempt to reflect this.
*
* Also ID3v2 tags are built up from a list of frames, which are in turn have a header and a list of fields.
* TagLib provides two ways of accessing the list of frames that are in a given ID3v2 tag.
* The first is simply via the frameList() method. This is just a list of pointers to the frames.
* The second is a map from the frame type -- i.e. "COMM" for comments -- and a list of frames of that type.
* (In some cases ID3v2 allows for multiple frames of the same type, hence this being a map to a list rather than just a map to an individual frame.)
*
* More information on the structure of frames can be found in the ID3v2::Frame class.
*
* read() and parse() pass binary data to the other ID3v2 class structures, they do not handle parsing of flags or fields, for instance.
* Those are handled by similar functions within those classes.
*
* \note All pointers to data structures within the tag will become invalid when the tag is destroyed.
*
* \warning Dealing with the nasty details of ID3v2 is not for the faint of
* heart and should not be done without much meditation on the spec.
* It's rather long, but if you're planning on messing with this class and others that deal with the details of ID3v2
* (rather than the nice, safe, abstract TagLib::Tag and friends), it's worth your time to familiarize yourself with said spec
* (which is distributed with the TagLib sources).
* TagLib tries to do most of the work, but with a little luck, you can still convince it to generate invalid ID3v2 tags.
* The APIs for ID3v2 assume a working knowledge of ID3v2 structure. You're been warned.
*/
class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag {
public:
/*!
* Constructs an empty ID3v2 tag.
*
* \note You must create at least one frame for this tag to be valid.
*/
* Constructs an empty ID3v2 tag.
*
* \note You must create at least one frame for this tag to be valid.
*/
Tag();
/*!
* Constructs an ID3v2 tag read from \a file starting at \a tagOffset.
* \a factory specifies which FrameFactory will be used for the
* construction of new frames.
*
* \note You should be able to ignore the \a factory parameter in almost
* all situations. You would want to specify your own FrameFactory
* subclass in the case that you are extending TagLib to support additional
* frame types, which would be incorporated into your factory.
*
* \see FrameFactory
*/
* Constructs an ID3v2 tag read from \a file starting at \a tagOffset.
* \a factory specifies which FrameFactory will be used for the construction of new frames.
*
* \note You should be able to ignore the \a factory parameter in almost all situations.
* You would want to specify your own FrameFactory subclass in the case that you are extending TagLib
* to support additional frame types, which would be incorporated into your factory.
*
* \see FrameFactory
*/
Tag(File *file, long tagOffset,
const FrameFactory *factory = FrameFactory::instance());
/*!
* Destroys this Tag instance.
*/
* Destroys this Tag instance.
*/
virtual ~Tag();
// Reimplementations.
@@ -174,226 +162,190 @@ class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag {
virtual bool isEmpty() const;
/*!
* Returns a pointer to the tag's header.
*/
* Returns a pointer to the tag's header.
*/
Header *header() const;
/*!
* Returns a pointer to the tag's extended header or null if there is no
* extended header.
*/
* Returns a pointer to the tag's extended header or null if there is no extended header.
*/
ExtendedHeader *extendedHeader() const;
/*!
* Returns a pointer to the tag's footer or null if there is no footer.
*
* \deprecated I don't see any reason to keep this around since there's
* nothing useful to be retrieved from the footer, but well, again, I'm
* prone to change my mind, so this gets to stay around until near a
* release.
*/
TAGLIB_DEPRECATED Footer *footer() const;
/*!
* Returns a reference to the frame list map. This is an FrameListMap of
* all of the frames in the tag.
*
* This is the most convenient structure for accessing the tag's frames.
* Many frame types allow multiple instances of the same frame type so this
* is a map of lists. In most cases however there will only be a single
* frame of a certain type.
*
* Let's say for instance that you wanted to access the frame for total
* beats per minute -- the TBPM frame.
*
* \code
* TagLib::MPEG::File f("foo.mp3");
*
* // Check to make sure that it has an ID3v2 tag
*
* if(f.ID3v2Tag()) {
*
* // Get the list of frames for a specific frame type
*
* TagLib::ID3v2::FrameList l = f.ID3v2Tag()->frameListMap()["TBPM"];
*
* if(!l.isEmpty())
* std::cout << l.front()->toString() << std::endl;
* }
*
* \endcode
*
* \warning You should not modify this data structure directly, instead
* use addFrame() and removeFrame().
*
* \see frameList()
*/
* Returns a reference to the frame list map. This is an FrameListMap of all of the frames in the tag.
*
* This is the most convenient structure for accessing the tag's frames.
* Many frame types allow multiple instances of the same frame type so this is a map of lists.
* In most cases however there will only be a single frame of a certain type.
*
* Let's say for instance that you wanted to access the frame for total beats per minute -- the TBPM frame.
*
* \code
* TagLib::MPEG::File f("foo.mp3");
*
* // Check to make sure that it has an ID3v2 tag
*
* if(f.ID3v2Tag()) {
*
* // Get the list of frames for a specific frame type
*
* TagLib::ID3v2::FrameList l = f.ID3v2Tag()->frameListMap()["TBPM"];
*
* if(!l.isEmpty())
* std::cout << l.front()->toString() << std::endl;
* }
*
* \endcode
*
* \warning You should not modify this data structure directly, instead use addFrame() and removeFrame().
*
* \see frameList()
*/
const FrameListMap &frameListMap() const;
/*!
* Returns a reference to the frame list. This is an FrameList of all of
* the frames in the tag in the order that they were parsed.
*
* This can be useful if for example you want iterate over the tag's frames
* in the order that they occur in the tag.
*
* \warning You should not modify this data structure directly, instead
* use addFrame() and removeFrame().
*/
* Returns a reference to the frame list.
* This is an FrameList of all of the frames in the tag in the order that they were parsed.
*
* This can be useful if for example you want iterate over the tag's frames in the order that they occur in the tag.
*
* \warning You should not modify this data structure directly, instead use addFrame() and removeFrame().
*/
const FrameList &frameList() const;
/*!
* Returns the frame list for frames with the id \a frameID or an empty
* list if there are no frames of that type. This is just a convenience
* and is equivalent to:
*
* \code
* frameListMap()[frameID];
* \endcode
*
* \see frameListMap()
*/
* Returns the frame list for frames with the id \a frameID or an empty list if there are no frames of that type.
* This is just a convenience and is equivalent to:
*
* \code
* frameListMap()[frameID];
* \endcode
*
* \see frameListMap()
*/
const FrameList &frameList(const ByteVector &frameID) const;
/*!
* Add a frame to the tag. At this point the tag takes ownership of
* the frame and will handle freeing its memory.
*
* \note Using this method will invalidate any pointers on the list
* returned by frameList()
*/
* Add a frame to the tag. At this point the tag takes ownership of the frame and will handle freeing its memory.
*
* \note Using this method will invalidate any pointers on the list returned by frameList()
*/
void addFrame(Frame *frame);
/*!
* Remove a frame from the tag. If \a del is true the frame's memory
* will be freed; if it is false, it must be deleted by the user.
*
* \note Using this method will invalidate any pointers on the list
* returned by frameList()
*/
* Remove a frame from the tag.
* If \a del is true the frame's memory will be freed; if it is false, it must be deleted by the user.
*
* \note Using this method will invalidate any pointers on the list returned by frameList()
*/
void removeFrame(Frame *frame, bool del = true);
/*!
* Remove all frames of type \a id from the tag and free their memory.
*
* \note Using this method will invalidate any pointers on the list
* returned by frameList()
*/
* Remove all frames of type \a id from the tag and free their memory.
*
* \note Using this method will invalidate any pointers on the list returned by frameList()
*/
void removeFrames(const ByteVector &id);
/*!
* Implements the unified property interface -- export function.
* This function does some work to translate the hard-specified ID3v2
* frame types into a free-form string-to-stringlist PropertyMap:
* - if ID3v2 frame ID is known by Frame::frameIDToKey(), the returned
* key is used
* - if the frame ID is "TXXX" (user text frame), the description() is
* used as key
* - if the frame ID is "WXXX" (user url frame),
* - if the description is empty or "URL", the key "URL" is used
* - otherwise, the key "URL:<description>" is used;
* - if the frame ID is "COMM" (comments frame),
* - if the description is empty or "COMMENT", the key "COMMENT"
* is used
* - otherwise, the key "COMMENT:<description>" is used;
* - if the frame ID is "USLT" (unsynchronized lyrics),
* - if the description is empty or "LYRICS", the key "LYRICS" is used
* - otherwise, the key "LYRICS:<description>" is used;
* - if the frame ID is "TIPL" (involved peoples list), and if all the
* roles defined in the frame are known in TextIdentificationFrame::involvedPeopleMap(),
* then "<role>=<name>" will be contained in the returned object for each
* - if the frame ID is "TMCL" (musician credit list), then
* "PERFORMER:<instrument>=<name>" will be contained in the returned
* PropertyMap for each defined musician
* In any other case, the unsupportedData() of the returned object will contain
* the frame's ID and, in case of a frame ID which is allowed to appear more than
* once, the description, separated by a "/".
*
*/
* Implements the unified property interface -- export function.
* This function does some work to translate the hard-specified ID3v2
* frame types into a free-form string-to-stringlist PropertyMap:
* - if ID3v2 frame ID is known by Frame::frameIDToKey(), the returned key is used
* - if the frame ID is "TXXX" (user text frame), the description() is used as key
* - if the frame ID is "WXXX" (user url frame),
* - if the description is empty or "URL", the key "URL" is used
* - otherwise, the key "URL:<description>" is used;
* - if the frame ID is "COMM" (comments frame),
* - if the description is empty or "COMMENT", the key "COMMENT" is used
* - otherwise, the key "COMMENT:<description>" is used;
* - if the frame ID is "USLT" (unsynchronized lyrics),
* - if the description is empty or "LYRICS", the key "LYRICS" is used
* - otherwise, the key "LYRICS:<description>" is used;
* - if the frame ID is "TIPL" (involved peoples list), and if all the
* roles defined in the frame are known in TextIdentificationFrame::involvedPeopleMap(),
* then "<role>=<name>" will be contained in the returned object for each
* - if the frame ID is "TMCL" (musician credit list), then
* "PERFORMER:<instrument>=<name>" will be contained in the returned PropertyMap for each defined musician
* In any other case, the unsupportedData() of the returned object will contain
* the frame's ID and, in case of a frame ID which is allowed to appear more than
* once, the description, separated by a "/".
*
*/
PropertyMap properties() const;
/*!
* Removes unsupported frames given by \a properties. The elements of
* \a properties must be taken from properties().unsupportedData(); they
* are of one of the following forms:
* - a four-character frame ID, if the ID3 specification allows only one
* frame with that ID (thus, the frame is uniquely determined)
* - frameID + "/" + description(), when the ID is one of "TXXX", "WXXX",
* "COMM", or "USLT",
* - "UNKNOWN/" + frameID, for frames that could not be parsed by TagLib.
* In that case, *all* unknown frames with the given ID will be removed.
*/
* Removes unsupported frames given by \a properties. The elements of
* \a properties must be taken from properties().unsupportedData(); they
* are of one of the following forms:
* - a four-character frame ID, if the ID3 specification allows only one
* frame with that ID (thus, the frame is uniquely determined)
* - frameID + "/" + description(), when the ID is one of "TXXX", "WXXX",
* "COMM", or "USLT",
* - "UNKNOWN/" + frameID, for frames that could not be parsed by TagLib.
* In that case, *all* unknown frames with the given ID will be removed.
*/
void removeUnsupportedProperties(const StringList &properties);
/*!
* Implements the unified property interface -- import function.
* See the comments in properties().
*/
* Implements the unified property interface -- import function.
* See the comments in properties().
*/
PropertyMap setProperties(const PropertyMap &);
/*!
* Render the tag back to binary data, suitable to be written to disk.
*/
* Render the tag back to binary data, suitable to be written to disk.
*/
ByteVector render() const;
/*!
* \deprecated
*/
TAGLIB_DEPRECATED ByteVector render(int version) const;
/*!
* Render the tag back to binary data, suitable to be written to disk.
*
* The \a version parameter specifies whether ID3v2.4 (default) or ID3v2.3
* should be used.
*/
* Render the tag back to binary data, suitable to be written to disk.
*
* The \a version parameter specifies whether ID3v2.4 (default) or ID3v2.3 should be used.
*/
ByteVector render(Version version) const;
/*!
* Gets the current string handler that decides how the "Latin-1" data
* will be converted to and from binary data.
*
* \see Latin1StringHandler
*/
* Gets the current string handler that decides how the "Latin-1" data will be converted to and from binary data.
*
* \see Latin1StringHandler
*/
static Latin1StringHandler const *latin1StringHandler();
/*!
* Sets the string handler that decides how the "Latin-1" data will be
* converted to and from binary data.
* If the parameter \a handler is null, the previous handler is
* released and default ISO-8859-1 handler is restored.
*
* \note The caller is responsible for deleting the previous handler
* as needed after it is released.
*
* \see Latin1StringHandler
*/
* Sets the string handler that decides how the "Latin-1" data will be converted to and from binary data.
* If the parameter \a handler is null, the previous handler is released and default ISO-8859-1 handler is restored.
*
* \note The caller is responsible for deleting the previous handler as needed after it is released.
*
* \see Latin1StringHandler
*/
static void setLatin1StringHandler(const Latin1StringHandler *handler);
protected:
/*!
* Reads data from the file specified in the constructor. It does basic
* parsing of the data in the largest chunks. It partitions the tag into
* the Header, the body of the tag (which contains the ExtendedHeader and
* frames) and Footer.
*/
* Reads data from the file specified in the constructor.
* It does basic parsing of the data in the largest chunks.
* It partitions the tag into the Header, the body of the tag
* (which contains the ExtendedHeader and frames) and Footer.
*/
void read();
/*!
* This is called by read to parse the body of the tag. It determines if an
* extended header exists and adds frames to the FrameListMap.
*/
* This is called by read to parse the body of the tag. It determines if an
* extended header exists and adds frames to the FrameListMap.
*/
void parse(const ByteVector &data);
/*!
* Sets the value of the text frame with the Frame ID \a id to \a value.
* If the frame does not exist, it is created.
*/
* Sets the value of the text frame with the Frame ID \a id to \a value.
* If the frame does not exist, it is created.
*/
void setTextFrame(const ByteVector &id, const String &value);
/*!
* Dowgrade frames from ID3v2.4 (used internally and by default) to ID3v2.3
*/
* Dowgrade frames from ID3v2.4 (used internally and by default) to ID3v2.3
*/
void downgradeFrames(FrameList *existingFrames, FrameList *newFrames) const;
private:

View File

@@ -53,7 +53,7 @@ class MPEG::File::FilePrivate {
APELocation(-1),
APEOriginalSize(0),
ID3v1Location(-1),
properties(0) {}
properties(nullptr) {}
~FilePrivate() {
delete properties;
@@ -92,6 +92,7 @@ class AdapterFile : public Strawberry_TagLib::TagLib::File {
} // namespace
bool MPEG::File::isSupported(IOStream *stream) {
if (!stream || !stream->isOpen())
return false;
@@ -121,30 +122,25 @@ bool MPEG::File::isSupported(IOStream *stream) {
stream->seek(originalPosition);
return false;
}
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
MPEG::File::File(FileName file, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file),
d(new FilePrivate()) {
MPEG::File::File(FileName file, ID3v2::FrameFactory *frameFactory, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file), d(new FilePrivate(frameFactory)) {
if (isOpen())
read(readProperties);
}
MPEG::File::File(FileName file, ID3v2::FrameFactory *frameFactory,
bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(file),
d(new FilePrivate(frameFactory)) {
if (isOpen())
read(readProperties);
}
MPEG::File::File(IOStream *stream, ID3v2::FrameFactory *frameFactory, bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(stream), d(new FilePrivate(frameFactory)) {
MPEG::File::File(IOStream *stream, ID3v2::FrameFactory *frameFactory,
bool readProperties, Properties::ReadStyle) : Strawberry_TagLib::TagLib::File(stream),
d(new FilePrivate(frameFactory)) {
if (isOpen())
read(readProperties);
}
MPEG::File::~File() {
@@ -164,12 +160,14 @@ void MPEG::File::removeUnsupportedProperties(const StringList &properties) {
}
PropertyMap MPEG::File::setProperties(const PropertyMap &properties) {
// update ID3v1 tag if it exists, but ignore the return value
if (ID3v1Tag())
ID3v1Tag()->setProperties(properties);
return ID3v2Tag(true)->setProperties(properties);
}
MPEG::Properties *MPEG::File::audioProperties() const {
@@ -184,24 +182,8 @@ bool MPEG::File::save(int tags) {
return save(tags, StripOthers);
}
bool MPEG::File::save(int tags, bool stripOthers) {
return save(tags, stripOthers ? StripOthers : StripNone, ID3v2::v4);
}
bool MPEG::File::save(int tags, bool stripOthers, int id3v2Version) {
return save(tags,
stripOthers ? StripOthers : StripNone,
id3v2Version == 3 ? ID3v2::v3 : ID3v2::v4);
}
bool MPEG::File::save(int tags, bool stripOthers, int id3v2Version, bool duplicateTags) {
return save(tags,
stripOthers ? StripOthers : StripNone,
id3v2Version == 3 ? ID3v2::v3 : ID3v2::v4,
duplicateTags ? Duplicate : DoNotDuplicate);
}
bool MPEG::File::save(int tags, StripTags strip, ID3v2::Version version, DuplicateTags duplicate) {
if (readOnly()) {
debug("MPEG::File::save() -- File is read only.");
return false;
@@ -308,6 +290,7 @@ bool MPEG::File::save(int tags, StripTags strip, ID3v2::Version version, Duplica
}
return true;
}
ID3v2::Tag *MPEG::File::ID3v2Tag(bool create) {
@@ -327,6 +310,7 @@ bool MPEG::File::strip(int tags) {
}
bool MPEG::File::strip(int tags, bool freeMemory) {
if (readOnly()) {
debug("MPEG::File::strip() - Cannot strip tags from a read only file.");
return false;
@@ -345,7 +329,7 @@ bool MPEG::File::strip(int tags, bool freeMemory) {
d->ID3v2OriginalSize = 0;
if (freeMemory)
d->tag.set(ID3v2Index, 0);
d->tag.set(ID3v2Index, nullptr);
}
if ((tags & ID3v1) && d->ID3v1Location >= 0) {
@@ -354,7 +338,7 @@ bool MPEG::File::strip(int tags, bool freeMemory) {
d->ID3v1Location = -1;
if (freeMemory)
d->tag.set(ID3v1Index, 0);
d->tag.set(ID3v1Index, nullptr);
}
if ((tags & APE) && d->APELocation >= 0) {
@@ -367,17 +351,15 @@ bool MPEG::File::strip(int tags, bool freeMemory) {
d->APEOriginalSize = 0;
if (freeMemory)
d->tag.set(APEIndex, 0);
d->tag.set(APEIndex, nullptr);
}
return true;
}
void MPEG::File::setID3v2FrameFactory(const ID3v2::FrameFactory *factory) {
d->ID3v2FrameFactory = factory;
}
long MPEG::File::nextFrameOffset(long position) {
ByteVector frameSyncBytes(2, '\0');
while (true) {
@@ -398,9 +380,11 @@ long MPEG::File::nextFrameOffset(long position) {
position += bufferSize();
}
}
long MPEG::File::previousFrameOffset(long position) {
ByteVector frameSyncBytes(2, '\0');
while (position > 0) {
@@ -422,18 +406,22 @@ long MPEG::File::previousFrameOffset(long position) {
}
return -1;
}
long MPEG::File::firstFrameOffset() {
long position = 0;
if (hasID3v2Tag())
position = d->ID3v2Location + ID3v2Tag()->header()->completeTagSize();
return nextFrameOffset(position);
}
long MPEG::File::lastFrameOffset() {
long position;
if (hasAPETag())
@@ -444,6 +432,7 @@ long MPEG::File::lastFrameOffset() {
position = length();
return previousFrameOffset(position);
}
bool MPEG::File::hasID3v1Tag() const {
@@ -463,6 +452,7 @@ bool MPEG::File::hasAPETag() const {
////////////////////////////////////////////////////////////////////////////////
void MPEG::File::read(bool readProperties) {
// Look for an ID3v2 tag
d->ID3v2Location = findID3v2();
@@ -496,9 +486,11 @@ void MPEG::File::read(bool readProperties) {
ID3v2Tag(true);
ID3v1Tag(true);
}
long MPEG::File::findID3v2() {
if (!isValid())
return -1;
@@ -544,4 +536,5 @@ long MPEG::File::findID3v2() {
position += bufferSize();
}
}

View File

@@ -55,17 +55,16 @@ namespace MPEG {
//! An MPEG file class with some useful methods specific to MPEG
/*!
* This implements the generic TagLib::File API and additionally provides
* access to properties that are distinct to MPEG files, notably access
* to the different ID3 tags.
*/
* This implements the generic TagLib::File API and additionally provides
* access to properties that are distinct to MPEG files, notably access
* to the different ID3 tags.
*/
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File {
public:
/*!
* This set of flags is used for various operations and is suitable for
* being OR-ed together.
*/
* This set of flags is used for various operations and is suitable for being OR-ed together.
*/
enum TagTypes {
//! Empty set. Matches no tag types.
NoTags = 0x0000,
@@ -80,302 +79,238 @@ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File {
};
/*!
* Constructs an MPEG 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.
*
* \deprecated This constructor will be dropped in favor of the one below
* in a future version.
*/
File(FileName file, bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
/*!
* Constructs an MPEG file from \a file. If \a readProperties is true the
* file's audio properties will also be read.
*
* If this file contains and ID3v2 tag the frames will be created using
* \a frameFactory.
*
* \note In the current implementation, \a propertiesStyle is ignored.
*/
* Constructs an MPEG file from \a file.
* If \a readProperties is true the file's audio properties will also be read.
*
* If this file contains and ID3v2 tag the frames will be created using
* \a frameFactory.
*
* \note In the current implementation, \a propertiesStyle is ignored.
*/
// BIC: merge with the above constructor
File(FileName file, ID3v2::FrameFactory *frameFactory,
bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
File(FileName file, ID3v2::FrameFactory *frameFactory, bool readProperties = true, Properties::ReadStyle propertiesStyle = Properties::Average);
/*!
* Constructs an MPEG 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.
*
* If this file contains and ID3v2 tag the frames will be created using
* \a frameFactory.
*
* \note In the current implementation, \a propertiesStyle is ignored.
*/
* Constructs an MPEG 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.
*
* If this file contains and ID3v2 tag the frames will be created using \a frameFactory.
*
* \note In the current implementation, \a propertiesStyle is ignored.
*/
File(IOStream *stream, ID3v2::FrameFactory *frameFactory,
bool readProperties = true,
Properties::ReadStyle propertiesStyle = Properties::Average);
/*!
* Destroys this instance of the File.
*/
* Destroys this instance of the File.
*/
virtual ~File();
/*!
* Returns a pointer to a tag that is the union of the ID3v2 and ID3v1
* tags. The ID3v2 tag is given priority in reading the information -- if
* requested information exists in both the ID3v2 tag and the ID3v1 tag,
* the information from the ID3v2 tag will be returned.
*
* If you would like more granular control over the content of the tags,
* with the concession of generality, use the tag-type specific calls.
*
* \note As this tag is not implemented as an ID3v2 tag or an ID3v1 tag,
* but a union of the two this pointer may not be cast to the specific
* tag types.
*
* \see ID3v1Tag()
* \see ID3v2Tag()
* \see APETag()
*/
* Returns a pointer to a tag that is the union of the ID3v2 and ID3v1 tags.
* The ID3v2 tag is given priority in reading the information -- if requested information exists in both the ID3v2 tag and the ID3v1 tag,
* the information from the ID3v2 tag will be returned.
*
* If you would like more granular control over the content of the tags,
* with the concession of generality, use the tag-type specific calls.
*
* \note As this tag is not implemented as an ID3v2 tag or an ID3v1 tag,
* but a union of the two this pointer may not be cast to the specific tag types.
*
* \see ID3v1Tag()
* \see ID3v2Tag()
* \see APETag()
*/
virtual Tag *tag() const;
/*!
* Implements the reading part of the unified property interface.
* If the file contains more than one tag, only the
* first one (in the order ID3v2, APE, ID3v1) will be converted to the
* PropertyMap.
*/
* Implements the reading part of the unified property interface.
* If the file contains more than one tag,
* only the first one (in the order ID3v2, APE, ID3v1) will be converted to the PropertyMap.
*/
PropertyMap properties() const;
void removeUnsupportedProperties(const StringList &properties);
/*!
* Implements the writing part of the unified tag dictionary interface.
* In order to avoid problems with deprecated tag formats, this method
* always creates an ID3v2 tag if necessary.
* If an ID3v1 tag exists, it will be updated as well, within the
* limitations of that format.
* The returned PropertyMap refers to the ID3v2 tag only.
*/
* Implements the writing part of the unified tag dictionary interface.
* In order to avoid problems with deprecated tag formats,
* this method always creates an ID3v2 tag if necessary.
* If an ID3v1 tag exists, it will be updated as well, within the limitations of that format.
* The returned PropertyMap refers to the ID3v2 tag only.
*/
PropertyMap setProperties(const PropertyMap &);
/*!
* Returns the MPEG::Properties for this file. If no audio properties
* were read then this will return a null pointer.
*/
* Returns the MPEG::Properties for this file.
* If no audio properties were read then this will return a null pointer.
*/
virtual Properties *audioProperties() const;
/*!
* Save the file. If at least one tag -- ID3v1 or ID3v2 -- exists this
* will duplicate its content into the other tag. This returns true
* if saving was successful.
*
* If neither exists or if both tags are empty, this will strip the tags
* from the file.
*
* This is the same as calling save(AllTags);
*
* If you would like more granular control over the content of the tags,
* with the concession of generality, use parameterized save call below.
*
* \see save(int tags)
*/
* Save the file. If at least one tag -- ID3v1 or ID3v2 -- exists this will duplicate its content into the other tag.
* This returns true if saving was successful.
*
* If neither exists or if both tags are empty, this will strip the tags from the file.
*
* This is the same as calling save(AllTags);
*
* If you would like more granular control over the content of the tags,
* with the concession of generality, use parameterized save call below.
*
* \see save(int tags)
*/
virtual bool save();
/*!
* Save the file. This will attempt to save all of the tag types that are
* specified by OR-ing together TagTypes values. The save() method above
* uses AllTags. This returns true if saving was successful.
*
* This strips all tags not included in the mask, but does not modify them
* in memory, so later calls to save() which make use of these tags will
* remain valid. This also strips empty tags.
*/
* Save the file.
* This will attempt to save all of the tag types that are specified by OR-ing together TagTypes values.
* The save() method above uses AllTags. This returns true if saving was successful.
*
* This strips all tags not included in the mask, but does not modify them
* in memory, so later calls to save() which make use of these tags will remain valid.
* This also strips empty tags.
*/
bool save(int tags);
/*!
* \deprecated
*/
// BIC: combine with the above method
TAGLIB_DEPRECATED bool save(int tags, bool stripOthers);
* Save the file. This will attempt to save all of the tag types that are
* specified by OR-ing together TagTypes values.
*
* \a strip can be set to strip all tags except those in \a tags.
* Those tags will not be modified in memory, and thus remain valid.
*
* \a version specifies the ID3v2 version to be used for writing tags.
* By default, the latest standard, ID3v2.4 is used.
*
* If \a duplicate is set to DuplicateTags and at least one tag -- ID3v1
* or ID3v2 -- exists this will duplicate its content into the other tag.
*/
bool save(int tags, StripTags strip, ID3v2::Version version = ID3v2::v4, DuplicateTags duplicate = Duplicate);
/*!
* \deprecated
*/
// BIC: combine with the above method
TAGLIB_DEPRECATED bool save(int tags, bool stripOthers, int id3v2Version);
/*!
* \deprecated
*/
// BIC: combine with the above method
TAGLIB_DEPRECATED bool save(int tags, bool stripOthers, int id3v2Version, bool duplicateTags);
/*!
* Save the file. This will attempt to save all of the tag types that are
* specified by OR-ing together TagTypes values.
*
* \a strip can be set to strip all tags except those in \a tags. Those
* tags will not be modified in memory, and thus remain valid.
*
* \a version specifies the ID3v2 version to be used for writing tags. By
* default, the latest standard, ID3v2.4 is used.
*
* If \a duplicate is set to DuplicateTags and at least one tag -- ID3v1
* or ID3v2 -- exists this will duplicate its content into the other tag.
*/
bool save(int tags, StripTags strip,
ID3v2::Version version = ID3v2::v4,
DuplicateTags duplicate = Duplicate);
/*!
* Returns a pointer to the ID3v2 tag of the file.
*
* If \a create is false (the default) this may return a null pointer
* if there is no valid ID3v2 tag. If \a create is true it will create
* an ID3v2 tag if one does not exist and returns a valid pointer.
*
* \note This may return a valid pointer regardless of whether or not the
* file on disk has an ID3v2 tag. Use hasID3v2Tag() to check if the file
* on disk actually has an ID3v2 tag.
*
* \note The Tag <b>is still</b> owned by the MPEG::File and should not be
* deleted by the user. It will be deleted when the file (object) is
* destroyed.
*
* \see hasID3v2Tag()
*/
* Returns a pointer to the ID3v2 tag of the file.
*
* If \a create is false (the default) this may return a null pointer
* if there is no valid ID3v2 tag.
* If \a create is true it will create an ID3v2 tag if one does not exist and returns a valid pointer.
*
* \note This may return a valid pointer regardless of whether or not the file on disk has an ID3v2 tag.
* Use hasID3v2Tag() to check if the file on disk actually has an ID3v2 tag.
*
* \note The Tag <b>is still</b> owned by the MPEG::File and should not be deleted by the user.
* It will be deleted when the file (object) is destroyed.
*
* \see hasID3v2Tag()
*/
ID3v2::Tag *ID3v2Tag(bool create = false);
/*!
* Returns a pointer to the ID3v1 tag of the file.
*
* If \a create is false (the default) this may return a null pointer
* if there is no valid ID3v1 tag. If \a create is true it will create
* an ID3v1 tag if one does not exist and returns a valid pointer.
*
* \note This may return a valid pointer regardless of whether or not the
* file on disk has an ID3v1 tag. Use hasID3v1Tag() to check if the file
* on disk actually has an ID3v1 tag.
*
* \note The Tag <b>is still</b> owned by the MPEG::File and should not be
* deleted by the user. It will be deleted when the file (object) is
* destroyed.
*
* \see hasID3v1Tag()
*/
* Returns a pointer to the ID3v1 tag of the file.
*
* If \a create is false (the default) this may return a null pointer
* if there is no valid ID3v1 tag.
* If \a create is true it will create an ID3v1 tag if one does not exist and returns a valid pointer.
*
* \note This may return a valid pointer regardless of whether or not the file on disk has an ID3v1 tag.
* Use hasID3v1Tag() to check if the file on disk actually has an ID3v1 tag.
*
* \note The Tag <b>is still</b> owned by the MPEG::File and should not be deleted by the user.
* It will be deleted when the file (object) is destroyed.
*
* \see hasID3v1Tag()
*/
ID3v1::Tag *ID3v1Tag(bool create = false);
/*!
* Returns a pointer to the APE tag of the file.
*
* If \a create is false (the default) this may return a null pointer
* if there is no valid APE tag. If \a create is true it will create
* an APE tag if one does not exist and returns a valid pointer.
*
* \note This may return a valid pointer regardless of whether or not the
* file on disk has an APE tag. Use hasAPETag() to check if the file
* on disk actually has an APE tag.
*
* \note The Tag <b>is still</b> owned by the MPEG::File and should not be
* deleted by the user. It will be deleted when the file (object) is
* destroyed.
*
* \see hasAPETag()
*/
* Returns a pointer to the APE tag of the file.
*
* If \a create is false (the default) this may return a null pointer if there is no valid APE tag.
* If \a create is true it will create an APE tag if one does not exist and returns a valid pointer.
*
* \note This may return a valid pointer regardless of whether or not the file on disk has an APE tag.
* Use hasAPETag() to check if the file on disk actually has an APE tag.
*
* \note The Tag <b>is still</b> owned by the MPEG::File and should not be deleted by the user.
* It will be deleted when the file (object) is destroyed.
*
* \see hasAPETag()
*/
APE::Tag *APETag(bool create = false);
/*!
* This will strip the tags that match the OR-ed together TagTypes from the
* file. By default it strips all tags. It returns true if the tags are
* successfully stripped.
*
* This is equivalent to strip(tags, true)
*
* \note This will also invalidate pointers to the ID3 and APE tags
* as their memory will be freed.
*
* \note This will update the file immediately.
*/
* This will strip the tags that match the OR-ed together TagTypes from the file.
* By default it strips all tags.
* It returns true if the tags are successfully stripped.
*
* This is equivalent to strip(tags, true)
*
* \note This will also invalidate pointers to the ID3 and APE tags as their memory will be freed.
*
* \note This will update the file immediately.
*/
bool strip(int tags = AllTags);
/*!
* This will strip the tags that match the OR-ed together TagTypes from the
* file. By default it strips all tags. It returns true if the tags are
* successfully stripped.
*
* If \a freeMemory is true the ID3 and APE tags will be deleted and
* pointers to them will be invalidated.
*
* \note This will update the file immediately.
*/
* This will strip the tags that match the OR-ed together TagTypes from the file.
* By default it strips all tags. It returns true if the tags are successfully stripped.
*
* If \a freeMemory is true the ID3 and APE tags will be deleted and pointers to them will be invalidated.
*
* \note This will update the file immediately.
*/
// BIC: merge with the method above
bool strip(int tags, bool freeMemory);
/*!
* Set the ID3v2::FrameFactory to something other than the default.
*
* \see ID3v2FrameFactory
* \deprecated This value should be passed in via the constructor
*/
TAGLIB_DEPRECATED void setID3v2FrameFactory(const ID3v2::FrameFactory *factory);
/*!
* Returns the position in the file of the first MPEG frame.
*/
* Returns the position in the file of the first MPEG frame.
*/
long firstFrameOffset();
/*!
* Returns the position in the file of the next MPEG frame,
* using the current position as start
*/
* Returns the position in the file of the next MPEG frame, using the current position as start
*/
long nextFrameOffset(long position);
/*!
* Returns the position in the file of the previous MPEG frame,
* using the current position as start
*/
* Returns the position in the file of the previous MPEG frame, using the current position as start
*/
long previousFrameOffset(long position);
/*!
* Returns the position in the file of the last MPEG frame.
*/
* Returns the position in the file of the last MPEG frame.
*/
long lastFrameOffset();
/*!
* Returns whether or not the file on disk actually has an ID3v1 tag.
*
* \see ID3v1Tag()
*/
* Returns whether or not the file on disk actually has an ID3v1 tag.
*
* \see ID3v1Tag()
*/
bool hasID3v1Tag() const;
/*!
* Returns whether or not the file on disk actually has an ID3v2 tag.
*
* \see ID3v2Tag()
*/
* Returns whether or not the file on disk actually has an ID3v2 tag.
*
* \see ID3v2Tag()
*/
bool hasID3v2Tag() const;
/*!
* Returns whether or not the file on disk actually has an APE tag.
*
* \see APETag()
*/
* Returns whether or not the file on disk actually has an APE tag.
*
* \see APETag()
*/
bool hasAPETag() const;
/*!
* Returns whether or not the given \a stream can be opened as an MPEG
* file.
*
* \note This method is designed to do a quick check. The result may
* not necessarily be correct.
*/
* Returns whether or not the given \a stream can be opened as an MPEG file.
*
* \note This method is designed to do a quick check. The result may not necessarily be correct.
*/
static bool isSupported(IOStream *stream);
private:
@@ -388,6 +323,7 @@ class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File {
class FilePrivate;
FilePrivate *d;
};
} // namespace MPEG
} // namespace TagLib
} // namespace Strawberry_TagLib

View File

@@ -67,10 +67,6 @@ class MPEG::Header::HeaderPrivate : public RefCounter {
// public members
////////////////////////////////////////////////////////////////////////////////
MPEG::Header::Header(const ByteVector &) : d(new HeaderPrivate()) {
debug("MPEG::Header::Header() - This constructor is no longer used.");
}
MPEG::Header::Header(File *file, long offset, bool checkLength) : d(new HeaderPrivate()) {
parse(file, offset, checkLength);
}
@@ -133,6 +129,7 @@ int MPEG::Header::samplesPerFrame() const {
}
MPEG::Header &MPEG::Header::operator=(const Header &h) {
if (&h == this)
return *this;
@@ -142,6 +139,7 @@ MPEG::Header &MPEG::Header::operator=(const Header &h) {
d = h.d;
d->ref();
return *this;
}
////////////////////////////////////////////////////////////////////////////////
@@ -149,6 +147,7 @@ MPEG::Header &MPEG::Header::operator=(const Header &h) {
////////////////////////////////////////////////////////////////////////////////
void MPEG::Header::parse(File *file, long offset, bool checkLength) {
file->seek(offset);
const ByteVector data = file->readBlock(4);
@@ -298,4 +297,5 @@ void MPEG::Header::parse(File *file, long offset, bool checkLength) {
// Now that we're done parsing, set this to be a valid frame.
d->isValid = true;
}

View File

@@ -39,49 +39,41 @@ namespace MPEG {
//! An implementation of MP3 frame headers
/*!
* This is an implementation of MPEG Layer III headers. The API follows more
* or less the binary format of these headers. I've used
* <a href="http://www.mp3-tech.org/programmer/frame_header.html">this</a>
* document as a reference.
*/
* This is an implementation of MPEG Layer III headers. The API follows more
* or less the binary format of these headers. I've used
* <a href="http://www.mp3-tech.org/programmer/frame_header.html">this</a>
* document as a reference.
*/
class TAGLIB_EXPORT Header {
public:
/*!
* Parses an MPEG header based on \a data.
*
* \deprecated
*/
TAGLIB_DEPRECATED Header(const ByteVector &data);
/*!
* Parses an MPEG header based on \a file and \a offset.
*
* \note If \a checkLength is true, this requires the next MPEG frame to
* check if the frame length is parsed and calculated correctly. So it's
* suitable for seeking for the first valid frame.
*/
* Parses an MPEG header based on \a file and \a offset.
*
* \note If \a checkLength is true, this requires the next MPEG frame to
* check if the frame length is parsed and calculated correctly.
* So it's suitable for seeking for the first valid frame.
*/
Header(File *file, long offset, bool checkLength = true);
/*!
* Does a shallow copy of \a h.
*/
* Does a shallow copy of \a h.
*/
Header(const Header &h);
/*!
* Destroys this Header instance.
*/
* Destroys this Header instance.
*/
virtual ~Header();
/*!
* Returns true if the frame is at least an appropriate size and has
* legal values.
*/
* Returns true if the frame is at least an appropriate size and has legal values.
*/
bool isValid() const;
/*!
* The MPEG Version.
*/
* The MPEG Version.
*/
enum Version {
//! MPEG Version 1
Version1 = 0,
@@ -92,39 +84,39 @@ class TAGLIB_EXPORT Header {
};
/*!
* Returns the MPEG Version of the header.
*/
* Returns the MPEG Version of the header.
*/
Version version() const;
/*!
* Returns the layer version. This will be between the values 1-3.
*/
* Returns the layer version. This will be between the values 1-3.
*/
int layer() const;
/*!
* Returns true if the MPEG protection bit is enabled.
*/
* Returns true if the MPEG protection bit is enabled.
*/
bool protectionEnabled() const;
/*!
* Returns the bitrate encoded in the header.
*/
* Returns the bitrate encoded in the header.
*/
int bitrate() const;
/*!
* Returns the sample rate in Hz.
*/
* Returns the sample rate in Hz.
*/
int sampleRate() const;
/*!
* Returns true if the frame is padded.
*/
* Returns true if the frame is padded.
*/
bool isPadded() const;
/*!
* There are a few combinations or one or two channel audio that are
* possible:
*/
* There are a few combinations or one or two channel audio that are
* possible:
*/
enum ChannelMode {
//! Stereo
Stereo = 0,
@@ -137,33 +129,33 @@ class TAGLIB_EXPORT Header {
};
/*!
* Returns the channel mode for this frame.
*/
* Returns the channel mode for this frame.
*/
ChannelMode channelMode() const;
/*!
* Returns true if the copyrighted bit is set.
*/
* Returns true if the copyrighted bit is set.
*/
bool isCopyrighted() const;
/*!
* Returns true if the "original" bit is set.
*/
* Returns true if the "original" bit is set.
*/
bool isOriginal() const;
/*!
* Returns the frame length in bytes.
*/
* Returns the frame length in bytes.
*/
int frameLength() const;
/*!
* Returns the number of frames per sample.
*/
* Returns the number of frames per sample.
*/
int samplesPerFrame() const;
/*!
* Makes a shallow copy of the header.
*/
* Makes a shallow copy of the header.
*/
Header &operator=(const Header &h);
private:
@@ -172,6 +164,7 @@ class TAGLIB_EXPORT Header {
class HeaderPrivate;
HeaderPrivate *d;
};
} // namespace MPEG
} // namespace TagLib
} // namespace Strawberry_TagLib

View File

@@ -36,7 +36,7 @@ using namespace Strawberry_TagLib::TagLib;
class MPEG::Properties::PropertiesPrivate {
public:
PropertiesPrivate() : xingHeader(0),
PropertiesPrivate() : xingHeader(nullptr),
length(0),
bitrate(0),
sampleRate(0),
@@ -69,8 +69,7 @@ class MPEG::Properties::PropertiesPrivate {
// public members
////////////////////////////////////////////////////////////////////////////////
MPEG::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style),
d(new PropertiesPrivate()) {
MPEG::Properties::Properties(File *file, ReadStyle style) : AudioProperties(style), d(new PropertiesPrivate()) {
read(file);
}
@@ -135,6 +134,7 @@ bool MPEG::Properties::isOriginal() const {
////////////////////////////////////////////////////////////////////////////////
void MPEG::Properties::read(File *file) {
// Only the first valid frame is required if we have a VBR header.
const long firstFrameOffset = file->firstFrameOffset();
@@ -152,7 +152,7 @@ void MPEG::Properties::read(File *file) {
d->xingHeader = new XingHeader(file->readBlock(firstHeader.frameLength()));
if (!d->xingHeader->isValid()) {
delete d->xingHeader;
d->xingHeader = 0;
d->xingHeader = nullptr;
}
if (d->xingHeader && firstHeader.samplesPerFrame() > 0 && firstHeader.sampleRate() > 0) {
@@ -197,4 +197,5 @@ void MPEG::Properties::read(File *file) {
d->channelMode = firstHeader.channelMode();
d->isCopyrighted = firstHeader.isCopyrighted();
d->isOriginal = firstHeader.isOriginal();
}

View File

@@ -33,7 +33,6 @@
namespace Strawberry_TagLib {
namespace TagLib {
namespace MPEG {
class File;
@@ -42,99 +41,95 @@ class XingHeader;
//! An implementation of audio property reading for MP3
/*!
* This reads the data from an MPEG Layer III stream found in the
* AudioProperties API.
*/
* This reads the data from an MPEG Layer III stream found in the AudioProperties API.
*/
class TAGLIB_EXPORT Properties : public AudioProperties {
public:
/*!
* Create an instance of MPEG::Properties with the data read from the
* MPEG::File \a file.
*/
* Create an instance of MPEG::Properties with the data read from the MPEG::File \a file.
*/
Properties(File *file, ReadStyle style = Average);
/*!
* Destroys this MPEG Properties instance.
*/
* Destroys this MPEG 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
*/
* 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
*/
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 a pointer to the Xing/VBRI header if one exists or null if no
* Xing/VBRI header was found.
*/
* Returns a pointer to the Xing/VBRI header if one exists or null if no Xing/VBRI header was found.
*/
const XingHeader *xingHeader() const;
/*!
* Returns the MPEG Version of the file.
*/
* Returns the MPEG Version of the file.
*/
Header::Version version() const;
/*!
* Returns the layer version. This will be between the values 1-3.
*/
* Returns the layer version. This will be between the values 1-3.
*/
int layer() const;
/*!
* Returns true if the MPEG protection bit is enabled.
*/
* Returns true if the MPEG protection bit is enabled.
*/
bool protectionEnabled() const;
/*!
* Returns the channel mode for this frame.
*/
* Returns the channel mode for this frame.
*/
Header::ChannelMode channelMode() const;
/*!
* Returns true if the copyrighted bit is set.
*/
* Returns true if the copyrighted bit is set.
*/
bool isCopyrighted() const;
/*!
* Returns true if the "original" bit is set.
*/
* Returns true if the "original" bit is set.
*/
bool isOriginal() const;
private:
@@ -146,6 +141,7 @@ class TAGLIB_EXPORT Properties : public AudioProperties {
class PropertiesPrivate;
PropertiesPrivate *d;
};
} // namespace MPEG
} // namespace TagLib
} // namespace Strawberry_TagLib

View File

@@ -36,13 +36,13 @@ namespace MPEG {
namespace {
/*!
* MPEG frames can be recognized by the bit pattern 11111111 111, so the
* first byte is easy to check for, however checking to see if the second byte
* starts with \e 111 is a bit more tricky, hence these functions.
*
* \note This does not check the length of the vector, since this is an
* internal utility function.
*/
* MPEG frames can be recognized by the bit pattern 11111111 111, so the
* first byte is easy to check for, however checking to see if the second byte
* starts with \e 111 is a bit more tricky, hence these functions.
*
* \note This does not check the length of the vector, since this is an
* internal utility function.
*/
inline bool isFrameSync(const ByteVector &bytes, unsigned int offset = 0) {
// 0xFF in the second byte is possible in theory, but it's very unlikely.

View File

@@ -34,9 +34,7 @@ using namespace Strawberry_TagLib::TagLib;
class MPEG::XingHeader::XingHeaderPrivate {
public:
XingHeaderPrivate() : frames(0),
size(0),
type(MPEG::XingHeader::Invalid) {}
XingHeaderPrivate() : frames(0), size(0), type(MPEG::XingHeader::Invalid) {}
unsigned int frames;
unsigned int size;
@@ -72,16 +70,12 @@ MPEG::XingHeader::HeaderType MPEG::XingHeader::type() const {
return d->type;
}
int MPEG::XingHeader::xingHeaderOffset(Strawberry_TagLib::TagLib::MPEG::Header::Version /*v*/,
Strawberry_TagLib::TagLib::MPEG::Header::ChannelMode /*c*/) {
return 0;
}
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
void MPEG::XingHeader::parse(const ByteVector &data) {
// Look for a Xing header.
long offset = data.find("Xing");
@@ -126,4 +120,5 @@ void MPEG::XingHeader::parse(const ByteVector &data) {
d->type = VBRI;
}
}
}

View File

@@ -41,78 +41,67 @@ class File;
//! An implementation of the Xing/VBRI headers
/*!
* This is a minimalistic implementation of the Xing/VBRI VBR headers.
* Xing/VBRI headers are often added to VBR (variable bit rate) MP3 streams
* to make it easy to compute the length and quality of a VBR stream. Our
* implementation is only concerned with the total size of the stream (so
* that we can calculate the total playing time and the average bitrate).
* It uses <a href="http://home.pcisys.net/~melanson/codecs/mp3extensions.txt">
* this text</a> and the XMMS sources as references.
*/
* This is a minimalistic implementation of the Xing/VBRI VBR headers.
* Xing/VBRI headers are often added to VBR (variable bit rate) MP3 streams
* to make it easy to compute the length and quality of a VBR stream.
* Our implementation is only concerned with the total size of the stream
* (so that we can calculate the total playing time and the average bitrate).
* It uses <a href="http://home.pcisys.net/~melanson/codecs/mp3extensions.txt">
* this text</a> and the XMMS sources as references.
*/
class TAGLIB_EXPORT XingHeader {
public:
/*!
* The type of the VBR header.
*/
* The type of the VBR header.
*/
enum HeaderType {
/*!
* Invalid header or no VBR header found.
*/
* Invalid header or no VBR header found.
*/
Invalid = 0,
/*!
* Xing header.
*/
* Xing header.
*/
Xing = 1,
/*!
* VBRI header.
*/
* VBRI header.
*/
VBRI = 2,
};
/*!
* Parses an Xing/VBRI header based on \a data which contains the entire
* first MPEG frame.
*/
* Parses an Xing/VBRI header based on \a data which contains the entire first MPEG frame.
*/
XingHeader(const ByteVector &data);
/*!
* Destroy this XingHeader instance.
*/
* Destroy this XingHeader instance.
*/
virtual ~XingHeader();
/*!
* Returns true if the data was parsed properly and if there is a valid
* Xing/VBRI header present.
*/
* Returns true if the data was parsed properly and if there is a valid Xing/VBRI header present.
*/
bool isValid() const;
/*!
* Returns the total number of frames.
*/
* Returns the total number of frames.
*/
unsigned int totalFrames() const;
/*!
* Returns the total size of stream in bytes.
*/
* Returns the total size of stream in bytes.
*/
unsigned int totalSize() const;
/*!
* Returns the type of the VBR header.
*/
* Returns the type of the VBR header.
*/
HeaderType type() const;
/*!
* Returns the offset for the start of this Xing header, given the
* version and channels of the frame
*
* \deprecated Always returns 0.
*/
TAGLIB_DEPRECATED static int xingHeaderOffset(Strawberry_TagLib::TagLib::MPEG::Header::Version v,
Strawberry_TagLib::TagLib::MPEG::Header::ChannelMode c);
private:
XingHeader(const XingHeader &);
XingHeader &operator=(const XingHeader &);