MPEGPlayer: Skip to next file when there is a problem with a video file in all-play...
[kugel-rb.git] / apps / radio / radio.c
blob7cc676b9a4c9e18feb0e122a2277736e5d01d5cf
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 "settings.h"
27 #include "button.h"
28 #include "status.h"
29 #include "thread.h"
30 #include "audio.h"
31 #include "mp3_playback.h"
32 #include "ctype.h"
33 #include "file.h"
34 #include "general.h"
35 #include "errno.h"
36 #include "string-extra.h"
37 #include "system.h"
38 #include "radio.h"
39 #include "menu.h"
40 #include "misc.h"
41 #include "keyboard.h"
42 #include "screens.h"
43 #include "peakmeter.h"
44 #include "lang.h"
45 #include "font.h"
46 #include "sound_menu.h"
47 #ifdef HAVE_RECORDING
48 #include "recording.h"
49 #endif
50 #ifdef IPOD_ACCESSORY_PROTOCOL
51 #include "iap.h"
52 #endif
53 #include "appevents.h"
54 #include "talk.h"
55 #include "tuner.h"
56 #include "power.h"
57 #include "sound.h"
58 #include "screen_access.h"
59 #include "splash.h"
60 #include "yesno.h"
61 #include "buttonbar.h"
62 #include "tree.h"
63 #include "dir.h"
64 #include "action.h"
65 #include "list.h"
66 #include "menus/exported_menus.h"
67 #include "root_menu.h"
68 #include "viewport.h"
69 #include "skin_engine/skin_engine.h"
70 #include "statusbar-skinned.h"
71 #include "buffering.h"
72 #if CONFIG_CODEC == SWCODEC
73 #include "playback.h"
74 #endif
75 #include "presets.h"
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 #elif (CONFIG_KEYPAD == MPIO_HD200_PAD)
138 #define FM_MENU
139 #define FM_STOP
140 #define FM_EXIT
141 #define FM_PLAY
142 #define FM_MODE
143 #define FM_STOP
145 #endif
147 /* presets.c needs these so keep unstatic or redo the whole thing! */
148 int curr_freq; /* current frequency in Hz */
150 static bool radio_menu(void);
152 int radio_mode = RADIO_SCAN_MODE;
153 static int search_dir = 0;
155 static int radio_status = FMRADIO_OFF;
156 static bool in_screen = false;
159 static void radio_off(void);
161 bool radio_scan_mode(void)
163 return radio_mode == RADIO_SCAN_MODE;
166 bool radio_is_stereo(void)
168 return tuner_get(RADIO_STEREO) && !global_settings.fm_force_mono;
170 int radio_current_frequency(void)
172 return curr_freq;
175 /* Function to manipulate all yesno dialogues.
176 This function needs the output text as an argument. */
177 bool yesno_pop(const char* text)
179 int i;
180 const char *lines[]={text};
181 const struct text_message message={lines, 1};
182 bool ret = (gui_syncyesno_run(&message,NULL,NULL)== YESNO_YES);
183 FOR_NB_SCREENS(i)
184 screens[i].clear_viewport();
185 return ret;
188 void radio_init(void)
190 tuner_init();
191 radio_off();
192 #ifdef HAVE_ALBUMART
193 radioart_init(false);
194 #endif
197 int get_radio_status(void)
199 return radio_status;
202 bool in_radio_screen(void)
204 return in_screen;
207 /* TODO: Move some more of the control functionality to firmware
208 and clean up the mess */
210 /* secret flag for starting paused - prevents unmute */
211 #define FMRADIO_START_PAUSED 0x8000
212 void radio_start(void)
214 const struct fm_region_data *fmr;
215 bool start_paused;
217 if(radio_status == FMRADIO_PLAYING)
218 return;
220 fmr = &fm_region_data[global_settings.fm_region];
222 start_paused = radio_status & FMRADIO_START_PAUSED;
223 /* clear flag before any yielding */
224 radio_status &= ~FMRADIO_START_PAUSED;
226 if(radio_status == FMRADIO_OFF)
227 tuner_power(true);
229 curr_freq = global_status.last_frequency * fmr->freq_step + fmr->freq_min;
231 tuner_set(RADIO_SLEEP, 0); /* wake up the tuner */
233 if(radio_status == FMRADIO_OFF)
235 #ifdef HAVE_RADIO_REGION
236 tuner_set(RADIO_REGION, global_settings.fm_region);
237 #endif
238 tuner_set(RADIO_FORCE_MONO, global_settings.fm_force_mono);
241 tuner_set(RADIO_FREQUENCY, curr_freq);
243 #ifdef HAVE_RADIO_MUTE_TIMEOUT
245 unsigned long mute_timeout = current_tick + HZ;
246 if (radio_status != FMRADIO_OFF)
248 /* paused */
249 mute_timeout += HZ;
252 while(!tuner_get(RADIO_STEREO) && !tuner_get(RADIO_TUNED))
254 if(TIME_AFTER(current_tick, mute_timeout))
255 break;
256 yield();
259 #endif
261 /* keep radio from sounding initially */
262 if(!start_paused)
263 tuner_set(RADIO_MUTE, 0);
265 radio_status = FMRADIO_PLAYING;
266 } /* radio_start */
268 void radio_pause(void)
270 if(radio_status == FMRADIO_PAUSED)
271 return;
273 if(radio_status == FMRADIO_OFF)
275 radio_status |= FMRADIO_START_PAUSED;
276 radio_start();
279 tuner_set(RADIO_MUTE, 1);
280 /* For si4700: 2==this is really 'pause'. other tuners treat it
281 * like 'bool'. */
282 tuner_set(RADIO_SLEEP, 2);
284 radio_status = FMRADIO_PAUSED;
285 } /* radio_pause */
287 static void radio_off(void)
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. */
295 void radio_stop(void)
297 if(radio_status == FMRADIO_OFF)
298 return;
300 radio_off();
301 } /* radio_stop */
303 bool radio_hardware_present(void)
305 return tuner_get(RADIO_PRESENT);
308 /* Keep freq on the grid for the current region */
309 int snap_freq_to_grid(int freq)
311 const struct fm_region_data * const fmr =
312 &fm_region_data[global_settings.fm_region];
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;
323 return freq;
326 void remember_frequency(void)
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();
335 /* Step to the next or previous frequency */
336 static int step_freq(int freq, int direction)
338 const struct fm_region_data * const fmr =
339 &fm_region_data[global_settings.fm_region];
341 freq += direction*fmr->freq_step;
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);
351 return freq;
354 /* Step to the next or previous station */
355 void next_station(int direction)
357 if (direction != 0 && radio_mode != RADIO_SCAN_MODE)
359 preset_next(direction);
360 return;
363 curr_freq = step_freq(curr_freq, direction);
365 if (radio_status == FMRADIO_PLAYING)
366 tuner_set(RADIO_MUTE, 1);
368 tuner_set(RADIO_FREQUENCY, curr_freq);
370 if (radio_status == FMRADIO_PLAYING)
371 tuner_set(RADIO_MUTE, 0);
373 preset_set_current(preset_find(curr_freq));
374 remember_frequency();
377 /* Ends an in-progress search */
378 static void end_search(void)
380 if (search_dir != 0 && radio_status == FMRADIO_PLAYING)
381 tuner_set(RADIO_MUTE, 0);
382 search_dir = 0;
385 /* Speak a frequency. */
386 void talk_freq(int freq, bool enqueue)
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);
397 void radio_screen(void)
399 bool done = false;
400 int button;
401 int i;
402 bool stereo = false, last_stereo = false;
403 int update_type = 0;
404 bool screen_freeze = false;
405 bool keep_playing = false;
406 bool talk = false;
407 #ifdef FM_RECORD_DBLPRE
408 int lastbutton = BUTTON_NONE;
409 unsigned long rec_lastclick = 0;
410 #endif
411 #if CONFIG_CODEC != SWCODEC
412 int timeout = current_tick + HZ/10;
413 unsigned int last_seconds = 0;
414 #if !defined(SIMULATOR)
415 unsigned int seconds = 0;
416 struct audio_recording_options rec_options;
417 #endif /* SIMULATOR */
418 #endif /* CONFIG_CODEC != SWCODEC */
419 #ifndef HAVE_NOISY_IDLE_MODE
420 int button_timeout = current_tick + (2*HZ);
421 #endif
423 /* change status to "in screen" */
424 in_screen = true;
426 if(radio_preset_count() <= 0)
428 radio_load_presets(global_settings.fmr_file);
430 skin_get_global_state()->id3 = NULL;
431 #ifdef HAVE_ALBUMART
432 radioart_init(true);
433 #endif
435 if(radio_status == FMRADIO_OFF)
436 audio_stop();
438 #ifndef SIMULATOR
440 #if CONFIG_CODEC != SWCODEC
441 rec_create_directory();
442 audio_init_recording(talk_get_bufsize());
444 sound_settings_apply();
445 /* Yes, we use the D/A for monitoring */
446 peak_meter_playback(true);
448 peak_meter_enable(true);
450 rec_init_recording_options(&rec_options);
451 rec_options.rec_source = AUDIO_SRC_LINEIN;
452 rec_set_recording_options(&rec_options);
454 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN),
455 sound_default(SOUND_RIGHT_GAIN), AUDIO_GAIN_LINEIN);
457 #endif /* CONFIG_CODEC != SWCODEC */
458 #endif /* ndef SIMULATOR */
460 /* turn on radio */
461 #if CONFIG_CODEC == SWCODEC
462 /* This should be done before touching audio settings */
463 while (!audio_is_thread_ready())
464 sleep(0);
466 audio_set_input_source(AUDIO_SRC_FMRADIO,
467 (radio_status == FMRADIO_PAUSED) ?
468 SRCF_FMRADIO_PAUSED : SRCF_FMRADIO_PLAYING);
469 #else
470 if (radio_status == FMRADIO_OFF)
471 radio_start();
472 #endif
474 if(radio_preset_count() < 1 && yesno_pop(ID2P(LANG_FM_FIRST_AUTOSCAN)))
475 presets_scan(NULL);
477 fms_fix_displays(FMS_ENTER);
478 FOR_NB_SCREENS(i)
479 skin_update(FM_SCREEN, i, SKIN_REFRESH_ALL);
481 preset_set_current(preset_find(curr_freq));
482 if(radio_current_preset() != -1)
483 radio_mode = RADIO_PRESET_MODE;
485 #ifndef HAVE_NOISY_IDLE_MODE
486 cpu_idle_mode(true);
487 #endif
489 while(!done)
491 if(search_dir != 0)
493 curr_freq = step_freq(curr_freq, search_dir);
494 update_type = SKIN_REFRESH_ALL;
496 if(tuner_set(RADIO_SCAN_FREQUENCY, curr_freq))
498 preset_set_current(preset_find(curr_freq));
499 remember_frequency();
500 end_search();
501 talk = true;
503 trigger_cpu_boost();
506 if (!update_type)
508 cancel_cpu_boost();
511 button = fms_do_button_loop(update_type>0);
513 #ifndef HAVE_NOISY_IDLE_MODE
514 if (button != ACTION_NONE)
516 cpu_idle_mode(false);
517 button_timeout = current_tick + (2*HZ);
519 #endif
520 switch(button)
522 case ACTION_FM_STOP:
523 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
524 if(audio_status() == AUDIO_STATUS_RECORD)
526 audio_stop();
528 else
529 #endif
531 done = true;
532 if(presets_have_changed())
534 if(yesno_pop(ID2P(LANG_FM_SAVE_CHANGES)))
536 presets_save();
540 update_type = SKIN_REFRESH_NON_STATIC;
541 break;
543 #ifdef FM_RECORD
544 case ACTION_FM_RECORD:
545 #ifdef FM_RECORD_DBLPRE
546 if (lastbutton != ACTION_FM_RECORD_DBLPRE)
548 rec_lastclick = 0;
549 break;
551 if (current_tick - rec_lastclick > HZ/2)
553 rec_lastclick = current_tick;
554 break;
556 #endif /* FM_RECORD_DBLPRE */
557 #ifndef SIMULATOR
558 if(audio_status() == AUDIO_STATUS_RECORD)
560 rec_command(RECORDING_CMD_START_NEWFILE);
561 update_type = SKIN_REFRESH_ALL;
563 else
565 rec_command(RECORDING_CMD_START);
566 update_type = SKIN_REFRESH_ALL;
568 #endif /* SIMULATOR */
569 last_seconds = 0;
570 break;
571 #endif /* #ifdef FM_RECORD */
573 case ACTION_FM_EXIT:
574 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
575 if(audio_status() == AUDIO_STATUS_RECORD)
576 audio_stop();
577 #endif
578 keep_playing = true;
579 done = true;
580 if(presets_have_changed())
582 if(yesno_pop(ID2P(LANG_FM_SAVE_CHANGES)))
584 presets_save();
588 break;
590 case ACTION_STD_PREV:
591 case ACTION_STD_NEXT:
592 next_station(button == ACTION_STD_PREV ? -1 : 1);
593 end_search();
594 update_type = SKIN_REFRESH_ALL;
595 talk = true;
596 break;
598 case ACTION_STD_PREVREPEAT:
599 case ACTION_STD_NEXTREPEAT:
601 int dir = search_dir;
602 search_dir = button == ACTION_STD_PREVREPEAT ? -1 : 1;
603 if (radio_mode != RADIO_SCAN_MODE)
605 preset_next(search_dir);
606 end_search();
607 talk = true;
609 else if (dir == 0)
611 /* Starting auto scan */
612 tuner_set(RADIO_MUTE, 1);
614 update_type = SKIN_REFRESH_ALL;
615 break;
618 case ACTION_SETTINGS_INC:
619 case ACTION_SETTINGS_INCREPEAT:
620 global_settings.volume++;
621 setvol();
622 update_type = SKIN_REFRESH_NON_STATIC;
623 break;
625 case ACTION_SETTINGS_DEC:
626 case ACTION_SETTINGS_DECREPEAT:
627 global_settings.volume--;
628 setvol();
629 update_type = SKIN_REFRESH_NON_STATIC;
630 break;
632 case ACTION_FM_PLAY:
633 if (radio_status == FMRADIO_PLAYING)
634 radio_pause();
635 else
636 radio_start();
638 update_type = SKIN_REFRESH_NON_STATIC;
639 talk = false;
640 talk_shutup();
641 break;
643 case ACTION_FM_MENU:
644 fms_fix_displays(FMS_EXIT);
645 radio_menu();
646 preset_set_current(preset_find(curr_freq));
647 fms_fix_displays(FMS_ENTER);
648 update_type = SKIN_REFRESH_ALL;
649 break;
651 #ifdef FM_PRESET
652 case ACTION_FM_PRESET:
653 if(radio_preset_count() < 1)
655 splash(HZ, ID2P(LANG_FM_NO_PRESETS));
656 update_type = SKIN_REFRESH_ALL;
657 break;
659 fms_fix_displays(FMS_EXIT);
660 handle_radio_presets();
661 fms_fix_displays(FMS_ENTER);
662 update_type = SKIN_REFRESH_ALL;
663 break;
664 #endif /* FM_PRESET */
666 #ifdef FM_FREEZE
667 case ACTION_FM_FREEZE:
668 if(!screen_freeze)
670 splash(HZ, str(LANG_FM_FREEZE));
671 screen_freeze = true;
673 else
675 update_type = SKIN_REFRESH_ALL;
676 screen_freeze = false;
678 break;
679 #endif /* FM_FREEZE */
681 case SYS_USB_CONNECTED:
682 #if CONFIG_CODEC != SWCODEC
683 /* Only accept USB connection when not recording */
684 if(audio_status() != AUDIO_STATUS_RECORD)
685 #endif
687 default_event_handler(SYS_USB_CONNECTED);
688 screen_freeze = true; /* Cosmetic: makes sure the
689 radio screen doesn't redraw */
690 done = true;
692 break;
694 #ifdef FM_MODE
695 case ACTION_FM_MODE:
696 if(radio_mode == RADIO_SCAN_MODE)
698 /* Force scan mode if there are no presets. */
699 if(radio_preset_count() > 0)
700 radio_mode = RADIO_PRESET_MODE;
702 else
703 radio_mode = RADIO_SCAN_MODE;
704 update_type = SKIN_REFRESH_ALL;
705 cond_talk_ids_fq(radio_mode ?
706 LANG_PRESET : LANG_RADIO_SCAN_MODE);
707 talk = true;
708 break;
709 #endif /* FM_MODE */
711 #ifdef FM_NEXT_PRESET
712 case ACTION_FM_NEXT_PRESET:
713 preset_next(1);
714 end_search();
715 update_type = SKIN_REFRESH_ALL;
716 talk = true;
717 break;
718 #endif
720 #ifdef FM_PREV_PRESET
721 case ACTION_FM_PREV_PRESET:
722 preset_next(-1);
723 end_search();
724 update_type = SKIN_REFRESH_ALL;
725 talk = true;
726 break;
727 #endif
728 case ACTION_NONE:
729 update_type = SKIN_REFRESH_NON_STATIC;
730 break;
732 default:
733 default_event_handler(button);
734 #ifdef HAVE_RDS_CAP
735 if (tuner_get(RADIO_EVENT))
736 update_type = SKIN_REFRESH_ALL;
737 #endif
738 if (!tuner_get(RADIO_PRESENT))
740 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
741 if(audio_status() == AUDIO_STATUS_RECORD)
742 audio_stop();
743 #endif
744 keep_playing = false;
745 done = true;
746 if(presets_have_changed())
748 if(yesno_pop(ID2P(LANG_FM_SAVE_CHANGES)))
750 radio_save_presets();
754 /* Clear the preset list on exit. */
755 preset_list_clear();
757 break;
758 } /*switch(button)*/
760 #ifdef FM_RECORD_DBLPRE
761 if (button != ACTION_NONE)
762 lastbutton = button;
763 #endif
765 #if CONFIG_CODEC != SWCODEC
766 peak_meter_peek();
767 #endif
769 if(!screen_freeze)
771 /* Only display the peak meter when not recording */
772 #if CONFIG_CODEC != SWCODEC
773 if(TIME_AFTER(current_tick, timeout))
775 timeout = current_tick + HZ;
776 #else /* SWCODEC */
778 #endif /* CONFIG_CODEC == SWCODEC */
780 /* keep "mono" from always being displayed when paused */
781 if (radio_status != FMRADIO_PAUSED)
783 stereo = tuner_get(RADIO_STEREO) &&
784 !global_settings.fm_force_mono;
786 if(stereo != last_stereo)
788 update_type = SKIN_REFRESH_ALL;
789 last_stereo = stereo;
794 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
795 seconds = audio_recorded_time() / HZ;
796 if (update_type || seconds > last_seconds)
798 last_seconds = seconds;
799 #else
800 if (update_type)
802 #endif
803 FOR_NB_SCREENS(i)
804 skin_update(FM_SCREEN, i, update_type);
807 update_type = 0;
809 if (global_settings.talk_file && talk
810 && radio_status == FMRADIO_PAUSED)
812 talk = false;
813 bool enqueue = false;
814 if (radio_mode == RADIO_SCAN_MODE)
816 talk_freq(curr_freq, enqueue);
817 enqueue = true;
819 if (radio_current_preset() >= 0)
820 preset_talk(radio_current_preset(), radio_mode == RADIO_PRESET_MODE,
821 enqueue);
824 #if CONFIG_CODEC != SWCODEC
825 if(audio_status() & AUDIO_STATUS_ERROR)
827 done = true;
829 #endif
831 #ifndef HAVE_NOISY_IDLE_MODE
832 if (TIME_AFTER(current_tick, button_timeout))
834 cpu_idle_mode(true);
836 #endif
837 } /*while(!done)*/
839 #ifndef SIMULATOR
840 #if CONFIG_CODEC != SWCODEC
841 if(audio_status() & AUDIO_STATUS_ERROR)
843 splash(0, str(LANG_DISK_FULL));
844 audio_error_clear();
846 while(1)
848 button = get_action(CONTEXT_FM, TIMEOUT_BLOCK);
849 if(button == ACTION_FM_STOP)
850 break;
854 audio_init_playback();
855 #endif /* CONFIG_CODEC != SWCODEC */
857 sound_settings_apply();
858 #endif /* SIMULATOR */
860 if(keep_playing)
862 /* Catch FMRADIO_PLAYING status for the sim. */
863 #ifndef SIMULATOR
864 #if CONFIG_CODEC != SWCODEC
865 /* Enable the Left and right A/D Converter */
866 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN),
867 sound_default(SOUND_RIGHT_GAIN),
868 AUDIO_GAIN_LINEIN);
869 mas_codec_writereg(6, 0x4000);
870 #endif
871 end_search();
872 #endif /* SIMULATOR */
874 else
876 #if CONFIG_CODEC == SWCODEC
877 audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
878 #else
879 radio_stop();
880 #endif
883 #ifndef HAVE_NOISY_IDLE_MODE
884 cpu_idle_mode(false);
885 #endif
886 fms_fix_displays(FMS_EXIT);
887 in_screen = false;
888 } /* radio_screen */
890 void toggle_mono_mode(bool mono)
892 tuner_set(RADIO_FORCE_MONO, mono);
895 void set_radio_region(int region)
897 #ifdef HAVE_RADIO_REGION
898 tuner_set(RADIO_REGION, region);
899 #endif
900 next_station(0);
901 remember_frequency();
902 (void)region;
905 MENUITEM_SETTING(set_region, &global_settings.fm_region, NULL);
906 MENUITEM_SETTING(force_mono, &global_settings.fm_force_mono, NULL);
908 #ifndef FM_MODE
909 static char* get_mode_text(int selected_item, void * data, char *buffer)
911 (void)selected_item;
912 (void)data;
913 snprintf(buffer, MAX_PATH, "%s %s", str(LANG_MODE),
914 radio_mode ? str(LANG_PRESET) :
915 str(LANG_RADIO_SCAN_MODE));
916 return buffer;
918 static int toggle_radio_mode(void)
920 radio_mode = (radio_mode == RADIO_SCAN_MODE) ?
921 RADIO_PRESET_MODE : RADIO_SCAN_MODE;
922 return 0;
924 MENUITEM_FUNCTION_DYNTEXT(radio_mode_item, 0,
925 toggle_radio_mode, NULL,
926 get_mode_text, NULL, NULL, NULL, Icon_NOICON);
927 #endif
931 #ifdef HAVE_RECORDING
933 #if defined(HAVE_FMRADIO_REC) && CONFIG_CODEC == SWCODEC
934 #define FM_RECORDING_SCREEN
935 static int fm_recording_screen(void)
937 bool ret;
939 /* switch recording source to FMRADIO for the duration */
940 int rec_source = global_settings.rec_source;
941 global_settings.rec_source = AUDIO_SRC_FMRADIO;
942 ret = recording_screen(true);
944 /* safe to reset as changing sources is prohibited here */
945 global_settings.rec_source = rec_source;
947 return ret;
950 #endif /* defined(HAVE_FMRADIO_REC) && CONFIG_CODEC == SWCODEC */
952 #if defined(HAVE_FMRADIO_REC) || CONFIG_CODEC != SWCODEC
953 #define FM_RECORDING_SETTINGS
954 static int fm_recording_settings(void)
956 bool ret = recording_menu(true);
958 #if CONFIG_CODEC != SWCODEC
959 if (!ret)
961 struct audio_recording_options rec_options;
962 rec_init_recording_options(&rec_options);
963 rec_options.rec_source = AUDIO_SRC_LINEIN;
964 rec_set_recording_options(&rec_options);
966 #endif
968 return ret;
971 #endif /* defined(HAVE_FMRADIO_REC) || CONFIG_CODEC != SWCODEC */
972 #endif /* HAVE_RECORDING */
974 #ifdef FM_RECORDING_SCREEN
975 MENUITEM_FUNCTION(recscreen_item, 0, ID2P(LANG_RECORDING),
976 fm_recording_screen, NULL, NULL, Icon_Recording);
977 #endif
978 #ifdef FM_RECORDING_SETTINGS
979 MENUITEM_FUNCTION(recsettings_item, 0, ID2P(LANG_RECORDING_SETTINGS),
980 fm_recording_settings, NULL, NULL, Icon_Recording);
981 #endif
982 #ifndef FM_PRESET
983 MENUITEM_FUNCTION(radio_presets_item, 0, ID2P(LANG_PRESET),
984 handle_radio_presets, NULL, NULL, Icon_NOICON);
985 #endif
986 #ifndef FM_PRESET_ADD
987 MENUITEM_FUNCTION(radio_addpreset_item, 0, ID2P(LANG_FM_ADD_PRESET),
988 handle_radio_add_preset, NULL, NULL, Icon_NOICON);
989 #endif
991 MENUITEM_FUNCTION(presetload_item, 0, ID2P(LANG_FM_PRESET_LOAD),
992 preset_list_load, NULL, NULL, Icon_NOICON);
993 MENUITEM_FUNCTION(presetsave_item, 0, ID2P(LANG_FM_PRESET_SAVE),
994 preset_list_save, NULL, NULL, Icon_NOICON);
995 MENUITEM_FUNCTION(presetclear_item, 0, ID2P(LANG_FM_PRESET_CLEAR),
996 preset_list_clear, NULL, NULL, Icon_NOICON);
997 MENUITEM_FUNCTION(scan_presets_item, MENU_FUNC_USEPARAM,
998 ID2P(LANG_FM_SCAN_PRESETS),
999 presets_scan, NULL, NULL, Icon_NOICON);
1001 MAKE_MENU(radio_settings_menu, ID2P(LANG_FM_MENU), NULL,
1002 Icon_Radio_screen,
1003 #ifndef FM_PRESET
1004 &radio_presets_item,
1005 #endif
1006 #ifndef FM_PRESET_ADD
1007 &radio_addpreset_item,
1008 #endif
1009 &presetload_item, &presetsave_item, &presetclear_item,
1010 &force_mono,
1011 #ifndef FM_MODE
1012 &radio_mode_item,
1013 #endif
1014 &set_region, &sound_settings,
1015 #ifdef FM_RECORDING_SCREEN
1016 &recscreen_item,
1017 #endif
1018 #ifdef FM_RECORDING_SETTINGS
1019 &recsettings_item,
1020 #endif
1021 &scan_presets_item);
1022 /* main menu of the radio screen */
1023 static bool radio_menu(void)
1025 return do_menu(&radio_settings_menu, NULL, NULL, false) ==
1026 MENU_ATTACHED_USB;
1029 #endif