1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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
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",
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"),
103 AFMT_ENTRY("Ogg", "vorbis.codec", NULL
, NULL
),
105 AFMT_ENTRY("FLAC", "flac.codec", NULL
, NULL
),
107 AFMT_ENTRY("MPC", "mpc.codec", NULL
, NULL
),
108 /* A/52 (aka AC3) audio */
109 AFMT_ENTRY("AC3", "a52.codec", NULL
, NULL
),
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
),
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
),
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 */
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
];
153 char* id3_get_codec(const struct mp3entry
* id3
)
155 if (id3
->codectype
< AFMT_NUM_CODECS
) {
156 return (char*)audio_formats
[id3
->codectype
].label
;
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
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
{
221 int (*ppFunc
)(struct mp3entry
*, char* tag
, int bufferpos
);
225 static bool global_ff_found
;
227 static int unsynchronize(char* tag
, int len
, bool *ff_found
)
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
242 /* Increment the write pointer if it isn't an unsynch pattern */
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
)
274 rc
= read(fd
, rp
, remaining
);
278 i
= unsynchronize(wp
, remaining
, &global_ff_found
);
286 static int skip_unsynched(int fd
, int len
)
294 rlen
= MIN(sizeof(buf
), (unsigned int)remaining
);
295 rc
= read(fd
, buf
, rlen
);
299 remaining
-= unsynchronize(buf
, rlen
, &global_ff_found
);
305 /* parse numeric value from string */
306 static int parsetracknum( struct mp3entry
* entry
, char* tag
, int bufferpos
)
308 entry
->tracknum
= atoi( tag
);
312 /* parse numeric value from string */
313 static int parseyearnum( struct mp3entry
* entry
, char* tag
, int bufferpos
)
315 entry
->year
= atoi( tag
);
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
;
332 entry
->genre_string
= tag
;
337 if( tag
[0] == '(' && tag
[1] != '(' ) {
338 entry
->genre
= atoi( tag
+ 1 );
339 entry
->genre_string
= 0;
340 return tag
- entry
->id3v2buf
;
343 entry
->genre_string
= tag
;
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
)
355 int desc_len
= strlen(tag
);
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
364 value
= tag
+ desc_len
+ 1;
365 value_len
= parse_replaygain(tag
, value
, entry
, tag
,
366 bufferpos
- (tag
- entry
->id3v2buf
));
370 bufferpos
= tag
- entry
->id3v2buf
+ value_len
;
372 bufferpos
= tag
- entry
->id3v2buf
;
378 /* parse RVA2 binary data and convert to replaygain information. */
379 static int parserva2( struct mp3entry
* entry
, char* tag
, int bufferpos
)
382 int desc_len
= strlen(tag
);
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
));
394 bufferpos
= tag
- entry
->id3v2buf
+ value_len
;
396 bufferpos
= tag
- entry
->id3v2buf
;
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 },
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
) {
435 char* utf8
= utf8buf
;
438 case 0x00: /* Type 0x00 is ordinary ISO 8859-1 */
441 utf8
= iso_decode(str
, utf8
, -1, *len
);
443 *len
= utf8
- utf8buf
;
446 case 0x01: /* Unicode with or without BOM */
451 /* Handle frames with more than one string
452 (needed for TXXX frames).*/
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? */
463 } else if(tmp
== 0xfeff) { /* Big endian? */
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. */
475 utf8
= utf16LEdecode(str
, utf8
, 1);
477 utf8
= utf16BEdecode(str
, utf8
, 1);
481 } while((str
[0] || str
[1]) && (i
< *len
));
483 *utf8
++ = 0; /* Terminate the string */
484 templen
+= (strlen(&utf8buf
[templen
]) + 1);
491 case 0x03: /* UTF-8 encoded string */
492 for(i
=0; i
< *len
; i
++)
497 default: /* Plain old string */
498 utf8
= iso_decode(str
, utf8
, -1, *len
);
500 *len
= utf8
- utf8buf
;
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};
521 if (-1 == lseek(fd
, -128, SEEK_END
))
524 if (read(fd
, buffer
, sizeof buffer
) != sizeof buffer
)
527 if (strncmp((char *)buffer
, "TAG", 3))
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
];
537 /* kill trailing space in strings */
538 for (j
=29; j
&& ptr
[j
]==' '; j
--)
546 /* convert string to utf8 */
547 utf8
= entry
->id3v1buf
[i
];
548 utf8
= iso_decode(ptr
, utf8
, -1, 30);
549 /* make sure string is terminated */
555 entry
->year
= atoi(ptr
);
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
;
569 entry
->genre
= ptr
[0];
574 entry
->title
= entry
->id3v1buf
[0];
575 entry
->artist
= entry
->id3v1buf
[1];
576 entry
->album
= entry
->id3v1buf
[2];
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
)
594 long bufferpos
= 0, totframelen
, framelen
;
597 unsigned char version
;
598 char *buffer
= entry
->id3v2buf
;
600 int buffersize
= sizeof(entry
->id3v2buf
);
601 unsigned char global_flags
;
604 bool global_unsynch
= false;
605 bool unsynch
= false;
610 global_ff_found
= false;
612 /* Bail out if the tag is shorter than 10 bytes */
613 if(entry
->id3v2len
< 10)
616 /* Read the ID3 tag version from the header */
617 lseek(fd
, 0, SEEK_SET
);
618 if(10 != read(fd
, header
, 10))
621 /* Get the total ID3 tag size */
622 size
= entry
->id3v2len
- 10;
627 version
= ID3_VER_2_2
;
632 version
= ID3_VER_2_3
;
637 version
= ID3_VER_2_4
;
642 /* unsupported id3 version */
645 entry
->id3version
= version
;
646 entry
->tracknum
= entry
->year
= 0;
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))
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]);
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))
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) {
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);
699 rc
= read(fd
, header
, 10);
702 /* Adjust for the 10 bytes we read */
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]);
711 /* version .3 files don't use synchsafe ints for
713 framelen
= BYTES2INT(header
[4], header
[5],
714 header
[6], header
[7]);
717 if(6 != read(fd
, header
, 6))
719 /* Adjust for the 6 bytes we read */
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
);
730 if (header
[0] == 0 && header
[1] == 0 && header
[2] == 0)
743 if (version
>= ID3_VER_2_4
) {
744 if(flags
& 0x0040) { /* Grouping identity */
745 lseek(fd
, 1, SEEK_CUR
); /* Skip 1 byte */
749 if(flags
& 0x0020) { /* Grouping identity */
750 lseek(fd
, 1, SEEK_CUR
); /* Skip 1 byte */
755 if(flags
& 0x000c) /* Compression or encryption */
757 /* Skip it using the total size in case
760 lseek(fd
, totframelen
, SEEK_CUR
);
764 if(flags
& 0x0002) /* Unsynchronization */
767 if (version
>= ID3_VER_2_4
) {
768 if(flags
& 0x0001) { /* Data length indicator */
769 if(4 != read(fd
, tmp
, 4))
772 data_length_ind
= UNSYNC(tmp
[0], tmp
[1], tmp
[2], tmp
[3]);
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
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
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
)
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))) {
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
);
830 bytesread
= read(fd
, tag
, framelen
);
832 if( bytesread
!= framelen
)
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
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
++)
855 /* remove trailing spaces */
856 while ( bytesread
> 0 && isspace(tag
[bytesread
-1]))
861 bufferpos
+= bytesread
+ 1;
867 bufferpos
= tr
->ppFunc(entry
, tag
, bufferpos
);
869 /* Seek to the next frame */
870 if(framelen
< totframelen
)
871 lseek(fd
, totframelen
- framelen
, SEEK_CUR
);
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
);
884 totframelen
= data_length_ind
;
887 if( lseek(fd
, totframelen
, SEEK_CUR
) == -1 )
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
)
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))
912 /* Now check what the ID3v2 size field says */
914 if(read(fd
, buf
, 4) != 4)
917 offset
= UNSYNC(buf
[0], buf
[1], buf
[2], buf
[3]) + 10;
919 DEBUGF("ID3V2 Length: 0x%x\n", 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;
940 /* Start searching after ID3v2 header */
941 if(-1 == lseek(fd
, entry
->id3v2len
, SEEK_SET
))
944 bytecount
= get_mp3file_info(fd
, &info
);
946 DEBUGF("Space between ID3V2 tag and first audio frame: 0x%x bytes\n",
952 bytecount
+= entry
->id3v2len
;
954 /* Validate byte count, in case the file has been edited without
955 * updating the header.
959 const unsigned long expected
= entry
->filesize
- entry
->id3v1len
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
)));
969 info
.frame_count
= 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
987 entry
->codectype
=AFMT_MPA_L1
;
991 entry
->codectype
=AFMT_MPA_L2
;
994 entry
->codectype
=AFMT_MPA_L3
;
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
;
1005 /* Prevent a division by zero */
1006 if (info
.bitrate
< 8)
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
);
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
));
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;
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! */
1080 /* Note, that this returns false for successful, true for error! */
1081 bool mp3info(struct mp3entry
*entry
, const char *filename
, bool v1first
)
1086 fd
= open(filename
, O_RDONLY
);
1090 result
= !get_mp3_metadata(fd
, entry
, filename
, v1first
);
1097 void adjust_mp3entry(struct mp3entry
*entry
, void *dest
, void *orig
)
1101 offset
= - ((size_t)orig
- (size_t)dest
);
1103 offset
= (size_t)dest
- (size_t)orig
;
1106 entry
->title
+= offset
;
1108 entry
->artist
+= offset
;
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
;
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];
1140 snprintf(buffer
, sizeof(buffer
), "%d:%02d.%d", secs
/60, secs
%60, ms
/100);
1144 int main(int argc
, char **argv
)
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
]);
1155 printf("****** File: %s\n"
1159 " Genre: %s (%d) \n"
1163 " Length: %s / %d s\n"
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>",
1172 mp3
.composer
?mp3
.composer
:"<blank>",
1173 mp3
.year_string
?mp3
.year_string
:"<blank>",
1175 mp3
.track_string
?mp3
.track_string
:"<blank>",
1177 secs2str(mp3
.length
),