diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/id3.c | 105 |
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 | ||
111 | static int unsynchronize(char* tag, int len) | 112 | static bool global_ff_found = false; |
113 | |||
114 | static 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 | ||
142 | static int unsynchronize_frame(char* tag, int len) | ||
143 | { | ||
144 | bool ff_found = false; | ||
145 | |||
146 | return unsynchronize(tag, len, &ff_found); | ||
147 | } | ||
148 | |||
149 | static 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 | |||
176 | static 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 */ |
141 | static int parsetracknum( struct mp3entry* entry, char* tag, int bufferpos ) | 199 | static 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; |