Undo unwanted commit r29310.
[kugel-rb.git] / apps / plugins / test_codec.c
blob9b00fdbb95bf319802bd7676e7f8be9a859e0ba6
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 || CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
35 #define TESTCODEC_EXITBUTTON BUTTON_POWER
36 #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
37 #define TESTCODEC_EXITBUTTON BUTTON_REC
38 #elif CONFIG_KEYPAD == MPIO_HD200_PAD
39 #define TESTCODEC_EXITBUTTON (BUTTON_REC | BUTTON_PLAY)
40 #elif CONFIG_KEYPAD == MPIO_HD300_PAD
41 #define TESTCODEC_EXITBUTTON (BUTTON_REC | BUTTON_REPEAT)
42 #elif defined(HAVE_TOUCHSCREEN)
43 #define TESTCODEC_EXITBUTTON BUTTON_TOPLEFT
44 #else
45 #define TESTCODEC_EXITBUTTON BUTTON_SELECT
46 #endif
48 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
49 static unsigned int boost =1;
51 static const struct opt_items boost_settings[2] = {
52 { "No", -1 },
53 { "Yes", -1 },
56 #endif
58 /* Log functions copied from test_disk.c */
59 static int line = 0;
60 static int max_line = 0;
61 static int log_fd = -1;
63 static void log_close(void)
65 if (log_fd >= 0)
66 rb->close(log_fd);
69 static bool log_init(bool use_logfile)
71 int h;
72 char logfilename[MAX_PATH];
74 rb->lcd_getstringsize("A", NULL, &h);
75 max_line = LCD_HEIGHT / h;
76 line = 0;
77 rb->lcd_clear_display();
78 rb->lcd_update();
80 if (use_logfile) {
81 log_close();
82 rb->create_numbered_filename(logfilename, "/", "test_codec_log_", ".txt",
83 2 IF_CNFN_NUM_(, NULL));
84 log_fd = rb->open(logfilename, O_RDWR|O_CREAT|O_TRUNC, 0666);
85 return log_fd >= 0;
88 return true;
91 static void log_text(char *text, bool advance)
93 rb->lcd_puts(0, line, text);
94 rb->lcd_update();
95 if (advance)
97 if (++line >= max_line)
98 line = 0;
99 if (log_fd >= 0)
100 rb->fdprintf(log_fd, "%s\n", text);
104 struct wavinfo_t
106 int fd;
107 int samplerate;
108 int channels;
109 int sampledepth;
110 int stereomode;
111 int totalsamples;
114 static void* audiobuf;
115 static void* codec_mallocbuf;
116 static size_t audiosize;
117 static size_t audiobufsize;
118 static int offset;
119 static int fd;
121 /* Our local implementation of the codec API */
122 static struct codec_api ci;
124 struct test_track_info {
125 struct mp3entry id3; /* TAG metadata */
126 size_t filesize; /* File total length */
129 static struct test_track_info track;
130 static bool taginfo_ready = true;
132 static bool use_dsp;
134 static bool checksum;
135 static uint32_t crc32;
137 static volatile unsigned int elapsed;
138 static volatile bool codec_playing;
139 static volatile long endtick;
140 static volatile long rebuffertick;
141 struct wavinfo_t wavinfo;
143 static unsigned char wav_header[44] =
145 'R','I','F','F', // 0 - ChunkID
146 0,0,0,0, // 4 - ChunkSize (filesize-8)
147 'W','A','V','E', // 8 - Format
148 'f','m','t',' ', // 12 - SubChunkID
149 16,0,0,0, // 16 - SubChunk1ID // 16 for PCM
150 1,0, // 20 - AudioFormat (1=16-bit)
151 0,0, // 22 - NumChannels
152 0,0,0,0, // 24 - SampleRate in Hz
153 0,0,0,0, // 28 - Byte Rate (SampleRate*NumChannels*(BitsPerSample/8)
154 0,0, // 32 - BlockAlign (== NumChannels * BitsPerSample/8)
155 16,0, // 34 - BitsPerSample
156 'd','a','t','a', // 36 - Subchunk2ID
157 0,0,0,0 // 40 - Subchunk2Size
160 static inline void int2le32(unsigned char* buf, int32_t x)
162 buf[0] = (x & 0xff);
163 buf[1] = (x & 0xff00) >> 8;
164 buf[2] = (x & 0xff0000) >> 16;
165 buf[3] = (x & 0xff000000) >>24;
168 static inline void int2le24(unsigned char* buf, int32_t x)
170 buf[0] = (x & 0xff);
171 buf[1] = (x & 0xff00) >> 8;
172 buf[2] = (x & 0xff0000) >> 16;
175 static inline void int2le16(unsigned char* buf, int16_t x)
177 buf[0] = (x & 0xff);
178 buf[1] = (x & 0xff00) >> 8;
181 static unsigned char *wavbuffer;
182 static unsigned char *dspbuffer;
184 void init_wav(char* filename)
186 wavinfo.totalsamples = 0;
188 wavinfo.fd = rb->creat(filename, 0666);
190 if (wavinfo.fd >= 0)
192 /* Write WAV header - we go back and fill in the details at the end */
193 rb->write(wavinfo.fd, wav_header, sizeof(wav_header));
198 void close_wav(void)
200 int filesize = rb->filesize(wavinfo.fd);
201 int channels = (wavinfo.stereomode == STEREO_MONO) ? 1 : 2;
202 int bps = 16; /* TODO */
204 /* We assume 16-bit, Stereo */
206 rb->lseek(wavinfo.fd,0,SEEK_SET);
208 int2le32(wav_header+4, filesize-8); /* ChunkSize */
210 int2le16(wav_header+22, channels);
212 int2le32(wav_header+24, wavinfo.samplerate);
214 int2le32(wav_header+28, wavinfo.samplerate * channels * (bps / 8)); /* ByteRate */
216 int2le16(wav_header+32, channels * (bps / 8));
218 int2le32(wav_header+40, filesize - 44); /* Subchunk2Size */
220 rb->write(wavinfo.fd, wav_header, sizeof(wav_header));
222 rb->close(wavinfo.fd);
225 /* Returns buffer to malloc array. Only codeclib should need this. */
226 static void* codec_get_buffer(size_t *size)
228 DEBUGF("codec_get_buffer(%"PRIuPTR")\n",(uintptr_t)size);
229 *size = CODEC_SIZE;
230 return codec_mallocbuf;
233 static int process_dsp(const void *ch1, const void *ch2, int count)
235 const char *src[2] = { ch1, ch2 };
236 int written_count = 0;
237 char *dest = dspbuffer;
239 while (count > 0)
241 int out_count = rb->dsp_output_count(ci.dsp, count);
243 int inp_count = rb->dsp_input_count(ci.dsp, out_count);
245 if (inp_count <= 0)
246 break;
248 if (inp_count > count)
249 inp_count = count;
251 out_count = rb->dsp_process(ci.dsp, dest, src, inp_count);
253 if (out_count <= 0)
254 break;
256 written_count += out_count;
257 dest += out_count * 4;
259 count -= inp_count;
262 return written_count;
265 static inline int32_t clip_sample(int32_t sample)
267 if ((int16_t)sample != sample)
268 sample = 0x7fff ^ (sample >> 31);
270 return sample;
273 /* Null output */
274 static void pcmbuf_insert_null(const void *ch1, const void *ch2, int count)
276 if (use_dsp)
277 process_dsp(ch1, ch2, count);
279 /* Prevent idle poweroff */
280 rb->reset_poweroff_timer();
284 * Helper function used when the file is larger then the available memory.
285 * Rebuffers the file by setting the start of the audio buffer to be
286 * new_offset and filling from there.
288 static int fill_buffer(int new_offset){
289 size_t n, bytestoread;
290 long temp = *rb->current_tick;
291 rb->lseek(fd,new_offset,SEEK_SET);
293 if(new_offset + audiobufsize <= track.filesize)
294 bytestoread = audiobufsize;
295 else
296 bytestoread = track.filesize-new_offset;
298 n = rb->read(fd, audiobuf,bytestoread);
300 if (n != bytestoread)
302 log_text("Read failed.",true);
303 DEBUGF("read fail: got %d bytes, expected %d\n", (int)n, (int)audiobufsize);
304 rb->backlight_on();
306 if (fd >= 0)
308 rb->close(fd);
311 return -1;
313 offset = new_offset;
315 /*keep track of how much time we spent buffering*/
316 rebuffertick += *rb->current_tick-temp;
318 return 0;
321 /* WAV output or calculate crc32 of output*/
322 static void pcmbuf_insert_wav_checksum(const void *ch1, const void *ch2, int count)
324 const int16_t* data1_16;
325 const int16_t* data2_16;
326 const int32_t* data1_32;
327 const int32_t* data2_32;
328 unsigned char* p = wavbuffer;
329 const int scale = wavinfo.sampledepth - 15;
330 const int dc_bias = 1 << (scale - 1);
331 int channels = (wavinfo.stereomode == STEREO_MONO) ? 1 : 2;
333 /* Prevent idle poweroff */
334 rb->reset_poweroff_timer();
336 if (use_dsp) {
337 count = process_dsp(ch1, ch2, count);
338 wavinfo.totalsamples += count;
339 if (channels == 1)
341 unsigned char *s = dspbuffer, *d = dspbuffer;
342 int c = count;
343 while (c-- > 0)
345 *d++ = *s++;
346 *d++ = *s++;
347 s++;
348 s++;
351 if (checksum)
352 crc32 = rb->crc_32(dspbuffer, count * 2 * channels, crc32);
353 else
354 rb->write(wavinfo.fd, dspbuffer, count * 2 * channels);
356 else
358 if (wavinfo.sampledepth <= 16) {
359 data1_16 = ch1;
360 data2_16 = ch2;
362 switch(wavinfo.stereomode)
364 case STEREO_INTERLEAVED:
365 while (count--) {
366 int2le16(p,*data1_16++);
367 p += 2;
368 int2le16(p,*data1_16++);
369 p += 2;
371 break;
373 case STEREO_NONINTERLEAVED:
374 while (count--) {
375 int2le16(p,*data1_16++);
376 p += 2;
377 int2le16(p,*data2_16++);
378 p += 2;
381 break;
383 case STEREO_MONO:
384 while (count--) {
385 int2le16(p,*data1_16++);
386 p += 2;
388 break;
390 } else {
391 data1_32 = ch1;
392 data2_32 = ch2;
394 switch(wavinfo.stereomode)
396 case STEREO_INTERLEAVED:
397 while (count--) {
398 int2le16(p, clip_sample((*data1_32++ + dc_bias) >> scale));
399 p += 2;
400 int2le16(p, clip_sample((*data1_32++ + dc_bias) >> scale));
401 p += 2;
403 break;
405 case STEREO_NONINTERLEAVED:
406 while (count--) {
407 int2le16(p, clip_sample((*data1_32++ + dc_bias) >> scale));
408 p += 2;
409 int2le16(p, clip_sample((*data2_32++ + dc_bias) >> scale));
410 p += 2;
413 break;
415 case STEREO_MONO:
416 while (count--) {
417 int2le16(p, clip_sample((*data1_32++ + dc_bias) >> scale));
418 p += 2;
420 break;
424 wavinfo.totalsamples += count;
425 if (checksum)
426 crc32 = rb->crc_32(wavbuffer, p - wavbuffer, crc32);
427 else
428 rb->write(wavinfo.fd, wavbuffer, p - wavbuffer);
429 } /* else */
432 /* Set song position in WPS (value in ms). */
433 static void set_elapsed(unsigned long value)
435 elapsed = value;
439 /* Read next <size> amount bytes from file buffer to <ptr>.
440 Will return number of bytes read or 0 if end of file. */
441 static size_t read_filebuf(void *ptr, size_t size)
443 if (ci.curpos > (off_t)track.filesize)
445 return 0;
446 } else {
447 size_t realsize = MIN(track.filesize-ci.curpos,size);
449 /* check if we have enough bytes ready*/
450 if(realsize >(audiobufsize - (ci.curpos-offset)))
452 /*rebuffer so that we start at ci.curpos*/
453 fill_buffer(ci.curpos);
456 rb->memcpy(ptr, audiobuf + (ci.curpos-offset), realsize);
457 ci.curpos += realsize;
458 return realsize;
463 /* Request pointer to file buffer which can be used to read
464 <realsize> amount of data. <reqsize> tells the buffer system
465 how much data it should try to allocate. If <realsize> is 0,
466 end of file is reached. */
467 static void* request_buffer(size_t *realsize, size_t reqsize)
469 *realsize = MIN(track.filesize-ci.curpos,reqsize);
471 /*check if we have enough bytes ready - requested > bufsize-currentbufpos*/
472 if(*realsize>(audiobufsize - (ci.curpos-offset)))
474 /*rebuffer so that we start at ci.curpos*/
475 fill_buffer(ci.curpos);
478 return (audiobuf + (ci.curpos-offset));
481 /* Advance file buffer position by <amount> amount of bytes. */
482 static void advance_buffer(size_t amount)
484 ci.curpos += amount;
488 /* Advance file buffer to a pointer location inside file buffer. */
489 static void advance_buffer_loc(void *ptr)
491 ci.curpos = ptr - (audiobuf - offset);
495 /* Seek file buffer to position <newpos> beginning of file. */
496 static bool seek_buffer(size_t newpos)
498 ci.curpos = newpos;
499 return true;
503 /* Codec should call this function when it has done the seeking. */
504 static void seek_complete(void)
506 /* Do nothing */
509 /* Request file change from file buffer. Returns true is next
510 track is available and changed. If return value is false,
511 codec should exit immediately with PLUGIN_OK status. */
512 static bool request_next_track(void)
514 /* We are only decoding a single track */
515 return false;
519 /* Free the buffer area of the current codec after its loaded */
520 static void discard_codec(void)
522 /* ??? */
526 static void set_offset(size_t value)
528 /* ??? */
529 (void)value;
533 /* Configure different codec buffer parameters. */
534 static void configure(int setting, intptr_t value)
536 if (use_dsp)
537 rb->dsp_configure(ci.dsp, setting, value);
538 switch(setting)
540 case DSP_SWITCH_FREQUENCY:
541 case DSP_SET_FREQUENCY:
542 DEBUGF("samplerate=%d\n",(int)value);
543 wavinfo.samplerate = (int)value;
544 break;
546 case DSP_SET_SAMPLE_DEPTH:
547 DEBUGF("sampledepth = %d\n",(int)value);
548 wavinfo.sampledepth=(int)value;
549 break;
551 case DSP_SET_STEREO_MODE:
552 DEBUGF("Stereo mode = %d\n",(int)value);
553 wavinfo.stereomode=(int)value;
554 break;
559 static void init_ci(void)
561 /* --- Our "fake" implementations of the codec API functions. --- */
563 ci.codec_get_buffer = codec_get_buffer;
565 if (wavinfo.fd >= 0 || checksum) {
566 ci.pcmbuf_insert = pcmbuf_insert_wav_checksum;
567 } else {
568 ci.pcmbuf_insert = pcmbuf_insert_null;
571 ci.set_elapsed = set_elapsed;
572 ci.read_filebuf = read_filebuf;
573 ci.request_buffer = request_buffer;
574 ci.advance_buffer = advance_buffer;
575 ci.advance_buffer_loc = advance_buffer_loc;
576 ci.seek_buffer = seek_buffer;
577 ci.seek_complete = seek_complete;
578 ci.request_next_track = request_next_track;
579 ci.discard_codec = discard_codec;
580 ci.set_offset = set_offset;
581 ci.configure = configure;
582 ci.dsp = (struct dsp_config *)rb->dsp_configure(NULL, DSP_MYDSP,
583 CODEC_IDX_AUDIO);
585 /* --- "Core" functions --- */
587 /* kernel/ system */
588 ci.sleep = rb->sleep;
589 ci.yield = rb->yield;
591 /* strings and memory */
592 ci.strcpy = rb->strcpy;
593 ci.strlen = rb->strlen;
594 ci.strcmp = rb->strcmp;
595 ci.strcat = rb->strcat;
596 ci.memset = rb->memset;
597 ci.memcpy = rb->memcpy;
598 ci.memmove = rb->memmove;
599 ci.memcmp = rb->memcmp;
600 ci.memchr = rb->memchr;
601 ci.strcasestr = rb->strcasestr;
602 #if defined(DEBUG) || defined(SIMULATOR)
603 ci.debugf = rb->debugf;
604 #endif
605 #ifdef ROCKBOX_HAS_LOGF
606 ci.logf = rb->logf;
607 #endif
609 ci.qsort = rb->qsort;
610 ci.global_settings = rb->global_settings;
612 #ifdef RB_PROFILE
613 ci.profile_thread = rb->profile_thread;
614 ci.profstop = rb->profstop;
615 ci.profile_func_enter = rb->profile_func_enter;
616 ci.profile_func_exit = rb->profile_func_exit;
617 #endif
619 ci.cpucache_invalidate = rb->cpucache_invalidate;
620 ci.cpucache_flush = rb->cpucache_flush;
622 #if NUM_CORES > 1
623 ci.create_thread = rb->create_thread;
624 ci.thread_thaw = rb->thread_thaw;
625 ci.thread_wait = rb->thread_wait;
626 ci.semaphore_init = rb->semaphore_init;
627 ci.semaphore_wait = rb->semaphore_wait;
628 ci.semaphore_release = rb->semaphore_release;
629 #endif
631 #if defined(CPU_ARM) && (CONFIG_PLATFORM & PLATFORM_NATIVE)
632 ci.__div0 = rb->__div0;
633 #endif
636 static void codec_thread(void)
638 const char* codecname;
639 int res;
641 codecname = rb->get_codec_filename(track.id3.codectype);
643 /* Load the codec and start decoding. */
644 res = rb->codec_load_file(codecname,&ci);
646 /* Signal to the main thread that we are done */
647 endtick = *rb->current_tick - rebuffertick;
648 codec_playing = false;
651 static enum plugin_status test_track(const char* filename)
653 size_t n;
654 enum plugin_status res = PLUGIN_ERROR;
655 long starttick;
656 long ticks;
657 unsigned long speed;
658 unsigned long duration;
659 const char* ch;
660 char str[MAX_PATH];
661 offset=0;
663 /* Display filename (excluding any path)*/
664 ch = rb->strrchr(filename, '/');
665 if (ch==NULL)
666 ch = filename;
667 else
668 ch++;
670 rb->snprintf(str,sizeof(str),"%s",ch);
671 log_text(str,true);
673 log_text("Loading...",false);
675 fd = rb->open(filename,O_RDONLY);
676 if (fd < 0)
678 log_text("Cannot open file",true);
679 goto exit;
682 track.filesize = rb->filesize(fd);
684 /* Clear the id3 struct */
685 rb->memset(&track.id3, 0, sizeof(struct mp3entry));
687 if (!rb->get_metadata(&(track.id3), fd, filename))
689 log_text("Cannot read metadata",true);
690 goto exit;
693 if (track.filesize > audiosize)
695 audiobufsize=audiosize;
697 } else
699 audiobufsize=track.filesize;
702 n = rb->read(fd, audiobuf, audiobufsize);
704 if (n != audiobufsize)
706 log_text("Read failed.",true);
707 goto exit;
711 /* Initialise the function pointers in the codec API */
712 init_ci();
714 /* Prepare the codec struct for playing the whole file */
715 ci.filesize = track.filesize;
716 ci.id3 = &track.id3;
717 ci.taginfo_ready = &taginfo_ready;
718 ci.curpos = 0;
719 ci.stop_codec = false;
720 ci.new_track = 0;
721 ci.seek_time = 0;
723 if (use_dsp)
724 rb->dsp_configure(ci.dsp, DSP_RESET, 0);
726 if (checksum)
727 crc32 = 0xffffffff;
729 rebuffertick=0;
730 starttick = *rb->current_tick;
732 codec_playing = true;
734 rb->codec_thread_do_callback(codec_thread, NULL);
736 /* Wait for codec thread to die */
737 while (codec_playing)
739 rb->sleep(HZ);
740 rb->snprintf(str,sizeof(str),"%d of %d",elapsed,(int)track.id3.length);
741 log_text(str,false);
743 ticks = endtick - starttick;
745 /* Be sure it is done */
746 rb->codec_thread_do_callback(NULL, NULL);
747 rb->backlight_on();
748 log_text(str,true);
750 if (checksum)
752 rb->snprintf(str, sizeof(str), "CRC32 - %08x", (unsigned)crc32);
753 log_text(str,true);
755 else if (wavinfo.fd < 0)
757 /* Display benchmark information */
758 rb->snprintf(str,sizeof(str),"Decode time - %d.%02ds",(int)ticks/100,(int)ticks%100);
759 log_text(str,true);
761 duration = track.id3.length / 10;
762 rb->snprintf(str,sizeof(str),"File duration - %d.%02ds",(int)duration/100,(int)duration%100);
763 log_text(str,true);
765 if (ticks > 0)
766 speed = duration * 10000 / ticks;
767 else
768 speed = 0;
770 rb->snprintf(str,sizeof(str),"%d.%02d%% realtime",(int)speed/100,(int)speed%100);
771 log_text(str,true);
773 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
774 /* show effective clockrate in MHz needed for realtime decoding */
775 if (speed > 0)
777 int freq = CPUFREQ_MAX;
779 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
780 if(!boost)
781 freq = CPUFREQ_NORMAL;
782 #endif
784 speed = freq / speed;
785 rb->snprintf(str,sizeof(str),"%d.%02dMHz needed for realtime",
786 (int)speed/100,(int)speed%100);
787 log_text(str,true);
789 #endif
792 res = PLUGIN_OK;
794 exit:
795 rb->backlight_on();
797 if (fd >= 0)
799 rb->close(fd);
802 return res;
805 /* plugin entry point */
806 enum plugin_status plugin_start(const void* parameter)
808 int result, selection = 0;
809 enum plugin_status res = PLUGIN_OK;
810 int scandir;
811 struct dirent *entry;
812 DIR* dir;
813 char* ch;
814 char dirpath[MAX_PATH];
815 char filename[MAX_PATH];
816 size_t buffer_size;
818 if (parameter == NULL)
820 rb->splash(HZ*2, "No File");
821 return PLUGIN_ERROR;
824 wavbuffer = rb->plugin_get_buffer(&buffer_size);
825 dspbuffer = wavbuffer + buffer_size / 2;
827 codec_mallocbuf = rb->plugin_get_audio_buffer(&audiosize);
828 /* Align codec_mallocbuf to pointer size, tlsf wants that */
829 codec_mallocbuf = (void*)(((intptr_t)codec_mallocbuf +
830 sizeof(intptr_t)-1) & ~(sizeof(intptr_t)-1));
831 audiobuf = SKIPBYTES(codec_mallocbuf, CODEC_SIZE);
832 audiosize -= CODEC_SIZE;
834 rb->lcd_clear_display();
835 rb->lcd_update();
837 enum
839 SPEED_TEST = 0,
840 SPEED_TEST_DIR,
841 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
842 BOOST,
843 #endif
844 WRITE_WAV,
845 SPEED_TEST_WITH_DSP,
846 SPEED_TEST_DIR_WITH_DSP,
847 WRITE_WAV_WITH_DSP,
848 CHECKSUM,
849 CHECKSUM_DIR,
850 QUIT,
853 MENUITEM_STRINGLIST(
854 menu, "test_codec", NULL,
855 "Speed test",
856 "Speed test folder",
857 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
858 "Boosting",
859 #endif
860 "Write WAV",
861 "Speed test with DSP",
862 "Speed test folder with DSP",
863 "Write WAV with DSP",
864 "Checksum",
865 "Checksum folder",
866 "Quit",
870 show_menu:
871 rb->lcd_clear_display();
873 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
874 menu:
875 #endif
877 result = rb->do_menu(&menu, &selection, NULL, false);
878 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
880 if (result == BOOST)
882 rb->set_option("Boosting", &boost, INT,
883 boost_settings, 2, NULL);
884 goto menu;
886 if(boost)
887 rb->cpu_boost(true);
888 #endif
890 if (result == QUIT)
892 res = PLUGIN_OK;
893 goto exit;
896 scandir = 0;
898 if ((checksum = (result == CHECKSUM || result == CHECKSUM_DIR)))
899 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
900 result -= 7;
901 #else
902 result -= 6;
903 #endif
905 if ((use_dsp = ((result >= SPEED_TEST_WITH_DSP)
906 && (result <= WRITE_WAV_WITH_DSP)))) {
907 result -= 3;
909 if (result == SPEED_TEST) {
910 wavinfo.fd = -1;
911 log_init(false);
912 } else if (result == SPEED_TEST_DIR) {
913 wavinfo.fd = -1;
914 scandir = 1;
916 /* Only create a log file when we are testing a folder */
917 if (!log_init(true)) {
918 rb->splash(HZ*2, "Cannot create logfile");
919 res = PLUGIN_ERROR;
920 goto exit;
922 } else if (result == WRITE_WAV) {
923 log_init(false);
924 init_wav("/test.wav");
925 if (wavinfo.fd < 0) {
926 rb->splash(HZ*2, "Cannot create /test.wav");
927 res = PLUGIN_ERROR;
928 goto exit;
930 } else if (result == MENU_ATTACHED_USB) {
931 res = PLUGIN_USB_CONNECTED;
932 goto exit;
933 } else if (result < 0) {
934 res = PLUGIN_OK;
935 goto exit;
938 if (scandir) {
939 /* Test all files in the same directory as the file selected by the
940 user */
942 rb->strlcpy(dirpath,parameter,sizeof(dirpath));
943 ch = rb->strrchr(dirpath,'/');
944 ch[1]=0;
946 DEBUGF("Scanning directory \"%s\"\n",dirpath);
947 dir = rb->opendir(dirpath);
948 if (dir) {
949 entry = rb->readdir(dir);
950 while (entry) {
951 struct dirinfo info = rb->dir_get_info(dir, entry);
952 if (!(info.attribute & ATTR_DIRECTORY)) {
953 rb->snprintf(filename,sizeof(filename),"%s%s",dirpath,entry->d_name);
954 test_track(filename);
955 log_text("", true);
958 /* Read next entry */
959 entry = rb->readdir(dir);
962 rb->closedir(dir);
964 } else {
965 /* Just test the file */
966 res = test_track(parameter);
968 /* Close WAV file (if there was one) */
969 if (wavinfo.fd >= 0) {
970 close_wav();
971 log_text("Wrote /test.wav",true);
973 while (rb->button_get(true) != TESTCODEC_EXITBUTTON);
976 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
977 if(boost)
978 rb->cpu_boost(false);
979 #endif
981 rb->button_clear_queue();
982 goto show_menu;
984 exit:
985 log_close();
987 return res;