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
This commit is contained in:
Thomas Martitz 2009-10-16 19:14:37 +00:00
parent 9072a4558c
commit a72ffe7bb5
2 changed files with 167 additions and 97 deletions

View file

@ -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;

View file

@ -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);