? foo.diff Index: gwps-common.c =================================================================== RCS file: /cvsroot/rockbox/apps/gui/gwps-common.c,v retrieving revision 1.22 diff -u -r1.22 gwps-common.c --- gwps-common.c 5 Jan 2006 21:05:42 -0000 1.22 +++ gwps-common.c 9 Jan 2006 12:20:10 -0000 @@ -83,17 +83,20 @@ return c; } #endif + /* * parse the given buffer for following static tags: + * * %x - load image for always display * %xl - preload image * %we - enable statusbar on wps regardless of the global setting * %wd - disable statusbar on wps regardless of the global setting + * * and also for: + * * # - a comment line * - * it returns true if one of these tags is found and handled - * false otherwise + * and also for any other tags which will be put into the token list */ bool wps_data_preload_tags(struct wps_data *data, char *buf, const char *bmpdir, size_t bmpdirlen) @@ -110,8 +113,10 @@ if(*buf == '#') return true; + if('%' != *buf) return false; + buf++; c = *buf; @@ -332,162 +337,107 @@ * buf_size - size of buffer. * flags - returns the type of the line. See constants i wps-display.h * - * Returns the tag. NULL indicates the tag wasn't available. + * Returns true if tag was parsed. */ -static char* get_tag(struct wps_data* wps_data, - struct mp3entry* cid3, - struct mp3entry* nid3, - const char* tag, - char* buf, - int buf_size, - unsigned char* tag_len, - unsigned short* subline_time_mult, - unsigned char* flags, - int *intval) +bool parse_token(struct wps_data* wps_data, + const char* tag, + unsigned char* tag_len, + unsigned char* flags) { - struct mp3entry *id3 = cid3; /* default to current song */ #ifndef HAVE_LCD_CHARCELLS (void)wps_data; #endif - if ((0 == tag[0]) || (0 == tag[1])) - { + + if ((0 == tag[0]) || (0 == tag[1])) { *tag_len = 0; - return NULL; + return false; } *tag_len = 2; - - *intval = 0; switch (tag[0]) { - case 'I': /* ID3 Information */ - id3 = nid3; /* display next-song data */ + case 'I': /* ID3 Information (next song) */ *flags |= WPS_REFRESH_DYNAMIC; - if(!id3) - return NULL; /* no such info (yet) */ - /* fall-through */ + wps_data->tokens[num_tokens].use_next_id3 = true; case 'i': /* ID3 Information */ *flags |= WPS_REFRESH_STATIC; + wps_data->tokens[num_tokens].requires_id3 = true; switch (tag[1]) { case 't': /* ID3 Title */ - return id3->title; + wps_data->tokens[num_tokens].type = WPS_TOKEN_ID3_TITLE; + return true; case 'a': /* ID3 Artist */ - return id3->artist; + wps_data->tokens[num_tokens].type = WPS_TOKEN_ID3_ARTIST; + return true; case 'n': /* ID3 Track Number */ - if (id3->track_string) - return id3->track_string; - - if (id3->tracknum) { - snprintf(buf, buf_size, "%d", id3->tracknum); - return buf; - } - return NULL; + wps_data->tokens[num_tokens].type = WPS_TOKEN_ID3_NUMBER; + return true; case 'd': /* ID3 Album/Disc */ - return id3->album; + wps_data->tokens[num_tokens].type = WPS_TOKEN_ID3_DISC; + return true; case 'c': /* ID3 Composer */ - return id3->composer; + wps_data->tokens[num_tokens].type = WPS_TOKEN_ID3_COMPOSER; + return true; case 'y': /* year */ - if( id3->year_string ) - return id3->year_string; - - if (id3->year) { - snprintf(buf, buf_size, "%d", id3->year); - return buf; - } - return NULL; + wps_data->tokens[num_tokens].type = WPS_TOKEN_ID3_YEAR; + return true; case 'g': /* genre */ - return id3_get_genre(id3); + wps_data->tokens[num_tokens].type = WPS_TOKEN_ID3_GENRE; + return true; case 'v': /* id3 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; - } + wps_data->tokens[num_tokens].type = WPS_TOKEN_ID3_VERSION; + return true; } break; - case 'F': /* File Information */ - id3 = nid3; + case 'F': /* File Information (next song) */ *flags |= WPS_REFRESH_DYNAMIC; - if(!id3) - return NULL; /* no such info (yet) */ - /* fall-through */ + wps_data->tokens[num_tokens].use_next_id3 = true; case 'f': /* File Information */ *flags |= WPS_REFRESH_STATIC; + wps_data->tokens[num_tokens].requires_id3 = true; switch(tag[1]) { case 'v': /* VBR file? */ - return id3->vbr ? "(avg)" : NULL; + wps_data->tokens[num_tokens].type = WPS_TOKEN_FILE_VBR; + return true; case 'b': /* File Bitrate */ - if(id3->bitrate) - snprintf(buf, buf_size, "%d", id3->bitrate); - else - snprintf(buf, buf_size, "?"); - return buf; + wps_data->tokens[num_tokens].type = WPS_TOKEN_FILE_BITRATE; + return true; case 'f': /* File Frequency */ - snprintf(buf, buf_size, "%ld", id3->frequency); - return buf; + wps_data->tokens[num_tokens].type = WPS_TOKEN_FILE_FREQUENCY; + return true; case 'p': /* File Path */ - return id3->path; + wps_data->tokens[num_tokens].type = WPS_TOKEN_FILE_PATH; + return true; case 'm': /* File Name - With Extension */ - return get_dir(buf, buf_size, id3->path, 0); + wps_data->tokens[num_tokens].type = WPS_TOKEN_FILE_NAME_WITH_EXT; + return true; case 'n': /* 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; - } + wps_data->tokens[num_tokens].type = WPS_TOKEN_FILE_NAME; + return true; case 's': /* File Size (in kilobytes) */ - snprintf(buf, buf_size, "%ld", id3->filesize / 1024); - return buf; + wps_data->tokens[num_tokens].type = WPS_TOKEN_FILE_SIZE; + return true; case 'c': /* File Codec */ - if(id3->codectype == AFMT_UNKNOWN) - *intval = AFMT_NUM_CODECS; - else - *intval = id3->codectype; - return id3_get_codec(id3); + wps_data->tokens[num_tokens].type = WPS_TOKEN_FILE_CODEC; + return true; } break; @@ -496,86 +446,59 @@ { case 'b': /* progress bar */ *flags |= WPS_REFRESH_PLAYER_PROGRESS; -#ifdef HAVE_LCD_CHARCELLS - snprintf(buf, buf_size, "%c", - wps_data->wps_progress_pat[0]); - wps_data->full_line_progressbar=0; - return buf; -#else - return "\x01"; -#endif + wps_data->tokens[num_tokens].type = WPS_TOKEN_PLAYLIST_PROGRESS; + return true; + case 'f': /* full-line progress bar */ -#ifdef HAVE_LCD_CHARCELLS - if(is_new_player()) { - *flags |= WPS_REFRESH_PLAYER_PROGRESS; - *flags |= WPS_REFRESH_DYNAMIC; - wps_data->full_line_progressbar=1; - /* we need 11 characters (full line) for - progress-bar */ - snprintf(buf, buf_size, " "); - } - else - { - /* Tell the user if we have an OldPlayer */ - snprintf(buf, buf_size, " "); - } - return buf; -#endif + wps_data->tokens[num_tokens].type = WPS_TOKEN_PLAYLIST_PROGRESS_FULL; + return true; + case 'p': /* Playlist Position */ *flags |= WPS_REFRESH_STATIC; - snprintf(buf, buf_size, "%d", - playlist_get_display_index()); - return buf; + wps_data->tokens[num_tokens].type = WPS_TOKEN_PLAYLIST_POSITION; + return true; case 'n': /* Playlist Name (without path) */ *flags |= WPS_REFRESH_STATIC; - return playlist_name(NULL, buf, buf_size); + wps_data->tokens[num_tokens].type = WPS_TOKEN_PLAYLIST_NAME; + return true; case 'e': /* Playlist Total Entries */ *flags |= WPS_REFRESH_STATIC; - snprintf(buf, buf_size, "%d", playlist_amount()); - return buf; + wps_data->tokens[num_tokens].type = WPS_TOKEN_PLAYLIST_TOTAL_ENTRIES; + return true; case 'c': /* Current Time in Song */ *flags |= WPS_REFRESH_DYNAMIC; - gui_wps_format_time(buf, buf_size, - id3->elapsed + wps_state.ff_rewind_count); - return buf; + wps_data->tokens[num_tokens].type = WPS_TOKEN_PLAYLIST_CURRENT_TIME; + wps_data->tokens[num_tokens].requires_id3 = true; + return true; case 'r': /* Remaining Time in Song */ *flags |= WPS_REFRESH_DYNAMIC; - gui_wps_format_time(buf, buf_size, - id3->length - id3->elapsed - - wps_state.ff_rewind_count); - return buf; + wps_data->tokens[num_tokens].type = WPS_TOKEN_PLAYLIST_REMAIN_TIME; + wps_data->tokens[num_tokens].requires_id3 = true; + return true; case 't': /* Total Time */ *flags |= WPS_REFRESH_STATIC; - gui_wps_format_time(buf, buf_size, id3->length); - return buf; + wps_data->tokens[num_tokens].type = WPS_TOKEN_PLAYLIST_TOTAL_TIME; + wps_data->tokens[num_tokens].requires_id3 = true; + return true; -#ifdef HAVE_LCD_BITMAP case 'm': /* Peak Meter */ - *flags |= WPS_REFRESH_PEAK_METER; - return "\x01"; -#endif + wps_data->tokens[num_tokens].type = WPS_TOKEN_PLAYLIST_PEAK_METER; + return true; + case 's': /* shuffle */ *flags |= WPS_REFRESH_DYNAMIC; - if ( global_settings.playlist_shuffle ) - return "s"; - else - return NULL; - break; + wps_data->tokens[num_tokens].type = WPS_TOKEN_PLAYLIST_SHUFFLE; + return true; case 'v': /* volume */ *flags |= WPS_REFRESH_DYNAMIC; - snprintf(buf, buf_size, "%d", global_settings.volume); - *intval = 10 * (global_settings.volume - - sound_min(SOUND_VOLUME)) - / (sound_max(SOUND_VOLUME) - - sound_min(SOUND_VOLUME)) + 1; - return buf; - + wps_data->tokens[num_tokens].type = WPS_TOKEN_PLAYLIST_VOLUME; + return true; } break; @@ -584,118 +507,67 @@ { case 'm': /* playback repeat mode */ *flags |= WPS_REFRESH_DYNAMIC; - *intval = global_settings.repeat_mode + 1; - snprintf(buf, buf_size, "%d", *intval); - return buf; + wps_data->tokens[num_tokens].type = WPS_TOKEN_MODE_REPEAT; + return true; - /* playback status */ - case 'p': /* play */ + case 'p': /* playback status play */ *flags |= WPS_REFRESH_DYNAMIC; - int status = audio_status(); - *intval = 1; - if (status == AUDIO_STATUS_PLAY && \ - !(status & AUDIO_STATUS_PAUSE)) - *intval = 2; - if (audio_status() & AUDIO_STATUS_PAUSE && \ - (! status_get_ffmode())) - *intval = 3; - if (status_get_ffmode() == STATUS_FASTFORWARD) - *intval = 4; - if (status_get_ffmode() == STATUS_FASTBACKWARD) - *intval = 5; - snprintf(buf, buf_size, "%d", *intval); - return buf; + wps_data->tokens[num_tokens].type = WPS_TOKEN_MODE_STATUS; + return true; #if (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD) case 'h': /* hold */ *flags |= WPS_REFRESH_DYNAMIC; - if (button_hold()) - return "h"; - else - return NULL; + wps_data->tokens[num_tokens].type = WPS_TOKEN_MODE_HOLD; + return true; + case 'r': /* remote hold */ *flags |= WPS_REFRESH_DYNAMIC; - if (remote_button_hold()) - return "r"; - else - return NULL; + wps_data->tokens[num_tokens].type = WPS_TOKEN_MODE_REMOTE_HOLD; + return true; #endif } break; case 'b': /* battery info */ - *flags |= WPS_REFRESH_DYNAMIC; switch (tag[1]) { case 'l': /* battery level */ - { - int l = battery_level(); - if (l > -1) - { - snprintf(buf, buf_size, "%d", l); - *intval = l / 20 + 1; - } - else - { - *intval = 6; - return "?%"; - } - return buf; - } + *flags |= WPS_REFRESH_DYNAMIC; + wps_data->tokens[num_tokens].type = WPS_TOKEN_BATTERY_LEVEL; + return true; case 't': /* estimated battery time */ - { - int t = battery_time(); - if (t >= 0) - snprintf(buf, buf_size, "%dh %dm", t / 60, t % 60); - else - strncpy(buf, "?h ?m", buf_size); - return buf; - } - - case 'p': /* External power plugged in? */ - { - if(charger_inserted()) - return "p"; - else - return NULL; - } + wps_data->tokens[num_tokens].type = WPS_TOKEN_BATTERY_TIME; + return true; } break; + + case 'p': /* External power plugged in? */ + wps_data->tokens[num_tokens].type = WPS_TOKEN_POWER; + return true; #if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD) case 'l': /* VIRTUAL_LED */ - { - switch(tag[1]) - { - case 'h': /* Only one we have so far HDD LED */ - *flags |= WPS_REFRESH_DYNAMIC; - if(led_read(HZ/2)) - return "h"; - else - return NULL; + if (tag[1] == 'h' && led_read(HZ/2)) { + wps_data->tokens[num_tokens].type = WPS_TOKEN_VIRTUAL_HDD_LED; + return true; } - } - break; + return false; #endif - case 'D': /* Directory path information */ - id3 = nid3; /* next song please! */ - *flags |= WPS_REFRESH_DYNAMIC; - if(!id3) - return NULL; /* no such info (yet) */ - /* fall-through */ + case 'D': /* Directory path information (next song) */ + wps_data->tokens[num_tokens].type = WPS_TOKEN_DIRECTORY; + wps_data->tokens[num_tokens].use_next_id3 = true; + wps_data->tokens[num_tokens].requires_id3 = true; + wps_data->tokens[num_tokens].value.n = tag[1] - '0'; + return true; + case 'd': /* Directory path information */ - { - int level = tag[1] - '0'; - *flags |= WPS_REFRESH_STATIC; - /* d1 through d9 */ - if ((0 < level) && (9 > level)) - { - return get_dir(buf, buf_size, id3->path, level); - } - } - break; + wps_data->tokens[num_tokens].type = WPS_TOKEN_DIRECTORY; + wps_data->tokens[num_tokens].requires_id3 = true; + wps_data->tokens[num_tokens].value.n = tag[1] - '0'; + return true; case 't': /* set sub line time multiplier */ { @@ -704,23 +576,17 @@ bool have_point = false; bool have_tenth = false; - while (((tag[d] >= '0') && - (tag[d] <= '9')) || - (tag[d] == '.')) + while (((tag[d] >= '0') && (tag[d] <= '9')) || (tag[d] == '.')) { - if (tag[d] != '.') - { + if (tag[d] != '.') { time_mult = time_mult * 10; time_mult = time_mult + tag[d] - '0'; - if (have_point) - { + if (have_point) { have_tenth = true; d++; break; } - } - else - { + } else { have_point = true; } d++; @@ -729,29 +595,98 @@ if (have_tenth == false) time_mult *= 10; - *subline_time_mult = time_mult; - *tag_len = d; - - buf[0] = 0; - return buf; + wps_data->tokens[num_tokens].type = WPS_TOKEN_TIME; + wps_data->tokesn[num_tokens].value.n = d; + return true; } break; + case 'r': /* Runtime database Information */ switch(tag[1]) { case 'p': /* Playcount */ - *flags |= WPS_REFRESH_STATIC; - snprintf(buf, buf_size, "%ld", cid3->playcount); - return buf; + wps_data->tokens[num_tokens].type = WPS_TOKEN_RTDB_PLAYCOUNT; + wps_data->tokens[num_tokens].requires_id3 = true; + return true; + case 'r': /* Rating */ *flags |= WPS_REFRESH_STATIC; - *intval = cid3->rating+1; - snprintf(buf, buf_size, "%d", cid3->rating); - return buf; + wps_data->tokens[num_tokens].type = WPS_TOKEN_RTDB_RATING; + wps_data->tokens[num_tokens].requires_id3 = true; + return true; } break; + + case 'a': /* Alignment */ + switch(tag[1]) + { + case 'l': /* align left */ + wps_data->tokens[num_tokens].type = WPS_TOKEN_ALIGN_LEFT; + return true; + + case 'c': /* align center */ + wps_data->tokens[num_tokens].type = WPS_TOKEN_ALIGN_CENTER; + return true; + + case 'r': /* align right */ + wps_data->tokens[num_tokens].type = WPS_TOKEN_ALIGN_RIGHT; + return true; + } + +#ifdef HAVE_LCD_BITMAP + case 'x': /* image support */ + if ('d' == fmt[1]) /* display image */ + { + wps_data->tokens[num_tokens].type = WPS_TOKEN_IMAGE; + wps_data->tokens[num_tokens].value.image = get_image_id(fmt[2]); + } + + fmt += 3; + return true; +#endif + + } + + return false; +} + +int get_conditional(struct wps_data* wps_data, + struct mp3entry* id3, + enum token_type type) +{ + switch (type) + { + case WPS_TOKEN_FILE_CODEC: + return (id3->codectype == AFMT_UNKNOWN) ? AFMT_NUM_CODECS : id3->codectype; + + case WPS_TOKEN_PLAYLIST_VOLUME: + return 10 * (global_settings.volume - sound_min(SOUND_VOLUME)) + / (sound_max(SOUND_VOLUME) - sound_min(SOUND_VOLUME)) + 1; + + case WPS_TOKEN_MODE_REPEAT: + return global_settings.repeat_mode + 1; + + case WPS_TOKEN_RTDB_RATING: + return id3->rating+1; + + case WPS_TOKEN_BATTERY_LEVEL: + return (battery_level() > -1) ? battery_level() / 20 + 1 : 6; + + case WPS_TOKEN_MODE_STATUS: + if (status_get_ffmode() == STATUS_FASTBACKWARD) + return 5; + else if (status_get_ffmode() == STATUS_FASTFORWARD) + return 4; + else if (audio_status() == AUDIO_STATUS_PAUSE && !status_get_ffmode()) + return 3; + else if (audio_status() == AUDIO_STATUS_PLAY && !(audio_status() & AUDIO_STATUS_PAUSE)) + return 2; + else + return 1; + + default: + return 0; } - return NULL; } #ifdef HAVE_LCD_BITMAP @@ -762,192 +697,275 @@ return; struct wps_data *data = gwps->data; gwps->display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); - gwps->display->fillrect(data->img[n].x, data->img[n].y, + gwps->display->fillrect(data->img[n].x, data->img[n].y, data->img[n].w, data->img[n].h); gwps->display->set_drawmode(DRMODE_SOLID); } #endif -/* Skip to the end of the current %? conditional. - * - * fmt - string to skip it. Should point to somewhere after the leading - * "<" char (and before or at the last ">"). - * num - number of |'s to skip, or 0 to skip to the end (the ">"). - * - * Returns the new position in fmt. - */ -static const char* skip_conditional(struct gui_wps *gwps, const char* fmt, - int num) +/* format_token + format a single token, putting the output into the buffer, when used + correctly this appends to existing formatted tokens */ +int format_token() { - int level = 1; - int count = num; - const char *last_alternative = NULL; -#ifdef HAVE_LCD_BITMAP - struct wps_data *data = NULL; - int last_x=-1, last_y=-1, last_w=-1, last_h=-1; - if(gwps) - data = gwps->data; + if (token->requires_id3 && id3 == NULL) + return 0; + + switch (token->type) + { + case WPS_TOKEN_STRING: + snprintf(buf, buf_size, "%s", token.value.string); + break; + + case WPS_TOKEN_ID3_TITLE: + snprintf(buf, buf_size, "%s", id3->title); + break; + + case WPS_TOKEN_ID3_ARTIST: + snprintf(buf, buf_size, "%s", id3->artist); + break; + + case WPS_TOKEN_ID3_NUMBER; + if (id3->track_string) + snprintf(buf, buf_size, "%s", id3->track_string); + else if (id3->tracknum) + snprintf(buf, buf_size, "%d", id3->tracknum); + else + snprintf(buf, buf_size, "?"); + break; + + case WPS_TOKEN_ID3_DISC: + snprintf(buf, buf_size, "%s", id3->disc); + break; + + case WPS_TOKEN_ID3_COMPOSER: + snprintf(buf, buf_size, "%s", id3->composer); + break; + + case WPS_TOKEN_ID3_YEAR: + if (id3->year_string) + snprintf(buf, buf_size, "%s", id3->year_string); + else if (id3->year) + snprintf(buf, buf_size, "%d", id3->year); + else + snprintf(buf, buf_size, "?"); + break; + + case WPS_TOKEN_ID3_COMPOSER: + snprintf(buf, buf_size, "%s", id3_get_genre(id3)); + break; + + case WPS_TOKEN_ID3_VERSION: + switch (id3->id3version) { + case ID3_VER_1_0: snprintf(buf, buf_size, "1"); + case ID3_VER_1_1: snprintf(buf, buf_size, "1.1"); + case ID3_VER_2_2: snprintf(buf, buf_size, "2.2"); + case ID3_VER_2_3: snprintf(buf, buf_size, "2.3"); + case ID3_VER_2_4: snprintf(buf, buf_size, "2.4"); + default: snprintf(buf, buf_size, "?"); + } + break; + + case WPS_TOKEN_FILE_VBR: + snprintf(buf, buf_size, "%s", id3->vbr ? "(avg)" : ""); + break; + + case WPS_TOKEN_FILE_BITRATE: + if (id3->bitrate) + snprintf(buf, buf_size, "%d", id3->bitrate); + else + snprintf(buf, buf_size, "?"); + break; + + case WPS_TOKEN_FILE_FREQUENCY: + snprintf(buf, buf_size, "%ld", id3->frequency); + break; + + case WPS_TOKEN_FILE_PATH: + snprintf(buf, buf_size, "%ld", id3->path); + return buf; + + case WPS_TOKEN_FILE_NAME_WITH_EXT: + snprintf(buf, buf_size, "%ld", get_dir(buf, buf_size, id3->path, 0)); + break; + + case WPS_TOKEN_FILE_NAME: + snprintf(buf, buf_size, "%ld", get_dir(buf, buf_size, id3->path, 0)); + char* sep = strrchr(buf, '.'); + if (NULL != sep) + *sep = 0; + break; + + case WPS_TOKEN_FILE_SIZE: + snprintf(buf, buf_size, "%ld", id3->filesize / 1024); + break; + + case WPS_TOKEN_FILE_CODEC: + snprintf(buf, buf_size, "%ld", id3_get_codec(id3)); + break; + + case WPS_TOKEN_PLAYLIST_PROGRESS: +#ifdef HAVE_LCD_CHARCELLS + snprintf(buf, buf_size, "%c", wps_data->wps_progress_pat[0]); + wps_data->full_line_progressbar = 0; + break; #else - (void)gwps; + snprintf(buf, buf_size, "\x01"); + break; #endif - while (*fmt) - { - switch (*fmt++) - { - case '%': + + case WPS_TOKEN_PLAYLIST_PROGRESS_FULL: +#ifdef HAVE_LCD_CHARCELLS + if (is_new_player()) { + snprintf(buf, buf_size, " "); + wps_data->full_line_progressbar = 1; + } else { + /* Tell the user if we have an OldPlayer */ + snprintf(buf, buf_size, " "); + } + break; +#else + snprintf(buf, buf_size, "\x01"); + break; +#endif + + case WPS_TOKEN_PLAYLIST_POSITION: + snprintf(buf, buf_size, "%d", playlist_get_display_index()); + break; + + case WPS_TOKEN_PLAYLIST_NAME: + snprintf(buf, buf_size, "%s", playlist_name(NULL, buf, buf_size)); + break; + + case WPS_TOKEN_PLAYLIST_TOTAL_ENTRIES: + snprintf(buf, buf_size, "%d", playlist_amount()); + break; + + case WPS_TOKEN_PLAYLIST_CURRENT_TIME: + gui_wps_format_time(buf, buf_size, id3->elapsed + wps_state.ff_rewind_count); + break; + + case WPS_TOKEN_PLAYLIST_REMAIN_TIME: + gui_wps_format_time(buf, buf_size, id3->length - id3->elapsed - wps_state.ff_rewind_count); + break; + + case WPS_TOKEN_PLAYLIST_TOTAL_TIME: + gui_wps_format_time(buf, buf_size, id3->length); + break; + #ifdef HAVE_LCD_BITMAP - if(data && *(fmt) == 'x' && *(fmt+1) == 'd' ) - { - fmt +=2; - int n = *fmt; - if(n >= 'a' && n <= 'z') - n -= 'a'; - if(n >= 'A' && n <= 'Z') - n = n - 'A' + 26; - if(last_x != data->img[n].x || last_y != data->img[n].y - || last_w != data->img[n].w || last_h != data->img[n].h) - { - last_x = data->img[n].x; - last_y = data->img[n].y; - last_w = data->img[n].w; - last_h = data->img[n].h; - clear_image_pos(gwps,n); - } - } + case WPS_TOKEN_PLAYLIST_PEAK_METER: + snprintf(buf, buf_size, "\x01"); + break; #endif - break; - case '|': - if(1 == level) { - last_alternative = fmt; - if(num) { - count--; - if(count == 0) - return fmt; - continue; - } - } - continue; + case WPS_TOKEN_PLAYLIST_SHUFFLE: + snprintf(buf, buf_size, "%s", global_settings.playlist_shuffle ? "s" : ""); + break; - case '>': - if (0 == --level) - { - /* We're just skipping to the end */ - if(num == 0) - return fmt; - - /* If we are parsing an enum, we'll return the selected - item. If there weren't enough items in the enum, we'll - return the last one found. */ - if(count && last_alternative) - { - return last_alternative; - } - return fmt - 1; - } - continue; + case WPS_TOKEN_PLAYLIST_VOLUME: + snprintf(buf, buf_size, "%d", global_settings.volume); + break; + + case WPS_TOKEN_MODE_REPEAT: + snprintf(buf, buf_size, "%d", global_settings.repeat_mode + 1); + break; + + case WPS_TOKEN_MODE_STATUS: + snprintf(buf, buf_size, "%d", get_conditional(wps_data, id3, WPS_TOKEN_MODE_STATUS)); + break; - default: - continue; - } +#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || (CONFIG_KEYPAD == IRIVER_H300_PAD) + case WPS_TOKEN_MODE_HOLD: + snprintf(buf, buf_size, "%s", button_hold() ? "h" : NULL); + break; - switch (*fmt++) - { - case 0: - case '%': - case '|': - case '<': - case '>': - break; + case WPS_TOKEN_MODE_REMOTE_HOLD: + snprintf(buf, buf_size, "%s", remote_button_hold() ? "h" : NULL); + break; +#endif - case '?': - while (*fmt && ('<' != *fmt)) - fmt++; + case WPS_TOKEN_BATTERY_LEVEL: + if (battery_level() > -1) + snprintf(buf, buf_size, "%d", battery_level()); + else + snprintf(buf, buf_size, "?%"); + break; - if ('<' == *fmt) - fmt++; + case WPS_TOKEN_BATTERY_TIME: + if (battery_time() >= 0) + snprintf(buf, buf_size, "%dh %dm", battery_time() / 60, battery_time() % 60); + else + snprintf(buf, buf_size, "?h ?m"); + break; + + case WPS_TOKEN_POWER: + snprintf(buf, buf_size, "%s", charger_inserted() ? "p" : NULL); + break; - level++; - break; + case WPS_TOKEN_DIRECTORY: + snprintf(buf, buf_size, "%s", get_dir(buf, buf_size, id3->path, token->value.n)); + break; - default: - break; - } + case WPS_TOKEN_RTDB_PLAYCOUNT: + snprintf(buf, buf_size, "%ld", id3->playcount); + break; + + case WPS_TOKEN_RTDB_RATING: + snprintf(buf, buf_size, "%d", id3->rating); + break; + + default: + break; } - return fmt; + return strlen(buf); } -/* Generate the display based on id3 information and format string. +/* Generate a single display line based on id3 information and token list * * buf - char buffer to write the display to. * buf_size - the size of buffer. - * id3 - the ID3 data to format with. + * cid3 - the ID3 data to format with. * nid3 - the ID3 data of the next song (might by NULL) - * fmt - format description. * flags - returns the type of the line. See constants i wps-display.h + * token - pointer to current token */ -static void format_display(struct gui_wps *gwps, char* buf, +static void format_display(struct gui_wps *gwps, + char* buf, int buf_size, - struct mp3entry* id3, + struct mp3entry* cid3, struct mp3entry* nid3, /* next song's id3 */ - const char* fmt, struct align_pos* align, unsigned short* subline_time_mult, - unsigned char* flags) + unsigned char* flags, + struct wps_token* token) { - char temp_buf[128]; char* buf_start = buf; - char* buf_end = buf + buf_size - 1; /* Leave room for end null */ - char* value = NULL; - int level = 0; - unsigned char tag_length; - int intval; - int cur_align; + char* buf_end = buf + buf_size - 1; char* cur_align_start; -#ifdef HAVE_LCD_BITMAP - struct gui_img *img = gwps->data->img; - int n; -#endif + int cur_align; cur_align_start = buf; cur_align = WPS_ALIGN_LEFT; - *subline_time_mult = DEFAULT_SUBLINE_TIME_MULTIPLIER; align->left = 0; align->center = 0; align->right = 0; - while (fmt && *fmt && buf < buf_end) + while (token < gpws->data->tokens + gpws->data->num_tokens) { - switch (*fmt) - { - case '%': - ++fmt; - break; + if (token->type == WPS_TOKEN_EOL) + break; - case '|': - case '>': - if (level > 0) - { - fmt = skip_conditional(NULL,fmt, 0); - level--; - continue; - } - /* Else fall through */ + if (get_conditional(token->conditional_type) != token->conditional_match) + continue; - default: - *buf++ = *fmt++; - continue; - } - - switch (*fmt) + switch (token->type) { - case 0: - *buf++ = '%'; - break; - case 'a': - ++fmt; + case WPS_TOKEN_ALIGN_LEFT: + case WPS_TOKEN_ALIGN_CENTER: + case WPS_TOKEN_ALIGN_RIGHT: /* remember where the current aligned text started */ switch (cur_align) { @@ -964,91 +982,32 @@ break; } /* start a new alignment */ - switch (*fmt) + switch (type) { - case 'l': + case WPS_TOKEN_ALIGN_LEFT: cur_align = WPS_ALIGN_LEFT; break; - case 'c': + + case WPS_TOKEN_ALIGN_CENTER: cur_align = WPS_ALIGN_CENTER; break; - case 'r': + + case WPS_TOKEN_ALIGN_RIGHT: cur_align = WPS_ALIGN_RIGHT; break; } - *buf++=0; - cur_align_start = buf; - ++fmt; - break; - case 's': - *flags |= WPS_REFRESH_SCROLL; - ++fmt; break; - case 'x': /* image support */ #ifdef HAVE_LCD_BITMAP - if ('d' == *(fmt+1) ) - { - fmt+=2; - - /* get the image ID */ - n = *fmt; - if(n >= 'a' && n <= 'z') - n -= 'a'; - if(n >= 'A' && n <= 'Z') - n = n - 'A' + 26; - if (n >= 0 && n < MAX_IMAGES && img[n].loaded) { - img[n].display = true; - } - } - -#endif - fmt++; - break; - - - case '%': - case '|': - case '<': - case '>': - case ';': - *buf++ = *fmt++; - break; - - case '?': - fmt++; - value = get_tag(gwps->data, id3, nid3, fmt, temp_buf, - sizeof(temp_buf),&tag_length, - subline_time_mult, flags, &intval); - - while (*fmt && ('<' != *fmt)) - fmt++; - - if ('<' == *fmt) - fmt++; - - /* No value, so skip to else part, using a sufficiently high - value to "hit" the last part of the conditional */ - if ((!value) || (!strlen(value))) - fmt = skip_conditional(gwps, fmt, 1000); - else - if(intval > 1) /* enum */ - fmt = skip_conditional(gwps, fmt, intval - 1); - - level++; + case WPS_TOKEN_IMAGE: + if (gwps->data->img[token.value.image].loaded) + gwps->data->img[token.value.image].display = true; break; +#endif default: - value = get_tag(gwps->data, id3, nid3, fmt, temp_buf, - sizeof(temp_buf), &tag_length, - subline_time_mult, flags,&intval); - fmt += tag_length; - - if (value) - { - while (*value && (buf < buf_end)) - *buf++ = *value++; - } + format_token(gwps, token, buf_start, buf_end - buf_start, (token->use_next_id3) ? nid3 : cid3); + break; } } @@ -1067,17 +1026,6 @@ align->right = cur_align_start; break; } - - *buf = 0; - - /* if resulting line is an empty line, set the subline time to 0 */ - if (buf - buf_start == 0) - *subline_time_mult = 0; - - /* If no flags have been set, the line didn't contain any format codes. - We still want to refresh it. */ - if(*flags == 0) - *flags = WPS_REFRESH_STATIC; } /* fades the volume */ @@ -1125,14 +1073,16 @@ } } -/* Set format string to use for WPS, splitting it into lines */ -void gui_wps_format(struct wps_data *data) +/* parse_format_buffer + convert the format buffer into tokens */ +void parse_format_buffer(struct wps_data *data) { char* buf = data->format_buffer; char* start_of_line = data->format_buffer; int line = 0; int subline; char c; + if(!data) return; @@ -1158,14 +1108,6 @@ switch (c) { - /* - * skip % sequences so "%;" doesn't start a new subline - * don't skip %x lines (pre-load bitmaps) - */ - case '%': - buf++; - break; - case '\r': /* CR */ *buf = 0; break; @@ -1173,8 +1115,12 @@ case '\n': /* LF */ *buf = 0; - if (*start_of_line != '#') /* A comment? */ + if (*start_of_line != '#') /* Not a comment? */ + { + wps_data->tokens[num_tokens].type = WPS_TOKEN_EOL; + num_tokens++; line++; + } if (line < WPS_MAX_LINES) { @@ -1182,6 +1128,7 @@ subline = 0; data->format_lines[line][subline] = buf+1; start_of_line = data->format_lines[line][subline]; + } break; Index: gwps.c =================================================================== RCS file: /cvsroot/rockbox/apps/gui/gwps.c,v retrieving revision 1.17 diff -u -r1.17 gwps.c --- gwps.c 9 Dec 2005 01:11:14 -0000 1.17 +++ gwps.c 9 Jan 2006 12:20:10 -0000 @@ -764,7 +764,7 @@ wps_clear(wps_data); strncpy(wps_data->format_buffer, buf, sizeof(wps_data->format_buffer)); wps_data->format_buffer[sizeof(wps_data->format_buffer) - 1] = 0; - gui_wps_format(wps_data); + parse_format_buffer(wps_data); return true; } else @@ -806,26 +806,22 @@ wps_data->img_buf_free = IMG_BUFSIZE; /* free space in image buffer */ #endif + /* TODO: inefficient, should parse per line, rather than slurp */ while( ( read_line(fd, &wps_data->format_buffer[start], sizeof(wps_data->format_buffer)-start) ) > 0 ) { - if(!wps_data_preload_tags(wps_data, - &wps_data->format_buffer[start], - buf, bmpdirlen)) + start += strlen(&wps_data->format_buffer[start]); + + if (start < sizeof(wps_data->format_buffer) - 1) { - start += strlen(&wps_data->format_buffer[start]); - - if (start < sizeof(wps_data->format_buffer) - 1) - { - wps_data->format_buffer[start++] = '\n'; - wps_data->format_buffer[start] = 0; - } + wps_data->format_buffer[start++] = '\n'; + wps_data->format_buffer[start] = 0; } } if (start > 0) { - gui_wps_format(wps_data); + parse_format_buffer(wps_data); } close(fd); Index: gwps.h =================================================================== RCS file: /cvsroot/rockbox/apps/gui/gwps.h,v retrieving revision 1.10 diff -u -r1.10 gwps.h --- gwps.h 19 Dec 2005 00:11:27 -0000 1.10 +++ gwps.h 9 Jan 2006 12:20:11 -0000 @@ -246,6 +246,80 @@ (1/HZ sec, or 100ths of sec) */ #define SUBLINE_RESET -1 +/* wps tokens + these are tokens used to represent tags in a wps; some tags do + not become tokens (eg, %x or %wd) but affect the wps structure + globally instead + */ +enum token_type { + WPS_TOKEN_STRING, + WPS_TOKEN_IMAGE, + WPS_TOKEN_ID3_TITLE, + WPS_TOKEN_ID3_ARTIST, + WPS_TOKEN_ID3_NUMBER, + WPS_TOKEN_ID3_DISC, + WPS_TOKEN_ID3_COMPOSER, + WPS_TOKEN_ID3_YEAR, + WPS_TOKEN_ID3_GENRE, + WPS_TOKEN_ID3_VERSION, + WPS_TOKEN_FILE_VBR, + WPS_TOKEN_FILE_BITRATE, + WPS_TOKEN_FILE_FREQUENCY, + WPS_TOKEN_FILE_PATH, + WPS_TOKEN_FILE_NAME_WITH_EXT, + WPS_TOKEN_FILE_NAME, + WPS_TOKEN_FILE_SIZE, + WPS_TOKEN_FILE_CODEC, + WPS_TOKEN_PLAYLIST_PROGRESS, + WPS_TOKEN_PLAYLIST_PROGRESS_FULL, + WPS_TOKEN_PLAYLIST_POSITION, + WPS_TOKEN_PLAYLIST_NAME, + WPS_TOKEN_PLAYLIST_NAME_WITH_PATH, + WPS_TOKEN_PLAYLIST_TOTAL_ENTRIES, + WPS_TOKEN_PLAYLIST_CURRENT_TIME, + WPS_TOKEN_PLAYLIST_REMAIN_TIME, + WPS_TOKEN_PLAYLIST_TOTAL_TIME, + WPS_TOKEN_PLAYLIST_PEAK_METER, + WPS_TOKEN_PLAYLIST_SHUFFLE, + WPS_TOKEN_PLAYLIST_VOLUME, + WPS_TOKEN_MODE_REPEAT, + WPS_TOKEN_MODE_STATUS, + WPS_TOKEN_MODE_HOLD, + WPS_TOKEN_MODE_REMOTE_HOLD, + WPS_TOKEN_BATTERY_LEVEL, + WPS_TOKEN_BATTERY_TIME, + WPS_TOKEN_POWER, + WPS_TOKEN_DIRECTORY, + WPS_TOKEN_TIME, + WPS_TOKEN_RTDB_PLAYCOUNT, + WPS_TOKEN_RTDB_RATING, + WPS_TOKEN_ALIGN_LEFT, + WPS_TOKEN_ALIGN_RIGHT, + WPS_TOKEN_ALIGN_CENTER, + WPS_TOKEN_EOL, + WPS_TOKEN_NULL +}; + +/* wps_token + this is the token representing a tag from the wps file */ +/* TODO: sublines */ + +struct wps_token +{ + enum token_type type; + bool use_next_id3; /* merge into flags? */ + bool requires_id3; /* merge into flags? */ + + union { + char *string; + int image; + int n; + } value; + + enum token_type conditional_test; + int conditional_match; +}; + /* wps_data this struct old all necessary data which describes the viewable content of a wps */ @@ -272,6 +346,9 @@ int curr_subline[WPS_MAX_LINES]; bool wps_loaded; bool peak_meter_enabled; + /* token based representation of the wps */ + struct wps_token tokens[WPS_MAX_LINES*WPS_MAX_SUBLINES]; + int num_tokens; }; /* initial setup of wps_data */