void radio_start(void) { const struct fm_region_data *fmr; bool start_paused; if(radio_status == FMRADIO_PLAYING) return; fmr = &fm_region_data[global_settings.fm_region]; start_paused = radio_status & FMRADIO_START_PAUSED; /* clear flag before any yielding */ radio_status &= ~FMRADIO_START_PAUSED; if(radio_status == FMRADIO_OFF) tuner_power(true); curr_freq = global_status.last_frequency * fmr->freq_step + fmr->freq_min; tuner_set(RADIO_SLEEP, 0); /* wake up the tuner */ if(radio_status == FMRADIO_OFF) { #ifdef HAVE_RADIO_REGION tuner_set(RADIO_REGION, global_settings.fm_region); #endif tuner_set(RADIO_FORCE_MONO, global_settings.fm_force_mono); } tuner_set(RADIO_FREQUENCY, curr_freq); #ifdef HAVE_RADIO_MUTE_TIMEOUT { unsigned long mute_timeout = current_tick + HZ; if (radio_status != FMRADIO_OFF) { /* paused */ mute_timeout += HZ; } while(!tuner_get(RADIO_STEREO) && !tuner_get(RADIO_TUNED)) { if(TIME_AFTER(current_tick, mute_timeout)) break; yield(); } } #endif /* keep radio from sounding initially */ if(!start_paused) tuner_set(RADIO_MUTE, 0); radio_status = FMRADIO_PLAYING; } /* radio_start */
void radio_screen(void) { bool done = false; int button; bool stereo = false, last_stereo = false; int update_type = 0; bool screen_freeze = false; bool keep_playing = false; bool talk = false; #ifdef FM_RECORD_DBLPRE int lastbutton = BUTTON_NONE; unsigned long rec_lastclick = 0; #endif #if CONFIG_CODEC != SWCODEC int timeout = current_tick + HZ/10; #if !defined(SIMULATOR) unsigned int last_seconds = 0; unsigned int seconds = 0; struct audio_recording_options rec_options; #endif /* SIMULATOR */ #endif /* CONFIG_CODEC != SWCODEC */ #ifndef HAVE_NOISY_IDLE_MODE int button_timeout = current_tick + (2*HZ); #endif /* change status to "in screen" */ push_current_activity(ACTIVITY_FM); in_screen = true; if(radio_preset_count() <= 0) { radio_load_presets(global_settings.fmr_file); } skin_get_global_state()->id3 = NULL; #ifdef HAVE_ALBUMART radioart_init(true); #endif if(radio_status == FMRADIO_OFF) audio_stop(); fms_fix_displays(FMS_ENTER); #ifndef SIMULATOR #if CONFIG_CODEC != SWCODEC rec_create_directory(); audio_init_recording(); sound_settings_apply(); /* Yes, we use the D/A for monitoring */ peak_meter_playback(true); peak_meter_enable(true); rec_init_recording_options(&rec_options); rec_options.rec_source = AUDIO_SRC_LINEIN; rec_set_recording_options(&rec_options); audio_set_recording_gain(sound_default(SOUND_LEFT_GAIN), sound_default(SOUND_RIGHT_GAIN), AUDIO_GAIN_LINEIN); #endif /* CONFIG_CODEC != SWCODEC */ #endif /* ndef SIMULATOR */ /* turn on radio */ #if CONFIG_CODEC == SWCODEC /* This should be done before touching audio settings */ while (!pcm_is_initialized()) sleep(0); audio_set_input_source(AUDIO_SRC_FMRADIO, (radio_status == FMRADIO_PAUSED) ? SRCF_FMRADIO_PAUSED : SRCF_FMRADIO_PLAYING); #else if (radio_status == FMRADIO_OFF) radio_start(); #endif if(radio_preset_count() < 1 && yesno_pop(ID2P(LANG_FM_FIRST_AUTOSCAN))) presets_scan(NULL); preset_set_current(preset_find(curr_freq)); if(radio_current_preset() != -1) radio_mode = RADIO_PRESET_MODE; /* Load/update the skin at last, when fully initialzed, so that it can * display the right content from the beginning */ FOR_NB_SCREENS(i) skin_update(FM_SCREEN, i, SKIN_REFRESH_ALL); #ifndef HAVE_NOISY_IDLE_MODE cpu_idle_mode(true); #endif while(!done) { if(search_dir != 0) { curr_freq = step_freq(curr_freq, search_dir); update_type = SKIN_REFRESH_ALL; if(tuner_set(RADIO_SCAN_FREQUENCY, curr_freq)) { preset_set_current(preset_find(curr_freq)); remember_frequency(); end_search(); talk = true; } trigger_cpu_boost(); } if (!update_type) { cancel_cpu_boost(); } button = fms_do_button_loop(update_type>0); #ifndef HAVE_NOISY_IDLE_MODE if (button != ACTION_NONE) { cpu_idle_mode(false); button_timeout = current_tick + (2*HZ); } #endif switch(button) { case ACTION_FM_STOP: #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR) if(audio_status() == AUDIO_STATUS_RECORD) { audio_stop(); } else #endif { done = true; if(presets_have_changed()) { if(yesno_pop(ID2P(LANG_SAVE_CHANGES))) { presets_save(); } } } update_type = SKIN_REFRESH_NON_STATIC; break; #ifdef FM_RECORD case ACTION_FM_RECORD: #ifdef FM_RECORD_DBLPRE if (lastbutton != ACTION_FM_RECORD_DBLPRE) { rec_lastclick = 0; break; } if (current_tick - rec_lastclick > HZ/2) { rec_lastclick = current_tick; break; } #endif /* FM_RECORD_DBLPRE */ #ifndef SIMULATOR if(audio_status() == AUDIO_STATUS_RECORD) { rec_command(RECORDING_CMD_START_NEWFILE); update_type = SKIN_REFRESH_ALL; } else { rec_command(RECORDING_CMD_START); update_type = SKIN_REFRESH_ALL; } #if CONFIG_CODEC != SWCODEC last_seconds = 0; #endif #endif /* SIMULATOR */ break; #endif /* #ifdef FM_RECORD */ case ACTION_FM_EXIT: #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR) if(audio_status() == AUDIO_STATUS_RECORD) audio_stop(); #endif keep_playing = true; done = true; if(presets_have_changed()) { if(yesno_pop(ID2P(LANG_SAVE_CHANGES))) { presets_save(); } } break; case ACTION_STD_PREV: case ACTION_STD_NEXT: next_station(button == ACTION_STD_PREV ? -1 : 1); end_search(); update_type = SKIN_REFRESH_ALL; talk = true; break; case ACTION_STD_PREVREPEAT: case ACTION_STD_NEXTREPEAT: { int dir = search_dir; search_dir = button == ACTION_STD_PREVREPEAT ? -1 : 1; if (radio_mode != RADIO_SCAN_MODE) { preset_next(search_dir); end_search(); talk = true; } else if (dir == 0) { /* Starting auto scan */ tuner_set(RADIO_MUTE, 1); } update_type = SKIN_REFRESH_ALL; break; } case ACTION_SETTINGS_INC: case ACTION_SETTINGS_INCREPEAT: global_settings.volume++; setvol(); update_type = SKIN_REFRESH_NON_STATIC; break; case ACTION_SETTINGS_DEC: case ACTION_SETTINGS_DECREPEAT: global_settings.volume--; setvol(); update_type = SKIN_REFRESH_NON_STATIC; break; case ACTION_FM_PLAY: if (radio_status == FMRADIO_PLAYING) radio_pause(); else radio_start(); update_type = SKIN_REFRESH_NON_STATIC; talk = false; talk_shutup(); break; case ACTION_FM_MENU: fms_fix_displays(FMS_EXIT); do_menu(&radio_settings_menu, NULL, NULL, false); preset_set_current(preset_find(curr_freq)); fms_fix_displays(FMS_ENTER); update_type = SKIN_REFRESH_ALL; break; #ifdef FM_PRESET case ACTION_FM_PRESET: if(radio_preset_count() < 1) { splash(HZ, ID2P(LANG_FM_NO_PRESETS)); update_type = SKIN_REFRESH_ALL; break; } fms_fix_displays(FMS_EXIT); handle_radio_presets(); fms_fix_displays(FMS_ENTER); update_type = SKIN_REFRESH_ALL; break; #endif /* FM_PRESET */ #ifdef FM_FREEZE case ACTION_FM_FREEZE: if(!screen_freeze) { splash(HZ, str(LANG_FM_FREEZE)); screen_freeze = true; } else { update_type = SKIN_REFRESH_ALL; screen_freeze = false; } break; #endif /* FM_FREEZE */ case SYS_USB_CONNECTED: #if CONFIG_CODEC != SWCODEC /* Only accept USB connection when not recording */ if(audio_status() != AUDIO_STATUS_RECORD) #endif { default_event_handler(SYS_USB_CONNECTED); screen_freeze = true; /* Cosmetic: makes sure the radio screen doesn't redraw */ done = true; } break; #ifdef FM_MODE case ACTION_FM_MODE: if(radio_mode == RADIO_SCAN_MODE) { /* Force scan mode if there are no presets. */ if(radio_preset_count() > 0) radio_mode = RADIO_PRESET_MODE; } else radio_mode = RADIO_SCAN_MODE; update_type = SKIN_REFRESH_ALL; cond_talk_ids_fq(radio_mode ? LANG_PRESET : LANG_RADIO_SCAN_MODE); talk = true; break; #endif /* FM_MODE */ #ifdef FM_NEXT_PRESET case ACTION_FM_NEXT_PRESET: preset_next(1); end_search(); update_type = SKIN_REFRESH_ALL; talk = true; break; #endif #ifdef FM_PREV_PRESET case ACTION_FM_PREV_PRESET: preset_next(-1); end_search(); update_type = SKIN_REFRESH_ALL; talk = true; break; #endif case ACTION_NONE: update_type = SKIN_REFRESH_NON_STATIC; break; /* this case is used by the softlock feature * it requests a full update here */ case ACTION_REDRAW: skin_request_full_update(FM_SCREEN); break; default: default_event_handler(button); #ifdef HAVE_RDS_CAP if (tuner_get(RADIO_EVENT)) update_type = SKIN_REFRESH_ALL; #endif if (!tuner_get(RADIO_PRESENT)) { #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR) if(audio_status() == AUDIO_STATUS_RECORD) audio_stop(); #endif keep_playing = false; done = true; if(presets_have_changed()) { if(yesno_pop(ID2P(LANG_SAVE_CHANGES))) { radio_save_presets(); } } /* Clear the preset list on exit. */ preset_list_clear(); } break; } /*switch(button)*/ #ifdef FM_RECORD_DBLPRE if (button != ACTION_NONE) lastbutton = button; #endif #if CONFIG_CODEC != SWCODEC peak_meter_peek(); #endif if(!screen_freeze) { /* Only display the peak meter when not recording */ #if CONFIG_CODEC != SWCODEC if(TIME_AFTER(current_tick, timeout)) { timeout = current_tick + HZ; #else /* SWCODEC */ { #endif /* CONFIG_CODEC == SWCODEC */ /* keep "mono" from always being displayed when paused */ if (radio_status != FMRADIO_PAUSED) { stereo = tuner_get(RADIO_STEREO) && !global_settings.fm_force_mono; if(stereo != last_stereo) { update_type = SKIN_REFRESH_ALL; last_stereo = stereo; } } } #if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR) seconds = audio_recorded_time() / HZ; if (update_type || seconds > last_seconds) { last_seconds = seconds; #else if (update_type) { #endif FOR_NB_SCREENS(i) skin_update(FM_SCREEN, i, update_type); if (update_type == (int)SKIN_REFRESH_ALL) skin_request_full_update(CUSTOM_STATUSBAR); } } update_type = 0; if (global_settings.talk_file && talk && radio_status == FMRADIO_PAUSED) { talk = false; bool enqueue = false; if (radio_mode == RADIO_SCAN_MODE) { talk_value_decimal(curr_freq, UNIT_INT, 6, enqueue); enqueue = true; } if (radio_current_preset() >= 0) preset_talk(radio_current_preset(), radio_mode == RADIO_PRESET_MODE, enqueue); } #if CONFIG_CODEC != SWCODEC if(audio_status() & AUDIO_STATUS_ERROR) { done = true; } #endif #ifndef HAVE_NOISY_IDLE_MODE if (TIME_AFTER(current_tick, button_timeout)) { cpu_idle_mode(true); } #endif } /*while(!done)*/ #ifndef SIMULATOR #if CONFIG_CODEC != SWCODEC if(audio_status() & AUDIO_STATUS_ERROR) { splash(0, str(LANG_DISK_FULL)); audio_error_clear(); while(1) { button = get_action(CONTEXT_FM|ALLOW_SOFTLOCK, TIMEOUT_BLOCK); if(button == ACTION_FM_STOP) break; } } audio_init_playback(); #endif /* CONFIG_CODEC != SWCODEC */ sound_settings_apply(); #endif /* SIMULATOR */ if(keep_playing) { /* Catch FMRADIO_PLAYING status for the sim. */ #ifndef SIMULATOR #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 end_search(); #endif /* SIMULATOR */ } else { #if CONFIG_CODEC == SWCODEC audio_set_input_source(AUDIO_SRC_PLAYBACK, SRCF_PLAYBACK); #else radio_stop(); #endif } #ifndef HAVE_NOISY_IDLE_MODE cpu_idle_mode(false); #endif fms_fix_displays(FMS_EXIT); pop_current_activity(); in_screen = false; } /* radio_screen */ void toggle_mono_mode(bool mono) { tuner_set(RADIO_FORCE_MONO, mono); } void set_radio_region(int region) { #ifdef HAVE_RADIO_REGION tuner_set(RADIO_REGION, region); #endif next_station(0); remember_frequency(); (void)region; }
bool radio_hardware_present(void) { return tuner_get(RADIO_PRESENT); }
bool radio_is_stereo(void) { return tuner_get(RADIO_STEREO) && !global_settings.fm_force_mono; }
void draw_progressbar(struct gui_wps *gwps, int line, struct progressbar *pb) { struct screen *display = gwps->display; struct viewport *vp = pb->vp; struct wps_state *state = skin_get_global_state(); struct mp3entry *id3 = state->id3; int x = pb->x, y = pb->y, width = pb->width, height = pb->height; unsigned long length, end; int flags = HORIZONTAL; if (height < 0) height = font_get(vp->font)->height; if (y < 0) { int line_height = font_get(vp->font)->height; /* center the pb in the line, but only if the line is higher than the pb */ int center = (line_height-height)/2; /* if Y was not set calculate by font height,Y is -line_number-1 */ y = line*line_height + (0 > center ? 0 : center); } if (pb->type == SKIN_TOKEN_VOLUMEBAR) { int minvol = sound_min(SOUND_VOLUME); int maxvol = sound_max(SOUND_VOLUME); length = maxvol-minvol; end = global_settings.volume-minvol; } else if (pb->type == SKIN_TOKEN_BATTERY_PERCENTBAR) { length = 100; end = battery_level(); } else if (pb->type == SKIN_TOKEN_PEAKMETER_LEFTBAR || pb->type == SKIN_TOKEN_PEAKMETER_RIGHTBAR) { int left, right, val; peak_meter_current_vals(&left, &right); val = pb->type == SKIN_TOKEN_PEAKMETER_LEFTBAR ? left : right; length = MAX_PEAK; end = peak_meter_scale_value(val, length); } #if CONFIG_TUNER else if (in_radio_screen() || (get_radio_status() != FMRADIO_OFF)) { #ifdef HAVE_RADIO_RSSI if (pb->type == SKIN_TOKEN_TUNER_RSSI_BAR) { int val = tuner_get(RADIO_RSSI); int min = tuner_get(RADIO_RSSI_MIN); int max = tuner_get(RADIO_RSSI_MAX); end = val - min; length = max - min; } else #endif { int min = fm_region_data[global_settings.fm_region].freq_min; end = radio_current_frequency() - min; length = fm_region_data[global_settings.fm_region].freq_max - min; } } #endif else if (id3 && id3->length) { length = id3->length; end = id3->elapsed + state->ff_rewind_count; } else { length = 1; end = 0; } if (!pb->horizontal) { /* we want to fill upwards which is technically inverted. */ flags = INVERTFILL; } if (pb->invert_fill_direction) { flags ^= INVERTFILL; } if (pb->nofill) { flags |= INNER_NOFILL; } if (pb->slider) { struct gui_img *img = pb->slider; /* clear the slider */ screen_clear_area(display, x, y, width, height); /* shrink the bar so the slider is inside bounds */ if (flags&HORIZONTAL) { width -= img->bm.width; x += img->bm.width / 2; } else { height -= img->bm.height; y += img->bm.height / 2; } } if (pb->backdrop) { struct gui_img *img = pb->backdrop; #if LCD_DEPTH > 1 if(img->bm.format == FORMAT_MONO) { #endif display->mono_bitmap_part(img->bm.data, 0, 0, img->bm.width, x, y, width, height); #if LCD_DEPTH > 1 } else { display->transparent_bitmap_part((fb_data *)img->bm.data, 0, 0, STRIDE(display->screen_type, img->bm.width, img->bm.height), x, y, width, height); } #endif flags |= DONT_CLEAR_EXCESS; } if (!pb->nobar) { if (pb->image) gui_bitmap_scrollbar_draw(display, &pb->image->bm, x, y, width, height, length, 0, end, flags); else gui_scrollbar_draw(display, x, y, width, height, length, 0, end, flags); } if (pb->slider) { int xoff = 0, yoff = 0; int w = width, h = height; struct gui_img *img = pb->slider; if (flags&HORIZONTAL) { w = img->bm.width; xoff = width * end / length; if (flags&INVERTFILL) xoff = width - xoff; xoff -= w / 2; } else { h = img->bm.height; yoff = height * end / length; if (flags&INVERTFILL) yoff = height - yoff; yoff -= h / 2; } #if LCD_DEPTH > 1 if(img->bm.format == FORMAT_MONO) { #endif display->mono_bitmap_part(img->bm.data, 0, 0, img->bm.width, x + xoff, y + yoff, w, h); #if LCD_DEPTH > 1 } else { display->transparent_bitmap_part((fb_data *)img->bm.data, 0, 0, STRIDE(display->screen_type, img->bm.width, img->bm.height), x + xoff, y + yoff, w, h); } #endif } if (pb->type == SKIN_TOKEN_PROGRESSBAR) { if (id3 && id3->length) { #ifdef AB_REPEAT_ENABLE if (ab_repeat_mode_enabled()) ab_draw_markers(display, id3->length, x, y, width, height); #endif if (id3->cuesheet) cue_draw_markers(display, id3->cuesheet, id3->length, x, y+1, width, height-2); } #if 0 /* disable for now CONFIG_TUNER */ else if (in_radio_screen() || (get_radio_status() != FMRADIO_OFF)) { presets_draw_markers(display, x, y, width, height); } #endif } }
void draw_progressbar(struct gui_wps *gwps, int line, struct progressbar *pb) { struct screen *display = gwps->display; struct viewport *vp = SKINOFFSETTOPTR(get_skin_buffer(gwps->data), pb->vp); struct wps_state *state = skin_get_global_state(); struct mp3entry *id3 = state->id3; int x = pb->x, y = pb->y, width = pb->width, height = pb->height; unsigned long length, end; int flags = HORIZONTAL; if (height < 0) height = font_get(vp->font)->height; if (y < 0) { int line_height = font_get(vp->font)->height; /* center the pb in the line, but only if the line is higher than the pb */ int center = (line_height-height)/2; /* if Y was not set calculate by font height,Y is -line_number-1 */ y = line*line_height + (0 > center ? 0 : center); } if (pb->type == SKIN_TOKEN_VOLUMEBAR) { int minvol = sound_min(SOUND_VOLUME); int maxvol = sound_max(SOUND_VOLUME); length = maxvol-minvol; end = global_settings.volume-minvol; } else if (pb->type == SKIN_TOKEN_BATTERY_PERCENTBAR) { length = 100; end = battery_level(); } else if (pb->type == SKIN_TOKEN_PEAKMETER_LEFTBAR || pb->type == SKIN_TOKEN_PEAKMETER_RIGHTBAR) { int left, right, val; peak_meter_current_vals(&left, &right); val = pb->type == SKIN_TOKEN_PEAKMETER_LEFTBAR ? left : right; length = MAX_PEAK; end = peak_meter_scale_value(val, length); } else if (pb->type == SKIN_TOKEN_LIST_SCROLLBAR) { int val, min, max; skinlist_get_scrollbar(&val, &min, &max); end = val - min; length = max - min; } else if (pb->type == SKIN_TOKEN_SETTINGBAR) { int val, count; get_setting_info_for_bar(pb->setting_id, &count, &val); length = count - 1; end = val; } #if CONFIG_TUNER else if (in_radio_screen() || (get_radio_status() != FMRADIO_OFF)) { #ifdef HAVE_RADIO_RSSI if (pb->type == SKIN_TOKEN_TUNER_RSSI_BAR) { int val = tuner_get(RADIO_RSSI); int min = tuner_get(RADIO_RSSI_MIN); int max = tuner_get(RADIO_RSSI_MAX); end = val - min; length = max - min; } else #endif { int min = fm_region_data[global_settings.fm_region].freq_min; end = radio_current_frequency() - min; length = fm_region_data[global_settings.fm_region].freq_max - min; } } #endif else if (id3 && id3->length) { length = id3->length; end = id3->elapsed + state->ff_rewind_count; } else { length = 1; end = 0; } if (!pb->horizontal) { /* we want to fill upwards which is technically inverted. */ flags = INVERTFILL; } if (pb->invert_fill_direction) { flags ^= INVERTFILL; } if (pb->nofill) { flags |= INNER_NOFILL; } if (SKINOFFSETTOPTR(get_skin_buffer(gwps->data), pb->slider)) { struct gui_img *img = SKINOFFSETTOPTR(get_skin_buffer(gwps->data), pb->slider); /* clear the slider */ screen_clear_area(display, x, y, width, height); /* account for the sliders width in the progressbar */ if (flags&HORIZONTAL) { width -= img->bm.width; } else { height -= img->bm.height; } } if (SKINOFFSETTOPTR(get_skin_buffer(gwps->data), pb->backdrop)) { struct gui_img *img = SKINOFFSETTOPTR(get_skin_buffer(gwps->data), pb->backdrop); img->bm.data = core_get_data(img->buflib_handle); display->bmp_part(&img->bm, 0, 0, x, y, pb->width, height); flags |= DONT_CLEAR_EXCESS; } if (!pb->nobar) { struct gui_img *img = SKINOFFSETTOPTR(get_skin_buffer(gwps->data), pb->image); if (img) { char *img_data = core_get_data(img->buflib_handle); img->bm.data = img_data; gui_bitmap_scrollbar_draw(display, &img->bm, x, y, width, height, length, 0, end, flags); } else gui_scrollbar_draw(display, x, y, width, height, length, 0, end, flags); } if (SKINOFFSETTOPTR(get_skin_buffer(gwps->data), pb->slider)) { int xoff = 0, yoff = 0; int w = width, h = height; struct gui_img *img = SKINOFFSETTOPTR(get_skin_buffer(gwps->data), pb->slider); img->bm.data = core_get_data(img->buflib_handle); if (flags&HORIZONTAL) { w = img->bm.width; xoff = width * end / length; if (flags&INVERTFILL) xoff = width - xoff; } else { h = img->bm.height; yoff = height * end / length; if (flags&INVERTFILL) yoff = height - yoff; } display->bmp_part(&img->bm, 0, 0, x + xoff, y + yoff, w, h); } if (pb->type == SKIN_TOKEN_PROGRESSBAR) { if (id3 && id3->length) { #ifdef AB_REPEAT_ENABLE if (ab_repeat_mode_enabled()) ab_draw_markers(display, id3->length, x, y, width, height); #endif if (id3->cuesheet) cue_draw_markers(display, id3->cuesheet, id3->length, x, y+1, width, height-2); } #if 0 /* disable for now CONFIG_TUNER */ else if (in_radio_screen() || (get_radio_status() != FMRADIO_OFF)) { presets_draw_markers(display, x, y, width, height); } #endif } }