more wps->skin engine work..

start redoing memory management in the skins to use a single larger buffer instead of lots of arrays for things like images and progressbars.
This commit removes the limit on the amount of progressbars allowed on the screen, still 1 per viewport, but unlimited otherwise(!)
Also a larger buffer for remote targets, same size for non-remote targets but very easy to make it bigger (technically removed the 52(?) image limit in skins, except still limited to 1 char identifiers)
Unlimited "string" tokens now (limit was 1024 which was rediculously wasteful)


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@22350 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Jonathan Gordon 2009-08-16 18:23:00 +00:00
parent eefe832785
commit 18a8e529b5
11 changed files with 597 additions and 365 deletions

View file

@ -84,9 +84,10 @@ gui/statusbar.c
gui/yesno.c gui/yesno.c
gui/viewport.c gui/viewport.c
gui/skin_engine/skin_buffer.c
gui/skin_engine/wps_debug.c gui/skin_engine/wps_debug.c
gui/skin_engine/skin_display.c gui/skin_engine/skin_display.c
gui/skin_engine/wps_parser.c gui/skin_engine/skin_parser.c
gui/skin_engine/skin_tokens.c gui/skin_engine/skin_tokens.c
#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)) #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))

View file

@ -0,0 +1,100 @@
/***************************************************************************
* __________ __ ___.
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "config.h"
#include "buffer.h"
#include "settings.h"
#include "screen_access.h"
/* skin buffer management.
* This module is used to allocate space in a single global skin buffer for
* tokens for both/all screens.
*
* This is mostly just copy/paste from firmware/buffer.c
*/
#define IMG_BUFSIZE (((LCD_HEIGHT*LCD_WIDTH*LCD_DEPTH/8) \
+ (2*LCD_HEIGHT*LCD_WIDTH/8)) * NB_SCREENS)
static unsigned char buffer_start[IMG_BUFSIZE], *buffer_pos = NULL;
static size_t buf_size = IMG_BUFSIZE;
void skin_buffer_init(void)
{
#if 0 /* this will go in again later probably */
if (buffer_start == NULL)
{
buf_size = IMG_BUFSIZE;/* global_settings.skin_buf_size */
buffer_start = buffer_alloc(buf_size);
buffer_pos = buffer_start;
}
else
#endif
{
/* reset the buffer.... */
buffer_pos = buffer_start;
}
}
/* get the number of bytes currently being used */
size_t skin_buffer_usage(void)
{
return buffer_pos-buffer_start;
}
/* Allocate size bytes from the buffer */
void* skin_buffer_alloc(size_t size)
{
void* retval = buffer_pos;
if (skin_buffer_usage()+size >= buf_size)
{
return NULL;
}
buffer_pos += size;
/* 32-bit aligned */
buffer_pos = (void *)(((unsigned long)buffer_pos + 3) & ~3);
return retval;
}
/* Get a pointer to the skin buffer and the count of how much is free
* used to do your own buffer management.
* Any memory used will be overwritten next time wps_buffer_alloc()
* is called unless skin_buffer_increment() is called first
*/
void* skin_buffer_grab(size_t *freespace)
{
*freespace = buf_size - skin_buffer_usage();
return buffer_pos;
}
/* Use after skin_buffer_grab() to specify how much buffer was used */
void skin_buffer_increment(size_t used)
{
buffer_pos += used;
/* 32-bit aligned */
buffer_pos = (void *)(((unsigned long)buffer_pos + 3) & ~3);
}

View file

@ -0,0 +1,51 @@
/***************************************************************************
* __________ __ ___.
* 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.
*
****************************************************************************/
#ifndef _SKIN_BUFFER_H_
#define _SKIN_BUFFER_H_
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* int the global buffer */
void skin_buffer_init(void);
/* get the number of bytes currently being used */
size_t skin_buffer_usage(void);
/* Allocate size bytes from the buffer */
void* skin_buffer_alloc(size_t size);
/* Get a pointer to the skin buffer and the count of how much is free
* used to do your own buffer management.
* Any memory used will be overwritten next time wps_buffer_alloc()
* is called unless skin_buffer_increment() is called first
*/
void* skin_buffer_grab(size_t *freespace);
/* Use after skin_buffer_grab() to specify how much buffer was used */
void skin_buffer_increment(size_t used);
#endif /* _SKIN_BUFFER_H_ */

View file

