fix crashes reported by Debian Cylab Mayhem Team
[swftools.git] / lib / lame / id3tag.c
blob2327f52f63440f7bea7cdb4b6f032607929c1b53
1 /*
2 * id3tag.c -- Write ID3 version 1 and 2 tags.
4 * Copyright (C) 2000 Don Melton.
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.
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.
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.
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.
28 * NOTE: See http://id3.org/ for more information about ID3 tag formats.
31 /* $Id: id3tag.c,v 1.2 2006/02/09 16:56:23 kramm Exp $ */
33 #include <stdlib.h>
34 #include "config_static.h"
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
52 #include "lame.h"
53 #include "id3tag.h"
54 #include "util.h"
55 #include "bitstream.h"
57 #ifdef WITH_DMALLOC
58 #include <dmalloc.h>
59 #endif
61 static const char *const genre_names[] =
64 * NOTE: The spelling of these genre names is identical to those found in
65 * Winamp and mp3info.
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"
95 #define GENRE_NAME_COUNT \
96 ((int)(sizeof genre_names / sizeof (const char *const)))
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
110 #define GENRE_ALPHA_COUNT ((int)(sizeof genre_alpha_map / sizeof (int)))
112 void
113 id3tag_genre_list(void (*handler)(int, const char *, void *), void *cookie)
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);
126 #define GENRE_NUM_UNKNOWN 255
128 void
129 id3tag_init(lame_global_flags *gfp)
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;
138 void
139 id3tag_add_v2(lame_global_flags *gfp)
141 lame_internal_flags *gfc = gfp->internal_flags;
142 gfc->tag_spec.flags &= ~V1_ONLY_FLAG;
143 gfc->tag_spec.flags |= ADD_V2_FLAG;
146 void
147 id3tag_v1_only(lame_global_flags *gfp)
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;
154 void
155 id3tag_v2_only(lame_global_flags *gfp)
157 lame_internal_flags *gfc = gfp->internal_flags;
158 gfc->tag_spec.flags &= ~V1_ONLY_FLAG;
159 gfc->tag_spec.flags |= V2_ONLY_FLAG;
162 void
163 id3tag_space_v1(lame_global_flags *gfp)
165 lame_internal_flags *gfc = gfp->internal_flags;
166 gfc->tag_spec.flags &= ~V2_ONLY_FLAG;
167 gfc->tag_spec.flags |= SPACE_V1_FLAG;
170 void
171 id3tag_pad_v2(lame_global_flags *gfp)
173 lame_internal_flags *gfc = gfp->internal_flags;
174 gfc->tag_spec.flags &= ~V1_ONLY_FLAG;
175 gfc->tag_spec.flags |= PAD_V2_FLAG;
178 void
179 id3tag_set_title(lame_global_flags *gfp, const char *title)
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;
188 void
189 id3tag_set_artist(lame_global_flags *gfp, const char *artist)
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;
198 void
199 id3tag_set_album(lame_global_flags *gfp, const char *album)
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;
208 void
209 id3tag_set_year(lame_global_flags *gfp, const char *year)
211 lame_internal_flags *gfc = gfp->internal_flags;
212 if (year && *year) {
213 int num = atoi(year);
214 if (num < 0) {
215 num = 0;
217 /* limit a year to 4 digits so it fits in a version 1 tag */
218 if (num > 9999) {
219 num = 9999;
221 if (num) {
222 gfc->tag_spec.year = num;
223 gfc->tag_spec.flags |= CHANGED_FLAG;
228 void
229 id3tag_set_comment(lame_global_flags *gfp, const char *comment)
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;
238 void
239 id3tag_set_track(lame_global_flags *gfp, const char *track)
241 lame_internal_flags *gfc = gfp->internal_flags;
242 if (track && *track) {
243 int num = atoi(track);
244 if (num < 0) {
245 num = 0;
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;
252 if (num) {
253 gfc->tag_spec.track = num;
254 gfc->tag_spec.flags |= CHANGED_FLAG;
259 /* would use real "strcasecmp" but it isn't portable */
260 static int
261 local_strcasecmp(const char *s1, const char *s2)
263 unsigned char c1;
264 unsigned char c2;
265 do {
266 c1 = tolower(*s1);
267 c2 = tolower(*s2);
268 if (!c1) {
269 break;
271 ++s1;
272 ++s2;
273 } while (c1 == c2);
274 return c1 - c2;
278 id3tag_set_genre(lame_global_flags *gfp, const char *genre)
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;
293 if (i == GENRE_NAME_COUNT) {
294 return -1;
296 } else if ((num < 0) || (num >= GENRE_NAME_COUNT)) {
297 return -1;
299 gfc->tag_spec.genre = num;
300 gfc->tag_spec.flags |= CHANGED_FLAG;
302 return 0;
305 static unsigned char *
306 set_4_byte_value(unsigned char *bytes, unsigned long value)
308 int index;
309 for (index = 3; index >= 0; --index) {
310 bytes[index] = value & 0xfful;
311 value >>= 8;
313 return bytes + 4;
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')
329 static unsigned char *
330 set_frame(unsigned char *frame, unsigned long id, const char *text,
331 size_t length)
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;
354 while (length--) {
355 *frame++ = *text++;
358 return frame;
362 id3tag_write_v2(lame_global_flags *gfp)
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;
399 if (artist_length) {
400 tag_size += 11 + artist_length;
402 if (album_length) {
403 tag_size += 11 + album_length;
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;
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;
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;
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;
428 if (gfc->tag_spec.flags & PAD_V2_FLAG) {
429 /* add 128 bytes of padding */
430 tag_size += 128;
432 tag = (unsigned char *)malloc(tag_size);
433 if (!tag) {
434 return -1;
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;
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.
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]);
478 free(tag);
479 return tag_size;
482 return 0;
485 static unsigned char *
486 set_text_field(unsigned char *field, const char *text, size_t size, int pad)
488 while (size--) {
489 if (text && *text) {
490 *field++ = *text++;
491 } else {
492 *field++ = pad;
495 return field;
499 id3tag_write_v1(lame_global_flags *gfp)
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;
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]);
530 return 128;
532 return 0;