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
108 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || (CONFIG_KEYPAD == SANSA_C200_PAD) ||\
109 (CONFIG_KEYPAD == SANSA_FUZE_PAD) || (CONFIG_KEYPAD == SANSA_CLIP_PAD)
117 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
121 #elif (CONFIG_KEYPAD == COWON_D2_PAD)
129 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
130 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
139 /* presets.c needs these so keep unstatic or redo the whole thing! */
140 int curr_freq
; /* current frequency in Hz */
141 /* these are all in presets.c... someone PLEASE rework this ! */
142 int handle_radio_presets(void);
143 static bool radio_menu(void);
144 int radio_add_preset(void);
145 int save_preset_list(void);
146 int load_preset_list(void);
147 int clear_preset_list(void);
148 void next_preset(int direction
);
149 void set_current_preset(int preset
);
150 int scan_presets(void *viewports
);
151 int find_preset(int freq
);
152 void radio_save_presets(void);
153 bool has_presets_changed(void);
154 void talk_preset(int preset
, bool fallback
, bool enqueue
);
155 void presets_save(void);
159 int radio_mode
= RADIO_SCAN_MODE
;
160 static int search_dir
= 0;
162 static int radio_status
= FMRADIO_OFF
;
163 static bool in_screen
= false;
166 static void radio_off(void);
168 bool radio_scan_mode(void)
170 return radio_mode
== RADIO_SCAN_MODE
;
173 bool radio_is_stereo(void)
175 return tuner_get(RADIO_STEREO
) && !global_settings
.fm_force_mono
;
177 int radio_current_frequency(void)
182 /* Function to manipulate all yesno dialogues.
183 This function needs the output text as an argument. */
184 bool yesno_pop(const char* text
)
187 const char *lines
[]={text
};
188 const struct text_message message
={lines
, 1};
189 bool ret
= (gui_syncyesno_run(&message
,NULL
,NULL
)== YESNO_YES
);
191 screens
[i
].clear_viewport();
195 void radio_init(void)
200 radioart_init(false);
204 int get_radio_status(void)
209 bool in_radio_screen(void)
214 /* TODO: Move some more of the control functionality to firmware
215 and clean up the mess */
217 /* secret flag for starting paused - prevents unmute */
218 #define FMRADIO_START_PAUSED 0x8000
219 void radio_start(void)
221 const struct fm_region_data
*fmr
;
224 if(radio_status
== FMRADIO_PLAYING
)
227 fmr
= &fm_region_data
[global_settings
.fm_region
];
229 start_paused
= radio_status
& FMRADIO_START_PAUSED
;
230 /* clear flag before any yielding */
231 radio_status
&= ~FMRADIO_START_PAUSED
;
233 if(radio_status
== FMRADIO_OFF
)
236 curr_freq
= global_status
.last_frequency
* fmr
->freq_step
+ fmr
->freq_min
;
238 tuner_set(RADIO_SLEEP
, 0); /* wake up the tuner */
240 if(radio_status
== FMRADIO_OFF
)
242 #ifdef HAVE_RADIO_REGION
243 tuner_set(RADIO_REGION
, global_settings
.fm_region
);
245 tuner_set(RADIO_FORCE_MONO
, global_settings
.fm_force_mono
);
248 tuner_set(RADIO_FREQUENCY
, curr_freq
);
250 #ifdef HAVE_RADIO_MUTE_TIMEOUT
252 unsigned long mute_timeout
= current_tick
+ HZ
;
253 if (radio_status
!= FMRADIO_OFF
)
259 while(!tuner_get(RADIO_STEREO
) && !tuner_get(RADIO_TUNED
))
261 if(TIME_AFTER(current_tick
, mute_timeout
))
268 /* keep radio from sounding initially */
270 tuner_set(RADIO_MUTE
, 0);
272 radio_status
= FMRADIO_PLAYING
;
275 void radio_pause(void)
277 if(radio_status
== FMRADIO_PAUSED
)
280 if(radio_status
== FMRADIO_OFF
)
282 radio_status
|= FMRADIO_START_PAUSED
;
286 tuner_set(RADIO_MUTE
, 1);
287 /* For si4700: 2==this is really 'pause'. other tuners treat it
289 tuner_set(RADIO_SLEEP
, 2);
291 radio_status
= FMRADIO_PAUSED
;
294 static void radio_off(void)
296 tuner_set(RADIO_MUTE
, 1);
297 tuner_set(RADIO_SLEEP
, 1); /* low power mode, if available */
298 radio_status
= FMRADIO_OFF
;
299 tuner_power(false); /* status update, power off if avail. */
302 void radio_stop(void)
304 if(radio_status
== FMRADIO_OFF
)
310 bool radio_hardware_present(void)
312 return tuner_get(RADIO_PRESENT
);
315 /* Keep freq on the grid for the current region */
316 int snap_freq_to_grid(int freq
)
318 const struct fm_region_data
* const fmr
=
319 &fm_region_data
[global_settings
.fm_region
];
321 /* Range clamp if out of range or just round to nearest */
322 if (freq
< fmr
->freq_min
)
323 freq
= fmr
->freq_min
;
324 else if (freq
> fmr
->freq_max
)
325 freq
= fmr
->freq_max
;
327 freq
= (freq
- fmr
->freq_min
+ fmr
->freq_step
/2) /
328 fmr
->freq_step
* fmr
->freq_step
+ fmr
->freq_min
;
333 void remember_frequency(void)
335 const struct fm_region_data
* const fmr
=
336 &fm_region_data
[global_settings
.fm_region
];
337 global_status
.last_frequency
= (curr_freq
- fmr
->freq_min
)
342 /* Step to the next or previous frequency */
343 static int step_freq(int freq
, int direction
)
345 const struct fm_region_data
* const fmr
=
346 &fm_region_data
[global_settings
.fm_region
];
348 freq
+= direction
*fmr
->freq_step
;
350 /* Wrap first or snapping to grid will not let us on the band extremes */
351 if (freq
> fmr
->freq_max
)
352 freq
= direction
> 0 ? fmr
->freq_min
: fmr
->freq_max
;
353 else if (freq
< fmr
->freq_min
)
354 freq
= direction
< 0 ? fmr
->freq_max
: fmr
->freq_min
;
356 freq
= snap_freq_to_grid(freq
);
361 /* Step to the next or previous station */
362 void next_station(int direction
)
364 if (direction
!= 0 && radio_mode
!= RADIO_SCAN_MODE
)
366 next_preset(direction
);
370 curr_freq
= step_freq(curr_freq
, direction
);
372 if (radio_status
== FMRADIO_PLAYING
)
373 tuner_set(RADIO_MUTE
, 1);
375 tuner_set(RADIO_FREQUENCY
, curr_freq
);
377 if (radio_status
== FMRADIO_PLAYING
)
378 tuner_set(RADIO_MUTE
, 0);
380 set_current_preset(find_preset(curr_freq
));
381 remember_frequency();
384 /* Ends an in-progress search */
385 static void end_search(void)
387 if (search_dir
!= 0 && radio_status
== FMRADIO_PLAYING
)
388 tuner_set(RADIO_MUTE
, 0);
392 /* Speak a frequency. */
393 void talk_freq(int freq
, bool enqueue
)
396 talk_number(freq
/ 100, enqueue
);
397 talk_id(LANG_POINT
, true);
398 talk_number(freq
% 100 / 10, true);
400 talk_number(freq
% 10, true);
404 int radio_screen(void)
407 int ret_val
= GO_TO_ROOT
;
410 bool stereo
= false, last_stereo
= false;
411 bool update_screen
= true, restore
= true;
412 bool screen_freeze
= false;
413 bool keep_playing
= false;
415 #ifdef FM_RECORD_DBLPRE
416 int lastbutton
= BUTTON_NONE
;
417 unsigned long rec_lastclick
= 0;
419 #if CONFIG_CODEC != SWCODEC
420 bool have_recorded
= false;
421 int timeout
= current_tick
+ HZ
/10;
422 unsigned int last_seconds
= 0;
423 #if !defined(SIMULATOR)
424 unsigned int seconds
= 0;
425 struct audio_recording_options rec_options
;
426 #endif /* SIMULATOR */
427 #endif /* CONFIG_CODEC != SWCODEC */
428 #ifndef HAVE_NOISY_IDLE_MODE
429 int button_timeout
= current_tick
+ (2*HZ
);
432 /* change status to "in screen" */
435 if(radio_preset_count() <= 0)
437 radio_load_presets(global_settings
.fmr_file
);
443 if(radio_status
== FMRADIO_OFF
)
448 #if CONFIG_CODEC != SWCODEC
449 if(rec_create_directory() > 0)
450 have_recorded
= true;
452 audio_init_recording(talk_get_bufsize());
454 sound_settings_apply();
455 /* Yes, we use the D/A for monitoring */
456 peak_meter_playback(true);
458 peak_meter_enable(true);
460 rec_init_recording_options(&rec_options
);
461 rec_options
.rec_source
= AUDIO_SRC_LINEIN
;
462 rec_set_recording_options(&rec_options
);
464 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN
),
465 sound_default(SOUND_RIGHT_GAIN
), AUDIO_GAIN_LINEIN
);
467 #endif /* CONFIG_CODEC != SWCODEC */
468 #endif /* ndef SIMULATOR */
471 #if CONFIG_CODEC == SWCODEC
472 /* This should be done before touching audio settings */
473 while (!audio_is_thread_ready())
476 audio_set_input_source(AUDIO_SRC_FMRADIO
,
477 (radio_status
== FMRADIO_PAUSED
) ?
478 SRCF_FMRADIO_PAUSED
: SRCF_FMRADIO_PLAYING
);
480 if (radio_status
== FMRADIO_OFF
)
484 if(radio_preset_count() < 1 && yesno_pop(ID2P(LANG_FM_FIRST_AUTOSCAN
)))
487 set_current_preset(find_preset(curr_freq
));
488 if(radio_current_preset() != -1)
489 radio_mode
= RADIO_PRESET_MODE
;
491 #ifndef HAVE_NOISY_IDLE_MODE
499 curr_freq
= step_freq(curr_freq
, search_dir
);
500 update_screen
= true;
502 if(tuner_set(RADIO_SCAN_FREQUENCY
, curr_freq
))
504 set_current_preset(find_preset(curr_freq
));
505 remember_frequency();
517 button
= fms_do_button_loop(update_screen
);
519 #ifndef HAVE_NOISY_IDLE_MODE
520 if (button
!= ACTION_NONE
)
522 cpu_idle_mode(false);
523 button_timeout
= current_tick
+ (2*HZ
);
529 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
530 if(audio_status() == AUDIO_STATUS_RECORD
)
538 if(has_presets_changed())
540 if(yesno_pop(ID2P(LANG_FM_SAVE_CHANGES
)))
546 update_screen
= true;
550 case ACTION_FM_RECORD
:
551 #ifdef FM_RECORD_DBLPRE
552 if (lastbutton
!= ACTION_FM_RECORD_DBLPRE
)
557 if (current_tick
- rec_lastclick
> HZ
/2)
559 rec_lastclick
= current_tick
;
562 #endif /* FM_RECORD_DBLPRE */
564 if(audio_status() == AUDIO_STATUS_RECORD
)
566 rec_command(RECORDING_CMD_START_NEWFILE
);
567 update_screen
= true;
571 have_recorded
= true;
572 rec_command(RECORDING_CMD_START
);
573 update_screen
= true;
575 #endif /* SIMULATOR */
578 #endif /* #ifdef FM_RECORD */
581 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
582 if(audio_status() == AUDIO_STATUS_RECORD
)
587 ret_val
= GO_TO_ROOT
;
588 if(has_presets_changed())
590 if(yesno_pop(ID2P(LANG_FM_SAVE_CHANGES
)))
598 case ACTION_STD_PREV
:
599 case ACTION_STD_NEXT
:
600 next_station(button
== ACTION_STD_PREV
? -1 : 1);
602 update_screen
= true;
606 case ACTION_STD_PREVREPEAT
:
607 case ACTION_STD_NEXTREPEAT
:
609 int dir
= search_dir
;
610 search_dir
= button
== ACTION_STD_PREVREPEAT
? -1 : 1;
611 if (radio_mode
!= RADIO_SCAN_MODE
)
613 next_preset(search_dir
);
615 update_screen
= true;
620 /* Starting auto scan */
621 tuner_set(RADIO_MUTE
, 1);
622 update_screen
= true;
627 case ACTION_SETTINGS_INC
:
628 case ACTION_SETTINGS_INCREPEAT
:
629 global_settings
.volume
++;
631 update_screen
= true;
634 case ACTION_SETTINGS_DEC
:
635 case ACTION_SETTINGS_DECREPEAT
:
636 global_settings
.volume
--;
638 update_screen
= true;
642 if (radio_status
== FMRADIO_PLAYING
)
647 update_screen
= true;
653 fms_fix_displays(FMS_EXIT
);
655 set_current_preset(find_preset(curr_freq
));
656 update_screen
= true;
661 case ACTION_FM_PRESET
:
662 if(radio_preset_count() < 1)
664 splash(HZ
, ID2P(LANG_FM_NO_PRESETS
));
665 update_screen
= true;
668 fms_fix_displays(FMS_EXIT
);
669 handle_radio_presets();
670 update_screen
= true;
673 #endif /* FM_PRESET */
676 case ACTION_FM_FREEZE
:
679 splash(HZ
, str(LANG_FM_FREEZE
));
680 screen_freeze
= true;
684 update_screen
= true;
685 screen_freeze
= false;
688 #endif /* FM_FREEZE */
690 case SYS_USB_CONNECTED
:
691 #if CONFIG_CODEC != SWCODEC
692 /* Only accept USB connection when not recording */
693 if(audio_status() != AUDIO_STATUS_RECORD
)
696 default_event_handler(SYS_USB_CONNECTED
);
697 screen_freeze
= true; /* Cosmetic: makes sure the
698 radio screen doesn't redraw */
705 if(radio_mode
== RADIO_SCAN_MODE
)
707 /* Force scan mode if there are no presets. */
708 if(radio_preset_count() > 0)
709 radio_mode
= RADIO_PRESET_MODE
;
712 radio_mode
= RADIO_SCAN_MODE
;
713 update_screen
= true;
714 cond_talk_ids_fq(radio_mode
?
715 LANG_PRESET
: LANG_RADIO_SCAN_MODE
);
720 #ifdef FM_NEXT_PRESET
721 case ACTION_FM_NEXT_PRESET
:
724 update_screen
= true;
729 #ifdef FM_PREV_PRESET
730 case ACTION_FM_PREV_PRESET
:
733 update_screen
= true;
739 default_event_handler(button
);
741 if (tuner_get(RADIO_EVENT
))
742 update_screen
= true;
744 if (!tuner_get(RADIO_PRESENT
))
746 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
747 if(audio_status() == AUDIO_STATUS_RECORD
)
750 keep_playing
= false;
752 ret_val
= GO_TO_ROOT
;
753 if(has_presets_changed())
755 if(yesno_pop(ID2P(LANG_FM_SAVE_CHANGES
)))
757 radio_save_presets();
761 /* Clear the preset list on exit. */
767 #ifdef FM_RECORD_DBLPRE
768 if (button
!= ACTION_NONE
)
772 #if CONFIG_CODEC != SWCODEC
778 /* Only display the peak meter when not recording */
779 #if CONFIG_CODEC != SWCODEC
780 if(TIME_AFTER(current_tick
, timeout
))
782 timeout
= current_tick
+ HZ
;
785 #endif /* CONFIG_CODEC == SWCODEC */
787 /* keep "mono" from always being displayed when paused */
788 if (radio_status
!= FMRADIO_PAUSED
)
790 stereo
= tuner_get(RADIO_STEREO
) &&
791 !global_settings
.fm_force_mono
;
793 if(stereo
!= last_stereo
)
795 update_screen
= true;
796 last_stereo
= stereo
;
801 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
802 seconds
= audio_recorded_time() / HZ
;
803 if (update_screen
|| seconds
> last_seconds
|| restore
)
805 last_seconds
= seconds
;
807 if (update_screen
|| restore
)
811 fms_fix_displays(FMS_ENTER
);
813 skin_update(fms_get(i
), WPS_REFRESH_ALL
);
817 update_screen
= false;
819 if (global_settings
.talk_file
&& talk
820 && radio_status
== FMRADIO_PAUSED
)
823 bool enqueue
= false;
824 if (radio_mode
== RADIO_SCAN_MODE
)
826 talk_freq(curr_freq
, enqueue
);
829 if (radio_current_preset() >= 0)
830 talk_preset(radio_current_preset(), radio_mode
== RADIO_PRESET_MODE
,
834 #if CONFIG_CODEC != SWCODEC
835 if(audio_status() & AUDIO_STATUS_ERROR
)
841 #ifndef HAVE_NOISY_IDLE_MODE
842 if (TIME_AFTER(current_tick
, button_timeout
))
850 #if CONFIG_CODEC != SWCODEC
851 if(audio_status() & AUDIO_STATUS_ERROR
)
853 splash(0, str(LANG_DISK_FULL
));
858 button
= get_action(CONTEXT_FM
, TIMEOUT_BLOCK
);
859 if(button
== ACTION_FM_STOP
)
864 audio_init_playback();
865 #endif /* CONFIG_CODEC != SWCODEC */
867 sound_settings_apply();
868 #endif /* SIMULATOR */
872 /* Catch FMRADIO_PLAYING status for the sim. */
874 #if CONFIG_CODEC != SWCODEC
875 /* Enable the Left and right A/D Converter */
876 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN
),
877 sound_default(SOUND_RIGHT_GAIN
),
879 mas_codec_writereg(6, 0x4000);
882 #endif /* SIMULATOR */
886 #if CONFIG_CODEC == SWCODEC
887 audio_set_input_source(AUDIO_SRC_PLAYBACK
, SRCF_PLAYBACK
);
893 #ifndef HAVE_NOISY_IDLE_MODE
894 cpu_idle_mode(false);
896 fms_fix_displays(FMS_EXIT
);
898 #if CONFIG_CODEC != SWCODEC
899 return have_recorded
;
905 void toggle_mono_mode(bool mono
)
907 tuner_set(RADIO_FORCE_MONO
, mono
);
910 void set_radio_region(int region
)
912 #ifdef HAVE_RADIO_REGION
913 tuner_set(RADIO_REGION
, region
);
916 remember_frequency();
920 MENUITEM_SETTING(set_region
, &global_settings
.fm_region
, NULL
);
921 MENUITEM_SETTING(force_mono
, &global_settings
.fm_force_mono
, NULL
);
924 static char* get_mode_text(int selected_item
, void * data
, char *buffer
)
928 snprintf(buffer
, MAX_PATH
, "%s %s", str(LANG_MODE
),
929 radio_mode
? str(LANG_PRESET
) :
930 str(LANG_RADIO_SCAN_MODE
));
933 static int toggle_radio_mode(void)
935 radio_mode
= (radio_mode
== RADIO_SCAN_MODE
) ?
936 RADIO_PRESET_MODE
: RADIO_SCAN_MODE
;
939 MENUITEM_FUNCTION_DYNTEXT(radio_mode_item
, 0,
940 toggle_radio_mode
, NULL
,
941 get_mode_text
, NULL
, NULL
, NULL
, Icon_NOICON
);
946 #ifdef HAVE_RECORDING
948 #if defined(HAVE_FMRADIO_REC) && CONFIG_CODEC == SWCODEC
949 #define FM_RECORDING_SCREEN
950 static int fm_recording_screen(void)
954 /* switch recording source to FMRADIO for the duration */
955 int rec_source
= global_settings
.rec_source
;
956 global_settings
.rec_source
= AUDIO_SRC_FMRADIO
;
957 ret
= recording_screen(true);
959 /* safe to reset as changing sources is prohibited here */
960 global_settings
.rec_source
= rec_source
;
965 #endif /* defined(HAVE_FMRADIO_REC) && CONFIG_CODEC == SWCODEC */
967 #if defined(HAVE_FMRADIO_REC) || CONFIG_CODEC != SWCODEC
968 #define FM_RECORDING_SETTINGS
969 static int fm_recording_settings(void)
971 bool ret
= recording_menu(true);
973 #if CONFIG_CODEC != SWCODEC
976 struct audio_recording_options rec_options
;
977 rec_init_recording_options(&rec_options
);
978 rec_options
.rec_source
= AUDIO_SRC_LINEIN
;
979 rec_set_recording_options(&rec_options
);
986 #endif /* defined(HAVE_FMRADIO_REC) || CONFIG_CODEC != SWCODEC */
987 #endif /* HAVE_RECORDING */
989 #ifdef FM_RECORDING_SCREEN
990 MENUITEM_FUNCTION(recscreen_item
, 0, ID2P(LANG_RECORDING
),
991 fm_recording_screen
, NULL
, NULL
, Icon_Recording
);
993 #ifdef FM_RECORDING_SETTINGS
994 MENUITEM_FUNCTION(recsettings_item
, 0, ID2P(LANG_RECORDING_SETTINGS
),
995 fm_recording_settings
, NULL
, NULL
, Icon_Recording
);
998 int handle_radio_presets_menu(void)
1000 return handle_radio_presets();
1002 MENUITEM_FUNCTION(radio_presets_item
, 0, ID2P(LANG_PRESET
),
1003 handle_radio_presets_menu
, NULL
, NULL
, Icon_NOICON
);
1005 #ifndef FM_PRESET_ADD
1006 int handle_radio_addpreset_menu(void)
1008 return radio_add_preset();
1010 MENUITEM_FUNCTION(radio_addpreset_item
, 0, ID2P(LANG_FM_ADD_PRESET
),
1011 radio_add_preset
, NULL
, NULL
, Icon_NOICON
);
1015 MENUITEM_FUNCTION(presetload_item
, 0, ID2P(LANG_FM_PRESET_LOAD
),
1016 load_preset_list
, NULL
, NULL
, Icon_NOICON
);
1017 MENUITEM_FUNCTION(presetsave_item
, 0, ID2P(LANG_FM_PRESET_SAVE
),
1018 save_preset_list
, NULL
, NULL
, Icon_NOICON
);
1019 MENUITEM_FUNCTION(presetclear_item
, 0, ID2P(LANG_FM_PRESET_CLEAR
),
1020 clear_preset_list
, NULL
, NULL
, Icon_NOICON
);
1021 MENUITEM_FUNCTION(scan_presets_item
, MENU_FUNC_USEPARAM
,
1022 ID2P(LANG_FM_SCAN_PRESETS
),
1023 scan_presets
, NULL
, NULL
, Icon_NOICON
);
1025 MAKE_MENU(radio_settings_menu
, ID2P(LANG_FM_MENU
), NULL
,
1028 &radio_presets_item
,
1030 #ifndef FM_PRESET_ADD
1031 &radio_addpreset_item
,
1033 &presetload_item
, &presetsave_item
, &presetclear_item
,
1038 &set_region
, &sound_settings
,
1039 #ifdef FM_RECORDING_SCREEN
1042 #ifdef FM_RECORDING_SETTINGS
1045 &scan_presets_item
);
1046 /* main menu of the radio screen */
1047 static bool radio_menu(void)
1049 return do_menu(&radio_settings_menu
, NULL
, NULL
, false) ==