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.1 2002/04/28 17:30:19 kramm Exp $ */
33 #include "config_static.h"
42 # define strrchr rindex
44 char *strchr (), *strrchr ();
46 # define memcpy(d, s, n) bcopy ((s), (d), (n))
47 # define memmove(d, s, n) bcopy ((s), (d), (n))
54 #include "bitstream.h"
60 static const char *const genre_names[] =
63 * NOTE: The spelling of these genre names is identical to those found in
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",
94 #define GENRE_NAME_COUNT \
95 ((int)(sizeof genre_names / sizeof (const char *const)))
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
109 #define GENRE_ALPHA_COUNT ((int)(sizeof genre_alpha_map / sizeof (int)))
112 id3tag_genre_list(void (*handler)(int, const char *, void *), void *cookie)
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);
125 #define GENRE_NUM_UNKNOWN 255
128 id3tag_init(lame_global_flags *gfp)
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;
138 id3tag_add_v2(lame_global_flags *gfp)
140 lame_internal_flags *gfc = gfp->internal_flags;
141 gfc->tag_spec.flags &= ~V1_ONLY_FLAG;
142 gfc->tag_spec.flags |= ADD_V2_FLAG;
146 id3tag_v1_only(lame_global_flags *gfp)
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;
154 id3tag_v2_only(lame_global_flags *gfp)
156 lame_internal_flags *gfc = gfp->internal_flags;
157 gfc->tag_spec.flags &= ~V1_ONLY_FLAG;
158 gfc->tag_spec.flags |= V2_ONLY_FLAG;
162 id3tag_space_v1(lame_global_flags *gfp)
164 lame_internal_flags *gfc = gfp->internal_flags;
165 gfc->tag_spec.flags &= ~V2_ONLY_FLAG;
166 gfc->tag_spec.flags |= SPACE_V1_FLAG;
170 id3tag_pad_v2(lame_global_flags *gfp)
172 lame_internal_flags *gfc = gfp->internal_flags;
173 gfc->tag_spec.flags &= ~V1_ONLY_FLAG;
174 gfc->tag_spec.flags |= PAD_V2_FLAG;
178 id3tag_set_title(lame_global_flags *gfp, const char *title)
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;
188 id3tag_set_artist(lame_global_flags *gfp, const char *artist)
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;
198 id3tag_set_album(lame_global_flags *gfp, const char *album)
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;
208 id3tag_set_year(lame_global_flags *gfp, const char *year)
210 lame_internal_flags *gfc = gfp->internal_flags;
212 int num = atoi(year);
216 /* limit a year to 4 digits so it fits in a version 1 tag */
221 gfc->tag_spec.year = num;
222 gfc->tag_spec.flags |= CHANGED_FLAG;
228 id3tag_set_comment(lame_global_flags *gfp, const char *comment)
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;
238 id3tag_set_track(lame_global_flags *gfp, const char *track)
240 lame_internal_flags *gfc = gfp->internal_flags;
241 if (track && *track) {
242 int num = atoi(track);
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 */
252 gfc->tag_spec.track = num;
253 gfc->tag_spec.flags |= CHANGED_FLAG;
258 /* would use real "strcasecmp" but it isn't portable */
260 local_strcasecmp(const char *s1, const char *s2)
277 id3tag_set_genre(lame_global_flags *gfp, const char *genre)
279 lame_internal_flags *gfc = gfp->internal_flags;
280 if (genre && *genre) {
282 int num = strtol(genre, &str, 10);
283 /* is the input a string or a valid number? */
286 for (i = 0; i < GENRE_NAME_COUNT; ++i) {
287 if (!local_strcasecmp(genre, genre_names[i])) {
292 if (i == GENRE_NAME_COUNT) {
295 } else if ((num < 0) || (num >= GENRE_NAME_COUNT)) {
298 gfc->tag_spec.genre = num;
299 gfc->tag_spec.flags |= CHANGED_FLAG;
304 static unsigned char *
305 set_4_byte_value(unsigned char *bytes, unsigned long value)
308 for (index = 3; index >= 0; --index) {
309 bytes[index] = value & 0xfful;
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')
328 static unsigned char *
329 set_frame(unsigned char *frame, unsigned long id, const char *text,
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
338 frame = set_4_byte_value(frame, ((id == COMMENT_FRAME_ID) ? 5 : 1)
340 /* clear 2-byte header flags */
343 /* clear 1 encoding descriptor byte to indicate ISO-8859-1 format */
345 if (id == COMMENT_FRAME_ID) {
346 /* use id3lib-compatible bogus language descriptor */
350 /* clear 1 byte to make content descriptor empty string */
361 id3tag_write_v2(lame_global_flags *gfp)
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))) {
390 size_t adjusted_tag_size;
392 /* calulate size of tag starting with 10-byte tag header */
395 /* add 10-byte frame header, 1 encoding descriptor byte ... */
396 tag_size += 11 + title_length;
399 tag_size += 11 + artist_length;
402 tag_size += 11 + album_length;
404 if (gfc->tag_spec.year) {
405 year_length = sprintf(year, "%d", gfc->tag_spec.year);
406 tag_size += 11 + year_length;
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;
415 if (gfc->tag_spec.track) {
416 track_length = sprintf(track, "%d", gfc->tag_spec.track);
417 tag_size += 11 + track_length;
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;
427 if (gfc->tag_spec.flags & PAD_V2_FLAG) {
428 /* add 128 bytes of padding */
431 tag = (unsigned char *)malloc(tag_size);
436 /* set tag header starting with file identifier */
437 *p++ = 'I'; *p++ = 'D'; *p++ = '3';
438 /* set version number word */
440 /* clear flags byte */
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;
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.
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,
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,
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]);
484 static unsigned char *
485 set_text_field(unsigned char *field, const char *text, size_t size, int pad)
498 id3tag_write_v1(lame_global_flags *gfp)
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;
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
519 if (gfc->tag_spec.track) {
520 /* clear the next byte to indicate a version 1.1 tag */
522 *p++ = gfc->tag_spec.track;
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]);