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 static const char* const codec_labels
[] = {
89 "???", /* Unknown file format */
91 "MP1", /* MPEG Audio layer 1 */
92 "MP2", /* MPEG Audio layer 2 */
93 "MP3", /* MPEG Audio layer 3 */
95 #if CONFIG_CODEC == SWCODEC
96 "WAV", /* Uncompressed PCM in a WAV file */
97 "Ogg", /* Ogg Vorbis */
100 "AC3", /* A/52 (aka AC3) audio */
102 "ALAC", /* Apple Lossless Audio Codec */
103 "AAC", /* Advanced Audio Coding in M4A container */
105 "AIFF", /* Audio Interchange File Format */
106 "SID", /* SID File Format */
110 char* id3_get_genre(const struct mp3entry
* id3
)
112 if( id3
->genre_string
)
113 return id3
->genre_string
;
115 if (id3
->genre
< sizeof(genres
)/sizeof(char*))
116 return (char*)genres
[id3
->genre
];
120 char* id3_get_codec(const struct mp3entry
* id3
)
122 if (id3
->codectype
< sizeof(codec_labels
)/sizeof(char*)) {
123 return (char*)codec_labels
[id3
->codectype
];
130 HOW TO ADD ADDITIONAL ID3 VERSION 2 TAGS
131 Code and comments by Thomas Paul Diffenbach
133 To add another ID3v2 Tag, do the following:
134 1. add a char* named for the tag to struct mp3entry in id3.h,
135 (I (tpd) prefer to use char* rather than ints, even for what seems like
136 numerical values, for cases where a number won't do, e.g.,
137 YEAR: "circa 1765", "1790/1977" (composed/performed), "28 Feb 1969"
138 TRACK: "1/12", "1 of 12", GENRE: "Freeform genre name"
139 Text is more flexible, and as the main use of id3 data is to
140 display it, converting it to an int just means reconverting to
141 display it, at a runtime cost.)
143 2. If any special processing beyond copying the tag value from the Id3
144 block to the struct mp3entry is rrequired (such as converting to an
145 int), write a function to perform this special processing.
147 This function's prototype must match that of
148 typedef tagPostProcessFunc, that is it must be:
149 int func( struct mp3entry*, char* tag, int bufferpos )
150 the first argument is a pointer to the current mp3entry structure the
151 second argument is a pointer to the null terminated string value of the
152 tag found the third argument is the offset of the next free byte in the
153 mp3entry's buffer your function should return the corrected offset; if
154 you don't lengthen or shorten the tag string, you can return the third
157 Unless you have a good reason no to, make the function static.
158 TO JUST COPY THE TAG NO SPECIAL PROCESSING FUNCTION IS NEEDED.
160 3. add one or more entries to the tagList array, using the format:
161 char* ID3 Tag symbolic name -- see the ID3 specification for these,
162 sizeof() that name minus 1,
163 offsetof( struct mp3entry, variable_name_in_struct_mp3entry ),
164 pointer to your special processing function or NULL
165 if you need no special processing
166 flag indicating if this tag is binary or textual
167 Many ID3 symbolic names come in more than one form. You can add both
168 forms, each referencing the same variable in struct mp3entry.
169 If both forms are present, the last found will be used.
170 Note that the offset can be zero, in which case no entry will be set
171 in the mp3entry struct; the frame is still read into the buffer and
172 the special processing function is called (several times, if there
173 are several frames with the same name).
175 4. Alternately, use the TAG_LIST_ENTRY macro with
176 ID3 tag symbolic name,
177 variable in struct mp3entry,
178 special processing function address
180 5. Add code to wps-display.c function get_tag to assign a printf-like
181 format specifier for the tag */
183 /* Structure for ID3 Tag extraction information */
184 struct tag_resolver
{
188 int (*ppFunc
)(struct mp3entry
*, char* tag
, int bufferpos
);
192 static bool global_ff_found
;
194 static int unsynchronize(char* tag
, int len
, bool *ff_found
)
198 unsigned char *rp
, *wp
;
200 wp
= rp
= (unsigned char *)tag
;
202 rp
= (unsigned char *)tag
;
203 for(i
= 0;i
< len
;i
++) {
204 /* Read the next byte and write it back, but don't increment the
209 /* Increment the write pointer if it isn't an unsynch pattern */
219 return (long)wp
- (long)tag
;
222 static int unsynchronize_frame(char* tag
, int len
)
224 bool ff_found
= false;
226 return unsynchronize(tag
, len
, &ff_found
);
229 static int read_unsynched(int fd
, void *buf
, int len
)
241 rc
= read(fd
, rp
, remaining
);
245 i
= unsynchronize(wp
, remaining
, &global_ff_found
);
253 static int skip_unsynched(int fd
, int len
)
261 rlen
= MIN(sizeof(buf
), (unsigned int)remaining
);
262 rc
= read(fd
, buf
, rlen
);
266 remaining
-= unsynchronize(buf
, rlen
, &global_ff_found
);
272 /* parse numeric value from string */
273 static int parsetracknum( struct mp3entry
* entry
, char* tag
, int bufferpos
)
275 entry
->tracknum
= atoi( tag
);
279 /* parse numeric value from string */
280 static int parseyearnum( struct mp3entry
* entry
, char* tag
, int bufferpos
)
282 entry
->year
= atoi( tag
);
286 /* parse numeric genre from string, version 2.2 and 2.3 */
287 static int parsegenre( struct mp3entry
* entry
, char* tag
, int bufferpos
)
289 if(entry
->id3version
>= ID3_VER_2_4
) {
290 /* In version 2.4 and up, there are no parentheses, and the genre frame
291 is a list of strings, either numbers or text. */
293 /* Is it a number? */
294 if(isdigit(tag
[0])) {
295 entry
->genre
= atoi( tag
);
296 entry
->genre_string
= 0;
297 return tag
- entry
->id3v2buf
;
299 entry
->genre_string
= tag
;
304 if( tag
[0] == '(' && tag
[1] != '(' ) {
305 entry
->genre
= atoi( tag
+ 1 );
306 entry
->genre_string
= 0;
307 return tag
- entry
->id3v2buf
;
310 entry
->genre_string
= tag
;
317 #if CONFIG_CODEC == SWCODEC
318 /* parse user defined text, looking for replaygain information. */
319 static int parseuser( struct mp3entry
* entry
, char* tag
, int bufferpos
)
322 int desc_len
= strlen(tag
);
325 /* Note: for ID3v2.4, parse_replaygain will not overwrite replaygain
326 values already parsed from RVA2 tags */
327 if ((tag
- entry
->id3v2buf
+ desc_len
+ 2) < bufferpos
) {
328 /* At least part of the value was read, so we can safely try to
331 value
= tag
+ desc_len
+ 1;
332 value_len
= parse_replaygain(tag
, value
, entry
, tag
,
333 bufferpos
- (tag
- entry
->id3v2buf
));
337 bufferpos
= tag
- entry
->id3v2buf
+ value_len
;
339 bufferpos
= tag
- entry
->id3v2buf
;
345 /* parse RVA2 binary data and convert to replaygain information. */
346 static int parserva2( struct mp3entry
* entry
, char* tag
, int bufferpos
)
349 int desc_len
= strlen(tag
);
352 /* Only parse RVA2 replaygain tags if tag version == 2.4 */
353 if (entry
->id3version
== ID3_VER_2_4
&&
354 (tag
- entry
->id3v2buf
+ desc_len
+ 2) < bufferpos
) {
355 value
= tag
+ desc_len
+ 1;
356 value_len
= parse_replaygain_rva(tag
, value
, entry
, tag
,
357 bufferpos
- (tag
- entry
->id3v2buf
));
361 bufferpos
= tag
- entry
->id3v2buf
+ value_len
;
363 bufferpos
= tag
- entry
->id3v2buf
;
370 static const struct tag_resolver taglist
[] = {
371 { "TPE1", 4, offsetof(struct mp3entry
, artist
), NULL
, false },
372 { "TP1", 3, offsetof(struct mp3entry
, artist
), NULL
, false },
373 { "TIT2", 4, offsetof(struct mp3entry
, title
), NULL
, false },
374 { "TT2", 3, offsetof(struct mp3entry
, title
), NULL
, false },
375 { "TALB", 4, offsetof(struct mp3entry
, album
), NULL
, false },
376 { "TAL", 3, offsetof(struct mp3entry
, album
), NULL
, false },
377 { "TRK", 3, offsetof(struct mp3entry
, track_string
), &parsetracknum
, false },
378 { "TRCK", 4, offsetof(struct mp3entry
, track_string
), &parsetracknum
, false },
379 { "TDRC", 4, offsetof(struct mp3entry
, year_string
), &parseyearnum
, false },
380 { "TYER", 4, offsetof(struct mp3entry
, year_string
), &parseyearnum
, false },
381 { "TYE", 3, offsetof(struct mp3entry
, year_string
), &parseyearnum
, false },
382 { "TCOM", 4, offsetof(struct mp3entry
, composer
), NULL
, false },
383 { "TCON", 4, offsetof(struct mp3entry
, genre_string
), &parsegenre
, false },
384 { "TCO", 3, offsetof(struct mp3entry
, genre_string
), &parsegenre
, false },
385 #if CONFIG_CODEC == SWCODEC
386 { "TXXX", 4, 0, &parseuser
, false },
387 { "RVA2", 4, 0, &parserva2
, true },
391 #define TAGLIST_SIZE ((int)(sizeof(taglist) / sizeof(taglist[0])))
393 /* Checks to see if the passed in string is a 16-bit wide Unicode v2
394 string. If it is, we convert it to a UTF-8 string. If it's not unicode,
395 we convert from the default codepage */
396 static int unicode_munge(char* string
, char* utf8buf
, int *len
) {
402 char* utf8
= utf8buf
;
405 case 0x00: /* Type 0x00 is ordinary ISO 8859-1 */
408 utf8
= iso_decode(str
, utf8
, -1, *len
);
410 *len
= utf8
- utf8buf
;
413 case 0x01: /* Unicode with or without BOM */
418 /* Handle frames with more than one string
419 (needed for TXXX frames).*/
421 tmp
= BYTES2INT(0, 0, str
[0], str
[1]);
423 /* Now check if there is a BOM
424 (zero-width non-breaking space, 0xfeff)
425 and if it is in little or big endian format */
426 if(tmp
== 0xfffe) { /* Little endian? */
430 } else if(tmp
== 0xfeff) { /* Big endian? */
434 /* If there is no BOM (which is a specification violation),
435 let's try to guess it. If one of the bytes is 0x00, it is
436 probably the most significant one. */
442 utf8
= utf16LEdecode(str
, utf8
, 1);
444 utf8
= utf16BEdecode(str
, utf8
, 1);
448 } while((str
[0] || str
[1]) && (i
< *len
));
450 *utf8
++ = 0; /* Terminate the string */
451 templen
+= (strlen(&utf8buf
[templen
]) + 1);
458 case 0x03: /* UTF-8 encoded string */
459 for(i
=0; i
< *len
; i
++)
464 default: /* Plain old string */
465 utf8
= iso_decode(str
, utf8
, -1, *len
);
467 *len
= utf8
- utf8buf
;
474 * Sets the title of an MP3 entry based on its ID3v1 tag.
476 * Arguments: file - the MP3 file to scen for a ID3v1 tag
477 * entry - the entry to set the title in
479 * Returns: true if a title was found and created, else false
481 static bool setid3v1title(int fd
, struct mp3entry
*entry
)
483 unsigned char buffer
[128];
484 static const char offsets
[] = {3, 33, 63, 93, 125, 127};
488 if (-1 == lseek(fd
, -128, SEEK_END
))
491 if (read(fd
, buffer
, sizeof buffer
) != sizeof buffer
)
494 if (strncmp((char *)buffer
, "TAG", 3))
497 entry
->id3v1len
= 128;
498 entry
->id3version
= ID3_VER_1_0
;
500 for (i
=0; i
< (int)sizeof offsets
; i
++) {
501 unsigned char* ptr
= (unsigned char *)buffer
+ offsets
[i
];
504 /* kill trailing space in strings */
505 for (j
=29; j
&& ptr
[j
]==' '; j
--)
513 /* convert string to utf8 */
514 utf8
= entry
->id3v1buf
[i
];
515 utf8
= iso_decode(ptr
, utf8
, -1, 30);
516 /* make sure string is terminated */
522 entry
->year
= atoi(ptr
);
526 /* id3v1.1 uses last two bytes of comment field for track
527 number: first must be 0 and second is track num */
528 if (!ptr
[0] && ptr
[1]) {
529 entry
->tracknum
= ptr
[1];
530 entry
->id3version
= ID3_VER_1_1
;
536 entry
->genre
= ptr
[0];
541 entry
->title
= entry
->id3v1buf
[0];
542 entry
->artist
= entry
->id3v1buf
[1];
543 entry
->album
= entry
->id3v1buf
[2];
550 * Sets the title of an MP3 entry based on its ID3v2 tag.
552 * Arguments: file - the MP3 file to scan for a ID3v2 tag
553 * entry - the entry to set the title in
555 * Returns: true if a title was found and created, else false
557 static void setid3v2title(int fd
, struct mp3entry
*entry
)
561 long bufferpos
= 0, totframelen
, framelen
;
564 unsigned char version
;
565 char *buffer
= entry
->id3v2buf
;
567 int buffersize
= sizeof(entry
->id3v2buf
);
568 unsigned char global_flags
;
571 bool global_unsynch
= false;
572 bool unsynch
= false;
577 global_ff_found
= false;
579 /* Bail out if the tag is shorter than 10 bytes */
580 if(entry
->id3v2len
< 10)
583 /* Read the ID3 tag version from the header */
584 lseek(fd
, 0, SEEK_SET
);
585 if(10 != read(fd
, header
, 10))
588 /* Get the total ID3 tag size */
589 size
= entry
->id3v2len
- 10;
594 version
= ID3_VER_2_2
;
599 version
= ID3_VER_2_3
;
604 version
= ID3_VER_2_4
;
609 /* unsupported id3 version */
612 entry
->id3version
= version
;
613 entry
->tracknum
= entry
->year
= 0;
615 entry
->title
= entry
->artist
= entry
->album
= NULL
;
617 global_flags
= header
[5];
619 /* Skip the extended header if it is present */
620 if(global_flags
& 0x40) {
621 if(version
== ID3_VER_2_3
) {
622 if(10 != read(fd
, header
, 10))
624 /* The 2.3 extended header size doesn't include the following
625 data, so we have to find out the size by checking the flags.
626 Also, it is not unsynched. */
627 framelen
= BYTES2INT(header
[0], header
[1], header
[2], header
[3]) +
628 BYTES2INT(header
[6], header
[7], header
[8], header
[9]);
629 flags
= BYTES2INT(0, 0, header
[4], header
[5]);
631 framelen
+= 4; /* CRC */
633 lseek(fd
, framelen
- 10, SEEK_CUR
);
636 if(version
>= ID3_VER_2_4
) {
637 if(4 != read(fd
, header
, 4))
640 /* The 2.4 extended header size does include the entire header,
641 so here we can just skip it. This header is unsynched. */
642 framelen
= UNSYNC(header
[0], header
[1],
643 header
[2], header
[3]);
645 lseek(fd
, framelen
- 4, SEEK_CUR
);
649 /* Is unsynchronization applied? */
650 if(global_flags
& 0x80) {
651 global_unsynch
= true;
655 * We must have at least minframesize bytes left for the
656 * remaining frames to be interesting
658 while (size
>= minframesize
&& bufferpos
< buffersize
- 1) {
661 /* Read frame header and check length */
662 if(version
>= ID3_VER_2_3
) {
663 if(global_unsynch
&& version
<= ID3_VER_2_3
)
664 rc
= read_unsynched(fd
, header
, 10);
666 rc
= read(fd
, header
, 10);
669 /* Adjust for the 10 bytes we read */
672 flags
= BYTES2INT(0, 0, header
[8], header
[9]);
674 if (version
>= ID3_VER_2_4
) {
675 framelen
= UNSYNC(header
[4], header
[5],
676 header
[6], header
[7]);
678 /* version .3 files don't use synchsafe ints for
680 framelen
= BYTES2INT(header
[4], header
[5],
681 header
[6], header
[7]);
684 if(6 != read(fd
, header
, 6))
686 /* Adjust for the 6 bytes we read */
689 framelen
= BYTES2INT(0, header
[3], header
[4], header
[5]);
692 /* Keep track of the total size */
693 totframelen
= framelen
;
695 DEBUGF("framelen = %d\n", framelen
);
697 if (header
[0] == 0 && header
[1] == 0 && header
[2] == 0)
710 if (version
>= ID3_VER_2_4
) {
711 if(flags
& 0x0040) { /* Grouping identity */
712 lseek(fd
, 1, SEEK_CUR
); /* Skip 1 byte */
716 if(flags
& 0x0020) { /* Grouping identity */
717 lseek(fd
, 1, SEEK_CUR
); /* Skip 1 byte */
722 if(flags
& 0x000c) /* Compression or encryption */
724 /* Skip it using the total size in case
727 lseek(fd
, totframelen
, SEEK_CUR
);
731 if(flags
& 0x0002) /* Unsynchronization */
734 if (version
>= ID3_VER_2_4
) {
735 if(flags
& 0x0001) { /* Data length indicator */
736 if(4 != read(fd
, tmp
, 4))
739 data_length_ind
= UNSYNC(tmp
[0], tmp
[1], tmp
[2], tmp
[3]);
745 /* If the frame is larger than the remaining buffer space we try
746 to read as much as would fit in the buffer */
747 if(framelen
>= buffersize
- bufferpos
)
748 framelen
= buffersize
- bufferpos
- 1;
750 DEBUGF("id3v2 frame: %.4s\n", header
);
752 /* Check for certain frame headers
754 'size' is the amount of frame bytes remaining. We decrement it by
755 the amount of bytes we read. If we fail to read as many bytes as
756 we expect, we assume that we can't read from this file, and bail
759 For each frame. we will iterate over the list of supported tags,
760 and read the tag into entry's buffer. All tags will be kept as
761 strings, for cases where a number won't do, e.g., YEAR: "circa
762 1765", "1790/1977" (composed/performed), "28 Feb 1969" TRACK:
763 "1/12", "1 of 12", GENRE: "Freeform genre name" Text is more
764 flexible, and as the main use of id3 data is to display it,
765 converting it to an int just means reconverting to display it, at a
768 For tags that the current code does convert to ints, a post
769 processing function will be called via a pointer to function. */
771 for (i
=0; i
<TAGLIST_SIZE
; i
++) {
772 const struct tag_resolver
* tr
= &taglist
[i
];
773 char** ptag
= tr
->offset
? (char**) (((char*)entry
) + tr
->offset
)
777 /* Only ID3_VER_2_2 uses frames with three-character names. */
778 if (((version
== ID3_VER_2_2
) && (tr
->tag_length
!= 3))
779 || ((version
> ID3_VER_2_2
) && (tr
->tag_length
!= 4))) {
783 /* Note that parser functions sometimes set *ptag to NULL, so
784 * the "!*ptag" check here doesn't always have the desired
785 * effect. Should the parser functions (parsegenre in
786 * particular) be updated to handle the case of being called
787 * multiple times, or should the "*ptag" check be removed?
789 if( (!ptag
|| !*ptag
) && !memcmp( header
, tr
->tag
, tr
->tag_length
) ) {
791 /* found a tag matching one in tagList, and not yet filled */
792 tag
= buffer
+ bufferpos
;
794 if(global_unsynch
&& version
<= ID3_VER_2_3
)
795 bytesread
= read_unsynched(fd
, tag
, framelen
);
797 bytesread
= read(fd
, tag
, framelen
);
799 if( bytesread
!= framelen
)
804 if(unsynch
|| (global_unsynch
&& version
>= ID3_VER_2_4
))
805 bytesread
= unsynchronize_frame(tag
, bytesread
);
807 /* Attempt to parse Unicode string only if the tag contents
810 /* UTF-8 could potentially be 3 times larger */
811 /* so we need to create a new buffer */
812 char utf8buf
[(3 * bytesread
) + 1];
814 unicode_munge( tag
, utf8buf
, &bytesread
);
816 if(bytesread
>= buffersize
- bufferpos
)
817 bytesread
= buffersize
- bufferpos
- 1;
819 for (j
= 0; j
< bytesread
; j
++)
822 /* remove trailing spaces */
823 while ( bytesread
> 0 && isspace(tag
[bytesread
-1]))
828 bufferpos
+= bytesread
+ 1;
834 bufferpos
= tr
->ppFunc(entry
, tag
, bufferpos
);
836 /* Seek to the next frame */
837 if(framelen
< totframelen
)
838 lseek(fd
, totframelen
- framelen
, SEEK_CUR
);
843 if( i
== TAGLIST_SIZE
) {
844 /* no tag in tagList was found, or it was a repeat.
845 skip it using the total size */
847 if(global_unsynch
&& version
<= ID3_VER_2_3
) {
848 size
-= skip_unsynched(fd
, totframelen
);
851 totframelen
= data_length_ind
;
854 if( lseek(fd
, totframelen
, SEEK_CUR
) == -1 )
862 * Calculates the size of the ID3v2 tag.
864 * Arguments: file - the file to search for a tag.
866 * Returns: the size of the tag or 0 if none was found
868 int getid3v2len(int fd
)
873 /* Make sure file has a ID3 tag */
874 if((-1 == lseek(fd
, 0, SEEK_SET
)) ||
875 (read(fd
, buf
, 6) != 6) ||
876 (strncmp(buf
, "ID3", strlen("ID3")) != 0))
879 /* Now check what the ID3v2 size field says */
881 if(read(fd
, buf
, 4) != 4)
884 offset
= UNSYNC(buf
[0], buf
[1], buf
[2], buf
[3]) + 10;
886 DEBUGF("ID3V2 Length: 0x%x\n", offset
);
891 * Calculates the length (in milliseconds) of an MP3 file.
893 * Modified to only use integers.
895 * Arguments: file - the file to calculate the length upon
896 * entry - the entry to update with the length
898 * Returns: the song length in milliseconds,
899 * 0 means that it couldn't be calculated
901 static int getsonglength(int fd
, struct mp3entry
*entry
)
903 unsigned long filetime
= 0;
907 /* Start searching after ID3v2 header */
908 if(-1 == lseek(fd
, entry
->id3v2len
, SEEK_SET
))
911 bytecount
= get_mp3file_info(fd
, &info
);
913 DEBUGF("Space between ID3V2 tag and first audio frame: 0x%x bytes\n",
919 bytecount
+= entry
->id3v2len
;
921 /* Validate byte count, in case the file has been edited without
922 * updating the header.
926 const unsigned long expected
= entry
->filesize
- entry
->id3v1len
928 const unsigned long diff
= MAX(10240, info
.byte_count
/ 20);
930 if ((info
.byte_count
> expected
+ diff
)
931 || (info
.byte_count
< expected
- diff
))
933 DEBUGF("Note: info.byte_count differs from expected value by "
934 "%d bytes\n", labs((long) (expected
- info
.byte_count
)));
936 info
.frame_count
= 0;
938 info
.enc_padding
= 0;
940 /* Even if the bitrate was based on "known bad" values, it
941 * should still be better for VBR files than using the bitrate
942 * of the first audio frame.
947 entry
->bitrate
= info
.bitrate
;
948 entry
->frequency
= info
.frequency
;
949 entry
->version
= info
.version
;
950 entry
->layer
= info
.layer
;
951 switch(entry
->layer
) {
952 #if CONFIG_CODEC==SWCODEC
954 entry
->codectype
=AFMT_MPA_L1
;
958 entry
->codectype
=AFMT_MPA_L2
;
961 entry
->codectype
=AFMT_MPA_L3
;
965 /* If the file time hasn't been established, this may be a fixed
966 rate MP3, so just use the default formula */
968 filetime
= info
.file_time
;
972 filetime
= (entry
->filesize
- bytecount
) / (info
.bitrate
/ 8);
973 /* bitrate is in kbps so this delivers milliseconds. Doing bitrate / 8
974 * instead of filesize * 8 is exact, because mpeg audio bitrates are
975 * always multiples of 8, and it avoids overflows. */
978 entry
->frame_count
= info
.frame_count
;
980 entry
->vbr
= info
.is_vbr
;
981 entry
->has_toc
= info
.has_toc
;
983 entry
->lead_trim
= info
.enc_delay
;
984 entry
->tail_trim
= info
.enc_padding
;
986 memcpy(entry
->toc
, info
.toc
, sizeof(info
.toc
));
988 entry
->vbr_header_pos
= info
.vbr_header_pos
;
990 /* Update the seek point for the first playable frame */
991 entry
->first_frame_offset
= bytecount
;
992 DEBUGF("First frame is at %x\n", entry
->first_frame_offset
);
998 * Checks all relevant information (such as ID3v1 tag, ID3v2 tag, length etc)
999 * about an MP3 file and updates it's entry accordingly.
1002 bool mp3info(struct mp3entry
*entry
, const char *filename
, bool v1first
)
1005 int v1found
= false;
1007 fd
= open(filename
, O_RDONLY
);
1011 #if CONFIG_CODEC != SWCODEC
1012 memset(entry
, 0, sizeof(struct mp3entry
));
1015 strncpy(entry
->path
, filename
, sizeof(entry
->path
));
1017 entry
->title
= NULL
;
1018 entry
->filesize
= filesize(fd
);
1019 entry
->id3v2len
= getid3v2len(fd
);
1020 entry
->tracknum
= 0;
1021 entry
->genre
= 0xff;
1024 v1found
= setid3v1title(fd
, entry
);
1026 if (!v1found
&& entry
->id3v2len
)
1027 setid3v2title(fd
, entry
);
1028 entry
->length
= getsonglength(fd
, entry
);
1030 /* Subtract the meta information from the file size to get
1031 the true size of the MP3 stream */
1032 entry
->filesize
-= entry
->first_frame_offset
;
1034 /* only seek to end of file if no id3v2 tags were found,
1035 and we already haven't looked for a v1 tag */
1036 if (!v1first
&& !entry
->id3v2len
) {
1037 setid3v1title(fd
, entry
);
1042 if(!entry
->length
|| (entry
->filesize
< 8 ))
1043 /* no song length or less than 8 bytes is hereby considered to be an
1044 invalid mp3 and won't be played by us! */
1050 void adjust_mp3entry(struct mp3entry
*entry
, void *dest
, void *orig
)
1054 offset
= - ((size_t)orig
- (size_t)dest
);
1056 offset
= (size_t)dest
- (size_t)orig
;
1059 entry
->title
+= offset
;
1061 entry
->artist
+= offset
;
1063 entry
->album
+= offset
;
1064 if (entry
->genre_string
)
1065 entry
->genre_string
+= offset
;
1066 if (entry
->track_string
)
1067 entry
->track_string
+= offset
;
1068 if (entry
->year_string
)
1069 entry
->year_string
+= offset
;
1070 if (entry
->composer
)
1071 entry
->composer
+= offset
;
1072 #if CONFIG_CODEC == SWCODEC
1073 if (entry
->track_gain_string
)
1074 entry
->track_gain_string
+= offset
;
1075 if (entry
->album_gain_string
)
1076 entry
->album_gain_string
+= offset
;
1080 void copy_mp3entry(struct mp3entry
*dest
, struct mp3entry
*orig
)
1082 memcpy(dest
, orig
, sizeof(struct mp3entry
));
1083 adjust_mp3entry(dest
, dest
, orig
);
1086 #ifdef DEBUG_STANDALONE
1088 char *secs2str(int ms
)
1090 static char buffer
[32];
1093 snprintf(buffer
, sizeof(buffer
), "%d:%02d.%d", secs
/60, secs
%60, ms
/100);
1097 int main(int argc
, char **argv
)
1100 for(i
=1; i
<argc
; i
++) {
1101 struct mp3entry mp3
;
1102 mp3
.album
= "Bogus";
1103 if(mp3info(&mp3
, argv
[i
], false)) {
1104 printf("Failed to get %s\n", argv
[i
]);
1108 printf("****** File: %s\n"
1112 " Genre: %s (%d) \n"
1116 " Length: %s / %d s\n"
1120 mp3
.title
?mp3
.title
:"<blank>",
1121 mp3
.artist
?mp3
.artist
:"<blank>",
1122 mp3
.album
?mp3
.album
:"<blank>",
1123 mp3
.genre_string
?mp3
.genre_string
:"<blank>",
1125 mp3
.composer
?mp3
.composer
:"<blank>",
1126 mp3
.year_string
?mp3
.year_string
:"<blank>",
1128 mp3
.track_string
?mp3
.track_string
:"<blank>",
1130 secs2str(mp3
.length
),