diff options
-rw-r--r-- | apps/lang/english.lang | 14 | ||||
-rw-r--r-- | apps/onplay.c | 253 |
2 files changed, 7 insertions, 260 deletions
diff --git a/apps/lang/english.lang b/apps/lang/english.lang index 21599cb992..4722d743a9 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang | |||
@@ -1316,21 +1316,21 @@ voice: "" | |||
1316 | new: | 1316 | new: |
1317 | 1317 | ||
1318 | id: LANG_VBRFIX_STOP_PLAY | 1318 | id: LANG_VBRFIX_STOP_PLAY |
1319 | desc: Tells the user to stop the playback | 1319 | desc: DEPRECATED |
1320 | eng: "Stop the playback first" | 1320 | eng: "" |
1321 | voice: "" | 1321 | voice: "" |
1322 | new: | 1322 | new: |
1323 | 1323 | ||
1324 | id: LANG_VBRFIX_NOT_VBR | 1324 | id: LANG_VBRFIX_NOT_VBR |
1325 | desc: Tells the user that the selected file is not a VBR file | 1325 | desc: DEPRECATED |
1326 | eng: "Not a VBR file" | 1326 | eng: "" |
1327 | voice: "" | 1327 | voice: "" |
1328 | new: | 1328 | new: |
1329 | 1329 | ||
1330 | id: LANG_VBRFIX | 1330 | id: LANG_VBRFIX |
1331 | desc: The context menu entry | 1331 | desc: DEPRECATED |
1332 | eng: "Update VBR file" | 1332 | eng: "" |
1333 | voice: "Update VBR file" | 1333 | voice: "" |
1334 | new: | 1334 | new: |
1335 | 1335 | ||
1336 | id: LANG_INVERT_CURSOR | 1336 | id: LANG_INVERT_CURSOR |
diff --git a/apps/onplay.c b/apps/onplay.c index d864b3b2a9..7873941af6 100644 --- a/apps/onplay.c +++ b/apps/onplay.c | |||
@@ -374,251 +374,6 @@ static bool rename_file(void) | |||
374 | return false; | 374 | return false; |
375 | } | 375 | } |
376 | 376 | ||
377 | static void xingupdate(int percent) | ||
378 | { | ||
379 | char buf[32]; | ||
380 | |||
381 | snprintf(buf, 32, "%d%%", percent); | ||
382 | lcd_puts(0, 1, buf); | ||
383 | lcd_update(); | ||
384 | } | ||
385 | |||
386 | |||
387 | static int insert_data_in_file(char *fname, int fpos, char *buf, int num_bytes) | ||
388 | { | ||
389 | int readlen; | ||
390 | int rc; | ||
391 | int orig_fd, fd; | ||
392 | char tmpname[MAX_PATH]; | ||
393 | |||
394 | talk_buffer_steal(); /* we use the mp3 buffer, need to tell */ | ||
395 | |||
396 | snprintf(tmpname, MAX_PATH, "%s.tmp", fname); | ||
397 | |||
398 | orig_fd = open(fname, O_RDONLY); | ||
399 | if(orig_fd < 0) { | ||
400 | return 10*orig_fd - 1; | ||
401 | } | ||
402 | |||
403 | fd = creat(tmpname, O_WRONLY); | ||
404 | if(fd < 0) { | ||
405 | close(orig_fd); | ||
406 | return 10*fd - 2; | ||
407 | } | ||
408 | |||
409 | /* First, copy the initial portion (the ID3 tag) */ | ||
410 | if(fpos) { | ||
411 | readlen = read(orig_fd, mp3buf, fpos); | ||
412 | if(readlen < 0) { | ||
413 | close(fd); | ||
414 | close(orig_fd); | ||
415 | return 10*readlen - 3; | ||
416 | } | ||
417 | |||
418 | rc = write(fd, mp3buf, readlen); | ||
419 | if(rc < 0) { | ||
420 | close(fd); | ||
421 | close(orig_fd); | ||
422 | return 10*rc - 4; | ||
423 | } | ||
424 | } | ||
425 | |||
426 | /* Now insert the data into the file */ | ||
427 | rc = write(fd, buf, num_bytes); | ||
428 | if(rc < 0) { | ||
429 | close(orig_fd); | ||
430 | close(fd); | ||
431 | return 10*rc - 5; | ||
432 | } | ||
433 | |||
434 | /* Copy the file */ | ||
435 | do { | ||
436 | readlen = read(orig_fd, mp3buf, mp3end - mp3buf); | ||
437 | if(readlen < 0) { | ||
438 | close(fd); | ||
439 | close(orig_fd); | ||
440 | return 10*readlen - 7; | ||
441 | } | ||
442 | |||
443 | rc = write(fd, mp3buf, readlen); | ||
444 | if(rc < 0) { | ||
445 | close(fd); | ||
446 | close(orig_fd); | ||
447 | return 10*rc - 8; | ||
448 | } | ||
449 | } while(readlen > 0); | ||
450 | |||
451 | close(fd); | ||
452 | close(orig_fd); | ||
453 | |||
454 | /* Remove the old file */ | ||
455 | rc = remove(fname); | ||
456 | if(rc < 0) { | ||
457 | return 10*rc - 9; | ||
458 | } | ||
459 | |||
460 | /* Replace the old file with the new */ | ||
461 | rc = rename(tmpname, fname); | ||
462 | if(rc < 0) { | ||
463 | return 10*rc - 9; | ||
464 | } | ||
465 | |||
466 | return 0; | ||
467 | } | ||
468 | |||
469 | static void fileerror(int rc) | ||
470 | { | ||
471 | splash(HZ*2, true, "File error: %d", rc); | ||
472 | } | ||
473 | |||
474 | static const unsigned char empty_id3_header[] = | ||
475 | { | ||
476 | 'I', 'D', '3', 0x04, 0x00, 0x00, | ||
477 | 0x00, 0x00, 0x1f, 0x76 /* Size is 4096 minus 10 bytes for the header */ | ||
478 | }; | ||
479 | |||
480 | static bool vbr_fix(void) | ||
481 | { | ||
482 | unsigned char xingbuf[1500]; | ||
483 | struct mp3entry entry; | ||
484 | int fd; | ||
485 | int rc; | ||
486 | int flen; | ||
487 | int num_frames; | ||
488 | int numbytes; | ||
489 | int framelen; | ||
490 | int unused_space; | ||
491 | |||
492 | if(mpeg_status()) { | ||
493 | splash(HZ*2, true, str(LANG_VBRFIX_STOP_PLAY)); | ||
494 | return onplay_result; | ||
495 | } | ||
496 | |||
497 | talk_buffer_steal(); /* we use the mp3 buffer, need to tell */ | ||
498 | |||
499 | lcd_clear_display(); | ||
500 | lcd_puts_scroll(0, 0, selected_file); | ||
501 | lcd_update(); | ||
502 | |||
503 | xingupdate(0); | ||
504 | |||
505 | rc = mp3info(&entry, selected_file); | ||
506 | if(rc < 0) { | ||
507 | fileerror(rc); | ||
508 | return true; | ||
509 | } | ||
510 | |||
511 | fd = open(selected_file, O_RDWR); | ||
512 | if(fd < 0) { | ||
513 | fileerror(fd); | ||
514 | return true; | ||
515 | } | ||
516 | |||
517 | flen = lseek(fd, 0, SEEK_END); | ||
518 | |||
519 | xingupdate(0); | ||
520 | |||
521 | num_frames = count_mp3_frames(fd, entry.first_frame_offset, | ||
522 | flen, xingupdate); | ||
523 | |||
524 | if(num_frames) { | ||
525 | /* Note: We don't need to pass a template header because it will be | ||
526 | taken from the mpeg stream */ | ||
527 | framelen = create_xing_header(fd, entry.first_frame_offset, | ||
528 | flen, xingbuf, num_frames, | ||
529 | 0, xingupdate, true); | ||
530 | |||
531 | /* Try to fit the Xing header first in the stream. Replace the existing | ||
532 | VBR header if there is one, else see if there is room between the | ||
533 | ID3 tag and the first MP3 frame. */ | ||
534 | if(entry.first_frame_offset - entry.id3v2len >= | ||
535 | (unsigned int)framelen) { | ||
536 | DEBUGF("Using existing space between ID3 and first frame\n"); | ||
537 | |||
538 | /* Seek to the beginning of the unused space */ | ||
539 | rc = lseek(fd, entry.id3v2len, SEEK_SET); | ||
540 | if(rc < 0) { | ||
541 | close(fd); | ||
542 | fileerror(rc); | ||
543 | return true; | ||
544 | } | ||
545 | |||
546 | unused_space = | ||
547 | entry.first_frame_offset - entry.id3v2len - framelen; | ||
548 | |||
549 | /* Fill the unused space with 0's (using the MP3 buffer) | ||
550 | and write it to the file */ | ||
551 | if(unused_space) | ||
552 | { | ||
553 | memset(mp3buf, 0, unused_space); | ||
554 | rc = write(fd, mp3buf, unused_space); | ||
555 | if(rc < 0) { | ||
556 | close(fd); | ||
557 | fileerror(rc); | ||
558 | return true; | ||
559 | } | ||
560 | } | ||
561 | |||
562 | /* Then write the Xing header */ | ||
563 | rc = write(fd, xingbuf, framelen); | ||
564 | if(rc < 0) { | ||
565 | close(fd); | ||
566 | fileerror(rc); | ||
567 | return true; | ||
568 | } | ||
569 | |||
570 | close(fd); | ||
571 | } else { | ||
572 | /* If not, insert some space. If there is an ID3 tag in the | ||
573 | file we only insert just enough to squeeze the Xing header | ||
574 | in. If not, we insert an additional empty ID3 tag of 4K. */ | ||
575 | |||
576 | close(fd); | ||
577 | |||
578 | /* Nasty trick alert! The insert_data_in_file() function | ||
579 | uses the MP3 buffer when copying the data. We assume | ||
580 | that the ID3 tag isn't longer than 1MB so the xing | ||
581 | buffer won't be overwritten. */ | ||
582 | |||
583 | if(entry.first_frame_offset) { | ||
584 | DEBUGF("Inserting %d bytes\n", framelen); | ||
585 | numbytes = framelen; | ||
586 | } else { | ||
587 | DEBUGF("Inserting 4096+%d bytes\n", framelen); | ||
588 | numbytes = 4096 + framelen; | ||
589 | |||
590 | memset(mp3buf + 0x100000, 0, numbytes); | ||
591 | |||
592 | /* Insert the ID3 header */ | ||
593 | memcpy(mp3buf + 0x100000, empty_id3_header, | ||
594 | sizeof(empty_id3_header)); | ||
595 | } | ||
596 | |||
597 | /* Copy the Xing header */ | ||
598 | memcpy(mp3buf + 0x100000 + numbytes - framelen, xingbuf, framelen); | ||
599 | |||
600 | rc = insert_data_in_file(selected_file, | ||
601 | entry.first_frame_offset, | ||
602 | mp3buf + 0x100000, numbytes); | ||
603 | |||
604 | if(rc < 0) { | ||
605 | fileerror(rc); | ||
606 | return true; | ||
607 | } | ||
608 | } | ||
609 | |||
610 | xingupdate(100); | ||
611 | } | ||
612 | else | ||
613 | { | ||
614 | /* Not a VBR file */ | ||
615 | DEBUGF("Not a VBR file\n"); | ||
616 | splash(HZ*2, true, str(LANG_VBRFIX_NOT_VBR)); | ||
617 | } | ||
618 | |||
619 | return false; | ||
620 | } | ||
621 | |||
622 | bool create_dir(void) | 377 | bool create_dir(void) |
623 | { | 378 | { |
624 | char dirname[MAX_PATH]; | 379 | char dirname[MAX_PATH]; |
@@ -696,14 +451,6 @@ int onplay(char* file, int attr) | |||
696 | items[i].function = delete_dir; | 451 | items[i].function = delete_dir; |
697 | i++; | 452 | i++; |
698 | } | 453 | } |
699 | |||
700 | if ((attr & TREE_ATTR_MASK) == TREE_ATTR_MPA) | ||
701 | { | ||
702 | items[i].desc = str(LANG_VBRFIX); | ||
703 | items[i].voice_id = LANG_VBRFIX; | ||
704 | items[i].function = vbr_fix; | ||
705 | i++; | ||
706 | } | ||
707 | } | 454 | } |
708 | 455 | ||
709 | items[i].desc = str(LANG_CREATE_DIR); | 456 | items[i].desc = str(LANG_CREATE_DIR); |