diff --git a/apps/gui/skin_engine/skin_display.c b/apps/gui/skin_engine/skin_display.c index a6cab63..b64de43 100644 --- a/apps/gui/skin_engine/skin_display.c +++ b/apps/gui/skin_engine/skin_display.c @@ -167,6 +167,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) @@ -178,27 +179,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); } @@ -277,12 +288,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) { @@ -325,12 +344,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); @@ -962,14 +993,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; int line, i, subline_idx; diff --git a/apps/gui/skin_engine/skin_tokens.c b/apps/gui/skin_engine/skin_tokens.c index 386dc5d..2aab81b 100644 --- a/apps/gui/skin_engine/skin_tokens.c +++ b/apps/gui/skin_engine/skin_tokens.c @@ -59,7 +59,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; @@ -115,6 +115,28 @@ 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 macros for the id3 == NULL case */ + +#define HANDLE_NULL_ID3(field) (LIKELY(id3) ? id3->field : na) + +#define HANDLE_NULL_ID3_NUM_ZERO { if (UNLIKELY(!id3)) return zero; } + +#define HANDLE_NULL_ID3_NUM_NULL { if (UNLIKELY(!id3)) return zero; } + +#define HANDLE_NULL_ID3_NUM_INTVAL(field) \ + do { \ + if (intval) { \ + *intval = (LIKELY(id3) ? id3->field + 1 : 0); \ + } \ + if (LIKELY(id3)) \ + { \ + snprintf(buf, buf_size, "%ld", id3->field); \ + return buf; \ + } \ + return zero; \ + } while (0) + const char *get_token_value(struct gui_wps *gwps, struct wps_token *token, char *buf, int buf_size, @@ -125,6 +147,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 = "n/a"; + static const char * const zero = "0"; if (!data || !state) return NULL; @@ -136,8 +161,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; @@ -171,17 +204,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: @@ -228,37 +261,38 @@ 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(artist); case WPS_TOKEN_METADATA_COMPOSER: - return id3->composer; + return HANDLE_NULL_ID3(composer); case WPS_TOKEN_METADATA_ALBUM: - return id3->album; + return HANDLE_NULL_ID3(album); case WPS_TOKEN_METADATA_ALBUM_ARTIST: - return id3->albumartist; + return HANDLE_NULL_ID3(albumartist); case WPS_TOKEN_METADATA_GROUPING: - return id3->grouping; + return HANDLE_NULL_ID3(grouping); case WPS_TOKEN_METADATA_GENRE: - return id3->genre_string; + return HANDLE_NULL_ID3(genre_string); case WPS_TOKEN_METADATA_DISC_NUMBER: + HANDLE_NULL_ID3_NUM_NULL; if (id3->disc_string) return id3->disc_string; if (id3->discnum) { @@ -268,6 +302,7 @@ const char *get_token_value(struct gui_wps *gwps, return NULL; case WPS_TOKEN_METADATA_TRACK_NUMBER: + HANDLE_NULL_ID3_NUM_NULL; if (id3->track_string) return id3->track_string; @@ -278,9 +313,10 @@ const char *get_token_value(struct gui_wps *gwps, return NULL; case WPS_TOKEN_METADATA_TRACK_TITLE: - return id3->title; + return HANDLE_NULL_ID3(title); case WPS_TOKEN_METADATA_VERSION: + HANDLE_NULL_ID3_NUM_NULL; switch (id3->id3version) { case ID3_VER_1_0: @@ -303,6 +339,7 @@ const char *get_token_value(struct gui_wps *gwps, } case WPS_TOKEN_METADATA_YEAR: + HANDLE_NULL_ID3_NUM_NULL; if( id3->year_string ) return id3->year_string; @@ -313,7 +350,7 @@ const char *get_token_value(struct gui_wps *gwps, return NULL; case WPS_TOKEN_METADATA_COMMENT: - return id3->comment; + return HANDLE_NULL_ID3(comment); #ifdef HAVE_ALBUMART case WPS_TOKEN_ALBUMART_DISPLAY: @@ -328,7 +365,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 "?"; @@ -337,7 +374,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; @@ -345,10 +384,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); @@ -359,6 +400,7 @@ const char *get_token_value(struct gui_wps *gwps, return buf; case WPS_TOKEN_FILE_NAME: + if (!id3) return na; if (get_dir(buf, buf_size, id3->path, 0)) { /* Remove extension */ char* sep = strrchr(buf, '.'); @@ -372,20 +414,24 @@ const char *get_token_value(struct gui_wps *gwps, } case WPS_TOKEN_FILE_NAME_WITH_EXTENSION: + if (!id3) return na; return get_dir(buf, buf_size, id3->path, 0); case WPS_TOKEN_FILE_PATH: - return id3->path; + return HANDLE_NULL_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; case WPS_TOKEN_BATTERY_PERCENT: { @@ -634,27 +680,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(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(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(score); #endif #if (CONFIG_CODEC == SWCODEC) @@ -672,9 +707,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 @@ -693,6 +732,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);