summaryrefslogtreecommitdiff
path: root/apps/radio/radio.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/radio/radio.c')
-rw-r--r--apps/radio/radio.c1042
1 files changed, 1042 insertions, 0 deletions
diff --git a/apps/radio/radio.c b/apps/radio/radio.c
new file mode 100644
index 0000000000..b3540610f1
--- /dev/null
+++ b/apps/radio/radio.c
@@ -0,0 +1,1042 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2003 Linus Nielsen Feltzing
11 *
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.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "config.h"
23#include <stdio.h>
24#include <stdbool.h>
25#include <stdlib.h>
26#include "mas.h"
27#include "settings.h"
28#include "button.h"
29#include "status.h"
30#include "thread.h"
31#include "audio.h"
32#include "mp3_playback.h"
33#include "ctype.h"
34#include "file.h"
35#include "general.h"
36#include "errno.h"
37#include "string-extra.h"
38#include "system.h"
39#include "radio.h"
40#include "menu.h"
41#include "misc.h"
42#include "keyboard.h"
43#include "screens.h"
44#include "peakmeter.h"
45#include "lang.h"
46#include "font.h"
47#include "sound_menu.h"
48#ifdef HAVE_RECORDING
49#include "recording.h"
50#endif
51#ifdef IPOD_ACCESSORY_PROTOCOL
52#include "iap.h"
53#endif
54#include "appevents.h"
55#include "talk.h"
56#include "tuner.h"
57#include "power.h"
58#include "sound.h"
59#include "screen_access.h"
60#include "splash.h"
61#include "yesno.h"
62#include "buttonbar.h"
63#include "tree.h"
64#include "dir.h"
65#include "action.h"
66#include "list.h"
67#include "menus/exported_menus.h"
68#include "root_menu.h"
69#include "viewport.h"
70#include "skin_engine/skin_engine.h"
71#include "statusbar-skinned.h"
72#include "buffering.h"
73
74#if CONFIG_TUNER
75
76#if CONFIG_KEYPAD == RECORDER_PAD
77#define FM_RECORD
78#define FM_PRESET_ADD
79#define FM_PRESET_ACTION
80#define FM_PRESET
81#define FM_MODE
82
83#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
84#define FM_PRESET
85#define FM_MODE
86#define FM_NEXT_PRESET
87#define FM_PREV_PRESET
88
89#elif CONFIG_KEYPAD == IRIVER_H10_PAD
90#define FM_PRESET
91#define FM_MODE
92
93#elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
94#define FM_PRESET
95#define FM_MODE
96/* This should be removeable if the whole tuning thing is sorted out since
97 proper tuning quiets the screen almost entirely in that extreme measures
98 have to be taken to hear any interference. */
99#define HAVE_NOISY_IDLE_MODE
100
101#elif CONFIG_KEYPAD == ONDIO_PAD
102#define FM_RECORD_DBLPRE
103#define FM_RECORD
104#elif (CONFIG_KEYPAD == SANSA_E200_PAD) || (CONFIG_KEYPAD == SANSA_C200_PAD)
105#define FM_MENU
106#define FM_PRESET
107#define FM_STOP
108#define FM_MODE
109#define FM_EXIT
110#define FM_PLAY
111
112#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
113#define FM_PRESET
114#define FM_MODE
115
116#elif (CONFIG_KEYPAD == COWON_D2_PAD)
117#define FM_MENU
118#define FM_PRESET
119#define FM_STOP
120#define FM_MODE
121#define FM_EXIT
122#define FM_PLAY
123
124#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
125 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
126#define FM_MENU
127#define FM_STOP
128#define FM_EXIT
129#define FM_PLAY
130#define FM_MODE
131
132#endif
133
134/* presets.c needs these so keep unstatic or redo the whole thing! */
135int curr_freq; /* current frequency in Hz */
136/* these are all in presets.c... someone PLEASE rework this ! */
137int handle_radio_presets(void);
138static bool radio_menu(void);
139int radio_add_preset(void);
140int save_preset_list(void);
141int load_preset_list(void);
142int clear_preset_list(void);
143void next_preset(int direction);
144void set_current_preset(int preset);
145int scan_presets(void *viewports);
146int find_preset(int freq);
147void radio_save_presets(void);
148bool has_presets_changed(void);
149void talk_preset(int preset, bool fallback, bool enqueue);
150void presets_save(void);
151
152
153
154int radio_mode = RADIO_SCAN_MODE;
155static int search_dir = 0;
156
157static int radio_status = FMRADIO_OFF;
158static bool in_screen = false;
159
160
161static void radio_off(void);
162
163bool radio_scan_mode(void)
164{
165 return radio_mode == RADIO_SCAN_MODE;
166}
167
168bool radio_is_stereo(void)
169{
170 return tuner_get(RADIO_STEREO) && !global_settings.fm_force_mono;
171}
172int radio_current_frequency(void)
173{
174 return curr_freq;
175}
176
177/* Function to manipulate all yesno dialogues.
178 This function needs the output text as an argument. */
179bool yesno_pop(const char* text)
180{
181 int i;
182 const char *lines[]={text};
183 const struct text_message message={lines, 1};
184 bool ret = (gui_syncyesno_run(&message,NULL,NULL)== YESNO_YES);
185 FOR_NB_SCREENS(i)
186 screens[i].clear_viewport();
187 return ret;
188}
189
190void radio_init(void)
191{
192 tuner_init();
193 radio_off();
194#ifdef HAVE_ALBUMART
195 radioart_init(false);
196#endif
197}
198
199int get_radio_status(void)
200{
201 return radio_status;
202}
203
204bool in_radio_screen(void)
205{
206 return in_screen;
207}
208
209/* TODO: Move some more of the control functionality to firmware
210 and clean up the mess */
211
212/* secret flag for starting paused - prevents unmute */
213#define FMRADIO_START_PAUSED 0x8000
214void radio_start(void)
215{
216 const struct fm_region_data *fmr;
217 bool start_paused;
218
219 if(radio_status == FMRADIO_PLAYING)
220 return;
221
222 fmr = &fm_region_data[global_settings.fm_region];
223
224 start_paused = radio_status & FMRADIO_START_PAUSED;
225 /* clear flag before any yielding */
226 radio_status &= ~FMRADIO_START_PAUSED;
227
228 if(radio_status == FMRADIO_OFF)
229 tuner_power(true);
230
231 curr_freq = global_status.last_frequency * fmr->freq_step + fmr->freq_min;
232
233 tuner_set(RADIO_SLEEP, 0); /* wake up the tuner */
234
235 if(radio_status == FMRADIO_OFF)
236 {
237#ifdef HAVE_RADIO_REGION
238 tuner_set(RADIO_REGION, global_settings.fm_region);
239#endif
240 tuner_set(RADIO_FORCE_MONO, global_settings.fm_force_mono);
241 }
242
243 tuner_set(RADIO_FREQUENCY, curr_freq);
244
245#ifdef HAVE_RADIO_MUTE_TIMEOUT
246 {
247 unsigned long mute_timeout = current_tick + HZ;
248 if (radio_status != FMRADIO_OFF)
249 {
250 /* paused */
251 mute_timeout += HZ;
252 }
253
254 while(!tuner_get(RADIO_STEREO) && !tuner_get(RADIO_TUNED))
255 {
256 if(TIME_AFTER(current_tick, mute_timeout))
257 break;
258 yield();
259 }
260 }
261#endif
262
263 /* keep radio from sounding initially */
264 if(!start_paused)
265 tuner_set(RADIO_MUTE, 0);
266
267 radio_status = FMRADIO_PLAYING;
268} /* radio_start */
269
270void radio_pause(void)
271{
272 if(radio_status == FMRADIO_PAUSED)
273 return;
274
275 if(radio_status == FMRADIO_OFF)
276 {
277 radio_status |= FMRADIO_START_PAUSED;
278 radio_start();
279 }
280
281 tuner_set(RADIO_MUTE, 1);
282 tuner_set(RADIO_SLEEP, 1);
283
284 radio_status = FMRADIO_PAUSED;
285} /* radio_pause */
286
287static void radio_off(void)
288{
289 tuner_set(RADIO_MUTE, 1);
290 tuner_set(RADIO_SLEEP, 1); /* low power mode, if available */
291 radio_status = FMRADIO_OFF;
292 tuner_power(false); /* status update, power off if avail. */
293}
294
295void radio_stop(void)
296{
297 if(radio_status == FMRADIO_OFF)
298 return;
299
300 radio_off();
301} /* radio_stop */
302
303bool radio_hardware_present(void)
304{
305 return tuner_get(RADIO_PRESENT);
306}
307
308/* Keep freq on the grid for the current region */
309int snap_freq_to_grid(int freq)
310{
311 const struct fm_region_data * const fmr =
312 &fm_region_data[global_settings.fm_region];
313
314 /* Range clamp if out of range or just round to nearest */
315 if (freq < fmr->freq_min)
316 freq = fmr->freq_min;
317 else if (freq > fmr->freq_max)
318 freq = fmr->freq_max;
319 else
320 freq = (freq - fmr->freq_min + fmr->freq_step/2) /
321 fmr->freq_step * fmr->freq_step + fmr->freq_min;
322
323 return freq;
324}
325
326void remember_frequency(void)
327{
328 const struct fm_region_data * const fmr =
329 &fm_region_data[global_settings.fm_region];
330 global_status.last_frequency = (curr_freq - fmr->freq_min)
331 / fmr->freq_step;
332 status_save();
333}
334
335/* Step to the next or previous frequency */
336static int step_freq(int freq, int direction)
337{
338 const struct fm_region_data * const fmr =
339 &fm_region_data[global_settings.fm_region];
340
341 freq += direction*fmr->freq_step;
342
343 /* Wrap first or snapping to grid will not let us on the band extremes */
344 if (freq > fmr->freq_max)
345 freq = direction > 0 ? fmr->freq_min : fmr->freq_max;
346 else if (freq < fmr->freq_min)
347 freq = direction < 0 ? fmr->freq_max : fmr->freq_min;
348 else
349 freq = snap_freq_to_grid(freq);
350
351 return freq;
352}
353
354/* Step to the next or previous station */
355void next_station(int direction)
356{
357 if (direction != 0 && radio_mode != RADIO_SCAN_MODE)
358 {
359 next_preset(direction);
360 return;
361 }
362
363 curr_freq = step_freq(curr_freq, direction);
364
365 if (radio_status == FMRADIO_PLAYING)
366 tuner_set(RADIO_MUTE, 1);
367
368 tuner_set(RADIO_FREQUENCY, curr_freq);
369
370 if (radio_status == FMRADIO_PLAYING)
371 tuner_set(RADIO_MUTE, 0);
372
373 set_current_preset(find_preset(curr_freq));
374 remember_frequency();
375}
376
377/* Ends an in-progress search */
378static void end_search(void)
379{
380 if (search_dir != 0 && radio_status == FMRADIO_PLAYING)
381 tuner_set(RADIO_MUTE, 0);
382 search_dir = 0;
383}
384
385/* Speak a frequency. */
386void talk_freq(int freq, bool enqueue)
387{
388 freq /= 10000;
389 talk_number(freq / 100, enqueue);
390 talk_id(LANG_POINT, true);
391 talk_number(freq % 100 / 10, true);
392 if (freq % 10)
393 talk_number(freq % 10, true);
394}
395
396
397int radio_screen(void)
398{
399 bool done = false;
400 int ret_val = GO_TO_ROOT;
401 int button;
402 int i;
403 bool stereo = false, last_stereo = false;
404 bool update_screen = true, restore = true;
405 bool screen_freeze = false;
406 bool keep_playing = false;
407 bool talk = false;
408#ifdef FM_RECORD_DBLPRE
409 int lastbutton = BUTTON_NONE;
410 unsigned long rec_lastclick = 0;
411#endif
412#if CONFIG_CODEC != SWCODEC
413 bool have_recorded = false;
414 int timeout = current_tick + HZ/10;
415 unsigned int last_seconds = 0;
416#ifndef SIMULATOR
417 unsigned int seconds = 0;
418 struct audio_recording_options rec_options;
419#endif
420#endif /* CONFIG_CODEC != SWCODEC */
421#ifndef HAVE_NOISY_IDLE_MODE
422 int button_timeout = current_tick + (2*HZ);
423#endif
424
425 /* change status to "in screen" */
426 in_screen = true;
427
428 if(radio_preset_count() <= 0)
429 {
430 radio_load_presets(global_settings.fmr_file);
431 }
432#ifdef HAVE_ALBUMART
433 radioart_init(true);
434#endif
435
436 if(radio_status == FMRADIO_OFF)
437 audio_stop();
438
439#ifndef SIMULATOR
440
441#if CONFIG_CODEC != SWCODEC
442 if(rec_create_directory() > 0)
443 have_recorded = true;
444
445 audio_init_recording(talk_get_bufsize());
446
447 sound_settings_apply();
448 /* Yes, we use the D/A for monitoring */
449 peak_meter_playback(true);
450
451 peak_meter_enable(true);
452
453 rec_init_recording_options(&rec_options);
454 rec_options.rec_source = AUDIO_SRC_LINEIN;
455 rec_set_recording_options(&rec_options);
456
457 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN),
458 sound_default(SOUND_RIGHT_GAIN), AUDIO_GAIN_LINEIN);
459
460#endif /* CONFIG_CODEC != SWCODEC */
461#endif /* ndef SIMULATOR */
462
463 /* turn on radio */
464#if CONFIG_CODEC == SWCODEC
465 audio_set_input_source(AUDIO_SRC_FMRADIO,
466 (radio_status == FMRADIO_PAUSED) ?
467 SRCF_FMRADIO_PAUSED : SRCF_FMRADIO_PLAYING);
468#else
469 if (radio_status == FMRADIO_OFF)
470 radio_start();
471#endif
472
473 if(radio_preset_count() < 1 && yesno_pop(ID2P(LANG_FM_FIRST_AUTOSCAN)))
474 scan_presets(NULL);
475
476 set_current_preset(find_preset(curr_freq));
477 if(radio_current_preset() != -1)
478 radio_mode = RADIO_PRESET_MODE;
479
480#ifndef HAVE_NOISY_IDLE_MODE
481 cpu_idle_mode(true);
482#endif
483
484 while(!done)
485 {
486 if(search_dir != 0)
487 {
488 curr_freq = step_freq(curr_freq, search_dir);
489 update_screen = true;
490
491 if(tuner_set(RADIO_SCAN_FREQUENCY, curr_freq))
492 {
493 set_current_preset(find_preset(curr_freq));
494 remember_frequency();
495 end_search();
496 talk = true;
497 }
498 trigger_cpu_boost();
499 }
500
501 if (!update_screen)
502 {
503 cancel_cpu_boost();
504 }
505
506 button = fms_do_button_loop(update_screen);
507
508#ifndef HAVE_NOISY_IDLE_MODE
509 if (button != ACTION_NONE)
510 {
511 cpu_idle_mode(false);
512 button_timeout = current_tick + (2*HZ);
513 }
514#endif
515 switch(button)
516 {
517 case ACTION_FM_STOP:
518#if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
519 if(audio_status() == AUDIO_STATUS_RECORD)
520 {
521 audio_stop();
522 }
523 else
524#endif
525 {
526 done = true;
527 if(has_presets_changed())
528 {
529 if(yesno_pop(ID2P(LANG_FM_SAVE_CHANGES)))
530 {
531 presets_save();
532 }
533 }
534 }
535 update_screen = true;
536 break;
537
538#ifdef FM_RECORD
539 case ACTION_FM_RECORD:
540#ifdef FM_RECORD_DBLPRE
541 if (lastbutton != ACTION_FM_RECORD_DBLPRE)
542 {
543 rec_lastclick = 0;
544 break;
545 }
546 if (current_tick - rec_lastclick > HZ/2)
547 {
548 rec_lastclick = current_tick;
549 break;
550 }
551#endif /* FM_RECORD_DBLPRE */
552#ifndef SIMULATOR
553 if(audio_status() == AUDIO_STATUS_RECORD)
554 {
555 rec_command(RECORDING_CMD_START_NEWFILE);
556 update_screen = true;
557 }
558 else
559 {
560 have_recorded = true;
561 rec_command(RECORDING_CMD_START);
562 update_screen = true;
563 }
564#endif /* SIMULATOR */
565 last_seconds = 0;
566 break;
567#endif /* #ifdef FM_RECORD */
568
569 case ACTION_FM_EXIT:
570#if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
571 if(audio_status() == AUDIO_STATUS_RECORD)
572 audio_stop();
573#endif
574 keep_playing = true;
575 done = true;
576 ret_val = GO_TO_ROOT;
577 if(has_presets_changed())
578 {
579 if(yesno_pop(ID2P(LANG_FM_SAVE_CHANGES)))
580 {
581 presets_save();
582 }
583 }
584
585 break;
586
587 case ACTION_STD_PREV:
588 case ACTION_STD_NEXT:
589 next_station(button == ACTION_STD_PREV ? -1 : 1);
590 end_search();
591 update_screen = true;
592 talk = true;
593 break;
594
595 case ACTION_STD_PREVREPEAT:
596 case ACTION_STD_NEXTREPEAT:
597 {
598 int dir = search_dir;
599 search_dir = button == ACTION_STD_PREVREPEAT ? -1 : 1;
600 if (radio_mode != RADIO_SCAN_MODE)
601 {
602 next_preset(search_dir);
603 end_search();
604 update_screen = true;
605 talk = true;
606 }
607 else if (dir == 0)
608 {
609 /* Starting auto scan */
610 tuner_set(RADIO_MUTE, 1);
611 update_screen = true;
612 }
613 break;
614 }
615
616 case ACTION_SETTINGS_INC:
617 case ACTION_SETTINGS_INCREPEAT:
618 global_settings.volume++;
619 setvol();
620 update_screen = true;
621 break;
622
623 case ACTION_SETTINGS_DEC:
624 case ACTION_SETTINGS_DECREPEAT:
625 global_settings.volume--;
626 setvol();
627 update_screen = true;
628 break;
629
630 case ACTION_FM_PLAY:
631 if (radio_status == FMRADIO_PLAYING)
632 radio_pause();
633 else
634 radio_start();
635
636 update_screen = true;
637 talk = false;
638 talk_shutup();
639 break;
640
641 case ACTION_FM_MENU:
642 fms_fix_displays(FMS_EXIT);
643 radio_menu();
644 set_current_preset(find_preset(curr_freq));
645 update_screen = true;
646 restore = true;
647 break;
648
649#ifdef FM_PRESET
650 case ACTION_FM_PRESET:
651 if(radio_preset_count() < 1)
652 {
653 splash(HZ, ID2P(LANG_FM_NO_PRESETS));
654 update_screen = true;
655 break;
656 }
657 fms_fix_displays(FMS_EXIT);
658 handle_radio_presets();
659 update_screen = true;
660 restore = true;
661 break;
662#endif /* FM_PRESET */
663
664#ifdef FM_FREEZE
665 case ACTION_FM_FREEZE:
666 if(!screen_freeze)
667 {
668 splash(HZ, str(LANG_FM_FREEZE));
669 screen_freeze = true;
670 }
671 else
672 {
673 update_screen = true;
674 screen_freeze = false;
675 }
676 break;
677#endif /* FM_FREEZE */
678
679 case SYS_USB_CONNECTED:
680#if CONFIG_CODEC != SWCODEC
681 /* Only accept USB connection when not recording */
682 if(audio_status() != AUDIO_STATUS_RECORD)
683#endif
684 {
685 default_event_handler(SYS_USB_CONNECTED);
686 screen_freeze = true; /* Cosmetic: makes sure the
687 radio screen doesn't redraw */
688 done = true;
689 }
690 break;
691
692#ifdef FM_MODE
693 case ACTION_FM_MODE:
694 if(radio_mode == RADIO_SCAN_MODE)
695 {
696 /* Force scan mode if there are no presets. */
697 if(radio_preset_count() > 0)
698 radio_mode = RADIO_PRESET_MODE;
699 }
700 else
701 radio_mode = RADIO_SCAN_MODE;
702 update_screen = true;
703 cond_talk_ids_fq(radio_mode ?
704 LANG_PRESET : LANG_RADIO_SCAN_MODE);
705 talk = true;
706 break;
707#endif /* FM_MODE */
708
709#ifdef FM_NEXT_PRESET
710 case ACTION_FM_NEXT_PRESET:
711 next_preset(1);
712 end_search();
713 update_screen = true;
714 talk = true;
715 break;
716#endif
717
718#ifdef FM_PREV_PRESET
719 case ACTION_FM_PREV_PRESET:
720 next_preset(-1);
721 end_search();
722 update_screen = true;
723 talk = true;
724 break;
725#endif
726
727 default:
728 default_event_handler(button);
729#ifdef HAVE_RDS_CAP
730 if (tuner_get(RADIO_EVENT))
731 update_screen = true;
732#endif
733 if (!tuner_get(RADIO_PRESENT))
734 {
735#if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
736 if(audio_status() == AUDIO_STATUS_RECORD)
737 audio_stop();
738#endif
739 keep_playing = false;
740 done = true;
741 ret_val = GO_TO_ROOT;
742 if(has_presets_changed())
743 {
744 if(yesno_pop(ID2P(LANG_FM_SAVE_CHANGES)))
745 {
746 radio_save_presets();
747 }
748 }
749
750 /* Clear the preset list on exit. */
751 clear_preset_list();
752 }
753 break;
754 } /*switch(button)*/
755
756#ifdef FM_RECORD_DBLPRE
757 if (button != ACTION_NONE)
758 lastbutton = button;
759#endif
760
761#if CONFIG_CODEC != SWCODEC
762 peak_meter_peek();
763#endif
764
765 if(!screen_freeze)
766 {
767 /* Only display the peak meter when not recording */
768#if CONFIG_CODEC != SWCODEC
769 if(TIME_AFTER(current_tick, timeout))
770 {
771 timeout = current_tick + HZ;
772#else /* SWCODEC */
773 {
774#endif /* CONFIG_CODEC == SWCODEC */
775
776 /* keep "mono" from always being displayed when paused */
777 if (radio_status != FMRADIO_PAUSED)
778 {
779 stereo = tuner_get(RADIO_STEREO) &&
780 !global_settings.fm_force_mono;
781
782 if(stereo != last_stereo)
783 {
784 update_screen = true;
785 last_stereo = stereo;
786 }
787 }
788 }
789
790#if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
791 seconds = audio_recorded_time() / HZ;
792 if (update_screen || seconds > last_seconds || restore)
793 {
794 last_seconds = seconds;
795#else
796 if (update_screen || restore)
797 {
798#endif
799 if (restore)
800 fms_fix_displays(FMS_ENTER);
801 FOR_NB_SCREENS(i)
802 skin_update(fms_get(i), WPS_REFRESH_ALL);
803 restore = false;
804 }
805 }
806 update_screen = false;
807
808 if (global_settings.talk_file && talk
809 && radio_status == FMRADIO_PAUSED)
810 {
811 talk = false;
812 bool enqueue = false;
813 if (radio_mode == RADIO_SCAN_MODE)
814 {
815 talk_freq(curr_freq, enqueue);
816 enqueue = true;
817 }
818 if (radio_current_preset() >= 0)
819 talk_preset(radio_current_preset(), radio_mode == RADIO_PRESET_MODE,
820 enqueue);
821 }
822
823#if CONFIG_CODEC != SWCODEC
824 if(audio_status() & AUDIO_STATUS_ERROR)
825 {
826 done = true;
827 }
828#endif
829
830#ifndef HAVE_NOISY_IDLE_MODE
831 if (TIME_AFTER(current_tick, button_timeout))
832 {
833 cpu_idle_mode(true);
834 }
835#endif
836 } /*while(!done)*/
837
838#ifndef SIMULATOR
839#if CONFIG_CODEC != SWCODEC
840 if(audio_status() & AUDIO_STATUS_ERROR)
841 {
842 splash(0, str(LANG_DISK_FULL));
843 audio_error_clear();
844
845 while(1)
846 {
847 button = get_action(CONTEXT_FM, TIMEOUT_BLOCK);
848 if(button == ACTION_FM_STOP)
849 break;
850 }
851 }
852
853 audio_init_playback();
854#endif /* CONFIG_CODEC != SWCODEC */
855
856 sound_settings_apply();
857#endif /* SIMULATOR */
858
859 if(keep_playing)
860 {
861/* Catch FMRADIO_PLAYING status for the sim. */
862#ifndef SIMULATOR
863#if CONFIG_CODEC != SWCODEC
864 /* Enable the Left and right A/D Converter */
865 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN),
866 sound_default(SOUND_RIGHT_GAIN),
867 AUDIO_GAIN_LINEIN);
868 mas_codec_writereg(6, 0x4000);
869#endif
870 end_search();
871#endif /* SIMULATOR */
872 }
873 else
874 {
875#if CONFIG_CODEC == SWCODEC
876 audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
877#else
878 radio_stop();
879#endif
880 }
881
882#ifndef HAVE_NOISY_IDLE_MODE
883 cpu_idle_mode(false);
884#endif
885 fms_fix_displays(FMS_EXIT);
886 in_screen = false;
887#if CONFIG_CODEC != SWCODEC
888 return have_recorded;
889#else
890 return false;
891#endif
892} /* radio_screen */
893
894void toggle_mono_mode(bool mono)
895{
896 tuner_set(RADIO_FORCE_MONO, mono);
897}
898
899void set_radio_region(int region)
900{
901#ifdef HAVE_RADIO_REGION
902 tuner_set(RADIO_REGION, region);
903#endif
904 next_station(0);
905 remember_frequency();
906 (void)region;
907}
908
909MENUITEM_SETTING(set_region, &global_settings.fm_region, NULL);
910MENUITEM_SETTING(force_mono, &global_settings.fm_force_mono, NULL);
911
912#ifndef FM_MODE
913static char* get_mode_text(int selected_item, void * data, char *buffer)
914{
915 (void)selected_item;
916 (void)data;
917 snprintf(buffer, MAX_PATH, "%s %s", str(LANG_MODE),
918 radio_mode ? str(LANG_PRESET) :
919 str(LANG_RADIO_SCAN_MODE));
920 return buffer;
921}
922static int toggle_radio_mode(void)
923{
924 radio_mode = (radio_mode == RADIO_SCAN_MODE) ?
925 RADIO_PRESET_MODE : RADIO_SCAN_MODE;
926 return 0;
927}
928MENUITEM_FUNCTION_DYNTEXT(radio_mode_item, 0,
929 toggle_radio_mode, NULL,
930 get_mode_text, NULL, NULL, NULL, Icon_NOICON);
931#endif
932
933
934
935#ifdef HAVE_RECORDING
936
937#if defined(HAVE_FMRADIO_REC) && CONFIG_CODEC == SWCODEC
938#define FM_RECORDING_SCREEN
939static int fm_recording_screen(void)
940{
941 bool ret;
942
943 /* switch recording source to FMRADIO for the duration */
944 int rec_source = global_settings.rec_source;
945 global_settings.rec_source = AUDIO_SRC_FMRADIO;
946 ret = recording_screen(true);
947
948 /* safe to reset as changing sources is prohibited here */
949 global_settings.rec_source = rec_source;
950
951 return ret;
952}
953
954#endif /* defined(HAVE_FMRADIO_REC) && CONFIG_CODEC == SWCODEC */
955
956#if defined(HAVE_FMRADIO_REC) || CONFIG_CODEC != SWCODEC
957#define FM_RECORDING_SETTINGS
958static int fm_recording_settings(void)
959{
960 bool ret = recording_menu(true);
961
962#if CONFIG_CODEC != SWCODEC
963 if (!ret)
964 {
965 struct audio_recording_options rec_options;
966 rec_init_recording_options(&rec_options);
967 rec_options.rec_source = AUDIO_SRC_LINEIN;
968 rec_set_recording_options(&rec_options);
969 }
970#endif
971
972 return ret;
973}
974
975#endif /* defined(HAVE_FMRADIO_REC) || CONFIG_CODEC != SWCODEC */
976#endif /* HAVE_RECORDING */
977
978#ifdef FM_RECORDING_SCREEN
979MENUITEM_FUNCTION(recscreen_item, 0, ID2P(LANG_RECORDING),
980 fm_recording_screen, NULL, NULL, Icon_Recording);
981#endif
982#ifdef FM_RECORDING_SETTINGS
983MENUITEM_FUNCTION(recsettings_item, 0, ID2P(LANG_RECORDING_SETTINGS),
984 fm_recording_settings, NULL, NULL, Icon_Recording);
985#endif
986#ifndef FM_PRESET
987int handle_radio_presets_menu(void)
988{
989 return handle_radio_presets();
990}
991MENUITEM_FUNCTION(radio_presets_item, 0, ID2P(LANG_PRESET),
992 handle_radio_presets_menu, NULL, NULL, Icon_NOICON);
993#endif
994#ifndef FM_PRESET_ADD
995int handle_radio_addpreset_menu(void)
996{
997 return radio_add_preset();
998}
999MENUITEM_FUNCTION(radio_addpreset_item, 0, ID2P(LANG_FM_ADD_PRESET),
1000 radio_add_preset, NULL, NULL, Icon_NOICON);
1001#endif
1002
1003
1004MENUITEM_FUNCTION(presetload_item, 0, ID2P(LANG_FM_PRESET_LOAD),
1005 load_preset_list, NULL, NULL, Icon_NOICON);
1006MENUITEM_FUNCTION(presetsave_item, 0, ID2P(LANG_FM_PRESET_SAVE),
1007 save_preset_list, NULL, NULL, Icon_NOICON);
1008MENUITEM_FUNCTION(presetclear_item, 0, ID2P(LANG_FM_PRESET_CLEAR),
1009 clear_preset_list, NULL, NULL, Icon_NOICON);
1010MENUITEM_FUNCTION(scan_presets_item, MENU_FUNC_USEPARAM,
1011 ID2P(LANG_FM_SCAN_PRESETS),
1012 scan_presets, NULL, NULL, Icon_NOICON);
1013
1014MAKE_MENU(radio_settings_menu, ID2P(LANG_FM_MENU), NULL,
1015 Icon_Radio_screen,
1016#ifndef FM_PRESET
1017 &radio_presets_item,
1018#endif
1019#ifndef FM_PRESET_ADD
1020 &radio_addpreset_item,
1021#endif
1022 &presetload_item, &presetsave_item, &presetclear_item,
1023 &force_mono,
1024#ifndef FM_MODE
1025 &radio_mode_item,
1026#endif
1027 &set_region, &sound_settings,
1028#ifdef FM_RECORDING_SCREEN
1029 &recscreen_item,
1030#endif
1031#ifdef FM_RECORDING_SETTINGS
1032 &recsettings_item,
1033#endif
1034 &scan_presets_item);
1035/* main menu of the radio screen */
1036static bool radio_menu(void)
1037{
1038 return do_menu(&radio_settings_menu, NULL, NULL, false) ==
1039 MENU_ATTACHED_USB;
1040}
1041
1042#endif