Revert 1207c7b and fix the actual warnings.
[maemo-rb.git] / apps / radio / radio.c
blob9f139f49a6f5a2670e7166646a1e9072b7562fd2
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 <stdio.h>
23 #include <stdbool.h>
24 #include <stdlib.h>
25 #include "config.h"
26 #include "system.h"
27 #include "settings.h"
28 #include "status.h"
29 #include "audio.h"
30 #include "general.h"
31 #include "radio.h"
32 #include "menu.h"
33 #include "menus/exported_menus.h"
34 #include "misc.h"
35 #include "screens.h"
36 #include "peakmeter.h"
37 #include "lang.h"
38 #ifdef HAVE_RECORDING
39 #include "recording.h"
40 #endif
41 #ifdef IPOD_ACCESSORY_PROTOCOL
42 #include "iap.h"
43 #endif
44 #include "talk.h"
45 #include "tuner.h"
46 #include "power.h"
47 #include "sound.h"
48 #include "screen_access.h"
49 #include "splash.h"
50 #include "yesno.h"
51 #include "tree.h"
52 #include "dir.h"
53 #include "action.h"
54 #include "viewport.h"
55 #include "skin_engine/skin_engine.h"
56 #include "statusbar-skinned.h"
57 #if CONFIG_CODEC == SWCODEC
58 #include "playback.h"
59 #endif
60 #include "presets.h"
62 #if CONFIG_TUNER
64 #if CONFIG_KEYPAD == RECORDER_PAD
65 #define FM_RECORD
66 #define FM_PRESET_ADD
67 #define FM_PRESET_ACTION
68 #define FM_PRESET
69 #define FM_MODE
71 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
72 #define FM_PRESET
73 #define FM_MODE
74 #define FM_NEXT_PRESET
75 #define FM_PREV_PRESET
77 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
78 #define FM_PRESET
79 #define FM_MODE
81 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
82 #define FM_PRESET
83 #define FM_MODE
84 /* This should be removeable if the whole tuning thing is sorted out since
85 proper tuning quiets the screen almost entirely in that extreme measures
86 have to be taken to hear any interference. */
87 #define HAVE_NOISY_IDLE_MODE
89 #elif CONFIG_KEYPAD == ONDIO_PAD
90 #define FM_RECORD_DBLPRE
91 #define FM_RECORD
93 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || (CONFIG_KEYPAD == SANSA_C200_PAD) ||\
94 (CONFIG_KEYPAD == SANSA_FUZE_PAD) || (CONFIG_KEYPAD == SANSA_CLIP_PAD)
95 #define FM_MENU
96 #define FM_PRESET
97 #define FM_STOP
98 #define FM_MODE
99 #define FM_EXIT
100 #define FM_PLAY
102 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
103 #define FM_PRESET
104 #define FM_MODE
106 #elif (CONFIG_KEYPAD == COWON_D2_PAD)
107 #define FM_MENU
108 #define FM_PRESET
109 #define FM_STOP
110 #define FM_MODE
111 #define FM_EXIT
112 #define FM_PLAY
114 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
115 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
116 #define FM_MENU
117 #define FM_STOP
118 #define FM_EXIT
119 #define FM_PLAY
120 #define FM_MODE
122 #elif (CONFIG_KEYPAD == MPIO_HD200_PAD)
123 #define FM_MENU
124 #define FM_STOP
125 #define FM_EXIT
126 #define FM_PLAY
127 #define FM_MODE
128 #define FM_STOP
130 #endif
132 /* presets.c needs these so keep unstatic or redo the whole thing! */
133 int curr_freq; /* current frequency in Hz */
134 int radio_mode = RADIO_SCAN_MODE;
136 static int search_dir = 0;
137 static int radio_status = FMRADIO_OFF;
138 static bool in_screen = false;
141 static void radio_off(void);
143 bool radio_scan_mode(void)
145 return radio_mode == RADIO_SCAN_MODE;
148 bool radio_is_stereo(void)
150 return tuner_get(RADIO_STEREO) && !global_settings.fm_force_mono;
152 int radio_current_frequency(void)
154 return curr_freq;
157 void radio_init(void)
159 tuner_init();
160 radio_off();
161 #ifdef HAVE_ALBUMART
162 radioart_init(false);
163 #endif
166 int get_radio_status(void)
168 return radio_status;
171 bool in_radio_screen(void)
173 return in_screen;
176 /* TODO: Move some more of the control functionality to firmware
177 and clean up the mess */
179 /* secret flag for starting paused - prevents unmute */
180 #define FMRADIO_START_PAUSED 0x8000
181 void radio_start(void)
183 const struct fm_region_data *fmr;
184 bool start_paused;
186 if(radio_status == FMRADIO_PLAYING)
187 return;
189 fmr = &fm_region_data[global_settings.fm_region];
191 start_paused = radio_status & FMRADIO_START_PAUSED;
192 /* clear flag before any yielding */
193 radio_status &= ~FMRADIO_START_PAUSED;
195 curr_freq = global_status.last_frequency * fmr->freq_step + fmr->freq_min;
197 tuner_set(RADIO_SLEEP, 0); /* wake up the tuner */
199 if(radio_status == FMRADIO_OFF)
201 #ifdef HAVE_RADIO_REGION
202 tuner_set(RADIO_REGION, global_settings.fm_region);
203 #endif
204 tuner_set(RADIO_FORCE_MONO, global_settings.fm_force_mono);
207 tuner_set(RADIO_FREQUENCY, curr_freq);
209 #ifdef HAVE_RADIO_MUTE_TIMEOUT
211 unsigned long mute_timeout = current_tick + HZ;
212 if (radio_status != FMRADIO_OFF)
214 /* paused */
215 mute_timeout += HZ;
218 while(!tuner_get(RADIO_STEREO) && !tuner_get(RADIO_TUNED))
220 if(TIME_AFTER(current_tick, mute_timeout))
221 break;
222 yield();
225 #endif
227 /* keep radio from sounding initially */
228 if(!start_paused)
229 tuner_set(RADIO_MUTE, 0);
231 radio_status = FMRADIO_PLAYING;
232 } /* radio_start */
234 void radio_pause(void)
236 if(radio_status == FMRADIO_PAUSED)
237 return;
239 if(radio_status == FMRADIO_OFF)
241 radio_status |= FMRADIO_START_PAUSED;
242 radio_start();
245 tuner_set(RADIO_MUTE, 1);
247 radio_status = FMRADIO_PAUSED;
248 } /* radio_pause */
250 static void radio_off(void)
252 tuner_set(RADIO_MUTE, 1);
253 tuner_set(RADIO_SLEEP, 1); /* low power mode, if available */
254 radio_status = FMRADIO_OFF;
257 void radio_stop(void)
259 if(radio_status == FMRADIO_OFF)
260 return;
262 radio_off();
263 } /* radio_stop */
265 bool radio_hardware_present(void)
267 return tuner_get(RADIO_PRESENT);
270 /* Keep freq on the grid for the current region */
271 int snap_freq_to_grid(int freq)
273 const struct fm_region_data * const fmr =
274 &fm_region_data[global_settings.fm_region];
276 /* Range clamp if out of range or just round to nearest */
277 if (freq < fmr->freq_min)
278 freq = fmr->freq_min;
279 else if (freq > fmr->freq_max)
280 freq = fmr->freq_max;
281 else
282 freq = (freq - fmr->freq_min + fmr->freq_step/2) /
283 fmr->freq_step * fmr->freq_step + fmr->freq_min;
285 return freq;
288 void remember_frequency(void)
290 const struct fm_region_data * const fmr =
291 &fm_region_data[global_settings.fm_region];
292 global_status.last_frequency = (curr_freq - fmr->freq_min)
293 / fmr->freq_step;
294 status_save();
297 /* Step to the next or previous frequency */
298 static int step_freq(int freq, int direction)
300 const struct fm_region_data * const fmr =
301 &fm_region_data[global_settings.fm_region];
303 freq += direction*fmr->freq_step;
305 /* Wrap first or snapping to grid will not let us on the band extremes */
306 if (freq > fmr->freq_max)
307 freq = direction > 0 ? fmr->freq_min : fmr->freq_max;
308 else if (freq < fmr->freq_min)
309 freq = direction < 0 ? fmr->freq_max : fmr->freq_min;
310 else
311 freq = snap_freq_to_grid(freq);
313 return freq;
316 /* Step to the next or previous station */
317 void next_station(int direction)
319 if (direction != 0 && radio_mode != RADIO_SCAN_MODE)
321 preset_next(direction);
322 return;
325 curr_freq = step_freq(curr_freq, direction);
327 if (radio_status == FMRADIO_PLAYING)
328 tuner_set(RADIO_MUTE, 1);
330 tuner_set(RADIO_FREQUENCY, curr_freq);
332 if (radio_status == FMRADIO_PLAYING)
333 tuner_set(RADIO_MUTE, 0);
335 preset_set_current(preset_find(curr_freq));
336 remember_frequency();
339 /* Ends an in-progress search */
340 static void end_search(void)
342 if (search_dir != 0 && radio_status == FMRADIO_PLAYING)
343 tuner_set(RADIO_MUTE, 0);
344 search_dir = 0;
347 void radio_screen(void)
349 bool done = false;
350 int button;
351 bool stereo = false, last_stereo = false;
352 int update_type = 0;
353 bool screen_freeze = false;
354 bool keep_playing = false;
355 bool talk = false;
356 #ifdef FM_RECORD_DBLPRE
357 int lastbutton = BUTTON_NONE;
358 unsigned long rec_lastclick = 0;
359 #endif
360 #if CONFIG_CODEC != SWCODEC
361 int timeout = current_tick + HZ/10;
362 #if !defined(SIMULATOR)
363 unsigned int last_seconds = 0;
364 unsigned int seconds = 0;
365 struct audio_recording_options rec_options;
366 #endif /* SIMULATOR */
367 #endif /* CONFIG_CODEC != SWCODEC */
368 #ifndef HAVE_NOISY_IDLE_MODE
369 int button_timeout = current_tick + (2*HZ);
370 #endif
372 /* change status to "in screen" */
373 push_current_activity(ACTIVITY_FM);
374 in_screen = true;
376 if(radio_preset_count() <= 0)
378 radio_load_presets(global_settings.fmr_file);
380 skin_get_global_state()->id3 = NULL;
381 #ifdef HAVE_ALBUMART
382 radioart_init(true);
383 #endif
385 if(radio_status == FMRADIO_OFF)
386 audio_stop();
388 #ifndef SIMULATOR
390 #if CONFIG_CODEC != SWCODEC
391 rec_create_directory();
392 audio_init_recording();
394 sound_settings_apply();
395 /* Yes, we use the D/A for monitoring */
396 peak_meter_playback(true);
398 peak_meter_enable(true);
400 rec_init_recording_options(&rec_options);
401 rec_options.rec_source = AUDIO_SRC_LINEIN;
402 rec_set_recording_options(&rec_options);
404 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN),
405 sound_default(SOUND_RIGHT_GAIN), AUDIO_GAIN_LINEIN);
407 #endif /* CONFIG_CODEC != SWCODEC */
408 #endif /* ndef SIMULATOR */
409 /* turn on radio */
410 #if CONFIG_CODEC == SWCODEC
411 /* This should be done before touching audio settings */
412 while (!pcm_is_initialized())
413 sleep(0);
415 audio_set_input_source(AUDIO_SRC_FMRADIO,
416 (radio_status == FMRADIO_PAUSED) ?
417 SRCF_FMRADIO_PAUSED : SRCF_FMRADIO_PLAYING);
418 #else
419 if (radio_status == FMRADIO_OFF)
420 radio_start();
421 #endif
423 if(radio_preset_count() < 1 && yesno_pop(ID2P(LANG_FM_FIRST_AUTOSCAN)))
424 presets_scan(NULL);
426 fms_fix_displays(FMS_ENTER);
427 FOR_NB_SCREENS(i)
428 skin_update(FM_SCREEN, i, SKIN_REFRESH_ALL);
430 preset_set_current(preset_find(curr_freq));
431 if(radio_current_preset() != -1)
432 radio_mode = RADIO_PRESET_MODE;
434 #ifndef HAVE_NOISY_IDLE_MODE
435 cpu_idle_mode(true);
436 #endif
438 while(!done)
440 if(search_dir != 0)
442 curr_freq = step_freq(curr_freq, search_dir);
443 update_type = SKIN_REFRESH_ALL;
445 if(tuner_set(RADIO_SCAN_FREQUENCY, curr_freq))
447 preset_set_current(preset_find(curr_freq));
448 remember_frequency();
449 end_search();
450 talk = true;
452 trigger_cpu_boost();
455 if (!update_type)
457 cancel_cpu_boost();
460 button = fms_do_button_loop(update_type>0);
462 #ifndef HAVE_NOISY_IDLE_MODE
463 if (button != ACTION_NONE)
465 cpu_idle_mode(false);
466 button_timeout = current_tick + (2*HZ);
468 #endif
469 switch(button)
471 case ACTION_FM_STOP:
472 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
473 if(audio_status() == AUDIO_STATUS_RECORD)
475 audio_stop();
477 else
478 #endif
480 done = true;
481 if(presets_have_changed())
483 if(yesno_pop(ID2P(LANG_SAVE_CHANGES)))
485 presets_save();
489 update_type = SKIN_REFRESH_NON_STATIC;
490 break;
492 #ifdef FM_RECORD
493 case ACTION_FM_RECORD:
494 #ifdef FM_RECORD_DBLPRE
495 if (lastbutton != ACTION_FM_RECORD_DBLPRE)
497 rec_lastclick = 0;
498 break;
500 if (current_tick - rec_lastclick > HZ/2)
502 rec_lastclick = current_tick;
503 break;
505 #endif /* FM_RECORD_DBLPRE */
506 #ifndef SIMULATOR
507 if(audio_status() == AUDIO_STATUS_RECORD)
509 rec_command(RECORDING_CMD_START_NEWFILE);
510 update_type = SKIN_REFRESH_ALL;
512 else
514 rec_command(RECORDING_CMD_START);
515 update_type = SKIN_REFRESH_ALL;
517 #if CONFIG_CODEC != SWCODEC
518 last_seconds = 0;
519 #endif
520 #endif /* SIMULATOR */
521 break;
522 #endif /* #ifdef FM_RECORD */
524 case ACTION_FM_EXIT:
525 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
526 if(audio_status() == AUDIO_STATUS_RECORD)
527 audio_stop();
528 #endif
529 keep_playing = true;
530 done = true;
531 if(presets_have_changed())
533 if(yesno_pop(ID2P(LANG_SAVE_CHANGES)))
535 presets_save();
539 break;
541 case ACTION_STD_PREV:
542 case ACTION_STD_NEXT:
543 next_station(button == ACTION_STD_PREV ? -1 : 1);
544 end_search();
545 update_type = SKIN_REFRESH_ALL;
546 talk = true;
547 break;
549 case ACTION_STD_PREVREPEAT:
550 case ACTION_STD_NEXTREPEAT:
552 int dir = search_dir;
553 search_dir = button == ACTION_STD_PREVREPEAT ? -1 : 1;
554 if (radio_mode != RADIO_SCAN_MODE)
556 preset_next(search_dir);
557 end_search();
558 talk = true;
560 else if (dir == 0)
562 /* Starting auto scan */
563 tuner_set(RADIO_MUTE, 1);
565 update_type = SKIN_REFRESH_ALL;
566 break;
569 case ACTION_SETTINGS_INC:
570 case ACTION_SETTINGS_INCREPEAT:
571 global_settings.volume++;
572 setvol();
573 update_type = SKIN_REFRESH_NON_STATIC;
574 break;
576 case ACTION_SETTINGS_DEC:
577 case ACTION_SETTINGS_DECREPEAT:
578 global_settings.volume--;
579 setvol();
580 update_type = SKIN_REFRESH_NON_STATIC;
581 break;
583 case ACTION_FM_PLAY:
584 if (radio_status == FMRADIO_PLAYING)
585 radio_pause();
586 else
587 radio_start();
589 update_type = SKIN_REFRESH_NON_STATIC;
590 talk = false;
591 talk_shutup();
592 break;
594 case ACTION_FM_MENU:
595 fms_fix_displays(FMS_EXIT);
596 do_menu(&radio_settings_menu, NULL, NULL, false);
597 preset_set_current(preset_find(curr_freq));
598 fms_fix_displays(FMS_ENTER);
599 update_type = SKIN_REFRESH_ALL;
600 break;
602 #ifdef FM_PRESET
603 case ACTION_FM_PRESET:
604 if(radio_preset_count() < 1)
606 splash(HZ, ID2P(LANG_FM_NO_PRESETS));
607 update_type = SKIN_REFRESH_ALL;
608 break;
610 fms_fix_displays(FMS_EXIT);
611 handle_radio_presets();
612 fms_fix_displays(FMS_ENTER);
613 update_type = SKIN_REFRESH_ALL;
614 break;
615 #endif /* FM_PRESET */
617 #ifdef FM_FREEZE
618 case ACTION_FM_FREEZE:
619 if(!screen_freeze)
621 splash(HZ, str(LANG_FM_FREEZE));
622 screen_freeze = true;
624 else
626 update_type = SKIN_REFRESH_ALL;
627 screen_freeze = false;
629 break;
630 #endif /* FM_FREEZE */
632 case SYS_USB_CONNECTED:
633 #if CONFIG_CODEC != SWCODEC
634 /* Only accept USB connection when not recording */
635 if(audio_status() != AUDIO_STATUS_RECORD)
636 #endif
638 default_event_handler(SYS_USB_CONNECTED);
639 screen_freeze = true; /* Cosmetic: makes sure the
640 radio screen doesn't redraw */
641 done = true;
643 break;
645 #ifdef FM_MODE
646 case ACTION_FM_MODE:
647 if(radio_mode == RADIO_SCAN_MODE)
649 /* Force scan mode if there are no presets. */
650 if(radio_preset_count() > 0)
651 radio_mode = RADIO_PRESET_MODE;
653 else
654 radio_mode = RADIO_SCAN_MODE;
655 update_type = SKIN_REFRESH_ALL;
656 cond_talk_ids_fq(radio_mode ?
657 LANG_PRESET : LANG_RADIO_SCAN_MODE);
658 talk = true;
659 break;
660 #endif /* FM_MODE */
662 #ifdef FM_NEXT_PRESET
663 case ACTION_FM_NEXT_PRESET:
664 preset_next(1);
665 end_search();
666 update_type = SKIN_REFRESH_ALL;
667 talk = true;
668 break;
669 #endif
671 #ifdef FM_PREV_PRESET
672 case ACTION_FM_PREV_PRESET:
673 preset_next(-1);
674 end_search();
675 update_type = SKIN_REFRESH_ALL;
676 talk = true;
677 break;
678 #endif
679 case ACTION_NONE:
680 update_type = SKIN_REFRESH_NON_STATIC;
681 break;
683 default:
684 default_event_handler(button);
685 #ifdef HAVE_RDS_CAP
686 if (tuner_get(RADIO_EVENT))
687 update_type = SKIN_REFRESH_ALL;
688 #endif
689 if (!tuner_get(RADIO_PRESENT))
691 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
692 if(audio_status() == AUDIO_STATUS_RECORD)
693 audio_stop();
694 #endif
695 keep_playing = false;
696 done = true;
697 if(presets_have_changed())
699 if(yesno_pop(ID2P(LANG_SAVE_CHANGES)))
701 radio_save_presets();
705 /* Clear the preset list on exit. */
706 preset_list_clear();
708 break;
709 } /*switch(button)*/
711 #ifdef FM_RECORD_DBLPRE
712 if (button != ACTION_NONE)
713 lastbutton = button;
714 #endif
716 #if CONFIG_CODEC != SWCODEC
717 peak_meter_peek();
718 #endif
720 if(!screen_freeze)
722 /* Only display the peak meter when not recording */
723 #if CONFIG_CODEC != SWCODEC
724 if(TIME_AFTER(current_tick, timeout))
726 timeout = current_tick + HZ;
727 #else /* SWCODEC */
729 #endif /* CONFIG_CODEC == SWCODEC */
731 /* keep "mono" from always being displayed when paused */
732 if (radio_status != FMRADIO_PAUSED)
734 stereo = tuner_get(RADIO_STEREO) &&
735 !global_settings.fm_force_mono;
737 if(stereo != last_stereo)
739 update_type = SKIN_REFRESH_ALL;
740 last_stereo = stereo;
745 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
746 seconds = audio_recorded_time() / HZ;
747 if (update_type || seconds > last_seconds)
749 last_seconds = seconds;
750 #else
751 if (update_type)
753 #endif
754 FOR_NB_SCREENS(i)
755 skin_update(FM_SCREEN, i, update_type);
756 if (update_type == (int)SKIN_REFRESH_ALL)
757 skin_request_full_update(CUSTOM_STATUSBAR);
760 update_type = 0;
762 if (global_settings.talk_file && talk
763 && radio_status == FMRADIO_PAUSED)
765 talk = false;
766 bool enqueue = false;
767 if (radio_mode == RADIO_SCAN_MODE)
769 talk_value_decimal(curr_freq, UNIT_INT, 6, enqueue);
770 enqueue = true;
772 if (radio_current_preset() >= 0)
773 preset_talk(radio_current_preset(), radio_mode == RADIO_PRESET_MODE,
774 enqueue);
777 #if CONFIG_CODEC != SWCODEC
778 if(audio_status() & AUDIO_STATUS_ERROR)
780 done = true;
782 #endif
784 #ifndef HAVE_NOISY_IDLE_MODE
785 if (TIME_AFTER(current_tick, button_timeout))
787 cpu_idle_mode(true);
789 #endif
790 } /*while(!done)*/
792 #ifndef SIMULATOR
793 #if CONFIG_CODEC != SWCODEC
794 if(audio_status() & AUDIO_STATUS_ERROR)
796 splash(0, str(LANG_DISK_FULL));
797 audio_error_clear();
799 while(1)
801 button = get_action(CONTEXT_FM, TIMEOUT_BLOCK);
802 if(button == ACTION_FM_STOP)
803 break;
807 audio_init_playback();
808 #endif /* CONFIG_CODEC != SWCODEC */
810 sound_settings_apply();
811 #endif /* SIMULATOR */
813 if(keep_playing)
815 /* Catch FMRADIO_PLAYING status for the sim. */
816 #ifndef SIMULATOR
817 #if CONFIG_CODEC != SWCODEC
818 /* Enable the Left and right A/D Converter */
819 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN),
820 sound_default(SOUND_RIGHT_GAIN),
821 AUDIO_GAIN_LINEIN);
822 mas_codec_writereg(6, 0x4000);
823 #endif
824 end_search();
825 #endif /* SIMULATOR */
827 else
829 #if CONFIG_CODEC == SWCODEC
830 audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
831 #else
832 radio_stop();
833 #endif
836 #ifndef HAVE_NOISY_IDLE_MODE
837 cpu_idle_mode(false);
838 #endif
839 fms_fix_displays(FMS_EXIT);
840 pop_current_activity();
841 in_screen = false;
842 } /* radio_screen */
844 void toggle_mono_mode(bool mono)
846 tuner_set(RADIO_FORCE_MONO, mono);
849 void set_radio_region(int region)
851 #ifdef HAVE_RADIO_REGION
852 tuner_set(RADIO_REGION, region);
853 #endif
854 next_station(0);
855 remember_frequency();
856 (void)region;
859 #endif