Index: tools/checkwps/checkwps.c =================================================================== --- tools/checkwps/checkwps.c (revision 24553) +++ tools/checkwps/checkwps.c (working copy) @@ -236,6 +236,13 @@ } #endif +#if CONFIG_TUNER +bool radio_hardware_present(void) +{ + return true; +} +#endif + int main(int argc, char **argv) { int res; Index: apps/recorder/radio.c =================================================================== --- apps/recorder/radio.c (revision 24553) +++ apps/recorder/radio.c (working copy) @@ -67,6 +67,8 @@ #include "menus/exported_menus.h" #include "root_menu.h" #include "viewport.h" +#include "skin_engine/skin_engine.h" +#include "statusbar-skinned.h" #if CONFIG_TUNER @@ -157,6 +159,32 @@ static int scan_presets(void *viewports); +bool radio_scan_mode(void) +{ + return radio_mode == RADIO_SCAN_MODE; +} + +bool radio_is_stereo(void) +{ + return tuner_get(RADIO_STEREO) && !global_settings.fm_force_mono; +} +int radio_current_frequency(void) +{ + return curr_freq; +} + +int radio_current_preset(void) +{ + return curr_preset; +} +int radio_preset_count(void) +{ + return num_presets; +} +const struct fmstation *radio_get_preset(int preset) +{ + return &presets[preset]; +} /* Function to manipulate all yesno dialogues. This function needs the output text as an argument. */ static bool yesno_pop(const char* text) @@ -464,17 +492,87 @@ } } +/* Skin stuff */ +extern struct wps_state wps_state; /* from wps.c */ +static struct gui_wps fms_skin[NB_SCREENS] = {{ .data = NULL }}; +static struct wps_data fms_skin_data[NB_SCREENS] = {{ .wps_loaded = 0 }}; +static struct wps_sync_data fms_skin_sync_data = { .do_full_update = false }; + + +void fms_data_load(enum screen_type screen, const char *buf, bool isfile) +{ + struct wps_data *data = fms_skin[screen].data; + int success; + success = buf && skin_data_load(screen, data, buf, isfile); + + if (!success ) /* load the default */ + { + const char default_fms[] = "%Sx|Station:| %tf\n" + "%?ts<%Sx|Stereo||%Sx|Mono|>\n" + "%?tm<%Sx|Mode:| %Sx|Scan||%Sx|Preset|: %Ti. %?Tn0<%Tn0|%Tf0>>\n" + "%pb\n" +#if CONFIG_CODEC != SWCODEC && !defined(SIMULATOR) + "%?Rr<%Sx|Time:| %Rh:%Rn:%Rs|" + "%?St|prerecording time|<%Sx|Prerecord Time| %Rs|%pm>>\n" +#endif + ; + skin_data_load(screen, data, default_fms, false); + } +} +enum fms_exiting { + FMS_EXIT, + FMS_ENTER +}; +void fms_fix_displays(enum fms_exiting toggle_state) +{ + int i; + FOR_NB_SCREENS(i) + { + if (toggle_state == FMS_ENTER) + { +#if LCD_DEPTH > 1 || defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 + screens[i].backdrop_show(fms_skin[i].data->backdrop); +#endif + viewportmanager_theme_enable(i, skin_has_sbs(i, fms_skin[i].data), NULL); + } + else + { + screens[i].stop_scroll(); +#if LCD_DEPTH > 1 || defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 + screens[i].backdrop_show(sb_get_backdrop(i)); +#endif + viewportmanager_theme_undo(i, false); + } + } +} + + +void fms_skin_init(void) +{ + int i; + FOR_NB_SCREENS(i) + { +#ifdef HAVE_ALBUMART + fms_skin_data[i].albumart = NULL; + fms_skin_data[i].playback_aa_slot = -1; +#endif + fms_skin[i].data = &fms_skin_data[i]; + fms_skin[i].display = &screens[i]; + /* Currently no seperate wps_state needed/possible + so use the only available ( "global" ) one */ + fms_skin[i].state = &wps_state; + fms_skin[i].sync_data = &fms_skin_sync_data; + } +} + int radio_screen(void) { - char buf[MAX_PATH]; bool done = false; int ret_val = GO_TO_ROOT; int button; int i; bool stereo = false, last_stereo = false; - int fh; - int top_of_screen = 0; - bool update_screen = true; + bool update_screen = true, restore = true; bool screen_freeze = false; bool keep_playing = false; bool talk = false; @@ -493,36 +591,10 @@ #ifndef HAVE_NOISY_IDLE_MODE int button_timeout = current_tick + (2*HZ); #endif - struct viewport vp[NB_SCREENS]; -#ifdef HAVE_BUTTONBAR - struct gui_buttonbar buttonbar; - gui_buttonbar_init(&buttonbar); - gui_buttonbar_set_display(&buttonbar, &(screens[SCREEN_MAIN]) ); -#endif /* change status to "in screen" */ in_screen = true; - /* always display status bar in radio screen for now */ - FOR_NB_SCREENS(i) - { - viewport_set_defaults(&vp[i], i); -#ifdef HAVE_BUTTONBAR - if (global_settings.buttonbar) - vp[i].height -= BUTTONBAR_HEIGHT; -#endif - screens[i].set_viewport(&vp[i]); - screens[i].stop_scroll(); - screens[i].clear_viewport(); - screens[i].update_viewport(); - } - - fh = font_get(FONT_UI)->height; - - /* Adjust for font size, trying to center the information vertically */ - if(fh < 10) - top_of_screen = 1; - if(num_presets <= 0) { radio_load_presets(global_settings.fmr_file); @@ -565,17 +637,12 @@ #endif if(num_presets < 1 && yesno_pop(ID2P(LANG_FM_FIRST_AUTOSCAN))) - scan_presets(vp); + scan_presets(NULL); curr_preset = find_preset(curr_freq); if(curr_preset != -1) radio_mode = RADIO_PRESET_MODE; -#ifdef HAVE_BUTTONBAR - gui_buttonbar_set(&buttonbar, str(LANG_BUTTONBAR_MENU), - str(LANG_PRESET), str(LANG_FM_BUTTONBAR_RECORD)); -#endif - #ifndef HAVE_NOISY_IDLE_MODE cpu_idle_mode(true); #endif @@ -757,25 +824,11 @@ break; case ACTION_FM_MENU: - FOR_NB_SCREENS(i) - { - screens[i].scroll_stop(&vp[i]); - } + fms_fix_displays(FMS_EXIT); radio_menu(); curr_preset = find_preset(curr_freq); - FOR_NB_SCREENS(i) - { - screens[i].set_viewport(&vp[i]); - screens[i].clear_viewport(); - screens[i].update_viewport(); - screens[i].set_viewport(NULL); - } -#ifdef HAVE_BUTTONBAR - gui_buttonbar_set(&buttonbar, str(LANG_BUTTONBAR_MENU), - str(LANG_PRESET), - str(LANG_FM_BUTTONBAR_RECORD)); -#endif update_screen = true; + restore = true; break; #ifdef FM_PRESET @@ -784,32 +837,13 @@ { splash(HZ, ID2P(LANG_FM_NO_PRESETS)); update_screen = true; - FOR_NB_SCREENS(i) - { - screens[i].set_viewport(&vp[i]); - screens[i].clear_viewport(); - screens[i].update_viewport(); - screens[i].set_viewport(NULL); - } - + restore = true; break; } + fms_fix_displays(FMS_EXIT); handle_radio_presets(); - FOR_NB_SCREENS(i) - { - screens[i].set_viewport(&vp[i]); - screens[i].stop_scroll(); - screens[i].clear_viewport(); - screens[i].update_viewport(); - screens[i].set_viewport(NULL); - } -#ifdef HAVE_BUTTONBAR - gui_buttonbar_set(&buttonbar, - str(LANG_BUTTONBAR_MENU), - str(LANG_PRESET), - str(LANG_FM_BUTTONBAR_RECORD)); -#endif update_screen = true; + restore = true; break; #endif /* FM_PRESET */ @@ -852,6 +886,7 @@ else radio_mode = RADIO_SCAN_MODE; update_screen = true; + restore = true; cond_talk_ids_fq(radio_mode ? LANG_PRESET : LANG_RADIO_SCAN_MODE); talk = true; @@ -863,6 +898,7 @@ next_preset(1); end_search(); update_screen = true; + restore = true; talk = true; break; #endif @@ -872,6 +908,7 @@ next_preset(-1); end_search(); update_screen = true; + restore = true; talk = true; break; #endif @@ -921,18 +958,6 @@ { /* Only display the peak meter when not recording */ #if CONFIG_CODEC != SWCODEC - if(!audio_status()) - { - FOR_NB_SCREENS(i) - { - screens[i].set_viewport(&vp[i]); - peak_meter_screen(&screens[i],0, fh*(top_of_screen + 4),fh); - screens[i].update_rect(0, fh*(top_of_screen + 4), - screens[i].getwidth(), fh); - screens[i].set_viewport(NULL); - } - } - if(TIME_AFTER(current_tick, timeout)) { timeout = current_tick + HZ; @@ -960,85 +985,17 @@ { last_seconds = seconds; #else - if (update_screen) + if (update_screen || restore) { #endif - int freq; - + if (restore) + fms_fix_displays(FMS_ENTER); FOR_NB_SCREENS(i) - { - screens[i].set_viewport(&vp[i]); - } - - snprintf(buf, 128, curr_preset >= 0 ? "%d. %s" : " ", - curr_preset + 1, presets[curr_preset].name); - - FOR_NB_SCREENS(i) - screens[i].puts_scroll(0, top_of_screen, buf); - - freq = curr_freq / 10000; - snprintf(buf, 128, str(LANG_FM_STATION), - freq / 100, freq % 100); - FOR_NB_SCREENS(i) - screens[i].puts_scroll(0, top_of_screen + 1, buf); - - FOR_NB_SCREENS(i) - screens[i].puts_scroll(0, top_of_screen + 2, - stereo ? str(LANG_CHANNEL_STEREO) : - str(LANG_CHANNEL_MONO)); - - snprintf(buf, 128, "%s %s", str(LANG_MODE), - radio_mode ? str(LANG_PRESET) : - str(LANG_RADIO_SCAN_MODE)); - FOR_NB_SCREENS(i) - screens[i].puts_scroll(0, top_of_screen + 3, buf); -#ifndef SIMULATOR -#ifdef HAVE_RDS_CAP - snprintf(buf, 128, "%s",tuner_get_rds_info(RADIO_RDS_NAME)); - FOR_NB_SCREENS(i) - screens[i].puts_scroll(0, top_of_screen + 4, buf); - - snprintf(buf, 128, "%s",tuner_get_rds_info(RADIO_RDS_TEXT)); - FOR_NB_SCREENS(i) - screens[i].puts_scroll(0, top_of_screen + 5, buf); -#endif -#endif /* SIMULATOR */ - -#if CONFIG_CODEC != SWCODEC - 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(rec_options.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); - } - } -#endif /* CONFIG_CODEC != SWCODEC */ - - FOR_NB_SCREENS(i) - { - screens[i].update_viewport(); - screens[i].set_viewport(NULL); - } - -#ifdef HAVE_BUTTONBAR - gui_buttonbar_draw(&buttonbar); -#endif + skin_update(&fms_skin[i], + restore ? WPS_REFRESH_ALL : WPS_REFRESH_NON_STATIC); + restore = false; } } - update_screen = false; if (global_settings.talk_file && talk @@ -1076,12 +1033,6 @@ if(audio_status() & AUDIO_STATUS_ERROR) { splash(0, str(LANG_DISK_FULL)); - FOR_NB_SCREENS(i) - { - screens[i].set_viewport(&vp[i]); - screens[i].update_viewport(); - screens[i].set_viewport(NULL); - } audio_error_clear(); while(1) @@ -1124,10 +1075,7 @@ #ifndef HAVE_NOISY_IDLE_MODE cpu_idle_mode(false); #endif - FOR_NB_SCREENS(i) - { - screens[i].scroll_stop(&vp[i]); - } + fms_fix_displays(FMS_EXIT); in_screen = false; #if CONFIG_CODEC != SWCODEC return have_recorded; Index: apps/recorder/radio.h =================================================================== --- apps/recorder/radio.h (revision 24553) +++ apps/recorder/radio.h (working copy) @@ -24,6 +24,7 @@ #ifndef FMRADIO_H #include "fmradio.h" #endif +#include "screen_access.h" #if CONFIG_TUNER void radio_load_presets(char *filename); @@ -34,6 +35,18 @@ void radio_stop(void); bool radio_hardware_present(void); bool in_radio_screen(void); + +bool radio_scan_mode(void); /* true for scan mode, false for preset mode */ +bool radio_is_stereo(void); +int radio_current_frequency(void); +int radio_current_preset(void); +int radio_preset_count(void); +const struct fmstation *radio_get_preset(int preset); + +/* skin functions */ +void fms_data_load(enum screen_type screen, const char *buf, bool isfile); +void fms_skin_init(void); + /* callbacks for the radio settings */ void set_radio_region(int region); void toggle_mono_mode(bool mono); Index: apps/lang/english.lang =================================================================== --- apps/lang/english.lang (revision 24553) +++ apps/lang/english.lang (working copy) @@ -5244,11 +5244,11 @@ user: core *: none - radio: "Station: %d.%02d MHz" + radio: "Station:" *: none - radio: "Station: %d.%02d MHz" + radio: "Station:" *: none Index: apps/settings.c =================================================================== --- apps/settings.c (revision 24566) +++ apps/settings.c (working copy) @@ -763,6 +763,20 @@ { wps_data_load(SCREEN_MAIN, NULL, true); } +#if CONFIG_TUNER + fms_skin_init(); + if ( global_settings.fms_file[0] && + global_settings.fms_file[0] != 0xff ) + { + snprintf(buf, sizeof buf, WPS_DIR "/%s.fms", + global_settings.fms_file); + fms_data_load(SCREEN_MAIN, buf, true); + } + else + { + fms_data_load(SCREEN_MAIN, NULL, true); + } +#endif #if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1) if ( global_settings.rsbs_file[0] && global_settings.rsbs_file[0] != 0xff ) { @@ -784,7 +798,20 @@ { wps_data_load(SCREEN_REMOTE, NULL, true); } +#if CONFIG_TUNER + if ( global_settings.rfms_file[0] && + global_settings.rfms_file[0] != 0xff ) + { + snprintf(buf, sizeof buf, WPS_DIR "/%s.rfms", + global_settings.rfms_file); + fms_data_load(SCREEN_REMOTE, buf, true); + } + else + { + fms_data_load(SCREEN_REMOTE, NULL, true); + } #endif +#endif viewportmanager_theme_changed(THEME_STATUSBAR); #if LCD_DEPTH > 1 || defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 int i; Index: apps/gui/skin_engine/skin_engine.h =================================================================== --- apps/gui/skin_engine/skin_engine.h (revision 24553) +++ apps/gui/skin_engine/skin_engine.h (working copy) @@ -30,6 +30,9 @@ enum skinnable_screens { CUSTOM_STATUSBAR, WPS, +#if CONFIG_TUNER + FM_SCREEN, +#endif SKINNABLE_SCREENS_COUNT @@ -60,4 +63,6 @@ /* call this in statusbar toggle handlers if needed */ void skin_statusbar_changed(struct gui_wps*); + +bool skin_has_sbs(enum screen_type screen, struct wps_data *data); #endif Index: apps/gui/skin_engine/wps_debug.c =================================================================== --- apps/gui/skin_engine/wps_debug.c (revision 24553) +++ apps/gui/skin_engine/wps_debug.c (working copy) @@ -61,6 +61,7 @@ { X(TOKEN_MARKER_PLAYLIST) }, { X(TOKEN_MARKER_MISC) }, { X(TOKEN_MARKER_RECORDING) }, + { X(TOKEN_MARKER_TUNER) }, { X(TOKEN_MARKER_END) }, }; #undef X Index: apps/gui/skin_engine/skin_parser.c =================================================================== --- apps/gui/skin_engine/skin_parser.c (revision 24553) +++ apps/gui/skin_engine/skin_parser.c (working copy) @@ -52,6 +52,7 @@ #include "skin_engine.h" #include "settings.h" #include "settings_list.h" +#include "radio.h" #ifdef HAVE_LCD_BITMAP #include "bmp.h" @@ -185,6 +186,10 @@ #else #define WPS_RTC_REFRESH WPS_REFRESH_STATIC #endif +#if CONFIG_TUNER +static int parse_presettoken(const char *wps_bufptr, + struct wps_token *token, struct wps_data *wps_data); +#endif /* array of available tags - those with more characters have to go first (e.g. "xl" and "xd" before "x"). It needs to end with the unknown token. */ @@ -340,6 +345,27 @@ { WPS_TOKEN_CROSSFADE, "xf", WPS_REFRESH_DYNAMIC, NULL }, #endif + { WPS_TOKEN_HAVE_TUNER, "tp", WPS_REFRESH_STATIC, NULL }, +#if CONFIG_TUNER /* Re-uses the 't' and 'T' prefixes, be careful about doubleups */ + /* TODO: alot of these can be made WPS_REFRESH_STATIC + * if the skin is fully redrawn when changing stuff(!) */ + { WPS_TOKEN_TUNER_TUNED, "tt", WPS_REFRESH_DYNAMIC, NULL }, + { WPS_TOKEN_TUNER_SCANMODE, "tm", WPS_REFRESH_DYNAMIC, NULL }, + { WPS_TOKEN_TUNER_STEREO, "ts", WPS_REFRESH_DYNAMIC, NULL }, + { WPS_TOKEN_TUNER_MINFREQ, "ta", WPS_REFRESH_STATIC, NULL }, + { WPS_TOKEN_TUNER_MAXFREQ, "tb", WPS_REFRESH_STATIC, NULL }, + { WPS_TOKEN_TUNER_CURFREQ, "tf", WPS_REFRESH_DYNAMIC, NULL }, + { WPS_TOKEN_PRESET_ID, "Ti", WPS_REFRESH_DYNAMIC, NULL }, + { WPS_TOKEN_PRESET_NAME, "Tn", WPS_REFRESH_DYNAMIC, parse_presettoken }, + { WPS_TOKEN_PRESET_FREQ, "Tf", WPS_REFRESH_DYNAMIC, parse_presettoken }, + { WPS_TOKEN_PRESET_COUNT, "Tc", WPS_REFRESH_DYNAMIC, NULL }, + { WPS_TOKEN_HAVE_RDS, "tx", WPS_REFRESH_STATIC, NULL }, +#ifdef HAVE_RDS_CAPS + { WPS_TOKEN_RDS_NAME, "ty", WPS_REFRESH_DYNAMIC, NULL }, + { WPS_TOKEN_RDS_TEXT, "tz", WPS_REFRESH_DYNAMIC, NULL }, +#endif +#endif /* CONFIG_TUNER */ + { WPS_NO_TOKEN, "s", WPS_REFRESH_SCROLL, NULL }, { WPS_TOKEN_SUBLINE_TIMEOUT, "t", 0, parse_timeout }, @@ -384,10 +410,14 @@ /* Recording Tokens */ { WPS_TOKEN_HAVE_RECORDING, "Rp", WPS_REFRESH_STATIC, NULL }, #ifdef HAVE_RECORDING + { WPS_TOKEN_IS_RECORDING, "Rr", WPS_REFRESH_DYNAMIC, NULL }, { WPS_TOKEN_REC_FREQ, "Rf", WPS_REFRESH_DYNAMIC, NULL }, { WPS_TOKEN_REC_ENCODER, "Re", WPS_REFRESH_DYNAMIC, NULL }, { WPS_TOKEN_REC_BITRATE, "Rb", WPS_REFRESH_DYNAMIC, NULL }, { WPS_TOKEN_REC_MONO, "Rm", WPS_REFRESH_DYNAMIC, NULL }, + { WPS_TOKEN_REC_SECONDS, "Rs", WPS_REFRESH_DYNAMIC, NULL }, + { WPS_TOKEN_REC_MINUTES, "Rn", WPS_REFRESH_DYNAMIC, NULL }, + { WPS_TOKEN_REC_HOURS, "Rh", WPS_REFRESH_DYNAMIC, NULL }, #endif { WPS_TOKEN_UNKNOWN, "", 0, NULL } /* the array MUST end with an empty string (first char is \0) */ @@ -1363,6 +1393,22 @@ }; #endif /* HAVE_ALBUMART */ +#if CONFIG_TUNER +static int parse_presettoken(const char *wps_bufptr, + struct wps_token *token, struct wps_data *wps_data) +{ + (void)wps_data; + /* tokens are in the form %xxN where N is a number + * stored as *signed* in the tokens data */ + int value = 0; + const char *ptr; + if (!(ptr = parse_list("d", NULL, '|',wps_bufptr, &value))) + return WPS_ERROR_INVALID_PARAM; + token->value.i = (signed int)value; + return ptr-wps_bufptr; +} +#endif /* CONFIG_TUNER */ + #ifdef HAVE_TOUCHSCREEN struct touchaction {const char* s; int action;}; @@ -1622,6 +1668,13 @@ #else return find_false_branch(wps_bufptr); #endif + case WPS_TOKEN_HAVE_TUNER: +#if CONFIG_TUNER + if (radio_hardware_present()) + return 0; +#endif + return find_false_branch(wps_bufptr); + default: /* not a tag we care about, just don't skip */ return 0; } Index: apps/gui/skin_engine/skin_tokens.c =================================================================== --- apps/gui/skin_engine/skin_tokens.c (revision 24553) +++ apps/gui/skin_engine/skin_tokens.c (working copy) @@ -61,6 +61,8 @@ #endif #include "language.h" #include "usb.h" +#include "radio.h" +#include "tuner.h" extern struct wps_state wps_state; @@ -342,6 +344,87 @@ return buf; } +#if CONFIG_TUNER +/* Tokens which are really only used by the radio screen go in here */ +const char *get_radio_token(struct wps_token *token, + char *buf, int buf_size, int limit, int *intval) +{ + (void)limit; + switch (token->type) + { + /* Radio/tuner tokens */ + case WPS_TOKEN_TUNER_TUNED: + if (tuner_get(RADIO_TUNED)) + return "t"; + return NULL; + case WPS_TOKEN_TUNER_SCANMODE: + if (radio_scan_mode()) + return "s"; + return NULL; + case WPS_TOKEN_TUNER_STEREO: + if (radio_is_stereo()) + return "s"; + return NULL; + case WPS_TOKEN_TUNER_MINFREQ: /* changes based on "region" */ + { + int freq = fm_region_data[global_settings.fm_region].freq_min / 10000; + snprintf(buf, buf_size, "%d.%d", freq/100, freq%100); + return buf; + } + case WPS_TOKEN_TUNER_MAXFREQ: /* changes based on "region" */ + { + int freq = fm_region_data[global_settings.fm_region].freq_max / 10000; + snprintf(buf, buf_size, "%d.%d", freq/100, freq%100); + return buf; + } + case WPS_TOKEN_TUNER_CURFREQ: + { + int freq = radio_current_frequency() / 10000; + snprintf(buf, buf_size, "%d.%d", freq/100, freq%100); + return buf; + } + case WPS_TOKEN_PRESET_ID: + snprintf(buf, buf_size, "%d", radio_current_preset()+1); + return buf; + case WPS_TOKEN_PRESET_NAME: + case WPS_TOKEN_PRESET_FREQ: + { + int preset = radio_current_preset() + (signed int)token->value.i; + /* make sure its in the valid range */ + while (preset < 0) + preset += radio_preset_count(); + preset %= radio_preset_count(); + if (token->type == WPS_TOKEN_PRESET_NAME) + { + snprintf(buf, buf_size, "%s", radio_get_preset(preset)->name); + } + else + { + int freq = radio_get_preset(preset)->frequency / 10000; + snprintf(buf, buf_size, "%d.%d", freq/100, freq%100); + } + return buf; + } + case WPS_TOKEN_PRESET_COUNT: + snprintf(buf, buf_size, "%d", radio_preset_count()); + if (intval) + *intval = radio_preset_count(); + return buf; + case WPS_TOKEN_HAVE_RDS: +#ifdef HAVE_RDS_CAP + return "rds"; + case WPS_TOKEN_RDS_NAME: + return tuner_get_rds_info(RADIO_RDS_NAME); + case WPS_TOKEN_RDS_TEXT: + return tuner_get_rds_info(RADIO_RDS_TEXT); +#else + return NULL; /* end of the WPS_TOKEN_HAVE_RDS case */ +#endif /* HAVE_RDS_CAP */ + } + return NULL; +} +#endif + /* Return the tags value as text. buf should be used as temp storage if needed. intval is used with conditionals/enums: when this function is called, @@ -399,6 +482,11 @@ out_text = get_id3_token(token, id3, buf, buf_size, limit, intval); if (out_text) return out_text; +#if CONFIG_TUNER + out_text = get_radio_token(token, buf, buf_size, limit, intval); + if (out_text) + return out_text; +#endif switch (token->type) { @@ -944,6 +1032,12 @@ cfg_to_string(token->value.i,buf,buf_size); return buf; } + case WPS_TOKEN_HAVE_TUNER: +#if CONFIG_TUNER + if (radio_hardware_present()) + return "r"; +#endif + return NULL; /* Recording tokens */ case WPS_TOKEN_HAVE_RECORDING: #ifdef HAVE_RECORDING @@ -953,6 +1047,10 @@ #endif #ifdef HAVE_RECORDING + case WPS_TOKEN_IS_RECORDING: + if (audio_status() == AUDIO_STATUS_RECORD) + return "r"; + return NULL; case WPS_TOKEN_REC_FREQ: /* order from REC_FREQ_CFG_VAL_LIST */ { #if CONFIG_CODEC == SWCODEC @@ -1135,8 +1233,25 @@ if (!global_settings.rec_channels) return "m"; return NULL; + + case WPS_TOKEN_REC_SECONDS: + if (intval) + *intval = (audio_recorded_time() / HZ) % 60; + snprintf(buf, buf_size, "%02d", (audio_recorded_time() / HZ) % 60); + return buf; + case WPS_TOKEN_REC_MINUTES: + if (intval) + *intval = (audio_recorded_time() / HZ) / 60; + snprintf(buf, buf_size, "%02d", (audio_recorded_time() / HZ) / 60); + return buf; + case WPS_TOKEN_REC_HOURS: + if (intval) + *intval = (audio_recorded_time() / HZ) / 3600; + snprintf(buf, buf_size, "%02d", (audio_recorded_time() / HZ) / 3600); + return buf; #endif /* HAVE_RECORDING */ + case WPS_TOKEN_CURRENT_SCREEN: { int curr_screen = current_screen(); Index: apps/gui/skin_engine/skin_display.c =================================================================== --- apps/gui/skin_engine/skin_display.c (revision 24565) +++ apps/gui/skin_engine/skin_display.c (working copy) @@ -53,6 +53,9 @@ #endif #include "backdrop.h" #include "viewport.h" +#include "radio.h" +#include "tuner.h" +#include "root_menu.h" #include "wps_internals.h" @@ -74,7 +77,12 @@ struct mp3entry *id3 = gwps->state->id3; bool cuesheet_update = (id3 != NULL ? cuesheet_subtrack_changed(id3) : false); gwps->sync_data->do_full_update |= cuesheet_update; + +#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1) + gwps->display->backdrop_show(gwps->data->backdrop); +#endif + retval = skin_redraw(gwps, gwps->sync_data->do_full_update ? WPS_REFRESH_ALL : update_type); return retval; @@ -121,6 +129,7 @@ struct wps_state *state = gwps->state; struct progressbar *pb = wps_vp->pb; struct mp3entry *id3 = state->id3; + int y = pb->y; if (y < 0) @@ -133,9 +142,18 @@ } int elapsed, length; +#if CONFIG_TUNER + if (current_screen() == GO_TO_FM) + { + int min = fm_region_data[global_settings.fm_region].freq_min; + elapsed = radio_current_frequency() - min; + length = fm_region_data[global_settings.fm_region].freq_max - min; + } + else +#endif if (id3) { - elapsed = id3->elapsed; + elapsed = id3->elapsed + state->ff_rewind_count; length = id3->length; } else @@ -148,12 +166,12 @@ gui_bitmap_scrollbar_draw(display, pb->bm, pb->x, y, pb->width, pb->bm.height, length ? length : 1, 0, - length ? elapsed + state->ff_rewind_count : 0, + length ? elapsed : 0, HORIZONTAL); else gui_scrollbar_draw(display, pb->x, y, pb->width, pb->height, length ? length : 1, 0, - length ? elapsed + state->ff_rewind_count : 0, + length ? elapsed : 0, HORIZONTAL); #ifdef AB_REPEAT_ENABLE if ( ab_repeat_mode_enabled() && length != 0 ) @@ -207,9 +225,21 @@ pid3 = NULL; } - int line = pid3 ? TRACK_HAS_INFO : TRACK_HAS_NO_INFO; + int line; int j = 0, cur_string = 0; - char *filename = playlist_peek(i-cur_playlist_pos); + char *filename; +#if CONFIG_TUNER + if (current_screen() == GO_TO_FM) + { + line = TRACK_HAS_INFO; + filename = ""; + } + else +#endif + { + line = pid3 ? TRACK_HAS_INFO : TRACK_HAS_NO_INFO; + filename = playlist_peek(i-cur_playlist_pos); + } buf[0] = '\0'; buf_used = 0; while (j < viewer->lines[line].count && (buf_usedlines[line].tokens[j]) { case WPS_TOKEN_STRING: @@ -1216,3 +1256,16 @@ return true; } + +bool skin_has_sbs(enum screen_type screen, struct wps_data *data) +{ + (void)screen; + bool draw = false; +#ifdef HAVE_LCD_BITMAP + if (data->wps_sb_tag) + draw = data->show_sb_on_wps; + else if (statusbar_position(screen) != STATUSBAR_OFF) + draw = true; +#endif + return draw; +} Index: apps/gui/skin_engine/skin_tokens.h =================================================================== --- apps/gui/skin_engine/skin_tokens.h (revision 24553) +++ apps/gui/skin_engine/skin_tokens.h (working copy) @@ -211,11 +211,39 @@ /* Recording Tokens */ TOKEN_MARKER_RECORDING, WPS_TOKEN_HAVE_RECORDING, + WPS_TOKEN_IS_RECORDING, WPS_TOKEN_REC_FREQ, WPS_TOKEN_REC_ENCODER, WPS_TOKEN_REC_BITRATE, /* SWCODEC: MP3 bitrate, HWCODEC: MP3 "quality" */ WPS_TOKEN_REC_MONO, + WPS_TOKEN_REC_SECONDS, + WPS_TOKEN_REC_MINUTES, + WPS_TOKEN_REC_HOURS, + + /* Radio Tokens */ + TOKEN_MARKER_TUNER, + WPS_TOKEN_HAVE_TUNER, +#if CONFIG_TUNER + WPS_TOKEN_TUNER_TUNED, + WPS_TOKEN_TUNER_SCANMODE, + WPS_TOKEN_TUNER_STEREO, + WPS_TOKEN_TUNER_MINFREQ, /* changes based on "region" */ + WPS_TOKEN_TUNER_MAXFREQ, /* changes based on "region" */ + WPS_TOKEN_TUNER_CURFREQ, + WPS_TOKEN_PRESET_ID, /* "id" of this preset.. really the array element number */ + WPS_TOKEN_PRESET_NAME, + WPS_TOKEN_PRESET_FREQ, + WPS_TOKEN_PRESET_COUNT, + /* RDS tokens */ + WPS_TOKEN_HAVE_RDS, +#ifdef HAVE_RDS_CAP + WPS_TOKEN_RDS_NAME, + WPS_TOKEN_RDS_TEXT, +#endif +#endif /* CONFIG_TUNER */ + + TOKEN_MARKER_END, /* this needs to be the last value in this enum */ }; Index: apps/gui/skin_engine/wps_internals.h =================================================================== --- apps/gui/skin_engine/wps_internals.h (revision 24553) +++ apps/gui/skin_engine/wps_internals.h (working copy) @@ -363,8 +363,11 @@ const char *get_id3_token(struct wps_token *token, struct mp3entry *id3, char *buf, int buf_size, int limit, int *intval); +#if CONFIG_TUNER +const char *get_radio_token(struct wps_token *token, + char *buf, int buf_size, int limit, int *intval); +#endif - struct gui_img* find_image(char label, struct wps_data *data); struct skin_viewport* find_viewport(char label, struct wps_data *data); Index: apps/gui/wps.c =================================================================== --- apps/gui/wps.c (revision 24566) +++ apps/gui/wps.c (working copy) @@ -568,16 +568,8 @@ #if LCD_DEPTH > 1 || defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 gui_wps[i].display->backdrop_show(sb_get_backdrop(i)); #endif + viewportmanager_theme_undo(i, skin_has_sbs(i, gui_wps[i].data)); -#ifdef HAVE_LCD_BITMAP - bool draw = false; - if (gui_wps[i].data->wps_sb_tag) - draw = gui_wps[i].data->show_sb_on_wps; - else if (statusbar_position(i) != STATUSBAR_OFF) - draw = true; -#endif - viewportmanager_theme_undo(i, draw); - } #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP) @@ -597,18 +589,11 @@ { struct gui_wps *gwps = &gui_wps[i]; struct screen *display = gwps->display; -#ifdef HAVE_LCD_BITMAP - bool draw = false; - if (gui_wps[i].data->wps_sb_tag) - draw = gui_wps[i].data->show_sb_on_wps; - else if (statusbar_position(i) != STATUSBAR_OFF) - draw = true; -#endif display->stop_scroll(); #if LCD_DEPTH > 1 || defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 display->backdrop_show(gwps->data->backdrop); #endif - viewportmanager_theme_enable(i, draw, NULL); + viewportmanager_theme_enable(i, skin_has_sbs(i, gui_wps[i].data), NULL); /* Update the values in the first (default) viewport - in case the user has modified the statusbar or colour settings */ Index: apps/settings.h =================================================================== --- apps/settings.h (revision 24553) +++ apps/settings.h (working copy) @@ -495,7 +495,11 @@ int fm_region; bool fm_force_mono; /* Forces Mono mode if true */ unsigned char fmr_file[MAX_FILENAME+1]; /* last fmr preset */ + unsigned char fms_file[MAX_FILENAME+1]; /* last fms */ +#ifdef HAVE_REMOTE_LCD + unsigned char rfms_file[MAX_FILENAME+1]; /* last remote-fms */ #endif +#endif /* CONFIG_TUNER */ /* misc options */ #ifndef HAVE_WHEEL_ACCELERATION Index: apps/settings_list.c =================================================================== --- apps/settings_list.c (revision 24564) +++ apps/settings_list.c (working copy) @@ -200,6 +200,7 @@ /* Default theme settings */ #define DEFAULT_WPSNAME "cabbiev2" #define DEFAULT_SBS_NAME DEFAULT_WPSNAME +#define DEFAULT_FMS_NAME DEFAULT_WPSNAME #ifdef HAVE_LCD_BITMAP @@ -1427,7 +1428,13 @@ #if CONFIG_TUNER TEXT_SETTING(0, fmr_file, "fmr", "", FMPRESET_PATH "/", ".fmr"), + TEXT_SETTING(F_THEMESETTING,fms_file, "fms", + DEFAULT_FMS_NAME, SBS_DIR "/", ".fms"), +#ifdef HAVE_REMOTE_LCD + TEXT_SETTING(F_THEMESETTING,rfms_file, "rfms", + DEFAULT_FMS_NAME, SBS_DIR "/", ".rfms"), #endif +#endif /* CONFIG_TUNER */ #ifdef HAVE_LCD_BITMAP TEXT_SETTING(F_THEMESETTING, font_file, "font", DEFAULT_FONTNAME, FONT_DIR "/", ".fnt"),