1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2003 Linus Nielsen Feltzing
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
32 #include "mp3_playback.h"
43 #include "peakmeter.h"
46 #include "sound_menu.h"
48 #include "recording.h"
54 #include "screen_access.h"
55 #include "statusbar.h"
59 #include "buttonbar.h"
65 #include "menus/exported_menus.h"
66 #include "root_menu.h"
70 #if CONFIG_KEYPAD == RECORDER_PAD
73 #define FM_PRESET_ACTION
77 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
80 #define FM_NEXT_PRESET
81 #define FM_PREV_PRESET
83 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
87 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
90 /* This should be removeable if the whole tuning thing is sorted out since
91 proper tuning quiets the screen almost entirely in that extreme measures
92 have to be taken to hear any interference. */
93 #define HAVE_NOISY_IDLE_MODE
95 #elif CONFIG_KEYPAD == ONDIO_PAD
96 #define FM_RECORD_DBLPRE
98 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || (CONFIG_KEYPAD == SANSA_C200_PAD)
107 #define RADIO_SCAN_MODE 0
108 #define RADIO_PRESET_MODE 1
110 static int curr_preset
= -1;
111 static int curr_freq
;
112 static int radio_mode
= RADIO_SCAN_MODE
;
113 static int search_dir
= 0;
115 static int radio_status
= FMRADIO_OFF
;
116 static bool in_screen
= false;
118 #define MAX_PRESETS 64
119 static bool presets_loaded
= false, presets_changed
= false;
120 static struct fmstation presets
[MAX_PRESETS
];
122 static char filepreset
[MAX_PATH
]; /* preset filename variable */
124 static int num_presets
= 0; /* The number of presets in the preset list */
126 static void radio_save_presets(void);
127 static int handle_radio_presets(void);
128 static bool radio_menu(void);
129 static int radio_add_preset(void);
130 static int save_preset_list(void);
131 static int load_preset_list(void);
132 static int clear_preset_list(void);
134 static int scan_presets(void);
136 /* Function to manipulate all yesno dialogues.
137 This function needs the output text as an argument. */
138 static bool yesno_pop(const char* text
)
141 const char *lines
[]={text
};
142 const struct text_message message
={lines
, 1};
143 bool ret
= (gui_syncyesno_run(&message
,NULL
,NULL
)== YESNO_YES
);
145 gui_textarea_clear(&screens
[i
]);
149 void radio_init(void)
155 int get_radio_status(void)
160 bool in_radio_screen(void)
165 /* TODO: Move some more of the control functionality to an HAL and clean up the
168 /* secret flag for starting paused - prevents unmute */
169 #define FMRADIO_START_PAUSED 0x8000
170 void radio_start(void)
172 const struct fm_region_data
*fmr
;
175 if(radio_status
== FMRADIO_PLAYING
)
178 fmr
= &fm_region_data
[global_settings
.fm_region
];
180 start_paused
= radio_status
& FMRADIO_START_PAUSED
;
181 /* clear flag before any yielding */
182 radio_status
&= ~FMRADIO_START_PAUSED
;
184 if(radio_status
== FMRADIO_OFF
)
187 curr_freq
= global_status
.last_frequency
188 * fmr
->freq_step
+ fmr
->freq_min
;
190 tuner_set(RADIO_SLEEP
, 0); /* wake up the tuner */
192 if(radio_status
== FMRADIO_OFF
)
194 #ifdef HAVE_RADIO_REGION
195 tuner_set(RADIO_REGION
, global_settings
.fm_region
);
197 tuner_set(RADIO_FORCE_MONO
, global_settings
.fm_force_mono
);
200 tuner_set(RADIO_FREQUENCY
, curr_freq
);
202 #ifdef HAVE_RADIO_MUTE_TIMEOUT
204 unsigned long mute_timeout
= current_tick
+ HZ
;
205 if (radio_status
!= FMRADIO_OFF
)
211 while(!tuner_get(RADIO_STEREO
) && !tuner_get(RADIO_TUNED
))
213 if(TIME_AFTER(current_tick
, mute_timeout
))
220 /* keep radio from sounding initially */
222 tuner_set(RADIO_MUTE
, 0);
224 radio_status
= FMRADIO_PLAYING
;
227 void radio_pause(void)
229 if(radio_status
== FMRADIO_PAUSED
)
232 if(radio_status
== FMRADIO_OFF
)
234 radio_status
|= FMRADIO_START_PAUSED
;
238 tuner_set(RADIO_MUTE
, 1);
239 tuner_set(RADIO_SLEEP
, 1);
241 radio_status
= FMRADIO_PAUSED
;
244 void radio_stop(void)
246 if(radio_status
== FMRADIO_OFF
)
249 tuner_set(RADIO_MUTE
, 1);
250 tuner_set(RADIO_SLEEP
, 1); /* low power mode, if available */
251 radio_status
= FMRADIO_OFF
;
252 tuner_power(false); /* status update, power off if avail. */
255 bool radio_hardware_present(void)
257 return tuner_get(RADIO_PRESENT
);
260 /* Keep freq on the grid for the current region */
261 static int snap_freq_to_grid(int freq
)
263 const struct fm_region_data
* const fmr
=
264 &fm_region_data
[global_settings
.fm_region
];
266 /* Range clamp if out of range or just round to nearest */
267 if (freq
< fmr
->freq_min
)
268 freq
= fmr
->freq_min
;
269 else if (freq
> fmr
->freq_max
)
270 freq
= fmr
->freq_max
;
272 freq
= (freq
- fmr
->freq_min
+ fmr
->freq_step
/2) /
273 fmr
->freq_step
* fmr
->freq_step
+ fmr
->freq_min
;
278 /* Find a matching preset to freq */
279 static int find_preset(int freq
)
284 for(i
= 0;i
< MAX_PRESETS
;i
++)
286 if(freq
== presets
[i
].frequency
)
293 /* Return the first preset encountered in the search direction with
295 static int find_closest_preset(int freq
, int direction
)
299 if (direction
== 0) /* direction == 0 isn't really used */
302 for (i
= 0; i
< MAX_PRESETS
; i
++)
304 int preset_frequency
= presets
[i
].frequency
;
306 if (preset_frequency
== freq
)
307 return i
; /* Exact match = stop */
308 /* Stop when the preset frequency exeeds freq so that we can
309 pick the correct one based on direction */
310 if (preset_frequency
> freq
)
314 /* wrap around depending on direction */
315 if (i
== 0 || i
>= num_presets
- 1)
316 i
= direction
< 0 ? num_presets
- 1 : 0;
317 else if (direction
< 0)
318 i
--; /* use previous */
323 static void remember_frequency(void)
325 const struct fm_region_data
* const fmr
=
326 &fm_region_data
[global_settings
.fm_region
];
327 global_status
.last_frequency
= (curr_freq
- fmr
->freq_min
)
332 static void next_preset(int direction
)
337 if (curr_preset
== -1)
338 curr_preset
= find_closest_preset(curr_freq
, direction
);
340 curr_preset
= (curr_preset
+ direction
+ num_presets
) % num_presets
;
342 /* Must stay on the current grid for the region */
343 curr_freq
= snap_freq_to_grid(presets
[curr_preset
].frequency
);
345 tuner_set(RADIO_FREQUENCY
, curr_freq
);
346 remember_frequency();
349 /* Step to the next or previous frequency */
350 static int step_freq(int freq
, int direction
)
352 const struct fm_region_data
* const fmr
=
353 &fm_region_data
[global_settings
.fm_region
];
355 freq
+= direction
*fmr
->freq_step
;
357 /* Wrap first or snapping to grid will not let us on the band extremes */
358 if (freq
> fmr
->freq_max
)
359 freq
= direction
> 0 ? fmr
->freq_min
: fmr
->freq_max
;
360 else if (freq
< fmr
->freq_min
)
361 freq
= direction
< 0 ? fmr
->freq_max
: fmr
->freq_min
;
363 freq
= snap_freq_to_grid(freq
);
368 /* Step to the next or previous station */
369 static void next_station(int direction
)
371 if (direction
!= 0 && radio_mode
!= RADIO_SCAN_MODE
)
373 next_preset(direction
);
377 curr_freq
= step_freq(curr_freq
, direction
);
379 if (radio_status
== FMRADIO_PLAYING
)
380 tuner_set(RADIO_MUTE
, 1);
382 tuner_set(RADIO_FREQUENCY
, curr_freq
);
384 if (radio_status
== FMRADIO_PLAYING
)
385 tuner_set(RADIO_MUTE
, 0);
387 curr_preset
= find_preset(curr_freq
);
388 remember_frequency();
391 /* Ends an in-progress search */
392 static void end_search(void)
394 if (search_dir
!= 0 && radio_status
== FMRADIO_PLAYING
)
395 tuner_set(RADIO_MUTE
, 0);
399 /* Speak a frequency. */
400 static void talk_freq(int freq
, bool enqueue
)
403 talk_number(freq
/ 100, enqueue
);
404 talk_id(LANG_POINT
, true);
405 talk_number(freq
% 100 / 10, true);
407 talk_number(freq
% 10, true);
410 /* Speak a preset by number or by spelling its name, depending on settings. */
411 static void talk_preset(int preset
, bool fallback
, bool enqueue
)
413 if (global_settings
.talk_file
== 1) /* number */
414 talk_number(preset
+ 1, enqueue
);
417 if(presets
[preset
].name
[0])
418 talk_spell(presets
[preset
].name
, enqueue
);
420 talk_freq(presets
[preset
].frequency
, enqueue
);
424 int radio_screen(void)
428 int ret_val
= GO_TO_ROOT
;
431 bool stereo
= false, last_stereo
= false;
433 int top_of_screen
= 0;
434 bool update_screen
= true;
435 bool screen_freeze
= false;
436 bool keep_playing
= false;
437 bool statusbar
= global_settings
.statusbar
;
439 #ifdef FM_RECORD_DBLPRE
440 int lastbutton
= BUTTON_NONE
;
441 unsigned long rec_lastclick
= 0;
443 #if CONFIG_CODEC != SWCODEC
444 bool have_recorded
= false;
445 int timeout
= current_tick
+ HZ
/10;
446 unsigned int seconds
= 0;
447 unsigned int last_seconds
= 0;
449 struct audio_recording_options rec_options
;
450 #endif /* CONFIG_CODEC != SWCODEC */
451 #ifndef HAVE_NOISY_IDLE_MODE
452 int button_timeout
= current_tick
+ (2*HZ
);
455 struct gui_buttonbar buttonbar
;
456 gui_buttonbar_init(&buttonbar
);
457 gui_buttonbar_set_display(&buttonbar
, &(screens
[SCREEN_MAIN
]) );
460 /* change status to "in screen" */
463 /* always display status bar in radio screen for now */
464 global_status
.statusbar_forced
= statusbar
?0:1;
465 global_settings
.statusbar
= true;
468 gui_textarea_clear(&screens
[i
]);
469 screen_set_xmargin(&screens
[i
],0);
472 gui_syncstatusbar_draw(&statusbars
,true);
474 fh
= font_get(FONT_UI
)->height
;
476 /* Adjust for font size, trying to center the information vertically */
482 memset(presets
, 0, sizeof(presets
));
483 radio_load_presets(global_settings
.fmr_file
);
486 if(radio_status
== FMRADIO_OFF
)
490 #if CONFIG_CODEC != SWCODEC
491 if(rec_create_directory() > 0)
492 have_recorded
= true;
494 audio_init_recording(talk_get_bufsize());
496 sound_settings_apply();
497 /* Yes, we use the D/A for monitoring */
498 peak_meter_playback(true);
500 peak_meter_enabled
= true;
502 rec_init_recording_options(&rec_options
);
503 rec_options
.rec_source
= AUDIO_SRC_LINEIN
;
504 rec_set_recording_options(&rec_options
);
506 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN
),
507 sound_default(SOUND_RIGHT_GAIN
), AUDIO_GAIN_LINEIN
);
509 #endif /* CONFIG_CODEC != SWCODEC */
510 #endif /* ndef SIMULATOR */
513 #if CONFIG_CODEC == SWCODEC
514 audio_set_input_source(AUDIO_SRC_FMRADIO
,
515 (radio_status
== FMRADIO_PAUSED
) ?
516 SRCF_FMRADIO_PAUSED
: SRCF_FMRADIO_PLAYING
);
518 if (radio_status
== FMRADIO_OFF
)
522 if(num_presets
< 1 && yesno_pop(ID2P(LANG_FM_FIRST_AUTOSCAN
)))
525 curr_preset
= find_preset(curr_freq
);
526 if(curr_preset
!= -1)
527 radio_mode
= RADIO_PRESET_MODE
;
530 gui_buttonbar_set(&buttonbar
, str(LANG_BUTTONBAR_MENU
),
531 str(LANG_PRESET
), str(LANG_FM_BUTTONBAR_RECORD
));
534 #ifndef HAVE_NOISY_IDLE_MODE
542 curr_freq
= step_freq(curr_freq
, search_dir
);
543 update_screen
= true;
545 if(tuner_set(RADIO_SCAN_FREQUENCY
, curr_freq
))
547 curr_preset
= find_preset(curr_freq
);
548 remember_frequency();
561 #if CONFIG_CODEC != SWCODEC
562 /* TODO: Can we timeout at HZ when recording since peaks aren't
563 displayed? This should quiet recordings too. */
564 button
= get_action(CONTEXT_FM
,
565 update_screen
? TIMEOUT_NOBLOCK
: HZ
/ PEAK_METER_FPS
);
567 button
= get_action(CONTEXT_FM
,
568 update_screen
? TIMEOUT_NOBLOCK
: HZ
);
571 #ifndef HAVE_NOISY_IDLE_MODE
572 if (button
!= ACTION_NONE
)
574 cpu_idle_mode(false);
575 button_timeout
= current_tick
+ (2*HZ
);
581 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
582 if(audio_status() == AUDIO_STATUS_RECORD
)
592 if(yesno_pop(ID2P(LANG_FM_SAVE_CHANGES
)))
594 if(filepreset
[0] == '\0')
597 radio_save_presets();
600 /* Clear the preset list on exit. */
603 update_screen
= true;
607 case ACTION_FM_RECORD
:
608 #ifdef FM_RECORD_DBLPRE
609 if (lastbutton
!= ACTION_FM_RECORD_DBLPRE
)
614 if (current_tick
- rec_lastclick
> HZ
/2)
616 rec_lastclick
= current_tick
;
619 #endif /* FM_RECORD_DBLPRE */
621 if(audio_status() == AUDIO_STATUS_RECORD
)
623 rec_command(RECORDING_CMD_START_NEWFILE
);
624 update_screen
= true;
628 have_recorded
= true;
629 rec_command(RECORDING_CMD_START
);
630 update_screen
= true;
632 #endif /* SIMULATOR */
635 #endif /* #ifdef FM_RECORD */
638 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
639 if(audio_status() == AUDIO_STATUS_RECORD
)
644 ret_val
= GO_TO_ROOT
;
647 if(yesno_pop(ID2P(LANG_FM_SAVE_CHANGES
)))
649 if(filepreset
[0] == '\0')
652 radio_save_presets();
656 /* Clear the preset list on exit. */
661 case ACTION_STD_PREV
:
662 case ACTION_STD_NEXT
:
663 next_station(button
== ACTION_STD_PREV
? -1 : 1);
665 update_screen
= true;
669 case ACTION_STD_PREVREPEAT
:
670 case ACTION_STD_NEXTREPEAT
:
672 int dir
= search_dir
;
673 search_dir
= button
== ACTION_STD_PREVREPEAT
? -1 : 1;
674 if (radio_mode
!= RADIO_SCAN_MODE
)
676 next_preset(search_dir
);
678 update_screen
= true;
683 /* Starting auto scan */
684 tuner_set(RADIO_MUTE
, 1);
685 update_screen
= true;
690 case ACTION_SETTINGS_INC
:
691 case ACTION_SETTINGS_INCREPEAT
:
692 global_settings
.volume
++;
694 update_screen
= true;
697 case ACTION_SETTINGS_DEC
:
698 case ACTION_SETTINGS_DECREPEAT
:
699 global_settings
.volume
--;
701 update_screen
= true;
705 if (radio_status
== FMRADIO_PLAYING
)
710 update_screen
= true;
717 curr_preset
= find_preset(curr_freq
);
719 struct screen
*sc
= &screens
[i
];
720 gui_textarea_clear(sc
);
721 screen_set_xmargin(sc
, 0);
724 gui_buttonbar_set(&buttonbar
, str(LANG_BUTTONBAR_MENU
),
726 str(LANG_FM_BUTTONBAR_RECORD
));
728 update_screen
= true;
732 case ACTION_FM_PRESET
:
735 gui_syncsplash(HZ
, ID2P(LANG_FM_NO_PRESETS
));
736 update_screen
= true;
739 struct screen
*sc
= &screens
[i
];
740 gui_textarea_clear(sc
);
741 screen_set_xmargin(sc
, 0);
742 gui_textarea_update(sc
);
747 handle_radio_presets();
750 struct screen
*sc
= &screens
[i
];
751 gui_textarea_clear(sc
);
752 screen_set_xmargin(sc
, 0);
753 gui_textarea_update(sc
);
756 gui_buttonbar_set(&buttonbar
,
757 str(LANG_BUTTONBAR_MENU
),
759 str(LANG_FM_BUTTONBAR_RECORD
));
761 update_screen
= true;
763 #endif /* FM_PRESET */
766 case ACTION_FM_FREEZE
:
769 gui_syncsplash(HZ
, str(LANG_FM_FREEZE
));
770 screen_freeze
= true;
774 update_screen
= true;
775 screen_freeze
= false;
778 #endif /* FM_FREEZE */
780 case SYS_USB_CONNECTED
:
781 #if CONFIG_CODEC != SWCODEC
782 /* Only accept USB connection when not recording */
783 if(audio_status() != AUDIO_STATUS_RECORD
)
786 default_event_handler(SYS_USB_CONNECTED
);
787 screen_freeze
= true; /* Cosmetic: makes sure the
788 radio screen doesn't redraw */
795 if(radio_mode
== RADIO_SCAN_MODE
)
797 /* Force scan mode if there are no presets. */
799 radio_mode
= RADIO_PRESET_MODE
;
802 radio_mode
= RADIO_SCAN_MODE
;
803 update_screen
= true;
804 cond_talk_ids_fq(radio_mode
?
805 LANG_PRESET
: LANG_RADIO_SCAN_MODE
);
810 #ifdef FM_NEXT_PRESET
811 case ACTION_FM_NEXT_PRESET
:
814 update_screen
= true;
819 #ifdef FM_PREV_PRESET
820 case ACTION_FM_PREV_PRESET
:
823 update_screen
= true;
829 default_event_handler(button
);
833 #ifdef FM_RECORD_DBLPRE
834 if (button
!= ACTION_NONE
)
838 #if CONFIG_CODEC != SWCODEC
844 /* Only display the peak meter when not recording */
845 #if CONFIG_CODEC != SWCODEC
850 peak_meter_screen(&screens
[i
],0,
851 STATUSBAR_HEIGHT
+ fh
*(top_of_screen
+ 4), fh
);
852 screens
[i
].update_rect(0, STATUSBAR_HEIGHT
+ fh
*(top_of_screen
+ 4),
853 screens
[i
].width
, fh
);
857 if(TIME_AFTER(current_tick
, timeout
))
859 timeout
= current_tick
+ HZ
;
862 #endif /* CONFIG_CODEC == SWCODEC */
864 /* keep "mono" from always being displayed when paused */
865 if (radio_status
!= FMRADIO_PAUSED
)
867 stereo
= tuner_get(RADIO_STEREO
) &&
868 !global_settings
.fm_force_mono
;
870 if(stereo
!= last_stereo
)
872 update_screen
= true;
873 last_stereo
= stereo
;
878 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
879 seconds
= audio_recorded_time() / HZ
;
880 if (update_screen
|| seconds
> last_seconds
)
882 last_seconds
= seconds
;
890 screens
[i
].setfont(FONT_UI
);
892 snprintf(buf
, 128, curr_preset
>= 0 ? "%d. %s" : " ",
893 curr_preset
+ 1, presets
[curr_preset
].name
);
896 screens
[i
].puts_scroll(0, top_of_screen
, buf
);
898 freq
= curr_freq
/ 10000;
899 snprintf(buf
, 128, str(LANG_FM_STATION
), freq
/ 100, freq
% 100);
901 screens
[i
].puts_scroll(0, top_of_screen
+ 1, buf
);
903 snprintf(buf
, 128, stereo
?str(LANG_CHANNEL_STEREO
):
904 str(LANG_CHANNEL_MONO
));
906 screens
[i
].puts_scroll(0, top_of_screen
+ 2, buf
);
908 snprintf(buf
, 128, "%s %s", str(LANG_MODE
),
909 radio_mode
? str(LANG_PRESET
) :
910 str(LANG_RADIO_SCAN_MODE
));
912 screens
[i
].puts_scroll(0, top_of_screen
+ 3, buf
);
914 #if CONFIG_CODEC != SWCODEC
915 if(audio_status() == AUDIO_STATUS_RECORD
)
917 hours
= seconds
/ 3600;
918 minutes
= (seconds
- (hours
* 3600)) / 60;
919 snprintf(buf
, 32, "%s %02d:%02d:%02d",
920 str(LANG_RECORDING_TIME
),
921 hours
, minutes
, seconds
%60);
923 screens
[i
].puts_scroll(0, top_of_screen
+ 4, buf
);
927 if(rec_options
.rec_prerecord_time
)
929 snprintf(buf
, 32, "%s %02d",
930 str(LANG_RECORD_PRERECORD
), seconds
%60);
932 screens
[i
].puts_scroll(0, top_of_screen
+ 4, buf
);
935 #endif /* CONFIG_CODEC != SWCODEC */
938 gui_buttonbar_draw(&buttonbar
);
941 gui_textarea_update(&screens
[i
]);
943 /* Only force the redraw if update_screen is true */
944 gui_syncstatusbar_draw(&statusbars
,true);
947 update_screen
= false;
949 if (global_settings
.talk_file
&& talk
950 && radio_status
== FMRADIO_PAUSED
)
953 bool enqueue
= false;
954 if (radio_mode
== RADIO_SCAN_MODE
)
956 talk_freq(curr_freq
, enqueue
);
959 if (curr_preset
>= 0)
960 talk_preset(curr_preset
, radio_mode
== RADIO_PRESET_MODE
,
964 #if CONFIG_CODEC != SWCODEC
965 if(audio_status() & AUDIO_STATUS_ERROR
)
971 #ifndef HAVE_NOISY_IDLE_MODE
972 if (TIME_AFTER(current_tick
, button_timeout
))
980 #if CONFIG_CODEC != SWCODEC
981 if(audio_status() & AUDIO_STATUS_ERROR
)
983 gui_syncsplash(0, str(LANG_DISK_FULL
));
984 gui_syncstatusbar_draw(&statusbars
,true);
986 gui_textarea_update(&screens
[i
]);
991 button
= get_action(CONTEXT_FM
, TIMEOUT_BLOCK
);
992 if(button
== ACTION_FM_STOP
)
997 audio_init_playback();
998 #endif /* CONFIG_CODEC != SWCODEC */
1000 sound_settings_apply();
1001 #endif /* SIMULATOR */
1005 /* Catch FMRADIO_PLAYING status for the sim. */
1007 #if CONFIG_CODEC != SWCODEC
1008 /* Enable the Left and right A/D Converter */
1009 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN
),
1010 sound_default(SOUND_RIGHT_GAIN
),
1012 mas_codec_writereg(6, 0x4000);
1015 #endif /* SIMULATOR */
1019 #if CONFIG_CODEC == SWCODEC
1020 audio_set_input_source(AUDIO_SRC_PLAYBACK
, SRCF_PLAYBACK
);
1026 #ifndef HAVE_NOISY_IDLE_MODE
1027 cpu_idle_mode(false);
1030 /* restore status bar settings */
1031 global_settings
.statusbar
= statusbar
;
1032 global_status
.statusbar_forced
= 0;
1034 #if CONFIG_CODEC != SWCODEC
1035 return have_recorded
;
1039 } /* radio_screen */
1041 static void radio_save_presets(void)
1046 fd
= creat(filepreset
);
1049 for(i
= 0;i
< num_presets
;i
++)
1051 fdprintf(fd
, "%d:%s\n", presets
[i
].frequency
, presets
[i
].name
);
1055 if(!strncasecmp(FMPRESET_PATH
, filepreset
, strlen(FMPRESET_PATH
)))
1056 set_file(filepreset
, global_settings
.fmr_file
, MAX_FILENAME
);
1057 presets_changed
= false;
1061 gui_syncsplash(HZ
, ID2P(LANG_FM_PRESET_SAVE_FAILED
));
1065 void radio_load_presets(char *filename
)
1075 memset(presets
, 0, sizeof(presets
));
1078 /* No Preset in configuration. */
1079 if(filename
[0] == '\0')
1081 filepreset
[0] = '\0';
1084 /* Temporary preset, loaded until player shuts down. */
1085 else if(filename
[0] == '/')
1086 strncpy(filepreset
, filename
, sizeof(filepreset
));
1087 /* Preset from default directory. */
1089 snprintf(filepreset
, sizeof(filepreset
), "%s/%s.fmr",
1090 FMPRESET_PATH
, filename
);
1092 fd
= open(filepreset
, O_RDONLY
);
1095 while(!done
&& num_presets
< MAX_PRESETS
)
1097 rc
= read_line(fd
, buf
, 128);
1100 if(settings_parseline(buf
, &freq
, &name
))
1103 if(f
) /* For backwards compatibility */
1105 struct fmstation
* const fms
= &presets
[num_presets
];
1107 strncpy(fms
->name
, name
, MAX_FMPRESET_LEN
);
1108 fms
->name
[MAX_FMPRESET_LEN
] = '\0';
1118 else /* invalid file name? */
1119 filepreset
[0] = '\0';
1121 presets_loaded
= num_presets
> 0;
1122 presets_changed
= false;
1126 static int radio_add_preset(void)
1128 char buf
[MAX_FMPRESET_LEN
+ 1];
1130 if(num_presets
< MAX_PRESETS
)
1132 memset(buf
, 0, MAX_FMPRESET_LEN
);
1134 if (!kbd_input(buf
, MAX_FMPRESET_LEN
))
1136 struct fmstation
* const fms
= &presets
[num_presets
];
1137 buf
[MAX_FMPRESET_LEN
] = '\0';
1138 strcpy(fms
->name
, buf
);
1139 fms
->frequency
= curr_freq
;
1141 presets_changed
= true;
1142 presets_loaded
= num_presets
> 0;
1147 gui_syncsplash(HZ
, ID2P(LANG_FM_NO_FREE_PRESETS
));
1152 /* needed to know which preset we are edit/delete-ing */
1153 static int selected_preset
= -1;
1154 static int radio_edit_preset(void)
1156 char buf
[MAX_FMPRESET_LEN
+ 1];
1158 if (num_presets
> 0)
1160 struct fmstation
* const fms
= &presets
[selected_preset
];
1162 strncpy(buf
, fms
->name
, MAX_FMPRESET_LEN
);
1164 if (!kbd_input(buf
, MAX_FMPRESET_LEN
))
1166 buf
[MAX_FMPRESET_LEN
] = '\0';
1167 strcpy(fms
->name
, buf
);
1168 presets_changed
= true;
1175 static int radio_delete_preset(void)
1177 if (num_presets
> 0)
1179 struct fmstation
* const fms
= &presets
[selected_preset
];
1181 if (selected_preset
>= --num_presets
)
1182 selected_preset
= num_presets
- 1;
1184 memmove(fms
, fms
+ 1, (uintptr_t)(fms
+ num_presets
) -
1189 /* Don't ask to save when all presets are deleted. */
1190 presets_changed
= num_presets
> 0;
1192 if (!presets_changed
)
1194 /* The preset list will be cleared, switch to Scan Mode. */
1195 radio_mode
= RADIO_SCAN_MODE
;
1196 presets_loaded
= false;
1202 static int load_preset_list(void)
1204 return !rockbox_browse(FMPRESET_PATH
, SHOW_FMR
);
1207 static int save_preset_list(void)
1211 bool bad_file_name
= true;
1213 if(!dir_exists(FMPRESET_PATH
)) /* Check if there is preset folder */
1214 mkdir(FMPRESET_PATH
);
1216 create_numbered_filename(filepreset
, FMPRESET_PATH
, "preset",
1217 ".fmr", 2 IF_CNFN_NUM_(, NULL
));
1219 while(bad_file_name
)
1221 if(!kbd_input(filepreset
, sizeof(filepreset
)))
1223 /* check the name: max MAX_FILENAME (20) chars */
1227 p1
= strrchr(filepreset
, '/');
1229 while((p1
) && (*p2
) && (*p2
!= '.'))
1231 len
= (int)(p2
-p1
) - 1;
1232 if((!p1
) || (len
> MAX_FILENAME
) || (len
== 0))
1234 /* no slash, too long or too short */
1235 gui_syncsplash(HZ
, ID2P(LANG_INVALID_FILENAME
));
1239 /* add correct extension (easier to always write)
1240 at this point, p2 points to 0 or the extension dot */
1242 strcat(filepreset
,".fmr");
1243 bad_file_name
= false;
1244 radio_save_presets();
1255 gui_syncsplash(HZ
, ID2P(LANG_FM_NO_PRESETS
));
1260 static int clear_preset_list(void)
1262 /* Clear all the preset entries */
1263 memset(presets
, 0, sizeof (presets
));
1266 presets_loaded
= false;
1267 /* The preset list will be cleared switch to Scan Mode. */
1268 radio_mode
= RADIO_SCAN_MODE
;
1270 presets_changed
= false; /* Don't ask to save when clearing the list. */
1275 MENUITEM_FUNCTION(radio_edit_preset_item
, MENU_FUNC_CHECK_RETVAL
,
1276 ID2P(LANG_FM_EDIT_PRESET
),
1277 radio_edit_preset
, NULL
, NULL
, Icon_NOICON
);
1278 MENUITEM_FUNCTION(radio_delete_preset_item
, MENU_FUNC_CHECK_RETVAL
,
1279 ID2P(LANG_FM_DELETE_PRESET
),
1280 radio_delete_preset
, NULL
, NULL
, Icon_NOICON
);
1281 static int radio_preset_callback(int action
,
1282 const struct menu_item_ex
*this_item
)
1284 if (action
== ACTION_STD_OK
)
1285 action
= ACTION_EXIT_AFTER_THIS_MENUITEM
;
1289 MAKE_MENU(handle_radio_preset_menu
, ID2P(LANG_PRESET
),
1290 radio_preset_callback
, Icon_NOICON
, &radio_edit_preset_item
,
1291 &radio_delete_preset_item
);
1292 /* present a list of preset stations */
1293 static char * presets_get_name(int selected_item
, void *data
,
1294 char *buffer
, size_t buffer_len
)
1297 struct fmstation
*p
= &presets
[selected_item
];
1300 int freq
= p
->frequency
/ 10000;
1301 int frac
= freq
% 100;
1303 snprintf(buffer
, buffer_len
,
1304 str(LANG_FM_DEFAULT_PRESET_NAME
), freq
, frac
);
1308 static int presets_speak_name(int selected_item
, void * data
)
1311 talk_preset(selected_item
, true, false);
1315 static int handle_radio_presets(void)
1317 struct gui_synclist lists
;
1319 int action
= ACTION_NONE
;
1320 #ifdef HAS_BUTTONBAR
1321 struct gui_buttonbar buttonbar
;
1324 if(presets_loaded
== false)
1327 #ifdef HAS_BUTTONBAR
1328 gui_buttonbar_init(&buttonbar
);
1329 gui_buttonbar_set_display(&buttonbar
, &(screens
[SCREEN_MAIN
]) );
1330 gui_buttonbar_set(&buttonbar
, str(LANG_FM_BUTTONBAR_ADD
),
1331 str(LANG_FM_BUTTONBAR_EXIT
),
1332 str(LANG_FM_BUTTONBAR_ACTION
));
1333 gui_buttonbar_draw(&buttonbar
);
1335 gui_synclist_init(&lists
, presets_get_name
, NULL
, false, 1, NULL
);
1336 gui_synclist_set_title(&lists
, str(LANG_PRESET
), NOICON
);
1337 gui_synclist_set_icon_callback(&lists
, NULL
);
1338 if(global_settings
.talk_file
)
1339 gui_synclist_set_voice_callback(&lists
, presets_speak_name
);
1340 gui_synclist_set_nb_items(&lists
, num_presets
);
1341 gui_synclist_select_item(&lists
, curr_preset
<0 ? 0 : curr_preset
);
1342 gui_synclist_speak_item(&lists
);
1346 gui_synclist_draw(&lists
);
1347 gui_syncstatusbar_draw(&statusbars
, true);
1348 list_do_action(CONTEXT_STD
, HZ
,
1349 &lists
, &action
, LIST_WRAP_UNLESS_HELD
);
1352 case ACTION_STD_MENU
:
1355 case ACTION_STD_CANCEL
:
1359 curr_preset
= gui_synclist_get_sel_pos(&lists
);
1360 curr_freq
= presets
[curr_preset
].frequency
;
1362 remember_frequency();
1366 case ACTION_STD_CONTEXT
:
1367 selected_preset
= gui_synclist_get_sel_pos(&lists
);
1368 do_menu(&handle_radio_preset_menu
, NULL
, NULL
, false);
1369 gui_synclist_speak_item(&lists
);
1372 if(default_event_handler(action
) == SYS_USB_CONNECTED
)
1379 void toggle_mono_mode(bool mono
)
1381 tuner_set(RADIO_FORCE_MONO
, mono
);
1384 void set_radio_region(int region
)
1386 #ifdef HAVE_RADIO_REGION
1387 tuner_set(RADIO_REGION
, region
);
1390 remember_frequency();
1394 MENUITEM_SETTING(set_region
, &global_settings
.fm_region
, NULL
);
1395 MENUITEM_SETTING(force_mono
, &global_settings
.fm_force_mono
, NULL
);
1398 static char* get_mode_text(int selected_item
, void * data
, char *buffer
)
1400 (void)selected_item
;
1402 snprintf(buffer
, MAX_PATH
, "%s %s", str(LANG_MODE
),
1403 radio_mode
? str(LANG_PRESET
) :
1404 str(LANG_RADIO_SCAN_MODE
));
1407 static int toggle_radio_mode(void)
1409 radio_mode
= (radio_mode
== RADIO_SCAN_MODE
) ?
1410 RADIO_PRESET_MODE
: RADIO_SCAN_MODE
;
1413 MENUITEM_FUNCTION_DYNTEXT(radio_mode_item
, 0,
1414 toggle_radio_mode
, NULL
,
1415 get_mode_text
, NULL
, NULL
, NULL
, Icon_NOICON
);
1418 static int scan_presets(void)
1420 bool do_scan
= true;
1422 if(num_presets
> 0) /* Do that to avoid 2 questions. */
1423 do_scan
= yesno_pop(ID2P(LANG_FM_CLEAR_PRESETS
));
1427 const struct fm_region_data
* const fmr
=
1428 &fm_region_data
[global_settings
.fm_region
];
1430 char buf
[MAX_FMPRESET_LEN
+ 1];
1433 curr_freq
= fmr
->freq_min
;
1435 memset(presets
, 0, sizeof(presets
));
1436 tuner_set(RADIO_MUTE
, 1);
1438 while(curr_freq
<= fmr
->freq_max
)
1441 if (num_presets
>= MAX_PRESETS
|| action_userabort(TIMEOUT_NOBLOCK
))
1444 freq
= curr_freq
/ 10000;
1448 snprintf(buf
, MAX_FMPRESET_LEN
, str(LANG_FM_SCANNING
), freq
, frac
);
1449 gui_syncsplash(0, buf
);
1451 if(tuner_set(RADIO_SCAN_FREQUENCY
, curr_freq
))
1454 presets
[num_presets
].name
[0] = '\0';
1455 presets
[num_presets
].frequency
= curr_freq
;
1459 curr_freq
+= fmr
->freq_step
;
1462 if (radio_status
== FMRADIO_PLAYING
)
1463 tuner_set(RADIO_MUTE
, 0);
1465 presets_changed
= true;
1469 gui_textarea_clear(&screens
[i
]);
1470 screen_set_xmargin(&screens
[i
],0);
1471 gui_textarea_update(&screens
[i
]);
1476 curr_freq
= presets
[0].frequency
;
1477 radio_mode
= RADIO_PRESET_MODE
;
1478 presets_loaded
= true;
1483 /* Wrap it to beginning or we'll be past end of band */
1484 presets_loaded
= false;
1492 #ifdef HAVE_RECORDING
1494 #if defined(HAVE_FMRADIO_REC) && CONFIG_CODEC == SWCODEC
1495 #define FM_RECORDING_SCREEN
1496 static int fm_recording_screen(void)
1500 /* switch recording source to FMRADIO for the duration */
1501 int rec_source
= global_settings
.rec_source
;
1502 global_settings
.rec_source
= AUDIO_SRC_FMRADIO
;
1504 ret
= recording_screen(true);
1506 /* safe to reset as changing sources is prohibited here */
1507 global_settings
.rec_source
= rec_source
;
1512 #endif /* defined(HAVE_FMRADIO_REC) && CONFIG_CODEC == SWCODEC */
1514 #if defined(HAVE_FMRADIO_REC) || CONFIG_CODEC != SWCODEC
1515 #define FM_RECORDING_SETTINGS
1516 static int fm_recording_settings(void)
1518 bool ret
= recording_menu(true);
1520 #if CONFIG_CODEC != SWCODEC
1523 struct audio_recording_options rec_options
;
1524 rec_init_recording_options(&rec_options
);
1525 rec_options
.rec_source
= AUDIO_SRC_LINEIN
;
1526 rec_set_recording_options(&rec_options
);
1533 #endif /* defined(HAVE_FMRADIO_REC) || CONFIG_CODEC != SWCODEC */
1534 #endif /* HAVE_RECORDING */
1536 #ifdef FM_RECORDING_SCREEN
1537 MENUITEM_FUNCTION(recscreen_item
, 0, ID2P(LANG_RECORDING
),
1538 fm_recording_screen
, NULL
, NULL
, Icon_Recording
);
1540 #ifdef FM_RECORDING_SETTINGS
1541 MENUITEM_FUNCTION(recsettings_item
, 0, ID2P(LANG_RECORDING_SETTINGS
),
1542 fm_recording_settings
, NULL
, NULL
, Icon_Recording
);
1545 MENUITEM_FUNCTION(radio_presets_item
, 0, ID2P(LANG_PRESET
),
1546 handle_radio_presets
, NULL
, NULL
, Icon_NOICON
);
1548 #ifndef FM_PRESET_ADD
1549 MENUITEM_FUNCTION(radio_addpreset_item
, 0, ID2P(LANG_FM_ADD_PRESET
),
1550 radio_add_preset
, NULL
, NULL
, Icon_NOICON
);
1554 MENUITEM_FUNCTION(presetload_item
, 0, ID2P(LANG_FM_PRESET_LOAD
),
1555 load_preset_list
, NULL
, NULL
, Icon_NOICON
);
1556 MENUITEM_FUNCTION(presetsave_item
, 0, ID2P(LANG_FM_PRESET_SAVE
),
1557 save_preset_list
, NULL
, NULL
, Icon_NOICON
);
1558 MENUITEM_FUNCTION(presetclear_item
, 0, ID2P(LANG_FM_PRESET_CLEAR
),
1559 clear_preset_list
, NULL
, NULL
, Icon_NOICON
);
1560 MENUITEM_FUNCTION(scan_presets_item
, 0, ID2P(LANG_FM_SCAN_PRESETS
),
1561 scan_presets
, NULL
, NULL
, Icon_NOICON
);
1563 MAKE_MENU(radio_settings_menu
, ID2P(LANG_FM_MENU
), NULL
,
1566 &radio_presets_item
,
1568 #ifndef FM_PRESET_ADD
1569 &radio_addpreset_item
,
1571 &presetload_item
, &presetsave_item
, &presetclear_item
,
1576 &set_region
, &sound_settings
,
1577 #ifdef FM_RECORDING_SCREEN
1580 #ifdef FM_RECORDING_SETTINGS
1583 &scan_presets_item
);
1584 /* main menu of the radio screen */
1585 static bool radio_menu(void)
1587 return do_menu(&radio_settings_menu
, NULL
, NULL
, false) == MENU_ATTACHED_USB
;