diff options
Diffstat (limited to 'apps/plugins')
-rw-r--r-- | apps/plugins/test_codec.c | 326 |
1 files changed, 289 insertions, 37 deletions
diff --git a/apps/plugins/test_codec.c b/apps/plugins/test_codec.c index 3d8da48341..4d9bff7a45 100644 --- a/apps/plugins/test_codec.c +++ b/apps/plugins/test_codec.c | |||
@@ -22,6 +22,16 @@ PLUGIN_HEADER | |||
22 | 22 | ||
23 | static struct plugin_api* rb; | 23 | static struct plugin_api* rb; |
24 | 24 | ||
25 | struct wavinfo_t | ||
26 | { | ||
27 | int fd; | ||
28 | int samplerate; | ||
29 | int channels; | ||
30 | int sampledepth; | ||
31 | int stereomode; | ||
32 | int totalsamples; | ||
33 | }; | ||
34 | |||
25 | static void* audiobuf; | 35 | static void* audiobuf; |
26 | static void* codec_mallocbuf; | 36 | static void* codec_mallocbuf; |
27 | static size_t audiosize; | 37 | static size_t audiosize; |
@@ -35,6 +45,85 @@ static bool taginfo_ready = true; | |||
35 | 45 | ||
36 | static volatile unsigned int elapsed; | 46 | static volatile unsigned int elapsed; |
37 | static volatile bool codec_playing; | 47 | static volatile bool codec_playing; |
48 | struct wavinfo_t wavinfo; | ||
49 | |||
50 | static unsigned char wav_header[44] = | ||
51 | { | ||
52 | 'R','I','F','F', // 0 - ChunkID | ||
53 | 0,0,0,0, // 4 - ChunkSize (filesize-8) | ||
54 | 'W','A','V','E', // 8 - Format | ||
55 | 'f','m','t',' ', // 12 - SubChunkID | ||
56 | 16,0,0,0, // 16 - SubChunk1ID // 16 for PCM | ||
57 | 1,0, // 20 - AudioFormat (1=16-bit) | ||
58 | 0,0, // 22 - NumChannels | ||
59 | 0,0,0,0, // 24 - SampleRate in Hz | ||
60 | 0,0,0,0, // 28 - Byte Rate (SampleRate*NumChannels*(BitsPerSample/8) | ||
61 | 0,0, // 32 - BlockAlign (== NumChannels * BitsPerSample/8) | ||
62 | 16,0, // 34 - BitsPerSample | ||
63 | 'd','a','t','a', // 36 - Subchunk2ID | ||
64 | 0,0,0,0 // 40 - Subchunk2Size | ||
65 | }; | ||
66 | |||
67 | static inline void int2le32(unsigned char* buf, int32_t x) | ||
68 | { | ||
69 | buf[0] = (x & 0xff); | ||
70 | buf[1] = (x & 0xff00) >> 8; | ||
71 | buf[2] = (x & 0xff0000) >> 16; | ||
72 | buf[3] = (x & 0xff000000) >>24; | ||
73 | } | ||
74 | |||
75 | static inline void int2le24(unsigned char* buf, int32_t x) | ||
76 | { | ||
77 | buf[0] = (x & 0xff); | ||
78 | buf[1] = (x & 0xff00) >> 8; | ||
79 | buf[2] = (x & 0xff0000) >> 16; | ||
80 | } | ||
81 | |||
82 | static inline void int2le16(unsigned char* buf, int16_t x) | ||
83 | { | ||
84 | buf[0] = (x & 0xff); | ||
85 | buf[1] = (x & 0xff00) >> 8; | ||
86 | } | ||
87 | |||
88 | void init_wav(char* filename) | ||
89 | { | ||
90 | wavinfo.totalsamples = 0; | ||
91 | |||
92 | wavinfo.fd = rb->creat(filename); | ||
93 | |||
94 | if (wavinfo.fd >= 0) | ||
95 | { | ||
96 | /* Write WAV header - we go back and fill in the details at the end */ | ||
97 | rb->write(wavinfo.fd, wav_header, sizeof(wav_header)); | ||
98 | } | ||
99 | } | ||
100 | |||
101 | |||
102 | void close_wav(void) { | ||
103 | int filesize = rb->filesize(wavinfo.fd); | ||
104 | int channels = (wavinfo.stereomode == STEREO_MONO) ? 1 : 2; | ||
105 | int bps = 16; /* TODO */ | ||
106 | |||
107 | /* We assume 16-bit, Stereo */ | ||
108 | |||
109 | rb->lseek(wavinfo.fd,0,SEEK_SET); | ||
110 | |||
111 | int2le32(wav_header+4, filesize-8); /* ChunkSize */ | ||
112 | |||
113 | int2le16(wav_header+22, channels); | ||
114 | |||
115 | int2le32(wav_header+24, wavinfo.samplerate); | ||
116 | |||
117 | int2le32(wav_header+28, wavinfo.samplerate * channels * (bps / 8)); /* ByteRate */ | ||
118 | |||
119 | int2le16(wav_header+32, channels * (bps / 8)); | ||
120 | |||
121 | int2le32(wav_header+40, filesize - 44); /* Subchunk2Size */ | ||
122 | |||
123 | rb->write(wavinfo.fd, wav_header, sizeof(wav_header)); | ||
124 | |||
125 | rb->close(wavinfo.fd); | ||
126 | } | ||
38 | 127 | ||
39 | /* Returns buffer to malloc array. Only codeclib should need this. */ | 128 | /* Returns buffer to malloc array. Only codeclib should need this. */ |
40 | static void* get_codec_memory(size_t *size) | 129 | static void* get_codec_memory(size_t *size) |
@@ -44,9 +133,8 @@ static void* get_codec_memory(size_t *size) | |||
44 | return codec_mallocbuf; | 133 | return codec_mallocbuf; |
45 | } | 134 | } |
46 | 135 | ||
47 | /* Insert PCM data into audio buffer for playback. Playback will start | 136 | /* Null output */ |
48 | automatically. */ | 137 | static bool pcmbuf_insert_null(const void *ch1, const void *ch2, int count) |
49 | static bool pcmbuf_insert(const void *ch1, const void *ch2, int count) | ||
50 | { | 138 | { |
51 | /* Always successful - just discard data */ | 139 | /* Always successful - just discard data */ |
52 | (void)ch1; | 140 | (void)ch1; |
@@ -56,6 +144,100 @@ static bool pcmbuf_insert(const void *ch1, const void *ch2, int count) | |||
56 | return true; | 144 | return true; |
57 | } | 145 | } |
58 | 146 | ||
147 | /* 64KB should be enough */ | ||
148 | static unsigned char wavbuffer[64*1024]; | ||
149 | |||
150 | static inline int32_t clip_sample(int32_t sample) | ||
151 | { | ||
152 | if ((int16_t)sample != sample) | ||
153 | sample = 0x7fff ^ (sample >> 31); | ||
154 | |||
155 | return sample; | ||
156 | } | ||
157 | |||
158 | |||
159 | /* WAV output */ | ||
160 | static bool pcmbuf_insert_wav(const void *ch1, const void *ch2, int count) | ||
161 | { | ||
162 | const int16_t* data1_16; | ||
163 | const int16_t* data2_16; | ||
164 | const int32_t* data1_32; | ||
165 | const int32_t* data2_32; | ||
166 | unsigned char* p = wavbuffer; | ||
167 | int scale = wavinfo.sampledepth - 15; | ||
168 | |||
169 | if (wavinfo.sampledepth <= 16) { | ||
170 | data1_16 = ch1; | ||
171 | data2_16 = ch2; | ||
172 | |||
173 | switch(wavinfo.stereomode) | ||
174 | { | ||
175 | case STEREO_INTERLEAVED: | ||
176 | while (count--) { | ||
177 | int2le16(p,*data1_16++); | ||
178 | p += 2; | ||
179 | int2le16(p,*data1_16++); | ||
180 | p += 2; | ||
181 | } | ||
182 | break; | ||
183 | |||
184 | case STEREO_NONINTERLEAVED: | ||
185 | while (count--) { | ||
186 | int2le16(p,*data1_16++); | ||
187 | p += 2; | ||
188 | int2le16(p,*data2_16++); | ||
189 | p += 2; | ||
190 | } | ||
191 | |||
192 | break; | ||
193 | |||
194 | case STEREO_MONO: | ||
195 | while (count--) { | ||
196 | int2le16(p,*data1_16++); | ||
197 | p += 2; | ||
198 | } | ||
199 | break; | ||
200 | } | ||
201 | } else { | ||
202 | data1_32 = ch1; | ||
203 | data2_32 = ch2; | ||
204 | |||
205 | switch(wavinfo.stereomode) | ||
206 | { | ||
207 | case STEREO_INTERLEAVED: | ||
208 | while (count--) { | ||
209 | int2le16(p, clip_sample((*data1_32++) >> scale)); | ||
210 | p += 2; | ||
211 | int2le16(p, clip_sample((*data1_32++) >> scale)); | ||
212 | p += 2; | ||
213 | } | ||
214 | break; | ||
215 | |||
216 | case STEREO_NONINTERLEAVED: | ||
217 | while (count--) { | ||
218 | int2le16(p, clip_sample((*data1_32++) >> scale)); | ||
219 | p += 2; | ||
220 | int2le16(p, clip_sample((*data2_32++) >> scale)); | ||
221 | p += 2; | ||
222 | } | ||
223 | |||
224 | break; | ||
225 | |||
226 | case STEREO_MONO: | ||
227 | while (count--) { | ||
228 | int2le16(p, clip_sample((*data1_32++) >> scale)); | ||
229 | p += 2; | ||
230 | } | ||
231 | break; | ||
232 | } | ||
233 | } | ||
234 | |||
235 | wavinfo.totalsamples += count; | ||
236 | rb->write(wavinfo.fd, wavbuffer, p - wavbuffer); | ||
237 | |||
238 | return true; | ||
239 | } | ||
240 | |||
59 | 241 | ||
60 | /* Set song position in WPS (value in ms). */ | 242 | /* Set song position in WPS (value in ms). */ |
61 | static void set_elapsed(unsigned int value) | 243 | static void set_elapsed(unsigned int value) |
@@ -68,7 +250,6 @@ static void set_elapsed(unsigned int value) | |||
68 | Will return number of bytes read or 0 if end of file. */ | 250 | Will return number of bytes read or 0 if end of file. */ |
69 | static size_t read_filebuf(void *ptr, size_t size) | 251 | static size_t read_filebuf(void *ptr, size_t size) |
70 | { | 252 | { |
71 | DEBUGF("read_filebuf(_,%d)\n",(int)size); | ||
72 | if (ci.curpos > (off_t)track.filesize) | 253 | if (ci.curpos > (off_t)track.filesize) |
73 | { | 254 | { |
74 | return 0; | 255 | return 0; |
@@ -76,7 +257,6 @@ static size_t read_filebuf(void *ptr, size_t size) | |||
76 | /* TODO: Don't read beyond end of buffer */ | 257 | /* TODO: Don't read beyond end of buffer */ |
77 | rb->memcpy(ptr, audiobuf + ci.curpos, size); | 258 | rb->memcpy(ptr, audiobuf + ci.curpos, size); |
78 | ci.curpos += size; | 259 | ci.curpos += size; |
79 | DEBUGF("New ci.curpos = %d\n",ci.curpos); | ||
80 | return size; | 260 | return size; |
81 | } | 261 | } |
82 | } | 262 | } |
@@ -98,7 +278,6 @@ static void* request_buffer(size_t *realsize, size_t reqsize) | |||
98 | static void advance_buffer(size_t amount) | 278 | static void advance_buffer(size_t amount) |
99 | { | 279 | { |
100 | ci.curpos += amount; | 280 | ci.curpos += amount; |
101 | DEBUGF("advance_buffer(%d) - new ci.curpos=%d\n",(int)amount,(int)ci.curpos); | ||
102 | } | 281 | } |
103 | 282 | ||
104 | 283 | ||
@@ -152,7 +331,6 @@ static void discard_codec(void) | |||
152 | 331 | ||
153 | static void set_offset(size_t value) | 332 | static void set_offset(size_t value) |
154 | { | 333 | { |
155 | DEBUGF("set_offset(%d)\n",(int)value); | ||
156 | /* ??? */ | 334 | /* ??? */ |
157 | (void)value; | 335 | (void)value; |
158 | } | 336 | } |
@@ -161,9 +339,25 @@ static void set_offset(size_t value) | |||
161 | /* Configure different codec buffer parameters. */ | 339 | /* Configure different codec buffer parameters. */ |
162 | static void configure(int setting, intptr_t value) | 340 | static void configure(int setting, intptr_t value) |
163 | { | 341 | { |
164 | (void)setting; | 342 | switch(setting) |
165 | (void)value; | 343 | { |
166 | DEBUGF("setting %d = %d\n",setting,(int)value); | 344 | case DSP_SWITCH_FREQUENCY: |
345 | case DSP_SET_FREQUENCY: | ||
346 | DEBUGF("samplerate=%d\n",(int)value); | ||
347 | wavinfo.samplerate = (int)value; | ||
348 | break; | ||
349 | |||
350 | case DSP_SET_SAMPLE_DEPTH: | ||
351 | DEBUGF("sampledepth = %d\n",(int)value); | ||
352 | wavinfo.sampledepth=(int)value; | ||
353 | break; | ||
354 | |||
355 | case DSP_SET_STEREO_MODE: | ||
356 | DEBUGF("Stereo mode = %d\n",(int)value); | ||
357 | wavinfo.stereomode=(int)value; | ||
358 | break; | ||
359 | } | ||
360 | |||
167 | } | 361 | } |
168 | 362 | ||
169 | static void init_ci(void) | 363 | static void init_ci(void) |
@@ -171,7 +365,12 @@ static void init_ci(void) | |||
171 | /* --- Our "fake" implementations of the codec API functions. --- */ | 365 | /* --- Our "fake" implementations of the codec API functions. --- */ |
172 | 366 | ||
173 | ci.get_codec_memory = get_codec_memory; | 367 | ci.get_codec_memory = get_codec_memory; |
174 | ci.pcmbuf_insert = pcmbuf_insert; | 368 | |
369 | if (wavinfo.fd >= 0) { | ||
370 | ci.pcmbuf_insert = pcmbuf_insert_wav; | ||
371 | } else { | ||
372 | ci.pcmbuf_insert = pcmbuf_insert_null; | ||
373 | } | ||
175 | ci.set_elapsed = set_elapsed; | 374 | ci.set_elapsed = set_elapsed; |
176 | ci.read_filebuf = read_filebuf; | 375 | ci.read_filebuf = read_filebuf; |
177 | ci.request_buffer = request_buffer; | 376 | ci.request_buffer = request_buffer; |
@@ -244,6 +443,7 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | |||
244 | size_t n; | 443 | size_t n; |
245 | int fd; | 444 | int fd; |
246 | int i; | 445 | int i; |
446 | enum plugin_status res = PLUGIN_OK; | ||
247 | unsigned long starttick; | 447 | unsigned long starttick; |
248 | unsigned long ticks; | 448 | unsigned long ticks; |
249 | unsigned long speed; | 449 | unsigned long speed; |
@@ -252,6 +452,9 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | |||
252 | unsigned char* codec_stack_copy; | 452 | unsigned char* codec_stack_copy; |
253 | size_t codec_stack_size; | 453 | size_t codec_stack_size; |
254 | struct thread_entry* codecthread_id; | 454 | struct thread_entry* codecthread_id; |
455 | int result; | ||
456 | char* ch; | ||
457 | int line = 0; | ||
255 | 458 | ||
256 | rb = api; | 459 | rb = api; |
257 | 460 | ||
@@ -261,6 +464,10 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | |||
261 | return PLUGIN_ERROR; | 464 | return PLUGIN_ERROR; |
262 | } | 465 | } |
263 | 466 | ||
467 | #ifdef SIMULATOR | ||
468 | /* The simulator thread implementation doesn't have stack buffers */ | ||
469 | (void)i; | ||
470 | #else | ||
264 | /* Borrow the codec thread's stack (in IRAM on most targets) */ | 471 | /* Borrow the codec thread's stack (in IRAM on most targets) */ |
265 | codec_stack = NULL; | 472 | codec_stack = NULL; |
266 | for (i = 0; i < MAXTHREADS; i++) | 473 | for (i = 0; i < MAXTHREADS; i++) |
@@ -278,14 +485,17 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | |||
278 | rb->splash(HZ*2, "No codec thread!"); | 485 | rb->splash(HZ*2, "No codec thread!"); |
279 | return PLUGIN_ERROR; | 486 | return PLUGIN_ERROR; |
280 | } | 487 | } |
488 | #endif | ||
281 | 489 | ||
282 | codec_mallocbuf = rb->plugin_get_audio_buffer(&audiosize); | 490 | codec_mallocbuf = rb->plugin_get_audio_buffer(&audiosize); |
283 | codec_stack_copy = codec_mallocbuf + 512*1024; | 491 | codec_stack_copy = codec_mallocbuf + 512*1024; |
284 | audiobuf = codec_stack_copy + codec_stack_size; | 492 | audiobuf = codec_stack_copy + codec_stack_size; |
285 | audiosize -= 512*1024 + codec_stack_size; | 493 | audiosize -= 512*1024 + codec_stack_size; |
286 | 494 | ||
495 | #ifndef SIMULATOR | ||
287 | /* Backup the codec thread's stack */ | 496 | /* Backup the codec thread's stack */ |
288 | rb->memcpy(codec_stack_copy,codec_stack,codec_stack_size); | 497 | rb->memcpy(codec_stack_copy,codec_stack,codec_stack_size); |
498 | #endif | ||
289 | 499 | ||
290 | fd = rb->open(parameter,O_RDONLY); | 500 | fd = rb->open(parameter,O_RDONLY); |
291 | if (fd < 0) | 501 | if (fd < 0) |
@@ -309,14 +519,46 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | |||
309 | return PLUGIN_ERROR; | 519 | return PLUGIN_ERROR; |
310 | } | 520 | } |
311 | 521 | ||
522 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | ||
523 | rb->cpu_boost(true); | ||
524 | #endif | ||
525 | rb->lcd_clear_display(); | ||
526 | rb->lcd_update(); | ||
527 | |||
528 | MENUITEM_STRINGLIST(menu,"test_codec",NULL,"Speed test","Write WAV"); | ||
529 | |||
530 | rb->lcd_clear_display(); | ||
531 | |||
532 | DEBUGF("Calling menu\n"); | ||
533 | result=rb->do_menu(&menu,&result); | ||
534 | DEBUGF("Done\n"); | ||
535 | |||
536 | if (result==1) { | ||
537 | init_wav("/test.wav"); | ||
538 | if (wavinfo.fd < 0) { | ||
539 | rb->splash(HZ*2, "Cannot create /test.wav"); | ||
540 | res = PLUGIN_ERROR; | ||
541 | goto exit; | ||
542 | } | ||
543 | } else if (result == MENU_ATTACHED_USB) { | ||
544 | res = PLUGIN_USB_CONNECTED; | ||
545 | goto exit; | ||
546 | } else if (result < 0) { | ||
547 | res = PLUGIN_OK; | ||
548 | goto exit; | ||
549 | } | ||
550 | |||
551 | rb->lcd_clear_display(); | ||
312 | rb->splash(0, "Loading..."); | 552 | rb->splash(0, "Loading..."); |
553 | rb->lcd_clear_display(); | ||
313 | 554 | ||
314 | n = rb->read(fd, audiobuf, track.filesize); | 555 | n = rb->read(fd, audiobuf, track.filesize); |
315 | 556 | ||
316 | if (n != track.filesize) | 557 | if (n != track.filesize) |
317 | { | 558 | { |
318 | rb->splash(HZ*2, "Read failed."); | 559 | rb->splash(HZ*2, "Read failed."); |
319 | return PLUGIN_ERROR; | 560 | res = PLUGIN_ERROR; |
561 | goto exit; | ||
320 | } | 562 | } |
321 | 563 | ||
322 | /* Initialise the function pointers in the codec API */ | 564 | /* Initialise the function pointers in the codec API */ |
@@ -331,15 +573,6 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | |||
331 | ci.new_track = 0; | 573 | ci.new_track = 0; |
332 | ci.seek_time = 0; | 574 | ci.seek_time = 0; |
333 | 575 | ||
334 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | ||
335 | rb->cpu_boost(true); | ||
336 | #endif | ||
337 | rb->lcd_set_backdrop(NULL); | ||
338 | rb->lcd_set_foreground(LCD_WHITE); | ||
339 | rb->lcd_set_background(LCD_BLACK); | ||
340 | rb->lcd_clear_display(); | ||
341 | rb->lcd_update(); | ||
342 | |||
343 | starttick = *rb->current_tick; | 576 | starttick = *rb->current_tick; |
344 | 577 | ||
345 | codec_playing = true; | 578 | codec_playing = true; |
@@ -352,44 +585,63 @@ enum plugin_status plugin_start(struct plugin_api* api, void* parameter) | |||
352 | goto exit; | 585 | goto exit; |
353 | } | 586 | } |
354 | 587 | ||
588 | /* Display filename (excluding any path)*/ | ||
589 | ch = rb->strrchr(parameter, '/'); | ||
590 | if (ch==NULL) | ||
591 | ch = parameter; | ||
592 | else | ||
593 | ch++; | ||
594 | |||
595 | rb->snprintf(str,sizeof(str),"%s",ch); | ||
596 | rb->lcd_puts(0,line++,str); | ||
597 | |||
355 | /* Wait for codec thread to die */ | 598 | /* Wait for codec thread to die */ |
356 | while (codec_playing) | 599 | while (codec_playing) |
357 | { | 600 | { |
358 | rb->sleep(HZ); | 601 | rb->sleep(HZ); |
359 | rb->snprintf(str,sizeof(str),"%d of %d",elapsed,(int)track.id3.length); | 602 | rb->snprintf(str,sizeof(str),"%d of %d",elapsed,(int)track.id3.length); |
360 | rb->lcd_puts(0,0,str); | 603 | rb->lcd_puts(0,line,str); |
361 | rb->lcd_update(); | 604 | rb->lcd_update(); |
362 | } | 605 | } |
606 | line++; | ||
607 | |||
608 | /* Close WAV file (if there was one) */ | ||
609 | if (wavinfo.fd >= 0) { | ||
610 | close_wav(); | ||
611 | rb->lcd_puts(0,line++,"Wrote /test.wav"); | ||
612 | } else { | ||
613 | /* Display benchmark information */ | ||
363 | 614 | ||
364 | /* Display benchmark information */ | 615 | ticks = *rb->current_tick - starttick; |
365 | 616 | rb->snprintf(str,sizeof(str),"Decode time - %d.%02ds",(int)ticks/100,(int)ticks%100); | |
366 | ticks = *rb->current_tick - starttick; | 617 | rb->lcd_puts(0,line++,str); |
367 | rb->snprintf(str,sizeof(str),"Decode time - %d.%02ds",(int)ticks/100,(int)ticks%100); | ||
368 | rb->lcd_puts(0,1,str); | ||
369 | 618 | ||
370 | duration = track.id3.length / 10; | 619 | duration = track.id3.length / 10; |
371 | rb->snprintf(str,sizeof(str),"File duration - %d.%02ds",(int)duration/100,(int)duration%100); | 620 | rb->snprintf(str,sizeof(str),"File duration - %d.%02ds",(int)duration/100,(int)duration%100); |
372 | rb->lcd_puts(0,2,str); | 621 | rb->lcd_puts(0,line++,str); |
373 | 622 | ||
374 | if (ticks > 0) | 623 | if (ticks > 0) |
375 | speed = duration * 10000 / ticks; | 624 | speed = duration * 10000 / ticks; |
376 | else | 625 | else |
377 | speed = 0; | 626 | speed = 0; |
378 | 627 | ||
379 | rb->snprintf(str,sizeof(str),"%d.%02d%% realtime",(int)speed/100,(int)speed%100); | 628 | rb->snprintf(str,sizeof(str),"%d.%02d%% realtime",(int)speed/100,(int)speed%100); |
380 | rb->lcd_puts(0,3,str); | 629 | rb->lcd_puts(0,line++,str); |
381 | 630 | ||
631 | } | ||
382 | rb->lcd_update(); | 632 | rb->lcd_update(); |
383 | 633 | ||
384 | while (rb->button_get(true) != BUTTON_SELECT); | 634 | while (rb->button_get(true) != BUTTON_SELECT); |
385 | 635 | ||
386 | exit: | 636 | exit: |
637 | #ifndef SIMULATOR | ||
387 | /* Restore the codec thread's stack */ | 638 | /* Restore the codec thread's stack */ |
388 | rb->memcpy(codec_stack, codec_stack_copy, codec_stack_size); | 639 | rb->memcpy(codec_stack, codec_stack_copy, codec_stack_size); |
640 | #endif | ||
389 | 641 | ||
390 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | 642 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ |
391 | rb->cpu_boost(false); | 643 | rb->cpu_boost(false); |
392 | #endif | 644 | #endif |
393 | 645 | ||
394 | return PLUGIN_OK; | 646 | return res; |
395 | } | 647 | } |