summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
authorLinus Nielsen Feltzing <linus@haxx.se>2004-01-04 00:37:30 +0000
committerLinus Nielsen Feltzing <linus@haxx.se>2004-01-04 00:37:30 +0000
commit219d52a86f47093868152122d791a84c54b0289b (patch)
treefdccb072cf27c5e770d7d5c4a4218032449170d0 /firmware
parent32c66315c8e2b8ed791f42f01c6ac1c2f5a24196 (diff)
downloadrockbox-219d52a86f47093868152122d791a84c54b0289b.tar.gz
rockbox-219d52a86f47093868152122d791a84c54b0289b.zip
ID3v2.3 treats the global unsynch flag in a silly way, so we have to unsynch the whole tag before we can parse the individual frames.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@4188 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/id3.c105
1 files changed, 79 insertions, 26 deletions
diff --git a/firmware/id3.c b/firmware/id3.c
index f3d1285f0c..1fad5ce8d3 100644
--- a/firmware/id3.c
+++ b/firmware/id3.c
@@ -40,6 +40,7 @@
40 40
41#include "id3.h" 41#include "id3.h"
42#include "mp3data.h" 42#include "mp3data.h"
43#include "system.h"
43 44
44#define UNSYNC(b0,b1,b2,b3) (((b0 & 0x7F) << (3*7)) | \ 45#define UNSYNC(b0,b1,b2,b3) (((b0 & 0x7F) << (3*7)) | \
45 ((b1 & 0x7F) << (2*7)) | \ 46 ((b1 & 0x7F) << (2*7)) | \
@@ -108,12 +109,13 @@ struct tag_resolver {
108 int (*ppFunc)(struct mp3entry*, char* tag, int bufferpos); 109 int (*ppFunc)(struct mp3entry*, char* tag, int bufferpos);
109}; 110};
110 111
111static int unsynchronize(char* tag, int len) 112static bool global_ff_found = false;
113
114static int unsynchronize(char* tag, int len, bool *ff_found)
112{ 115{
113 int i; 116 int i;
114 unsigned char c; 117 unsigned char c;
115 unsigned char *rp, *wp; 118 unsigned char *rp, *wp;
116 bool ff_found = false;
117 119
118 wp = rp = tag; 120 wp = rp = tag;
119 121
@@ -123,20 +125,76 @@ static int unsynchronize(char* tag, int len)
123 write pointer */ 125 write pointer */
124 c = *rp++; 126 c = *rp++;
125 *wp = c; 127 *wp = c;
126 if(ff_found) { 128 if(*ff_found) {
127 /* Increment the write pointer if it isn't an unsynch pattern */ 129 /* Increment the write pointer if it isn't an unsynch pattern */
128 if(c != 0) 130 if(c != 0)
129 wp++; 131 wp++;
130 ff_found = false; 132 *ff_found = false;
131 } else { 133 } else {
132 if(c == 0xff) 134 if(c == 0xff)
133 ff_found = true; 135 *ff_found = true;
134 wp++; 136 wp++;
135 } 137 }
136 } 138 }
137 return (int)wp - (int)tag; 139 return (int)wp - (int)tag;
138} 140}
139 141
142static int unsynchronize_frame(char* tag, int len)
143{
144 bool ff_found = false;
145
146 return unsynchronize(tag, len, &ff_found);
147}
148
149static int read_unsynched(int fd, void *buf, int len, bool reset)
150{
151 int i;
152 int rc;
153 int remaining = len;
154 char *wp;
155 char *rp;
156
157 if(reset)
158 global_ff_found = false;
159
160 wp = buf;
161
162 while(remaining) {
163 rp = wp;
164 rc = read(fd, rp, remaining);
165 if(rc < 0)
166 return rc;
167
168 i = unsynchronize(wp, remaining, &global_ff_found);
169 remaining -= i;
170 wp += i;
171 }
172
173 return len;
174};
175
176static int skip_unsynched(int fd, int len, bool reset)
177{
178 int rc;
179 int remaining = len;
180 int rlen;
181 char buf[32];
182
183 if(reset)
184 global_ff_found = false;
185
186 while(remaining) {
187 rlen = MIN(sizeof(buf), (unsigned int)remaining);
188 rc = read(fd, buf, rlen);
189 if(rc < 0)
190 return rc;
191
192 remaining -= unsynchronize(buf, rlen, &global_ff_found);
193 }
194
195 return len;
196};
197
140/* parse numeric value from string */ 198/* parse numeric value from string */
141static int parsetracknum( struct mp3entry* entry, char* tag, int bufferpos ) 199static int parsetracknum( struct mp3entry* entry, char* tag, int bufferpos )
142{ 200{
@@ -365,6 +423,7 @@ static void setid3v2title(int fd, struct mp3entry *entry)
365 bool unsynch = false; 423 bool unsynch = false;
366 int data_length_ind; 424 int data_length_ind;
367 int i; 425 int i;
426 int rc;
368 427
369 /* Bail out if the tag is shorter than 10 bytes */ 428 /* Bail out if the tag is shorter than 10 bytes */
370 if(entry->id3v2len < 10) 429 if(entry->id3v2len < 10)
@@ -433,7 +492,11 @@ static void setid3v2title(int fd, struct mp3entry *entry)
433 492
434 /* Read frame header and check length */ 493 /* Read frame header and check length */
435 if(version >= ID3_VER_2_3) { 494 if(version >= ID3_VER_2_3) {
436 if(10 != read(fd, header, 10)) 495 if(global_unsynch && version <= ID3_VER_2_3)
496 rc = read_unsynched(fd, header, 10, false);
497 else
498 rc = read(fd, header, 10);
499 if(rc != 10)
437 return; 500 return;
438 /* Adjust for the 10 bytes we read */ 501 /* Adjust for the 10 bytes we read */
439 size -= 10; 502 size -= 10;
@@ -531,15 +594,20 @@ static void setid3v2title(int fd, struct mp3entry *entry)
531 if( !*ptag && !memcmp( header, tr->tag, tr->tag_length ) ) { 594 if( !*ptag && !memcmp( header, tr->tag, tr->tag_length ) ) {
532 595
533 /* found a tag matching one in tagList, and not yet filled */ 596 /* found a tag matching one in tagList, and not yet filled */
534 bytesread = read(fd, buffer + bufferpos, framelen); 597 if(global_unsynch && version <= ID3_VER_2_3)
598 bytesread = read_unsynched(fd, buffer + bufferpos,
599 framelen, false);
600 else
601 bytesread = read(fd, buffer + bufferpos, framelen);
602
535 if( bytesread != framelen ) 603 if( bytesread != framelen )
536 return; 604 return;
537 605
538 size -= bytesread; 606 size -= bytesread;
539 *ptag = buffer + bufferpos; 607 *ptag = buffer + bufferpos;
540 608
541 if(global_unsynch || unsynch) 609 if(unsynch || (global_unsynch && version >= ID3_VER_2_4))
542 bytesread = unsynchronize(*ptag, bytesread); 610 bytesread = unsynchronize_frame(*ptag, bytesread);
543 611
544 unicode_munge( ptag, &bytesread ); 612 unicode_munge( ptag, &bytesread );
545 tag = *ptag; 613 tag = *ptag;
@@ -555,23 +623,8 @@ static void setid3v2title(int fd, struct mp3entry *entry)
555 /* no tag in tagList was found, or it was a repeat. 623 /* no tag in tagList was found, or it was a repeat.
556 skip it using the total size */ 624 skip it using the total size */
557 625
558 /* We may need to compensate for the unsynchronization scheme */ 626 if(global_unsynch && version <= ID3_VER_2_3) {
559 if(global_unsynch && !data_length_ind) { 627 skip_unsynched(fd, totframelen, false);
560 bool ff_found = false;
561
562 for(i = 0;i < totframelen;i++) {
563 unsigned char c;
564 bytesread = read(fd, &c, 1);
565 if(ff_found) {
566 if(c == 0)
567 /* Found an unsynch pattern, counting it */
568 totframelen++;
569 ff_found = false;
570 } else {
571 if(c == 0xff)
572 ff_found = true;
573 }
574 }
575 } else { 628 } else {
576 if(data_length_ind) 629 if(data_length_ind)
577 totframelen = data_length_ind; 630 totframelen = data_length_ind;