Index: apps/lang/english.lang
===================================================================
--- apps/lang/english.lang (revision 19998)
+++ apps/lang/english.lang (working copy)
@@ -12166,19 +12166,19 @@
id: LANG_ALBUMART
- desc: Display the expected AA size
+ desc: deprecated
user:
*: none
- albumart: "Album Art:"
+ albumart: ""
*: none
- albumart: "Album Art:"
+ albumart: ""
*: none
- albumart: "Album Art:"
+ albumart: ""
@@ -12359,3 +12359,17 @@
*: "Credits"
+
+ id: LANG_WPS_RAM_USAGE
+ desc: in the info screen, display amount of bytes used by WPS
+ user:
+
+ *: "WPS RAM Usage:"
+
+
+ *: "WPS RAM Usage:"
+
+
+ *: "WPS RAM Usage"
+
+
Index: apps/settings.c
===================================================================
--- apps/settings.c (revision 19998)
+++ apps/settings.c (working copy)
@@ -834,6 +834,11 @@
#if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
unload_remote_wps_backdrop();
#endif
+
+ wps_buffer_init(); /* reinitialise the wps buffer here instead of in
+ * wps_data_load() to protect it when there is
+ * more than one screen... This does mean that there
+ * will be waste if you just load a .wps file */
if ( global_settings.wps_file[0] &&
global_settings.wps_file[0] != 0xff ) {
snprintf(buf, sizeof buf, WPS_DIR "/%s.wps",
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,90 @@
+/***************************************************************************
+ * __________ __ ___.
+ * 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;
+#define IMG_BUFSIZE ((LCD_HEIGHT*LCD_WIDTH*LCD_DEPTH/8) \
+ + (2*LCD_HEIGHT*LCD_WIDTH/8))
+void wps_buffer_init(void)
+{
+ if (buffer_start == NULL)
+ {
+ /* WAY more than needed but sensible untill configurable */
+ buf_size = IMG_BUFSIZE;/* global_settings.wps_buf_size */
+
+ 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 19998)
+++ apps/gui/gwps-common.c (working copy)
@@ -331,8 +331,12 @@
#if LCD_DEPTH > 1
if (gui_wps[i].display->depth > 1)
{
- gui_wps[i].data->viewports[0].vp.fg_pattern = gui_wps[i].display->get_foreground();
- gui_wps[i].data->viewports[0].vp.bg_pattern = gui_wps[i].display->get_background();
+ struct wps_viewport *vp = find_viewport(gui_wps[i].data, '\0');
+ if (vp)
+ {
+ vp->vp.fg_pattern = gui_wps[i].display->get_foreground();
+ vp->vp.bg_pattern = gui_wps[i].display->get_background();
+ }
}
#endif
#endif
@@ -504,15 +508,40 @@
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;
+}
+struct wps_viewport* find_viewport(struct wps_data *wps_data, char id)
+{
+ struct wpsll *llitem = wps_data->viewports;
+ struct wps_viewport *vp;
+ for(llitem = wps_data->viewports; llitem; llitem = llitem->next)
+ {
+ vp = (struct wps_viewport *)llitem->token->value.data;
+ if (vp->label == id)
+ return vp;
+ }
+ 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 +549,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 +579,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 +834,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 +1588,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
@@ -1606,20 +1636,11 @@
break;
case WPS_VIEWPORT_ENABLE:
{
- char label = data->tokens[i].value.i;
- int j;
+ struct wps_viewport *thisvp = data->tokens[i].value.data;
char temp = VP_DRAW_HIDEABLE;
- for(j=0;jnum_viewports;j++)
- {
- temp = VP_DRAW_HIDEABLE;
- if ((data->viewports[j].hidden_flags&VP_DRAW_HIDEABLE) &&
- (data->viewports[j].label == label))
- {
- if (data->viewports[j].hidden_flags&VP_DRAW_WASHIDDEN)
- temp |= VP_DRAW_WASHIDDEN;
- data->viewports[j].hidden_flags = temp;
- }
- }
+ if (thisvp->hidden_flags&VP_DRAW_WASHIDDEN)
+ temp |= VP_DRAW_WASHIDDEN;
+ thisvp->hidden_flags = temp;
}
break;
default:
@@ -1942,7 +1963,7 @@
if(!gwps || !data || !state || !display)
return false;
- int v, line, i, subline_idx;
+ int line, i, subline_idx;
unsigned char flags;
char linebuf[MAX_PATH];
unsigned char vp_refresh_mode;
@@ -1970,7 +1991,8 @@
/* reset to first subline if refresh all flag is set */
if (refresh_mode == WPS_REFRESH_ALL)
{
- display->set_viewport(&data->viewports[0].vp);
+ struct wps_viewport *wvp = find_viewport(data, '\0');
+ display->set_viewport(&wvp->vp);
display->clear_viewport();
for (i = 0; i <= data->num_lines; i++)
@@ -1996,50 +2018,55 @@
state->ff_rewind_count = ffwd_offset;
/* disable any viewports which are conditionally displayed */
- for (v = 0; v < data->num_viewports; v++)
+ struct wpsll *viewportll;
+ for(viewportll=data->viewports; viewportll; viewportll = viewportll->next)
{
- if (data->viewports[v].hidden_flags&VP_DRAW_HIDEABLE)
+ struct wps_viewport *wvp = viewportll->token->value.data;
+ if (wvp->hidden_flags&VP_DRAW_HIDEABLE)
{
- if (data->viewports[v].hidden_flags&VP_DRAW_HIDDEN)
- data->viewports[v].hidden_flags |= VP_DRAW_WASHIDDEN;
+ if (wvp->hidden_flags&VP_DRAW_HIDDEN)
+ wvp->hidden_flags |= VP_DRAW_WASHIDDEN;
else
- data->viewports[v].hidden_flags |= VP_DRAW_HIDDEN;
+ wvp->hidden_flags |= VP_DRAW_HIDDEN;
}
}
- for (v = 0; v < data->num_viewports; v++)
+ for(viewportll=data->viewports; viewportll; viewportll = viewportll->next)
{
- display->set_viewport(&data->viewports[v].vp);
+ struct wps_viewport *wvp = viewportll->token->value.data;
+ display->set_viewport(&wvp->vp);
vp_refresh_mode = refresh_mode;
#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 */
- if ((data->viewports[v].hidden_flags&VP_DRAW_HIDDEN))
+ if ((wvp->hidden_flags&VP_DRAW_HIDDEN))
{
- if (!(data->viewports[v].hidden_flags&VP_DRAW_WASHIDDEN))
- display->scroll_stop(&data->viewports[v].vp);
- data->viewports[v].hidden_flags |= VP_DRAW_WASHIDDEN;
+ if (!(wvp->hidden_flags&VP_DRAW_WASHIDDEN))
+ display->scroll_stop(&wvp->vp);
+ wvp->hidden_flags |= VP_DRAW_WASHIDDEN;
continue;
}
- else if (((data->viewports[v].hidden_flags&
+ else if (((wvp->hidden_flags&
(VP_DRAW_WASHIDDEN|VP_DRAW_HIDEABLE))
== (VP_DRAW_WASHIDDEN|VP_DRAW_HIDEABLE)))
{
vp_refresh_mode = WPS_REFRESH_ALL;
- data->viewports[v].hidden_flags = VP_DRAW_HIDEABLE;
+ wvp->hidden_flags = VP_DRAW_HIDEABLE;
}
if (vp_refresh_mode == WPS_REFRESH_ALL)
{
display->clear_viewport();
}
- for (line = data->viewports[v].first_line;
- line <= data->viewports[v].last_line; line++)
+ for (line = wvp->first_line;
+ line <= wvp->last_line; line++)
{
memset(linebuf, 0, sizeof(linebuf));
update_line = false;
@@ -2065,8 +2092,8 @@
/* the peakmeter should be alone on its line */
update_line = false;
- int h = font_get(data->viewports[v].vp.font)->height;
- int peak_meter_y = (line - data->viewports[v].first_line)* h;
+ int h = font_get(wvp->vp.font)->height;
+ int peak_meter_y = (line - wvp->first_line)* h;
/* The user might decide to have the peak meter in the last
line so that it is only displayed if no status bar is
@@ -2103,17 +2130,17 @@
viewport there will be a blank line.
To get around this we dont allow any actual drawing to happen in the
deault vp if other vp's are defined */
- ((data->num_viewports>1 && v!=0) || data->num_viewports == 1))
+ ((viewportll->next && wvp->label!='\0') || !viewportll->next))
{
if (flags & WPS_REFRESH_SCROLL)
{
/* if the line is a scrolling one we don't want to update
too often, so that it has the time to scroll */
if ((vp_refresh_mode & WPS_REFRESH_SCROLL) || new_subline_refresh)
- write_line(display, &align, line - data->viewports[v].first_line, true);
+ write_line(display, &align, line - wvp->first_line, true);
}
else
- write_line(display, &align, line - data->viewports[v].first_line, false);
+ write_line(display, &align, line - wvp->first_line, false);
}
}
@@ -2121,11 +2148,11 @@
/* progressbar */
if (vp_refresh_mode & WPS_REFRESH_PLAYER_PROGRESS)
{
- if (data->viewports[v].pb)
- draw_progressbar(gwps, data->viewports[v].pb);
+ if (wvp->pb)
+ draw_progressbar(gwps, wvp->pb);
}
/* Now display any images in this viewport */
- wps_display_images(gwps, &data->viewports[v].vp);
+ wps_display_images(gwps, &wvp->vp);
#endif
}
Index: apps/gui/wps_debug.c
===================================================================
--- apps/gui/wps_debug.c (revision 19998)
+++ 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)
{
@@ -502,26 +502,30 @@
if (wps_verbose_level > 0)
{
- DEBUGF("Number of viewports : %d\n", data->num_viewports);
- for (v = 0; v < data->num_viewports; v++)
+ struct wpsll *ll;
+ for (v=0, ll=data->viewports; ll; ll = ll->next, v++)
{
- DEBUGF("vp %d: First line: %d\n", v, data->viewports[v].first_line);
- DEBUGF("vp %d: Last line: %d\n", v, data->viewports[v].last_line);
+ struct wps_viewport *vp = ll->token->value.data;
+ DEBUGF("vp %d: First line: %d\n", v, vp->first_line);
+ DEBUGF("vp %d: Last line: %d\n", v, vp->last_line);
}
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");
}
if (wps_verbose_level > 1)
{
- for (v = 0; v < data->num_viewports; v++)
+ struct wpsll *ll;
+ for (v=0, ll=data->viewports; ll; ll = ll->next, v++)
{
- DEBUGF("Viewport %d - +%d+%d (%dx%d)\n",v,data->viewports[v].vp.x,
- data->viewports[v].vp.y,
- data->viewports[v].vp.width,
- data->viewports[v].vp.height);
- for (i = data->viewports[v].first_line, line = &data->lines[data->viewports[v].first_line]; i <= data->viewports[v].last_line; i++,line++)
+ struct wps_viewport *vp = ll->token->value.data;
+ DEBUGF("Viewport %d - +%d+%d (%dx%d)\n",v,vp->vp.x,
+ vp->vp.y,
+ vp->vp.width,
+ vp->vp.height);
+ for (i = vp->first_line, line = &data->lines[vp->first_line]; i <= vp->last_line; i++,line++)
{
DEBUGF("Line %2d (num_sublines=%d, first_subline=%d)\n",
i, line->num_sublines, line->first_subline_idx);
@@ -544,36 +548,12 @@
}
}
}
+ DEBUGF("Buffer Usage (pre image loading): %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 +562,6 @@
if (debug_wps && wps_verbose_level)
{
dump_wps_tokens(data);
- print_wps_strings(data);
print_line_info(data);
}
#endif /* SIMULATOR */
@@ -609,7 +588,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 +596,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 +604,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.c
===================================================================
--- apps/gui/gwps.c (revision 19998)
+++ apps/gui/gwps.c (working copy)
@@ -758,7 +758,7 @@
FOR_NB_SCREENS(i)
{
- struct wps_viewport *vp = &gui_wps[i].data->viewports[0];
+ struct wps_viewport *vp = find_viewport(gui_wps[i].data, '\0');
if (gui_wps[i].data->wps_sb_tag)
draw = gui_wps[i].data->show_sb_on_wps;
if (!draw)
Index: apps/gui/gwps.h
===================================================================
--- apps/gui/gwps.h (revision 19998)
+++ 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,31 +109,16 @@
#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
-#define WPS_MAX_VIEWPORTS 2
#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 +300,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 {
@@ -347,6 +340,8 @@
#define VP_DRAW_HIDEABLE 0x1
#define VP_DRAW_HIDDEN 0x2
#define VP_DRAW_WASHIDDEN 0x4
+#define DEFAULT_VP_LBL '\0'
+#define STATIC_VP_LBL '|'
struct wps_viewport {
struct viewport vp; /* The LCD viewport struct */
struct progressbar *pb;
@@ -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
@@ -401,9 +394,7 @@
the index of the line being parsed. */
int num_lines;
- /* Number of viewports in the WPS */
- int num_viewports;
- struct wps_viewport viewports[WPS_MAX_VIEWPORTS];
+ struct wpsll *viewports;
struct wps_line lines[WPS_MAX_LINES];
@@ -417,10 +408,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 +496,16 @@
bool gui_sync_wps_uses_albumart(void);
#endif
+
+struct gui_img* find_img(struct wps_data *wps_data, char id); /* in gwps-common.c */
+struct wps_viewport* find_viewport(struct wps_data *wps_data, char id);
+
+/* 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 19998)
+++ apps/gui/wps_parser.c (working copy)
@@ -79,22 +79,9 @@
/* the current line in the file */
static int line;
-#ifdef HAVE_LCD_BITMAP
+/* the current viewport */
+static struct wps_viewport *curr_vp;
-#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 +329,34 @@
/* the array MUST end with an empty string (first char is \0) */
};
+/* add a wpsll item to the list chain. ALWAYS appended because some of the
+ * chains require the order to be kept.
+ */
+static void add_to_ll_chain(struct wpsll **list, struct wpsll *item)
+{
+ if (*list == NULL)
+ *list = item;
+ else
+ {
+ struct wpsll *t = *list;
+ while (t->next)
+ t = t->next;
+ t->next = item;
+ }
+}
+/* create and init a new wpsll item.
+ * passing NULL to token will alloc a new one.
+ */
+static struct wpsll *new_wpsll_item(struct wps_token *token)
+{
+ struct wpsll *llitem = wps_buffer_alloc(sizeof(struct wpsll));
+ if (!token)
+ token = wps_buffer_alloc(sizeof(struct wps_token));
+ llitem->next = NULL;
+ llitem->token = token;
+ return llitem;
+}
+
/* 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)
@@ -368,12 +383,13 @@
struct wps_data *wps_data)
{
(void)token; /* Kill warnings */
+ struct wps_viewport *vp = find_viewport(wps_data, '\0');
wps_data->wps_sb_tag = true;
wps_data->show_sb_on_wps = true;
- if (wps_data->viewports[0].vp.y == 0)
+ if (vp->vp.y == 0)
{
- wps_data->viewports[0].vp.y = STATUSBAR_HEIGHT;
- wps_data->viewports[0].vp.height -= STATUSBAR_HEIGHT;
+ vp->vp.y = STATUSBAR_HEIGHT;
+ vp->vp.height -= STATUSBAR_HEIGHT;
}
return skip_end_of_line(wps_bufptr);
}
@@ -383,12 +399,13 @@
struct wps_data *wps_data)
{
(void)token; /* Kill warnings */
+ struct wps_viewport *vp = find_viewport(wps_data, '\0');
wps_data->wps_sb_tag = true;
wps_data->show_sb_on_wps = false;
- if (wps_data->viewports[0].vp.y == STATUSBAR_HEIGHT)
+ if (vp->vp.y == STATUSBAR_HEIGHT)
{
- wps_data->viewports[0].vp.y = 0;
- wps_data->viewports[0].vp.height += STATUSBAR_HEIGHT;
+ vp->vp.y = 0;
+ vp->vp.height += STATUSBAR_HEIGHT;
}
return skip_end_of_line(wps_bufptr);
}
@@ -397,16 +414,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 +435,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 +479,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 +492,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 +508,20 @@
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;
-
+ /* tokens for image lod are not saved, so we need a new copy to be able to link them */
+ struct wpsll *llitem = new_wpsll_item((token->type == WPS_TOKEN_IMAGE_DISPLAY)?token:NULL);
+ struct gui_img *img = wps_buffer_alloc(sizeof(struct gui_img));
+ llitem->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 +534,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 = &curr_vp->vp;
if (token->type == WPS_TOKEN_IMAGE_DISPLAY)
{
- wps_data->img[n].always_display = true;
+ img->always_display = true;
}
else
{
@@ -543,12 +558,13 @@
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;
}
-
+ add_to_ll_chain(&wps_data->images, llitem);
+
/* Skip the rest of the line */
return skip_end_of_line(wps_bufptr);
}
@@ -559,13 +575,22 @@
{
(void)wps_data;
char letter = wps_bufptr[0];
-
- if (letter < 'a' || letter > 'z')
+ struct wps_viewport *vp = find_viewport(wps_data, letter);
+ /* viewports are regularly mentioned before being setup.
+ * so if find_viewport() doesnt find one we need to create it first.
+ * this means in parse_viewport() we need to make sure it hasnt been created yet
+ * before allocating room on the buffer for one
+ */
+ if (vp == NULL)
{
- /* invalid viewport tag */
- return WPS_ERROR_INVALID_PARAM;
+ struct wpsll *llitem = new_wpsll_item(token);
+ struct wps_viewport *wvp = wps_buffer_alloc(sizeof(struct wps_viewport));
+ token->value.data = wvp;
+ wvp->label = letter;
+ add_to_ll_chain(&wps_data->viewports, llitem);
+ return 1;
}
- token->value.i = letter;
+ token->value.data = vp;
return 1;
}
@@ -578,6 +603,10 @@
struct viewport* vp;
int depth;
uint32_t set = 0;
+ struct wpsll *llitem = NULL;
+ struct wps_viewport *wvp = NULL, *prev_vp = curr_vp;
+ bool add_to_ll = true;
+ /* tokens for viewport load are not saved, so we need a new copy to be able to link them */
enum {
PL_X = 0,
PL_Y,
@@ -595,15 +624,9 @@
lcd_height = LCD_REMOTE_HEIGHT;
}
#endif
-
- if (wps_data->num_viewports >= WPS_MAX_VIEWPORTS)
- return WPS_ERROR_INVALID_PARAM;
- wps_data->num_viewports++;
/* check for the optional letter to signify its a hideable viewport */
/* %Vl|