@ -68,34 +68,16 @@
static bool skin_redraw(struct gui_wps *gwps, unsigned refresh_mode); static bool skin_redraw(struct gui_wps *gwps, unsigned refresh_mode);
#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 */ /* initial setup of wps_data */
void skin_data_init(struct wps_data *wps_data) void skin_data_init(struct wps_data *wps_data)
{ {
#ifdef HAVE_LCD_BITMAP #ifdef HAVE_LCD_BITMAP
wps_images_clear(wps_data);
wps_data->wps_sb_tag = false; wps_data->wps_sb_tag = false;
wps_data->show_sb_on_wps = 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; wps_data->peak_meter_enabled = false;
wps_data->images = NULL;
wps_data->progressbars = NULL;
/* progress bars */ /* progress bars */
wps_data->progressbar_count = 0;
#else /* HAVE_LCD_CHARCELLS */ #else /* HAVE_LCD_CHARCELLS */
int i; int i;
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
@ -191,41 +173,38 @@ static void draw_progressbar(struct gui_wps *gwps,
} }
/* clears the area where the image was shown */ /* clears the area where the image was shown */
static void clear_image_pos(struct gui_wps *gwps, int n) static void clear_image_pos(struct gui_wps *gwps, struct gui_img *img)
{ {
if(!gwps) if(!gwps)
return; return;
struct wps_data *data = gwps->data;
gwps->display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); gwps->display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
gwps->display->fillrect(data->img[n].x, data->img[n].y, gwps->display->fillrect(img->x, img->y, img->bm.width, img->subimage_height);
data->img[n].bm.width, data->img[n].subimage_height);
gwps->display->set_drawmode(DRMODE_SOLID); gwps->display->set_drawmode(DRMODE_SOLID);
} }
static void wps_draw_image(struct gui_wps *gwps, int n, int subimage) static void wps_draw_image(struct gui_wps *gwps, struct gui_img *img, int subimage)
{ {
struct screen *display = gwps->display; struct screen *display = gwps->display;
struct wps_data *data = gwps->data; if(img->always_display)
if(data->img[n].always_display)
display->set_drawmode(DRMODE_FG); display->set_drawmode(DRMODE_FG);
else else
display->set_drawmode(DRMODE_SOLID); display->set_drawmode(DRMODE_SOLID);
#if LCD_DEPTH > 1 #if LCD_DEPTH > 1
if(data->img[n].bm.format == FORMAT_MONO) { if(img->bm.format == FORMAT_MONO) {
#endif #endif
display->mono_bitmap_part(data->img[n].bm.data, display->mono_bitmap_part(img->bm.data,
0, data->img[n].subimage_height * subimage, 0, img->subimage_height * subimage,
data->img[n].bm.width, data->img[n].x, img->bm.width, img->x,
data->img[n].y, data->img[n].bm.width, img->y, img->bm.width,
data->img[n].subimage_height); img->subimage_height);
#if LCD_DEPTH > 1 #if LCD_DEPTH > 1
} else { } else {
display->transparent_bitmap_part((fb_data *)data->img[n].bm.data, display->transparent_bitmap_part((fb_data *)img->bm.data,
0, data->img[n].subimage_height * subimage, 0, img->subimage_height * subimage,
data->img[n].bm.width, data->img[n].x, img->bm.width, img->x,
data->img[n].y, data->img[n].bm.width, img->y, img->bm.width,
data->img[n].subimage_height); img->subimage_height);
} }
#endif #endif
} }
@ -235,22 +214,25 @@ static void wps_display_images(struct gui_wps *gwps, struct viewport* vp)
if(!gwps || !gwps->data || !gwps->display) if(!gwps || !gwps->data || !gwps->display)
return; return;
int n;
struct wps_data *data = gwps->data; struct wps_data *data = gwps->data;
struct screen *display = gwps->display; struct screen *display = gwps->display;
struct skin_token_list *list = data->images;
for (n = 0; n < MAX_IMAGES; n++) while (list)
{ {
if (data->img[n].loaded) struct gui_img *img = (struct gui_img*)list->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); wps_draw_image(gwps, img, img->display);
} else if (data->img[n].always_display && data->img[n].vp == vp) }
else if (img->always_display && img->vp == vp)
{ {
wps_draw_image(gwps, n, 0); wps_draw_image(gwps, img, 0);
} }
} }
list = list->next;
} }
display->set_drawmode(DRMODE_SOLID); display->set_drawmode(DRMODE_SOLID);
} }
@ -484,7 +466,7 @@ static bool evaluate_conditional(struct gui_wps *gwps, int *token_index)
#ifdef HAVE_LCD_BITMAP #ifdef HAVE_LCD_BITMAP
/* clear all pictures in the conditional and nested ones */ /* clear all pictures in the conditional and nested ones */
if (data->tokens[i].type == WPS_TOKEN_IMAGE_PRELOAD_DISPLAY) if (data->tokens[i].type == WPS_TOKEN_IMAGE_PRELOAD_DISPLAY)
clear_image_pos(gwps, data->tokens[i].value.i & 0xFF); clear_image_pos(gwps, find_image(data->tokens[i].value.i&0xFF, gwps->data));
#endif #endif
#ifdef HAVE_ALBUMART #ifdef HAVE_ALBUMART
if (data->tokens[i].type == WPS_TOKEN_ALBUMART_DISPLAY) if (data->tokens[i].type == WPS_TOKEN_ALBUMART_DISPLAY)
@ -494,7 +476,20 @@ static bool evaluate_conditional(struct gui_wps *gwps, int *token_index)
return true; return true;
} }
struct gui_img* find_image(int n, struct wps_data *data)
{
struct skin_token_list *list = data->images;
while (list)
{
struct gui_img *img = (struct gui_img *)list->token->value.data;
if (img->id == n)
return img;
list = list->next;
}
return NULL;
}
/* Read a (sub)line to the given alignment format buffer. /* Read a (sub)line to the given alignment format buffer.
linebuf is the buffer where the data is actually stored. linebuf is the buffer where the data is actually stored.
align is the alignment format that'll be used to display the text. align is the alignment format that'll be used to display the text.
@ -544,12 +539,12 @@ static bool get_line(struct gui_wps *gwps,
#ifdef HAVE_LCD_BITMAP #ifdef HAVE_LCD_BITMAP
case WPS_TOKEN_IMAGE_PRELOAD_DISPLAY: case WPS_TOKEN_IMAGE_PRELOAD_DISPLAY:
{ {
struct gui_img *img = data->img;
int n = data->tokens[i].value.i & 0xFF; int n = data->tokens[i].value.i & 0xFF;
int subimage = data->tokens[i].value.i >> 8; int subimage = data->tokens[i].value.i >> 8;
struct gui_img *img = find_image(n, data);
if (n >= 0 && n < MAX_IMAGES && img[n].loaded) if (img && img->loaded)
img[n].display = subimage; img->display = subimage;
break; break;
} }
#endif #endif
@ -992,9 +987,12 @@ static bool skin_redraw(struct gui_wps *gwps, unsigned refresh_mode)
#ifdef HAVE_LCD_BITMAP #ifdef HAVE_LCD_BITMAP
/* Set images to not to be displayed */ /* Set images to not to be displayed */
for (i = 0; i < MAX_IMAGES; i++) struct skin_token_list *imglist = data->images;
while (imglist)
{ {
data->img[i].display = -1; struct gui_img *img = (struct gui_img *)imglist->token->value.data;
img->display = -1;
imglist = imglist->next;
} }
#endif #endif
/* dont redraw the viewport if its disabled */ /* dont redraw the viewport if its disabled */

