00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #ifdef HAVE_CONFIG_H
00034 #include <config.h>
00035 #endif
00036
00037 #ifdef STDC_HEADERS
00038 # include <stddef.h>
00039 # include <stdlib.h>
00040 # include <string.h>
00041 #else
00042 # ifndef HAVE_STRCHR
00043 # define strchr index
00044 # define strrchr rindex
00045 # endif
00046 char *strchr(), *strrchr();
00047 # ifndef HAVE_MEMCPY
00048 # define memcpy(d, s, n) bcopy ((s), (d), (n))
00049 # define memmove(d, s, n) bcopy ((s), (d), (n))
00050 # endif
00051 #endif
00052
00053
00054 #ifdef _MSC_VER
00055 #define snprintf _snprintf
00056 #endif
00057
00058
00059 #include "lame.h"
00060 #include "machine.h"
00061 #include "encoder.h"
00062 #include "id3tag.h"
00063 #include "lame_global_flags.h"
00064 #include "util.h"
00065 #include "bitstream.h"
00066
00067
00068 static const char *const genre_names[] = {
00069
00070
00071
00072
00073 "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge",
00074 "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies", "Other", "Pop", "R&B",
00075 "Rap", "Reggae", "Rock", "Techno", "Industrial", "Alternative", "Ska",
00076 "Death Metal", "Pranks", "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop",
00077 "Vocal", "Jazz+Funk", "Fusion", "Trance", "Classical", "Instrumental",
00078 "Acid", "House", "Game", "Sound Clip", "Gospel", "Noise", "Alternative Rock",
00079 "Bass", "Soul", "Punk", "Space", "Meditative", "Instrumental Pop",
00080 "Instrumental Rock", "Ethnic", "Gothic", "Darkwave", "Techno-Industrial",
00081 "Electronic", "Pop-Folk", "Eurodance", "Dream", "Southern Rock", "Comedy",
00082 "Cult", "Gangsta", "Top 40", "Christian Rap", "Pop/Funk", "Jungle",
00083 "Native US", "Cabaret", "New Wave", "Psychedelic", "Rave",
00084 "Showtunes", "Trailer", "Lo-Fi", "Tribal", "Acid Punk", "Acid Jazz",
00085 "Polka", "Retro", "Musical", "Rock & Roll", "Hard Rock", "Folk",
00086 "Folk-Rock", "National Folk", "Swing", "Fast Fusion", "Bebob", "Latin",
00087 "Revival", "Celtic", "Bluegrass", "Avantgarde", "Gothic Rock",
00088 "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", "Slow Rock",
00089 "Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech",
00090 "Chanson", "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass",
00091 "Primus", "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba",
00092 "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle", "Duet",
00093 "Punk Rock", "Drum Solo", "Acappella", "Euro-House", "Dance Hall",
00094 "Goa", "Drum & Bass", "Club-House", "Hardcore", "Terror", "Indie",
00095 "BritPop", "Negerpunk", "Polsk Punk", "Beat", "Christian Gangsta",
00096 "Heavy Metal", "Black Metal", "Crossover", "Contemporary Christian",
00097 "Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime", "JPop",
00098 "SynthPop"
00099 };
00100
00101 #define GENRE_NAME_COUNT \
00102 ((int)(sizeof genre_names / sizeof (const char *const)))
00103
00104 static const int genre_alpha_map[] = {
00105 123, 34, 74, 73, 99, 20, 40, 26, 145, 90, 116, 41, 135, 85, 96, 138, 89, 0,
00106 107, 132, 65, 88, 104, 102, 97, 136, 61, 141, 32, 1, 112, 128, 57, 140, 2,
00107 139, 58, 3, 125, 50, 22, 4, 55, 127, 122, 120, 98, 52, 48, 54, 124, 25, 84,
00108 80, 115, 81, 119, 5, 30, 36, 59, 126, 38, 49, 91, 6, 129, 79, 137, 7, 35,
00109 100, 131, 19, 33, 46, 47, 8, 29, 146, 63, 86, 71, 45, 142, 9, 77, 82, 64,
00110 133, 10, 66, 39, 11, 103, 12, 75, 134, 13, 53, 62, 109, 117, 23, 108, 92,
00111 67, 93, 43, 121, 15, 68, 14, 16, 76, 87, 118, 17, 78, 143, 114, 110, 69, 21,
00112 111, 95, 105, 42, 37, 24, 56, 44, 101, 83, 94, 106, 147, 113, 18, 51, 130,
00113 144, 60, 70, 31, 72, 27, 28
00114 };
00115
00116 #define GENRE_ALPHA_COUNT ((int)(sizeof genre_alpha_map / sizeof (int)))
00117
00118 #define GENRE_INDEX_OTHER 12
00119
00120 void
00121 id3tag_genre_list(void (*handler) (int, const char *, void *), void *cookie)
00122 {
00123 if (handler) {
00124 int i;
00125 for (i = 0; i < GENRE_NAME_COUNT; ++i) {
00126 if (i < GENRE_ALPHA_COUNT) {
00127 int j = genre_alpha_map[i];
00128 handler(j, genre_names[j], cookie);
00129 }
00130 }
00131 }
00132 }
00133
00134 #define GENRE_NUM_UNKNOWN 255
00135
00136 void
00137 id3tag_init(lame_global_flags * gfp)
00138 {
00139 lame_internal_flags *gfc = gfp->internal_flags;
00140 free_id3tag(gfc);
00141 memset(&gfc->tag_spec, 0, sizeof gfc->tag_spec);
00142 gfc->tag_spec.genre_id3v1 = GENRE_NUM_UNKNOWN;
00143 }
00144
00145
00146
00147 void
00148 id3tag_add_v2(lame_global_flags * gfp)
00149 {
00150 lame_internal_flags *gfc = gfp->internal_flags;
00151 gfc->tag_spec.flags &= ~V1_ONLY_FLAG;
00152 gfc->tag_spec.flags |= ADD_V2_FLAG;
00153 }
00154
00155 void
00156 id3tag_v1_only(lame_global_flags * gfp)
00157 {
00158 lame_internal_flags *gfc = gfp->internal_flags;
00159 gfc->tag_spec.flags &= ~(ADD_V2_FLAG | V2_ONLY_FLAG);
00160 gfc->tag_spec.flags |= V1_ONLY_FLAG;
00161 }
00162
00163 void
00164 id3tag_v2_only(lame_global_flags * gfp)
00165 {
00166 lame_internal_flags *gfc = gfp->internal_flags;
00167 gfc->tag_spec.flags &= ~V1_ONLY_FLAG;
00168 gfc->tag_spec.flags |= V2_ONLY_FLAG;
00169 }
00170
00171 void
00172 id3tag_space_v1(lame_global_flags * gfp)
00173 {
00174 lame_internal_flags *gfc = gfp->internal_flags;
00175 gfc->tag_spec.flags &= ~V2_ONLY_FLAG;
00176 gfc->tag_spec.flags |= SPACE_V1_FLAG;
00177 }
00178
00179 void
00180 id3tag_pad_v2(lame_global_flags * gfp)
00181 {
00182 lame_internal_flags *gfc = gfp->internal_flags;
00183 gfc->tag_spec.flags &= ~V1_ONLY_FLAG;
00184 gfc->tag_spec.flags |= PAD_V2_FLAG;
00185 }
00186
00187
00188 static void
00189 local_strdup( char** dst, const char* src )
00190 {
00191 if (dst == 0) {
00192 return;
00193 }
00194 if (src == 0) {
00195 return;
00196 }
00197 if (*dst != 0) {
00198 free(*dst);
00199 }
00200 *dst = strdup(src);
00201 }
00202
00203
00204 void
00205 id3tag_set_title(lame_global_flags * gfp, const char *title)
00206 {
00207 lame_internal_flags *gfc = gfp->internal_flags;
00208 if (title && *title) {
00209 local_strdup(&gfc->tag_spec.title, title);
00210 gfc->tag_spec.flags |= CHANGED_FLAG;
00211 }
00212 }
00213
00214 void
00215 id3tag_set_artist(lame_global_flags * gfp, const char *artist)
00216 {
00217 lame_internal_flags *gfc = gfp->internal_flags;
00218 if (artist && *artist) {
00219 local_strdup(&gfc->tag_spec.artist, artist);
00220 gfc->tag_spec.flags |= CHANGED_FLAG;
00221 }
00222 }
00223
00224 void
00225 id3tag_set_album(lame_global_flags * gfp, const char *album)
00226 {
00227 lame_internal_flags *gfc = gfp->internal_flags;
00228 if (album && *album) {
00229 local_strdup(&gfc->tag_spec.album, album);
00230 gfc->tag_spec.flags |= CHANGED_FLAG;
00231 }
00232 }
00233
00234 void
00235 id3tag_set_year(lame_global_flags * gfp, const char *year)
00236 {
00237 lame_internal_flags *gfc = gfp->internal_flags;
00238 if (year && *year) {
00239 int num = atoi(year);
00240 if (num < 0) {
00241 num = 0;
00242 }
00243
00244 if (num > 9999) {
00245 num = 9999;
00246 }
00247 if (num) {
00248 gfc->tag_spec.year = num;
00249 gfc->tag_spec.flags |= CHANGED_FLAG;
00250 }
00251 }
00252 }
00253
00254 void
00255 id3tag_set_comment(lame_global_flags * gfp, const char *comment)
00256 {
00257 lame_internal_flags *gfc = gfp->internal_flags;
00258 if (comment && *comment) {
00259 local_strdup(&gfc->tag_spec.comment, comment);
00260 gfc->tag_spec.flags |= CHANGED_FLAG;
00261 }
00262 }
00263
00264 int
00265 id3tag_set_track(lame_global_flags * gfp, const char *track)
00266 {
00267 char *trackcount;
00268 lame_internal_flags *gfc = gfp->internal_flags;
00269 int ret = 0;
00270
00271 if (track && *track) {
00272 int num = atoi(track);
00273
00274 if (num < 1 || num > 255) {
00275 num = 0;
00276 ret = -1;
00277 gfc->tag_spec.flags |= (CHANGED_FLAG | ADD_V2_FLAG);
00278 }
00279 if (num) {
00280 gfc->tag_spec.track_id3v1 = num;
00281 gfc->tag_spec.flags |= CHANGED_FLAG;
00282 }
00283 local_strdup(&gfc->tag_spec.track_id3v2, track);
00284
00285
00286 trackcount = strchr(track, '/');
00287 if (trackcount && *trackcount) {
00288 gfc->tag_spec.flags |= (CHANGED_FLAG | ADD_V2_FLAG);
00289 }
00290 }
00291 return ret;
00292 }
00293
00294
00295 static int
00296 local_strcasecmp(const char *s1, const char *s2)
00297 {
00298 unsigned char c1;
00299 unsigned char c2;
00300 do {
00301 c1 = tolower(*s1);
00302 c2 = tolower(*s2);
00303 if (!c1) {
00304 break;
00305 }
00306 ++s1;
00307 ++s2;
00308 } while (c1 == c2);
00309 return c1 - c2;
00310 }
00311
00312 int
00313 id3tag_set_genre(lame_global_flags * gfp, const char *genre)
00314 {
00315 lame_internal_flags *gfc = gfp->internal_flags;
00316 int ret = 0;
00317 if (genre && *genre) {
00318 char *str;
00319 int num = strtol(genre, &str, 10);
00320
00321 if (*str) {
00322 int i;
00323 for (i = 0; i < GENRE_NAME_COUNT; ++i) {
00324 if (!local_strcasecmp(genre, genre_names[i])) {
00325 num = i;
00326 break;
00327 }
00328 }
00329 if (i == GENRE_NAME_COUNT) {
00330 num = GENRE_INDEX_OTHER;
00331 ret = -2;
00332 }
00333 }
00334 else {
00335 if ((num < 0) || (num >= GENRE_NAME_COUNT)) {
00336 return -1;
00337 }
00338 genre = genre_names[num];
00339 }
00340 local_strdup(&gfc->tag_spec.genre_id3v2, genre);
00341 gfc->tag_spec.genre_id3v1 = num;
00342 gfc->tag_spec.flags |= CHANGED_FLAG;
00343 if (ret) {
00344 gfc->tag_spec.flags |= ADD_V2_FLAG;
00345 }
00346 }
00347 return ret;
00348 }
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362 int
00363 id3tag_set_fieldvalue(lame_global_flags * gfp, const char *fieldvalue)
00364 {
00365 lame_internal_flags *gfc = gfp->internal_flags;
00366 if (fieldvalue && *fieldvalue) {
00367 char **p = NULL;
00368 if (strlen(fieldvalue) < 5 || fieldvalue[4] != '=') {
00369 return -1;
00370 }
00371 p = (char **)realloc(gfc->tag_spec.values, sizeof(char*) * (gfc->tag_spec.num_values + 1));
00372 if (!p) {
00373 return -1;
00374 }
00375 gfc->tag_spec.values = (char**)p;
00376 gfc->tag_spec.values[gfc->tag_spec.num_values++] = strdup(fieldvalue);
00377 gfc->tag_spec.flags |= CHANGED_FLAG;
00378 }
00379 id3tag_add_v2(gfp);
00380 return 0;
00381 }
00382
00383 int
00384 id3tag_set_albumart(lame_global_flags* gfp, const char* image, unsigned long size)
00385 {
00386 int mimetype = 0;
00387 unsigned char *data = (unsigned char *)image;
00388 lame_internal_flags *gfc = gfp->internal_flags;
00389
00390
00391 if (LAME_MAXALBUMART < size) {
00392 return -1;
00393 }
00394
00395 if (2 < size && data[0] == 0xFF && data[1] == 0xD8) {
00396 mimetype = MIMETYPE_JPEG;
00397 } else if (4 < size && data[0] == 0x89 && strncmp((const char *)&data[1], "PNG", 3) == 0) {
00398 mimetype = MIMETYPE_PNG;
00399 } else if (4 < size && strncmp((const char *)data, "GIF8", 4) == 0) {
00400 mimetype = MIMETYPE_GIF;
00401 } else {
00402 return -1;
00403 }
00404 if (gfc->tag_spec.albumart != 0) {
00405 free(gfc->tag_spec.albumart);
00406 gfc->tag_spec.albumart = 0;
00407 gfc->tag_spec.albumart_size = 0;
00408 gfc->tag_spec.albumart_mimetype = MIMETYPE_NONE;
00409 }
00410 if (size < 1) {
00411 return 0;
00412 }
00413 gfc->tag_spec.albumart = malloc(size);
00414 if (gfc->tag_spec.albumart != 0) {
00415 memcpy(gfc->tag_spec.albumart, image, size);
00416 gfc->tag_spec.albumart_size = size;
00417 gfc->tag_spec.albumart_mimetype = mimetype;
00418 gfc->tag_spec.flags |= CHANGED_FLAG;
00419 id3tag_add_v2(gfp);
00420 }
00421 return 0;
00422 }
00423
00424 static unsigned char *
00425 set_4_byte_value(unsigned char *bytes, unsigned long value)
00426 {
00427 int index;
00428 for (index = 3; index >= 0; --index) {
00429 bytes[index] = value & 0xfful;
00430 value >>= 8;
00431 }
00432 return bytes + 4;
00433 }
00434
00435 #define FRAME_ID(a, b, c, d) \
00436 ( ((unsigned long)(a) << 24) \
00437 | ((unsigned long)(b) << 16) \
00438 | ((unsigned long)(c) << 8) \
00439 | ((unsigned long)(d) << 0) )
00440 #define TITLE_FRAME_ID FRAME_ID('T', 'I', 'T', '2')
00441 #define ARTIST_FRAME_ID FRAME_ID('T', 'P', 'E', '1')
00442 #define ALBUM_FRAME_ID FRAME_ID('T', 'A', 'L', 'B')
00443 #define YEAR_FRAME_ID FRAME_ID('T', 'Y', 'E', 'R')
00444 #define COMMENT_FRAME_ID FRAME_ID('C', 'O', 'M', 'M')
00445 #define TRACK_FRAME_ID FRAME_ID('T', 'R', 'C', 'K')
00446 #define GENRE_FRAME_ID FRAME_ID('T', 'C', 'O', 'N')
00447 #define ENCODER_FRAME_ID FRAME_ID('T', 'S', 'S', 'E')
00448 #define PLAYLENGTH_FRAME_ID FRAME_ID('T', 'L', 'E', 'N')
00449
00450 static unsigned char *
00451 set_frame(unsigned char *frame, unsigned long id, const char *text, size_t length)
00452 {
00453 if (length) {
00454 unsigned long frame_size = (unsigned long)length;
00455 frame_size += ((id == COMMENT_FRAME_ID) ? 5 : 1);
00456 frame = set_4_byte_value(frame, id);
00457
00458
00459
00460
00461 frame = set_4_byte_value(frame, frame_size);
00462
00463 *frame++ = 0;
00464 *frame++ = 0;
00465
00466 *frame++ = 0;
00467 if (id == COMMENT_FRAME_ID) {
00468
00469 *frame++ = 'X';
00470 *frame++ = 'X';
00471 *frame++ = 'X';
00472
00473 *frame++ = 0;
00474 }
00475 while (length--) {
00476 *frame++ = *text++;
00477 }
00478 }
00479 return frame;
00480 }
00481
00482 static unsigned char *
00483 set_frame_custom(unsigned char *frame, const char *fieldvalue)
00484 {
00485 if (fieldvalue && *fieldvalue) {
00486 const char *value = fieldvalue + 5;
00487 size_t length = strlen(value);
00488 *frame++ = *fieldvalue++;
00489 *frame++ = *fieldvalue++;
00490 *frame++ = *fieldvalue++;
00491 *frame++ = *fieldvalue++;
00492 frame = set_4_byte_value(frame, (unsigned long)(strlen(value) + 1));
00493
00494 *frame++ = 0;
00495 *frame++ = 0;
00496
00497 *frame++ = 0;
00498 while (length--) {
00499 *frame++ = *value++;
00500 }
00501 }
00502 return frame;
00503 }
00504
00505 static unsigned char *
00506 set_frame_apic(unsigned char *frame, const char *mimetype, const unsigned char *data, size_t size)
00507 {
00508
00509
00510
00511
00512
00513
00514
00515
00516 if (mimetype && data && size) {
00517 frame = set_4_byte_value(frame, FRAME_ID('A', 'P', 'I', 'C'));
00518 frame = set_4_byte_value(frame, (unsigned long)(4 + strlen(mimetype) + size));
00519
00520 *frame++ = 0;
00521 *frame++ = 0;
00522
00523 *frame++ = 0;
00524
00525 while (*mimetype) {
00526 *frame++ = *mimetype++;
00527 }
00528 *frame++ = 0;
00529
00530 *frame++ = 0;
00531
00532 *frame++ = 0;
00533
00534 while (size--) {
00535 *frame++ = *data++;
00536 }
00537 }
00538 return frame;
00539 }
00540
00541 int
00542 id3tag_write_v2(lame_global_flags * gfp)
00543 {
00544 lame_internal_flags *gfc = gfp->internal_flags;
00545 if ((gfc->tag_spec.flags & CHANGED_FLAG)
00546 && !(gfc->tag_spec.flags & V1_ONLY_FLAG)) {
00547
00548 size_t title_length = gfc->tag_spec.title ? strlen(gfc->tag_spec.title) : 0;
00549 size_t artist_length = gfc->tag_spec.artist ? strlen(gfc->tag_spec.artist) : 0;
00550 size_t album_length = gfc->tag_spec.album ? strlen(gfc->tag_spec.album) : 0;
00551 size_t comment_length = gfc->tag_spec.comment ? strlen(gfc->tag_spec.comment) : 0;
00552
00553 if ((gfc->tag_spec.flags & (ADD_V2_FLAG | V2_ONLY_FLAG))
00554 || (title_length > 30)
00555 || (artist_length > 30) || (album_length > 30)
00556 || (comment_length > 30)
00557 || (gfc->tag_spec.track_id3v1 && (comment_length > 28))) {
00558 size_t tag_size;
00559 char encoder[80];
00560 size_t encoder_length;
00561 unsigned long playlength_ms;
00562 char playlength[20];
00563 size_t playlength_length;
00564 char year[5];
00565 size_t year_length;
00566 size_t track_length;
00567 size_t genre_length = 0;
00568 unsigned char *tag;
00569 unsigned char *p;
00570 size_t adjusted_tag_size;
00571 unsigned int index;
00572 const char *albumart_mime = NULL;
00573 static const char *mime_jpeg = "image/jpeg";
00574 static const char *mime_png = "image/png";
00575 static const char *mime_gif = "image/gif";
00576
00577 {
00578 double const max_ulong = MAX_U_32_NUM;
00579 double ms = gfp->num_samples;
00580 ms *= 1000;
00581 ms /= gfp->in_samplerate;
00582 if (ms > max_ulong) {
00583 playlength_ms = max_ulong;
00584 }
00585 else if (ms < 0) {
00586 playlength_ms = 0;
00587 }
00588 else {
00589 playlength_ms = ms;
00590 }
00591 }
00592
00593 tag_size = 10;
00594 #if defined(__hpux) || defined(__svr4__) || defined(M_UNIX) || defined(_AIX)
00595 encoder_length = sprintf(encoder, "LAME v%s", get_lame_version());
00596 if (encoder_length + 1 > sizeof(encoder))
00597 abort();
00598 playlength_length = sprintf(playlength, "%lu", playlength_ms);
00599 if (playlength_length + 1 > sizeof(playlength))
00600 abort();
00601 #else
00602 #if defined(__sun__)
00603 (void) sprintf(encoder, "LAME v%s", get_lame_version());
00604 encoder_length = strlen(encoder);
00605 (void) sprintf(playlength, "%lu", playlength_ms);
00606 playlength_length = strlen(playlength);
00607 #else
00608 encoder_length = snprintf(encoder, sizeof(encoder),
00609 "LAME v%s", get_lame_version());
00610 playlength_length = snprintf(playlength, sizeof(playlength), "%lu", playlength_ms);
00611 #endif
00612 #endif
00613 tag_size += 11 + encoder_length;
00614 tag_size += 11 + playlength_length;
00615 if (title_length) {
00616
00617 tag_size += 11 + title_length;
00618 }
00619 if (artist_length) {
00620 tag_size += 11 + artist_length;
00621 }
00622 if (album_length) {
00623 tag_size += 11 + album_length;
00624 }
00625 if (gfc->tag_spec.year) {
00626 year_length = sprintf(year, "%d", gfc->tag_spec.year);
00627 if (year_length + 1 > sizeof(year))
00628 abort();
00629 tag_size += 11 + year_length;
00630 }
00631 else {
00632 year_length = 0;
00633 }
00634 if (comment_length) {
00635
00636
00637 tag_size += 15 + comment_length;
00638 }
00639 if (gfc->tag_spec.track_id3v2 != 0) {
00640 track_length = strlen(gfc->tag_spec.track_id3v2);
00641 tag_size += 11 + track_length;
00642 }
00643 else {
00644 track_length = 0;
00645 }
00646 if (gfc->tag_spec.genre_id3v2 != 0) {
00647 genre_length = strlen(gfc->tag_spec.genre_id3v2);
00648 tag_size += 11 + genre_length;
00649 }
00650 else {
00651 genre_length = 0;
00652 }
00653 for (index = 0;index < gfc->tag_spec.num_values;++index) {
00654 tag_size += 6 + strlen(gfc->tag_spec.values[index]);
00655 }
00656 if (gfc->tag_spec.albumart && gfc->tag_spec.albumart_size) {
00657 switch (gfc->tag_spec.albumart_mimetype) {
00658 case MIMETYPE_JPEG:
00659 albumart_mime = mime_jpeg;
00660 break;
00661 case MIMETYPE_PNG:
00662 albumart_mime = mime_png;
00663 break;
00664 case MIMETYPE_GIF:
00665 albumart_mime = mime_gif;
00666 break;
00667 }
00668 tag_size += 10 + 4 + strlen(albumart_mime) + gfc->tag_spec.albumart_size;
00669 }
00670 if (gfc->tag_spec.flags & PAD_V2_FLAG) {
00671
00672 tag_size += 128;
00673 }
00674 tag = (unsigned char *) malloc(tag_size);
00675 if (!tag) {
00676 return -1;
00677 }
00678 p = tag;
00679
00680 *p++ = 'I';
00681 *p++ = 'D';
00682 *p++ = '3';
00683
00684 *p++ = 3;
00685 *p++ = 0;
00686
00687 *p++ = 0;
00688
00689 adjusted_tag_size = tag_size - 10;
00690
00691
00692 *p++ = (unsigned char)((adjusted_tag_size >> 21) & 0x7fu);
00693 *p++ = (unsigned char)((adjusted_tag_size >> 14) & 0x7fu);
00694 *p++ = (unsigned char)((adjusted_tag_size >> 7) & 0x7fu);
00695 *p++ = (unsigned char)(adjusted_tag_size & 0x7fu);
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708 p = set_frame(p, ENCODER_FRAME_ID, encoder, encoder_length);
00709 p = set_frame(p, PLAYLENGTH_FRAME_ID, playlength, playlength_length);
00710 p = set_frame(p, TITLE_FRAME_ID, gfc->tag_spec.title, title_length);
00711 p = set_frame(p, ARTIST_FRAME_ID, gfc->tag_spec.artist, artist_length);
00712 p = set_frame(p, ALBUM_FRAME_ID, gfc->tag_spec.album, album_length);
00713 p = set_frame(p, YEAR_FRAME_ID, year, year_length);
00714 p = set_frame(p, COMMENT_FRAME_ID, gfc->tag_spec.comment, comment_length);
00715 p = set_frame(p, TRACK_FRAME_ID, gfc->tag_spec.track_id3v2, track_length);
00716 p = set_frame(p, GENRE_FRAME_ID, gfc->tag_spec.genre_id3v2, genre_length);
00717 p = set_frame_apic(p, albumart_mime, gfc->tag_spec.albumart, gfc->tag_spec.albumart_size);
00718 for (index = 0;index < gfc->tag_spec.num_values;++index) {
00719 p = set_frame_custom(p, gfc->tag_spec.values[index]);
00720 }
00721
00722 memset(p, 0, tag_size - (p - tag));
00723
00724 for (index = 0; index < tag_size; ++index) {
00725 add_dummy_byte(gfp, tag[index], 1);
00726 }
00727 free(tag);
00728 return (int)tag_size;
00729 }
00730 }
00731 return 0;
00732 }
00733
00734 static unsigned char *
00735 set_text_field(unsigned char *field, const char *text, size_t size, int pad)
00736 {
00737 while (size--) {
00738 if (text && *text) {
00739 *field++ = *text++;
00740 }
00741 else {
00742 *field++ = pad;
00743 }
00744 }
00745 return field;
00746 }
00747
00748 int
00749 id3tag_write_v1(lame_global_flags * gfp)
00750 {
00751 lame_internal_flags *gfc = gfp->internal_flags;
00752 if ((gfc->tag_spec.flags & CHANGED_FLAG)
00753 && !(gfc->tag_spec.flags & V2_ONLY_FLAG)) {
00754 unsigned char tag[128];
00755 unsigned char *p = tag;
00756 int pad = (gfc->tag_spec.flags & SPACE_V1_FLAG) ? ' ' : 0;
00757 char year[5];
00758 int year_length;
00759 unsigned int index;
00760
00761 *p++ = 'T';
00762 *p++ = 'A';
00763 *p++ = 'G';
00764
00765 p = set_text_field(p, gfc->tag_spec.title, 30, pad);
00766 p = set_text_field(p, gfc->tag_spec.artist, 30, pad);
00767 p = set_text_field(p, gfc->tag_spec.album, 30, pad);
00768 year_length = sprintf(year, "%d", gfc->tag_spec.year);
00769 if (year_length + 1 > sizeof(year))
00770 abort();
00771 p = set_text_field(p, gfc->tag_spec.year ? year : NULL, 4, pad);
00772
00773 p = set_text_field(p, gfc->tag_spec.comment, gfc->tag_spec.track_id3v1 ? 28 : 30, pad);
00774 if (gfc->tag_spec.track_id3v1) {
00775
00776 *p++ = 0;
00777 *p++ = gfc->tag_spec.track_id3v1;
00778 }
00779 *p++ = gfc->tag_spec.genre_id3v1;
00780
00781 for (index = 0; index < 128; ++index) {
00782 add_dummy_byte(gfp, tag[index], 1);
00783 }
00784 return 128;
00785 }
00786 return 0;
00787 }