1 /***************************************************************************
2 copyright : (C) 2002 - 2008 by Scott Wheeler
3 email : wheeler@kde.org
4 ***************************************************************************/
6 /***************************************************************************
7 * This library is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU Lesser General Public License version *
9 * 2.1 as published by the Free Software Foundation. *
11 * This library is distributed in the hope that it will be useful, but *
12 * WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
14 * Lesser General Public License for more details. *
16 * You should have received a copy of the GNU Lesser General Public *
17 * License along with this library; if not, write to the Free Software *
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
21 * Alternatively, this file is available under the Mozilla Public *
22 * License Version 1.1. You may obtain a copy of the License at *
23 * http://www.mozilla.org/MPL/ *
24 ***************************************************************************/
26 #include <tbytevectorlist.h>
29 #include "textidentificationframe.h"
31 using namespace TagLib;
32 using namespace ID3v2;
34 class TextIdentificationFrame::TextIdentificationFramePrivate
37 TextIdentificationFramePrivate() : textEncoding(String::Latin1) {}
38 String::Type textEncoding;
42 ////////////////////////////////////////////////////////////////////////////////
43 // TextIdentificationFrame public members
44 ////////////////////////////////////////////////////////////////////////////////
46 TextIdentificationFrame::TextIdentificationFrame(const ByteVector &type, String::Type encoding) :
49 d = new TextIdentificationFramePrivate;
50 d->textEncoding = encoding;
53 TextIdentificationFrame::TextIdentificationFrame(const ByteVector &data) :
56 d = new TextIdentificationFramePrivate;
60 TextIdentificationFrame::~TextIdentificationFrame()
65 void TextIdentificationFrame::setText(const StringList &l)
70 void TextIdentificationFrame::setText(const String &s)
75 String TextIdentificationFrame::toString() const
77 return d->fieldList.toString();
80 StringList TextIdentificationFrame::fieldList() const
85 String::Type TextIdentificationFrame::textEncoding() const
87 return d->textEncoding;
90 void TextIdentificationFrame::setTextEncoding(String::Type encoding)
92 d->textEncoding = encoding;
95 ////////////////////////////////////////////////////////////////////////////////
96 // TextIdentificationFrame protected members
97 ////////////////////////////////////////////////////////////////////////////////
99 void TextIdentificationFrame::parseFields(const ByteVector &data)
101 // Don't try to parse invalid frames
106 // read the string data type (the first byte of the field data)
108 d->textEncoding = String::Type(data[0]);
110 // split the byte array into chunks based on the string type (two byte delimiter
111 // for unicode encodings)
113 int byteAlign = d->textEncoding == String::Latin1 || d->textEncoding == String::UTF8 ? 1 : 2;
115 // build a small counter to strip nulls off the end of the field
117 int dataLength = data.size() - 1;
119 while(dataLength > 0 && data[dataLength] == 0)
122 while(dataLength % byteAlign != 0)
125 ByteVectorList l = ByteVectorList::split(data.mid(1, dataLength), textDelimiter(d->textEncoding), byteAlign);
127 d->fieldList.clear();
129 // append those split values to the list and make sure that the new string's
130 // type is the same specified for this frame
132 for(ByteVectorList::Iterator it = l.begin(); it != l.end(); it++) {
133 if(!(*it).isEmpty()) {
134 String s(*it, d->textEncoding);
135 d->fieldList.append(s);
140 ByteVector TextIdentificationFrame::renderFields() const
142 String::Type encoding = checkEncoding(d->fieldList, d->textEncoding);
146 v.append(char(encoding));
148 for(StringList::ConstIterator it = d->fieldList.begin(); it != d->fieldList.end(); it++) {
150 // Since the field list is null delimited, if this is not the first
151 // element in the list, append the appropriate delimiter for this
154 if(it != d->fieldList.begin())
155 v.append(textDelimiter(encoding));
157 v.append((*it).data(encoding));
163 ////////////////////////////////////////////////////////////////////////////////
164 // TextIdentificationFrame private members
165 ////////////////////////////////////////////////////////////////////////////////
167 TextIdentificationFrame::TextIdentificationFrame(const ByteVector &data, Header *h) : Frame(h)
169 d = new TextIdentificationFramePrivate;
170 parseFields(fieldData(data));
173 ////////////////////////////////////////////////////////////////////////////////
174 // UserTextIdentificationFrame public members
175 ////////////////////////////////////////////////////////////////////////////////
177 UserTextIdentificationFrame::UserTextIdentificationFrame(String::Type encoding) :
178 TextIdentificationFrame("TXXX", encoding),
182 l.append(String::null);
183 l.append(String::null);
188 UserTextIdentificationFrame::UserTextIdentificationFrame(const ByteVector &data) :
189 TextIdentificationFrame(data)
194 String UserTextIdentificationFrame::toString() const
196 return "[" + description() + "] " + fieldList().toString();
199 String UserTextIdentificationFrame::description() const
201 return !TextIdentificationFrame::fieldList().isEmpty()
202 ? TextIdentificationFrame::fieldList().front()
206 StringList UserTextIdentificationFrame::fieldList() const
208 // TODO: remove this function
210 return TextIdentificationFrame::fieldList();
213 void UserTextIdentificationFrame::setText(const String &text)
215 if(description().isEmpty())
216 setDescription(String::null);
218 TextIdentificationFrame::setText(StringList(description()).append(text));
221 void UserTextIdentificationFrame::setText(const StringList &fields)
223 if(description().isEmpty())
224 setDescription(String::null);
226 TextIdentificationFrame::setText(StringList(description()).append(fields));
229 void UserTextIdentificationFrame::setDescription(const String &s)
231 StringList l = fieldList();
238 TextIdentificationFrame::setText(l);
241 UserTextIdentificationFrame *UserTextIdentificationFrame::find(
242 ID3v2::Tag *tag, const String &description) // static
244 FrameList l = tag->frameList("TXXX");
245 for(FrameList::Iterator it = l.begin(); it != l.end(); ++it) {
246 UserTextIdentificationFrame *f = dynamic_cast<UserTextIdentificationFrame *>(*it);
247 if(f && f->description() == description)
253 ////////////////////////////////////////////////////////////////////////////////
254 // UserTextIdentificationFrame private members
255 ////////////////////////////////////////////////////////////////////////////////
257 UserTextIdentificationFrame::UserTextIdentificationFrame(const ByteVector &data, Header *h) :
258 TextIdentificationFrame(data, h)
263 void UserTextIdentificationFrame::checkFields()
265 int fields = fieldList().size();
268 setDescription(String::null);
270 setText(String::null);