summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--firmware/id3.c105
1 files changed, 88 insertions, 17 deletions
diff --git a/firmware/id3.c b/firmware/id3.c
index d059841991..a76cd2bc3e 100644
--- a/firmware/id3.c
+++ b/firmware/id3.c
@@ -108,6 +108,35 @@ struct tag_resolver {
108 int (*ppFunc)(struct mp3entry*, char* tag, int bufferpos); 108 int (*ppFunc)(struct mp3entry*, char* tag, int bufferpos);
109}; 109};
110 110
111static int unsynchronize(char* tag, int len)
112{
113 int i;
114 unsigned char c;
115 unsigned char *rp, *wp;
116 bool ff_found = false;
117
118 wp = rp = tag;
119
120 rp = (unsigned char *)tag;
121 for(i = 0;i < len;i++) {
122 /* Read the next byte and write it back, but don't increment the
123 write pointer */
124 c = *rp++;
125 *wp = c;
126 if(ff_found) {
127 /* Increment the write pointer if it isn't an unsynch pattern */
128 if(c != 0)
129 wp++;
130 ff_found = false;
131 } else {
132 if(c == 0xff)
133 ff_found = true;
134 wp++;
135 }
136 }
137 return (int)wp - (int)tag;
138}
139
111/* parse numeric value from string */ 140/* parse numeric value from string */
112static int parsetracknum( struct mp3entry* entry, char* tag, int bufferpos ) 141static int parsetracknum( struct mp3entry* entry, char* tag, int bufferpos )
113{ 142{
@@ -326,12 +355,17 @@ static void setid3v2title(int fd, struct mp3entry *entry)
326 int size; 355 int size;
327 int bufferpos = 0, totframelen, framelen; 356 int bufferpos = 0, totframelen, framelen;
328 char header[10]; 357 char header[10];
358 char tmp[4];
329 unsigned char version; 359 unsigned char version;
330 char *buffer = entry->id3v2buf; 360 char *buffer = entry->id3v2buf;
331 int bytesread = 0; 361 int bytesread = 0;
332 int buffersize = sizeof(entry->id3v2buf); 362 int buffersize = sizeof(entry->id3v2buf);
363 unsigned char global_flags;
333 int flags; 364 int flags;
334 int skip; 365 int skip;
366 bool global_unsynch = false;
367 bool unsynch = false;
368 int data_length_ind;
335 int i; 369 int i;
336 370
337 /* Bail out if the tag is shorter than 10 bytes */ 371 /* Bail out if the tag is shorter than 10 bytes */
@@ -372,9 +406,11 @@ static void setid3v2title(int fd, struct mp3entry *entry)
372 entry->genre = 0xff; 406 entry->genre = 0xff;
373 entry->title = entry->artist = entry->album = NULL; 407 entry->title = entry->artist = entry->album = NULL;
374 408
409 global_flags = header[5];
410
375 /* Skip the extended header if it is present */ 411 /* Skip the extended header if it is present */
376 if(version >= ID3_VER_2_4) { 412 if(version >= ID3_VER_2_4) {
377 if(header[5] & 0x40) { 413 if(global_flags & 0x40) {
378 if(4 != read(fd, header, 4)) 414 if(4 != read(fd, header, 4))
379 return; 415 return;
380 416
@@ -384,6 +420,11 @@ static void setid3v2title(int fd, struct mp3entry *entry)
384 lseek(fd, framelen - 4, SEEK_CUR); 420 lseek(fd, framelen - 4, SEEK_CUR);
385 } 421 }
386 } 422 }
423
424 /* Is unsynchronization applied? */
425 if(global_flags & 0x80) {
426 global_unsynch = true;
427 }
387 428
388 /* 429 /*
389 * We must have at least minframesize bytes left for the 430 * We must have at least minframesize bytes left for the
@@ -425,13 +466,18 @@ static void setid3v2title(int fd, struct mp3entry *entry)
425 if(framelen == 0) 466 if(framelen == 0)
426 return; 467 return;
427 468
469 unsynch = false;
470 data_length_ind = 0;
471
428 if(flags) 472 if(flags)
429 { 473 {
430 skip = 0; 474 skip = 0;
431 475
432 if(flags & 0x0040) /* Grouping identity */ 476 if(flags & 0x0040) { /* Grouping identity */
433 skip++; 477 lseek(fd, 1, SEEK_CUR); /* Skip 1 byte */
434 478 framelen--;
479 }
480
435 if(flags & 0x000c) /* Compression or encryption */ 481 if(flags & 0x000c) /* Compression or encryption */
436 { 482 {
437 /* Skip it using the total size in case 483 /* Skip it using the total size in case
@@ -441,19 +487,18 @@ static void setid3v2title(int fd, struct mp3entry *entry)
441 continue; 487 continue;
442 } 488 }
443 489
444 /* The Unsynchronization flag can't be trusted, so we 490 if(flags & 0x0002) /* Unsynchronization */
445 don't check it for now... */ 491 unsynch = true;
446
447 if(flags & 0x0001) /* Data length indicator */
448 skip += 4;
449 492
450 if(skip) 493 if(flags & 0x0001) { /* Data length indicator */
451 { 494 if(4 != read(fd, tmp, 4))
452 lseek(fd, skip, SEEK_CUR); 495 return;
453 framelen -= skip; 496
497 data_length_ind = UNSYNC(tmp[0], tmp[1], tmp[2], tmp[3]);
498 framelen -= 4;
454 } 499 }
455 } 500 }
456 501
457 /* If the frame is larger than the remaining buffer space we try 502 /* If the frame is larger than the remaining buffer space we try
458 to read as much as would fit in the buffer */ 503 to read as much as would fit in the buffer */
459 if(framelen >= buffersize - bufferpos) 504 if(framelen >= buffersize - bufferpos)
@@ -494,6 +539,10 @@ static void setid3v2title(int fd, struct mp3entry *entry)
494 539
495 size -= bytesread; 540 size -= bytesread;
496 *ptag = buffer + bufferpos; 541 *ptag = buffer + bufferpos;
542
543 if(global_unsynch || unsynch)
544 bytesread = unsynchronize(*ptag, bytesread);
545
497 unicode_munge( ptag, &bytesread ); 546 unicode_munge( ptag, &bytesread );
498 tag = *ptag; 547 tag = *ptag;
499 tag[bytesread + 1] = 0; 548 tag[bytesread + 1] = 0;
@@ -508,9 +557,31 @@ static void setid3v2title(int fd, struct mp3entry *entry)
508 /* no tag in tagList was found, or it was a repeat. 557 /* no tag in tagList was found, or it was a repeat.
509 skip it using the total size */ 558 skip it using the total size */
510 559
511 size -= totframelen; 560 /* We may need to compensate for the unsynchronization scheme */
512 if( lseek(fd, totframelen, SEEK_CUR) == -1 ) 561 if(global_unsynch && !data_length_ind) {
513 return; 562 bool ff_found = false;
563
564 for(i = 0;i < totframelen;i++) {
565 unsigned char c;
566 bytesread = read(fd, &c, 1);
567 if(ff_found) {
568 if(c == 0)
569 /* Found an unsynch pattern, counting it */
570 totframelen++;
571 ff_found = false;
572 } else {
573 if(c == 0xff)
574 ff_found = true;
575 }
576 }
577 } else {
578 if(data_length_ind)
579 totframelen = data_length_ind;
580
581 size -= totframelen;
582 if( lseek(fd, totframelen, SEEK_CUR) == -1 )
583 return;
584 }
514 } 585 }
515 } 586 }
516} 587}