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 ****************************************************************************/
33 #include "menus/exported_menus.h"
36 #include "peakmeter.h"
39 #include "recording.h"
41 #ifdef IPOD_ACCESSORY_PROTOCOL
48 #include "screen_access.h"
55 #include "skin_engine/skin_engine.h"
56 #include "statusbar-skinned.h"
57 #if CONFIG_CODEC == SWCODEC
64 #if CONFIG_KEYPAD == RECORDER_PAD
67 #define FM_PRESET_ACTION
71 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
74 #define FM_NEXT_PRESET
75 #define FM_PREV_PRESET
77 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
81 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
84 /* This should be removeable if the whole tuning thing is sorted out since
85 proper tuning quiets the screen almost entirely in that extreme measures
86 have to be taken to hear any interference. */
87 #define HAVE_NOISY_IDLE_MODE
89 #elif CONFIG_KEYPAD == ONDIO_PAD
90 #define FM_RECORD_DBLPRE
93 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || (CONFIG_KEYPAD == SANSA_C200_PAD) ||\
94 (CONFIG_KEYPAD == SANSA_FUZE_PAD) || (CONFIG_KEYPAD == SANSA_CLIP_PAD)
102 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
106 #elif (CONFIG_KEYPAD == COWON_D2_PAD)
114 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
115 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
122 #elif (CONFIG_KEYPAD == MPIO_HD200_PAD)
132 /* presets.c needs these so keep unstatic or redo the whole thing! */
133 int curr_freq
; /* current frequency in Hz */
134 int radio_mode
= RADIO_SCAN_MODE
;
136 static int search_dir
= 0;
137 static int radio_status
= FMRADIO_OFF
;
138 static bool in_screen
= false;
141 static void radio_off(void);
143 bool radio_scan_mode(void)
145 return radio_mode
== RADIO_SCAN_MODE
;
148 bool radio_is_stereo(void)
150 return tuner_get(RADIO_STEREO
) && !global_settings
.fm_force_mono
;
152 int radio_current_frequency(void)
157 /* Function to manipulate all yesno dialogues.
158 This function needs the output text as an argument. */
159 bool yesno_pop(const char* text
)
162 const char *lines
[]={text
};
163 const struct text_message message
={lines
, 1};
164 bool ret
= (gui_syncyesno_run(&message
,NULL
,NULL
)== YESNO_YES
);
166 screens
[i
].clear_viewport();
170 void radio_init(void)
175 radioart_init(false);
179 int get_radio_status(void)
184 bool in_radio_screen(void)
189 /* TODO: Move some more of the control functionality to firmware
190 and clean up the mess */
192 /* secret flag for starting paused - prevents unmute */
193 #define FMRADIO_START_PAUSED 0x8000
194 void radio_start(void)
196 const struct fm_region_data
*fmr
;
199 if(radio_status
== FMRADIO_PLAYING
)
202 fmr
= &fm_region_data
[global_settings
.fm_region
];
204 start_paused
= radio_status
& FMRADIO_START_PAUSED
;
205 /* clear flag before any yielding */
206 radio_status
&= ~FMRADIO_START_PAUSED
;
208 if(radio_status
== FMRADIO_OFF
)
211 curr_freq
= global_status
.last_frequency
* fmr
->freq_step
+ fmr
->freq_min
;
213 tuner_set(RADIO_SLEEP
, 0); /* wake up the tuner */
215 if(radio_status
== FMRADIO_OFF
)
217 #ifdef HAVE_RADIO_REGION
218 tuner_set(RADIO_REGION
, global_settings
.fm_region
);
220 tuner_set(RADIO_FORCE_MONO
, global_settings
.fm_force_mono
);
223 tuner_set(RADIO_FREQUENCY
, curr_freq
);
225 #ifdef HAVE_RADIO_MUTE_TIMEOUT
227 unsigned long mute_timeout
= current_tick
+ HZ
;
228 if (radio_status
!= FMRADIO_OFF
)
234 while(!tuner_get(RADIO_STEREO
) && !tuner_get(RADIO_TUNED
))
236 if(TIME_AFTER(current_tick
, mute_timeout
))
243 /* keep radio from sounding initially */
245 tuner_set(RADIO_MUTE
, 0);
247 radio_status
= FMRADIO_PLAYING
;
250 void radio_pause(void)
252 if(radio_status
== FMRADIO_PAUSED
)
255 if(radio_status
== FMRADIO_OFF
)
257 radio_status
|= FMRADIO_START_PAUSED
;
261 tuner_set(RADIO_MUTE
, 1);
262 /* For si4700: 2==this is really 'pause'. other tuners treat it
264 tuner_set(RADIO_SLEEP
, 2);
266 radio_status
= FMRADIO_PAUSED
;
269 static void radio_off(void)
271 tuner_set(RADIO_MUTE
, 1);
272 tuner_set(RADIO_SLEEP
, 1); /* low power mode, if available */
273 radio_status
= FMRADIO_OFF
;
274 tuner_power(false); /* status update, power off if avail. */
277 void radio_stop(void)
279 if(radio_status
== FMRADIO_OFF
)
285 bool radio_hardware_present(void)
287 return tuner_get(RADIO_PRESENT
);
290 /* Keep freq on the grid for the current region */
291 int snap_freq_to_grid(int freq
)
293 const struct fm_region_data
* const fmr
=
294 &fm_region_data
[global_settings
.fm_region
];
296 /* Range clamp if out of range or just round to nearest */
297 if (freq
< fmr
->freq_min
)
298 freq
= fmr
->freq_min
;
299 else if (freq
> fmr
->freq_max
)
300 freq
= fmr
->freq_max
;
302 freq
= (freq
- fmr
->freq_min
+ fmr
->freq_step
/2) /
303 fmr
->freq_step
* fmr
->freq_step
+ fmr
->freq_min
;
308 void remember_frequency(void)
310 const struct fm_region_data
* const fmr
=
311 &fm_region_data
[global_settings
.fm_region
];
312 global_status
.last_frequency
= (curr_freq
- fmr
->freq_min
)
317 /* Step to the next or previous frequency */
318 static int step_freq(int freq
, int direction
)
320 const struct fm_region_data
* const fmr
=
321 &fm_region_data
[global_settings
.fm_region
];
323 freq
+= direction
*fmr
->freq_step
;
325 /* Wrap first or snapping to grid will not let us on the band extremes */
326 if (freq
> fmr
->freq_max
)
327 freq
= direction
> 0 ? fmr
->freq_min
: fmr
->freq_max
;
328 else if (freq
< fmr
->freq_min
)
329 freq
= direction
< 0 ? fmr
->freq_max
: fmr
->freq_min
;
331 freq
= snap_freq_to_grid(freq
);
336 /* Step to the next or previous station */
337 void next_station(int direction
)
339 if (direction
!= 0 && radio_mode
!= RADIO_SCAN_MODE
)
341 preset_next(direction
);
345 curr_freq
= step_freq(curr_freq
, direction
);
347 if (radio_status
== FMRADIO_PLAYING
)
348 tuner_set(RADIO_MUTE
, 1);
350 tuner_set(RADIO_FREQUENCY
, curr_freq
);
352 if (radio_status
== FMRADIO_PLAYING
)
353 tuner_set(RADIO_MUTE
, 0);
355 preset_set_current(preset_find(curr_freq
));
356 remember_frequency();
359 /* Ends an in-progress search */
360 static void end_search(void)
362 if (search_dir
!= 0 && radio_status
== FMRADIO_PLAYING
)
363 tuner_set(RADIO_MUTE
, 0);
367 /* Speak a frequency. */
368 void talk_freq(int freq
, bool enqueue
)
371 talk_number(freq
/ 100, enqueue
);
372 talk_id(LANG_POINT
, true);
373 talk_number(freq
% 100 / 10, true);
375 talk_number(freq
% 10, true);
379 void radio_screen(void)
384 bool stereo
= false, last_stereo
= false;
386 bool screen_freeze
= false;
387 bool keep_playing
= false;
389 #ifdef FM_RECORD_DBLPRE
390 int lastbutton
= BUTTON_NONE
;
391 unsigned long rec_lastclick
= 0;
393 #if CONFIG_CODEC != SWCODEC
394 int timeout
= current_tick
+ HZ
/10;
395 #if !defined(SIMULATOR)
396 unsigned int last_seconds
= 0;
397 unsigned int seconds
= 0;
398 struct audio_recording_options rec_options
;
399 #endif /* SIMULATOR */
400 #endif /* CONFIG_CODEC != SWCODEC */
401 #ifndef HAVE_NOISY_IDLE_MODE
402 int button_timeout
= current_tick
+ (2*HZ
);
405 /* change status to "in screen" */
408 if(radio_preset_count() <= 0)
410 radio_load_presets(global_settings
.fmr_file
);
412 skin_get_global_state()->id3
= NULL
;
417 if(radio_status
== FMRADIO_OFF
)
422 #if CONFIG_CODEC != SWCODEC
423 rec_create_directory();
424 audio_init_recording(talk_get_bufsize());
426 sound_settings_apply();
427 /* Yes, we use the D/A for monitoring */
428 peak_meter_playback(true);
430 peak_meter_enable(true);
432 rec_init_recording_options(&rec_options
);
433 rec_options
.rec_source
= AUDIO_SRC_LINEIN
;
434 rec_set_recording_options(&rec_options
);
436 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN
),
437 sound_default(SOUND_RIGHT_GAIN
), AUDIO_GAIN_LINEIN
);
439 #endif /* CONFIG_CODEC != SWCODEC */
440 #endif /* ndef SIMULATOR */
443 #if CONFIG_CODEC == SWCODEC
444 /* This should be done before touching audio settings */
445 while (!audio_is_thread_ready())
448 audio_set_input_source(AUDIO_SRC_FMRADIO
,
449 (radio_status
== FMRADIO_PAUSED
) ?
450 SRCF_FMRADIO_PAUSED
: SRCF_FMRADIO_PLAYING
);
452 if (radio_status
== FMRADIO_OFF
)
456 if(radio_preset_count() < 1 && yesno_pop(ID2P(LANG_FM_FIRST_AUTOSCAN
)))
459 fms_fix_displays(FMS_ENTER
);
461 skin_update(FM_SCREEN
, i
, SKIN_REFRESH_ALL
);
463 preset_set_current(preset_find(curr_freq
));
464 if(radio_current_preset() != -1)
465 radio_mode
= RADIO_PRESET_MODE
;
467 #ifndef HAVE_NOISY_IDLE_MODE
475 curr_freq
= step_freq(curr_freq
, search_dir
);
476 update_type
= SKIN_REFRESH_ALL
;
478 if(tuner_set(RADIO_SCAN_FREQUENCY
, curr_freq
))
480 preset_set_current(preset_find(curr_freq
));
481 remember_frequency();
493 button
= fms_do_button_loop(update_type
>0);
495 #ifndef HAVE_NOISY_IDLE_MODE
496 if (button
!= ACTION_NONE
)
498 cpu_idle_mode(false);
499 button_timeout
= current_tick
+ (2*HZ
);
505 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
506 if(audio_status() == AUDIO_STATUS_RECORD
)
514 if(presets_have_changed())
516 if(yesno_pop(ID2P(LANG_FM_SAVE_CHANGES
)))
522 update_type
= SKIN_REFRESH_NON_STATIC
;
526 case ACTION_FM_RECORD
:
527 #ifdef FM_RECORD_DBLPRE
528 if (lastbutton
!= ACTION_FM_RECORD_DBLPRE
)
533 if (current_tick
- rec_lastclick
> HZ
/2)
535 rec_lastclick
= current_tick
;
538 #endif /* FM_RECORD_DBLPRE */
540 if(audio_status() == AUDIO_STATUS_RECORD
)
542 rec_command(RECORDING_CMD_START_NEWFILE
);
543 update_type
= SKIN_REFRESH_ALL
;
547 rec_command(RECORDING_CMD_START
);
548 update_type
= SKIN_REFRESH_ALL
;
550 #if CONFIG_CODEC != SWCODEC
553 #endif /* SIMULATOR */
555 #endif /* #ifdef FM_RECORD */
558 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
559 if(audio_status() == AUDIO_STATUS_RECORD
)
564 if(presets_have_changed())
566 if(yesno_pop(ID2P(LANG_FM_SAVE_CHANGES
)))
574 case ACTION_STD_PREV
:
575 case ACTION_STD_NEXT
:
576 next_station(button
== ACTION_STD_PREV
? -1 : 1);
578 update_type
= SKIN_REFRESH_ALL
;
582 case ACTION_STD_PREVREPEAT
:
583 case ACTION_STD_NEXTREPEAT
:
585 int dir
= search_dir
;
586 search_dir
= button
== ACTION_STD_PREVREPEAT
? -1 : 1;
587 if (radio_mode
!= RADIO_SCAN_MODE
)
589 preset_next(search_dir
);
595 /* Starting auto scan */
596 tuner_set(RADIO_MUTE
, 1);
598 update_type
= SKIN_REFRESH_ALL
;
602 case ACTION_SETTINGS_INC
:
603 case ACTION_SETTINGS_INCREPEAT
:
604 global_settings
.volume
++;
606 update_type
= SKIN_REFRESH_NON_STATIC
;
609 case ACTION_SETTINGS_DEC
:
610 case ACTION_SETTINGS_DECREPEAT
:
611 global_settings
.volume
--;
613 update_type
= SKIN_REFRESH_NON_STATIC
;
617 if (radio_status
== FMRADIO_PLAYING
)
622 update_type
= SKIN_REFRESH_NON_STATIC
;
628 fms_fix_displays(FMS_EXIT
);
629 do_menu(&radio_settings_menu
, NULL
, NULL
, false);
630 preset_set_current(preset_find(curr_freq
));
631 fms_fix_displays(FMS_ENTER
);
632 update_type
= SKIN_REFRESH_ALL
;
636 case ACTION_FM_PRESET
:
637 if(radio_preset_count() < 1)
639 splash(HZ
, ID2P(LANG_FM_NO_PRESETS
));
640 update_type
= SKIN_REFRESH_ALL
;
643 fms_fix_displays(FMS_EXIT
);
644 handle_radio_presets();
645 fms_fix_displays(FMS_ENTER
);
646 update_type
= SKIN_REFRESH_ALL
;
648 #endif /* FM_PRESET */
651 case ACTION_FM_FREEZE
:
654 splash(HZ
, str(LANG_FM_FREEZE
));
655 screen_freeze
= true;
659 update_type
= SKIN_REFRESH_ALL
;
660 screen_freeze
= false;
663 #endif /* FM_FREEZE */
665 case SYS_USB_CONNECTED
:
666 #if CONFIG_CODEC != SWCODEC
667 /* Only accept USB connection when not recording */
668 if(audio_status() != AUDIO_STATUS_RECORD
)
671 default_event_handler(SYS_USB_CONNECTED
);
672 screen_freeze
= true; /* Cosmetic: makes sure the
673 radio screen doesn't redraw */
680 if(radio_mode
== RADIO_SCAN_MODE
)
682 /* Force scan mode if there are no presets. */
683 if(radio_preset_count() > 0)
684 radio_mode
= RADIO_PRESET_MODE
;
687 radio_mode
= RADIO_SCAN_MODE
;
688 update_type
= SKIN_REFRESH_ALL
;
689 cond_talk_ids_fq(radio_mode
?
690 LANG_PRESET
: LANG_RADIO_SCAN_MODE
);
695 #ifdef FM_NEXT_PRESET
696 case ACTION_FM_NEXT_PRESET
:
699 update_type
= SKIN_REFRESH_ALL
;
704 #ifdef FM_PREV_PRESET
705 case ACTION_FM_PREV_PRESET
:
708 update_type
= SKIN_REFRESH_ALL
;
713 update_type
= SKIN_REFRESH_NON_STATIC
;
717 default_event_handler(button
);
719 if (tuner_get(RADIO_EVENT
))
720 update_type
= SKIN_REFRESH_ALL
;
722 if (!tuner_get(RADIO_PRESENT
))
724 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
725 if(audio_status() == AUDIO_STATUS_RECORD
)
728 keep_playing
= false;
730 if(presets_have_changed())
732 if(yesno_pop(ID2P(LANG_FM_SAVE_CHANGES
)))
734 radio_save_presets();
738 /* Clear the preset list on exit. */
744 #ifdef FM_RECORD_DBLPRE
745 if (button
!= ACTION_NONE
)
749 #if CONFIG_CODEC != SWCODEC
755 /* Only display the peak meter when not recording */
756 #if CONFIG_CODEC != SWCODEC
757 if(TIME_AFTER(current_tick
, timeout
))
759 timeout
= current_tick
+ HZ
;
762 #endif /* CONFIG_CODEC == SWCODEC */
764 /* keep "mono" from always being displayed when paused */
765 if (radio_status
!= FMRADIO_PAUSED
)
767 stereo
= tuner_get(RADIO_STEREO
) &&
768 !global_settings
.fm_force_mono
;
770 if(stereo
!= last_stereo
)
772 update_type
= SKIN_REFRESH_ALL
;
773 last_stereo
= stereo
;
778 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
779 seconds
= audio_recorded_time() / HZ
;
780 if (update_type
|| seconds
> last_seconds
)
782 last_seconds
= seconds
;
788 skin_update(FM_SCREEN
, i
, update_type
);
793 if (global_settings
.talk_file
&& talk
794 && radio_status
== FMRADIO_PAUSED
)
797 bool enqueue
= false;
798 if (radio_mode
== RADIO_SCAN_MODE
)
800 talk_freq(curr_freq
, enqueue
);
803 if (radio_current_preset() >= 0)
804 preset_talk(radio_current_preset(), radio_mode
== RADIO_PRESET_MODE
,
808 #if CONFIG_CODEC != SWCODEC
809 if(audio_status() & AUDIO_STATUS_ERROR
)
815 #ifndef HAVE_NOISY_IDLE_MODE
816 if (TIME_AFTER(current_tick
, button_timeout
))
824 #if CONFIG_CODEC != SWCODEC
825 if(audio_status() & AUDIO_STATUS_ERROR
)
827 splash(0, str(LANG_DISK_FULL
));
832 button
= get_action(CONTEXT_FM
, TIMEOUT_BLOCK
);
833 if(button
== ACTION_FM_STOP
)
838 audio_init_playback();
839 #endif /* CONFIG_CODEC != SWCODEC */
841 sound_settings_apply();
842 #endif /* SIMULATOR */
846 /* Catch FMRADIO_PLAYING status for the sim. */
848 #if CONFIG_CODEC != SWCODEC
849 /* Enable the Left and right A/D Converter */
850 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN
),
851 sound_default(SOUND_RIGHT_GAIN
),
853 mas_codec_writereg(6, 0x4000);
856 #endif /* SIMULATOR */
860 #if CONFIG_CODEC == SWCODEC
861 audio_set_input_source(AUDIO_SRC_PLAYBACK
, SRCF_PLAYBACK
);
867 #ifndef HAVE_NOISY_IDLE_MODE
868 cpu_idle_mode(false);
870 fms_fix_displays(FMS_EXIT
);
874 void toggle_mono_mode(bool mono
)
876 tuner_set(RADIO_FORCE_MONO
, mono
);
879 void set_radio_region(int region
)
881 #ifdef HAVE_RADIO_REGION
882 tuner_set(RADIO_REGION
, region
);
885 remember_frequency();