View file

@ -23,6 +23,8 @@
#ifndef _SKIN_ENGINE_H #ifndef _SKIN_ENGINE_H
#define _SKIN_ENGINE_H #define _SKIN_ENGINE_H
#include "skin_buffer.h"
#include "wps_internals.h" /* TODO: remove this line.. shoudlnt be needed */ #include "wps_internals.h" /* TODO: remove this line.. shoudlnt be needed */

View file

@ -355,6 +355,40 @@ static const struct wps_tag all_tags[] = {
/* the array MUST end with an empty string (first char is \0) */ /* 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 skin_token_list **list, struct skin_token_list *item)
{
if (*list == NULL)
*list = item;
else
{
struct skin_token_list *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 skin_token_list *new_skin_token_list_item(struct wps_token *token,
void* token_data)
{
struct skin_token_list *llitem = skin_buffer_alloc(sizeof(struct skin_token_list));
if (!token)
token = skin_buffer_alloc(sizeof(struct wps_token));
if (!llitem || !token)
return NULL;
llitem->next = NULL;
llitem->token = token;
if (token_data)
llitem->token->value.data = token_data;
return llitem;
}
/* Returns the number of chars that should be skipped to jump /* 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 */ immediately after the first eol, i.e. to the start of the next line */
static int skip_end_of_line(const char *wps_bufptr) static int skip_end_of_line(const char *wps_bufptr)
@ -406,37 +440,6 @@ static int parse_statusbar_disable(const char *wps_bufptr,
return skip_end_of_line(wps_bufptr); return skip_end_of_line(wps_bufptr);
} }
static bool load_bitmap(struct wps_data *wps_data,
char* filename,
struct bitmap *bm)
{
int format;
#ifdef HAVE_REMOTE_LCD
if (wps_data->remote_wps)
format = FORMAT_ANY|FORMAT_REMOTE;
else
#endif
format = FORMAT_ANY|FORMAT_TRANSPARENT;
int ret = read_bmp_file(filename, bm,
wps_data->img_buf_free,
format,NULL);
if (ret > 0)
{
#if LCD_DEPTH == 16
if (ret % 2) ret++;
/* Always consume an even number of bytes */
#endif
wps_data->img_buf_ptr += ret;
wps_data->img_buf_free -= ret;
return true;
}
else
return false;
}
static int get_image_id(int c) static int get_image_id(int c)
{ {
if(c >= 'a' && c <= 'z') if(c >= 'a' && c <= 'z')
@ -472,9 +475,9 @@ static int parse_image_display(const char *wps_bufptr,
struct wps_token *token, struct wps_token *token,
struct wps_data *wps_data) struct wps_data *wps_data)
{ {
(void)wps_data;
int n = get_image_id(wps_bufptr[0]); int n = get_image_id(wps_bufptr[0]);
int subimage; int subimage;
struct gui_img *img;;
if (n == -1) if (n == -1)
{ {
@ -484,8 +487,9 @@ static int parse_image_display(const char *wps_bufptr,
if ((subimage = get_image_id(wps_bufptr[1])) != -1) if ((subimage = get_image_id(wps_bufptr[1])) != -1)
{ {
img = find_image(n, wps_data);
/* Sanity check */ /* Sanity check */
if (subimage >= wps_data->img[n].num_subimages) if (!img || subimage >= img->num_subimages)
return WPS_ERROR_INVALID_PARAM; return WPS_ERROR_INVALID_PARAM;
/* Store sub-image number to display in high bits */ /* Store sub-image number to display in high bits */
@ -508,6 +512,7 @@ static int parse_image_load(const char *wps_bufptr,
const char* id; const char* id;
const char *newline; const char *newline;
int x,y; int x,y;
struct gui_img *img;
/* format: %x|n|filename.bmp|x|y| /* format: %x|n|filename.bmp|x|y|
or %xl|n|filename.bmp|x|y| or %xl|n|filename.bmp|x|y|
@ -530,24 +535,28 @@ static int parse_image_load(const char *wps_bufptr,
n = get_image_id(*id); n = get_image_id(*id);
/* check the image number and load state */ /* check the image number and load state */
if(n < 0 || n >= MAX_IMAGES || wps_data->img[n].loaded) if(n < 0 || find_image(n, wps_data))
{ {
/* Invalid image ID */ /* Invalid image ID */
return WPS_ERROR_INVALID_PARAM; return WPS_ERROR_INVALID_PARAM;
} }
img = skin_buffer_alloc(sizeof(struct gui_img));
if (!img)
return WPS_ERROR_INVALID_PARAM;
/* save a pointer to the filename */ /* save a pointer to the filename */
bmp_names[n] = filename; img->bm.data = (char*)filename;
img->id = n;
wps_data->img[n].x = x; img->x = x;
wps_data->img[n].y = y; img->y = y;
img->num_subimages = 1;
img->always_display = false;
/* save current viewport */ /* 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) if (token->type == WPS_TOKEN_IMAGE_DISPLAY)
{ {
wps_data->img[n].always_display = true; img->always_display = true;
} }
else else
{ {
@ -556,11 +565,15 @@ static int parse_image_load(const char *wps_bufptr,
newline = strchr(ptr, '\n'); newline = strchr(ptr, '\n');
pos = strchr(ptr, '|'); pos = strchr(ptr, '|');
if (pos && pos < newline) 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; return WPS_ERROR_INVALID_PARAM;
} }
struct skin_token_list *item = new_skin_token_list_item(NULL, img);
if (!item)
return WPS_ERROR_INVALID_PARAM;
add_to_ll_chain(&wps_data->images, item);
/* Skip the rest of the line */ /* Skip the rest of the line */
return skip_end_of_line(wps_bufptr); return skip_end_of_line(wps_bufptr);
@ -781,7 +794,6 @@ static int parse_progressbar(const char *wps_bufptr,
struct wps_token *token, struct wps_token *token,
struct wps_data *wps_data) struct wps_data *wps_data)
{ {
(void)token; /* Kill warnings */
/* %pb or %pb|filename|x|y|width|height| /* %pb or %pb|filename|x|y|width|height|
using - for any of the params uses "sane" values */ using - for any of the params uses "sane" values */
#ifdef HAVE_LCD_BITMAP #ifdef HAVE_LCD_BITMAP
@ -796,7 +808,12 @@ static int parse_progressbar(const char *wps_bufptr,
int x, y, height, width; int x, y, height, width;
uint32_t set = 0; uint32_t set = 0;
const char *ptr = wps_bufptr; const char *ptr = wps_bufptr;
struct progressbar *pb; struct progressbar *pb = skin_buffer_alloc(sizeof(struct progressbar));
struct skin_token_list *item = new_skin_token_list_item(token, pb);
if (!pb || !item)
return WPS_ERROR_INVALID_PARAM;
struct viewport *vp = &wps_data->viewports[wps_data->num_viewports].vp; struct viewport *vp = &wps_data->viewports[wps_data->num_viewports].vp;
#ifndef __PCTOOL__ #ifndef __PCTOOL__
int font_height = font_get(vp->font)->height; int font_height = font_get(vp->font)->height;
@ -806,11 +823,8 @@ static int parse_progressbar(const char *wps_bufptr,
int line_num = wps_data->num_lines - int line_num = wps_data->num_lines -
wps_data->viewports[wps_data->num_viewports].first_line; 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; pb->have_bitmap_pb = false;
pb->bm.data = NULL; /* no bitmap specified */
if (*wps_bufptr != '|') /* regular old style */ if (*wps_bufptr != '|') /* regular old style */
{ {
@ -820,7 +834,7 @@ static int parse_progressbar(const char *wps_bufptr,
pb->y = -line_num - 1; /* Will be computed during the rendering */ pb->y = -line_num - 1; /* Will be computed during the rendering */
wps_data->viewports[wps_data->num_viewports].pb = pb; wps_data->viewports[wps_data->num_viewports].pb = pb;
wps_data->progressbar_count++; add_to_ll_chain(&wps_data->progressbars, item);
return 0; return 0;
} }
ptr = wps_bufptr + 1; ptr = wps_bufptr + 1;
@ -830,7 +844,7 @@ static int parse_progressbar(const char *wps_bufptr,
return WPS_ERROR_INVALID_PARAM; return WPS_ERROR_INVALID_PARAM;
if (LIST_VALUE_PARSED(set, PB_FILENAME)) /* filename */ if (LIST_VALUE_PARSED(set, PB_FILENAME)) /* filename */
bmp_names[PROGRESSBAR_BMP+wps_data->progressbar_count] = filename; pb->bm.data = (char*)filename;
if (LIST_VALUE_PARSED(set, PB_X)) /* x */ if (LIST_VALUE_PARSED(set, PB_X)) /* x */
pb->x = x; pb->x = x;
@ -865,7 +879,7 @@ static int parse_progressbar(const char *wps_bufptr,
pb->y = -line_num - 1; /* Will be computed during the rendering */ pb->y = -line_num - 1; /* Will be computed during the rendering */
wps_data->viewports[wps_data->num_viewports].pb = pb; wps_data->viewports[wps_data->num_viewports].pb = pb;
wps_data->progressbar_count++; add_to_ll_chain(&wps_data->progressbars, item);
/* Skip the rest of the line */ /* Skip the rest of the line */
return skip_end_of_line(wps_bufptr)-1; return skip_end_of_line(wps_bufptr)-1;
@ -1250,9 +1264,6 @@ static bool wps_parse(struct wps_data *data, const char *wps_bufptr)
{ {
if (!data || !wps_bufptr || !*wps_bufptr) if (!data || !wps_bufptr || !*wps_bufptr)
return false; return false;
char *stringbuf = data->string_buffer;
int stringbuf_used = 0;
enum wps_parse_error fail = PARSE_OK; enum wps_parse_error fail = PARSE_OK;
int ret; int ret;
line = 1; line = 1;
@ -1404,42 +1415,45 @@ static bool wps_parse(struct wps_data *data, const char *wps_bufptr)
} }
/* look if we already have that string */ /* look if we already have that string */
char **str; char *str;
int i; bool found = false;
bool found; struct skin_token_list *list = data->strings;
for (i = 0, str = data->strings, found = false; while (list)
i < data->num_strings && {
!(found = (strlen(*str) == len && str = (char*)list->token->value.data;
strncmp(string_start, *str, len) == 0)); found = (strlen(str) == len &&
i++, str++); strncmp(string_start, str, len) == 0);
if (found)
break; /* break here because the list item is
used if its found */
list = list->next;
}
/* If a matching string is found, found is true and i is /* If a matching string is found, found is true and i is
the index of the string. If not, found is false */ the index of the string. If not, found is false */
if (!found) if (!found)
{ {
/* new string */ /* new string */
str = (char*)skin_buffer_alloc(len+1);
if (stringbuf_used + len > STRING_BUFFER_SIZE - 1 if (!str)
|| data->num_strings >= WPS_MAX_STRINGS) {
{ fail = PARSE_FAIL_LIMITS_EXCEEDED;
/* too many strings or characters */ break;
fail = PARSE_FAIL_LIMITS_EXCEEDED;
break;
} }
strlcpy(str, string_start, len+1);
strlcpy(stringbuf, string_start, len+1); struct skin_token_list *item =
new_skin_token_list_item(&data->tokens[data->num_tokens], str);
data->strings[data->num_strings] = stringbuf; if(!item)
stringbuf += len + 1; {
stringbuf_used += len + 1; fail = PARSE_FAIL_LIMITS_EXCEEDED;
data->tokens[data->num_tokens].value.i = break;
data->num_strings; }
data->num_strings++; add_to_ll_chain(&data->strings, item);
} }
else else
{ {
/* another occurrence of an existing string */ /* another occurrence of an existing string */
data->tokens[data->num_tokens].value.i = i; data->tokens[data->num_tokens].value.data = list->token->value.data;
} }
data->tokens[data->num_tokens].type = WPS_TOKEN_STRING; data->tokens[data->num_tokens].type = WPS_TOKEN_STRING;
data->num_tokens++; data->num_tokens++;
@ -1480,54 +1494,75 @@ static void wps_reset(struct wps_data *data)
} }
#ifdef HAVE_LCD_BITMAP #ifdef HAVE_LCD_BITMAP
static bool load_skin_bmp(struct wps_data *wps_data, struct bitmap *bitmap, char* bmpdir)
{
(void)wps_data; /* only needed for remote targets */
bool loaded = false;
char img_path[MAX_PATH];
get_image_filename(bitmap->data, bmpdir,
img_path, sizeof(img_path));
/* load the image */
int format;
#ifdef HAVE_REMOTE_LCD
if (wps_data->remote_wps)
format = FORMAT_ANY|FORMAT_REMOTE;
else
#endif
format = FORMAT_ANY|FORMAT_TRANSPARENT;
size_t max_buf;
char* imgbuf = (char*)skin_buffer_grab(&max_buf);
bitmap->data = imgbuf;
int ret = read_bmp_file(img_path, bitmap, max_buf, format, NULL);
if (ret > 0)
{
skin_buffer_increment(ret);
loaded = true;
}
else
{
/* Abort if we can't load an image */
DEBUGF("ERR: Failed to load image - %s\n",img_path);
loaded = false;
}
return loaded;
}
static bool load_skin_bitmaps(struct wps_data *wps_data, char *bmpdir) static bool load_skin_bitmaps(struct wps_data *wps_data, char *bmpdir)
{ {
char img_path[MAX_PATH]; struct skin_token_list *list;
struct bitmap *bitmap; /* do the progressbars */
bool *loaded; list = wps_data->progressbars;
int n; while (list)
for (n = 0; n < BACKDROP_BMP; n++)
{ {
if (bmp_names[n]) struct progressbar *pb = (struct progressbar*)list->token->value.data;
if (pb->bm.data)
{ {
get_image_filename(bmp_names[n], bmpdir, pb->have_bitmap_pb = load_skin_bmp(wps_data, &pb->bm, 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;
}
/* load the image */
bitmap->data = wps_data->img_buf_ptr;
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;
}
else
{
/* Abort if we can't load an image */
DEBUGF("ERR: Failed to load image %d - %s\n",n,img_path);
return false;
}
} }
list = list->next;
}
/* regular images */
list = wps_data->images;
while (list)
{
struct gui_img *img = (struct gui_img*)list->token->value.data;
if (img->bm.data)
{
img->loaded = load_skin_bmp(wps_data, &img->bm, bmpdir);
if (img->loaded)
img->subimage_height = img->bm.height / img->num_subimages;
}
list = list->next;
} }
#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)) #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
if (bmp_names[BACKDROP_BMP]) if (bmp_names[BACKDROP_BMP])
{ {
int screen = SCREEN_MAIN; int screen = SCREEN_MAIN;
char img_path[MAX_PATH];
get_image_filename(bmp_names[BACKDROP_BMP], bmpdir, get_image_filename(bmp_names[BACKDROP_BMP], bmpdir,
img_path, sizeof(img_path)); img_path, sizeof(img_path));
#if defined(HAVE_REMOTE_LCD) #if defined(HAVE_REMOTE_LCD)

View file

@ -167,7 +167,7 @@ const char *get_token_value(struct gui_wps *gwps,
return &(token->value.c); return &(token->value.c);
case WPS_TOKEN_STRING: case WPS_TOKEN_STRING:
return data->strings[token->value.i]; return (char*)token->value.data;
case WPS_TOKEN_TRACK_TIME_ELAPSED: case WPS_TOKEN_TRACK_TIME_ELAPSED:
format_time(buf, buf_size, format_time(buf, buf_size,

View file

@ -0,0 +1,218 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id: wps_internals.h 22223 2009-08-09 17:30:05Z jdgordon $
*
* Copyright (C) 2007 Nicolas Pennequin
*
* 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.
*
****************************************************************************/
#ifndef _SKIN_TOKENS_H_
#define _SKIN_TOKENS_H_
#include <stdbool.h>
enum wps_token_type {
WPS_NO_TOKEN, /* for WPS tags we don't want to save as tokens */
WPS_TOKEN_UNKNOWN,
/* Markers */
WPS_TOKEN_CHARACTER,
WPS_TOKEN_STRING,
/* Alignment */
WPS_TOKEN_ALIGN_LEFT,
WPS_TOKEN_ALIGN_CENTER,
WPS_TOKEN_ALIGN_RIGHT,
/* Sublines */
WPS_TOKEN_SUBLINE_TIMEOUT,
/* Battery */
WPS_TOKEN_BATTERY_PERCENT,
WPS_TOKEN_BATTERY_VOLTS,
WPS_TOKEN_BATTERY_TIME,
WPS_TOKEN_BATTERY_CHARGER_CONNECTED,
WPS_TOKEN_BATTERY_CHARGING,
WPS_TOKEN_BATTERY_SLEEPTIME,
/* Sound */
#if (CONFIG_CODEC != MAS3507D)
WPS_TOKEN_SOUND_PITCH,
#endif
#if (CONFIG_CODEC == SWCODEC)
WPS_TOKEN_REPLAYGAIN,
WPS_TOKEN_CROSSFADE,
#endif
/* Time */
WPS_TOKEN_RTC_PRESENT,
/* The begin/end values allow us to know if a token is an RTC one.
New RTC tokens should be added between the markers. */
WPS_TOKENS_RTC_BEGIN, /* just the start marker, not an actual token */
WPS_TOKEN_RTC_DAY_OF_MONTH,
WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED,
WPS_TOKEN_RTC_12HOUR_CFG,
WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED,
WPS_TOKEN_RTC_HOUR_24,
WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED,
WPS_TOKEN_RTC_HOUR_12,
WPS_TOKEN_RTC_MONTH,
WPS_TOKEN_RTC_MINUTE,
WPS_TOKEN_RTC_SECOND,
WPS_TOKEN_RTC_YEAR_2_DIGITS,
WPS_TOKEN_RTC_YEAR_4_DIGITS,
WPS_TOKEN_RTC_AM_PM_UPPER,
WPS_TOKEN_RTC_AM_PM_LOWER,
WPS_TOKEN_RTC_WEEKDAY_NAME,
WPS_TOKEN_RTC_MONTH_NAME,
WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON,
WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN,
WPS_TOKENS_RTC_END, /* just the end marker, not an actual token */
/* Conditional */
WPS_TOKEN_CONDITIONAL,
WPS_TOKEN_CONDITIONAL_START,
WPS_TOKEN_CONDITIONAL_OPTION,
WPS_TOKEN_CONDITIONAL_END,
/* Database */
#ifdef HAVE_TAGCACHE
WPS_TOKEN_DATABASE_PLAYCOUNT,
WPS_TOKEN_DATABASE_RATING,
WPS_TOKEN_DATABASE_AUTOSCORE,
#endif
/* File */
WPS_TOKEN_FILE_BITRATE,
WPS_TOKEN_FILE_CODEC,
WPS_TOKEN_FILE_FREQUENCY,
WPS_TOKEN_FILE_FREQUENCY_KHZ,
WPS_TOKEN_FILE_NAME,
WPS_TOKEN_FILE_NAME_WITH_EXTENSION,
WPS_TOKEN_FILE_PATH,
WPS_TOKEN_FILE_SIZE,
WPS_TOKEN_FILE_VBR,
WPS_TOKEN_FILE_DIRECTORY,
#ifdef HAVE_LCD_BITMAP
/* Image */
WPS_TOKEN_IMAGE_BACKDROP,
WPS_TOKEN_IMAGE_PROGRESS_BAR,
WPS_TOKEN_IMAGE_PRELOAD,
WPS_TOKEN_IMAGE_PRELOAD_DISPLAY,
WPS_TOKEN_IMAGE_DISPLAY,
#endif
#ifdef HAVE_ALBUMART
/* Albumart */
WPS_TOKEN_ALBUMART_DISPLAY,
WPS_TOKEN_ALBUMART_FOUND,
#endif
/* Metadata */
WPS_TOKEN_METADATA_ARTIST,
WPS_TOKEN_METADATA_COMPOSER,
WPS_TOKEN_METADATA_ALBUM_ARTIST,
WPS_TOKEN_METADATA_GROUPING,
WPS_TOKEN_METADATA_ALBUM,
WPS_TOKEN_METADATA_GENRE,
WPS_TOKEN_METADATA_DISC_NUMBER,
WPS_TOKEN_METADATA_TRACK_NUMBER,
WPS_TOKEN_METADATA_TRACK_TITLE,
WPS_TOKEN_METADATA_VERSION,
WPS_TOKEN_METADATA_YEAR,
WPS_TOKEN_METADATA_COMMENT,
/* Mode */
WPS_TOKEN_REPEAT_MODE,
WPS_TOKEN_PLAYBACK_STATUS,
WPS_TOKEN_MAIN_HOLD,
#ifdef HAS_REMOTE_BUTTON_HOLD
WPS_TOKEN_REMOTE_HOLD,
#endif
/* Progressbar */
WPS_TOKEN_PROGRESSBAR,
#ifdef HAVE_LCD_CHARCELLS
WPS_TOKEN_PLAYER_PROGRESSBAR,
#endif
#ifdef HAVE_LCD_BITMAP
/* Peakmeter */
WPS_TOKEN_PEAKMETER,
#endif
/* Volume level */
WPS_TOKEN_VOLUME,
/* Current track */
WPS_TOKEN_TRACK_ELAPSED_PERCENT,
WPS_TOKEN_TRACK_TIME_ELAPSED,
WPS_TOKEN_TRACK_TIME_REMAINING,
WPS_TOKEN_TRACK_LENGTH,
/* Playlist */
WPS_TOKEN_PLAYLIST_ENTRIES,
WPS_TOKEN_PLAYLIST_NAME,
WPS_TOKEN_PLAYLIST_POSITION,
WPS_TOKEN_PLAYLIST_SHUFFLE,
#if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
/* Virtual LED */
WPS_TOKEN_VLED_HDD,
#endif
/* Viewport display */
WPS_VIEWPORT_ENABLE,
/* buttons */
WPS_TOKEN_BUTTON_VOLUME,
WPS_TOKEN_LASTTOUCH,
/* Setting option */
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;
void* data;
} value;
};
struct skin_token_list {
struct wps_token *token;
struct skin_token_list *next;
};
#endif

View file

@ -23,6 +23,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include "wps.h"
#include "wps_internals.h" #include "wps_internals.h"
#ifdef __PCTOOL__ #ifdef __PCTOOL__
#ifdef WPSEDITOR #ifdef WPSEDITOR
@ -548,15 +549,18 @@ static void print_line_info(struct wps_data *data)
DEBUGF("\n"); DEBUGF("\n");
} }
} }
#if 0
/* NOTE: this is probaly not even needed anymore */
static void print_wps_strings(struct wps_data *data) static void print_wps_strings(struct wps_data *data)
{ {
int i, len, total_len = 0, buf_used = 0; int i, len, total_len = 0, buf_used = 0;
if (wps_verbose_level > 1) DEBUGF("Strings:\n"); if (wps_verbose_level > 1) DEBUGF("Strings:\n");
for (i = 0; i < data->num_strings; i++) struct skin_token_list *strings = data->strings;
while (strings)
{ {
len = strlen(data->strings[i]); char* str = (char*)strings->token->value.data;
len = strlen(str);
total_len += len; total_len += len;
buf_used += len + 1; buf_used += len + 1;
if (wps_verbose_level > 1) if (wps_verbose_level > 1)
@ -575,6 +579,7 @@ static void print_wps_strings(struct wps_data *data)
} }
} }
#endif #endif
#endif
void print_debug_info(struct wps_data *data, enum wps_parse_error fail, int line) void print_debug_info(struct wps_data *data, enum wps_parse_error fail, int line)
{ {
@ -582,7 +587,7 @@ void print_debug_info(struct wps_data *data, enum wps_parse_error fail, int line
if (debug_wps && wps_verbose_level) if (debug_wps && wps_verbose_level)
{ {
dump_wps_tokens(data); dump_wps_tokens(data);
print_wps_strings(data); /* print_wps_strings(data); */
print_line_info(data); print_line_info(data);
} }
#endif /* SIMULATOR */ #endif /* SIMULATOR */

View file

@ -31,7 +31,7 @@
#define TIMEOUT_UNIT (HZ/10) /* I.e. 0.1 sec */ #define TIMEOUT_UNIT (HZ/10) /* I.e. 0.1 sec */
#define DEFAULT_SUBLINE_TIME_MULTIPLIER 20 /* In TIMEOUT_UNIT's */ #define DEFAULT_SUBLINE_TIME_MULTIPLIER 20 /* In TIMEOUT_UNIT's */
#include "skin_tokens.h"
/* TODO: sort this mess out */ /* TODO: sort this mess out */
@ -77,6 +77,7 @@
#ifdef HAVE_LCD_BITMAP #ifdef HAVE_LCD_BITMAP
struct gui_img { struct gui_img {
short int id;
struct bitmap bm; struct bitmap bm;
struct viewport* vp; /* The viewport to display this image in */ struct viewport* vp; /* The viewport to display this image in */
short int x; /* x-pos */ short int x; /* x-pos */
@ -88,6 +89,7 @@ struct gui_img {
bool always_display; /* not using the preload/display mechanism */ bool always_display; /* not using the preload/display mechanism */
}; };
struct progressbar { struct progressbar {
/* regular pb */ /* regular pb */
short x; short x;
@ -153,187 +155,6 @@ enum wps_parse_error {
PARSE_FAIL_LIMITS_EXCEEDED, PARSE_FAIL_LIMITS_EXCEEDED,
}; };
enum wps_token_type {
WPS_NO_TOKEN, /* for WPS tags we don't want to save as tokens */
WPS_TOKEN_UNKNOWN,
/* Markers */
WPS_TOKEN_CHARACTER,
WPS_TOKEN_STRING,
/* Alignment */
WPS_TOKEN_ALIGN_LEFT,
WPS_TOKEN_ALIGN_CENTER,
WPS_TOKEN_ALIGN_RIGHT,
/* Sublines */
WPS_TOKEN_SUBLINE_TIMEOUT,
/* Battery */
WPS_TOKEN_BATTERY_PERCENT,
WPS_TOKEN_BATTERY_VOLTS,
WPS_TOKEN_BATTERY_TIME,
WPS_TOKEN_BATTERY_CHARGER_CONNECTED,
WPS_TOKEN_BATTERY_CHARGING,
WPS_TOKEN_BATTERY_SLEEPTIME,
/* Sound */
#if (CONFIG_CODEC != MAS3507D)
WPS_TOKEN_SOUND_PITCH,
#endif
#if (CONFIG_CODEC == SWCODEC)
WPS_TOKEN_REPLAYGAIN,
WPS_TOKEN_CROSSFADE,
#endif
/* Time */
WPS_TOKEN_RTC_PRESENT,
/* The begin/end values allow us to know if a token is an RTC one.
New RTC tokens should be added between the markers. */
WPS_TOKENS_RTC_BEGIN, /* just the start marker, not an actual token */
WPS_TOKEN_RTC_DAY_OF_MONTH,
WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED,
WPS_TOKEN_RTC_12HOUR_CFG,
WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED,
WPS_TOKEN_RTC_HOUR_24,
WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED,
WPS_TOKEN_RTC_HOUR_12,
WPS_TOKEN_RTC_MONTH,
WPS_TOKEN_RTC_MINUTE,
WPS_TOKEN_RTC_SECOND,
WPS_TOKEN_RTC_YEAR_2_DIGITS,
WPS_TOKEN_RTC_YEAR_4_DIGITS,
WPS_TOKEN_RTC_AM_PM_UPPER,
WPS_TOKEN_RTC_AM_PM_LOWER,
WPS_TOKEN_RTC_WEEKDAY_NAME,
WPS_TOKEN_RTC_MONTH_NAME,
WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON,
WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN,
WPS_TOKENS_RTC_END, /* just the end marker, not an actual token */
/* Conditional */
WPS_TOKEN_CONDITIONAL,
WPS_TOKEN_CONDITIONAL_START,
WPS_TOKEN_CONDITIONAL_OPTION,
WPS_TOKEN_CONDITIONAL_END,
/* Database */
#ifdef HAVE_TAGCACHE
WPS_TOKEN_DATABASE_PLAYCOUNT,
WPS_TOKEN_DATABASE_RATING,
WPS_TOKEN_DATABASE_AUTOSCORE,
#endif
/* File */
WPS_TOKEN_FILE_BITRATE,
WPS_TOKEN_FILE_CODEC,
WPS_TOKEN_FILE_FREQUENCY,
WPS_TOKEN_FILE_FREQUENCY_KHZ,
WPS_TOKEN_FILE_NAME,
WPS_TOKEN_FILE_NAME_WITH_EXTENSION,
WPS_TOKEN_FILE_PATH,
WPS_TOKEN_FILE_SIZE,
WPS_TOKEN_FILE_VBR,
WPS_TOKEN_FILE_DIRECTORY,
#ifdef HAVE_LCD_BITMAP
/* Image */
WPS_TOKEN_IMAGE_BACKDROP,
WPS_TOKEN_IMAGE_PROGRESS_BAR,
WPS_TOKEN_IMAGE_PRELOAD,
WPS_TOKEN_IMAGE_PRELOAD_DISPLAY,
WPS_TOKEN_IMAGE_DISPLAY,
#endif
#ifdef HAVE_ALBUMART
/* Albumart */
WPS_TOKEN_ALBUMART_DISPLAY,
WPS_TOKEN_ALBUMART_FOUND,
#endif
/* Metadata */
WPS_TOKEN_METADATA_ARTIST,
WPS_TOKEN_METADATA_COMPOSER,
WPS_TOKEN_METADATA_ALBUM_ARTIST,
WPS_TOKEN_METADATA_GROUPING,
WPS_TOKEN_METADATA_ALBUM,
WPS_TOKEN_METADATA_GENRE,
WPS_TOKEN_METADATA_DISC_NUMBER,
WPS_TOKEN_METADATA_TRACK_NUMBER,
WPS_TOKEN_METADATA_TRACK_TITLE,
WPS_TOKEN_METADATA_VERSION,
WPS_TOKEN_METADATA_YEAR,
WPS_TOKEN_METADATA_COMMENT,
/* Mode */
WPS_TOKEN_REPEAT_MODE,
WPS_TOKEN_PLAYBACK_STATUS,
WPS_TOKEN_MAIN_HOLD,
#ifdef HAS_REMOTE_BUTTON_HOLD
WPS_TOKEN_REMOTE_HOLD,
#endif
/* Progressbar */
WPS_TOKEN_PROGRESSBAR,
#ifdef HAVE_LCD_CHARCELLS
WPS_TOKEN_PLAYER_PROGRESSBAR,
#endif
#ifdef HAVE_LCD_BITMAP
/* Peakmeter */
WPS_TOKEN_PEAKMETER,
#endif
/* Volume level */
WPS_TOKEN_VOLUME,
/* Current track */
WPS_TOKEN_TRACK_ELAPSED_PERCENT,
WPS_TOKEN_TRACK_TIME_ELAPSED,
WPS_TOKEN_TRACK_TIME_REMAINING,
WPS_TOKEN_TRACK_LENGTH,
/* Playlist */
WPS_TOKEN_PLAYLIST_ENTRIES,
WPS_TOKEN_PLAYLIST_NAME,
WPS_TOKEN_PLAYLIST_POSITION,
WPS_TOKEN_PLAYLIST_SHUFFLE,
#if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
/* Virtual LED */
WPS_TOKEN_VLED_HDD,
#endif
/* Viewport display */
WPS_VIEWPORT_ENABLE,
/* buttons */
WPS_TOKEN_BUTTON_VOLUME,
WPS_TOKEN_LASTTOUCH,
/* Setting option */
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 */ /* Description of a subline on the WPS */
struct wps_subline { struct wps_subline {
@ -406,15 +227,11 @@ struct touchregion {
struct wps_data struct wps_data
{ {
#ifdef HAVE_LCD_BITMAP #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 wps_sb_tag;
bool show_sb_on_wps; bool show_sb_on_wps;
struct progressbar progressbar[MAX_PROGRESSBARS]; struct skin_token_list *images;
short progressbar_count; struct skin_token_list *progressbars;
bool peak_meter_enabled; bool peak_meter_enabled;
@ -465,9 +282,7 @@ struct wps_data
int num_tokens; int num_tokens;
struct wps_token tokens[WPS_MAX_TOKENS]; struct wps_token tokens[WPS_MAX_TOKENS];
char string_buffer[STRING_BUFFER_SIZE]; struct skin_token_list *strings;
char *strings[WPS_MAX_STRINGS];
int num_strings;
bool wps_loaded; bool wps_loaded;
@ -533,4 +348,8 @@ const char *get_token_value(struct gui_wps *gwps,
char *buf, int buf_size, char *buf, int buf_size,
int *intval); int *intval);
struct gui_img* find_image(int n, struct wps_data *data);
#endif #endif

View file

@ -70,6 +70,7 @@
#include "radio.h" #include "radio.h"
#endif #endif
#include "wps.h" #include "wps.h"
#include "skin_engine/skin_engine.h"
#if CONFIG_CODEC == MAS3507D #if CONFIG_CODEC == MAS3507D
void dac_line_in(bool enable); void dac_line_in(bool enable);
@ -818,6 +819,8 @@ void settings_apply(bool read_disk)
if (read_disk) if (read_disk)
{ {
/* re-initialize the skin buffer before we start reloading skins */
skin_buffer_init();
#ifdef HAVE_LCD_BITMAP #ifdef HAVE_LCD_BITMAP
/* fonts need to be loaded before the WPS */ /* fonts need to be loaded before the WPS */