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_display.c | 83 +++++++++++------ apps/gui/skin_engine/skin_tokens.c | 181 ++++++++++++++++++++++-------------- 2 files changed, 167 insertions(+), 97 deletions(-) diff --git a/apps/gui/skin_engine/skin_display.c b/apps/gui/skin_engine/skin_display.c index 7d75b48506..67984cd2bb 100644 --- a/apps/gui/skin_engine/skin_display.c +++ b/apps/gui/skin_engine/skin_display.c @@ -145,6 +145,7 @@ static void draw_progressbar(struct gui_wps *gwps, struct screen *display = gwps->display; struct wps_state *state = gwps->state; struct progressbar *pb = wps_vp->pb; + struct mp3entry *id3 = state->id3; int y = pb->y; if (y < 0) @@ -156,27 +157,37 @@ static void draw_progressbar(struct gui_wps *gwps, y = (-y -1)*line_height + (0 > center ? 0 : center); } + int elapsed, length; + if (id3) + { + elapsed = id3->elapsed; + length = id3->length; + } + else + { + elapsed = 0; + length = 0; + } + if (pb->have_bitmap_pb) gui_bitmap_scrollbar_draw(display, pb->bm, - pb->x, y, pb->width, pb->bm.height, - state->id3->length ? state->id3->length : 1, 0, - state->id3->length ? state->id3->elapsed - + state->ff_rewind_count : 0, - HORIZONTAL); + pb->x, y, pb->width, pb->bm.height, + length ? length : 1, 0, + length ? elapsed + state->ff_rewind_count : 0, + HORIZONTAL); else gui_scrollbar_draw(display, pb->x, y, pb->width, pb->height, - state->id3->length ? state->id3->length : 1, 0, - state->id3->length ? state->id3->elapsed - + state->ff_rewind_count : 0, - HORIZONTAL); + length ? length : 1, 0, + length ? elapsed + state->ff_rewind_count : 0, + HORIZONTAL); #ifdef AB_REPEAT_ENABLE - if ( ab_repeat_mode_enabled() && state->id3->length != 0 ) - ab_draw_markers(display, state->id3->length, + if ( ab_repeat_mode_enabled() && length != 0 ) + ab_draw_markers(display, length, pb->x, pb->x + pb->width, y, pb->height); #endif - if (state->id3->cuesheet) - cue_draw_markers(display, state->id3->cuesheet, state->id3->length, + if (id3 && id3->cuesheet) + cue_draw_markers(display, state->id3->cuesheet, length, pb->x, pb->x + pb->width, y+1, pb->height-2); } @@ -266,12 +277,20 @@ static bool draw_player_progress(struct gui_wps *gwps) int pos = 0; int i; - if (!state->id3) - return false; + int elapsed, length; + if (LIKELY(state->id3)) + { + elapsed = state->id3->elapsed; + length = state->id3->length; + } + else + { + elapsed = 0; + length = 0; + } - if (state->id3->length) - pos = 36 * (state->id3->elapsed + state->ff_rewind_count) - / state->id3->length; + if (length) + pos = 36 * (elapsed + state->ff_rewind_count) / length; for (i = 0; i < 7; i++, pos -= 5) { @@ -314,12 +333,24 @@ static void draw_player_fullbar(struct gui_wps *gwps, char* buf, int buf_size) int digit, i, j; bool softchar; - if (!state->id3 || buf_size < 34) /* worst case: 11x UTF-8 char + \0 */ + int elapsed, length; + if (LIKELY(state->id3)) + { + elapsed = id3->elapsed; + length = id3->length; + } + else + { + elapsed = 0; + length = 0; + } + + if (buf_size < 34) /* worst case: 11x UTF-8 char + \0 */ return; - time = state->id3->elapsed + state->ff_rewind_count; - if (state->id3->length) - pos = 55 * time / state->id3->length; + time = elapsed + state->ff_rewind_count; + if (length) + pos = 55 * time / length; memset(timestr, 0, sizeof(timestr)); format_time(timestr, sizeof(timestr)-2, time); @@ -879,14 +910,8 @@ static bool skin_redraw(struct gui_wps *gwps, unsigned refresh_mode) { struct wps_data *data = gwps->data; struct screen *display = gwps->display; - struct wps_state *state = gwps->state; - - if (!data || !state || !display) - return false; - - struct mp3entry *id3 = state->id3; - if (!id3) + if (!data || !display || !gwps->state) return false; unsigned flags; 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