1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
32 #include "mp3_playback.h"
37 #include "string-extra.h"
44 #include "peakmeter.h"
47 #include "sound_menu.h"
49 #include "recording.h"
51 #ifdef IPOD_ACCESSORY_PROTOCOL
54 #include "appevents.h"
59 #include "screen_access.h"
62 #include "buttonbar.h"
67 #include "menus/exported_menus.h"
68 #include "root_menu.h"
70 #include "skin_engine/skin_engine.h"
71 #include "statusbar-skinned.h"
72 #include "buffering.h"
76 #if CONFIG_KEYPAD == RECORDER_PAD
79 #define FM_PRESET_ACTION
83 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
86 #define FM_NEXT_PRESET
87 #define FM_PREV_PRESET
89 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
93 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
96 /* This should be removeable if the whole tuning thing is sorted out since
97 proper tuning quiets the screen almost entirely in that extreme measures
98 have to be taken to hear any interference. */
99 #define HAVE_NOISY_IDLE_MODE
101 #elif CONFIG_KEYPAD == ONDIO_PAD
102 #define FM_RECORD_DBLPRE
104 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || (CONFIG_KEYPAD == SANSA_C200_PAD)
112 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
116 #elif (CONFIG_KEYPAD == COWON_D2_PAD)
124 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
125 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
134 /* presets.c needs these so keep unstatic or redo the whole thing! */
135 int curr_freq
; /* current frequency in Hz */
136 /* these are all in presets.c... someone PLEASE rework this ! */
137 int handle_radio_presets(void);
138 static bool radio_menu(void);
139 int radio_add_preset(void);
140 int save_preset_list(void);
141 int load_preset_list(void);
142 int clear_preset_list(void);
143 void next_preset(int direction
);
144 void set_current_preset(int preset
);
145 int scan_presets(void *viewports
);
146 int find_preset(int freq
);
147 void radio_save_presets(void);
148 bool has_presets_changed(void);
149 void talk_preset(int preset
, bool fallback
, bool enqueue
);
150 void presets_save(void);
154 int radio_mode
= RADIO_SCAN_MODE
;
155 static int search_dir
= 0;
157 static int radio_status
= FMRADIO_OFF
;
158 static bool in_screen
= false;
161 static void radio_off(void);
163 bool radio_scan_mode(void)
165 return radio_mode
== RADIO_SCAN_MODE
;
168 bool radio_is_stereo(void)
170 return tuner_get(RADIO_STEREO
) && !global_settings
.fm_force_mono
;
172 int radio_current_frequency(void)
177 /* Function to manipulate all yesno dialogues.
178 This function needs the output text as an argument. */
179 bool yesno_pop(const char* text
)
182 const char *lines
[]={text
};
183 const struct text_message message
={lines
, 1};
184 bool ret
= (gui_syncyesno_run(&message
,NULL
,NULL
)== YESNO_YES
);
186 screens
[i
].clear_viewport();
190 void radio_init(void)
195 radioart_init(false);
199 int get_radio_status(void)
204 bool in_radio_screen(void)
209 /* TODO: Move some more of the control functionality to firmware
210 and clean up the mess */
212 /* secret flag for starting paused - prevents unmute */
213 #define FMRADIO_START_PAUSED 0x8000
214 void radio_start(void)
216 const struct fm_region_data
*fmr
;
219 if(radio_status
== FMRADIO_PLAYING
)
222 fmr
= &fm_region_data
[global_settings
.fm_region
];
224 start_paused
= radio_status
& FMRADIO_START_PAUSED
;
225 /* clear flag before any yielding */
226 radio_status
&= ~FMRADIO_START_PAUSED
;
228 if(radio_status
== FMRADIO_OFF
)
231 curr_freq
= global_status
.last_frequency
* fmr
->freq_step
+ fmr
->freq_min
;
233 tuner_set(RADIO_SLEEP
, 0); /* wake up the tuner */
235 if(radio_status
== FMRADIO_OFF
)
237 #ifdef HAVE_RADIO_REGION
238 tuner_set(RADIO_REGION
, global_settings
.fm_region
);
240 tuner_set(RADIO_FORCE_MONO
, global_settings
.fm_force_mono
);
243 tuner_set(RADIO_FREQUENCY
, curr_freq
);
245 #ifdef HAVE_RADIO_MUTE_TIMEOUT
247 unsigned long mute_timeout
= current_tick
+ HZ
;
248 if (radio_status
!= FMRADIO_OFF
)
254 while(!tuner_get(RADIO_STEREO
) && !tuner_get(RADIO_TUNED
))
256 if(TIME_AFTER(current_tick
, mute_timeout
))
263 /* keep radio from sounding initially */
265 tuner_set(RADIO_MUTE
, 0);
267 radio_status
= FMRADIO_PLAYING
;
270 void radio_pause(void)
272 if(radio_status
== FMRADIO_PAUSED
)
275 if(radio_status
== FMRADIO_OFF
)
277 radio_status
|= FMRADIO_START_PAUSED
;
281 tuner_set(RADIO_MUTE
, 1);
282 /* For si4700: 2==this is really 'pause'. other tuners treat it
284 tuner_set(RADIO_SLEEP
, 2);
286 radio_status
= FMRADIO_PAUSED
;
289 static void radio_off(void)
291 tuner_set(RADIO_MUTE
, 1);
292 tuner_set(RADIO_SLEEP
, 1); /* low power mode, if available */
293 radio_status
= FMRADIO_OFF
;
294 tuner_power(false); /* status update, power off if avail. */
297 void radio_stop(void)
299 if(radio_status
== FMRADIO_OFF
)
305 bool radio_hardware_present(void)
307 return tuner_get(RADIO_PRESENT
);
310 /* Keep freq on the grid for the current region */
311 int snap_freq_to_grid(int freq
)
313 const struct fm_region_data
* const fmr
=
314 &fm_region_data
[global_settings
.fm_region
];
316 /* Range clamp if out of range or just round to nearest */
317 if (freq
< fmr
->freq_min
)
318 freq
= fmr
->freq_min
;
319 else if (freq
> fmr
->freq_max
)
320 freq
= fmr
->freq_max
;
322 freq
= (freq
- fmr
->freq_min
+ fmr
->freq_step
/2) /
323 fmr
->freq_step
* fmr
->freq_step
+ fmr
->freq_min
;
328 void remember_frequency(void)
330 const struct fm_region_data
* const fmr
=
331 &fm_region_data
[global_settings
.fm_region
];
332 global_status
.last_frequency
= (curr_freq
- fmr
->freq_min
)
337 /* Step to the next or previous frequency */
338 static int step_freq(int freq
, int direction
)
340 const struct fm_region_data
* const fmr
=
341 &fm_region_data
[global_settings
.fm_region
];
343 freq
+= direction
*fmr
->freq_step
;
345 /* Wrap first or snapping to grid will not let us on the band extremes */
346 if (freq
> fmr
->freq_max
)
347 freq
= direction
> 0 ? fmr
->freq_min
: fmr
->freq_max
;
348 else if (freq
< fmr
->freq_min
)
349 freq
= direction
< 0 ? fmr
->freq_max
: fmr
->freq_min
;
351 freq
= snap_freq_to_grid(freq
);
356 /* Step to the next or previous station */
357 void next_station(int direction
)
359 if (direction
!= 0 && radio_mode
!= RADIO_SCAN_MODE
)
361 next_preset(direction
);
365 curr_freq
= step_freq(curr_freq
, direction
);
367 if (radio_status
== FMRADIO_PLAYING
)
368 tuner_set(RADIO_MUTE
, 1);
370 tuner_set(RADIO_FREQUENCY
, curr_freq
);
372 if (radio_status
== FMRADIO_PLAYING
)
373 tuner_set(RADIO_MUTE
, 0);
375 set_current_preset(find_preset(curr_freq
));
376 remember_frequency();
379 /* Ends an in-progress search */
380 static void end_search(void)
382 if (search_dir
!= 0 && radio_status
== FMRADIO_PLAYING
)
383 tuner_set(RADIO_MUTE
, 0);
387 /* Speak a frequency. */
388 void talk_freq(int freq
, bool enqueue
)
391 talk_number(freq
/ 100, enqueue
);
392 talk_id(LANG_POINT
, true);
393 talk_number(freq
% 100 / 10, true);
395 talk_number(freq
% 10, true);
399 int radio_screen(void)
402 int ret_val
= GO_TO_ROOT
;
405 bool stereo
= false, last_stereo
= false;
406 bool update_screen
= true, restore
= true;
407 bool screen_freeze
= false;
408 bool keep_playing
= false;
410 #ifdef FM_RECORD_DBLPRE
411 int lastbutton
= BUTTON_NONE
;
412 unsigned long rec_lastclick
= 0;
414 #if CONFIG_CODEC != SWCODEC
415 bool have_recorded
= false;
416 int timeout
= current_tick
+ HZ
/10;
417 unsigned int last_seconds
= 0;
419 unsigned int seconds
= 0;
420 struct audio_recording_options rec_options
;
422 #endif /* CONFIG_CODEC != SWCODEC */
423 #ifndef HAVE_NOISY_IDLE_MODE
424 int button_timeout
= current_tick
+ (2*HZ
);
427 /* change status to "in screen" */
430 if(radio_preset_count() <= 0)
432 radio_load_presets(global_settings
.fmr_file
);
438 if(radio_status
== FMRADIO_OFF
)
443 #if CONFIG_CODEC != SWCODEC
444 if(rec_create_directory() > 0)
445 have_recorded
= true;
447 audio_init_recording(talk_get_bufsize());
449 sound_settings_apply();
450 /* Yes, we use the D/A for monitoring */
451 peak_meter_playback(true);
453 peak_meter_enable(true);
455 rec_init_recording_options(&rec_options
);
456 rec_options
.rec_source
= AUDIO_SRC_LINEIN
;
457 rec_set_recording_options(&rec_options
);
459 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN
),
460 sound_default(SOUND_RIGHT_GAIN
), AUDIO_GAIN_LINEIN
);
462 #endif /* CONFIG_CODEC != SWCODEC */
463 #endif /* ndef SIMULATOR */
466 #if CONFIG_CODEC == SWCODEC
467 /* This should be done before touching audio settings */
468 while (!audio_is_thread_ready())
471 audio_set_input_source(AUDIO_SRC_FMRADIO
,
472 (radio_status
== FMRADIO_PAUSED
) ?
473 SRCF_FMRADIO_PAUSED
: SRCF_FMRADIO_PLAYING
);
475 if (radio_status
== FMRADIO_OFF
)
479 if(radio_preset_count() < 1 && yesno_pop(ID2P(LANG_FM_FIRST_AUTOSCAN
)))
482 set_current_preset(find_preset(curr_freq
));
483 if(radio_current_preset() != -1)
484 radio_mode
= RADIO_PRESET_MODE
;
486 #ifndef HAVE_NOISY_IDLE_MODE
494 curr_freq
= step_freq(curr_freq
, search_dir
);
495 update_screen
= true;
497 if(tuner_set(RADIO_SCAN_FREQUENCY
, curr_freq
))
499 set_current_preset(find_preset(curr_freq
));
500 remember_frequency();
512 button
= fms_do_button_loop(update_screen
);
514 #ifndef HAVE_NOISY_IDLE_MODE
515 if (button
!= ACTION_NONE
)
517 cpu_idle_mode(false);
518 button_timeout
= current_tick
+ (2*HZ
);
524 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
525 if(audio_status() == AUDIO_STATUS_RECORD
)
533 if(has_presets_changed())
535 if(yesno_pop(ID2P(LANG_FM_SAVE_CHANGES
)))
541 update_screen
= true;
545 case ACTION_FM_RECORD
:
546 #ifdef FM_RECORD_DBLPRE
547 if (lastbutton
!= ACTION_FM_RECORD_DBLPRE
)
552 if (current_tick
- rec_lastclick
> HZ
/2)
554 rec_lastclick
= current_tick
;
557 #endif /* FM_RECORD_DBLPRE */
559 if(audio_status() == AUDIO_STATUS_RECORD
)
561 rec_command(RECORDING_CMD_START_NEWFILE
);
562 update_screen
= true;
566 have_recorded
= true;
567 rec_command(RECORDING_CMD_START
);
568 update_screen
= true;
570 #endif /* SIMULATOR */
573 #endif /* #ifdef FM_RECORD */
576 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
577 if(audio_status() == AUDIO_STATUS_RECORD
)
582 ret_val
= GO_TO_ROOT
;
583 if(has_presets_changed())
585 if(yesno_pop(ID2P(LANG_FM_SAVE_CHANGES
)))
593 case ACTION_STD_PREV
:
594 case ACTION_STD_NEXT
:
595 next_station(button
== ACTION_STD_PREV
? -1 : 1);
597 update_screen
= true;
601 case ACTION_STD_PREVREPEAT
:
602 case ACTION_STD_NEXTREPEAT
:
604 int dir
= search_dir
;
605 search_dir
= button
== ACTION_STD_PREVREPEAT
? -1 : 1;
606 if (radio_mode
!= RADIO_SCAN_MODE
)
608 next_preset(search_dir
);
610 update_screen
= true;
615 /* Starting auto scan */
616 tuner_set(RADIO_MUTE
, 1);
617 update_screen
= true;
622 case ACTION_SETTINGS_INC
:
623 case ACTION_SETTINGS_INCREPEAT
:
624 global_settings
.volume
++;
626 update_screen
= true;
629 case ACTION_SETTINGS_DEC
:
630 case ACTION_SETTINGS_DECREPEAT
:
631 global_settings
.volume
--;
633 update_screen
= true;
637 if (radio_status
== FMRADIO_PLAYING
)
642 update_screen
= true;
648 fms_fix_displays(FMS_EXIT
);
650 set_current_preset(find_preset(curr_freq
));
651 update_screen
= true;
656 case ACTION_FM_PRESET
:
657 if(radio_preset_count() < 1)
659 splash(HZ
, ID2P(LANG_FM_NO_PRESETS
));
660 update_screen
= true;
663 fms_fix_displays(FMS_EXIT
);
664 handle_radio_presets();
665 update_screen
= true;
668 #endif /* FM_PRESET */
671 case ACTION_FM_FREEZE
:
674 splash(HZ
, str(LANG_FM_FREEZE
));
675 screen_freeze
= true;
679 update_screen
= true;
680 screen_freeze
= false;
683 #endif /* FM_FREEZE */
685 case SYS_USB_CONNECTED
:
686 #if CONFIG_CODEC != SWCODEC
687 /* Only accept USB connection when not recording */
688 if(audio_status() != AUDIO_STATUS_RECORD
)
691 default_event_handler(SYS_USB_CONNECTED
);
692 screen_freeze
= true; /* Cosmetic: makes sure the
693 radio screen doesn't redraw */
700 if(radio_mode
== RADIO_SCAN_MODE
)
702 /* Force scan mode if there are no presets. */
703 if(radio_preset_count() > 0)
704 radio_mode
= RADIO_PRESET_MODE
;
707 radio_mode
= RADIO_SCAN_MODE
;
708 update_screen
= true;
709 cond_talk_ids_fq(radio_mode
?
710 LANG_PRESET
: LANG_RADIO_SCAN_MODE
);
715 #ifdef FM_NEXT_PRESET
716 case ACTION_FM_NEXT_PRESET
:
719 update_screen
= true;
724 #ifdef FM_PREV_PRESET
725 case ACTION_FM_PREV_PRESET
:
728 update_screen
= true;
734 default_event_handler(button
);
736 if (tuner_get(RADIO_EVENT
))
737 update_screen
= true;
739 if (!tuner_get(RADIO_PRESENT
))
741 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
742 if(audio_status() == AUDIO_STATUS_RECORD
)
745 keep_playing
= false;
747 ret_val
= GO_TO_ROOT
;
748 if(has_presets_changed())
750 if(yesno_pop(ID2P(LANG_FM_SAVE_CHANGES
)))
752 radio_save_presets();
756 /* Clear the preset list on exit. */
762 #ifdef FM_RECORD_DBLPRE
763 if (button
!= ACTION_NONE
)
767 #if CONFIG_CODEC != SWCODEC
773 /* Only display the peak meter when not recording */
774 #if CONFIG_CODEC != SWCODEC
775 if(TIME_AFTER(current_tick
, timeout
))
777 timeout
= current_tick
+ HZ
;
780 #endif /* CONFIG_CODEC == SWCODEC */
782 /* keep "mono" from always being displayed when paused */
783 if (radio_status
!= FMRADIO_PAUSED
)
785 stereo
= tuner_get(RADIO_STEREO
) &&
786 !global_settings
.fm_force_mono
;
788 if(stereo
!= last_stereo
)
790 update_screen
= true;
791 last_stereo
= stereo
;
796 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
797 seconds
= audio_recorded_time() / HZ
;
798 if (update_screen
|| seconds
> last_seconds
|| restore
)
800 last_seconds
= seconds
;
802 if (update_screen
|| restore
)
806 fms_fix_displays(FMS_ENTER
);
808 skin_update(fms_get(i
), WPS_REFRESH_ALL
);
812 update_screen
= false;
814 if (global_settings
.talk_file
&& talk
815 && radio_status
== FMRADIO_PAUSED
)
818 bool enqueue
= false;
819 if (radio_mode
== RADIO_SCAN_MODE
)
821 talk_freq(curr_freq
, enqueue
);
824 if (radio_current_preset() >= 0)
825 talk_preset(radio_current_preset(), radio_mode
== RADIO_PRESET_MODE
,
829 #if CONFIG_CODEC != SWCODEC
830 if(audio_status() & AUDIO_STATUS_ERROR
)
836 #ifndef HAVE_NOISY_IDLE_MODE
837 if (TIME_AFTER(current_tick
, button_timeout
))
845 #if CONFIG_CODEC != SWCODEC
846 if(audio_status() & AUDIO_STATUS_ERROR
)
848 splash(0, str(LANG_DISK_FULL
));
853 button
= get_action(CONTEXT_FM
, TIMEOUT_BLOCK
);
854 if(button
== ACTION_FM_STOP
)
859 audio_init_playback();
860 #endif /* CONFIG_CODEC != SWCODEC */
862 sound_settings_apply();
863 #endif /* SIMULATOR */
867 /* Catch FMRADIO_PLAYING status for the sim. */
869 #if CONFIG_CODEC != SWCODEC
870 /* Enable the Left and right A/D Converter */
871 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN
),
872 sound_default(SOUND_RIGHT_GAIN
),
874 mas_codec_writereg(6, 0x4000);
877 #endif /* SIMULATOR */
881 #if CONFIG_CODEC == SWCODEC
882 audio_set_input_source(AUDIO_SRC_PLAYBACK
, SRCF_PLAYBACK
);
888 #ifndef HAVE_NOISY_IDLE_MODE
889 cpu_idle_mode(false);
891 fms_fix_displays(FMS_EXIT
);
893 #if CONFIG_CODEC != SWCODEC
894 return have_recorded
;
900 void toggle_mono_mode(bool mono
)
902 tuner_set(RADIO_FORCE_MONO
, mono
);
905 void set_radio_region(int region
)
907 #ifdef HAVE_RADIO_REGION
908 tuner_set(RADIO_REGION
, region
);
911 remember_frequency();
915 MENUITEM_SETTING(set_region
, &global_settings
.fm_region
, NULL
);
916 MENUITEM_SETTING(force_mono
, &global_settings
.fm_force_mono
, NULL
);
919 static char* get_mode_text(int selected_item
, void * data
, char *buffer
)
923 snprintf(buffer
, MAX_PATH
, "%s %s", str(LANG_MODE
),
924 radio_mode
? str(LANG_PRESET
) :
925 str(LANG_RADIO_SCAN_MODE
));
928 static int toggle_radio_mode(void)
930 radio_mode
= (radio_mode
== RADIO_SCAN_MODE
) ?
931 RADIO_PRESET_MODE
: RADIO_SCAN_MODE
;
934 MENUITEM_FUNCTION_DYNTEXT(radio_mode_item
, 0,
935 toggle_radio_mode
, NULL
,
936 get_mode_text
, NULL
, NULL
, NULL
, Icon_NOICON
);
941 #ifdef HAVE_RECORDING
943 #if defined(HAVE_FMRADIO_REC) && CONFIG_CODEC == SWCODEC
944 #define FM_RECORDING_SCREEN
945 static int fm_recording_screen(void)
949 /* switch recording source to FMRADIO for the duration */
950 int rec_source
= global_settings
.rec_source
;
951 global_settings
.rec_source
= AUDIO_SRC_FMRADIO
;
952 ret
= recording_screen(true);
954 /* safe to reset as changing sources is prohibited here */
955 global_settings
.rec_source
= rec_source
;
960 #endif /* defined(HAVE_FMRADIO_REC) && CONFIG_CODEC == SWCODEC */
962 #if defined(HAVE_FMRADIO_REC) || CONFIG_CODEC != SWCODEC
963 #define FM_RECORDING_SETTINGS
964 static int fm_recording_settings(void)
966 bool ret
= recording_menu(true);
968 #if CONFIG_CODEC != SWCODEC
971 struct audio_recording_options rec_options
;
972 rec_init_recording_options(&rec_options
);
973 rec_options
.rec_source
= AUDIO_SRC_LINEIN
;
974 rec_set_recording_options(&rec_options
);
981 #endif /* defined(HAVE_FMRADIO_REC) || CONFIG_CODEC != SWCODEC */
982 #endif /* HAVE_RECORDING */
984 #ifdef FM_RECORDING_SCREEN
985 MENUITEM_FUNCTION(recscreen_item
, 0, ID2P(LANG_RECORDING
),
986 fm_recording_screen
, NULL
, NULL
, Icon_Recording
);
988 #ifdef FM_RECORDING_SETTINGS
989 MENUITEM_FUNCTION(recsettings_item
, 0, ID2P(LANG_RECORDING_SETTINGS
),
990 fm_recording_settings
, NULL
, NULL
, Icon_Recording
);
993 int handle_radio_presets_menu(void)
995 return handle_radio_presets();
997 MENUITEM_FUNCTION(radio_presets_item
, 0, ID2P(LANG_PRESET
),
998 handle_radio_presets_menu
, NULL
, NULL
, Icon_NOICON
);
1000 #ifndef FM_PRESET_ADD
1001 int handle_radio_addpreset_menu(void)
1003 return radio_add_preset();
1005 MENUITEM_FUNCTION(radio_addpreset_item
, 0, ID2P(LANG_FM_ADD_PRESET
),
1006 radio_add_preset
, NULL
, NULL
, Icon_NOICON
);
1010 MENUITEM_FUNCTION(presetload_item
, 0, ID2P(LANG_FM_PRESET_LOAD
),
1011 load_preset_list
, NULL
, NULL
, Icon_NOICON
);
1012 MENUITEM_FUNCTION(presetsave_item
, 0, ID2P(LANG_FM_PRESET_SAVE
),
1013 save_preset_list
, NULL
, NULL
, Icon_NOICON
);
1014 MENUITEM_FUNCTION(presetclear_item
, 0, ID2P(LANG_FM_PRESET_CLEAR
),
1015 clear_preset_list
, NULL
, NULL
, Icon_NOICON
);
1016 MENUITEM_FUNCTION(scan_presets_item
, MENU_FUNC_USEPARAM
,
1017 ID2P(LANG_FM_SCAN_PRESETS
),
1018 scan_presets
, NULL
, NULL
, Icon_NOICON
);
1020 MAKE_MENU(radio_settings_menu
, ID2P(LANG_FM_MENU
), NULL
,
1023 &radio_presets_item
,
1025 #ifndef FM_PRESET_ADD
1026 &radio_addpreset_item
,
1028 &presetload_item
, &presetsave_item
, &presetclear_item
,
1033 &set_region
, &sound_settings
,
1034 #ifdef FM_RECORDING_SCREEN
1037 #ifdef FM_RECORDING_SETTINGS
1040 &scan_presets_item
);
1041 /* main menu of the radio screen */
1042 static bool radio_menu(void)
1044 return do_menu(&radio_settings_menu
, NULL
, NULL
, false) ==