summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Nielsen Feltzing <linus@haxx.se>2003-04-13 15:01:44 +0000
committerLinus Nielsen Feltzing <linus@haxx.se>2003-04-13 15:01:44 +0000
commit1793634a9bbb85b9c1997c65b66fe17f00b51695 (patch)
tree6629762b58cad47590eec8511a3dc3832e8a4549
parentb5401749cb413a644d7d787e804506b71e7898e1 (diff)
downloadrockbox-1793634a9bbb85b9c1997c65b66fe17f00b51695.tar.gz
rockbox-1793634a9bbb85b9c1997c65b66fe17f00b51695.zip
VBRFix should now work on all VBR files, with or without Xing headers and ID3 tags
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@3545 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/onplay.c113
1 files changed, 68 insertions, 45 deletions
diff --git a/apps/onplay.c b/apps/onplay.c
index fb9d940bf3..ceaae2c238 100644
--- a/apps/onplay.c
+++ b/apps/onplay.c
@@ -117,7 +117,7 @@ static void xingupdate(int percent)
117extern unsigned char mp3buf[]; 117extern unsigned char mp3buf[];
118extern unsigned char mp3end[]; 118extern unsigned char mp3end[];
119 119
120static int insert_space_in_file(char *fname, int fpos, int num_bytes) 120static int insert_data_in_file(char *fname, int fpos, char *buf, int num_bytes)
121{ 121{
122 int readlen; 122 int readlen;
123 int rc; 123 int rc;
@@ -154,23 +154,14 @@ static int insert_space_in_file(char *fname, int fpos, int num_bytes)
154 } 154 }
155 } 155 }
156 156
157 /* Now insert some 0's in the file */ 157 /* Now insert the data into the file */
158 memset(mp3buf, 0, num_bytes); 158 rc = write(fd, buf, num_bytes);
159
160 rc = write(fd, mp3buf, num_bytes);
161 if(rc < 0) { 159 if(rc < 0) {
162 close(orig_fd); 160 close(orig_fd);
163 close(fd); 161 close(fd);
164 return 10*rc - 5; 162 return 10*rc - 5;
165 } 163 }
166 164
167 rc = lseek(orig_fd, 0, SEEK_SET);
168 if(rc < 0) {
169 close(orig_fd);
170 close(fd);
171 return 10*rc - 6;
172 }
173
174 /* Copy the file */ 165 /* Copy the file */
175 do { 166 do {
176 readlen = read(orig_fd, mp3buf, mp3end - mp3buf); 167 readlen = read(orig_fd, mp3buf, mp3end - mp3buf);
@@ -211,6 +202,12 @@ static void fileerror(int rc)
211 splash(HZ*2, 0, true, "File error: %d", rc); 202 splash(HZ*2, 0, true, "File error: %d", rc);
212} 203}
213 204
205static const unsigned char empty_id3_header[] =
206{
207 'I', 'D', '3', 0x04, 0x00, 0x00,
208 0x00, 0x00, 0x1f, 0x76 /* Size is 4096 minus 10 bytes for the header */
209};
210
214static bool vbr_fix(void) 211static bool vbr_fix(void)
215{ 212{
216 unsigned char xingbuf[417]; 213 unsigned char xingbuf[417];
@@ -264,55 +261,81 @@ static bool vbr_fix(void)
264 fpos = entry.vbr_header_pos; 261 fpos = entry.vbr_header_pos;
265 262
266 DEBUGF("Reusing Xing header at %d\n", fpos); 263 DEBUGF("Reusing Xing header at %d\n", fpos);
264
265 rc = lseek(fd, entry.vbr_header_pos, SEEK_SET);
266 if(rc < 0) {
267 close(fd);
268 fileerror(rc);
269 return true;
270 }
271
272 rc = write(fd, xingbuf, 417);
273 if(rc < 0) {
274 close(fd);
275 fileerror(rc);
276 return true;
277 }
278
279 close(fd);
267 } else { 280 } else {
268 /* Any room between ID3 tag and first MP3 frame? */ 281 /* Any room between ID3 tag and first MP3 frame? */
269 if(entry.first_frame_offset - entry.id3v2len > 417) { 282 if(entry.first_frame_offset - entry.id3v2len > 417) {
270 fpos = entry.first_frame_offset - 417; 283 DEBUGF("Using existing space between ID3 and first frame\n");
284 rc = lseek(fd, entry.first_frame_offset - 417, SEEK_SET);
285 if(rc < 0) {
286 close(fd);
287 fileerror(rc);
288 return true;
289 }
290
291 rc = write(fd, xingbuf, 417);
292 if(rc < 0) {
293 close(fd);
294 fileerror(rc);
295 return true;
296 }
297
298 close(fd);
271 } else { 299 } else {
272 /* If not, insert some space. If there is an ID3 tag in the 300 /* If not, insert some space. If there is an ID3 tag in the
273 file we only insert just enough to squeeze the Xing header 301 file we only insert just enough to squeeze the Xing header
274 in. If not, we insert 4K. */ 302 in. If not, we insert an additional empty ID3 tag of 4K. */
303
275 close(fd); 304 close(fd);
276 if(entry.first_frame_offset) 305
306 /* Nasty trick alert! The insert_data_in_file() function
307 uses the MP3 buffer when copying the data. We assume
308 that the ID3 tag isn't longer than 1MB so the xing
309 buffer won't be overwritten. */
310
311 if(entry.first_frame_offset) {
312 DEBUGF("Inserting 417 bytes\n");
277 numbytes = 417; 313 numbytes = 417;
278 else 314 } else {
279 numbytes = 4096; 315 DEBUGF("Inserting 4096+417 bytes\n");
316 numbytes = 4096 + 417;
317
318 memset(mp3buf + 0x100000, 0, numbytes);
319
320 /* Insert the ID3 header */
321 memcpy(mp3buf + 0x100000, empty_id3_header,
322 sizeof(empty_id3_header));
323 }
324
325 /* Copy the Xing header */
326 memcpy(mp3buf + 0x100000 + numbytes - 417, xingbuf, 417);
280 327
281 rc = insert_space_in_file(selected_file, 328 rc = insert_data_in_file(selected_file,
282 entry.first_frame_offset, numbytes); 329 entry.first_frame_offset,
330 mp3buf + 0x100000, numbytes);
283 331
284 if(rc < 0) { 332 if(rc < 0) {
285 fileerror(rc); 333 fileerror(rc);
286 return true; 334 return true;
287 } 335 }
288
289 /* Reopen the file */
290 fd = open(selected_file, O_RDWR);
291 if(fd < 0) {
292 splash(HZ*2, 0, true, "File reopen error: %d", fd);
293 return true;
294 }
295
296 fpos = numbytes - 417;
297 } 336 }
298 } 337 }
299 338
300 rc = lseek(fd, fpos, SEEK_SET);
301 if(rc < 0) {
302 close(fd);
303 fileerror(rc);
304 return true;
305 }
306
307 rc = write(fd, xingbuf, 417);
308 if(rc < 0) {
309 close(fd);
310 fileerror(rc);
311 return true;
312 }
313
314 close(fd);
315
316 xingupdate(100); 339 xingupdate(100);
317 } 340 }
318 else 341 else
@@ -352,7 +375,7 @@ int onplay(char* file, int attr)
352 375
353 if (attr & TREE_ATTR_MPA) 376 if (attr & TREE_ATTR_MPA)
354 { 377 {
355 menu[i].desc = "VBRfix"; 378 menu[i].desc = str(LANG_VBRFIX);
356 menu[i].function = vbr_fix; 379 menu[i].function = vbr_fix;
357 i++; 380 i++;
358 } 381 }