diff options
author | Linus Nielsen Feltzing <linus@haxx.se> | 2003-10-22 13:06:31 +0000 |
---|---|---|
committer | Linus Nielsen Feltzing <linus@haxx.se> | 2003-10-22 13:06:31 +0000 |
commit | 5557fe3259b1e0c5fb6c7527456b6cbca9da9208 (patch) | |
tree | 00e0afc4cac36570c23eb43bd917d8e8c5b73fc6 /firmware | |
parent | 9ace15871d1d087d23a55ac5f48a887aa87872ba (diff) | |
download | rockbox-5557fe3259b1e0c5fb6c7527456b6cbca9da9208.tar.gz rockbox-5557fe3259b1e0c5fb6c7527456b6cbca9da9208.zip |
Added unsynchronization
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@3983 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/id3.c | 105 |
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 | ||
111 | static 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 */ |
112 | static int parsetracknum( struct mp3entry* entry, char* tag, int bufferpos ) | 141 | static 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 | } |