Fix warning about missing newline at the EOF
[maemo-rb.git] / apps / plugins / test_codec.c
blob4c0739f660141fcd438038ab473bdc3a187c8d19
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"
23 /* All swcodec targets have BUTTON_SELECT apart from the H10 and M3 */
25 #if CONFIG_KEYPAD == IRIVER_H10_PAD
26 #define TESTCODEC_EXITBUTTON BUTTON_RIGHT
27 #elif CONFIG_KEYPAD == IAUDIO_M3_PAD
28 #define TESTCODEC_EXITBUTTON BUTTON_RC_PLAY
29 #elif CONFIG_KEYPAD == SAMSUNG_YH_PAD
30 #define TESTCODEC_EXITBUTTON BUTTON_PLAY
31 #elif CONFIG_KEYPAD == COWON_D2_PAD || CONFIG_KEYPAD == ONDAVX747_PAD \
32 || CONFIG_KEYPAD == PHILIPS_HDD6330_PAD
33 #define TESTCODEC_EXITBUTTON BUTTON_POWER
34 #elif CONFIG_KEYPAD == PBELL_VIBE500_PAD
35 #define TESTCODEC_EXITBUTTON BUTTON_REC
36 #elif CONFIG_KEYPAD == MPIO_HD200_PAD
37 #define TESTCODEC_EXITBUTTON (BUTTON_REC | BUTTON_PLAY)
38 #elif CONFIG_KEYPAD == MPIO_HD300_PAD
39 #define TESTCODEC_EXITBUTTON (BUTTON_REC | BUTTON_REPEAT)
40 #elif CONFIG_KEYPAD == RK27XX_GENERIC_PAD
41 #define TESTCODEC_EXITBUTTON (BUTTON_M | BUTTON_REPEAT)
42 #elif CONFIG_KEYPAD == SAMSUNG_YPR0_PAD
43 #define TESTCODEC_EXITBUTTON BUTTON_BACK
44 #elif defined(HAVE_TOUCHSCREEN)
45 #define TESTCODEC_EXITBUTTON BUTTON_TOPLEFT
46 #else
47 #define TESTCODEC_EXITBUTTON BUTTON_SELECT
48 #endif
50 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
51 static unsigned int boost =1;
53 static const struct opt_items boost_settings[2] = {
54 { "No", -1 },
55 { "Yes", -1 },
57 #endif
59 /* Log functions copied from test_disk.c */
60 static int line = 0;
61 static int max_line = 0;
62 static int log_fd = -1;
64 static void log_close(void)
66 if (log_fd >= 0)
67 rb->close(log_fd);
70 static bool log_init(bool use_logfile)
72 int h;
73 char logfilename[MAX_PATH];
75 rb->lcd_getstringsize("A", NULL, &h);
76 max_line = LCD_HEIGHT / h;
77 line = 0;
78 rb->lcd_clear_display();
79 rb->lcd_update();
81 if (use_logfile) {
82 log_close();
83 rb->create_numbered_filename(logfilename, HOME_DIR, "test_codec_log_", ".txt",
84 2 IF_CNFN_NUM_(, NULL));
85 log_fd = rb->open(logfilename, O_RDWR|O_CREAT|O_TRUNC, 0666);
86 return log_fd >= 0;
89 return true;
92 static void log_text(char *text, bool advance)
94 rb->lcd_puts(0, line, text);
95 rb->lcd_update();
96 if (advance)
98 if (++line >= max_line)
99 line = 0;
100 if (log_fd >= 0)
101 rb->fdprintf(log_fd, "%s\n", text);
105 struct wavinfo_t
107 int fd;
108 int samplerate;
109 int channels;
110 int sampledepth;
111 int stereomode;
112 int totalsamples;
115 static void* audiobuf;
116 static void* codec_mallocbuf;
117 static size_t audiosize;
118 static size_t audiobufsize;
119 static int offset;
120 static int fd;
122 /* Our local implementation of the codec API */
123 static struct codec_api ci;
125 struct test_track_info {
126 struct mp3entry id3; /* TAG metadata */
127 size_t filesize; /* File total length */
130 static struct test_track_info track;
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 enum codec_command_action codec_action;
140 static volatile long endtick;
141 static volatile long rebuffertick;
142 struct wavinfo_t wavinfo;
144 static unsigned char wav_header[44] =
146 'R','I','F','F', // 0 - ChunkID
147 0,0,0,0, // 4 - ChunkSize (filesize-8)
148 'W','A','V','E', // 8 - Format
149 'f','m','t',' ', // 12 - SubChunkID
150 16,0,0,0, // 16 - SubChunk1ID // 16 for PCM
151 1,0, // 20 - AudioFormat (1=16-bit)
152 0,0, // 22 - NumChannels
153 0,0,0,0, // 24 - SampleRate in Hz
154 0,0,0,0, // 28 - Byte Rate (SampleRate*NumChannels*(BitsPerSample/8)
155 0,0, // 32 - BlockAlign (== NumChannels * BitsPerSample/8)
156 16,0, // 34 - BitsPerSample
157 'd','a','t','a', // 36 - Subchunk2ID
158 0,0,0,0 // 40 - Subchunk2Size
161 static inline void int2le32(unsigned char* buf, int32_t x)
163 buf[0] = (x & 0xff);
164 buf[1] = (x & 0xff00) >> 8;
165 buf[2] = (x & 0xff0000) >> 16;
166 buf[3] = (x & 0xff000000) >>24;
169 static inline void int2le24(unsigned char* buf, int32_t x)
171 buf[0] = (x & 0xff);
172 buf[1] = (x & 0xff00) >> 8;
173 buf[2] = (x & 0xff0000) >> 16;
176 static inline void int2le16(unsigned char* buf, int16_t x)
178 buf[0] = (x & 0xff);
179 buf[1] = (x & 0xff00) >> 8;
182 static unsigned char *wavbuffer;
183 static unsigned char *dspbuffer;
185 void init_wav(char* filename)
187 wavinfo.totalsamples = 0;
189 wavinfo.fd = rb->creat(filename, 0666);
191 if (wavinfo.fd >= 0)
193 /* Write WAV header - we go back and fill in the details at the end */
194 rb->write(wavinfo.fd, wav_header, sizeof(wav_header));
199 void close_wav(void)
201 int filesize = rb->filesize(wavinfo.fd);
202 int channels = (wavinfo.stereomode == STEREO_MONO) ? 1 : 2;
203 int bps = 16; /* TODO */
205 /* We assume 16-bit, Stereo */
207 rb->lseek(wavinfo.fd,0,SEEK_SET);
209 int2le32(wav_header+4, filesize-8); /* ChunkSize */
211 int2le16(wav_header+22, channels);
213 int2le32(wav_header+24, wavinfo.samplerate);
215 int2le32(wav_header+28, wavinfo.samplerate * channels * (bps / 8)); /* ByteRate */
217 int2le16(wav_header+32, channels * (bps / 8));
219 int2le32(wav_header+40, filesize - 44); /* Subchunk2Size */
221 rb->write(wavinfo.fd, wav_header, sizeof(wav_header));
223 rb->close(wavinfo.fd);
226 /* Returns buffer to malloc array. Only codeclib should need this. */
227 static void* codec_get_buffer(size_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;
436 ci.id3->elapsed = value;
440 /* Read next <size> amount bytes from file buffer to <ptr>.
441 Will return number of bytes read or 0 if end of file. */
442 static size_t read_filebuf(void *ptr, size_t size)
444 if (ci.curpos > (off_t)track.filesize)
446 return 0;
447 } else {
448 size_t realsize = MIN(track.filesize-ci.curpos,size);
450 /* check if we have enough bytes ready*/
451 if(realsize >(audiobufsize - (ci.curpos-offset)))
453 /*rebuffer so that we start at ci.curpos*/
454 fill_buffer(ci.curpos);
457 rb->memcpy(ptr, audiobuf + (ci.curpos-offset), realsize);
458 ci.curpos += realsize;
459 return realsize;
464 /* Request pointer to file buffer which can be used to read
465 <realsize> amount of data. <reqsize> tells the buffer system
466 how much data it should try to allocate. If <realsize> is 0,
467 end of file is reached. */
468 static void* request_buffer(size_t *realsize, size_t reqsize)
470 *realsize = MIN(track.filesize-ci.curpos,reqsize);
472 /*check if we have enough bytes ready - requested > bufsize-currentbufpos*/
473 if(*realsize>(audiobufsize - (ci.curpos-offset)))
475 /*rebuffer so that we start at ci.curpos*/
476 fill_buffer(ci.curpos);
479 return (audiobuf + (ci.curpos-offset));
482 /* Advance file buffer position by <amount> amount of bytes. */
483 static void advance_buffer(size_t amount)
485 ci.curpos += amount;
486 ci.id3->offset = ci.curpos;
490 /* Seek file buffer to position <newpos> beginning of file. */
491 static bool seek_buffer(size_t newpos)
493 ci.curpos = newpos;
494 return true;
498 /* Codec should call this function when it has done the seeking. */
499 static void seek_complete(void)
501 /* Do nothing */
504 /* Codec calls this to know what it should do next. */
505 static enum codec_command_action get_command(intptr_t *param)
507 rb->yield();
508 return codec_action;
509 (void)param;
512 /* Some codecs call this to determine whether they should loop. */
513 static bool loop_track(void)
515 return false;
518 static void set_offset(size_t value)
520 ci.id3->offset = value;
524 /* Configure different codec buffer parameters. */
525 static void configure(int setting, intptr_t value)
527 if (use_dsp)
528 rb->dsp_configure(ci.dsp, setting, value);
529 switch(setting)
531 case DSP_SWITCH_FREQUENCY:
532 case DSP_SET_FREQUENCY:
533 DEBUGF("samplerate=%d\n",(int)value);
534 wavinfo.samplerate = (int)value;
535 break;
537 case DSP_SET_SAMPLE_DEPTH:
538 DEBUGF("sampledepth = %d\n",(int)value);
539 wavinfo.sampledepth=(int)value;
540 break;
542 case DSP_SET_STEREO_MODE:
543 DEBUGF("Stereo mode = %d\n",(int)value);
544 wavinfo.stereomode=(int)value;
545 break;
550 static void init_ci(void)
552 /* --- Our "fake" implementations of the codec API functions. --- */
554 ci.dsp = (struct dsp_config *)rb->dsp_configure(NULL, DSP_MYDSP,
555 CODEC_IDX_AUDIO);
557 ci.codec_get_buffer = codec_get_buffer;
559 if (wavinfo.fd >= 0 || checksum) {
560 ci.pcmbuf_insert = pcmbuf_insert_wav_checksum;
561 } else {
562 ci.pcmbuf_insert = pcmbuf_insert_null;
565 ci.set_elapsed = set_elapsed;
566 ci.read_filebuf = read_filebuf;
567 ci.request_buffer = request_buffer;
568 ci.advance_buffer = advance_buffer;
569 ci.seek_buffer = seek_buffer;
570 ci.seek_complete = seek_complete;
571 ci.set_offset = set_offset;
572 ci.configure = configure;
573 ci.get_command = get_command;
574 ci.loop_track = loop_track;
576 /* --- "Core" functions --- */
578 /* kernel/ system */
579 ci.sleep = rb->sleep;
580 ci.yield = rb->yield;
582 /* strings and memory */
583 ci.strcpy = rb->strcpy;
584 ci.strlen = rb->strlen;
585 ci.strcmp = rb->strcmp;
586 ci.strcat = rb->strcat;
587 ci.memset = rb->memset;
588 ci.memcpy = rb->memcpy;
589 ci.memmove = rb->memmove;
590 ci.memcmp = rb->memcmp;
591 ci.memchr = rb->memchr;
592 #if defined(DEBUG) || defined(SIMULATOR)
593 ci.debugf = rb->debugf;
594 #endif
595 #ifdef ROCKBOX_HAS_LOGF
596 ci.logf = rb->logf;
597 #endif
599 ci.qsort = rb->qsort;
601 #ifdef RB_PROFILE
602 ci.profile_thread = rb->profile_thread;
603 ci.profstop = rb->profstop;
604 ci.profile_func_enter = rb->profile_func_enter;
605 ci.profile_func_exit = rb->profile_func_exit;
606 #endif
608 ci.commit_dcache = rb->commit_dcache;
609 ci.commit_discard_dcache = rb->commit_discard_dcache;
610 ci.commit_discard_idcache = rb->commit_discard_idcache;
612 #if NUM_CORES > 1
613 ci.create_thread = rb->create_thread;
614 ci.thread_thaw = rb->thread_thaw;
615 ci.thread_wait = rb->thread_wait;
616 ci.semaphore_init = rb->semaphore_init;
617 ci.semaphore_wait = rb->semaphore_wait;
618 ci.semaphore_release = rb->semaphore_release;
619 #endif
621 #if defined(CPU_ARM) && (CONFIG_PLATFORM & PLATFORM_NATIVE)
622 ci.__div0 = rb->__div0;
623 #endif
626 static void codec_thread(void)
628 const char* codecname;
629 int res;
631 codecname = rb->get_codec_filename(track.id3.codectype);
633 /* Load the codec */
634 res = rb->codec_load_file(codecname, &ci);
636 if (res >= 0)
638 /* Decode the file */
639 res = rb->codec_run_proc();
642 /* Clean up */
643 rb->codec_close();
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.curpos = 0;
718 if (use_dsp)
719 rb->dsp_configure(ci.dsp, DSP_RESET, 0);
721 if (checksum)
722 crc32 = 0xffffffff;
724 rebuffertick=0;
725 starttick = *rb->current_tick;
727 codec_playing = true;
728 codec_action = CODEC_ACTION_NULL;
730 rb->codec_thread_do_callback(codec_thread, NULL);
732 /* Wait for codec thread to die */
733 while (codec_playing)
735 if (rb->button_get_w_tmo(HZ) == TESTCODEC_EXITBUTTON)
737 codec_action = CODEC_ACTION_HALT;
738 break;
741 rb->snprintf(str,sizeof(str),"%d of %d",elapsed,(int)track.id3.length);
742 log_text(str,false);
744 ticks = endtick - starttick;
746 /* Be sure it is done */
747 rb->codec_thread_do_callback(NULL, NULL);
748 rb->backlight_on();
749 log_text(str,true);
751 if (codec_action == CODEC_ACTION_HALT)
753 /* User aborted test */
755 else if (checksum)
757 rb->snprintf(str, sizeof(str), "CRC32 - %08x", (unsigned)crc32);
758 log_text(str,true);
760 else if (wavinfo.fd < 0)
762 /* Display benchmark information */
763 rb->snprintf(str,sizeof(str),"Decode time - %d.%02ds",(int)ticks/100,(int)ticks%100);
764 log_text(str,true);
766 duration = track.id3.length / 10;
767 rb->snprintf(str,sizeof(str),"File duration - %d.%02ds",(int)duration/100,(int)duration%100);
768 log_text(str,true);
770 if (ticks > 0)
771 speed = duration * 10000 / ticks;
772 else
773 speed = 0;
775 rb->snprintf(str,sizeof(str),"%d.%02d%% realtime",(int)speed/100,(int)speed%100);
776 log_text(str,true);
778 #if (CONFIG_PLATFORM & PLATFORM_NATIVE)
779 /* show effective clockrate in MHz needed for realtime decoding */
780 if (speed > 0)
782 int freq = CPUFREQ_MAX;
784 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
785 if(!boost)
786 freq = CPUFREQ_NORMAL;
787 #endif
789 speed = freq / speed;
790 rb->snprintf(str,sizeof(str),"%d.%02dMHz needed for realtime",
791 (int)speed/100,(int)speed%100);
792 log_text(str,true);
794 #endif
797 res = PLUGIN_OK;
799 exit:
800 rb->backlight_on();
802 if (fd >= 0)
804 rb->close(fd);
807 return res;
810 /* plugin entry point */
811 enum plugin_status plugin_start(const void* parameter)
813 int result, selection = 0;
814 enum plugin_status res = PLUGIN_OK;
815 int scandir;
816 struct dirent *entry;
817 DIR* dir;
818 char* ch;
819 char dirpath[MAX_PATH];
820 char filename[MAX_PATH];
821 size_t buffer_size;
823 if (parameter == NULL)
825 rb->splash(HZ*2, "No File");
826 return PLUGIN_ERROR;
829 wavbuffer = rb->plugin_get_buffer(&buffer_size);
830 dspbuffer = wavbuffer + buffer_size / 2;
832 codec_mallocbuf = rb->plugin_get_audio_buffer(&audiosize);
833 /* Align codec_mallocbuf to pointer size, tlsf wants that */
834 codec_mallocbuf = (void*)(((intptr_t)codec_mallocbuf +
835 sizeof(intptr_t)-1) & ~(sizeof(intptr_t)-1));
836 audiobuf = SKIPBYTES(codec_mallocbuf, CODEC_SIZE);
837 audiosize -= CODEC_SIZE;
839 rb->lcd_clear_display();
840 rb->lcd_update();
842 enum
844 SPEED_TEST = 0,
845 SPEED_TEST_DIR,
846 WRITE_WAV,
847 SPEED_TEST_WITH_DSP,
848 SPEED_TEST_DIR_WITH_DSP,
849 WRITE_WAV_WITH_DSP,
850 CHECKSUM,
851 CHECKSUM_DIR,
852 QUIT,
853 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
854 BOOST,
855 #endif
858 MENUITEM_STRINGLIST(
859 menu, "test_codec", NULL,
860 "Speed test",
861 "Speed test folder",
862 "Write WAV",
863 "Speed test with DSP",
864 "Speed test folder with DSP",
865 "Write WAV with DSP",
866 "Checksum",
867 "Checksum folder",
868 "Quit",
869 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
870 "Boosting",
871 #endif
875 show_menu:
876 rb->lcd_clear_display();
878 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
879 menu:
880 #endif
882 result = rb->do_menu(&menu, &selection, NULL, false);
884 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
885 if (result == BOOST)
887 rb->set_option("Boosting", &boost, INT,
888 boost_settings, 2, NULL);
889 goto menu;
891 if(boost)
892 rb->cpu_boost(true);
893 #endif
895 if (result == QUIT)
897 res = PLUGIN_OK;
898 goto exit;
901 scandir = 0;
903 /* Map test runs with checksum calcualtion to standard runs
904 * SPEED_TEST and SPEED_TEST_DIR and set the 'checksum' flag. */
905 if ((checksum = (result == CHECKSUM ||
906 result == CHECKSUM_DIR)))
907 result -= 6;
909 /* Map test runs with DSP to standard runs SPEED_TEST,
910 * SPEED_TEST_DIR and WRITE_WAV and set the 'use_dsp' flag. */
911 if ((use_dsp = (result >= SPEED_TEST_WITH_DSP &&
912 result <= WRITE_WAV_WITH_DSP)))
913 result -= 3;
915 if (result == SPEED_TEST) {
916 wavinfo.fd = -1;
917 log_init(false);
918 } else if (result == SPEED_TEST_DIR) {
919 wavinfo.fd = -1;
920 scandir = 1;
922 /* Only create a log file when we are testing a folder */
923 if (!log_init(true)) {
924 rb->splash(HZ*2, "Cannot create logfile");
925 res = PLUGIN_ERROR;
926 goto exit;
928 } else if (result == WRITE_WAV) {
929 log_init(false);
930 init_wav("/test.wav");
931 if (wavinfo.fd < 0) {
932 rb->splash(HZ*2, "Cannot create /test.wav");
933 res = PLUGIN_ERROR;
934 goto exit;
936 } else if (result == MENU_ATTACHED_USB) {
937 res = PLUGIN_USB_CONNECTED;
938 goto exit;
939 } else if (result < 0) {
940 res = PLUGIN_OK;
941 goto exit;
944 if (scandir) {
945 /* Test all files in the same directory as the file selected by the
946 user */
948 rb->strlcpy(dirpath,parameter,sizeof(dirpath));
949 ch = rb->strrchr(dirpath,'/');
950 ch[1]=0;
952 DEBUGF("Scanning directory \"%s\"\n",dirpath);
953 dir = rb->opendir(dirpath);
954 if (dir) {
955 entry = rb->readdir(dir);
956 while (entry) {
957 struct dirinfo info = rb->dir_get_info(dir, entry);
958 if (!(info.attribute & ATTR_DIRECTORY)) {
959 rb->snprintf(filename,sizeof(filename),"%s%s",dirpath,entry->d_name);
960 test_track(filename);
962 if (codec_action == CODEC_ACTION_HALT)
963 break;
965 log_text("", true);
968 /* Read next entry */
969 entry = rb->readdir(dir);
972 rb->closedir(dir);
974 } else {
975 /* Just test the file */
976 res = test_track(parameter);
978 /* Close WAV file (if there was one) */
979 if (wavinfo.fd >= 0) {
980 close_wav();
981 log_text("Wrote /test.wav",true);
984 while (codec_action != CODEC_ACTION_HALT &&
985 rb->button_get(true) != TESTCODEC_EXITBUTTON);
988 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
989 if(boost)
990 rb->cpu_boost(false);
991 #endif
993 rb->button_clear_queue();
994 goto show_menu;
996 exit:
997 log_close();
999 return res;