How punny. Just one more whack-a-mole to get.
[kugel-rb.git] / apps / recorder / radio.c
blob5425e8a2ab228729f79d9a8ed2db647d1938269c
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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 ****************************************************************************/
22 #include "config.h"
23 #include <stdio.h>
24 #include <stdbool.h>
25 #include <stdlib.h>
26 #include "mas.h"
27 #include "settings.h"
28 #include "button.h"
29 #include "status.h"
30 #include "thread.h"
31 #include "audio.h"
32 #include "mp3_playback.h"
33 #include "ctype.h"
34 #include "file.h"
35 #include "general.h"
36 #include "errno.h"
37 #include "string-extra.h"
38 #include "system.h"
39 #include "radio.h"
40 #include "menu.h"
41 #include "misc.h"
42 #include "keyboard.h"
43 #include "screens.h"
44 #include "peakmeter.h"
45 #include "lang.h"
46 #include "font.h"
47 #include "sound_menu.h"
48 #ifdef HAVE_RECORDING
49 #include "recording.h"
50 #endif
51 #ifdef IPOD_ACCESSORY_PROTOCOL
52 #include "iap.h"
53 #endif
54 #include "appevents.h"
55 #include "talk.h"
56 #include "tuner.h"
57 #include "power.h"
58 #include "sound.h"
59 #include "screen_access.h"
60 #include "splash.h"
61 #include "yesno.h"
62 #include "buttonbar.h"
63 #include "tree.h"
64 #include "dir.h"
65 #include "action.h"
66 #include "list.h"
67 #include "menus/exported_menus.h"
68 #include "root_menu.h"
69 #include "viewport.h"
70 #include "skin_engine/skin_engine.h"
71 #include "statusbar-skinned.h"
72 #include "buffering.h"
74 #if CONFIG_TUNER
76 #if CONFIG_KEYPAD == RECORDER_PAD
77 #define FM_RECORD
78 #define FM_PRESET_ADD
79 #define FM_PRESET_ACTION
80 #define FM_PRESET
81 #define FM_MODE
83 #elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD)
84 #define FM_PRESET
85 #define FM_MODE
86 #define FM_NEXT_PRESET
87 #define FM_PREV_PRESET
89 #elif CONFIG_KEYPAD == IRIVER_H10_PAD
90 #define FM_PRESET
91 #define FM_MODE
93 #elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)
94 #define FM_PRESET
95 #define FM_MODE
96 /* This should be removeable if the whole tuning thing is sorted out since
97 proper tuning quiets the screen almost entirely in that extreme measures
98 have to be taken to hear any interference. */
99 #define HAVE_NOISY_IDLE_MODE
101 #elif CONFIG_KEYPAD == ONDIO_PAD
102 #define FM_RECORD_DBLPRE
103 #define FM_RECORD
104 #elif (CONFIG_KEYPAD == SANSA_E200_PAD) || (CONFIG_KEYPAD == SANSA_C200_PAD)
105 #define FM_MENU
106 #define FM_PRESET
107 #define FM_STOP
108 #define FM_MODE
109 #define FM_EXIT
110 #define FM_PLAY
112 #elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)
113 #define FM_PRESET
114 #define FM_MODE
116 #elif (CONFIG_KEYPAD == COWON_D2_PAD)
117 #define FM_MENU
118 #define FM_PRESET
119 #define FM_STOP
120 #define FM_MODE
121 #define FM_EXIT
122 #define FM_PLAY
124 #elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \
125 (CONFIG_KEYPAD == IPOD_1G2G_PAD)
126 #define FM_MENU
127 #define FM_STOP
128 #define FM_EXIT
129 #define FM_PLAY
130 #define FM_MODE
132 #endif
134 #define RADIO_SCAN_MODE 0
135 #define RADIO_PRESET_MODE 1
137 static int curr_preset = -1;
138 static int curr_freq; /* current frequency in Hz */
139 static int radio_mode = RADIO_SCAN_MODE;
140 static int search_dir = 0;
142 static int radio_status = FMRADIO_OFF;
143 static bool in_screen = false;
145 #define MAX_PRESETS 64
146 static bool presets_loaded = false, presets_changed = false;
147 static struct fmstation presets[MAX_PRESETS];
149 static char filepreset[MAX_PATH]; /* preset filename variable */
151 static int num_presets = 0; /* The number of presets in the preset list */
153 static void radio_save_presets(void);
154 static int handle_radio_presets(void);
155 static bool radio_menu(void);
156 static int radio_add_preset(void);
157 static int save_preset_list(void);
158 static int load_preset_list(void);
159 static int clear_preset_list(void);
161 static int scan_presets(void *viewports);
162 static void radio_off(void);
164 bool radio_scan_mode(void)
166 return radio_mode == RADIO_SCAN_MODE;
169 bool radio_is_stereo(void)
171 return tuner_get(RADIO_STEREO) && !global_settings.fm_force_mono;
173 int radio_current_frequency(void)
175 return curr_freq;
178 int radio_current_preset(void)
180 return curr_preset;
182 int radio_preset_count(void)
184 return num_presets;
186 const struct fmstation *radio_get_preset(int preset)
188 return &presets[preset];
190 /* Function to manipulate all yesno dialogues.
191 This function needs the output text as an argument. */
192 static bool yesno_pop(const char* text)
194 int i;
195 const char *lines[]={text};
196 const struct text_message message={lines, 1};
197 bool ret = (gui_syncyesno_run(&message,NULL,NULL)== YESNO_YES);
198 FOR_NB_SCREENS(i)
199 screens[i].clear_viewport();
200 return ret;
203 #if defined(HAVE_RECORDING) && defined(HAVE_ALBUMART)
204 static void recording_started_handler(void *data);
205 static void recording_stopped_handler(void *data);
206 #endif
207 void radio_init(void)
209 tuner_init();
210 radio_off();
211 #if defined(HAVE_RECORDING) && defined(HAVE_ALBUMART)
212 add_event(RECORDING_EVENT_START, false, recording_started_handler);
213 add_event(RECORDING_EVENT_STOP, false, recording_stopped_handler);
214 #endif
217 int get_radio_status(void)
219 return radio_status;
222 bool in_radio_screen(void)
224 return in_screen;
227 /* TODO: Move some more of the control functionality to firmware
228 and clean up the mess */
230 /* secret flag for starting paused - prevents unmute */
231 #define FMRADIO_START_PAUSED 0x8000
232 void radio_start(void)
234 const struct fm_region_data *fmr;
235 bool start_paused;
237 if(radio_status == FMRADIO_PLAYING)
238 return;
240 fmr = &fm_region_data[global_settings.fm_region];
242 start_paused = radio_status & FMRADIO_START_PAUSED;
243 /* clear flag before any yielding */
244 radio_status &= ~FMRADIO_START_PAUSED;
246 if(radio_status == FMRADIO_OFF)
247 tuner_power(true);
249 curr_freq = global_status.last_frequency * fmr->freq_step + fmr->freq_min;
251 tuner_set(RADIO_SLEEP, 0); /* wake up the tuner */
253 if(radio_status == FMRADIO_OFF)
255 #ifdef HAVE_RADIO_REGION
256 tuner_set(RADIO_REGION, global_settings.fm_region);
257 #endif
258 tuner_set(RADIO_FORCE_MONO, global_settings.fm_force_mono);
261 tuner_set(RADIO_FREQUENCY, curr_freq);
263 #ifdef HAVE_RADIO_MUTE_TIMEOUT
265 unsigned long mute_timeout = current_tick + HZ;
266 if (radio_status != FMRADIO_OFF)
268 /* paused */
269 mute_timeout += HZ;
272 while(!tuner_get(RADIO_STEREO) && !tuner_get(RADIO_TUNED))
274 if(TIME_AFTER(current_tick, mute_timeout))
275 break;
276 yield();
279 #endif
281 /* keep radio from sounding initially */
282 if(!start_paused)
283 tuner_set(RADIO_MUTE, 0);
285 radio_status = FMRADIO_PLAYING;
286 } /* radio_start */
288 void radio_pause(void)
290 if(radio_status == FMRADIO_PAUSED)
291 return;
293 if(radio_status == FMRADIO_OFF)
295 radio_status |= FMRADIO_START_PAUSED;
296 radio_start();
299 tuner_set(RADIO_MUTE, 1);
300 tuner_set(RADIO_SLEEP, 1);
302 radio_status = FMRADIO_PAUSED;
303 } /* radio_pause */
305 static void radio_off(void)
307 tuner_set(RADIO_MUTE, 1);
308 tuner_set(RADIO_SLEEP, 1); /* low power mode, if available */
309 radio_status = FMRADIO_OFF;
310 tuner_power(false); /* status update, power off if avail. */
313 void radio_stop(void)
315 if(radio_status == FMRADIO_OFF)
316 return;
318 radio_off();
319 } /* radio_stop */
321 bool radio_hardware_present(void)
323 return tuner_get(RADIO_PRESENT);
326 /* Keep freq on the grid for the current region */
327 static int snap_freq_to_grid(int freq)
329 const struct fm_region_data * const fmr =
330 &fm_region_data[global_settings.fm_region];
332 /* Range clamp if out of range or just round to nearest */
333 if (freq < fmr->freq_min)
334 freq = fmr->freq_min;
335 else if (freq > fmr->freq_max)
336 freq = fmr->freq_max;
337 else
338 freq = (freq - fmr->freq_min + fmr->freq_step/2) /
339 fmr->freq_step * fmr->freq_step + fmr->freq_min;
341 return freq;
344 /* Find a matching preset to freq */
345 static int find_preset(int freq)
347 int i;
348 if(num_presets < 1)
349 return -1;
350 for(i = 0;i < MAX_PRESETS;i++)
352 if(freq == presets[i].frequency)
353 return i;
356 return -1;
359 /* Return the closest preset encountered in the search direction with
360 wraparound. */
361 static int find_closest_preset(int freq, int direction)
363 int i;
364 int lowpreset = 0;
365 int highpreset = 0;
366 int closest = -1;
368 if (direction == 0) /* direction == 0 isn't really used */
369 return 0;
371 for (i = 0; i < num_presets; i++)
373 int f = presets[i].frequency;
374 if (f == freq)
375 return i; /* Exact match = stop */
377 /* remember the highest and lowest presets for wraparound */
378 if (f < presets[lowpreset].frequency)
379 lowpreset = i;
380 if (f > presets[highpreset].frequency)
381 highpreset = i;
383 /* find the closest preset in the given direction */
384 if (direction > 0 && f > freq)
386 if (closest < 0 || f < presets[closest].frequency)
387 closest = i;
389 else if (direction < 0 && f < freq)
391 if (closest < 0 || f > presets[closest].frequency)
392 closest = i;
396 if (closest < 0)
398 /* no presets in the given direction */
399 /* wrap around depending on direction */
400 if (direction < 0)
401 closest = highpreset;
402 else
403 closest = lowpreset;
406 return closest;
409 static void remember_frequency(void)
411 const struct fm_region_data * const fmr =
412 &fm_region_data[global_settings.fm_region];
413 global_status.last_frequency = (curr_freq - fmr->freq_min)
414 / fmr->freq_step;
415 status_save();
418 static void next_preset(int direction)
420 if (num_presets < 1)
421 return;
423 if (curr_preset == -1)
424 curr_preset = find_closest_preset(curr_freq, direction);
425 else
426 curr_preset = (curr_preset + direction + num_presets) % num_presets;
428 /* Must stay on the current grid for the region */
429 curr_freq = snap_freq_to_grid(presets[curr_preset].frequency);
431 tuner_set(RADIO_FREQUENCY, curr_freq);
432 remember_frequency();
435 /* Step to the next or previous frequency */
436 static int step_freq(int freq, int direction)
438 const struct fm_region_data * const fmr =
439 &fm_region_data[global_settings.fm_region];
441 freq += direction*fmr->freq_step;
443 /* Wrap first or snapping to grid will not let us on the band extremes */
444 if (freq > fmr->freq_max)
445 freq = direction > 0 ? fmr->freq_min : fmr->freq_max;
446 else if (freq < fmr->freq_min)
447 freq = direction < 0 ? fmr->freq_max : fmr->freq_min;
448 else
449 freq = snap_freq_to_grid(freq);
451 return freq;
454 /* Step to the next or previous station */
455 static void next_station(int direction)
457 if (direction != 0 && radio_mode != RADIO_SCAN_MODE)
459 next_preset(direction);
460 return;
463 curr_freq = step_freq(curr_freq, direction);
465 if (radio_status == FMRADIO_PLAYING)
466 tuner_set(RADIO_MUTE, 1);
468 tuner_set(RADIO_FREQUENCY, curr_freq);
470 if (radio_status == FMRADIO_PLAYING)
471 tuner_set(RADIO_MUTE, 0);
473 curr_preset = find_preset(curr_freq);
474 remember_frequency();
477 /* Ends an in-progress search */
478 static void end_search(void)
480 if (search_dir != 0 && radio_status == FMRADIO_PLAYING)
481 tuner_set(RADIO_MUTE, 0);
482 search_dir = 0;
485 /* Speak a frequency. */
486 static void talk_freq(int freq, bool enqueue)
488 freq /= 10000;
489 talk_number(freq / 100, enqueue);
490 talk_id(LANG_POINT, true);
491 talk_number(freq % 100 / 10, true);
492 if (freq % 10)
493 talk_number(freq % 10, true);
496 /* Speak a preset by number or by spelling its name, depending on settings. */
497 static void talk_preset(int preset, bool fallback, bool enqueue)
499 if (global_settings.talk_file == 1) /* number */
500 talk_number(preset + 1, enqueue);
501 else
502 { /* spell */
503 if(presets[preset].name[0])
504 talk_spell(presets[preset].name, enqueue);
505 else if(fallback)
506 talk_freq(presets[preset].frequency, enqueue);
510 /* Skin stuff */
511 extern struct wps_state wps_state; /* from wps.c */
512 static struct gui_wps fms_skin[NB_SCREENS] = {{ .data = NULL }};
513 static struct wps_data fms_skin_data[NB_SCREENS] = {{ .wps_loaded = 0 }};
514 static struct wps_sync_data fms_skin_sync_data = { .do_full_update = false };
516 #ifdef HAVE_ALBUMART
517 #define MAX_RADIOART_IMAGES 10
518 struct radioart {
519 int handle;
520 long last_tick;
521 struct dim dim;
522 char name[MAX_FMPRESET_LEN+1];
525 static struct radioart radioart[MAX_RADIOART_IMAGES];
526 #ifdef HAVE_RECORDING
527 static bool allow_buffer_access = true; /* If we are recording dont touch the buffers! */
528 #endif
529 static int find_oldest_image(void)
531 int i;
532 long oldest_tick = radioart[0].last_tick;
533 int oldest_idx = 0;
534 for(i=1;i<MAX_RADIOART_IMAGES;i++)
536 if (radioart[i].last_tick < oldest_tick)
538 oldest_tick = radioart[i].last_tick;
539 oldest_idx = i;
542 return oldest_idx;
544 static int load_radioart_image(struct radioart *ra, char* preset_name, struct dim *dim)
546 char path[MAX_PATH];
547 #ifndef HAVE_NOISY_IDLE_MODE
548 cpu_idle_mode(false);
549 #endif
550 snprintf(path, sizeof(path), FMPRESET_PATH "/%s.bmp",preset_name);
551 if (!file_exists(path))
552 snprintf(path, sizeof(path), FMPRESET_PATH "/%s.jpg",preset_name);
553 if (!file_exists(path))
555 #ifndef HAVE_NOISY_IDLE_MODE
556 cpu_idle_mode(true);
557 #endif
558 return -1;
560 strlcpy(ra->name, preset_name, MAX_FMPRESET_LEN+1);
561 ra->dim.height = dim->height;
562 ra->dim.width = dim->width;
563 ra->last_tick = current_tick;
564 ra->handle = bufopen(path, 0, TYPE_BITMAP, &ra->dim);
565 if (ra->handle == ERR_BUFFER_FULL)
567 int i = find_oldest_image();
568 bufclose(i);
569 ra->handle = bufopen(path, 0, TYPE_BITMAP, &ra->dim);
571 #ifndef HAVE_NOISY_IDLE_MODE
572 cpu_idle_mode(true);
573 #endif
574 return ra->handle;
576 int radio_get_art_hid(struct dim *requested_dim)
578 int preset = radio_current_preset();
579 int i, free_idx = -1;
580 if ((radio_mode != RADIO_PRESET_MODE) || preset < 0)
581 return -1;
582 #ifdef HAVE_RECORDING
583 if (!allow_buffer_access)
584 return -1;
585 #endif
586 for(i=0;i<MAX_RADIOART_IMAGES;i++)
588 if (radioart[i].handle < 0)
590 free_idx = i;
592 else if (!strcmp(radioart[i].name, presets[preset].name) &&
593 radioart[i].dim.width == requested_dim->width &&
594 radioart[i].dim.height == requested_dim->height)
596 radioart[i].last_tick = current_tick;
597 return radioart[i].handle;
600 if (free_idx >= 0)
602 return load_radioart_image(&radioart[free_idx],
603 presets[preset].name, requested_dim);
605 else
607 int i = find_oldest_image();
608 bufclose(radioart[i].handle);
609 return load_radioart_image(&radioart[i],
610 presets[preset].name, requested_dim);
613 return -1;
615 static void playback_restarting_handler(void *data)
617 (void)data;
618 int i;
619 for(i=0;i<MAX_RADIOART_IMAGES;i++)
621 if (radioart[i].handle >= 0)
622 bufclose(radioart[i].handle);
623 radioart[i].handle = -1;
624 radioart[i].name[0] = '\0';
627 #ifdef HAVE_RECORDING
628 static void recording_started_handler(void *data)
630 (void)data;
631 allow_buffer_access = false;
632 playback_restarting_handler(NULL);
634 static void recording_stopped_handler(void *data)
636 (void)data;
637 allow_buffer_access = true;
639 #endif
640 #endif
642 void fms_data_load(enum screen_type screen, const char *buf, bool isfile)
644 struct wps_data *data = fms_skin[screen].data;
645 int success;
646 success = buf && skin_data_load(screen, data, buf, isfile);
648 if (!success ) /* load the default */
650 const char default_fms[] = "%Sx|Station:| %tf\n"
651 "%?ts<%Sx|Stereo||%Sx|Mono|>\n"
652 "%?tm<%Sx|Mode:| %Sx|Scan||%Sx|Preset|: %Ti. %?Tn<%Tn|%Tf>>\n"
653 "%pb\n"
654 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
655 "%?Rr<%Sx|Time:| %Rh:%Rn:%Rs|"
656 "%?St|prerecording time|<%Sx|Prerecord Time| %Rs|%pm>>\n"
657 #endif
658 #ifdef HAVE_RDS_CAP
659 "\n%s%ty\n"
660 "%s%tz\n"
661 #endif
663 skin_data_load(screen, data, default_fms, false);
666 enum fms_exiting {
667 FMS_EXIT,
668 FMS_ENTER
670 void fms_fix_displays(enum fms_exiting toggle_state)
672 int i;
673 FOR_NB_SCREENS(i)
675 if (toggle_state == FMS_ENTER)
677 viewportmanager_theme_enable(i, skin_has_sbs(i, fms_skin[i].data), NULL);
678 #if LCD_DEPTH > 1 || defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
679 screens[i].backdrop_show(fms_skin[i].data->backdrop);
680 #endif
681 screens[i].clear_display();
682 /* force statusbar/skin update since we just cleared the whole screen */
683 send_event(GUI_EVENT_ACTIONUPDATE, (void*)1);
685 else
687 screens[i].stop_scroll();
688 #if LCD_DEPTH > 1 || defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
689 screens[i].backdrop_show(sb_get_backdrop(i));
690 #endif
691 viewportmanager_theme_undo(i, skin_has_sbs(i, fms_skin[i].data));
697 void fms_skin_init(void)
699 int i;
700 FOR_NB_SCREENS(i)
702 #ifdef HAVE_ALBUMART
703 fms_skin_data[i].albumart = NULL;
704 fms_skin_data[i].playback_aa_slot = -1;
705 #endif
706 fms_skin[i].data = &fms_skin_data[i];
707 fms_skin[i].display = &screens[i];
708 /* Currently no seperate wps_state needed/possible
709 so use the only available ( "global" ) one */
710 fms_skin[i].state = &wps_state;
711 fms_skin[i].sync_data = &fms_skin_sync_data;
715 int radio_screen(void)
717 bool done = false;
718 int ret_val = GO_TO_ROOT;
719 int button;
720 int i;
721 bool stereo = false, last_stereo = false;
722 bool update_screen = true, restore = true;
723 bool screen_freeze = false;
724 bool keep_playing = false;
725 bool talk = false;
726 #ifdef FM_RECORD_DBLPRE
727 int lastbutton = BUTTON_NONE;
728 unsigned long rec_lastclick = 0;
729 #endif
730 #if CONFIG_CODEC != SWCODEC
731 bool have_recorded = false;
732 int timeout = current_tick + HZ/10;
733 unsigned int last_seconds = 0;
734 #ifndef SIMULATOR
735 unsigned int seconds = 0;
736 struct audio_recording_options rec_options;
737 #endif
738 #endif /* CONFIG_CODEC != SWCODEC */
739 #ifndef HAVE_NOISY_IDLE_MODE
740 int button_timeout = current_tick + (2*HZ);
741 #endif
743 /* change status to "in screen" */
744 in_screen = true;
746 if(num_presets <= 0)
748 radio_load_presets(global_settings.fmr_file);
750 #ifdef HAVE_ALBUMART
751 for(i=0;i<MAX_RADIOART_IMAGES;i++)
753 radioart[i].handle = -1;
754 radioart[i].name[0] = '\0';
756 add_event(PLAYBACK_EVENT_START_PLAYBACK, true, playback_restarting_handler);
757 #endif
759 if(radio_status == FMRADIO_OFF)
760 audio_stop();
762 #ifndef SIMULATOR
764 #if CONFIG_CODEC != SWCODEC
765 if(rec_create_directory() > 0)
766 have_recorded = true;
768 audio_init_recording(talk_get_bufsize());
770 sound_settings_apply();
771 /* Yes, we use the D/A for monitoring */
772 peak_meter_playback(true);
774 peak_meter_enable(true);
776 rec_init_recording_options(&rec_options);
777 rec_options.rec_source = AUDIO_SRC_LINEIN;
778 rec_set_recording_options(&rec_options);
780 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN),
781 sound_default(SOUND_RIGHT_GAIN), AUDIO_GAIN_LINEIN);
783 #endif /* CONFIG_CODEC != SWCODEC */
784 #endif /* ndef SIMULATOR */
786 /* turn on radio */
787 #if CONFIG_CODEC == SWCODEC
788 audio_set_input_source(AUDIO_SRC_FMRADIO,
789 (radio_status == FMRADIO_PAUSED) ?
790 SRCF_FMRADIO_PAUSED : SRCF_FMRADIO_PLAYING);
791 #else
792 if (radio_status == FMRADIO_OFF)
793 radio_start();
794 #endif
796 if(num_presets < 1 && yesno_pop(ID2P(LANG_FM_FIRST_AUTOSCAN)))
797 scan_presets(NULL);
799 curr_preset = find_preset(curr_freq);
800 if(curr_preset != -1)
801 radio_mode = RADIO_PRESET_MODE;
803 #ifndef HAVE_NOISY_IDLE_MODE
804 cpu_idle_mode(true);
805 #endif
807 while(!done)
809 if(search_dir != 0)
811 curr_freq = step_freq(curr_freq, search_dir);
812 update_screen = true;
814 if(tuner_set(RADIO_SCAN_FREQUENCY, curr_freq))
816 curr_preset = find_preset(curr_freq);
817 remember_frequency();
818 end_search();
819 talk = true;
821 trigger_cpu_boost();
824 if (!update_screen)
826 cancel_cpu_boost();
829 button = skin_wait_for_action(fms_skin, CONTEXT_FM,
830 update_screen ? TIMEOUT_NOBLOCK : HZ);
832 #ifndef HAVE_NOISY_IDLE_MODE
833 if (button != ACTION_NONE)
835 cpu_idle_mode(false);
836 button_timeout = current_tick + (2*HZ);
838 #endif
839 switch(button)
841 case ACTION_FM_STOP:
842 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
843 if(audio_status() == AUDIO_STATUS_RECORD)
845 audio_stop();
847 else
848 #endif
850 done = true;
851 if(presets_changed)
853 if(yesno_pop(ID2P(LANG_FM_SAVE_CHANGES)))
855 if(filepreset[0] == '\0')
856 save_preset_list();
857 else
858 radio_save_presets();
862 update_screen = true;
863 break;
865 #ifdef FM_RECORD
866 case ACTION_FM_RECORD:
867 #ifdef FM_RECORD_DBLPRE
868 if (lastbutton != ACTION_FM_RECORD_DBLPRE)
870 rec_lastclick = 0;
871 break;
873 if (current_tick - rec_lastclick > HZ/2)
875 rec_lastclick = current_tick;
876 break;
878 #endif /* FM_RECORD_DBLPRE */
879 #ifndef SIMULATOR
880 if(audio_status() == AUDIO_STATUS_RECORD)
882 rec_command(RECORDING_CMD_START_NEWFILE);
883 update_screen = true;
885 else
887 have_recorded = true;
888 rec_command(RECORDING_CMD_START);
889 update_screen = true;
891 #endif /* SIMULATOR */
892 last_seconds = 0;
893 break;
894 #endif /* #ifdef FM_RECORD */
896 case ACTION_FM_EXIT:
897 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
898 if(audio_status() == AUDIO_STATUS_RECORD)
899 audio_stop();
900 #endif
901 keep_playing = true;
902 done = true;
903 ret_val = GO_TO_ROOT;
904 if(presets_changed)
906 if(yesno_pop(ID2P(LANG_FM_SAVE_CHANGES)))
908 if(filepreset[0] == '\0')
909 save_preset_list();
910 else
911 radio_save_presets();
915 break;
917 case ACTION_STD_PREV:
918 case ACTION_STD_NEXT:
919 next_station(button == ACTION_STD_PREV ? -1 : 1);
920 end_search();
921 update_screen = true;
922 talk = true;
923 break;
925 case ACTION_STD_PREVREPEAT:
926 case ACTION_STD_NEXTREPEAT:
928 int dir = search_dir;
929 search_dir = button == ACTION_STD_PREVREPEAT ? -1 : 1;
930 if (radio_mode != RADIO_SCAN_MODE)
932 next_preset(search_dir);
933 end_search();
934 update_screen = true;
935 talk = true;
937 else if (dir == 0)
939 /* Starting auto scan */
940 tuner_set(RADIO_MUTE, 1);
941 update_screen = true;
943 break;
946 case ACTION_SETTINGS_INC:
947 case ACTION_SETTINGS_INCREPEAT:
948 global_settings.volume++;
949 setvol();
950 update_screen = true;
951 break;
953 case ACTION_SETTINGS_DEC:
954 case ACTION_SETTINGS_DECREPEAT:
955 global_settings.volume--;
956 setvol();
957 update_screen = true;
958 break;
960 case ACTION_FM_PLAY:
961 if (radio_status == FMRADIO_PLAYING)
962 radio_pause();
963 else
964 radio_start();
966 update_screen = true;
967 talk = false;
968 talk_shutup();
969 break;
971 case ACTION_FM_MENU:
972 fms_fix_displays(FMS_EXIT);
973 radio_menu();
974 curr_preset = find_preset(curr_freq);
975 update_screen = true;
976 restore = true;
977 break;
979 #ifdef FM_PRESET
980 case ACTION_FM_PRESET:
981 if(num_presets < 1)
983 splash(HZ, ID2P(LANG_FM_NO_PRESETS));
984 update_screen = true;
985 break;
987 fms_fix_displays(FMS_EXIT);
988 handle_radio_presets();
989 update_screen = true;
990 restore = true;
991 break;
992 #endif /* FM_PRESET */
994 #ifdef FM_FREEZE
995 case ACTION_FM_FREEZE:
996 if(!screen_freeze)
998 splash(HZ, str(LANG_FM_FREEZE));
999 screen_freeze = true;
1001 else
1003 update_screen = true;
1004 screen_freeze = false;
1006 break;
1007 #endif /* FM_FREEZE */
1009 case SYS_USB_CONNECTED:
1010 #if CONFIG_CODEC != SWCODEC
1011 /* Only accept USB connection when not recording */
1012 if(audio_status() != AUDIO_STATUS_RECORD)
1013 #endif
1015 default_event_handler(SYS_USB_CONNECTED);
1016 screen_freeze = true; /* Cosmetic: makes sure the
1017 radio screen doesn't redraw */
1018 done = true;
1020 break;
1022 #ifdef FM_MODE
1023 case ACTION_FM_MODE:
1024 if(radio_mode == RADIO_SCAN_MODE)
1026 /* Force scan mode if there are no presets. */
1027 if(num_presets > 0)
1028 radio_mode = RADIO_PRESET_MODE;
1030 else
1031 radio_mode = RADIO_SCAN_MODE;
1032 update_screen = true;
1033 cond_talk_ids_fq(radio_mode ?
1034 LANG_PRESET : LANG_RADIO_SCAN_MODE);
1035 talk = true;
1036 break;
1037 #endif /* FM_MODE */
1039 #ifdef FM_NEXT_PRESET
1040 case ACTION_FM_NEXT_PRESET:
1041 next_preset(1);
1042 end_search();
1043 update_screen = true;
1044 talk = true;
1045 break;
1046 #endif
1048 #ifdef FM_PREV_PRESET
1049 case ACTION_FM_PREV_PRESET:
1050 next_preset(-1);
1051 end_search();
1052 update_screen = true;
1053 talk = true;
1054 break;
1055 #endif
1057 default:
1058 default_event_handler(button);
1059 #ifdef HAVE_RDS_CAP
1060 if (tuner_get(RADIO_EVENT))
1061 update_screen = true;
1062 #endif
1063 if (!tuner_get(RADIO_PRESENT))
1065 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
1066 if(audio_status() == AUDIO_STATUS_RECORD)
1067 audio_stop();
1068 #endif
1069 keep_playing = false;
1070 done = true;
1071 ret_val = GO_TO_ROOT;
1072 if(presets_changed)
1074 if(yesno_pop(ID2P(LANG_FM_SAVE_CHANGES)))
1076 if(filepreset[0] == '\0')
1077 save_preset_list();
1078 else
1079 radio_save_presets();
1083 /* Clear the preset list on exit. */
1084 clear_preset_list();
1086 break;
1087 } /*switch(button)*/
1089 #ifdef FM_RECORD_DBLPRE
1090 if (button != ACTION_NONE)
1091 lastbutton = button;
1092 #endif
1094 #if CONFIG_CODEC != SWCODEC
1095 peak_meter_peek();
1096 #endif
1098 if(!screen_freeze)
1100 /* Only display the peak meter when not recording */
1101 #if CONFIG_CODEC != SWCODEC
1102 if(TIME_AFTER(current_tick, timeout))
1104 timeout = current_tick + HZ;
1105 #else /* SWCODEC */
1107 #endif /* CONFIG_CODEC == SWCODEC */
1109 /* keep "mono" from always being displayed when paused */
1110 if (radio_status != FMRADIO_PAUSED)
1112 stereo = tuner_get(RADIO_STEREO) &&
1113 !global_settings.fm_force_mono;
1115 if(stereo != last_stereo)
1117 update_screen = true;
1118 last_stereo = stereo;
1123 #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR)
1124 seconds = audio_recorded_time() / HZ;
1125 if (update_screen || seconds > last_seconds || restore)
1127 last_seconds = seconds;
1128 #else
1129 if (update_screen || restore)
1131 #endif
1132 if (restore)
1133 fms_fix_displays(FMS_ENTER);
1134 FOR_NB_SCREENS(i)
1135 skin_update(&fms_skin[i], WPS_REFRESH_ALL);
1136 restore = false;
1139 update_screen = false;
1141 if (global_settings.talk_file && talk
1142 && radio_status == FMRADIO_PAUSED)
1144 talk = false;
1145 bool enqueue = false;
1146 if (radio_mode == RADIO_SCAN_MODE)
1148 talk_freq(curr_freq, enqueue);
1149 enqueue = true;
1151 if (curr_preset >= 0)
1152 talk_preset(curr_preset, radio_mode == RADIO_PRESET_MODE,
1153 enqueue);
1156 #if CONFIG_CODEC != SWCODEC
1157 if(audio_status() & AUDIO_STATUS_ERROR)
1159 done = true;
1161 #endif
1163 #ifndef HAVE_NOISY_IDLE_MODE
1164 if (TIME_AFTER(current_tick, button_timeout))
1166 cpu_idle_mode(true);
1168 #endif
1169 } /*while(!done)*/
1171 #ifndef SIMULATOR
1172 #if CONFIG_CODEC != SWCODEC
1173 if(audio_status() & AUDIO_STATUS_ERROR)
1175 splash(0, str(LANG_DISK_FULL));
1176 audio_error_clear();
1178 while(1)
1180 button = get_action(CONTEXT_FM, TIMEOUT_BLOCK);
1181 if(button == ACTION_FM_STOP)
1182 break;
1186 audio_init_playback();
1187 #endif /* CONFIG_CODEC != SWCODEC */
1189 sound_settings_apply();
1190 #endif /* SIMULATOR */
1192 if(keep_playing)
1194 /* Catch FMRADIO_PLAYING status for the sim. */
1195 #ifndef SIMULATOR
1196 #if CONFIG_CODEC != SWCODEC
1197 /* Enable the Left and right A/D Converter */
1198 audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN),
1199 sound_default(SOUND_RIGHT_GAIN),
1200 AUDIO_GAIN_LINEIN);
1201 mas_codec_writereg(6, 0x4000);
1202 #endif
1203 end_search();
1204 #endif /* SIMULATOR */
1206 else
1208 #if CONFIG_CODEC == SWCODEC
1209 audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK);
1210 #else
1211 radio_stop();
1212 #endif
1215 #ifndef HAVE_NOISY_IDLE_MODE
1216 cpu_idle_mode(false);
1217 #endif
1218 fms_fix_displays(FMS_EXIT);
1219 in_screen = false;
1220 #if CONFIG_CODEC != SWCODEC
1221 return have_recorded;
1222 #else
1223 return false;
1224 #endif
1225 } /* radio_screen */
1227 static void radio_save_presets(void)
1229 int fd;
1230 int i;
1232 fd = creat(filepreset, 0666);
1233 if(fd >= 0)
1235 for(i = 0;i < num_presets;i++)
1237 fdprintf(fd, "%d:%s\n", presets[i].frequency, presets[i].name);
1239 close(fd);
1241 if(!strncasecmp(FMPRESET_PATH, filepreset, strlen(FMPRESET_PATH)))
1242 set_file(filepreset, global_settings.fmr_file, MAX_FILENAME);
1243 presets_changed = false;
1245 else
1247 splash(HZ, ID2P(LANG_FM_PRESET_SAVE_FAILED));
1251 void radio_load_presets(char *filename)
1253 int fd;
1254 int rc;
1255 char buf[128];
1256 char *freq;
1257 char *name;
1258 bool done = false;
1259 int f;
1261 memset(presets, 0, sizeof(presets));
1262 num_presets = 0;
1264 /* No Preset in configuration. */
1265 if(filename[0] == '\0')
1267 filepreset[0] = '\0';
1268 return;
1270 /* Temporary preset, loaded until player shuts down. */
1271 else if(filename[0] == '/')
1272 strlcpy(filepreset, filename, sizeof(filepreset));
1273 /* Preset from default directory. */
1274 else
1275 snprintf(filepreset, sizeof(filepreset), "%s/%s.fmr",
1276 FMPRESET_PATH, filename);
1278 fd = open_utf8(filepreset, O_RDONLY);
1279 if(fd >= 0)
1281 while(!done && num_presets < MAX_PRESETS)
1283 rc = read_line(fd, buf, 128);
1284 if(rc > 0)
1286 if(settings_parseline(buf, &freq, &name))
1288 f = atoi(freq);
1289 if(f) /* For backwards compatibility */
1291 struct fmstation * const fms = &presets[num_presets];
1292 fms->frequency = f;
1293 strlcpy(fms->name, name, MAX_FMPRESET_LEN+1);
1294 num_presets++;
1298 else
1299 done = true;
1301 close(fd);
1303 else /* invalid file name? */
1304 filepreset[0] = '\0';
1306 presets_loaded = num_presets > 0;
1307 presets_changed = false;
1311 static int radio_add_preset(void)
1313 char buf[MAX_FMPRESET_LEN + 1];
1315 if(num_presets < MAX_PRESETS)
1317 buf[0] = '\0';
1319 if (!kbd_input(buf, MAX_FMPRESET_LEN + 1))
1321 struct fmstation * const fms = &presets[num_presets];
1322 strcpy(fms->name, buf);
1323 fms->frequency = curr_freq;
1324 num_presets++;
1325 presets_changed = true;
1326 presets_loaded = num_presets > 0;
1327 return true;
1330 else
1332 splash(HZ, ID2P(LANG_FM_NO_FREE_PRESETS));
1334 return false;
1337 /* needed to know which preset we are edit/delete-ing */
1338 static int selected_preset = -1;
1339 static int radio_edit_preset(void)
1341 char buf[MAX_FMPRESET_LEN + 1];
1343 if (num_presets > 0)
1345 struct fmstation * const fms = &presets[selected_preset];
1347 strcpy(buf, fms->name);
1349 if (!kbd_input(buf, MAX_FMPRESET_LEN + 1))
1351 strcpy(fms->name, buf);
1352 presets_changed = true;
1356 return 1;
1359 static int radio_delete_preset(void)
1361 if (num_presets > 0)
1363 struct fmstation * const fms = &presets[selected_preset];
1365 if (selected_preset >= --num_presets)
1366 selected_preset = num_presets - 1;
1368 memmove(fms, fms + 1, (uintptr_t)(fms + num_presets) -
1369 (uintptr_t)fms);
1371 if (curr_preset >= num_presets)
1372 --curr_preset;
1375 /* Don't ask to save when all presets are deleted. */
1376 presets_changed = num_presets > 0;
1378 if (!presets_changed)
1380 /* The preset list will be cleared, switch to Scan Mode. */
1381 radio_mode = RADIO_SCAN_MODE;
1382 curr_preset = -1;
1383 presets_loaded = false;
1386 return 1;
1389 static int load_preset_list(void)
1391 return !rockbox_browse(FMPRESET_PATH, SHOW_FMR);
1394 static int save_preset_list(void)
1396 if(num_presets > 0)
1398 bool bad_file_name = true;
1400 if(!dir_exists(FMPRESET_PATH)) /* Check if there is preset folder */
1401 mkdir(FMPRESET_PATH);
1403 create_numbered_filename(filepreset, FMPRESET_PATH, "preset",
1404 ".fmr", 2 IF_CNFN_NUM_(, NULL));
1406 while(bad_file_name)
1408 if(!kbd_input(filepreset, sizeof(filepreset)))
1410 /* check the name: max MAX_FILENAME (20) chars */
1411 char* p2;
1412 char* p1;
1413 int len;
1414 p1 = strrchr(filepreset, '/');
1415 p2 = p1;
1416 while((p1) && (*p2) && (*p2 != '.'))
1417 p2++;
1418 len = (int)(p2-p1) - 1;
1419 if((!p1) || (len > MAX_FILENAME) || (len == 0))
1421 /* no slash, too long or too short */
1422 splash(HZ, ID2P(LANG_INVALID_FILENAME));
1424 else
1426 /* add correct extension (easier to always write)
1427 at this point, p2 points to 0 or the extension dot */
1428 *p2 = '\0';
1429 strcat(filepreset,".fmr");
1430 bad_file_name = false;
1431 radio_save_presets();
1434 else
1436 /* user aborted */
1437 return false;
1441 else
1442 splash(HZ, ID2P(LANG_FM_NO_PRESETS));
1444 return true;
1447 static int clear_preset_list(void)
1449 /* Clear all the preset entries */
1450 memset(presets, 0, sizeof (presets));
1452 num_presets = 0;
1453 presets_loaded = false;
1454 /* The preset list will be cleared switch to Scan Mode. */
1455 radio_mode = RADIO_SCAN_MODE;
1456 curr_preset = -1;
1457 presets_changed = false; /* Don't ask to save when clearing the list. */
1459 return true;
1462 MENUITEM_FUNCTION(radio_edit_preset_item, MENU_FUNC_CHECK_RETVAL,
1463 ID2P(LANG_FM_EDIT_PRESET),
1464 radio_edit_preset, NULL, NULL, Icon_NOICON);
1465 MENUITEM_FUNCTION(radio_delete_preset_item, MENU_FUNC_CHECK_RETVAL,
1466 ID2P(LANG_FM_DELETE_PRESET),
1467 radio_delete_preset, NULL, NULL, Icon_NOICON);
1468 static int radio_preset_callback(int action,
1469 const struct menu_item_ex *this_item)
1471 if (action == ACTION_STD_OK)
1472 action = ACTION_EXIT_AFTER_THIS_MENUITEM;
1473 return action;
1474 (void)this_item;
1476 MAKE_MENU(handle_radio_preset_menu, ID2P(LANG_PRESET),
1477 radio_preset_callback, Icon_NOICON, &radio_edit_preset_item,
1478 &radio_delete_preset_item);
1479 /* present a list of preset stations */
1480 static const char* presets_get_name(int selected_item, void *data,
1481 char *buffer, size_t buffer_len)
1483 (void)data;
1484 struct fmstation *p = &presets[selected_item];
1485 if(p->name[0])
1486 return p->name;
1487 int freq = p->frequency / 10000;
1488 int frac = freq % 100;
1489 freq /= 100;
1490 snprintf(buffer, buffer_len,
1491 str(LANG_FM_DEFAULT_PRESET_NAME), freq, frac);
1492 return buffer;
1495 static int presets_speak_name(int selected_item, void * data)
1497 (void)data;
1498 talk_preset(selected_item, true, false);
1499 return 0;
1502 static int handle_radio_presets(void)
1504 struct gui_synclist lists;
1505 int result = 0;
1506 int action = ACTION_NONE;
1507 #ifdef HAVE_BUTTONBAR
1508 struct gui_buttonbar buttonbar;
1509 #endif
1511 if(presets_loaded == false)
1512 return result;
1514 #ifdef HAVE_BUTTONBAR
1515 gui_buttonbar_init(&buttonbar);
1516 gui_buttonbar_set_display(&buttonbar, &(screens[SCREEN_MAIN]) );
1517 gui_buttonbar_set(&buttonbar, str(LANG_FM_BUTTONBAR_ADD),
1518 str(LANG_FM_BUTTONBAR_EXIT),
1519 str(LANG_FM_BUTTONBAR_ACTION));
1520 gui_buttonbar_draw(&buttonbar);
1521 #endif
1522 gui_synclist_init(&lists, presets_get_name, NULL, false, 1, NULL);
1523 gui_synclist_set_title(&lists, str(LANG_PRESET), NOICON);
1524 gui_synclist_set_icon_callback(&lists, NULL);
1525 if(global_settings.talk_file)
1526 gui_synclist_set_voice_callback(&lists, presets_speak_name);
1527 gui_synclist_set_nb_items(&lists, num_presets);
1528 gui_synclist_select_item(&lists, curr_preset<0 ? 0 : curr_preset);
1529 gui_synclist_speak_item(&lists);
1531 while (result == 0)
1533 gui_synclist_draw(&lists);
1534 list_do_action(CONTEXT_STD, TIMEOUT_BLOCK,
1535 &lists, &action, LIST_WRAP_UNLESS_HELD);
1536 switch (action)
1538 case ACTION_STD_MENU:
1539 if (radio_add_preset())
1541 gui_synclist_set_nb_items(&lists, num_presets);
1542 gui_synclist_select_item(&lists, num_presets - 1);
1544 break;
1545 case ACTION_STD_CANCEL:
1546 result = 1;
1547 break;
1548 case ACTION_STD_OK:
1549 curr_preset = gui_synclist_get_sel_pos(&lists);
1550 curr_freq = presets[curr_preset].frequency;
1551 next_station(0);
1552 remember_frequency();
1553 result = 1;
1554 break;
1555 case ACTION_F3:
1556 case ACTION_STD_CONTEXT:
1557 selected_preset = gui_synclist_get_sel_pos(&lists);
1558 do_menu(&handle_radio_preset_menu, NULL, NULL, false);
1559 gui_synclist_set_nb_items(&lists, num_presets);
1560 gui_synclist_select_item(&lists, selected_preset);
1561 gui_synclist_speak_item(&lists);
1562 break;
1563 default:
1564 if(default_event_handler(action) == SYS_USB_CONNECTED)
1565 result = 2;
1568 return result - 1;
1571 void toggle_mono_mode(bool mono)
1573 tuner_set(RADIO_FORCE_MONO, mono);
1576 void set_radio_region(int region)
1578 #ifdef HAVE_RADIO_REGION
1579 tuner_set(RADIO_REGION, region);
1580 #endif
1581 next_station(0);
1582 remember_frequency();
1583 (void)region;
1586 MENUITEM_SETTING(set_region, &global_settings.fm_region, NULL);
1587 MENUITEM_SETTING(force_mono, &global_settings.fm_force_mono, NULL);
1589 #ifndef FM_MODE
1590 static char* get_mode_text(int selected_item, void * data, char *buffer)
1592 (void)selected_item;
1593 (void)data;
1594 snprintf(buffer, MAX_PATH, "%s %s", str(LANG_MODE),
1595 radio_mode ? str(LANG_PRESET) :
1596 str(LANG_RADIO_SCAN_MODE));
1597 return buffer;
1599 static int toggle_radio_mode(void)
1601 radio_mode = (radio_mode == RADIO_SCAN_MODE) ?
1602 RADIO_PRESET_MODE : RADIO_SCAN_MODE;
1603 return 0;
1605 MENUITEM_FUNCTION_DYNTEXT(radio_mode_item, 0,
1606 toggle_radio_mode, NULL,
1607 get_mode_text, NULL, NULL, NULL, Icon_NOICON);
1608 #endif
1610 static int scan_presets(void *viewports)
1612 bool do_scan = true;
1613 int i;
1614 struct viewport *vp = (struct viewport *)viewports;
1616 FOR_NB_SCREENS(i)
1617 screens[i].set_viewport(vp?&vp[i]:NULL);
1618 if(num_presets > 0) /* Do that to avoid 2 questions. */
1619 do_scan = yesno_pop(ID2P(LANG_FM_CLEAR_PRESETS));
1621 if(do_scan)
1623 const struct fm_region_data * const fmr =
1624 &fm_region_data[global_settings.fm_region];
1626 curr_freq = fmr->freq_min;
1627 num_presets = 0;
1628 memset(presets, 0, sizeof(presets));
1630 tuner_set(RADIO_MUTE, 1);
1632 while(curr_freq <= fmr->freq_max)
1634 int freq, frac;
1635 if(num_presets >= MAX_PRESETS || action_userabort(TIMEOUT_NOBLOCK))
1636 break;
1638 freq = curr_freq / 10000;
1639 frac = freq % 100;
1640 freq /= 100;
1642 splashf(0, str(LANG_FM_SCANNING), freq, frac);
1644 if(tuner_set(RADIO_SCAN_FREQUENCY, curr_freq))
1646 /* add preset */
1647 presets[num_presets].name[0] = '\0';
1648 presets[num_presets].frequency = curr_freq;
1649 num_presets++;
1652 curr_freq += fmr->freq_step;
1655 if (radio_status == FMRADIO_PLAYING)
1656 tuner_set(RADIO_MUTE, 0);
1658 presets_changed = true;
1660 FOR_NB_SCREENS(i)
1662 screens[i].clear_viewport();
1663 screens[i].update_viewport();
1666 if(num_presets > 0)
1668 curr_freq = presets[0].frequency;
1669 radio_mode = RADIO_PRESET_MODE;
1670 presets_loaded = true;
1671 next_station(0);
1673 else
1675 /* Wrap it to beginning or we'll be past end of band */
1676 presets_loaded = false;
1677 next_station(1);
1680 return true;
1684 #ifdef HAVE_RECORDING
1686 #if defined(HAVE_FMRADIO_REC) && CONFIG_CODEC == SWCODEC
1687 #define FM_RECORDING_SCREEN
1688 static int fm_recording_screen(void)
1690 bool ret;
1692 /* switch recording source to FMRADIO for the duration */
1693 int rec_source = global_settings.rec_source;
1694 global_settings.rec_source = AUDIO_SRC_FMRADIO;
1695 ret = recording_screen(true);
1697 /* safe to reset as changing sources is prohibited here */
1698 global_settings.rec_source = rec_source;
1700 return ret;
1703 #endif /* defined(HAVE_FMRADIO_REC) && CONFIG_CODEC == SWCODEC */
1705 #if defined(HAVE_FMRADIO_REC) || CONFIG_CODEC != SWCODEC
1706 #define FM_RECORDING_SETTINGS
1707 static int fm_recording_settings(void)
1709 bool ret = recording_menu(true);
1711 #if CONFIG_CODEC != SWCODEC
1712 if (!ret)
1714 struct audio_recording_options rec_options;
1715 rec_init_recording_options(&rec_options);
1716 rec_options.rec_source = AUDIO_SRC_LINEIN;
1717 rec_set_recording_options(&rec_options);
1719 #endif
1721 return ret;
1724 #endif /* defined(HAVE_FMRADIO_REC) || CONFIG_CODEC != SWCODEC */
1725 #endif /* HAVE_RECORDING */
1727 #ifdef FM_RECORDING_SCREEN
1728 MENUITEM_FUNCTION(recscreen_item, 0, ID2P(LANG_RECORDING),
1729 fm_recording_screen, NULL, NULL, Icon_Recording);
1730 #endif
1731 #ifdef FM_RECORDING_SETTINGS
1732 MENUITEM_FUNCTION(recsettings_item, 0, ID2P(LANG_RECORDING_SETTINGS),
1733 fm_recording_settings, NULL, NULL, Icon_Recording);
1734 #endif
1735 #ifndef FM_PRESET
1736 MENUITEM_FUNCTION(radio_presets_item, 0, ID2P(LANG_PRESET),
1737 handle_radio_presets, NULL, NULL, Icon_NOICON);
1738 #endif
1739 #ifndef FM_PRESET_ADD
1740 MENUITEM_FUNCTION(radio_addpreset_item, 0, ID2P(LANG_FM_ADD_PRESET),
1741 radio_add_preset, NULL, NULL, Icon_NOICON);
1742 #endif
1745 MENUITEM_FUNCTION(presetload_item, 0, ID2P(LANG_FM_PRESET_LOAD),
1746 load_preset_list, NULL, NULL, Icon_NOICON);
1747 MENUITEM_FUNCTION(presetsave_item, 0, ID2P(LANG_FM_PRESET_SAVE),
1748 save_preset_list, NULL, NULL, Icon_NOICON);
1749 MENUITEM_FUNCTION(presetclear_item, 0, ID2P(LANG_FM_PRESET_CLEAR),
1750 clear_preset_list, NULL, NULL, Icon_NOICON);
1751 MENUITEM_FUNCTION(scan_presets_item, MENU_FUNC_USEPARAM,
1752 ID2P(LANG_FM_SCAN_PRESETS),
1753 scan_presets, NULL, NULL, Icon_NOICON);
1755 MAKE_MENU(radio_settings_menu, ID2P(LANG_FM_MENU), NULL,
1756 Icon_Radio_screen,
1757 #ifndef FM_PRESET
1758 &radio_presets_item,
1759 #endif
1760 #ifndef FM_PRESET_ADD
1761 &radio_addpreset_item,
1762 #endif
1763 &presetload_item, &presetsave_item, &presetclear_item,
1764 &force_mono,
1765 #ifndef FM_MODE
1766 &radio_mode_item,
1767 #endif
1768 &set_region, &sound_settings,
1769 #ifdef FM_RECORDING_SCREEN
1770 &recscreen_item,
1771 #endif
1772 #ifdef FM_RECORDING_SETTINGS
1773 &recsettings_item,
1774 #endif
1775 &scan_presets_item);
1776 /* main menu of the radio screen */
1777 static bool radio_menu(void)
1779 return do_menu(&radio_settings_menu, NULL, NULL, false) ==
1780 MENU_ATTACHED_USB;
1783 #endif