diff options
Diffstat (limited to 'apps')
-rw-r--r-- | apps/plugins/test_codec.c | 332 |
1 files changed, 224 insertions, 108 deletions
diff --git a/apps/plugins/test_codec.c b/apps/plugins/test_codec.c index de3746bb29..446bffb8a1 100644 --- a/apps/plugins/test_codec.c +++ b/apps/plugins/test_codec.c | |||
@@ -30,6 +30,52 @@ PLUGIN_HEADER | |||
30 | 30 | ||
31 | static struct plugin_api* rb; | 31 | static struct plugin_api* rb; |
32 | 32 | ||
33 | /* Log functions copied from test_disk.c */ | ||
34 | static int line = 0; | ||
35 | static int max_line = 0; | ||
36 | static int log_fd = -1; | ||
37 | static char logfilename[MAX_PATH]; | ||
38 | |||
39 | static bool log_init(bool use_logfile) | ||
40 | { | ||
41 | int h; | ||
42 | |||
43 | rb->lcd_setmargins(0, 0); | ||
44 | rb->lcd_getstringsize("A", NULL, &h); | ||
45 | max_line = LCD_HEIGHT / h; | ||
46 | line = 0; | ||
47 | rb->lcd_clear_display(); | ||
48 | rb->lcd_update(); | ||
49 | |||
50 | if (use_logfile) { | ||
51 | rb->create_numbered_filename(logfilename, "/", "test_codec_log_", ".txt", | ||
52 | 2 IF_CNFN_NUM_(, NULL)); | ||
53 | log_fd = rb->open(logfilename, O_RDWR|O_CREAT|O_TRUNC); | ||
54 | return log_fd >= 0; | ||
55 | } | ||
56 | |||
57 | return true; | ||
58 | } | ||
59 | |||
60 | static void log_text(char *text, bool advance) | ||
61 | { | ||
62 | rb->lcd_puts(0, line, text); | ||
63 | rb->lcd_update(); | ||
64 | if (advance) | ||
65 | { | ||
66 | if (++line >= max_line) | ||
67 | line = 0; | ||
68 | if (log_fd >= 0) | ||
69 | rb->fdprintf(log_fd, "%s\n", text); | ||
70 | } | ||
71 | } | ||
72 | |||
73 | static void log_close(void) | ||
74 | { | ||
75 | if (log_fd >= 0) | ||
76 | rb->close(log_fd); | ||
77 | } | ||
78 | |||
33 | struct wavinfo_t | 79 | struct wavinfo_t |
34 | { | 80 | { |
35 | int fd; | 81 | int fd; |
@@ -43,7 +89,7 @@ struct wavinfo_t | |||
43 | static void* audiobuf; | 89 | static void* audiobuf; |
44 | static void* codec_mallocbuf; | 90 | static void* codec_mallocbuf; |
45 | static size_t audiosize; | 91 | static size_t audiosize; |
46 | static char str[40]; | 92 | static char str[MAX_PATH]; |
47 | 93 | ||
48 | /* Our local implementation of the codec API */ | 94 | /* Our local implementation of the codec API */ |
49 | static struct codec_api ci; | 95 | static struct codec_api ci; |
@@ -149,6 +195,9 @@ static bool pcmbuf_insert_null(const void *ch1, const void *ch2, int count) | |||
149 | (void)ch2; | 195 | (void)ch2; |
150 | (void)count; | 196 | (void)count; |
151 | 197 | ||
198 | /* Prevent idle poweroff */ | ||
199 | rb->reset_poweroff_timer(); | ||
200 | |||
152 | return true; | 201 | return true; |
153 | } | 202 | } |
154 | 203 | ||
@@ -174,6 +223,9 @@ static bool pcmbuf_insert_wav(const void *ch1, const void *ch2, int count) | |||
174 | unsigned char* p = wavbuffer; | 223 | unsigned char* p = wavbuffer; |
175 | int scale = wavinfo.sampledepth - 15; | 224 | int scale = wavinfo.sampledepth - 15; |
176 | 225 | ||
226 | /* Prevent idle poweroff */ | ||
227 | rb->reset_poweroff_timer(); | ||
228 | |||
177 | if (wavinfo.sampledepth <= 16) { | 229 | if (wavinfo.sampledepth <= 16) { |
178 | data1_16 = ch1; | 230 | data1_16 = ch1; |
179 | data2_16 = ch2; | 231 | data2_16 = ch2; |
@@ -445,127 +497,63 @@ static void codec_thread(void) | |||
445 | rb->remove_thread(NULL); | 497 | rb->remove_thread(NULL); |
446 | } | 498 | } |
447 | 499 | ||
448 | /* plugin entry point */ | 500 | static unsigned char* codec_stack; |
449 | enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | 501 | static size_t codec_stack_size; |
502 | |||
503 | static enum plugin_status test_track(char* filename) | ||
450 | { | 504 | { |
451 | size_t n; | 505 | size_t n; |
452 | int fd; | 506 | int fd; |
453 | int i; | ||
454 | enum plugin_status res = PLUGIN_OK; | 507 | enum plugin_status res = PLUGIN_OK; |
455 | unsigned long starttick; | 508 | unsigned long starttick; |
456 | unsigned long ticks; | 509 | unsigned long ticks; |
457 | unsigned long speed; | 510 | unsigned long speed; |
458 | unsigned long duration; | 511 | unsigned long duration; |
459 | unsigned char* codec_stack; | ||
460 | unsigned char* codec_stack_copy; | ||
461 | size_t codec_stack_size; | ||
462 | struct thread_entry* codecthread_id; | 512 | struct thread_entry* codecthread_id; |
463 | int result, selection = 0; | ||
464 | char* ch; | 513 | char* ch; |
465 | int line = 0; | ||
466 | |||
467 | rb = api; | ||
468 | |||
469 | if (parameter == NULL) | ||
470 | { | ||
471 | rb->splash(HZ*2, "No File"); | ||
472 | return PLUGIN_ERROR; | ||
473 | } | ||
474 | |||
475 | #ifdef SIMULATOR | ||
476 | /* The simulator thread implementation doesn't have stack buffers */ | ||
477 | (void)i; | ||
478 | codec_stack_size = 0; | ||
479 | #else | ||
480 | /* Borrow the codec thread's stack (in IRAM on most targets) */ | ||
481 | codec_stack = NULL; | ||
482 | for (i = 0; i < MAXTHREADS; i++) | ||
483 | { | ||
484 | if (rb->strcmp(rb->threads[i].name,"codec")==0) | ||
485 | { | ||
486 | codec_stack = rb->threads[i].stack; | ||
487 | codec_stack_size = rb->threads[i].stack_size; | ||
488 | break; | ||
489 | } | ||
490 | } | ||
491 | 514 | ||
492 | if (codec_stack == NULL) | 515 | /* Display filename (excluding any path)*/ |
493 | { | 516 | ch = rb->strrchr(filename, '/'); |
494 | rb->splash(HZ*2, "No codec thread!"); | 517 | if (ch==NULL) |
495 | return PLUGIN_ERROR; | 518 | ch = filename; |
496 | } | 519 | else |
497 | #endif | 520 | ch++; |
498 | 521 | ||
499 | codec_mallocbuf = rb->plugin_get_audio_buffer(&audiosize); | 522 | rb->snprintf(str,sizeof(str),"%s",ch); |
500 | codec_stack_copy = codec_mallocbuf + 512*1024; | 523 | log_text(str,true); |
501 | audiobuf = codec_stack_copy + codec_stack_size; | ||
502 | audiosize -= 512*1024 + codec_stack_size; | ||
503 | 524 | ||
504 | #ifndef SIMULATOR | 525 | log_text("Loading...",false); |
505 | /* Backup the codec thread's stack */ | ||
506 | rb->memcpy(codec_stack_copy,codec_stack,codec_stack_size); | ||
507 | #endif | ||
508 | 526 | ||
509 | fd = rb->open(parameter,O_RDONLY); | 527 | fd = rb->open(filename,O_RDONLY); |
510 | if (fd < 0) | 528 | if (fd < 0) |
511 | { | 529 | { |
512 | rb->splash(HZ*2, "Cannot open file"); | 530 | log_text("Cannot open file",true); |
513 | return PLUGIN_ERROR; | 531 | return PLUGIN_ERROR; |
514 | } | 532 | } |
515 | 533 | ||
516 | track.filesize = rb->filesize(fd); | 534 | track.filesize = rb->filesize(fd); |
517 | 535 | ||
518 | if (!rb->get_metadata(&track, fd, parameter, | 536 | /* Clear the id3 struct */ |
537 | rb->memset(&track.id3, 0, sizeof(struct mp3entry)); | ||
538 | |||
539 | if (!rb->get_metadata(&track, fd, filename, | ||
519 | rb->global_settings->id3_v1_first)) | 540 | rb->global_settings->id3_v1_first)) |
520 | { | 541 | { |
521 | rb->splash(HZ*2, "Cannot read metadata"); | 542 | log_text("Cannot read metadata",true); |
522 | return PLUGIN_ERROR; | 543 | return PLUGIN_ERROR; |
523 | } | 544 | } |
524 | 545 | ||
525 | if (track.filesize > audiosize) | 546 | if (track.filesize > audiosize) |
526 | { | 547 | { |
527 | rb->splash(HZ*2, "File too large"); | 548 | log_text("File too large",true); |
528 | return PLUGIN_ERROR; | 549 | return PLUGIN_ERROR; |
529 | } | 550 | } |
530 | 551 | ||
531 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | ||
532 | rb->cpu_boost(true); | ||
533 | #endif | ||
534 | rb->lcd_clear_display(); | ||
535 | rb->lcd_update(); | ||
536 | |||
537 | MENUITEM_STRINGLIST(menu,"test_codec",NULL,"Speed test","Write WAV"); | ||
538 | |||
539 | rb->lcd_clear_display(); | ||
540 | |||
541 | result=rb->do_menu(&menu,&selection); | ||
542 | |||
543 | if (result==0) { | ||
544 | wavinfo.fd = -1; | ||
545 | } else if (result==1) { | ||
546 | init_wav("/test.wav"); | ||
547 | if (wavinfo.fd < 0) { | ||
548 | rb->splash(HZ*2, "Cannot create /test.wav"); | ||
549 | res = PLUGIN_ERROR; | ||
550 | goto exit; | ||
551 | } | ||
552 | } else if (result == MENU_ATTACHED_USB) { | ||
553 | res = PLUGIN_USB_CONNECTED; | ||
554 | goto exit; | ||
555 | } else if (result < 0) { | ||
556 | res = PLUGIN_OK; | ||
557 | goto exit; | ||
558 | } | ||
559 | |||
560 | rb->lcd_clear_display(); | ||
561 | rb->splash(0, "Loading..."); | ||
562 | rb->lcd_clear_display(); | ||
563 | |||
564 | n = rb->read(fd, audiobuf, track.filesize); | 552 | n = rb->read(fd, audiobuf, track.filesize); |
565 | 553 | ||
566 | if (n != track.filesize) | 554 | if (n != track.filesize) |
567 | { | 555 | { |
568 | rb->splash(HZ*2, "Read failed."); | 556 | log_text("Read failed.",true); |
569 | res = PLUGIN_ERROR; | 557 | res = PLUGIN_ERROR; |
570 | goto exit; | 558 | goto exit; |
571 | } | 559 | } |
@@ -590,44 +578,34 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | |||
590 | (uint8_t*)codec_stack, codec_stack_size, "testcodec" IF_PRIO(,PRIORITY_PLAYBACK) | 578 | (uint8_t*)codec_stack, codec_stack_size, "testcodec" IF_PRIO(,PRIORITY_PLAYBACK) |
591 | IF_COP(, CPU, false))) == NULL) | 579 | IF_COP(, CPU, false))) == NULL) |
592 | { | 580 | { |
593 | rb->splash(HZ, "Cannot create codec thread!"); | 581 | log_text("Cannot create codec thread!",true); |
594 | goto exit; | 582 | goto exit; |
595 | } | 583 | } |
596 | 584 | ||
597 | /* Display filename (excluding any path)*/ | ||
598 | ch = rb->strrchr(parameter, '/'); | ||
599 | if (ch==NULL) | ||
600 | ch = parameter; | ||
601 | else | ||
602 | ch++; | ||
603 | |||
604 | rb->snprintf(str,sizeof(str),"%s",ch); | ||
605 | rb->lcd_puts(0,line++,str); | ||
606 | |||
607 | /* Wait for codec thread to die */ | 585 | /* Wait for codec thread to die */ |
608 | while (codec_playing) | 586 | while (codec_playing) |
609 | { | 587 | { |
610 | rb->sleep(HZ); | 588 | rb->sleep(HZ); |
611 | rb->snprintf(str,sizeof(str),"%d of %d",elapsed,(int)track.id3.length); | 589 | rb->snprintf(str,sizeof(str),"%d of %d",elapsed,(int)track.id3.length); |
612 | rb->lcd_puts(0,line,str); | 590 | log_text(str,false); |
613 | rb->lcd_update(); | ||
614 | } | 591 | } |
615 | line++; | 592 | /* Save the current time before we spin up the disk to access the log */ |
593 | ticks = *rb->current_tick - starttick; | ||
594 | |||
595 | log_text(str,true); | ||
616 | 596 | ||
617 | /* Close WAV file (if there was one) */ | 597 | /* Close WAV file (if there was one) */ |
618 | if (wavinfo.fd >= 0) { | 598 | if (wavinfo.fd >= 0) { |
619 | close_wav(); | 599 | close_wav(); |
620 | rb->lcd_puts(0,line++,"Wrote /test.wav"); | 600 | log_text("Wrote /test.wav",true); |
621 | } else { | 601 | } else { |
622 | /* Display benchmark information */ | 602 | /* Display benchmark information */ |
623 | |||
624 | ticks = *rb->current_tick - starttick; | ||
625 | rb->snprintf(str,sizeof(str),"Decode time - %d.%02ds",(int)ticks/100,(int)ticks%100); | 603 | rb->snprintf(str,sizeof(str),"Decode time - %d.%02ds",(int)ticks/100,(int)ticks%100); |
626 | rb->lcd_puts(0,line++,str); | 604 | log_text(str,true); |
627 | 605 | ||
628 | duration = track.id3.length / 10; | 606 | duration = track.id3.length / 10; |
629 | rb->snprintf(str,sizeof(str),"File duration - %d.%02ds",(int)duration/100,(int)duration%100); | 607 | rb->snprintf(str,sizeof(str),"File duration - %d.%02ds",(int)duration/100,(int)duration%100); |
630 | rb->lcd_puts(0,line++,str); | 608 | log_text(str,true); |
631 | 609 | ||
632 | if (ticks > 0) | 610 | if (ticks > 0) |
633 | speed = duration * 10000 / ticks; | 611 | speed = duration * 10000 / ticks; |
@@ -635,14 +613,152 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | |||
635 | speed = 0; | 613 | speed = 0; |
636 | 614 | ||
637 | rb->snprintf(str,sizeof(str),"%d.%02d%% realtime",(int)speed/100,(int)speed%100); | 615 | rb->snprintf(str,sizeof(str),"%d.%02d%% realtime",(int)speed/100,(int)speed%100); |
638 | rb->lcd_puts(0,line++,str); | 616 | log_text(str,true); |
617 | } | ||
618 | |||
619 | /* Write an empty line to the log */ | ||
620 | log_text("",true); | ||
621 | |||
622 | exit: | ||
623 | return res; | ||
624 | } | ||
625 | |||
626 | /* plugin entry point */ | ||
627 | enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | ||
628 | { | ||
629 | unsigned char* codec_stack_copy; | ||
630 | int result, selection = 0; | ||
631 | enum plugin_status res = PLUGIN_OK; | ||
632 | int scandir; | ||
633 | int i; | ||
634 | struct dirent *entry; | ||
635 | DIR* dir; | ||
636 | char* ch; | ||
637 | char dirpath[MAX_PATH]; | ||
638 | char filename[MAX_PATH]; | ||
639 | |||
640 | rb = api; | ||
639 | 641 | ||
642 | if (parameter == NULL) | ||
643 | { | ||
644 | rb->splash(HZ*2, "No File"); | ||
645 | return PLUGIN_ERROR; | ||
646 | } | ||
647 | |||
648 | #ifdef SIMULATOR | ||
649 | /* The simulator thread implementation doesn't have stack buffers */ | ||
650 | (void)i; | ||
651 | codec_stack_size = 0; | ||
652 | #else | ||
653 | /* Borrow the codec thread's stack (in IRAM on most targets) */ | ||
654 | codec_stack = NULL; | ||
655 | for (i = 0; i < MAXTHREADS; i++) | ||
656 | { | ||
657 | if (rb->strcmp(rb->threads[i].name,"codec")==0) | ||
658 | { | ||
659 | codec_stack = rb->threads[i].stack; | ||
660 | codec_stack_size = rb->threads[i].stack_size; | ||
661 | break; | ||
662 | } | ||
663 | } | ||
664 | |||
665 | if (codec_stack == NULL) | ||
666 | { | ||
667 | rb->splash(HZ*2, "No codec thread!"); | ||
668 | return PLUGIN_ERROR; | ||
640 | } | 669 | } |
670 | #endif | ||
671 | |||
672 | codec_mallocbuf = rb->plugin_get_audio_buffer(&audiosize); | ||
673 | codec_stack_copy = codec_mallocbuf + 512*1024; | ||
674 | audiobuf = codec_stack_copy + codec_stack_size; | ||
675 | audiosize -= 512*1024 + codec_stack_size; | ||
676 | |||
677 | #ifndef SIMULATOR | ||
678 | /* Backup the codec thread's stack */ | ||
679 | rb->memcpy(codec_stack_copy,codec_stack,codec_stack_size); | ||
680 | #endif | ||
681 | |||
682 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | ||
683 | rb->cpu_boost(true); | ||
684 | #endif | ||
685 | rb->lcd_clear_display(); | ||
641 | rb->lcd_update(); | 686 | rb->lcd_update(); |
642 | 687 | ||
643 | while (rb->button_get(true) != TESTCODEC_EXITBUTTON); | 688 | MENUITEM_STRINGLIST( |
689 | menu, "test_codec", NULL, | ||
690 | "Speed test", | ||
691 | "Speed test folder", | ||
692 | "Write WAV", | ||
693 | ); | ||
694 | |||
695 | rb->lcd_clear_display(); | ||
696 | |||
697 | result=rb->do_menu(&menu,&selection); | ||
698 | |||
699 | scandir = 0; | ||
700 | |||
701 | if (result==0) { | ||
702 | wavinfo.fd = -1; | ||
703 | log_init(false); | ||
704 | } else if (result==1) { | ||
705 | wavinfo.fd = -1; | ||
706 | scandir = 1; | ||
707 | |||
708 | /* Only create a log file when we are testing a folder */ | ||
709 | if (!log_init(true)) { | ||
710 | rb->splash(HZ*2, "Cannot create logfile"); | ||
711 | res = PLUGIN_ERROR; | ||
712 | goto exit; | ||
713 | } | ||
714 | } else if (result==2) { | ||
715 | log_init(false); | ||
716 | init_wav("/test.wav"); | ||
717 | if (wavinfo.fd < 0) { | ||
718 | rb->splash(HZ*2, "Cannot create /test.wav"); | ||
719 | res = PLUGIN_ERROR; | ||
720 | goto exit; | ||
721 | } | ||
722 | } else if (result == MENU_ATTACHED_USB) { | ||
723 | res = PLUGIN_USB_CONNECTED; | ||
724 | goto exit; | ||
725 | } else if (result < 0) { | ||
726 | res = PLUGIN_OK; | ||
727 | goto exit; | ||
728 | } | ||
729 | |||
730 | if (scandir) { | ||
731 | /* Test all files in the same directory as the file selected by the | ||
732 | user */ | ||
733 | |||
734 | rb->strncpy(dirpath,parameter,sizeof(dirpath)); | ||
735 | ch = rb->strrchr(dirpath,'/'); | ||
736 | ch[1]=0; | ||
737 | |||
738 | DEBUGF("Scanning directory \"%s\"\n",dirpath); | ||
739 | dir = rb->opendir(dirpath); | ||
740 | if (dir) { | ||
741 | entry = rb->readdir(dir); | ||
742 | while (entry) { | ||
743 | if (!(entry->attribute & ATTR_DIRECTORY)) { | ||
744 | rb->snprintf(filename,sizeof(filename),"%s%s",dirpath,entry->d_name); | ||
745 | test_track(filename); | ||
746 | } | ||
747 | |||
748 | /* Read next entry */ | ||
749 | entry = rb->readdir(dir); | ||
750 | } | ||
751 | } | ||
752 | } else { | ||
753 | /* Just test the file */ | ||
754 | res = test_track(parameter); | ||
755 | |||
756 | while (rb->button_get(true) != TESTCODEC_EXITBUTTON); | ||
757 | } | ||
644 | 758 | ||
645 | exit: | 759 | exit: |
760 | log_close(); | ||
761 | |||
646 | #ifndef SIMULATOR | 762 | #ifndef SIMULATOR |
647 | /* Restore the codec thread's stack */ | 763 | /* Restore the codec thread's stack */ |
648 | rb->memcpy(codec_stack, codec_stack_copy, codec_stack_size); | 764 | rb->memcpy(codec_stack, codec_stack_copy, codec_stack_size); |