HD300 - plugins keymaps
[kugel-rb.git] / apps / plugins / test_codec.c
blob6def9ca2cdb3fd09c97cfb6fb0fd0ceb89a8bf60
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2007 Dave Chapman
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include "plugin.h"
25 /* All swcodec targets have BUTTON_SELECT apart from the H10 and M3 */
27 #if CONFIG_KEYPAD == IRIVER_H10_PAD
28 #define TESTCODEC_EXITBUTTON BUTTON_RIGHT
29 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
30 #define TESTCODEC_EXITBUTTON BUTTON_RC_PLAY
31 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
32 #define TESTCODEC_EXITBUTTON BUTTON_PLAY
33 #elif CONFIG_KEYPAD == COWON_D2_PAD || CONFIG_KEYPAD == ONDAVX747_PAD
34 #define TESTCODEC_EXITBUTTON BUTTON_POWER
35 #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
36 #define TESTCODEC_EXITBUTTON BUTTON_REC
37 #elif CONFIG_KEYPAD == MPIO_HD200_PAD
38 #define TESTCODEC_EXITBUTTON (BUTTON_REC | BUTTON_PLAY)
39 #elif CONFIG_KEYPAD == MPIO_HD300_PAD
40 #define TESTCODEC_EXITBUTTON (BUTTON_REC | BUTTON_REPEAT)
41 #elif defined(HAVE_TOUCHSCREEN)
42 #define TESTCODEC_EXITBUTTON BUTTON_TOPLEFT
43 #else
44 #define TESTCODEC_EXITBUTTON BUTTON_SELECT
45 #endif
47 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
48 static unsigned int boost =1;
50 static const struct opt_items boost_settings[2] = {
51 { "No", -1 },
52 { "Yes", -1 },
55 #endif
57 /* Log functions copied from test_disk.c */
58 static int line = 0;
59 static int max_line = 0;
60 static int log_fd = -1;
62 static void log_close(void)
64 if (log_fd >= 0)
65 rb->close(log_fd);
68 static bool log_init(bool use_logfile)
70 int h;
71 char logfilename[MAX_PATH];
73 rb->lcd_getstringsize("A", NULL, &h);
74 max_line = LCD_HEIGHT / h;
75 line = 0;
76 rb->lcd_clear_display();
77 rb->lcd_update();
79 if (use_logfile) {
80 log_close();
81 rb->create_numbered_filename(logfilename, "/", "test_codec_log_", ".txt",
82 2 IF_CNFN_NUM_(, NULL));
83 log_fd = rb->open(logfilename, O_RDWR|O_CREAT|O_TRUNC, 0666);
84 return log_fd >= 0;
87 return true;
90 static void log_text(char *text, bool advance)
92 rb->lcd_puts(0, line, text);
93 rb->lcd_update();
94 if (advance)
96 if (++line >= max_line)
97 line = 0;
98 if (log_fd >= 0)
99 rb->fdprintf(log_fd, "%s\n", text);
103 struct wavinfo_t
105 int fd;
106 int samplerate;
107 int channels;
108 int sampledepth;
109 int stereomode;
110 int totalsamples;
113 static void* audiobuf;
114 static void* codec_mallocbuf;
115 static size_t audiosize;
116 static size_t audiobufsize;
117 static int offset;
118 static int fd;
120 /* Our local implementation of the codec API */
121 static struct codec_api ci;
123 struct test_track_info {
124 struct mp3entry id3; /* TAG metadata */
125 size_t filesize; /* File total length */
128 static struct test_track_info track;
129 static bool taginfo_ready = true;
131 static bool use_dsp;
133 static bool checksum;
134 static uint32_t crc32;
136 static volatile unsigned int elapsed;
137 static volatile bool codec_playing;
138 static volatile long endtick;
139 static volatile long rebuffertick;
140 struct wavinfo_t wavinfo;
142 static unsigned char wav_header[44] =
144 'R','I','F','F', // 0 - ChunkID
145 0,0,0,0, // 4 - ChunkSize (filesize-8)
146 'W','A','V','E', // 8 - Format
147 'f','m','t',' ', // 12 - SubChunkID
148 16,0,0,0, // 16 - SubChunk1ID // 16 for PCM
149 1,0, // 20 - AudioFormat (1=16-bit)
150 0,0, // 22 - NumChannels
151 0,0,0,0, // 24 - SampleRate in Hz
152 0,0,0,0, // 28 - Byte Rate (SampleRate*NumChannels*(BitsPerSample/8)
153 0,0, // 32 - BlockAlign (== NumChannels * BitsPerSample/8)
154 16,0, // 34 - BitsPerSample
155 'd','a','t','a', // 36 - Subchunk2ID
156 0,0,0,0 // 40 - Subchunk2Size
159 static inline void int2le32(unsigned char* buf, int32_t x)
161 buf[0] = (x & 0xff);
162 buf[1] = (x & 0xff00) >> 8;
163 buf[2] = (x & 0xff0000) >> 16;
164 buf[3] = (x & 0xff000000) >>24;
167 static inline void int2le24(unsigned char* buf, int32_t x)
169 buf[0] = (x & 0xff);
170 buf[1] = (x & 0xff00) >> 8;
171 buf[2] = (x & 0xff0000) >> 16;
174 static inline void int2le16(unsigned char* buf, int16_t x)
176 buf[0] = (x & 0xff);
177 buf[1] = (x & 0xff00) >> 8;
180 static unsigned char *wavbuffer;
181 static unsigned char *dspbuffer;
183 void init_wav(char* filename)
185 wavinfo.totalsamples = 0;
187 wavinfo.fd = rb->creat(filename, 0666);
189 if (wavinfo.fd >= 0)
191 /* Write WAV header - we go back and fill in the details at the end */
192 rb->write(wavinfo.fd, wav_header, sizeof(wav_header));
197 void close_wav(void)
199 int filesize = rb->filesize(wavinfo.fd);
200 int channels = (wavinfo.stereomode == STEREO_MONO) ? 1 : 2;
201 int bps = 16; /* TODO */
203 /* We assume 16-bit, Stereo */
205 rb->lseek(wavinfo.fd,0,SEEK_SET);
207 int2le32(wav_header+4, filesize-8); /* ChunkSize */
209 int2le16(wav_header+22, channels);
211 int2le32(wav_header+24, wavinfo.samplerate);
213 int2le32(wav_header+28, wavinfo.samplerate * channels * (bps / 8)); /* ByteRate */
215 int2le16(wav_header+32, channels * (bps / 8));
217 int2le32(wav_header+40, filesize - 44); /* Subchunk2Size */
219 rb->write(wavinfo.fd, wav_header, sizeof(wav_header));
221 rb->close(wavinfo.fd);
224 /* Returns buffer to malloc array. Only codeclib should need this. */
225 static void* codec_get_buffer(size_t *size)
227 DEBUGF("codec_get_buffer(%"PRIuPTR")\n",(uintptr_t)size);
228 *size = CODEC_SIZE;
229 return codec_mallocbuf;
232 static int process_dsp(const void *ch1, const void *ch2, int count)
234 const char *src[2] = { ch1, ch2 };
235 int written_count = 0;
236 char *dest = dspbuffer;
238 while (count > 0)
240 int out_count = rb->dsp_output_count(ci.dsp, count);
242 int inp_count = rb->dsp_input_count(ci.dsp, out_count);
244 if (inp_count <= 0)
245 break;
247 if (inp_count > count)
248 inp_count = count;
250 out_count = rb->dsp_process(ci.dsp, dest, src, inp_count);
252 if (out_count <= 0)
253 break;
255 written_count += out_count;
256 dest += out_count * 4;
258 count -= inp_count;
261 return written_count;
264 static inline int32_t clip_sample(int32_t sample)
266 if ((int16_t)sample != sample)
267 sample = 0x7fff ^ (sample >> 31);
269 return sample;
272 /* Null output */
273 static void pcmbuf_insert_null(const void *ch1, const void *ch2, int count)
275 if (use_dsp)
276 process_dsp(ch1, ch2, count);
278 /* Prevent idle poweroff */
279 rb->reset_poweroff_timer();
283 * Helper function used when the file is larger then the available memory.
284 * Rebuffers the file by setting the start of the audio buffer to be
285 * new_offset and filling from there.
287 static int fill_buffer(int new_offset){
288 size_t n, bytestoread;
289 long temp = *rb->current_tick;
290 rb->lseek(fd,new_offset,SEEK_SET);
292 if(new_offset + audiobufsize <= track.filesize)
293 bytestoread = audiobufsize;
294 else
295 bytestoread = track.filesize-new_offset;
297 n = rb->read(fd, audiobuf,bytestoread);
299 if (n != bytestoread)
301 log_text("Read failed.",true);
302 DEBUGF("read fail: got %d bytes, expected %d\n", (int)n, (int)audiobufsize);
303 rb->backlight_on();
305 if (fd >= 0)
307 rb->close(fd);
310 return -1;
312 offset = new_offset;
314 /*keep track of how much time we spent buffering*/
315 rebuffertick += *rb->current_tick-temp;
317 return 0;
320 /* WAV output or calculate crc32 of output*/
321 static void pcmbuf_insert_wav_checksum(const void *ch1, const void *ch2, int count)
323 const int16_t* data1_16;
324 const int16_t* data2_16;
325 const int32_t* data1_32;
326 const int32_t* data2_32;
327 unsigned char* p = wavbuffer;
328 const int scale = wavinfo.sampledepth - 15;
329 const int dc_bias = 1 << (scale - 1);
330 int channels = (wavinfo.stereomode == STEREO_MONO) ? 1 : 2;
332 /* Prevent idle poweroff */
333 rb->reset_poweroff_timer();
335 if (use_dsp) {
336 count = process_dsp(ch1, ch2, count);
337 wavinfo.totalsamples += count;
338 if (channels == 1)
340 unsigned char *s = dspbuffer, *d = dspbuffer;
341 int c = count;
342 while (c-- > 0)
344 *d++ = *s++;
345 *d++ = *s++;
346 s++;
347 s++;
350 if (checksum)
351 crc32 = rb->crc_32(dspbuffer, count * 2 * channels, crc32);
352 else
353 rb->write(wavinfo.fd, dspbuffer, count * 2 * channels);
355 else
357 if (wavinfo.sampledepth <= 16) {
358 data1_16 = ch1;
359 data2_16 = ch2;
361 switch(wavinfo.stereomode)
363 case STEREO_INTERLEAVED:
364 while (count--) {
365 int2le16(p,*data1_16++);
366 p += 2;
367 int2le16(p,*data1_16++);
368 p += 2;
370 break;
372 case STEREO_NONINTERLEAVED:
373 while (count--) {
374 int2le16(p,*data1_16++);
375 p += 2;
376 int2le16(p,*data2_16++);
377 p += 2;
380 break;
382 case STEREO_MONO:
383 while (count--) {
384 int2le16(p,*data1_16++);
385 p += 2;
387 break;
389 } else {
390 data1_32 = ch1;
391 data2_32 = ch2;
393 switch(wavinfo.stereomode)
395 case STEREO_INTERLEAVED:
396 while (count--) {
397 int2le16(p, clip_sample((*data1_32++ + dc_bias) >> scale));
398 p += 2;
399 int2le16(p, clip_sample((*data1_32++ + dc_bias) >> scale));
400 p += 2;
402 break;
404 case STEREO_NONINTERLEAVED:
405 while (count--) {
406 int2le16(p, clip_sample((*data1_32++ + dc_bias) >> scale));
407 p += 2;
408 int2le16(p, clip_sample((*data2_32++ + dc_bias) >> scale));
409 p += 2;
412 break;
414 case STEREO_MONO:
415 while (count--) {
416 int2le16(p, clip_sample((*data1_32++ + dc_bias) >> scale));
417 p += 2;
419 break;
423 wavinfo.totalsamples += count;
424 if (checksum)
425 crc32 = rb->crc_32(wavbuffer, p - wavbuffer, crc32);
426 else
427 rb->write(wavinfo.fd, wavbuffer, p - wavbuffer);
428 } /* else */
431 /* Set song position in WPS (value in ms). */
432 static void set_elapsed(unsigned long value)
434 elapsed = value;
438 /* Read next <size> amount bytes from file buffer to <ptr>.
439 Will return number of bytes read or 0 if end of file. */
440 static size_t read_filebuf(void *ptr, size_t size)
442 if (ci.curpos > (off_t)track.filesize)
444 return 0;
445 } else {
446 size_t realsize = MIN(track.filesize-ci.curpos,size);
448 /* check if we have enough bytes ready*/
449 if(realsize >(audiobufsize - (ci.curpos-offset)))
451 /*rebuffer so that we start at ci.curpos*/
452 fill_buffer(ci.curpos);
455 rb->memcpy(ptr, audiobuf + (ci.curpos-offset), realsize);
456 ci.curpos += realsize;
457 return realsize;
462 /* Request pointer to file buffer which can be used to read
463 <realsize> amount of data. <reqsize> tells the buffer system
464 how much data it should try to allocate. If <realsize> is 0,
465 end of file is reached. */
466 static void* request_buffer(size_t *realsize, size_t reqsize)
468 *realsize = MIN(track.filesize-ci.curpos,reqsize);
470 /*check if we have enough bytes ready - requested > bufsize-currentbufpos*/
471 if(*realsize>(audiobufsize - (ci.curpos-offset)))
473 /*rebuffer so that we start at ci.curpos*/
474 fill_buffer(ci.curpos);
477 return (audiobuf + (ci.curpos-offset));
480 /* Advance file buffer position by <amount> amount of bytes. */
481 static void advance_buffer(size_t amount)
483 ci.curpos += amount;
487 /* Advance file buffer to a pointer location inside file buffer. */
488 static void advance_buffer_loc(void *ptr)
490 ci.curpos = ptr - (audiobuf - offset);
494 /* Seek file buffer to position <newpos> beginning of file. */
495 static bool seek_buffer(size_t newpos)
497 ci.curpos = newpos;
498 return true;
502 /* Codec should call this function when it has done the seeking. */
503 static void seek_complete(void)
505 /* Do nothing */
508 /* Request file change from file buffer. Returns true is next
509 track is available and changed. If return value is false,
510 codec should exit immediately with PLUGIN_OK status. */
511 static bool request_next_track(void)
513 /* We are only decoding a single track */
514 return false;
518 /* Free the buffer area of the current codec after its loaded */
519 static void discard_codec(void)
521 /* ??? */
525 static void set_offset(size_t value)
527 /* ??? */
528 (void)value;
532 /* Configure different codec buffer parameters. */
533 static void configure(int setting, intptr_t value)
535 if (use_dsp)
536 rb->dsp_configure(ci.dsp, setting, value);
537 switch(setting)
539 case DSP_SWITCH_FREQUENCY:
540 case DSP_SET_FREQUENCY:
541 DEBUGF("samplerate=%d\n",(int)value);
542 wavinfo.samplerate = (int)value;
543 break;
545 case DSP_SET_SAMPLE_DEPTH:
546 DEBUGF("sampledepth = %d\n",(int)value);
547 wavinfo.sampledepth=(int)value;
548 break;
550 case DSP_SET_STEREO_MODE:
551 DEBUGF("Stereo mode = %d\n",(int)value);
552 wavinfo.stereomode=(int)value;
553 break;
558 static void init_ci(void)
560 /* --- Our "fake" implementations of the codec API functions. --- */
562 ci.codec_get_buffer = codec_get_buffer;
564 if (wavinfo.fd >= 0 || checksum) {
565 ci.pcmbuf_insert = pcmbuf_insert_wav_checksum;
566 } else {
567 ci.pcmbuf_insert = pcmbuf_insert_null;
570 ci.set_elapsed = set_elapsed;
571 ci.read_filebuf = read_filebuf;
572 ci.request_buffer = request_buffer;
573 ci.advance_buffer = advance_buffer;
574 ci.advance_buffer_loc = advance_buffer_loc;
575 ci.seek_buffer = seek_buffer;
576 ci.seek_complete = seek_complete;
577 ci.request_next_track = request_next_track;
578 ci.discard_codec = discard_codec;
579 ci.set_offset = set_offset;
580 ci.configure = configure;
581 ci.dsp = (struct dsp_config *)rb->dsp_configure(NULL, DSP_MYDSP,
582 CODEC_IDX_AUDIO);
584 /* --- "Core" functions --- */
586 /* kernel/ system */
587 ci.sleep = rb->sleep;
588 ci.yield = rb->yield;
590 /* strings and memory */
591 ci.strcpy = rb->strcpy;
592 ci.strlen = rb->strlen;
593 ci.strcmp = rb->strcmp;
594 ci.strcat = rb->strcat;
595 ci.memset = rb->memset;
596 ci.memcpy = rb->memcpy;
597 ci.memmove = rb->memmove;
598 ci.memcmp = rb->memcmp;
599 ci.memchr = rb->memchr;
600 ci.strcasestr = rb->strcasestr;
601 #if defined(DEBUG) || defined(SIMULATOR)
602 ci.debugf = rb->debugf;
603 #endif
604 #ifdef ROCKBOX_HAS_LOGF
605 ci.logf = rb->logf;
606 #endif
608 ci.qsort = rb->qsort;
609 ci.global_settings = rb->global_settings;
611 #ifdef RB_PROFILE
612 ci.profile_thread = rb->profile_thread;
613 ci.profstop = rb->profstop;
614 ci.profile_func_enter = rb->profile_func_enter;
615 ci.profile_func_exit = rb->profile_func_exit;
616 #endif
618 ci.cpucache_invalidate = rb->cpucache_invalidate;
619 ci.cpucache_flush = rb->cpucache_flush;
621 #if NUM_CORES > 1
622 ci.create_thread = rb->create_thread;
623 ci.thread_thaw = rb->thread_thaw;
624 ci.thread_wait = rb->thread_wait;
625 ci.semaphore_init = rb->semaphore_init;
626 ci.semaphore_wait = rb->semaphore_wait;
627 ci.semaphore_release = rb->semaphore_release;
628 #endif
630 #if defined(CPU_ARM) && (CONFIG_PLATFORM & PLATFORM_NATIVE)
631 ci.__div0 = rb->__div0;
632 #endif
635 static void codec_thread(void)
637 const char* codecname;
638 int res;
640 codecname = rb->get_codec_filename(track.id3.codectype);
642 /* Load the codec and start decoding. */
643 res = rb->codec_load_file(codecname,&ci);
645 /* Signal to the main thread that we are done */
646 endtick = *rb->current_tick - rebuffertick;
647 codec_playing = false;
650 static enum plugin_status test_track(const char* filename)
652 size_t n;
653 enum plugin_status res = PLUGIN_ERROR;
654 long starttick;
655 long ticks;
656 unsigned long speed;
657 unsigned long duration;
658 const char* ch;
659 char str[MAX_PATH];
660 offset=0;
662 /* Display filename (excluding any path)*/
663 ch = rb->strrchr(filename, '/');
664 if (ch==NULL)
665 ch = filename;
666 else
667 ch++;
669 rb->snprintf(str,sizeof(str),"%s",ch);
670 log_text(str,true);
672 log_text("Loading...",false);
674 fd = rb->open(filename,O_RDONLY);
675 if (fd < 0)
677 log_text("Cannot open file",true);
678 goto exit;
681 track.filesize = rb->filesize(fd);
683 /* Clear the id3 struct */
684 rb->memset(&track.id3, 0, sizeof(struct mp3entry));
686 if (!rb->get_metadata(&(track.id3), fd, filename))
688 log_text("Cannot read metadata",true);
689 goto exit;
692 if (track.filesize > audiosize)
694 audiobufsize=audiosize;
696 } else
698 audiobufsize=track.filesize;
701 n = rb->read(fd, audiobuf, audiobufsize);
703 if (n != audiobufsize)
705 log_text("Read failed.",true);
706 goto exit;
710 /* Initialise the function pointers in the codec API */
711 init_ci();
713 /* Prepare the codec struct for playing the whole file */
714 ci.filesize = track.filesize;
715 ci.id3 = &track.id3;
716 ci.taginfo_ready = &taginfo_ready;
717 ci.curpos = 0;
718 ci.stop_codec = false;
719 ci.new_track = 0;
720 ci.seek_time = 0;
722 if (use_dsp)
723 rb->dsp_configure(ci.dsp, DSP_RESET, 0);
725 if (checksum)
726 crc32 = 0xffffffff;
728 rebuffertick=0;
729 starttick = *rb->current_tick;
731 codec_playing = true;
733 rb->codec_thread_do_callback(codec_thread, NULL);
735 /* Wait for codec thread to die */
736 while (codec_playing)
738 rb->sleep(HZ);
739 rb->snprintf(str,sizeof(str),"%d of %d",elapsed,(int)track.id3.length);
740 log_text(str,false);
742 ticks = endtick - starttick;
744 /* Be sure it is done */
745 rb->codec_thread_do_callback(NULL, NULL);
746 rb->backlight_on();
747 log_text(str,true);
749 if (checksum)
751 rb->snprintf(str, sizeof(str), "CRC32 - %08x", (unsigned)crc32);
752 log_text(str,true);
754 else if (wavinfo.fd < 0)
756 /* Display benchmark information */
757 rb->snprintf(str,sizeof(str),"Decode time - %d.%02ds",(int)ticks/100,(int)ticks%100);
758 log_text(str,true);
760 duration = track.id3.length / 10;
761 rb->snprintf(str,sizeof(str),"File duration - %d.%02ds",(int)duration/100,(int)duration%100);
762 log_text(str,true);
764 if (ticks > 0)
765 speed = duration * 10000 / ticks;
766 else
767 speed = 0;
769 rb->snprintf(str,sizeof(str),"%d.%02d%% realtime",(int)speed/100,(int)speed%100);
770 log_text(str,true);
772 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
773 /* show effective clockrate in MHz needed for realtime decoding */
774 if (speed > 0)
776 int freq = CPUFREQ_MAX;
778 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
779 if(!boost)
780 freq = CPUFREQ_NORMAL;
781 #endif
783 speed = freq / speed;
784 rb->snprintf(str,sizeof(str),"%d.%02dMHz needed for realtime",
785 (int)speed/100,(int)speed%100);
786 log_text(str,true);
788 #endif
791 res = PLUGIN_OK;
793 exit:
794 rb->backlight_on();
796 if (fd >= 0)
798 rb->close(fd);
801 return res;
804 /* plugin entry point */
805 enum plugin_status plugin_start(const void* parameter)
807 int result, selection = 0;
808 enum plugin_status res = PLUGIN_OK;
809 int scandir;
810 struct dirent *entry;
811 DIR* dir;
812 char* ch;
813 char dirpath[MAX_PATH];
814 char filename[MAX_PATH];
815 size_t buffer_size;
817 if (parameter == NULL)
819 rb->splash(HZ*2, "No File");
820 return PLUGIN_ERROR;
823 wavbuffer = rb->plugin_get_buffer(&buffer_size);
824 dspbuffer = wavbuffer + buffer_size / 2;
826 codec_mallocbuf = rb->plugin_get_audio_buffer(&audiosize);
827 /* Align codec_mallocbuf to pointer size, tlsf wants that */
828 codec_mallocbuf = (void*)(((intptr_t)codec_mallocbuf +
829 sizeof(intptr_t)-1) & ~(sizeof(intptr_t)-1));
830 audiobuf = SKIPBYTES(codec_mallocbuf, CODEC_SIZE);
831 audiosize -= CODEC_SIZE;
833 rb->lcd_clear_display();
834 rb->lcd_update();
836 enum
838 SPEED_TEST = 0,
839 SPEED_TEST_DIR,
840 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
841 BOOST,
842 #endif
843 WRITE_WAV,
844 SPEED_TEST_WITH_DSP,
845 SPEED_TEST_DIR_WITH_DSP,
846 WRITE_WAV_WITH_DSP,
847 CHECKSUM,
848 CHECKSUM_DIR,
849 QUIT,
852 MENUITEM_STRINGLIST(
853 menu, "test_codec", NULL,
854 "Speed test",
855 "Speed test folder",
856 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
857 "Boosting",
858 #endif
859 "Write WAV",
860 "Speed test with DSP",
861 "Speed test folder with DSP",
862 "Write WAV with DSP",
863 "Checksum",
864 "Checksum folder",
865 "Quit",
869 show_menu:
870 rb->lcd_clear_display();
872 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
873 menu:
874 #endif
876 result = rb->do_menu(&menu, &selection, NULL, false);
877 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
879 if (result == BOOST)
881 rb->set_option("Boosting", &boost, INT,
882 boost_settings, 2, NULL);
883 goto menu;
885 if(boost)
886 rb->cpu_boost(true);
887 #endif
889 if (result == QUIT)
891 res = PLUGIN_OK;
892 goto exit;
895 scandir = 0;
897 if ((checksum = (result == CHECKSUM || result == CHECKSUM_DIR)))
898 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
899 result -= 7;
900 #else
901 result -= 6;
902 #endif
904 if ((use_dsp = ((result >= SPEED_TEST_WITH_DSP)
905 && (result <= WRITE_WAV_WITH_DSP)))) {
906 result -= 3;
908 if (result == SPEED_TEST) {
909 wavinfo.fd = -1;
910 log_init(false);
911 } else if (result == SPEED_TEST_DIR) {
912 wavinfo.fd = -1;
913 scandir = 1;
915 /* Only create a log file when we are testing a folder */
916 if (!log_init(true)) {
917 rb->splash(HZ*2, "Cannot create logfile");
918 res = PLUGIN_ERROR;
919 goto exit;
921 } else if (result == WRITE_WAV) {
922 log_init(false);
923 init_wav("/test.wav");
924 if (wavinfo.fd < 0) {
925 rb->splash(HZ*2, "Cannot create /test.wav");
926 res = PLUGIN_ERROR;
927 goto exit;
929 } else if (result == MENU_ATTACHED_USB) {
930 res = PLUGIN_USB_CONNECTED;
931 goto exit;
932 } else if (result < 0) {
933 res = PLUGIN_OK;
934 goto exit;
937 if (scandir) {
938 /* Test all files in the same directory as the file selected by the
939 user */
941 rb->strlcpy(dirpath,parameter,sizeof(dirpath));
942 ch = rb->strrchr(dirpath,'/');
943 ch[1]=0;
945 DEBUGF("Scanning directory \"%s\"\n",dirpath);
946 dir = rb->opendir(dirpath);
947 if (dir) {
948 entry = rb->readdir(dir);
949 while (entry) {
950 struct dirinfo info = rb->dir_get_info(dir, entry);
951 if (!(info.attribute & ATTR_DIRECTORY)) {
952 rb->snprintf(filename,sizeof(filename),"%s%s",dirpath,entry->d_name);
953 test_track(filename);
954 log_text("", true);
957 /* Read next entry */
958 entry = rb->readdir(dir);
961 rb->closedir(dir);
963 } else {
964 /* Just test the file */
965 res = test_track(parameter);
967 /* Close WAV file (if there was one) */
968 if (wavinfo.fd >= 0) {
969 close_wav();
970 log_text("Wrote /test.wav",true);
972 while (rb->button_get(true) != TESTCODEC_EXITBUTTON);
975 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
976 if(boost)
977 rb->cpu_boost(false);
978 #endif
980 rb->button_clear_queue();
981 goto show_menu;
983 exit:
984 log_close();
986 return res;