Merge branch 'master' into merge-master-to-taglib2

Conflicts:
	taglib/asf/asftag.cpp
	taglib/mp4/mp4tag.cpp
	taglib/toolkit/tstring.h
This commit is contained in:
Tsuda Kageyu 2014-04-11 18:31:49 +09:00
commit 1a9c49e42b
12 changed files with 939 additions and 5 deletions

View File

@ -1,6 +1,10 @@
project(taglib)
cmake_minimum_required(VERSION 2.6.0 FATAL_ERROR)
cmake_minimum_required(VERSION 2.8.0 FATAL_ERROR)
if(NOT ${CMAKE_VERSION} VERSION_LESS 2.8.12)
cmake_policy(SET CMP0022 OLD)
endif()
option(ENABLE_STATIC "Make static version of libtag" OFF)
if(ENABLE_STATIC)

View File

@ -70,11 +70,13 @@ set(tag_HDRS
mpeg/id3v2/id3v2tag.h
mpeg/id3v2/frames/attachedpictureframe.h
mpeg/id3v2/frames/commentsframe.h
mpeg/id3v2/frames/eventtimingcodesframe.h
mpeg/id3v2/frames/generalencapsulatedobjectframe.h
mpeg/id3v2/frames/ownershipframe.h
mpeg/id3v2/frames/popularimeterframe.h
mpeg/id3v2/frames/privateframe.h
mpeg/id3v2/frames/relativevolumeframe.h
mpeg/id3v2/frames/synchronizedlyricsframe.h
mpeg/id3v2/frames/textidentificationframe.h
mpeg/id3v2/frames/uniquefileidentifierframe.h
mpeg/id3v2/frames/unknownframe.h
@ -168,11 +170,13 @@ set(id3v2_SRCS
set(frames_SRCS
mpeg/id3v2/frames/attachedpictureframe.cpp
mpeg/id3v2/frames/commentsframe.cpp
mpeg/id3v2/frames/eventtimingcodesframe.cpp
mpeg/id3v2/frames/generalencapsulatedobjectframe.cpp
mpeg/id3v2/frames/ownershipframe.cpp
mpeg/id3v2/frames/popularimeterframe.cpp
mpeg/id3v2/frames/privateframe.cpp
mpeg/id3v2/frames/relativevolumeframe.cpp
mpeg/id3v2/frames/synchronizedlyricsframe.cpp
mpeg/id3v2/frames/textidentificationframe.cpp
mpeg/id3v2/frames/uniquefileidentifierframe.cpp
mpeg/id3v2/frames/unknownframe.cpp

View File

@ -197,6 +197,7 @@ namespace
{
const char *keyTranslation[][2] = {
{ "WM/AlbumTitle", "ALBUM" },
{ "WM/AlbumArtist", "ALBUMARTIST" },
{ "WM/Composer", "COMPOSER" },
{ "WM/Writer", "WRITER" },
{ "WM/Conductor", "CONDUCTOR" },

View File

@ -777,6 +777,7 @@ namespace
{ "\251day", "DATE" },
{ "\251wrt", "COMPOSER" },
{ "\251grp", "GROUPING" },
{ "aART", "ALBUMARTIST" },
{ "trkn", "TRACKNUMBER" },
{ "disk", "DISCNUMBER" },
{ "cpil", "COMPILATION" },

View File

@ -0,0 +1,144 @@
/***************************************************************************
copyright : (C) 2014 by Urs Fleisch
email : ufleisch@users.sourceforge.net
***************************************************************************/
/***************************************************************************
* 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., 51 Franklin Street, Fifth Floor, Boston, MA *
* 02110-1301 USA *
* *
* Alternatively, this file is available under the Mozilla Public *
* License Version 1.1. You may obtain a copy of the License at *
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include "eventtimingcodesframe.h"
#include <tbytevectorlist.h>
#include <id3v2tag.h>
#include <tdebug.h>
#include <tpropertymap.h>
using namespace TagLib;
using namespace ID3v2;
class EventTimingCodesFrame::EventTimingCodesFramePrivate
{
public:
EventTimingCodesFramePrivate() :
timestampFormat(EventTimingCodesFrame::AbsoluteMilliseconds) {}
EventTimingCodesFrame::TimestampFormat timestampFormat;
EventTimingCodesFrame::SynchedEventList synchedEvents;
};
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
EventTimingCodesFrame::EventTimingCodesFrame() :
Frame("ETCO")
{
d = new EventTimingCodesFramePrivate;
}
EventTimingCodesFrame::EventTimingCodesFrame(const ByteVector &data) :
Frame(data)
{
d = new EventTimingCodesFramePrivate;
setData(data);
}
EventTimingCodesFrame::~EventTimingCodesFrame()
{
delete d;
}
String EventTimingCodesFrame::toString() const
{
return String();
}
EventTimingCodesFrame::TimestampFormat
EventTimingCodesFrame::timestampFormat() const
{
return d->timestampFormat;
}
EventTimingCodesFrame::SynchedEventList
EventTimingCodesFrame::synchedEvents() const
{
return d->synchedEvents;
}
void EventTimingCodesFrame::setTimestampFormat(
EventTimingCodesFrame::TimestampFormat f)
{
d->timestampFormat = f;
}
void EventTimingCodesFrame::setSynchedEvents(
const EventTimingCodesFrame::SynchedEventList &e)
{
d->synchedEvents = e;
}
////////////////////////////////////////////////////////////////////////////////
// protected members
////////////////////////////////////////////////////////////////////////////////
void EventTimingCodesFrame::parseFields(const ByteVector &data)
{
const size_t end = data.size();
if(end < 1) {
debug("An event timing codes frame must contain at least 1 byte.");
return;
}
d->timestampFormat = TimestampFormat(data[0]);
size_t pos = 1;
d->synchedEvents.clear();
while(pos + 4 < end) {
EventType type = EventType(uchar(data[pos++]));
uint time = data.toUInt32BE(pos);
pos += 4;
d->synchedEvents.append(SynchedEvent(time, type));
}
}
ByteVector EventTimingCodesFrame::renderFields() const
{
ByteVector v;
v.append(char(d->timestampFormat));
for(SynchedEventList::ConstIterator it = d->synchedEvents.begin();
it != d->synchedEvents.end();
++it) {
const SynchedEvent &entry = *it;
v.append(char(entry.type));
v.append(ByteVector::fromUInt32BE(entry.time));
}
return v;
}
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
EventTimingCodesFrame::EventTimingCodesFrame(const ByteVector &data, Header *h)
: Frame(h)
{
d = new EventTimingCodesFramePrivate();
parseFields(fieldData(data));
}

View File

@ -0,0 +1,185 @@
/***************************************************************************
copyright : (C) 2014 by Urs Fleisch
email : ufleisch@users.sourceforge.net
***************************************************************************/
/***************************************************************************
* 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., 51 Franklin Street, Fifth Floor, Boston, MA *
* 02110-1301 USA *
* *
* Alternatively, this file is available under the Mozilla Public *
* License Version 1.1. You may obtain a copy of the License at *
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#ifndef TAGLIB_EVENTTIMINGCODESFRAME_H
#define TAGLIB_EVENTTIMINGCODESFRAME_H
#include "id3v2frame.h"
#include "tlist.h"
namespace TagLib {
namespace ID3v2 {
//! ID3v2 event timing codes frame
/*!
* An implementation of ID3v2 event timing codes.
*/
class TAGLIB_EXPORT EventTimingCodesFrame : public Frame
{
friend class FrameFactory;
public:
/*!
* Specifies the timestamp format used.
*/
enum TimestampFormat {
//! The timestamp is of unknown format.
Unknown = 0x00,
//! The timestamp represents the number of MPEG frames since
//! the beginning of the audio stream.
AbsoluteMpegFrames = 0x01,
//! The timestamp represents the number of milliseconds since
//! the beginning of the audio stream.
AbsoluteMilliseconds = 0x02
};
/*!
* Event types defined in id3v2.4.0-frames.txt 4.5. Event timing codes.
*/
enum EventType {
Padding = 0x00,
EndOfInitialSilence = 0x01,
IntroStart = 0x02,
MainPartStart = 0x03,
OutroStart = 0x04,
OutroEnd = 0x05,
VerseStart = 0x06,
RefrainStart = 0x07,
InterludeStart = 0x08,
ThemeStart = 0x09,
VariationStart = 0x0a,
KeyChange = 0x0b,
TimeChange = 0x0c,
MomentaryUnwantedNoise = 0x0d,
SustainedNoise = 0x0e,
SustainedNoiseEnd = 0x0f,
IntroEnd = 0x10,
MainPartEnd = 0x11,
VerseEnd = 0x12,
RefrainEnd = 0x13,
ThemeEnd = 0x14,
Profanity = 0x15,
ProfanityEnd = 0x16,
NotPredefinedSynch0 = 0xe0,
NotPredefinedSynch1 = 0xe1,
NotPredefinedSynch2 = 0xe2,
NotPredefinedSynch3 = 0xe3,
NotPredefinedSynch4 = 0xe4,
NotPredefinedSynch5 = 0xe5,
NotPredefinedSynch6 = 0xe6,
NotPredefinedSynch7 = 0xe7,
NotPredefinedSynch8 = 0xe8,
NotPredefinedSynch9 = 0xe9,
NotPredefinedSynchA = 0xea,
NotPredefinedSynchB = 0xeb,
NotPredefinedSynchC = 0xec,
NotPredefinedSynchD = 0xed,
NotPredefinedSynchE = 0xee,
NotPredefinedSynchF = 0xef,
AudioEnd = 0xfd,
AudioFileEnds = 0xfe
};
/*!
* Single entry of time stamp and event.
*/
struct SynchedEvent {
SynchedEvent(uint ms, EventType t) : time(ms), type(t) {}
uint time;
EventType type;
};
/*!
* List of synchronized events.
*/
typedef TagLib::List<SynchedEvent> SynchedEventList;
/*!
* Construct an empty event timing codes frame.
*/
explicit EventTimingCodesFrame();
/*!
* Construct a event timing codes frame based on the data in \a data.
*/
explicit EventTimingCodesFrame(const ByteVector &data);
/*!
* Destroys this EventTimingCodesFrame instance.
*/
virtual ~EventTimingCodesFrame();
/*!
* Returns a null string.
*/
virtual String toString() const;
/*!
* Returns the timestamp format.
*/
TimestampFormat timestampFormat() const;
/*!
* Returns the events with the time stamps.
*/
SynchedEventList synchedEvents() const;
/*!
* Set the timestamp format.
*
* \see timestampFormat()
*/
void setTimestampFormat(TimestampFormat f);
/*!
* Sets the text with the time stamps.
*
* \see text()
*/
void setSynchedEvents(const SynchedEventList &e);
protected:
// Reimplementations.
virtual void parseFields(const ByteVector &data);
virtual ByteVector renderFields() const;
private:
/*!
* The constructor used by the FrameFactory.
*/
EventTimingCodesFrame(const ByteVector &data, Header *h);
EventTimingCodesFrame(const EventTimingCodesFrame &);
EventTimingCodesFrame &operator=(const EventTimingCodesFrame &);
class EventTimingCodesFramePrivate;
EventTimingCodesFramePrivate *d;
};
}
}
#endif

View File

@ -0,0 +1,243 @@
/***************************************************************************
copyright : (C) 2014 by Urs Fleisch
email : ufleisch@users.sourceforge.net
***************************************************************************/
/***************************************************************************
* 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., 51 Franklin Street, Fifth Floor, Boston, MA *
* 02110-1301 USA *
* *
* Alternatively, this file is available under the Mozilla Public *
* License Version 1.1. You may obtain a copy of the License at *
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#include "synchronizedlyricsframe.h"
#include <tbytevectorlist.h>
#include <id3v2tag.h>
#include <tdebug.h>
#include <tpropertymap.h>
using namespace TagLib;
using namespace ID3v2;
class SynchronizedLyricsFrame::SynchronizedLyricsFramePrivate
{
public:
SynchronizedLyricsFramePrivate() :
textEncoding(String::Latin1),
timestampFormat(SynchronizedLyricsFrame::AbsoluteMilliseconds),
type(SynchronizedLyricsFrame::Lyrics) {}
String::Type textEncoding;
ByteVector language;
SynchronizedLyricsFrame::TimestampFormat timestampFormat;
SynchronizedLyricsFrame::Type type;
String description;
SynchronizedLyricsFrame::SynchedTextList synchedText;
};
////////////////////////////////////////////////////////////////////////////////
// public members
////////////////////////////////////////////////////////////////////////////////
SynchronizedLyricsFrame::SynchronizedLyricsFrame(String::Type encoding) :
Frame("SYLT")
{
d = new SynchronizedLyricsFramePrivate;
d->textEncoding = encoding;
}
SynchronizedLyricsFrame::SynchronizedLyricsFrame(const ByteVector &data) :
Frame(data)
{
d = new SynchronizedLyricsFramePrivate;
setData(data);
}
SynchronizedLyricsFrame::~SynchronizedLyricsFrame()
{
delete d;
}
String SynchronizedLyricsFrame::toString() const
{
return d->description;
}
String::Type SynchronizedLyricsFrame::textEncoding() const
{
return d->textEncoding;
}
ByteVector SynchronizedLyricsFrame::language() const
{
return d->language;
}
SynchronizedLyricsFrame::TimestampFormat
SynchronizedLyricsFrame::timestampFormat() const
{
return d->timestampFormat;
}
SynchronizedLyricsFrame::Type SynchronizedLyricsFrame::type() const
{
return d->type;
}
String SynchronizedLyricsFrame::description() const
{
return d->description;
}
SynchronizedLyricsFrame::SynchedTextList
SynchronizedLyricsFrame::synchedText() const
{
return d->synchedText;
}
void SynchronizedLyricsFrame::setTextEncoding(String::Type encoding)
{
d->textEncoding = encoding;
}
void SynchronizedLyricsFrame::setLanguage(const ByteVector &languageEncoding)
{
d->language = languageEncoding.mid(0, 3);
}
void SynchronizedLyricsFrame::setTimestampFormat(
SynchronizedLyricsFrame::TimestampFormat f)
{
d->timestampFormat = f;
}
void SynchronizedLyricsFrame::setType(SynchronizedLyricsFrame::Type t)
{
d->type = t;
}
void SynchronizedLyricsFrame::setDescription(const String &s)
{
d->description = s;
}
void SynchronizedLyricsFrame::setSynchedText(
const SynchronizedLyricsFrame::SynchedTextList &t)
{
d->synchedText = t;
}
////////////////////////////////////////////////////////////////////////////////
// protected members
////////////////////////////////////////////////////////////////////////////////
void SynchronizedLyricsFrame::parseFields(const ByteVector &data)
{
const size_t end = data.size();
if(end < 7) {
debug("A synchronized lyrics frame must contain at least 7 bytes.");
return;
}
d->textEncoding = String::Type(data[0]);
d->language = data.mid(1, 3);
d->timestampFormat = TimestampFormat(data[4]);
d->type = Type(data[5]);
size_t pos = 6;
d->description = readStringField(data, d->textEncoding, pos);
if(d->description.isNull())
return;
/*
* If UTF16 strings are found in SYLT frames, a BOM may only be
* present in the first string (content descriptor), and the strings of
* the synchronized text have no BOM. Here the BOM is read from
* the first string to have a specific encoding with endianness for the
* case of strings without BOM so that readStringField() will work.
*/
String::Type encWithEndianness = d->textEncoding;
if(d->textEncoding == String::UTF16) {
ushort bom = data.toUInt16BE(6);
if(bom == 0xfffe) {
encWithEndianness = String::UTF16LE;
} else if(bom == 0xfeff) {
encWithEndianness = String::UTF16BE;
}
}
d->synchedText.clear();
while(pos < end) {
String::Type enc = d->textEncoding;
// If a UTF16 string has no BOM, use the encoding found above.
if(enc == String::UTF16 && pos + 1 < end) {
ushort bom = data.toUInt16BE(pos);
if(bom != 0xfffe && bom != 0xfeff) {
enc = encWithEndianness;
}
}
String text = readStringField(data, enc, pos);
if(text.isNull() || pos + 4 > end)
return;
uint time = data.toUInt32BE(pos);
pos += 4;
d->synchedText.append(SynchedText(time, text));
}
}
ByteVector SynchronizedLyricsFrame::renderFields() const
{
ByteVector v;
String::Type encoding = d->textEncoding;
encoding = checkTextEncoding(d->description, encoding);
for(SynchedTextList::ConstIterator it = d->synchedText.begin();
it != d->synchedText.end();
++it) {
encoding = checkTextEncoding(it->text, encoding);
}
v.append(char(encoding));
v.append(d->language.size() == 3 ? d->language : "XXX");
v.append(char(d->timestampFormat));
v.append(char(d->type));
v.append(d->description.data(encoding));
v.append(textDelimiter(encoding));
for(SynchedTextList::ConstIterator it = d->synchedText.begin();
it != d->synchedText.end();
++it) {
const SynchedText &entry = *it;
v.append(entry.text.data(encoding));
v.append(textDelimiter(encoding));
v.append(ByteVector::fromUInt32BE(entry.time));
}
return v;
}
////////////////////////////////////////////////////////////////////////////////
// private members
////////////////////////////////////////////////////////////////////////////////
SynchronizedLyricsFrame::SynchronizedLyricsFrame(const ByteVector &data, Header *h)
: Frame(h)
{
d = new SynchronizedLyricsFramePrivate();
parseFields(fieldData(data));
}

View File

@ -0,0 +1,231 @@
/***************************************************************************
copyright : (C) 2014 by Urs Fleisch
email : ufleisch@users.sourceforge.net
***************************************************************************/
/***************************************************************************
* 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., 51 Franklin Street, Fifth Floor, Boston, MA *
* 02110-1301 USA *
* *
* Alternatively, this file is available under the Mozilla Public *
* License Version 1.1. You may obtain a copy of the License at *
* http://www.mozilla.org/MPL/ *
***************************************************************************/
#ifndef TAGLIB_SYNCHRONIZEDLYRICSFRAME_H
#define TAGLIB_SYNCHRONIZEDLYRICSFRAME_H
#include "id3v2frame.h"
#include "tlist.h"
namespace TagLib {
namespace ID3v2 {
//! ID3v2 synchronized lyrics frame
/*!
* An implementation of ID3v2 synchronized lyrics.
*/
class TAGLIB_EXPORT SynchronizedLyricsFrame : public Frame
{
friend class FrameFactory;
public:
/*!
* Specifies the timestamp format used.
*/
enum TimestampFormat {
//! The timestamp is of unknown format.
Unknown = 0x00,
//! The timestamp represents the number of MPEG frames since
//! the beginning of the audio stream.
AbsoluteMpegFrames = 0x01,
//! The timestamp represents the number of milliseconds since
//! the beginning of the audio stream.
AbsoluteMilliseconds = 0x02
};
/*!
* Specifies the type of text contained.
*/
enum Type {
//! The text is some other type of text.
Other = 0x00,
//! The text contains lyrical data.
Lyrics = 0x01,
//! The text contains a transcription.
TextTranscription = 0x02,
//! The text lists the movements in the piece.
Movement = 0x03,
//! The text describes events that occur.
Events = 0x04,
//! The text contains chord changes that occur in the music.
Chord = 0x05,
//! The text contains trivia or "pop up" information about the media.
Trivia = 0x06,
//! The text contains URLs for relevant webpages.
WebpageUrls = 0x07,
//! The text contains URLs for relevant images.
ImageUrls = 0x08
};
/*!
* Single entry of time stamp and lyrics text.
*/
struct SynchedText {
SynchedText(uint ms, String str) : time(ms), text(str) {}
uint time;
String text;
};
/*!
* List of synchronized lyrics.
*/
typedef TagLib::List<SynchedText> SynchedTextList;
/*!
* Construct an empty synchronized lyrics frame that will use the text
* encoding \a encoding.
*/
explicit SynchronizedLyricsFrame(String::Type encoding = String::Latin1);
/*!
* Construct a synchronized lyrics frame based on the data in \a data.
*/
explicit SynchronizedLyricsFrame(const ByteVector &data);
/*!
* Destroys this SynchronizedLyricsFrame instance.
*/
virtual ~SynchronizedLyricsFrame();
/*!
* Returns the description of this synchronized lyrics frame.
*
* \see description()
*/
virtual String toString() const;
/*!
* Returns the text encoding that will be used in rendering this frame.
* This defaults to the type that was either specified in the constructor
* or read from the frame when parsed.
*
* \see setTextEncoding()
* \see render()
*/
String::Type textEncoding() const;
/*!
* Returns the language encoding as a 3 byte encoding as specified by
* <a href="http://en.wikipedia.org/wiki/ISO_639">ISO-639-2</a>.
*
* \note Most taggers simply ignore this value.
*
* \see setLanguage()
*/
ByteVector language() const;
/*!
* Returns the timestamp format.
*/
TimestampFormat timestampFormat() const;
/*!
* Returns the type of text contained.
*/
Type type() const;
/*!
* Returns the description of this synchronized lyrics frame.
*
* \note Most taggers simply ignore this value.
*
* \see setDescription()
*/
String description() const;
/*!
* Returns the text with the time stamps.
*/
SynchedTextList synchedText() const;
/*!
* Sets the text encoding to be used when rendering this frame to
* \a encoding.
*
* \see textEncoding()
* \see render()
*/
void setTextEncoding(String::Type encoding);
/*!
* Set the language using the 3 byte language code from
* <a href="http://en.wikipedia.org/wiki/ISO_639">ISO-639-2</a> to
* \a languageCode.
*
* \see language()
*/
void setLanguage(const ByteVector &languageCode);
/*!
* Set the timestamp format.
*
* \see timestampFormat()
*/
void setTimestampFormat(TimestampFormat f);
/*!
* Set the type of text contained.
*
* \see type()
*/
void setType(Type t);
/*!
* Sets the description of the synchronized lyrics frame to \a s.
*
* \see decription()
*/
void setDescription(const String &s);
/*!
* Sets the text with the time stamps.
*
* \see text()
*/
void setSynchedText(const SynchedTextList &t);
protected:
// Reimplementations.
virtual void parseFields(const ByteVector &data);
virtual ByteVector renderFields() const;
private:
/*!
* The constructor used by the FrameFactory.
*/
SynchronizedLyricsFrame(const ByteVector &data, Header *h);
SynchronizedLyricsFrame(const SynchronizedLyricsFrame &);
SynchronizedLyricsFrame &operator=(const SynchronizedLyricsFrame &);
class SynchronizedLyricsFramePrivate;
SynchronizedLyricsFramePrivate *d;
};
}
}
#endif

View File

@ -45,6 +45,8 @@
#include "frames/popularimeterframe.h"
#include "frames/privateframe.h"
#include "frames/ownershipframe.h"
#include "frames/synchronizedlyricsframe.h"
#include "frames/eventtimingcodesframe.h"
using namespace TagLib;
using namespace ID3v2;
@ -241,6 +243,20 @@ Frame *FrameFactory::createFrame(const ByteVector &origData, Header *tagHeader)
return f;
}
// Synchronised lyrics/text (frames 4.9)
if(frameID == "SYLT") {
SynchronizedLyricsFrame *f = new SynchronizedLyricsFrame(data, header);
if(d->useDefaultEncoding)
f->setTextEncoding(d->defaultEncoding);
return f;
}
// Event timing codes (frames 4.5)
if(frameID == "ETCO")
return new EventTimingCodesFrame(data, header);
// Popularimeter (frames 4.17)
if(frameID == "POPM")

View File

@ -431,8 +431,7 @@ ByteVector String::data(Type t) const
ByteVector v(2 + size() * 2, 0);
char *p = v.data();
// Assume that if we're doing UTF16 and not UTF16BE that we want little
// endian encoding. (Byte Order Mark)
// We use little-endian encoding here and need a BOM.
*p++ = '\xff';
*p++ = '\xfe';

View File

@ -165,7 +165,6 @@ namespace TagLib {
*/
String(wchar_t c, Type t = WCharByteOrder);
/*!
* Makes a deep copy of the data in \a s.
*
@ -175,7 +174,7 @@ namespace TagLib {
String(const char *s, Type t = Latin1);
/*!
* Makes a deep copy of the data in \a s.
* Makes a deep copy of the data in \a v.
*/
String(const ByteVector &v, Type t = Latin1);
@ -333,6 +332,9 @@ namespace TagLib {
* UTF8, this will return a vector of 8 bit characters, otherwise it will use
* 16 bit characters.
*
* \note If \a t is UTF16, the returned data is encoded in little-endian
* format and has a BOM.
*
* \note The returned data is not null terminated.
*/
ByteVector data(Type t) const;

View File

@ -14,6 +14,8 @@
#include <textidentificationframe.h>
#include <attachedpictureframe.h>
#include <unsynchronizedlyricsframe.h>
#include <synchronizedlyricsframe.h>
#include <eventtimingcodesframe.h>
#include <generalencapsulatedobjectframe.h>
#include <relativevolumeframe.h>
#include <popularimeterframe.h>
@ -71,6 +73,10 @@ class TestID3v2 : public CppUnit::TestFixture
CPPUNIT_TEST(testRenderUserUrlLinkFrame);
CPPUNIT_TEST(testParseOwnershipFrame);
CPPUNIT_TEST(testRenderOwnershipFrame);
CPPUNIT_TEST(testParseSynchronizedLyricsFrame);
CPPUNIT_TEST(testRenderSynchronizedLyricsFrame);
CPPUNIT_TEST(testParseEventTimingCodesFrame);
CPPUNIT_TEST(testRenderEventTimingCodesFrame);
CPPUNIT_TEST(testSaveUTF16Comment);
CPPUNIT_TEST(testUpdateGenre23_1);
CPPUNIT_TEST(testUpdateGenre23_2);
@ -429,6 +435,104 @@ public:
f.render());
}
void testParseSynchronizedLyricsFrame()
{
ID3v2::SynchronizedLyricsFrame f(
ByteVector("SYLT" // Frame ID
"\x00\x00\x00\x21" // Frame size
"\x00\x00" // Frame flags
"\x00" // Text encoding
"eng" // Language
"\x02" // Time stamp format
"\x01" // Content type
"foo\x00" // Content descriptor
"Example\x00" // 1st text
"\x00\x00\x04\xd2" // 1st time stamp
"Lyrics\x00" // 2nd text
"\x00\x00\x11\xd7", 43)); // 2nd time stamp
CPPUNIT_ASSERT_EQUAL(String::Latin1, f.textEncoding());
CPPUNIT_ASSERT_EQUAL(ByteVector("eng", 3), f.language());
CPPUNIT_ASSERT_EQUAL(ID3v2::SynchronizedLyricsFrame::AbsoluteMilliseconds,
f.timestampFormat());
CPPUNIT_ASSERT_EQUAL(ID3v2::SynchronizedLyricsFrame::Lyrics, f.type());
CPPUNIT_ASSERT_EQUAL(String("foo"), f.description());
ID3v2::SynchronizedLyricsFrame::SynchedTextList stl = f.synchedText();
CPPUNIT_ASSERT_EQUAL(size_t(2), stl.size());
CPPUNIT_ASSERT_EQUAL(String("Example"), stl[0].text);
CPPUNIT_ASSERT_EQUAL(TagLib::uint(1234), stl[0].time);
CPPUNIT_ASSERT_EQUAL(String("Lyrics"), stl[1].text);
CPPUNIT_ASSERT_EQUAL(TagLib::uint(4567), stl[1].time);
}
void testRenderSynchronizedLyricsFrame()
{
ID3v2::SynchronizedLyricsFrame f;
f.setTextEncoding(String::Latin1);
f.setLanguage(ByteVector("eng", 3));
f.setTimestampFormat(ID3v2::SynchronizedLyricsFrame::AbsoluteMilliseconds);
f.setType(ID3v2::SynchronizedLyricsFrame::Lyrics);
f.setDescription("foo");
ID3v2::SynchronizedLyricsFrame::SynchedTextList stl;
stl.append(ID3v2::SynchronizedLyricsFrame::SynchedText(1234, "Example"));
stl.append(ID3v2::SynchronizedLyricsFrame::SynchedText(4567, "Lyrics"));
f.setSynchedText(stl);
CPPUNIT_ASSERT_EQUAL(
ByteVector("SYLT" // Frame ID
"\x00\x00\x00\x21" // Frame size
"\x00\x00" // Frame flags
"\x00" // Text encoding
"eng" // Language
"\x02" // Time stamp format
"\x01" // Content type
"foo\x00" // Content descriptor
"Example\x00" // 1st text
"\x00\x00\x04\xd2" // 1st time stamp
"Lyrics\x00" // 2nd text
"\x00\x00\x11\xd7", 43), // 2nd time stamp
f.render());
}
void testParseEventTimingCodesFrame()
{
ID3v2::EventTimingCodesFrame f(
ByteVector("ETCO" // Frame ID
"\x00\x00\x00\x0b" // Frame size
"\x00\x00" // Frame flags
"\x02" // Time stamp format
"\x02" // 1st event
"\x00\x00\xf3\x5c" // 1st time stamp
"\xfe" // 2nd event
"\x00\x36\xee\x80", 21)); // 2nd time stamp
CPPUNIT_ASSERT_EQUAL(ID3v2::EventTimingCodesFrame::AbsoluteMilliseconds,
f.timestampFormat());
ID3v2::EventTimingCodesFrame::SynchedEventList sel = f.synchedEvents();
CPPUNIT_ASSERT_EQUAL(size_t(2), sel.size());
CPPUNIT_ASSERT_EQUAL(ID3v2::EventTimingCodesFrame::IntroStart, sel[0].type);
CPPUNIT_ASSERT_EQUAL(TagLib::uint(62300), sel[0].time);
CPPUNIT_ASSERT_EQUAL(ID3v2::EventTimingCodesFrame::AudioFileEnds, sel[1].type);
CPPUNIT_ASSERT_EQUAL(TagLib::uint(3600000), sel[1].time);
}
void testRenderEventTimingCodesFrame()
{
ID3v2::EventTimingCodesFrame f;
f.setTimestampFormat(ID3v2::EventTimingCodesFrame::AbsoluteMilliseconds);
ID3v2::EventTimingCodesFrame::SynchedEventList sel;
sel.append(ID3v2::EventTimingCodesFrame::SynchedEvent(62300, ID3v2::EventTimingCodesFrame::IntroStart));
sel.append(ID3v2::EventTimingCodesFrame::SynchedEvent(3600000, ID3v2::EventTimingCodesFrame::AudioFileEnds));
f.setSynchedEvents(sel);
CPPUNIT_ASSERT_EQUAL(
ByteVector("ETCO" // Frame ID
"\x00\x00\x00\x0b" // Frame size
"\x00\x00" // Frame flags
"\x02" // Time stamp format
"\x02" // 1st event
"\x00\x00\xf3\x5c" // 1st time stamp
"\xfe" // 2nd event
"\x00\x36\xee\x80", 21), // 2nd time stamp
f.render());
}
void testItunes24FrameSize()
{
MPEG::File f(TEST_FILE_PATH_C("005411.id3"), false);