From 3790897189e008aba2c255a02f8294b50946a02e Mon Sep 17 00:00:00 2001 From: Jonathan Gordon Date: Thu, 6 Aug 2009 04:33:35 +0000 Subject: more wps->skin moving/renaming git-svn-id: svn://svn.rockbox.org/rockbox/trunk@22180 a1c6a512-1295-4272-9138-f99709370657 --- apps/gui/skin_engine/skin_tokens.c | 807 +++++++++++++++++++++++++++++++++++++ 1 file changed, 807 insertions(+) create mode 100644 apps/gui/skin_engine/skin_tokens.c (limited to 'apps/gui/skin_engine/skin_tokens.c') diff --git a/apps/gui/skin_engine/skin_tokens.c b/apps/gui/skin_engine/skin_tokens.c new file mode 100644 index 0000000000..b1163aa88a --- /dev/null +++ b/apps/gui/skin_engine/skin_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 "wps.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; + } +} -- cgit v1.2.3