From a72ffe7bb533302dbf4e6c7c4f1e4bd4078d3ed6 Mon Sep 17 00:00:00 2001 From: Thomas Martitz Date: Fri, 16 Oct 2009 19:14:37 +0000 Subject: Make the skin engine behave sane if the skin's id3 pointer is NULL (the one in struct wps_state), so that skins don't need audio to be played before being displayed (needed for upcoming custom statusbar). git-svn-id: svn://svn.rockbox.org/rockbox/trunk@23208 a1c6a512-1295-4272-9138-f99709370657 --- apps/gui/skin_engine/skin_tokens.c | 181 +++++++++++++++++++++++-------------- 1 file changed, 113 insertions(+), 68 deletions(-) (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 index ac37c6dd3e..d607538f0f 100644 --- a/apps/gui/skin_engine/skin_tokens.c +++ b/apps/gui/skin_engine/skin_tokens.c @@ -63,7 +63,7 @@ static char* get_codectype(const struct mp3entry* id3) { - if (id3->codectype < AFMT_NUM_CODECS) { + if (id3 && id3->codectype < AFMT_NUM_CODECS) { return (char*)audio_formats[id3->codectype].label; } else { return NULL; @@ -119,6 +119,27 @@ static char* get_dir(char* buf, int buf_size, const char* path, int level) and the original value of *intval, inclusive). When not treating a conditional/enum, intval should be NULL. */ + +/* a few convinience macros for the id3 == NULL case + * depends on a few variable names in get_token_value() */ + +#define HANDLE_NULL_ID3(id3field) (LIKELY(id3) ? (id3field) : na_str) + +#define HANDLE_NULL_ID3_NUM_ZERO { if (UNLIKELY(!id3)) return zero_str; } + +#define HANDLE_NULL_ID3_NUM_INTVAL(id3field) \ + do { \ + if (intval) { \ + *intval = (LIKELY(id3) ? (id3field) + 1 : 0); \ + } \ + if (LIKELY(id3)) \ + { \ + snprintf(buf, buf_size, "%ld", (id3field)); \ + return buf; \ + } \ + return zero_str; \ + } while (0) + const char *get_token_value(struct gui_wps *gwps, struct wps_token *token, char *buf, int buf_size, @@ -129,6 +150,9 @@ const char *get_token_value(struct gui_wps *gwps, struct wps_data *data = gwps->data; struct wps_state *state = gwps->state; + int elapsed, length; + static const char * const na_str = "n/a"; + static const char * const zero_str = "0"; if (!data || !state) return NULL; @@ -140,8 +164,16 @@ const char *get_token_value(struct gui_wps *gwps, else id3 = state->id3; - if (!id3) - return NULL; + if (id3) + { + elapsed = id3->elapsed; + length = id3->length; + } + else + { + elapsed = 0; + length = 0; + } #if CONFIG_RTC struct tm* tm = NULL; @@ -180,17 +212,17 @@ const char *get_token_value(struct gui_wps *gwps, case WPS_TOKEN_TRACK_TIME_ELAPSED: format_time(buf, buf_size, - id3->elapsed + state->ff_rewind_count); + elapsed + state->ff_rewind_count); return buf; case WPS_TOKEN_TRACK_TIME_REMAINING: format_time(buf, buf_size, - id3->length - id3->elapsed - + length - elapsed - state->ff_rewind_count); return buf; case WPS_TOKEN_TRACK_LENGTH: - format_time(buf, buf_size, id3->length); + format_time(buf, buf_size, length); return buf; case WPS_TOKEN_PLAYLIST_ENTRIES: @@ -237,92 +269,102 @@ const char *get_token_value(struct gui_wps *gwps, return buf; case WPS_TOKEN_TRACK_ELAPSED_PERCENT: - if (id3->length <= 0) + if (length <= 0) return NULL; if (intval) { - *intval = limit * (id3->elapsed + state->ff_rewind_count) - / id3->length + 1; + *intval = limit * (elapsed + state->ff_rewind_count) + / length + 1; } snprintf(buf, buf_size, "%d", - 100*(id3->elapsed + state->ff_rewind_count) / id3->length); + 100*(elapsed + state->ff_rewind_count) / length); return buf; case WPS_TOKEN_METADATA_ARTIST: - return id3->artist; + return HANDLE_NULL_ID3(id3->artist); case WPS_TOKEN_METADATA_COMPOSER: - return id3->composer; + return HANDLE_NULL_ID3(id3->composer); case WPS_TOKEN_METADATA_ALBUM: - return id3->album; + return HANDLE_NULL_ID3(id3->album); case WPS_TOKEN_METADATA_ALBUM_ARTIST: - return id3->albumartist; + return HANDLE_NULL_ID3(id3->albumartist); case WPS_TOKEN_METADATA_GROUPING: - return id3->grouping; + return HANDLE_NULL_ID3(id3->grouping); case WPS_TOKEN_METADATA_GENRE: - return id3->genre_string; + return HANDLE_NULL_ID3(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; + if (LIKELY(id3)) { + 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 (LIKELY(id3)) { + if (id3->track_string) + return id3->track_string; - if (id3->tracknum) { - snprintf(buf, buf_size, "%d", id3->tracknum); - return buf; + if (id3->tracknum) { + snprintf(buf, buf_size, "%d", id3->tracknum); + return buf; + } } return NULL; case WPS_TOKEN_METADATA_TRACK_TITLE: - return id3->title; + return HANDLE_NULL_ID3(id3->title); case WPS_TOKEN_METADATA_VERSION: - switch (id3->id3version) + if (LIKELY(id3)) { - case ID3_VER_1_0: - return "1"; + switch (id3->id3version) + { + case ID3_VER_1_0: + return "1"; - case ID3_VER_1_1: - return "1.1"; + case ID3_VER_1_1: + return "1.1"; - case ID3_VER_2_2: - return "2.2"; + case ID3_VER_2_2: + return "2.2"; - case ID3_VER_2_3: - return "2.3"; + case ID3_VER_2_3: + return "2.3"; - case ID3_VER_2_4: - return "2.4"; + case ID3_VER_2_4: + return "2.4"; - default: - return NULL; + default: + break; + } } + return NULL; case WPS_TOKEN_METADATA_YEAR: - if( id3->year_string ) - return id3->year_string; + if (LIKELY(id3)) { + if( id3->year_string ) + return id3->year_string; - if (id3->year) { - snprintf(buf, buf_size, "%d", id3->year); - return buf; + if (id3->year) { + snprintf(buf, buf_size, "%d", id3->year); + return buf; + } } return NULL; case WPS_TOKEN_METADATA_COMMENT: - return id3->comment; + return HANDLE_NULL_ID3(id3->comment); #ifdef HAVE_ALBUMART case WPS_TOKEN_ALBUMART_FOUND: @@ -340,7 +382,7 @@ const char *get_token_value(struct gui_wps *gwps, #endif case WPS_TOKEN_FILE_BITRATE: - if(id3->bitrate) + if(id3 && id3->bitrate) snprintf(buf, buf_size, "%d", id3->bitrate); else return "?"; @@ -349,7 +391,9 @@ const char *get_token_value(struct gui_wps *gwps, case WPS_TOKEN_FILE_CODEC: if (intval) { - if(id3->codectype == AFMT_UNKNOWN) + if (UNLIKELY(!id3)) + *intval = 0; + else if(id3->codectype == AFMT_UNKNOWN) *intval = AFMT_NUM_CODECS; else *intval = id3->codectype; @@ -357,10 +401,12 @@ const char *get_token_value(struct gui_wps *gwps, return get_codectype(id3); case WPS_TOKEN_FILE_FREQUENCY: + HANDLE_NULL_ID3_NUM_ZERO; snprintf(buf, buf_size, "%ld", id3->frequency); return buf; case WPS_TOKEN_FILE_FREQUENCY_KHZ: + HANDLE_NULL_ID3_NUM_ZERO; /* ignore remainders < 100, so 22050 Hz becomes just 22k */ if ((id3->frequency % 1000) < 100) snprintf(buf, buf_size, "%ld", id3->frequency / 1000); @@ -371,6 +417,7 @@ const char *get_token_value(struct gui_wps *gwps, return buf; case WPS_TOKEN_FILE_NAME: + if (!id3) return na_str; if (get_dir(buf, buf_size, id3->path, 0)) { /* Remove extension */ char* sep = strrchr(buf, '.'); @@ -384,20 +431,24 @@ const char *get_token_value(struct gui_wps *gwps, } case WPS_TOKEN_FILE_NAME_WITH_EXTENSION: + if (!id3) return na_str; return get_dir(buf, buf_size, id3->path, 0); case WPS_TOKEN_FILE_PATH: - return id3->path; + return HANDLE_NULL_ID3(id3->path); case WPS_TOKEN_FILE_SIZE: + HANDLE_NULL_ID3_NUM_ZERO; snprintf(buf, buf_size, "%ld", id3->filesize / 1024); return buf; case WPS_TOKEN_FILE_VBR: - return id3->vbr ? "(avg)" : NULL; + return (LIKELY(id3) && id3->vbr) ? "(avg)" : NULL; case WPS_TOKEN_FILE_DIRECTORY: - return get_dir(buf, buf_size, id3->path, token->value.i); + if (LIKELY(id3)) + return get_dir(buf, buf_size, id3->path, token->value.i); + return na_str; case WPS_TOKEN_BATTERY_PERCENT: { @@ -664,27 +715,16 @@ const char *get_token_value(struct gui_wps *gwps, 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; + HANDLE_NULL_ID3_NUM_INTVAL(id3->playcount); case WPS_TOKEN_DATABASE_RATING: - if (intval) { - *intval = id3->rating + 1; - } - snprintf(buf, buf_size, "%d", id3->rating); - return buf; + HANDLE_NULL_ID3_NUM_INTVAL(id3->rating); case WPS_TOKEN_DATABASE_AUTOSCORE: - if (intval) - *intval = id3->score + 1; - - snprintf(buf, buf_size, "%d", id3->score); - return buf; + HANDLE_NULL_ID3_NUM_INTVAL(id3->score); #endif #if (CONFIG_CODEC == SWCODEC) @@ -702,9 +742,13 @@ const char *get_token_value(struct gui_wps *gwps, val = 1; /* off */ else { - int type = - get_replaygain_mode(id3->track_gain_string != NULL, + int type; + if (LIKELY(id3)) + type = get_replaygain_mode(id3->track_gain_string != NULL, id3->album_gain_string != NULL); + else + type = -1; + if (type < 0) val = 6; /* no tag */ else @@ -723,6 +767,7 @@ const char *get_token_value(struct gui_wps *gwps, case 6: return "+0.00 dB"; break; + /* due to above, coming here with !id3 shouldn't be possible */ case 2: case 4: strlcpy(buf, id3->track_gain_string, buf_size); -- cgit v1.2.3