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