1/***************************************************************************
2 copyright : (C) 2002 - 2008 by Scott Wheeler
3 email : wheeler@kde.org
4 ***************************************************************************/
5
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. *
10 * *
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. *
15 * *
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., 51 Franklin Street, Fifth Floor, Boston, MA *
19 * 02110-1301 USA *
20 * *
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 ***************************************************************************/
25
26#ifndef TAGLIB_ID3V2TAG_H
27#define TAGLIB_ID3V2TAG_H
28
29#include "tag.h"
30#include "tbytevector.h"
31#include "tstring.h"
32#include "tlist.h"
33#include "tmap.h"
34#include "taglib_export.h"
35
36#include "id3v2framefactory.h"
37
38namespace TagLib {
39
40 class File;
41
42 //! An ID3v2 implementation
43
44 /*!
45 * This is a relatively complete and flexible framework for working with ID3v2
46 * tags.
47 *
48 * \see ID3v2::Tag
49 */
50
51 namespace ID3v2 {
52
53 class Header;
54 class ExtendedHeader;
55 class Footer;
56
57 typedef List<Frame *> FrameList;
58 typedef Map<ByteVector, FrameList> FrameListMap;
59
60 //! An abstraction for the ISO-8859-1 string to data encoding in ID3v2 tags.
61
62 /*!
63 * ID3v2 tag can store strings in ISO-8859-1 (Latin1), and TagLib only
64 * supports genuine ISO-8859-1 by default. However, in practice, non
65 * ISO-8859-1 encodings are often used instead of ISO-8859-1, such as
66 * Windows-1252 for western languages, Shift_JIS for Japanese and so on.
67 *
68 * Here is an option to read such tags by subclassing this class,
69 * reimplementing parse() and setting your reimplementation as the default
70 * with ID3v2::Tag::setStringHandler().
71 *
72 * \note Writing non-ISO-8859-1 tags is not implemented intentionally.
73 * Use UTF-16 or UTF-8 instead.
74 *
75 * \see ID3v2::Tag::setStringHandler()
76 */
77 class TAGLIB_EXPORT Latin1StringHandler
78 {
79 public:
80 Latin1StringHandler();
81 virtual ~Latin1StringHandler();
82
83 /*!
84 * Decode a string from \a data. The default implementation assumes that
85 * \a data is an ISO-8859-1 (Latin1) character array.
86 */
87 virtual String parse(const ByteVector &data) const;
88 };
89
90 //! The main class in the ID3v2 implementation
91
92 /*!
93 * This is the main class in the ID3v2 implementation. It serves two
94 * functions. This first, as is obvious from the public API, is to provide a
95 * container for the other ID3v2 related classes. In addition, through the
96 * read() and parse() protected methods, it provides the most basic level of
97 * parsing. In these methods the ID3v2 tag is extracted from the file and
98 * split into data components.
99 *
100 * ID3v2 tags have several parts, TagLib attempts to provide an interface
101 * for them all. header(), footer() and extendedHeader() correspond to those
102 * data structures in the ID3v2 standard and the APIs for the classes that
103 * they return attempt to reflect this.
104 *
105 * Also ID3v2 tags are built up from a list of frames, which are in turn
106 * have a header and a list of fields. TagLib provides two ways of accessing
107 * the list of frames that are in a given ID3v2 tag. The first is simply
108 * via the frameList() method. This is just a list of pointers to the frames.
109 * The second is a map from the frame type -- i.e. "COMM" for comments -- and
110 * a list of frames of that type. (In some cases ID3v2 allows for multiple
111 * frames of the same type, hence this being a map to a list rather than just
112 * a map to an individual frame.)
113 *
114 * More information on the structure of frames can be found in the ID3v2::Frame
115 * class.
116 *
117 * read() and parse() pass binary data to the other ID3v2 class structures,
118 * they do not handle parsing of flags or fields, for instance. Those are
119 * handled by similar functions within those classes.
120 *
121 * \note All pointers to data structures within the tag will become invalid
122 * when the tag is destroyed.
123 *
124 * \warning Dealing with the nasty details of ID3v2 is not for the faint of
125 * heart and should not be done without much meditation on the spec. It's
126 * rather long, but if you're planning on messing with this class and others
127 * that deal with the details of ID3v2 (rather than the nice, safe, abstract
128 * TagLib::Tag and friends), it's worth your time to familiarize yourself
129 * with said spec (which is distributed with the TagLib sources). TagLib
130 * tries to do most of the work, but with a little luck, you can still
131 * convince it to generate invalid ID3v2 tags. The APIs for ID3v2 assume a
132 * working knowledge of ID3v2 structure. You're been warned.
133 */
134
135 class TAGLIB_EXPORT Tag : public TagLib::Tag
136 {
137 public:
138 /*!
139 * Constructs an empty ID3v2 tag.
140 *
141 * \note You must create at least one frame for this tag to be valid.
142 */
143 Tag();
144
145 /*!
146 * Constructs an ID3v2 tag read from \a file starting at \a tagOffset.
147 * \a factory specifies which FrameFactory will be used for the
148 * construction of new frames.
149 *
150 * \note You should be able to ignore the \a factory parameter in almost
151 * all situations. You would want to specify your own FrameFactory
152 * subclass in the case that you are extending TagLib to support additional
153 * frame types, which would be incorporated into your factory.
154 *
155 * \see FrameFactory
156 */
157 Tag(File *file, long tagOffset,
158 const FrameFactory *factory = FrameFactory::instance());
159
160 /*!
161 * Destroys this Tag instance.
162 */
163 virtual ~Tag();
164
165 // Reimplementations.
166
167 virtual String title() const;
168 virtual String artist() const;
169 virtual String album() const;
170 virtual String comment() const;
171 virtual String genre() const;
172 virtual unsigned int year() const;
173 virtual unsigned int track() const;
174
175 virtual void setTitle(const String &s);
176 virtual void setArtist(const String &s);
177 virtual void setAlbum(const String &s);
178 virtual void setComment(const String &s);
179 virtual void setGenre(const String &s);
180 virtual void setYear(unsigned int i);
181 virtual void setTrack(unsigned int i);
182
183 virtual bool isEmpty() const;
184
185 /*!
186 * Returns a pointer to the tag's header.
187 */
188 Header *header() const;
189
190 /*!
191 * Returns a pointer to the tag's extended header or null if there is no
192 * extended header.
193 */
194 ExtendedHeader *extendedHeader() const;
195
196 /*!
197 * Returns a pointer to the tag's footer or null if there is no footer.
198 *
199 * \deprecated I don't see any reason to keep this around since there's
200 * nothing useful to be retrieved from the footer, but well, again, I'm
201 * prone to change my mind, so this gets to stay around until near a
202 * release.
203 */
204 Footer *footer() const;
205
206 /*!
207 * Returns a reference to the frame list map. This is an FrameListMap of
208 * all of the frames in the tag.
209 *
210 * This is the most convenient structure for accessing the tag's frames.
211 * Many frame types allow multiple instances of the same frame type so this
212 * is a map of lists. In most cases however there will only be a single
213 * frame of a certain type.
214 *
215 * Let's say for instance that you wanted to access the frame for total
216 * beats per minute -- the TBPM frame.
217 *
218 * \code
219 * TagLib::MPEG::File f("foo.mp3");
220 *
221 * // Check to make sure that it has an ID3v2 tag
222 *
223 * if(f.ID3v2Tag()) {
224 *
225 * // Get the list of frames for a specific frame type
226 *
227 * TagLib::ID3v2::FrameList l = f.ID3v2Tag()->frameListMap()["TBPM"];
228 *
229 * if(!l.isEmpty())
230 * std::cout << l.front()->toString() << std::endl;
231 * }
232 *
233 * \endcode
234 *
235 * \warning You should not modify this data structure directly, instead
236 * use addFrame() and removeFrame().
237 *
238 * \see frameList()
239 */
240 const FrameListMap &frameListMap() const;
241
242 /*!
243 * Returns a reference to the frame list. This is an FrameList of all of
244 * the frames in the tag in the order that they were parsed.
245 *
246 * This can be useful if for example you want iterate over the tag's frames
247 * in the order that they occur in the tag.
248 *
249 * \warning You should not modify this data structure directly, instead
250 * use addFrame() and removeFrame().
251 */
252 const FrameList &frameList() const;
253
254 /*!
255 * Returns the frame list for frames with the id \a frameID or an empty
256 * list if there are no frames of that type. This is just a convenience
257 * and is equivalent to:
258 *
259 * \code
260 * frameListMap()[frameID];
261 * \endcode
262 *
263 * \see frameListMap()
264 */
265 const FrameList &frameList(const ByteVector &frameID) const;
266
267 /*!
268 * Add a frame to the tag. At this point the tag takes ownership of
269 * the frame and will handle freeing its memory.
270 *
271 * \note Using this method will invalidate any pointers on the list
272 * returned by frameList()
273 */
274 void addFrame(Frame *frame);
275
276 /*!
277 * Remove a frame from the tag. If \a del is true the frame's memory
278 * will be freed; if it is false, it must be deleted by the user.
279 *
280 * \note Using this method will invalidate any pointers on the list
281 * returned by frameList()
282 */
283 void removeFrame(Frame *frame, bool del = true);
284
285 /*!
286 * Remove all frames of type \a id from the tag and free their memory.
287 *
288 * \note Using this method will invalidate any pointers on the list
289 * returned by frameList()
290 */
291 void removeFrames(const ByteVector &id);
292
293 /*!
294 * Implements the unified property interface -- export function.
295 * This function does some work to translate the hard-specified ID3v2
296 * frame types into a free-form string-to-stringlist PropertyMap:
297 * - if ID3v2 frame ID is known by Frame::frameIDToKey(), the returned
298 * key is used
299 * - if the frame ID is "TXXX" (user text frame), the description() is
300 * used as key
301 * - if the frame ID is "WXXX" (user url frame),
302 * - if the description is empty or "URL", the key "URL" is used
303 * - otherwise, the key "URL:<description>" is used;
304 * - if the frame ID is "COMM" (comments frame),
305 * - if the description is empty or "COMMENT", the key "COMMENT"
306 * is used
307 * - otherwise, the key "COMMENT:<description>" is used;
308 * - if the frame ID is "USLT" (unsynchronized lyrics),
309 * - if the description is empty or "LYRICS", the key "LYRICS" is used
310 * - otherwise, the key "LYRICS:<description>" is used;
311 * - if the frame ID is "TIPL" (involved peoples list), and if all the
312 * roles defined in the frame are known in TextIdentificationFrame::involvedPeopleMap(),
313 * then "<role>=<name>" will be contained in the returned obejct for each
314 * - if the frame ID is "TMCL" (musician credit list), then
315 * "PERFORMER:<instrument>=<name>" will be contained in the returned
316 * PropertyMap for each defined musician
317 * In any other case, the unsupportedData() of the returned object will contain
318 * the frame's ID and, in case of a frame ID which is allowed to appear more than
319 * once, the description, separated by a "/".
320 *
321 */
322 PropertyMap properties() const;
323
324 /*!
325 * Removes unsupported frames given by \a properties. The elements of
326 * \a properties must be taken from properties().unsupportedData(); they
327 * are of one of the following forms:
328 * - a four-character frame ID, if the ID3 specification allows only one
329 * frame with that ID (thus, the frame is uniquely determined)
330 * - frameID + "/" + description(), when the ID is one of "TXXX", "WXXX",
331 * "COMM", or "USLT",
332 * - "UNKNOWN/" + frameID, for frames that could not be parsed by TagLib.
333 * In that case, *all* unknown frames with the given ID will be removed.
334 */
335 void removeUnsupportedProperties(const StringList &properties);
336
337 /*!
338 * Implements the unified property interface -- import function.
339 * See the comments in properties().
340 */
341 PropertyMap setProperties(const PropertyMap &);
342
343 /*!
344 * Render the tag back to binary data, suitable to be written to disk.
345 */
346 ByteVector render() const;
347
348 /*!
349 * Render the tag back to binary data, suitable to be written to disk.
350 *
351 * The \a version parameter specifies the version of the rendered
352 * ID3v2 tag. It can be either 4 or 3.
353 */
354 // BIC: combine with the above method
355 ByteVector render(int version) const;
356
357 /*!
358 * Gets the current string handler that decides how the "Latin-1" data
359 * will be converted to and from binary data.
360 *
361 * \see Latin1StringHandler
362 */
363 static Latin1StringHandler const *latin1StringHandler();
364
365 /*!
366 * Sets the string handler that decides how the "Latin-1" data will be
367 * converted to and from binary data.
368 * If the parameter \a handler is null, the previous handler is
369 * released and default ISO-8859-1 handler is restored.
370 *
371 * \note The caller is responsible for deleting the previous handler
372 * as needed after it is released.
373 *
374 * \see Latin1StringHandler
375 */
376 static void setLatin1StringHandler(const Latin1StringHandler *handler);
377
378 protected:
379 /*!
380 * Reads data from the file specified in the constructor. It does basic
381 * parsing of the data in the largest chunks. It partitions the tag into
382 * the Header, the body of the tag (which contains the ExtendedHeader and
383 * frames) and Footer.
384 */
385 void read();
386
387 /*!
388 * This is called by read to parse the body of the tag. It determines if an
389 * extended header exists and adds frames to the FrameListMap.
390 */
391 void parse(const ByteVector &data);
392
393 /*!
394 * Sets the value of the text frame with the Frame ID \a id to \a value.
395 * If the frame does not exist, it is created.
396 */
397 void setTextFrame(const ByteVector &id, const String &value);
398
399 void downgradeFrames(FrameList *existingFrames, FrameList *newFrames) const;
400
401 private:
402 Tag(const Tag &);
403 Tag &operator=(const Tag &);
404
405 class TagPrivate;
406 TagPrivate *d;
407 };
408
409 }
410}
411
412#endif
413