fixed graphics bug
[swftools.git] / lib / lame / id3tag.c
1 /*
2  * id3tag.c -- Write ID3 version 1 and 2 tags.
3  *
4  * Copyright (C) 2000 Don Melton.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library 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, USA.
19  */
20
21 /*
22  * HISTORY: This source file is part of LAME (see http://www.mp3dev.org/mp3/)
23  * and was originally adapted by Conrad Sanderson <c.sanderson@me.gu.edu.au>
24  * from mp3info by Ricardo Cerqueira <rmc@rccn.net> to write only ID3 version 1
25  * tags.  Don Melton <don@blivet.com> COMPLETELY rewrote it to support version
26  * 2 tags and be more conformant to other standards while remaining flexible.
27  *
28  * NOTE: See http://id3.org/ for more information about ID3 tag formats.
29  */
30
31 /* $Id: id3tag.c,v 1.1 2002/04/28 17:30:19 kramm Exp $ */
32
33 #include "config_static.h"
34
35 #ifdef STDC_HEADERS
36 # include <stddef.h>
37 # include <stdlib.h>
38 # include <string.h>
39 #else
40 # ifndef HAVE_STRCHR
41 #  define strchr index
42 #  define strrchr rindex
43 # endif
44 char *strchr (), *strrchr ();
45 # ifndef HAVE_MEMCPY
46 #  define memcpy(d, s, n) bcopy ((s), (d), (n))
47 #  define memmove(d, s, n) bcopy ((s), (d), (n))
48 # endif
49 #endif
50
51 #include "lame.h"
52 #include "id3tag.h"
53 #include "util.h"
54 #include "bitstream.h"
55
56 #ifdef WITH_DMALLOC
57 #include <dmalloc.h>
58 #endif
59
60 static const char *const genre_names[] =
61 {
62     /*
63      * NOTE: The spelling of these genre names is identical to those found in
64      * Winamp and mp3info.
65      */
66     "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge",
67     "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies", "Other", "Pop", "R&B",
68     "Rap", "Reggae", "Rock", "Techno", "Industrial", "Alternative", "Ska",
69     "Death Metal", "Pranks", "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop",
70     "Vocal", "Jazz+Funk", "Fusion", "Trance", "Classical", "Instrumental",
71     "Acid", "House", "Game", "Sound Clip", "Gospel", "Noise", "Alt. Rock",
72     "Bass", "Soul", "Punk", "Space", "Meditative", "Instrumental Pop",
73     "Instrumental Rock", "Ethnic", "Gothic", "Darkwave", "Techno-Industrial",
74     "Electronic", "Pop-Folk", "Eurodance", "Dream", "Southern Rock", "Comedy",
75     "Cult", "Gangsta Rap", "Top 40", "Christian Rap", "Pop/Funk", "Jungle",
76     "Native American", "Cabaret", "New Wave", "Psychedelic", "Rave",
77     "Showtunes", "Trailer", "Lo-Fi", "Tribal", "Acid Punk", "Acid Jazz",
78     "Polka", "Retro", "Musical", "Rock & Roll", "Hard Rock", "Folk",
79     "Folk/Rock", "National Folk", "Swing", "Fast-Fusion", "Bebob", "Latin",
80     "Revival", "Celtic", "Bluegrass", "Avantgarde", "Gothic Rock",
81     "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", "Slow Rock",
82     "Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech",
83     "Chanson", "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass",
84     "Primus", "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba",
85     "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle", "Duet",
86     "Punk Rock", "Drum Solo", "A Cappella", "Euro-House", "Dance Hall",
87     "Goa", "Drum & Bass", "Club-House", "Hardcore", "Terror", "Indie",
88     "BritPop", "Negerpunk", "Polsk Punk", "Beat", "Christian Gangsta Rap",
89     "Heavy Metal", "Black Metal", "Crossover", "Contemporary Christian",
90     "Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime", "JPop",
91     "Synthpop"
92 };
93
94 #define GENRE_NAME_COUNT \
95     ((int)(sizeof genre_names / sizeof (const char *const)))
96
97 static const int genre_alpha_map [] = {
98     123, 34, 74, 73, 99, 20, 40, 26, 145, 90, 116, 41, 135, 85, 96, 138, 89, 0,
99     107, 132, 65, 88, 104, 102, 97, 136, 61, 141, 32, 1, 112, 128, 57, 140, 2,
100     139, 58, 3, 125, 50, 22, 4, 55, 127, 122, 120, 98, 52, 48, 54, 124, 25, 84,
101     80, 115, 81, 119, 5, 30, 36, 59, 126, 38, 49, 91, 6, 129, 79, 137, 7, 35,
102     100, 131, 19, 33, 46, 47, 8, 29, 146, 63, 86, 71, 45, 142, 9, 77, 82, 64,
103     133, 10, 66, 39, 11, 103, 12, 75, 134, 13, 53, 62, 109, 117, 23, 108, 92,
104     67, 93, 43, 121, 15, 68, 14, 16, 76, 87, 118, 17, 78, 143, 114, 110, 69, 21,
105     111, 95, 105, 42, 37, 24, 56, 44, 101, 83, 94, 106, 147, 113, 18, 51, 130,
106     144, 60, 70, 31, 72, 27, 28
107 };
108
109 #define GENRE_ALPHA_COUNT ((int)(sizeof genre_alpha_map / sizeof (int)))
110
111 void
112 id3tag_genre_list(void (*handler)(int, const char *, void *), void *cookie)
113 {
114     if (handler) {
115         int i;
116         for (i = 0; i < GENRE_NAME_COUNT; ++i) {
117             if (i < GENRE_ALPHA_COUNT) {
118                 int j = genre_alpha_map[i];
119                 handler(j, genre_names[j], cookie);
120             }
121         }
122     }
123 }
124
125 #define GENRE_NUM_UNKNOWN 255
126
127 void
128 id3tag_init(lame_global_flags *gfp)
129 {
130     lame_internal_flags *gfc = gfp->internal_flags;
131     memset(&gfc->tag_spec, 0, sizeof gfc->tag_spec);
132     gfc->tag_spec.genre = GENRE_NUM_UNKNOWN;
133 }
134
135
136
137 void
138 id3tag_add_v2(lame_global_flags *gfp)
139 {
140     lame_internal_flags *gfc = gfp->internal_flags;
141     gfc->tag_spec.flags &= ~V1_ONLY_FLAG;
142     gfc->tag_spec.flags |= ADD_V2_FLAG;
143 }
144
145 void
146 id3tag_v1_only(lame_global_flags *gfp)
147 {
148     lame_internal_flags *gfc = gfp->internal_flags;
149     gfc->tag_spec.flags &= ~(ADD_V2_FLAG | V2_ONLY_FLAG);
150     gfc->tag_spec.flags |= V1_ONLY_FLAG;
151 }
152
153 void
154 id3tag_v2_only(lame_global_flags *gfp)
155 {
156     lame_internal_flags *gfc = gfp->internal_flags;
157     gfc->tag_spec.flags &= ~V1_ONLY_FLAG;
158     gfc->tag_spec.flags |= V2_ONLY_FLAG;
159 }
160
161 void
162 id3tag_space_v1(lame_global_flags *gfp)
163 {
164     lame_internal_flags *gfc = gfp->internal_flags;
165     gfc->tag_spec.flags &= ~V2_ONLY_FLAG;
166     gfc->tag_spec.flags |= SPACE_V1_FLAG;
167 }
168
169 void
170 id3tag_pad_v2(lame_global_flags *gfp)
171 {
172     lame_internal_flags *gfc = gfp->internal_flags;
173     gfc->tag_spec.flags &= ~V1_ONLY_FLAG;
174     gfc->tag_spec.flags |= PAD_V2_FLAG;
175 }
176
177 void
178 id3tag_set_title(lame_global_flags *gfp, const char *title)
179 {
180     lame_internal_flags *gfc = gfp->internal_flags;
181     if (title && *title) {
182         gfc->tag_spec.title = title;
183         gfc->tag_spec.flags |= CHANGED_FLAG;
184     }
185 }
186
187 void
188 id3tag_set_artist(lame_global_flags *gfp, const char *artist)
189 {
190     lame_internal_flags *gfc = gfp->internal_flags;
191     if (artist && *artist) {
192         gfc->tag_spec.artist = artist;
193         gfc->tag_spec.flags |= CHANGED_FLAG;
194     }
195 }
196
197 void
198 id3tag_set_album(lame_global_flags *gfp, const char *album)
199 {
200     lame_internal_flags *gfc = gfp->internal_flags;
201     if (album && *album) {
202         gfc->tag_spec.album = album;
203         gfc->tag_spec.flags |= CHANGED_FLAG;
204     }
205 }
206
207 void
208 id3tag_set_year(lame_global_flags *gfp, const char *year)
209 {
210     lame_internal_flags *gfc = gfp->internal_flags;
211     if (year && *year) {
212         int num = atoi(year);
213         if (num < 0) {
214             num = 0;
215         }
216         /* limit a year to 4 digits so it fits in a version 1 tag */
217         if (num > 9999) {
218             num = 9999;
219         }
220         if (num) {
221             gfc->tag_spec.year = num;
222             gfc->tag_spec.flags |= CHANGED_FLAG;
223         }
224     }
225 }
226
227 void
228 id3tag_set_comment(lame_global_flags *gfp, const char *comment)
229 {
230     lame_internal_flags *gfc = gfp->internal_flags;
231     if (comment && *comment) {
232         gfc->tag_spec.comment = comment;
233         gfc->tag_spec.flags |= CHANGED_FLAG;
234     }
235 }
236
237 void
238 id3tag_set_track(lame_global_flags *gfp, const char *track)
239 {
240     lame_internal_flags *gfc = gfp->internal_flags;
241     if (track && *track) {
242         int num = atoi(track);
243         if (num < 0) {
244             num = 0;
245         }
246         /* limit a track to 255 so it fits in a version 1 tag even though CD
247          * audio doesn't allow more than 99 tracks */
248         if (num > 255) {
249             num = 255;
250         }
251         if (num) {
252             gfc->tag_spec.track = num;
253             gfc->tag_spec.flags |= CHANGED_FLAG;
254         }
255     }
256 }
257
258 /* would use real "strcasecmp" but it isn't portable */
259 static int
260 local_strcasecmp(const char *s1, const char *s2)
261 {
262     unsigned char c1;
263     unsigned char c2;
264     do {
265         c1 = tolower(*s1);
266         c2 = tolower(*s2);
267         if (!c1) {
268             break;
269         }
270         ++s1;
271         ++s2;
272     } while (c1 == c2);
273     return c1 - c2;
274 }
275
276 int
277 id3tag_set_genre(lame_global_flags *gfp, const char *genre)
278 {
279     lame_internal_flags *gfc = gfp->internal_flags;
280     if (genre && *genre) {
281         char *str;
282         int num = strtol(genre, &str, 10);
283         /* is the input a string or a valid number? */
284         if (*str) {
285             int i;
286             for (i = 0; i < GENRE_NAME_COUNT; ++i) {
287                 if (!local_strcasecmp(genre, genre_names[i])) {
288                     num = i;
289                     break;
290                 }
291             }
292             if (i == GENRE_NAME_COUNT) {
293                 return -1;
294             }
295         } else if ((num < 0) || (num >= GENRE_NAME_COUNT)) {
296             return -1;
297         }
298         gfc->tag_spec.genre = num;
299         gfc->tag_spec.flags |= CHANGED_FLAG;
300     }
301     return 0;
302 }
303
304 static unsigned char *
305 set_4_byte_value(unsigned char *bytes, unsigned long value)
306 {
307     int index;
308     for (index = 3; index >= 0; --index) {
309         bytes[index] = value & 0xfful;
310         value >>= 8;
311     }
312     return bytes + 4;
313 }
314
315 #define FRAME_ID(a, b, c, d) \
316     ( ((unsigned long)(a) << 24) \
317     | ((unsigned long)(b) << 16) \
318     | ((unsigned long)(c) <<  8) \
319     | ((unsigned long)(d) <<  0) )
320 #define TITLE_FRAME_ID FRAME_ID('T', 'I', 'T', '2')
321 #define ARTIST_FRAME_ID FRAME_ID('T', 'P', 'E', '1')
322 #define ALBUM_FRAME_ID FRAME_ID('T', 'A', 'L', 'B')
323 #define YEAR_FRAME_ID FRAME_ID('T', 'Y', 'E', 'R')
324 #define COMMENT_FRAME_ID FRAME_ID('C', 'O', 'M', 'M')
325 #define TRACK_FRAME_ID FRAME_ID('T', 'R', 'C', 'K')
326 #define GENRE_FRAME_ID FRAME_ID('T', 'C', 'O', 'N')
327
328 static unsigned char *
329 set_frame(unsigned char *frame, unsigned long id, const char *text,
330     size_t length)
331 {
332     if (length) {
333         frame = set_4_byte_value(frame, id);
334         /* Set frame size = total size - header size.  Frame header and field
335          * bytes include 2-byte header flags, 1 encoding descriptor byte, and
336          * for comment frames: 3-byte language descriptor and 1 content
337          * descriptor byte */
338         frame = set_4_byte_value(frame, ((id == COMMENT_FRAME_ID) ? 5 : 1)
339                 + length);
340         /* clear 2-byte header flags */
341         *frame++ = 0;
342         *frame++ = 0;
343         /* clear 1 encoding descriptor byte to indicate ISO-8859-1 format */
344         *frame++ = 0;
345         if (id == COMMENT_FRAME_ID) {
346             /* use id3lib-compatible bogus language descriptor */
347             *frame++ = 'X';
348             *frame++ = 'X';
349             *frame++ = 'X';
350             /* clear 1 byte to make content descriptor empty string */
351             *frame++ = 0;
352         }
353         while (length--) {
354             *frame++ = *text++;
355         }
356     }
357     return frame;
358 }
359
360 int
361 id3tag_write_v2(lame_global_flags *gfp)
362 {
363     lame_internal_flags *gfc = gfp->internal_flags;
364     if ((gfc->tag_spec.flags & CHANGED_FLAG)
365             && !(gfc->tag_spec.flags & V1_ONLY_FLAG)) {
366         /* calculate length of four fields which may not fit in verion 1 tag */
367         size_t title_length = gfc->tag_spec.title
368             ? strlen(gfc->tag_spec.title) : 0;
369         size_t artist_length = gfc->tag_spec.artist
370             ? strlen(gfc->tag_spec.artist) : 0;
371         size_t album_length = gfc->tag_spec.album
372             ? strlen(gfc->tag_spec.album) : 0;
373         size_t comment_length = gfc->tag_spec.comment
374             ? strlen(gfc->tag_spec.comment) : 0;
375         /* write tag if explicitly requested or if fields overflow */
376         if ((gfc->tag_spec.flags & (ADD_V2_FLAG | V2_ONLY_FLAG))
377                 || (title_length > 30)
378                 || (artist_length > 30) || (album_length > 30)
379                 || (comment_length > 30)
380                 || (gfc->tag_spec.track && (comment_length > 28))) {
381             size_t tag_size;
382             char year[5];
383             size_t year_length;
384             char track[3];
385             size_t track_length;
386             char genre[6];
387             size_t genre_length;
388             unsigned char *tag;
389             unsigned char *p;
390             size_t adjusted_tag_size;
391             unsigned int index;
392             /* calulate size of tag starting with 10-byte tag header */
393             tag_size = 10;
394             if (title_length) {
395                 /* add 10-byte frame header, 1 encoding descriptor byte ... */
396                 tag_size += 11 + title_length;
397             }
398             if (artist_length) {
399                 tag_size += 11 + artist_length;
400             }
401             if (album_length) {
402                 tag_size += 11 + album_length;
403             }
404             if (gfc->tag_spec.year) {
405                 year_length = sprintf(year, "%d", gfc->tag_spec.year);
406                 tag_size += 11 + year_length;
407             } else {
408                 year_length = 0;
409             }
410             if (comment_length) {
411                 /* add 10-byte frame header, 1 encoding descriptor byte,
412                  * 3-byte language descriptor, 1 content descriptor byte ... */
413                 tag_size += 15 + comment_length;
414             }
415             if (gfc->tag_spec.track) {
416                 track_length = sprintf(track, "%d", gfc->tag_spec.track);
417                 tag_size += 11 + track_length;
418             } else {
419                 track_length = 0;
420             }
421             if (gfc->tag_spec.genre != GENRE_NUM_UNKNOWN) {
422                 genre_length = sprintf(genre, "(%d)", gfc->tag_spec.genre);
423                 tag_size += 11 + genre_length;
424             } else {
425                 genre_length = 0;
426             }
427             if (gfc->tag_spec.flags & PAD_V2_FLAG) {
428                 /* add 128 bytes of padding */
429                 tag_size += 128;
430             }
431             tag = (unsigned char *)malloc(tag_size);
432             if (!tag) {
433                 return -1;
434             }
435             p = tag;
436             /* set tag header starting with file identifier */
437             *p++ = 'I'; *p++ = 'D'; *p++ = '3';
438             /* set version number word */
439             *p++ = 3; *p++ = 0;
440             /* clear flags byte */
441             *p++ = 0;
442             /* calculate and set tag size = total size - header size */
443             adjusted_tag_size = tag_size - 10;
444             /* encode adjusted size into four bytes where most significant 
445              * bit is clear in each byte, for 28-bit total */
446             *p++ = (adjusted_tag_size >> 21) & 0x7fu;
447             *p++ = (adjusted_tag_size >> 14) & 0x7fu;
448             *p++ = (adjusted_tag_size >> 7) & 0x7fu;
449             *p++ = adjusted_tag_size & 0x7fu;
450
451             /*
452              * NOTE: The remainder of the tag (frames and padding, if any)
453              * are not "unsynchronized" to prevent false MPEG audio headers
454              * from appearing in the bitstream.  Why?  Well, most players
455              * and utilities know how to skip the ID3 version 2 tag by now
456              * even if they don't read its contents, and it's actually
457              * very unlikely that such a false "sync" pattern would occur
458              * in just the simple text frames added here.
459              */
460
461             /* set each frame in tag */
462             p = set_frame(p, TITLE_FRAME_ID, gfc->tag_spec.title, title_length);
463             p = set_frame(p, ARTIST_FRAME_ID, gfc->tag_spec.artist,
464                     artist_length);
465             p = set_frame(p, ALBUM_FRAME_ID, gfc->tag_spec.album, album_length);
466             p = set_frame(p, YEAR_FRAME_ID, year, year_length);
467             p = set_frame(p, COMMENT_FRAME_ID, gfc->tag_spec.comment,
468                     comment_length);
469             p = set_frame(p, TRACK_FRAME_ID, track, track_length);
470             p = set_frame(p, GENRE_FRAME_ID, genre, genre_length);
471             /* clear any padding bytes */
472             memset(p, 0, tag_size - (p - tag));
473             /* write tag directly into bitstream at current position */
474             for (index = 0; index < tag_size; ++index) {
475                 add_dummy_byte(gfp, tag[index]);
476             }
477             free(tag);
478             return tag_size;
479         }
480     }
481     return 0;
482 }
483
484 static unsigned char *
485 set_text_field(unsigned char *field, const char *text, size_t size, int pad)
486 {
487     while (size--) {
488         if (text && *text) {
489             *field++ = *text++;
490         } else {
491             *field++ = pad;
492         }
493     }
494     return field;
495 }
496
497 int
498 id3tag_write_v1(lame_global_flags *gfp)
499 {
500     lame_internal_flags *gfc = gfp->internal_flags;
501     if ((gfc->tag_spec.flags & CHANGED_FLAG)
502             && !(gfc->tag_spec.flags & V2_ONLY_FLAG)) {
503         unsigned char tag[128];
504         unsigned char *p = tag;
505         int pad = (gfc->tag_spec.flags & SPACE_V1_FLAG) ? ' ' : 0;
506         char year[5];
507         unsigned int index;
508         /* set tag identifier */
509         *p++ = 'T'; *p++ = 'A'; *p++ = 'G';
510         /* set each field in tag */
511         p = set_text_field(p, gfc->tag_spec.title, 30, pad);
512         p = set_text_field(p, gfc->tag_spec.artist, 30, pad);
513         p = set_text_field(p, gfc->tag_spec.album, 30, pad);
514         sprintf(year, "%d", gfc->tag_spec.year);
515         p = set_text_field(p, gfc->tag_spec.year ? year : NULL, 4, pad);
516         /* limit comment field to 28 bytes if a track is specified */
517         p = set_text_field(p, gfc->tag_spec.comment, gfc->tag_spec.track
518                 ? 28 : 30, pad);
519         if (gfc->tag_spec.track) {
520             /* clear the next byte to indicate a version 1.1 tag */
521             *p++ = 0;
522             *p++ = gfc->tag_spec.track;
523         }
524         *p++ = gfc->tag_spec.genre;
525         /* write tag directly into bitstream at current position */
526         for (index = 0; index < 128; ++index) {
527             add_dummy_byte(gfp, tag[index]);
528         }
529         return 128;
530     }
531     return 0;
532 }