? radio_finished.patch Index: apps/gui/gwps-common.c =================================================================== RCS file: /cvsroot/rockbox/apps/gui/gwps-common.c,v retrieving revision 1.41 diff -u -r1.41 gwps-common.c --- apps/gui/gwps-common.c 12 Feb 2006 15:37:15 -0000 1.41 +++ apps/gui/gwps-common.c 15 Feb 2006 11:41:17 -0000 @@ -5,7 +5,7 @@ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ - * $Id: gwps-common.c,v 1.41 2006-02-12 15:37:15 lostlogic Exp $ + * $Id: gwps-common.c,v 1.40 2006/02/10 13:57:11 benbasha Exp $ * * Copyright (C) 2002 Björn Stenberg * @@ -50,6 +50,10 @@ #ifdef HAVE_LCD_COLOR #include "backdrop.h" #endif +#include "debug.h" +#ifdef CONFIG_TUNER +#include "radio.h" +#endif #ifdef HAVE_LCD_CHARCELLS static bool draw_player_progress(struct gui_wps *gwps); @@ -395,6 +399,7 @@ (int) (time / 3600000), (int) (time % 3600000 / 60000), (int) (time % 60000 / 1000)); } + } /* Extract a part from a path. @@ -453,6 +458,13 @@ * * Returns the tag. NULL indicates the tag wasn't available. */ +#ifdef CONFIG_TUNER +#define IGNORE_IF_RADIO() if (wps_state.wps_type == WPS_TYPE_RADIO) break; +#define IGNORE_IF_REGULAR() if (wps_state.wps_type == WPS_TYPE_REGULAR) break; +#else +#define IGNORE_IF_RADIO() +#define IGNORE_IF_REGULAR() +#endif static char* get_tag(struct wps_data* wps_data, struct mp3entry* cid3, struct mp3entry* nid3, @@ -481,12 +493,14 @@ switch (tag[0]) { case 'I': /* ID3 Information */ + IGNORE_IF_RADIO(); id3 = nid3; /* display next-song data */ *flags |= WPS_REFRESH_DYNAMIC; if(!id3) return NULL; /* no such info (yet) */ /* fall-through */ case 'i': /* ID3 Information */ + IGNORE_IF_RADIO(); *flags |= WPS_REFRESH_STATIC; switch (tag[1]) { @@ -550,12 +564,14 @@ break; case 'F': /* File Information */ + IGNORE_IF_RADIO(); id3 = nid3; *flags |= WPS_REFRESH_DYNAMIC; if(!id3) return NULL; /* no such info (yet) */ /* fall-through */ case 'f': /* File Information */ + IGNORE_IF_RADIO(); *flags |= WPS_REFRESH_STATIC; switch(tag[1]) { @@ -666,27 +682,32 @@ return buf; #endif case 'p': /* Playlist Position */ + IGNORE_IF_RADIO(); *flags |= WPS_REFRESH_STATIC; snprintf(buf, buf_size, "%d", playlist_get_display_index()); return buf; case 'n': /* Playlist Name (without path) */ + IGNORE_IF_RADIO(); *flags |= WPS_REFRESH_STATIC; return playlist_name(NULL, buf, buf_size); case 'e': /* Playlist Total Entries */ + IGNORE_IF_RADIO(); *flags |= WPS_REFRESH_STATIC; snprintf(buf, buf_size, "%d", playlist_amount()); return buf; case 'c': /* Current Time in Song */ + IGNORE_IF_RADIO(); *flags |= WPS_REFRESH_DYNAMIC; gui_wps_format_time(buf, buf_size, id3->elapsed + wps_state.ff_rewind_count); return buf; case 'r': /* Remaining Time in Song */ + IGNORE_IF_RADIO(); *flags |= WPS_REFRESH_DYNAMIC; gui_wps_format_time(buf, buf_size, id3->length - id3->elapsed - @@ -694,8 +715,9 @@ return buf; case 't': /* Total Time */ + IGNORE_IF_RADIO(); *flags |= WPS_REFRESH_STATIC; - gui_wps_format_time(buf, buf_size, id3->length); + gui_wps_format_time(buf, buf_size, id3->length); return buf; #ifdef HAVE_LCD_BITMAP @@ -704,6 +726,7 @@ return "\x01"; #endif case 's': /* shuffle */ + IGNORE_IF_RADIO(); *flags |= WPS_REFRESH_DYNAMIC; if ( global_settings.playlist_shuffle ) return "s"; @@ -713,7 +736,14 @@ case 'v': /* volume */ *flags |= WPS_REFRESH_DYNAMIC; - snprintf(buf, buf_size, "%d", global_settings.volume); + if (tag[2] == '%') + { + int min = sound_min(SOUND_VOLUME); + int max = sound_max(SOUND_VOLUME); + int vol = (global_settings.volume-min)*100/(max-min); + snprintf(buf, buf_size, "%d", vol); + } + else snprintf(buf, buf_size, "%d", global_settings.volume); *intval = 10 * (global_settings.volume - sound_min(SOUND_VOLUME)) / (sound_max(SOUND_VOLUME) @@ -727,6 +757,7 @@ switch (tag[1]) { case 'm': /* playback repeat mode */ + IGNORE_IF_RADIO(); *flags |= WPS_REFRESH_DYNAMIC; *intval = global_settings.repeat_mode + 1; snprintf(buf, buf_size, "%d", *intval); @@ -735,18 +766,41 @@ /* playback status */ case 'p': /* play */ *flags |= WPS_REFRESH_DYNAMIC; - int status = audio_status(); - *intval = 1; - if (status == AUDIO_STATUS_PLAY && \ - !(status & AUDIO_STATUS_PAUSE)) - *intval = 2; - if (audio_status() & AUDIO_STATUS_PAUSE && \ - (! status_get_ffmode())) - *intval = 3; - if (status_get_ffmode() == STATUS_FASTFORWARD) - *intval = 4; - if (status_get_ffmode() == STATUS_FASTBACKWARD) - *intval = 5; + int status; +#ifdef CONFIG_TUNER + if (wps_state.wps_type==WPS_TYPE_REGULAR) + { +#endif + status = audio_status(); + *intval = 1; + if (status == AUDIO_STATUS_PLAY && \ + !(status & AUDIO_STATUS_PAUSE)) + *intval = 2; + if (audio_status() & AUDIO_STATUS_PAUSE && \ + (! status_get_ffmode())) + *intval = 3; + if (status_get_ffmode() == STATUS_FASTFORWARD) + *intval = 4; + if (status_get_ffmode() == STATUS_FASTBACKWARD) + *intval = 5; +#ifdef CONFIG_TUNER + } + else if (wps_state.wps_type==WPS_TYPE_RADIO) + { + status = get_radio_status(); + *intval = 1; + if (status == FMRADIO_PLAYING && \ + !(status & FMRADIO_PAUSED)) + *intval = 2; + if (status & FMRADIO_PAUSED && \ + (! status&(FMRADIO_SCANFWD|FMRADIO_SCANBACK))) + *intval = 3; + if (status & FMRADIO_SCANFWD) + *intval = 4; + if (status & FMRADIO_SCANBACK) + *intval = 5; + } +#endif snprintf(buf, buf_size, "%d", *intval); return buf; @@ -845,12 +899,14 @@ #endif case 'D': /* Directory path information */ + IGNORE_IF_RADIO(); id3 = nid3; /* next song please! */ *flags |= WPS_REFRESH_DYNAMIC; if(!id3) return NULL; /* no such info (yet) */ /* fall-through */ case 'd': /* Directory path information */ + IGNORE_IF_RADIO(); { int level = tag[1] - '0'; *flags |= WPS_REFRESH_STATIC; @@ -901,7 +957,8 @@ return buf; } break; - case 'r': /* Runtime database Information */ + case 'r': /* Runtime database Information */ + IGNORE_IF_RADIO(); switch(tag[1]) { case 'p': /* Playcount */ @@ -915,6 +972,81 @@ return buf; } break; +#ifdef CONFIG_TUNER + case 'R': /* radio screen */ + { + struct radioinfo *radio = (struct radioinfo *)cid3; /*its a union.. so this is ok */ + int freq; + switch (tag[1]) /* all this because of the %?R tag which is required always */ + { + case 'f': + case 'l': + case 'L': + case 'm': + case 'p': + case 's': + case 't': + IGNORE_IF_REGULAR(); + break; + } + + switch (tag[1]) + { + case 'f': /* frequncey */ + { + freq = (radio->frequency) / 100000; + snprintf(buf, buf_size, "%d.%d", freq / 10, freq % 10); + *intval = radio->frequency; + return buf; + } + case 'l': /* min freq */ + { + freq = (radio->min_freq) / 100000; + snprintf(buf, buf_size, "%d.%d", freq / 10, freq % 10); + *intval = radio->min_freq; + return buf; + } + case 'L': /* max freq */ + { + freq = radio->max_freq / 100000; + snprintf(buf, buf_size, "%d.%d", freq / 10, freq % 10); + *intval = radio->max_freq; + return buf; + } + case 'm': /* mode */ + return radio->radio_mode; + + case 'p': /* preset */ + if (tag[2] == 'n') + { + snprintf(buf, buf_size, "%s", radio->preset_info.name); + *tag_len = 3; + } + else if (tag[2] == 'i') + { + snprintf(buf, buf_size, "%d", radio->preset_num); + *intval = radio->preset_num; + *tag_len = 3; + } + else + { + return (radio->using_preset)?"p":NULL; + } + return buf; + case 's': /* stereo */ + return radio->stereo?"s":NULL; + case 't': /* tuned */ + return radio->tuned?"t":NULL; + default: /* is it the radio screen? */ + *intval = wps_state.wps_type+1; + snprintf(buf, buf_size, "%d", wps_state.wps_type); + *tag_len = 1; + return buf; + } + break; /* case 'R' */ + } +#endif /* CONFIG_TUNER */ + } return NULL; } @@ -1203,7 +1335,7 @@ level++; break; - + default: value = get_tag(gwps->data, id3, nid3, fmt, temp_buf, sizeof(temp_buf), &tag_length, @@ -1619,7 +1751,6 @@ update_line = true; peak_meter_y = i * h + offset; - /* The user might decide to have the peak meter in the last line so that it is only displayed if no status bar is visible. If so we neither want do draw nor enable the @@ -2230,7 +2361,6 @@ case WPS_RC_NEXT: #endif audio_ff_rewind(wps_state.id3->elapsed+ff_rewind_count); - wps_state.id3->elapsed = wps_state.id3->elapsed+ff_rewind_count; ff_rewind_count = 0; wps_state.ff_rewind = false; status_set_ffmode(0); @@ -2254,6 +2384,10 @@ button = button_get(true); } + /* let audio thread update id3->elapsed before calling wps_refresh */ + yield(); + FOR_NB_SCREENS(i) + gui_wps_refresh(&gui_wps[i], 0, WPS_REFRESH_ALL); return usb; } @@ -2283,12 +2417,21 @@ { #ifdef HAVE_LCD_BITMAP wps_data_load(gui_wps[i].data, +#ifdef CONFIG_TUNER + "%s%?R<%s%?it<%?in<%in. |>%it|%fn>|Station:%RfMHz>\n" + "%s%?R<%?ia<%ia|%?d2<%d2|(root)>>|Mode:%Rm>\n" + "%s%?R<%?id<%id|%?d1<%d1|(root)>> %?iy<(%iy)|>|%?Rp<%Rpi. %Rpn|>\n" + "\n" + "%al%?R<%pc/%pt%ar[%pp:%pe]|>\n" + "%?R<%fbkBit %?fv %?iv<(id3v%iv)|(no id3)>|%al%Rl %ac%Rf %ar%RL>\n" +#else "%s%?it<%?in<%in. |>%it|%fn>\n" "%s%?ia<%ia|%?d2<%d2|(root)>>\n" "%s%?id<%id|%?d1<%d1|(root)>> %?iy<(%iy)|>\n" "\n" "%al%pc/%pt%ar[%pp:%pe]\n" "%fbkBit %?fv %?iv<(id3v%iv)|(no id3)>\n" +#endif /* CONFIG_TUNER */ "%pb\n" "%pm\n", false); #else @@ -2302,10 +2445,19 @@ else if(i == 1) { wps_data_load(gui_wps[i].data, +#ifdef CONFIG_TUNER + "%s%?R<%?ia<%ia|%?d2<%d2|(root)>>|Station:%RfMHz>\n" + "%s%?R<%?it<%?in<%in. |>%it|%fn>|Mode:%Rm>\n" + "%s%?R<%al%pc/%pt%ar[%pp:%pe]|%?Rp<%Rpi. %Rpn| >\n" + "\n" + "%?R<%fbkBit %?fv %?iv<(id3v%iv)|(no id3)>|%al%Rl %ac%Rf %ar%RL>\n" +#else "%s%?ia<%ia|%?d2<%d2|(root)>>\n" "%s%?it<%?in<%in. |>%it|%fn>\n" "%al%pc/%pt%ar[%pp:%pe]\n" + "\n" "%fbkBit %?fv %?iv<(id3v%iv)|(no id3)>\n" +#endif /* CONFIG_TUNER */ "%pb", false); } #endif Index: apps/gui/gwps.c =================================================================== RCS file: /cvsroot/rockbox/apps/gui/gwps.c,v retrieving revision 1.26 diff -u -r1.26 gwps.c --- apps/gui/gwps.c 10 Feb 2006 14:07:53 -0000 1.26 +++ apps/gui/gwps.c 15 Feb 2006 11:41:19 -0000 @@ -5,7 +5,7 @@ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ - * $Id: gwps.c,v 1.26 2006-02-10 14:07:53 benbasha Exp $ + * $Id: gwps.c,v 1.26 2006/02/10 14:07:53 benbasha Exp $ * * Copyright (C) 2002 Jerome Kuptz * @@ -75,7 +75,7 @@ static void wps_state_update_ctp(const char *path); #ifdef HAVE_LCD_BITMAP -static void gui_wps_set_margin(struct gui_wps *gwps) +void gui_wps_set_margin(struct gui_wps *gwps) { int offset = 0; struct wps_data *data = gwps->data; @@ -99,7 +99,7 @@ unsigned long left_lastclick = 0; int i; - wps_state_init(); + wps_state_init(WPS_TYPE_REGULAR); #ifdef HAVE_LCD_CHARCELLS status_set_audio(true); @@ -535,6 +535,7 @@ #endif if (main_menu()) return true; + wps_state_init(WPS_TYPE_REGULAR); #ifdef HAVE_LCD_COLOR if (wps_has_backdrop) lcd_set_backdrop(&wps_backdrop[0][0]); @@ -943,13 +944,14 @@ /* wps_state */ -void wps_state_init(void) +void wps_state_init(int wps_type) { wps_state.ff_rewind = false; wps_state.paused = false; wps_state.id3 = NULL; wps_state.nid3 = NULL; wps_state.current_track_path[0] = '\0'; + wps_state.wps_type = wps_type; } #if 0 Index: apps/gui/gwps.h =================================================================== RCS file: /cvsroot/rockbox/apps/gui/gwps.h,v retrieving revision 1.21 diff -u -r1.21 gwps.h --- apps/gui/gwps.h 10 Feb 2006 13:57:11 -0000 1.21 +++ apps/gui/gwps.h 15 Feb 2006 11:41:20 -0000 @@ -5,7 +5,7 @@ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ - * $Id: gwps.h,v 1.21 2006-02-10 13:57:11 benbasha Exp $ + * $Id: gwps.h,v 1.21 2006/02/10 13:57:11 benbasha Exp $ * * Copyright (C) 2002 Jerome Kuptz * @@ -22,7 +22,10 @@ #include "screen_access.h" #include "statusbar.h" #include "id3.h" -#include "playlist.h" +#include "playlist.h" +#ifdef CONFIG_TUNER +#include "radio.h" +#endif /* button definitions */ @@ -338,19 +341,31 @@ holds the data which belongs to the current played track, the track which will be played afterwards, current path to the track and some status infos */ +enum { + WPS_TYPE_REGULAR = 0, + WPS_TYPE_RADIO, + WPS_TYPE_RECORDING, + + WPS_TYPE_COUNT +}; + struct wps_state { bool ff_rewind; bool paused; int ff_rewind_count; - bool wps_time_countup; - struct mp3entry* id3; + bool wps_time_countup; + union { + struct mp3entry* id3; + struct radioinfo* radio; + }; struct mp3entry* nid3; char current_track_path[MAX_PATH+1]; + int wps_type; /* from above enum */ }; /* initial setup of wps_data */ -void wps_state_init(void); +void wps_state_init(int wps_type); /* change the ff/rew-status if ff_rew = true then we are in skipping mode @@ -372,7 +387,9 @@ struct wps_state *state; struct gui_statusbar *statusbar; }; - +#ifdef HAVE_LCD_BITMAP +void gui_wps_set_margin(struct gui_wps *gwps); +#endif /* initial setup of a wps */ void gui_wps_init(struct gui_wps *gui_wps); @@ -391,6 +408,7 @@ /* currently only on wps_state is needed */ extern struct wps_state wps_state; extern struct gui_wps gui_wps[NB_SCREENS]; +extern struct wps_data wps_datas[NB_SCREENS]; void gui_sync_wps_init(void); void gui_sync_wps_screen_init(void); Index: apps/recorder/radio.c =================================================================== RCS file: /cvsroot/rockbox/apps/recorder/radio.c,v retrieving revision 1.90 diff -u -r1.90 radio.c --- apps/recorder/radio.c 8 Feb 2006 13:08:55 -0000 1.90 +++ apps/recorder/radio.c 15 Feb 2006 11:41:22 -0000 @@ -5,7 +5,7 @@ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ - * $Id: radio.c,v 1.90 2006-02-08 13:08:55 bger Exp $ + * $Id: radio.c,v 1.90 2006/02/08 13:08:55 bger Exp $ * * Copyright (C) 2003 Linus Nielsen Feltzing * @@ -17,111 +17,17 @@ * ****************************************************************************/ -#include "config.h" -#include -#include -#include "sprintf.h" -#include "mas.h" -#include "settings.h" -#include "button.h" -#include "fmradio.h" -#include "status.h" -#include "kernel.h" -#include "mpeg.h" -#include "audio.h" -#include "mp3_playback.h" -#include "ctype.h" -#include "file.h" -#include "errno.h" -#include "atoi.h" -#include "string.h" -#include "system.h" -#include "radio.h" -#include "menu.h" -#include "misc.h" -#include "keyboard.h" -#include "screens.h" -#include "peakmeter.h" -#include "lang.h" -#include "font.h" -#include "sound_menu.h" -#include "recording.h" -#include "talk.h" -#include "tuner.h" -#include "hwcompat.h" -#include "power.h" -#include "sound.h" -#include "screen_access.h" -#include "statusbar.h" -#include "textarea.h" -#include "splash.h" -#include "yesno.h" -#include "buttonbar.h" -#include "power.h" #ifdef CONFIG_TUNER +#include "config.h" +#include "radio.h" +#include "lang.h" #if CONFIG_CODEC == SWCODEC #include "uda1380.h" #include "pcm_record.h" #endif -#if CONFIG_KEYPAD == RECORDER_PAD -#define FM_MENU BUTTON_F1 -#define FM_PRESET BUTTON_F2 -#define FM_RECORD BUTTON_F3 -#define FM_FREEZE BUTTON_PLAY -#define FM_STOP BUTTON_OFF -#define FM_MODE (BUTTON_ON | BUTTON_REPEAT) -#define FM_EXIT_PRE BUTTON_ON -#define FM_EXIT (BUTTON_ON | BUTTON_REL) -#define FM_PRESET_ADD BUTTON_F1 -#define FM_PRESET_ACTION BUTTON_F3 - -#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD) -/* pause/play - short PLAY */ -#define FM_PLAY_PRE BUTTON_ON -#define FM_RC_PLAY_PRE BUTTON_RC_ON -#define FM_PLAY (BUTTON_ON | BUTTON_REL) -#define FM_RC_PLAY (BUTTON_RC_ON | BUTTON_REL) -/* preset/scan mode - long PLAY */ -#define FM_MODE (BUTTON_ON | BUTTON_REPEAT) -#define FM_RC_MODE (BUTTON_RC_ON | BUTTON_REPEAT) -/* preset menu - short SELECT */ -#define FM_PRESET_PRE BUTTON_SELECT -#define FM_RC_PRESET_PRE BUTTON_RC_MENU -#define FM_PRESET (BUTTON_SELECT | BUTTON_REL) -#define FM_RC_PRESET (BUTTON_RC_MENU | BUTTON_REL) -/* fm menu - long SELECT */ -#define FM_MENU (BUTTON_SELECT | BUTTON_REPEAT) -#define FM_RC_MENU (BUTTON_RC_MENU | BUTTON_REPEAT) -/* main menu(exit radio while playing) - A-B */ -#define FM_EXIT_PRE BUTTON_MODE -#define FM_EXIT (BUTTON_MODE | BUTTON_REL) -#define FM_RC_EXIT_PRE BUTTON_RC_MODE -#define FM_RC_EXIT (BUTTON_RC_MODE | BUTTON_REL) -/* prev/next preset on the remote - BITRATE/SOURCE */ -#define FM_NEXT_PRESET (BUTTON_RC_BITRATE | BUTTON_REL) -#define FM_PREV_PRESET (BUTTON_RC_SOURCE | BUTTON_REL) -/* stop and exit radio - STOP */ -#define FM_STOP BUTTON_OFF -#define FM_RC_STOP BUTTON_RC_STOP - -#elif CONFIG_KEYPAD == ONDIO_PAD /* restricted keypad */ -#define FM_MENU (BUTTON_MENU | BUTTON_REPEAT) -#define FM_RECORD_DBLPRE BUTTON_MENU -#define FM_RECORD (BUTTON_MENU | BUTTON_REL) -#define FM_STOP_PRE BUTTON_OFF -#define FM_STOP (BUTTON_OFF | BUTTON_REL) -#define FM_EXIT (BUTTON_OFF | BUTTON_REPEAT) -#endif - -#define MAX_FREQ (108000000) -#define MIN_FREQ (87500000) -#define FREQ_STEP 100000 -#define RADIO_SCAN_MODE 0 -#define RADIO_PRESET_MODE 1 static int curr_preset = -1; static int curr_freq; @@ -129,7 +35,7 @@ static int radio_status = FMRADIO_OFF; -#define MAX_PRESETS 64 + static bool presets_loaded = false; static struct fmstation presets[MAX_PRESETS]; @@ -182,7 +88,30 @@ int get_radio_status(void) { return radio_status; -} +} + +int get_radio_mode(void) +{ + return radio_mode; +} + +bool is_radio_tuned(void) +{ + return radio_get(RADIO_TUNED); +} + +void radio_start(void) +{ + curr_freq = global_settings.last_frequency * FREQ_STEP + MIN_FREQ; + radio_power(true); + radio_set(RADIO_SLEEP, 0); /* wake up the tuner */ + radio_set(RADIO_FREQUENCY, curr_freq); + radio_set(RADIO_IF_MEASUREMENT, 0); + radio_set(RADIO_SENSITIVITY, 0); + radio_set(RADIO_FORCE_MONO, global_settings.fm_force_mono); + radio_set(RADIO_MUTE, 0); + radio_status = FMRADIO_PLAYING; +} void radio_stop(void) { @@ -190,7 +119,15 @@ radio_set(RADIO_SLEEP, 1); /* low power mode, if available */ radio_status = FMRADIO_OFF; radio_power(false); /* status update, power off if avail. */ -} +} + +void radio_pause(bool yes) +{ + radio_set(RADIO_SLEEP, yes); + radio_set(RADIO_FREQUENCY, curr_freq); + radio_set(RADIO_MUTE, yes); + radio_status = yes?FMRADIO_PAUSED:FMRADIO_PLAYING; +} bool radio_hardware_present(void) { @@ -204,6 +141,25 @@ return radio_get(RADIO_PRESENT); #endif } +int get_freq(void) +{ + return curr_freq; +} + +bool is_radio_stereo(void) +{ + return radio_get(RADIO_STEREO); +} + +int get_preset(struct fmstation *preset) +{ + if (curr_preset>=0) + { + // preset = &presets[curr_preset]; + memcpy(preset,&presets[curr_preset],sizeof(struct fmstation)); + } + return curr_preset; +} static int find_preset(int freq) { @@ -231,10 +187,10 @@ return i; if(diff < 0) diff = -diff; - if(diff < min_diff) + if(diff < min_diff) { preset = i; - min_diff = diff; + min_diff = diff; } } @@ -242,13 +198,29 @@ } - static void remember_frequency(void) { global_settings.last_frequency = (curr_freq - MIN_FREQ) / FREQ_STEP; settings_save(); } - +bool tune_freq(int freq) +{ + int tuned; + /* Tune in and delay */ + radio_set(RADIO_FREQUENCY, freq); + sleep(1); + + /* Start IF measurement */ + radio_set(RADIO_IF_MEASUREMENT, 1); + sleep(1); + + /* Now check how close to the IF frequency we are */ + curr_freq = freq; + tuned = radio_get(RADIO_TUNED); + if (tuned) + remember_frequency(); + return tuned; +} void next_preset(int direction) { if (num_presets < 1) @@ -267,7 +239,7 @@ else if (num_presets > 1) { if (direction > 0) - curr_preset = 0; + curr_preset = 0; else curr_preset = num_presets - 1; } @@ -278,1069 +250,1001 @@ remember_frequency(); } -bool radio_screen(void) -{ - char buf[MAX_PATH]; - bool done = false; - int button, lastbutton = BUTTON_NONE; -#ifdef FM_RECORD_DBLPRE - unsigned long rec_lastclick = 0; -#endif - int freq, i; - bool tuned; - bool stereo = false; - int search_dir = 0; - int fh; - bool last_stereo_status = false; - int top_of_screen = 0; - bool update_screen = true; - int timeout = current_tick + HZ/10; - bool screen_freeze = false; - bool have_recorded = false; - unsigned int seconds = 0; - unsigned int last_seconds = 0; - int hours, minutes; - bool keep_playing = false; - bool statusbar = global_settings.statusbar; -#ifdef HAS_BUTTONBAR - struct gui_buttonbar buttonbar; - gui_buttonbar_init(&buttonbar); - gui_buttonbar_set_display(&buttonbar, &(screens[SCREEN_MAIN]) ); -#endif - /* always display status bar in radio screen for now */ - global_settings.statusbar = true; - FOR_NB_SCREENS(i){ - gui_textarea_clear(&screens[i]); - screen_set_xmargin(&screens[i],0); - } - - gui_syncstatusbar_draw(&statusbars,true); - - fh = font_get(FONT_UI)->height; - - /* Adjust for font size, trying to center the information vertically */ - if(fh < 10) - top_of_screen = 1; - - radio_load_presets(); -#ifndef SIMULATOR -#if CONFIG_CODEC != SWCODEC - if(rec_create_directory() > 0) - have_recorded = true; -#endif +void radio_save_presets(void) +{ + int fd; + int i; - audio_stop(); - -#if CONFIG_CODEC != SWCODEC - audio_init_recording(); + fd = creat(default_filename, O_WRONLY); + if(fd >= 0) + { + for(i = 0;i < num_presets;i++) + { + fdprintf(fd, "%d:%s\n", presets[i].frequency, presets[i].name); + } + close(fd); + } + else + { + gui_syncsplash(HZ*2, true, str(LANG_FM_PRESET_SAVE_FAILED)); + } +} - sound_settings_apply(); +void radio_load_presets(void) +{ + int fd; + int rc; + char buf[128]; + char *freq; + char *name; + bool done = false; + int f; - /* Yes, we use the D/A for monitoring */ - peak_meter_playback(true); + if(!presets_loaded) + { + memset(presets, 0, sizeof(presets)); + num_presets = 0; - peak_meter_enabled = true; + fd = open(default_filename, O_RDONLY); + if(fd >= 0) + { + while(!done && num_presets < MAX_PRESETS) + { + rc = read_line(fd, buf, 128); + if(rc > 0) + { + if(settings_parseline(buf, &freq, &name)) + { + f = atoi(freq); + if(f) /* For backwards compatibility */ + { + presets[num_presets].frequency = f; + strncpy(presets[num_presets].name, name, 27); + presets[num_presets].name[27] = 0; + num_presets++; + } + } + } + else + done = true; + } + close(fd); + } + } + presets_loaded = true; +} - if (global_settings.rec_prerecord_time) - talk_buffer_steal(); /* will use the mp3 buffer */ +static void rebuild_preset_menu(void) +{ + int i; + for(i = 0;i < num_presets;i++) + { + preset_menu_items[i].desc = presets[i].name; + } +} - audio_set_recording_options(global_settings.rec_frequency, - global_settings.rec_quality, - 1, /* Line In */ - global_settings.rec_channels, - global_settings.rec_editable, - global_settings.rec_prerecord_time); +bool radio_add_preset(void) +{ + char buf[27]; - - audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN), - sound_default(SOUND_RIGHT_GAIN), AUDIO_GAIN_LINEIN); -#else - uda1380_enable_recording(false); - uda1380_set_recvol(10, 10, AUDIO_GAIN_DECIMATOR); - uda1380_set_recvol(0, 0, AUDIO_GAIN_LINEIN); - uda1380_set_monitor(true); + if(num_presets < MAX_PRESETS) + { + memset(buf, 0, 27); + + if (!kbd_input(buf, 27)) + { + buf[27] = 0; + strcpy(presets[num_presets].name, buf); + presets[num_presets].frequency = curr_freq; +#ifdef FM_PRESET_ADD /* only for archos */ + menu_insert(preset_menu, -1, + presets[num_presets].name, 0); + /* We must still rebuild the menu table, since the + item name pointers must be updated */ + rebuild_preset_menu(); +#endif + num_presets++; + radio_save_presets(); + } + } + else + { + gui_syncsplash(HZ*2, true, str(LANG_FM_NO_FREE_PRESETS)); + } + return true; +} - /* Set the input multiplexer to FM */ - pcm_rec_mux(1); -#endif +/* button preprocessor for preset option submenu */ +static int handle_radio_presets_menu_cb(int key, int m) +{ + (void)m; +#ifdef FM_PRESET_ACTION + switch(key) + { + case FM_PRESET_ACTION: + key = MENU_EXIT; /* Fake an exit */ + break; + + case FM_PRESET_ACTION | BUTTON_REL: + /* Ignore the release events */ + key = BUTTON_NONE; + break; + } #endif + return key; +} - curr_freq = global_settings.last_frequency * FREQ_STEP + MIN_FREQ; - - if(radio_status != FMRADIO_PLAYING){ - radio_power(true); - radio_set(RADIO_SLEEP, 0); /* wake up the tuner */ - radio_set(RADIO_FREQUENCY, curr_freq); - radio_set(RADIO_IF_MEASUREMENT, 0); - radio_set(RADIO_SENSITIVITY, 0); - radio_set(RADIO_FORCE_MONO, global_settings.fm_force_mono); - radio_set(RADIO_MUTE, 0); - radio_status = FMRADIO_PLAYING; +static bool radio_edit_preset(void) +{ + int pos = menu_cursor(preset_menu); + char buf[27]; + + strncpy(buf, menu_description(preset_menu, pos), 27); + + if (!kbd_input(buf, 27)) + { + buf[27] = 0; + strcpy(presets[pos].name, buf); + radio_save_presets(); } - - curr_preset = find_preset(curr_freq); - if(curr_preset != -1) - radio_mode = RADIO_PRESET_MODE; + return true; +} -#ifdef HAS_BUTTONBAR - gui_buttonbar_set(&buttonbar, str(LANG_BUTTONBAR_MENU), str(LANG_FM_BUTTONBAR_PRESETS), - str(LANG_FM_BUTTONBAR_RECORD)); -#endif +bool radio_delete_preset(void) +{ + int pos = menu_cursor(preset_menu); + int i; - cpu_idle_mode(true); + for(i = pos;i < num_presets;i++) + presets[i] = presets[i+1]; + num_presets--; - while(!done) - { - if(search_dir) - { - curr_freq += search_dir * FREQ_STEP; - if(curr_freq < MIN_FREQ) - curr_freq = MAX_FREQ; - if(curr_freq > MAX_FREQ) - curr_freq = MIN_FREQ; - - /* Tune in and delay */ - radio_set(RADIO_FREQUENCY, curr_freq); - sleep(1); - - /* Start IF measurement */ - radio_set(RADIO_IF_MEASUREMENT, 1); - sleep(1); + menu_delete(preset_menu, pos); + /* We must still rebuild the menu table, since the + item name pointers must be updated */ + rebuild_preset_menu(); + radio_save_presets(); - /* Now check how close to the IF frequency we are */ - tuned = radio_get(RADIO_TUNED); + return true; /* Make the menu return immediately */ +} - /* Stop searching if the tuning is close */ - if(tuned) - { - search_dir = 0; - curr_preset = find_preset(curr_freq); - remember_frequency(); - } - - update_screen = true; - } +/* little menu on what to do with a preset entry */ +bool handle_radio_presets_menu(void) +{ + static const struct menu_item preset_menu_items[] = { + { ID2P(LANG_FM_EDIT_PRESET), radio_edit_preset }, + { ID2P(LANG_FM_DELETE_PRESET), radio_delete_preset }, + }; + int m; - if(search_dir) - button = button_get(false); - else - button = button_get_w_tmo(HZ / PEAK_METER_FPS); - switch(button) - { -#ifdef FM_RC_STOP - case FM_RC_STOP: -#endif - case FM_STOP: -#ifdef FM_STOP_PRE - if (lastbutton != FM_STOP_PRE) - break; -#endif -#ifndef SIMULATOR - if(audio_status() == AUDIO_STATUS_RECORD) - { - audio_stop(); - } - else -#endif - { - done = true; - } - update_screen = true; - break; + m = menu_init( preset_menu_items, + sizeof preset_menu_items / sizeof(struct menu_item), + handle_radio_presets_menu_cb, + NULL, NULL, str(LANG_FM_BUTTONBAR_EXIT)); + menu_run(m); + menu_exit(m); + return false; +} -#ifdef FM_RECORD - case FM_RECORD: -#ifdef FM_RECORD_DBLPRE - if (lastbutton != FM_RECORD_DBLPRE) - { - rec_lastclick = 0; - break; - } - if (current_tick - rec_lastclick > HZ/2) - { - rec_lastclick = current_tick; - break; - } +/* button preprocessor for list of preset stations menu */ +int handle_radio_presets_cb(int key, int m) +{ + (void)m; + switch(key) + { +#ifdef FM_PRESET_ADD + case FM_PRESET_ADD: + radio_add_preset(); + menu_draw(m); + key = BUTTON_NONE; + break; #endif -#ifndef SIMULATOR - if(audio_status() == AUDIO_STATUS_RECORD) - { - audio_new_file(rec_create_filename(buf)); - update_screen = true; - } - else - { - have_recorded = true; - talk_buffer_steal(); /* we use the mp3 buffer */ - audio_record(rec_create_filename(buf)); - update_screen = true; - } +#if (CONFIG_KEYPAD != IRIVER_H100_PAD) && (CONFIG_KEYPAD != IRIVER_H300_PAD) +#ifdef FM_PRESET + case FM_PRESET: + menu_draw(m); + key = MENU_EXIT; /* Fake an exit */ + break; #endif - last_seconds = 0; - break; -#endif /* #ifdef FM_RECORD */ - -#ifdef FM_RC_EXIT - case FM_RC_EXIT: #endif - case FM_EXIT: -#ifdef FM_EXIT_PRE - if(lastbutton != FM_EXIT_PRE -#ifdef FM_RC_EXIT_PRE - && lastbutton != FM_RC_EXIT_PRE -#endif - ) - break; +#ifdef FM_PRESET_ACTION + case FM_PRESET_ACTION: #endif -#ifndef SIMULATOR - if(audio_status() == AUDIO_STATUS_RECORD) - audio_stop(); +#ifdef MENU_ENTER2 + case MENU_ENTER2 | BUTTON_REPEAT: #endif - keep_playing = true; - done = true; - break; - -#ifdef BUTTON_RC_REW - case BUTTON_RC_REW: + case MENU_ENTER | BUTTON_REPEAT: /* long gives options */ + { + bool ret; + ret = handle_radio_presets_menu(); + menu_draw(m); + if(ret) + key = MENU_ATTACHED_USB; + else + key = BUTTON_NONE; + break; + } +#ifdef MENU_ENTER2 + case MENU_ENTER2 | BUTTON_REL: #endif - case BUTTON_LEFT: - if(radio_mode == RADIO_SCAN_MODE) - { - curr_freq -= FREQ_STEP; - if(curr_freq < MIN_FREQ) - curr_freq = MAX_FREQ; - radio_set(RADIO_FREQUENCY, curr_freq); - curr_preset = find_preset(curr_freq); - remember_frequency(); - } - else - next_preset(-1); - search_dir = 0; - update_screen = true; - break; + case MENU_ENTER | BUTTON_REL: + key = MENU_ENTER; /* fake enter for short press */ + break; -#ifdef BUTTON_RC_FF - case BUTTON_RC_FF: +#ifdef MENU_ENTER2 + case MENU_ENTER2: #endif - case BUTTON_RIGHT: - if(radio_mode == RADIO_SCAN_MODE) - { - curr_freq += FREQ_STEP; - if(curr_freq > MAX_FREQ) - curr_freq = MIN_FREQ; - radio_set(RADIO_FREQUENCY, curr_freq); - curr_preset = find_preset(curr_freq); - remember_frequency(); - } - else - next_preset(1); - search_dir = 0; - update_screen = true; - break; - -#ifdef BUTTON_RC_REW - case BUTTON_RC_REW | BUTTON_REPEAT: + case MENU_ENTER: /* ignore down event */ + /* Ignore the release events */ +#ifdef FM_PRESET_ADD + case FM_PRESET_ADD | BUTTON_REL: #endif - case BUTTON_LEFT | BUTTON_REPEAT: - if(radio_mode == RADIO_SCAN_MODE) - search_dir = -1; - break; - -#ifdef BUTTON_RC_FF - case BUTTON_RC_FF | BUTTON_REPEAT: +#ifdef FM_PRESET_ACTION + case FM_PRESET_ACTION | BUTTON_REL: #endif - case BUTTON_RIGHT | BUTTON_REPEAT: - if(radio_mode == RADIO_SCAN_MODE) - search_dir = 1; - break; + key = BUTTON_NONE; + break; + } + return key; +} -#ifdef BUTTON_RC_VOL_UP - case BUTTON_RC_VOL_UP: - case BUTTON_RC_VOL_UP | BUTTON_REPEAT: -#endif - case BUTTON_UP: - case BUTTON_UP | BUTTON_REPEAT: - global_settings.volume++; - if(global_settings.volume > sound_max(SOUND_VOLUME)) - global_settings.volume = sound_max(SOUND_VOLUME); - sound_set_volume(global_settings.volume); - update_screen = true; - settings_save(); - break; +/* present a list of preset stations */ +bool handle_radio_presets(void) +{ + int result; + bool reload_dir = false; -#ifdef BUTTON_RC_VOL_DOWN - case BUTTON_RC_VOL_DOWN: - case BUTTON_RC_VOL_DOWN | BUTTON_REPEAT: -#endif - case BUTTON_DOWN: - case BUTTON_DOWN | BUTTON_REPEAT: - global_settings.volume--; - if(global_settings.volume < sound_min(SOUND_VOLUME)) - global_settings.volume = sound_min(SOUND_VOLUME); - sound_set_volume(global_settings.volume); - update_screen = true; - settings_save(); - break; + if(presets_loaded) + { + rebuild_preset_menu(); -#ifdef FM_PLAY -#ifdef FM_RC_PLAY - case FM_RC_PLAY: + /* DIY menu handling, since we want to exit after selection */ + preset_menu = menu_init( preset_menu_items, num_presets, + handle_radio_presets_cb, + str(LANG_FM_BUTTONBAR_ADD), + str(LANG_FM_BUTTONBAR_EXIT), + str(LANG_FM_BUTTONBAR_ACTION)); + if (curr_preset >= 0) + menu_set_cursor(preset_menu, curr_preset); + result = menu_show(preset_menu); + menu_exit(preset_menu); + if (result == MENU_SELECTED_EXIT) + return false; + else if (result == MENU_ATTACHED_USB) + reload_dir = true; + + if (result >= 0) /* A preset was selected */ + { + curr_preset = menu_cursor(preset_menu); + curr_freq = presets[curr_preset].frequency; + radio_set(RADIO_FREQUENCY, curr_freq); + remember_frequency(); + } + } + + return reload_dir; +} + +#ifndef SIMULATOR +#if CONFIG_CODEC != SWCODEC +static bool fm_recording_settings(void) +{ + bool ret; + + ret = recording_menu(true); + if(!ret) + { + if (global_settings.rec_prerecord_time) + talk_buffer_steal(); /* will use the mp3 buffer */ + + audio_set_recording_options(global_settings.rec_frequency, + global_settings.rec_quality, + 1, /* Line In */ + global_settings.rec_channels, + global_settings.rec_editable, + global_settings.rec_prerecord_time); + } + return ret; +} #endif - case FM_PLAY: -#ifdef FM_PLAY_PRE - if(lastbutton != FM_PLAY_PRE -#ifdef FM_RC_PLAY_PRE - && lastbutton != FM_RC_PLAY_PRE -#endif - ) - break; -#endif - if(radio_status != FMRADIO_PLAYING) - { - radio_set(RADIO_SLEEP, 0); - radio_set(RADIO_FREQUENCY, curr_freq); - radio_set(RADIO_MUTE, 0); - radio_status = FMRADIO_PLAYING; - } - else - { - radio_set(RADIO_MUTE, 1); - radio_set(RADIO_SLEEP, 1); - radio_status = FMRADIO_PAUSED; - } - update_screen = true; - break; -#endif -#ifdef FM_MENU -#ifdef FM_RC_MENU - case FM_RC_MENU: -#endif - case FM_MENU: - radio_menu(); - curr_preset = find_preset(curr_freq); - FOR_NB_SCREENS(i){ - gui_textarea_clear(&screens[i]); - screen_set_xmargin(&screens[i],0); - } -#ifdef HAS_BUTTONBAR - gui_buttonbar_set(&buttonbar, str(LANG_BUTTONBAR_MENU), - str(LANG_FM_BUTTONBAR_PRESETS), - str(LANG_FM_BUTTONBAR_RECORD)); -#endif - update_screen = true; - break; #endif -#ifdef FM_RC_PRESET - case FM_RC_PRESET: -#endif -#ifdef FM_PRESET - case FM_PRESET: -#ifdef FM_PRESET_PRE - if(lastbutton != FM_PRESET_PRE -#ifdef FM_RC_PRESET_PRE - && lastbutton != FM_RC_PRESET_PRE -#endif - ) - break; -#endif - if(num_presets < 1){ - gui_syncsplash(HZ, true, str(LANG_FM_NO_PRESETS)); - update_screen = true; - break; - } - handle_radio_presets(); - curr_preset = find_preset(curr_freq); - FOR_NB_SCREENS(i){ - gui_textarea_clear(&screens[i]); - screen_set_xmargin(&screens[i],0); - } -#ifdef HAS_BUTTONBAR - gui_buttonbar_set(&buttonbar, - str(LANG_BUTTONBAR_MENU), - str(LANG_FM_BUTTONBAR_PRESETS), - str(LANG_FM_BUTTONBAR_RECORD)); -#endif - update_screen = true; - break; -#endif - -#ifdef FM_FREEZE - case FM_FREEZE: - if(!screen_freeze) - { - gui_syncsplash(HZ, true, str(LANG_FM_FREEZE)); - screen_freeze = true; - } - else - { - update_screen = true; - screen_freeze = false; - } - break; -#endif - case SYS_USB_CONNECTED: - /* Only accept USB connection when not recording */ - if(audio_status() != AUDIO_STATUS_RECORD) - { - default_event_handler(SYS_USB_CONNECTED); - screen_freeze = true; /* Cosmetic: makes sure the - radio screen doesn't redraw */ - done = true; - } - break; +char monomode_menu_string[32]; -#ifdef FM_RC_MODE - case FM_RC_MODE: -#endif -#ifdef FM_MODE - case FM_MODE: - if(lastbutton != FM_MODE -#ifdef FM_RC_MODE - && lastbutton != FM_RC_MODE -#endif - ) - { - if(radio_mode == RADIO_SCAN_MODE) - radio_mode = RADIO_PRESET_MODE; - else - radio_mode = RADIO_SCAN_MODE; - update_screen = true; - } - break; -#endif -#ifdef FM_NEXT_PRESET - case FM_NEXT_PRESET: - next_preset(1); - search_dir = 0; - update_screen = true; - break; -#endif -#ifdef FM_PREV_PRESET - case FM_PREV_PRESET: - next_preset(-1); - search_dir = 0; - update_screen = true; - break; -#endif - - default: - default_event_handler(button); - break; - } +static void create_monomode_menu(void) +{ + snprintf(monomode_menu_string, sizeof monomode_menu_string, + "%s: %s", str(LANG_FM_MONO_MODE), + global_settings.fm_force_mono? + str(LANG_SET_BOOL_YES):str(LANG_SET_BOOL_NO)); +} - if (button != BUTTON_NONE) - lastbutton = button; - - peak_meter_peek(); +static bool toggle_mono_mode(void) +{ + global_settings.fm_force_mono = !global_settings.fm_force_mono; + radio_set(RADIO_FORCE_MONO, global_settings.fm_force_mono); + settings_save(); + create_monomode_menu(); + return false; +} - if(!screen_freeze) - { - /* Only display the peak meter when not recording */ - if(!audio_status()) - { - /* just main screen for the time being */ - peak_meter_draw(0, STATUSBAR_HEIGHT + fh*(top_of_screen + 4), LCD_WIDTH, fh); - screens[SCREEN_MAIN].update_rect(0, STATUSBAR_HEIGHT + fh*(top_of_screen + 4), screens[SCREEN_MAIN].width, fh); - } +#ifndef FM_MODE +char radiomode_menu_string[32]; - if(TIME_AFTER(current_tick, timeout)) - { - timeout = current_tick + HZ; - - stereo = radio_get(RADIO_STEREO) && - !global_settings.fm_force_mono; - if(stereo != last_stereo_status) - { - update_screen = true; - last_stereo_status = stereo; - } - } - -#ifndef SIMULATOR -#if CONFIG_CODEC != SWCODEC - seconds = audio_recorded_time() / HZ; -#endif +static void create_radiomode_menu(void) +{ + snprintf(radiomode_menu_string, 32, "%s %s", str(LANG_FM_TUNE_MODE), + radio_mode ? str(LANG_RADIO_PRESET_MODE) : + str(LANG_RADIO_SCAN_MODE)); +} + +static bool toggle_radio_mode(void) +{ + radio_mode = (radio_mode == RADIO_SCAN_MODE) ? + RADIO_PRESET_MODE : RADIO_SCAN_MODE; + create_radiomode_menu(); + return false; +} #endif - if(update_screen || seconds > last_seconds) - { - last_seconds = seconds; - FOR_NB_SCREENS(i) - screens[i].setfont(FONT_UI); - - if (curr_preset >= 0 ) - snprintf(buf, 128, "%d. %s",curr_preset + 1, - presets[curr_preset].name); - else - snprintf(buf, 128, " "); - FOR_NB_SCREENS(i) - screens[i].puts_scroll(0, top_of_screen, buf); - - freq = curr_freq / 100000; - snprintf(buf, 128, str(LANG_FM_STATION), freq / 10, freq % 10); - FOR_NB_SCREENS(i) - screens[i].puts_scroll(0, top_of_screen + 1, buf); - - strcat(buf, stereo?str(LANG_CHANNEL_STEREO): - str(LANG_CHANNEL_MONO)); +static bool scan_presets(void) +{ + bool tuned = false; + char buf[27]; + int freq, i; + char *lines[]={str(LANG_FM_CLEAR_PRESETS)}; + struct text_message message={lines, 1}; + + if(gui_syncyesno_run(&message,NULL,NULL)==YESNO_YES){ + FOR_NB_SCREENS(i) + gui_textarea_clear(&screens[i]); + curr_freq = MIN_FREQ; + num_presets = 0; + while(curr_freq <= MAX_FREQ){ + if (num_presets >= MAX_PRESETS) + break; - snprintf(buf, 128, stereo?str(LANG_CHANNEL_STEREO): - str(LANG_CHANNEL_MONO)); - FOR_NB_SCREENS(i) - screens[i].puts_scroll(0, top_of_screen + 2, buf); - - snprintf(buf, 128, "%s %s", str(LANG_FM_TUNE_MODE), - radio_mode ? str(LANG_RADIO_PRESET_MODE) : - str(LANG_RADIO_SCAN_MODE)); - FOR_NB_SCREENS(i) - screens[i].puts_scroll(0, top_of_screen + 3, buf); + freq = curr_freq /100000; + snprintf(buf, 27, str(LANG_FM_SCANNING), freq/10, freq % 10); + gui_syncsplash(0, true, buf); - if(audio_status() == AUDIO_STATUS_RECORD) - { - hours = seconds / 3600; - minutes = (seconds - (hours * 3600)) / 60; - snprintf(buf, 32, "%s %02d:%02d:%02d", - str(LANG_RECORDING_TIME), - hours, minutes, seconds%60); - FOR_NB_SCREENS(i) - screens[i].puts_scroll(0, top_of_screen + 4, buf); - } - else - { - if(global_settings.rec_prerecord_time) - { - snprintf(buf, 32, "%s %02d", - str(LANG_RECORD_PRERECORD), seconds%60); - FOR_NB_SCREENS(i) - screens[i].puts_scroll(0, top_of_screen + 4, buf); - } - } + tuned = tune_freq(curr_freq); -#ifdef HAS_BUTTONBAR - gui_buttonbar_draw(&buttonbar); -#endif - FOR_NB_SCREENS(i) - gui_textarea_update(&screens[i]); + /* add preset */ + if(tuned){ + snprintf(buf, 27, str(LANG_FM_DEFAULT_PRESET_NAME),freq/10, freq % 10); + strcpy(presets[num_presets].name,buf); + presets[num_presets].frequency = curr_freq; + num_presets++; } - /* Only force the redraw if update_screen is true */ - gui_syncstatusbar_draw(&statusbars,true); - update_screen = false; + curr_freq += FREQ_STEP; + } - if(audio_status() & AUDIO_STATUS_ERROR) - { - done = true; + radio_save_presets(); + + if(num_presets > 0 ){ + curr_freq = presets[0].frequency; + radio_set(RADIO_FREQUENCY, curr_freq); + remember_frequency(); + radio_mode = RADIO_PRESET_MODE; } } + return true; +} -#ifndef SIMULATOR - if(audio_status() & AUDIO_STATUS_ERROR) +/* button preprocessor for the main menu */ +int radio_menu_cb(int key, int m) +{ + (void)m; + switch(key) { - gui_syncsplash(0, true, str(LANG_DISK_FULL)); - gui_syncstatusbar_draw(&statusbars,true); - FOR_NB_SCREENS(i) - gui_textarea_update(&screens[i]); - audio_error_clear(); +#if (CONFIG_KEYPAD != IRIVER_H100_PAD) && (CONFIG_KEYPAD != IRIVER_H300_PAD) +#ifdef MENU_ENTER2 + case MENU_ENTER2: +#endif +#endif + case MENU_ENTER: + key = BUTTON_NONE; /* eat the downpress, next menu reacts on release */ + break; - while(1) - { - button = button_get(true); - if(button == (BUTTON_OFF | BUTTON_REL)) - break; - } - } - -#if CONFIG_CODEC != SWCODEC - audio_init_playback(); -#endif - - sound_settings_apply(); - - if(keep_playing) - { -#if CONFIG_CODEC != SWCODEC - /* Enable the Left and right A/D Converter */ - audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN), - sound_default(SOUND_RIGHT_GAIN), AUDIO_GAIN_LINEIN); - mas_codec_writereg(6, 0x4000); +#if (CONFIG_KEYPAD != IRIVER_H100_PAD) && (CONFIG_KEYPAD != IRIVER_H300_PAD) +#ifdef MENU_ENTER2 + case MENU_ENTER2 | BUTTON_REL: #endif - } - else - { - radio_stop(); -#if CONFIG_CODEC == SWCODEC - pcm_rec_mux(0); /* Line In */ #endif + case MENU_ENTER | BUTTON_REL: + key = MENU_ENTER; /* fake downpress, next menu doesn't like release */ + break; } -#endif - - cpu_idle_mode(false); - - /* restore status bar settings */ - global_settings.statusbar = statusbar; - - return have_recorded; + return key; } -void radio_save_presets(void) +/* main menu of the radio screen */ +bool radio_menu(void) { - int fd; - int i; + int m; + bool result; - fd = creat(default_filename, O_WRONLY); - if(fd >= 0) - { - for(i = 0;i < num_presets;i++) - { - fdprintf(fd, "%d:%s\n", presets[i].frequency, presets[i].name); - } - close(fd); - } - else - { - gui_syncsplash(HZ*2, true, str(LANG_FM_PRESET_SAVE_FAILED)); - } + static const struct menu_item items[] = { +/* Add functions not accessible via buttons */ +#ifndef FM_PRESET + { ID2P(LANG_FM_BUTTONBAR_PRESETS), handle_radio_presets }, +#endif +#ifndef FM_PRESET_ADD + { ID2P(LANG_FM_ADD_PRESET) , radio_add_preset }, +#endif + { monomode_menu_string , toggle_mono_mode }, +#ifndef FM_MODE + { radiomode_menu_string , toggle_radio_mode }, +#endif + { ID2P(LANG_SOUND_SETTINGS) , sound_menu }, +#if !defined(SIMULATOR) && (CONFIG_CODEC != SWCODEC) + { ID2P(LANG_RECORDING_SETTINGS) , fm_recording_settings}, +#endif + { ID2P(LANG_FM_SCAN_PRESETS) , scan_presets }, + }; + + create_monomode_menu(); +#ifndef FM_MODE + create_radiomode_menu(); +#endif + m = menu_init(items, sizeof(items) / sizeof(*items), + radio_menu_cb, NULL, NULL, NULL); + result = menu_run(m); + menu_exit(m); + return result; } -void radio_load_presets(void) -{ - int fd; - int rc; - char buf[128]; - char *freq; - char *name; - bool done = false; - int f; +/***************************************** radio wps stuff ****************************/ +#include "../gui/gwps-common.h" +#include "../gui/gwps.h" +#ifdef HAVE_LCD_COLOR +#include "backdrop.h" +#endif +#define WPS_DEFAULTCFG WPS_DIR "/rockbox_default.wps" +#define RWPS_DEFAULTCFG WPS_DIR "/rockbox_default.rwps" +struct radioinfo radio; - if(!presets_loaded) - { - memset(presets, 0, sizeof(presets)); - num_presets = 0; - - fd = open(default_filename, O_RDONLY); - if(fd >= 0) - { - while(!done && num_presets < MAX_PRESETS) - { - rc = read_line(fd, buf, 128); - if(rc > 0) - { - if(settings_parseline(buf, &freq, &name)) - { - f = atoi(freq); - if(f) /* For backwards compatibility */ - { - presets[num_presets].frequency = f; - strncpy(presets[num_presets].name, name, 27); - presets[num_presets].name[27] = 0; - num_presets++; - } - } - } - else - done = true; - } - close(fd); - } - } - presets_loaded = true; -} +#ifdef HAVE_LCD_COLOR +bool wps_has_backdrop; +fb_data* old_backdrop; +#endif -static void rebuild_preset_menu(void) -{ - int i; - for(i = 0;i < num_presets;i++) - { - preset_menu_items[i].desc = presets[i].name; - } -} +char *mode_str[2] = {"Scan","Presets"}; -bool radio_add_preset(void) +void fill_radio_info(struct radioinfo *info) { - char buf[27]; - - if(num_presets < MAX_PRESETS) + if (curr_preset>=0) { - memset(buf, 0, 27); - - if (!kbd_input(buf, 27)) - { - buf[27] = 0; - strcpy(presets[num_presets].name, buf); - presets[num_presets].frequency = curr_freq; -#ifdef FM_PRESET_ADD /* only for archos */ - menu_insert(preset_menu, -1, - presets[num_presets].name, 0); - /* We must still rebuild the menu table, since the - item name pointers must be updated */ - rebuild_preset_menu(); -#endif - num_presets++; - radio_save_presets(); - } + memcpy(&(info->preset_info),&presets[curr_preset],sizeof(presets[curr_preset])); + info->using_preset = true; } else { - gui_syncsplash(HZ*2, true, str(LANG_FM_NO_FREE_PRESETS)); + info->using_preset = false; } - return true; + info->frequency = curr_freq; + info->min_freq = MIN_FREQ; + info->max_freq = MAX_FREQ; + info->tuned = is_radio_tuned(); + info->stereo = is_radio_stereo(); + info->radio_status = get_radio_status(); + info->radio_mode = mode_str[radio_mode]; + info->preset_num = curr_preset; } -/* button preprocessor for preset option submenu */ -static int handle_radio_presets_menu_cb(int key, int m) + +bool radio_screen(void) { - (void)m; -#ifdef FM_PRESET_ACTION - switch(key) - { - case FM_PRESET_ACTION: - key = MENU_EXIT; /* Fake an exit */ - break; - - case FM_PRESET_ACTION | BUTTON_REL: - /* Ignore the release events */ - key = BUTTON_NONE; - break; + bool done = false; + int button, lastbutton = BUTTON_NONE; +#ifdef FM_RECORD_DBLPRE + unsigned long rec_lastclick = 0; +#endif + int i; + bool tuned; + bool keep_playing = false; + int search_dir = 0; + bool update_screen = true; + bool screen_freeze = false; + bool have_recorded = false; + int timeout = current_tick + HZ/10; +#ifdef HAS_BUTTONBAR + struct gui_buttonbar buttonbar; + gui_buttonbar_init(&buttonbar); + gui_buttonbar_set_display(&buttonbar, &(screens[SCREEN_MAIN]) ); +#endif + + radio_load_presets(); + + /* set up the screen */ + wps_state_init(WPS_TYPE_RADIO); + + fill_radio_info(&radio); + wps_state.radio = &radio; +#ifndef HAVE_LCD_CHARCELLS + FOR_NB_SCREENS(i) + { + gui_wps_display(); + gui_wps_set_margin(&gui_wps[i]); + } +#ifdef HAVE_LCD_COLOR + old_backdrop = lcd_get_backdrop(); + if (wps_has_backdrop) { + lcd_set_backdrop(&wps_backdrop[0][0]); } #endif - return key; -} +#endif + + -static bool radio_edit_preset(void) -{ - int pos = menu_cursor(preset_menu); - char buf[27]; +#ifndef SIMULATOR +#if CONFIG_CODEC != SWCODEC + if(rec_create_directory() > 0) + have_recorded = true; +#endif + + audio_stop(); - strncpy(buf, menu_description(preset_menu, pos), 27); - - if (!kbd_input(buf, 27)) - { - buf[27] = 0; - strcpy(presets[pos].name, buf); - radio_save_presets(); - } - return true; -} +#if CONFIG_CODEC != SWCODEC + audio_init_recording(); -bool radio_delete_preset(void) -{ - int pos = menu_cursor(preset_menu); - int i; + sound_settings_apply(); - for(i = pos;i < num_presets;i++) - presets[i] = presets[i+1]; - num_presets--; + /* Yes, we use the D/A for monitoring */ + peak_meter_playback(true); - menu_delete(preset_menu, pos); - /* We must still rebuild the menu table, since the - item name pointers must be updated */ - rebuild_preset_menu(); - radio_save_presets(); - - return true; /* Make the menu return immediately */ -} + peak_meter_enabled = true; -/* little menu on what to do with a preset entry */ -bool handle_radio_presets_menu(void) -{ - static const struct menu_item preset_menu_items[] = { - { ID2P(LANG_FM_EDIT_PRESET), radio_edit_preset }, - { ID2P(LANG_FM_DELETE_PRESET), radio_delete_preset }, - }; - int m; + if (global_settings.rec_prerecord_time) + talk_buffer_steal(); /* will use the mp3 buffer */ - m = menu_init( preset_menu_items, - sizeof preset_menu_items / sizeof(struct menu_item), - handle_radio_presets_menu_cb, - NULL, NULL, str(LANG_FM_BUTTONBAR_EXIT)); - menu_run(m); - menu_exit(m); - return false; -} + audio_set_recording_options(global_settings.rec_frequency, + global_settings.rec_quality, + 1, /* Line In */ + global_settings.rec_channels, + global_settings.rec_editable, + global_settings.rec_prerecord_time); -/* button preprocessor for list of preset stations menu */ -int handle_radio_presets_cb(int key, int m) -{ - (void)m; - switch(key) + + audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN), + sound_default(SOUND_RIGHT_GAIN), AUDIO_GAIN_LINEIN); +#else + uda1380_enable_recording(false); + uda1380_set_recvol(10, 10, AUDIO_GAIN_DECIMATOR); + uda1380_set_recvol(0, 0, AUDIO_GAIN_LINEIN); + uda1380_set_monitor(true); + + /* Set the input multiplexer to FM */ + pcm_rec_mux(1); +#endif +#endif + + curr_freq = global_settings.last_frequency * FREQ_STEP + MIN_FREQ; + + if(radio_status != FMRADIO_PLAYING){ + radio_start(); + } + + curr_preset = find_preset(curr_freq); + if(curr_preset != -1) + radio_mode = RADIO_PRESET_MODE; + +#ifdef HAS_BUTTONBAR + gui_buttonbar_set(&buttonbar, str(LANG_BUTTONBAR_MENU), str(LANG_FM_BUTTONBAR_PRESETS), + str(LANG_FM_BUTTONBAR_RECORD)); +#endif + + while(!done) { -#ifdef FM_PRESET_ADD - case FM_PRESET_ADD: - radio_add_preset(); - menu_draw(m); - key = BUTTON_NONE; - break; + if(TIME_AFTER(current_tick, timeout)) + { + timeout = current_tick + HZ; + update_screen = true; + } + if(!screen_freeze && update_screen) + { + fill_radio_info(&radio); + FOR_NB_SCREENS(i) + { + gui_wps_refresh(&gui_wps[i], 0, WPS_REFRESH_ALL); + update(&gui_wps[i]); + } + } + if(search_dir) + { + curr_freq += search_dir * FREQ_STEP; + if(curr_freq < MIN_FREQ) + curr_freq = MAX_FREQ; + if(curr_freq > MAX_FREQ) + curr_freq = MIN_FREQ; + + tuned = tune_freq(curr_freq); + + /* Stop searching if the tuning is close */ + if(tuned) + { + search_dir = 0; + curr_preset = find_preset(curr_freq); + remember_frequency(); + } + + update_screen = true; + } + else radio_status &= ~(FMRADIO_SCANFWD|FMRADIO_SCANBACK); + + button = button_get_w_tmo(HZ / PEAK_METER_FPS); + FOR_NB_SCREENS(i) + { + if(gui_wps[i].data->peak_meter_enabled) + gui_wps_refresh(&gui_wps[i], 0, + WPS_REFRESH_PEAK_METER); + } + if (button != BUTTON_NONE) + cpu_idle_mode(false); + switch(button) + { +#ifdef FM_RC_STOP + case FM_RC_STOP: #endif -#if (CONFIG_KEYPAD != IRIVER_H100_PAD) && (CONFIG_KEYPAD != IRIVER_H300_PAD) -#ifdef FM_PRESET - case FM_PRESET: - menu_draw(m); - key = MENU_EXIT; /* Fake an exit */ - break; + case FM_STOP: +#ifdef FM_STOP_PRE + if (lastbutton != FM_STOP_PRE) + break; #endif +#ifndef SIMULATOR + if(audio_status() == AUDIO_STATUS_RECORD) + { + audio_stop(); + } + else #endif -#ifdef FM_PRESET_ACTION - case FM_PRESET_ACTION: + { + done = true; + } + update_screen = true; + break; + +#ifdef FM_RECORD + case FM_RECORD: +#ifdef FM_RECORD_DBLPRE + if (lastbutton != FM_RECORD_DBLPRE) + { + rec_lastclick = 0; + break; + } + if (current_tick - rec_lastclick > HZ/2) + { + rec_lastclick = current_tick; + break; + } #endif -#ifdef MENU_ENTER2 - case MENU_ENTER2 | BUTTON_REPEAT: +#ifndef SIMULATOR + if(audio_status() == AUDIO_STATUS_RECORD) + { + audio_new_file(rec_create_filename(buf)); + update_screen = true; + } + else + { + have_recorded = true; + talk_buffer_steal(); /* we use the mp3 buffer */ + audio_record(rec_create_filename(buf)); + update_screen = true; + } #endif - case MENU_ENTER | BUTTON_REPEAT: /* long gives options */ - { - bool ret; - ret = handle_radio_presets_menu(); - menu_draw(m); - if(ret) - key = MENU_ATTACHED_USB; - else - key = BUTTON_NONE; - break; - } -#ifdef MENU_ENTER2 - case MENU_ENTER2 | BUTTON_REL: + break; +#endif /* #ifdef FM_RECORD */ + +#ifdef FM_RC_EXIT + case FM_RC_EXIT: #endif - case MENU_ENTER | BUTTON_REL: - key = MENU_ENTER; /* fake enter for short press */ - break; + case FM_EXIT: +#ifdef FM_EXIT_PRE + if(lastbutton != FM_EXIT_PRE +#ifdef FM_RC_EXIT_PRE + && lastbutton != FM_RC_EXIT_PRE +#endif + ) + break; +#endif +#ifndef SIMULATOR + if(audio_status() == AUDIO_STATUS_RECORD) + audio_stop(); +#endif + keep_playing = true; + done = true; + break; + +#ifdef BUTTON_RC_REW + case BUTTON_RC_REW: +#endif + case BUTTON_LEFT: + if(radio_mode == RADIO_SCAN_MODE) + { + curr_freq -= FREQ_STEP; + if(curr_freq < MIN_FREQ) + curr_freq = MAX_FREQ; + tune_freq(curr_freq); + curr_preset = find_preset(curr_freq); + remember_frequency(); + radio_status &= ~FMRADIO_SCANBACK; + } + else + next_preset(-1); + search_dir = 0; + update_screen = true; + break; -#ifdef MENU_ENTER2 - case MENU_ENTER2: +#ifdef BUTTON_RC_FF + case BUTTON_RC_FF: #endif - case MENU_ENTER: /* ignore down event */ - /* Ignore the release events */ -#ifdef FM_PRESET_ADD - case FM_PRESET_ADD | BUTTON_REL: + case BUTTON_RIGHT: + if(radio_mode == RADIO_SCAN_MODE) + { + curr_freq += FREQ_STEP; + if(curr_freq > MAX_FREQ) + curr_freq = MIN_FREQ; + tune_freq(curr_freq); + curr_preset = find_preset(curr_freq); + remember_frequency(); + radio_status &= ~FMRADIO_SCANFWD; + } + else + next_preset(1); + search_dir = 0; + update_screen = true; + break; + +#ifdef BUTTON_RC_REW + case BUTTON_RC_REW | BUTTON_REPEAT: +#endif + case BUTTON_LEFT | BUTTON_REPEAT: + if(radio_mode == RADIO_SCAN_MODE) + search_dir = -1; + radio_status |= FMRADIO_SCANBACK; + break; + +#ifdef BUTTON_RC_FF + case BUTTON_RC_FF | BUTTON_REPEAT: +#endif + case BUTTON_RIGHT | BUTTON_REPEAT: + if(radio_mode == RADIO_SCAN_MODE) + search_dir = 1; + radio_status |= FMRADIO_SCANFWD; + break; + +#ifdef BUTTON_RC_VOL_UP + case BUTTON_RC_VOL_UP: + case BUTTON_RC_VOL_UP | BUTTON_REPEAT: +#endif + case BUTTON_UP: + case BUTTON_UP | BUTTON_REPEAT: + global_settings.volume++; + if(global_settings.volume > sound_max(SOUND_VOLUME)) + global_settings.volume = sound_max(SOUND_VOLUME); + sound_set_volume(global_settings.volume); + update_screen = true; + settings_save(); + break; + +#ifdef BUTTON_RC_VOL_DOWN + case BUTTON_RC_VOL_DOWN: + case BUTTON_RC_VOL_DOWN | BUTTON_REPEAT: +#endif + case BUTTON_DOWN: + case BUTTON_DOWN | BUTTON_REPEAT: + global_settings.volume--; + if(global_settings.volume < sound_min(SOUND_VOLUME)) + global_settings.volume = sound_min(SOUND_VOLUME); + sound_set_volume(global_settings.volume); + update_screen = true; + settings_save(); + break; + +#ifdef FM_PLAY +#ifdef FM_RC_PLAY + case FM_RC_PLAY: +#endif + case FM_PLAY: +#ifdef FM_PLAY_PRE + if(lastbutton != FM_PLAY_PRE +#ifdef FM_RC_PLAY_PRE + && lastbutton != FM_RC_PLAY_PRE +#endif + ) + break; +#endif + radio_pause(radio_status == FMRADIO_PLAYING); + update_screen = true; + break; +#endif +#ifdef FM_MENU +#ifdef FM_RC_MENU + case FM_RC_MENU: +#endif + case FM_MENU: + radio_menu(); + curr_preset = find_preset(curr_freq); + FOR_NB_SCREENS(i){ + gui_textarea_clear(&screens[i]); + screen_set_xmargin(&screens[i],0); + } +#ifdef HAS_BUTTONBAR + gui_buttonbar_set(&buttonbar, str(LANG_BUTTONBAR_MENU), + str(LANG_FM_BUTTONBAR_PRESETS), + str(LANG_FM_BUTTONBAR_RECORD)); +#endif + update_screen = true; + break; +#endif + +#ifdef FM_RC_PRESET + case FM_RC_PRESET: +#endif +#ifdef FM_PRESET + case FM_PRESET: +#ifdef FM_PRESET_PRE + if(lastbutton != FM_PRESET_PRE +#ifdef FM_RC_PRESET_PRE + && lastbutton != FM_RC_PRESET_PRE +#endif + ) + break; +#endif + if(num_presets < 1){ + gui_syncsplash(HZ, true, str(LANG_FM_NO_PRESETS)); + update_screen = true; + break; + } + handle_radio_presets(); + curr_preset = find_preset(curr_freq); + FOR_NB_SCREENS(i){ + gui_textarea_clear(&screens[i]); + screen_set_xmargin(&screens[i],0); + } +#ifdef HAS_BUTTONBAR + gui_buttonbar_set(&buttonbar, + str(LANG_BUTTONBAR_MENU), + str(LANG_FM_BUTTONBAR_PRESETS), + str(LANG_FM_BUTTONBAR_RECORD)); +#endif + update_screen = true; + break; +#endif + +#ifdef FM_FREEZE + case FM_FREEZE: + if(!screen_freeze) + { + gui_syncsplash(HZ, true, str(LANG_FM_FREEZE)); + screen_freeze = true; + } + else + { + update_screen = true; + screen_freeze = false; + } + break; +#endif + case SYS_USB_CONNECTED: + /* Only accept USB connection when not recording */ + if(audio_status() != AUDIO_STATUS_RECORD) + { + default_event_handler(SYS_USB_CONNECTED); + screen_freeze = true; /* Cosmetic: makes sure the + radio screen doesn't redraw */ + done = true; + } + break; + +#ifdef FM_RC_MODE + case FM_RC_MODE: +#endif +#ifdef FM_MODE + case FM_MODE: + if(lastbutton != FM_MODE +#ifdef FM_RC_MODE + && lastbutton != FM_RC_MODE +#endif + ) + { + if(radio_mode == RADIO_SCAN_MODE) + radio_mode = RADIO_PRESET_MODE; + else + radio_mode = RADIO_SCAN_MODE; + update_screen = true; + } + break; #endif -#ifdef FM_PRESET_ACTION - case FM_PRESET_ACTION | BUTTON_REL: +#ifdef FM_NEXT_PRESET + case FM_NEXT_PRESET: + next_preset(1); + search_dir = 0; + update_screen = true; + break; #endif - key = BUTTON_NONE; - break; - } - return key; -} - -/* present a list of preset stations */ -bool handle_radio_presets(void) -{ - int result; - bool reload_dir = false; +#ifdef FM_PREV_PRESET + case FM_PREV_PRESET: + next_preset(-1); + search_dir = 0; + update_screen = true; + break; +#endif + default: + default_event_handler(button); + break; + } /* switch(button) */ - if(presets_loaded) - { - rebuild_preset_menu(); + if (button != BUTTON_NONE) + lastbutton = button; + else cpu_idle_mode(true); + + peak_meter_peek(); - /* DIY menu handling, since we want to exit after selection */ - preset_menu = menu_init( preset_menu_items, num_presets, - handle_radio_presets_cb, - str(LANG_FM_BUTTONBAR_ADD), - str(LANG_FM_BUTTONBAR_EXIT), - str(LANG_FM_BUTTONBAR_ACTION)); - if (curr_preset >= 0) - menu_set_cursor(preset_menu, curr_preset); - result = menu_show(preset_menu); - menu_exit(preset_menu); - if (result == MENU_SELECTED_EXIT) - return false; - else if (result == MENU_ATTACHED_USB) - reload_dir = true; - if (result >= 0) /* A preset was selected */ + + if(audio_status() & AUDIO_STATUS_ERROR) { - curr_preset = menu_cursor(preset_menu); - curr_freq = presets[curr_preset].frequency; - radio_set(RADIO_FREQUENCY, curr_freq); - remember_frequency(); + done = true; } - } - - return reload_dir; -} + +#ifdef HAS_BUTTONBAR + gui_buttonbar_draw(&buttonbar); +#endif + } /* while(!done) */ #ifndef SIMULATOR -#if CONFIG_CODEC != SWCODEC -static bool fm_recording_settings(void) -{ - bool ret; - - ret = recording_menu(true); - if(!ret) + if(audio_status() & AUDIO_STATUS_ERROR) { - if (global_settings.rec_prerecord_time) - talk_buffer_steal(); /* will use the mp3 buffer */ + gui_syncsplash(0, true, str(LANG_DISK_FULL)); + gui_syncstatusbar_draw(&statusbars,true); + FOR_NB_SCREENS(i) + gui_textarea_update(&screens[i]); + audio_error_clear(); - audio_set_recording_options(global_settings.rec_frequency, - global_settings.rec_quality, - 1, /* Line In */ - global_settings.rec_channels, - global_settings.rec_editable, - global_settings.rec_prerecord_time); + while(1) + { + button = button_get(true); + if(button == (BUTTON_OFF | BUTTON_REL)) + break; + } } - return ret; -} -#endif + +#if CONFIG_CODEC != SWCODEC + audio_init_playback(); #endif -char monomode_menu_string[32]; - -static void create_monomode_menu(void) -{ - snprintf(monomode_menu_string, sizeof monomode_menu_string, - "%s: %s", str(LANG_FM_MONO_MODE), - global_settings.fm_force_mono? - str(LANG_SET_BOOL_YES):str(LANG_SET_BOOL_NO)); -} - -static bool toggle_mono_mode(void) -{ - global_settings.fm_force_mono = !global_settings.fm_force_mono; - radio_set(RADIO_FORCE_MONO, global_settings.fm_force_mono); - settings_save(); - create_monomode_menu(); - return false; -} - -#ifndef FM_MODE -char radiomode_menu_string[32]; -static void create_radiomode_menu(void) -{ - snprintf(radiomode_menu_string, 32, "%s %s", str(LANG_FM_TUNE_MODE), - radio_mode ? str(LANG_RADIO_PRESET_MODE) : - str(LANG_RADIO_SCAN_MODE)); -} + sound_settings_apply(); -static bool toggle_radio_mode(void) -{ - radio_mode = (radio_mode == RADIO_SCAN_MODE) ? - RADIO_PRESET_MODE : RADIO_SCAN_MODE; - create_radiomode_menu(); - return false; -} + if(keep_playing) + { +#if CONFIG_CODEC != SWCODEC + /* Enable the Left and right A/D Converter */ + audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN), + sound_default(SOUND_RIGHT_GAIN), AUDIO_GAIN_LINEIN); + mas_codec_writereg(6, 0x4000); #endif - -static bool scan_presets(void) -{ - bool tuned = false; - char buf[27]; - int freq, i; - char *lines[]={str(LANG_FM_CLEAR_PRESETS)}; - struct text_message message={lines, 1}; - - if(gui_syncyesno_run(&message,NULL,NULL)==YESNO_YES){ - FOR_NB_SCREENS(i) - gui_textarea_clear(&screens[i]); - curr_freq = MIN_FREQ; - num_presets = 0; - while(curr_freq <= MAX_FREQ){ - if (num_presets >= MAX_PRESETS) - break; - - freq = curr_freq /100000; - snprintf(buf, 27, str(LANG_FM_SCANNING), freq/10, freq % 10); - gui_syncsplash(0, true, buf); - - /* Tune in and delay */ - radio_set(RADIO_FREQUENCY, curr_freq); - sleep(1); - - /* Start IF measurement */ - radio_set(RADIO_IF_MEASUREMENT, 1); - sleep(1); - - /* Now check how close to the IF frequency we are */ - tuned = radio_get(RADIO_TUNED); - - /* add preset */ - if(tuned){ - snprintf(buf, 27, str(LANG_FM_DEFAULT_PRESET_NAME),freq/10, freq % 10); - strcpy(presets[num_presets].name,buf); - presets[num_presets].frequency = curr_freq; - num_presets++; - } - - curr_freq += FREQ_STEP; - - } - - radio_save_presets(); - - if(num_presets > 0 ){ - curr_freq = presets[0].frequency; - radio_set(RADIO_FREQUENCY, curr_freq); - remember_frequency(); - radio_mode = RADIO_PRESET_MODE; - } } - return true; -} - -/* button preprocessor for the main menu */ -int radio_menu_cb(int key, int m) -{ - (void)m; - switch(key) + else { -#if (CONFIG_KEYPAD != IRIVER_H100_PAD) && (CONFIG_KEYPAD != IRIVER_H300_PAD) -#ifdef MENU_ENTER2 - case MENU_ENTER2: -#endif -#endif - case MENU_ENTER: - key = BUTTON_NONE; /* eat the downpress, next menu reacts on release */ - break; - -#if (CONFIG_KEYPAD != IRIVER_H100_PAD) && (CONFIG_KEYPAD != IRIVER_H300_PAD) -#ifdef MENU_ENTER2 - case MENU_ENTER2 | BUTTON_REL: -#endif + radio_stop(); +#if CONFIG_CODEC == SWCODEC + pcm_rec_mux(0); /* Line In */ #endif - case MENU_ENTER | BUTTON_REL: - key = MENU_ENTER; /* fake downpress, next menu doesn't like release */ - break; } - return key; -} - -/* main menu of the radio screen */ -bool radio_menu(void) -{ - int m; - bool result; - - static const struct menu_item items[] = { -/* Add functions not accessible via buttons */ -#ifndef FM_PRESET - { ID2P(LANG_FM_BUTTONBAR_PRESETS), handle_radio_presets }, -#endif -#ifndef FM_PRESET_ADD - { ID2P(LANG_FM_ADD_PRESET) , radio_add_preset }, -#endif - { monomode_menu_string , toggle_mono_mode }, -#ifndef FM_MODE - { radiomode_menu_string , toggle_radio_mode }, -#endif - { ID2P(LANG_SOUND_SETTINGS) , sound_menu }, -#if !defined(SIMULATOR) && (CONFIG_CODEC != SWCODEC) - { ID2P(LANG_RECORDING_SETTINGS) , fm_recording_settings}, -#endif - { ID2P(LANG_FM_SCAN_PRESETS) , scan_presets }, - }; - - create_monomode_menu(); -#ifndef FM_MODE - create_radiomode_menu(); #endif - m = menu_init(items, sizeof(items) / sizeof(*items), - radio_menu_cb, NULL, NULL, NULL); - result = menu_run(m); - menu_exit(m); - return result; + + cpu_idle_mode(false); + + return have_recorded; } + #endif Index: apps/recorder/radio.h =================================================================== RCS file: /cvsroot/rockbox/apps/recorder/radio.h,v retrieving revision 1.7 diff -u -r1.7 radio.h --- apps/recorder/radio.h 19 Nov 2005 19:23:43 -0000 1.7 +++ apps/recorder/radio.h 15 Feb 2006 11:41:23 -0000 @@ -17,11 +17,111 @@ * ****************************************************************************/ #ifndef RADIO_H -#define RADIO_H +#define RADIO_H + +#include "config.h" +#include +#include +#include "sprintf.h" +#include "mas.h" +#include "settings.h" +#include "button.h" +#include "fmradio.h" +#include "status.h" +#include "kernel.h" +#include "mpeg.h" +#include "audio.h" +#include "mp3_playback.h" +#include "ctype.h" +#include "file.h" +#include "errno.h" +#include "atoi.h" +#include "string.h" +#include "system.h" +#include "radio.h" +#include "menu.h" +#include "misc.h" +#include "keyboard.h" +#include "screens.h" +#include "peakmeter.h" +#include "font.h" +#include "sound_menu.h" +#include "recording.h" +#include "talk.h" +#include "tuner.h" +#include "hwcompat.h" +#include "power.h" +#include "sound.h" +#include "screen_access.h" +#include "statusbar.h" +#include "textarea.h" +#include "splash.h" +#include "yesno.h" +#include "buttonbar.h" +#include "power.h" #define FMRADIO_OFF 0 #define FMRADIO_PLAYING 1 -#define FMRADIO_PAUSED 2 +#define FMRADIO_PAUSED 2 +#define FMRADIO_SCANFWD 4 +#define FMRADIO_SCANBACK 8 + +#define MAX_FREQ (108000000) +#define MIN_FREQ (87500000) +#define FREQ_STEP 100000 + +#define RADIO_SCAN_MODE 0 +#define RADIO_PRESET_MODE 1 + +#if CONFIG_KEYPAD == RECORDER_PAD +#define FM_MENU BUTTON_F1 +#define FM_PRESET BUTTON_F2 +#define FM_RECORD BUTTON_F3 +#define FM_FREEZE BUTTON_PLAY +#define FM_STOP BUTTON_OFF +#define FM_MODE (BUTTON_ON | BUTTON_REPEAT) +#define FM_EXIT_PRE BUTTON_ON +#define FM_EXIT (BUTTON_ON | BUTTON_REL) +#define FM_PRESET_ADD BUTTON_F1 +#define FM_PRESET_ACTION BUTTON_F3 + +#elif (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD) +/* pause/play - short PLAY */ +#define FM_PLAY_PRE BUTTON_ON +#define FM_RC_PLAY_PRE BUTTON_RC_ON +#define FM_PLAY (BUTTON_ON | BUTTON_REL) +#define FM_RC_PLAY (BUTTON_RC_ON | BUTTON_REL) +/* preset/scan mode - long PLAY */ +#define FM_MODE (BUTTON_ON | BUTTON_REPEAT) +#define FM_RC_MODE (BUTTON_RC_ON | BUTTON_REPEAT) +/* preset menu - short SELECT */ +#define FM_PRESET_PRE BUTTON_SELECT +#define FM_RC_PRESET_PRE BUTTON_RC_MENU +#define FM_PRESET (BUTTON_SELECT | BUTTON_REL) +#define FM_RC_PRESET (BUTTON_RC_MENU | BUTTON_REL) +/* fm menu - long SELECT */ +#define FM_MENU (BUTTON_SELECT | BUTTON_REPEAT) +#define FM_RC_MENU (BUTTON_RC_MENU | BUTTON_REPEAT) +/* main menu(exit radio while playing) - A-B */ +#define FM_EXIT_PRE BUTTON_MODE +#define FM_EXIT (BUTTON_MODE | BUTTON_REL) +#define FM_RC_EXIT_PRE BUTTON_RC_MODE +#define FM_RC_EXIT (BUTTON_RC_MODE | BUTTON_REL) +/* prev/next preset on the remote - BITRATE/SOURCE */ +#define FM_NEXT_PRESET (BUTTON_RC_BITRATE | BUTTON_REL) +#define FM_PREV_PRESET (BUTTON_RC_SOURCE | BUTTON_REL) +/* stop and exit radio - STOP */ +#define FM_STOP BUTTON_OFF +#define FM_RC_STOP BUTTON_RC_STOP + +#elif CONFIG_KEYPAD == ONDIO_PAD /* restricted keypad */ +#define FM_MENU (BUTTON_MENU | BUTTON_REPEAT) +#define FM_RECORD_DBLPRE BUTTON_MENU +#define FM_RECORD (BUTTON_MENU | BUTTON_REL) +#define FM_STOP_PRE BUTTON_OFF +#define FM_STOP (BUTTON_OFF | BUTTON_REL) +#define FM_EXIT (BUTTON_OFF | BUTTON_REPEAT) +#endif #ifdef CONFIG_TUNER void radio_init(void); @@ -29,13 +129,42 @@ void radio_stop(void); bool radio_hardware_present(void); int get_radio_status(void); - + +#define MAX_PRESETS 64 struct fmstation { int frequency; /* In Hz */ char name[28]; +}; +struct radioinfo +{ + int frequency; + char* radio_mode; + int radio_status; + bool tuned; + bool stereo; + int min_freq; + int max_freq; + + struct fmstation preset_info; + int preset_num; + bool using_preset; }; +/****************** functions *****************/ +void draw_radio(int update_screen); + + +void radio_start(void); +void radio_pause(bool yes); /* yes=1 pause, yes=0 unpause */ + +int get_radio_status(void); +int get_radio_mode(void); +bool is_radio_tuned(void); +int get_freq(void); +bool is_radio_stereo(void); +int get_preset(struct fmstation *preset); /* gets the current preset and puts it in preset */ + +bool tune_freq(int freq); /* returns true if the radio is tuned ok, the freq will be set regardless */ +#endif /* CONFIG_TUNER */ -#endif - -#endif +#endif /* RADIO_H */