mirror of
https://github.com/taglib/taglib.git
synced 2025-07-19 05:24:25 -04:00
This commit was manufactured by cvs2svn to accommodate
a server-side copy/move. git-svn-id: svn://anonsvn.kde.org/home/kde/trunk/kdesupport/taglib@288617 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
This commit is contained in:
23
mpeg/id3v2/Makefile.am
Normal file
23
mpeg/id3v2/Makefile.am
Normal file
@ -0,0 +1,23 @@
|
||||
SUBDIRS = frames
|
||||
INCLUDES = \
|
||||
-I$(top_srcdir)/taglib \
|
||||
-I$(top_srcdir)/taglib/toolkit \
|
||||
-I$(top_srcdir)/taglib/mpeg \
|
||||
-I$(top_srcdir)/taglib/mpeg/id3v1 \
|
||||
$(all_includes)
|
||||
|
||||
noinst_LTLIBRARIES = libid3v2.la
|
||||
|
||||
libid3v2_la_SOURCES = \
|
||||
id3v2framefactory.cpp id3v2synchdata.cpp id3v2tag.cpp \
|
||||
id3v2header.cpp id3v2frame.cpp id3v2footer.cpp \
|
||||
id3v2extendedheader.cpp
|
||||
|
||||
taglib_include_HEADERS = \
|
||||
id3v2extendedheader.h id3v2frame.h id3v2header.h \
|
||||
id3v2synchdata.h id3v2footer.h id3v2framefactory.h id3v2tag.h
|
||||
|
||||
taglib_includedir = $(includedir)/taglib
|
||||
libid3v2_la_LIBADD = ./frames/libframes.la
|
||||
|
||||
EXTRA_DIST = $(libid3v2_la_SOURCES) $(taglib_include_HEADERS) id3v2.4.0-frames.txt id3v2.4.0-structure.txt
|
13
mpeg/id3v2/frames/Makefile.am
Normal file
13
mpeg/id3v2/frames/Makefile.am
Normal file
@ -0,0 +1,13 @@
|
||||
INCLUDES = \
|
||||
-I$(top_srcdir)/taglib/toolkit \
|
||||
-I$(top_srcdir)/taglib/mpeg/id3v2 \
|
||||
$(all_includes)
|
||||
|
||||
noinst_LTLIBRARIES = libframes.la
|
||||
|
||||
libframes_la_SOURCES = unknownframe.cpp textidentificationframe.cpp commentsframe.cpp
|
||||
|
||||
taglib_include_HEADERS = unknownframe.h textidentificationframe.h commentsframe.h
|
||||
taglib_includedir = $(includedir)/taglib
|
||||
|
||||
EXTRA_DIST = $(libframes_la_SOURCES) $(taglib_include_HEADERS)
|
152
mpeg/id3v2/frames/commentsframe.cpp
Normal file
152
mpeg/id3v2/frames/commentsframe.cpp
Normal file
@ -0,0 +1,152 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2002, 2003 by Scott Wheeler
|
||||
email : wheeler@kde.org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
* USA *
|
||||
***************************************************************************/
|
||||
|
||||
#include <tbytevectorlist.h>
|
||||
#include <tdebug.h>
|
||||
|
||||
#include "commentsframe.h"
|
||||
|
||||
using namespace TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
class CommentsFrame::CommentsFramePrivate
|
||||
{
|
||||
public:
|
||||
CommentsFramePrivate() : textEncoding(String::Latin1) {}
|
||||
String::Type textEncoding;
|
||||
ByteVector language;
|
||||
String description;
|
||||
String text;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CommentsFrame::CommentsFrame(String::Type encoding) : Frame("COMM")
|
||||
{
|
||||
d = new CommentsFramePrivate();
|
||||
d->textEncoding = encoding;
|
||||
}
|
||||
|
||||
CommentsFrame::CommentsFrame(const ByteVector &data) : Frame(data)
|
||||
{
|
||||
d = new CommentsFramePrivate();
|
||||
parseFields(data.mid(Header::size(), size()));
|
||||
}
|
||||
|
||||
CommentsFrame::~CommentsFrame()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
String CommentsFrame::toString() const
|
||||
{
|
||||
return d->text;
|
||||
}
|
||||
|
||||
ByteVector CommentsFrame::language() const
|
||||
{
|
||||
return d->language;
|
||||
}
|
||||
|
||||
String CommentsFrame::description() const
|
||||
{
|
||||
return d->description;
|
||||
}
|
||||
|
||||
String CommentsFrame::text() const
|
||||
{
|
||||
return d->text;
|
||||
}
|
||||
|
||||
void CommentsFrame::setLanguage(const ByteVector &languageEncoding)
|
||||
{
|
||||
d->language = languageEncoding.mid(0, 3);
|
||||
}
|
||||
|
||||
void CommentsFrame::setDescription(const String &s)
|
||||
{
|
||||
d->description = s;
|
||||
}
|
||||
|
||||
void CommentsFrame::setText(const String &s)
|
||||
{
|
||||
d->text = s;
|
||||
}
|
||||
|
||||
|
||||
String::Type CommentsFrame::textEncoding() const
|
||||
{
|
||||
return d->textEncoding;
|
||||
}
|
||||
|
||||
void CommentsFrame::setTextEncoding(String::Type encoding)
|
||||
{
|
||||
d->textEncoding = encoding;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void CommentsFrame::parseFields(const ByteVector &data)
|
||||
{
|
||||
if(data.size() < 5) {
|
||||
debug("A comment frame must contain at least 5 bytes.");
|
||||
return;
|
||||
}
|
||||
|
||||
d->textEncoding = String::Type(data[0]);
|
||||
d->language = data.mid(1, 3);
|
||||
|
||||
int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2;
|
||||
|
||||
ByteVectorList l = ByteVectorList::split(data.mid(4), textDelimiter(d->textEncoding), byteAlign);
|
||||
|
||||
if(l.size() == 2) {
|
||||
d->description = String(l.front(), d->textEncoding);
|
||||
d->text = String(l.back(), d->textEncoding);
|
||||
}
|
||||
}
|
||||
|
||||
ByteVector CommentsFrame::renderFields() const
|
||||
{
|
||||
ByteVector v;
|
||||
|
||||
v.append(char(d->textEncoding));
|
||||
v.append(d->language);
|
||||
v.append(d->description.data(d->textEncoding));
|
||||
v.append(textDelimiter(d->textEncoding));
|
||||
v.append(d->text.data(d->textEncoding));
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
CommentsFrame::CommentsFrame(const ByteVector &data, Header *h) : Frame(h)
|
||||
{
|
||||
d = new CommentsFramePrivate();
|
||||
parseFields(data.mid(Header::size(), size()));
|
||||
}
|
154
mpeg/id3v2/frames/commentsframe.h
Normal file
154
mpeg/id3v2/frames/commentsframe.h
Normal file
@ -0,0 +1,154 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2002, 2003 by Scott Wheeler
|
||||
email : wheeler@kde.org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
* USA *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_COMMENTSFRAME_H
|
||||
#define TAGLIB_COMMENTSFRAME_H
|
||||
|
||||
#include <id3v2frame.h>
|
||||
|
||||
namespace TagLib {
|
||||
|
||||
namespace ID3v2 {
|
||||
|
||||
//! An implementation of ID3v2 comments
|
||||
|
||||
/*!
|
||||
* This implements the ID3v2 comment format. An ID3v2 comment concists of
|
||||
* a language encoding, a description and a single text field.
|
||||
*/
|
||||
|
||||
class CommentsFrame : public Frame
|
||||
{
|
||||
friend class FrameFactory;
|
||||
|
||||
public:
|
||||
/*!
|
||||
* 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.
|
||||
*/
|
||||
explicit CommentsFrame(const ByteVector &data);
|
||||
|
||||
/*!
|
||||
* Destroys this CommentFrame instance.
|
||||
*/
|
||||
virtual ~CommentsFrame();
|
||||
|
||||
/*!
|
||||
* 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()
|
||||
*/
|
||||
ByteVector language() const;
|
||||
|
||||
/*!
|
||||
* 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()
|
||||
*/
|
||||
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()
|
||||
*/
|
||||
void setLanguage(const ByteVector &languageCode);
|
||||
|
||||
/*!
|
||||
* Sets the description of the comment to \a s.
|
||||
*
|
||||
* \see decription()
|
||||
*/
|
||||
void setDescription(const String &s);
|
||||
|
||||
/*!
|
||||
* 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()
|
||||
*/
|
||||
String::Type textEncoding() const;
|
||||
|
||||
/*!
|
||||
* Sets the text encoding to be used when rendering this frame to
|
||||
* \a encoding.
|
||||
*
|
||||
* \see textEncoding()
|
||||
* \see render()
|
||||
*/
|
||||
void setTextEncoding(String::Type encoding);
|
||||
|
||||
protected:
|
||||
// Reimplementations.
|
||||
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
|
||||
private:
|
||||
/*!
|
||||
* The constructor used by the FrameFactory.
|
||||
*/
|
||||
CommentsFrame(const ByteVector &data, Header *h);
|
||||
CommentsFrame(const CommentsFrame &);
|
||||
CommentsFrame &operator=(const CommentsFrame &);
|
||||
|
||||
class CommentsFramePrivate;
|
||||
CommentsFramePrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
150
mpeg/id3v2/frames/textidentificationframe.cpp
Normal file
150
mpeg/id3v2/frames/textidentificationframe.cpp
Normal file
@ -0,0 +1,150 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2002, 2003 by Scott Wheeler
|
||||
email : wheeler@kde.org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
* USA *
|
||||
***************************************************************************/
|
||||
|
||||
#include <tbytevectorlist.h>
|
||||
|
||||
#include "textidentificationframe.h"
|
||||
|
||||
using namespace TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
class TextIdentificationFrame::TextIdentificationFramePrivate
|
||||
{
|
||||
public:
|
||||
TextIdentificationFramePrivate() : textEncoding(String::Latin1) {}
|
||||
String::Type textEncoding;
|
||||
StringList fieldList;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TextIdentificationFrame::TextIdentificationFrame(const ByteVector &type, String::Type encoding)
|
||||
: Frame(type)
|
||||
{
|
||||
d = new TextIdentificationFramePrivate;
|
||||
d->textEncoding = encoding;
|
||||
}
|
||||
|
||||
TextIdentificationFrame::TextIdentificationFrame(const ByteVector &data)
|
||||
: Frame(data)
|
||||
{
|
||||
d = new TextIdentificationFramePrivate;
|
||||
setData(data);
|
||||
}
|
||||
|
||||
TextIdentificationFrame::~TextIdentificationFrame()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
void TextIdentificationFrame::setText(const StringList &l)
|
||||
{
|
||||
d->fieldList = l;
|
||||
}
|
||||
|
||||
void TextIdentificationFrame::setText(const String &s)
|
||||
{
|
||||
d->fieldList = s;
|
||||
}
|
||||
|
||||
String TextIdentificationFrame::toString() const
|
||||
{
|
||||
return d->fieldList.toString();
|
||||
}
|
||||
|
||||
StringList TextIdentificationFrame::fieldList() const
|
||||
{
|
||||
return d->fieldList;
|
||||
}
|
||||
|
||||
String::Type TextIdentificationFrame::textEncoding() const
|
||||
{
|
||||
return d->textEncoding;
|
||||
}
|
||||
|
||||
void TextIdentificationFrame::setTextEncoding(String::Type encoding)
|
||||
{
|
||||
d->textEncoding = encoding;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void TextIdentificationFrame::parseFields(const ByteVector &data)
|
||||
{
|
||||
// read the string data type (the first byte of the field data)
|
||||
|
||||
d->textEncoding = String::Type(data[0]);
|
||||
|
||||
// split the byte array into chunks based on the string type (two byte delimiter
|
||||
// for unicode encodings)
|
||||
|
||||
int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2;
|
||||
|
||||
ByteVectorList l = ByteVectorList::split(data.mid(1), textDelimiter(d->textEncoding), byteAlign);
|
||||
|
||||
d->fieldList.clear();
|
||||
|
||||
// append those split values to the list and make sure that the new string's
|
||||
// type is the same specified for this frame
|
||||
|
||||
for(ByteVectorList::Iterator it = l.begin(); it != l.end(); it++) {
|
||||
String s(*it, d->textEncoding);
|
||||
d->fieldList.append(s);
|
||||
}
|
||||
}
|
||||
|
||||
ByteVector TextIdentificationFrame::renderFields() const
|
||||
{
|
||||
ByteVector v;
|
||||
|
||||
if(d->fieldList.size() > 0) {
|
||||
|
||||
v.append(char(d->textEncoding));
|
||||
|
||||
for(StringList::Iterator it = d->fieldList.begin(); it != d->fieldList.end(); it++) {
|
||||
|
||||
// Since the field list is null delimited, if this is not the first
|
||||
// element in the list, append the appropriate delimiter for this
|
||||
// encoding.
|
||||
|
||||
if(it != d->fieldList.begin())
|
||||
v.append(textDelimiter(d->textEncoding));
|
||||
|
||||
v.append((*it).data(d->textEncoding));
|
||||
}
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TextIdentificationFrame::TextIdentificationFrame(const ByteVector &data, Header *h) : Frame(h)
|
||||
{
|
||||
d = new TextIdentificationFramePrivate;
|
||||
parseFields(data.mid(Header::size(), size()));
|
||||
}
|
179
mpeg/id3v2/frames/textidentificationframe.h
Normal file
179
mpeg/id3v2/frames/textidentificationframe.h
Normal file
@ -0,0 +1,179 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2002, 2003 by Scott Wheeler
|
||||
email : wheeler@kde.org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
* USA *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_TEXTIDENTIFICATIONFRAME_H
|
||||
#define TAGLIB_TEXTIDENTIFICATIONFRAME_H
|
||||
|
||||
#include <tstringlist.h>
|
||||
|
||||
#include <id3v2frame.h>
|
||||
|
||||
namespace TagLib {
|
||||
|
||||
namespace ID3v2 {
|
||||
|
||||
//! 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.
|
||||
*/
|
||||
|
||||
class 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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
explicit TextIdentificationFrame(const ByteVector &data);
|
||||
|
||||
/*!
|
||||
* 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.
|
||||
*/
|
||||
void setText(const StringList &l);
|
||||
|
||||
// Reimplementations.
|
||||
|
||||
virtual void setText(const String &s);
|
||||
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()
|
||||
*/
|
||||
String::Type textEncoding() const;
|
||||
|
||||
/*!
|
||||
* Sets the text encoding to be used when rendering this frame to
|
||||
* \a encoding.
|
||||
*
|
||||
* \see textEncoding()
|
||||
* \see render()
|
||||
*/
|
||||
void setTextEncoding(String::Type encoding);
|
||||
|
||||
/*!
|
||||
* Returns a list of the strings in this frame.
|
||||
*/
|
||||
StringList fieldList() const;
|
||||
|
||||
protected:
|
||||
// Reimplementations.
|
||||
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
|
||||
private:
|
||||
/*!
|
||||
* The constructor used by the FrameFactory.
|
||||
*/
|
||||
TextIdentificationFrame(const ByteVector &data, Header *h);
|
||||
TextIdentificationFrame(const TextIdentificationFrame &);
|
||||
TextIdentificationFrame &operator=(const TextIdentificationFrame &);
|
||||
|
||||
class TextIdentificationFramePrivate;
|
||||
TextIdentificationFramePrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
80
mpeg/id3v2/frames/unknownframe.cpp
Normal file
80
mpeg/id3v2/frames/unknownframe.cpp
Normal file
@ -0,0 +1,80 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2002 by Scott Wheeler
|
||||
email : wheeler@kde.org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
* USA *
|
||||
***************************************************************************/
|
||||
|
||||
#include "unknownframe.h"
|
||||
|
||||
using namespace TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
class UnknownFrame::UnknownFramePrivate
|
||||
{
|
||||
public:
|
||||
ByteVector fieldData;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
UnknownFrame::UnknownFrame(const ByteVector &data) : Frame(data)
|
||||
{
|
||||
d = new UnknownFramePrivate();
|
||||
setData(data);
|
||||
}
|
||||
|
||||
UnknownFrame::~UnknownFrame()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
String UnknownFrame::toString() const
|
||||
{
|
||||
return String::null;
|
||||
}
|
||||
|
||||
ByteVector UnknownFrame::data() const
|
||||
{
|
||||
return d->fieldData;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void UnknownFrame::parseFields(const ByteVector &data)
|
||||
{
|
||||
d->fieldData = data;
|
||||
}
|
||||
|
||||
ByteVector UnknownFrame::renderFields() const
|
||||
{
|
||||
return d->fieldData;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
UnknownFrame::UnknownFrame(const ByteVector &data, Header *h) : Frame(h)
|
||||
{
|
||||
d = new UnknownFramePrivate;
|
||||
parseFields(data.mid(Header::size(), size()));
|
||||
}
|
74
mpeg/id3v2/frames/unknownframe.h
Normal file
74
mpeg/id3v2/frames/unknownframe.h
Normal file
@ -0,0 +1,74 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2002 by Scott Wheeler
|
||||
email : wheeler@kde.org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
* USA *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_UNKNOWNFRAME_H
|
||||
#define TAGLIB_UNKNOWNFRAME_H
|
||||
|
||||
#include <id3v2frame.h>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
class UnknownFrame : public Frame
|
||||
{
|
||||
friend class FrameFactory;
|
||||
|
||||
public:
|
||||
UnknownFrame(const ByteVector &data);
|
||||
virtual ~UnknownFrame();
|
||||
|
||||
virtual String toString() const;
|
||||
|
||||
/*!
|
||||
* Returns the field data (everything but the header) for this frame.
|
||||
*/
|
||||
ByteVector data() const;
|
||||
|
||||
protected:
|
||||
virtual void parseFields(const ByteVector &data);
|
||||
virtual ByteVector renderFields() const;
|
||||
|
||||
private:
|
||||
UnknownFrame(const ByteVector &data, Header *h);
|
||||
UnknownFrame(const UnknownFrame &);
|
||||
UnknownFrame &operator=(const UnknownFrame &);
|
||||
|
||||
class UnknownFramePrivate;
|
||||
UnknownFramePrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
1734
mpeg/id3v2/id3v2.4.0-frames.txt
Normal file
1734
mpeg/id3v2/id3v2.4.0-frames.txt
Normal file
File diff suppressed because it is too large
Load Diff
733
mpeg/id3v2/id3v2.4.0-structure.txt
Normal file
733
mpeg/id3v2/id3v2.4.0-structure.txt
Normal file
@ -0,0 +1,733 @@
|
||||
|
||||
Informal standard M. Nilsson
|
||||
Document: id3v2.4.0-structure.txt 16 September 2001
|
||||
|
||||
|
||||
ID3 tag version 2.4.0 - Main Structure
|
||||
|
||||
Status of this document
|
||||
|
||||
This document is an informal standard and replaces the ID3v2.3.0
|
||||
standard [ID3v2]. A formal standard will use another revision number
|
||||
even if the content is identical to document. The contents in this
|
||||
document may change for clarifications but never for added or altered
|
||||
functionallity.
|
||||
|
||||
Distribution of this document is unlimited.
|
||||
|
||||
|
||||
Abstract
|
||||
|
||||
This document describes the main structure of ID3v2.4.0, which is a
|
||||
revised version of the ID3v2 informal standard [ID3v2] version
|
||||
2.3.0. The ID3v2 offers a flexible way of storing audio meta
|
||||
information within the audio file itself. The information may be
|
||||
technical information, such as equalisation curves, as well as
|
||||
title, performer, copyright etc.
|
||||
|
||||
ID3v2.4.0 is meant to be as close as possible to ID3v2.3.0 in order
|
||||
to allow for implementations to be revised as easily as possible.
|
||||
|
||||
|
||||
1. Table of contents
|
||||
|
||||
Status of this document
|
||||
Abstract
|
||||
1. Table of contents
|
||||
2. Conventions in this document
|
||||
2. Standard overview
|
||||
3. ID3v2 overview
|
||||
3.1. ID3v2 header
|
||||
3.2. ID3v2 extended header
|
||||
3.3. Padding
|
||||
3.4. ID3v2 footer
|
||||
4. ID3v2 frames overview
|
||||
4.1. Frame header flags
|
||||
4.1.1. Frame status flags
|
||||
4.1.2. Frame format flags
|
||||
5. Tag location
|
||||
6. Unsynchronisation
|
||||
6.1. The unsynchronisation scheme
|
||||
6.2. Synchsafe integers
|
||||
7. Copyright
|
||||
8. References
|
||||
9. Author's Address
|
||||
|
||||
|
||||
2. Conventions in this document
|
||||
|
||||
Text within "" is a text string exactly as it appears in a tag.
|
||||
Numbers preceded with $ are hexadecimal and numbers preceded with %
|
||||
are binary. $xx is used to indicate a byte with unknown content. %x
|
||||
is used to indicate a bit with unknown content. The most significant
|
||||
bit (MSB) of a byte is called 'bit 7' and the least significant bit
|
||||
(LSB) is called 'bit 0'.
|
||||
|
||||
A tag is the whole tag described in this document. A frame is a block
|
||||
of information in the tag. The tag consists of a header, frames and
|
||||
optional padding. A field is a piece of information; one value, a
|
||||
string etc. A numeric string is a string that consists of the
|
||||
characters "0123456789" only.
|
||||
|
||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
|
||||
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
|
||||
document are to be interpreted as described in RFC 2119 [KEYWORDS].
|
||||
|
||||
|
||||
3. ID3v2 overview
|
||||
|
||||
ID3v2 is a general tagging format for audio, which makes it possible
|
||||
to store meta data about the audio inside the audio file itself. The
|
||||
ID3 tag described in this document is mainly targeted at files
|
||||
encoded with MPEG-1/2 layer I, MPEG-1/2 layer II, MPEG-1/2 layer III
|
||||
and MPEG-2.5, but may work with other types of encoded audio or as a
|
||||
stand alone format for audio meta data.
|
||||
|
||||
ID3v2 is designed to be as flexible and expandable as possible to
|
||||
meet new meta information needs that might arise. To achieve that
|
||||
ID3v2 is constructed as a container for several information blocks,
|
||||
called frames, whose format need not be known to the software that
|
||||
encounters them. At the start of every frame is an unique and
|
||||
predefined identifier, a size descriptor that allows software to skip
|
||||
unknown frames and a flags field. The flags describes encoding
|
||||
details and if the frame should remain in the tag, should it be
|
||||
unknown to the software, if the file is altered.
|
||||
|
||||
The bitorder in ID3v2 is most significant bit first (MSB). The
|
||||
byteorder in multibyte numbers is most significant byte first (e.g.
|
||||
$12345678 would be encoded $12 34 56 78), also known as big endian
|
||||
and network byte order.
|
||||
|
||||
Overall tag structure:
|
||||
|
||||
+-----------------------------+
|
||||
| Header (10 bytes) |
|
||||
+-----------------------------+
|
||||
| Extended Header |
|
||||
| (variable length, OPTIONAL) |
|
||||
+-----------------------------+
|
||||
| Frames (variable length) |
|
||||
+-----------------------------+
|
||||
| Padding |
|
||||
| (variable length, OPTIONAL) |
|
||||
+-----------------------------+
|
||||
| Footer (10 bytes, OPTIONAL) |
|
||||
+-----------------------------+
|
||||
|
||||
In general, padding and footer are mutually exclusive. See details in
|
||||
sections 3.3, 3.4 and 5.
|
||||
|
||||
|
||||
3.1. ID3v2 header
|
||||
|
||||
The first part of the ID3v2 tag is the 10 byte tag header, laid out
|
||||
as follows:
|
||||
|
||||
ID3v2/file identifier "ID3"
|
||||
ID3v2 version $04 00
|
||||
ID3v2 flags %abcd0000
|
||||
ID3v2 size 4 * %0xxxxxxx
|
||||
|
||||
The first three bytes of the tag are always "ID3", to indicate that
|
||||
this is an ID3v2 tag, directly followed by the two version bytes. The
|
||||
first byte of ID3v2 version is its major version, while the second
|
||||
byte is its revision number. In this case this is ID3v2.4.0. All
|
||||
revisions are backwards compatible while major versions are not. If
|
||||
software with ID3v2.4.0 and below support should encounter version
|
||||
five or higher it should simply ignore the whole tag. Version or
|
||||
revision will never be $FF.
|
||||
|
||||
The version is followed by the ID3v2 flags field, of which currently
|
||||
four flags are used.
|
||||
|
||||
|
||||
a - Unsynchronisation
|
||||
|
||||
Bit 7 in the 'ID3v2 flags' indicates whether or not
|
||||
unsynchronisation is applied on all frames (see section 6.1 for
|
||||
details); a set bit indicates usage.
|
||||
|
||||
|
||||
b - Extended header
|
||||
|
||||
The second bit (bit 6) indicates whether or not the header is
|
||||
followed by an extended header. The extended header is described in
|
||||
section 3.2. A set bit indicates the presence of an extended
|
||||
header.
|
||||
|
||||
|
||||
c - Experimental indicator
|
||||
|
||||
The third bit (bit 5) is used as an 'experimental indicator'. This
|
||||
flag SHALL always be set when the tag is in an experimental stage.
|
||||
|
||||
|
||||
d - Footer present
|
||||
|
||||
Bit 4 indicates that a footer (section 3.4) is present at the very
|
||||
end of the tag. A set bit indicates the presence of a footer.
|
||||
|
||||
|
||||
All the other flags MUST be cleared. If one of these undefined flags
|
||||
are set, the tag might not be readable for a parser that does not
|
||||
know the flags function.
|
||||
|
||||
The ID3v2 tag size is stored as a 32 bit synchsafe integer (section
|
||||
6.2), making a total of 28 effective bits (representing up to 256MB).
|
||||
|
||||
The ID3v2 tag size is the sum of the byte length of the extended
|
||||
header, the padding and the frames after unsynchronisation. If a
|
||||
footer is present this equals to ('total size' - 20) bytes, otherwise
|
||||
('total size' - 10) bytes.
|
||||
|
||||
An ID3v2 tag can be detected with the following pattern:
|
||||
$49 44 33 yy yy xx zz zz zz zz
|
||||
Where yy is less than $FF, xx is the 'flags' byte and zz is less than
|
||||
$80.
|
||||
|
||||
|
||||
3.2. Extended header
|
||||
|
||||
The extended header contains information that can provide further
|
||||
insight in the structure of the tag, but is not vital to the correct
|
||||
parsing of the tag information; hence the extended header is
|
||||
optional.
|
||||
|
||||
Extended header size 4 * %0xxxxxxx
|
||||
Number of flag bytes $01
|
||||
Extended Flags $xx
|
||||
|
||||
Where the 'Extended header size' is the size of the whole extended
|
||||
header, stored as a 32 bit synchsafe integer. An extended header can
|
||||
thus never have a size of fewer than six bytes.
|
||||
|
||||
The extended flags field, with its size described by 'number of flag
|
||||
bytes', is defined as:
|
||||
|
||||
%0bcd0000
|
||||
|
||||
Each flag that is set in the extended header has data attached, which
|
||||
comes in the order in which the flags are encountered (i.e. the data
|
||||
for flag 'b' comes before the data for flag 'c'). Unset flags cannot
|
||||
have any attached data. All unknown flags MUST be unset and their
|
||||
corresponding data removed when a tag is modified.
|
||||
|
||||
Every set flag's data starts with a length byte, which contains a
|
||||
value between 0 and 127 ($00 - $7f), followed by data that has the
|
||||
field length indicated by the length byte. If a flag has no attached
|
||||
data, the value $00 is used as length byte.
|
||||
|
||||
|
||||
b - Tag is an update
|
||||
|
||||
If this flag is set, the present tag is an update of a tag found
|
||||
earlier in the present file or stream. If frames defined as unique
|
||||
are found in the present tag, they are to override any
|
||||
corresponding ones found in the earlier tag. This flag has no
|
||||
corresponding data.
|
||||
|
||||
Flag data length $00
|
||||
|
||||
c - CRC data present
|
||||
|
||||
If this flag is set, a CRC-32 [ISO-3309] data is included in the
|
||||
extended header. The CRC is calculated on all the data between the
|
||||
header and footer as indicated by the header's tag length field,
|
||||
minus the extended header. Note that this includes the padding (if
|
||||
there is any), but excludes the footer. The CRC-32 is stored as an
|
||||
35 bit synchsafe integer, leaving the upper four bits always
|
||||
zeroed.
|
||||
|
||||
Flag data length $05
|
||||
Total frame CRC 5 * %0xxxxxxx
|
||||
|
||||
d - Tag restrictions
|
||||
|
||||
For some applications it might be desired to restrict a tag in more
|
||||
ways than imposed by the ID3v2 specification. Note that the
|
||||
presence of these restrictions does not affect how the tag is
|
||||
decoded, merely how it was restricted before encoding. If this flag
|
||||
is set the tag is restricted as follows:
|
||||
|
||||
Flag data length $01
|
||||
Restrictions %ppqrrstt
|
||||
|
||||
p - Tag size restrictions
|
||||
|
||||
00 No more than 128 frames and 1 MB total tag size.
|
||||
01 No more than 64 frames and 128 KB total tag size.
|
||||
10 No more than 32 frames and 40 KB total tag size.
|
||||
11 No more than 32 frames and 4 KB total tag size.
|
||||
|
||||
q - Text encoding restrictions
|
||||
|
||||
0 No restrictions
|
||||
1 Strings are only encoded with ISO-8859-1 [ISO-8859-1] or
|
||||
UTF-8 [UTF-8].
|
||||
|
||||
r - Text fields size restrictions
|
||||
|
||||
00 No restrictions
|
||||
01 No string is longer than 1024 characters.
|
||||
10 No string is longer than 128 characters.
|
||||
11 No string is longer than 30 characters.
|
||||
|
||||
Note that nothing is said about how many bytes is used to
|
||||
represent those characters, since it is encoding dependent. If a
|
||||
text frame consists of more than one string, the sum of the
|
||||
strungs is restricted as stated.
|
||||
|
||||
s - Image encoding restrictions
|
||||
|
||||
0 No restrictions
|
||||
1 Images are encoded only with PNG [PNG] or JPEG [JFIF].
|
||||
|
||||
t - Image size restrictions
|
||||
|
||||
00 No restrictions
|
||||
01 All images are 256x256 pixels or smaller.
|
||||
10 All images are 64x64 pixels or smaller.
|
||||
11 All images are exactly 64x64 pixels, unless required
|
||||
otherwise.
|
||||
|
||||
|
||||
3.3. Padding
|
||||
|
||||
It is OPTIONAL to include padding after the final frame (at the end
|
||||
of the ID3 tag), making the size of all the frames together smaller
|
||||
than the size given in the tag header. A possible purpose of this
|
||||
padding is to allow for adding a few additional frames or enlarge
|
||||
existing frames within the tag without having to rewrite the entire
|
||||
file. The value of the padding bytes must be $00. A tag MUST NOT have
|
||||
any padding between the frames or between the tag header and the
|
||||
frames. Furthermore it MUST NOT have any padding when a tag footer is
|
||||
added to the tag.
|
||||
|
||||
|
||||
3.4. ID3v2 footer
|
||||
|
||||
To speed up the process of locating an ID3v2 tag when searching from
|
||||
the end of a file, a footer can be added to the tag. It is REQUIRED
|
||||
to add a footer to an appended tag, i.e. a tag located after all
|
||||
audio data. The footer is a copy of the header, but with a different
|
||||
identifier.
|
||||
|
||||
ID3v2 identifier "3DI"
|
||||
ID3v2 version $04 00
|
||||
ID3v2 flags %abcd0000
|
||||
ID3v2 size 4 * %0xxxxxxx
|
||||
|
||||
|
||||
4. ID3v2 frame overview
|
||||
|
||||
All ID3v2 frames consists of one frame header followed by one or more
|
||||
fields containing the actual information. The header is always 10
|
||||
bytes and laid out as follows:
|
||||
|
||||
Frame ID $xx xx xx xx (four characters)
|
||||
Size 4 * %0xxxxxxx
|
||||
Flags $xx xx
|
||||
|
||||
The frame ID is made out of the characters capital A-Z and 0-9.
|
||||
Identifiers beginning with "X", "Y" and "Z" are for experimental
|
||||
frames and free for everyone to use, without the need to set the
|
||||
experimental bit in the tag header. Bear in mind that someone else
|
||||
might have used the same identifier as you. All other identifiers are
|
||||
either used or reserved for future use.
|
||||
|
||||
The frame ID is followed by a size descriptor containing the size of
|
||||
the data in the final frame, after encryption, compression and
|
||||
unsynchronisation. The size is excluding the frame header ('total
|
||||
frame size' - 10 bytes) and stored as a 32 bit synchsafe integer.
|
||||
|
||||
In the frame header the size descriptor is followed by two flag
|
||||
bytes. These flags are described in section 4.1.
|
||||
|
||||
There is no fixed order of the frames' appearance in the tag,
|
||||
although it is desired that the frames are arranged in order of
|
||||
significance concerning the recognition of the file. An example of
|
||||
such order: UFID, TIT2, MCDI, TRCK ...
|
||||
|
||||
A tag MUST contain at least one frame. A frame must be at least 1
|
||||
byte big, excluding the header.
|
||||
|
||||
If nothing else is said, strings, including numeric strings and URLs
|
||||
[URL], are represented as ISO-8859-1 [ISO-8859-1] characters in the
|
||||
range $20 - $FF. Such strings are represented in frame descriptions
|
||||
as <text string>, or <full text string> if newlines are allowed. If
|
||||
nothing else is said newline character is forbidden. In ISO-8859-1 a
|
||||
newline is represented, when allowed, with $0A only.
|
||||
|
||||
Frames that allow different types of text encoding contains a text
|
||||
encoding description byte. Possible encodings:
|
||||
|
||||
$00 ISO-8859-1 [ISO-8859-1]. Terminated with $00.
|
||||
$01 UTF-16 [UTF-16] encoded Unicode [UNICODE] with BOM. All
|
||||
strings in the same frame SHALL have the same byteorder.
|
||||
Terminated with $00 00.
|
||||
$02 UTF-16BE [UTF-16] encoded Unicode [UNICODE] without BOM.
|
||||
Terminated with $00 00.
|
||||
$03 UTF-8 [UTF-8] encoded Unicode [UNICODE]. Terminated with $00.
|
||||
|
||||
Strings dependent on encoding are represented in frame descriptions
|
||||
as <text string according to encoding>, or <full text string
|
||||
according to encoding> if newlines are allowed. Any empty strings of
|
||||
type $01 which are NULL-terminated may have the Unicode BOM followed
|
||||
by a Unicode NULL ($FF FE 00 00 or $FE FF 00 00).
|
||||
|
||||
The timestamp fields are based on a subset of ISO 8601. When being as
|
||||
precise as possible the format of a time string is
|
||||
yyyy-MM-ddTHH:mm:ss (year, "-", month, "-", day, "T", hour (out of
|
||||
24), ":", minutes, ":", seconds), but the precision may be reduced by
|
||||
removing as many time indicators as wanted. Hence valid timestamps
|
||||
are
|
||||
yyyy, yyyy-MM, yyyy-MM-dd, yyyy-MM-ddTHH, yyyy-MM-ddTHH:mm and
|
||||
yyyy-MM-ddTHH:mm:ss. All time stamps are UTC. For durations, use
|
||||
the slash character as described in 8601, and for multiple non-
|
||||
contiguous dates, use multiple strings, if allowed by the frame
|
||||
definition.
|
||||
|
||||
The three byte language field, present in several frames, is used to
|
||||
describe the language of the frame's content, according to ISO-639-2
|
||||
[ISO-639-2]. The language should be represented in lower case. If the
|
||||
language is not known the string "XXX" should be used.
|
||||
|
||||
All URLs [URL] MAY be relative, e.g. "picture.png", "../doc.txt".
|
||||
|
||||
If a frame is longer than it should be, e.g. having more fields than
|
||||
specified in this document, that indicates that additions to the
|
||||
frame have been made in a later version of the ID3v2 standard. This
|
||||
is reflected by the revision number in the header of the tag.
|
||||
|
||||
|
||||
4.1. Frame header flags
|
||||
|
||||
In the frame header the size descriptor is followed by two flag
|
||||
bytes. All unused flags MUST be cleared. The first byte is for
|
||||
'status messages' and the second byte is a format description. If an
|
||||
unknown flag is set in the first byte the frame MUST NOT be changed
|
||||
without that bit cleared. If an unknown flag is set in the second
|
||||
byte the frame is likely to not be readable. Some flags in the second
|
||||
byte indicates that extra information is added to the header. These
|
||||
fields of extra information is ordered as the flags that indicates
|
||||
them. The flags field is defined as follows (l and o left out because
|
||||
ther resemblence to one and zero):
|
||||
|
||||
%0abc0000 %0h00kmnp
|
||||
|
||||
Some frame format flags indicate that additional information fields
|
||||
are added to the frame. This information is added after the frame
|
||||
header and before the frame data in the same order as the flags that
|
||||
indicates them. I.e. the four bytes of decompressed size will precede
|
||||
the encryption method byte. These additions affects the 'frame size'
|
||||
field, but are not subject to encryption or compression.
|
||||
|
||||
The default status flags setting for a frame is, unless stated
|
||||
otherwise, 'preserved if tag is altered' and 'preserved if file is
|
||||
altered', i.e. %00000000.
|
||||
|
||||
|
||||
4.1.1. Frame status flags
|
||||
|
||||
a - Tag alter preservation
|
||||
|
||||
This flag tells the tag parser what to do with this frame if it is
|
||||
unknown and the tag is altered in any way. This applies to all
|
||||
kinds of alterations, including adding more padding and reordering
|
||||
the frames.
|
||||
|
||||
0 Frame should be preserved.
|
||||
1 Frame should be discarded.
|
||||
|
||||
|
||||
b - File alter preservation
|
||||
|
||||
This flag tells the tag parser what to do with this frame if it is
|
||||
unknown and the file, excluding the tag, is altered. This does not
|
||||
apply when the audio is completely replaced with other audio data.
|
||||
|
||||
0 Frame should be preserved.
|
||||
1 Frame should be discarded.
|
||||
|
||||
|
||||
c - Read only
|
||||
|
||||
This flag, if set, tells the software that the contents of this
|
||||
frame are intended to be read only. Changing the contents might
|
||||
break something, e.g. a signature. If the contents are changed,
|
||||
without knowledge of why the frame was flagged read only and
|
||||
without taking the proper means to compensate, e.g. recalculating
|
||||
the signature, the bit MUST be cleared.
|
||||
|
||||
|
||||
4.1.2. Frame format flags
|
||||
|
||||
h - Grouping identity
|
||||
|
||||
This flag indicates whether or not this frame belongs in a group
|
||||
with other frames. If set, a group identifier byte is added to the
|
||||
frame. Every frame with the same group identifier belongs to the
|
||||
same group.
|
||||
|
||||
0 Frame does not contain group information
|
||||
1 Frame contains group information
|
||||
|
||||
|
||||
k - Compression
|
||||
|
||||
This flag indicates whether or not the frame is compressed.
|
||||
A 'Data Length Indicator' byte MUST be included in the frame.
|
||||
|
||||
0 Frame is not compressed.
|
||||
1 Frame is compressed using zlib [zlib] deflate method.
|
||||
If set, this requires the 'Data Length Indicator' bit
|
||||
to be set as well.
|
||||
|
||||
|
||||
m - Encryption
|
||||
|
||||
This flag indicates whether or not the frame is encrypted. If set,
|
||||
one byte indicating with which method it was encrypted will be
|
||||
added to the frame. See description of the ENCR frame for more
|
||||
information about encryption method registration. Encryption
|
||||
should be done after compression. Whether or not setting this flag
|
||||
requires the presence of a 'Data Length Indicator' depends on the
|
||||
specific algorithm used.
|
||||
|
||||
0 Frame is not encrypted.
|
||||
1 Frame is encrypted.
|
||||
|
||||
n - Unsynchronisation
|
||||
|
||||
This flag indicates whether or not unsynchronisation was applied
|
||||
to this frame. See section 6 for details on unsynchronisation.
|
||||
If this flag is set all data from the end of this header to the
|
||||
end of this frame has been unsynchronised. Although desirable, the
|
||||
presence of a 'Data Length Indicator' is not made mandatory by
|
||||
unsynchronisation.
|
||||
|
||||
0 Frame has not been unsynchronised.
|
||||
1 Frame has been unsyrchronised.
|
||||
|
||||
p - Data length indicator
|
||||
|
||||
This flag indicates that a data length indicator has been added to
|
||||
the frame. The data length indicator is the value one would write
|
||||
as the 'Frame length' if all of the frame format flags were
|
||||
zeroed, represented as a 32 bit synchsafe integer.
|
||||
|
||||
0 There is no Data Length Indicator.
|
||||
1 A data length Indicator has been added to the frame.
|
||||
|
||||
|
||||
5. Tag location
|
||||
|
||||
The default location of an ID3v2 tag is prepended to the audio so
|
||||
that players can benefit from the information when the data is
|
||||
streamed. It is however possible to append the tag, or make a
|
||||
prepend/append combination. When deciding upon where an unembedded
|
||||
tag should be located, the following order of preference SHOULD be
|
||||
considered.
|
||||
|
||||
1. Prepend the tag.
|
||||
|
||||
2. Prepend a tag with all vital information and add a second tag at
|
||||
the end of the file, before tags from other tagging systems. The
|
||||
first tag is required to have a SEEK frame.
|
||||
|
||||
3. Add a tag at the end of the file, before tags from other tagging
|
||||
systems.
|
||||
|
||||
In case 2 and 3 the tag can simply be appended if no other known tags
|
||||
are present. The suggested method to find ID3v2 tags are:
|
||||
|
||||
1. Look for a prepended tag using the pattern found in section 3.1.
|
||||
|
||||
2. If a SEEK frame was found, use its values to guide further
|
||||
searching.
|
||||
|
||||
3. Look for a tag footer, scanning from the back of the file.
|
||||
|
||||
For every new tag that is found, the old tag should be discarded
|
||||
unless the update flag in the extended header (section 3.2) is set.
|
||||
|
||||
|
||||
6. Unsynchronisation
|
||||
|
||||
The only purpose of unsynchronisation is to make the ID3v2 tag as
|
||||
compatible as possible with existing software and hardware. There is
|
||||
no use in 'unsynchronising' tags if the file is only to be processed
|
||||
only by ID3v2 aware software and hardware. Unsynchronisation is only
|
||||
useful with tags in MPEG 1/2 layer I, II and III, MPEG 2.5 and AAC
|
||||
files.
|
||||
|
||||
|
||||
6.1. The unsynchronisation scheme
|
||||
|
||||
Whenever a false synchronisation is found within the tag, one zeroed
|
||||
byte is inserted after the first false synchronisation byte. The
|
||||
format of synchronisations that should be altered by ID3 encoders is
|
||||
as follows:
|
||||
|
||||
%11111111 111xxxxx
|
||||
|
||||
and should be replaced with:
|
||||
|
||||
%11111111 00000000 111xxxxx
|
||||
|
||||
This has the side effect that all $FF 00 combinations have to be
|
||||
altered, so they will not be affected by the decoding process.
|
||||
Therefore all the $FF 00 combinations have to be replaced with the
|
||||
$FF 00 00 combination during the unsynchronisation.
|
||||
|
||||
To indicate usage of the unsynchronisation, the unsynchronisation
|
||||
flag in the frame header should be set. This bit MUST be set if the
|
||||
frame was altered by the unsynchronisation and SHOULD NOT be set if
|
||||
unaltered. If all frames in the tag are unsynchronised the
|
||||
unsynchronisation flag in the tag header SHOULD be set. It MUST NOT
|
||||
be set if the tag has a frame which is not unsynchronised.
|
||||
|
||||
Assume the first byte of the audio to be $FF. The special case when
|
||||
the last byte of the last frame is $FF and no padding nor footer is
|
||||
used will then introduce a false synchronisation. This can be solved
|
||||
by adding a footer, adding padding or unsynchronising the frame and
|
||||
add $00 to the end of the frame data, thus adding more byte to the
|
||||
frame size than a normal unsynchronisation would. Although not
|
||||
preferred, it is allowed to apply the last method on all frames
|
||||
ending with $FF.
|
||||
|
||||
It is preferred that the tag is either completely unsynchronised or
|
||||
not unsynchronised at all. A completely unsynchronised tag has no
|
||||
false synchonisations in it, as defined above, and does not end with
|
||||
$FF. A completely non-unsynchronised tag contains no unsynchronised
|
||||
frames, and thus the unsynchronisation flag in the header is cleared.
|
||||
|
||||
Do bear in mind, that if compression or encryption is used, the
|
||||
unsynchronisation scheme MUST be applied afterwards. When decoding an
|
||||
unsynchronised frame, the unsynchronisation scheme MUST be reversed
|
||||
first, encryption and decompression afterwards.
|
||||
|
||||
|
||||
6.2. Synchsafe integers
|
||||
|
||||
In some parts of the tag it is inconvenient to use the
|
||||
unsychronisation scheme because the size of unsynchronised data is
|
||||
not known in advance, which is particularly problematic with size
|
||||
descriptors. The solution in ID3v2 is to use synchsafe integers, in
|
||||
which there can never be any false synchs. Synchsafe integers are
|
||||
integers that keep its highest bit (bit 7) zeroed, making seven bits
|
||||
out of eight available. Thus a 32 bit synchsafe integer can store 28
|
||||
bits of information.
|
||||
|
||||
Example:
|
||||
|
||||
255 (%11111111) encoded as a 16 bit synchsafe integer is 383
|
||||
(%00000001 01111111).
|
||||
|
||||
|
||||
7. Copyright
|
||||
|
||||
Copyright (C) Martin Nilsson 2000. All Rights Reserved.
|
||||
|
||||
This document and translations of it may be copied and furnished to
|
||||
others, and derivative works that comment on or otherwise explain it
|
||||
or assist in its implementation may be prepared, copied, published
|
||||
and distributed, in whole or in part, without restriction of any
|
||||
kind, provided that a reference to this document is included on all
|
||||
such copies and derivative works. However, this document itself may
|
||||
not be modified in any way and reissued as the original document.
|
||||
|
||||
The limited permissions granted above are perpetual and will not be
|
||||
revoked.
|
||||
|
||||
This document and the information contained herein is provided on an
|
||||
'AS IS' basis and THE AUTHORS DISCLAIMS ALL WARRANTIES, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF
|
||||
THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
|
||||
8. References
|
||||
|
||||
[ID3v2] Martin Nilsson, 'ID3v2 informal standard'.
|
||||
|
||||
<url:http://www.id3.org/id3v2.3.0.txt>
|
||||
|
||||
[ISO-639-2] ISO/FDIS 639-2.
|
||||
'Codes for the representation of names of languages, Part 2: Alpha-3
|
||||
code.' Technical committee / subcommittee: TC 37 / SC 2
|
||||
|
||||
[ISO-3309] ISO 3309
|
||||
'Information Processing Systems--Data Communication High-Level Data
|
||||
Link Control Procedure--Frame Structure', IS 3309, October 1984, 3rd
|
||||
Edition.
|
||||
|
||||
[ISO-8859-1] ISO/IEC DIS 8859-1.
|
||||
'8-bit single-byte coded graphic character sets, Part 1: Latin
|
||||
alphabet No. 1.' Technical committee / subcommittee: JTC 1 / SC 2
|
||||
|
||||
[JFIF] 'JPEG File Interchange Format, version 1.02'
|
||||
|
||||
<url:http://www.w3.org/Graphics/JPEG/jfif.txt>
|
||||
|
||||
[KEYWORDS] S. Bradner, 'Key words for use in RFCs to Indicate
|
||||
Requirement Levels', RFC 2119, March 1997.
|
||||
|
||||
<url:ftp://ftp.isi.edu/in-notes/rfc2119.txt>
|
||||
|
||||
[MPEG] ISO/IEC 11172-3:1993.
|
||||
'Coding of moving pictures and associated audio for digital storage
|
||||
media at up to about 1,5 Mbit/s, Part 3: Audio.'
|
||||
Technical committee / subcommittee: JTC 1 / SC 29
|
||||
and
|
||||
ISO/IEC 13818-3:1995
|
||||
'Generic coding of moving pictures and associated audio information,
|
||||
Part 3: Audio.'
|
||||
Technical committee / subcommittee: JTC 1 / SC 29
|
||||
and
|
||||
ISO/IEC DIS 13818-3
|
||||
'Generic coding of moving pictures and associated audio information,
|
||||
Part 3: Audio (Revision of ISO/IEC 13818-3:1995)'
|
||||
|
||||
[PNG] 'Portable Network Graphics, version 1.0'
|
||||
|
||||
<url:http://www.w3.org/TR/REC-png-multi.html>
|
||||
|
||||
[UNICODE] The Unicode Consortium,
|
||||
'The Unicode Standard Version 3.0', ISBN 0-201-61633-5.
|
||||
|
||||
<url:http://www.unicode.org/unicode/standard/versions/Unicode3.0.htm>
|
||||
|
||||
[URL] T. Berners-Lee, L. Masinter & M. McCahill, 'Uniform Resource
|
||||
Locators (URL)', RFC 1738, December 1994.
|
||||
|
||||
<url:ftp://ftp.isi.edu/in-notes/rfc1738.txt>
|
||||
|
||||
[UTF-8] F. Yergeau, 'UTF-8, a transformation format of ISO 10646',
|
||||
RFC 2279, January 1998.
|
||||
|
||||
<url:ftp://ftp.isi.edu/in-notes/rfc2279.txt>
|
||||
|
||||
[UTF-16] F. Yergeau, 'UTF-16, an encoding of ISO 10646', RFC 2781,
|
||||
February 2000.
|
||||
|
||||
<url:ftp://ftp.isi.edu/in-notes/rfc2781.txt>
|
||||
|
||||
[ZLIB] P. Deutsch, Aladdin Enterprises & J-L. Gailly, 'ZLIB
|
||||
Compressed Data Format Specification version 3.3', RFC 1950,
|
||||
May 1996.
|
||||
|
||||
<url:ftp://ftp.isi.edu/in-notes/rfc1950.txt>
|
||||
|
||||
|
||||
9. Author's Address
|
||||
|
||||
Written by
|
||||
|
||||
Martin Nilsson
|
||||
Rydsv<73>gen 246 C. 30
|
||||
SE-584 34 Link<6E>ping
|
||||
Sweden
|
||||
|
||||
Email: nilsson@id3.org
|
||||
|
67
mpeg/id3v2/id3v2extendedheader.cpp
Normal file
67
mpeg/id3v2/id3v2extendedheader.cpp
Normal file
@ -0,0 +1,67 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2002, 2003 by Scott Wheeler
|
||||
email : wheeler@kde.org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
* USA *
|
||||
***************************************************************************/
|
||||
|
||||
#include "id3v2extendedheader.h"
|
||||
#include "id3v2synchdata.h"
|
||||
|
||||
using namespace TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
class ExtendedHeader::ExtendedHeaderPrivate
|
||||
{
|
||||
public:
|
||||
ExtendedHeaderPrivate() : size(0) {}
|
||||
|
||||
uint size;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public methods
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ExtendedHeader::ExtendedHeader()
|
||||
{
|
||||
d = new ExtendedHeaderPrivate();
|
||||
}
|
||||
|
||||
ExtendedHeader::~ExtendedHeader()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
TagLib::uint ExtendedHeader::size() const
|
||||
{
|
||||
return d->size;
|
||||
}
|
||||
|
||||
void ExtendedHeader::setData(const ByteVector &data)
|
||||
{
|
||||
parse(data);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ExtendedHeader::parse(const ByteVector &data)
|
||||
{
|
||||
d->size = SynchData::toUInt(data.mid(0, 4)); // (structure 3.2 "Extended header size")
|
||||
}
|
88
mpeg/id3v2/id3v2extendedheader.h
Normal file
88
mpeg/id3v2/id3v2extendedheader.h
Normal file
@ -0,0 +1,88 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2002, 2003 by Scott Wheeler
|
||||
email : wheeler@kde.org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
* USA *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_ID3V2EXTENDEDHEADER_H
|
||||
#define TAGLIB_ID3V2EXTENDEDHEADER_H
|
||||
|
||||
#include <tbytevector.h>
|
||||
#include <taglib.h>
|
||||
|
||||
namespace TagLib {
|
||||
|
||||
namespace ID3v2 {
|
||||
|
||||
//! ID3v2 extended header implementation
|
||||
|
||||
/*!
|
||||
* This class implements ID3v2 extended headers. It attempts to follow,
|
||||
* both semantically and programatically, 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 ExtendedHeader
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
* Constructs an empty ID3v2 extended header.
|
||||
*/
|
||||
ExtendedHeader();
|
||||
|
||||
/*!
|
||||
* Destroys the extended header.
|
||||
*/
|
||||
virtual ~ExtendedHeader();
|
||||
|
||||
/*!
|
||||
* Returns the size of the extended header. This is variable for the
|
||||
* extended header.
|
||||
*/
|
||||
uint 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().
|
||||
*/
|
||||
void setData(const ByteVector &data);
|
||||
|
||||
protected:
|
||||
/*!
|
||||
* Called by setData() to parse the extended header data. It makes this
|
||||
* information available through the public API.
|
||||
*/
|
||||
void parse(const ByteVector &data);
|
||||
|
||||
private:
|
||||
ExtendedHeader(const ExtendedHeader &);
|
||||
ExtendedHeader &operator=(const ExtendedHeader &);
|
||||
|
||||
class ExtendedHeaderPrivate;
|
||||
ExtendedHeaderPrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
56
mpeg/id3v2/id3v2footer.cpp
Normal file
56
mpeg/id3v2/id3v2footer.cpp
Normal file
@ -0,0 +1,56 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2002, 2003 by Scott Wheeler
|
||||
email : wheeler@kde.org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
* USA *
|
||||
***************************************************************************/
|
||||
|
||||
#include "id3v2footer.h"
|
||||
#include "id3v2header.h"
|
||||
|
||||
using namespace TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
class Footer::FooterPrivate
|
||||
{
|
||||
public:
|
||||
static const uint size = 10;
|
||||
};
|
||||
|
||||
Footer::Footer()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Footer::~Footer()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
const unsigned int Footer::size()
|
||||
{
|
||||
return FooterPrivate::size;
|
||||
}
|
||||
|
||||
ByteVector Footer::render(const Header *header) const
|
||||
{
|
||||
ByteVector headerData = header->render();
|
||||
headerData[0] = '3';
|
||||
headerData[1] = 'D';
|
||||
headerData[2] = 'I';
|
||||
return headerData;
|
||||
}
|
77
mpeg/id3v2/id3v2footer.h
Normal file
77
mpeg/id3v2/id3v2footer.h
Normal file
@ -0,0 +1,77 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2002, 2003 by Scott Wheeler
|
||||
email : wheeler@kde.org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
* USA *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_ID3V2FOOTER_H
|
||||
#define TAGLIB_ID3V2FOOTER_H
|
||||
|
||||
#include <tbytevector.h>
|
||||
|
||||
namespace TagLib {
|
||||
|
||||
namespace ID3v2 {
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
class Footer
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
* Constructs an empty ID3v2 footer.
|
||||
*/
|
||||
Footer();
|
||||
/*!
|
||||
* Destroys the footer.
|
||||
*/
|
||||
virtual ~Footer();
|
||||
|
||||
/*!
|
||||
* Returns the size of the footer. Presently this is always 10 bytes.
|
||||
*/
|
||||
static const unsigned int size();
|
||||
|
||||
/*!
|
||||
* Renders the footer based on the data in \a header.
|
||||
*/
|
||||
ByteVector render(const Header *header) const;
|
||||
|
||||
private:
|
||||
Footer(const Footer &);
|
||||
Footer &operator=(const Footer &);
|
||||
|
||||
class FooterPrivate;
|
||||
FooterPrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
#endif
|
241
mpeg/id3v2/id3v2frame.cpp
Normal file
241
mpeg/id3v2/id3v2frame.cpp
Normal file
@ -0,0 +1,241 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2002, 2003 by Scott Wheeler
|
||||
email : wheeler@kde.org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
* USA *
|
||||
***************************************************************************/
|
||||
|
||||
#include <tdebug.h>
|
||||
|
||||
#include "id3v2frame.h"
|
||||
#include "id3v2synchdata.h"
|
||||
|
||||
using namespace TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
class Frame::FramePrivate
|
||||
{
|
||||
public:
|
||||
FramePrivate() {
|
||||
header = 0;
|
||||
}
|
||||
|
||||
~FramePrivate() {
|
||||
delete header;
|
||||
}
|
||||
|
||||
Frame::Header *header;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// static methods
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TagLib::uint Frame::headerSize()
|
||||
{
|
||||
return Header::size();
|
||||
}
|
||||
|
||||
ByteVector Frame::textDelimiter(String::Type t)
|
||||
{
|
||||
ByteVector d = char(0);
|
||||
if(t == String::UTF16 || t == String::UTF16BE)
|
||||
d.append(char(0));
|
||||
return d;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Frame::~Frame()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
ByteVector Frame::frameID() const
|
||||
{
|
||||
if(d->header)
|
||||
return d->header->frameID();
|
||||
else
|
||||
return ByteVector::null;
|
||||
}
|
||||
|
||||
TagLib::uint Frame::size() const
|
||||
{
|
||||
if(d->header)
|
||||
return d->header->frameSize();
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Frame::setData(const ByteVector &data)
|
||||
{
|
||||
parse(data);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Frame::Frame(const ByteVector &data)
|
||||
{
|
||||
d = new FramePrivate();
|
||||
d->header = new Header(data);
|
||||
}
|
||||
|
||||
Frame::Frame(Header *h)
|
||||
{
|
||||
d = new FramePrivate();
|
||||
d->header = h;
|
||||
}
|
||||
|
||||
Frame::Header *Frame::header() const
|
||||
{
|
||||
return d->header;
|
||||
}
|
||||
|
||||
void Frame::setHeader(Header *h, bool deleteCurrent)
|
||||
{
|
||||
if(deleteCurrent)
|
||||
delete d->header;
|
||||
|
||||
d->header = h;
|
||||
}
|
||||
|
||||
void Frame::parse(const ByteVector &data)
|
||||
{
|
||||
if(d->header)
|
||||
d->header->setData(data);
|
||||
else
|
||||
d->header = new Header(data);
|
||||
|
||||
// size() is the lenght of the field data
|
||||
parseFields(data.mid(Header::size(), size()));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Frame::Header class
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class Frame::Header::HeaderPrivate
|
||||
{
|
||||
public:
|
||||
HeaderPrivate() : frameSize(0) {}
|
||||
|
||||
ByteVector frameID;
|
||||
uint frameSize;
|
||||
static const unsigned int size = 10;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// static members (Frame::Header)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TagLib::uint Frame::Header::size()
|
||||
{
|
||||
return HeaderPrivate::size;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members (Frame::Header)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Frame::Header::Header(const ByteVector &data, bool synchSafeInts)
|
||||
{
|
||||
d = new HeaderPrivate;
|
||||
setData(data, synchSafeInts);
|
||||
}
|
||||
|
||||
Frame::Header::~Header()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
void Frame::Header::setData(const ByteVector &data, bool synchSafeInts)
|
||||
{
|
||||
if(data.size() < 4) {
|
||||
debug("You must at least specify a frame ID.");
|
||||
return;
|
||||
}
|
||||
|
||||
// set the frame ID -- the first four bytes
|
||||
|
||||
d->frameID = data.mid(0, 4);
|
||||
|
||||
// If the full header information was not passed in, do not continue to the
|
||||
// steps to parse the frame size and flags.
|
||||
|
||||
if(data.size() < 10) {
|
||||
d->frameSize = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the size -- the frame size is the four bytes starting at byte four in
|
||||
// the frame header (structure 4)
|
||||
|
||||
if(synchSafeInts)
|
||||
d->frameSize = SynchData::toUInt(data.mid(4, 4));
|
||||
else
|
||||
d->frameSize = data.mid(4, 4).toUInt();
|
||||
|
||||
// read flags
|
||||
// ...
|
||||
}
|
||||
|
||||
ByteVector Frame::Header::frameID() const
|
||||
{
|
||||
return d->frameID;
|
||||
}
|
||||
|
||||
void Frame::Header::setFrameID(const ByteVector &id)
|
||||
{
|
||||
d->frameID = id.mid(0, 4);
|
||||
}
|
||||
|
||||
TagLib::uint Frame::Header::frameSize() const
|
||||
{
|
||||
return d->frameSize;
|
||||
}
|
||||
|
||||
void Frame::Header::setFrameSize(uint size)
|
||||
{
|
||||
d->frameSize = size;
|
||||
}
|
||||
|
||||
ByteVector Frame::Header::render() const
|
||||
{
|
||||
ByteVector flags(2, char(0)); // just blank for the moment
|
||||
|
||||
ByteVector v = d->frameID + SynchData::fromUInt(d->frameSize) + flags;
|
||||
|
||||
return v;
|
||||
}
|
252
mpeg/id3v2/id3v2frame.h
Normal file
252
mpeg/id3v2/id3v2frame.h
Normal file
@ -0,0 +1,252 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2002, 2003 by Scott Wheeler
|
||||
email : wheeler@kde.org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
* USA *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_ID3V2FRAME_H
|
||||
#define TAGLIB_ID3V2FRAME_H
|
||||
|
||||
#include <tstring.h>
|
||||
#include <tbytevector.h>
|
||||
|
||||
namespace TagLib {
|
||||
|
||||
namespace ID3v2 {
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
class Frame
|
||||
{
|
||||
friend class FrameFactory;
|
||||
|
||||
public:
|
||||
/*!
|
||||
* 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>)
|
||||
*/
|
||||
ByteVector frameID() const;
|
||||
|
||||
/*!
|
||||
* Returns the size of the frame.
|
||||
*/
|
||||
uint size() const;
|
||||
|
||||
/*!
|
||||
* Returns the size of the frame header
|
||||
*/
|
||||
static uint headerSize();
|
||||
|
||||
/*!
|
||||
* 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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
virtual String toString() const = 0;
|
||||
|
||||
/*!
|
||||
* 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.
|
||||
*/
|
||||
static ByteVector textDelimiter(String::Type t);
|
||||
|
||||
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 constain 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.
|
||||
*/
|
||||
Frame(Header *h);
|
||||
|
||||
/*!
|
||||
* 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.
|
||||
*/
|
||||
void setHeader(Header *h, bool deleteCurrent = true);
|
||||
|
||||
/*!
|
||||
* 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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
virtual ByteVector renderFields() const = 0;
|
||||
|
||||
private:
|
||||
Frame(const Frame &);
|
||||
Frame &operator=(const Frame &);
|
||||
|
||||
class FramePrivate;
|
||||
FramePrivate *d;
|
||||
};
|
||||
|
||||
//! 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.
|
||||
*/
|
||||
|
||||
class 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.
|
||||
*/
|
||||
explicit Header(const ByteVector &data, bool synchSafeInts = true);
|
||||
|
||||
/*!
|
||||
* Destroys this Header instance.
|
||||
*/
|
||||
virtual ~Header();
|
||||
|
||||
/*!
|
||||
* Sets the data for the Header.
|
||||
*/
|
||||
void setData(const ByteVector &data, bool synchSafeInts = true);
|
||||
|
||||
/*!
|
||||
* 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.
|
||||
*/
|
||||
void setFrameID(const ByteVector &id);
|
||||
|
||||
/*!
|
||||
* Returns the size of the frame data portion, as set when setData() was
|
||||
* called or set explicity via setFrameSize().
|
||||
*/
|
||||
uint frameSize() const;
|
||||
|
||||
/*!
|
||||
* Sets the size of the frame data portion.
|
||||
*/
|
||||
void setFrameSize(uint size);
|
||||
|
||||
/*!
|
||||
* Returns the size of the frame header in bytes. Currently this is
|
||||
* always 10.
|
||||
*/
|
||||
static uint size();
|
||||
|
||||
/*!
|
||||
* Render the Header back to binary format in a ByteVector.
|
||||
*/
|
||||
ByteVector render() const;
|
||||
|
||||
private:
|
||||
Header(const Header &);
|
||||
Header &operator=(const Header &);
|
||||
|
||||
class HeaderPrivate;
|
||||
HeaderPrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
169
mpeg/id3v2/id3v2framefactory.cpp
Normal file
169
mpeg/id3v2/id3v2framefactory.cpp
Normal file
@ -0,0 +1,169 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2002, 2003 by Scott Wheeler
|
||||
email : wheeler@kde.org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
* USA *
|
||||
***************************************************************************/
|
||||
|
||||
#include <tdebug.h>
|
||||
|
||||
#include "id3v2framefactory.h"
|
||||
|
||||
#include "frames/unknownframe.h"
|
||||
#include "frames/textidentificationframe.h"
|
||||
#include "frames/commentsframe.h"
|
||||
|
||||
using namespace TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
class FrameFactory::FrameFactoryPrivate
|
||||
{
|
||||
public:
|
||||
FrameFactoryPrivate() :
|
||||
defaultEncoding(String::Latin1),
|
||||
useDefaultEncoding(false) {}
|
||||
|
||||
String::Type defaultEncoding;
|
||||
bool useDefaultEncoding;
|
||||
};
|
||||
|
||||
FrameFactory *FrameFactory::factory = 0;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FrameFactory *FrameFactory::instance()
|
||||
{
|
||||
if(!factory)
|
||||
factory = new FrameFactory;
|
||||
return factory;
|
||||
}
|
||||
|
||||
Frame *FrameFactory::createFrame(const ByteVector &data, bool synchSafeInts) const
|
||||
{
|
||||
Frame::Header *header = new Frame::Header(data, synchSafeInts);
|
||||
|
||||
TagLib::ByteVector frameID = header->frameID();
|
||||
|
||||
// A quick sanity check -- make sure that the frameID is 4 uppercase Latin1
|
||||
// characters. Also make sure that there is data in the frame.
|
||||
|
||||
if(!frameID.size() == 4 || header->frameSize() <= 0)
|
||||
return 0;
|
||||
|
||||
for(ByteVector::ConstIterator it = frameID.begin(); it != frameID.end(); it++) {
|
||||
if( (*it < 'A' || *it > 'Z') && (*it < '1' || *it > '9') ) {
|
||||
delete header;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(!updateFrame(header)) {
|
||||
delete header;
|
||||
return 0;
|
||||
}
|
||||
|
||||
frameID = header->frameID();
|
||||
|
||||
// This is where things get necissarily nasty. Here we determine which
|
||||
// Frame subclass (or if none is found simply an Frame) based
|
||||
// on the frame ID. Since there are a lot of possibilities, that means
|
||||
// a lot of if blocks.
|
||||
|
||||
// Text Identification (frames 4.2)
|
||||
|
||||
if(frameID.startsWith("T") && frameID != "TXXX") {
|
||||
TextIdentificationFrame *f = new TextIdentificationFrame(data, header);
|
||||
if(d->useDefaultEncoding)
|
||||
f->setTextEncoding(d->defaultEncoding);
|
||||
return f;
|
||||
}
|
||||
|
||||
// Comments (frames 4.10)
|
||||
|
||||
if(frameID == "COMM") {
|
||||
CommentsFrame *f = new CommentsFrame(data, header);
|
||||
if(d->useDefaultEncoding)
|
||||
f->setTextEncoding(d->defaultEncoding);
|
||||
return f;
|
||||
}
|
||||
|
||||
return new UnknownFrame(data, header);
|
||||
}
|
||||
|
||||
String::Type FrameFactory::defaultTextEncoding() const
|
||||
{
|
||||
return d->defaultEncoding;
|
||||
}
|
||||
|
||||
void FrameFactory::setDefaultTextEncoding(String::Type encoding)
|
||||
{
|
||||
d->useDefaultEncoding = true;
|
||||
d->defaultEncoding = encoding;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
FrameFactory::FrameFactory()
|
||||
{
|
||||
d = new FrameFactoryPrivate;
|
||||
}
|
||||
|
||||
FrameFactory::~FrameFactory()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
bool FrameFactory::updateFrame(Frame::Header *header) const
|
||||
{
|
||||
TagLib::ByteVector frameID = header->frameID();
|
||||
if(frameID == "EQUA" ||
|
||||
frameID == "RVAD" ||
|
||||
frameID == "TIME" ||
|
||||
frameID == "TRDA" ||
|
||||
frameID == "TSIZ")
|
||||
{
|
||||
debug("ID3v2.4 no longer supports the frame type " + String(frameID) +
|
||||
". It will be discarded from the tag.");
|
||||
return false;
|
||||
}
|
||||
|
||||
convertFrame("TDAT", "TRDC", header);
|
||||
convertFrame("TORY", "TDOR", header);
|
||||
convertFrame("TYER", "TRDC", header);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// private members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void FrameFactory::convertFrame(const ByteVector &from, const ByteVector &to,
|
||||
Frame::Header *header) const
|
||||
{
|
||||
if(header->frameID() != from)
|
||||
return;
|
||||
|
||||
// debug("ID3v2.4 no longer supports the frame type " + String(from) + " It has" +
|
||||
// "been converted to the type " + String(to) + ".");
|
||||
|
||||
header->setFrameID(to);
|
||||
}
|
129
mpeg/id3v2/id3v2framefactory.h
Normal file
129
mpeg/id3v2/id3v2framefactory.h
Normal file
@ -0,0 +1,129 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2002, 2003 by Scott Wheeler
|
||||
email : wheeler@kde.org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
* USA *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_ID3V2FRAMEFACTORY_H
|
||||
#define TAGLIB_ID3V2FRAMEFACTORY_H
|
||||
|
||||
#include <tbytevector.h>
|
||||
#include "id3v2frame.h"
|
||||
|
||||
namespace TagLib {
|
||||
|
||||
namespace ID3v2 {
|
||||
|
||||
//! A factory for creating ID3v2 frames
|
||||
|
||||
/*!
|
||||
* 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 or with
|
||||
* MPEG::File::setID3v2FrameFactory() 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>).
|
||||
*/
|
||||
|
||||
class 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.
|
||||
*/
|
||||
Frame *createFrame(const ByteVector &data, bool synchSafeInts = true) 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 explitly 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.
|
||||
*
|
||||
* \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.
|
||||
*/
|
||||
FrameFactory();
|
||||
|
||||
/*!
|
||||
* Destroys the frame factory. In most cases this will never be called (as
|
||||
* is typical of singletons).
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
virtual bool updateFrame(Frame::Header *header) const;
|
||||
|
||||
private:
|
||||
FrameFactory(const FrameFactory &);
|
||||
FrameFactory &operator=(const FrameFactory &);
|
||||
|
||||
/*!
|
||||
* This method is used internally to convert a frame from ID \a from to ID
|
||||
* \a to. If the frame matches the \a from pattern and converts the frame
|
||||
* ID in the \a header or simply does nothing if the frame ID does not match.
|
||||
*/
|
||||
void convertFrame(const ByteVector &from, const ByteVector &to,
|
||||
Frame::Header *header) const;
|
||||
|
||||
static FrameFactory *factory;
|
||||
|
||||
class FrameFactoryPrivate;
|
||||
FrameFactoryPrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
227
mpeg/id3v2/id3v2header.cpp
Normal file
227
mpeg/id3v2/id3v2header.cpp
Normal file
@ -0,0 +1,227 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2002, 2003 by Scott Wheeler
|
||||
email : wheeler@kde.org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
* USA *
|
||||
***************************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include <bitset>
|
||||
|
||||
#include <tstring.h>
|
||||
#include <tdebug.h>
|
||||
|
||||
#include "id3v2header.h"
|
||||
#include "id3v2footer.h"
|
||||
#include "id3v2synchdata.h"
|
||||
|
||||
using namespace TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
class Header::HeaderPrivate
|
||||
{
|
||||
public:
|
||||
HeaderPrivate() : majorVersion(0),
|
||||
revisionNumber(0),
|
||||
unsynchronisation(false),
|
||||
extendedHeader(false),
|
||||
experimentalIndicator(false),
|
||||
footerPresent(false),
|
||||
tagSize(0) {}
|
||||
|
||||
~HeaderPrivate() {}
|
||||
|
||||
uint majorVersion;
|
||||
uint revisionNumber;
|
||||
|
||||
bool unsynchronisation;
|
||||
bool extendedHeader;
|
||||
bool experimentalIndicator;
|
||||
bool footerPresent;
|
||||
|
||||
uint tagSize;
|
||||
|
||||
static const uint size = 10;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// static members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TagLib::uint Header::size()
|
||||
{
|
||||
return HeaderPrivate::size;
|
||||
}
|
||||
|
||||
ByteVector Header::fileIdentifier()
|
||||
{
|
||||
return ByteVector::fromCString("ID3");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Header::Header()
|
||||
{
|
||||
d = new HeaderPrivate();
|
||||
}
|
||||
|
||||
Header::Header(const ByteVector &data)
|
||||
{
|
||||
d = new HeaderPrivate();
|
||||
parse(data);
|
||||
}
|
||||
|
||||
Header::~Header()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
TagLib::uint Header::majorVersion() const
|
||||
{
|
||||
return d->majorVersion;
|
||||
}
|
||||
|
||||
TagLib::uint Header::revisionNumber() const
|
||||
{
|
||||
return d->revisionNumber;
|
||||
}
|
||||
|
||||
bool Header::unsynchronisation() const
|
||||
{
|
||||
return d->unsynchronisation;
|
||||
}
|
||||
|
||||
bool Header::extendedHeader() const
|
||||
{
|
||||
return d->extendedHeader;
|
||||
}
|
||||
|
||||
bool Header::experimentalIndicator() const
|
||||
{
|
||||
return d->experimentalIndicator;
|
||||
}
|
||||
|
||||
bool Header::footerPresent() const
|
||||
{
|
||||
return d->footerPresent;
|
||||
}
|
||||
|
||||
TagLib::uint Header::tagSize() const
|
||||
{
|
||||
return d->tagSize;
|
||||
}
|
||||
|
||||
TagLib::uint Header::completeTagSize() const
|
||||
{
|
||||
if(d->footerPresent)
|
||||
return d->tagSize + d->size + Footer::size();
|
||||
else
|
||||
return d->tagSize + d->size;
|
||||
}
|
||||
|
||||
void Header::setTagSize(uint s)
|
||||
{
|
||||
d->tagSize = s;
|
||||
}
|
||||
|
||||
void Header::setData(const ByteVector &data)
|
||||
{
|
||||
parse(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.
|
||||
|
||||
v.append(char(4));
|
||||
v.append(char(0));
|
||||
|
||||
// render and add the flags
|
||||
std::bitset<8> flags;
|
||||
|
||||
flags[7] = d->unsynchronisation;
|
||||
flags[6] = d->extendedHeader;
|
||||
flags[5] = d->experimentalIndicator;
|
||||
flags[4] = d->footerPresent;
|
||||
|
||||
v.append(char(flags.to_ulong()));
|
||||
|
||||
// add the size
|
||||
v.append(SynchData::fromUInt(d->tagSize));
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
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.
|
||||
|
||||
// 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);
|
||||
|
||||
if(sizeData.size() != 4) {
|
||||
d->tagSize = 0;
|
||||
debug("TagLib::ID3v2::Header::parse() - The tag size as read was 0 bytes!");
|
||||
return;
|
||||
}
|
||||
|
||||
for(ByteVector::Iterator it = sizeData.begin(); it != sizeData.end(); it++) {
|
||||
if(uchar(*it) >= 128) {
|
||||
d->tagSize = 0;
|
||||
debug("TagLib::ID3v2::Header::parse() - One of the size bytes in the id3v2 header was greater than the allowed 128.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// The first three bytes, data[0..2], are the File Identifier, "ID3". (structure 3.1 "file identifier")
|
||||
|
||||
// Read the version number from the fourth and fifth bytes.
|
||||
d->majorVersion = data[3]; // (structure 3.1 "major version")
|
||||
d->revisionNumber = data[4]; // (structure 3.1 "revision number")
|
||||
|
||||
// Read the flags, the first four bits of the sixth byte.
|
||||
std::bitset<8> flags(data[5]);
|
||||
|
||||
d->unsynchronisation = flags[7]; // (structure 3.1.a)
|
||||
d->extendedHeader = flags[6]; // (structure 3.1.b)
|
||||
d->experimentalIndicator = flags[5]; // (structure 3.1.c)
|
||||
d->footerPresent = flags[4]; // (structure 3.1.d)
|
||||
|
||||
// Get the size from the remaining four bytes (read above)
|
||||
|
||||
d->tagSize = SynchData::toUInt(sizeData); // (structure 3.1 "size")
|
||||
}
|
159
mpeg/id3v2/id3v2header.h
Normal file
159
mpeg/id3v2/id3v2header.h
Normal file
@ -0,0 +1,159 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2002, 2003 by Scott Wheeler
|
||||
email : wheeler@kde.org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
* USA *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_ID3V2HEADER_H
|
||||
#define TAGLIB_ID3V2HEADER_H
|
||||
|
||||
#include <tbytevector.h>
|
||||
|
||||
namespace TagLib {
|
||||
|
||||
namespace ID3v2 {
|
||||
|
||||
//! An implementation of ID3v2 headers
|
||||
|
||||
/*!
|
||||
* This class implements ID3v2 headers. It attempts to follow, both
|
||||
* semantically and programatically, 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 Header
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
* Constructs an empty ID3v2 header.
|
||||
*/
|
||||
Header();
|
||||
|
||||
/*!
|
||||
* Constructs an ID3v2 header based on \a data. parse() is called
|
||||
* immediately.
|
||||
*/
|
||||
Header(const ByteVector &data);
|
||||
|
||||
/*!
|
||||
* 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.)
|
||||
*/
|
||||
uint majorVersion() const;
|
||||
|
||||
/*!
|
||||
* Returns the revision number. (Note: This is the 0, not the 4 in
|
||||
* ID3v2.4.0. The 2 is implied.)
|
||||
*/
|
||||
uint revisionNumber() const;
|
||||
|
||||
/*!
|
||||
* Returns true if unsynchronisation has been applied to all frames.
|
||||
*/
|
||||
bool unsynchronisation() const;
|
||||
|
||||
/*!
|
||||
* Returns true if an extended header is present in the tag.
|
||||
*/
|
||||
bool extendedHeader() const;
|
||||
|
||||
/*!
|
||||
* Returns true if the experimental indicator flag is set.
|
||||
*/
|
||||
bool experimentalIndicator() const;
|
||||
|
||||
/*!
|
||||
* 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()
|
||||
*/
|
||||
uint tagSize() const;
|
||||
|
||||
/*!
|
||||
* Returns the tag size, including the header and, if present, the footer
|
||||
* size.
|
||||
*
|
||||
* \see tagSize()
|
||||
*/
|
||||
uint completeTagSize() const;
|
||||
|
||||
/*!
|
||||
* Set the tag size to \a s.
|
||||
* \see tagSize()
|
||||
*/
|
||||
void setTagSize(uint s);
|
||||
|
||||
/*!
|
||||
* Returns the size of the header. Presently this is always 10 bytes.
|
||||
*/
|
||||
static uint size();
|
||||
|
||||
/*!
|
||||
* 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 extended header. 10 bytes,
|
||||
* starting from \a data will be used.
|
||||
*/
|
||||
void setData(const ByteVector &data);
|
||||
|
||||
/*!
|
||||
* 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.
|
||||
*/
|
||||
void parse(const ByteVector &data);
|
||||
|
||||
private:
|
||||
Header(const Header &);
|
||||
Header &operator=(const Header &);
|
||||
|
||||
class HeaderPrivate;
|
||||
HeaderPrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
48
mpeg/id3v2/id3v2synchdata.cpp
Normal file
48
mpeg/id3v2/id3v2synchdata.cpp
Normal file
@ -0,0 +1,48 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2002, 2003 by Scott Wheeler
|
||||
email : wheeler@kde.org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
* USA *
|
||||
***************************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "id3v2synchdata.h"
|
||||
|
||||
using namespace TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
TagLib::uint SynchData::toUInt(const ByteVector &data)
|
||||
{
|
||||
uint sum = 0;
|
||||
int last = data.size() > 4 ? 3 : data.size() - 1;
|
||||
|
||||
for(int i = 0; i <= last; i++)
|
||||
sum |= (data[i] & 0x7f) << ((last - i) * 7);
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
ByteVector SynchData::fromUInt(uint value)
|
||||
{
|
||||
ByteVector v(4, 0);
|
||||
|
||||
for(int i = 0; i < 4; i++)
|
||||
v[i] = uchar(value >> ((3 - i) * 7) & 0x7f);
|
||||
|
||||
return v;
|
||||
}
|
61
mpeg/id3v2/id3v2synchdata.h
Normal file
61
mpeg/id3v2/id3v2synchdata.h
Normal file
@ -0,0 +1,61 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2002, 2003 by Scott Wheeler
|
||||
email : wheeler@kde.org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
* USA *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_ID3V2SYNCHDATA_H
|
||||
#define TAGLIB_ID3V2SYNCHDATA_H
|
||||
|
||||
#include <tbytevector.h>
|
||||
#include <taglib.h>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
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.
|
||||
*/
|
||||
uint toUInt(const ByteVector &data);
|
||||
|
||||
/*!
|
||||
* Returns a 4 byte (32 bit) synchsafe integer based on \a value.
|
||||
*/
|
||||
ByteVector fromUInt(uint value);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
417
mpeg/id3v2/id3v2tag.cpp
Normal file
417
mpeg/id3v2/id3v2tag.cpp
Normal file
@ -0,0 +1,417 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2002, 2003 by Scott Wheeler
|
||||
email : wheeler@kde.org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
* USA *
|
||||
***************************************************************************/
|
||||
|
||||
#include <tfile.h>
|
||||
#include <tdebug.h>
|
||||
|
||||
#include "id3v2tag.h"
|
||||
#include "id3v2header.h"
|
||||
#include "id3v2extendedheader.h"
|
||||
#include "id3v2footer.h"
|
||||
|
||||
#include "id3v1genres.h"
|
||||
|
||||
#include "frames/textidentificationframe.h"
|
||||
#include "frames/commentsframe.h"
|
||||
|
||||
using namespace TagLib;
|
||||
using namespace ID3v2;
|
||||
|
||||
class ID3v2::Tag::TagPrivate
|
||||
{
|
||||
public:
|
||||
TagPrivate() : file(0), tagOffset(-1), extendedHeader(0), footer(0), paddingSize(0)
|
||||
{
|
||||
frameList.setAutoDelete(true);
|
||||
}
|
||||
~TagPrivate()
|
||||
{
|
||||
delete extendedHeader;
|
||||
delete footer;
|
||||
}
|
||||
|
||||
File *file;
|
||||
long tagOffset;
|
||||
const FrameFactory *factory;
|
||||
|
||||
Header header;
|
||||
ExtendedHeader *extendedHeader;
|
||||
Footer *footer;
|
||||
|
||||
int paddingSize;
|
||||
|
||||
FrameListMap frameListMap;
|
||||
FrameList frameList;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// public members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
ID3v2::Tag::Tag() : TagLib::Tag()
|
||||
{
|
||||
d = new TagPrivate;
|
||||
d->factory = FrameFactory::instance();
|
||||
}
|
||||
|
||||
ID3v2::Tag::Tag(File *file, long tagOffset, const FrameFactory *factory) :
|
||||
TagLib::Tag()
|
||||
{
|
||||
d = new TagPrivate;
|
||||
|
||||
d->file = file;
|
||||
d->tagOffset = tagOffset;
|
||||
d->factory = factory;
|
||||
|
||||
read();
|
||||
}
|
||||
|
||||
ID3v2::Tag::~Tag()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
|
||||
String ID3v2::Tag::title() const
|
||||
{
|
||||
if(!d->frameListMap["TIT2"].isEmpty())
|
||||
return d->frameListMap["TIT2"].front()->toString();
|
||||
return String::null;
|
||||
}
|
||||
|
||||
String ID3v2::Tag::artist() const
|
||||
{
|
||||
if(!d->frameListMap["TPE1"].isEmpty())
|
||||
return d->frameListMap["TPE1"].front()->toString();
|
||||
return String::null;
|
||||
}
|
||||
|
||||
String ID3v2::Tag::album() const
|
||||
{
|
||||
if(!d->frameListMap["TALB"].isEmpty())
|
||||
return d->frameListMap["TALB"].front()->toString();
|
||||
return String::null;
|
||||
}
|
||||
|
||||
String ID3v2::Tag::comment() const
|
||||
{
|
||||
if(!d->frameListMap["COMM"].isEmpty())
|
||||
return d->frameListMap["COMM"].front()->toString();
|
||||
return String::null;
|
||||
}
|
||||
|
||||
String ID3v2::Tag::genre() const
|
||||
{
|
||||
if(!d->frameListMap["TCON"].isEmpty()) {
|
||||
String s = d->frameListMap["TCON"].front()->toString();
|
||||
|
||||
// ID3v2 "content type" can contain a ID3v1 genre number in parenthesis at
|
||||
// the beginning of the field. If this is all that the field contains, do a
|
||||
// translation from that number to the name and return that. If there is a
|
||||
// string folloing the ID3v1 genre number, that is considered to be
|
||||
// authoritative and we return that instead. Or finally, the field may
|
||||
// simply be free text, in which case we just return the value.
|
||||
|
||||
int closing = s.find(")");
|
||||
if(s.substr(0, 1) == "(" && closing > 0) {
|
||||
if(closing == int(s.size() - 1))
|
||||
return ID3v1::genre(s.substr(1, s.size() - 2).toInt());
|
||||
else
|
||||
return s.substr(closing + 1);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
return String::null;
|
||||
}
|
||||
|
||||
TagLib::uint ID3v2::Tag::year() const
|
||||
{
|
||||
if(!d->frameListMap["TRDC"].isEmpty())
|
||||
return d->frameListMap["TRDC"].front()->toString().substr(0, 4).toInt();
|
||||
return 0;
|
||||
}
|
||||
|
||||
TagLib::uint 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)
|
||||
{
|
||||
setTextFrame("TIT2", s);
|
||||
}
|
||||
|
||||
void ID3v2::Tag::setArtist(const String &s)
|
||||
{
|
||||
setTextFrame("TPE1", s);
|
||||
}
|
||||
|
||||
void ID3v2::Tag::setAlbum(const String &s)
|
||||
{
|
||||
setTextFrame("TALB", s);
|
||||
}
|
||||
|
||||
void ID3v2::Tag::setComment(const String &s)
|
||||
{
|
||||
if(s.isEmpty()) {
|
||||
removeFrames("COMM");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!d->frameListMap["COMM"].isEmpty())
|
||||
d->frameListMap["COMM"].front()->setText(s);
|
||||
else {
|
||||
CommentsFrame *f = new CommentsFrame(d->factory->defaultTextEncoding());
|
||||
addFrame(f);
|
||||
f->setText(s);
|
||||
}
|
||||
}
|
||||
|
||||
void ID3v2::Tag::setGenre(const String &s)
|
||||
{
|
||||
if(s.isEmpty()) {
|
||||
removeFrames("TCON");
|
||||
return;
|
||||
}
|
||||
|
||||
int index = ID3v1::genreIndex(s);
|
||||
|
||||
if(index != 255)
|
||||
setTextFrame("TCON", "(" + String::number(index) + ")");
|
||||
else
|
||||
setTextFrame("TCON", s);
|
||||
}
|
||||
|
||||
void ID3v2::Tag::setYear(uint i)
|
||||
{
|
||||
if(i <= 0) {
|
||||
removeFrames("TRDC");
|
||||
return;
|
||||
}
|
||||
setTextFrame("TRDC", String::number(i));
|
||||
}
|
||||
|
||||
void ID3v2::Tag::setTrack(uint i)
|
||||
{
|
||||
if(i <= 0) {
|
||||
removeFrames("TRCK");
|
||||
return;
|
||||
}
|
||||
setTextFrame("TRCK", String::number(i));
|
||||
}
|
||||
|
||||
bool ID3v2::Tag::isEmpty() const
|
||||
{
|
||||
return d->frameList.isEmpty();
|
||||
}
|
||||
|
||||
Header *ID3v2::Tag::header() const
|
||||
{
|
||||
return &(d->header);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
const FrameList &ID3v2::Tag::frameList() const
|
||||
{
|
||||
return d->frameList;
|
||||
}
|
||||
|
||||
void ID3v2::Tag::addFrame(Frame *frame)
|
||||
{
|
||||
d->frameList.append(frame);
|
||||
d->frameListMap[frame->frameID()].append(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);
|
||||
|
||||
// ...and from the frame list map
|
||||
it = d->frameListMap[frame->frameID()].find(frame);
|
||||
d->frameListMap[frame->frameID()].erase(it);
|
||||
|
||||
// ...and delete as desired
|
||||
if(del)
|
||||
delete *it;
|
||||
}
|
||||
|
||||
void ID3v2::Tag::removeFrames(const ByteVector &id)
|
||||
{
|
||||
FrameList l = d->frameListMap[id];
|
||||
for(FrameList::Iterator it = l.begin(); it != l.end(); ++it)
|
||||
removeFrame(*it, true);
|
||||
}
|
||||
|
||||
ByteVector ID3v2::Tag::render() 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
|
||||
// padding, but does not include the tag's header or footer.
|
||||
|
||||
ByteVector tagData;
|
||||
|
||||
// TODO: Render the extended header.
|
||||
|
||||
// Loop through the frames rendering them and adding them to the tagData.
|
||||
|
||||
for(FrameList::Iterator it = d->frameList.begin(); it != d->frameList.end(); it++)
|
||||
tagData.append((*it)->render());
|
||||
|
||||
// Compute the amount of padding, and append that to tagData.
|
||||
|
||||
uint paddingSize = 0;
|
||||
uint originalSize = d->header.tagSize();
|
||||
|
||||
if(tagData.size() < originalSize)
|
||||
paddingSize = originalSize - tagData.size();
|
||||
else
|
||||
paddingSize = 1024;
|
||||
|
||||
tagData.append(ByteVector(paddingSize, char(0)));
|
||||
|
||||
// Set the tag size.
|
||||
d->header.setTagSize(tagData.size());
|
||||
|
||||
// TODO: This should eventually include d->footer->render().
|
||||
return d->header.render() + tagData;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// protected members
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void ID3v2::Tag::read()
|
||||
{
|
||||
if(d->file && d->file->isOpen()) {
|
||||
|
||||
d->file->seek(d->tagOffset);
|
||||
d->header.setData(d->file->readBlock(Header::size()));
|
||||
|
||||
// if the tag size is 0, then this is an invalid tag (tags must contain at
|
||||
// least one frame)
|
||||
|
||||
if(d->header.tagSize() == 0)
|
||||
return;
|
||||
|
||||
parse(d->file->readBlock(d->header.tagSize()));
|
||||
}
|
||||
}
|
||||
|
||||
void ID3v2::Tag::parse(const ByteVector &data)
|
||||
{
|
||||
uint frameDataOffset = 0;
|
||||
uint frameDataLength = data.size();
|
||||
|
||||
// check for extended header
|
||||
|
||||
if(d->header.extendedHeader()) {
|
||||
if(!d->extendedHeader)
|
||||
d->extendedHeader = new ExtendedHeader;
|
||||
d->extendedHeader->setData(data);
|
||||
if(d->extendedHeader->size() <= data.size()) {
|
||||
frameDataOffset += d->extendedHeader->size();
|
||||
frameDataLength -= d->extendedHeader->size();
|
||||
}
|
||||
}
|
||||
|
||||
// check for footer -- we don't actually need to parse it, as it *must*
|
||||
// contain the same data as the header, but we do need to account for its
|
||||
// size.
|
||||
|
||||
if(d->header.footerPresent() && Footer::size() <= frameDataLength)
|
||||
frameDataLength -= Footer::size();
|
||||
|
||||
// parse frames
|
||||
|
||||
uint frameDataPosition = 0;
|
||||
|
||||
// Make sure that there is at least enough room in the remaining frame data for
|
||||
// a frame header.
|
||||
|
||||
while(frameDataPosition < frameDataLength - Frame::headerSize()) {
|
||||
|
||||
// If the next data is position is 0, assume that we've hit the padding
|
||||
// portion of the frame data.
|
||||
|
||||
if(data.at(frameDataPosition) == 0) {
|
||||
|
||||
if(d->header.footerPresent())
|
||||
debug("Padding *and* a footer found. This is not allowed by the spec.");
|
||||
|
||||
d->paddingSize = frameDataLength - frameDataPosition;
|
||||
return;
|
||||
}
|
||||
|
||||
bool synchSafeInts = d->header.majorVersion() >= 4;
|
||||
|
||||
Frame *frame = d->factory->createFrame(data.mid(frameDataOffset + frameDataPosition),
|
||||
synchSafeInts);
|
||||
|
||||
if(!frame)
|
||||
return;
|
||||
|
||||
// Checks to make sure that frame parsed correctly.
|
||||
|
||||
if(frame->size() <= 0) {
|
||||
delete frame;
|
||||
return;
|
||||
}
|
||||
|
||||
frameDataPosition += frame->size() + Frame::headerSize();
|
||||
addFrame(frame);
|
||||
}
|
||||
}
|
||||
|
||||
void ID3v2::Tag::setTextFrame(const ByteVector &id, const String &value)
|
||||
{
|
||||
if(value.isEmpty()) {
|
||||
removeFrames(id);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!d->frameListMap[id].isEmpty())
|
||||
d->frameListMap[id].front()->setText(value);
|
||||
else {
|
||||
const String::Type encoding = d->factory->defaultTextEncoding();
|
||||
TextIdentificationFrame *f = new TextIdentificationFrame(id, encoding);
|
||||
addFrame(f);
|
||||
f->setText(value);
|
||||
}
|
||||
}
|
243
mpeg/id3v2/id3v2tag.h
Normal file
243
mpeg/id3v2/id3v2tag.h
Normal file
@ -0,0 +1,243 @@
|
||||
/***************************************************************************
|
||||
copyright : (C) 2002, 2003 by Scott Wheeler
|
||||
email : wheeler@kde.org
|
||||
***************************************************************************/
|
||||
|
||||
/***************************************************************************
|
||||
* This library is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU Lesser General Public License version *
|
||||
* 2.1 as published by the Free Software Foundation. *
|
||||
* *
|
||||
* This library is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with this library; if not, write to the Free Software *
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
|
||||
* USA *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TAGLIB_ID3V2TAG_H
|
||||
#define TAGLIB_ID3V2TAG_H
|
||||
|
||||
#include <tag.h>
|
||||
#include <tbytevector.h>
|
||||
#include <tstring.h>
|
||||
#include <tlist.h>
|
||||
#include <tmap.h>
|
||||
|
||||
#include "id3v2framefactory.h"
|
||||
|
||||
namespace TagLib {
|
||||
|
||||
class File;
|
||||
|
||||
//! An ID3v2 implementation
|
||||
|
||||
/*!
|
||||
* This is a relatively complete and flexible framework for working with ID3v2
|
||||
* tags.
|
||||
*
|
||||
* \see ID3v2::Tag
|
||||
*/
|
||||
|
||||
namespace ID3v2 {
|
||||
|
||||
class Header;
|
||||
class ExtendedHeader;
|
||||
class Footer;
|
||||
|
||||
typedef List<Frame *> FrameList;
|
||||
typedef Map<ByteVector, FrameList> FrameListMap;
|
||||
|
||||
//! 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() corespond 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 instace. 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 distrubuted 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 Tag : public TagLib::Tag
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
* 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 incorperated into your factory.
|
||||
*
|
||||
* \see FrameFactory
|
||||
*/
|
||||
Tag(File *file, long tagOffset,
|
||||
const FrameFactory *factory = FrameFactory::instance());
|
||||
|
||||
/*!
|
||||
* Destroys this Tag instance.
|
||||
*/
|
||||
virtual ~Tag();
|
||||
|
||||
// Reimplementations.
|
||||
|
||||
virtual String title() const;
|
||||
virtual String artist() const;
|
||||
virtual String album() const;
|
||||
virtual String comment() const;
|
||||
virtual String genre() const;
|
||||
virtual uint year() const;
|
||||
virtual uint track() const;
|
||||
|
||||
virtual void setTitle(const String &s);
|
||||
virtual void setArtist(const String &s);
|
||||
virtual void setAlbum(const String &s);
|
||||
virtual void setComment(const String &s);
|
||||
virtual void setGenre(const String &s);
|
||||
virtual void setYear(uint i);
|
||||
virtual void setTrack(uint i);
|
||||
|
||||
virtual bool isEmpty() const;
|
||||
|
||||
/*!
|
||||
* 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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
Footer *footer() const;
|
||||
|
||||
/*!
|
||||
* Returns a pointer to the frame list map. This is an FrameListMap of
|
||||
* all of the frames in the tag.
|
||||
*
|
||||
* \warning You should not modify this data structure directly, instead
|
||||
* use addFrame() and removeFrame().
|
||||
*/
|
||||
const FrameListMap &frameListMap() const;
|
||||
|
||||
/*!
|
||||
* Returns a pointer to the frame list. This is an FrameList of all of
|
||||
* the frames in the tag in the order that they were parsed.
|
||||
*
|
||||
* \warning You should not modify this data structure directly, instead
|
||||
* use addFrame() and removeFrame().
|
||||
*/
|
||||
const FrameList &frameList() const;
|
||||
|
||||
/*!
|
||||
* Add a frame to the tag. At this point the tag takes ownership of
|
||||
* the frame and will handle freeing its memory.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
void removeFrame(Frame *frame, bool del = true);
|
||||
|
||||
/*!
|
||||
* Remove all frames of type \a id from the tag and free their memory.
|
||||
*/
|
||||
void removeFrames(const ByteVector &id);
|
||||
|
||||
/*!
|
||||
* Render the tag back to binary data, suitable to be written to disk.
|
||||
*/
|
||||
ByteVector render() const;
|
||||
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
void setTextFrame(const ByteVector &id, const String &value);
|
||||
|
||||
private:
|
||||
Tag(const Tag &);
|
||||
Tag &operator=(const Tag &);
|
||||
|
||||
class TagPrivate;
|
||||
TagPrivate *d;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user