diff --git a/mpeg/id3v2/frames/Makefile.am b/mpeg/id3v2/frames/Makefile.am index fe4a48f7..5d1966b4 100644 --- a/mpeg/id3v2/frames/Makefile.am +++ b/mpeg/id3v2/frames/Makefile.am @@ -1,4 +1,5 @@ INCLUDES = \ + -I$(top_srcdir)/taglib \ -I$(top_srcdir)/taglib/toolkit \ -I$(top_srcdir)/taglib/mpeg/id3v2 \ $(all_includes) diff --git a/mpeg/id3v2/frames/textidentificationframe.cpp b/mpeg/id3v2/frames/textidentificationframe.cpp index 90e06e5f..ee213787 100644 --- a/mpeg/id3v2/frames/textidentificationframe.cpp +++ b/mpeg/id3v2/frames/textidentificationframe.cpp @@ -20,6 +20,7 @@ ***************************************************************************/ #include +#include #include "textidentificationframe.h" @@ -35,7 +36,7 @@ public: }; //////////////////////////////////////////////////////////////////////////////// -// public members +// TextIdentificationFrame public members //////////////////////////////////////////////////////////////////////////////// TextIdentificationFrame::TextIdentificationFrame(const ByteVector &type, String::Type encoding) : @@ -88,7 +89,7 @@ void TextIdentificationFrame::setTextEncoding(String::Type encoding) } //////////////////////////////////////////////////////////////////////////////// -// protected members +// TextIdentificationFrame protected members //////////////////////////////////////////////////////////////////////////////// void TextIdentificationFrame::parseFields(const ByteVector &data) @@ -140,7 +141,7 @@ ByteVector TextIdentificationFrame::renderFields() const } //////////////////////////////////////////////////////////////////////////////// -// private members +// TextIdentificationFrame private members //////////////////////////////////////////////////////////////////////////////// TextIdentificationFrame::TextIdentificationFrame(const ByteVector &data, Header *h) : Frame(h) @@ -148,3 +149,97 @@ TextIdentificationFrame::TextIdentificationFrame(const ByteVector &data, Header d = new TextIdentificationFramePrivate; parseFields(fieldData(data)); } + +//////////////////////////////////////////////////////////////////////////////// +// UserTextIdentificationFrame public members +//////////////////////////////////////////////////////////////////////////////// + +UserTextIdentificationFrame::UserTextIdentificationFrame(String::Type encoding) : + TextIdentificationFrame("TXXX", encoding), + d(0) +{ + StringList l; + l.append(String::null); + l.append(String::null); + setText(l); +} + + +UserTextIdentificationFrame::UserTextIdentificationFrame(const ByteVector &data) : + TextIdentificationFrame(data) +{ + +} + +String UserTextIdentificationFrame::toString() const +{ + return "[" + description() + "] " + fieldList().toString(); +} + +String UserTextIdentificationFrame::description() const +{ + return !TextIdentificationFrame::fieldList().isEmpty() + ? TextIdentificationFrame::fieldList().front() + : String::null; +} + +StringList UserTextIdentificationFrame::fieldList() const +{ + StringList l = TextIdentificationFrame::fieldList(); + + if(!l.isEmpty()) { + StringList::Iterator it = l.begin(); + l.erase(it); + } + + return l; +} + +void UserTextIdentificationFrame::setText(const String &text) +{ + if(description().isEmpty()) + setDescription(String::null); + + TextIdentificationFrame::setText(StringList(description()).append(text)); +} + +void UserTextIdentificationFrame::setText(const StringList &fields) +{ + if(description().isEmpty()) + setDescription(String::null); + + TextIdentificationFrame::setText(StringList(description()).append(fields)); +} + +void UserTextIdentificationFrame::setDescription(const String &s) +{ + StringList l = fieldList(); + + if(l.isEmpty()) + l.append(s); + else + l[0] = s; + + TextIdentificationFrame::setText(l); +} + +UserTextIdentificationFrame *find(ID3v2::Tag *tag, const String &description) // static +{ + FrameList l = tag->frameList("TXXX"); + for(FrameList::Iterator it = l.begin(); it != l.end(); ++it) { + UserTextIdentificationFrame *f = dynamic_cast(*it); + if(f && f->description() == description) + return f; + } + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +// UserTextIdentificationFrame private members +//////////////////////////////////////////////////////////////////////////////// + +UserTextIdentificationFrame::UserTextIdentificationFrame(const ByteVector &data, Header *h) : + TextIdentificationFrame(data, h) +{ + +} diff --git a/mpeg/id3v2/frames/textidentificationframe.h b/mpeg/id3v2/frames/textidentificationframe.h index 7f6a6fc5..dc06b7f2 100644 --- a/mpeg/id3v2/frames/textidentificationframe.h +++ b/mpeg/id3v2/frames/textidentificationframe.h @@ -30,6 +30,8 @@ namespace TagLib { namespace ID3v2 { + class Tag; + //! An ID3v2 text identification frame implementation /*! @@ -162,11 +164,12 @@ namespace TagLib { virtual void parseFields(const ByteVector &data); virtual ByteVector renderFields() const; - private: /*! * The constructor used by the FrameFactory. */ TextIdentificationFrame(const ByteVector &data, Header *h); + + private: TextIdentificationFrame(const TextIdentificationFrame &); TextIdentificationFrame &operator=(const TextIdentificationFrame &); @@ -174,6 +177,63 @@ namespace TagLib { TextIdentificationFramePrivate *d; }; + /*! + * This is a specialization of text identification frames that allows for + * user defined entries. Each entry has a description in addition to the + * normal list of fields that a text identification frame has. + * + * This description identifies the frame and must be unique. + */ + + class UserTextIdentificationFrame : public TextIdentificationFrame + { + friend class FrameFactory; + + public: + /*! + * Constructs an empty user defined text identification frame. For this to be + * a useful frame both a description and text must be set. + */ + explicit UserTextIdentificationFrame(String::Type encoding = String::Latin1); + + /*! + * Creates a frame based on \a data. + */ + explicit UserTextIdentificationFrame(const ByteVector &data); + + virtual String toString() const; + + /*! + * Returns the description for this frame. + */ + String description() const; + + /*! + * Sets the description of the frame to \a s. \a s must be unique. You can + * check for the presense of another user defined text frame of the same type + * using find() and testing for null. + */ + void setDescription(const String &s); + + StringList fieldList() const; + void setText(const String &text); + void setText(const StringList &fields); + + /*! + * Searches for the user defined text frame with the description \a description + * in \a tag. This returns null if no matching frames were found. + */ + static UserTextIdentificationFrame *find(Tag *tag, const String &description); + + private: + UserTextIdentificationFrame(const ByteVector &data, Header *h); + UserTextIdentificationFrame(const TextIdentificationFrame &); + UserTextIdentificationFrame &operator=(const UserTextIdentificationFrame &); + + class UserTextIdentificationFramePrivate; + UserTextIdentificationFramePrivate *d; + }; + } } #endif diff --git a/mpeg/id3v2/id3v2framefactory.cpp b/mpeg/id3v2/id3v2framefactory.cpp index f98b8855..320551d7 100644 --- a/mpeg/id3v2/id3v2framefactory.cpp +++ b/mpeg/id3v2/id3v2framefactory.cpp @@ -106,8 +106,11 @@ Frame *FrameFactory::createFrame(const ByteVector &data, uint version) const // Text Identification (frames 4.2) - if(frameID.startsWith("T") && frameID != "TXXX") { - TextIdentificationFrame *f = new TextIdentificationFrame(data, header); + if(frameID.startsWith("T")) { + TextIdentificationFrame *f = frameID != "TXXX" + ? new TextIdentificationFrame(data, header) + : new UserTextIdentificationFrame(data, header); + if(d->useDefaultEncoding) f->setTextEncoding(d->defaultEncoding); return f;