1 /**
2 * Handling of Replay Gain information in ID3v2 tags.
3 *
4 * We store Replay Gain data in RVA2 frames inside the ID3v2.4 tag.
5 * Album and track gain are written as two separate frames.
6 * We use the RVA2 frame as follows:
7 *
8 * Identification string: either "track" or "album";
9 * Channel number: always 1 (master volume);
10 * Volume adjustment: recommended gain relative to 89 dB standard;
11 * Bits representing peak: always 16;
12 * Peak volume: max absolute sample value relative to full scale
13 *
14 * The meaning of the RVA2 peak volume field is not specified in ID3v2.4.
15 * We follow the interpretation of QuodLibet/mutagen: Peak volume is the
16 * maximum absolute sample value relative to full scale, before application
17 * of the volume adjustment, stored as an unsigned fixed point value with
18 * 1 integer bit and (peakbits-1) fractional bits.
19 *
20 * In addition to standard Replay Gain data, we also store mp3gain-specific
21 * fields in TXXX frames. The description string of such frames starts with
22 * "MP3GAIN_". These frames are only needed when mp3gain updates the encoded
23 * audio volume in MP3 stream (-r and -a command line options).
24 *
25 * We read tag data in ID3v2.2, ID3v2.3 or ID3v2.4 format, from either
26 * the beginning or the end of the file. Extended tag headers are ignored
27 * and removed; compressed frames are ignored but preserved. No workarounds
28 * are attempted for invalid ID3v2.4 tags.
29 *
30 * When writing/updating tag data, we always write a single ID3v2.4 tag
31 * at the beginning of the file, fully unsynchronized. If the original
32 * file had an ID3v2.2 or ID3v2.3 tag, it is upgraded to ID3v2.4. If the
33 * original file had only an appended tag, it is moved to the beginning of
34 * the file. If the original file contained multiple tags, we update only
35 * the first tag and ignore the rest (this is bad, but it's probably a
36 * rare case). If the original file had only an ID3v1 tag, it is copied
37 * to a new ID3v2 tag and the ID3v1 tag is left as it was.
38 *
39 * See: http://www.id3.org/id3v2.4.0-structure
40 * http://www.id3.org/id3v2.4.0-frames
41 */
42
43
44 #include <stdlib.h>
45 #include <stdio.h>
46 #include <stdarg.h>
47 #include <string.h>
48 #include "apetag.h"
49 #include "id3tag.h"
50 #include "mp3gain.h"
51
52
53 #ifdef WIN32
54 #define strcasecmp(x,y) _stricmp(x,y)
55 #endif
56
57 #define DBG(x)
58 /*#define DBG(x) (printf x)*/
59
60 #define TAGFL_UNSYNC (0x80)
61 #define TAGFL_EXTHDR (0x40)
62 #define TAGFL_EXPR (0x20)
63 #define TAGFL_FOOTER (0x10)
64 #define FRAMEFL_BAD (0x00f0)
65 #define FRAMEFL_TAGALTER (0x4000)
66 #define FRAMEFL_GROUP (0x0040)
67 #define FRAMEFL_COMPR (0x0008)
68 #define FRAMEFL_CRYPT (0x0004)
69 #define FRAMEFL_UNSYNC (0x0002)
70 #define FRAMEFL_DLEN (0x0001)
71 #define SYNCSAFE_INT_BAD (0xffffffff)
72
73
74 struct ID3v2TagStruct {
75 unsigned long offset; /* offset of tag in file */
76 unsigned long length; /* total length of ID3v2 tag, including header/footer */
77 unsigned int version; /* ID3v2 version */
78 unsigned int flags; /* tag flags */
79 struct ID3v2FrameStruct *frames; /* linked list of frames */
80 };
81
82 struct ID3v2FrameStruct {
83 struct ID3v2FrameStruct *next; /* pointer to next frame */
84 char frameid[4]; /* frame ID */
85 unsigned int flags; /* frame flags */
86 unsigned long len; /* length of frame, excluding header */
87 unsigned long hskip; /* length of flag parameters */
88 unsigned char *data; /* pointer to data, excluding header */
89 };
90
91 struct upgrade_id3v22_struct {
92 char id_v22[3];
93 char id_new[4];
94 };
95
96 static const struct upgrade_id3v22_struct upgrade_id3v22_table[] = {
97 { "BUF", "RBUF" }, { "CNT", "PCNT" },
98 { "COM", "COMM" }, { "CRA", "AENC" },
99 { "ETC", "ETCO" }, { "EQU", "EQUA" },
100 { "GEO", "GEOB" }, { "IPL", "IPLS" },
101 { "LNK", "LINK" }, { "MCI", "MCDI" },
102 { "MLL", "MLLT" }, { "PIC", "APIC" /* NOTE: incompatible format */ },
103 { "POP", "POPM" }, { "REV", "RVRB" },
104 { "RVA", "RVAD" }, { "SLT", "SYLT" },
105 { "STC", "SYTC" }, { "TAL", "TALB" },
106 { "TBP", "TBPM" }, { "TCM", "TCOM" },
107 { "TCO", "TCON" }, { "TCR", "TCOP" },
108 { "TDA", "TDAT" }, { "TDY", "TDLY" },
109 { "TEN", "TENC" }, { "TFT", "TFLT" },
110 { "TIM", "TIME" }, { "TKE", "TKEY" },
111 { "TLA", "TLAN" }, { "TLE", "TLEN" },
112 { "TMT", "TMED" }, { "TOA", "TOPE" },
113 { "TOF", "TOFN" }, { "TOL", "TOLY" },
114 { "TOR", "TORY" }, { "TOT", "TOAL" },
115 { "TP1", "TPE1" }, { "TP2", "TPE2" },
116 { "TP3", "TPE3" }, { "TP4", "TPE4" },
117 { "TPA", "TPOS" }, { "TPB", "TPUB" },
118 { "TRC", "TSRC" }, { "TRD", "TRDA" },
119 { "TRK", "TRCK" }, { "TSI", "TSIZ" },
120 { "TSS", "TSSE" }, { "TT1", "TIT1" },
121 { "TT2", "TIT2" }, { "TT3", "TIT3" },
122 { "TXT", "TEXT" }, { "TXX", "TXXX" },
123 { "TYE", "TYER" }, { "UFI", "UFID" },
124 { "ULT", "USLT" }, { "WAF", "WOAF" },
125 { "WAR", "WOAR" }, { "WAS", "WOAS" },
126 { "WCM", "WCOM" }, { "WCP", "WCOP" },
127 { "WPB", "WPUB" }, { "WXX", "WXXX" },
128 { "\0\0\0", "\0\0\0\0" } };
129
130
131 /**
132 * Decode a 4-byte unsigned integer.
133 */
id3_get_int32(const unsigned char * p)134 static __inline unsigned long id3_get_int32(const unsigned char *p)
135 {
136 return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
137 }
138
139
140 /**
141 * Decode a 4-byte unsigned synchsafe integer.
142 */
id3_get_syncsafe_int(const unsigned char * p)143 static __inline unsigned long id3_get_syncsafe_int(const unsigned char *p)
144 {
145 if ((p[0] | p[1] | p[2] | p[3]) & 0x80)
146 return SYNCSAFE_INT_BAD;
147 return (p[0] << 21) | (p[1] << 14) | (p[2] << 7) | p[3];
148 }
149
150
151 /**
152 * Write a 4-byte unsigned synchsafe integer.
153 */
id3_put_syncsafe_int(unsigned char * p,unsigned long i)154 static __inline void id3_put_syncsafe_int(unsigned char *p, unsigned long i)
155 {
156 p[0] = (i >> 21) & 0x7f;
157 p[1] = (i >> 14) & 0x7f;
158 p[2] = (i >> 7) & 0x7f;
159 p[3] = i & 0x7f;
160 }
161
162
163 /**
164 * Decode srclen bytes of unsynchronized data from src into dest.
165 * Return the number of bytes written into dest.
166 *
167 * The buffer pointed to by dest must be large enough to hold the decoded data.
168 * The decoded data will never be longer than the unsynchronized data.
169 * Decoding may be performed in-place by specifying dest equal to src.
170 *
171 * If dest == NULL, decoded data are not stored but the decoded length is
172 * still computed and returned.
173 */
id3_get_unsync_data(unsigned char * dest,const unsigned char * src,unsigned long srclen)174 static unsigned long id3_get_unsync_data(unsigned char *dest, const unsigned char *src, unsigned long srclen)
175 {
176 unsigned long k = 0, i;
177 for (i = 0; i < srclen; i++) {
178 if (dest)
179 dest[k] = src[i];
180 k++;
181 if (src[i] == 0xff && i + 1 < srclen && src[i+1] == 0x00)
182 i++;
183 }
184 return k;
185 }
186
187
188 /**
189 * Encode srclen bytes of data from src, writing the unsynchronized version
190 * into dest. Return the number of bytes written into dest.
191 *
192 * The buffer pointed to by dest must be large enough to hold the
193 * unsynchronized data.
194 *
195 * If dest == NULL, unsynchronized data are not stored but the unsynchronized
196 * length is still computed and returned.
197 *
198 * If the returned length is equal to srclen, unsynchronization is not
199 * needed for these data.
200 */
id3_put_unsync_data(unsigned char * dest,const unsigned char * src,unsigned long srclen)201 static unsigned long id3_put_unsync_data(unsigned char *dest, const unsigned char *src, unsigned long srclen)
202 {
203 unsigned long k = 0, i;
204 for (i = 0; i < srclen; i++) {
205 if (dest)
206 dest[k] = src[i];
207 k++;
208 if (src[i] == 0xff && (i + 1 == srclen || src[i+1] == 0x00 || (src[i+1] & 0xe0) == 0xe0)) {
209 if (dest)
210 dest[k] = 0x00;
211 k++;
212 }
213 }
214 return k;
215 }
216
217
218 /**
219 * Release memory associated with a chain of frame structures.
220 */
id3_release_frames(struct ID3v2FrameStruct * frame)221 static void id3_release_frames(struct ID3v2FrameStruct *frame)
222 {
223 struct ID3v2FrameStruct *tframe;
224 while (frame) {
225 tframe = frame;
226 frame = frame->next;
227 free(tframe->data);
228 free(tframe);
229 }
230 }
231
232
233 /**
234 * Construct an ID3v2 frame according to specified format and parameters.
235 *
236 * The format string contains one character per field in the frame:
237 * 's' stores a string without null-termination (expects const char *)
238 * 'b' stores a single byte (expects unsigned int)
239 * 'h' stores a 16-bit big-endian integer (expects unsigned int)
240 *
241 * Return a newly allocated ID3v2FrameStruct, or NULL if the format
242 * is invalid.
243 */
id3_make_frame(const char * frameid,const char * format,...)244 static struct ID3v2FrameStruct * id3_make_frame(const char *frameid, const char *format, ...)
245 {
246 va_list ap;
247 struct ID3v2FrameStruct *frame;
248 unsigned long j, k;
249 unsigned int i;
250 const char *p, *s;
251
252 va_start(ap, format);
253 k = 0;
254 for (p = format; *p; p++) {
255 switch (*p) {
256 case 's': /* string */
257 s = va_arg(ap, const char *);
258 k += strlen(s);
259 break;
260 case 'b': /* byte */
261 i = va_arg(ap, unsigned int);
262 k += 1;
263 break;
264 case 'h': /* 16-bit integer */
265 i = va_arg(ap, unsigned int);
266 k += 2;
267 break;
268 default:
269 va_end(ap);
270 return NULL;
271 }
272 }
273 va_end(ap);
274
275 frame = malloc(sizeof(struct ID3v2FrameStruct));
276 frame->next = NULL;
277 strncpy(frame->frameid, frameid, 4);
278 frame->flags = 0;
279 frame->len = k;
280 frame->hskip = 0;
281 frame->data = malloc(k);
282
283 va_start(ap, format);
284 k = 0;
285 for (p = format; *p; p++) {
286 switch (*p) {
287 case 's': /* string */
288 s = va_arg(ap, const char *);
289 j = strlen(s);
290 memcpy(frame->data + k, s, j);
291 k += j;
292 break;
293 case 'b': /* byte */
294 i = va_arg(ap, unsigned int);
295 frame->data[k] = i;
296 k += 1;
297 break;
298 case 'h': /* 16-bit integer */
299 i = va_arg(ap, unsigned int);
300 frame->data[k] = (i >> 8) & 0xff;
301 frame->data[k+1] = i & 0xff;
302 k += 2;
303 break;
304 default:
305 va_end(ap);
306 free(frame->data);
307 free(frame);
308 return NULL;
309 }
310 }
311 va_end(ap);
312
313 return frame;
314 }
315
316
317 /**
318 * Decode an RVA2 frame (only track/album gain, only master channel).
319 *
320 * Store gain information in the info structure, unless info == NULL.
321 * Return 1 if the frame is an RVA2 frame with track/album gain, 0 otherwise.
322 */
id3_decode_rva2_frame(const struct ID3v2FrameStruct * frame,struct MP3GainTagInfo * info)323 static int id3_decode_rva2_frame(const struct ID3v2FrameStruct *frame, struct MP3GainTagInfo *info)
324 {
325 unsigned long p;
326 int is_album_gain, channel, peakbits;
327 double gain, peak;
328
329 /* Ignore non-RVA2 frames. */
330 if (memcmp(frame->frameid, "RVA2", 4) != 0)
331 return 0;
332
333 p = frame->hskip;
334
335 /* Check identification string; we understand only "track" and "album". */
336 if (p + 6 <= frame->len &&
337 (memcmp(frame->data + p, "track\0", 6) == 0 ||
338 memcmp(frame->data + p, "TRACK\0", 6) == 0)) {
339 is_album_gain = 0;
340 p += 6;
341 } else if (p + 6 <= frame->len &&
342 (memcmp(frame->data + p, "album\0", 6) == 0 ||
343 memcmp(frame->data + p, "ALBUM\0", 6) == 0)) {
344 is_album_gain = 1;
345 p += 6;
346 } else {
347 return 0;
348 }
349
350 /* Process per-channel data. */
351 while (p + 4 <= frame->len) {
352 /*
353 * p+0 : channel number
354 * p+1, p+2 : 16-bit signed BE int = adjustment * 512
355 * p+3 : nr of bits representing peak
356 * p+4 ... : unsigned multibyte BE int = peak sample * 2**(peakbits-1)
357 */
358 channel = frame->data[p];
359 gain = (double)(((signed char)(frame->data[p+1]) << 8) | frame->data[p+2]) / 512.0;
360 peakbits = frame->data[p+3];
361 if (p + 4 + (peakbits + 7) / 8 > frame->len)
362 break;
363 peak = 0;
364 if (peakbits > 0) peak += (double)(frame->data[p+4]);
365 if (peakbits > 8) peak += (double)(frame->data[p+5]) / 256.0;
366 if (peakbits > 16) peak += (double)(frame->data[p+6]) / 65536.0;
367 if (peakbits > 0) peak = peak / (double)(1 << ((peakbits - 1) & 7));
368 p += 4 + (peakbits + 7) / 8;
369 if (channel == 1) { /* channel == master volume channel */
370 if (info) {
371 if (is_album_gain) {
372 info->haveAlbumGain = 1;
373 info->albumGain = gain;
374 info->haveAlbumPeak = (peakbits > 0);
375 info->albumPeak = peak;
376 } else {
377 info->haveTrackGain = 1;
378 info->trackGain = gain;
379 info->haveTrackPeak = (peakbits > 0);
380 info->trackPeak = peak;
381 }
382 }
383 }
384 }
385
386 return 1;
387 }
388
389
390 /**
391 * Create an RVA2 frame, track or album gain, master channel.
392 * Return a newly allocated ID3v2FrameStruct.
393 */
id3_make_rva2_frame(int is_album_gain,double gain,int have_peak,double peak)394 static struct ID3v2FrameStruct * id3_make_rva2_frame(int is_album_gain, double gain, int have_peak, double peak)
395 {
396 const char *ident;
397 int g;
398 unsigned int p;
399 /*
400 * identification: string = "track" or "album"
401 * channel type: byte = 1 (master volume)
402 * volume adjustment: int16 = gain * 512
403 * peak bits: byte = 16 (or 0 if no peak information)
404 * peak: uint16 = peak * 32768
405 */
406 ident = (is_album_gain) ? "album" : "track";
407 g = (gain <= -64) ? -32768 :
408 (gain >= 64) ? 32767 :
409 (int)(gain * 512);
410 if (g < -32768) g = -32768;
411 if (g > 32767) g = 32767;
412 if (have_peak) {
413 p = (peak <= 0) ? 0 :
414 (peak >= 2) ? 65535 :
415 (unsigned int)(peak * 32768);
416 if (p > 65535) p = 65535;
417 return id3_make_frame("RVA2", "sbbhbh", ident, 0, 1, g, 16, p);
418 } else {
419 return id3_make_frame("RVA2", "sbbhb", ident, 0, 1, g, 0);
420 }
421 }
422
423
424 /**
425 * Decode an APEv2/Vorbis-style TXXX frame, matching
426 * /REPLAYGAIN_(ALBUM|TRACK)_(GAIN|PEAK)/ case-insensitively.
427 *
428 * Store gain information in the info structure, unless info == NULL.
429 * Return 1 if the frame is one of our TXXX frames, 0 otherwise.
430 */
id3_decode_txxx_frame(const struct ID3v2FrameStruct * frame,struct MP3GainTagInfo * info)431 static int id3_decode_txxx_frame(const struct ID3v2FrameStruct *frame, struct MP3GainTagInfo *info)
432 {
433 unsigned long p, k;
434 char buf[64];
435 const char *value;
436
437 /* Ignore non-TXXX frames. */
438 if (memcmp(frame->frameid, "TXXX", 4) != 0)
439 return 0;
440
441 p = frame->hskip;
442
443 /* Check text encoding; we understand only 0 (ISO-8859-1) and 3 (UTF-8). */
444 if (p >= frame->len || (frame->data[p] != 0 && frame->data[p] != 3))
445 return 0;
446 p++;
447
448 /* Copy character data to temporary buffer. */
449 k = (frame->len - p + 1 < sizeof(buf)) ? (frame->len - p) : (sizeof(buf) - 2);
450 memcpy(buf, frame->data + p, k);
451 buf[k] = '\0'; /* terminate the value string */
452 buf[k+1] = '\0'; /* ensure buf contains two terminated strings, even for invalid frame data */
453 value = buf + strlen(buf) + 1;
454
455 /* Check identification string. */
456 if (strcasecmp(buf, "REPLAYGAIN_ALBUM_GAIN") == 0) {
457 if (info) {
458 info->haveAlbumGain = !0;
459 info->albumGain = atof(value);
460 }
461 return 1;
462 } else if (strcasecmp(buf, "REPLAYGAIN_TRACK_GAIN") == 0) {
463 if (info) {
464 info->haveTrackGain = !0;
465 info->trackGain = atof(value);
466 }
467 return 1;
468 } else if (strcasecmp(buf, "REPLAYGAIN_ALBUM_PEAK") == 0) {
469 if (info) {
470 info->haveAlbumPeak = !0;
471 info->albumPeak = atof(value);
472 }
473 return 1;
474 } else if (strcasecmp(buf, "REPLAYGAIN_TRACK_PEAK") == 0) {
475 if (info) {
476 info->haveTrackPeak = !0;
477 info->trackPeak = atof(value);
478 }
479 return 1;
480 } else if (strcasecmp(buf, "REPLAYGAIN_REFERENCE_LOUDNESS") == 0) {
481 /* we derive no information from this at the moment, but
482 * we do want to delete this frame if re-writing */
483 return 1;
484 }
485
486 return 0;
487 }
488
489 /**
490 * Decode a mp3gain-specific TXXX frame, either "MP3GAIN_UNDO" or
491 * "MP3GAIN_MINMAX" or "MP3GAIN_ALBUM_MINMAX".
492 *
493 * Store gain information in the info structure, unless info == NULL.
494 * Return 1 if the frame is a mp3gain-specific TXXX frame, 0 otherwise.
495 */
id3_decode_mp3gain_frame(const struct ID3v2FrameStruct * frame,struct MP3GainTagInfo * info)496 static int id3_decode_mp3gain_frame(const struct ID3v2FrameStruct *frame, struct MP3GainTagInfo *info)
497 {
498 unsigned long p, k;
499 char buf[64];
500 int f1, f2;
501 char f3;
502
503 /* Ignore non-TXXX frames. */
504 if (memcmp(frame->frameid, "TXXX", 4) != 0)
505 return 0;
506
507 p = frame->hskip;
508
509 /* Check text encoding; we understand only 0 (ISO-8859-1) and 3 (UTF-8). */
510 if (p >= frame->len || (frame->data[p] != 0 && frame->data[p] != 3))
511 return 0;
512 p++;
513
514 /* Copy character data to temporary buffer. */
515 k = (frame->len - p + 1 < sizeof(buf)) ? (frame->len - p) : (sizeof(buf) - 2);
516 memcpy(buf, frame->data + p, k);
517 buf[k] = '\0'; /* terminate the value string */
518 buf[k+1] = '\0'; /* ensure buf contains two terminated strings, even for invalid frame data */
519
520 /* Check identification string. */
521 if (strcasecmp(buf, "MP3GAIN_UNDO") == 0) {
522 /* value should be something like "+003,+003,W" */
523 if (sscanf(buf + strlen(buf) + 1, "%d,%d,%c", &f1, &f2, &f3) == 3 &&
524 info != NULL) {
525 info->haveUndo = 1;
526 info->undoLeft = f1;
527 info->undoRight = f2;
528 info->undoWrap = (f3 == 'w' || f3 == 'W');
529 }
530 return 1;
531 } else if (strcasecmp(buf, "MP3GAIN_MINMAX") == 0) {
532 /* value should be something like "001,153" */
533 if (sscanf(buf + strlen(buf) + 1, "%d,%d", &f1, &f2) == 2 &&
534 info != NULL) {
535 info->haveMinMaxGain = 1;
536 info->minGain = f1;
537 info->maxGain = f2;
538 }
539 return 1;
540 } else if (strcasecmp(buf, "MP3GAIN_ALBUM_MINMAX") == 0) {
541 /* value should be something like "001,153" */
542 if (sscanf(buf + strlen(buf) + 1, "%d,%d", &f1, &f2) == 2 &&
543 info != NULL) {
544 info->haveAlbumMinMaxGain = 1;
545 info->albumMinGain = f1;
546 info->albumMaxGain = f2;
547 }
548 return 1;
549 }
550
551 return 0;
552 }
553
554
555 /**
556 * Read an ID3v2 tag from the current position in the MP3 file.
557 *
558 * Return 1 on success, 0 if no tag is found, or a negative error code
559 * if the tag can not be processed.
560 */
id3_parse_v2_tag(FILE * f,struct ID3v2TagStruct * tag)561 static int id3_parse_v2_tag(FILE *f, struct ID3v2TagStruct *tag)
562 {
563 unsigned char buf[12], frameid[4];
564 unsigned int fflags;
565 unsigned long dlen, flen, fhskip, p, k;
566 unsigned char *tagdata;
567 struct ID3v2FrameStruct *frame, **pframe;
568
569 /* Read header */
570 tag->offset = ftell(f);
571 if (fread(buf, 1, 10, f) != 10)
572 return 0;
573
574 /* Check 'ID3' signature. */
575 if (memcmp(buf, "ID3", 3) != 0)
576 return 0;
577
578 DBG(("DEBUG: Found ID3v2 tag at offset %lu\n", tag->offset));
579
580 /* Check version and flags. */
581 switch (buf[3]) {
582 case 2: /* ID3v2.2 */
583 if (buf[5] & (~(TAGFL_UNSYNC)))
584 return M3G_ERR_TAGFORMAT; /* unknown flags */
585 break;
586 case 3: /* ID3v2.3 */
587 if (buf[5] & (~(TAGFL_UNSYNC | TAGFL_EXTHDR | TAGFL_EXPR)))
588 return M3G_ERR_TAGFORMAT; /* unknown flags */
589 break;
590 case 4: /* ID3v2.4 */
591 if (buf[5] & (~(TAGFL_UNSYNC | TAGFL_EXTHDR | TAGFL_EXPR | TAGFL_FOOTER)))
592 return M3G_ERR_TAGFORMAT; /* unknown flags */
593 break;
594 default:
595 return M3G_ERR_TAGFORMAT; /* unknown version */
596 }
597
598 /* Check length. */
599 dlen = id3_get_syncsafe_int(buf + 6);
600 if (dlen == SYNCSAFE_INT_BAD)
601 return M3G_ERR_TAGFORMAT;
602
603 /* Fill tag structure. */
604 tag->flags = buf[5];
605 tag->version = (buf[3] << 8) | buf[4];
606 tag->length = 10 + dlen + ((tag->flags & TAGFL_FOOTER) ? 10 : 0);
607 tag->frames = NULL;
608
609 DBG((" version=%04x length=%lu flags=%02x\n", tag->version, tag->length, tag->flags));
610
611 /* Read rest of the tag. */
612 tagdata = malloc(dlen);
613 if (fread(tagdata, 1, dlen, f) != dlen)
614 goto badtag;
615
616 /* If this is an unsynced v2.2 or v2.3 tag, decode it now. */
617 if ((tag->version >> 8) != 4 && (tag->flags & TAGFL_UNSYNC) != 0) {
618 dlen = id3_get_unsync_data(tagdata, tagdata, dlen);
619 }
620
621 /* Skip extended header. */
622 p = 0;
623 if ((tag->flags & TAGFL_EXTHDR) != 0) {
624 DBG((" skip extended header\n"));
625 if (p + 6 > dlen)
626 goto badtag;
627 if ((tag->version >> 8) == 4) {
628 /* Skip ID3v2.4 extended header */
629 k = id3_get_syncsafe_int(tagdata + p);
630 if (k == SYNCSAFE_INT_BAD || k > dlen)
631 goto badtag;
632 p += k;
633 } else if ((tag->version >> 8) == 3) {
634 /* Skip ID3v2.3 extended header */
635 k = id3_get_int32(tagdata + p);
636 if (k > dlen)
637 goto badtag;
638 p += 4 + k;
639 }
640 }
641
642 /* Scan frames. */
643 pframe = &(tag->frames);
644 while (p < dlen && tagdata[p] != '\0') {
645
646 /* Decode frame header. */
647 switch (tag->version >> 8) {
648
649 case 2: /* ID3v2.2 */
650 if (p + 5 > dlen)
651 goto badtag;
652 memset(frameid, 0, 4);
653 for (k = 0; upgrade_id3v22_table[k].id_new[0]; k++) {
654 if (memcmp(tagdata + p, upgrade_id3v22_table[k].id_v22, 3) == 0) {
655 memcpy(frameid, upgrade_id3v22_table[k].id_new, 4);
656 break;
657 }
658 }
659 flen = (tagdata[p+3] << 16) | (tagdata[p+4] << 8) | tagdata[p+5];
660 fflags = 0;
661 if (flen > dlen)
662 goto badtag;
663 p += 6;
664 break;
665
666 case 3: /* ID3v2.3 */
667 if (p + 10 > dlen)
668 goto badtag;
669 memcpy(frameid, tagdata + p, 4);
670 flen = id3_get_int32(tagdata + p + 4);
671 fflags = (tagdata[p+8] << 7) & 0xff00;
672 if (tagdata[p+9] & 0x80) fflags |= FRAMEFL_COMPR | FRAMEFL_DLEN;
673 if (tagdata[p+9] & 0x40) fflags |= FRAMEFL_CRYPT;
674 if (tagdata[p+9] & 0x20) fflags |= FRAMEFL_GROUP;
675 if (tagdata[p+9] & 0x1f) fflags |= FRAMEFL_BAD;
676 if (flen > dlen)
677 goto badtag;
678 p += 10;
679 break;
680
681 case 4: /* ID3v2.4 */
682 if (p + 10 > dlen)
683 goto badtag;
684 memcpy(frameid, tagdata + p, 4);
685 flen = id3_get_syncsafe_int(tagdata + p + 4);
686 fflags = (tagdata[p+8] << 8) | tagdata[p+9];
687 if (flen == SYNCSAFE_INT_BAD || flen > dlen)
688 goto badtag;
689 p += 10;
690 break;
691
692 default: /* unreachable */
693 goto badtag;
694 }
695
696 if (p + flen > dlen)
697 goto badtag;
698
699 DBG((" got frameid=%.4s fflags=%04x\n", frameid, fflags));
700
701 /* Drop unsupported frame types. */
702 if (frameid[0] == '\0' ||
703 memcmp(frameid, "RVAD", 4) == 0 ||
704 memcmp(frameid, "RGAD", 4) == 0 ||
705 memcmp(frameid, "XRVA", 4) == 0) {
706 DBG((" drop unsupported frame\n"));
707 p += flen;
708 continue;
709 }
710
711 /* Drop v2.3 frames which we can not upgrade. */
712 if ((tag->version >> 8) == 3 && (fflags & (FRAMEFL_CRYPT | FRAMEFL_BAD)) != 0) {
713 DBG((" drop non-upgradable frame\n"));
714 p += flen;
715 continue;
716 }
717
718 /* Drop frames that are too short for their flags. */
719 fhskip = (fflags & FRAMEFL_GROUP ? 1 : 0) +
720 (fflags & FRAMEFL_CRYPT ? 1 : 0) +
721 (fflags & FRAMEFL_DLEN ? 4 : 0);
722 if (fhskip > flen) {
723 DBG((" drop short frame\n"));
724 p += flen;
725 continue;
726 }
727
728 /* Drop v2.2 PIC frames that are too short. */
729 if ((tag->version >> 8) == 2 && memcmp(frameid, "APIC", 4) == 0 && flen < 6) {
730 DBG((" drop short PIC frame\n"));
731 p += flen;
732 continue;
733 }
734
735 /* Rename TYER (Year) to TDRC (Recording time) */
736 if (memcmp(frameid, "TYER", 4) == 0)
737 memcpy(frameid, "TDRC", 4);
738
739 /* Drop frames that want to be dropped on tag alteration. */
740 if (fflags & FRAMEFL_TAGALTER) {
741 DBG((" drop FRAMEFL_TAGALTER frame\n"));
742 p += flen;
743 continue;
744 }
745
746 /* Allocate frame structure. */
747 frame = malloc(sizeof(struct ID3v2FrameStruct));
748 frame->next = NULL;
749 memcpy(frame->frameid, frameid, 4);
750 frame->flags = fflags;
751 frame->hskip = fhskip;
752 *pframe = frame;
753 pframe = &(frame->next);
754
755 /* Copy frame data. */
756 if ((tag->version >> 8) == 4 && (fflags & FRAMEFL_UNSYNC) != 0) {
757 /* This frame is unsynchronized; decode it now. */
758 frame->data = malloc(flen);
759 k = id3_get_unsync_data(frame->data, tagdata + p, flen);
760 frame->len = k;
761 p += flen;
762 } else if ((tag->version >> 8) == 2 && memcmp(frameid, "APIC", 4) == 0) {
763 /* APIC frame format differs from PIC frame format */
764 frame->data = malloc(flen + 12);
765 frame->data[0] = tagdata[p];
766 k = 1;
767 if (memcmp(tagdata + p + 1, "PNG", 3) == 0) {
768 memcpy(frame->data + k, "image/png", strlen("image/png") + 1);
769 k += strlen("image/png") + 1;
770 } else if (memcmp(tagdata + p + 1, "JPG", 3) == 0) {
771 memcpy(frame->data + k, "image/jpeg", strlen("image/jpeg") + 1);
772 k += strlen("image/jpeg") + 1;
773 } else if (tagdata[p+1] == '\0') {
774 memcpy(frame->data + k, tagdata + p + 1, 3);
775 frame->data[k+3] = '\0';
776 k += 4;
777 }
778 memcpy(frame->data + k, tagdata + p + 4, flen - 4);
779 frame->len = k + flen - 4;
780 p += flen;
781 } else {
782 /* Normal case, just copy the data. */
783 frame->data = malloc(flen);
784 memcpy(frame->data, tagdata + p, flen);
785 frame->len = flen;
786 p += flen;
787 }
788
789 /* Reorder flag parameters of upgraded v2.3 frames. */
790 if ((tag->version >> 8) == 3 && (fflags & FRAMEFL_DLEN) != 0) {
791 k = id3_get_int32(frame->data);
792 if (fflags & FRAMEFL_GROUP) {
793 frame->data[0] = frame->data[4];
794 id3_put_syncsafe_int(frame->data + 1, k);
795 } else {
796 id3_put_syncsafe_int(frame->data, k);
797 }
798 }
799
800 }
801
802 if (p > dlen)
803 goto badtag;
804
805 free(tagdata);
806 return 1;
807
808 badtag:
809 free(tagdata);
810 id3_release_frames(tag->frames);
811 return M3G_ERR_TAGFORMAT;
812 }
813
814
815 /**
816 * Write an ID3v2 tag at the current position in the MP3 file.
817 *
818 * Tags are always written in ID3v2.4 format.
819 * Tags are always written completely unsynchronized,
820 * without extended header, padded up to an integer multiple of 2 KB.
821 * We don't write a tag footer (not supported by QuodLibet).
822 *
823 * Return 1 on success, 0 if the tag contains no frames,
824 * or a negative error code.
825 */
id3_write_tag(FILE * f,struct ID3v2TagStruct * tag)826 static int id3_write_tag(FILE *f, struct ID3v2TagStruct *tag)
827 {
828 unsigned long dlen, p, k;
829 unsigned char *tagdata;
830 struct ID3v2FrameStruct *frame;
831
832 DBG(("DEBUG: Writing ID3v2 tag\n"));
833
834 /* Do not write a tag with zero frames. */
835 if (tag->frames == NULL)
836 return 0;
837
838 /* Compute raw total length of tag. */
839 dlen = 10; /* tag header */
840 for (frame = tag->frames; frame; frame = frame->next) {
841 dlen += 10;
842 dlen += id3_put_unsync_data(NULL, frame->data, frame->len);
843 }
844 dlen = (dlen + 2047) & (~2047); /* padding */
845
846 DBG((" length=%lu\n", dlen));
847
848 /* Allocate buffer and fill with zeros. */
849 tagdata = calloc(dlen, sizeof(unsigned char));
850
851 /* Prepare tag header. */
852 tagdata[0] = 'I';
853 tagdata[1] = 'D';
854 tagdata[2] = '3';
855 tagdata[3] = 4;
856 tagdata[4] = 0;
857 tagdata[5] = TAGFL_UNSYNC | (tag->flags & TAGFL_EXPR);
858 id3_put_syncsafe_int(tagdata + 6, dlen - 10);
859 p = 10;
860
861 /* Prepare frames. */
862 for (frame = tag->frames; frame; frame = frame->next) {
863 unsigned long fflags = frame->flags & (~FRAMEFL_UNSYNC);
864 memcpy(tagdata + p, frame->frameid, 4);
865 k = id3_put_unsync_data(tagdata + p + 10, frame->data, frame->len);
866 id3_put_syncsafe_int(tagdata + p + 4, k);
867 if (k != frame->len) fflags |= FRAMEFL_UNSYNC;
868 tagdata[p+8] = (fflags >> 8) & 0xff;
869 tagdata[p+9] = fflags & 0xff;
870 p += 10 + k;
871 DBG((" write frameid=%.4s length=%lu\n", frame->frameid, 10 + k));
872 }
873
874 /* Write the whole thing. */
875 if (fwrite(tagdata, 1, dlen, f) != dlen) {
876 free(tagdata);
877 return M3G_ERR_WRITE;
878 }
879
880 free(tagdata);
881 return 1;
882 }
883
884
885 /**
886 * Read an ID3v1 tag from the current position in the MP3 file.
887 *
888 * Return 1 on success, 0 if no tag is found.
889 */
id3_parse_v1_tag(FILE * f,struct ID3v2TagStruct * tag)890 static int id3_parse_v1_tag(FILE *f, struct ID3v2TagStruct *tag)
891 {
892 unsigned char buf[128];
893 char sbuf[32],*p;
894
895 struct ID3v2FrameStruct **pframe;
896
897 /* Read tag */
898 tag->offset = ftell(f);
899 if (fread(buf, 1, 128, f) != 128)
900 return 0;
901
902 /* Check 'TAG' signature. */
903 if (memcmp(buf, "TAG", 3) != 0)
904 return 0;
905
906 DBG(("DEBUG: Found ID3v1 tag at offset %lu\n", tag->offset));
907
908 /* Convert ID3v1 data to ID3v2.4 */
909 tag->length = 128;
910 tag->version = 0;
911 tag->flags = 0;
912 tag->frames = NULL;
913
914 pframe = &(tag->frames);
915
916 /* Add title field (offset 3, len 30). */
917 if (buf[3] != '\0') {
918 memcpy(sbuf, buf + 3, 30);
919 sbuf[30] = '\0';
920 /* get rid of trailing spaces */
921 for(p=sbuf+29; *p==' ' && p>=sbuf; *p--='\0');
922 *pframe = id3_make_frame("TIT2", "bs", 0, sbuf);
923 pframe = &((*pframe)->next);
924 }
925
926 /* Add artist field (offset 33, len 30). */
927 if (buf[33] != '\0') {
928 memcpy(sbuf, buf + 33, 30);
929 sbuf[30] = '\0';
930 /* get rid of trailing spaces */
931 for(p=sbuf+29; *p==' ' && p>=sbuf; *p--='\0');
932 DBG(("fixed v1 artist: \"%s\"\n",sbuf));
933 *pframe = id3_make_frame("TPE1", "bs", 0, sbuf);
934 pframe = &((*pframe)->next);
935 }
936
937 /* Add album field (offset 63, len 30). */
938 if (buf[63] != '\0') {
939 memcpy(sbuf, buf + 63, 30);
940 sbuf[30] = '\0';
941 /* get rid of trailing spaces */
942 for(p=sbuf+29; *p==' ' && p>=sbuf; *p--='\0');
943 *pframe = id3_make_frame("TALB", "bs", 0, sbuf);
944 pframe = &((*pframe)->next);
945 }
946
947 /* Add release year (offset 93, len 4). */
948 if (buf[93] >= '0' && buf[93] <= '9' &&
949 buf[94] >= '0' && buf[94] <= '9' &&
950 buf[95] >= '0' && buf[95] <= '9' &&
951 buf[96] >= '0' && buf[96] <= '9') {
952 memcpy(sbuf, buf + 93, 4);
953 sbuf[4] = '\0';
954 *pframe = id3_make_frame("TDRC", "bs", 0, sbuf);
955 pframe = &((*pframe)->next);
956 }
957
958 /* Add comment (offset 97, len 30). */
959 if (buf[97] != '\0') {
960 memcpy(sbuf, buf + 97, 30);
961 sbuf[30] = '\0';
962 /* get rid of trailing spaces */
963 for(p=sbuf+29; *p==' ' && p>=sbuf; *p--='\0');
964 /* assume ISO-8859-1, unknown language, no description */
965 *pframe = id3_make_frame("COMM", "bssbs", 0, "XXX", "", 0, sbuf);
966 pframe = &((*pframe)->next);
967 }
968
969 /* Add track number (offset 126, len 1). */
970 if (buf[125] == '\0' && buf[126] != 0) {
971 sprintf(sbuf, "%u", buf[126]);
972 *pframe = id3_make_frame("TRCK", "bs", 0, sbuf);
973 pframe = &((*pframe)->next);
974 }
975
976 return 1;
977 }
978
979
980 /**
981 * Search for an ID3v2 tag at the beginning and end of the file.
982 * If no ID3v2 tag is found, search for an ID3v1 tag at the end
983 * of the file.
984 *
985 * Return 1 on success, 0 if no tag is found, or a negative error code
986 * if the tag can not be processed.
987 */
id3_search_tag(FILE * f,struct ID3v2TagStruct * tag)988 static int id3_search_tag(FILE *f, struct ID3v2TagStruct *tag)
989 {
990 unsigned char buf[32];
991 unsigned long pos, k, id3v1_pos = 0;
992 int j, ret;
993
994 /* Look for ID3v2 at the beginning of the file. */
995 fseek(f, 0, SEEK_SET);
996 ret = id3_parse_v2_tag(f, tag);
997
998 if (ret == 0) {
999 /* Look for ID3v2 at the end of the file. */
1000
1001 fseek(f, 0, SEEK_END);
1002 pos = ftell(f);
1003
1004 while (pos > 128) {
1005
1006 /* Test for ID3v2 footer */
1007 fseek(f, pos - 10, SEEK_SET);
1008 if (fread(buf, 1, 10, f) != 10)
1009 return M3G_ERR_READ;
1010 if (memcmp(buf, "3DI", 3) == 0 &&
1011 buf[3] == 4 &&
1012 ((buf[6] | buf[7] | buf[8] | buf[9]) & 0x80) == 0) {
1013 /* Parse ID3v2.4 tag */
1014 k = id3_get_syncsafe_int(buf + 6);
1015 if (20 + k < pos) {
1016 pos -= 20 + k;
1017 fseek(f, pos, SEEK_SET);
1018 ret = id3_parse_v2_tag(f, tag);
1019 break;
1020 }
1021 }
1022
1023 /* Test for ID3v1/Lyrics3v2 tag */
1024 fseek(f, pos - 128, SEEK_SET);
1025 if (fread(buf, 1, 3, f) != 3)
1026 return M3G_ERR_READ;
1027 if (memcmp(buf, "TAG", 3) == 0) {
1028 /* Skip over ID3v1 tag and continue */
1029 pos -= 128;
1030 DBG(("DEBUG: Skipping ID3v1 tag at offset %lu\n", pos));
1031 id3v1_pos = pos;
1032 /* Test for Lyrics3v2 tag */
1033 if (pos > 26) {
1034 fseek(f, pos - 15, SEEK_SET);
1035 if (fread(buf, 1, 15, f) != 15)
1036 return M3G_ERR_READ;
1037 if (memcmp(buf + 6, "LYRICS200", 9) == 0) {
1038 /* Skip over Lyrics tag */
1039 k = 0;
1040 for (j = 0; j < 6; j++) {
1041 if (buf[j] < '0' || buf[j] > '9') {
1042 k = 0;
1043 break;
1044 }
1045 k = 10 * k + (buf[j] - '0');
1046 }
1047 if (k >= 11 && k + 15 < pos) {
1048 pos -= k + 15;
1049 DBG(("DEBUG: Skipping Lyrics3v2 tag at offset %lu\n", pos));
1050 }
1051 }
1052 }
1053 continue;
1054 }
1055
1056 /* Test for APE tag */
1057 fseek(f, pos - 32, SEEK_SET);
1058 if (fread(buf, 1, 32, f) != 32)
1059 return M3G_ERR_READ;
1060 if (memcmp(buf, "APETAGEX", 8) == 0) {
1061 /* Skip over APE tag and continue */
1062 k = buf[12] | (buf[13] << 8) | (buf[14] << 16) | (buf[15] << 24); /* tag length */
1063 if (buf[23] & 0x80)
1064 k += 32; /* tag header present */
1065 if (k >= 32 && k < pos) {
1066 pos -= k;
1067 DBG(("DEBUG: Skipping APE tag at offset %lu\n", pos));
1068 continue;
1069 }
1070 }
1071
1072 /* No more tags to skip. */
1073 break;
1074
1075 }
1076
1077 }
1078
1079 if (ret == 0 && id3v1_pos != 0) {
1080 /* Read ID3v1 at the end of the file. */
1081 fseek(f, id3v1_pos, SEEK_SET);
1082 ret = id3_parse_v1_tag(f, tag);
1083 }
1084
1085 return ret;
1086 }
1087
1088
1089 /**
1090 * Seek to offset in inf and copy count bytes to the current
1091 * position in outf. If count == -1, copy until the end of the file.
1092 *
1093 * Return 1 on success, otherwise a negative error code.
1094 */
id3_copy_data(FILE * inf,FILE * outf,long offset,long count)1095 static int id3_copy_data(FILE *inf, FILE *outf, long offset, long count)
1096 {
1097 const long bufsize = 65536;
1098 char *buf;
1099 size_t k;
1100 int ret;
1101
1102 ret = 1;
1103 buf = malloc(bufsize);
1104
1105 if (fseek(inf, offset, SEEK_SET))
1106 ret = M3G_ERR_READ;
1107
1108 while (ret == 1 && count != 0) {
1109 k = (count > 0 && count < bufsize) ? count : bufsize;
1110 k = fread(buf, 1, k, inf);
1111 if (k == 0) {
1112 if (!feof(inf) || count > 0)
1113 ret = M3G_ERR_READ;
1114 break;
1115 }
1116 if (fwrite(buf, 1, k, outf) != k) {
1117 ret = M3G_ERR_WRITE;
1118 break;
1119 }
1120 if (count > 0)
1121 count -= k;
1122 }
1123
1124 free(buf);
1125 return ret;
1126 }
1127
1128
1129 /**
1130 * Read gain information from an ID3v2 tag.
1131 */
ReadMP3GainID3Tag(char * filename,struct MP3GainTagInfo * info)1132 int ReadMP3GainID3Tag(char *filename, struct MP3GainTagInfo *info)
1133 {
1134 FILE *f;
1135 struct ID3v2TagStruct tag;
1136 struct ID3v2FrameStruct *frame;
1137 int ret;
1138
1139 f = fopen(filename, "rb");
1140 if (f == NULL) {
1141 passError(MP3GAIN_UNSPECIFED_ERROR, 3, "Could not open ", filename, "\n");
1142 return M3G_ERR_FILEOPEN;
1143 }
1144
1145 ret = id3_search_tag(f, &tag);
1146 fclose(f);
1147
1148 if (ret == M3G_ERR_READ) {
1149 passError(MP3GAIN_UNSPECIFED_ERROR, 3, "Error reading ", filename, "\n");
1150 }
1151
1152 if (ret == 1) {
1153 /* Got the tag; extract gain information from the RVA2/TXXX frames. */
1154 frame = tag.frames;
1155 while (frame) {
1156 id3_decode_rva2_frame(frame, info);
1157 id3_decode_txxx_frame(frame, info);
1158 id3_decode_mp3gain_frame(frame, info);
1159 frame = frame->next;
1160 }
1161 id3_release_frames(tag.frames);
1162 }
1163
1164 return ret;
1165 }
1166
1167
1168 /**
1169 * (Re-)Write gain information to an ID3v2 tag.
1170 *
1171 * Writes or updates an ID3v2.4 tag at the beginning of the file.
1172 * If the file does not yet contain an ID3v2 tag, a new tag is created,
1173 * copying basic fields from an ID3v1 tag if present.
1174 * If the file contains an ID3v2.2 or ID3v2.3 tag, it is rewritten as ID3v2.4.
1175 *
1176 * Since modifications are made at the beginning of the file, the entire
1177 * file is rewritten to a temporary file and then moved in place of the
1178 * old file.
1179 */
WriteMP3GainID3Tag(char * filename,struct MP3GainTagInfo * info,int saveTimeStamp)1180 int WriteMP3GainID3Tag(char *filename, struct MP3GainTagInfo *info, int saveTimeStamp)
1181 {
1182 char sbuf[32];
1183 char *tmpfilename;
1184 FILE *f, *outf;
1185 struct ID3v2TagStruct tag;
1186 struct ID3v2FrameStruct *frame, **pframe;
1187 int ret, need_update;
1188
1189 if (saveTimeStamp)
1190 fileTime(filename, storeTime);
1191
1192 f = fopen(filename, "rb");
1193 if (f == NULL) {
1194 passError(MP3GAIN_UNSPECIFED_ERROR, 3, "Could not open ", filename, "\n");
1195 return M3G_ERR_FILEOPEN;
1196 }
1197 ret = id3_search_tag(f, &tag);
1198
1199 switch (ret) {
1200 case M3G_ERR_READ:
1201 passError(MP3GAIN_UNSPECIFED_ERROR, 3, "Error reading ", filename, "\n");
1202 break;
1203 case M3G_ERR_TAGFORMAT:
1204 passError(MP3GAIN_UNSPECIFED_ERROR, 3, "Unsupported ID3v2 tag in ", filename, "\n");
1205 break;
1206 }
1207
1208 if (ret < 0) {
1209 /* Error. */
1210 fclose(f);
1211 return ret;
1212 }
1213
1214 if (ret == 0) {
1215 /* No ID3v2 or ID3v1 tag found in the file; create a new tag. */
1216 tag.offset = 0;
1217 tag.length = 0;
1218 tag.version = 0;
1219 tag.flags = 0;
1220 tag.frames = NULL;
1221 }
1222
1223 /* Kill existing replaygain frames. */
1224 need_update = 0;
1225 pframe = &(tag.frames);
1226 while ((frame = *pframe)) {
1227 if (id3_decode_rva2_frame(frame, NULL) == 1 ||
1228 id3_decode_txxx_frame(frame, NULL) == 1 ||
1229 id3_decode_mp3gain_frame(frame, NULL) == 1) {
1230 /* This is a ReplayGain frame; kill it. */
1231 need_update = 1;
1232 *pframe = frame->next;
1233 free(frame->data);
1234 free(frame);
1235 } else {
1236 pframe = &((*pframe)->next);
1237 }
1238 }
1239
1240 /* Append new replaygain frames. The TXXX versions are lower-case,
1241 * because that's what Winamp wants... */
1242
1243 if (info->haveTrackGain || info->haveTrackPeak ||
1244 info->haveAlbumGain || info->haveAlbumPeak) {
1245 need_update = 1;
1246 frame = id3_make_frame("TXXX", "bsbs", 0, "replaygain_reference_loudness", 0, "89.0 dB");
1247 *pframe = frame;
1248 pframe = &(frame->next);
1249 }
1250
1251 if (info->haveTrackGain) {
1252 need_update = 1;
1253 frame = id3_make_rva2_frame(0, info->trackGain, info->haveTrackPeak, info->trackPeak);
1254 *pframe = frame;
1255 pframe = &(frame->next);
1256
1257 sprintf(sbuf, "%-+9.6f dB", info->trackGain);
1258 frame = id3_make_frame("TXXX", "bsbs", 0, "replaygain_track_gain", 0, sbuf);
1259 *pframe = frame;
1260 pframe = &(frame->next);
1261 }
1262 if (info->haveTrackPeak) {
1263 need_update = 1;
1264 sprintf(sbuf, "%-8.6f", info->trackPeak);
1265 frame = id3_make_frame("TXXX", "bsbs", 0, "replaygain_track_peak", 0, sbuf);
1266 *pframe = frame;
1267 pframe = &(frame->next);
1268 }
1269
1270 if (info->haveAlbumGain) {
1271 need_update = 1;
1272 frame = id3_make_rva2_frame(1, info->albumGain, info->haveAlbumPeak, info->albumPeak);
1273 *pframe = frame;
1274 pframe = &(frame->next);
1275
1276 sprintf(sbuf, "%-+9.6f dB", info->albumGain);
1277 frame = id3_make_frame("TXXX", "bsbs", 0, "replaygain_album_gain", 0, sbuf);
1278 *pframe = frame;
1279 pframe = &(frame->next);
1280 }
1281 if (info->haveAlbumPeak) {
1282 need_update = 1;
1283 sprintf(sbuf, "%-8.6f", info->albumPeak);
1284 frame = id3_make_frame("TXXX", "bsbs", 0, "replaygain_album_peak", 0, sbuf);
1285 *pframe = frame;
1286 pframe = &(frame->next);
1287 }
1288
1289 /* Append mp3gain-specific frames. */
1290 if (info->haveMinMaxGain) {
1291 need_update = 1;
1292 sprintf(sbuf, "%03d,%03d", info->minGain, info->maxGain);
1293 frame = id3_make_frame("TXXX", "bsbs", 0, "MP3GAIN_MINMAX", 0, sbuf);
1294 *pframe = frame;
1295 pframe = &(frame->next);
1296 }
1297 if (info->haveAlbumMinMaxGain) {
1298 need_update = 1;
1299 sprintf(sbuf, "%03d,%03d", info->albumMinGain, info->albumMaxGain);
1300 frame = id3_make_frame("TXXX", "bsbs", 0, "MP3GAIN_ALBUM_MINMAX", 0, sbuf);
1301 *pframe = frame;
1302 pframe = &(frame->next);
1303 }
1304 if (info->haveUndo) {
1305 need_update = 1;
1306 sprintf(sbuf, "%+04d,%+04d,%c", info->undoLeft, info->undoRight, info->undoWrap ? 'W' : 'N');
1307 frame = id3_make_frame("TXXX", "bsbs", 0, "MP3GAIN_UNDO", 0, sbuf);
1308 *pframe = frame;
1309 pframe = &(frame->next);
1310 }
1311
1312 if (!need_update) {
1313 /* No need to change MP3 file. */
1314 fclose(f);
1315 id3_release_frames(tag.frames);
1316 return 0;
1317 }
1318
1319 /* Create temporary file. */
1320 tmpfilename = malloc(strlen(filename) + 5);
1321 strcpy(tmpfilename, filename);
1322 strcat(tmpfilename, ".TMP");
1323 outf = fopen(tmpfilename, "wb");
1324 if (outf == NULL) {
1325 passError(MP3GAIN_UNSPECIFED_ERROR, 3, "Can not create temporary file ", tmpfilename, "\n");
1326 fclose(f);
1327 free(tmpfilename);
1328 id3_release_frames(tag.frames);
1329 return M3G_ERR_CANT_MAKE_TMP;
1330 }
1331
1332 /* Write new ID3v2 tag. */
1333 ret = id3_write_tag(outf, &tag);
1334
1335 /* Write rest of MP3 file. */
1336 if (ret >= 0) {
1337 if (tag.version == 0) {
1338 /* The original file has no ID3v2 tag; copy everything. */
1339 ret = id3_copy_data(f, outf, 0, -1);
1340 } else {
1341 /* The original file has an ID3v2 tag; copy everything
1342 except the original tag. */
1343 ret = id3_copy_data(f, outf, 0, tag.offset);
1344 if (ret >= 0)
1345 ret = id3_copy_data(f, outf, tag.offset + tag.length, -1);
1346 }
1347 }
1348
1349 fclose(outf);
1350 fclose(f);
1351 id3_release_frames(tag.frames);
1352
1353 switch (ret) {
1354 case M3G_ERR_READ:
1355 passError(MP3GAIN_UNSPECIFED_ERROR, 3, "Error reading ", filename, "\n");
1356 break;
1357 case M3G_ERR_WRITE:
1358 passError(MP3GAIN_UNSPECIFED_ERROR, 3, "Error writing ", tmpfilename, "\n");
1359 break;
1360 }
1361
1362 if (ret < 0) {
1363 /* Delete temp file after error. */
1364 remove(tmpfilename);
1365 free(tmpfilename);
1366 return ret;
1367 }
1368
1369 /* Replace original file. */
1370 #ifdef WIN32
1371 /* "rename" function in WIN32 does _not_ replace existing destination file, so
1372 we have to manually remove it first */
1373 if (remove(filename) != 0) {
1374 passError(MP3GAIN_UNSPECIFED_ERROR, 5, "Can not rename ", tmpfilename, " to ", filename, "\n");
1375 ret = M3G_ERR_RENAME_TMP;
1376 /* Do NOT remove the temp file itself, just in case the "remove(filename)" function
1377 only _temporarily_ failed, and the original file will disappear soon, such as when
1378 all handles on the file are closed. If it does disappear and we also
1379 delete the tmp file, then the file is completely gone... */
1380 free(tmpfilename);
1381 }
1382 #endif
1383
1384 ret = 1;
1385 if (rename(tmpfilename, filename)) {
1386 remove(tmpfilename);
1387 passError(MP3GAIN_UNSPECIFED_ERROR, 5, "Can not rename ", tmpfilename, " to ", filename, "\n");
1388 ret = M3G_ERR_RENAME_TMP;
1389 } else {
1390 if (saveTimeStamp)
1391 fileTime(filename, setStoredTime);
1392 }
1393
1394 free(tmpfilename);
1395
1396 return ret;
1397 }
1398
1399
1400 /**
1401 * Remove gain information from the ID3v2 tag.
1402 * Return 1 on success, 0 if no changes are needed, or a negative error code.
1403 */
RemoveMP3GainID3Tag(char * filename,int saveTimeStamp)1404 int RemoveMP3GainID3Tag(char *filename, int saveTimeStamp)
1405 {
1406 struct MP3GainTagInfo info;
1407
1408 info.haveAlbumGain = 0;
1409 info.haveAlbumPeak = 0;
1410 info.haveTrackGain = 0;
1411 info.haveTrackPeak = 0;
1412 info.haveMinMaxGain = 0;
1413 info.haveAlbumMinMaxGain = 0;
1414 info.haveUndo = 0;
1415
1416 return WriteMP3GainID3Tag(filename, &info, saveTimeStamp);
1417 }
1418
1419