From 1cce533678037e305e28bc3cdd9e5c5c26d7b3fa Mon Sep 17 00:00:00 2001 From: Magnus Holmgren Date: Wed, 7 Dec 2005 20:42:06 +0000 Subject: Patch #1367059 by _FireFly_: New wps loader. The wps buffer size can be reduced now, but it isn't done in this patch. Note that %wd, %we, %x| and %xl now need to be on a line on their own. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8193 a1c6a512-1295-4272-9138-f99709370657 --- apps/gui/gwps-common.c | 341 +++++++++++++++++++++++++++---------------------- apps/gui/gwps-common.h | 5 +- apps/gui/gwps.c | 40 ++++-- apps/gui/gwps.h | 2 + 4 files changed, 220 insertions(+), 168 deletions(-) (limited to 'apps/gui') diff --git a/apps/gui/gwps-common.c b/apps/gui/gwps-common.c index 665f6f4bb0..a6ef9b04d3 100644 --- a/apps/gui/gwps-common.c +++ b/apps/gui/gwps-common.c @@ -55,11 +55,191 @@ static void draw_player_fullbar(struct gui_wps *gwps, /* 3% of 30min file == 54s step size */ #define MIN_FF_REWIND_STEP 500 +/* + * returns the image_id between + * a..z and A..Z + */ +#ifdef HAVE_LCD_BITMAP +static int get_image_id(int c) +{ + if(c >= 'a' && c <= 'z') + c -= 'a'; + if(c >= 'A' && c <= 'Z') + c = c - 'A' + 26; + 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 + */ +bool wps_data_preload_tags(struct wps_data *data, unsigned char *buf, + const char *bmpdir, size_t bmpdirlen) +{ + if(!data || !buf) return false; + + char c; +#ifndef HAVE_LCD_BITMAP + /* no bitmap-lcd == no bitmap loading */ + (void)bmpdir; + (void)bmpdirlen; +#endif + /* jump over the UTF-8 BOM(Byte Order Mark) if exist + * the BOM for UTF-8 is 3 bytes long and looks like so: + * 1. Byte: 0xEF + * 2. Byte: 0xBB + * 3. Byte: 0xBF + */ + if(buf[0] == 0xef && buf[1] == 0xbb && buf[2] == 0xbf) + buf+=3; + + if(*buf == '#') + return true; + if('%' != *buf) + return false; + buf++; + + c = *buf; + switch (c) + { +#ifdef HAVE_LCD_BITMAP + case 'w': + /* + * if tag found then return because these two tags must be on + * must be on their own line + */ + if(*(buf+1) == 'd' || *(buf+1) == 'e') + { + data->wps_sb_tag = true; + if( *(buf+1) == 'e' ) + data->show_sb_on_wps = true; + return true; + } + break; + + case 'x': + /* Preload images so the %xd# tag can display it */ + { + int ret = 0; + int n; + char *ptr = buf+1; + char *pos = NULL; + char imgname[MAX_PATH]; + char qual = *ptr; + + if (qual == 'l' || qual == '|') /* format: + %x|n|filename.bmp|x|y| + or + %xl|n|filename.bmp|x|y| + */ + { + ptr = strchr(ptr, '|') + 1; + pos = strchr(ptr, '|'); + if (pos) + { + /* get the image ID */ + n = get_image_id(*ptr); + + if(n < 0 || n >= MAX_IMAGES) + { + /* Skip the rest of the line */ + while(*buf != '\n') + buf++; + return false; + } + ptr = pos+1; + + /* check the image number and load state */ + if (data->img[n].loaded) + { + /* Skip the rest of the line */ + while(*buf != '\n') + buf++; + return false; + } + else + { + /* get filename */ + pos = strchr(ptr, '|'); + if ((pos - ptr) < + (int)sizeof(imgname)-ROCKBOX_DIR_LEN-2) + { + memcpy(imgname, bmpdir, bmpdirlen); + imgname[bmpdirlen] = '/'; + memcpy(&imgname[bmpdirlen+1], + ptr, pos - ptr); + imgname[bmpdirlen+1+pos-ptr] = 0; + } + else + /* filename too long */ + imgname[0] = 0; + + ptr = pos+1; + + /* get x-position */ + pos = strchr(ptr, '|'); + if (pos) + data->img[n].x = atoi(ptr); + else + { + /* weird syntax, bail out */ + buf++; + return false; + } + + /* get y-position */ + ptr = pos+1; + pos = strchr(ptr, '|'); + if (pos) + data->img[n].y = atoi(ptr); + else + { + /* weird syntax, bail out */ + buf++; + return false; + } + + /* load the image */ + ret = read_bmp_file(imgname, &data->img[n].w, + &data->img[n].h, data->img_buf_ptr, + data->img_buf_free); + if (ret > 0) + { + data->img[n].ptr = data->img_buf_ptr; + data->img_buf_ptr += ret; + data->img_buf_free -= ret; + data->img[n].loaded = true; + if(qual == '|') + data->img[n].always_display = true; + } + return true; + } + } + } + } + + break; +#endif + } + /* no of these tags found */ + return false; +} + + /* draws the statusbar on the given wps-screen */ #ifdef HAVE_LCD_BITMAP static void gui_wps_statusbar_draw(struct gui_wps *wps, bool force) { bool draw = global_settings.statusbar; + if(wps->data->wps_sb_tag && wps->data->show_sb_on_wps) draw = true; @@ -781,13 +961,7 @@ static void format_display(struct gui_wps *gwps, char* buf, case 'x': /* image support */ #ifdef HAVE_LCD_BITMAP - /* skip preload or regular image tag */ - if ('l' == *(fmt+1) || '|' == *(fmt+1)) - { - while (*fmt && *fmt != '\n') - fmt++; - } - else if ('d' == *(fmt+1) ) + if ('d' == *(fmt+1) ) { fmt+=2; @@ -925,23 +1099,13 @@ void fade(bool fade_in) } /* Set format string to use for WPS, splitting it into lines */ -void gui_wps_format(struct wps_data *data, const char *bmpdir, - size_t bmpdirlen) +void gui_wps_format(struct wps_data *data) { char* buf = data->format_buffer; char* start_of_line = data->format_buffer; int line = 0; int subline; - char c, lastc = 0; -#ifndef HAVE_LCD_BITMAP - /* no bitmap lcd == no bitmap loading */ - (void)bmpdir; - (void)bmpdirlen; -#else - unsigned char* img_buf_ptr = data->img_buf; /* where in image buffer */ - - int img_buf_free = IMG_BUFSIZE; /* free space in image buffer */ -#endif + char c; if(!data) return; @@ -955,16 +1119,11 @@ void gui_wps_format(struct wps_data *data, const char *bmpdir, data->subline_expire_time[line] = 0; data->curr_subline[line] = SUBLINE_RESET; } - + line = 0; subline = 0; data->format_lines[line][subline] = buf; -#ifdef HAVE_LCD_BITMAP - bool wps_tag_found = false; - data->wps_sb_tag = false; - data->show_sb_on_wps = false; -#endif while ((*buf) && (line < WPS_MAX_LINES)) { c = *buf; @@ -976,18 +1135,7 @@ void gui_wps_format(struct wps_data *data, const char *bmpdir, * don't skip %x lines (pre-load bitmaps) */ case '%': -#ifdef HAVE_LCD_BITMAP - if(*(buf+1) == 'w' && (*(buf+2) == 'd' || *(buf+2) == 'e') - && !wps_tag_found) - { - data->wps_sb_tag = true; - if( *(buf+1) == 'w' && *(buf+2) == 'e' ) - data->show_sb_on_wps = true; - wps_tag_found = true; - } - if (*(buf+1) != 'x') -#endif - buf++; + buf++; break; case '\r': /* CR */ @@ -1029,126 +1177,7 @@ void gui_wps_format(struct wps_data *data, const char *bmpdir, subline = 0; } break; - - case 'x': -#ifdef HAVE_LCD_BITMAP - /* Preload images so the %xd# tag can display it */ - { - int ret = 0; - int n; - char *ptr = buf+1; - char *pos = NULL; - char imgname[MAX_PATH]; - char qual = *ptr; - - if(lastc != '%') - break; - - if (qual == 'l' || qual == '|') /* format: - %x|n|filename.bmp|x|y| - or - %xl|n|filename.bmp|x|y| - */ - { - ptr = strchr(ptr, '|') + 1; - pos = strchr(ptr, '|'); - if (pos) - { - /* get the image ID */ - n = *ptr; - if(n >= 'a' && n <= 'z') - n -= 'a'; - if(n >= 'A' && n <= 'Z') - n = n - 'A' + 26; - - if(n < 0 || n >= MAX_IMAGES) - { - /* Skip the rest of the line */ - while(*buf != '\n') - buf++; - break; - } - ptr = pos+1; - - /* check the image number and load state */ - if (data->img[n].loaded) - { - /* Skip the rest of the line */ - while(*buf != '\n') - buf++; - break; - } - else - { - /* get filename */ - pos = strchr(ptr, '|'); - if ((pos - ptr) < - (int)sizeof(imgname)-ROCKBOX_DIR_LEN-2) - { - memcpy(imgname, bmpdir, bmpdirlen); - imgname[bmpdirlen] = '/'; - memcpy(&imgname[bmpdirlen+1], - ptr, pos - ptr); - imgname[bmpdirlen+1+pos-ptr] = 0; - } - else - /* filename too long */ - imgname[0] = 0; - - ptr = pos+1; - - /* get x-position */ - pos = strchr(ptr, '|'); - if (pos) - data->img[n].x = atoi(ptr); - else - { - /* weird syntax, bail out */ - buf++; - break; - } - - /* get y-position */ - ptr = pos+1; - pos = strchr(ptr, '|'); - if (pos) - data->img[n].y = atoi(ptr); - else - { - /* weird syntax, bail out */ - buf++; - break; - } - - pos++; - - /* reposition buf pointer to next WPS element */ - while (*pos && *pos != ';' && *pos != '\n') - pos++; - - buf = pos; - - /* load the image */ - ret = read_bmp_file(imgname, &data->img[n].w, - &data->img[n].h, (char *)img_buf_ptr, - img_buf_free); - if (ret > 0) - { - data->img[n].ptr = img_buf_ptr; - img_buf_ptr += ret; - img_buf_free -= ret; - data->img[n].loaded = true; - if(qual == '|') - data->img[n].always_display = true; - } - } - } - } - } -#endif - break; } - lastc = c; buf++; } } diff --git a/apps/gui/gwps-common.h b/apps/gui/gwps-common.h index e9c1a42299..7909270419 100644 --- a/apps/gui/gwps-common.h +++ b/apps/gui/gwps-common.h @@ -25,8 +25,7 @@ void gui_wps_format_time(char* buf, int buf_size, long time); void fade(bool fade_in); -void gui_wps_format(struct wps_data *data, const char *bmpdir, - size_t bmpdirlen); +void gui_wps_format(struct wps_data *data); bool gui_wps_refresh(struct gui_wps *gwps, int ffwd_offset, unsigned char refresh_mode); bool gui_wps_display(void); @@ -34,6 +33,8 @@ void setvol(void); bool update_onvol_change(struct gui_wps * gwps); bool update(struct gui_wps *gwps); bool ffwd_rew(int button); +bool wps_data_preload_tags(struct wps_data *data, unsigned char *buf, + const char *bmpdir, size_t bmpdirlen); #ifdef WPS_KEYLOCK void display_keylock_text(bool locked); void waitfor_nokey(void); diff --git a/apps/gui/gwps.c b/apps/gui/gwps.c index 52242d856e..bd7591fb37 100644 --- a/apps/gui/gwps.c +++ b/apps/gui/gwps.c @@ -734,6 +734,8 @@ static void wps_clear(struct wps_data *data ) data->img[i].display = false; data->img[i].always_display = false; } + data->wps_sb_tag = false; + data->show_sb_on_wps = false; } #else #define wps_clear(a) @@ -764,7 +766,7 @@ bool wps_data_load(struct wps_data *wps_data, 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, NULL, 0); + gui_wps_format(wps_data); return true; } else @@ -798,16 +800,34 @@ bool wps_data_load(struct wps_data *wps_data, if (fd >= 0) { - int numread = read(fd, wps_data->format_buffer, - sizeof(wps_data->format_buffer) - 1); - - if (numread > 0) - { + unsigned int start = 0; + + wps_reset(wps_data); #ifdef HAVE_LCD_BITMAP - wps_clear(wps_data); + wps_data->img_buf_ptr = wps_data->img_buf; /* where in image buffer */ + + wps_data->img_buf_free = IMG_BUFSIZE; /* free space in image buffer */ #endif - wps_data->format_buffer[numread] = 0; - gui_wps_format(wps_data, buf, bmpdirlen); + 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) + { + wps_data->format_buffer[start++] = '\n'; + wps_data->format_buffer[start] = 0; + } + } + } + + if (start > 0) + { + gui_wps_format(wps_data); } close(fd); @@ -853,7 +873,7 @@ bool wps_data_load(struct wps_data *wps_data, } wps_data->wps_loaded = true; - return numread > 0; + return start > 0; } } diff --git a/apps/gui/gwps.h b/apps/gui/gwps.h index 66199bcfc4..4072e17cfa 100644 --- a/apps/gui/gwps.h +++ b/apps/gui/gwps.h @@ -255,6 +255,8 @@ struct wps_data #ifdef HAVE_LCD_BITMAP struct gui_img img[MAX_IMAGES]; unsigned char img_buf[IMG_BUFSIZE]; + unsigned char* img_buf_ptr; + int img_buf_free; bool wps_sb_tag; bool show_sb_on_wps; #endif -- cgit v1.2.3