Disable AAC-SBR, AAC-SSR, and AAC-PS on Sansa clip. Clean up warnings introduced...
[kugel-rb.git] / apps / recorder / radio.c
blobfe6f277fcb028614e20b040d3f2975f934edc805
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 "sprintf.h"
27 #include "mas.h"
28 #include "settings.h"
29 #include "button.h"
30 #include "status.h"
31 #include "thread.h"
32 #include "mpeg.h"
33 #include "audio.h"
34 #include "mp3_playback.h"
35 #include "ctype.h"
36 #include "file.h"
37 #include "general.h"
38 #include "errno.h"
39 #include "string.h"
40 #include "system.h"
41 #include "radio.h"
42 #include "menu.h"
43 #include "misc.h"
44 #include "keyboard.h"
45 #include "screens.h"
46 #include "peakmeter.h"
47 #include "lang.h"
48 #include "font.h"
49 #include "sound_menu.h"
50 #ifdef HAVE_RECORDING
51 #include "recording.h"
52 #endif
53 #include "talk.h"
54 #include "tuner.h"
55 #include "power.h"
56 #include "sound.h"
57 #include "screen_access.h"
58 #include "statusbar.h"
59 #include "splash.h"
60 #include "yesno.h"
61 #include "buttonbar.h"
62 #include "power.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"
71 #if CONFIG_TUNER
73 #if CONFIG_KEYPAD == RECORDER_PAD
74 #define FM_RECORD
75 #define FM_PRESET_ADD
76 #define FM_PRESET_ACTION
77 #define FM_PRESET
78 #define FM_MODE
80 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
81 #define FM_PRESET
82 #define FM_MODE
83 #define FM_NEXT_PRESET
84 #define FM_PREV_PRESET
86 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
87 #define FM_PRESET
88 #define FM_MODE
90 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
91 #define FM_PRESET
92 #define FM_MODE
93 /* This should be removeable if the whole tuning thing is sorted out since
94 proper tuning quiets the screen almost entirely in that extreme measures
95 have to be taken to hear any interference. */
96 #define HAVE_NOISY_IDLE_MODE
98 #elif CONFIG_KEYPAD == ONDIO_PAD
99 #define FM_RECORD_DBLPRE
100 #define FM_RECORD
101 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || (CONFIG_KEYPAD == SANSA_C200_PAD)
102 #define FM_MENU
103 #define FM_PRESET
104 #define FM_STOP
105 #define FM_MODE
106 #define FM_EXIT
107 #define FM_PLAY
109 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
110 #define FM_PRESET
111 #define FM_MODE
113 #elif (CONFIG_KEYPAD == COWOND2_PAD)
114 #define FM_MENU
115 #define FM_PRESET
116 #define FM_STOP
117 #define FM_MODE
118 #define FM_EXIT
119 #define FM_PLAY
120 #endif
122 #define RADIO_SCAN_MODE 0
123 #define RADIO_PRESET_MODE 1
125 static int curr_preset = -1;
126 static int curr_freq; /* current frequency in Hz */
127 static int radio_mode = RADIO_SCAN_MODE;
128 static int search_dir = 0;
130 static int radio_status = FMRADIO_OFF;
131 static bool in_screen = false;
133 #define MAX_PRESETS 64
134 static bool presets_loaded = false, presets_changed = false;
135 static struct fmstation presets[MAX_PRESETS];
137 static char filepreset[MAX_PATH]; /* preset filename variable */
139 static int num_presets = 0; /* The number of presets in the preset list */
141 static void radio_save_presets(void);
142 static int handle_radio_presets(void);
143 static bool radio_menu(void);
144 static int radio_add_preset(void);
145 static int save_preset_list(void);
146 static int load_preset_list(void);
147 static int clear_preset_list(void);
149 static int scan_presets(void *viewports);
151 /* Function to manipulate all yesno dialogues.
152 This function needs the output text as an argument. */
153 static bool yesno_pop(const char* text)
155 int i;
156 const char *lines[]={text};
157 const struct text_message message={lines, 1};
158 bool ret = (gui_syncyesno_run(&message,NULL,NULL)== YESNO_YES);
159 FOR_NB_SCREENS(i)
160 screens[i].clear_viewport();
161 return ret;
164 void radio_init(void)
166 tuner_init();
167 radio_stop();
170 int get_radio_status(void)
172 return radio_status;
175 bool in_radio_screen(void)
177 return in_screen;
180 /* TODO: Move some more of the control functionality to firmware
181 and clean up the mess */
183 /* secret flag for starting paused - prevents unmute */
184 #define FMRADIO_START_PAUSED 0x8000
185 void radio_start(void)
187 const struct fm_region_data *fmr;
188 bool start_paused;
190 if(radio_status == FMRADIO_PLAYING)
191 return;
193 fmr = &fm_region_data[global_settings.fm_region];
195 start_paused = radio_status & FMRADIO_START_PAUSED;
196 /* clear flag before any yielding */
197 radio_status &= ~FMRADIO_START_PAUSED;
199 if(radio_status == FMRADIO_OFF)
200 tuner_power(true);
202 curr_freq = global_status.last_frequency * fmr->freq_step + fmr->freq_min;
204 tuner_set(RADIO_SLEEP, 0); /* wake up the tuner */
206 if(radio_status == FMRADIO_OFF)
208 #ifdef HAVE_RADIO_REGION
209 tuner_set(RADIO_REGION, global_settings.fm_region);
210 #endif
211 tuner_set(RADIO_FORCE_MONO, global_settings.fm_force_mono);
214 tuner_set(RADIO_FREQUENCY, curr_freq);
216 #ifdef HAVE_RADIO_MUTE_TIMEOUT
218 unsigned long mute_timeout = current_tick + HZ;
219 if (radio_status != FMRADIO_OFF)
221 /* paused */
222 mute_timeout += HZ;
225 while(!tuner_get(RADIO_STEREO) && !tuner_get(RADIO_TUNED))
227 if(TIME_AFTER(current_tick, mute_timeout))
228 break;
229 yield();
232 #endif
234 /* keep radio from sounding initially */
235 if(!start_paused)
236 tuner_set(RADIO_MUTE, 0);
238 radio_status = FMRADIO_PLAYING;
239 } /* radio_start */
241 void radio_pause(void)
243 if(radio_status == FMRADIO_PAUSED)
244 return;
246 if(radio_status == FMRADIO_OFF)
248 radio_status |= FMRADIO_START_PAUSED;
249 radio_start();
252 tuner_set(RADIO_MUTE, 1);
253 tuner_set(RADIO_SLEEP, 1);
255 radio_status = FMRADIO_PAUSED;
256 } /* radio_pause */
258 void radio_stop(void)
260 if(radio_status == FMRADIO_OFF)
261 return;
263 tuner_set(RADIO_MUTE, 1);
264 tuner_set(RADIO_SLEEP, 1); /* low power mode, if available */
265 radio_status = FMRADIO_OFF;
266 tuner_power(false); /* status update, power off if avail. */
267 } /* radio_stop */
269 bool radio_hardware_present(void)
271 return tuner_get(RADIO_PRESENT);
274 /* Keep freq on the grid for the current region */
275 static int snap_freq_to_grid(int freq)
277 const struct fm_region_data * const fmr =
278 &fm_region_data[global_settings.fm_region];
280 /* Range clamp if out of range or just round to nearest */
281 if (freq < fmr->freq_min)
282 freq = fmr->freq_min;
283 else if (freq > fmr->freq_max)
284 freq = fmr->freq_max;
285 else
286 freq = (freq - fmr->freq_min + fmr->freq_step/2) /
287 fmr->freq_step * fmr->freq_step + fmr->freq_min;
289 return freq;
292 /* Find a matching preset to freq */
293 static int find_preset(int freq)
295 int i;
296 if(num_presets < 1)
297 return -1;
298 for(i = 0;i < MAX_PRESETS;i++)
300 if(freq == presets[i].frequency)
301 return i;
304 return -1;
307 /* Return the closest preset encountered in the search direction with
308 wraparound. */
309 static int find_closest_preset(int freq, int direction)
311 int i;
312 int lowpreset = 0;
313 int highpreset = 0;
314 int closest = -1;
316 if (direction == 0) /* direction == 0 isn't really used */
317 return 0;
319 for (i = 0; i < num_presets; i++)
321 int f = presets[i].frequency;
322 if (f == freq)
323 return i; /* Exact match = stop */
325 /* remember the highest and lowest presets for wraparound */
326 if (f < presets[lowpreset].frequency)
327 lowpreset = i;
328 if (f > presets[highpreset].frequency)
329 highpreset = i;
331 /* find the closest preset in the given direction */
332 if (direction > 0 && f > freq)
334 if (closest < 0 || f < presets[closest].frequency)
335 closest = i;
337 else if (direction < 0 && f < freq)
339 if (closest < 0 || f > presets[closest].frequency)
340 closest = i;
344 if (closest < 0)
346 /* no presets in the given direction */
347 /* wrap around depending on direction */
348 if (direction < 0)
349 closest = highpreset;
350 else
351 closest = lowpreset;
354 return closest;
357 static void remember_frequency(void)
359 const struct fm_region_data * const fmr =
360 &fm_region_data[global_settings.fm_region];
361 global_status.last_frequency = (curr_freq - fmr->freq_min)
362 / fmr->freq_step;
363 status_save();
366 static void next_preset(int direction)
368 if (num_presets < 1)
369 return;
371 if (curr_preset == -1)
372 curr_preset = find_closest_preset(curr_freq, direction);
373 else
374 curr_preset = (curr_preset + direction + num_presets) % num_presets;
376 /* Must stay on the current grid for the region */
377 curr_freq = snap_freq_to_grid(presets[curr_preset].frequency);
379 tuner_set(RADIO_FREQUENCY, curr_freq);
380 remember_frequency();
383 /* Step to the next or previous frequency */
384 static int step_freq(int freq, int direction)
386 const struct fm_region_data * const fmr =
387 &fm_region_data[global_settings.fm_region];
389 freq += direction*fmr->freq_step;
391 /* Wrap first or snapping to grid will not let us on the band extremes */
392 if (freq > fmr->freq_max)
393 freq = direction > 0 ? fmr->freq_min : fmr->freq_max;
394 else if (freq < fmr->freq_min)
395 freq = direction < 0 ? fmr->freq_max : fmr->freq_min;
396 else
397 freq = snap_freq_to_grid(freq);
399 return freq;
402 /* Step to the next or previous station */
403 static void next_station(int direction)
405 if (direction != 0 && radio_mode != RADIO_SCAN_MODE)
407 next_preset(direction);
408 return;
411 curr_freq = step_freq(curr_freq, direction);
413 if (radio_status == FMRADIO_PLAYING)
414 tuner_set(RADIO_MUTE, 1);
416 tuner_set(RADIO_FREQUENCY, curr_freq);
418 if (radio_status == FMRADIO_PLAYING)
419 tuner_set(RADIO_MUTE, 0);
421 curr_preset = find_preset(curr_freq);
422 remember_frequency();
425 /* Ends an in-progress search */
426 static void end_search(void)
428 if (search_dir != 0 && radio_status == FMRADIO_PLAYING)
429 tuner_set(RADIO_MUTE, 0);
430 search_dir = 0;
433 /* Speak a frequency. */
434 static void talk_freq(int freq, bool enqueue)
436 freq /= 10000;
437 talk_number(freq / 100, enqueue);
438 talk_id(LANG_POINT, true);
439 talk_number(freq % 100 / 10, true);
440 if (freq % 10)
441 talk_number(freq % 10, true);
444 /* Speak a preset by number or by spelling its name, depending on settings. */
445 static void talk_preset(int preset, bool fallback, bool enqueue)
447 if (global_settings.talk_file == 1) /* number */
448 talk_number(preset + 1, enqueue);
449 else
450 { /* spell */
451 if(presets[preset].name[0])
452 talk_spell(presets[preset].name, enqueue);
453 else if(fallback)
454 talk_freq(presets[preset].frequency, enqueue);
458 int radio_screen(void)
460 char buf[MAX_PATH];
461 bool done = false;
462 int ret_val = GO_TO_ROOT;
463 int button;
464 int i;
465 bool stereo = false, last_stereo = false;
466 int fh;
467 int top_of_screen = 0;
468 bool update_screen = true;
469 bool screen_freeze = false;
470 bool keep_playing = false;
471 bool talk = false;
472 #ifdef FM_RECORD_DBLPRE
473 int lastbutton = BUTTON_NONE;
474 unsigned long rec_lastclick = 0;
475 #endif
476 #if CONFIG_CODEC != SWCODEC
477 bool have_recorded = false;
478 int timeout = current_tick + HZ/10;
479 unsigned int seconds = 0;
480 unsigned int last_seconds = 0;
481 int hours, minutes;
482 struct audio_recording_options rec_options;
483 #endif /* CONFIG_CODEC != SWCODEC */
484 #ifndef HAVE_NOISY_IDLE_MODE
485 int button_timeout = current_tick + (2*HZ);
486 #endif
487 struct viewport vp[NB_SCREENS];
488 int oldbars = 0, fmbars = VP_SB_ALLSCREENS;
489 #ifdef HAVE_BUTTONBAR
490 struct gui_buttonbar buttonbar;
491 gui_buttonbar_init(&buttonbar);
492 gui_buttonbar_set_display(&buttonbar, &(screens[SCREEN_MAIN]) );
493 #endif
495 /* change status to "in screen" */
496 in_screen = true;
498 /* always display status bar in radio screen for now */
499 FOR_NB_SCREENS(i)
500 fmbars |= VP_SB_IGNORE_SETTING(i);
501 oldbars = viewportmanager_set_statusbar(fmbars);
502 FOR_NB_SCREENS(i)
504 viewport_set_defaults(&vp[i], i);
505 #ifdef HAVE_BUTTONBAR
506 if (global_settings.buttonbar)
507 vp[i].height -= BUTTONBAR_HEIGHT;
508 #endif
509 screens[i].set_viewport(&vp[i]);
510 screens[i].stop_scroll();
511 screens[i].clear_viewport();
512 screens[i].update_viewport();
515 fh = font_get(FONT_UI)->height;
517 /* Adjust for font size, trying to center the information vertically */
518 if(fh < 10)
519 top_of_screen = 1;
521 if(num_presets <= 0)
523 memset(presets, 0, sizeof(presets));
524 radio_load_presets(global_settings.fmr_file);
527 if(radio_status == FMRADIO_OFF)
528 audio_stop();
529 #ifndef SIMULATOR
531 #if CONFIG_CODEC != SWCODEC
532 if(rec_create_directory() > 0)
533 have_recorded = true;
535 audio_init_recording(talk_get_bufsize());
537 sound_settings_apply();
538 /* Yes, we use the D/A for monitoring */
539 peak_meter_playback(true);
541 peak_meter_enabled = true;
543 rec_init_recording_options(&rec_options);
544 rec_options.rec_source = AUDIO_SRC_LINEIN;
545 rec_set_recording_options(&rec_options);
547 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN),
548 sound_default(SOUND_RIGHT_GAIN), AUDIO_GAIN_LINEIN);
550 #endif /* CONFIG_CODEC != SWCODEC */
551 #endif /* ndef SIMULATOR */
553 /* turn on radio */
554 #if CONFIG_CODEC == SWCODEC
555 audio_set_input_source(AUDIO_SRC_FMRADIO,
556 (radio_status == FMRADIO_PAUSED) ?
557 SRCF_FMRADIO_PAUSED : SRCF_FMRADIO_PLAYING);
558 #else
559 if (radio_status == FMRADIO_OFF)
560 radio_start();
561 #endif
563 if(num_presets < 1 && yesno_pop(ID2P(LANG_FM_FIRST_AUTOSCAN)))
564 scan_presets(vp);
566 curr_preset = find_preset(curr_freq);
567 if(curr_preset != -1)
568 radio_mode = RADIO_PRESET_MODE;
570 #ifdef HAVE_BUTTONBAR
571 gui_buttonbar_set(&buttonbar, str(LANG_BUTTONBAR_MENU),
572 str(LANG_PRESET), str(LANG_FM_BUTTONBAR_RECORD));
573 #endif
575 #ifndef HAVE_NOISY_IDLE_MODE
576 cpu_idle_mode(true);
577 #endif
579 while(!done)
581 if(search_dir != 0)
583 curr_freq = step_freq(curr_freq, search_dir);
584 update_screen = true;
586 if(tuner_set(RADIO_SCAN_FREQUENCY, curr_freq))
588 curr_preset = find_preset(curr_freq);
589 remember_frequency();
590 end_search();
591 talk = true;
594 trigger_cpu_boost();
597 if (!update_screen)
599 cancel_cpu_boost();
602 #if CONFIG_CODEC != SWCODEC
603 /* TODO: Can we timeout at HZ when recording since peaks aren't
604 displayed? This should quiet recordings too. */
605 button = get_action(CONTEXT_FM,
606 update_screen ? TIMEOUT_NOBLOCK : HZ / PEAK_METER_FPS);
607 #else
608 button = get_action(CONTEXT_FM,
609 update_screen ? TIMEOUT_NOBLOCK : HZ);
610 #endif
612 #ifndef HAVE_NOISY_IDLE_MODE
613 if (button != ACTION_NONE)
615 cpu_idle_mode(false);
616 button_timeout = current_tick + (2*HZ);
618 #endif
619 switch(button)
621 case ACTION_FM_STOP:
622 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
623 if(audio_status() == AUDIO_STATUS_RECORD)
625 audio_stop();
627 else
628 #endif
630 done = true;
631 if(presets_changed)
633 if(yesno_pop(ID2P(LANG_FM_SAVE_CHANGES)))
635 if(filepreset[0] == '\0')
636 save_preset_list();
637 else
638 radio_save_presets();
641 /* Clear the preset list on exit. */
642 clear_preset_list();
644 update_screen = true;
645 break;
647 #ifdef FM_RECORD
648 case ACTION_FM_RECORD:
649 #ifdef FM_RECORD_DBLPRE
650 if (lastbutton != ACTION_FM_RECORD_DBLPRE)
652 rec_lastclick = 0;
653 break;
655 if (current_tick - rec_lastclick > HZ/2)
657 rec_lastclick = current_tick;
658 break;
660 #endif /* FM_RECORD_DBLPRE */
661 #ifndef SIMULATOR
662 if(audio_status() == AUDIO_STATUS_RECORD)
664 rec_command(RECORDING_CMD_START_NEWFILE);
665 update_screen = true;
667 else
669 have_recorded = true;
670 rec_command(RECORDING_CMD_START);
671 update_screen = true;
673 #endif /* SIMULATOR */
674 last_seconds = 0;
675 break;
676 #endif /* #ifdef FM_RECORD */
678 case ACTION_FM_EXIT:
679 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
680 if(audio_status() == AUDIO_STATUS_RECORD)
681 audio_stop();
682 #endif
683 keep_playing = true;
684 done = true;
685 ret_val = GO_TO_ROOT;
686 if(presets_changed)
688 if(yesno_pop(ID2P(LANG_FM_SAVE_CHANGES)))
690 if(filepreset[0] == '\0')
691 save_preset_list();
692 else
693 radio_save_presets();
697 /* Clear the preset list on exit. */
698 clear_preset_list();
700 break;
702 case ACTION_STD_PREV:
703 case ACTION_STD_NEXT:
704 next_station(button == ACTION_STD_PREV ? -1 : 1);
705 end_search();
706 update_screen = true;
707 talk = true;
708 break;
710 case ACTION_STD_PREVREPEAT:
711 case ACTION_STD_NEXTREPEAT:
713 int dir = search_dir;
714 search_dir = button == ACTION_STD_PREVREPEAT ? -1 : 1;
715 if (radio_mode != RADIO_SCAN_MODE)
717 next_preset(search_dir);
718 end_search();
719 update_screen = true;
720 talk = true;
722 else if (dir == 0)
724 /* Starting auto scan */
725 tuner_set(RADIO_MUTE, 1);
726 update_screen = true;
728 break;
731 case ACTION_SETTINGS_INC:
732 case ACTION_SETTINGS_INCREPEAT:
733 global_settings.volume++;
734 setvol();
735 update_screen = true;
736 break;
738 case ACTION_SETTINGS_DEC:
739 case ACTION_SETTINGS_DECREPEAT:
740 global_settings.volume--;
741 setvol();
742 update_screen = true;
743 break;
745 case ACTION_FM_PLAY:
746 if (radio_status == FMRADIO_PLAYING)
747 radio_pause();
748 else
749 radio_start();
751 update_screen = true;
752 talk = false;
753 talk_shutup();
754 break;
756 case ACTION_FM_MENU:
757 viewportmanager_set_statusbar(oldbars);
758 radio_menu();
759 curr_preset = find_preset(curr_freq);
760 viewportmanager_set_statusbar(fmbars);
761 FOR_NB_SCREENS(i)
763 screens[i].set_viewport(&vp[i]);
764 screens[i].clear_viewport();
765 screens[i].update_viewport();
766 screens[i].set_viewport(NULL);
768 #ifdef HAVE_BUTTONBAR
769 gui_buttonbar_set(&buttonbar, str(LANG_BUTTONBAR_MENU),
770 str(LANG_PRESET),
771 str(LANG_FM_BUTTONBAR_RECORD));
772 #endif
773 update_screen = true;
774 break;
776 #ifdef FM_PRESET
777 case ACTION_FM_PRESET:
778 if(num_presets < 1)
780 splash(HZ, ID2P(LANG_FM_NO_PRESETS));
781 update_screen = true;
782 FOR_NB_SCREENS(i)
784 screens[i].set_viewport(&vp[i]);
785 screens[i].clear_viewport();
786 screens[i].update_viewport();
787 screens[i].set_viewport(NULL);
790 break;
792 viewportmanager_set_statusbar(oldbars);
793 handle_radio_presets();
794 viewportmanager_set_statusbar(fmbars);
795 FOR_NB_SCREENS(i)
797 screens[i].set_viewport(&vp[i]);
798 screens[i].stop_scroll();
799 screens[i].clear_viewport();
800 screens[i].update_viewport();
801 screens[i].set_viewport(NULL);
803 #ifdef HAVE_BUTTONBAR
804 gui_buttonbar_set(&buttonbar,
805 str(LANG_BUTTONBAR_MENU),
806 str(LANG_PRESET),
807 str(LANG_FM_BUTTONBAR_RECORD));
808 #endif
809 update_screen = true;
810 break;
811 #endif /* FM_PRESET */
813 #ifdef FM_FREEZE
814 case ACTION_FM_FREEZE:
815 if(!screen_freeze)
817 splash(HZ, str(LANG_FM_FREEZE));
818 screen_freeze = true;
820 else
822 update_screen = true;
823 screen_freeze = false;
825 break;
826 #endif /* FM_FREEZE */
828 case SYS_USB_CONNECTED:
829 #if CONFIG_CODEC != SWCODEC
830 /* Only accept USB connection when not recording */
831 if(audio_status() != AUDIO_STATUS_RECORD)
832 #endif
834 default_event_handler(SYS_USB_CONNECTED);
835 screen_freeze = true; /* Cosmetic: makes sure the
836 radio screen doesn't redraw */
837 done = true;
839 break;
841 #ifdef FM_MODE
842 case ACTION_FM_MODE:
843 if(radio_mode == RADIO_SCAN_MODE)
845 /* Force scan mode if there are no presets. */
846 if(num_presets > 0)
847 radio_mode = RADIO_PRESET_MODE;
849 else
850 radio_mode = RADIO_SCAN_MODE;
851 update_screen = true;
852 cond_talk_ids_fq(radio_mode ?
853 LANG_PRESET : LANG_RADIO_SCAN_MODE);
854 talk = true;
855 break;
856 #endif /* FM_MODE */
858 #ifdef FM_NEXT_PRESET
859 case ACTION_FM_NEXT_PRESET:
860 next_preset(1);
861 end_search();
862 update_screen = true;
863 talk = true;
864 break;
865 #endif
867 #ifdef FM_PREV_PRESET
868 case ACTION_FM_PREV_PRESET:
869 next_preset(-1);
870 end_search();
871 update_screen = true;
872 talk = true;
873 break;
874 #endif
876 default:
877 default_event_handler(button);
878 break;
879 } /*switch(button)*/
881 #ifdef FM_RECORD_DBLPRE
882 if (button != ACTION_NONE)
883 lastbutton = button;
884 #endif
886 #if CONFIG_CODEC != SWCODEC
887 peak_meter_peek();
888 #endif
890 if(!screen_freeze)
892 /* Only display the peak meter when not recording */
893 #if CONFIG_CODEC != SWCODEC
894 if(!audio_status())
896 FOR_NB_SCREENS(i)
898 screens[i].set_viewport(&vp[i]);
899 peak_meter_screen(&screens[i],0,
900 STATUSBAR_HEIGHT + fh*(top_of_screen + 4),
901 fh);
902 screens[i].update_rect(0,
903 STATUSBAR_HEIGHT + fh*(top_of_screen + 4),
904 screens[i].getwidth(), fh);
905 screens[i].set_viewport(NULL);
909 if(TIME_AFTER(current_tick, timeout))
911 timeout = current_tick + HZ;
912 #else /* SWCODEC */
914 #endif /* CONFIG_CODEC == SWCODEC */
916 /* keep "mono" from always being displayed when paused */
917 if (radio_status != FMRADIO_PAUSED)
919 stereo = tuner_get(RADIO_STEREO) &&
920 !global_settings.fm_force_mono;
922 if(stereo != last_stereo)
924 update_screen = true;
925 last_stereo = stereo;
930 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
931 seconds = audio_recorded_time() / HZ;
932 if (update_screen || seconds > last_seconds)
934 last_seconds = seconds;
935 #else
936 if (update_screen)
938 #endif
939 int freq;
941 FOR_NB_SCREENS(i)
943 screens[i].set_viewport(&vp[i]);
946 snprintf(buf, 128, curr_preset >= 0 ? "%d. %s" : " ",
947 curr_preset + 1, presets[curr_preset].name);
949 FOR_NB_SCREENS(i)
950 screens[i].puts_scroll(0, top_of_screen, buf);
952 freq = curr_freq / 10000;
953 snprintf(buf, 128, str(LANG_FM_STATION),
954 freq / 100, freq % 100);
955 FOR_NB_SCREENS(i)
956 screens[i].puts_scroll(0, top_of_screen + 1, buf);
958 snprintf(buf, 128, "%s", stereo?str(LANG_CHANNEL_STEREO):
959 str(LANG_CHANNEL_MONO));
960 FOR_NB_SCREENS(i)
961 screens[i].puts_scroll(0, top_of_screen + 2, buf);
963 snprintf(buf, 128, "%s %s", str(LANG_MODE),
964 radio_mode ? str(LANG_PRESET) :
965 str(LANG_RADIO_SCAN_MODE));
966 FOR_NB_SCREENS(i)
967 screens[i].puts_scroll(0, top_of_screen + 3, buf);
969 #if CONFIG_CODEC != SWCODEC
970 if(audio_status() == AUDIO_STATUS_RECORD)
972 hours = seconds / 3600;
973 minutes = (seconds - (hours * 3600)) / 60;
974 snprintf(buf, 32, "%s %02d:%02d:%02d",
975 str(LANG_RECORDING_TIME),
976 hours, minutes, seconds%60);
977 FOR_NB_SCREENS(i)
978 screens[i].puts_scroll(0, top_of_screen + 4, buf);
980 else
982 if(rec_options.rec_prerecord_time)
984 snprintf(buf, 32, "%s %02d",
985 str(LANG_RECORD_PRERECORD), seconds%60);
986 FOR_NB_SCREENS(i)
987 screens[i].puts_scroll(0, top_of_screen + 4, buf);
990 #endif /* CONFIG_CODEC != SWCODEC */
992 FOR_NB_SCREENS(i)
994 screens[i].update_viewport();
995 screens[i].set_viewport(NULL);
998 #ifdef HAVE_BUTTONBAR
999 gui_buttonbar_draw(&buttonbar);
1000 #endif
1004 update_screen = false;
1006 if (global_settings.talk_file && talk
1007 && radio_status == FMRADIO_PAUSED)
1009 talk = false;
1010 bool enqueue = false;
1011 if (radio_mode == RADIO_SCAN_MODE)
1013 talk_freq(curr_freq, enqueue);
1014 enqueue = true;
1016 if (curr_preset >= 0)
1017 talk_preset(curr_preset, radio_mode == RADIO_PRESET_MODE,
1018 enqueue);
1021 #if CONFIG_CODEC != SWCODEC
1022 if(audio_status() & AUDIO_STATUS_ERROR)
1024 done = true;
1026 #endif
1028 #ifndef HAVE_NOISY_IDLE_MODE
1029 if (TIME_AFTER(current_tick, button_timeout))
1031 cpu_idle_mode(true);
1033 #endif
1034 } /*while(!done)*/
1036 #ifndef SIMULATOR
1037 #if CONFIG_CODEC != SWCODEC
1038 if(audio_status() & AUDIO_STATUS_ERROR)
1040 splash(0, str(LANG_DISK_FULL));
1041 FOR_NB_SCREENS(i)
1043 screens[i].set_viewport(&vp[i]);
1044 screens[i].update_viewport();
1045 screens[i].set_viewport(NULL);
1047 audio_error_clear();
1049 while(1)
1051 button = get_action(CONTEXT_FM, TIMEOUT_BLOCK);
1052 if(button == ACTION_FM_STOP)
1053 break;
1057 audio_init_playback();
1058 #endif /* CONFIG_CODEC != SWCODEC */
1060 sound_settings_apply();
1061 #endif /* SIMULATOR */
1063 if(keep_playing)
1065 /* Catch FMRADIO_PLAYING status for the sim. */
1066 #ifndef SIMULATOR
1067 #if CONFIG_CODEC != SWCODEC
1068 /* Enable the Left and right A/D Converter */
1069 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN),
1070 sound_default(SOUND_RIGHT_GAIN),
1071 AUDIO_GAIN_LINEIN);
1072 mas_codec_writereg(6, 0x4000);
1073 #endif
1074 end_search();
1075 #endif /* SIMULATOR */
1077 else
1079 #if CONFIG_CODEC == SWCODEC
1080 audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
1081 #else
1082 radio_stop();
1083 #endif
1086 #ifndef HAVE_NOISY_IDLE_MODE
1087 cpu_idle_mode(false);
1088 #endif
1090 viewportmanager_set_statusbar(oldbars);
1091 in_screen = false;
1092 #if CONFIG_CODEC != SWCODEC
1093 return have_recorded;
1094 #else
1095 return false;
1096 #endif
1097 } /* radio_screen */
1099 static void radio_save_presets(void)
1101 int fd;
1102 int i;
1104 fd = creat(filepreset);
1105 if(fd >= 0)
1107 for(i = 0;i < num_presets;i++)
1109 fdprintf(fd, "%d:%s\n", presets[i].frequency, presets[i].name);
1111 close(fd);
1113 if(!strncasecmp(FMPRESET_PATH, filepreset, strlen(FMPRESET_PATH)))
1114 set_file(filepreset, global_settings.fmr_file, MAX_FILENAME);
1115 presets_changed = false;
1117 else
1119 splash(HZ, ID2P(LANG_FM_PRESET_SAVE_FAILED));
1123 void radio_load_presets(char *filename)
1125 int fd;
1126 int rc;
1127 char buf[128];
1128 char *freq;
1129 char *name;
1130 bool done = false;
1131 int f;
1133 memset(presets, 0, sizeof(presets));
1134 num_presets = 0;
1136 /* No Preset in configuration. */
1137 if(filename[0] == '\0')
1139 filepreset[0] = '\0';
1140 return;
1142 /* Temporary preset, loaded until player shuts down. */
1143 else if(filename[0] == '/')
1144 strncpy(filepreset, filename, sizeof(filepreset));
1145 /* Preset from default directory. */
1146 else
1147 snprintf(filepreset, sizeof(filepreset), "%s/%s.fmr",
1148 FMPRESET_PATH, filename);
1150 fd = open_utf8(filepreset, O_RDONLY);
1151 if(fd >= 0)
1153 while(!done && num_presets < MAX_PRESETS)
1155 rc = read_line(fd, buf, 128);
1156 if(rc > 0)
1158 if(settings_parseline(buf, &freq, &name))
1160 f = atoi(freq);
1161 if(f) /* For backwards compatibility */
1163 struct fmstation * const fms = &presets[num_presets];
1164 fms->frequency = f;
1165 strncpy(fms->name, name, MAX_FMPRESET_LEN);
1166 fms->name[MAX_FMPRESET_LEN] = '\0';
1167 num_presets++;
1171 else
1172 done = true;
1174 close(fd);
1176 else /* invalid file name? */
1177 filepreset[0] = '\0';
1179 presets_loaded = num_presets > 0;
1180 presets_changed = false;
1184 static int radio_add_preset(void)
1186 char buf[MAX_FMPRESET_LEN + 1];
1188 if(num_presets < MAX_PRESETS)
1190 buf[0] = '\0';
1192 if (!kbd_input(buf, MAX_FMPRESET_LEN + 1))
1194 struct fmstation * const fms = &presets[num_presets];
1195 strcpy(fms->name, buf);
1196 fms->frequency = curr_freq;
1197 num_presets++;
1198 presets_changed = true;
1199 presets_loaded = num_presets > 0;
1200 return true;
1203 else
1205 splash(HZ, ID2P(LANG_FM_NO_FREE_PRESETS));
1207 return false;
1210 /* needed to know which preset we are edit/delete-ing */
1211 static int selected_preset = -1;
1212 static int radio_edit_preset(void)
1214 char buf[MAX_FMPRESET_LEN + 1];
1216 if (num_presets > 0)
1218 struct fmstation * const fms = &presets[selected_preset];
1220 strcpy(buf, fms->name);
1222 if (!kbd_input(buf, MAX_FMPRESET_LEN + 1))
1224 strcpy(fms->name, buf);
1225 presets_changed = true;
1229 return 1;
1232 static int radio_delete_preset(void)
1234 if (num_presets > 0)
1236 struct fmstation * const fms = &presets[selected_preset];
1238 if (selected_preset >= --num_presets)
1239 selected_preset = num_presets - 1;
1241 memmove(fms, fms + 1, (uintptr_t)(fms + num_presets) -
1242 (uintptr_t)fms);
1244 if (curr_preset >= num_presets)
1245 --curr_preset;
1248 /* Don't ask to save when all presets are deleted. */
1249 presets_changed = num_presets > 0;
1251 if (!presets_changed)
1253 /* The preset list will be cleared, switch to Scan Mode. */
1254 radio_mode = RADIO_SCAN_MODE;
1255 curr_preset = -1;
1256 presets_loaded = false;
1259 return 1;
1262 static int load_preset_list(void)
1264 return !rockbox_browse(FMPRESET_PATH, SHOW_FMR);
1267 static int save_preset_list(void)
1269 if(num_presets > 0)
1271 bool bad_file_name = true;
1273 if(!dir_exists(FMPRESET_PATH)) /* Check if there is preset folder */
1274 mkdir(FMPRESET_PATH);
1276 create_numbered_filename(filepreset, FMPRESET_PATH, "preset",
1277 ".fmr", 2 IF_CNFN_NUM_(, NULL));
1279 while(bad_file_name)
1281 if(!kbd_input(filepreset, sizeof(filepreset)))
1283 /* check the name: max MAX_FILENAME (20) chars */
1284 char* p2;
1285 char* p1;
1286 int len;
1287 p1 = strrchr(filepreset, '/');
1288 p2 = p1;
1289 while((p1) && (*p2) && (*p2 != '.'))
1290 p2++;
1291 len = (int)(p2-p1) - 1;
1292 if((!p1) || (len > MAX_FILENAME) || (len == 0))
1294 /* no slash, too long or too short */
1295 splash(HZ, ID2P(LANG_INVALID_FILENAME));
1297 else
1299 /* add correct extension (easier to always write)
1300 at this point, p2 points to 0 or the extension dot */
1301 *p2 = '\0';
1302 strcat(filepreset,".fmr");
1303 bad_file_name = false;
1304 radio_save_presets();
1307 else
1309 /* user aborted */
1310 return false;
1314 else
1315 splash(HZ, ID2P(LANG_FM_NO_PRESETS));
1317 return true;
1320 static int clear_preset_list(void)
1322 /* Clear all the preset entries */
1323 memset(presets, 0, sizeof (presets));
1325 num_presets = 0;
1326 presets_loaded = false;
1327 /* The preset list will be cleared switch to Scan Mode. */
1328 radio_mode = RADIO_SCAN_MODE;
1329 curr_preset = -1;
1331 presets_changed = false; /* Don't ask to save when clearing the list. */
1333 return true;
1336 MENUITEM_FUNCTION(radio_edit_preset_item, MENU_FUNC_CHECK_RETVAL,
1337 ID2P(LANG_FM_EDIT_PRESET),
1338 radio_edit_preset, NULL, NULL, Icon_NOICON);
1339 MENUITEM_FUNCTION(radio_delete_preset_item, MENU_FUNC_CHECK_RETVAL,
1340 ID2P(LANG_FM_DELETE_PRESET),
1341 radio_delete_preset, NULL, NULL, Icon_NOICON);
1342 static int radio_preset_callback(int action,
1343 const struct menu_item_ex *this_item)
1345 if (action == ACTION_STD_OK)
1346 action = ACTION_EXIT_AFTER_THIS_MENUITEM;
1347 return action;
1348 (void)this_item;
1350 MAKE_MENU(handle_radio_preset_menu, ID2P(LANG_PRESET),
1351 radio_preset_callback, Icon_NOICON, &radio_edit_preset_item,
1352 &radio_delete_preset_item);
1353 /* present a list of preset stations */
1354 static char * presets_get_name(int selected_item, void *data,
1355 char *buffer, size_t buffer_len)
1357 (void)data;
1358 struct fmstation *p = &presets[selected_item];
1359 if(p->name[0])
1360 return p->name;
1361 int freq = p->frequency / 10000;
1362 int frac = freq % 100;
1363 freq /= 100;
1364 snprintf(buffer, buffer_len,
1365 str(LANG_FM_DEFAULT_PRESET_NAME), freq, frac);
1366 return buffer;
1369 static int presets_speak_name(int selected_item, void * data)
1371 (void)data;
1372 talk_preset(selected_item, true, false);
1373 return 0;
1376 static int handle_radio_presets(void)
1378 struct gui_synclist lists;
1379 int result = 0;
1380 int action = ACTION_NONE;
1381 #ifdef HAVE_BUTTONBAR
1382 struct gui_buttonbar buttonbar;
1383 #endif
1385 if(presets_loaded == false)
1386 return result;
1388 #ifdef HAVE_BUTTONBAR
1389 gui_buttonbar_init(&buttonbar);
1390 gui_buttonbar_set_display(&buttonbar, &(screens[SCREEN_MAIN]) );
1391 gui_buttonbar_set(&buttonbar, str(LANG_FM_BUTTONBAR_ADD),
1392 str(LANG_FM_BUTTONBAR_EXIT),
1393 str(LANG_FM_BUTTONBAR_ACTION));
1394 gui_buttonbar_draw(&buttonbar);
1395 #endif
1396 gui_synclist_init(&lists, presets_get_name, NULL, false, 1, NULL);
1397 gui_synclist_set_title(&lists, str(LANG_PRESET), NOICON);
1398 gui_synclist_set_icon_callback(&lists, NULL);
1399 if(global_settings.talk_file)
1400 gui_synclist_set_voice_callback(&lists, presets_speak_name);
1401 gui_synclist_set_nb_items(&lists, num_presets);
1402 gui_synclist_select_item(&lists, curr_preset<0 ? 0 : curr_preset);
1403 gui_synclist_speak_item(&lists);
1405 while (result == 0)
1407 gui_synclist_draw(&lists);
1408 list_do_action(CONTEXT_STD, TIMEOUT_BLOCK,
1409 &lists, &action, LIST_WRAP_UNLESS_HELD);
1410 switch (action)
1412 case ACTION_STD_MENU:
1413 if (radio_add_preset())
1415 gui_synclist_set_nb_items(&lists, num_presets);
1416 gui_synclist_select_item(&lists, num_presets - 1);
1418 break;
1419 case ACTION_STD_CANCEL:
1420 result = 1;
1421 break;
1422 case ACTION_STD_OK:
1423 curr_preset = gui_synclist_get_sel_pos(&lists);
1424 curr_freq = presets[curr_preset].frequency;
1425 next_station(0);
1426 remember_frequency();
1427 result = 1;
1428 break;
1429 case ACTION_F3:
1430 case ACTION_STD_CONTEXT:
1431 selected_preset = gui_synclist_get_sel_pos(&lists);
1432 do_menu(&handle_radio_preset_menu, NULL, NULL, false);
1433 gui_synclist_set_nb_items(&lists, num_presets);
1434 gui_synclist_select_item(&lists, selected_preset);
1435 gui_synclist_speak_item(&lists);
1436 break;
1437 default:
1438 if(default_event_handler(action) == SYS_USB_CONNECTED)
1439 result = 2;
1442 return result - 1;
1445 void toggle_mono_mode(bool mono)
1447 tuner_set(RADIO_FORCE_MONO, mono);
1450 void set_radio_region(int region)
1452 #ifdef HAVE_RADIO_REGION
1453 tuner_set(RADIO_REGION, region);
1454 #endif
1455 next_station(0);
1456 remember_frequency();
1457 (void)region;
1460 MENUITEM_SETTING(set_region, &global_settings.fm_region, NULL);
1461 MENUITEM_SETTING(force_mono, &global_settings.fm_force_mono, NULL);
1463 #ifndef FM_MODE
1464 static char* get_mode_text(int selected_item, void * data, char *buffer)
1466 (void)selected_item;
1467 (void)data;
1468 snprintf(buffer, MAX_PATH, "%s %s", str(LANG_MODE),
1469 radio_mode ? str(LANG_PRESET) :
1470 str(LANG_RADIO_SCAN_MODE));
1471 return buffer;
1473 static int toggle_radio_mode(void)
1475 radio_mode = (radio_mode == RADIO_SCAN_MODE) ?
1476 RADIO_PRESET_MODE : RADIO_SCAN_MODE;
1477 return 0;
1479 MENUITEM_FUNCTION_DYNTEXT(radio_mode_item, 0,
1480 toggle_radio_mode, NULL,
1481 get_mode_text, NULL, NULL, NULL, Icon_NOICON);
1482 #endif
1484 static int scan_presets(void *viewports)
1486 bool do_scan = true;
1487 int i;
1488 struct viewport *vp = (struct viewport *)viewports;
1490 FOR_NB_SCREENS(i)
1491 screens[i].set_viewport(vp?&vp[i]:NULL);
1492 if(num_presets > 0) /* Do that to avoid 2 questions. */
1493 do_scan = yesno_pop(ID2P(LANG_FM_CLEAR_PRESETS));
1495 if(do_scan)
1497 const struct fm_region_data * const fmr =
1498 &fm_region_data[global_settings.fm_region];
1500 curr_freq = fmr->freq_min;
1501 num_presets = 0;
1502 memset(presets, 0, sizeof(presets));
1503 tuner_set(RADIO_MUTE, 1);
1505 while(curr_freq <= fmr->freq_max)
1507 int freq, frac;
1508 if(num_presets >= MAX_PRESETS || action_userabort(TIMEOUT_NOBLOCK))
1509 break;
1511 freq = curr_freq / 10000;
1512 frac = freq % 100;
1513 freq /= 100;
1515 splashf(0, str(LANG_FM_SCANNING), freq, frac);
1517 if(tuner_set(RADIO_SCAN_FREQUENCY, curr_freq))
1519 /* add preset */
1520 presets[num_presets].name[0] = '\0';
1521 presets[num_presets].frequency = curr_freq;
1522 num_presets++;
1525 curr_freq += fmr->freq_step;
1528 if (radio_status == FMRADIO_PLAYING)
1529 tuner_set(RADIO_MUTE, 0);
1531 presets_changed = true;
1533 FOR_NB_SCREENS(i)
1535 screens[i].clear_viewport();
1536 screens[i].update_viewport();
1539 if(num_presets > 0)
1541 curr_freq = presets[0].frequency;
1542 radio_mode = RADIO_PRESET_MODE;
1543 presets_loaded = true;
1544 next_station(0);
1546 else
1548 /* Wrap it to beginning or we'll be past end of band */
1549 presets_loaded = false;
1550 next_station(1);
1553 return true;
1557 #ifdef HAVE_RECORDING
1559 #if defined(HAVE_FMRADIO_REC) && CONFIG_CODEC == SWCODEC
1560 #define FM_RECORDING_SCREEN
1561 static int fm_recording_screen(void)
1563 bool ret;
1565 /* switch recording source to FMRADIO for the duration */
1566 int rec_source = global_settings.rec_source;
1567 global_settings.rec_source = AUDIO_SRC_FMRADIO;
1569 ret = recording_screen(true);
1571 /* safe to reset as changing sources is prohibited here */
1572 global_settings.rec_source = rec_source;
1574 return ret;
1577 #endif /* defined(HAVE_FMRADIO_REC) && CONFIG_CODEC == SWCODEC */
1579 #if defined(HAVE_FMRADIO_REC) || CONFIG_CODEC != SWCODEC
1580 #define FM_RECORDING_SETTINGS
1581 static int fm_recording_settings(void)
1583 bool ret = recording_menu(true);
1585 #if CONFIG_CODEC != SWCODEC
1586 if (!ret)
1588 struct audio_recording_options rec_options;
1589 rec_init_recording_options(&rec_options);
1590 rec_options.rec_source = AUDIO_SRC_LINEIN;
1591 rec_set_recording_options(&rec_options);
1593 #endif
1595 return ret;
1598 #endif /* defined(HAVE_FMRADIO_REC) || CONFIG_CODEC != SWCODEC */
1599 #endif /* HAVE_RECORDING */
1601 #ifdef FM_RECORDING_SCREEN
1602 MENUITEM_FUNCTION(recscreen_item, 0, ID2P(LANG_RECORDING),
1603 fm_recording_screen, NULL, NULL, Icon_Recording);
1604 #endif
1605 #ifdef FM_RECORDING_SETTINGS
1606 MENUITEM_FUNCTION(recsettings_item, 0, ID2P(LANG_RECORDING_SETTINGS),
1607 fm_recording_settings, NULL, NULL, Icon_Recording);
1608 #endif
1609 #ifndef FM_PRESET
1610 MENUITEM_FUNCTION(radio_presets_item, 0, ID2P(LANG_PRESET),
1611 handle_radio_presets, NULL, NULL, Icon_NOICON);
1612 #endif
1613 #ifndef FM_PRESET_ADD
1614 MENUITEM_FUNCTION(radio_addpreset_item, 0, ID2P(LANG_FM_ADD_PRESET),
1615 radio_add_preset, NULL, NULL, Icon_NOICON);
1616 #endif
1619 MENUITEM_FUNCTION(presetload_item, 0, ID2P(LANG_FM_PRESET_LOAD),
1620 load_preset_list, NULL, NULL, Icon_NOICON);
1621 MENUITEM_FUNCTION(presetsave_item, 0, ID2P(LANG_FM_PRESET_SAVE),
1622 save_preset_list, NULL, NULL, Icon_NOICON);
1623 MENUITEM_FUNCTION(presetclear_item, 0, ID2P(LANG_FM_PRESET_CLEAR),
1624 clear_preset_list, NULL, NULL, Icon_NOICON);
1625 MENUITEM_FUNCTION(scan_presets_item, MENU_FUNC_USEPARAM,
1626 ID2P(LANG_FM_SCAN_PRESETS),
1627 scan_presets, NULL, NULL, Icon_NOICON);
1629 MAKE_MENU(radio_settings_menu, ID2P(LANG_FM_MENU), NULL,
1630 Icon_Radio_screen,
1631 #ifndef FM_PRESET
1632 &radio_presets_item,
1633 #endif
1634 #ifndef FM_PRESET_ADD
1635 &radio_addpreset_item,
1636 #endif
1637 &presetload_item, &presetsave_item, &presetclear_item,
1638 &force_mono,
1639 #ifndef FM_MODE
1640 &radio_mode_item,
1641 #endif
1642 &set_region, &sound_settings,
1643 #ifdef FM_RECORDING_SCREEN
1644 &recscreen_item,
1645 #endif
1646 #ifdef FM_RECORDING_SETTINGS
1647 &recsettings_item,
1648 #endif
1649 &scan_presets_item);
1650 /* main menu of the radio screen */
1651 static bool radio_menu(void)
1653 return do_menu(&radio_settings_menu, NULL, NULL, false) ==
1654 MENU_ATTACHED_USB;
1657 #endif