Fix remote screen check in graphic equalizer, so that it can be used on logf-enabled...
[Rockbox.git] / firmware / id3.c
blob92f60a20954e466b8b3295d4a787254b8af6d4bf
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 by Daniel Stenberg
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
20 * Parts of this code has been stolen from the Ample project and was written
21 * by David Härdeman. It has since been extended and enhanced pretty much by
22 * all sorts of friendly Rockbox people.
26 /* tagResolver and associated code copyright 2003 Thomas Paul Diffenbach
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <errno.h>
33 #include <stdbool.h>
34 #include <stddef.h>
35 #include <ctype.h>
36 #include "config.h"
37 #include "file.h"
38 #include "debug.h"
39 #include "atoi.h"
41 #include "id3.h"
42 #include "mp3data.h"
43 #include "system.h"
44 #include "replaygain.h"
45 #include "rbunicode.h"
47 #define UNSYNC(b0,b1,b2,b3) (((long)(b0 & 0x7F) << (3*7)) | \
48 ((long)(b1 & 0x7F) << (2*7)) | \
49 ((long)(b2 & 0x7F) << (1*7)) | \
50 ((long)(b3 & 0x7F) << (0*7)))
52 #define BYTES2INT(b0,b1,b2,b3) (((long)(b0 & 0xFF) << (3*8)) | \
53 ((long)(b1 & 0xFF) << (2*8)) | \
54 ((long)(b2 & 0xFF) << (1*8)) | \
55 ((long)(b3 & 0xFF) << (0*8)))
57 static const char* const genres[] = {
58 "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge",
59 "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies", "Other", "Pop", "R&B",
60 "Rap", "Reggae", "Rock", "Techno", "Industrial", "Alternative", "Ska",
61 "Death Metal", "Pranks", "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop",
62 "Vocal", "Jazz+Funk", "Fusion", "Trance", "Classical", "Instrumental",
63 "Acid", "House", "Game", "Sound Clip", "Gospel", "Noise", "AlternRock",
64 "Bass", "Soul", "Punk", "Space", "Meditative", "Instrumental Pop",
65 "Instrumental Rock", "Ethnic", "Gothic", "Darkwave", "Techno-Industrial",
66 "Electronic", "Pop-Folk", "Eurodance", "Dream", "Southern Rock", "Comedy",
67 "Cult", "Gangsta", "Top 40", "Christian Rap", "Pop/Funk", "Jungle",
68 "Native American", "Cabaret", "New Wave", "Psychadelic", "Rave",
69 "Showtunes", "Trailer", "Lo-Fi", "Tribal", "Acid Punk", "Acid Jazz",
70 "Polka", "Retro", "Musical", "Rock & Roll", "Hard Rock",
72 /* winamp extensions */
73 "Folk", "Folk-Rock", "National Folk", "Swing", "Fast Fusion", "Bebob",
74 "Latin", "Revival", "Celtic", "Bluegrass", "Avantgarde", "Gothic Rock",
75 "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", "Slow Rock",
76 "Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech",
77 "Chanson", "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass",
78 "Primus", "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba",
79 "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle",
80 "Duet", "Punk Rock", "Drum Solo", "A capella", "Euro-House", "Dance Hall",
81 "Goa", "Drum & Bass", "Club-House", "Hardcore", "Terror", "Indie",
82 "BritPop", "Negerpunk", "Polsk Punk", "Beat", "Christian Gangsta Rap",
83 "Heavy Metal", "Black Metal", "Crossover", "Contemporary Christian",
84 "Christian Rock", "Merengue", "Salsa", "Trash Metal", "Anime", "Jpop",
85 "Synthpop"
88 /* database of audio formats */
89 const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
91 /* Unknown file format */
92 AFMT_ENTRY("???", NULL, NULL, NULL ),
93 /* MPEG Audio layer 1 */
94 AFMT_ENTRY("MP1", "mpa.codec", NULL, NULL ),
95 /* MPEG Audio layer 2 */
96 AFMT_ENTRY("MP2", "mpa.codec", NULL, NULL ),
97 /* MPEG Audio layer 3 */
98 AFMT_ENTRY("MP3", "mpa.codec", "mp3_enc.codec", ".mp3"),
99 #if CONFIG_CODEC == SWCODEC
100 /* Uncompressed PCM in a WAV file */
101 AFMT_ENTRY("WAV", "wav.codec", "wav_enc.codec", ".wav"),
102 /* Ogg Vorbis */
103 AFMT_ENTRY("Ogg", "vorbis.codec", NULL, NULL ),
104 /* FLAC */
105 AFMT_ENTRY("FLAC", "flac.codec", NULL, NULL ),
106 /* Musepack */
107 AFMT_ENTRY("MPC", "mpc.codec", NULL, NULL ),
108 /* A/52 (aka AC3) audio */
109 AFMT_ENTRY("AC3", "a52.codec", NULL, NULL ),
110 /* WavPack */
111 AFMT_ENTRY("WV", "wavpack.codec", "wavpack_enc.codec", ".wv" ),
112 /* Apple Lossless Audio Codec */
113 AFMT_ENTRY("ALAC", "alac.codec", NULL, NULL ),
114 /* Advanced Audio Coding in M4A container */
115 AFMT_ENTRY("AAC", "aac.codec", NULL, NULL ),
116 /* Shorten */
117 AFMT_ENTRY("SHN", "shorten.codec", NULL, NULL ),
118 /* Audio Interchange File Format */
119 AFMT_ENTRY("AIFF", "aiff.codec", NULL, NULL ),
120 /* SID File Format */
121 AFMT_ENTRY("SID", "sid.codec", NULL, NULL ),
122 /* ADX File Format */
123 AFMT_ENTRY("ADX", "adx.codec", NULL, NULL ),
124 #endif
127 #if CONFIG_CODEC == SWCODEC
128 /* recording quality to AFMT_* */
129 const int rec_quality_info_afmt[9] =
131 AFMT_MPA_L3, /* MPEG L3 64 kBit/s */
132 AFMT_MPA_L3, /* MPEG L3 96 kBit/s */
133 AFMT_MPA_L3, /* MPEG L3 128 kBit/s */
134 AFMT_MPA_L3, /* MPEG L3 160 kBit/s */
135 AFMT_MPA_L3, /* MPEG L3 192 kBit/s */
136 AFMT_MPA_L3, /* MPEG L3 224 kBit/s */
137 AFMT_MPA_L3, /* MPEG L3 320 kBit/s */
138 AFMT_WAVPACK, /* WavPack 909 kBit/s */
139 AFMT_PCM_WAV, /* PCM Wav 1411 kBit/s */
141 #endif /* SWCODEC */
143 char* id3_get_genre(const struct mp3entry* id3)
145 if( id3->genre_string )
146 return id3->genre_string ;
148 if (id3->genre < sizeof(genres)/sizeof(char*))
149 return (char*)genres[id3->genre];
150 return NULL;
153 char* id3_get_codec(const struct mp3entry* id3)
155 if (id3->codectype < AFMT_NUM_CODECS) {
156 return (char*)audio_formats[id3->codectype].label;
157 } else {
158 return NULL;
163 HOW TO ADD ADDITIONAL ID3 VERSION 2 TAGS
164 Code and comments by Thomas Paul Diffenbach
166 To add another ID3v2 Tag, do the following:
167 1. add a char* named for the tag to struct mp3entry in id3.h,
168 (I (tpd) prefer to use char* rather than ints, even for what seems like
169 numerical values, for cases where a number won't do, e.g.,
170 YEAR: "circa 1765", "1790/1977" (composed/performed), "28 Feb 1969"
171 TRACK: "1/12", "1 of 12", GENRE: "Freeform genre name"
172 Text is more flexible, and as the main use of id3 data is to
173 display it, converting it to an int just means reconverting to
174 display it, at a runtime cost.)
176 2. If any special processing beyond copying the tag value from the Id3
177 block to the struct mp3entry is rrequired (such as converting to an
178 int), write a function to perform this special processing.
180 This function's prototype must match that of
181 typedef tagPostProcessFunc, that is it must be:
182 int func( struct mp3entry*, char* tag, int bufferpos )
183 the first argument is a pointer to the current mp3entry structure the
184 second argument is a pointer to the null terminated string value of the
185 tag found the third argument is the offset of the next free byte in the
186 mp3entry's buffer your function should return the corrected offset; if
187 you don't lengthen or shorten the tag string, you can return the third
188 argument unchanged.
190 Unless you have a good reason no to, make the function static.
191 TO JUST COPY THE TAG NO SPECIAL PROCESSING FUNCTION IS NEEDED.
193 3. add one or more entries to the tagList array, using the format:
194 char* ID3 Tag symbolic name -- see the ID3 specification for these,
195 sizeof() that name minus 1,
196 offsetof( struct mp3entry, variable_name_in_struct_mp3entry ),
197 pointer to your special processing function or NULL
198 if you need no special processing
199 flag indicating if this tag is binary or textual
200 Many ID3 symbolic names come in more than one form. You can add both
201 forms, each referencing the same variable in struct mp3entry.
202 If both forms are present, the last found will be used.
203 Note that the offset can be zero, in which case no entry will be set
204 in the mp3entry struct; the frame is still read into the buffer and
205 the special processing function is called (several times, if there
206 are several frames with the same name).
208 4. Alternately, use the TAG_LIST_ENTRY macro with
209 ID3 tag symbolic name,
210 variable in struct mp3entry,
211 special processing function address
213 5. Add code to wps-display.c function get_tag to assign a printf-like
214 format specifier for the tag */
216 /* Structure for ID3 Tag extraction information */
217 struct tag_resolver {
218 const char* tag;
219 int tag_length;
220 size_t offset;
221 int (*ppFunc)(struct mp3entry*, char* tag, int bufferpos);
222 bool binary;
225 static bool global_ff_found;
227 static int unsynchronize(char* tag, int len, bool *ff_found)
229 int i;
230 unsigned char c;
231 unsigned char *rp, *wp;
233 wp = rp = (unsigned char *)tag;
235 rp = (unsigned char *)tag;
236 for(i = 0;i < len;i++) {
237 /* Read the next byte and write it back, but don't increment the
238 write pointer */
239 c = *rp++;
240 *wp = c;
241 if(*ff_found) {
242 /* Increment the write pointer if it isn't an unsynch pattern */
243 if(c != 0)
244 wp++;
245 *ff_found = false;
246 } else {
247 if(c == 0xff)
248 *ff_found = true;
249 wp++;
252 return (long)wp - (long)tag;
255 static int unsynchronize_frame(char* tag, int len)
257 bool ff_found = false;
259 return unsynchronize(tag, len, &ff_found);
262 static int read_unsynched(int fd, void *buf, int len)
264 int i;
265 int rc;
266 int remaining = len;
267 char *wp;
268 char *rp;
270 wp = buf;
272 while(remaining) {
273 rp = wp;
274 rc = read(fd, rp, remaining);
275 if(rc < 0)
276 return rc;
278 i = unsynchronize(wp, remaining, &global_ff_found);
279 remaining -= i;
280 wp += i;
283 return len;
286 static int skip_unsynched(int fd, int len)
288 int rc;
289 int remaining = len;
290 int rlen;
291 char buf[32];
293 while(remaining) {
294 rlen = MIN(sizeof(buf), (unsigned int)remaining);
295 rc = read(fd, buf, rlen);
296 if(rc < 0)
297 return rc;
299 remaining -= unsynchronize(buf, rlen, &global_ff_found);
302 return len;
305 /* parse numeric value from string */
306 static int parsetracknum( struct mp3entry* entry, char* tag, int bufferpos )
308 entry->tracknum = atoi( tag );
309 return bufferpos;
312 /* parse numeric value from string */
313 static int parseyearnum( struct mp3entry* entry, char* tag, int bufferpos )
315 entry->year = atoi( tag );
316 return bufferpos;
319 /* parse numeric genre from string, version 2.2 and 2.3 */
320 static int parsegenre( struct mp3entry* entry, char* tag, int bufferpos )
322 if(entry->id3version >= ID3_VER_2_4) {
323 /* In version 2.4 and up, there are no parentheses, and the genre frame
324 is a list of strings, either numbers or text. */
326 /* Is it a number? */
327 if(isdigit(tag[0])) {
328 entry->genre = atoi( tag );
329 entry->genre_string = 0;
330 return tag - entry->id3v2buf;
331 } else {
332 entry->genre_string = tag;
333 entry->genre = 0xff;
334 return bufferpos;
336 } else {
337 if( tag[0] == '(' && tag[1] != '(' ) {
338 entry->genre = atoi( tag + 1 );
339 entry->genre_string = 0;
340 return tag - entry->id3v2buf;
342 else {
343 entry->genre_string = tag;
344 entry->genre = 0xff;
345 return bufferpos;
350 #if CONFIG_CODEC == SWCODEC
351 /* parse user defined text, looking for replaygain information. */
352 static int parseuser( struct mp3entry* entry, char* tag, int bufferpos )
354 char* value = NULL;
355 int desc_len = strlen(tag);
356 int value_len = 0;
358 /* Note: for ID3v2.4, parse_replaygain will not overwrite replaygain
359 values already parsed from RVA2 tags */
360 if ((tag - entry->id3v2buf + desc_len + 2) < bufferpos) {
361 /* At least part of the value was read, so we can safely try to
362 * parse it
364 value = tag + desc_len + 1;
365 value_len = parse_replaygain(tag, value, entry, tag,
366 bufferpos - (tag - entry->id3v2buf));
369 if (value_len) {
370 bufferpos = tag - entry->id3v2buf + value_len;
371 } else {
372 bufferpos = tag - entry->id3v2buf;
375 return bufferpos;
378 /* parse RVA2 binary data and convert to replaygain information. */
379 static int parserva2( struct mp3entry* entry, char* tag, int bufferpos )
381 char* value = NULL;
382 int desc_len = strlen(tag);
383 int value_len = 0;
385 /* Only parse RVA2 replaygain tags if tag version == 2.4 */
386 if (entry->id3version == ID3_VER_2_4 &&
387 (tag - entry->id3v2buf + desc_len + 2) < bufferpos) {
388 value = tag + desc_len + 1;
389 value_len = parse_replaygain_rva(tag, value, entry, tag,
390 bufferpos - (tag - entry->id3v2buf));
393 if (value_len) {
394 bufferpos = tag - entry->id3v2buf + value_len;
395 } else {
396 bufferpos = tag - entry->id3v2buf;
399 return bufferpos;
401 #endif
403 static const struct tag_resolver taglist[] = {
404 { "TPE1", 4, offsetof(struct mp3entry, artist), NULL, false },
405 { "TP1", 3, offsetof(struct mp3entry, artist), NULL, false },
406 { "TIT2", 4, offsetof(struct mp3entry, title), NULL, false },
407 { "TT2", 3, offsetof(struct mp3entry, title), NULL, false },
408 { "TALB", 4, offsetof(struct mp3entry, album), NULL, false },
409 { "TAL", 3, offsetof(struct mp3entry, album), NULL, false },
410 { "TRK", 3, offsetof(struct mp3entry, track_string), &parsetracknum, false },
411 { "TRCK", 4, offsetof(struct mp3entry, track_string), &parsetracknum, false },
412 { "TDRC", 4, offsetof(struct mp3entry, year_string), &parseyearnum, false },
413 { "TYER", 4, offsetof(struct mp3entry, year_string), &parseyearnum, false },
414 { "TYE", 3, offsetof(struct mp3entry, year_string), &parseyearnum, false },
415 { "TCOM", 4, offsetof(struct mp3entry, composer), NULL, false },
416 { "TCON", 4, offsetof(struct mp3entry, genre_string), &parsegenre, false },
417 { "TCO", 3, offsetof(struct mp3entry, genre_string), &parsegenre, false },
418 #if CONFIG_CODEC == SWCODEC
419 { "TXXX", 4, 0, &parseuser, false },
420 { "RVA2", 4, 0, &parserva2, true },
421 #endif
424 #define TAGLIST_SIZE ((int)(sizeof(taglist) / sizeof(taglist[0])))
426 /* Checks to see if the passed in string is a 16-bit wide Unicode v2
427 string. If it is, we convert it to a UTF-8 string. If it's not unicode,
428 we convert from the default codepage */
429 static int unicode_munge(char* string, char* utf8buf, int *len) {
430 long tmp;
431 bool le = false;
432 int i = 0;
433 char *str = string;
434 int templen = 0;
435 char* utf8 = utf8buf;
437 switch (str[0]) {
438 case 0x00: /* Type 0x00 is ordinary ISO 8859-1 */
439 str++;
440 (*len)--;
441 utf8 = iso_decode(str, utf8, -1, *len);
442 *utf8 = 0;
443 *len = utf8 - utf8buf;
444 break;
446 case 0x01: /* Unicode with or without BOM */
447 case 0x02:
448 (*len)--;
449 str++;
451 /* Handle frames with more than one string
452 (needed for TXXX frames).*/
453 do {
454 tmp = BYTES2INT(0, 0, str[0], str[1]);
456 /* Now check if there is a BOM
457 (zero-width non-breaking space, 0xfeff)
458 and if it is in little or big endian format */
459 if(tmp == 0xfffe) { /* Little endian? */
460 le = true;
461 str += 2;
462 (*len)-=2;
463 } else if(tmp == 0xfeff) { /* Big endian? */
464 str += 2;
465 (*len)-=2;
466 } else
467 /* If there is no BOM (which is a specification violation),
468 let's try to guess it. If one of the bytes is 0x00, it is
469 probably the most significant one. */
470 if(str[1] == 0)
471 le = true;
473 do {
474 if(le)
475 utf8 = utf16LEdecode(str, utf8, 1);
476 else
477 utf8 = utf16BEdecode(str, utf8, 1);
479 str+=2;
480 i += 2;
481 } while((str[0] || str[1]) && (i < *len));
483 *utf8++ = 0; /* Terminate the string */
484 templen += (strlen(&utf8buf[templen]) + 1);
485 str += 2;
486 i+=2;
487 } while(i < *len);
488 *len = templen - 1;
489 break;
491 case 0x03: /* UTF-8 encoded string */
492 for(i=0; i < *len; i++)
493 utf8[i] = str[i+1];
494 (*len)--;
495 break;
497 default: /* Plain old string */
498 utf8 = iso_decode(str, utf8, -1, *len);
499 *utf8 = 0;
500 *len = utf8 - utf8buf;
501 break;
503 return 0;
507 * Sets the title of an MP3 entry based on its ID3v1 tag.
509 * Arguments: file - the MP3 file to scen for a ID3v1 tag
510 * entry - the entry to set the title in
512 * Returns: true if a title was found and created, else false
514 static bool setid3v1title(int fd, struct mp3entry *entry)
516 unsigned char buffer[128];
517 static const char offsets[] = {3, 33, 63, 93, 125, 127};
518 int i, j;
519 unsigned char* utf8;
521 if (-1 == lseek(fd, -128, SEEK_END))
522 return false;
524 if (read(fd, buffer, sizeof buffer) != sizeof buffer)
525 return false;
527 if (strncmp((char *)buffer, "TAG", 3))
528 return false;
530 entry->id3v1len = 128;
531 entry->id3version = ID3_VER_1_0;
533 for (i=0; i < (int)sizeof offsets; i++) {
534 unsigned char* ptr = (unsigned char *)buffer + offsets[i];
536 if (i<3) {
537 /* kill trailing space in strings */
538 for (j=29; j && ptr[j]==' '; j--)
539 ptr[j] = 0;
542 switch(i) {
543 case 0:
544 case 1:
545 case 2:
546 /* convert string to utf8 */
547 utf8 = entry->id3v1buf[i];
548 utf8 = iso_decode(ptr, utf8, -1, 30);
549 /* make sure string is terminated */
550 *utf8 = 0;
551 break;
553 case 3:
554 ptr[4] = 0;
555 entry->year = atoi(ptr);
556 break;
558 case 4:
559 /* id3v1.1 uses last two bytes of comment field for track
560 number: first must be 0 and second is track num */
561 if (!ptr[0] && ptr[1]) {
562 entry->tracknum = ptr[1];
563 entry->id3version = ID3_VER_1_1;
565 break;
567 case 5:
568 /* genre */
569 entry->genre = ptr[0];
570 break;
574 entry->title = entry->id3v1buf[0];
575 entry->artist = entry->id3v1buf[1];
576 entry->album = entry->id3v1buf[2];
578 return true;
583 * Sets the title of an MP3 entry based on its ID3v2 tag.
585 * Arguments: file - the MP3 file to scan for a ID3v2 tag
586 * entry - the entry to set the title in
588 * Returns: true if a title was found and created, else false
590 static void setid3v2title(int fd, struct mp3entry *entry)
592 int minframesize;
593 int size;
594 long bufferpos = 0, totframelen, framelen;
595 char header[10];
596 char tmp[4];
597 unsigned char version;
598 char *buffer = entry->id3v2buf;
599 int bytesread = 0;
600 int buffersize = sizeof(entry->id3v2buf);
601 unsigned char global_flags;
602 int flags;
603 int skip;
604 bool global_unsynch = false;
605 bool unsynch = false;
606 int data_length_ind;
607 int i, j;
608 int rc;
610 global_ff_found = false;
612 /* Bail out if the tag is shorter than 10 bytes */
613 if(entry->id3v2len < 10)
614 return;
616 /* Read the ID3 tag version from the header */
617 lseek(fd, 0, SEEK_SET);
618 if(10 != read(fd, header, 10))
619 return;
621 /* Get the total ID3 tag size */
622 size = entry->id3v2len - 10;
624 version = header[3];
625 switch ( version ) {
626 case 2:
627 version = ID3_VER_2_2;
628 minframesize = 8;
629 break;
631 case 3:
632 version = ID3_VER_2_3;
633 minframesize = 12;
634 break;
636 case 4:
637 version = ID3_VER_2_4;
638 minframesize = 12;
639 break;
641 default:
642 /* unsupported id3 version */
643 return;
645 entry->id3version = version;
646 entry->tracknum = entry->year = 0;
647 entry->genre = 0xff;
648 entry->title = entry->artist = entry->album = NULL;
650 global_flags = header[5];
652 /* Skip the extended header if it is present */
653 if(global_flags & 0x40) {
654 if(version == ID3_VER_2_3) {
655 if(10 != read(fd, header, 10))
656 return;
657 /* The 2.3 extended header size doesn't include the following
658 data, so we have to find out the size by checking the flags.
659 Also, it is not unsynched. */
660 framelen = BYTES2INT(header[0], header[1], header[2], header[3]) +
661 BYTES2INT(header[6], header[7], header[8], header[9]);
662 flags = BYTES2INT(0, 0, header[4], header[5]);
663 if(flags & 0x8000)
664 framelen += 4; /* CRC */
666 lseek(fd, framelen - 10, SEEK_CUR);
669 if(version >= ID3_VER_2_4) {
670 if(4 != read(fd, header, 4))
671 return;
673 /* The 2.4 extended header size does include the entire header,
674 so here we can just skip it. This header is unsynched. */
675 framelen = UNSYNC(header[0], header[1],
676 header[2], header[3]);
678 lseek(fd, framelen - 4, SEEK_CUR);
682 /* Is unsynchronization applied? */
683 if(global_flags & 0x80) {
684 global_unsynch = true;
688 * We must have at least minframesize bytes left for the
689 * remaining frames to be interesting
691 while (size >= minframesize && bufferpos < buffersize - 1) {
692 flags = 0;
694 /* Read frame header and check length */
695 if(version >= ID3_VER_2_3) {
696 if(global_unsynch && version <= ID3_VER_2_3)
697 rc = read_unsynched(fd, header, 10);
698 else
699 rc = read(fd, header, 10);
700 if(rc != 10)
701 return;
702 /* Adjust for the 10 bytes we read */
703 size -= 10;
705 flags = BYTES2INT(0, 0, header[8], header[9]);
707 if (version >= ID3_VER_2_4) {
708 framelen = UNSYNC(header[4], header[5],
709 header[6], header[7]);
710 } else {
711 /* version .3 files don't use synchsafe ints for
712 * size */
713 framelen = BYTES2INT(header[4], header[5],
714 header[6], header[7]);
716 } else {
717 if(6 != read(fd, header, 6))
718 return;
719 /* Adjust for the 6 bytes we read */
720 size -= 6;
722 framelen = BYTES2INT(0, header[3], header[4], header[5]);
725 /* Keep track of the total size */
726 totframelen = framelen;
728 DEBUGF("framelen = %d\n", framelen);
729 if(framelen == 0){
730 if (header[0] == 0 && header[1] == 0 && header[2] == 0)
731 return;
732 else
733 continue;
736 unsynch = false;
737 data_length_ind = 0;
739 if(flags)
741 skip = 0;
743 if (version >= ID3_VER_2_4) {
744 if(flags & 0x0040) { /* Grouping identity */
745 lseek(fd, 1, SEEK_CUR); /* Skip 1 byte */
746 framelen--;
748 } else {
749 if(flags & 0x0020) { /* Grouping identity */
750 lseek(fd, 1, SEEK_CUR); /* Skip 1 byte */
751 framelen--;
755 if(flags & 0x000c) /* Compression or encryption */
757 /* Skip it using the total size in case
758 it was truncated */
759 size -= totframelen;
760 lseek(fd, totframelen, SEEK_CUR);
761 continue;
764 if(flags & 0x0002) /* Unsynchronization */
765 unsynch = true;
767 if (version >= ID3_VER_2_4) {
768 if(flags & 0x0001) { /* Data length indicator */
769 if(4 != read(fd, tmp, 4))
770 return;
772 data_length_ind = UNSYNC(tmp[0], tmp[1], tmp[2], tmp[3]);
773 framelen -= 4;
778 /* If the frame is larger than the remaining buffer space we try
779 to read as much as would fit in the buffer */
780 if(framelen >= buffersize - bufferpos)
781 framelen = buffersize - bufferpos - 1;
783 DEBUGF("id3v2 frame: %.4s\n", header);
785 /* Check for certain frame headers
787 'size' is the amount of frame bytes remaining. We decrement it by
788 the amount of bytes we read. If we fail to read as many bytes as
789 we expect, we assume that we can't read from this file, and bail
790 out.
792 For each frame. we will iterate over the list of supported tags,
793 and read the tag into entry's buffer. All tags will be kept as
794 strings, for cases where a number won't do, e.g., YEAR: "circa
795 1765", "1790/1977" (composed/performed), "28 Feb 1969" TRACK:
796 "1/12", "1 of 12", GENRE: "Freeform genre name" Text is more
797 flexible, and as the main use of id3 data is to display it,
798 converting it to an int just means reconverting to display it, at a
799 runtime cost.
801 For tags that the current code does convert to ints, a post
802 processing function will be called via a pointer to function. */
804 for (i=0; i<TAGLIST_SIZE; i++) {
805 const struct tag_resolver* tr = &taglist[i];
806 char** ptag = tr->offset ? (char**) (((char*)entry) + tr->offset)
807 : NULL;
808 char* tag;
810 /* Only ID3_VER_2_2 uses frames with three-character names. */
811 if (((version == ID3_VER_2_2) && (tr->tag_length != 3))
812 || ((version > ID3_VER_2_2) && (tr->tag_length != 4))) {
813 continue;
816 /* Note that parser functions sometimes set *ptag to NULL, so
817 * the "!*ptag" check here doesn't always have the desired
818 * effect. Should the parser functions (parsegenre in
819 * particular) be updated to handle the case of being called
820 * multiple times, or should the "*ptag" check be removed?
822 if( (!ptag || !*ptag) && !memcmp( header, tr->tag, tr->tag_length ) ) {
824 /* found a tag matching one in tagList, and not yet filled */
825 tag = buffer + bufferpos;
827 if(global_unsynch && version <= ID3_VER_2_3)
828 bytesread = read_unsynched(fd, tag, framelen);
829 else
830 bytesread = read(fd, tag, framelen);
832 if( bytesread != framelen )
833 return;
835 size -= bytesread;
837 if(unsynch || (global_unsynch && version >= ID3_VER_2_4))
838 bytesread = unsynchronize_frame(tag, bytesread);
840 /* Attempt to parse Unicode string only if the tag contents
841 aren't binary */
842 if(!tr->binary) {
843 /* UTF-8 could potentially be 3 times larger */
844 /* so we need to create a new buffer */
845 char utf8buf[(3 * bytesread) + 1];
847 unicode_munge( tag, utf8buf, &bytesread );
849 if(bytesread >= buffersize - bufferpos)
850 bytesread = buffersize - bufferpos - 1;
852 for (j = 0; j < bytesread; j++)
853 tag[j] = utf8buf[j];
855 /* remove trailing spaces */
856 while ( bytesread > 0 && isspace(tag[bytesread-1]))
857 bytesread--;
860 tag[bytesread] = 0;
861 bufferpos += bytesread + 1;
863 if (ptag)
864 *ptag = tag;
866 if( tr->ppFunc )
867 bufferpos = tr->ppFunc(entry, tag, bufferpos);
869 /* Seek to the next frame */
870 if(framelen < totframelen)
871 lseek(fd, totframelen - framelen, SEEK_CUR);
872 break;
876 if( i == TAGLIST_SIZE ) {
877 /* no tag in tagList was found, or it was a repeat.
878 skip it using the total size */
880 if(global_unsynch && version <= ID3_VER_2_3) {
881 size -= skip_unsynched(fd, totframelen);
882 } else {
883 if(data_length_ind)
884 totframelen = data_length_ind;
886 size -= totframelen;
887 if( lseek(fd, totframelen, SEEK_CUR) == -1 )
888 return;
895 * Calculates the size of the ID3v2 tag.
897 * Arguments: file - the file to search for a tag.
899 * Returns: the size of the tag or 0 if none was found
901 int getid3v2len(int fd)
903 char buf[6];
904 int offset;
906 /* Make sure file has a ID3 tag */
907 if((-1 == lseek(fd, 0, SEEK_SET)) ||
908 (read(fd, buf, 6) != 6) ||
909 (strncmp(buf, "ID3", strlen("ID3")) != 0))
910 offset = 0;
912 /* Now check what the ID3v2 size field says */
913 else
914 if(read(fd, buf, 4) != 4)
915 offset = 0;
916 else
917 offset = UNSYNC(buf[0], buf[1], buf[2], buf[3]) + 10;
919 DEBUGF("ID3V2 Length: 0x%x\n", offset);
920 return offset;
924 * Calculates the length (in milliseconds) of an MP3 file.
926 * Modified to only use integers.
928 * Arguments: file - the file to calculate the length upon
929 * entry - the entry to update with the length
931 * Returns: the song length in milliseconds,
932 * 0 means that it couldn't be calculated
934 static int getsonglength(int fd, struct mp3entry *entry)
936 unsigned long filetime = 0;
937 struct mp3info info;
938 long bytecount;
940 /* Start searching after ID3v2 header */
941 if(-1 == lseek(fd, entry->id3v2len, SEEK_SET))
942 return 0;
944 bytecount = get_mp3file_info(fd, &info);
946 DEBUGF("Space between ID3V2 tag and first audio frame: 0x%x bytes\n",
947 bytecount);
949 if(bytecount < 0)
950 return -1;
952 bytecount += entry->id3v2len;
954 /* Validate byte count, in case the file has been edited without
955 * updating the header.
957 if (info.byte_count)
959 const unsigned long expected = entry->filesize - entry->id3v1len
960 - entry->id3v2len;
961 const unsigned long diff = MAX(10240, info.byte_count / 20);
963 if ((info.byte_count > expected + diff)
964 || (info.byte_count < expected - diff))
966 DEBUGF("Note: info.byte_count differs from expected value by "
967 "%d bytes\n", labs((long) (expected - info.byte_count)));
968 info.byte_count = 0;
969 info.frame_count = 0;
970 info.file_time = 0;
971 info.enc_padding = 0;
973 /* Even if the bitrate was based on "known bad" values, it
974 * should still be better for VBR files than using the bitrate
975 * of the first audio frame.
980 entry->bitrate = info.bitrate;
981 entry->frequency = info.frequency;
982 entry->version = info.version;
983 entry->layer = info.layer;
984 switch(entry->layer) {
985 #if CONFIG_CODEC==SWCODEC
986 case 0:
987 entry->codectype=AFMT_MPA_L1;
988 break;
989 #endif
990 case 1:
991 entry->codectype=AFMT_MPA_L2;
992 break;
993 case 2:
994 entry->codectype=AFMT_MPA_L3;
995 break;
998 /* If the file time hasn't been established, this may be a fixed
999 rate MP3, so just use the default formula */
1001 filetime = info.file_time;
1003 if(filetime == 0)
1005 /* Prevent a division by zero */
1006 if (info.bitrate < 8)
1007 filetime = 0;
1008 else
1009 filetime = (entry->filesize - bytecount) / (info.bitrate / 8);
1010 /* bitrate is in kbps so this delivers milliseconds. Doing bitrate / 8
1011 * instead of filesize * 8 is exact, because mpeg audio bitrates are
1012 * always multiples of 8, and it avoids overflows. */
1015 entry->frame_count = info.frame_count;
1017 entry->vbr = info.is_vbr;
1018 entry->has_toc = info.has_toc;
1020 entry->lead_trim = info.enc_delay;
1021 entry->tail_trim = info.enc_padding;
1023 memcpy(entry->toc, info.toc, sizeof(info.toc));
1025 entry->vbr_header_pos = info.vbr_header_pos;
1027 /* Update the seek point for the first playable frame */
1028 entry->first_frame_offset = bytecount;
1029 DEBUGF("First frame is at %x\n", entry->first_frame_offset);
1031 return filetime;
1035 * Checks all relevant information (such as ID3v1 tag, ID3v2 tag, length etc)
1036 * about an MP3 file and updates it's entry accordingly.
1038 Note, that this returns true for successful, false for error! */
1039 bool get_mp3_metadata(int fd, struct mp3entry *entry, const char *filename, bool v1first)
1041 int v1found = false;
1043 #if CONFIG_CODEC != SWCODEC
1044 memset(entry, 0, sizeof(struct mp3entry));
1045 #endif
1047 strncpy(entry->path, filename, sizeof(entry->path));
1049 entry->title = NULL;
1050 entry->filesize = filesize(fd);
1051 entry->id3v2len = getid3v2len(fd);
1052 entry->tracknum = 0;
1053 entry->genre = 0xff;
1055 if(v1first)
1056 v1found = setid3v1title(fd, entry);
1058 if (!v1found && entry->id3v2len)
1059 setid3v2title(fd, entry);
1060 entry->length = getsonglength(fd, entry);
1062 /* Subtract the meta information from the file size to get
1063 the true size of the MP3 stream */
1064 entry->filesize -= entry->first_frame_offset;
1066 /* only seek to end of file if no id3v2 tags were found,
1067 and we already haven't looked for a v1 tag */
1068 if (!v1first && !entry->id3v2len) {
1069 setid3v1title(fd, entry);
1072 if(!entry->length || (entry->filesize < 8 ))
1073 /* no song length or less than 8 bytes is hereby considered to be an
1074 invalid mp3 and won't be played by us! */
1075 return false;
1077 return true;
1080 /* Note, that this returns false for successful, true for error! */
1081 bool mp3info(struct mp3entry *entry, const char *filename, bool v1first)
1083 int fd;
1084 bool result;
1086 fd = open(filename, O_RDONLY);
1087 if (fd < 0)
1088 return true;
1090 result = !get_mp3_metadata(fd, entry, filename, v1first);
1092 close(fd);
1094 return result;
1097 void adjust_mp3entry(struct mp3entry *entry, void *dest, void *orig)
1099 long offset;
1100 if (orig > dest)
1101 offset = - ((size_t)orig - (size_t)dest);
1102 else
1103 offset = (size_t)dest - (size_t)orig;
1105 if (entry->title)
1106 entry->title += offset;
1107 if (entry->artist)
1108 entry->artist += offset;
1109 if (entry->album)
1110 entry->album += offset;
1111 if (entry->genre_string)
1112 entry->genre_string += offset;
1113 if (entry->track_string)
1114 entry->track_string += offset;
1115 if (entry->year_string)
1116 entry->year_string += offset;
1117 if (entry->composer)
1118 entry->composer += offset;
1119 #if CONFIG_CODEC == SWCODEC
1120 if (entry->track_gain_string)
1121 entry->track_gain_string += offset;
1122 if (entry->album_gain_string)
1123 entry->album_gain_string += offset;
1124 #endif
1127 void copy_mp3entry(struct mp3entry *dest, struct mp3entry *orig)
1129 memcpy(dest, orig, sizeof(struct mp3entry));
1130 adjust_mp3entry(dest, dest, orig);
1133 #ifdef DEBUG_STANDALONE
1135 char *secs2str(int ms)
1137 static char buffer[32];
1138 int secs = ms/1000;
1139 ms %= 1000;
1140 snprintf(buffer, sizeof(buffer), "%d:%02d.%d", secs/60, secs%60, ms/100);
1141 return buffer;
1144 int main(int argc, char **argv)
1146 int i;
1147 for(i=1; i<argc; i++) {
1148 struct mp3entry mp3;
1149 mp3.album = "Bogus";
1150 if(mp3info(&mp3, argv[i], false)) {
1151 printf("Failed to get %s\n", argv[i]);
1152 return 0;
1155 printf("****** File: %s\n"
1156 " Title: %s\n"
1157 " Artist: %s\n"
1158 " Album: %s\n"
1159 " Genre: %s (%d) \n"
1160 " Composer: %s\n"
1161 " Year: %s (%d)\n"
1162 " Track: %s (%d)\n"
1163 " Length: %s / %d s\n"
1164 " Bitrate: %d\n"
1165 " Frequency: %d\n",
1166 argv[i],
1167 mp3.title?mp3.title:"<blank>",
1168 mp3.artist?mp3.artist:"<blank>",
1169 mp3.album?mp3.album:"<blank>",
1170 mp3.genre_string?mp3.genre_string:"<blank>",
1171 mp3.genre,
1172 mp3.composer?mp3.composer:"<blank>",
1173 mp3.year_string?mp3.year_string:"<blank>",
1174 mp3.year,
1175 mp3.track_string?mp3.track_string:"<blank>",
1176 mp3.tracknum,
1177 secs2str(mp3.length),
1178 mp3.length/1000,
1179 mp3.bitrate,
1180 mp3.frequency);
1183 return 0;
1186 #endif