Index: apps/gui/wps/wps_buffer.c =================================================================== --- apps/gui/wps/wps_buffer.c (revision 0) +++ apps/gui/wps/wps_buffer.c (revision 0) @@ -0,0 +1,87 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: wps_parser.c 19880 2009-01-29 20:49:43Z mcuelenaere $ + * + * Copyright (C) 2002 by Linus Nielsen Feltzing + * Copyright (C) 2009 Jonathan Gordon + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include +#include +#include +#include "config.h" +#include "buffer.h" +#include "settings.h" + +/* WPS buffer management. + * This module is used to allocate space in a single global WPS buffer for + * tokens for both/all screens. + * + * This is mostly just copy/paste from firmware/buffer.c + */ + +static unsigned char *buffer_start = NULL, *buffer_pos = NULL; +static size_t buf_size; + +void wps_buffer_init(void) +{ + if (buffer_start == NULL) + { + buf_size = /* global_settings.wps_buf_size */ 0x200000; // 2MB for now + buffer_start = buffer_alloc(buf_size); + buffer_pos = buffer_start; + } + else + { + /* reset the buffer.... */ + buffer_pos = buffer_start; + } +} + +/* get the number of bytes currently being used */ +size_t wps_buffer_usage(void) +{ + return buffer_pos-buffer_start; +} + +/* Allocate size bytes from the buffer */ +void* wps_buffer_alloc(size_t size) +{ + void* retval = buffer_pos; + if (wps_buffer_usage()+size >= buf_size) + { + return NULL; + } + buffer_pos += size; + /* 32-bit aligned */ + buffer_pos = (void *)(((unsigned long)buffer_pos + 3) & ~3); + return retval; +} + +void* wps_buffer_grab(size_t *freespace) +{ + *freespace = buf_size - wps_buffer_usage(); + return buffer_pos; +} + +void wps_buffer_increment(size_t used) +{ + buffer_pos += used; + /* 32-bit aligned */ + buffer_pos = (void *)(((unsigned long)buffer_pos + 3) & ~3); +} + Index: apps/gui/gwps-common.c =================================================================== --- apps/gui/gwps-common.c (revision 19918) +++ apps/gui/gwps-common.c (working copy) @@ -504,15 +504,28 @@ pb->x, pb->x + pb->width, pb->y+1, pb->height-2); } +struct gui_img* find_img(struct wps_data *wps_data, char id) +{ + struct wpsll *llitem = wps_data->images; + struct gui_img *img; + for(llitem = wps_data->images; llitem; llitem = llitem->next) + { + img = (struct gui_img *)llitem->token->value.data; + if (img->id == id) + return img; + } + return NULL; +} /* clears the area where the image was shown */ static void clear_image_pos(struct gui_wps *gwps, int n) { if(!gwps) return; struct wps_data *data = gwps->data; + struct gui_img *img = find_img(data, n); gwps->display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); - gwps->display->fillrect(data->img[n].x, data->img[n].y, - data->img[n].bm.width, data->img[n].subimage_height); + gwps->display->fillrect(img->x, img->y, + img->bm.width, img->subimage_height); gwps->display->set_drawmode(DRMODE_SOLID); } @@ -520,26 +533,27 @@ { struct screen *display = gwps->display; struct wps_data *data = gwps->data; - if(data->img[n].always_display) + struct gui_img *img = find_img(data, n); + if(img->always_display) display->set_drawmode(DRMODE_FG); else display->set_drawmode(DRMODE_SOLID); #if LCD_DEPTH > 1 - if(data->img[n].bm.format == FORMAT_MONO) { + if(img->bm.format == FORMAT_MONO) { #endif - display->mono_bitmap_part(data->img[n].bm.data, - 0, data->img[n].subimage_height * subimage, - data->img[n].bm.width, data->img[n].x, - data->img[n].y, data->img[n].bm.width, - data->img[n].subimage_height); + display->mono_bitmap_part(img->bm.data, + 0, img->subimage_height * subimage, + img->bm.width, img->x, + img->y, img->bm.width, + img->subimage_height); #if LCD_DEPTH > 1 } else { - display->transparent_bitmap_part((fb_data *)data->img[n].bm.data, - 0, data->img[n].subimage_height * subimage, - data->img[n].bm.width, data->img[n].x, - data->img[n].y, data->img[n].bm.width, - data->img[n].subimage_height); + display->transparent_bitmap_part((fb_data *)img->bm.data, + 0, img->subimage_height * subimage, + img->bm.width, img->x, + img->y, img->bm.width, + img->subimage_height); } #endif } @@ -549,20 +563,20 @@ if(!gwps || !gwps->data || !gwps->display) return; - int n; struct wps_data *data = gwps->data; struct screen *display = gwps->display; - - for (n = 0; n < MAX_IMAGES; n++) + struct wpsll *llitem; + for ( llitem = data->images; llitem; llitem = llitem->next) { - if (data->img[n].loaded) + struct gui_img *img = (struct gui_img*)llitem->token->value.data; + if (img->loaded) { - if (data->img[n].display >= 0) + if (img->display >= 0) { - wps_draw_image(gwps, n, data->img[n].display); - } else if (data->img[n].always_display && data->img[n].vp == vp) + wps_draw_image(gwps, img->id, img->display); + } else if (img->always_display && img->vp == vp) { - wps_draw_image(gwps, n, 0); + wps_draw_image(gwps, img->id, 0); } } } @@ -804,7 +818,7 @@ return &(token->value.c); case WPS_TOKEN_STRING: - return data->strings[token->value.i]; + return token->value.data; case WPS_TOKEN_TRACK_TIME_ELAPSED: format_time(buf, buf_size, @@ -1558,12 +1572,12 @@ #ifdef HAVE_LCD_BITMAP case WPS_TOKEN_IMAGE_PRELOAD_DISPLAY: { - struct gui_img *img = data->img; int n = data->tokens[i].value.i & 0xFF; + struct gui_img *img = find_img(data, n); int subimage = data->tokens[i].value.i >> 8; - if (n >= 0 && n < MAX_IMAGES && img[n].loaded) - img[n].display = subimage; + if (img->loaded) + img->display = subimage; break; } #endif @@ -2013,9 +2027,11 @@ #ifdef HAVE_LCD_BITMAP /* Set images to not to be displayed */ - for (i = 0; i < MAX_IMAGES; i++) + struct wpsll *llitem; + for ( llitem = data->images; llitem; llitem = llitem->next) { - data->img[i].display = -1; + struct gui_img *img = (struct gui_img*)llitem->token->value.data; + img->display = -1; } #endif /* dont redraw the viewport if its disabled */ Index: apps/gui/wps_debug.c =================================================================== --- apps/gui/wps_debug.c (revision 19916) +++ apps/gui/wps_debug.c (working copy) @@ -43,7 +43,7 @@ return next ? "next " : ""; } -static char *get_token_desc(struct wps_token *token, struct wps_data *data, +static char *get_token_desc(struct wps_token *token, char *buf, int bufsize) { bool next = token->next; @@ -65,7 +65,7 @@ case WPS_TOKEN_STRING: snprintf(buf, bufsize, "String '%s'", - data->strings[token->value.i]); + token->value.data); break; #ifdef HAVE_LCD_BITMAP @@ -456,7 +456,7 @@ /* Dump parsed WPS */ for (i = 0, token = data->tokens; i < data->num_tokens; i++, token++) { - get_token_desc(token, data, buf, sizeof(buf)); + get_token_desc(token, buf, sizeof(buf)); switch(token->type) { @@ -510,6 +510,7 @@ } DEBUGF("Number of sublines : %d\n", data->num_sublines); DEBUGF("Number of tokens : %d\n", data->num_tokens); + DEBUGF("Buffer Usage: %ld\n", wps_buffer_usage()); DEBUGF("\n"); } @@ -544,36 +545,12 @@ } } } + DEBUGF("Buffer Usage: %ld\n", wps_buffer_usage()); DEBUGF("\n"); } } -static void print_wps_strings(struct wps_data *data) -{ - int i, len, total_len = 0, buf_used = 0; - - if (wps_verbose_level > 1) DEBUGF("Strings:\n"); - for (i = 0; i < data->num_strings; i++) - { - len = strlen(data->strings[i]); - total_len += len; - buf_used += len + 1; - if (wps_verbose_level > 1) - DEBUGF("%2d: (%2d) '%s'\n", i, len, data->strings[i]); - } - if (wps_verbose_level > 1) DEBUGF("\n"); - - if (wps_verbose_level > 0) - { - DEBUGF("Number of unique strings: %d (max: %d)\n", - data->num_strings, WPS_MAX_STRINGS); - DEBUGF("Total string length: %d\n", total_len); - DEBUGF("String buffer used: %d out of %d bytes\n", - buf_used, STRING_BUFFER_SIZE); - DEBUGF("\n"); - } -} #endif void print_debug_info(struct wps_data *data, enum wps_parse_error fail, int line) @@ -582,7 +559,6 @@ if (debug_wps && wps_verbose_level) { dump_wps_tokens(data); - print_wps_strings(data); print_line_info(data); } #endif /* SIMULATOR */ @@ -609,7 +585,7 @@ case PARSE_FAIL_INVALID_CHAR: DEBUGF("ERR: Unexpected conditional char after token %d: \"%s\"", data->num_tokens-1, - get_token_desc(&data->tokens[data->num_tokens-1], data, + get_token_desc(&data->tokens[data->num_tokens-1], buf, sizeof(buf)) ); break; @@ -617,7 +593,7 @@ case PARSE_FAIL_COND_SYNTAX_ERROR: DEBUGF("ERR: Conditional syntax error after token %d: \"%s\"", data->num_tokens-1, - get_token_desc(&data->tokens[data->num_tokens-1], data, + get_token_desc(&data->tokens[data->num_tokens-1], buf, sizeof(buf)) ); break; @@ -625,7 +601,7 @@ case PARSE_FAIL_COND_INVALID_PARAM: DEBUGF("ERR: Invalid parameter list for token %d: \"%s\"", data->num_tokens, - get_token_desc(&data->tokens[data->num_tokens], data, + get_token_desc(&data->tokens[data->num_tokens], buf, sizeof(buf)) ); break; Index: apps/gui/gwps.h =================================================================== --- apps/gui/gwps.h (revision 19916) +++ apps/gui/gwps.h (working copy) @@ -56,9 +56,28 @@ #endif /* HAVE_ALBUMART */ /* wps_data*/ +struct wps_token { + unsigned char type; /* enough to store the token type */ + /* Whether the tag (e.g. track name or the album) refers the + current or the next song (false=current, true=next) */ + bool next; + + union { + char c; + unsigned int i; + void *data; /* pointer into global wps buffer */ + } value; +}; + +struct wpsll { + struct wps_token *token; + struct wpsll *next; +}; + #ifdef HAVE_LCD_BITMAP struct gui_img{ + short id; struct bitmap bm; struct viewport* vp; /* The viewport to display this image in */ short int x; /* x-pos */ @@ -90,21 +109,10 @@ #ifdef HAVE_LCD_BITMAP -#define MAX_IMAGES (26*2) /* a-z and A-Z */ -#define MAX_PROGRESSBARS 3 - -/* The image buffer is big enough to store one full-screen native bitmap, - plus two full-screen mono bitmaps. */ - -#define IMG_BUFSIZE ((LCD_HEIGHT*LCD_WIDTH*LCD_DEPTH/8) \ - + (2*LCD_HEIGHT*LCD_WIDTH/8)) - #define WPS_MAX_VIEWPORTS 24 #define WPS_MAX_LINES ((LCD_HEIGHT/5+1) * 2) #define WPS_MAX_SUBLINES (WPS_MAX_LINES*3) #define WPS_MAX_TOKENS 1024 -#define WPS_MAX_STRINGS 128 -#define STRING_BUFFER_SIZE 1024 #define WPS_MAX_COND_LEVEL 10 #else @@ -113,8 +121,6 @@ #define WPS_MAX_LINES 2 #define WPS_MAX_SUBLINES 12 #define WPS_MAX_TOKENS 64 -#define WPS_MAX_STRINGS 32 -#define STRING_BUFFER_SIZE 64 #define WPS_MAX_COND_LEVEL 5 #endif @@ -296,19 +302,8 @@ WPS_TOKEN_SETTING, }; -struct wps_token { - unsigned char type; /* enough to store the token type */ - /* Whether the tag (e.g. track name or the album) refers the - current or the next song (false=current, true=next) */ - bool next; - union { - char c; - unsigned short i; - } value; -}; - /* Description of a subline on the WPS */ struct wps_subline { @@ -363,16 +358,14 @@ 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; - struct progressbar progressbar[MAX_PROGRESSBARS]; - short progressbar_count; + struct wpsll *images; + struct wpsll *progressbars; + struct wps_token *backdrop; + bool peak_meter_enabled; #ifdef HAVE_ALBUMART @@ -417,10 +410,8 @@ int num_tokens; struct wps_token tokens[WPS_MAX_TOKENS]; - char string_buffer[STRING_BUFFER_SIZE]; - char *strings[WPS_MAX_STRINGS]; - int num_strings; - + struct wpsll *strings; + bool wps_loaded; /* tick the volume button was last pressed */ @@ -507,4 +498,15 @@ bool gui_sync_wps_uses_albumart(void); #endif + +struct gui_img* find_img(struct wps_data *wps_data, char id); /* in gwps-common.c */ + +/* wps_buffer functions */ + +void wps_buffer_init(void); +void* wps_buffer_alloc(size_t size); +void* wps_buffer_grab(size_t *freespace); +void wps_buffer_increment(size_t used); +size_t wps_buffer_usage(void); + #endif Index: apps/gui/wps_parser.c =================================================================== --- apps/gui/wps_parser.c (revision 19916) +++ apps/gui/wps_parser.c (working copy) @@ -79,22 +79,6 @@ /* the current line in the file */ static int line; -#ifdef HAVE_LCD_BITMAP - -#if LCD_DEPTH > 1 -#define MAX_BITMAPS (MAX_IMAGES+MAX_PROGRESSBARS+1) /* WPS images + pbar bitmap + backdrop */ -#else -#define MAX_BITMAPS (MAX_IMAGES+MAX_PROGRESSBARS) /* WPS images + pbar bitmap */ -#endif - -#define PROGRESSBAR_BMP MAX_IMAGES -#define BACKDROP_BMP (MAX_BITMAPS-1) - -/* pointers to the bitmap filenames in the WPS source */ -static const char *bmp_names[MAX_BITMAPS]; - -#endif /* HAVE_LCD_BITMAP */ - #if defined(DEBUG) || defined(SIMULATOR) /* debugging function */ extern void print_debug_info(struct wps_data *data, int fail, int line); @@ -342,6 +326,18 @@ /* the array MUST end with an empty string (first char is \0) */ }; +static void add_to_ll_chain(struct wpsll **list, struct wpsll *item) +{ + if (*list == NULL) + *list = item; + else + { /* order doesnt matter, so insert at the front for speed */ + struct wpsll *temp = *list; + item->next = temp; + *list = item; + } +} + /* Returns the number of chars that should be skipped to jump immediately after the first eol, i.e. to the start of the next line */ static int skip_end_of_line(const char *wps_bufptr) @@ -397,16 +393,19 @@ char* filename, struct bitmap *bm) { + (void)wps_data; int format; + size_t bm_space_avilable; #ifdef HAVE_REMOTE_LCD if (wps_data->remote_wps) format = FORMAT_ANY|FORMAT_REMOTE; else #endif format = FORMAT_ANY|FORMAT_TRANSPARENT; - + bm->data = wps_buffer_grab(&bm_space_avilable); + int ret = read_bmp_file(filename, bm, - wps_data->img_buf_free, + bm_space_avilable, format,NULL); if (ret > 0) @@ -415,8 +414,8 @@ if (ret % 2) ret++; /* Always consume an even number of bytes */ #endif - wps_data->img_buf_ptr += ret; - wps_data->img_buf_free -= ret; + /* let the buffer manager know how much we used */ + wps_buffer_increment(ret); return true; } @@ -459,11 +458,11 @@ struct wps_token *token, struct wps_data *wps_data) { - (void)wps_data; - int n = get_image_id(wps_bufptr[0]); + int n = (wps_bufptr[0]); + struct gui_img *img = find_img(wps_data, n); int subimage; - if (n == -1) + if (n == -1 || !img) { /* invalid picture display tag */ return WPS_ERROR_INVALID_PARAM; @@ -472,7 +471,7 @@ if ((subimage = get_image_id(wps_bufptr[1])) != -1) { /* Sanity check */ - if (subimage >= wps_data->img[n].num_subimages) + if (subimage >= img->num_subimages) return WPS_ERROR_INVALID_PARAM; /* Store sub-image number to display in high bits */ @@ -488,19 +487,21 @@ struct wps_token *token, struct wps_data *wps_data) { - int n; const char *ptr = wps_bufptr; const char *pos; const char* filename; const char* id; const char *newline; int x,y; - + struct wpsll *llitem = wps_buffer_alloc(sizeof(struct wpsll)); + struct gui_img *img = wps_buffer_alloc(sizeof(struct gui_img)); + /* tokens for image lod are not saved, so we need a new copy to be able to link them */ + struct wps_token *tmp_token = wps_buffer_alloc(sizeof(struct wps_token)); + tmp_token->value.data = img; /* format: %x|n|filename.bmp|x|y| or %xl|n|filename.bmp|x|y| or %xl|n|filename.bmp|x|y|num_subimages| */ - if (*ptr != '|') return WPS_ERROR_INVALID_PARAM; @@ -513,28 +514,22 @@ if (*ptr != '|') return WPS_ERROR_INVALID_PARAM; - /* get the image ID */ - n = get_image_id(*id); - - /* check the image number and load state */ - if(n < 0 || n >= MAX_IMAGES || wps_data->img[n].loaded) - { - /* Invalid image ID */ - return WPS_ERROR_INVALID_PARAM; - } - + /* store the image ID */ + img->id = (id[0]); + /* save a pointer to the filename */ - bmp_names[n] = filename; + img->bm.data = (unsigned char*)filename; - wps_data->img[n].x = x; - wps_data->img[n].y = y; + img->x = x; + img->y = y; + img->num_subimages = 1; /* save current viewport */ - wps_data->img[n].vp = &wps_data->viewports[wps_data->num_viewports].vp; + img->vp = &wps_data->viewports[wps_data->num_viewports].vp; if (token->type == WPS_TOKEN_IMAGE_DISPLAY) { - wps_data->img[n].always_display = true; + img->always_display = true; } else { @@ -543,12 +538,15 @@ newline = strchr(ptr, '\n'); pos = strchr(ptr, '|'); if (pos && pos < newline) - wps_data->img[n].num_subimages = atoi(ptr); + img->num_subimages = atoi(ptr); - if (wps_data->img[n].num_subimages <= 0) + if (img->num_subimages <= 0) return WPS_ERROR_INVALID_PARAM; } - + llitem->token = tmp_token; + llitem->next = NULL; + add_to_ll_chain(&wps_data->images, llitem); + /* Skip the rest of the line */ return skip_end_of_line(wps_bufptr); } @@ -727,8 +725,6 @@ struct wps_token *token, struct wps_data *wps_data) { - (void)wps_data; /* kill warning */ - (void)token; const char *pos = NULL; const char *newline; @@ -741,7 +737,13 @@ if (token->type == WPS_TOKEN_IMAGE_BACKDROP) { /* format: %X|filename.bmp| */ - bmp_names[BACKDROP_BMP] = wps_bufptr + 1; + /* get_image_filename() expects the filename to end with a | + * so make sure that gets copied also */ + char* bar = strchr(wps_bufptr + 1, '|'); + int len = bar-wps_bufptr; + token->value.data = (char*)wps_buffer_alloc(len); + strncpy(token->value.data, wps_bufptr + 1, len); + wps_data->backdrop = token; } #endif @@ -853,7 +855,6 @@ struct wps_token *token, struct wps_data *wps_data) { - (void)token; /* Kill warnings */ /* %pb or %pb|filename|x|y|width|height| using - for any of the params uses "sane" values */ #ifdef HAVE_LCD_BITMAP @@ -868,8 +869,11 @@ int x, y, height, width; uint32_t set = 0; const char *ptr = wps_bufptr; - struct progressbar *pb; struct viewport *vp = &wps_data->viewports[wps_data->num_viewports].vp; + struct wpsll *llitem = wps_buffer_alloc(sizeof(struct wpsll)); + struct progressbar *pb = wps_buffer_alloc(sizeof(struct progressbar)); + + token->value.data = pb; #ifndef __PCTOOL__ int font_height = font_get(vp->font)->height; #else @@ -878,11 +882,10 @@ int line_y_pos = font_height*(wps_data->num_lines - wps_data->viewports[wps_data->num_viewports].first_line); - if (wps_data->progressbar_count >= MAX_PROGRESSBARS) - return WPS_ERROR_INVALID_PARAM; - - pb = &wps_data->progressbar[wps_data->progressbar_count]; pb->have_bitmap_pb = false; + llitem->token = token; + llitem->next = NULL; + add_to_ll_chain(&wps_data->progressbars, llitem); if (*wps_bufptr != '|') /* regular old style */ { @@ -890,9 +893,9 @@ pb->width = vp->width; pb->height = SYSFONT_HEIGHT-2; pb->y = line_y_pos + (font_height-pb->height)/2; + pb->bm.data = NULL; wps_data->viewports[wps_data->num_viewports].pb = pb; - wps_data->progressbar_count++; return 0; } ptr = wps_bufptr + 1; @@ -902,7 +905,9 @@ return WPS_ERROR_INVALID_PARAM; if (LIST_VALUE_PARSED(set, PB_FILENAME)) /* filename */ - bmp_names[PROGRESSBAR_BMP+wps_data->progressbar_count] = filename; + pb->bm.data = (unsigned char*)filename; + else + pb->bm.data = NULL; if (LIST_VALUE_PARSED(set, PB_X)) /* x */ pb->x = x; @@ -937,7 +942,6 @@ pb->y = line_y_pos + (font_height-pb->height)/2; wps_data->viewports[wps_data->num_viewports].pb = pb; - wps_data->progressbar_count++; /* Skip the rest of the line */ return skip_end_of_line(wps_bufptr)-1; @@ -1222,8 +1226,6 @@ if (!data || !wps_bufptr || !*wps_bufptr) return false; - char *stringbuf = data->string_buffer; - int stringbuf_used = 0; enum wps_parse_error fail = PARSE_OK; int ret; line = 1; @@ -1375,45 +1377,37 @@ } /* look if we already have that string */ - char **str; - int i; - bool found; - for (i = 0, str = data->strings, found = false; - i < data->num_strings && - !(found = (strlen(*str) == len && - strncmp(string_start, *str, len) == 0)); - i++, str++); - /* If a matching string is found, found is true and i is - the index of the string. If not, found is false */ - + + bool found = false; + char *str; + struct wpsll *ll; + for(ll = data->strings; ll; ll = ll->next) + { + str = ll->token->value.data; + found = (strlen(str) == len && + strncmp(string_start, str, len) == 0); + if (found) + break; + } + if (!found) { /* new string */ - - if (stringbuf_used + len > STRING_BUFFER_SIZE - 1 - || data->num_strings >= WPS_MAX_STRINGS) - { - /* too many strings or characters */ - fail = PARSE_FAIL_LIMITS_EXCEEDED; - break; - } - - strncpy(stringbuf, string_start, len); - *(stringbuf + len) = '\0'; - - data->strings[data->num_strings] = stringbuf; - stringbuf += len + 1; - stringbuf_used += len + 1; - data->tokens[data->num_tokens].value.i = - data->num_strings; - data->num_strings++; + str = wps_buffer_alloc(len+1); + strncpy(str, string_start, len); + *(str + len) = '\0'; + data->tokens[data->num_tokens].value.data = str; } else { /* another occurrence of an existing string */ - data->tokens[data->num_tokens].value.i = i; + data->tokens[data->num_tokens].value.data = ll->token->value.data; } data->tokens[data->num_tokens].type = WPS_TOKEN_STRING; + ll = wps_buffer_alloc(sizeof(struct wpsll)); + ll->token = &data->tokens[data->num_tokens]; + ll->next = NULL; + add_to_ll_chain(&data->strings, ll); data->num_tokens++; } break; @@ -1439,34 +1433,19 @@ return (fail == 0); } -#ifdef HAVE_LCD_BITMAP -/* Clear the WPS image cache */ -static void wps_images_clear(struct wps_data *data) -{ - int i; - /* set images to unloaded and not displayed */ - for (i = 0; i < MAX_IMAGES; i++) - { - data->img[i].loaded = false; - data->img[i].display = -1; - data->img[i].always_display = false; - data->img[i].num_subimages = 1; - } -} -#endif /* initial setup of wps_data */ void wps_data_init(struct wps_data *wps_data) { + wps_buffer_init(); #ifdef HAVE_LCD_BITMAP - wps_images_clear(wps_data); + wps_data->backdrop = NULL; + wps_data->images = NULL; wps_data->wps_sb_tag = false; wps_data->show_sb_on_wps = false; - 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 */ wps_data->peak_meter_enabled = false; /* progress bars */ - wps_data->progressbar_count = 0; + wps_data->progressbars = NULL; #else /* HAVE_LCD_CHARCELLS */ int i; for (i = 0; i < 8; i++) @@ -1495,37 +1474,51 @@ static bool load_wps_bitmaps(struct wps_data *wps_data, char *bmpdir) { + /* NOTE: image filenames get put in the images bm->data member, + * so copy before use */ char img_path[MAX_PATH]; struct bitmap *bitmap; bool *loaded; int n; - for (n = 0; n < BACKDROP_BMP; n++) + struct wpsll *llitem; + + /* load the progressbar images */ + for ( llitem = wps_data->progressbars; llitem; llitem = llitem->next) { - if (bmp_names[n]) + struct progressbar *pb = (struct progressbar *)llitem->token->value.data; + if (pb->bm.data) { - get_image_filename(bmp_names[n], bmpdir, + get_image_filename(pb->bm.data, bmpdir, img_path, sizeof(img_path)); - - if (n >= PROGRESSBAR_BMP ) { - /* progressbar bitmap */ - bitmap = &wps_data->progressbar[n-PROGRESSBAR_BMP].bm; - loaded = &wps_data->progressbar[n-PROGRESSBAR_BMP].have_bitmap_pb; - } else { - /* regular bitmap */ - bitmap = &wps_data->img[n].bm; - loaded = &wps_data->img[n].loaded; + bitmap = &pb->bm; + loaded = &pb->have_bitmap_pb; + if (load_bitmap(wps_data, img_path, bitmap)) + { + *loaded = true; } - - /* load the image */ - bitmap->data = wps_data->img_buf_ptr; + else + { + /* Abort if we can't load an image */ + DEBUGF("ERR: Failed to load image %d - %s\n",n,img_path); + return false; + } + } + } + /* load regular images */ + for ( llitem = wps_data->images; llitem; llitem = llitem->next) + { + struct gui_img *img = (struct gui_img*)llitem->token->value.data; + if (img->bm.data) + { + get_image_filename(img->bm.data, bmpdir, + img_path, sizeof(img_path)); + bitmap = &img->bm; + loaded = &img->loaded; if (load_bitmap(wps_data, img_path, bitmap)) { *loaded = true; - /* Calculate and store height if this image has sub-images */ - if (n < MAX_IMAGES) - wps_data->img[n].subimage_height = wps_data->img[n].bm.height / - wps_data->img[n].num_subimages; + img->subimage_height = img->bm.height / img->num_subimages; } else { @@ -1536,12 +1529,13 @@ } } + /* special cases */ #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)) - if (bmp_names[BACKDROP_BMP]) + if (wps_data->backdrop) { - get_image_filename(bmp_names[BACKDROP_BMP], bmpdir, - img_path, sizeof(img_path)); - + char* filename = (char*)wps_data->backdrop->value.data; + get_image_filename(filename, bmpdir, + img_path, sizeof(img_path)); #if defined(HAVE_REMOTE_LCD) /* We only need to check LCD type if there is a remote LCD */ if (!wps_data->remote_wps) @@ -1670,11 +1664,6 @@ if (start <= 0) return false; -#ifdef HAVE_LCD_BITMAP - /* Set all filename pointers to NULL */ - memset(bmp_names, 0, sizeof(bmp_names)); -#endif - /* parse the WPS source */ if (!wps_parse(wps_data, wps_buffer)) { wps_reset(wps_data); Index: apps/SOURCES =================================================================== --- apps/SOURCES (revision 19916) +++ apps/SOURCES (working copy) @@ -60,6 +60,7 @@ #ifdef HAVE_BUTTONBAR gui/buttonbar.c #endif +gui/wps/wps_buffer.c gui/gwps.c gui/gwps-common.c #ifdef HAVE_LCD_BITMAP