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"
44 #include "peakmeter.h"
47 #include "sound_menu.h"
49 #include "recording.h"
55 #include "screen_access.h"
56 #include "statusbar.h"
60 #include "buttonbar.h"
66 #include "menus/exported_menus.h"
67 #include "root_menu.h"
71 #if CONFIG_KEYPAD == RECORDER_PAD
74 #define FM_PRESET_ACTION
78 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
81 #define FM_NEXT_PRESET
82 #define FM_PREV_PRESET
84 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
88 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
91 /* This should be removeable if the whole tuning thing is sorted out since
92 proper tuning quiets the screen almost entirely in that extreme measures
93 have to be taken to hear any interference. */
94 #define HAVE_NOISY_IDLE_MODE
96 #elif CONFIG_KEYPAD == ONDIO_PAD
97 #define FM_RECORD_DBLPRE
99 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || (CONFIG_KEYPAD == SANSA_C200_PAD)
108 #define RADIO_SCAN_MODE 0
109 #define RADIO_PRESET_MODE 1
111 static int curr_preset
= -1;
112 static int curr_freq
;
113 static int radio_mode
= RADIO_SCAN_MODE
;
114 static int search_dir
= 0;
116 static int radio_status
= FMRADIO_OFF
;
117 static bool in_screen
= false;
119 #define MAX_PRESETS 64
120 static bool presets_loaded
= false, presets_changed
= false;
121 static struct fmstation presets
[MAX_PRESETS
];
123 static char filepreset
[MAX_PATH
]; /* preset filename variable */
125 static int num_presets
= 0; /* The number of presets in the preset list */
127 static void radio_save_presets(void);
128 static int handle_radio_presets(void);
129 static bool radio_menu(void);
130 static int radio_add_preset(void);
131 static int save_preset_list(void);
132 static int load_preset_list(void);
133 static int clear_preset_list(void);
135 static int scan_presets(void);
137 /* Function to manipulate all yesno dialogues.
138 This function needs the output text as an argument. */
139 static bool yesno_pop(char* text
)
142 char *lines
[]={text
};
143 struct text_message message
={lines
, 1};
144 bool ret
= (gui_syncyesno_run(&message
,NULL
,NULL
)== YESNO_YES
);
146 gui_textarea_clear(&screens
[i
]);
150 void radio_init(void)
156 int get_radio_status(void)
161 bool in_radio_screen(void)
166 /* TODO: Move some more of the control functionality to an HAL and clean up the
169 /* secret flag for starting paused - prevents unmute */
170 #define FMRADIO_START_PAUSED 0x8000
171 void radio_start(void)
173 const struct fm_region_data
*fmr
;
176 if(radio_status
== FMRADIO_PLAYING
)
179 fmr
= &fm_region_data
[global_settings
.fm_region
];
181 start_paused
= radio_status
& FMRADIO_START_PAUSED
;
182 /* clear flag before any yielding */
183 radio_status
&= ~FMRADIO_START_PAUSED
;
185 if(radio_status
== FMRADIO_OFF
)
188 curr_freq
= global_status
.last_frequency
189 * fmr
->freq_step
+ fmr
->freq_min
;
191 tuner_set(RADIO_SLEEP
, 0); /* wake up the tuner */
193 if(radio_status
== FMRADIO_OFF
)
195 #ifdef HAVE_RADIO_REGION
196 tuner_set(RADIO_REGION
, global_settings
.fm_region
);
198 tuner_set(RADIO_FORCE_MONO
, global_settings
.fm_force_mono
);
201 tuner_set(RADIO_FREQUENCY
, curr_freq
);
203 #ifdef HAVE_RADIO_MUTE_TIMEOUT
205 unsigned long mute_timeout
= current_tick
+ HZ
;
206 if (radio_status
!= FMRADIO_OFF
)
212 while(!tuner_get(RADIO_STEREO
) && !tuner_get(RADIO_TUNED
))
214 if(TIME_AFTER(current_tick
, mute_timeout
))
221 /* keep radio from sounding initially */
223 tuner_set(RADIO_MUTE
, 0);
225 radio_status
= FMRADIO_PLAYING
;
228 void radio_pause(void)
230 if(radio_status
== FMRADIO_PAUSED
)
233 if(radio_status
== FMRADIO_OFF
)
235 radio_status
|= FMRADIO_START_PAUSED
;
239 tuner_set(RADIO_MUTE
, 1);
240 tuner_set(RADIO_SLEEP
, 1);
242 radio_status
= FMRADIO_PAUSED
;
245 void radio_stop(void)
247 if(radio_status
== FMRADIO_OFF
)
250 tuner_set(RADIO_MUTE
, 1);
251 tuner_set(RADIO_SLEEP
, 1); /* low power mode, if available */
252 radio_status
= FMRADIO_OFF
;
253 tuner_power(false); /* status update, power off if avail. */
256 bool radio_hardware_present(void)
258 return tuner_get(RADIO_PRESENT
);
261 /* Keep freq on the grid for the current region */
262 static int snap_freq_to_grid(int freq
)
264 const struct fm_region_data
* const fmr
=
265 &fm_region_data
[global_settings
.fm_region
];
267 /* Range clamp if out of range or just round to nearest */
268 if (freq
< fmr
->freq_min
)
269 freq
= fmr
->freq_min
;
270 else if (freq
> fmr
->freq_max
)
271 freq
= fmr
->freq_max
;
273 freq
= (freq
- fmr
->freq_min
+ fmr
->freq_step
/2) /
274 fmr
->freq_step
* fmr
->freq_step
+ fmr
->freq_min
;
279 /* Find a matching preset to freq */
280 static int find_preset(int freq
)
285 for(i
= 0;i
< MAX_PRESETS
;i
++)
287 if(freq
== presets
[i
].frequency
)
294 /* Return the first preset encountered in the search direction with
296 static int find_closest_preset(int freq
, int direction
)
300 if (direction
== 0) /* direction == 0 isn't really used */
303 for (i
= 0; i
< MAX_PRESETS
; i
++)
305 int preset_frequency
= presets
[i
].frequency
;
307 if (preset_frequency
== freq
)
308 return i
; /* Exact match = stop */
309 /* Stop when the preset frequency exeeds freq so that we can
310 pick the correct one based on direction */
311 if (preset_frequency
> freq
)
315 /* wrap around depending on direction */
316 if (i
== 0 || i
>= num_presets
- 1)
317 i
= direction
< 0 ? num_presets
- 1 : 0;
318 else if (direction
< 0)
319 i
--; /* use previous */
324 static void remember_frequency(void)
326 const struct fm_region_data
* const fmr
=
327 &fm_region_data
[global_settings
.fm_region
];
328 global_status
.last_frequency
= (curr_freq
- fmr
->freq_min
)
333 static void next_preset(int direction
)
338 if (curr_preset
== -1)
339 curr_preset
= find_closest_preset(curr_freq
, direction
);
341 curr_preset
= (curr_preset
+ direction
+ num_presets
) % num_presets
;
343 /* Must stay on the current grid for the region */
344 curr_freq
= snap_freq_to_grid(presets
[curr_preset
].frequency
);
346 tuner_set(RADIO_FREQUENCY
, curr_freq
);
347 remember_frequency();
350 /* Step to the next or previous frequency */
351 static int step_freq(int freq
, int direction
)
353 const struct fm_region_data
* const fmr
=
354 &fm_region_data
[global_settings
.fm_region
];
356 freq
+= direction
*fmr
->freq_step
;
358 /* Wrap first or snapping to grid will not let us on the band extremes */
359 if (freq
> fmr
->freq_max
)
360 freq
= direction
> 0 ? fmr
->freq_min
: fmr
->freq_max
;
361 else if (freq
< fmr
->freq_min
)
362 freq
= direction
< 0 ? fmr
->freq_max
: fmr
->freq_min
;
364 freq
= snap_freq_to_grid(freq
);
369 /* Step to the next or previous station */
370 static void next_station(int direction
)
372 if (direction
!= 0 && radio_mode
!= RADIO_SCAN_MODE
)
374 next_preset(direction
);
378 curr_freq
= step_freq(curr_freq
, direction
);
380 if (radio_status
== FMRADIO_PLAYING
)
381 tuner_set(RADIO_MUTE
, 1);
383 tuner_set(RADIO_FREQUENCY
, curr_freq
);
385 if (radio_status
== FMRADIO_PLAYING
)
386 tuner_set(RADIO_MUTE
, 0);
388 curr_preset
= find_preset(curr_freq
);
389 remember_frequency();
392 /* Ends an in-progress search */
393 static void end_search(void)
395 if (search_dir
!= 0 && radio_status
== FMRADIO_PLAYING
)
396 tuner_set(RADIO_MUTE
, 0);
400 /* Speak a frequency. */
401 static void talk_freq(int freq
, bool enqueue
)
404 talk_number(freq
/ 100, enqueue
);
405 talk_id(LANG_POINT
, true);
406 talk_number(freq
% 100 / 10, true);
408 talk_number(freq
% 10, true);
411 /* Speak a preset by number or by spelling its name, depending on settings. */
412 static void talk_preset(int preset
, bool fallback
, bool enqueue
)
414 if (global_settings
.talk_file
== 1) /* number */
415 talk_number(preset
+ 1, enqueue
);
418 if(presets
[preset
].name
[0])
419 talk_spell(presets
[preset
].name
, enqueue
);
421 talk_freq(presets
[preset
].frequency
, enqueue
);
425 int radio_screen(void)
429 int ret_val
= GO_TO_ROOT
;
432 bool stereo
= false, last_stereo
= false;
434 int top_of_screen
= 0;
435 bool update_screen
= true;
436 bool screen_freeze
= false;
437 bool keep_playing
= false;
438 bool statusbar
= global_settings
.statusbar
;
440 #ifdef FM_RECORD_DBLPRE
441 int lastbutton
= BUTTON_NONE
;
442 unsigned long rec_lastclick
= 0;
444 #if CONFIG_CODEC != SWCODEC
445 bool have_recorded
= false;
446 int timeout
= current_tick
+ HZ
/10;
447 unsigned int seconds
= 0;
448 unsigned int last_seconds
= 0;
450 struct audio_recording_options rec_options
;
451 #endif /* CONFIG_CODEC != SWCODEC */
452 #ifndef HAVE_NOISY_IDLE_MODE
453 int button_timeout
= current_tick
+ (2*HZ
);
456 struct gui_buttonbar buttonbar
;
457 gui_buttonbar_init(&buttonbar
);
458 gui_buttonbar_set_display(&buttonbar
, &(screens
[SCREEN_MAIN
]) );
461 /* change status to "in screen" */
464 /* always display status bar in radio screen for now */
465 global_status
.statusbar_forced
= statusbar
?0:1;
466 global_settings
.statusbar
= true;
469 gui_textarea_clear(&screens
[i
]);
470 screen_set_xmargin(&screens
[i
],0);
473 gui_syncstatusbar_draw(&statusbars
,true);
475 fh
= font_get(FONT_UI
)->height
;
477 /* Adjust for font size, trying to center the information vertically */
483 memset(presets
, 0, sizeof(presets
));
484 radio_load_presets(global_settings
.fmr_file
);
487 if(radio_status
== FMRADIO_OFF
)
491 #if CONFIG_CODEC != SWCODEC
492 if(rec_create_directory() > 0)
493 have_recorded
= true;
495 audio_init_recording(talk_get_bufsize());
497 sound_settings_apply();
498 /* Yes, we use the D/A for monitoring */
499 peak_meter_playback(true);
501 peak_meter_enabled
= true;
503 rec_init_recording_options(&rec_options
);
504 rec_options
.rec_source
= AUDIO_SRC_LINEIN
;
505 rec_set_recording_options(&rec_options
);
507 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN
),
508 sound_default(SOUND_RIGHT_GAIN
), AUDIO_GAIN_LINEIN
);
510 #endif /* CONFIG_CODEC != SWCODEC */
511 #endif /* ndef SIMULATOR */
514 #if CONFIG_CODEC == SWCODEC
515 audio_set_input_source(AUDIO_SRC_FMRADIO
,
516 (radio_status
== FMRADIO_PAUSED
) ?
517 SRCF_FMRADIO_PAUSED
: SRCF_FMRADIO_PLAYING
);
519 if (radio_status
== FMRADIO_OFF
)
523 if(num_presets
< 1 && yesno_pop(ID2P(LANG_FM_FIRST_AUTOSCAN
)))
526 curr_preset
= find_preset(curr_freq
);
527 if(curr_preset
!= -1)
528 radio_mode
= RADIO_PRESET_MODE
;
531 gui_buttonbar_set(&buttonbar
, str(LANG_BUTTONBAR_MENU
),
532 str(LANG_PRESET
), str(LANG_FM_BUTTONBAR_RECORD
));
535 #ifndef HAVE_NOISY_IDLE_MODE
543 curr_freq
= step_freq(curr_freq
, search_dir
);
544 update_screen
= true;
546 if(tuner_set(RADIO_SCAN_FREQUENCY
, curr_freq
))
548 curr_preset
= find_preset(curr_freq
);
549 remember_frequency();
562 #if CONFIG_CODEC != SWCODEC
563 /* TODO: Can we timeout at HZ when recording since peaks aren't
564 displayed? This should quiet recordings too. */
565 button
= get_action(CONTEXT_FM
,
566 update_screen
? TIMEOUT_NOBLOCK
: HZ
/ PEAK_METER_FPS
);
568 button
= get_action(CONTEXT_FM
,
569 update_screen
? TIMEOUT_NOBLOCK
: HZ
);
572 #ifndef HAVE_NOISY_IDLE_MODE
573 if (button
!= ACTION_NONE
)
575 cpu_idle_mode(false);
576 button_timeout
= current_tick
+ (2*HZ
);
582 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
583 if(audio_status() == AUDIO_STATUS_RECORD
)
593 if(yesno_pop(ID2P(LANG_FM_SAVE_CHANGES
)))
595 if(filepreset
[0] == '\0')
598 radio_save_presets();
601 /* Clear the preset list on exit. */
604 update_screen
= true;
608 case ACTION_FM_RECORD
:
609 #ifdef FM_RECORD_DBLPRE
610 if (lastbutton
!= ACTION_FM_RECORD_DBLPRE
)
615 if (current_tick
- rec_lastclick
> HZ
/2)
617 rec_lastclick
= current_tick
;
620 #endif /* FM_RECORD_DBLPRE */
622 if(audio_status() == AUDIO_STATUS_RECORD
)
624 rec_command(RECORDING_CMD_START_NEWFILE
);
625 update_screen
= true;
629 have_recorded
= true;
630 rec_command(RECORDING_CMD_START
);
631 update_screen
= true;
633 #endif /* SIMULATOR */
636 #endif /* #ifdef FM_RECORD */
639 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
640 if(audio_status() == AUDIO_STATUS_RECORD
)
645 ret_val
= GO_TO_ROOT
;
648 if(yesno_pop(ID2P(LANG_FM_SAVE_CHANGES
)))
650 if(filepreset
[0] == '\0')
653 radio_save_presets();
657 /* Clear the preset list on exit. */
662 case ACTION_STD_PREV
:
663 case ACTION_STD_NEXT
:
664 next_station(button
== ACTION_STD_PREV
? -1 : 1);
666 update_screen
= true;
670 case ACTION_STD_PREVREPEAT
:
671 case ACTION_STD_NEXTREPEAT
:
673 int dir
= search_dir
;
674 search_dir
= button
== ACTION_STD_PREVREPEAT
? -1 : 1;
675 if (radio_mode
!= RADIO_SCAN_MODE
)
677 next_preset(search_dir
);
679 update_screen
= true;
684 /* Starting auto scan */
685 tuner_set(RADIO_MUTE
, 1);
686 update_screen
= true;
691 case ACTION_SETTINGS_INC
:
692 case ACTION_SETTINGS_INCREPEAT
:
693 global_settings
.volume
++;
695 update_screen
= true;
698 case ACTION_SETTINGS_DEC
:
699 case ACTION_SETTINGS_DECREPEAT
:
700 global_settings
.volume
--;
702 update_screen
= true;
706 if (radio_status
== FMRADIO_PLAYING
)
711 update_screen
= true;
718 curr_preset
= find_preset(curr_freq
);
720 struct screen
*sc
= &screens
[i
];
721 gui_textarea_clear(sc
);
722 screen_set_xmargin(sc
, 0);
725 gui_buttonbar_set(&buttonbar
, str(LANG_BUTTONBAR_MENU
),
727 str(LANG_FM_BUTTONBAR_RECORD
));
729 update_screen
= true;
733 case ACTION_FM_PRESET
:
736 gui_syncsplash(HZ
, ID2P(LANG_FM_NO_PRESETS
));
737 update_screen
= true;
740 struct screen
*sc
= &screens
[i
];
741 gui_textarea_clear(sc
);
742 screen_set_xmargin(sc
, 0);
743 gui_textarea_update(sc
);
748 handle_radio_presets();
751 struct screen
*sc
= &screens
[i
];
752 gui_textarea_clear(sc
);
753 screen_set_xmargin(sc
, 0);
754 gui_textarea_update(sc
);
757 gui_buttonbar_set(&buttonbar
,
758 str(LANG_BUTTONBAR_MENU
),
760 str(LANG_FM_BUTTONBAR_RECORD
));
762 update_screen
= true;
764 #endif /* FM_PRESET */
767 case ACTION_FM_FREEZE
:
770 gui_syncsplash(HZ
, str(LANG_FM_FREEZE
));
771 screen_freeze
= true;
775 update_screen
= true;
776 screen_freeze
= false;
779 #endif /* FM_FREEZE */
781 case SYS_USB_CONNECTED
:
782 #if CONFIG_CODEC != SWCODEC
783 /* Only accept USB connection when not recording */
784 if(audio_status() != AUDIO_STATUS_RECORD
)
787 default_event_handler(SYS_USB_CONNECTED
);
788 screen_freeze
= true; /* Cosmetic: makes sure the
789 radio screen doesn't redraw */
796 if(radio_mode
== RADIO_SCAN_MODE
)
798 /* Force scan mode if there are no presets. */
800 radio_mode
= RADIO_PRESET_MODE
;
803 radio_mode
= RADIO_SCAN_MODE
;
804 update_screen
= true;
805 cond_talk_ids_fq(radio_mode
?
806 LANG_PRESET
: LANG_RADIO_SCAN_MODE
);
811 #ifdef FM_NEXT_PRESET
812 case ACTION_FM_NEXT_PRESET
:
815 update_screen
= true;
820 #ifdef FM_PREV_PRESET
821 case ACTION_FM_PREV_PRESET
:
824 update_screen
= true;
830 default_event_handler(button
);
834 #ifdef FM_RECORD_DBLPRE
835 if (button
!= ACTION_NONE
)
839 #if CONFIG_CODEC != SWCODEC
845 /* Only display the peak meter when not recording */
846 #if CONFIG_CODEC != SWCODEC
851 peak_meter_screen(&screens
[i
],0,
852 STATUSBAR_HEIGHT
+ fh
*(top_of_screen
+ 4), fh
);
853 screens
[i
].update_rect(0, STATUSBAR_HEIGHT
+ fh
*(top_of_screen
+ 4),
854 screens
[i
].width
, fh
);
858 if(TIME_AFTER(current_tick
, timeout
))
860 timeout
= current_tick
+ HZ
;
863 #endif /* CONFIG_CODEC == SWCODEC */
865 /* keep "mono" from always being displayed when paused */
866 if (radio_status
!= FMRADIO_PAUSED
)
868 stereo
= tuner_get(RADIO_STEREO
) &&
869 !global_settings
.fm_force_mono
;
871 if(stereo
!= last_stereo
)
873 update_screen
= true;
874 last_stereo
= stereo
;
879 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
880 seconds
= audio_recorded_time() / HZ
;
881 if (update_screen
|| seconds
> last_seconds
)
883 last_seconds
= seconds
;
891 screens
[i
].setfont(FONT_UI
);
893 snprintf(buf
, 128, curr_preset
>= 0 ? "%d. %s" : " ",
894 curr_preset
+ 1, presets
[curr_preset
].name
);
897 screens
[i
].puts_scroll(0, top_of_screen
, buf
);
899 freq
= curr_freq
/ 10000;
900 snprintf(buf
, 128, str(LANG_FM_STATION
), freq
/ 100, freq
% 100);
902 screens
[i
].puts_scroll(0, top_of_screen
+ 1, buf
);
904 snprintf(buf
, 128, stereo
?str(LANG_CHANNEL_STEREO
):
905 str(LANG_CHANNEL_MONO
));
907 screens
[i
].puts_scroll(0, top_of_screen
+ 2, buf
);
909 snprintf(buf
, 128, "%s %s", str(LANG_MODE
),
910 radio_mode
? str(LANG_PRESET
) :
911 str(LANG_RADIO_SCAN_MODE
));
913 screens
[i
].puts_scroll(0, top_of_screen
+ 3, buf
);
915 #if CONFIG_CODEC != SWCODEC
916 if(audio_status() == AUDIO_STATUS_RECORD
)
918 hours
= seconds
/ 3600;
919 minutes
= (seconds
- (hours
* 3600)) / 60;
920 snprintf(buf
, 32, "%s %02d:%02d:%02d",
921 str(LANG_RECORDING_TIME
),
922 hours
, minutes
, seconds
%60);
924 screens
[i
].puts_scroll(0, top_of_screen
+ 4, buf
);
928 if(rec_options
.rec_prerecord_time
)
930 snprintf(buf
, 32, "%s %02d",
931 str(LANG_RECORD_PRERECORD
), seconds
%60);
933 screens
[i
].puts_scroll(0, top_of_screen
+ 4, buf
);
936 #endif /* CONFIG_CODEC != SWCODEC */
939 gui_buttonbar_draw(&buttonbar
);
942 gui_textarea_update(&screens
[i
]);
944 /* Only force the redraw if update_screen is true */
945 gui_syncstatusbar_draw(&statusbars
,true);
948 update_screen
= false;
950 if (global_settings
.talk_file
&& talk
951 && radio_status
== FMRADIO_PAUSED
)
954 bool enqueue
= false;
955 if (radio_mode
== RADIO_SCAN_MODE
)
957 talk_freq(curr_freq
, enqueue
);
960 if (curr_preset
>= 0)
961 talk_preset(curr_preset
, radio_mode
== RADIO_PRESET_MODE
,
965 #if CONFIG_CODEC != SWCODEC
966 if(audio_status() & AUDIO_STATUS_ERROR
)
972 #ifndef HAVE_NOISY_IDLE_MODE
973 if (TIME_AFTER(current_tick
, button_timeout
))
981 #if CONFIG_CODEC != SWCODEC
982 if(audio_status() & AUDIO_STATUS_ERROR
)
984 gui_syncsplash(0, str(LANG_DISK_FULL
));
985 gui_syncstatusbar_draw(&statusbars
,true);
987 gui_textarea_update(&screens
[i
]);
992 button
= get_action(CONTEXT_FM
, TIMEOUT_BLOCK
);
993 if(button
== ACTION_FM_STOP
)
998 audio_init_playback();
999 #endif /* CONFIG_CODEC != SWCODEC */
1001 sound_settings_apply();
1002 #endif /* SIMULATOR */
1006 /* Catch FMRADIO_PLAYING status for the sim. */
1008 #if CONFIG_CODEC != SWCODEC
1009 /* Enable the Left and right A/D Converter */
1010 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN
),
1011 sound_default(SOUND_RIGHT_GAIN
),
1013 mas_codec_writereg(6, 0x4000);
1016 #endif /* SIMULATOR */
1020 #if CONFIG_CODEC == SWCODEC
1021 audio_set_input_source(AUDIO_SRC_PLAYBACK
, SRCF_PLAYBACK
);
1027 #ifndef HAVE_NOISY_IDLE_MODE
1028 cpu_idle_mode(false);
1031 /* restore status bar settings */
1032 global_settings
.statusbar
= statusbar
;
1033 global_status
.statusbar_forced
= 0;
1035 #if CONFIG_CODEC != SWCODEC
1036 return have_recorded
;
1040 } /* radio_screen */
1042 static void radio_save_presets(void)
1047 fd
= creat(filepreset
);
1050 for(i
= 0;i
< num_presets
;i
++)
1052 fdprintf(fd
, "%d:%s\n", presets
[i
].frequency
, presets
[i
].name
);
1056 if(!strncasecmp(FMPRESET_PATH
, filepreset
, strlen(FMPRESET_PATH
)))
1057 set_file(filepreset
, global_settings
.fmr_file
, MAX_FILENAME
);
1058 presets_changed
= false;
1062 gui_syncsplash(HZ
, ID2P(LANG_FM_PRESET_SAVE_FAILED
));
1066 void radio_load_presets(char *filename
)
1076 memset(presets
, 0, sizeof(presets
));
1079 /* No Preset in configuration. */
1080 if(filename
[0] == '\0')
1082 filepreset
[0] = '\0';
1085 /* Temporary preset, loaded until player shuts down. */
1086 else if(filename
[0] == '/')
1087 strncpy(filepreset
, filename
, sizeof(filepreset
));
1088 /* Preset from default directory. */
1090 snprintf(filepreset
, sizeof(filepreset
), "%s/%s.fmr",
1091 FMPRESET_PATH
, filename
);
1093 fd
= open(filepreset
, O_RDONLY
);
1096 while(!done
&& num_presets
< MAX_PRESETS
)
1098 rc
= read_line(fd
, buf
, 128);
1101 if(settings_parseline(buf
, &freq
, &name
))
1104 if(f
) /* For backwards compatibility */
1106 struct fmstation
* const fms
= &presets
[num_presets
];
1108 strncpy(fms
->name
, name
, MAX_FMPRESET_LEN
);
1109 fms
->name
[MAX_FMPRESET_LEN
] = '\0';
1119 else /* invalid file name? */
1120 filepreset
[0] = '\0';
1122 presets_loaded
= num_presets
> 0;
1123 presets_changed
= false;
1127 static int radio_add_preset(void)
1129 char buf
[MAX_FMPRESET_LEN
+ 1];
1131 if(num_presets
< MAX_PRESETS
)
1133 memset(buf
, 0, MAX_FMPRESET_LEN
);
1135 if (!kbd_input(buf
, MAX_FMPRESET_LEN
))
1137 struct fmstation
* const fms
= &presets
[num_presets
];
1138 buf
[MAX_FMPRESET_LEN
] = '\0';
1139 strcpy(fms
->name
, buf
);
1140 fms
->frequency
= curr_freq
;
1142 presets_changed
= true;
1143 presets_loaded
= num_presets
> 0;
1148 gui_syncsplash(HZ
, ID2P(LANG_FM_NO_FREE_PRESETS
));
1153 /* needed to know which preset we are edit/delete-ing */
1154 static int selected_preset
= -1;
1155 static int radio_edit_preset(void)
1157 char buf
[MAX_FMPRESET_LEN
+ 1];
1159 if (num_presets
> 0)
1161 struct fmstation
* const fms
= &presets
[selected_preset
];
1163 strncpy(buf
, fms
->name
, MAX_FMPRESET_LEN
);
1165 if (!kbd_input(buf
, MAX_FMPRESET_LEN
))
1167 buf
[MAX_FMPRESET_LEN
] = '\0';
1168 strcpy(fms
->name
, buf
);
1169 presets_changed
= true;
1176 static int radio_delete_preset(void)
1178 if (num_presets
> 0)
1180 struct fmstation
* const fms
= &presets
[selected_preset
];
1182 if (selected_preset
>= --num_presets
)
1183 selected_preset
= num_presets
- 1;
1185 memmove(fms
, fms
+ 1, (uintptr_t)(fms
+ num_presets
) -
1190 /* Don't ask to save when all presets are deleted. */
1191 presets_changed
= num_presets
> 0;
1193 if (!presets_changed
)
1195 /* The preset list will be cleared, switch to Scan Mode. */
1196 radio_mode
= RADIO_SCAN_MODE
;
1197 presets_loaded
= false;
1203 static int load_preset_list(void)
1205 return !rockbox_browse(FMPRESET_PATH
, SHOW_FMR
);
1208 static int save_preset_list(void)
1212 bool bad_file_name
= true;
1214 if(!opendir(FMPRESET_PATH
)) /* Check if there is preset folder */
1215 mkdir(FMPRESET_PATH
);
1217 create_numbered_filename(filepreset
, FMPRESET_PATH
, "preset",
1218 ".fmr", 2 IF_CNFN_NUM_(, NULL
));
1220 while(bad_file_name
)
1222 if(!kbd_input(filepreset
, sizeof(filepreset
)))
1224 /* check the name: max MAX_FILENAME (20) chars */
1228 p1
= strrchr(filepreset
, '/');
1230 while((p1
) && (*p2
) && (*p2
!= '.'))
1232 len
= (int)(p2
-p1
) - 1;
1233 if((!p1
) || (len
> MAX_FILENAME
) || (len
== 0))
1235 /* no slash, too long or too short */
1236 gui_syncsplash(HZ
, ID2P(LANG_INVALID_FILENAME
));
1240 /* add correct extension (easier to always write)
1241 at this point, p2 points to 0 or the extension dot */
1243 strcat(filepreset
,".fmr");
1244 bad_file_name
= false;
1245 radio_save_presets();
1256 gui_syncsplash(HZ
, ID2P(LANG_FM_NO_PRESETS
));
1261 static int clear_preset_list(void)
1263 /* Clear all the preset entries */
1264 memset(presets
, 0, sizeof (presets
));
1267 presets_loaded
= false;
1268 /* The preset list will be cleared switch to Scan Mode. */
1269 radio_mode
= RADIO_SCAN_MODE
;
1271 presets_changed
= false; /* Don't ask to save when clearing the list. */
1276 MENUITEM_FUNCTION(radio_edit_preset_item
, MENU_FUNC_CHECK_RETVAL
,
1277 ID2P(LANG_FM_EDIT_PRESET
),
1278 radio_edit_preset
, NULL
, NULL
, Icon_NOICON
);
1279 MENUITEM_FUNCTION(radio_delete_preset_item
, MENU_FUNC_CHECK_RETVAL
,
1280 ID2P(LANG_FM_DELETE_PRESET
),
1281 radio_delete_preset
, NULL
, NULL
, Icon_NOICON
);
1282 int radio_preset_callback(int action
, 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 char * presets_get_name(int selected_item
, void * data
, char *buffer
)
1296 struct fmstation
*p
= &presets
[selected_item
];
1299 int freq
= p
->frequency
/ 10000;
1300 int frac
= freq
% 100;
1302 snprintf(buffer
, MAX_PATH
,
1303 str(LANG_FM_DEFAULT_PRESET_NAME
), freq
, frac
);
1307 static int presets_speak_name(int selected_item
, void * data
)
1310 talk_preset(selected_item
, true, false);
1314 static int handle_radio_presets(void)
1316 struct gui_synclist lists
;
1318 int action
= ACTION_NONE
;
1319 #ifdef HAS_BUTTONBAR
1320 struct gui_buttonbar buttonbar
;
1323 if(presets_loaded
== false)
1326 #ifdef HAS_BUTTONBAR
1327 gui_buttonbar_init(&buttonbar
);
1328 gui_buttonbar_set_display(&buttonbar
, &(screens
[SCREEN_MAIN
]) );
1329 gui_buttonbar_set(&buttonbar
, str(LANG_FM_BUTTONBAR_ADD
),
1330 str(LANG_FM_BUTTONBAR_EXIT
),
1331 str(LANG_FM_BUTTONBAR_ACTION
));
1332 gui_buttonbar_draw(&buttonbar
);
1334 gui_synclist_init(&lists
, presets_get_name
, NULL
, false, 1);
1335 gui_synclist_set_title(&lists
, str(LANG_PRESET
), NOICON
);
1336 gui_synclist_set_icon_callback(&lists
, NULL
);
1337 if(global_settings
.talk_file
)
1338 gui_synclist_set_voice_callback(&lists
, presets_speak_name
);
1339 gui_synclist_set_nb_items(&lists
, num_presets
);
1340 gui_synclist_select_item(&lists
, curr_preset
<0 ? 0 : curr_preset
);
1341 gui_synclist_speak_item(&lists
);
1345 gui_synclist_draw(&lists
);
1346 gui_syncstatusbar_draw(&statusbars
, true);
1347 list_do_action(CONTEXT_STD
, HZ
,
1348 &lists
, &action
, LIST_WRAP_UNLESS_HELD
);
1351 case ACTION_STD_MENU
:
1354 case ACTION_STD_CANCEL
:
1358 curr_preset
= gui_synclist_get_sel_pos(&lists
);
1359 curr_freq
= presets
[curr_preset
].frequency
;
1361 remember_frequency();
1365 case ACTION_STD_CONTEXT
:
1366 selected_preset
= gui_synclist_get_sel_pos(&lists
);
1367 do_menu(&handle_radio_preset_menu
, NULL
);
1368 gui_synclist_speak_item(&lists
);
1371 if(default_event_handler(action
) == SYS_USB_CONNECTED
)
1378 void toggle_mono_mode(bool mono
)
1380 tuner_set(RADIO_FORCE_MONO
, mono
);
1383 void set_radio_region(int region
)
1385 #ifdef HAVE_RADIO_REGION
1386 tuner_set(RADIO_REGION
, region
);
1389 remember_frequency();
1393 MENUITEM_SETTING(set_region
, &global_settings
.fm_region
, NULL
);
1394 MENUITEM_SETTING(force_mono
, &global_settings
.fm_force_mono
, NULL
);
1397 char* get_mode_text(int selected_item
, void * data
, char *buffer
)
1399 (void)selected_item
;
1401 snprintf(buffer
, MAX_PATH
, "%s %s", str(LANG_MODE
),
1402 radio_mode
? str(LANG_PRESET
) :
1403 str(LANG_RADIO_SCAN_MODE
));
1406 static int toggle_radio_mode(void)
1408 radio_mode
= (radio_mode
== RADIO_SCAN_MODE
) ?
1409 RADIO_PRESET_MODE
: RADIO_SCAN_MODE
;
1412 MENUITEM_FUNCTION_DYNTEXT(radio_mode_item
, 0,
1413 toggle_radio_mode
, NULL
,
1414 get_mode_text
, NULL
, NULL
, NULL
, Icon_NOICON
);
1417 static int scan_presets(void)
1419 bool do_scan
= true;
1421 if(num_presets
> 0) /* Do that to avoid 2 questions. */
1422 do_scan
= yesno_pop(ID2P(LANG_FM_CLEAR_PRESETS
));
1426 const struct fm_region_data
* const fmr
=
1427 &fm_region_data
[global_settings
.fm_region
];
1429 char buf
[MAX_FMPRESET_LEN
+ 1];
1432 curr_freq
= fmr
->freq_min
;
1434 memset(presets
, 0, sizeof(presets
));
1435 tuner_set(RADIO_MUTE
, 1);
1437 while(curr_freq
<= fmr
->freq_max
)
1440 if (num_presets
>= MAX_PRESETS
|| action_userabort(TIMEOUT_NOBLOCK
))
1443 freq
= curr_freq
/ 10000;
1447 snprintf(buf
, MAX_FMPRESET_LEN
, str(LANG_FM_SCANNING
), freq
, frac
);
1448 gui_syncsplash(0, buf
);
1450 if(tuner_set(RADIO_SCAN_FREQUENCY
, curr_freq
))
1453 presets
[num_presets
].name
[0] = '\0';
1454 presets
[num_presets
].frequency
= curr_freq
;
1458 curr_freq
+= fmr
->freq_step
;
1461 if (radio_status
== FMRADIO_PLAYING
)
1462 tuner_set(RADIO_MUTE
, 0);
1464 presets_changed
= true;
1468 gui_textarea_clear(&screens
[i
]);
1469 screen_set_xmargin(&screens
[i
],0);
1470 gui_textarea_update(&screens
[i
]);
1475 curr_freq
= presets
[0].frequency
;
1476 radio_mode
= RADIO_PRESET_MODE
;
1477 presets_loaded
= true;
1482 /* Wrap it to beginning or we'll be past end of band */
1483 presets_loaded
= false;
1491 #ifdef HAVE_RECORDING
1493 #if defined(HAVE_FMRADIO_REC) && CONFIG_CODEC == SWCODEC
1494 #define FM_RECORDING_SCREEN
1495 static int fm_recording_screen(void)
1499 /* switch recording source to FMRADIO for the duration */
1500 int rec_source
= global_settings
.rec_source
;
1501 global_settings
.rec_source
= AUDIO_SRC_FMRADIO
;
1503 ret
= recording_screen(true);
1505 /* safe to reset as changing sources is prohibited here */
1506 global_settings
.rec_source
= rec_source
;
1511 #endif /* defined(HAVE_FMRADIO_REC) && CONFIG_CODEC == SWCODEC */
1513 #if defined(HAVE_FMRADIO_REC) || CONFIG_CODEC != SWCODEC
1514 #define FM_RECORDING_SETTINGS
1515 static int fm_recording_settings(void)
1517 bool ret
= recording_menu(true);
1519 #if CONFIG_CODEC != SWCODEC
1522 struct audio_recording_options rec_options
;
1523 rec_init_recording_options(&rec_options
);
1524 rec_options
.rec_source
= AUDIO_SRC_LINEIN
;
1525 rec_set_recording_options(&rec_options
);
1532 #endif /* defined(HAVE_FMRADIO_REC) || CONFIG_CODEC != SWCODEC */
1533 #endif /* HAVE_RECORDING */
1535 #ifdef FM_RECORDING_SCREEN
1536 MENUITEM_FUNCTION(recscreen_item
, 0, ID2P(LANG_RECORDING
),
1537 fm_recording_screen
, NULL
, NULL
, Icon_Recording
);
1539 #ifdef FM_RECORDING_SETTINGS
1540 MENUITEM_FUNCTION(recsettings_item
, 0, ID2P(LANG_RECORDING_SETTINGS
),
1541 fm_recording_settings
, NULL
, NULL
, Icon_Recording
);
1544 MENUITEM_FUNCTION(radio_presets_item
, 0, ID2P(LANG_PRESET
),
1545 handle_radio_presets
, NULL
, NULL
, Icon_NOICON
);
1547 #ifndef FM_PRESET_ADD
1548 MENUITEM_FUNCTION(radio_addpreset_item
, 0, ID2P(LANG_FM_ADD_PRESET
),
1549 radio_add_preset
, NULL
, NULL
, Icon_NOICON
);
1553 MENUITEM_FUNCTION(presetload_item
, 0, ID2P(LANG_FM_PRESET_LOAD
),
1554 load_preset_list
, NULL
, NULL
, Icon_NOICON
);
1555 MENUITEM_FUNCTION(presetsave_item
, 0, ID2P(LANG_FM_PRESET_SAVE
),
1556 save_preset_list
, NULL
, NULL
, Icon_NOICON
);
1557 MENUITEM_FUNCTION(presetclear_item
, 0, ID2P(LANG_FM_PRESET_CLEAR
),
1558 clear_preset_list
, NULL
, NULL
, Icon_NOICON
);
1559 MENUITEM_FUNCTION(scan_presets_item
, 0, ID2P(LANG_FM_SCAN_PRESETS
),
1560 scan_presets
, NULL
, NULL
, Icon_NOICON
);
1562 MAKE_MENU(radio_settings_menu
, ID2P(LANG_FM_MENU
), NULL
,
1565 &radio_presets_item
,
1567 #ifndef FM_PRESET_ADD
1568 &radio_addpreset_item
,
1570 &presetload_item
, &presetsave_item
, &presetclear_item
,
1575 &set_region
, &sound_settings
,
1576 #ifdef FM_RECORDING_SCREEN
1579 #ifdef FM_RECORDING_SETTINGS
1582 &scan_presets_item
);
1583 /* main menu of the radio screen */
1584 static bool radio_menu(void)
1586 return do_menu(&radio_settings_menu
, NULL
) == MENU_ATTACHED_USB
;