Merge branch 'master' into gsoc-ifdef-cleanup
[kugel-rb.git] / apps / radio / radio.c
blob3728afc39c0248c00de77b665c487e8402a0a1dd
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2003 Linus Nielsen Feltzing
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 ****************************************************************************/
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 #if CONFIG_CODEC == SWCODEC
74 #include "playback.h"
75 #endif
77 #if CONFIG_TUNER
79 #if CONFIG_KEYPAD == RECORDER_PAD
80 #define FM_RECORD
81 #define FM_PRESET_ADD
82 #define FM_PRESET_ACTION
83 #define FM_PRESET
84 #define FM_MODE
86 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
87 #define FM_PRESET
88 #define FM_MODE
89 #define FM_NEXT_PRESET
90 #define FM_PREV_PRESET
92 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
93 #define FM_PRESET
94 #define FM_MODE
96 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
97 #define FM_PRESET
98 #define FM_MODE
99 /* This should be removeable if the whole tuning thing is sorted out since
100 proper tuning quiets the screen almost entirely in that extreme measures
101 have to be taken to hear any interference. */
102 #define HAVE_NOISY_IDLE_MODE
104 #elif CONFIG_KEYPAD == ONDIO_PAD
105 #define FM_RECORD_DBLPRE
106 #define FM_RECORD
108 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || (CONFIG_KEYPAD == SANSA_C200_PAD) ||\
109 (CONFIG_KEYPAD == SANSA_FUZE_PAD) || (CONFIG_KEYPAD == SANSA_CLIP_PAD)
110 #define FM_MENU
111 #define FM_PRESET
112 #define FM_STOP
113 #define FM_MODE
114 #define FM_EXIT
115 #define FM_PLAY
117 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
118 #define FM_PRESET
119 #define FM_MODE
121 #elif (CONFIG_KEYPAD == COWON_D2_PAD)
122 #define FM_MENU
123 #define FM_PRESET
124 #define FM_STOP
125 #define FM_MODE
126 #define FM_EXIT
127 #define FM_PLAY
129 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
130 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
131 #define FM_MENU
132 #define FM_STOP
133 #define FM_EXIT
134 #define FM_PLAY
135 #define FM_MODE
137 #endif
139 /* presets.c needs these so keep unstatic or redo the whole thing! */
140 int curr_freq; /* current frequency in Hz */
141 /* these are all in presets.c... someone PLEASE rework this ! */
142 int handle_radio_presets(void);
143 static bool radio_menu(void);
144 int radio_add_preset(void);
145 int save_preset_list(void);
146 int load_preset_list(void);
147 int clear_preset_list(void);
148 void next_preset(int direction);
149 void set_current_preset(int preset);
150 int scan_presets(void *viewports);
151 int find_preset(int freq);
152 void radio_save_presets(void);
153 bool has_presets_changed(void);
154 void talk_preset(int preset, bool fallback, bool enqueue);
155 void presets_save(void);
159 int radio_mode = RADIO_SCAN_MODE;
160 static int search_dir = 0;
162 static int radio_status = FMRADIO_OFF;
163 static bool in_screen = false;
166 static void radio_off(void);
168 bool radio_scan_mode(void)
170 return radio_mode == RADIO_SCAN_MODE;
173 bool radio_is_stereo(void)
175 return tuner_get(RADIO_STEREO) && !global_settings.fm_force_mono;
177 int radio_current_frequency(void)
179 return curr_freq;
182 /* Function to manipulate all yesno dialogues.
183 This function needs the output text as an argument. */
184 bool yesno_pop(const char* text)
186 int i;
187 const char *lines[]={text};
188 const struct text_message message={lines, 1};
189 bool ret = (gui_syncyesno_run(&message,NULL,NULL)== YESNO_YES);
190 FOR_NB_SCREENS(i)
191 screens[i].clear_viewport();
192 return ret;
195 void radio_init(void)
197 tuner_init();
198 radio_off();
199 #ifdef HAVE_ALBUMART
200 radioart_init(false);
201 #endif
204 int get_radio_status(void)
206 return radio_status;
209 bool in_radio_screen(void)
211 return in_screen;
214 /* TODO: Move some more of the control functionality to firmware
215 and clean up the mess */
217 /* secret flag for starting paused - prevents unmute */
218 #define FMRADIO_START_PAUSED 0x8000
219 void radio_start(void)
221 const struct fm_region_data *fmr;
222 bool start_paused;
224 if(radio_status == FMRADIO_PLAYING)
225 return;
227 fmr = &fm_region_data[global_settings.fm_region];
229 start_paused = radio_status & FMRADIO_START_PAUSED;
230 /* clear flag before any yielding */
231 radio_status &= ~FMRADIO_START_PAUSED;
233 if(radio_status == FMRADIO_OFF)
234 tuner_power(true);
236 curr_freq = global_status.last_frequency * fmr->freq_step + fmr->freq_min;
238 tuner_set(RADIO_SLEEP, 0); /* wake up the tuner */
240 if(radio_status == FMRADIO_OFF)
242 #ifdef HAVE_RADIO_REGION
243 tuner_set(RADIO_REGION, global_settings.fm_region);
244 #endif
245 tuner_set(RADIO_FORCE_MONO, global_settings.fm_force_mono);
248 tuner_set(RADIO_FREQUENCY, curr_freq);
250 #ifdef HAVE_RADIO_MUTE_TIMEOUT
252 unsigned long mute_timeout = current_tick + HZ;
253 if (radio_status != FMRADIO_OFF)
255 /* paused */
256 mute_timeout += HZ;
259 while(!tuner_get(RADIO_STEREO) && !tuner_get(RADIO_TUNED))
261 if(TIME_AFTER(current_tick, mute_timeout))
262 break;
263 yield();
266 #endif
268 /* keep radio from sounding initially */
269 if(!start_paused)
270 tuner_set(RADIO_MUTE, 0);
272 radio_status = FMRADIO_PLAYING;
273 } /* radio_start */
275 void radio_pause(void)
277 if(radio_status == FMRADIO_PAUSED)
278 return;
280 if(radio_status == FMRADIO_OFF)
282 radio_status |= FMRADIO_START_PAUSED;
283 radio_start();
286 tuner_set(RADIO_MUTE, 1);
287 /* For si4700: 2==this is really 'pause'. other tuners treat it
288 * like 'bool'. */
289 tuner_set(RADIO_SLEEP, 2);
291 radio_status = FMRADIO_PAUSED;
292 } /* radio_pause */
294 static void radio_off(void)
296 tuner_set(RADIO_MUTE, 1);
297 tuner_set(RADIO_SLEEP, 1); /* low power mode, if available */
298 radio_status = FMRADIO_OFF;
299 tuner_power(false); /* status update, power off if avail. */
302 void radio_stop(void)
304 if(radio_status == FMRADIO_OFF)
305 return;
307 radio_off();
308 } /* radio_stop */
310 bool radio_hardware_present(void)
312 return tuner_get(RADIO_PRESENT);
315 /* Keep freq on the grid for the current region */
316 int snap_freq_to_grid(int freq)
318 const struct fm_region_data * const fmr =
319 &fm_region_data[global_settings.fm_region];
321 /* Range clamp if out of range or just round to nearest */
322 if (freq < fmr->freq_min)
323 freq = fmr->freq_min;
324 else if (freq > fmr->freq_max)
325 freq = fmr->freq_max;
326 else
327 freq = (freq - fmr->freq_min + fmr->freq_step/2) /
328 fmr->freq_step * fmr->freq_step + fmr->freq_min;
330 return freq;
333 void remember_frequency(void)
335 const struct fm_region_data * const fmr =
336 &fm_region_data[global_settings.fm_region];
337 global_status.last_frequency = (curr_freq - fmr->freq_min)
338 / fmr->freq_step;
339 status_save();
342 /* Step to the next or previous frequency */
343 static int step_freq(int freq, int direction)
345 const struct fm_region_data * const fmr =
346 &fm_region_data[global_settings.fm_region];
348 freq += direction*fmr->freq_step;
350 /* Wrap first or snapping to grid will not let us on the band extremes */
351 if (freq > fmr->freq_max)
352 freq = direction > 0 ? fmr->freq_min : fmr->freq_max;
353 else if (freq < fmr->freq_min)
354 freq = direction < 0 ? fmr->freq_max : fmr->freq_min;
355 else
356 freq = snap_freq_to_grid(freq);
358 return freq;
361 /* Step to the next or previous station */
362 void next_station(int direction)
364 if (direction != 0 && radio_mode != RADIO_SCAN_MODE)
366 next_preset(direction);
367 return;
370 curr_freq = step_freq(curr_freq, direction);
372 if (radio_status == FMRADIO_PLAYING)
373 tuner_set(RADIO_MUTE, 1);
375 tuner_set(RADIO_FREQUENCY, curr_freq);
377 if (radio_status == FMRADIO_PLAYING)
378 tuner_set(RADIO_MUTE, 0);
380 set_current_preset(find_preset(curr_freq));
381 remember_frequency();
384 /* Ends an in-progress search */
385 static void end_search(void)
387 if (search_dir != 0 && radio_status == FMRADIO_PLAYING)
388 tuner_set(RADIO_MUTE, 0);
389 search_dir = 0;
392 /* Speak a frequency. */
393 void talk_freq(int freq, bool enqueue)
395 freq /= 10000;
396 talk_number(freq / 100, enqueue);
397 talk_id(LANG_POINT, true);
398 talk_number(freq % 100 / 10, true);
399 if (freq % 10)
400 talk_number(freq % 10, true);
404 int radio_screen(void)
406 bool done = false;
407 int ret_val = GO_TO_ROOT;
408 int button;
409 int i;
410 bool stereo = false, last_stereo = false;
411 bool update_screen = true, restore = true;
412 bool screen_freeze = false;
413 bool keep_playing = false;
414 bool talk = false;
415 #ifdef FM_RECORD_DBLPRE
416 int lastbutton = BUTTON_NONE;
417 unsigned long rec_lastclick = 0;
418 #endif
419 #if CONFIG_CODEC != SWCODEC
420 bool have_recorded = false;
421 int timeout = current_tick + HZ/10;
422 unsigned int last_seconds = 0;
423 #if !defined(SIMULATOR)
424 unsigned int seconds = 0;
425 struct audio_recording_options rec_options;
426 #endif /* SIMULATOR */
427 #endif /* CONFIG_CODEC != SWCODEC */
428 #ifndef HAVE_NOISY_IDLE_MODE
429 int button_timeout = current_tick + (2*HZ);
430 #endif
432 /* change status to "in screen" */
433 in_screen = true;
435 if(radio_preset_count() <= 0)
437 radio_load_presets(global_settings.fmr_file);
439 #ifdef HAVE_ALBUMART
440 radioart_init(true);
441 #endif
443 if(radio_status == FMRADIO_OFF)
444 audio_stop();
446 #ifndef SIMULATOR
448 #if CONFIG_CODEC != SWCODEC
449 if(rec_create_directory() > 0)
450 have_recorded = true;
452 audio_init_recording(talk_get_bufsize());
454 sound_settings_apply();
455 /* Yes, we use the D/A for monitoring */
456 peak_meter_playback(true);
458 peak_meter_enable(true);
460 rec_init_recording_options(&rec_options);
461 rec_options.rec_source = AUDIO_SRC_LINEIN;
462 rec_set_recording_options(&rec_options);
464 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN),
465 sound_default(SOUND_RIGHT_GAIN), AUDIO_GAIN_LINEIN);
467 #endif /* CONFIG_CODEC != SWCODEC */
468 #endif /* ndef SIMULATOR */
470 /* turn on radio */
471 #if CONFIG_CODEC == SWCODEC
472 /* This should be done before touching audio settings */
473 while (!audio_is_thread_ready())
474 sleep(0);
476 audio_set_input_source(AUDIO_SRC_FMRADIO,
477 (radio_status == FMRADIO_PAUSED) ?
478 SRCF_FMRADIO_PAUSED : SRCF_FMRADIO_PLAYING);
479 #else
480 if (radio_status == FMRADIO_OFF)
481 radio_start();
482 #endif
484 if(radio_preset_count() < 1 && yesno_pop(ID2P(LANG_FM_FIRST_AUTOSCAN)))
485 scan_presets(NULL);
487 set_current_preset(find_preset(curr_freq));
488 if(radio_current_preset() != -1)
489 radio_mode = RADIO_PRESET_MODE;
491 #ifndef HAVE_NOISY_IDLE_MODE
492 cpu_idle_mode(true);
493 #endif
495 while(!done)
497 if(search_dir != 0)
499 curr_freq = step_freq(curr_freq, search_dir);
500 update_screen = true;
502 if(tuner_set(RADIO_SCAN_FREQUENCY, curr_freq))
504 set_current_preset(find_preset(curr_freq));
505 remember_frequency();
506 end_search();
507 talk = true;
509 trigger_cpu_boost();
512 if (!update_screen)
514 cancel_cpu_boost();
517 button = fms_do_button_loop(update_screen);
519 #ifndef HAVE_NOISY_IDLE_MODE
520 if (button != ACTION_NONE)
522 cpu_idle_mode(false);
523 button_timeout = current_tick + (2*HZ);
525 #endif
526 switch(button)
528 case ACTION_FM_STOP:
529 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
530 if(audio_status() == AUDIO_STATUS_RECORD)
532 audio_stop();
534 else
535 #endif
537 done = true;
538 if(has_presets_changed())
540 if(yesno_pop(ID2P(LANG_FM_SAVE_CHANGES)))
542 presets_save();
546 update_screen = true;
547 break;
549 #ifdef FM_RECORD
550 case ACTION_FM_RECORD:
551 #ifdef FM_RECORD_DBLPRE
552 if (lastbutton != ACTION_FM_RECORD_DBLPRE)
554 rec_lastclick = 0;
555 break;
557 if (current_tick - rec_lastclick > HZ/2)
559 rec_lastclick = current_tick;
560 break;
562 #endif /* FM_RECORD_DBLPRE */
563 #ifndef SIMULATOR
564 if(audio_status() == AUDIO_STATUS_RECORD)
566 rec_command(RECORDING_CMD_START_NEWFILE);
567 update_screen = true;
569 else
571 have_recorded = true;
572 rec_command(RECORDING_CMD_START);
573 update_screen = true;
575 #endif /* SIMULATOR */
576 last_seconds = 0;
577 break;
578 #endif /* #ifdef FM_RECORD */
580 case ACTION_FM_EXIT:
581 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
582 if(audio_status() == AUDIO_STATUS_RECORD)
583 audio_stop();
584 #endif
585 keep_playing = true;
586 done = true;
587 ret_val = GO_TO_ROOT;
588 if(has_presets_changed())
590 if(yesno_pop(ID2P(LANG_FM_SAVE_CHANGES)))
592 presets_save();
596 break;
598 case ACTION_STD_PREV:
599 case ACTION_STD_NEXT:
600 next_station(button == ACTION_STD_PREV ? -1 : 1);
601 end_search();
602 update_screen = true;
603 talk = true;
604 break;
606 case ACTION_STD_PREVREPEAT:
607 case ACTION_STD_NEXTREPEAT:
609 int dir = search_dir;
610 search_dir = button == ACTION_STD_PREVREPEAT ? -1 : 1;
611 if (radio_mode != RADIO_SCAN_MODE)
613 next_preset(search_dir);
614 end_search();
615 update_screen = true;
616 talk = true;
618 else if (dir == 0)
620 /* Starting auto scan */
621 tuner_set(RADIO_MUTE, 1);
622 update_screen = true;
624 break;
627 case ACTION_SETTINGS_INC:
628 case ACTION_SETTINGS_INCREPEAT:
629 global_settings.volume++;
630 setvol();
631 update_screen = true;
632 break;
634 case ACTION_SETTINGS_DEC:
635 case ACTION_SETTINGS_DECREPEAT:
636 global_settings.volume--;
637 setvol();
638 update_screen = true;
639 break;
641 case ACTION_FM_PLAY:
642 if (radio_status == FMRADIO_PLAYING)
643 radio_pause();
644 else
645 radio_start();
647 update_screen = true;
648 talk = false;
649 talk_shutup();
650 break;
652 case ACTION_FM_MENU:
653 fms_fix_displays(FMS_EXIT);
654 radio_menu();
655 set_current_preset(find_preset(curr_freq));
656 update_screen = true;
657 restore = true;
658 break;
660 #ifdef FM_PRESET
661 case ACTION_FM_PRESET:
662 if(radio_preset_count() < 1)
664 splash(HZ, ID2P(LANG_FM_NO_PRESETS));
665 update_screen = true;
666 break;
668 fms_fix_displays(FMS_EXIT);
669 handle_radio_presets();
670 update_screen = true;
671 restore = true;
672 break;
673 #endif /* FM_PRESET */
675 #ifdef FM_FREEZE
676 case ACTION_FM_FREEZE:
677 if(!screen_freeze)
679 splash(HZ, str(LANG_FM_FREEZE));
680 screen_freeze = true;
682 else
684 update_screen = true;
685 screen_freeze = false;
687 break;
688 #endif /* FM_FREEZE */
690 case SYS_USB_CONNECTED:
691 #if CONFIG_CODEC != SWCODEC
692 /* Only accept USB connection when not recording */
693 if(audio_status() != AUDIO_STATUS_RECORD)
694 #endif
696 default_event_handler(SYS_USB_CONNECTED);
697 screen_freeze = true; /* Cosmetic: makes sure the
698 radio screen doesn't redraw */
699 done = true;
701 break;
703 #ifdef FM_MODE
704 case ACTION_FM_MODE:
705 if(radio_mode == RADIO_SCAN_MODE)
707 /* Force scan mode if there are no presets. */
708 if(radio_preset_count() > 0)
709 radio_mode = RADIO_PRESET_MODE;
711 else
712 radio_mode = RADIO_SCAN_MODE;
713 update_screen = true;
714 cond_talk_ids_fq(radio_mode ?
715 LANG_PRESET : LANG_RADIO_SCAN_MODE);
716 talk = true;
717 break;
718 #endif /* FM_MODE */
720 #ifdef FM_NEXT_PRESET
721 case ACTION_FM_NEXT_PRESET:
722 next_preset(1);
723 end_search();
724 update_screen = true;
725 talk = true;
726 break;
727 #endif
729 #ifdef FM_PREV_PRESET
730 case ACTION_FM_PREV_PRESET:
731 next_preset(-1);
732 end_search();
733 update_screen = true;
734 talk = true;
735 break;
736 #endif
738 default:
739 default_event_handler(button);
740 #ifdef HAVE_RDS_CAP
741 if (tuner_get(RADIO_EVENT))
742 update_screen = true;
743 #endif
744 if (!tuner_get(RADIO_PRESENT))
746 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
747 if(audio_status() == AUDIO_STATUS_RECORD)
748 audio_stop();
749 #endif
750 keep_playing = false;
751 done = true;
752 ret_val = GO_TO_ROOT;
753 if(has_presets_changed())
755 if(yesno_pop(ID2P(LANG_FM_SAVE_CHANGES)))
757 radio_save_presets();
761 /* Clear the preset list on exit. */
762 clear_preset_list();
764 break;
765 } /*switch(button)*/
767 #ifdef FM_RECORD_DBLPRE
768 if (button != ACTION_NONE)
769 lastbutton = button;
770 #endif
772 #if CONFIG_CODEC != SWCODEC
773 peak_meter_peek();
774 #endif
776 if(!screen_freeze)
778 /* Only display the peak meter when not recording */
779 #if CONFIG_CODEC != SWCODEC
780 if(TIME_AFTER(current_tick, timeout))
782 timeout = current_tick + HZ;
783 #else /* SWCODEC */
785 #endif /* CONFIG_CODEC == SWCODEC */
787 /* keep "mono" from always being displayed when paused */
788 if (radio_status != FMRADIO_PAUSED)
790 stereo = tuner_get(RADIO_STEREO) &&
791 !global_settings.fm_force_mono;
793 if(stereo != last_stereo)
795 update_screen = true;
796 last_stereo = stereo;
801 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
802 seconds = audio_recorded_time() / HZ;
803 if (update_screen || seconds > last_seconds || restore)
805 last_seconds = seconds;
806 #else
807 if (update_screen || restore)
809 #endif
810 if (restore)
811 fms_fix_displays(FMS_ENTER);
812 FOR_NB_SCREENS(i)
813 skin_update(fms_get(i), WPS_REFRESH_ALL);
814 restore = false;
817 update_screen = false;
819 if (global_settings.talk_file && talk
820 && radio_status == FMRADIO_PAUSED)
822 talk = false;
823 bool enqueue = false;
824 if (radio_mode == RADIO_SCAN_MODE)
826 talk_freq(curr_freq, enqueue);
827 enqueue = true;
829 if (radio_current_preset() >= 0)
830 talk_preset(radio_current_preset(), radio_mode == RADIO_PRESET_MODE,
831 enqueue);
834 #if CONFIG_CODEC != SWCODEC
835 if(audio_status() & AUDIO_STATUS_ERROR)
837 done = true;
839 #endif
841 #ifndef HAVE_NOISY_IDLE_MODE
842 if (TIME_AFTER(current_tick, button_timeout))
844 cpu_idle_mode(true);
846 #endif
847 } /*while(!done)*/
849 #ifndef SIMULATOR
850 #if CONFIG_CODEC != SWCODEC
851 if(audio_status() & AUDIO_STATUS_ERROR)
853 splash(0, str(LANG_DISK_FULL));
854 audio_error_clear();
856 while(1)
858 button = get_action(CONTEXT_FM, TIMEOUT_BLOCK);
859 if(button == ACTION_FM_STOP)
860 break;
864 audio_init_playback();
865 #endif /* CONFIG_CODEC != SWCODEC */
867 sound_settings_apply();
868 #endif /* SIMULATOR */
870 if(keep_playing)
872 /* Catch FMRADIO_PLAYING status for the sim. */
873 #ifndef SIMULATOR
874 #if CONFIG_CODEC != SWCODEC
875 /* Enable the Left and right A/D Converter */
876 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN),
877 sound_default(SOUND_RIGHT_GAIN),
878 AUDIO_GAIN_LINEIN);
879 mas_codec_writereg(6, 0x4000);
880 #endif
881 end_search();
882 #endif /* SIMULATOR */
884 else
886 #if CONFIG_CODEC == SWCODEC
887 audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
888 #else
889 radio_stop();
890 #endif
893 #ifndef HAVE_NOISY_IDLE_MODE
894 cpu_idle_mode(false);
895 #endif
896 fms_fix_displays(FMS_EXIT);
897 in_screen = false;
898 #if CONFIG_CODEC != SWCODEC
899 return have_recorded;
900 #else
901 return false;
902 #endif
903 } /* radio_screen */
905 void toggle_mono_mode(bool mono)
907 tuner_set(RADIO_FORCE_MONO, mono);
910 void set_radio_region(int region)
912 #ifdef HAVE_RADIO_REGION
913 tuner_set(RADIO_REGION, region);
914 #endif
915 next_station(0);
916 remember_frequency();
917 (void)region;
920 MENUITEM_SETTING(set_region, &global_settings.fm_region, NULL);
921 MENUITEM_SETTING(force_mono, &global_settings.fm_force_mono, NULL);
923 #ifndef FM_MODE
924 static char* get_mode_text(int selected_item, void * data, char *buffer)
926 (void)selected_item;
927 (void)data;
928 snprintf(buffer, MAX_PATH, "%s %s", str(LANG_MODE),
929 radio_mode ? str(LANG_PRESET) :
930 str(LANG_RADIO_SCAN_MODE));
931 return buffer;
933 static int toggle_radio_mode(void)
935 radio_mode = (radio_mode == RADIO_SCAN_MODE) ?
936 RADIO_PRESET_MODE : RADIO_SCAN_MODE;
937 return 0;
939 MENUITEM_FUNCTION_DYNTEXT(radio_mode_item, 0,
940 toggle_radio_mode, NULL,
941 get_mode_text, NULL, NULL, NULL, Icon_NOICON);
942 #endif
946 #ifdef HAVE_RECORDING
948 #if defined(HAVE_FMRADIO_REC) && CONFIG_CODEC == SWCODEC
949 #define FM_RECORDING_SCREEN
950 static int fm_recording_screen(void)
952 bool ret;
954 /* switch recording source to FMRADIO for the duration */
955 int rec_source = global_settings.rec_source;
956 global_settings.rec_source = AUDIO_SRC_FMRADIO;
957 ret = recording_screen(true);
959 /* safe to reset as changing sources is prohibited here */
960 global_settings.rec_source = rec_source;
962 return ret;
965 #endif /* defined(HAVE_FMRADIO_REC) && CONFIG_CODEC == SWCODEC */
967 #if defined(HAVE_FMRADIO_REC) || CONFIG_CODEC != SWCODEC
968 #define FM_RECORDING_SETTINGS
969 static int fm_recording_settings(void)
971 bool ret = recording_menu(true);
973 #if CONFIG_CODEC != SWCODEC
974 if (!ret)
976 struct audio_recording_options rec_options;
977 rec_init_recording_options(&rec_options);
978 rec_options.rec_source = AUDIO_SRC_LINEIN;
979 rec_set_recording_options(&rec_options);
981 #endif
983 return ret;
986 #endif /* defined(HAVE_FMRADIO_REC) || CONFIG_CODEC != SWCODEC */
987 #endif /* HAVE_RECORDING */
989 #ifdef FM_RECORDING_SCREEN
990 MENUITEM_FUNCTION(recscreen_item, 0, ID2P(LANG_RECORDING),
991 fm_recording_screen, NULL, NULL, Icon_Recording);
992 #endif
993 #ifdef FM_RECORDING_SETTINGS
994 MENUITEM_FUNCTION(recsettings_item, 0, ID2P(LANG_RECORDING_SETTINGS),
995 fm_recording_settings, NULL, NULL, Icon_Recording);
996 #endif
997 #ifndef FM_PRESET
998 int handle_radio_presets_menu(void)
1000 return handle_radio_presets();
1002 MENUITEM_FUNCTION(radio_presets_item, 0, ID2P(LANG_PRESET),
1003 handle_radio_presets_menu, NULL, NULL, Icon_NOICON);
1004 #endif
1005 #ifndef FM_PRESET_ADD
1006 int handle_radio_addpreset_menu(void)
1008 return radio_add_preset();
1010 MENUITEM_FUNCTION(radio_addpreset_item, 0, ID2P(LANG_FM_ADD_PRESET),
1011 radio_add_preset, NULL, NULL, Icon_NOICON);
1012 #endif
1015 MENUITEM_FUNCTION(presetload_item, 0, ID2P(LANG_FM_PRESET_LOAD),
1016 load_preset_list, NULL, NULL, Icon_NOICON);
1017 MENUITEM_FUNCTION(presetsave_item, 0, ID2P(LANG_FM_PRESET_SAVE),
1018 save_preset_list, NULL, NULL, Icon_NOICON);
1019 MENUITEM_FUNCTION(presetclear_item, 0, ID2P(LANG_FM_PRESET_CLEAR),
1020 clear_preset_list, NULL, NULL, Icon_NOICON);
1021 MENUITEM_FUNCTION(scan_presets_item, MENU_FUNC_USEPARAM,
1022 ID2P(LANG_FM_SCAN_PRESETS),
1023 scan_presets, NULL, NULL, Icon_NOICON);
1025 MAKE_MENU(radio_settings_menu, ID2P(LANG_FM_MENU), NULL,
1026 Icon_Radio_screen,
1027 #ifndef FM_PRESET
1028 &radio_presets_item,
1029 #endif
1030 #ifndef FM_PRESET_ADD
1031 &radio_addpreset_item,
1032 #endif
1033 &presetload_item, &presetsave_item, &presetclear_item,
1034 &force_mono,
1035 #ifndef FM_MODE
1036 &radio_mode_item,
1037 #endif
1038 &set_region, &sound_settings,
1039 #ifdef FM_RECORDING_SCREEN
1040 &recscreen_item,
1041 #endif
1042 #ifdef FM_RECORDING_SETTINGS
1043 &recsettings_item,
1044 #endif
1045 &scan_presets_item);
1046 /* main menu of the radio screen */
1047 static bool radio_menu(void)
1049 return do_menu(&radio_settings_menu, NULL, NULL, false) ==
1050 MENU_ATTACHED_USB;
1053 #endif