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"
73 #if CONFIG_CODEC == SWCODEC
79 #if CONFIG_KEYPAD == RECORDER_PAD
82 #define FM_PRESET_ACTION
86 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
89 #define FM_NEXT_PRESET
90 #define FM_PREV_PRESET
92 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
96 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
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
107 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || (CONFIG_KEYPAD == SANSA_C200_PAD)
115 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
119 #elif (CONFIG_KEYPAD == COWON_D2_PAD)
127 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
128 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
137 /* presets.c needs these so keep unstatic or redo the whole thing! */
138 int curr_freq
; /* current frequency in Hz */
139 /* these are all in presets.c... someone PLEASE rework this ! */
140 int handle_radio_presets(void);
141 static bool radio_menu(void);
142 int radio_add_preset(void);
143 int save_preset_list(void);
144 int load_preset_list(void);
145 int clear_preset_list(void);
146 void next_preset(int direction
);
147 void set_current_preset(int preset
);
148 int scan_presets(void *viewports
);
149 int find_preset(int freq
);
150 void radio_save_presets(void);
151 bool has_presets_changed(void);
152 void talk_preset(int preset
, bool fallback
, bool enqueue
);
153 void presets_save(void);
157 int radio_mode
= RADIO_SCAN_MODE
;
158 static int search_dir
= 0;
160 static int radio_status
= FMRADIO_OFF
;
161 static bool in_screen
= false;
164 static void radio_off(void);
166 bool radio_scan_mode(void)
168 return radio_mode
== RADIO_SCAN_MODE
;
171 bool radio_is_stereo(void)
173 return tuner_get(RADIO_STEREO
) && !global_settings
.fm_force_mono
;
175 int radio_current_frequency(void)
180 /* Function to manipulate all yesno dialogues.
181 This function needs the output text as an argument. */
182 bool yesno_pop(const char* text
)
185 const char *lines
[]={text
};
186 const struct text_message message
={lines
, 1};
187 bool ret
= (gui_syncyesno_run(&message
,NULL
,NULL
)== YESNO_YES
);
189 screens
[i
].clear_viewport();
193 void radio_init(void)
198 radioart_init(false);
202 int get_radio_status(void)
207 bool in_radio_screen(void)
212 /* TODO: Move some more of the control functionality to firmware
213 and clean up the mess */
215 /* secret flag for starting paused - prevents unmute */
216 #define FMRADIO_START_PAUSED 0x8000
217 void radio_start(void)
219 const struct fm_region_data
*fmr
;
222 if(radio_status
== FMRADIO_PLAYING
)
225 fmr
= &fm_region_data
[global_settings
.fm_region
];
227 start_paused
= radio_status
& FMRADIO_START_PAUSED
;
228 /* clear flag before any yielding */
229 radio_status
&= ~FMRADIO_START_PAUSED
;
231 if(radio_status
== FMRADIO_OFF
)
234 curr_freq
= global_status
.last_frequency
* fmr
->freq_step
+ fmr
->freq_min
;
236 tuner_set(RADIO_SLEEP
, 0); /* wake up the tuner */
238 if(radio_status
== FMRADIO_OFF
)
240 #ifdef HAVE_RADIO_REGION
241 tuner_set(RADIO_REGION
, global_settings
.fm_region
);
243 tuner_set(RADIO_FORCE_MONO
, global_settings
.fm_force_mono
);
246 tuner_set(RADIO_FREQUENCY
, curr_freq
);
248 #ifdef HAVE_RADIO_MUTE_TIMEOUT
250 unsigned long mute_timeout
= current_tick
+ HZ
;
251 if (radio_status
!= FMRADIO_OFF
)
257 while(!tuner_get(RADIO_STEREO
) && !tuner_get(RADIO_TUNED
))
259 if(TIME_AFTER(current_tick
, mute_timeout
))
266 /* keep radio from sounding initially */
268 tuner_set(RADIO_MUTE
, 0);
270 radio_status
= FMRADIO_PLAYING
;
273 void radio_pause(void)
275 if(radio_status
== FMRADIO_PAUSED
)
278 if(radio_status
== FMRADIO_OFF
)
280 radio_status
|= FMRADIO_START_PAUSED
;
284 tuner_set(RADIO_MUTE
, 1);
285 /* For si4700: 2==this is really 'pause'. other tuners treat it
287 tuner_set(RADIO_SLEEP
, 2);
289 radio_status
= FMRADIO_PAUSED
;
292 static void radio_off(void)
294 tuner_set(RADIO_MUTE
, 1);
295 tuner_set(RADIO_SLEEP
, 1); /* low power mode, if available */
296 radio_status
= FMRADIO_OFF
;
297 tuner_power(false); /* status update, power off if avail. */
300 void radio_stop(void)
302 if(radio_status
== FMRADIO_OFF
)
308 bool radio_hardware_present(void)
310 return tuner_get(RADIO_PRESENT
);
313 /* Keep freq on the grid for the current region */
314 int snap_freq_to_grid(int freq
)
316 const struct fm_region_data
* const fmr
=
317 &fm_region_data
[global_settings
.fm_region
];
319 /* Range clamp if out of range or just round to nearest */
320 if (freq
< fmr
->freq_min
)
321 freq
= fmr
->freq_min
;
322 else if (freq
> fmr
->freq_max
)
323 freq
= fmr
->freq_max
;
325 freq
= (freq
- fmr
->freq_min
+ fmr
->freq_step
/2) /
326 fmr
->freq_step
* fmr
->freq_step
+ fmr
->freq_min
;
331 void remember_frequency(void)
333 const struct fm_region_data
* const fmr
=
334 &fm_region_data
[global_settings
.fm_region
];
335 global_status
.last_frequency
= (curr_freq
- fmr
->freq_min
)
340 /* Step to the next or previous frequency */
341 static int step_freq(int freq
, int direction
)
343 const struct fm_region_data
* const fmr
=
344 &fm_region_data
[global_settings
.fm_region
];
346 freq
+= direction
*fmr
->freq_step
;
348 /* Wrap first or snapping to grid will not let us on the band extremes */
349 if (freq
> fmr
->freq_max
)
350 freq
= direction
> 0 ? fmr
->freq_min
: fmr
->freq_max
;
351 else if (freq
< fmr
->freq_min
)
352 freq
= direction
< 0 ? fmr
->freq_max
: fmr
->freq_min
;
354 freq
= snap_freq_to_grid(freq
);
359 /* Step to the next or previous station */
360 void next_station(int direction
)
362 if (direction
!= 0 && radio_mode
!= RADIO_SCAN_MODE
)
364 next_preset(direction
);
368 curr_freq
= step_freq(curr_freq
, direction
);
370 if (radio_status
== FMRADIO_PLAYING
)
371 tuner_set(RADIO_MUTE
, 1);
373 tuner_set(RADIO_FREQUENCY
, curr_freq
);
375 if (radio_status
== FMRADIO_PLAYING
)
376 tuner_set(RADIO_MUTE
, 0);
378 set_current_preset(find_preset(curr_freq
));
379 remember_frequency();
382 /* Ends an in-progress search */
383 static void end_search(void)
385 if (search_dir
!= 0 && radio_status
== FMRADIO_PLAYING
)
386 tuner_set(RADIO_MUTE
, 0);
390 /* Speak a frequency. */
391 void talk_freq(int freq
, bool enqueue
)
394 talk_number(freq
/ 100, enqueue
);
395 talk_id(LANG_POINT
, true);
396 talk_number(freq
% 100 / 10, true);
398 talk_number(freq
% 10, true);
402 int radio_screen(void)
405 int ret_val
= GO_TO_ROOT
;
408 bool stereo
= false, last_stereo
= false;
409 bool update_screen
= true, restore
= true;
410 bool screen_freeze
= false;
411 bool keep_playing
= false;
413 #ifdef FM_RECORD_DBLPRE
414 int lastbutton
= BUTTON_NONE
;
415 unsigned long rec_lastclick
= 0;
417 #if CONFIG_CODEC != SWCODEC
418 bool have_recorded
= false;
419 int timeout
= current_tick
+ HZ
/10;
420 unsigned int last_seconds
= 0;
422 unsigned int seconds
= 0;
423 struct audio_recording_options rec_options
;
425 #endif /* CONFIG_CODEC != SWCODEC */
426 #ifndef HAVE_NOISY_IDLE_MODE
427 int button_timeout
= current_tick
+ (2*HZ
);
430 /* change status to "in screen" */
433 if(radio_preset_count() <= 0)
435 radio_load_presets(global_settings
.fmr_file
);
441 if(radio_status
== FMRADIO_OFF
)
446 #if CONFIG_CODEC != SWCODEC
447 if(rec_create_directory() > 0)
448 have_recorded
= true;
450 audio_init_recording(talk_get_bufsize());
452 sound_settings_apply();
453 /* Yes, we use the D/A for monitoring */
454 peak_meter_playback(true);
456 peak_meter_enable(true);
458 rec_init_recording_options(&rec_options
);
459 rec_options
.rec_source
= AUDIO_SRC_LINEIN
;
460 rec_set_recording_options(&rec_options
);
462 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN
),
463 sound_default(SOUND_RIGHT_GAIN
), AUDIO_GAIN_LINEIN
);
465 #endif /* CONFIG_CODEC != SWCODEC */
466 #endif /* ndef SIMULATOR */
469 #if CONFIG_CODEC == SWCODEC
470 /* This should be done before touching audio settings */
471 while (!audio_is_thread_ready())
474 audio_set_input_source(AUDIO_SRC_FMRADIO
,
475 (radio_status
== FMRADIO_PAUSED
) ?
476 SRCF_FMRADIO_PAUSED
: SRCF_FMRADIO_PLAYING
);
478 if (radio_status
== FMRADIO_OFF
)
482 if(radio_preset_count() < 1 && yesno_pop(ID2P(LANG_FM_FIRST_AUTOSCAN
)))
485 set_current_preset(find_preset(curr_freq
));
486 if(radio_current_preset() != -1)
487 radio_mode
= RADIO_PRESET_MODE
;
489 #ifndef HAVE_NOISY_IDLE_MODE
497 curr_freq
= step_freq(curr_freq
, search_dir
);
498 update_screen
= true;
500 if(tuner_set(RADIO_SCAN_FREQUENCY
, curr_freq
))
502 set_current_preset(find_preset(curr_freq
));
503 remember_frequency();
515 button
= fms_do_button_loop(update_screen
);
517 #ifndef HAVE_NOISY_IDLE_MODE
518 if (button
!= ACTION_NONE
)
520 cpu_idle_mode(false);
521 button_timeout
= current_tick
+ (2*HZ
);
527 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
528 if(audio_status() == AUDIO_STATUS_RECORD
)
536 if(has_presets_changed())
538 if(yesno_pop(ID2P(LANG_FM_SAVE_CHANGES
)))
544 update_screen
= true;
548 case ACTION_FM_RECORD
:
549 #ifdef FM_RECORD_DBLPRE
550 if (lastbutton
!= ACTION_FM_RECORD_DBLPRE
)
555 if (current_tick
- rec_lastclick
> HZ
/2)
557 rec_lastclick
= current_tick
;
560 #endif /* FM_RECORD_DBLPRE */
562 if(audio_status() == AUDIO_STATUS_RECORD
)
564 rec_command(RECORDING_CMD_START_NEWFILE
);
565 update_screen
= true;
569 have_recorded
= true;
570 rec_command(RECORDING_CMD_START
);
571 update_screen
= true;
573 #endif /* SIMULATOR */
576 #endif /* #ifdef FM_RECORD */
579 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
580 if(audio_status() == AUDIO_STATUS_RECORD
)
585 ret_val
= GO_TO_ROOT
;
586 if(has_presets_changed())
588 if(yesno_pop(ID2P(LANG_FM_SAVE_CHANGES
)))
596 case ACTION_STD_PREV
:
597 case ACTION_STD_NEXT
:
598 next_station(button
== ACTION_STD_PREV
? -1 : 1);
600 update_screen
= true;
604 case ACTION_STD_PREVREPEAT
:
605 case ACTION_STD_NEXTREPEAT
:
607 int dir
= search_dir
;
608 search_dir
= button
== ACTION_STD_PREVREPEAT
? -1 : 1;
609 if (radio_mode
!= RADIO_SCAN_MODE
)
611 next_preset(search_dir
);
613 update_screen
= true;
618 /* Starting auto scan */
619 tuner_set(RADIO_MUTE
, 1);
620 update_screen
= true;
625 case ACTION_SETTINGS_INC
:
626 case ACTION_SETTINGS_INCREPEAT
:
627 global_settings
.volume
++;
629 update_screen
= true;
632 case ACTION_SETTINGS_DEC
:
633 case ACTION_SETTINGS_DECREPEAT
:
634 global_settings
.volume
--;
636 update_screen
= true;
640 if (radio_status
== FMRADIO_PLAYING
)
645 update_screen
= true;
651 fms_fix_displays(FMS_EXIT
);
653 set_current_preset(find_preset(curr_freq
));
654 update_screen
= true;
659 case ACTION_FM_PRESET
:
660 if(radio_preset_count() < 1)
662 splash(HZ
, ID2P(LANG_FM_NO_PRESETS
));
663 update_screen
= true;
666 fms_fix_displays(FMS_EXIT
);
667 handle_radio_presets();
668 update_screen
= true;
671 #endif /* FM_PRESET */
674 case ACTION_FM_FREEZE
:
677 splash(HZ
, str(LANG_FM_FREEZE
));
678 screen_freeze
= true;
682 update_screen
= true;
683 screen_freeze
= false;
686 #endif /* FM_FREEZE */
688 case SYS_USB_CONNECTED
:
689 #if CONFIG_CODEC != SWCODEC
690 /* Only accept USB connection when not recording */
691 if(audio_status() != AUDIO_STATUS_RECORD
)
694 default_event_handler(SYS_USB_CONNECTED
);
695 screen_freeze
= true; /* Cosmetic: makes sure the
696 radio screen doesn't redraw */
703 if(radio_mode
== RADIO_SCAN_MODE
)
705 /* Force scan mode if there are no presets. */
706 if(radio_preset_count() > 0)
707 radio_mode
= RADIO_PRESET_MODE
;
710 radio_mode
= RADIO_SCAN_MODE
;
711 update_screen
= true;
712 cond_talk_ids_fq(radio_mode
?
713 LANG_PRESET
: LANG_RADIO_SCAN_MODE
);
718 #ifdef FM_NEXT_PRESET
719 case ACTION_FM_NEXT_PRESET
:
722 update_screen
= true;
727 #ifdef FM_PREV_PRESET
728 case ACTION_FM_PREV_PRESET
:
731 update_screen
= true;
737 default_event_handler(button
);
739 if (tuner_get(RADIO_EVENT
))
740 update_screen
= true;
742 if (!tuner_get(RADIO_PRESENT
))
744 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
745 if(audio_status() == AUDIO_STATUS_RECORD
)
748 keep_playing
= false;
750 ret_val
= GO_TO_ROOT
;
751 if(has_presets_changed())
753 if(yesno_pop(ID2P(LANG_FM_SAVE_CHANGES
)))
755 radio_save_presets();
759 /* Clear the preset list on exit. */
765 #ifdef FM_RECORD_DBLPRE
766 if (button
!= ACTION_NONE
)
770 #if CONFIG_CODEC != SWCODEC
776 /* Only display the peak meter when not recording */
777 #if CONFIG_CODEC != SWCODEC
778 if(TIME_AFTER(current_tick
, timeout
))
780 timeout
= current_tick
+ HZ
;
783 #endif /* CONFIG_CODEC == SWCODEC */
785 /* keep "mono" from always being displayed when paused */
786 if (radio_status
!= FMRADIO_PAUSED
)
788 stereo
= tuner_get(RADIO_STEREO
) &&
789 !global_settings
.fm_force_mono
;
791 if(stereo
!= last_stereo
)
793 update_screen
= true;
794 last_stereo
= stereo
;
799 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
800 seconds
= audio_recorded_time() / HZ
;
801 if (update_screen
|| seconds
> last_seconds
|| restore
)
803 last_seconds
= seconds
;
805 if (update_screen
|| restore
)
809 fms_fix_displays(FMS_ENTER
);
811 skin_update(fms_get(i
), WPS_REFRESH_ALL
);
815 update_screen
= false;
817 if (global_settings
.talk_file
&& talk
818 && radio_status
== FMRADIO_PAUSED
)
821 bool enqueue
= false;
822 if (radio_mode
== RADIO_SCAN_MODE
)
824 talk_freq(curr_freq
, enqueue
);
827 if (radio_current_preset() >= 0)
828 talk_preset(radio_current_preset(), radio_mode
== RADIO_PRESET_MODE
,
832 #if CONFIG_CODEC != SWCODEC
833 if(audio_status() & AUDIO_STATUS_ERROR
)
839 #ifndef HAVE_NOISY_IDLE_MODE
840 if (TIME_AFTER(current_tick
, button_timeout
))
848 #if CONFIG_CODEC != SWCODEC
849 if(audio_status() & AUDIO_STATUS_ERROR
)
851 splash(0, str(LANG_DISK_FULL
));
856 button
= get_action(CONTEXT_FM
, TIMEOUT_BLOCK
);
857 if(button
== ACTION_FM_STOP
)
862 audio_init_playback();
863 #endif /* CONFIG_CODEC != SWCODEC */
865 sound_settings_apply();
866 #endif /* SIMULATOR */
870 /* Catch FMRADIO_PLAYING status for the sim. */
872 #if CONFIG_CODEC != SWCODEC
873 /* Enable the Left and right A/D Converter */
874 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN
),
875 sound_default(SOUND_RIGHT_GAIN
),
877 mas_codec_writereg(6, 0x4000);
880 #endif /* SIMULATOR */
884 #if CONFIG_CODEC == SWCODEC
885 audio_set_input_source(AUDIO_SRC_PLAYBACK
, SRCF_PLAYBACK
);
891 #ifndef HAVE_NOISY_IDLE_MODE
892 cpu_idle_mode(false);
894 fms_fix_displays(FMS_EXIT
);
896 #if CONFIG_CODEC != SWCODEC
897 return have_recorded
;
903 void toggle_mono_mode(bool mono
)
905 tuner_set(RADIO_FORCE_MONO
, mono
);
908 void set_radio_region(int region
)
910 #ifdef HAVE_RADIO_REGION
911 tuner_set(RADIO_REGION
, region
);
914 remember_frequency();
918 MENUITEM_SETTING(set_region
, &global_settings
.fm_region
, NULL
);
919 MENUITEM_SETTING(force_mono
, &global_settings
.fm_force_mono
, NULL
);
922 static char* get_mode_text(int selected_item
, void * data
, char *buffer
)
926 snprintf(buffer
, MAX_PATH
, "%s %s", str(LANG_MODE
),
927 radio_mode
? str(LANG_PRESET
) :
928 str(LANG_RADIO_SCAN_MODE
));
931 static int toggle_radio_mode(void)
933 radio_mode
= (radio_mode
== RADIO_SCAN_MODE
) ?
934 RADIO_PRESET_MODE
: RADIO_SCAN_MODE
;
937 MENUITEM_FUNCTION_DYNTEXT(radio_mode_item
, 0,
938 toggle_radio_mode
, NULL
,
939 get_mode_text
, NULL
, NULL
, NULL
, Icon_NOICON
);
944 #ifdef HAVE_RECORDING
946 #if defined(HAVE_FMRADIO_REC) && CONFIG_CODEC == SWCODEC
947 #define FM_RECORDING_SCREEN
948 static int fm_recording_screen(void)
952 /* switch recording source to FMRADIO for the duration */
953 int rec_source
= global_settings
.rec_source
;
954 global_settings
.rec_source
= AUDIO_SRC_FMRADIO
;
955 ret
= recording_screen(true);
957 /* safe to reset as changing sources is prohibited here */
958 global_settings
.rec_source
= rec_source
;
963 #endif /* defined(HAVE_FMRADIO_REC) && CONFIG_CODEC == SWCODEC */
965 #if defined(HAVE_FMRADIO_REC) || CONFIG_CODEC != SWCODEC
966 #define FM_RECORDING_SETTINGS
967 static int fm_recording_settings(void)
969 bool ret
= recording_menu(true);
971 #if CONFIG_CODEC != SWCODEC
974 struct audio_recording_options rec_options
;
975 rec_init_recording_options(&rec_options
);
976 rec_options
.rec_source
= AUDIO_SRC_LINEIN
;
977 rec_set_recording_options(&rec_options
);
984 #endif /* defined(HAVE_FMRADIO_REC) || CONFIG_CODEC != SWCODEC */
985 #endif /* HAVE_RECORDING */
987 #ifdef FM_RECORDING_SCREEN
988 MENUITEM_FUNCTION(recscreen_item
, 0, ID2P(LANG_RECORDING
),
989 fm_recording_screen
, NULL
, NULL
, Icon_Recording
);
991 #ifdef FM_RECORDING_SETTINGS
992 MENUITEM_FUNCTION(recsettings_item
, 0, ID2P(LANG_RECORDING_SETTINGS
),
993 fm_recording_settings
, NULL
, NULL
, Icon_Recording
);
996 int handle_radio_presets_menu(void)
998 return handle_radio_presets();
1000 MENUITEM_FUNCTION(radio_presets_item
, 0, ID2P(LANG_PRESET
),
1001 handle_radio_presets_menu
, NULL
, NULL
, Icon_NOICON
);
1003 #ifndef FM_PRESET_ADD
1004 int handle_radio_addpreset_menu(void)
1006 return radio_add_preset();
1008 MENUITEM_FUNCTION(radio_addpreset_item
, 0, ID2P(LANG_FM_ADD_PRESET
),
1009 radio_add_preset
, NULL
, NULL
, Icon_NOICON
);
1013 MENUITEM_FUNCTION(presetload_item
, 0, ID2P(LANG_FM_PRESET_LOAD
),
1014 load_preset_list
, NULL
, NULL
, Icon_NOICON
);
1015 MENUITEM_FUNCTION(presetsave_item
, 0, ID2P(LANG_FM_PRESET_SAVE
),
1016 save_preset_list
, NULL
, NULL
, Icon_NOICON
);
1017 MENUITEM_FUNCTION(presetclear_item
, 0, ID2P(LANG_FM_PRESET_CLEAR
),
1018 clear_preset_list
, NULL
, NULL
, Icon_NOICON
);
1019 MENUITEM_FUNCTION(scan_presets_item
, MENU_FUNC_USEPARAM
,
1020 ID2P(LANG_FM_SCAN_PRESETS
),
1021 scan_presets
, NULL
, NULL
, Icon_NOICON
);
1023 MAKE_MENU(radio_settings_menu
, ID2P(LANG_FM_MENU
), NULL
,
1026 &radio_presets_item
,
1028 #ifndef FM_PRESET_ADD
1029 &radio_addpreset_item
,
1031 &presetload_item
, &presetsave_item
, &presetclear_item
,
1036 &set_region
, &sound_settings
,
1037 #ifdef FM_RECORDING_SCREEN
1040 #ifdef FM_RECORDING_SETTINGS
1043 &scan_presets_item
);
1044 /* main menu of the radio screen */
1045 static bool radio_menu(void)
1047 return do_menu(&radio_settings_menu
, NULL
, NULL
, false) ==