keybox: fix issue when deleted all items.
[kugel-rb.git] / apps / metadata / mp3.c
blob21cdeff3fc6c92ec3ed81ed0a13787ac6ea3d8a2
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 by Daniel Stenberg
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 * Parts of this code has been stolen from the Ample project and was written
23 * by David H�deman. It has since been extended and enhanced pretty much by
24 * all sorts of friendly Rockbox people.
28 /* tagResolver and associated code copyright 2003 Thomas Paul Diffenbach
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <errno.h>
35 #include <stdbool.h>
36 #include <stddef.h>
37 #include <ctype.h>
38 #include "config.h"
39 #include "file.h"
40 #include "logf.h"
42 #include "mp3data.h"
43 #include "system.h"
44 #include "replaygain.h"
45 #include "rbunicode.h"
46 #include "metadata_parsers.h"
48 static unsigned long unsync(unsigned long b0,
49 unsigned long b1,
50 unsigned long b2,
51 unsigned long b3)
53 return (((long)(b0 & 0x7F) << (3*7)) |
54 ((long)(b1 & 0x7F) << (2*7)) |
55 ((long)(b2 & 0x7F) << (1*7)) |
56 ((long)(b3 & 0x7F) << (0*7)));
59 static const char* const genres[] = {
60 "Blues", "Classic Rock", "Country", "Dance", "Disco", "Funk", "Grunge",
61 "Hip-Hop", "Jazz", "Metal", "New Age", "Oldies", "Other", "Pop", "R&B",
62 "Rap", "Reggae", "Rock", "Techno", "Industrial", "Alternative", "Ska",
63 "Death Metal", "Pranks", "Soundtrack", "Euro-Techno", "Ambient", "Trip-Hop",
64 "Vocal", "Jazz+Funk", "Fusion", "Trance", "Classical", "Instrumental",
65 "Acid", "House", "Game", "Sound Clip", "Gospel", "Noise", "AlternRock",
66 "Bass", "Soul", "Punk", "Space", "Meditative", "Instrumental Pop",
67 "Instrumental Rock", "Ethnic", "Gothic", "Darkwave", "Techno-Industrial",
68 "Electronic", "Pop-Folk", "Eurodance", "Dream", "Southern Rock", "Comedy",
69 "Cult", "Gangsta", "Top 40", "Christian Rap", "Pop/Funk", "Jungle",
70 "Native American", "Cabaret", "New Wave", "Psychadelic", "Rave",
71 "Showtunes", "Trailer", "Lo-Fi", "Tribal", "Acid Punk", "Acid Jazz",
72 "Polka", "Retro", "Musical", "Rock & Roll", "Hard Rock",
74 /* winamp extensions */
75 "Folk", "Folk-Rock", "National Folk", "Swing", "Fast Fusion", "Bebob",
76 "Latin", "Revival", "Celtic", "Bluegrass", "Avantgarde", "Gothic Rock",
77 "Progressive Rock", "Psychedelic Rock", "Symphonic Rock", "Slow Rock",
78 "Big Band", "Chorus", "Easy Listening", "Acoustic", "Humour", "Speech",
79 "Chanson", "Opera", "Chamber Music", "Sonata", "Symphony", "Booty Bass",
80 "Primus", "Porn Groove", "Satire", "Slow Jam", "Club", "Tango", "Samba",
81 "Folklore", "Ballad", "Power Ballad", "Rhythmic Soul", "Freestyle",
82 "Duet", "Punk Rock", "Drum Solo", "A capella", "Euro-House", "Dance Hall",
83 "Goa", "Drum & Bass", "Club-House", "Hardcore", "Terror", "Indie",
84 "BritPop", "Negerpunk", "Polsk Punk", "Beat", "Christian Gangsta Rap",
85 "Heavy Metal", "Black Metal", "Crossover", "Contemporary Christian",
86 "Christian Rock", "Merengue", "Salsa", "Thrash Metal", "Anime", "Jpop",
87 "Synthpop"
90 char* id3_get_num_genre(unsigned int genre_num)
92 if (genre_num < ARRAYLEN(genres))
93 return (char*)genres[genre_num];
94 return NULL;
98 HOW TO ADD ADDITIONAL ID3 VERSION 2 TAGS
99 Code and comments by Thomas Paul Diffenbach
101 To add another ID3v2 Tag, do the following:
102 1. add a char* named for the tag to struct mp3entry in id3.h,
103 (I (tpd) prefer to use char* rather than ints, even for what seems like
104 numerical values, for cases where a number won't do, e.g.,
105 YEAR: "circa 1765", "1790/1977" (composed/performed), "28 Feb 1969"
106 TRACK: "1/12", "1 of 12", GENRE: "Freeform genre name"
107 Text is more flexible, and as the main use of id3 data is to
108 display it, converting it to an int just means reconverting to
109 display it, at a runtime cost.)
111 2. If any special processing beyond copying the tag value from the Id3
112 block to the struct mp3entry is rrequired (such as converting to an
113 int), write a function to perform this special processing.
115 This function's prototype must match that of
116 typedef tagPostProcessFunc, that is it must be:
117 int func( struct mp3entry*, char* tag, int bufferpos )
118 the first argument is a pointer to the current mp3entry structure the
119 second argument is a pointer to the null terminated string value of the
120 tag found the third argument is the offset of the next free byte in the
121 mp3entry's buffer your function should return the corrected offset; if
122 you don't lengthen or shorten the tag string, you can return the third
123 argument unchanged.
125 Unless you have a good reason no to, make the function static.
126 TO JUST COPY THE TAG NO SPECIAL PROCESSING FUNCTION IS NEEDED.
128 3. add one or more entries to the tagList array, using the format:
129 char* ID3 Tag symbolic name -- see the ID3 specification for these,
130 sizeof() that name minus 1,
131 offsetof( struct mp3entry, variable_name_in_struct_mp3entry ),
132 pointer to your special processing function or NULL
133 if you need no special processing
134 flag indicating if this tag is binary or textual
135 Many ID3 symbolic names come in more than one form. You can add both
136 forms, each referencing the same variable in struct mp3entry.
137 If both forms are present, the last found will be used.
138 Note that the offset can be zero, in which case no entry will be set
139 in the mp3entry struct; the frame is still read into the buffer and
140 the special processing function is called (several times, if there
141 are several frames with the same name).
143 4. Alternately, use the TAG_LIST_ENTRY macro with
144 ID3 tag symbolic name,
145 variable in struct mp3entry,
146 special processing function address
148 5. Add code to wps-display.c function get_tag to assign a printf-like
149 format specifier for the tag */
151 /* Structure for ID3 Tag extraction information */
152 struct tag_resolver {
153 const char* tag;
154 int tag_length;
155 size_t offset;
156 int (*ppFunc)(struct mp3entry*, char* tag, int bufferpos);
157 bool binary;
160 static bool global_ff_found;
162 static int unsynchronize(char* tag, int len, bool *ff_found)
164 int i;
165 unsigned char c;
166 unsigned char *rp, *wp;
168 wp = rp = (unsigned char *)tag;
170 rp = (unsigned char *)tag;
171 for(i = 0;i < len;i++) {
172 /* Read the next byte and write it back, but don't increment the
173 write pointer */
174 c = *rp++;
175 *wp = c;
176 if(*ff_found) {
177 /* Increment the write pointer if it isn't an unsynch pattern */
178 if(c != 0)
179 wp++;
180 *ff_found = false;
181 } else {
182 if(c == 0xff)
183 *ff_found = true;
184 wp++;
187 return (long)wp - (long)tag;
190 static int unsynchronize_frame(char* tag, int len)
192 bool ff_found = false;
194 return unsynchronize(tag, len, &ff_found);
197 static int read_unsynched(int fd, void *buf, int len)
199 int i;
200 int rc;
201 int remaining = len;
202 char *wp;
203 char *rp;
205 wp = buf;
207 while(remaining) {
208 rp = wp;
209 rc = read(fd, rp, remaining);
210 if(rc <= 0)
211 return rc;
213 i = unsynchronize(wp, remaining, &global_ff_found);
214 remaining -= i;
215 wp += i;
218 return len;
221 static int skip_unsynched(int fd, int len)
223 int rc;
224 int remaining = len;
225 int rlen;
226 char buf[32];
228 while(remaining) {
229 rlen = MIN(sizeof(buf), (unsigned int)remaining);
230 rc = read(fd, buf, rlen);
231 if(rc <= 0)
232 return rc;
234 remaining -= unsynchronize(buf, rlen, &global_ff_found);
237 return len;
240 /* parse numeric value from string */
241 static int parsetracknum( struct mp3entry* entry, char* tag, int bufferpos )
243 entry->tracknum = atoi( tag );
244 return bufferpos;
247 /* parse numeric value from string */
248 static int parsediscnum( struct mp3entry* entry, char* tag, int bufferpos )
250 entry->discnum = atoi( tag );
251 return bufferpos;
254 /* parse numeric value from string */
255 static int parseyearnum( struct mp3entry* entry, char* tag, int bufferpos )
257 entry->year = atoi( tag );
258 return bufferpos;
261 /* parse numeric genre from string, version 2.2 and 2.3 */
262 static int parsegenre( struct mp3entry* entry, char* tag, int bufferpos )
264 if(entry->id3version >= ID3_VER_2_4) {
265 /* In version 2.4 and up, there are no parentheses, and the genre frame
266 is a list of strings, either numbers or text. */
268 /* Is it a number? */
269 if(isdigit(tag[0])) {
270 entry->genre_string = id3_get_num_genre(atoi( tag ));
271 return tag - entry->id3v2buf;
272 } else {
273 entry->genre_string = tag;
274 return bufferpos;
276 } else {
277 if( tag[0] == '(' && tag[1] != '(' ) {
278 entry->genre_string = id3_get_num_genre(atoi( tag + 1 ));
279 return tag - entry->id3v2buf;
281 else {
282 entry->genre_string = tag;
283 return bufferpos;
288 /* parse user defined text, looking for album artist and replaygain
289 * information.
291 static int parseuser( struct mp3entry* entry, char* tag, int bufferpos )
293 char* value = NULL;
294 int desc_len = strlen(tag);
295 int value_len = 0;
297 if ((tag - entry->id3v2buf + desc_len + 2) < bufferpos) {
298 /* At least part of the value was read, so we can safely try to
299 * parse it
301 value = tag + desc_len + 1;
302 value_len = bufferpos - (tag - entry->id3v2buf);
304 if (!strcasecmp(tag, "ALBUM ARTIST")) {
305 strlcpy(tag, value, value_len);
306 entry->albumartist = tag;
307 #if CONFIG_CODEC == SWCODEC
308 } else {
309 value_len = parse_replaygain(tag, value, entry, tag,
310 value_len);
311 #endif
315 return tag - entry->id3v2buf + value_len;
318 #if CONFIG_CODEC == SWCODEC
319 /* parse RVA2 binary data and convert to replaygain information. */
320 static int parserva2( struct mp3entry* entry, char* tag, int bufferpos )
322 int desc_len = strlen(tag);
323 int start_pos = tag - entry->id3v2buf;
324 int end_pos = start_pos + desc_len + 5;
325 int value_len = 0;
326 unsigned char* value = tag + desc_len + 1;
328 /* Only parse RVA2 replaygain tags if tag version == 2.4 and channel
329 * type is master volume.
331 if (entry->id3version == ID3_VER_2_4 && end_pos < bufferpos
332 && *value++ == 1) {
333 long gain = 0;
334 long peak = 0;
335 long peakbits;
336 long peakbytes;
337 bool album = false;
339 /* The RVA2 specification is unclear on some things (id string and
340 * peak volume), but this matches how Quod Libet use them.
343 gain = (int16_t) ((value[0] << 8) | value[1]);
344 value += 2;
345 peakbits = *value++;
346 peakbytes = (peakbits + 7) / 8;
348 /* Only use the topmost 24 bits for peak volume */
349 if (peakbytes > 3) {
350 peakbytes = 3;
353 /* Make sure the peak bits were read */
354 if (end_pos + peakbytes < bufferpos) {
355 long shift = ((8 - (peakbits & 7)) & 7) + (3 - peakbytes) * 8;
357 for ( ; peakbytes; peakbytes--) {
358 peak <<= 8;
359 peak += *value++;
362 peak <<= shift;
364 if (peakbits > 24) {
365 peak += *value >> (8 - shift);
369 if (strcasecmp(tag, "album") == 0) {
370 album = true;
371 } else if (strcasecmp(tag, "track") != 0) {
372 /* Only accept non-track values if we don't have any previous
373 * value.
375 if (entry->track_gain != 0) {
376 return start_pos;
380 value_len = parse_replaygain_int(album, gain, peak * 2, entry,
381 tag, sizeof(entry->id3v2buf) - start_pos);
384 return start_pos + value_len;
386 #endif
388 static int parsembtid( struct mp3entry* entry, char* tag, int bufferpos )
390 char* value = NULL;
391 int desc_len = strlen(tag);
392 /*DEBUGF("MBID len: %d\n", desc_len);*/
393 /* Musicbrainz track IDs are always 36 chars long */
394 const size_t mbtid_len = 36;
396 if ((tag - entry->id3v2buf + desc_len + 2) < bufferpos)
398 value = tag + desc_len + 1;
400 if (strcasecmp(tag, "http://musicbrainz.org") == 0)
402 if (mbtid_len == strlen(value))
404 entry->mb_track_id = value;
405 return bufferpos + mbtid_len + 1;
410 return bufferpos;
413 static const struct tag_resolver taglist[] = {
414 { "TPE1", 4, offsetof(struct mp3entry, artist), NULL, false },
415 { "TP1", 3, offsetof(struct mp3entry, artist), NULL, false },
416 { "TIT2", 4, offsetof(struct mp3entry, title), NULL, false },
417 { "TT2", 3, offsetof(struct mp3entry, title), NULL, false },
418 { "TALB", 4, offsetof(struct mp3entry, album), NULL, false },
419 { "TAL", 3, offsetof(struct mp3entry, album), NULL, false },
420 { "TRK", 3, offsetof(struct mp3entry, track_string), &parsetracknum, false },
421 { "TPOS", 4, offsetof(struct mp3entry, disc_string), &parsediscnum, false },
422 { "TRCK", 4, offsetof(struct mp3entry, track_string), &parsetracknum, false },
423 { "TDRC", 4, offsetof(struct mp3entry, year_string), &parseyearnum, false },
424 { "TYER", 4, offsetof(struct mp3entry, year_string), &parseyearnum, false },
425 { "TYE", 3, offsetof(struct mp3entry, year_string), &parseyearnum, false },
426 { "TCOM", 4, offsetof(struct mp3entry, composer), NULL, false },
427 { "TPE2", 4, offsetof(struct mp3entry, albumartist), NULL, false },
428 { "TP2", 3, offsetof(struct mp3entry, albumartist), NULL, false },
429 { "TIT1", 4, offsetof(struct mp3entry, grouping), NULL, false },
430 { "TT1", 3, offsetof(struct mp3entry, grouping), NULL, false },
431 { "COMM", 4, offsetof(struct mp3entry, comment), NULL, false },
432 { "TCON", 4, offsetof(struct mp3entry, genre_string), &parsegenre, false },
433 { "TCO", 3, offsetof(struct mp3entry, genre_string), &parsegenre, false },
434 { "TXXX", 4, 0, &parseuser, false },
435 #if CONFIG_CODEC == SWCODEC
436 { "RVA2", 4, 0, &parserva2, true },
437 #endif
438 { "UFID", 4, 0, &parsembtid, false },
441 #define TAGLIST_SIZE ((int)ARRAYLEN(taglist))
443 /* Get the length of an ID3 string in the given encoding. Returns the length
444 * in bytes, including end nil, or -1 if the encoding is unknown.
446 static int unicode_len(char encoding, const void* string)
448 int len = 0;
450 if (encoding == 0x01 || encoding == 0x02) {
451 char first;
452 const char *s = string;
453 /* string might be unaligned, so using short* can crash on ARM and SH1 */
454 do {
455 first = *s++;
456 } while ((first | *s++) != 0);
458 len = s - (const char*) string;
459 } else {
460 len = strlen((char*) string) + 1;
463 return len;
466 /* Checks to see if the passed in string is a 16-bit wide Unicode v2
467 string. If it is, we convert it to a UTF-8 string. If it's not unicode,
468 we convert from the default codepage */
469 static int unicode_munge(char* string, char* utf8buf, int *len) {
470 long tmp;
471 bool le = false;
472 int i = 0;
473 unsigned char *str = (unsigned char *)string;
474 int templen = 0;
475 unsigned char* utf8 = (unsigned char *)utf8buf;
477 switch (str[0]) {
478 case 0x00: /* Type 0x00 is ordinary ISO 8859-1 */
479 str++;
480 (*len)--;
481 utf8 = iso_decode(str, utf8, -1, *len);
482 *utf8 = 0;
483 *len = (unsigned long)utf8 - (unsigned long)utf8buf;
484 break;
486 case 0x01: /* Unicode with or without BOM */
487 case 0x02:
488 (*len)--;
489 str++;
491 /* Handle frames with more than one string
492 (needed for TXXX frames).*/
493 do {
494 tmp = bytes2int(0, 0, str[0], str[1]);
496 /* Now check if there is a BOM
497 (zero-width non-breaking space, 0xfeff)
498 and if it is in little or big endian format */
499 if(tmp == 0xfffe) { /* Little endian? */
500 le = true;
501 str += 2;
502 (*len)-=2;
503 } else if(tmp == 0xfeff) { /* Big endian? */
504 str += 2;
505 (*len)-=2;
506 } else
507 /* If there is no BOM (which is a specification violation),
508 let's try to guess it. If one of the bytes is 0x00, it is
509 probably the most significant one. */
510 if(str[1] == 0)
511 le = true;
513 do {
514 if(le)
515 utf8 = utf16LEdecode(str, utf8, 1);
516 else
517 utf8 = utf16BEdecode(str, utf8, 1);
519 str+=2;
520 i += 2;
521 } while((str[0] || str[1]) && (i < *len));
523 *utf8++ = 0; /* Terminate the string */
524 templen += (strlen(&utf8buf[templen]) + 1);
525 str += 2;
526 i+=2;
527 } while(i < *len);
528 *len = templen - 1;
529 break;
531 case 0x03: /* UTF-8 encoded string */
532 for(i=0; i < *len; i++)
533 utf8[i] = str[i+1];
534 (*len)--;
535 break;
537 default: /* Plain old string */
538 utf8 = iso_decode(str, utf8, -1, *len);
539 *utf8 = 0;
540 *len = (unsigned long)utf8 - (unsigned long)utf8buf;
541 break;
543 return 0;
547 * Sets the title of an MP3 entry based on its ID3v1 tag.
549 * Arguments: file - the MP3 file to scen for a ID3v1 tag
550 * entry - the entry to set the title in
552 * Returns: true if a title was found and created, else false
554 static bool setid3v1title(int fd, struct mp3entry *entry)
556 unsigned char buffer[128];
557 static const char offsets[] = {3, 33, 63, 97, 93, 125, 127};
558 int i, j;
559 unsigned char* utf8;
561 if (-1 == lseek(fd, -128, SEEK_END))
562 return false;
564 if (read(fd, buffer, sizeof buffer) != sizeof buffer)
565 return false;
567 if (strncmp((char *)buffer, "TAG", 3))
568 return false;
570 entry->id3v1len = 128;
571 entry->id3version = ID3_VER_1_0;
573 for (i=0; i < (int)sizeof offsets; i++) {
574 unsigned char* ptr = (unsigned char *)buffer + offsets[i];
576 switch(i) {
577 case 0:
578 case 1:
579 case 2:
580 /* kill trailing space in strings */
581 for (j=29; j && (ptr[j]==0 || ptr[j]==' '); j--)
582 ptr[j] = 0;
583 /* convert string to utf8 */
584 utf8 = (unsigned char *)entry->id3v1buf[i];
585 utf8 = iso_decode(ptr, utf8, -1, 30);
586 /* make sure string is terminated */
587 *utf8 = 0;
588 break;
590 case 3:
591 /* kill trailing space in strings */
592 for (j=27; j && (ptr[j]==0 || ptr[j]==' '); j--)
593 ptr[j] = 0;
594 /* convert string to utf8 */
595 utf8 = (unsigned char *)entry->id3v1buf[3];
596 utf8 = iso_decode(ptr, utf8, -1, 28);
597 /* make sure string is terminated */
598 *utf8 = 0;
599 break;
601 case 4:
602 ptr[4] = 0;
603 entry->year = atoi((char *)ptr);
604 break;
606 case 5:
607 /* id3v1.1 uses last two bytes of comment field for track
608 number: first must be 0 and second is track num */
609 if (!ptr[0] && ptr[1]) {
610 entry->tracknum = ptr[1];
611 entry->id3version = ID3_VER_1_1;
613 break;
615 case 6:
616 /* genre */
617 entry->genre_string = id3_get_num_genre(ptr[0]);
618 break;
622 entry->title = entry->id3v1buf[0];
623 entry->artist = entry->id3v1buf[1];
624 entry->album = entry->id3v1buf[2];
625 entry->comment = entry->id3v1buf[3];
627 return true;
632 * Sets the title of an MP3 entry based on its ID3v2 tag.
634 * Arguments: file - the MP3 file to scan for a ID3v2 tag
635 * entry - the entry to set the title in
637 * Returns: true if a title was found and created, else false
639 static void setid3v2title(int fd, struct mp3entry *entry)
641 int minframesize;
642 int size;
643 long bufferpos = 0, totframelen, framelen;
644 char header[10];
645 char tmp[4];
646 unsigned char version;
647 char *buffer = entry->id3v2buf;
648 int bytesread = 0;
649 int buffersize = sizeof(entry->id3v2buf);
650 unsigned char global_flags;
651 int flags;
652 int skip;
653 bool global_unsynch = false;
654 bool unsynch = false;
655 int i, j;
656 int rc;
658 global_ff_found = false;
660 /* Bail out if the tag is shorter than 10 bytes */
661 if(entry->id3v2len < 10)
662 return;
664 /* Read the ID3 tag version from the header */
665 lseek(fd, 0, SEEK_SET);
666 if(10 != read(fd, header, 10))
667 return;
669 /* Get the total ID3 tag size */
670 size = entry->id3v2len - 10;
672 version = header[3];
673 switch ( version ) {
674 case 2:
675 version = ID3_VER_2_2;
676 minframesize = 8;
677 break;
679 case 3:
680 version = ID3_VER_2_3;
681 minframesize = 12;
682 break;
684 case 4:
685 version = ID3_VER_2_4;
686 minframesize = 12;
687 break;
689 default:
690 /* unsupported id3 version */
691 return;
693 entry->id3version = version;
694 entry->tracknum = entry->year = entry->discnum = 0;
695 entry->title = entry->artist = entry->album = NULL; /* FIXME incomplete */
697 global_flags = header[5];
699 /* Skip the extended header if it is present */
700 if(global_flags & 0x40) {
701 if(version == ID3_VER_2_3) {
702 if(10 != read(fd, header, 10))
703 return;
704 /* The 2.3 extended header size doesn't include the header size
705 field itself. Also, it is not unsynched. */
706 framelen =
707 bytes2int(header[0], header[1], header[2], header[3]) + 4;
709 /* Skip the rest of the header */
710 lseek(fd, framelen - 10, SEEK_CUR);
713 if(version >= ID3_VER_2_4) {
714 if(4 != read(fd, header, 4))
715 return;
717 /* The 2.4 extended header size does include the entire header,
718 so here we can just skip it. This header is unsynched. */
719 framelen = unsync(header[0], header[1],
720 header[2], header[3]);
722 lseek(fd, framelen - 4, SEEK_CUR);
726 /* Is unsynchronization applied? */
727 if(global_flags & 0x80) {
728 global_unsynch = true;
732 * We must have at least minframesize bytes left for the
733 * remaining frames to be interesting
735 while (size >= minframesize && bufferpos < buffersize - 1) {
736 flags = 0;
738 /* Read frame header and check length */
739 if(version >= ID3_VER_2_3) {
740 if(global_unsynch && version <= ID3_VER_2_3)
741 rc = read_unsynched(fd, header, 10);
742 else
743 rc = read(fd, header, 10);
744 if(rc != 10)
745 return;
746 /* Adjust for the 10 bytes we read */
747 size -= 10;
749 flags = bytes2int(0, 0, header[8], header[9]);
751 if (version >= ID3_VER_2_4) {
752 framelen = unsync(header[4], header[5],
753 header[6], header[7]);
754 } else {
755 /* version .3 files don't use synchsafe ints for
756 * size */
757 framelen = bytes2int(header[4], header[5],
758 header[6], header[7]);
760 } else {
761 if(6 != read(fd, header, 6))
762 return;
763 /* Adjust for the 6 bytes we read */
764 size -= 6;
766 framelen = bytes2int(0, header[3], header[4], header[5]);
769 logf("framelen = %ld, flags = 0x%04x", framelen, flags);
770 if(framelen == 0){
771 if (header[0] == 0 && header[1] == 0 && header[2] == 0)
772 return;
773 else
774 continue;
777 unsynch = false;
779 if(flags)
781 skip = 0;
783 if (version >= ID3_VER_2_4) {
784 if(flags & 0x0040) { /* Grouping identity */
785 lseek(fd, 1, SEEK_CUR); /* Skip 1 byte */
786 framelen--;
788 } else {
789 if(flags & 0x0020) { /* Grouping identity */
790 lseek(fd, 1, SEEK_CUR); /* Skip 1 byte */
791 framelen--;
795 if(flags & 0x000c) /* Compression or encryption */
797 /* Skip it */
798 size -= framelen;
799 lseek(fd, framelen, SEEK_CUR);
800 continue;
803 if(flags & 0x0002) /* Unsynchronization */
804 unsynch = true;
806 if (version >= ID3_VER_2_4) {
807 if(flags & 0x0001) { /* Data length indicator */
808 if(4 != read(fd, tmp, 4))
809 return;
811 /* We don't need the data length */
812 framelen -= 4;
817 if (framelen == 0)
818 continue;
820 if (framelen < 0)
821 return;
823 /* Keep track of the remaining frame size */
824 totframelen = framelen;
826 /* If the frame is larger than the remaining buffer space we try
827 to read as much as would fit in the buffer */
828 if(framelen >= buffersize - bufferpos)
829 framelen = buffersize - bufferpos - 1;
831 logf("id3v2 frame: %.4s", header);
833 /* Check for certain frame headers
835 'size' is the amount of frame bytes remaining. We decrement it by
836 the amount of bytes we read. If we fail to read as many bytes as
837 we expect, we assume that we can't read from this file, and bail
838 out.
840 For each frame. we will iterate over the list of supported tags,
841 and read the tag into entry's buffer. All tags will be kept as
842 strings, for cases where a number won't do, e.g., YEAR: "circa
843 1765", "1790/1977" (composed/performed), "28 Feb 1969" TRACK:
844 "1/12", "1 of 12", GENRE: "Freeform genre name" Text is more
845 flexible, and as the main use of id3 data is to display it,
846 converting it to an int just means reconverting to display it, at a
847 runtime cost.
849 For tags that the current code does convert to ints, a post
850 processing function will be called via a pointer to function. */
852 for (i=0; i<TAGLIST_SIZE; i++) {
853 const struct tag_resolver* tr = &taglist[i];
854 char** ptag = tr->offset ? (char**) (((char*)entry) + tr->offset)
855 : NULL;
856 char* tag;
858 /* Only ID3_VER_2_2 uses frames with three-character names. */
859 if (((version == ID3_VER_2_2) && (tr->tag_length != 3))
860 || ((version > ID3_VER_2_2) && (tr->tag_length != 4))) {
861 continue;
864 /* Note that parser functions sometimes set *ptag to NULL, so
865 * the "!*ptag" check here doesn't always have the desired
866 * effect. Should the parser functions (parsegenre in
867 * particular) be updated to handle the case of being called
868 * multiple times, or should the "*ptag" check be removed?
870 if( (!ptag || !*ptag) && !memcmp( header, tr->tag, tr->tag_length ) ) {
872 /* found a tag matching one in tagList, and not yet filled */
873 tag = buffer + bufferpos;
875 if(global_unsynch && version <= ID3_VER_2_3)
876 bytesread = read_unsynched(fd, tag, framelen);
877 else
878 bytesread = read(fd, tag, framelen);
880 if( bytesread != framelen )
881 return;
883 size -= bytesread;
885 if(unsynch || (global_unsynch && version >= ID3_VER_2_4))
886 bytesread = unsynchronize_frame(tag, bytesread);
888 /* the COMM frame has a 3 char field to hold an ISO-639-1
889 * language string and an optional short description;
890 * remove them so unicode_munge can work correctly
893 if(!memcmp( header, "COMM", 4 )) {
894 int offset;
895 /* ignore comments with iTunes 7 soundcheck/gapless data */
896 if(!strncmp(tag+4, "iTun", 4))
897 break;
898 offset = 3 + unicode_len(*tag, tag + 4);
899 if(bytesread > offset) {
900 bytesread -= offset;
901 memmove(tag + 1, tag + 1 + offset, bytesread - 1);
905 /* Attempt to parse Unicode string only if the tag contents
906 aren't binary */
907 if(!tr->binary) {
908 /* UTF-8 could potentially be 3 times larger */
909 /* so we need to create a new buffer */
910 char utf8buf[(3 * bytesread) + 1];
912 unicode_munge( tag, utf8buf, &bytesread );
914 if(bytesread >= buffersize - bufferpos)
915 bytesread = buffersize - bufferpos - 1;
917 for (j = 0; j < bytesread; j++)
918 tag[j] = utf8buf[j];
920 /* remove trailing spaces */
921 while ( bytesread > 0 && isspace(tag[bytesread-1]))
922 bytesread--;
925 tag[bytesread] = 0;
926 bufferpos += bytesread + 1;
928 if (ptag)
929 *ptag = tag;
931 if( tr->ppFunc )
932 bufferpos = tr->ppFunc(entry, tag, bufferpos);
934 /* Seek to the next frame */
935 if(framelen < totframelen)
936 lseek(fd, totframelen - framelen, SEEK_CUR);
937 break;
941 if( i == TAGLIST_SIZE ) {
942 /* no tag in tagList was found, or it was a repeat.
943 skip it using the total size */
945 if(global_unsynch && version <= ID3_VER_2_3) {
946 size -= skip_unsynched(fd, totframelen);
947 } else {
948 size -= totframelen;
949 if( lseek(fd, totframelen, SEEK_CUR) == -1 )
950 return;
957 * Calculates the size of the ID3v2 tag.
959 * Arguments: file - the file to search for a tag.
961 * Returns: the size of the tag or 0 if none was found
963 int getid3v2len(int fd)
965 char buf[6];
966 int offset;
968 /* Make sure file has a ID3 tag */
969 if((-1 == lseek(fd, 0, SEEK_SET)) ||
970 (read(fd, buf, 6) != 6) ||
971 (strncmp(buf, "ID3", strlen("ID3")) != 0))
972 offset = 0;
974 /* Now check what the ID3v2 size field says */
975 else
976 if(read(fd, buf, 4) != 4)
977 offset = 0;
978 else
979 offset = unsync(buf[0], buf[1], buf[2], buf[3]) + 10;
981 logf("ID3V2 Length: 0x%x", offset);
982 return offset;
986 * Calculates the length (in milliseconds) of an MP3 file.
988 * Modified to only use integers.
990 * Arguments: file - the file to calculate the length upon
991 * entry - the entry to update with the length
993 * Returns: the song length in milliseconds,
994 * 0 means that it couldn't be calculated
996 static int getsonglength(int fd, struct mp3entry *entry)
998 unsigned long filetime = 0;
999 struct mp3info info;
1000 long bytecount;
1002 /* Start searching after ID3v2 header */
1003 if(-1 == lseek(fd, entry->id3v2len, SEEK_SET))
1004 return 0;
1006 bytecount = get_mp3file_info(fd, &info);
1008 logf("Space between ID3V2 tag and first audio frame: 0x%lx bytes",
1009 bytecount);
1011 if(bytecount < 0)
1012 return -1;
1014 bytecount += entry->id3v2len;
1016 /* Validate byte count, in case the file has been edited without
1017 * updating the header.
1019 if (info.byte_count)
1021 const unsigned long expected = entry->filesize - entry->id3v1len
1022 - entry->id3v2len;
1023 const unsigned long diff = MAX(10240, info.byte_count / 20);
1025 if ((info.byte_count > expected + diff)
1026 || (info.byte_count < expected - diff))
1028 logf("Note: info.byte_count differs from expected value by "
1029 "%ld bytes", labs((long) (expected - info.byte_count)));
1030 info.byte_count = 0;
1031 info.frame_count = 0;
1032 info.file_time = 0;
1033 info.enc_padding = 0;
1035 /* Even if the bitrate was based on "known bad" values, it
1036 * should still be better for VBR files than using the bitrate
1037 * of the first audio frame.
1042 entry->bitrate = info.bitrate;
1043 entry->frequency = info.frequency;
1044 entry->version = info.version;
1045 entry->layer = info.layer;
1046 switch(entry->layer) {
1047 #if CONFIG_CODEC==SWCODEC
1048 case 0:
1049 entry->codectype=AFMT_MPA_L1;
1050 break;
1051 #endif
1052 case 1:
1053 entry->codectype=AFMT_MPA_L2;
1054 break;
1055 case 2:
1056 entry->codectype=AFMT_MPA_L3;
1057 break;
1060 /* If the file time hasn't been established, this may be a fixed
1061 rate MP3, so just use the default formula */
1063 filetime = info.file_time;
1065 if(filetime == 0)
1067 /* Prevent a division by zero */
1068 if (info.bitrate < 8)
1069 filetime = 0;
1070 else
1071 filetime = (entry->filesize - bytecount) / (info.bitrate / 8);
1072 /* bitrate is in kbps so this delivers milliseconds. Doing bitrate / 8
1073 * instead of filesize * 8 is exact, because mpeg audio bitrates are
1074 * always multiples of 8, and it avoids overflows. */
1077 entry->frame_count = info.frame_count;
1079 entry->vbr = info.is_vbr;
1080 entry->has_toc = info.has_toc;
1082 #if CONFIG_CODEC==SWCODEC
1083 entry->lead_trim = info.enc_delay;
1084 entry->tail_trim = info.enc_padding;
1085 #endif
1087 memcpy(entry->toc, info.toc, sizeof(info.toc));
1089 entry->vbr_header_pos = info.vbr_header_pos;
1091 /* Update the seek point for the first playable frame */
1092 entry->first_frame_offset = bytecount;
1093 logf("First frame is at %lx", entry->first_frame_offset);
1095 return filetime;
1099 * Checks all relevant information (such as ID3v1 tag, ID3v2 tag, length etc)
1100 * about an MP3 file and updates it's entry accordingly.
1102 Note, that this returns true for successful, false for error! */
1103 bool get_mp3_metadata(int fd, struct mp3entry *entry, const char *filename)
1105 #if CONFIG_CODEC != SWCODEC
1106 memset(entry, 0, sizeof(struct mp3entry));
1107 #endif
1109 strlcpy(entry->path, filename, sizeof(entry->path));
1111 entry->title = NULL;
1112 entry->filesize = filesize(fd);
1113 entry->id3v2len = getid3v2len(fd);
1114 entry->tracknum = 0;
1115 entry->discnum = 0;
1117 if (entry->id3v2len)
1118 setid3v2title(fd, entry);
1119 int len = getsonglength(fd, entry);
1120 if (len < 0)
1121 return false;
1122 entry->length = len;
1124 /* Subtract the meta information from the file size to get
1125 the true size of the MP3 stream */
1126 entry->filesize -= entry->first_frame_offset;
1128 /* only seek to end of file if no id3v2 tags were found */
1129 if (!entry->id3v2len) {
1130 setid3v1title(fd, entry);
1133 if(!entry->length || (entry->filesize < 8 ))
1134 /* no song length or less than 8 bytes is hereby considered to be an
1135 invalid mp3 and won't be played by us! */
1136 return false;
1138 return true;
1141 #ifdef DEBUG_STANDALONE
1143 char *secs2str(int ms)
1145 static char buffer[32];
1146 int secs = ms/1000;
1147 ms %= 1000;
1148 snprintf(buffer, sizeof(buffer), "%d:%02d.%d", secs/60, secs%60, ms/100);
1149 return buffer;
1152 int main(int argc, char **argv)
1154 int i;
1155 for(i=1; i<argc; i++) {
1156 struct mp3entry mp3;
1157 mp3.album = "Bogus";
1158 if(mp3info(&mp3, argv[i], false)) {
1159 printf("Failed to get %s\n", argv[i]);
1160 return 0;
1163 printf("****** File: %s\n"
1164 " Title: %s\n"
1165 " Artist: %s\n"
1166 " Album: %s\n"
1167 " Genre: %s (%d) \n"
1168 " Composer: %s\n"
1169 " Year: %s (%d)\n"
1170 " Track: %s (%d)\n"
1171 " Length: %s / %d s\n"
1172 " Bitrate: %d\n"
1173 " Frequency: %d\n",
1174 argv[i],
1175 mp3.title?mp3.title:"<blank>",
1176 mp3.artist?mp3.artist:"<blank>",
1177 mp3.album?mp3.album:"<blank>",
1178 mp3.genre_string?mp3.genre_string:"<blank>",
1179 mp3.genre,
1180 mp3.composer?mp3.composer:"<blank>",
1181 mp3.year_string?mp3.year_string:"<blank>",
1182 mp3.year,
1183 mp3.track_string?mp3.track_string:"<blank>",
1184 mp3.tracknum,
1185 secs2str(mp3.length),
1186 mp3.length/1000,
1187 mp3.bitrate,
1188 mp3.frequency);
1191 return 0;
1194 #endif