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