diff --git a/taglib/CMakeLists.txt b/taglib/CMakeLists.txt index 1e16dd18..073d8904 100644 --- a/taglib/CMakeLists.txt +++ b/taglib/CMakeLists.txt @@ -67,6 +67,7 @@ mpeg/id3v2/frames/relativevolumeframe.cpp mpeg/id3v2/frames/textidentificationframe.cpp mpeg/id3v2/frames/uniquefileidentifierframe.cpp mpeg/id3v2/frames/unknownframe.cpp +mpeg/id3v2/frames/unsynchronizedlyricsframe.cpp mpeg/id3v2/frames/urllinkframe.cpp ) diff --git a/taglib/mpeg/id3v2/frames/CMakeLists.txt b/taglib/mpeg/id3v2/frames/CMakeLists.txt index 90716949..1fb1e208 100644 --- a/taglib/mpeg/id3v2/frames/CMakeLists.txt +++ b/taglib/mpeg/id3v2/frames/CMakeLists.txt @@ -6,5 +6,6 @@ INSTALL(FILES textidentificationframe.h uniquefileidentifierframe.h unknownframe.h + unsynchronizedlyricsframe.h urllinkframe.h DESTINATION ${INCLUDE_INSTALL_DIR}/taglib) diff --git a/taglib/mpeg/id3v2/frames/Makefile.am b/taglib/mpeg/id3v2/frames/Makefile.am index bb8affd4..517cd753 100644 --- a/taglib/mpeg/id3v2/frames/Makefile.am +++ b/taglib/mpeg/id3v2/frames/Makefile.am @@ -14,6 +14,7 @@ libframes_la_SOURCES = \ textidentificationframe.cpp \ uniquefileidentifierframe.cpp \ unknownframe.cpp \ + unsynchronizedlyricsframe.cpp \ urllinkframe.cpp taglib_include_HEADERS = \ @@ -24,6 +25,7 @@ taglib_include_HEADERS = \ textidentificationframe.h \ uniquefileidentifierframe.h \ unknownframe.h \ + unsynchronizedlyricsframe.h \ urllinkframe.h taglib_includedir = $(includedir)/taglib diff --git a/taglib/mpeg/id3v2/frames/unsynchronizedlyricsframe.cpp b/taglib/mpeg/id3v2/frames/unsynchronizedlyricsframe.cpp new file mode 100644 index 00000000..c607f24e --- /dev/null +++ b/taglib/mpeg/id3v2/frames/unsynchronizedlyricsframe.cpp @@ -0,0 +1,162 @@ +/*************************************************************************** + copyright : (C) 2002, 2003 by Scott Wheeler + email : wheeler@kde.org + copyright : (C) 2006 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * + * 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 "unsynchronizedlyricsframe.h" +#include +#include + +using namespace TagLib; +using namespace ID3v2; + +class UnsynchronizedLyricsFrame::UnsynchronizedLyricsFramePrivate +{ +public: + UnsynchronizedLyricsFramePrivate() : textEncoding(String::Latin1) {} + String::Type textEncoding; + ByteVector language; + String description; + String text; +}; + +//////////////////////////////////////////////////////////////////////////////// +// public members +//////////////////////////////////////////////////////////////////////////////// + +UnsynchronizedLyricsFrame::UnsynchronizedLyricsFrame(String::Type encoding) : + Frame("USLT") +{ + d = new UnsynchronizedLyricsFramePrivate; + d->textEncoding = encoding; +} + +UnsynchronizedLyricsFrame::UnsynchronizedLyricsFrame(const ByteVector &data) : + Frame(data) +{ + d = new UnsynchronizedLyricsFramePrivate; + setData(data); +} + +UnsynchronizedLyricsFrame::~UnsynchronizedLyricsFrame() +{ + delete d; +} + +String UnsynchronizedLyricsFrame::toString() const +{ + return d->text; +} + +ByteVector UnsynchronizedLyricsFrame::language() const +{ + return d->language; +} + +String UnsynchronizedLyricsFrame::description() const +{ + return d->description; +} + +String UnsynchronizedLyricsFrame::text() const +{ + return d->text; +} + +void UnsynchronizedLyricsFrame::setLanguage(const ByteVector &languageEncoding) +{ + d->language = languageEncoding.mid(0, 3); +} + +void UnsynchronizedLyricsFrame::setDescription(const String &s) +{ + d->description = s; +} + +void UnsynchronizedLyricsFrame::setText(const String &s) +{ + d->text = s; +} + + +String::Type UnsynchronizedLyricsFrame::textEncoding() const +{ + return d->textEncoding; +} + +void UnsynchronizedLyricsFrame::setTextEncoding(String::Type encoding) +{ + d->textEncoding = encoding; +} + +//////////////////////////////////////////////////////////////////////////////// +// protected members +//////////////////////////////////////////////////////////////////////////////// + +void UnsynchronizedLyricsFrame::parseFields(const ByteVector &data) +{ + if(data.size() < 5) { + debug("An unsynchronized lyrics 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, 2); + + if(l.size() == 2) { + d->description = String(l.front(), d->textEncoding); + d->text = String(l.back(), d->textEncoding); + } +} + +ByteVector UnsynchronizedLyricsFrame::renderFields() const +{ + ByteVector v; + + v.append(char(d->textEncoding)); + v.append(d->language.size() == 3 ? d->language : "XXX"); + v.append(d->description.data(d->textEncoding)); + v.append(textDelimiter(d->textEncoding)); + v.append(d->text.data(d->textEncoding)); + + return v; +} + +//////////////////////////////////////////////////////////////////////////////// +// private members +//////////////////////////////////////////////////////////////////////////////// + +UnsynchronizedLyricsFrame::UnsynchronizedLyricsFrame(const ByteVector &data, Header *h) + : Frame(h) +{ + d = new UnsynchronizedLyricsFramePrivate(); + parseFields(fieldData(data)); +} diff --git a/taglib/mpeg/id3v2/frames/unsynchronizedlyricsframe.h b/taglib/mpeg/id3v2/frames/unsynchronizedlyricsframe.h new file mode 100644 index 00000000..ec93a0a4 --- /dev/null +++ b/taglib/mpeg/id3v2/frames/unsynchronizedlyricsframe.h @@ -0,0 +1,152 @@ +/*************************************************************************** + copyright : (C) 2002, 2003 by Scott Wheeler + email : wheeler@kde.org + copyright : (C) 2006 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * + * USA * + ***************************************************************************/ + +#ifndef TAGLIB_UNSYNCHRONIZEDLYRICSFRAME_H +#define TAGLIB_UNSYNCHRONIZEDLYRICSFRAME_H + +#include + +namespace TagLib { + + namespace ID3v2 { + + /*! + * An implementation of ID3v2 unsynchronized lyrics. + */ + class UnsynchronizedLyricsFrame : public Frame + { + friend class FrameFactory; + + public: + /*! + * Construct an empty unsynchronized lyrics frame that will use the text encoding + * \a encoding. + */ + explicit UnsynchronizedLyricsFrame(String::Type encoding = String::Latin1); + + /*! + * Construct a unsynchronized lyrics frame based on the data in \a data. + */ + explicit UnsynchronizedLyricsFrame(const ByteVector &data); + + /*! + * Destroys this UnsynchronizedLyricsFrame instance. + */ + virtual ~UnsynchronizedLyricsFrame(); + + /*! + * Returns the text of this unsynchronized lyrics frame. + * + * \see text() + */ + virtual String toString() const; + + /*! + * Returns the language encoding as a 3 byte encoding as specified by + * ISO-639-2. + * + * \note Most taggers simply ignore this value. + * + * \see setLanguage() + */ + ByteVector language() const; + + /*! + * Returns the description of this unsynchronized lyrics frame. + * + * \note Most taggers simply ignore this value. + * + * \see setDescription() + */ + String description() const; + + /*! + * Returns the text of this unsynchronized lyrics frame. + * + * \see setText() + */ + String text() const; + + /*! + * Set the language using the 3 byte language code from + * ISO-639-2 to + * \a languageCode. + * + * \see language() + */ + void setLanguage(const ByteVector &languageCode); + + /*! + * Sets the description of the unsynchronized lyrics frame to \a s. + * + * \see decription() + */ + void setDescription(const String &s); + + /*! + * Sets the text portion of the unsynchronized lyrics frame to \a s. + * + * \see text() + */ + virtual void setText(const String &s); + + /*! + * Returns the text encoding that will be used in rendering this frame. + * This defaults to the type that was either specified in the constructor + * or read from the frame when parsed. + * + * \see setTextEncoding() + * \see render() + */ + 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. + */ + UnsynchronizedLyricsFrame(const ByteVector &data, Header *h); + UnsynchronizedLyricsFrame(const UnsynchronizedLyricsFrame &); + UnsynchronizedLyricsFrame &operator=(const UnsynchronizedLyricsFrame &); + + class UnsynchronizedLyricsFramePrivate; + UnsynchronizedLyricsFramePrivate *d; + }; + + } +} +#endif diff --git a/taglib/mpeg/id3v2/id3v2framefactory.cpp b/taglib/mpeg/id3v2/id3v2framefactory.cpp index 1e03cd77..3b92a824 100644 --- a/taglib/mpeg/id3v2/id3v2framefactory.cpp +++ b/taglib/mpeg/id3v2/id3v2framefactory.cpp @@ -38,6 +38,7 @@ #include "frames/unknownframe.h" #include "frames/generalencapsulatedobjectframe.h" #include "frames/urllinkframe.h" +#include "frames/unsynchronizedlyricsframe.h" using namespace TagLib; using namespace ID3v2; @@ -208,6 +209,15 @@ Frame *FrameFactory::createFrame(const ByteVector &origData, Header *tagHeader) } } + // Unsynchronized lyric/text transcription (frames 4.8) + + if(frameID == "USLT") { + UnsynchronizedLyricsFrame *f = new UnsynchronizedLyricsFrame(data, header); + if(d->useDefaultEncoding) + f->setTextEncoding(d->defaultEncoding); + return f; + } + return new UnknownFrame(data, header); }