diff --git a/apps/SOURCES b/apps/SOURCES index 8166dbe4e2..e1d85a75f0 100644 --- a/apps/SOURCES +++ b/apps/SOURCES @@ -60,8 +60,6 @@ screen_access.c #ifdef HAVE_BUTTONBAR gui/buttonbar.c #endif -gui/gwps.c -gui/gwps-common.c #ifdef HAVE_LCD_BITMAP gui/icon.c #endif @@ -78,14 +76,19 @@ gui/pitchscreen.c #ifdef HAVE_QUICKSCREEN gui/quickscreen.c #endif + +gui/music_screen.c gui/scrollbar.c gui/splash.c gui/statusbar.c gui/yesno.c -gui/wps_debug.c -gui/wps_parser.c gui/viewport.c +gui/wps_engine/wps_debug.c +gui/wps_engine/wps_display.c +gui/wps_engine/wps_parser.c +gui/wps_engine/wps_tokens.c + #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)) gui/backdrop.c #endif diff --git a/apps/filetree.c b/apps/filetree.c index 87ac37c2e0..458d553e27 100644 --- a/apps/filetree.c +++ b/apps/filetree.c @@ -33,7 +33,6 @@ #include "filetypes.h" #include "talk.h" #include "playlist.h" -#include "gwps.h" #include "lang.h" #include "language.h" #include "screens.h" @@ -52,7 +51,7 @@ #if CONFIG_TUNER #include "radio.h" #endif - +#include "wps_engine/wps_internals.h" /* FIXME: REMOVE ME */ #include "backdrop.h" static int compare_sort_dir; /* qsort key for sorting directories */ diff --git a/apps/gui/gwps.c b/apps/gui/music_screen.c similarity index 80% rename from apps/gui/gwps.c rename to apps/gui/music_screen.c index 10c2a6806b..39d5e0e85b 100644 --- a/apps/gui/gwps.c +++ b/apps/gui/music_screen.c @@ -34,8 +34,8 @@ #include "debug.h" #include "sprintf.h" #include "settings.h" -#include "gwps.h" -#include "gwps-common.h" +#include "wps_engine/wps_engine.h" +#include "mp3_playback.h" #include "audio.h" #include "usb.h" #include "status.h" @@ -66,6 +66,7 @@ #include "option_select.h" #include "dsp.h" #include "playlist_viewer.h" +#include "music_screen.h" #define RESTORE_WPS_INSTANTLY 0l #define RESTORE_WPS_NEXT_SECOND ((long)(HZ+current_tick)) @@ -84,6 +85,234 @@ static void track_changed_callback(void *param); static void nextid3available_callback(void* param); + +#define FF_REWIND_MAX_PERCENT 3 /* cap ff/rewind step size at max % of file */ + /* 3% of 30min file == 54s step size */ +#define MIN_FF_REWIND_STEP 500 + +bool wps_fading_out = false; +void fade(bool fade_in, bool updatewps) +{ + int fp_global_vol = global_settings.volume << 8; + int fp_min_vol = sound_min(SOUND_VOLUME) << 8; + int fp_step = (fp_global_vol - fp_min_vol) / 30; + int i; + wps_fading_out = !fade_in; + if (fade_in) { + /* fade in */ + int fp_volume = fp_min_vol; + + /* zero out the sound */ + sound_set_volume(fp_min_vol >> 8); + + sleep(HZ/10); /* let audio thread run */ + audio_resume(); + + while (fp_volume < fp_global_vol - fp_step) { + fp_volume += fp_step; + sound_set_volume(fp_volume >> 8); + if (updatewps) + { + FOR_NB_SCREENS(i) + gui_wps_redraw(&gui_wps[i], 0, WPS_REFRESH_NON_STATIC); + } + sleep(1); + } + sound_set_volume(global_settings.volume); + } + else { + /* fade out */ + int fp_volume = fp_global_vol; + + while (fp_volume > fp_min_vol + fp_step) { + fp_volume -= fp_step; + sound_set_volume(fp_volume >> 8); + if (updatewps) + { + FOR_NB_SCREENS(i) + gui_wps_redraw(&gui_wps[i], 0, WPS_REFRESH_NON_STATIC); + } + sleep(1); + } + audio_pause(); + wps_fading_out = false; +#if CONFIG_CODEC != SWCODEC +#ifndef SIMULATOR + /* let audio thread run and wait for the mas to run out of data */ + while (!mp3_pause_done()) +#endif + sleep(HZ/10); +#endif + + /* reset volume to what it was before the fade */ + sound_set_volume(global_settings.volume); + } +} +bool is_wps_fading(void) +{ + return wps_fading_out; +} + +bool update_onvol_change(struct gui_wps * gwps) +{ + gui_wps_redraw(gwps, 0, WPS_REFRESH_NON_STATIC); + +#ifdef HAVE_LCD_CHARCELLS + splashf(0, "Vol: %3d dB", + sound_val2phys(SOUND_VOLUME, global_settings.volume)); + return true; +#endif + return false; +} + +bool ffwd_rew(int button) +{ + unsigned int step = 0; /* current ff/rewind step */ + unsigned int max_step = 0; /* maximum ff/rewind step */ + int ff_rewind_count = 0; /* current ff/rewind count (in ticks) */ + int direction = -1; /* forward=1 or backward=-1 */ + bool exit = false; + bool usb = false; + int i = 0; + const long ff_rw_accel = (global_settings.ff_rewind_accel + 3); + + if (button == ACTION_NONE) + { + status_set_ffmode(0); + return usb; + } + while (!exit) + { + switch ( button ) + { + case ACTION_WPS_SEEKFWD: + direction = 1; + case ACTION_WPS_SEEKBACK: + if (wps_state.ff_rewind) + { + if (direction == 1) + { + /* fast forwarding, calc max step relative to end */ + max_step = (wps_state.id3->length - + (wps_state.id3->elapsed + + ff_rewind_count)) * + FF_REWIND_MAX_PERCENT / 100; + } + else + { + /* rewinding, calc max step relative to start */ + max_step = (wps_state.id3->elapsed + ff_rewind_count) * + FF_REWIND_MAX_PERCENT / 100; + } + + max_step = MAX(max_step, MIN_FF_REWIND_STEP); + + if (step > max_step) + step = max_step; + + ff_rewind_count += step * direction; + + /* smooth seeking by multiplying step by: 1 + (2 ^ -accel) */ + step += step >> ff_rw_accel; + } + else + { + if ( (audio_status() & AUDIO_STATUS_PLAY) && + wps_state.id3 && wps_state.id3->length ) + { + if (!wps_state.paused) +#if (CONFIG_CODEC == SWCODEC) + audio_pre_ff_rewind(); +#else + audio_pause(); +#endif +#if CONFIG_KEYPAD == PLAYER_PAD + FOR_NB_SCREENS(i) + gui_wps[i].display->stop_scroll(); +#endif + if (direction > 0) + status_set_ffmode(STATUS_FASTFORWARD); + else + status_set_ffmode(STATUS_FASTBACKWARD); + + wps_state.ff_rewind = true; + + step = 1000 * global_settings.ff_rewind_min_step; + } + else + break; + } + + if (direction > 0) { + if ((wps_state.id3->elapsed + ff_rewind_count) > + wps_state.id3->length) + ff_rewind_count = wps_state.id3->length - + wps_state.id3->elapsed; + } + else { + if ((int)(wps_state.id3->elapsed + ff_rewind_count) < 0) + ff_rewind_count = -wps_state.id3->elapsed; + } + + FOR_NB_SCREENS(i) + gui_wps_redraw(&gui_wps[i], + (wps_state.wps_time_countup == false)? + ff_rewind_count:-ff_rewind_count, + WPS_REFRESH_PLAYER_PROGRESS | + WPS_REFRESH_DYNAMIC); + + break; + + case ACTION_WPS_STOPSEEK: + wps_state.id3->elapsed = wps_state.id3->elapsed+ff_rewind_count; + audio_ff_rewind(wps_state.id3->elapsed); + ff_rewind_count = 0; + wps_state.ff_rewind = false; + status_set_ffmode(0); +#if (CONFIG_CODEC != SWCODEC) + if (!wps_state.paused) + audio_resume(); +#endif +#ifdef HAVE_LCD_CHARCELLS + FOR_NB_SCREENS(i) + gui_wps_redraw(&gui_wps[i],0, WPS_REFRESH_ALL); +#endif + exit = true; + break; + + default: + if(default_event_handler(button) == SYS_USB_CONNECTED) { + status_set_ffmode(0); + usb = true; + exit = true; + } + break; + } + if (!exit) + { + button = get_action(CONTEXT_WPS|ALLOW_SOFTLOCK,TIMEOUT_BLOCK); +#ifdef HAVE_TOUCHSCREEN + if (button == ACTION_TOUCHSCREEN) + button = wps_get_touchaction(gui_wps[SCREEN_MAIN].data); +#endif + } + } + return usb; +} + + +void display_keylock_text(bool locked) +{ + int i; + FOR_NB_SCREENS(i) + gui_wps[i].display->stop_scroll(); + + splash(HZ, locked ? ID2P(LANG_KEYLOCK_ON) : ID2P(LANG_KEYLOCK_OFF)); +} + + + + #if defined(HAVE_BACKLIGHT) || defined(HAVE_REMOTE_LCD) static void gwps_caption_backlight(struct wps_state *state) { diff --git a/apps/gui/gwps-common.h b/apps/gui/music_screen.h similarity index 59% rename from apps/gui/gwps-common.h rename to apps/gui/music_screen.h index 0d196b28e4..90614cb65b 100644 --- a/apps/gui/gwps-common.h +++ b/apps/gui/music_screen.h @@ -5,7 +5,7 @@ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ - * $Id$ + * $Id: gwps-common.h 20492 2009-03-23 17:19:48Z alle $ * * Copyright (C) 2002 Björn Stenberg * @@ -18,36 +18,20 @@ * KIND, either express or implied. * ****************************************************************************/ -#ifndef _GWPS_COMMON_ -#define _GWPS_COMMON_ +#ifndef _MUSICSCREEN_H_ +#define _MUSICSCREEN_H_ #include -#include /* for size_t */ - -#include "gwps.h" + +long gui_wps_show(void); + + +void gui_sync_wps_init(void); /* fades the volume, e.g. on pause or stop */ void fade(bool fade_in, bool updatewps); -/* Initially display the wps, can fall back to the built-in wps - * if the chosen wps is invalid. - * - * Return true on success, otherwise false */ -bool gui_wps_display(struct gui_wps *gui_wps); - -/* return true if screen restore is needed - return false otherwise */ -bool update_onvol_change(struct gui_wps * gwps); - -/* Update track info related stuff, handle cue sheets as well, and redraw */ -bool gui_wps_update(struct gui_wps *gwps); - bool ffwd_rew(int button); void display_keylock_text(bool locked); -/* Refresh the WPS according to refresh_mode. - * - * Return true on success, otherwise false */ -bool gui_wps_redraw(struct gui_wps *gwps, - int ffwd_offset, - unsigned refresh_mode); +bool is_wps_fading(void); #endif diff --git a/apps/gui/gwps.h b/apps/gui/wps_engine/gwps.h similarity index 100% rename from apps/gui/gwps.h rename to apps/gui/wps_engine/gwps.h diff --git a/apps/gui/wps_debug.c b/apps/gui/wps_engine/wps_debug.c similarity index 99% rename from apps/gui/wps_debug.c rename to apps/gui/wps_engine/wps_debug.c index 727d9078c6..a89f61af9d 100644 --- a/apps/gui/wps_debug.c +++ b/apps/gui/wps_engine/wps_debug.c @@ -23,7 +23,7 @@ #include #include -#include "gwps.h" +#include "wps_internals.h" #ifdef __PCTOOL__ #ifdef WPSEDITOR #include "proxy.h" diff --git a/apps/gui/gwps-common.c b/apps/gui/wps_engine/wps_display.c similarity index 55% rename from apps/gui/gwps-common.c rename to apps/gui/wps_engine/wps_display.c index 721682f248..c74e2cedfa 100644 --- a/apps/gui/gwps-common.c +++ b/apps/gui/wps_engine/wps_display.c @@ -19,7 +19,6 @@ * KIND, either express or implied. * ****************************************************************************/ -#include "gwps-common.h" #include "font.h" #include #include @@ -62,222 +61,9 @@ #include "backdrop.h" #include "viewport.h" -#define FF_REWIND_MAX_PERCENT 3 /* cap ff/rewind step size at max % of file */ - /* 3% of 30min file == 54s step size */ -#define MIN_FF_REWIND_STEP 500 -/* Timeout unit expressed in HZ. In WPS, all timeouts are given in seconds - (possibly with a decimal fraction) but stored as integer values. - E.g. 2.5 is stored as 25. This means 25 tenth of a second, i.e. 25 units. -*/ -#define TIMEOUT_UNIT (HZ/10) /* I.e. 0.1 sec */ -#define DEFAULT_SUBLINE_TIME_MULTIPLIER 20 /* In TIMEOUT_UNIT's */ - -bool wps_fading_out = false; -void fade(bool fade_in, bool updatewps) -{ - int fp_global_vol = global_settings.volume << 8; - int fp_min_vol = sound_min(SOUND_VOLUME) << 8; - int fp_step = (fp_global_vol - fp_min_vol) / 30; - int i; - wps_fading_out = !fade_in; - if (fade_in) { - /* fade in */ - int fp_volume = fp_min_vol; - - /* zero out the sound */ - sound_set_volume(fp_min_vol >> 8); - - sleep(HZ/10); /* let audio thread run */ - audio_resume(); - - while (fp_volume < fp_global_vol - fp_step) { - fp_volume += fp_step; - sound_set_volume(fp_volume >> 8); - if (updatewps) - { - FOR_NB_SCREENS(i) - gui_wps_redraw(&gui_wps[i], 0, WPS_REFRESH_NON_STATIC); - } - sleep(1); - } - sound_set_volume(global_settings.volume); - } - else { - /* fade out */ - int fp_volume = fp_global_vol; - - while (fp_volume > fp_min_vol + fp_step) { - fp_volume -= fp_step; - sound_set_volume(fp_volume >> 8); - if (updatewps) - { - FOR_NB_SCREENS(i) - gui_wps_redraw(&gui_wps[i], 0, WPS_REFRESH_NON_STATIC); - } - sleep(1); - } - audio_pause(); - wps_fading_out = false; -#if CONFIG_CODEC != SWCODEC -#ifndef SIMULATOR - /* let audio thread run and wait for the mas to run out of data */ - while (!mp3_pause_done()) -#endif - sleep(HZ/10); -#endif - - /* reset volume to what it was before the fade */ - sound_set_volume(global_settings.volume); - } -} - -bool update_onvol_change(struct gui_wps * gwps) -{ - gui_wps_redraw(gwps, 0, WPS_REFRESH_NON_STATIC); - -#ifdef HAVE_LCD_CHARCELLS - splashf(0, "Vol: %3d dB", - sound_val2phys(SOUND_VOLUME, global_settings.volume)); - return true; -#endif - return false; -} - -bool ffwd_rew(int button) -{ - unsigned int step = 0; /* current ff/rewind step */ - unsigned int max_step = 0; /* maximum ff/rewind step */ - int ff_rewind_count = 0; /* current ff/rewind count (in ticks) */ - int direction = -1; /* forward=1 or backward=-1 */ - bool exit = false; - bool usb = false; - int i = 0; - const long ff_rw_accel = (global_settings.ff_rewind_accel + 3); - - if (button == ACTION_NONE) - { - status_set_ffmode(0); - return usb; - } - while (!exit) - { - switch ( button ) - { - case ACTION_WPS_SEEKFWD: - direction = 1; - case ACTION_WPS_SEEKBACK: - if (wps_state.ff_rewind) - { - if (direction == 1) - { - /* fast forwarding, calc max step relative to end */ - max_step = (wps_state.id3->length - - (wps_state.id3->elapsed + - ff_rewind_count)) * - FF_REWIND_MAX_PERCENT / 100; - } - else - { - /* rewinding, calc max step relative to start */ - max_step = (wps_state.id3->elapsed + ff_rewind_count) * - FF_REWIND_MAX_PERCENT / 100; - } - - max_step = MAX(max_step, MIN_FF_REWIND_STEP); - - if (step > max_step) - step = max_step; - - ff_rewind_count += step * direction; - - /* smooth seeking by multiplying step by: 1 + (2 ^ -accel) */ - step += step >> ff_rw_accel; - } - else - { - if ( (audio_status() & AUDIO_STATUS_PLAY) && - wps_state.id3 && wps_state.id3->length ) - { - if (!wps_state.paused) -#if (CONFIG_CODEC == SWCODEC) - audio_pre_ff_rewind(); -#else - audio_pause(); -#endif -#if CONFIG_KEYPAD == PLAYER_PAD - FOR_NB_SCREENS(i) - gui_wps[i].display->stop_scroll(); -#endif - if (direction > 0) - status_set_ffmode(STATUS_FASTFORWARD); - else - status_set_ffmode(STATUS_FASTBACKWARD); - - wps_state.ff_rewind = true; - - step = 1000 * global_settings.ff_rewind_min_step; - } - else - break; - } - - if (direction > 0) { - if ((wps_state.id3->elapsed + ff_rewind_count) > - wps_state.id3->length) - ff_rewind_count = wps_state.id3->length - - wps_state.id3->elapsed; - } - else { - if ((int)(wps_state.id3->elapsed + ff_rewind_count) < 0) - ff_rewind_count = -wps_state.id3->elapsed; - } - - FOR_NB_SCREENS(i) - gui_wps_redraw(&gui_wps[i], - (wps_state.wps_time_countup == false)? - ff_rewind_count:-ff_rewind_count, - WPS_REFRESH_PLAYER_PROGRESS | - WPS_REFRESH_DYNAMIC); - - break; - - case ACTION_WPS_STOPSEEK: - wps_state.id3->elapsed = wps_state.id3->elapsed+ff_rewind_count; - audio_ff_rewind(wps_state.id3->elapsed); - ff_rewind_count = 0; - wps_state.ff_rewind = false; - status_set_ffmode(0); -#if (CONFIG_CODEC != SWCODEC) - if (!wps_state.paused) - audio_resume(); -#endif -#ifdef HAVE_LCD_CHARCELLS - FOR_NB_SCREENS(i) - gui_wps_redraw(&gui_wps[i],0, WPS_REFRESH_ALL); -#endif - exit = true; - break; - - default: - if(default_event_handler(button) == SYS_USB_CONNECTED) { - status_set_ffmode(0); - usb = true; - exit = true; - } - break; - } - if (!exit) - { - button = get_action(CONTEXT_WPS|ALLOW_SOFTLOCK,TIMEOUT_BLOCK); -#ifdef HAVE_TOUCHSCREEN - if (button == ACTION_TOUCHSCREEN) - button = wps_get_touchaction(gui_wps[SCREEN_MAIN].data); -#endif - } - } - return usb; -} +#include "wps_internals.h" +#include "wps_engine.h" bool gui_wps_display(struct gui_wps *gwps) { @@ -364,15 +150,6 @@ bool gui_wps_update(struct gui_wps *gwps) } -void display_keylock_text(bool locked) -{ - int i; - FOR_NB_SCREENS(i) - gui_wps[i].display->stop_scroll(); - - splash(HZ, locked ? ID2P(LANG_KEYLOCK_ON) : ID2P(LANG_KEYLOCK_OFF)); -} - #ifdef HAVE_LCD_BITMAP static void draw_progressbar(struct gui_wps *gwps, @@ -605,755 +382,6 @@ static void draw_player_fullbar(struct gui_wps *gwps, char* buf, int buf_size) #endif /* HAVE_LCD_CHARCELL */ -static char* get_codectype(const struct mp3entry* id3) -{ - if (id3->codectype < AFMT_NUM_CODECS) { - return (char*)audio_formats[id3->codectype].label; - } else { - return NULL; - } -} - -/* Extract a part from a path. - * - * buf - buffer extract part to. - * buf_size - size of buffer. - * path - path to extract from. - * level - what to extract. 0 is file name, 1 is parent of file, 2 is - * parent of parent, etc. - * - * Returns buf if the desired level was found, NULL otherwise. - */ -static char* get_dir(char* buf, int buf_size, const char* path, int level) -{ - const char* sep; - const char* last_sep; - int len; - - sep = path + strlen(path); - last_sep = sep; - - while (sep > path) - { - if ('/' == *(--sep)) - { - if (!level) - break; - - level--; - last_sep = sep - 1; - } - } - - if (level || (last_sep <= sep)) - return NULL; - - len = MIN(last_sep - sep, buf_size - 1); - strlcpy(buf, sep + 1, len + 1); - return buf; -} - -/* Return the tag found at index i and write its value in buf. - The return value is buf if the tag had a value, or NULL if not. - - intval is used with conditionals/enums: when this function is called, - intval should contain the number of options in the conditional/enum. - When this function returns, intval is -1 if the tag is non numeric or, - if the tag is numeric, *intval is the enum case we want to go to (between 1 - and the original value of *intval, inclusive). - When not treating a conditional/enum, intval should be NULL. -*/ -static const char *get_token_value(struct gui_wps *gwps, - struct wps_token *token, - char *buf, int buf_size, - int *intval) -{ - if (!gwps) - return NULL; - - struct wps_data *data = gwps->data; - struct wps_state *state = gwps->state; - - if (!data || !state) - return NULL; - - struct mp3entry *id3; - - if (token->next) - id3 = state->nid3; - else - id3 = state->id3; - - if (!id3) - return NULL; - -#if CONFIG_RTC - struct tm* tm = NULL; - - /* if the token is an RTC one, update the time - and do the necessary checks */ - if (token->type >= WPS_TOKENS_RTC_BEGIN - && token->type <= WPS_TOKENS_RTC_END) - { - tm = get_time(); - - if (!valid_time(tm)) - return NULL; - } -#endif - - int limit = 1; - if (intval) - { - limit = *intval; - *intval = -1; - } - - switch (token->type) - { - case WPS_TOKEN_CHARACTER: - return &(token->value.c); - - case WPS_TOKEN_STRING: - return data->strings[token->value.i]; - - case WPS_TOKEN_TRACK_TIME_ELAPSED: - format_time(buf, buf_size, - id3->elapsed + state->ff_rewind_count); - return buf; - - case WPS_TOKEN_TRACK_TIME_REMAINING: - format_time(buf, buf_size, - id3->length - id3->elapsed - - state->ff_rewind_count); - return buf; - - case WPS_TOKEN_TRACK_LENGTH: - format_time(buf, buf_size, id3->length); - return buf; - - case WPS_TOKEN_PLAYLIST_ENTRIES: - snprintf(buf, buf_size, "%d", playlist_amount()); - return buf; - - case WPS_TOKEN_PLAYLIST_NAME: - return playlist_name(NULL, buf, buf_size); - - case WPS_TOKEN_PLAYLIST_POSITION: - snprintf(buf, buf_size, "%d", playlist_get_display_index()); - return buf; - - case WPS_TOKEN_PLAYLIST_SHUFFLE: - if ( global_settings.playlist_shuffle ) - return "s"; - else - return NULL; - break; - - case WPS_TOKEN_VOLUME: - snprintf(buf, buf_size, "%d", global_settings.volume); - if (intval) - { - if (global_settings.volume == sound_min(SOUND_VOLUME)) - { - *intval = 1; - } - else if (global_settings.volume == 0) - { - *intval = limit - 1; - } - else if (global_settings.volume > 0) - { - *intval = limit; - } - else - { - *intval = (limit - 3) * (global_settings.volume - - sound_min(SOUND_VOLUME) - 1) - / (-1 - sound_min(SOUND_VOLUME)) + 2; - } - } - return buf; - - case WPS_TOKEN_TRACK_ELAPSED_PERCENT: - if (id3->length <= 0) - return NULL; - - if (intval) - { - *intval = limit * (id3->elapsed + state->ff_rewind_count) - / id3->length + 1; - } - snprintf(buf, buf_size, "%d", - 100*(id3->elapsed + state->ff_rewind_count) / id3->length); - return buf; - - case WPS_TOKEN_METADATA_ARTIST: - return id3->artist; - - case WPS_TOKEN_METADATA_COMPOSER: - return id3->composer; - - case WPS_TOKEN_METADATA_ALBUM: - return id3->album; - - case WPS_TOKEN_METADATA_ALBUM_ARTIST: - return id3->albumartist; - - case WPS_TOKEN_METADATA_GROUPING: - return id3->grouping; - - case WPS_TOKEN_METADATA_GENRE: - return id3->genre_string; - - case WPS_TOKEN_METADATA_DISC_NUMBER: - if (id3->disc_string) - return id3->disc_string; - if (id3->discnum) { - snprintf(buf, buf_size, "%d", id3->discnum); - return buf; - } - return NULL; - - case WPS_TOKEN_METADATA_TRACK_NUMBER: - if (id3->track_string) - return id3->track_string; - - if (id3->tracknum) { - snprintf(buf, buf_size, "%d", id3->tracknum); - return buf; - } - return NULL; - - case WPS_TOKEN_METADATA_TRACK_TITLE: - return id3->title; - - case WPS_TOKEN_METADATA_VERSION: - switch (id3->id3version) - { - case ID3_VER_1_0: - return "1"; - - case ID3_VER_1_1: - return "1.1"; - - case ID3_VER_2_2: - return "2.2"; - - case ID3_VER_2_3: - return "2.3"; - - case ID3_VER_2_4: - return "2.4"; - - default: - return NULL; - } - - case WPS_TOKEN_METADATA_YEAR: - if( id3->year_string ) - return id3->year_string; - - if (id3->year) { - snprintf(buf, buf_size, "%d", id3->year); - return buf; - } - return NULL; - - case WPS_TOKEN_METADATA_COMMENT: - return id3->comment; - -#ifdef HAVE_ALBUMART - case WPS_TOKEN_ALBUMART_DISPLAY: - draw_album_art(gwps, audio_current_aa_hid(), false); - return NULL; - - case WPS_TOKEN_ALBUMART_FOUND: - if (audio_current_aa_hid() >= 0) { - return "C"; - } - return NULL; -#endif - - case WPS_TOKEN_FILE_BITRATE: - if(id3->bitrate) - snprintf(buf, buf_size, "%d", id3->bitrate); - else - return "?"; - return buf; - - case WPS_TOKEN_FILE_CODEC: - if (intval) - { - if(id3->codectype == AFMT_UNKNOWN) - *intval = AFMT_NUM_CODECS; - else - *intval = id3->codectype; - } - return get_codectype(id3); - - case WPS_TOKEN_FILE_FREQUENCY: - snprintf(buf, buf_size, "%ld", id3->frequency); - return buf; - - case WPS_TOKEN_FILE_FREQUENCY_KHZ: - /* ignore remainders < 100, so 22050 Hz becomes just 22k */ - if ((id3->frequency % 1000) < 100) - snprintf(buf, buf_size, "%ld", id3->frequency / 1000); - else - snprintf(buf, buf_size, "%ld.%d", - id3->frequency / 1000, - (id3->frequency % 1000) / 100); - return buf; - - case WPS_TOKEN_FILE_NAME: - if (get_dir(buf, buf_size, id3->path, 0)) { - /* Remove extension */ - char* sep = strrchr(buf, '.'); - if (NULL != sep) { - *sep = 0; - } - return buf; - } - else { - return NULL; - } - - case WPS_TOKEN_FILE_NAME_WITH_EXTENSION: - return get_dir(buf, buf_size, id3->path, 0); - - case WPS_TOKEN_FILE_PATH: - return id3->path; - - case WPS_TOKEN_FILE_SIZE: - snprintf(buf, buf_size, "%ld", id3->filesize / 1024); - return buf; - - case WPS_TOKEN_FILE_VBR: - return id3->vbr ? "(avg)" : NULL; - - case WPS_TOKEN_FILE_DIRECTORY: - return get_dir(buf, buf_size, id3->path, token->value.i); - - case WPS_TOKEN_BATTERY_PERCENT: - { - int l = battery_level(); - - if (intval) - { - limit = MAX(limit, 2); - if (l > -1) { - /* First enum is used for "unknown level". */ - *intval = (limit - 1) * l / 100 + 2; - } else { - *intval = 1; - } - } - - if (l > -1) { - snprintf(buf, buf_size, "%d", l); - return buf; - } else { - return "?"; - } - } - - case WPS_TOKEN_BATTERY_VOLTS: - { - unsigned int v = battery_voltage(); - snprintf(buf, buf_size, "%d.%02d", v / 1000, (v % 1000) / 10); - return buf; - } - - case WPS_TOKEN_BATTERY_TIME: - { - int t = battery_time(); - if (t >= 0) - snprintf(buf, buf_size, "%dh %dm", t / 60, t % 60); - else - return "?h ?m"; - return buf; - } - -#if CONFIG_CHARGING - case WPS_TOKEN_BATTERY_CHARGER_CONNECTED: - { - if(charger_input_state==CHARGER) - return "p"; - else - return NULL; - } -#endif -#if CONFIG_CHARGING >= CHARGING_MONITOR - case WPS_TOKEN_BATTERY_CHARGING: - { - if (charge_state == CHARGING || charge_state == TOPOFF) { - return "c"; - } else { - return NULL; - } - } -#endif - case WPS_TOKEN_BATTERY_SLEEPTIME: - { - if (get_sleep_timer() == 0) - return NULL; - else - { - format_time(buf, buf_size, get_sleep_timer() * 1000); - return buf; - } - } - - case WPS_TOKEN_PLAYBACK_STATUS: - { - int status = audio_status(); - int mode = 1; - if (status == AUDIO_STATUS_PLAY) - mode = 2; - if (wps_fading_out || - (status & AUDIO_STATUS_PAUSE && !status_get_ffmode())) - mode = 3; - if (status_get_ffmode() == STATUS_FASTFORWARD) - mode = 4; - if (status_get_ffmode() == STATUS_FASTBACKWARD) - mode = 5; - - if (intval) { - *intval = mode; - } - - snprintf(buf, buf_size, "%d", mode-1); - return buf; - } - - case WPS_TOKEN_REPEAT_MODE: - if (intval) - *intval = global_settings.repeat_mode + 1; - snprintf(buf, buf_size, "%d", global_settings.repeat_mode); - return buf; - - case WPS_TOKEN_RTC_PRESENT: -#if CONFIG_RTC - return "c"; -#else - return NULL; -#endif - -#if CONFIG_RTC - case WPS_TOKEN_RTC_12HOUR_CFG: - if (intval) - *intval = global_settings.timeformat + 1; - snprintf(buf, buf_size, "%d", global_settings.timeformat); - return buf; - - case WPS_TOKEN_RTC_DAY_OF_MONTH: - /* d: day of month (01..31) */ - snprintf(buf, buf_size, "%02d", tm->tm_mday); - return buf; - - case WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED: - /* e: day of month, blank padded ( 1..31) */ - snprintf(buf, buf_size, "%2d", tm->tm_mday); - return buf; - - case WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED: - /* H: hour (00..23) */ - snprintf(buf, buf_size, "%02d", tm->tm_hour); - return buf; - - case WPS_TOKEN_RTC_HOUR_24: - /* k: hour ( 0..23) */ - snprintf(buf, buf_size, "%2d", tm->tm_hour); - return buf; - - case WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED: - /* I: hour (01..12) */ - snprintf(buf, buf_size, "%02d", - (tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12); - return buf; - - case WPS_TOKEN_RTC_HOUR_12: - /* l: hour ( 1..12) */ - snprintf(buf, buf_size, "%2d", - (tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12); - return buf; - - case WPS_TOKEN_RTC_MONTH: - /* m: month (01..12) */ - if (intval) - *intval = tm->tm_mon + 1; - snprintf(buf, buf_size, "%02d", tm->tm_mon + 1); - return buf; - - case WPS_TOKEN_RTC_MINUTE: - /* M: minute (00..59) */ - snprintf(buf, buf_size, "%02d", tm->tm_min); - return buf; - - case WPS_TOKEN_RTC_SECOND: - /* S: second (00..59) */ - snprintf(buf, buf_size, "%02d", tm->tm_sec); - return buf; - - case WPS_TOKEN_RTC_YEAR_2_DIGITS: - /* y: last two digits of year (00..99) */ - snprintf(buf, buf_size, "%02d", tm->tm_year % 100); - return buf; - - case WPS_TOKEN_RTC_YEAR_4_DIGITS: - /* Y: year (1970...) */ - snprintf(buf, buf_size, "%04d", tm->tm_year + 1900); - return buf; - - case WPS_TOKEN_RTC_AM_PM_UPPER: - /* p: upper case AM or PM indicator */ - return tm->tm_hour/12 == 0 ? "AM" : "PM"; - - case WPS_TOKEN_RTC_AM_PM_LOWER: - /* P: lower case am or pm indicator */ - return tm->tm_hour/12 == 0 ? "am" : "pm"; - - case WPS_TOKEN_RTC_WEEKDAY_NAME: - /* a: abbreviated weekday name (Sun..Sat) */ - return str(LANG_WEEKDAY_SUNDAY + tm->tm_wday); - - case WPS_TOKEN_RTC_MONTH_NAME: - /* b: abbreviated month name (Jan..Dec) */ - return str(LANG_MONTH_JANUARY + tm->tm_mon); - - case WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON: - /* u: day of week (1..7); 1 is Monday */ - if (intval) - *intval = (tm->tm_wday == 0) ? 7 : tm->tm_wday; - snprintf(buf, buf_size, "%1d", tm->tm_wday + 1); - return buf; - - case WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN: - /* w: day of week (0..6); 0 is Sunday */ - if (intval) - *intval = tm->tm_wday + 1; - snprintf(buf, buf_size, "%1d", tm->tm_wday); - return buf; -#else - case WPS_TOKEN_RTC_DAY_OF_MONTH: - case WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED: - case WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED: - case WPS_TOKEN_RTC_HOUR_24: - case WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED: - case WPS_TOKEN_RTC_HOUR_12: - case WPS_TOKEN_RTC_MONTH: - case WPS_TOKEN_RTC_MINUTE: - case WPS_TOKEN_RTC_SECOND: - case WPS_TOKEN_RTC_AM_PM_UPPER: - case WPS_TOKEN_RTC_AM_PM_LOWER: - case WPS_TOKEN_RTC_YEAR_2_DIGITS: - return "--"; - case WPS_TOKEN_RTC_YEAR_4_DIGITS: - return "----"; - case WPS_TOKEN_RTC_WEEKDAY_NAME: - case WPS_TOKEN_RTC_MONTH_NAME: - return "---"; - case WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON: - case WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN: - return "-"; -#endif - -#ifdef HAVE_LCD_CHARCELLS - case WPS_TOKEN_PROGRESSBAR: - { - char *end = utf8encode(data->wps_progress_pat[0], buf); - *end = '\0'; - return buf; - } - - case WPS_TOKEN_PLAYER_PROGRESSBAR: - if(is_new_player()) - { - /* we need 11 characters (full line) for - progress-bar */ - strlcpy(buf, " ", buf_size); - } - else - { - /* Tell the user if we have an OldPlayer */ - strlcpy(buf, " ", buf_size); - } - return buf; -#endif - -#ifdef HAVE_TAGCACHE - case WPS_TOKEN_DATABASE_PLAYCOUNT: - if (intval) { - *intval = id3->playcount + 1; - } - snprintf(buf, buf_size, "%ld", id3->playcount); - return buf; - - case WPS_TOKEN_DATABASE_RATING: - if (intval) { - *intval = id3->rating + 1; - } - snprintf(buf, buf_size, "%d", id3->rating); - return buf; - - case WPS_TOKEN_DATABASE_AUTOSCORE: - if (intval) - *intval = id3->score + 1; - - snprintf(buf, buf_size, "%d", id3->score); - return buf; -#endif - -#if (CONFIG_CODEC == SWCODEC) - case WPS_TOKEN_CROSSFADE: - if (intval) - *intval = global_settings.crossfade + 1; - snprintf(buf, buf_size, "%d", global_settings.crossfade); - return buf; - - case WPS_TOKEN_REPLAYGAIN: - { - int val; - - if (global_settings.replaygain_type == REPLAYGAIN_OFF) - val = 1; /* off */ - else - { - int type = - get_replaygain_mode(id3->track_gain_string != NULL, - id3->album_gain_string != NULL); - if (type < 0) - val = 6; /* no tag */ - else - val = type + 2; - - if (global_settings.replaygain_type == REPLAYGAIN_SHUFFLE) - val += 2; - } - - if (intval) - *intval = val; - - switch (val) - { - case 1: - case 6: - return "+0.00 dB"; - break; - case 2: - case 4: - strlcpy(buf, id3->track_gain_string, buf_size); - break; - case 3: - case 5: - strlcpy(buf, id3->album_gain_string, buf_size); - break; - } - return buf; - } -#endif /* (CONFIG_CODEC == SWCODEC) */ - -#if (CONFIG_CODEC != MAS3507D) - case WPS_TOKEN_SOUND_PITCH: - { - int val = sound_get_pitch(); - snprintf(buf, buf_size, "%d.%d", - val / 10, val % 10); - return buf; - } -#endif - - case WPS_TOKEN_MAIN_HOLD: -#ifdef HAS_BUTTON_HOLD - if (button_hold()) -#else - if (is_keys_locked()) -#endif /*hold switch or softlock*/ - return "h"; - else - return NULL; - -#ifdef HAS_REMOTE_BUTTON_HOLD - case WPS_TOKEN_REMOTE_HOLD: - if (remote_button_hold()) - return "r"; - else - return NULL; -#endif - -#if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD) - case WPS_TOKEN_VLED_HDD: - if(led_read(HZ/2)) - return "h"; - else - return NULL; -#endif - case WPS_TOKEN_BUTTON_VOLUME: - if (data->button_time_volume && - TIME_BEFORE(current_tick, data->button_time_volume + - token->value.i * TIMEOUT_UNIT)) - return "v"; - return NULL; - case WPS_TOKEN_LASTTOUCH: -#ifdef HAVE_TOUCHSCREEN - if (TIME_BEFORE(current_tick, token->value.i * TIMEOUT_UNIT + - touchscreen_last_touch())) - return "t"; -#endif - return NULL; - - case WPS_TOKEN_SETTING: - { - if (intval) - { - /* Handle contionals */ - const struct settings_list *s = settings+token->value.i; - switch (s->flags&F_T_MASK) - { - case F_T_INT: - case F_T_UINT: - if (s->flags&F_RGB) - /* %?St|name|<#000000|#000001|...|#FFFFFF> */ - /* shouldn't overflow since colors are stored - * on 16 bits ... - * but this is pretty useless anyway */ - *intval = *(int*)s->setting + 1; - else if (s->cfg_vals == NULL) - /* %?St|name|<1st choice|2nd choice|...> */ - *intval = (*(int*)s->setting-s->int_setting->min) - /s->int_setting->step + 1; - else - /* %?St|name|<1st choice|2nd choice|...> */ - /* Not sure about this one. cfg_name/vals are - * indexed from 0 right? */ - *intval = *(int*)s->setting + 1; - break; - case F_T_BOOL: - /* %?St|name| */ - *intval = *(bool*)s->setting?1:2; - break; - case F_T_CHARPTR: - /* %?St|name| - * The string's emptyness discards the setting's - * prefix and suffix */ - *intval = ((char*)s->setting)[0]?1:2; - break; - default: - /* This shouldn't happen ... but you never know */ - *intval = -1; - break; - } - } - cfg_to_string(token->value.i,buf,buf_size); - return buf; - } - - default: - return NULL; - } -} - /* Return the index to the end token for the conditional token at index. The conditional token can be either a start token or a separator (i.e. option) token. diff --git a/apps/gui/wps_engine/wps_engine.h b/apps/gui/wps_engine/wps_engine.h new file mode 100644 index 0000000000..fe034f9138 --- /dev/null +++ b/apps/gui/wps_engine/wps_engine.h @@ -0,0 +1,49 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: gwps.h 22003 2009-07-22 22:10:25Z kugel $ + * + * Copyright (C) 2007 Nicolas Pennequin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + + /** Use this for stuff which external code needs to include **/ + +#ifndef _WPS_ENGINE_H +#define _WPS_ENGINE_H +#include +#include "wps_internals.h" /* TODO: remove this line.. shoudlnt be needed */ + + +#ifdef HAVE_TOUCHSCREEN +int wps_get_touchaction(struct wps_data *data); +#endif + +#ifdef HAVE_ALBUMART +/* gives back if WPS contains an albumart tag */ +bool gui_sync_wps_uses_albumart(void); +#endif + +/* setup and display a WPS for the first time */ +bool gui_wps_display(struct gui_wps *gwps); +/* do a requested redraw */ +bool gui_wps_redraw(struct gui_wps *gwps, + int ffwd_offset, + unsigned refresh_mode); +/* do a partial redraw, or full if required, also do any housekeeping + * which might be needed */ +bool gui_wps_update(struct gui_wps *gwps); + +#endif diff --git a/apps/gui/wps_engine/wps_internals.h b/apps/gui/wps_engine/wps_internals.h new file mode 100644 index 0000000000..581763fb9a --- /dev/null +++ b/apps/gui/wps_engine/wps_internals.h @@ -0,0 +1,556 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2007 Nicolas Pennequin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + + /* This stuff is for the wps engine only.. anyone caught using this outside + * of apps/gui/wps_engine will be shot on site! */ + +#ifndef _WPS_ENGINE_INTERNALS_ +#define _WPS_ENGINE_INTERNALS_ +/* Timeout unit expressed in HZ. In WPS, all timeouts are given in seconds + (possibly with a decimal fraction) but stored as integer values. + E.g. 2.5 is stored as 25. This means 25 tenth of a second, i.e. 25 units. +*/ +#define TIMEOUT_UNIT (HZ/10) /* I.e. 0.1 sec */ +#define DEFAULT_SUBLINE_TIME_MULTIPLIER 20 /* In TIMEOUT_UNIT's */ + + + + +/* TODO: sort this mess out */ + +#include "screen_access.h" +#include "statusbar.h" +#include "metadata.h" + +/* constants used in line_type and as refresh_mode for wps_refresh */ +#define WPS_REFRESH_STATIC (1u<<0) /* line doesn't change over time */ +#define WPS_REFRESH_DYNAMIC (1u<<1) /* line may change (e.g. time flag) */ +#define WPS_REFRESH_SCROLL (1u<<2) /* line scrolls */ +#define WPS_REFRESH_PLAYER_PROGRESS (1u<<3) /* line contains a progress bar */ +#define WPS_REFRESH_PEAK_METER (1u<<4) /* line contains a peak meter */ +#define WPS_REFRESH_STATUSBAR (1u<<5) /* refresh statusbar */ +#define WPS_REFRESH_ALL (0xffffffffu) /* to refresh all line types */ + +/* to refresh only those lines that change over time */ +#define WPS_REFRESH_NON_STATIC (WPS_REFRESH_DYNAMIC| \ + WPS_REFRESH_PLAYER_PROGRESS| \ + WPS_REFRESH_PEAK_METER) +/* alignments */ +#define WPS_ALIGN_RIGHT 32 +#define WPS_ALIGN_CENTER 64 +#define WPS_ALIGN_LEFT 128 + +#ifdef HAVE_ALBUMART + +/* albumart definitions */ +#define WPS_ALBUMART_NONE 0 /* WPS does not contain AA tag */ +#define WPS_ALBUMART_CHECK 1 /* WPS contains AA conditional tag */ +#define WPS_ALBUMART_LOAD 2 /* WPS contains AA tag */ + +#define WPS_ALBUMART_ALIGN_RIGHT 1 /* x align: right */ +#define WPS_ALBUMART_ALIGN_CENTER 2 /* x/y align: center */ +#define WPS_ALBUMART_ALIGN_LEFT 4 /* x align: left */ +#define WPS_ALBUMART_ALIGN_TOP 1 /* y align: top */ +#define WPS_ALBUMART_ALIGN_BOTTOM 4 /* y align: bottom */ + +#endif /* HAVE_ALBUMART */ + +/* wps_data*/ + +#ifdef HAVE_LCD_BITMAP +struct gui_img { + struct bitmap bm; + struct viewport* vp; /* The viewport to display this image in */ + short int x; /* x-pos */ + short int y; /* y-pos */ + short int num_subimages; /* number of sub-images */ + short int subimage_height; /* height of each sub-image */ + short int display; /* -1 for no display, 0..n to display a subimage */ + bool loaded; /* load state */ + bool always_display; /* not using the preload/display mechanism */ +}; + +struct progressbar { + /* regular pb */ + short x; + /* >=0: explicitly set in the tag -> y-coord within the viewport + <0 : not set in the tag -> negated 1-based line number within + the viewport. y-coord will be computed based on the font height */ + short y; + short width; + short height; + /*progressbar image*/ + struct bitmap bm; + bool have_bitmap_pb; +}; +#endif + + + +struct align_pos { + char* left; + char* center; + char* right; +}; + +#ifdef HAVE_LCD_BITMAP + +#define MAX_IMAGES (26*2) /* a-z and A-Z */ +#define MAX_PROGRESSBARS 3 + +/* The image buffer is big enough to store one full-screen native bitmap, + plus two full-screen mono bitmaps. */ + +#define IMG_BUFSIZE ((LCD_HEIGHT*LCD_WIDTH*LCD_DEPTH/8) \ + + (2*LCD_HEIGHT*LCD_WIDTH/8)) + +#define WPS_MAX_VIEWPORTS 24 +#define WPS_MAX_LINES ((LCD_HEIGHT/5+1) * 2) +#define WPS_MAX_SUBLINES (WPS_MAX_LINES*3) +#define WPS_MAX_TOKENS 1024 +#define WPS_MAX_STRINGS 128 +#define STRING_BUFFER_SIZE 1024 +#define WPS_MAX_COND_LEVEL 10 + +#else + +#define WPS_MAX_VIEWPORTS 2 +#define WPS_MAX_LINES 2 +#define WPS_MAX_SUBLINES 12 +#define WPS_MAX_TOKENS 64 +#define WPS_MAX_STRINGS 32 +#define STRING_BUFFER_SIZE 64 +#define WPS_MAX_COND_LEVEL 5 + +#endif + +#define SUBLINE_RESET -1 + +enum wps_parse_error { + PARSE_OK, + PARSE_FAIL_UNCLOSED_COND, + PARSE_FAIL_INVALID_CHAR, + PARSE_FAIL_COND_SYNTAX_ERROR, + PARSE_FAIL_COND_INVALID_PARAM, + PARSE_FAIL_LIMITS_EXCEEDED, +}; + +enum wps_token_type { + WPS_NO_TOKEN, /* for WPS tags we don't want to save as tokens */ + WPS_TOKEN_UNKNOWN, + + /* Markers */ + WPS_TOKEN_CHARACTER, + WPS_TOKEN_STRING, + + /* Alignment */ + WPS_TOKEN_ALIGN_LEFT, + WPS_TOKEN_ALIGN_CENTER, + WPS_TOKEN_ALIGN_RIGHT, + + /* Sublines */ + WPS_TOKEN_SUBLINE_TIMEOUT, + + /* Battery */ + WPS_TOKEN_BATTERY_PERCENT, + WPS_TOKEN_BATTERY_VOLTS, + WPS_TOKEN_BATTERY_TIME, + WPS_TOKEN_BATTERY_CHARGER_CONNECTED, + WPS_TOKEN_BATTERY_CHARGING, + WPS_TOKEN_BATTERY_SLEEPTIME, + + /* Sound */ +#if (CONFIG_CODEC != MAS3507D) + WPS_TOKEN_SOUND_PITCH, +#endif +#if (CONFIG_CODEC == SWCODEC) + WPS_TOKEN_REPLAYGAIN, + WPS_TOKEN_CROSSFADE, +#endif + + /* Time */ + + WPS_TOKEN_RTC_PRESENT, + + /* The begin/end values allow us to know if a token is an RTC one. + New RTC tokens should be added between the markers. */ + + WPS_TOKENS_RTC_BEGIN, /* just the start marker, not an actual token */ + + WPS_TOKEN_RTC_DAY_OF_MONTH, + WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED, + WPS_TOKEN_RTC_12HOUR_CFG, + WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED, + WPS_TOKEN_RTC_HOUR_24, + WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED, + WPS_TOKEN_RTC_HOUR_12, + WPS_TOKEN_RTC_MONTH, + WPS_TOKEN_RTC_MINUTE, + WPS_TOKEN_RTC_SECOND, + WPS_TOKEN_RTC_YEAR_2_DIGITS, + WPS_TOKEN_RTC_YEAR_4_DIGITS, + WPS_TOKEN_RTC_AM_PM_UPPER, + WPS_TOKEN_RTC_AM_PM_LOWER, + WPS_TOKEN_RTC_WEEKDAY_NAME, + WPS_TOKEN_RTC_MONTH_NAME, + WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON, + WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN, + + WPS_TOKENS_RTC_END, /* just the end marker, not an actual token */ + + /* Conditional */ + WPS_TOKEN_CONDITIONAL, + WPS_TOKEN_CONDITIONAL_START, + WPS_TOKEN_CONDITIONAL_OPTION, + WPS_TOKEN_CONDITIONAL_END, + + /* Database */ +#ifdef HAVE_TAGCACHE + WPS_TOKEN_DATABASE_PLAYCOUNT, + WPS_TOKEN_DATABASE_RATING, + WPS_TOKEN_DATABASE_AUTOSCORE, +#endif + + /* File */ + WPS_TOKEN_FILE_BITRATE, + WPS_TOKEN_FILE_CODEC, + WPS_TOKEN_FILE_FREQUENCY, + WPS_TOKEN_FILE_FREQUENCY_KHZ, + WPS_TOKEN_FILE_NAME, + WPS_TOKEN_FILE_NAME_WITH_EXTENSION, + WPS_TOKEN_FILE_PATH, + WPS_TOKEN_FILE_SIZE, + WPS_TOKEN_FILE_VBR, + WPS_TOKEN_FILE_DIRECTORY, + +#ifdef HAVE_LCD_BITMAP + /* Image */ + WPS_TOKEN_IMAGE_BACKDROP, + WPS_TOKEN_IMAGE_PROGRESS_BAR, + WPS_TOKEN_IMAGE_PRELOAD, + WPS_TOKEN_IMAGE_PRELOAD_DISPLAY, + WPS_TOKEN_IMAGE_DISPLAY, +#endif + +#ifdef HAVE_ALBUMART + /* Albumart */ + WPS_TOKEN_ALBUMART_DISPLAY, + WPS_TOKEN_ALBUMART_FOUND, +#endif + + /* Metadata */ + WPS_TOKEN_METADATA_ARTIST, + WPS_TOKEN_METADATA_COMPOSER, + WPS_TOKEN_METADATA_ALBUM_ARTIST, + WPS_TOKEN_METADATA_GROUPING, + WPS_TOKEN_METADATA_ALBUM, + WPS_TOKEN_METADATA_GENRE, + WPS_TOKEN_METADATA_DISC_NUMBER, + WPS_TOKEN_METADATA_TRACK_NUMBER, + WPS_TOKEN_METADATA_TRACK_TITLE, + WPS_TOKEN_METADATA_VERSION, + WPS_TOKEN_METADATA_YEAR, + WPS_TOKEN_METADATA_COMMENT, + + /* Mode */ + WPS_TOKEN_REPEAT_MODE, + WPS_TOKEN_PLAYBACK_STATUS, + + WPS_TOKEN_MAIN_HOLD, + +#ifdef HAS_REMOTE_BUTTON_HOLD + WPS_TOKEN_REMOTE_HOLD, +#endif + + /* Progressbar */ + WPS_TOKEN_PROGRESSBAR, +#ifdef HAVE_LCD_CHARCELLS + WPS_TOKEN_PLAYER_PROGRESSBAR, +#endif + +#ifdef HAVE_LCD_BITMAP + /* Peakmeter */ + WPS_TOKEN_PEAKMETER, +#endif + + /* Volume level */ + WPS_TOKEN_VOLUME, + + /* Current track */ + WPS_TOKEN_TRACK_ELAPSED_PERCENT, + WPS_TOKEN_TRACK_TIME_ELAPSED, + WPS_TOKEN_TRACK_TIME_REMAINING, + WPS_TOKEN_TRACK_LENGTH, + + /* Playlist */ + WPS_TOKEN_PLAYLIST_ENTRIES, + WPS_TOKEN_PLAYLIST_NAME, + WPS_TOKEN_PLAYLIST_POSITION, + WPS_TOKEN_PLAYLIST_SHUFFLE, + +#if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD) + /* Virtual LED */ + WPS_TOKEN_VLED_HDD, +#endif + + /* Viewport display */ + WPS_VIEWPORT_ENABLE, + + /* buttons */ + WPS_TOKEN_BUTTON_VOLUME, + WPS_TOKEN_LASTTOUCH, + + /* Setting option */ + WPS_TOKEN_SETTING, +}; + +struct wps_token { + unsigned char type; /* enough to store the token type */ + + /* Whether the tag (e.g. track name or the album) refers the + current or the next song (false=current, true=next) */ + bool next; + + union { + char c; + unsigned short i; + } value; +}; + +/* Description of a subline on the WPS */ +struct wps_subline { + + /* Index of the first token for this subline in the token array. + Tokens of this subline end where tokens for the next subline + begin. */ + unsigned short first_token_idx; + + /* Bit or'ed WPS_REFRESH_xxx */ + unsigned char line_type; + + /* How long the subline should be displayed, in 10ths of sec */ + unsigned char time_mult; +}; + +/* Description of a line on the WPS. A line is a set of sublines. + A subline is displayed for a certain amount of time. After that, + the next subline of the line is displayed. And so on. */ +struct wps_line { + + /* Number of sublines in this line */ + signed char num_sublines; + + /* Number (0-based) of the subline within this line currently being displayed */ + signed char curr_subline; + + /* Index of the first subline of this line in the subline array. + Sublines for this line end where sublines for the next line begin. */ + unsigned short first_subline_idx; + + /* When the next subline of this line should be displayed + (absolute time value in ticks) */ + long subline_expire_time; +}; + +#define VP_DRAW_HIDEABLE 0x1 +#define VP_DRAW_HIDDEN 0x2 +#define VP_DRAW_WASHIDDEN 0x4 +struct wps_viewport { + struct viewport vp; /* The LCD viewport struct */ + struct progressbar *pb; + /* Indexes of the first and last lines belonging to this viewport in the + lines[] array */ + int first_line, last_line; + char hidden_flags; + char label; +}; + +#ifdef HAVE_TOUCHSCREEN +struct touchregion { + struct wps_viewport* wvp;/* The viewport this region is in */ + short int x; /* x-pos */ + short int y; /* y-pos */ + short int width; /* width */ + short int height; /* height */ + bool repeat; /* requires the area be held for the action */ + int action; /* action this button will return */ +}; +#define MAX_TOUCHREGIONS 15 +#endif +/* wps_data + this struct holds all necessary data which describes the + viewable content of a wps */ +struct wps_data +{ +#ifdef HAVE_LCD_BITMAP + struct gui_img img[MAX_IMAGES]; + unsigned char img_buf[IMG_BUFSIZE]; + unsigned char* img_buf_ptr; + int img_buf_free; + bool wps_sb_tag; + bool show_sb_on_wps; + + struct progressbar progressbar[MAX_PROGRESSBARS]; + short progressbar_count; + + bool peak_meter_enabled; + +#ifdef HAVE_ALBUMART + /* Album art support */ + unsigned char wps_uses_albumart; /* WPS_ALBUMART_NONE, _CHECK, _LOAD */ + short albumart_x; + short albumart_y; + unsigned char albumart_xalign; /* WPS_ALBUMART_ALIGN_LEFT, _CENTER, _RIGHT */ + unsigned char albumart_yalign; /* WPS_ALBUMART_ALIGN_TOP, _CENTER, _BOTTOM */ + short albumart_max_width; + short albumart_max_height; + + int albumart_cond_index; +#endif + +#else /*HAVE_LCD_CHARCELLS */ + unsigned short wps_progress_pat[8]; + bool full_line_progressbar; +#endif + +#ifdef HAVE_TOUCHSCREEN + struct touchregion touchregion[MAX_TOUCHREGIONS]; + short touchregion_count; +#endif + +#ifdef HAVE_REMOTE_LCD + bool remote_wps; +#endif + + /* Number of lines in the WPS. During WPS parsing, this is + the index of the line being parsed. */ + int num_lines; + + /* Number of viewports in the WPS */ + int num_viewports; + struct wps_viewport viewports[WPS_MAX_VIEWPORTS]; + + struct wps_line lines[WPS_MAX_LINES]; + + /* Total number of sublines in the WPS. During WPS parsing, this is + the index of the subline where the parsed tokens are added to. */ + int num_sublines; + struct wps_subline sublines[WPS_MAX_SUBLINES]; + + /* Total number of tokens in the WPS. During WPS parsing, this is + the index of the token being parsed. */ + int num_tokens; + struct wps_token tokens[WPS_MAX_TOKENS]; + + char string_buffer[STRING_BUFFER_SIZE]; + char *strings[WPS_MAX_STRINGS]; + int num_strings; + + bool wps_loaded; + + /* tick the volume button was last pressed */ + unsigned int button_time_volume; +}; + +/* initial setup of wps_data */ +void wps_data_init(struct wps_data *wps_data); + +/* to setup up the wps-data from a format-buffer (isfile = false) + from a (wps-)file (isfile = true)*/ +bool wps_data_load(struct wps_data *wps_data, + struct screen *display, + const char *buf, + bool isfile); + +/* Redraw statusbars if necessary */ +void gwps_draw_statusbars(void); + +/* Returns the index of the subline in the subline array + line - 0-based line number + subline - 0-based subline number within the line + */ +int wps_subline_index(struct wps_data *wps_data, int line, int subline); + +/* Returns the index of the first subline's token in the token array + line - 0-based line number + subline - 0-based subline number within the line + */ +int wps_first_token_index(struct wps_data *data, int line, int subline); + +/* Returns the index of the last subline's token in the token array. + line - 0-based line number + subline - 0-based subline number within the line + */ +int wps_last_token_index(struct wps_data *data, int line, int subline); + +/* wps_data end */ + +/* wps_state + 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 */ +struct wps_state +{ + bool ff_rewind; + bool paused; + int ff_rewind_count; + bool wps_time_countup; + struct mp3entry* id3; + struct mp3entry* nid3; + bool do_full_update; +}; + + +/* change the ff/rew-status + if ff_rew = true then we are in skipping mode + else we are in normal mode */ +/* void wps_state_update_ff_rew(bool ff_rew); Currently unused */ + +/* change the tag-information of the current played track + and the following track */ +/* void wps_state_update_id3_nid3(struct mp3entry *id3, struct mp3entry *nid3); Currently unused */ +/* wps_state end*/ + +/* gui_wps + defines a wps with its data, state, + and the screen on which the wps-content should be drawn */ +struct gui_wps +{ + struct screen *display; + struct wps_data *data; + struct wps_state *state; +}; + +/* gui_wps end */ + + +/* currently only on wps_state is needed */ +extern struct wps_state wps_state; +extern struct gui_wps gui_wps[NB_SCREENS]; + +/***** wps_tokens.c ******/ + +const char *get_token_value(struct gui_wps *gwps, + struct wps_token *token, + char *buf, int buf_size, + int *intval); + +#endif diff --git a/apps/gui/wps_parser.c b/apps/gui/wps_engine/wps_parser.c similarity index 99% rename from apps/gui/wps_parser.c rename to apps/gui/wps_engine/wps_parser.c index fb0b3ac4c6..15acc1401d 100644 --- a/apps/gui/wps_parser.c +++ b/apps/gui/wps_engine/wps_parser.c @@ -43,7 +43,7 @@ #include #include "font.h" -#include "gwps.h" +#include "wps_internals.h" #include "settings.h" #include "settings_list.h" diff --git a/apps/gui/wps_engine/wps_tokens.c b/apps/gui/wps_engine/wps_tokens.c new file mode 100644 index 0000000000..3852251916 --- /dev/null +++ b/apps/gui/wps_engine/wps_tokens.c @@ -0,0 +1,807 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2002-2007 Björn Stenberg + * Copyright (C) 2007-2008 Nicolas Pennequin + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#include "font.h" +#include +#include +#include +#include "action.h" +#include "system.h" +#include "settings.h" +#include "settings_list.h" +#include "rbunicode.h" +#include "timefuncs.h" +#include "audio.h" +#include "status.h" +#include "power.h" +#include "powermgmt.h" +#include "sound.h" +#include "debug.h" +#ifdef HAVE_LCD_CHARCELLS +#include "hwcompat.h" +#endif +#include "abrepeat.h" +#include "mp3_playback.h" +#include "lang.h" +#include "misc.h" +#include "led.h" +#ifdef HAVE_LCD_BITMAP +/* Image stuff */ +#include "albumart.h" +#endif +#include "dsp.h" +#include "playlist.h" +#if CONFIG_CODEC == SWCODEC +#include "playback.h" +#endif +#include "viewport.h" + +#include "wps_internals.h" +#include "music_screen.h" + +static char* get_codectype(const struct mp3entry* id3) +{ + if (id3->codectype < AFMT_NUM_CODECS) { + return (char*)audio_formats[id3->codectype].label; + } else { + return NULL; + } +} + +/* Extract a part from a path. + * + * buf - buffer extract part to. + * buf_size - size of buffer. + * path - path to extract from. + * level - what to extract. 0 is file name, 1 is parent of file, 2 is + * parent of parent, etc. + * + * Returns buf if the desired level was found, NULL otherwise. + */ +static char* get_dir(char* buf, int buf_size, const char* path, int level) +{ + const char* sep; + const char* last_sep; + int len; + + sep = path + strlen(path); + last_sep = sep; + + while (sep > path) + { + if ('/' == *(--sep)) + { + if (!level) + break; + + level--; + last_sep = sep - 1; + } + } + + if (level || (last_sep <= sep)) + return NULL; + + len = MIN(last_sep - sep, buf_size - 1); + strlcpy(buf, sep + 1, len + 1); + return buf; +} + +/* Return the tag found at index i and write its value in buf. + The return value is buf if the tag had a value, or NULL if not. + + intval is used with conditionals/enums: when this function is called, + intval should contain the number of options in the conditional/enum. + When this function returns, intval is -1 if the tag is non numeric or, + if the tag is numeric, *intval is the enum case we want to go to (between 1 + and the original value of *intval, inclusive). + When not treating a conditional/enum, intval should be NULL. +*/ +const char *get_token_value(struct gui_wps *gwps, + struct wps_token *token, + char *buf, int buf_size, + int *intval) +{ + if (!gwps) + return NULL; + + struct wps_data *data = gwps->data; + struct wps_state *state = gwps->state; + + if (!data || !state) + return NULL; + + struct mp3entry *id3; + + if (token->next) + id3 = state->nid3; + else + id3 = state->id3; + + if (!id3) + return NULL; + +#if CONFIG_RTC + struct tm* tm = NULL; + + /* if the token is an RTC one, update the time + and do the necessary checks */ + if (token->type >= WPS_TOKENS_RTC_BEGIN + && token->type <= WPS_TOKENS_RTC_END) + { + tm = get_time(); + + if (!valid_time(tm)) + return NULL; + } +#endif + + int limit = 1; + if (intval) + { + limit = *intval; + *intval = -1; + } + + switch (token->type) + { + case WPS_TOKEN_CHARACTER: + return &(token->value.c); + + case WPS_TOKEN_STRING: + return data->strings[token->value.i]; + + case WPS_TOKEN_TRACK_TIME_ELAPSED: + format_time(buf, buf_size, + id3->elapsed + state->ff_rewind_count); + return buf; + + case WPS_TOKEN_TRACK_TIME_REMAINING: + format_time(buf, buf_size, + id3->length - id3->elapsed - + state->ff_rewind_count); + return buf; + + case WPS_TOKEN_TRACK_LENGTH: + format_time(buf, buf_size, id3->length); + return buf; + + case WPS_TOKEN_PLAYLIST_ENTRIES: + snprintf(buf, buf_size, "%d", playlist_amount()); + return buf; + + case WPS_TOKEN_PLAYLIST_NAME: + return playlist_name(NULL, buf, buf_size); + + case WPS_TOKEN_PLAYLIST_POSITION: + snprintf(buf, buf_size, "%d", playlist_get_display_index()); + return buf; + + case WPS_TOKEN_PLAYLIST_SHUFFLE: + if ( global_settings.playlist_shuffle ) + return "s"; + else + return NULL; + break; + + case WPS_TOKEN_VOLUME: + snprintf(buf, buf_size, "%d", global_settings.volume); + if (intval) + { + if (global_settings.volume == sound_min(SOUND_VOLUME)) + { + *intval = 1; + } + else if (global_settings.volume == 0) + { + *intval = limit - 1; + } + else if (global_settings.volume > 0) + { + *intval = limit; + } + else + { + *intval = (limit - 3) * (global_settings.volume + - sound_min(SOUND_VOLUME) - 1) + / (-1 - sound_min(SOUND_VOLUME)) + 2; + } + } + return buf; + + case WPS_TOKEN_TRACK_ELAPSED_PERCENT: + if (id3->length <= 0) + return NULL; + + if (intval) + { + *intval = limit * (id3->elapsed + state->ff_rewind_count) + / id3->length + 1; + } + snprintf(buf, buf_size, "%d", + 100*(id3->elapsed + state->ff_rewind_count) / id3->length); + return buf; + + case WPS_TOKEN_METADATA_ARTIST: + return id3->artist; + + case WPS_TOKEN_METADATA_COMPOSER: + return id3->composer; + + case WPS_TOKEN_METADATA_ALBUM: + return id3->album; + + case WPS_TOKEN_METADATA_ALBUM_ARTIST: + return id3->albumartist; + + case WPS_TOKEN_METADATA_GROUPING: + return id3->grouping; + + case WPS_TOKEN_METADATA_GENRE: + return id3->genre_string; + + case WPS_TOKEN_METADATA_DISC_NUMBER: + if (id3->disc_string) + return id3->disc_string; + if (id3->discnum) { + snprintf(buf, buf_size, "%d", id3->discnum); + return buf; + } + return NULL; + + case WPS_TOKEN_METADATA_TRACK_NUMBER: + if (id3->track_string) + return id3->track_string; + + if (id3->tracknum) { + snprintf(buf, buf_size, "%d", id3->tracknum); + return buf; + } + return NULL; + + case WPS_TOKEN_METADATA_TRACK_TITLE: + return id3->title; + + case WPS_TOKEN_METADATA_VERSION: + switch (id3->id3version) + { + case ID3_VER_1_0: + return "1"; + + case ID3_VER_1_1: + return "1.1"; + + case ID3_VER_2_2: + return "2.2"; + + case ID3_VER_2_3: + return "2.3"; + + case ID3_VER_2_4: + return "2.4"; + + default: + return NULL; + } + + case WPS_TOKEN_METADATA_YEAR: + if( id3->year_string ) + return id3->year_string; + + if (id3->year) { + snprintf(buf, buf_size, "%d", id3->year); + return buf; + } + return NULL; + + case WPS_TOKEN_METADATA_COMMENT: + return id3->comment; + +#ifdef HAVE_ALBUMART + case WPS_TOKEN_ALBUMART_DISPLAY: + draw_album_art(gwps, audio_current_aa_hid(), false); + return NULL; + + case WPS_TOKEN_ALBUMART_FOUND: + if (audio_current_aa_hid() >= 0) { + return "C"; + } + return NULL; +#endif + + case WPS_TOKEN_FILE_BITRATE: + if(id3->bitrate) + snprintf(buf, buf_size, "%d", id3->bitrate); + else + return "?"; + return buf; + + case WPS_TOKEN_FILE_CODEC: + if (intval) + { + if(id3->codectype == AFMT_UNKNOWN) + *intval = AFMT_NUM_CODECS; + else + *intval = id3->codectype; + } + return get_codectype(id3); + + case WPS_TOKEN_FILE_FREQUENCY: + snprintf(buf, buf_size, "%ld", id3->frequency); + return buf; + + case WPS_TOKEN_FILE_FREQUENCY_KHZ: + /* ignore remainders < 100, so 22050 Hz becomes just 22k */ + if ((id3->frequency % 1000) < 100) + snprintf(buf, buf_size, "%ld", id3->frequency / 1000); + else + snprintf(buf, buf_size, "%ld.%d", + id3->frequency / 1000, + (id3->frequency % 1000) / 100); + return buf; + + case WPS_TOKEN_FILE_NAME: + if (get_dir(buf, buf_size, id3->path, 0)) { + /* Remove extension */ + char* sep = strrchr(buf, '.'); + if (NULL != sep) { + *sep = 0; + } + return buf; + } + else { + return NULL; + } + + case WPS_TOKEN_FILE_NAME_WITH_EXTENSION: + return get_dir(buf, buf_size, id3->path, 0); + + case WPS_TOKEN_FILE_PATH: + return id3->path; + + case WPS_TOKEN_FILE_SIZE: + snprintf(buf, buf_size, "%ld", id3->filesize / 1024); + return buf; + + case WPS_TOKEN_FILE_VBR: + return id3->vbr ? "(avg)" : NULL; + + case WPS_TOKEN_FILE_DIRECTORY: + return get_dir(buf, buf_size, id3->path, token->value.i); + + case WPS_TOKEN_BATTERY_PERCENT: + { + int l = battery_level(); + + if (intval) + { + limit = MAX(limit, 2); + if (l > -1) { + /* First enum is used for "unknown level". */ + *intval = (limit - 1) * l / 100 + 2; + } else { + *intval = 1; + } + } + + if (l > -1) { + snprintf(buf, buf_size, "%d", l); + return buf; + } else { + return "?"; + } + } + + case WPS_TOKEN_BATTERY_VOLTS: + { + unsigned int v = battery_voltage(); + snprintf(buf, buf_size, "%d.%02d", v / 1000, (v % 1000) / 10); + return buf; + } + + case WPS_TOKEN_BATTERY_TIME: + { + int t = battery_time(); + if (t >= 0) + snprintf(buf, buf_size, "%dh %dm", t / 60, t % 60); + else + return "?h ?m"; + return buf; + } + +#if CONFIG_CHARGING + case WPS_TOKEN_BATTERY_CHARGER_CONNECTED: + { + if(charger_input_state==CHARGER) + return "p"; + else + return NULL; + } +#endif +#if CONFIG_CHARGING >= CHARGING_MONITOR + case WPS_TOKEN_BATTERY_CHARGING: + { + if (charge_state == CHARGING || charge_state == TOPOFF) { + return "c"; + } else { + return NULL; + } + } +#endif + case WPS_TOKEN_BATTERY_SLEEPTIME: + { + if (get_sleep_timer() == 0) + return NULL; + else + { + format_time(buf, buf_size, get_sleep_timer() * 1000); + return buf; + } + } + + case WPS_TOKEN_PLAYBACK_STATUS: + { + int status = audio_status(); + int mode = 1; + if (status == AUDIO_STATUS_PLAY) + mode = 2; + if (is_wps_fading() || + (status & AUDIO_STATUS_PAUSE && !status_get_ffmode())) + mode = 3; + if (status_get_ffmode() == STATUS_FASTFORWARD) + mode = 4; + if (status_get_ffmode() == STATUS_FASTBACKWARD) + mode = 5; + + if (intval) { + *intval = mode; + } + + snprintf(buf, buf_size, "%d", mode-1); + return buf; + } + + case WPS_TOKEN_REPEAT_MODE: + if (intval) + *intval = global_settings.repeat_mode + 1; + snprintf(buf, buf_size, "%d", global_settings.repeat_mode); + return buf; + + case WPS_TOKEN_RTC_PRESENT: +#if CONFIG_RTC + return "c"; +#else + return NULL; +#endif + +#if CONFIG_RTC + case WPS_TOKEN_RTC_12HOUR_CFG: + if (intval) + *intval = global_settings.timeformat + 1; + snprintf(buf, buf_size, "%d", global_settings.timeformat); + return buf; + + case WPS_TOKEN_RTC_DAY_OF_MONTH: + /* d: day of month (01..31) */ + snprintf(buf, buf_size, "%02d", tm->tm_mday); + return buf; + + case WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED: + /* e: day of month, blank padded ( 1..31) */ + snprintf(buf, buf_size, "%2d", tm->tm_mday); + return buf; + + case WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED: + /* H: hour (00..23) */ + snprintf(buf, buf_size, "%02d", tm->tm_hour); + return buf; + + case WPS_TOKEN_RTC_HOUR_24: + /* k: hour ( 0..23) */ + snprintf(buf, buf_size, "%2d", tm->tm_hour); + return buf; + + case WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED: + /* I: hour (01..12) */ + snprintf(buf, buf_size, "%02d", + (tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12); + return buf; + + case WPS_TOKEN_RTC_HOUR_12: + /* l: hour ( 1..12) */ + snprintf(buf, buf_size, "%2d", + (tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12); + return buf; + + case WPS_TOKEN_RTC_MONTH: + /* m: month (01..12) */ + if (intval) + *intval = tm->tm_mon + 1; + snprintf(buf, buf_size, "%02d", tm->tm_mon + 1); + return buf; + + case WPS_TOKEN_RTC_MINUTE: + /* M: minute (00..59) */ + snprintf(buf, buf_size, "%02d", tm->tm_min); + return buf; + + case WPS_TOKEN_RTC_SECOND: + /* S: second (00..59) */ + snprintf(buf, buf_size, "%02d", tm->tm_sec); + return buf; + + case WPS_TOKEN_RTC_YEAR_2_DIGITS: + /* y: last two digits of year (00..99) */ + snprintf(buf, buf_size, "%02d", tm->tm_year % 100); + return buf; + + case WPS_TOKEN_RTC_YEAR_4_DIGITS: + /* Y: year (1970...) */ + snprintf(buf, buf_size, "%04d", tm->tm_year + 1900); + return buf; + + case WPS_TOKEN_RTC_AM_PM_UPPER: + /* p: upper case AM or PM indicator */ + return tm->tm_hour/12 == 0 ? "AM" : "PM"; + + case WPS_TOKEN_RTC_AM_PM_LOWER: + /* P: lower case am or pm indicator */ + return tm->tm_hour/12 == 0 ? "am" : "pm"; + + case WPS_TOKEN_RTC_WEEKDAY_NAME: + /* a: abbreviated weekday name (Sun..Sat) */ + return str(LANG_WEEKDAY_SUNDAY + tm->tm_wday); + + case WPS_TOKEN_RTC_MONTH_NAME: + /* b: abbreviated month name (Jan..Dec) */ + return str(LANG_MONTH_JANUARY + tm->tm_mon); + + case WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON: + /* u: day of week (1..7); 1 is Monday */ + if (intval) + *intval = (tm->tm_wday == 0) ? 7 : tm->tm_wday; + snprintf(buf, buf_size, "%1d", tm->tm_wday + 1); + return buf; + + case WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN: + /* w: day of week (0..6); 0 is Sunday */ + if (intval) + *intval = tm->tm_wday + 1; + snprintf(buf, buf_size, "%1d", tm->tm_wday); + return buf; +#else + case WPS_TOKEN_RTC_DAY_OF_MONTH: + case WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED: + case WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED: + case WPS_TOKEN_RTC_HOUR_24: + case WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED: + case WPS_TOKEN_RTC_HOUR_12: + case WPS_TOKEN_RTC_MONTH: + case WPS_TOKEN_RTC_MINUTE: + case WPS_TOKEN_RTC_SECOND: + case WPS_TOKEN_RTC_AM_PM_UPPER: + case WPS_TOKEN_RTC_AM_PM_LOWER: + case WPS_TOKEN_RTC_YEAR_2_DIGITS: + return "--"; + case WPS_TOKEN_RTC_YEAR_4_DIGITS: + return "----"; + case WPS_TOKEN_RTC_WEEKDAY_NAME: + case WPS_TOKEN_RTC_MONTH_NAME: + return "---"; + case WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON: + case WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN: + return "-"; +#endif + +#ifdef HAVE_LCD_CHARCELLS + case WPS_TOKEN_PROGRESSBAR: + { + char *end = utf8encode(data->wps_progress_pat[0], buf); + *end = '\0'; + return buf; + } + + case WPS_TOKEN_PLAYER_PROGRESSBAR: + if(is_new_player()) + { + /* we need 11 characters (full line) for + progress-bar */ + strlcpy(buf, " ", buf_size); + } + else + { + /* Tell the user if we have an OldPlayer */ + strlcpy(buf, " ", buf_size); + } + return buf; +#endif + +#ifdef HAVE_TAGCACHE + case WPS_TOKEN_DATABASE_PLAYCOUNT: + if (intval) { + *intval = id3->playcount + 1; + } + snprintf(buf, buf_size, "%ld", id3->playcount); + return buf; + + case WPS_TOKEN_DATABASE_RATING: + if (intval) { + *intval = id3->rating + 1; + } + snprintf(buf, buf_size, "%d", id3->rating); + return buf; + + case WPS_TOKEN_DATABASE_AUTOSCORE: + if (intval) + *intval = id3->score + 1; + + snprintf(buf, buf_size, "%d", id3->score); + return buf; +#endif + +#if (CONFIG_CODEC == SWCODEC) + case WPS_TOKEN_CROSSFADE: + if (intval) + *intval = global_settings.crossfade + 1; + snprintf(buf, buf_size, "%d", global_settings.crossfade); + return buf; + + case WPS_TOKEN_REPLAYGAIN: + { + int val; + + if (global_settings.replaygain_type == REPLAYGAIN_OFF) + val = 1; /* off */ + else + { + int type = + get_replaygain_mode(id3->track_gain_string != NULL, + id3->album_gain_string != NULL); + if (type < 0) + val = 6; /* no tag */ + else + val = type + 2; + + if (global_settings.replaygain_type == REPLAYGAIN_SHUFFLE) + val += 2; + } + + if (intval) + *intval = val; + + switch (val) + { + case 1: + case 6: + return "+0.00 dB"; + break; + case 2: + case 4: + strlcpy(buf, id3->track_gain_string, buf_size); + break; + case 3: + case 5: + strlcpy(buf, id3->album_gain_string, buf_size); + break; + } + return buf; + } +#endif /* (CONFIG_CODEC == SWCODEC) */ + +#if (CONFIG_CODEC != MAS3507D) + case WPS_TOKEN_SOUND_PITCH: + { + int val = sound_get_pitch(); + snprintf(buf, buf_size, "%d.%d", + val / 10, val % 10); + return buf; + } +#endif + + case WPS_TOKEN_MAIN_HOLD: +#ifdef HAS_BUTTON_HOLD + if (button_hold()) +#else + if (is_keys_locked()) +#endif /*hold switch or softlock*/ + return "h"; + else + return NULL; + +#ifdef HAS_REMOTE_BUTTON_HOLD + case WPS_TOKEN_REMOTE_HOLD: + if (remote_button_hold()) + return "r"; + else + return NULL; +#endif + +#if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD) + case WPS_TOKEN_VLED_HDD: + if(led_read(HZ/2)) + return "h"; + else + return NULL; +#endif + case WPS_TOKEN_BUTTON_VOLUME: + if (data->button_time_volume && + TIME_BEFORE(current_tick, data->button_time_volume + + token->value.i * TIMEOUT_UNIT)) + return "v"; + return NULL; + case WPS_TOKEN_LASTTOUCH: +#ifdef HAVE_TOUCHSCREEN + if (TIME_BEFORE(current_tick, token->value.i * TIMEOUT_UNIT + + touchscreen_last_touch())) + return "t"; +#endif + return NULL; + + case WPS_TOKEN_SETTING: + { + if (intval) + { + /* Handle contionals */ + const struct settings_list *s = settings+token->value.i; + switch (s->flags&F_T_MASK) + { + case F_T_INT: + case F_T_UINT: + if (s->flags&F_RGB) + /* %?St|name|<#000000|#000001|...|#FFFFFF> */ + /* shouldn't overflow since colors are stored + * on 16 bits ... + * but this is pretty useless anyway */ + *intval = *(int*)s->setting + 1; + else if (s->cfg_vals == NULL) + /* %?St|name|<1st choice|2nd choice|...> */ + *intval = (*(int*)s->setting-s->int_setting->min) + /s->int_setting->step + 1; + else + /* %?St|name|<1st choice|2nd choice|...> */ + /* Not sure about this one. cfg_name/vals are + * indexed from 0 right? */ + *intval = *(int*)s->setting + 1; + break; + case F_T_BOOL: + /* %?St|name| */ + *intval = *(bool*)s->setting?1:2; + break; + case F_T_CHARPTR: + /* %?St|name| + * The string's emptyness discards the setting's + * prefix and suffix */ + *intval = ((char*)s->setting)[0]?1:2; + break; + default: + /* This shouldn't happen ... but you never know */ + *intval = -1; + break; + } + } + cfg_to_string(token->value.i,buf,buf_size); + return buf; + } + + default: + return NULL; + } +} diff --git a/apps/iap.c b/apps/iap.c index 592bbdbbf8..f7a808d8b2 100644 --- a/apps/iap.c +++ b/apps/iap.c @@ -36,7 +36,7 @@ #include "audio.h" #include "settings.h" #include "metadata.h" -#include "gwps.h" +#include "wps_engine/wps_engine.h" #include "action.h" diff --git a/apps/main.c b/apps/main.c index 929c946334..2cf9ce7175 100644 --- a/apps/main.c +++ b/apps/main.c @@ -52,7 +52,7 @@ #include "sprintf.h" #include "font.h" #include "language.h" -#include "gwps.h" +#include "music_screen.h" #include "playlist.h" #include "buffer.h" #include "rolo.h" diff --git a/apps/menu.c b/apps/menu.c index f6d0ef967d..6690972e50 100644 --- a/apps/menu.c +++ b/apps/menu.c @@ -48,7 +48,6 @@ #include "string.h" #include "root_menu.h" #include "bookmark.h" -#include "gwps-common.h" /* for fade() */ #include "audio.h" #include "viewport.h" #include "quickscreen.h" diff --git a/apps/menus/main_menu.c b/apps/menus/main_menu.c index 76ed01d9ba..4009566c44 100644 --- a/apps/menus/main_menu.c +++ b/apps/menus/main_menu.c @@ -50,7 +50,7 @@ #endif #include "version.h" #include "time.h" -#include "gwps.h" +#include "gui/wps_engine/wps_engine.h" static const struct browse_folder_info config = {ROCKBOX_DIR, SHOW_CFG}; diff --git a/apps/misc.c b/apps/misc.c index e6f8ca840b..2e7051cbd3 100644 --- a/apps/misc.c +++ b/apps/misc.c @@ -75,9 +75,8 @@ #include "bmp.h" #include "icons.h" #endif /* End HAVE_LCD_BITMAP */ -#include "gui/gwps-common.h" #include "bookmark.h" - +#include "music_screen.h" #include "playback.h" #ifdef BOOTFILE diff --git a/apps/recorder/albumart.c b/apps/recorder/albumart.c index a378c332b3..f1315da71f 100644 --- a/apps/recorder/albumart.c +++ b/apps/recorder/albumart.c @@ -24,7 +24,6 @@ #include "system.h" #include "albumart.h" #include "metadata.h" -#include "gwps.h" #include "buffering.h" #include "dircache.h" #include "misc.h" diff --git a/apps/recorder/albumart.h b/apps/recorder/albumart.h index edf464fb7a..82e0b79aec 100644 --- a/apps/recorder/albumart.h +++ b/apps/recorder/albumart.h @@ -26,7 +26,7 @@ #include #include "metadata.h" -#include "gwps.h" +#include "wps_engine/wps_engine.h" /* Look for albumart bitmap in the same dir as the track and in its parent dir. * Stores the found filename in the buf parameter. diff --git a/apps/root_menu.c b/apps/root_menu.c index 15bc524cce..37fda98cb3 100644 --- a/apps/root_menu.c +++ b/apps/root_menu.c @@ -53,7 +53,7 @@ #ifdef HAVE_RECORDING #include "recording.h" #endif -#include "gwps-common.h" +#include "music_screen.h" #include "bookmark.h" #include "playlist.h" #include "tagtree.h" diff --git a/apps/settings.c b/apps/settings.c index 29360f14d3..800cc59a56 100644 --- a/apps/settings.c +++ b/apps/settings.c @@ -52,7 +52,6 @@ #endif #include "lang.h" #include "language.h" -#include "gwps.h" #include "powermgmt.h" #include "sprintf.h" #include "keyboard.h" @@ -70,6 +69,7 @@ #if CONFIG_TUNER #include "radio.h" #endif +#include "wps_engine/wps_engine.h" #if CONFIG_CODEC == MAS3507D void dac_line_in(bool enable); diff --git a/apps/tree.c b/apps/tree.c index 576453a3ad..2c6c85f2a8 100644 --- a/apps/tree.c +++ b/apps/tree.c @@ -36,7 +36,7 @@ #include "audio.h" #include "playlist.h" #include "menu.h" -#include "gwps.h" +#include "wps_engine/wps_engine.h" #include "settings.h" #include "debug.h" #include "storage.h" @@ -64,7 +64,6 @@ #include "tagcache.h" #endif #include "yesno.h" -#include "gwps-common.h" #include "eeprom_settings.h" #include "playlist_catalog.h"