summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apps/SOURCES3
-rw-r--r--apps/cuesheet.c14
-rw-r--r--apps/gui/skin_engine/skin_backdrops.c4
-rw-r--r--apps/gui/skin_engine/skin_buffer.c170
-rw-r--r--apps/gui/skin_engine/skin_buffer.h64
-rw-r--r--apps/gui/skin_engine/skin_display.c728
-rw-r--r--apps/gui/skin_engine/skin_display.h59
-rw-r--r--apps/gui/skin_engine/skin_engine.h33
-rw-r--r--apps/gui/skin_engine/skin_fonts.c2
-rw-r--r--apps/gui/skin_engine/skin_fonts.h1
-rw-r--r--apps/gui/skin_engine/skin_parser.c2057
-rw-r--r--apps/gui/skin_engine/skin_render.c614
-rw-r--r--apps/gui/skin_engine/skin_tokens.c279
-rw-r--r--apps/gui/skin_engine/skin_tokens.h238
-rw-r--r--apps/gui/skin_engine/wps_debug.c1
-rw-r--r--apps/gui/skin_engine/wps_internals.h102
-rw-r--r--apps/gui/statusbar-skinned.c103
-rw-r--r--apps/gui/theme_settings.c12
-rw-r--r--apps/gui/viewport.c84
-rw-r--r--apps/gui/viewport.h21
-rw-r--r--apps/gui/wps.c16
-rw-r--r--apps/main.c2
-rw-r--r--apps/menus/main_menu.c2
-rw-r--r--apps/misc.c135
-rw-r--r--apps/misc.h11
-rw-r--r--apps/radio/radio.c4
-rw-r--r--apps/recorder/albumart.h4
-rw-r--r--apps/settings.h1
-rw-r--r--lib/skin_parser/SOURCES2
-rw-r--r--lib/skin_parser/skin_buffer.c38
-rw-r--r--lib/skin_parser/skin_buffer.h6
-rw-r--r--lib/skin_parser/skin_debug.c40
-rw-r--r--lib/skin_parser/skin_debug.h9
-rw-r--r--lib/skin_parser/skin_parser.c169
-rw-r--r--lib/skin_parser/skin_parser.h15
-rw-r--r--lib/skin_parser/skin_scan.c8
-rw-r--r--lib/skin_parser/skin_scan.h1
-rw-r--r--lib/skin_parser/tag_table.c325
-rw-r--r--lib/skin_parser/tag_table.h21
-rw-r--r--tools/checkwps/SOURCES1
-rw-r--r--tools/checkwps/checkwps.c15
-rw-r--r--tools/checkwps/checkwps.make4
-rw-r--r--tools/root.make4
-rw-r--r--utils/newparser/skin_render.c5
44 files changed, 2103 insertions, 3324 deletions
diff --git a/apps/SOURCES b/apps/SOURCES
index 181c780fb6..d15ba5bf6a 100644
--- a/apps/SOURCES
+++ b/apps/SOURCES
@@ -94,13 +94,12 @@ gui/yesno.c
gui/viewport.c
gui/skin_engine/skin_backdrops.c
-gui/skin_engine/skin_buffer.c
-gui/skin_engine/wps_debug.c
gui/skin_engine/skin_display.c
#ifdef HAVE_LCD_BITMAP
gui/skin_engine/skin_fonts.c
#endif
gui/skin_engine/skin_parser.c
+gui/skin_engine/skin_render.c
gui/skin_engine/skin_tokens.c
#ifdef HAVE_TOUCHSCREEN
gui/skin_engine/skin_touchsupport.c
diff --git a/apps/cuesheet.c b/apps/cuesheet.c
index cadb2ab8f6..a262b12d73 100644
--- a/apps/cuesheet.c
+++ b/apps/cuesheet.c
@@ -363,20 +363,22 @@ const char *get_cuesheetid3_token(struct wps_token *token, struct mp3entry *id3,
}
switch (token->type)
{
- case WPS_TOKEN_METADATA_ARTIST:
+ case SKIN_TOKEN_METADATA_ARTIST:
return *track->performer ? track->performer : NULL;
- case WPS_TOKEN_METADATA_COMPOSER:
+ case SKIN_TOKEN_METADATA_COMPOSER:
return *track->songwriter ? track->songwriter : NULL;
- case WPS_TOKEN_METADATA_ALBUM:
+ case SKIN_TOKEN_METADATA_ALBUM:
return *cue->title ? cue->title : NULL;
- case WPS_TOKEN_METADATA_ALBUM_ARTIST:
+ case SKIN_TOKEN_METADATA_ALBUM_ARTIST:
return *cue->performer ? cue->performer : NULL;
- case WPS_TOKEN_METADATA_TRACK_TITLE:
+ case SKIN_TOKEN_METADATA_TRACK_TITLE:
return *track->title ? track->title : NULL;
- case WPS_TOKEN_METADATA_TRACK_NUMBER:
+ case SKIN_TOKEN_METADATA_TRACK_NUMBER:
snprintf(buf, buf_size, "%d/%d",
cue->curr_track_idx+offset_tracks+1, cue->track_count);
return buf;
+ default:
+ return NULL;
}
return NULL;
}
diff --git a/apps/gui/skin_engine/skin_backdrops.c b/apps/gui/skin_engine/skin_backdrops.c
index a32bfbe589..4288e0a7b4 100644
--- a/apps/gui/skin_engine/skin_backdrops.c
+++ b/apps/gui/skin_engine/skin_backdrops.c
@@ -24,9 +24,9 @@
#include <stdlib.h>
#include "string-extra.h"
#include "settings.h"
-#include "skin_buffer.h"
#include "wps_internals.h"
#include "skin_engine.h"
+#include "skin_buffer.h"
#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
@@ -100,7 +100,7 @@ char* skin_backdrop_load(char* backdrop, char *bmpdir, enum screen_type screen)
if (!bdrop)
return NULL; /* too many backdrops loaded */
- bdrop->buffer = skin_buffer_alloc(buf_size);
+ bdrop->buffer = (char*)skin_buffer_alloc(buf_size);
if (!bdrop->buffer)
return NULL;
loaded = screens[screen].backdrop_load(filename, bdrop->buffer);
diff --git a/apps/gui/skin_engine/skin_buffer.c b/apps/gui/skin_engine/skin_buffer.c
deleted file mode 100644
index d503b83e42..0000000000
--- a/apps/gui/skin_engine/skin_buffer.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * 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"
-#include "skin_engine.h"
-#include "wps_internals.h"
-#include "skin_tokens.h"
-#include "skin_buffer.h"
-#include "skin_fonts.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
- *
- *
- * MAIN_ and REMOTE_BUFFER are just for reasonable size calibration,
- * both screens can use the whole buffer as they need; it's not split
- * between screens
- *
- * Buffer can be allocated from either "end" of the global buffer.
- * items with unknown sizes get allocated from the start (0->) (data)
- * items with known sizes get allocated from the end (<-buf_size) (tokens)
- * After loading 2 skins the buffer will look like this:
- * |tokens skin1|images skin1|tokens s2|images s2|---SPACE---|data skin2|data skin1|
- * Make sure to never start allocating from the beginning before letting us know
- * how much was used. and RESPECT THE buf_free RETURN VALUES!
- *
- */
-
-
-#ifdef HAVE_LCD_BITMAP
-#define MAIN_BUFFER ((2*LCD_HEIGHT*LCD_WIDTH*LCD_DEPTH/8) \
- + (SKINNABLE_SCREENS_COUNT * LCD_BACKDROP_BYTES))
-
-#if (NB_SCREENS > 1)
-#define REMOTE_BUFFER (2*(LCD_REMOTE_HEIGHT*LCD_REMOTE_WIDTH*LCD_REMOTE_DEPTH/8) \
- + (SKINNABLE_SCREENS_COUNT * REMOTE_LCD_BACKDROP_BYTES))
-#else
-#define REMOTE_BUFFER 0
-#endif
-
-
-#define SKIN_BUFFER_SIZE (MAIN_BUFFER + REMOTE_BUFFER + SKIN_FONT_SIZE) + \
- (WPS_MAX_TOKENS * sizeof(struct wps_token))
-#endif
-
-#ifdef HAVE_LCD_CHARCELLS
-#define SKIN_BUFFER_SIZE (LCD_HEIGHT * LCD_WIDTH) * 64 + \
- (WPS_MAX_TOKENS * sizeof(struct wps_token))
-#endif
-
-static unsigned char buffer[SKIN_BUFFER_SIZE];
-static unsigned char *buffer_front = NULL; /* start of the free space,
- increases with allocation*/
-static unsigned char *buffer_back = NULL; /* end of the free space
- decreases with allocation */
-static size_t buf_size = SKIN_BUFFER_SIZE;
-
-void skin_buffer_init(void)
-{
-#if 0 /* this will go in again later probably */
- if (buffer == NULL)
- {
- buf_size = SKIN_BUFFER_SIZE;/* global_settings.skin_buf_size */
-
- buffer = buffer_alloc(buf_size);
- buffer_front = buffer;
- buffer_back = bufer + buf_size;
- }
- else
-#endif
- {
- /* reset the buffer.... */
- buffer_front = buffer;
- buffer_back = buffer + buf_size;
- }
-}
-
-/* get the number of bytes currently being used */
-size_t skin_buffer_usage(void)
-{
- return buf_size - (buffer_back-buffer_front);
-}
-
-size_t skin_buffer_freespace(void)
-{
- return buffer_back-buffer_front;
-}
-
-/* Allocate size bytes from the buffer
- * allocates from the back end (data end)
- */
-void* skin_buffer_alloc(size_t size)
-{
- if (skin_buffer_freespace() <= size)
- {
- return NULL;
- }
- buffer_back -= size;
- /* 32-bit aligned */
- buffer_back = (void *)(((unsigned long)buffer_back) & ~3);
-
- memset(buffer_back, 0, size);
- return buffer_back;
-}
-
-/* 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
- *
- * This is from the start of the buffer, it is YOUR responsility to make
- * sure you dont ever use more then *freespace, and bear in mind this will only
- * be valid untill skin_buffer_alloc() is next called...
- * so call skin_buffer_increment() and skin_buffer_freespace() regularly
- */
-void* skin_buffer_grab(size_t *freespace)
-{
- *freespace = buf_size - skin_buffer_usage();
- return buffer_front;
-}
-
-/* Use after skin_buffer_grab() to specify how much buffer was used */
-void skin_buffer_increment(size_t used, bool align)
-{
- buffer_front += used;
- if (align)
- {
- /* 32-bit aligned */
- buffer_front = (void *)(((unsigned long)buffer_front + 3) & ~3);
- }
-}
-
-/* free previously skin_buffer_increment()'ed space. This just moves the pointer
- * back 'used' bytes so make sure you actually want to do this */
-void skin_buffer_free_from_front(size_t used)
-{
- buffer_front -= used;
- /* 32-bit aligned */
- buffer_front = (void *)(((unsigned long)buffer_front + 3) & ~3);
-}
-
-
diff --git a/apps/gui/skin_engine/skin_buffer.h b/apps/gui/skin_engine/skin_buffer.h
deleted file mode 100644
index 521631f03b..0000000000
--- a/apps/gui/skin_engine/skin_buffer.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * 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);
-size_t skin_buffer_freespace(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
- *
- * This is from the start of the buffer, it is YOUR responsility to make
- * sure you dont ever use more then *freespace, and bear in mind this will only
- * be valid untill skin_buffer_alloc() is next called...
- * so call skin_buffer_increment() and skin_buffer_freespace() regularly
- */
-void* skin_buffer_grab(size_t *freespace);
-
-/* Use after skin_buffer_grab() to specify how much buffer was used.
- * align should always be true unless there is a possibility that you will need
- * more space *immediatly* after the previous allocation. (i.e in an array).
- * NEVER leave the buffer unaligned */
-void skin_buffer_increment(size_t used, bool align);
-
-/* free previously skin_buffer_increment()'ed space. This just moves the pointer
- * back 'used' bytes so make sure you actually want to do this */
-void skin_buffer_free_from_front(size_t used);
-
-#endif /* _SKIN_BUFFER_H_ */
diff --git a/apps/gui/skin_engine/skin_display.c b/apps/gui/skin_engine/skin_display.c
index 3d3a654c30..559ae8519f 100644
--- a/apps/gui/skin_engine/skin_display.c
+++ b/apps/gui/skin_engine/skin_display.c
@@ -69,25 +69,22 @@
#include "skin_engine.h"
#include "statusbar-skinned.h"
-static bool skin_redraw(struct gui_wps *gwps, unsigned refresh_mode);
+void skin_render(struct gui_wps *gwps, unsigned refresh_mode);
/* update a skinned screen, update_type is WPS_REFRESH_* values.
* Usually it should only be WPS_REFRESH_NON_STATIC
* A full update will be done if required (state.do_full_update == true)
*/
-bool skin_update(struct gui_wps *gwps, unsigned int update_type)
+void skin_update(struct gui_wps *gwps, unsigned int update_type)
{
- bool retval;
- /* This maybe shouldnt be here, but while the skin is only used to
- * display the music screen this is better than whereever we are being
- * called from. This is also safe for skined screen which dont use the id3 */
+ /* This maybe shouldnt be here,
+ * This is also safe for skined screen which dont use the id3 */
struct mp3entry *id3 = gwps->state->id3;
bool cuesheet_update = (id3 != NULL ? cuesheet_subtrack_changed(id3) : false);
gwps->sync_data->do_full_update |= cuesheet_update;
- retval = skin_redraw(gwps, gwps->sync_data->do_full_update ?
- WPS_REFRESH_ALL : update_type);
- return retval;
+ skin_render(gwps, gwps->sync_data->do_full_update ?
+ SKIN_REFRESH_ALL : update_type);
}
#ifdef HAVE_LCD_BITMAP
@@ -124,8 +121,7 @@ void skin_statusbar_changed(struct gui_wps *skin)
}
}
-static void draw_progressbar(struct gui_wps *gwps,
- struct progressbar *pb)
+void draw_progressbar(struct gui_wps *gwps, int line, struct progressbar *pb)
{
struct screen *display = gwps->display;
struct viewport *vp = pb->vp;
@@ -143,17 +139,17 @@ static void draw_progressbar(struct gui_wps *gwps,
/* center the pb in the line, but only if the line is higher than the pb */
int center = (line_height-height)/2;
/* if Y was not set calculate by font height,Y is -line_number-1 */
- y = (-y -1)*line_height + (0 > center ? 0 : center);
+ y = line*line_height + (0 > center ? 0 : center);
}
- if (pb->type == WPS_TOKEN_VOLUMEBAR)
+ if (pb->type == SKIN_TOKEN_VOLUMEBAR)
{
int minvol = sound_min(SOUND_VOLUME);
int maxvol = sound_max(SOUND_VOLUME);
length = maxvol-minvol;
elapsed = global_settings.volume-minvol;
}
- else if (pb->type == WPS_TOKEN_BATTERY_PERCENTBAR)
+ else if (pb->type == SKIN_TOKEN_BATTERY_PERCENTBAR)
{
length = 100;
elapsed = battery_level();
@@ -185,7 +181,7 @@ static void draw_progressbar(struct gui_wps *gwps,
gui_scrollbar_draw(display, pb->x, y, pb->width, height,
length, 0, elapsed, HORIZONTAL);
- if (pb->type == WPS_TOKEN_PROGRESSBAR)
+ if (pb->type == SKIN_TOKEN_PROGRESSBAR)
{
if (id3 && id3->length)
{
@@ -208,8 +204,7 @@ static void draw_progressbar(struct gui_wps *gwps,
}
}
-static void draw_playlist_viewer_list(struct gui_wps *gwps,
- struct playlistviewer *viewer)
+void draw_playlist_viewer_list(struct gui_wps *gwps, struct playlistviewer *viewer)
{
struct wps_state *state = gwps->state;
int lines = viewport_get_nb_lines(viewer->vp);
@@ -217,8 +212,9 @@ static void draw_playlist_viewer_list(struct gui_wps *gwps,
int cur_pos, max;
int start_item;
int i;
- struct wps_token token;
- int x, length, alignment = WPS_TOKEN_ALIGN_LEFT;
+ bool scroll = false;
+ struct wps_token *token;
+ int x, length, alignment = SKIN_TOKEN_ALIGN_LEFT;
struct mp3entry *pid3;
char buf[MAX_PATH*2], tempbuf[MAX_PATH];
@@ -281,51 +277,58 @@ static void draw_playlist_viewer_list(struct gui_wps *gwps,
}
line = pid3 ? TRACK_HAS_INFO : TRACK_HAS_NO_INFO;
}
- int j = 0, cur_string = 0;
unsigned int line_len = 0;
+ if (viewer->lines[line]->children_count == 0)
+ return;
+ struct skin_element *element = viewer->lines[line]->children[0];
buf[0] = '\0';
- while (j < viewer->lines[line].count && line_len < sizeof(buf))
+ while (element && line_len < sizeof(buf))
{
const char *out = NULL;
- token.type = viewer->lines[line].tokens[j];
- token.value.i = 0;
- token.next = false;
- out = get_id3_token(&token, pid3, tempbuf, sizeof(tempbuf), -1, NULL);
+ if (element->type == TEXT)
+ {
+ line_len = strlcat(buf, (char*)element->data, sizeof(buf));
+ element = element->next;
+ continue;
+ }
+ if (element->type != TAG)
+ {
+ element = element->next;
+ continue;
+ }
+ if (element->tag->type == SKIN_TOKEN_SUBLINE_SCROLL)
+ scroll = true;
+ token = (struct wps_token*)element->data;
+ out = get_id3_token(token, pid3, tempbuf, sizeof(tempbuf), -1, NULL);
#if CONFIG_TUNER
if (!out)
- out = get_radio_token(&token, i-cur_pos,
+ out = get_radio_token(token, i-cur_pos,
tempbuf, sizeof(tempbuf), -1, NULL);
#endif
if (out)
{
line_len = strlcat(buf, out, sizeof(buf));
- j++;
+ element = element->next;
continue;
}
- switch (viewer->lines[line].tokens[j])
+ switch (token->type)
{
- case WPS_TOKEN_ALIGN_CENTER:
- case WPS_TOKEN_ALIGN_LEFT:
- case WPS_TOKEN_ALIGN_LEFT_RTL:
- case WPS_TOKEN_ALIGN_RIGHT:
- case WPS_TOKEN_ALIGN_RIGHT_RTL:
- alignment = viewer->lines[line].tokens[j];
+ case SKIN_TOKEN_ALIGN_CENTER:
+ case SKIN_TOKEN_ALIGN_LEFT:
+ case SKIN_TOKEN_ALIGN_LEFT_RTL:
+ case SKIN_TOKEN_ALIGN_RIGHT:
+ case SKIN_TOKEN_ALIGN_RIGHT_RTL:
+ alignment = token->type;
tempbuf[0] = '\0';
break;
- case WPS_TOKEN_STRING:
- case WPS_TOKEN_CHARACTER:
- snprintf(tempbuf, sizeof(tempbuf), "%s",
- viewer->lines[line].strings[cur_string]);
- cur_string++;
- break;
- case WPS_TOKEN_PLAYLIST_POSITION:
+ case SKIN_TOKEN_PLAYLIST_POSITION:
snprintf(tempbuf, sizeof(tempbuf), "%d", i);
break;
- case WPS_TOKEN_FILE_NAME:
+ case SKIN_TOKEN_FILE_NAME:
get_dir(tempbuf, sizeof(tempbuf), filename, 0);
break;
- case WPS_TOKEN_FILE_PATH:
+ case SKIN_TOKEN_FILE_PATH:
snprintf(tempbuf, sizeof(tempbuf), "%s", filename);
break;
default:
@@ -336,12 +339,12 @@ static void draw_playlist_viewer_list(struct gui_wps *gwps,
{
line_len = strlcat(buf, tempbuf, sizeof(buf));
}
- j++;
+ element = element->next;
}
int vpwidth = viewer->vp->width;
length = gwps->display->getstringsize(buf, NULL, NULL);
- if (viewer->lines[line].scroll && length >= vpwidth)
+ if (scroll && length >= vpwidth)
{
gwps->display->puts_scroll(0, (i-start_item), buf );
}
@@ -353,25 +356,25 @@ static void draw_playlist_viewer_list(struct gui_wps *gwps,
{
switch (alignment)
{
- case WPS_TOKEN_ALIGN_CENTER:
+ case SKIN_TOKEN_ALIGN_CENTER:
x = (vpwidth-length)/2;
break;
- case WPS_TOKEN_ALIGN_LEFT_RTL:
+ case SKIN_TOKEN_ALIGN_LEFT_RTL:
if (lang_is_rtl() && VP_IS_RTL(viewer->vp))
{
x = vpwidth - length;
break;
}
- case WPS_TOKEN_ALIGN_LEFT:
+ case SKIN_TOKEN_ALIGN_LEFT:
x = 0;
break;
- case WPS_TOKEN_ALIGN_RIGHT_RTL:
+ case SKIN_TOKEN_ALIGN_RIGHT_RTL:
if (lang_is_rtl() && VP_IS_RTL(viewer->vp))
{
x = 0;
break;
}
- case WPS_TOKEN_ALIGN_RIGHT:
+ case SKIN_TOKEN_ALIGN_RIGHT:
x = vpwidth - length;
break;
default:
@@ -386,7 +389,7 @@ static void draw_playlist_viewer_list(struct gui_wps *gwps,
/* clears the area where the image was shown */
-static void clear_image_pos(struct gui_wps *gwps, struct gui_img *img)
+void clear_image_pos(struct gui_wps *gwps, struct gui_img *img)
{
if(!gwps)
return;
@@ -395,7 +398,7 @@ static void clear_image_pos(struct gui_wps *gwps, struct gui_img *img)
gwps->display->set_drawmode(DRMODE_SOLID);
}
-static void wps_draw_image(struct gui_wps *gwps, struct gui_img *img, int subimage)
+void wps_draw_image(struct gui_wps *gwps, struct gui_img *img, int subimage)
{
struct screen *display = gwps->display;
if(img->always_display)
@@ -423,7 +426,8 @@ static void wps_draw_image(struct gui_wps *gwps, struct gui_img *img, int subima
#endif
}
-static void wps_display_images(struct gui_wps *gwps, struct viewport* vp)
+
+void wps_display_images(struct gui_wps *gwps, struct viewport* vp)
{
if(!gwps || !gwps->data || !gwps->display)
return;
@@ -451,18 +455,10 @@ static void wps_display_images(struct gui_wps *gwps, struct viewport* vp)
#ifdef HAVE_ALBUMART
/* now draw the AA */
if (data->albumart && data->albumart->vp == vp
- && data->albumart->draw)
+ && data->albumart->draw_handle >= 0)
{
- int handle = playback_current_aa_hid(data->playback_aa_slot);
-#if CONFIG_TUNER
- if (in_radio_screen() || (get_radio_status() != FMRADIO_OFF))
- {
- struct dim dim = {data->albumart->width, data->albumart->height};
- handle = radio_get_art_hid(&dim);
- }
-#endif
- draw_album_art(gwps, handle, false);
- data->albumart->draw = false;
+ draw_album_art(gwps, data->albumart->draw_handle, false);
+ data->albumart->draw_handle = -1;
}
#endif
@@ -471,7 +467,7 @@ static void wps_display_images(struct gui_wps *gwps, struct viewport* vp)
#else /* HAVE_LCD_CHARCELL */
-static bool draw_player_progress(struct gui_wps *gwps)
+bool draw_player_progress(struct gui_wps *gwps)
{
struct wps_state *state = gwps->state;
struct screen *display = gwps->display;
@@ -508,7 +504,7 @@ static bool draw_player_progress(struct gui_wps *gwps)
return true;
}
-static void draw_player_fullbar(struct gui_wps *gwps, char* buf, int buf_size)
+void draw_player_fullbar(struct gui_wps *gwps, char* buf, int buf_size)
{
static const unsigned char numbers[10][4] = {
{0x0e, 0x0a, 0x0a, 0x0e}, /* 0 */
@@ -613,44 +609,25 @@ static void draw_player_fullbar(struct gui_wps *gwps, char* buf, int buf_size)
#endif /* HAVE_LCD_CHARCELL */
-/* Return the index to the end token for the conditional token at index.
- The conditional token can be either a start token or a separator
- (i.e. option) token.
-*/
-static int find_conditional_end(struct wps_data *data, int index)
-{
- int ret = index;
- while (data->tokens[ret].type != WPS_TOKEN_CONDITIONAL_END)
- ret = data->tokens[ret].value.i;
-
- /* ret now is the index to the end token for the conditional. */
- return ret;
-}
-
/* Evaluate the conditional that is at *token_index and return whether a skip
has ocurred. *token_index is updated with the new position.
*/
-static bool evaluate_conditional(struct gui_wps *gwps, int *token_index)
+int evaluate_conditional(struct gui_wps *gwps, struct conditional *conditional, int num_options)
{
if (!gwps)
return false;
- struct wps_data *data = gwps->data;
-
- int i, cond_end;
- int cond_index = *token_index;
char result[128];
const char *value;
- unsigned char num_options = data->tokens[cond_index].value.i & 0xFF;
- unsigned char prev_val = (data->tokens[cond_index].value.i & 0xFF00) >> 8;
- /* treat ?xx<true> constructs as if they had 2 options. */
+ /* treat ?xx<true> constructs as if they had 2 options.
+ * (i.e ?xx<true|false>) */
if (num_options < 2)
num_options = 2;
int intval = num_options;
/* get_token_value needs to know the number of options in the enum */
- value = get_token_value(gwps, &data->tokens[cond_index + 1],
+ value = get_token_value(gwps, conditional->token,
result, sizeof(result), &intval);
/* intval is now the number of the enum option we want to read,
@@ -659,334 +636,18 @@ static bool evaluate_conditional(struct gui_wps *gwps, int *token_index)
intval = (value && *value) ? 1 : num_options;
else if (intval > num_options || intval < 1)
intval = num_options;
-
- data->tokens[cond_index].value.i = (intval << 8) + num_options;
-
- /* skip to the appropriate enum case */
- int next = cond_index + 2;
- for (i = 1; i < intval; i++)
- {
- next = data->tokens[next].value.i;
- }
- *token_index = next;
-
- if (prev_val == intval)
- {
- /* Same conditional case as previously. Return without clearing the
- pictures */
- return false;
- }
-
- cond_end = find_conditional_end(data, cond_index + 2);
- for (i = cond_index + 3; i < cond_end; i++)
- {
-#ifdef HAVE_LCD_BITMAP
- /* clear all pictures in the conditional and nested ones */
- if (data->tokens[i].type == WPS_TOKEN_IMAGE_PRELOAD_DISPLAY)
- clear_image_pos(gwps, find_image(data->tokens[i].value.i&0xFF, data));
- else if (data->tokens[i].type == WPS_TOKEN_VOLUMEBAR ||
- data->tokens[i].type == WPS_TOKEN_PROGRESSBAR ||
- data->tokens[i].type == WPS_TOKEN_BATTERY_PERCENTBAR )
- {
- struct progressbar *bar = (struct progressbar*)data->tokens[i].value.data;
- bar->draw = false;
- }
- else if (data->tokens[i].type == WPS_TOKEN_PEAKMETER)
- {
- data->peak_meter_enabled = false;
- }
-#endif
-#ifdef HAVE_ALBUMART
- if (data->albumart && data->tokens[i].type == WPS_TOKEN_ALBUMART_DISPLAY)
- {
- draw_album_art(gwps,
- playback_current_aa_hid(data->playback_aa_slot), true);
- data->albumart->draw = false;
- }
-#endif
- }
-
- return true;
-}
-
-
-/* Read a (sub)line to the given alignment format buffer.
- linebuf is the buffer where the data is actually stored.
- align is the alignment format that'll be used to display the text.
- The return value indicates whether the line needs to be updated.
-*/
-static bool get_line(struct gui_wps *gwps,
- struct skin_subline *subline,
- struct align_pos *align,
- char *linebuf,
- int linebuf_size,
- unsigned refresh_mode)
-{
- struct wps_data *data = gwps->data;
-
- char temp_buf[128];
- char *buf = linebuf; /* will always point to the writing position */
- char *linebuf_end = linebuf + linebuf_size - 1;
- bool update = false;
- int i;
- (void)refresh_mode; /* silence warning on charcell */
-
- /* alignment-related variables */
- int cur_align;
- char* cur_align_start;
- cur_align_start = buf;
- cur_align = WPS_ALIGN_LEFT;
- align->left = NULL;
- align->center = NULL;
- align->right = NULL;
- /* Process all tokens of the desired subline */
- for (i = subline->first_token_idx;
- i <= subline->last_token_idx; i++)
- {
- switch(data->tokens[i].type)
- {
- case WPS_TOKEN_CONDITIONAL:
- /* place ourselves in the right conditional case */
- update |= evaluate_conditional(gwps, &i);
- break;
-
- case WPS_TOKEN_CONDITIONAL_OPTION:
- /* we've finished in the curent conditional case,
- skip to the end of the conditional structure */
- i = find_conditional_end(data, i);
- break;
-#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
- case WPS_TOKEN_VIEWPORT_FGCOLOUR:
- {
- struct viewport_colour *col = data->tokens[i].value.data;
- col->vp->fg_pattern = col->colour;
- }
- break;
- case WPS_TOKEN_VIEWPORT_BGCOLOUR:
- {
- struct viewport_colour *col = data->tokens[i].value.data;
- col->vp->bg_pattern = col->colour;
- }
- break;
-#endif
-#ifdef HAVE_LCD_BITMAP
- case WPS_TOKEN_PEAKMETER:
- data->peak_meter_enabled = true;
- break;
- case WPS_TOKEN_VOLUMEBAR:
- case WPS_TOKEN_BATTERY_PERCENTBAR:
- case WPS_TOKEN_PROGRESSBAR:
- {
- struct progressbar *bar = (struct progressbar*)data->tokens[i].value.data;
- bar->draw = true;
- }
- break;
- case WPS_TOKEN_IMAGE_PRELOAD_DISPLAY:
- {
- char n = data->tokens[i].value.i & 0xFF;
- int subimage = data->tokens[i].value.i >> 8;
- struct gui_img *img = find_image(n, data);
-
- if (img && img->loaded)
- img->display = subimage;
- break;
- }
- case WPS_TOKEN_DRAW_INBUILTBAR:
- gui_statusbar_draw(&(statusbars.statusbars[gwps->display->screen_type]),
- refresh_mode == WPS_REFRESH_ALL,
- data->tokens[i].value.data);
- break;
-#endif
-
- case WPS_TOKEN_ALIGN_LEFT:
- case WPS_TOKEN_ALIGN_LEFT_RTL:
- case WPS_TOKEN_ALIGN_CENTER:
- case WPS_TOKEN_ALIGN_RIGHT:
- case WPS_TOKEN_ALIGN_RIGHT_RTL:
- /* remember where the current aligned text started */
- switch (cur_align)
- {
- case WPS_ALIGN_LEFT:
- align->left = cur_align_start;
- break;
-
- case WPS_ALIGN_CENTER:
- align->center = cur_align_start;
- break;
-
- case WPS_ALIGN_RIGHT:
- align->right = cur_align_start;
- break;
- }
- /* start a new alignment */
- switch (data->tokens[i].type)
- {
- case WPS_TOKEN_ALIGN_LEFT:
- cur_align = WPS_ALIGN_LEFT;
- break;
- case WPS_TOKEN_ALIGN_LEFT_RTL:
- cur_align = lang_is_rtl() ? WPS_ALIGN_RIGHT :
- WPS_ALIGN_LEFT;
- break;
- case WPS_TOKEN_ALIGN_CENTER:
- cur_align = WPS_ALIGN_CENTER;
- break;
- case WPS_TOKEN_ALIGN_RIGHT:
- cur_align = WPS_ALIGN_RIGHT;
- break;
- case WPS_TOKEN_ALIGN_RIGHT_RTL:
- cur_align = lang_is_rtl() ? WPS_ALIGN_LEFT :
- WPS_ALIGN_RIGHT;
- break;
- default:
- break;
- }
- *buf++ = 0;
- cur_align_start = buf;
- break;
- case WPS_VIEWPORT_ENABLE:
- {
- char label = data->tokens[i].value.i;
- char temp = VP_DRAW_HIDEABLE;
- /* viewports are allowed to share id's so find and enable
- * all of them */
- struct skin_token_list *list = data->viewports;
- while (list)
- {
- struct skin_viewport *vp =
- (struct skin_viewport *)list->token->value.data;
- if (vp->label == label)
- {
- if (vp->hidden_flags&VP_DRAW_WASHIDDEN)
- temp |= VP_DRAW_WASHIDDEN;
- vp->hidden_flags = temp;
- }
- list = list->next;
- }
- }
- break;
-#ifdef HAVE_LCD_BITMAP
- case WPS_TOKEN_UIVIEWPORT_ENABLE:
- sb_set_info_vp(gwps->display->screen_type,
- data->tokens[i].value.i|VP_INFO_LABEL);
- break;
- case WPS_VIEWPORT_CUSTOMLIST:
- draw_playlist_viewer_list(gwps, data->tokens[i].value.data);
- break;
-#endif
- default:
- {
- /* get the value of the tag and copy it to the buffer */
- const char *value = get_token_value(gwps, &data->tokens[i],
- temp_buf, sizeof(temp_buf), NULL);
- if (value)
- {
- update = true;
- while (*value && (buf < linebuf_end))
- *buf++ = *value++;
- }
- break;
- }
- }
- }
-
- /* close the current alignment */
- switch (cur_align)
- {
- case WPS_ALIGN_LEFT:
- align->left = cur_align_start;
- break;
-
- case WPS_ALIGN_CENTER:
- align->center = cur_align_start;
- break;
-
- case WPS_ALIGN_RIGHT:
- align->right = cur_align_start;
- break;
- }
-
- return update;
-}
-static void get_subline_timeout(struct gui_wps *gwps, struct skin_subline *subline)
-{
- struct wps_data *data = gwps->data;
- int i;
- subline->time_mult = DEFAULT_SUBLINE_TIME_MULTIPLIER;
-
- for (i = subline->first_token_idx;
- i <= subline->last_token_idx; i++)
- {
- switch(data->tokens[i].type)
- {
- case WPS_TOKEN_CONDITIONAL:
- /* place ourselves in the right conditional case */
- evaluate_conditional(gwps, &i);
- break;
-
- case WPS_TOKEN_CONDITIONAL_OPTION:
- /* we've finished in the curent conditional case,
- skip to the end of the conditional structure */
- i = find_conditional_end(data, i);
- break;
-
- case WPS_TOKEN_SUBLINE_TIMEOUT:
- subline->time_mult = data->tokens[i].value.i;
- break;
-
- default:
- break;
- }
- }
+
+ conditional->last_value = intval -1;
+ return intval -1;
}
-/* Calculates which subline should be displayed for the specified line
- Returns true iff the subline must be refreshed */
-static bool update_curr_subline(struct gui_wps *gwps, struct skin_line *line)
-{
- /* shortcut this whole thing if we need to reset the line completly */
- if (line->curr_subline == NULL)
- {
- line->subline_expire_time = current_tick;
- line->curr_subline = &line->sublines;
- if (!line->curr_subline->next)
- {
- line->subline_expire_time += 100*HZ;
- }
- else
- {
- get_subline_timeout(gwps, line->curr_subline);
- line->subline_expire_time += TIMEOUT_UNIT*line->curr_subline->time_mult;
- }
- return true;
- }
- /* if time to advance to next sub-line */
- if (TIME_AFTER(current_tick, line->subline_expire_time - 1))
- {
- /* if there is only one subline, there is no need to search for a new one */
- if (&line->sublines == line->curr_subline &&
- line->curr_subline->next == NULL)
- {
- line->subline_expire_time += 100 * HZ;
- return false;
- }
- if (line->curr_subline->next)
- line->curr_subline = line->curr_subline->next;
- else
- line->curr_subline = &line->sublines;
- get_subline_timeout(gwps, line->curr_subline);
- line->subline_expire_time = current_tick + TIMEOUT_UNIT*line->curr_subline->time_mult;
- return true;
- }
- return false;
-}
/* Display a line appropriately according to its alignment format.
format_align contains the text, separated between left, center and right.
line is the index of the line on the screen.
scroll indicates whether the line is a scrolling one or not.
*/
-static void write_line(struct screen *display,
+void write_line(struct screen *display,
struct align_pos *format_align,
int line,
bool scroll)
@@ -1143,244 +804,30 @@ static void write_line(struct screen *display,
}
}
-static bool skin_redraw(struct gui_wps *gwps, unsigned refresh_mode)
+#ifdef HAVE_LCD_BITMAP
+void draw_peakmeters(struct gui_wps *gwps, int line_number,
+ struct viewport *viewport)
{
struct wps_data *data = gwps->data;
- struct screen *display = gwps->display;
-
- if (!data || !display || !gwps->state)
- return false;
-
- unsigned flags;
- char linebuf[MAX_PATH];
-
- struct align_pos align;
- align.left = NULL;
- align.center = NULL;
- align.right = NULL;
-
-
- struct skin_token_list *viewport_list;
-
- bool update_line, new_subline_refresh;
-
- /* reset to first subline if refresh all flag is set */
- if (refresh_mode == WPS_REFRESH_ALL)
+ if (!data->peak_meter_enabled)
{
- struct skin_line *line;
- struct skin_viewport *skin_viewport = find_viewport(VP_DEFAULT_LABEL, data);
-
- if (!(skin_viewport->hidden_flags & VP_NEVER_VISIBLE))
- {
- display->set_viewport(&skin_viewport->vp);
- display->clear_viewport();
- }
-
- for (viewport_list = data->viewports;
- viewport_list; viewport_list = viewport_list->next)
- {
- skin_viewport =
- (struct skin_viewport *)viewport_list->token->value.data;
- for(line = skin_viewport->lines; line; line = line->next)
- {
- line->curr_subline = NULL;
- }
- }
+ peak_meter_enable(false);
}
-
-#ifdef HAVE_LCD_CHARCELLS
- int i;
- for (i = 0; i < 8; i++)
- {
- if (data->wps_progress_pat[i] == 0)
- data->wps_progress_pat[i] = display->get_locked_pattern();
- }
-#endif
-
- /* disable any viewports which are conditionally displayed.
- * If we are only refreshing the peak meter then don't change the viewport
- * enabled flags as this will stop scrolling. viewports cant be
- * toggled in this refresh mode anyway (FS#10215)*/
- if (refresh_mode != WPS_REFRESH_PEAK_METER)
- {
- for (viewport_list = data->viewports;
- viewport_list; viewport_list = viewport_list->next)
- {
- struct skin_viewport *skin_viewport =
- (struct skin_viewport *)viewport_list->token->value.data;
- if (skin_viewport->hidden_flags&VP_NEVER_VISIBLE)
- {
- continue;
- }
- if (skin_viewport->hidden_flags&VP_DRAW_HIDEABLE)
- {
- if (skin_viewport->hidden_flags&VP_DRAW_HIDDEN)
- skin_viewport->hidden_flags |= VP_DRAW_WASHIDDEN;
- else
- skin_viewport->hidden_flags |= VP_DRAW_HIDDEN;
- }
- }
- }
- for (viewport_list = data->viewports;
- viewport_list; viewport_list = viewport_list->next)
+ else
{
- struct skin_viewport *skin_viewport =
- (struct skin_viewport *)viewport_list->token->value.data;
- unsigned vp_refresh_mode = refresh_mode;
-#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
- skin_viewport->vp.fg_pattern = skin_viewport->start_fgcolour;
- skin_viewport->vp.bg_pattern = skin_viewport->start_bgcolour;
-#endif
- display->set_viewport(&skin_viewport->vp);
-
- int hidden_vp = 0;
+ int h = font_get(viewport->font)->height;
+ int peak_meter_y = line_number * h;
-#ifdef HAVE_LCD_BITMAP
- /* Set images to not to be displayed */
- struct skin_token_list *imglist = data->images;
- while (imglist)
- {
- struct gui_img *img = (struct gui_img *)imglist->token->value.data;
- img->display = -1;
- imglist = imglist->next;
- }
-#endif
- /* dont redraw the viewport if its disabled */
- if (skin_viewport->hidden_flags&VP_NEVER_VISIBLE)
- { /* don't draw anything into this one */
- vp_refresh_mode = 0; hidden_vp = true;
- }
- else if ((skin_viewport->hidden_flags&VP_DRAW_HIDDEN))
- {
- if (!(skin_viewport->hidden_flags&VP_DRAW_WASHIDDEN))
- display->scroll_stop(&skin_viewport->vp);
- skin_viewport->hidden_flags |= VP_DRAW_WASHIDDEN;
- continue;
- }
- else if (((skin_viewport->hidden_flags&
- (VP_DRAW_WASHIDDEN|VP_DRAW_HIDEABLE))
- == (VP_DRAW_WASHIDDEN|VP_DRAW_HIDEABLE)))
- {
- vp_refresh_mode = WPS_REFRESH_ALL;
- skin_viewport->hidden_flags = VP_DRAW_HIDEABLE;
- }
-
- if (vp_refresh_mode == WPS_REFRESH_ALL)
- {
- display->clear_viewport();
+ /* The user might decide to have the peak meter in the last
+ line so that it is only displayed if no status bar is
+ visible. If so we neither want do draw nor enable the
+ peak meter. */
+ if (peak_meter_y + h <= viewport->y+viewport->height) {
+ peak_meter_enable(true);
+ peak_meter_screen(gwps->display, 0, peak_meter_y,
+ MIN(h, viewport->y+viewport->height - peak_meter_y));
}
-
- /* loop over the lines for this viewport */
- struct skin_line *line;
- /* %V() doesnt eat the \n which means the first line of text
- * is actually going to be one line down. so set line_count to -1
- * unless we are using the default viewport which doesnt have this problem */
- int line_count = skin_viewport->label==VP_DEFAULT_LABEL?0:-1;
-
- for (line = skin_viewport->lines; line; line = line->next, line_count++)
- {
- struct skin_subline *subline;
- memset(linebuf, 0, sizeof(linebuf));
- update_line = false;
-
- /* get current subline for the line */
- new_subline_refresh = update_curr_subline(gwps, line);
- subline = line->curr_subline;
- flags = line->curr_subline->line_type;
-
- if (vp_refresh_mode == WPS_REFRESH_ALL || (flags & vp_refresh_mode)
- || new_subline_refresh || hidden_vp)
- {
- /* get_line tells us if we need to update the line */
- update_line = get_line(gwps, subline, &align,
- linebuf, sizeof(linebuf), vp_refresh_mode);
- }
-#ifdef HAVE_LCD_BITMAP
- /* peakmeter */
- if (flags & vp_refresh_mode & WPS_REFRESH_PEAK_METER)
- {
- if (!data->peak_meter_enabled)
- {
- peak_meter_enable(false);
- }
- else
- {
- /* the peakmeter should be alone on its line */
- update_line = false;
-
- int h = font_get(skin_viewport->vp.font)->height;
- int peak_meter_y = line_count* 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
- visible. If so we neither want do draw nor enable the
- peak meter. */
- if (peak_meter_y + h <= skin_viewport->vp.y+skin_viewport->vp.height) {
- peak_meter_enable(true);
- peak_meter_screen(gwps->display, 0, peak_meter_y,
- MIN(h, skin_viewport->vp.y+skin_viewport->vp.height - peak_meter_y));
- }
- }
- }
-
-#else /* HAVE_LCD_CHARCELL */
-
- /* progressbar */
- if (flags & vp_refresh_mode & WPS_REFRESH_PLAYER_PROGRESS)
- {
- if (data->full_line_progressbar)
- draw_player_fullbar(gwps, linebuf, sizeof(linebuf));
- else
- draw_player_progress(gwps);
- }
-#endif
-
- if (line_count>= 0 && update_line && !hidden_vp &&
- /* conditionals clear the line which means if the %Vd is put into the default
- 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 */
- ((skin_viewport->label != VP_DEFAULT_LABEL && viewport_list->next) ||
- !viewport_list->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_count, true);
- }
- else
- write_line(display, &align, line_count, false);
- }
- }
-#ifdef HAVE_LCD_BITMAP
- /* progressbar */
- if (vp_refresh_mode & WPS_REFRESH_PLAYER_PROGRESS)
- {
- struct skin_token_list *bar = gwps->data->progressbars;
- while (bar)
- {
- struct progressbar *thisbar = (struct progressbar*)bar->token->value.data;
- if (thisbar->vp == &skin_viewport->vp && thisbar->draw)
- {
- draw_progressbar(gwps, thisbar);
- }
- bar = bar->next;
- }
- }
- /* Now display any images in this viewport */
- if (!hidden_vp)
- wps_display_images(gwps, &skin_viewport->vp);
-#endif
}
-
- /* Restore the default viewport */
- display->set_viewport(NULL);
-
- display->update();
-
- return true;
}
bool skin_has_sbs(enum screen_type screen, struct wps_data *data)
@@ -1396,6 +843,7 @@ bool skin_has_sbs(enum screen_type screen, struct wps_data *data)
#endif
return draw;
}
+#endif
/* do the button loop as often as required for the peak meters to update
* with a good refresh rate.
@@ -1434,7 +882,7 @@ int skin_wait_for_action(struct gui_wps *gwps, int context, int timeout)
FOR_NB_SCREENS(i)
{
if(gwps[i].data->peak_meter_enabled)
- skin_update(&gwps[i], WPS_REFRESH_PEAK_METER);
+ skin_update(&gwps[i], SKIN_REFRESH_PEAK_METER);
next_refresh += HZ / PEAK_METER_FPS;
}
}
diff --git a/apps/gui/skin_engine/skin_display.h b/apps/gui/skin_engine/skin_display.h
new file mode 100644
index 0000000000..81274a7391
--- /dev/null
+++ b/apps/gui/skin_engine/skin_display.h
@@ -0,0 +1,59 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2002-2007 Björn Stenberg
+ * Copyright (C) 2007-2008 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.
+ *
+ ****************************************************************************/
+#include "config.h"
+#include <stdio.h>
+#include "wps_internals.h"
+#include "skin_engine.h"
+#include "statusbar-skinned.h"
+
+#ifndef _SKIN_DISPLAY_H_
+#define _SKIN_DISPLAY_H_
+
+
+#ifdef HAVE_LCD_BITMAP
+void draw_progressbar(struct gui_wps *gwps, int line, struct progressbar *pb);
+void draw_playlist_viewer_list(struct gui_wps *gwps, struct playlistviewer *viewer);
+/* clears the area where the image was shown */
+void clear_image_pos(struct gui_wps *gwps, struct gui_img *img);
+void wps_draw_image(struct gui_wps *gwps, struct gui_img *img, int subimage);
+void wps_display_images(struct gui_wps *gwps, struct viewport* vp);
+#else
+bool draw_player_progress(struct gui_wps *gwps);
+void draw_player_fullbar(struct gui_wps *gwps, char* buf, int buf_size);
+#endif
+
+/* Evaluate the conditional that is at *token_index and return whether a skip
+ has ocurred. *token_index is updated with the new position.
+*/
+int evaluate_conditional(struct gui_wps *gwps, struct conditional *conditional, int num_options);
+/* Display a line appropriately according to its alignment format.
+ format_align contains the text, separated between left, center and right.
+ line is the index of the line on the screen.
+ scroll indicates whether the line is a scrolling one or not.
+*/
+void write_line(struct screen *display,
+ struct align_pos *format_align,
+ int line,
+ bool scroll);
+void draw_peakmeters(struct gui_wps *gwps, int line_number,
+ struct viewport *viewport);
+#endif
diff --git a/apps/gui/skin_engine/skin_engine.h b/apps/gui/skin_engine/skin_engine.h
index 69991ab587..9845d8ca8a 100644
--- a/apps/gui/skin_engine/skin_engine.h
+++ b/apps/gui/skin_engine/skin_engine.h
@@ -23,7 +23,10 @@
#ifndef _SKIN_ENGINE_H
#define _SKIN_ENGINE_H
-#include "skin_buffer.h"
+#ifndef PLUGIN
+
+#include "skin_fonts.h"
+#include "tag_table.h"
#include "wps_internals.h" /* TODO: remove this line.. shoudlnt be needed */
@@ -39,13 +42,37 @@ enum skinnable_screens {
};
+#ifdef HAVE_LCD_BITMAP
+#define MAIN_BUFFER ((2*LCD_HEIGHT*LCD_WIDTH*LCD_DEPTH/8) \
+ + (SKINNABLE_SCREENS_COUNT * LCD_BACKDROP_BYTES))
+
+#if (NB_SCREENS > 1)
+#define REMOTE_BUFFER (2*(LCD_REMOTE_HEIGHT*LCD_REMOTE_WIDTH*LCD_REMOTE_DEPTH/8) \
+ + (SKINNABLE_SCREENS_COUNT * REMOTE_LCD_BACKDROP_BYTES))
+#else
+#define REMOTE_BUFFER 0
+#endif
+
+
+#define SKIN_BUFFER_SIZE (MAIN_BUFFER + REMOTE_BUFFER + SKIN_FONT_SIZE) + \
+ (WPS_MAX_TOKENS * \
+ (sizeof(struct wps_token) + (sizeof(struct skin_element))))
+#endif
+
+#ifdef HAVE_LCD_CHARCELLS
+#define SKIN_BUFFER_SIZE (LCD_HEIGHT * LCD_WIDTH) * 64 + \
+ (WPS_MAX_TOKENS * \
+ (sizeof(struct wps_token) + (sizeof(struct skin_element))))
+#endif
+
+
#ifdef HAVE_TOUCHSCREEN
int skin_get_touchaction(struct wps_data *data, int* edge_offset);
void skin_disarm_touchregions(struct wps_data *data);
#endif
/* Do a update_type update of the skinned screen */
-bool skin_update(struct gui_wps *gwps, unsigned int update_type);
+void skin_update(struct gui_wps *gwps, unsigned int update_type);
/*
* setup up the skin-data from a format-buffer (isfile = false)
@@ -72,3 +99,5 @@ void skin_backdrop_init(void);
*/
int skin_wait_for_action(struct gui_wps *gwps, int context, int timeout);
#endif
+
+#endif
diff --git a/apps/gui/skin_engine/skin_fonts.c b/apps/gui/skin_engine/skin_fonts.c
index f446a9948b..92a6a22ccf 100644
--- a/apps/gui/skin_engine/skin_fonts.c
+++ b/apps/gui/skin_engine/skin_fonts.c
@@ -88,7 +88,7 @@ int skin_font_load(char* font_name)
pf = &font->font;
if (!font->buffer)
{
- pf->buffer_start = skin_buffer_alloc(SKIN_FONT_SIZE);
+ pf->buffer_start = (char*)skin_buffer_alloc(SKIN_FONT_SIZE);
if (!pf->buffer_start)
return -1;
font->buffer = pf->buffer_start;
diff --git a/apps/gui/skin_engine/skin_fonts.h b/apps/gui/skin_engine/skin_fonts.h
index 6e3634e740..2988b43415 100644
--- a/apps/gui/skin_engine/skin_fonts.h
+++ b/apps/gui/skin_engine/skin_fonts.h
@@ -27,7 +27,6 @@
#include "file.h"
#include "settings.h"
#include "font.h"
-#include "skin_buffer.h"
#ifndef _SKINFONTS_H_
#define _SKINFONTS_H_
diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c
index a62791e397..52e7e1155c 100644
--- a/apps/gui/skin_engine/skin_parser.c
+++ b/apps/gui/skin_engine/skin_parser.c
@@ -8,6 +8,7 @@
* $Id$
*
* Copyright (C) 2007 Nicolas Pennequin, Dan Everton, Matthias Mohr
+ * 2010 Jonathan Gordon
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -28,6 +29,10 @@
#include "plugin.h"
#include "viewport.h"
+#include "skin_buffer.h"
+#include "skin_parser.h"
+#include "tag_table.h"
+
#ifdef __PCTOOL__
#ifdef WPSEDITOR
#include "proxy.h"
@@ -71,377 +76,29 @@
#define WPS_ERROR_INVALID_PARAM -1
-/* which screen are we parsing for? */
-static enum screen_type curr_screen;
-
-/* level of current conditional.
- -1 means we're not in a conditional. */
-static int level = -1;
-
-/* index of the last WPS_TOKEN_CONDITIONAL_OPTION
- or WPS_TOKEN_CONDITIONAL_START in current level */
-static int lastcond[WPS_MAX_COND_LEVEL];
-
-/* index of the WPS_TOKEN_CONDITIONAL in current level */
-static int condindex[WPS_MAX_COND_LEVEL];
-
-/* number of condtional options in current level */
-static int numoptions[WPS_MAX_COND_LEVEL];
-
-/* line number, debug only */
-static int line_number;
-
-/* the current viewport */
-static struct skin_viewport *curr_vp;
-/* the current line, linked to the above viewport */
-static struct skin_line *curr_line;
-
-static int follow_lang_direction = 0;
-
-#if defined(DEBUG) || defined(SIMULATOR)
-/* debugging function */
-extern void print_debug_info(struct wps_data *data, int fail, int line);
-extern void debug_skin_usage(void);
-#endif
-
-/* Function for parsing of details for a token. At the moment the
- function is called, the token type has already been set. The
- function must fill in the details and possibly add more tokens
- to the token array. It should return the number of chars that
- has been consumed.
-
- wps_bufptr points to the char following the tag (i.e. where
- details begin).
- token is the pointer to the 'main' token being parsed
- */
-typedef int (*wps_tag_parse_func)(const char *wps_bufptr,
- struct wps_token *token, struct wps_data *wps_data);
-
-struct wps_tag {
- enum wps_token_type type;
- const char name[3];
- unsigned char refresh_type;
- const wps_tag_parse_func parse_func;
-};
-static int skip_end_of_line(const char *wps_bufptr);
-/* prototypes of all special parse functions : */
-static int parse_timeout(const char *wps_bufptr,
- struct wps_token *token, struct wps_data *wps_data);
-static int parse_progressbar(const char *wps_bufptr,
- struct wps_token *token, struct wps_data *wps_data);
-static int parse_dir_level(const char *wps_bufptr,
- struct wps_token *token, struct wps_data *wps_data);
-static int parse_setting_and_lang(const char *wps_bufptr,
- struct wps_token *token, struct wps_data *wps_data);
-
-
-static int parse_languagedirection(const char *wps_bufptr,
- struct wps_token *token, struct wps_data *wps_data)
-{
- (void)wps_bufptr;
- (void)token;
- (void)wps_data;
- follow_lang_direction = 2; /* 2 because it is decremented immediatly after
- this token is parsed, after the next token it
- will be 0 again. */
- return 0;
-}
-#ifdef HAVE_LCD_BITMAP
-static int parse_viewport_display(const char *wps_bufptr,
- struct wps_token *token, struct wps_data *wps_data);
-static int parse_playlistview(const char *wps_bufptr,
- struct wps_token *token, struct wps_data *wps_data);
-static int parse_viewport(const char *wps_bufptr,
- struct wps_token *token, struct wps_data *wps_data);
-static int parse_statusbar_enable(const char *wps_bufptr,
- struct wps_token *token, struct wps_data *wps_data);
-static int parse_statusbar_disable(const char *wps_bufptr,
- struct wps_token *token, struct wps_data *wps_data);
-static int parse_statusbar_inbuilt(const char *wps_bufptr,
- struct wps_token *token, struct wps_data *wps_data);
-static int parse_image_display(const char *wps_bufptr,
- struct wps_token *token, struct wps_data *wps_data);
-static int parse_image_load(const char *wps_bufptr,
- struct wps_token *token, struct wps_data *wps_data);
-static int parse_font_load(const char *wps_bufptr,
- struct wps_token *token, struct wps_data *wps_data);
-#endif /*HAVE_LCD_BITMAP */
-#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
-static int parse_viewportcolour(const char *wps_bufptr,
- struct wps_token *token, struct wps_data *wps_data);
-static int parse_image_special(const char *wps_bufptr,
- struct wps_token *token, struct wps_data *wps_data);
-#endif
-#ifdef HAVE_ALBUMART
-static int parse_albumart_load(const char *wps_bufptr,
- struct wps_token *token, struct wps_data *wps_data);
-static int parse_albumart_display(const char *wps_bufptr,
- struct wps_token *token, struct wps_data *wps_data);
-#endif /* HAVE_ALBUMART */
-#ifdef HAVE_TOUCHSCREEN
-static int parse_touchregion(const char *wps_bufptr,
- struct wps_token *token, struct wps_data *wps_data);
-#else
-static int fulline_tag_not_supported(const char *wps_bufptr,
- struct wps_token *token, struct wps_data *wps_data)
+static bool isdefault(struct skin_tag_parameter *param)
{
- (void)token; (void)wps_data;
- return skip_end_of_line(wps_bufptr);
+ return param->type == DEFAULT;
}
-#define parse_touchregion fulline_tag_not_supported
-#endif
-#ifdef CONFIG_RTC
-#define WPS_RTC_REFRESH WPS_REFRESH_DYNAMIC
-#else
-#define WPS_RTC_REFRESH WPS_REFRESH_STATIC
-#endif
-/* array of available tags - those with more characters have to go first
- (e.g. "xl" and "xd" before "x"). It needs to end with the unknown token. */
-static const struct wps_tag all_tags[] = {
-
- { WPS_TOKEN_ALIGN_CENTER, "ac", 0, NULL },
- { WPS_TOKEN_ALIGN_LEFT, "al", 0, NULL },
- { WPS_TOKEN_ALIGN_LEFT_RTL, "aL", 0, NULL },
- { WPS_TOKEN_ALIGN_RIGHT, "ar", 0, NULL },
- { WPS_TOKEN_ALIGN_RIGHT_RTL, "aR", 0, NULL },
- { WPS_NO_TOKEN, "ax", 0, parse_languagedirection },
-
- { WPS_TOKEN_BATTERY_PERCENT, "bl", WPS_REFRESH_DYNAMIC, parse_progressbar },
- { WPS_TOKEN_BATTERY_VOLTS, "bv", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_BATTERY_TIME, "bt", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_BATTERY_SLEEPTIME, "bs", WPS_REFRESH_DYNAMIC, NULL },
-#if CONFIG_CHARGING >= CHARGING_MONITOR
- { WPS_TOKEN_BATTERY_CHARGING, "bc", WPS_REFRESH_DYNAMIC, NULL },
-#endif
-#if CONFIG_CHARGING
- { WPS_TOKEN_BATTERY_CHARGER_CONNECTED,"bp", WPS_REFRESH_DYNAMIC, NULL },
-#endif
-#ifdef HAVE_USB_POWER
- { WPS_TOKEN_USB_POWERED, "bu", WPS_REFRESH_DYNAMIC, NULL },
-#endif
- { WPS_TOKEN_RTC_PRESENT , "cc", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_RTC_DAY_OF_MONTH, "cd", WPS_RTC_REFRESH, NULL },
- { WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED,"ce", WPS_RTC_REFRESH, NULL },
- { WPS_TOKEN_RTC_12HOUR_CFG, "cf", WPS_RTC_REFRESH, NULL },
- { WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED, "cH", WPS_RTC_REFRESH, NULL },
- { WPS_TOKEN_RTC_HOUR_24, "ck", WPS_RTC_REFRESH, NULL },
- { WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED, "cI", WPS_RTC_REFRESH, NULL },
- { WPS_TOKEN_RTC_HOUR_12, "cl", WPS_RTC_REFRESH, NULL },
- { WPS_TOKEN_RTC_MONTH, "cm", WPS_RTC_REFRESH, NULL },
- { WPS_TOKEN_RTC_MINUTE, "cM", WPS_RTC_REFRESH, NULL },
- { WPS_TOKEN_RTC_SECOND, "cS", WPS_RTC_REFRESH, NULL },
- { WPS_TOKEN_RTC_YEAR_2_DIGITS, "cy", WPS_RTC_REFRESH, NULL },
- { WPS_TOKEN_RTC_YEAR_4_DIGITS, "cY", WPS_RTC_REFRESH, NULL },
- { WPS_TOKEN_RTC_AM_PM_UPPER, "cP", WPS_RTC_REFRESH, NULL },
- { WPS_TOKEN_RTC_AM_PM_LOWER, "cp", WPS_RTC_REFRESH, NULL },
- { WPS_TOKEN_RTC_WEEKDAY_NAME, "ca", WPS_RTC_REFRESH, NULL },
- { WPS_TOKEN_RTC_MONTH_NAME, "cb", WPS_RTC_REFRESH, NULL },
- { WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON, "cu", WPS_RTC_REFRESH, NULL },
- { WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN, "cw", WPS_RTC_REFRESH, NULL },
-
- /* current file */
- { WPS_TOKEN_FILE_BITRATE, "fb", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_FILE_CODEC, "fc", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_FILE_FREQUENCY, "ff", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_FILE_FREQUENCY_KHZ, "fk", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_FILE_NAME_WITH_EXTENSION, "fm", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_FILE_NAME, "fn", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_FILE_PATH, "fp", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_FILE_SIZE, "fs", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_FILE_VBR, "fv", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_FILE_DIRECTORY, "d", WPS_REFRESH_STATIC,
- parse_dir_level },
-
- /* next file */
- { WPS_TOKEN_FILE_BITRATE, "Fb", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_FILE_CODEC, "Fc", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_FILE_FREQUENCY, "Ff", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_FILE_FREQUENCY_KHZ, "Fk", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_FILE_NAME_WITH_EXTENSION, "Fm", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_FILE_NAME, "Fn", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_FILE_PATH, "Fp", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_FILE_SIZE, "Fs", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_FILE_VBR, "Fv", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_FILE_DIRECTORY, "D", WPS_REFRESH_STATIC,
- parse_dir_level },
-
- /* current metadata */
- { WPS_TOKEN_METADATA_ARTIST, "ia", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_METADATA_COMPOSER, "ic", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_METADATA_ALBUM, "id", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_METADATA_ALBUM_ARTIST, "iA", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_METADATA_GROUPING, "iG", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_METADATA_GENRE, "ig", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_METADATA_DISC_NUMBER, "ik", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_METADATA_TRACK_NUMBER, "in", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_METADATA_TRACK_TITLE, "it", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_METADATA_VERSION, "iv", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_METADATA_YEAR, "iy", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_METADATA_COMMENT, "iC", WPS_REFRESH_STATIC, NULL },
-
- /* next metadata */
- { WPS_TOKEN_METADATA_ARTIST, "Ia", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_METADATA_COMPOSER, "Ic", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_METADATA_ALBUM, "Id", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_METADATA_ALBUM_ARTIST, "IA", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_METADATA_GROUPING, "IG", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_METADATA_GENRE, "Ig", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_METADATA_DISC_NUMBER, "Ik", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_METADATA_TRACK_NUMBER, "In", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_METADATA_TRACK_TITLE, "It", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_METADATA_VERSION, "Iv", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_METADATA_YEAR, "Iy", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_METADATA_COMMENT, "IC", WPS_REFRESH_STATIC, NULL },
-
-#if (CONFIG_CODEC != MAS3507D)
- { WPS_TOKEN_SOUND_PITCH, "Sp", WPS_REFRESH_DYNAMIC, NULL },
-#endif
-#if (CONFIG_CODEC == SWCODEC)
- { WPS_TOKEN_SOUND_SPEED, "Ss", WPS_REFRESH_DYNAMIC, NULL },
-#endif
-#if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
- { WPS_TOKEN_VLED_HDD, "lh", WPS_REFRESH_DYNAMIC, NULL },
-#endif
-
- { WPS_TOKEN_MAIN_HOLD, "mh", WPS_REFRESH_DYNAMIC, NULL },
-
-#ifdef HAS_REMOTE_BUTTON_HOLD
- { WPS_TOKEN_REMOTE_HOLD, "mr", WPS_REFRESH_DYNAMIC, NULL },
-#else
- { WPS_TOKEN_UNKNOWN, "mr", 0, NULL },
-#endif
-
- { WPS_TOKEN_REPEAT_MODE, "mm", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_PLAYBACK_STATUS, "mp", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_BUTTON_VOLUME, "mv", WPS_REFRESH_DYNAMIC,
- parse_timeout },
-
-#ifdef HAVE_LCD_BITMAP
- { WPS_TOKEN_PEAKMETER, "pm", WPS_REFRESH_PEAK_METER, NULL },
-#else
- { WPS_TOKEN_PLAYER_PROGRESSBAR, "pf",
- WPS_REFRESH_DYNAMIC | WPS_REFRESH_PLAYER_PROGRESS, parse_progressbar },
-#endif
- { WPS_TOKEN_PROGRESSBAR, "pb", WPS_REFRESH_PLAYER_PROGRESS,
- parse_progressbar },
-
- { WPS_TOKEN_VOLUME, "pv", WPS_REFRESH_DYNAMIC,
- parse_progressbar },
-
- { WPS_TOKEN_TRACK_ELAPSED_PERCENT, "px", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_TRACK_TIME_ELAPSED, "pc", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_TRACK_TIME_REMAINING, "pr", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_TRACK_LENGTH, "pt", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_TRACK_STARTING, "pS", WPS_REFRESH_DYNAMIC, parse_timeout },
- { WPS_TOKEN_TRACK_ENDING, "pE", WPS_REFRESH_DYNAMIC, parse_timeout },
-
- { WPS_TOKEN_PLAYLIST_POSITION, "pp", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_PLAYLIST_ENTRIES, "pe", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_PLAYLIST_NAME, "pn", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_PLAYLIST_SHUFFLE, "ps", WPS_REFRESH_DYNAMIC, NULL },
-
-#ifdef HAVE_TAGCACHE
- { WPS_TOKEN_DATABASE_PLAYCOUNT, "rp", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_DATABASE_RATING, "rr", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_DATABASE_AUTOSCORE, "ra", WPS_REFRESH_DYNAMIC, NULL },
-#endif
-
-#if CONFIG_CODEC == SWCODEC
- { WPS_TOKEN_REPLAYGAIN, "rg", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_CROSSFADE, "xf", WPS_REFRESH_DYNAMIC, NULL },
-#endif
-
- { WPS_TOKEN_HAVE_TUNER, "tp", WPS_REFRESH_STATIC, NULL },
-#if CONFIG_TUNER /* Re-uses the 't' and 'T' prefixes, be careful about doubleups */
- { WPS_TOKEN_TUNER_TUNED, "tt", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_TUNER_SCANMODE, "tm", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_TUNER_STEREO, "ts", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_TUNER_MINFREQ, "ta", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_TUNER_MAXFREQ, "tb", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_TUNER_CURFREQ, "tf", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_PRESET_ID, "Ti", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_PRESET_NAME, "Tn", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_PRESET_FREQ, "Tf", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_PRESET_COUNT, "Tc", WPS_REFRESH_STATIC, NULL },
- { WPS_TOKEN_HAVE_RDS, "tx", WPS_REFRESH_STATIC, NULL },
-#ifdef HAVE_RDS_CAP
- { WPS_TOKEN_RDS_NAME, "ty", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_RDS_TEXT, "tz", WPS_REFRESH_DYNAMIC, NULL },
-#endif
-#endif /* CONFIG_TUNER */
-
- { WPS_NO_TOKEN, "s", WPS_REFRESH_SCROLL, NULL },
- { WPS_TOKEN_SUBLINE_TIMEOUT, "t", 0, parse_timeout },
+/* which screen are we parsing for? */
+static enum screen_type curr_screen;
-#ifdef HAVE_LCD_BITMAP
- { WPS_NO_TOKEN, "we", 0, parse_statusbar_enable },
- { WPS_NO_TOKEN, "wd", 0, parse_statusbar_disable },
- { WPS_TOKEN_DRAW_INBUILTBAR, "wi", WPS_REFRESH_DYNAMIC, parse_statusbar_inbuilt },
+/* the current viewport */
+static struct skin_element *curr_viewport_element;
+static struct skin_viewport *curr_vp;
- { WPS_NO_TOKEN, "xl", 0, parse_image_load },
+struct line *curr_line;
- { WPS_TOKEN_IMAGE_PRELOAD_DISPLAY, "xd", WPS_REFRESH_STATIC,
- parse_image_display },
+static int follow_lang_direction = 0;
- { WPS_TOKEN_IMAGE_DISPLAY, "x", 0, parse_image_load },
- { WPS_NO_TOKEN, "Fl", 0, parse_font_load },
-#ifdef HAVE_ALBUMART
- { WPS_NO_TOKEN, "Cl", 0, parse_albumart_load },
- { WPS_TOKEN_ALBUMART_DISPLAY, "Cd", WPS_REFRESH_STATIC, parse_albumart_display },
- { WPS_TOKEN_ALBUMART_FOUND, "C", WPS_REFRESH_STATIC, NULL },
-#endif
+typedef int (*parse_function)(struct skin_element *element,
+ struct wps_token *token,
+ struct wps_data *wps_data);
- { WPS_VIEWPORT_ENABLE, "Vd", WPS_REFRESH_DYNAMIC,
- parse_viewport_display },
- { WPS_TOKEN_UIVIEWPORT_ENABLE, "VI", WPS_REFRESH_STATIC,
- parse_viewport_display },
#ifdef HAVE_LCD_BITMAP
- { WPS_VIEWPORT_CUSTOMLIST, "Vp", WPS_REFRESH_STATIC, parse_playlistview },
- { WPS_TOKEN_LIST_TITLE_TEXT, "Lt", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_LIST_TITLE_ICON, "Li", WPS_REFRESH_DYNAMIC, NULL },
-#endif
-#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
- { WPS_TOKEN_VIEWPORT_FGCOLOUR, "Vf", WPS_REFRESH_STATIC, parse_viewportcolour },
- { WPS_TOKEN_VIEWPORT_BGCOLOUR, "Vb", WPS_REFRESH_STATIC, parse_viewportcolour },
-#endif
- { WPS_NO_TOKEN, "V", 0, parse_viewport },
-
-#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
- { WPS_TOKEN_IMAGE_BACKDROP, "X", 0, parse_image_special },
-#endif
-#endif
-
- { WPS_TOKEN_SETTING, "St", WPS_REFRESH_DYNAMIC,
- parse_setting_and_lang },
- { WPS_TOKEN_TRANSLATEDSTRING, "Sx", WPS_REFRESH_STATIC,
- parse_setting_and_lang },
- { WPS_TOKEN_LANG_IS_RTL , "Sr", WPS_REFRESH_STATIC, NULL },
-
- { WPS_TOKEN_LASTTOUCH, "Tl", WPS_REFRESH_DYNAMIC, parse_timeout },
- { WPS_TOKEN_CURRENT_SCREEN, "cs", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_NO_TOKEN, "T", 0, parse_touchregion },
-
-
- /* Recording Tokens */
- { WPS_TOKEN_HAVE_RECORDING, "Rp", WPS_REFRESH_STATIC, NULL },
-#ifdef HAVE_RECORDING
- { WPS_TOKEN_IS_RECORDING, "Rr", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_REC_FREQ, "Rf", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_REC_ENCODER, "Re", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_REC_BITRATE, "Rb", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_REC_MONO, "Rm", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_REC_SECONDS, "Rs", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_REC_MINUTES, "Rn", WPS_REFRESH_DYNAMIC, NULL },
- { WPS_TOKEN_REC_HOURS, "Rh", WPS_REFRESH_DYNAMIC, NULL },
-#endif
- { WPS_TOKEN_UNKNOWN, "", 0, NULL }
- /* the array MUST end with an empty string (first char is \0) */
-};
-
-
/* add a skin_token_list item to the list chain. ALWAYS appended because some of the
* chains require the order to be kept.
*/
@@ -459,7 +116,6 @@ static void add_to_ll_chain(struct skin_token_list **list, struct skin_token_lis
}
/* traverse the image linked-list for an image */
-#ifdef HAVE_LCD_BITMAP
struct gui_img* find_image(char label, struct wps_data *data)
{
struct skin_token_list *list = data->images;
@@ -478,10 +134,10 @@ struct gui_img* find_image(char label, struct wps_data *data)
/* traverse the viewport linked list for a viewport */
struct skin_viewport* find_viewport(char label, struct wps_data *data)
{
- struct skin_token_list *list = data->viewports;
+ struct skin_element *list = data->tree;
while (list)
{
- struct skin_viewport *vp = (struct skin_viewport *)list->token->value.data;
+ struct skin_viewport *vp = (struct skin_viewport *)list->data;
if (vp->label == label)
return vp;
list = list->next;
@@ -489,6 +145,7 @@ struct skin_viewport* find_viewport(char label, struct wps_data *data)
return NULL;
}
+#ifdef HAVE_LCD_BITMAP
/* create and init a new wpsll item.
* passing NULL to token will alloc a new one.
@@ -498,9 +155,10 @@ struct skin_viewport* find_viewport(char label, struct wps_data *data)
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));
+ struct skin_token_list *llitem =
+ (struct skin_token_list *)skin_buffer_alloc(sizeof(struct skin_token_list));
if (!token)
- token = skin_buffer_alloc(sizeof(struct wps_token));
+ token = (struct wps_token*)skin_buffer_alloc(sizeof(struct wps_token));
if (!llitem || !token)
return NULL;
llitem->next = NULL;
@@ -510,108 +168,36 @@ static struct skin_token_list *new_skin_token_list_item(struct wps_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)
-{
- line_number++;
- int skip = 0;
- while(*(wps_bufptr + skip) != '\n')
- skip++;
- return ++skip;
-}
-
-/* Starts a new subline in the current line during parsing */
-static bool skin_start_new_subline(struct skin_line *line, int curr_token)
-{
- struct skin_subline *subline = skin_buffer_alloc(sizeof(struct skin_subline));
- if (!subline)
- return false;
-
- subline->first_token_idx = curr_token;
- subline->next = NULL;
-
- subline->line_type = 0;
- subline->time_mult = 0;
-
- line->curr_subline->last_token_idx = curr_token-1;
- line->curr_subline->next = subline;
- line->curr_subline = subline;
- return true;
-}
-
-static bool skin_start_new_line(struct skin_viewport *vp, int curr_token)
+static int parse_statusbar_tags(struct skin_element* element,
+ struct wps_token *token,
+ struct wps_data *wps_data)
{
- struct skin_line *line = skin_buffer_alloc(sizeof(struct skin_line));
- struct skin_subline *subline = NULL;
- if (!line)
- return false;
-
- /* init the subline */
- subline = &line->sublines;
- subline->first_token_idx = curr_token;
- subline->next = NULL;
- subline->line_type = 0;
- subline->time_mult = 0;
-
- /* init the new line */
- line->curr_subline = &line->sublines;
- line->next = NULL;
- line->subline_expire_time = 0;
-
- /* connect to curr_line and vp pointers.
- * 1) close the previous lines subline
- * 2) connect to vp pointer
- * 3) connect to curr_line global pointer
- */
- if (curr_line)
+ (void)element;
+ if (token->type == SKIN_TOKEN_DRAW_INBUILTBAR)
{
- curr_line->curr_subline->last_token_idx = curr_token - 1;
- curr_line->next = line;
- curr_line->curr_subline = NULL;
+ token->value.data = (void*)&curr_vp->vp;
}
- curr_line = line;
- if (!vp->lines)
- vp->lines = line;
- return true;
-}
-
-#ifdef HAVE_LCD_BITMAP
-
-static int parse_statusbar_enable(const char *wps_bufptr,
- struct wps_token *token,
- struct wps_data *wps_data)
-{
- (void)token; /* Kill warnings */
- wps_data->wps_sb_tag = true;
- wps_data->show_sb_on_wps = true;
- struct skin_viewport *default_vp = find_viewport(VP_DEFAULT_LABEL, wps_data);
- viewport_set_defaults(&default_vp->vp, curr_screen);
- default_vp->vp.font = FONT_UI;
- return skip_end_of_line(wps_bufptr);
-}
-
-static int parse_statusbar_disable(const char *wps_bufptr,
- struct wps_token *token,
- struct wps_data *wps_data)
-{
- (void)token; /* Kill warnings */
- wps_data->wps_sb_tag = true;
- wps_data->show_sb_on_wps = false;
- struct skin_viewport *default_vp = find_viewport(VP_DEFAULT_LABEL, wps_data);
- viewport_set_fullscreen(&default_vp->vp, curr_screen);
- default_vp->vp.font = FONT_UI;
- return skip_end_of_line(wps_bufptr);
-}
-
-static int parse_statusbar_inbuilt(const char *wps_bufptr,
- struct wps_token *token, struct wps_data *wps_data)
-{
- (void)wps_data;
- token->value.data = (void*)&curr_vp->vp;
- return skip_end_of_line(wps_bufptr);
+ else
+ {
+ struct skin_element *def_vp = wps_data->tree;
+ struct skin_viewport *default_vp = def_vp->data;
+ if (def_vp->params_count == 0)
+ {
+ wps_data->wps_sb_tag = true;
+ wps_data->show_sb_on_wps = (token->type == SKIN_TOKEN_ENABLE_THEME);
+ }
+ if (wps_data->show_sb_on_wps)
+ {
+ viewport_set_defaults(&default_vp->vp, curr_screen);
+ }
+ else
+ {
+ viewport_set_fullscreen(&default_vp->vp, curr_screen);
+ }
+ }
+ return 0;
}
-
+
static int get_image_id(int c)
{
if(c >= 'a' && c <= 'z')
@@ -625,32 +211,20 @@ static int get_image_id(int c)
char *get_image_filename(const char *start, const char* bmpdir,
char *buf, int buf_size)
{
- const char *end = start;
- int bmpdirlen = strlen(bmpdir);
-
- while (*end && *end != ',' && *end != ')')
- end++;
- if ( !end || (end - start) >= (buf_size - bmpdirlen - 2) )
- {
- buf[0] = '\0';
- return NULL;
- }
-
- strcpy(buf, bmpdir);
- buf[bmpdirlen] = '/';
- memcpy( &buf[bmpdirlen + 1], start, end - start);
- buf[bmpdirlen + 1 + end - start] = 0;
-
+ snprintf(buf, buf_size, "%s/%s", bmpdir, start);
+
return buf;
}
-static int parse_image_display(const char *wps_bufptr,
+static int parse_image_display(struct skin_element *element,
struct wps_token *token,
struct wps_data *wps_data)
{
- char label = wps_bufptr[1];
+ char *text = element->params[0].data.text;
+ char label = text[0];
+ char sublabel = text[1];
int subimage;
- struct gui_img *img;;
+ struct gui_img *img;
/* sanity check */
img = find_image(label, wps_data);
@@ -660,7 +234,7 @@ static int parse_image_display(const char *wps_bufptr,
return WPS_ERROR_INVALID_PARAM;
}
- if ((subimage = get_image_id(wps_bufptr[2])) != -1)
+ if ((subimage = get_image_id(sublabel)) != -1)
{
if (subimage >= img->num_subimages)
return WPS_ERROR_INVALID_PARAM;
@@ -674,32 +248,24 @@ static int parse_image_display(const char *wps_bufptr,
}
}
-static int parse_image_load(const char *wps_bufptr,
+static int parse_image_load(struct skin_element *element,
struct wps_token *token,
struct wps_data *wps_data)
{
- const char *ptr = wps_bufptr;
const char* filename;
const char* id;
int x,y;
struct gui_img *img;
- /* format: %x|n|filename.bmp|x|y|
- or %xl|n|filename.bmp|x|y|
- or %xl|n|filename.bmp|x|y|num_subimages|
+ /* 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;
-
- ptr++;
-
- if (!(ptr = parse_list("ssdd", NULL, ',', ptr, &id, &filename, &x, &y)))
- return WPS_ERROR_INVALID_PARAM;
-
- /* Check there is a terminating ) */
- if (*ptr != ')' && *ptr != ',')
- return WPS_ERROR_INVALID_PARAM;
+ id = element->params[0].data.text;
+ filename = element->params[1].data.text;
+ x = element->params[2].data.number;
+ y = element->params[3].data.number;
/* check the image number and load state */
if(find_image(*id, wps_data))
@@ -707,7 +273,7 @@ static int parse_image_load(const char *wps_bufptr,
/* Invalid image ID */
return WPS_ERROR_INVALID_PARAM;
}
- img = skin_buffer_alloc(sizeof(struct gui_img));
+ img = (struct gui_img*)skin_buffer_alloc(sizeof(struct gui_img));
if (!img)
return WPS_ERROR_INVALID_PARAM;
/* save a pointer to the filename */
@@ -717,62 +283,44 @@ static int parse_image_load(const char *wps_bufptr,
img->y = y;
img->num_subimages = 1;
img->always_display = false;
+ // img->just_drawn = false;
+ img->display = -1;
/* save current viewport */
img->vp = &curr_vp->vp;
- if (token->type == WPS_TOKEN_IMAGE_DISPLAY)
+ if (token->type == SKIN_TOKEN_IMAGE_DISPLAY)
{
img->always_display = true;
}
- else if (*ptr == ',')
+ else if (element->params_count == 5)
{
- /* Parse the (optional) number of sub-images */
- ptr++;
- img->num_subimages = atoi(ptr);
+ img->num_subimages = element->params[4].data.number;
if (img->num_subimages <= 0)
return WPS_ERROR_INVALID_PARAM;
- /* Check there is a terminating ) */
- while(isdigit(*ptr))
- ptr++;
- if (*ptr != ')')
- return WPS_ERROR_INVALID_PARAM;
}
- struct skin_token_list *item = new_skin_token_list_item(NULL, img);
+ struct skin_token_list *item =
+ (struct skin_token_list *)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 */
- return skip_end_of_line(wps_bufptr);
+ return 0;
}
struct skin_font {
int id; /* the id from font_load */
char *name; /* filename without path and extension */
};
static struct skin_font skinfonts[MAXUSERFONTS];
-static int parse_font_load(const char *wps_bufptr,
- struct wps_token *token, struct wps_data *wps_data)
+static int parse_font_load(struct skin_element *element,
+ struct wps_token *token,
+ struct wps_data *wps_data)
{
(void)wps_data; (void)token;
- const char *ptr = wps_bufptr;
- int id;
- char *filename;
-
- if (*ptr != '(')
- return WPS_ERROR_INVALID_PARAM;
-
- ptr++;
-
- if (!(ptr = parse_list("ds", NULL, ',', ptr, &id, &filename)))
- return WPS_ERROR_INVALID_PARAM;
-
- /* Check there is a terminating ) */
- if (*ptr != ')')
- return WPS_ERROR_INVALID_PARAM;
-
- if (id <= FONT_UI || id >= MAXFONTS-1)
- return WPS_ERROR_INVALID_PARAM;
+ int id = element->params[0].data.number;
+ char *filename = element->params[1].data.text;
+ char *ptr;
+
#if defined(DEBUG) || defined(SIMULATOR)
if (skinfonts[id-FONT_FIRSTUSERFONT].name != NULL)
{
@@ -782,286 +330,65 @@ static int parse_font_load(const char *wps_bufptr,
/* make sure the filename contains .fnt,
* we dont actually use it, but require it anyway */
ptr = strchr(filename, '.');
- if (!ptr || strncmp(ptr, ".fnt)", 5))
+ if (!ptr || strncmp(ptr, ".fnt", 4))
return WPS_ERROR_INVALID_PARAM;
skinfonts[id-FONT_FIRSTUSERFONT].id = -1;
skinfonts[id-FONT_FIRSTUSERFONT].name = filename;
- return skip_end_of_line(wps_bufptr);
+ return 0;
}
-static int parse_viewport_display(const char *wps_bufptr,
- struct wps_token *token,
- struct wps_data *wps_data)
-{
- (void)wps_data;
- char letter = wps_bufptr[1];
-
- if (letter < 'a' || letter > 'z')
- {
- /* invalid viewport tag */
- return WPS_ERROR_INVALID_PARAM;
- }
- token->value.i = letter;
- return 3;
-}
-
#ifdef HAVE_LCD_BITMAP
-static int parse_playlistview_text(struct playlistviewer *viewer,
- enum info_line_type line, char* text)
-{
- int cur_string = 0;
- const struct wps_tag *tag;
- int taglen = 0;
- const char *start = text;
- if (*text != ',')
- return -1;
- text++;
- viewer->lines[line].count = 0;
- viewer->lines[line].scroll = false;
- while (*text != ',' && *text != ')')
- {
- if (*text == '%') /* it is a token of some type */
- {
- text++;
- taglen = 0;
- switch(*text)
- {
- case '%':
- case '<':
- case '|':
- case '>':
- case ';':
- case '#':
- case '(':
- case ')':
- case ',':
- /* escaped characters */
- viewer->lines[line].tokens[viewer->lines[line].count++] = WPS_TOKEN_CHARACTER;
- viewer->lines[line].strings[cur_string][0] = *text;
- viewer->lines[line].strings[cur_string++][1] = '\0';
- text++;
- break;
- default:
- for (tag = all_tags;
- strncmp(text, tag->name, strlen(tag->name)) != 0;
- tag++) ;
- /* %s isnt stored as a tag so manually check for it */
- if (tag->type == WPS_NO_TOKEN)
- {
- if (!strncmp(tag->name, "s", 1))
- {
- viewer->lines[line].scroll = true;
- taglen = 1;
- }
- }
- else if (tag->type == WPS_TOKEN_UNKNOWN)
- {
- int i = 0;
- /* just copy the string */
- viewer->lines[line].tokens[viewer->lines[line].count++] = WPS_TOKEN_STRING;
- while (i<(MAX_PLAYLISTLINE_STRLEN-1) && text[i] != ',' && text[i] != ')' && text[i] != '%')
- {
- viewer->lines[line].strings[cur_string][i] = text[i];
- i++;
- }
- viewer->lines[line].strings[cur_string][i] = '\0';
- cur_string++;
- taglen = i;
- }
- else
- {
- if (tag->parse_func)
- {
- /* unsupported tag, reject */
- return -1;
- }
- taglen = strlen(tag->name);
- viewer->lines[line].tokens[viewer->lines[line].count++] = tag->type;
- }
- text += taglen;
- }
- }
- else
- {
- /* regular string */
- int i = 0;
- /* just copy the string */
- viewer->lines[line].tokens[viewer->lines[line].count++] = WPS_TOKEN_STRING;
- while (i<(MAX_PLAYLISTLINE_STRLEN-1) && text[i] != ',' && text[i] != ')' && text[i] != '%')
- {
- viewer->lines[line].strings[cur_string][i] = text[i];
- i++;
- }
- viewer->lines[line].strings[cur_string][i] = '\0';
- cur_string++;
- text += i;
- }
- }
- return text - start;
-}
-static int parse_playlistview(const char *wps_bufptr,
- struct wps_token *token, struct wps_data *wps_data)
+static int parse_playlistview(struct skin_element *element,
+ struct wps_token *token,
+ struct wps_data *wps_data)
{
(void)wps_data;
- /* %Vp|<use icons>|<start offset>|info line text|no info text| */
- struct playlistviewer *viewer = skin_buffer_alloc(sizeof(struct playlistviewer));
- char *ptr = strchr(wps_bufptr, '(');
- int length;
- if (!viewer || !ptr)
+ struct playlistviewer *viewer =
+ (struct playlistviewer *)skin_buffer_alloc(sizeof(struct playlistviewer));
+ if (!viewer)
return WPS_ERROR_INVALID_PARAM;
viewer->vp = &curr_vp->vp;
viewer->show_icons = true;
- viewer->start_offset = atoi(ptr+1);
+ viewer->start_offset = element->params[0].data.number;
+ viewer->lines[0] = element->params[1].data.code;
+ viewer->lines[1] = element->params[2].data.code;
+
token->value.data = (void*)viewer;
- ptr = strchr(ptr+1, ',');
- length = parse_playlistview_text(viewer, TRACK_HAS_INFO, ptr);
- if (length < 0)
- return WPS_ERROR_INVALID_PARAM;
- length = parse_playlistview_text(viewer, TRACK_HAS_NO_INFO, ptr+length);
- if (length < 0)
- return WPS_ERROR_INVALID_PARAM;
-
- return skip_end_of_line(wps_bufptr);
+
+ return 0;
}
#endif
-static int parse_viewport(const char *wps_bufptr,
- struct wps_token *token,
- struct wps_data *wps_data)
-{
- (void)token; /* Kill warnings */
- const char *ptr = wps_bufptr;
-
- struct skin_viewport *skin_vp = skin_buffer_alloc(sizeof(struct skin_viewport));
-
- /* check for the optional letter to signify its a hideable viewport */
- /* %Vl|<label>|<rest of tags>| */
- skin_vp->hidden_flags = 0;
- skin_vp->label = VP_NO_LABEL;
- skin_vp->lines = NULL;
- if (curr_line)
- {
- curr_line->curr_subline->last_token_idx = wps_data->num_tokens
- - (wps_data->num_tokens > 0 ? 1 : 0);
- }
-
- curr_line = NULL;
- if (!skin_start_new_line(skin_vp, wps_data->num_tokens))
- return WPS_ERROR_INVALID_PARAM;
-
- if (*ptr == 'i')
- {
- if (*(ptr+1) == '(')
- {
- char label = *(ptr+2);
- if (label >= 'a' && label <= 'z')
- {
- skin_vp->hidden_flags = VP_NEVER_VISIBLE;
- skin_vp->label = VP_INFO_LABEL|label;
- ptr += 3;
- }
- else
- {
- if (label != '-')
- return WPS_ERROR_INVALID_PARAM;
- skin_vp->label = VP_INFO_LABEL|VP_DEFAULT_LABEL;
- skin_vp->hidden_flags = VP_NEVER_VISIBLE;
- ptr += 3;
- }
- }
- else
- return WPS_ERROR_INVALID_PARAM; /* malformed token: e.g. %Cl7 */
- }
- else if (*ptr == 'l')
- {
- if (*(ptr+1) == '(')
- {
- char label = *(ptr+2);
- if (label >= 'a' && label <= 'z')
- {
- skin_vp->hidden_flags = VP_DRAW_HIDEABLE;
- skin_vp->label = label;
- }
- else
- return WPS_ERROR_INVALID_PARAM; /* malformed token: e.g. %Cl7 */
- ptr += 3;
- }
- }
- if (*ptr != ',' && *ptr != '(')
- return WPS_ERROR_INVALID_PARAM;
-
- ptr++;
- struct viewport *vp = &skin_vp->vp;
- /* format: %V|x|y|width|height|font| */
- if (!(ptr = viewport_parse_viewport(vp, curr_screen, ptr, ',')))
- return WPS_ERROR_INVALID_PARAM;
-
- /* Check for trailing ) */
- if (*ptr != ')')
- return WPS_ERROR_INVALID_PARAM;
- ptr++;
-
- if (follow_lang_direction && lang_is_rtl())
- {
- vp->flags |= VP_FLAG_ALIGN_RIGHT;
- vp->x = screens[curr_screen].lcdwidth - vp->width - vp->x;
- }
- else
- vp->flags &= ~VP_FLAG_ALIGN_RIGHT; /* ignore right-to-left languages */
-
#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
- skin_vp->start_fgcolour = vp->fg_pattern;
- skin_vp->start_bgcolour = vp->bg_pattern;
-#endif
- struct skin_token_list *list = new_skin_token_list_item(NULL, skin_vp);
- if (!list)
- return WPS_ERROR_INVALID_PARAM;
- add_to_ll_chain(&wps_data->viewports, list);
- curr_vp = skin_vp;
- /* Skip the rest of the line */
- return ptr-wps_bufptr;
-}
-#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
-static int parse_viewportcolour(const char *wps_bufptr,
- struct wps_token *token, struct wps_data *wps_data)
+static int parse_viewportcolour(struct skin_element *element,
+ struct wps_token *token,
+ struct wps_data *wps_data)
{
(void)wps_data;
- const char *ptr = wps_bufptr;
- int i;
- bool found_text;
- struct viewport_colour *colour = skin_buffer_alloc(sizeof(struct viewport_colour));
- uint32_t set;
- if (*ptr != '(' || !colour)
- return -1;
- ptr++;
- if (!(ptr = parse_list("c", &set, ',', ptr, &colour->colour)))
- return -1;
- if (*ptr != ')')
+ struct skin_tag_parameter *param = element->params;
+ struct viewport_colour *colour =
+ (struct viewport_colour *)skin_buffer_alloc(sizeof(struct viewport_colour));
+ if (!colour)
return -1;
- if (!set)
+ if (isdefault(param))
+ {
colour->colour = get_viewport_default_colour(curr_screen,
- token->type == WPS_TOKEN_VIEWPORT_FGCOLOUR);
- colour->vp = &curr_vp->vp;
- token->value.data = colour;
- /* If there havnt been any text tags between the %V() line and here use
- * the colour as the viewport colour. fixes scrolling lines not
- * having the correct colour */
- i = curr_vp->lines->sublines.first_token_idx;
- found_text = false;
- while (!found_text && i< curr_vp->lines->sublines.last_token_idx)
+ token->type == SKIN_TOKEN_VIEWPORT_FGCOLOUR);
+ }
+ else
{
- if (wps_data->tokens[i++].type != WPS_TOKEN_CHARACTER &&
- wps_data->tokens[i++].type != WPS_TOKEN_VIEWPORT_FGCOLOUR &&
- wps_data->tokens[i++].type != WPS_TOKEN_VIEWPORT_BGCOLOUR )
- found_text = true;
+ if (!parse_color(param->data.text, &colour->colour))
+ return -1;
}
- if (!found_text)
+ colour->vp = &curr_vp->vp;
+ token->value.data = colour;
+ if (element->line == curr_viewport_element->line)
{
- if (token->type == WPS_TOKEN_VIEWPORT_FGCOLOUR)
+ if (token->type == SKIN_TOKEN_VIEWPORT_FGCOLOUR)
{
curr_vp->start_fgcolour = colour->colour;
curr_vp->vp.fg_pattern = colour->colour;
@@ -1072,72 +399,54 @@ static int parse_viewportcolour(const char *wps_bufptr,
curr_vp->vp.bg_pattern = colour->colour;
}
}
- ptr++;
- return ptr - wps_bufptr;
+ return 0;
}
-static int parse_image_special(const char *wps_bufptr,
+static int parse_image_special(struct skin_element *element,
struct wps_token *token,
struct wps_data *wps_data)
{
(void)wps_data; /* kill warning */
(void)token;
- const char *pos = NULL;
- const char *newline;
bool error = false;
- pos = strchr(wps_bufptr + 1, ')');
- newline = strchr(wps_bufptr, '\n');
-
- error = (pos > newline);
-
#if LCD_DEPTH > 1
- if (token->type == WPS_TOKEN_IMAGE_BACKDROP)
+ if (token->type == SKIN_TOKEN_IMAGE_BACKDROP)
{
+ char *filename = element->params[0].data.text;
/* format: %X|filename.bmp| or %Xd */
- if (!strncmp(wps_bufptr, "(d)", 3))
+ if (!strcmp(filename, "d"))
{
wps_data->backdrop = NULL;
- return skip_end_of_line(wps_bufptr);
+ return 0;
}
else if (!error)
- wps_data->backdrop = (char*)wps_bufptr + 1;
+ {
+ wps_data->backdrop = filename;
+ }
}
#endif
- if (error)
- return WPS_ERROR_INVALID_PARAM;
/* Skip the rest of the line */
- return skip_end_of_line(wps_bufptr);
+ return error ? WPS_ERROR_INVALID_PARAM : 0;
}
#endif
#endif /* HAVE_LCD_BITMAP */
-static int parse_setting_and_lang(const char *wps_bufptr,
- struct wps_token *token,
- struct wps_data *wps_data)
+static int parse_setting_and_lang(struct skin_element *element,
+ struct wps_token *token,
+ struct wps_data *wps_data)
{
/* NOTE: both the string validations that happen in here will
* automatically PASS on checkwps because its too hard to get
- * settings_list.c and englinsh.lang built for it.
+ * settings_list.c and english.lang built for it.
* If that ever changes remove the #ifndef __PCTOOL__'s here
*/
(void)wps_data;
- const char *ptr = wps_bufptr;
- const char *end;
- int i = 0;
- char temp[64];
-
- /* Find the setting's cfg_name */
- if (*ptr != '(')
- return WPS_ERROR_INVALID_PARAM;
- ptr++;
- end = strchr(ptr,')');
- if (!end || (size_t)(end-ptr+1) > sizeof temp)
- return WPS_ERROR_INVALID_PARAM;
- strlcpy(temp, ptr,end-ptr+1);
+ char *temp = element->params[0].data.text;
+ int i;
- if (token->type == WPS_TOKEN_TRANSLATEDSTRING)
+ if (token->type == SKIN_TOKEN_TRANSLATEDSTRING)
{
#ifndef __PCTOOL__
i = lang_english_to_id(temp);
@@ -1159,170 +468,104 @@ static int parse_setting_and_lang(const char *wps_bufptr,
}
/* Store the setting number */
token->value.i = i;
-
- /* Skip the rest of the line */
- return end-ptr+2;
-}
-
-
-static int parse_dir_level(const char *wps_bufptr,
- struct wps_token *token,
- struct wps_data *wps_data)
-{
- char val[] = { wps_bufptr[1], '\0' };
- if (wps_bufptr[0] != '(' || wps_bufptr[2] != ')')
- return WPS_ERROR_INVALID_PARAM;
- token->value.i = atoi(val);
- (void)wps_data; /* Kill warnings */
- return 3;
+ return 0;
}
-static int parse_timeout(const char *wps_bufptr,
- struct wps_token *token,
- struct wps_data *wps_data)
+static int parse_timeout_tag(struct skin_element *element,
+ struct wps_token *token,
+ struct wps_data *wps_data)
{
- int skip = 0;
+ (void)wps_data;
int val = 0;
- bool have_point = false;
- bool have_tenth = false;
-
- (void)wps_data; /* Kill the warning */
- if (*wps_bufptr == '(')
- {
- wps_bufptr++;
- skip++;
- while ( isdigit(*wps_bufptr) || *wps_bufptr == '.' )
- {
- if (*wps_bufptr != '.')
- {
- val *= 10;
- val += *wps_bufptr - '0';
- if (have_point)
- {
- have_tenth = true;
- wps_bufptr++;
- skip++;
- break;
- }
- }
- else
- have_point = true;
-
- wps_bufptr++;
- skip++;
- }
- if (*wps_bufptr != ')')
- return -1;
- skip++;
- }
- if (have_tenth == false)
- val *= 10;
-
- if (val == 0 && skip == 0)
+ if (element->params_count == 0)
{
- /* decide what to do if no value was specified */
switch (token->type)
{
- case WPS_TOKEN_SUBLINE_TIMEOUT:
+ case SKIN_TOKEN_SUBLINE_TIMEOUT:
return -1;
- case WPS_TOKEN_BUTTON_VOLUME:
- case WPS_TOKEN_TRACK_STARTING:
- case WPS_TOKEN_TRACK_ENDING:
+ case SKIN_TOKEN_BUTTON_VOLUME:
+ case SKIN_TOKEN_TRACK_STARTING:
+ case SKIN_TOKEN_TRACK_ENDING:
+ case SKIN_TOKEN_LASTTOUCH:
val = 10;
break;
+ default:
+ break;
}
}
+ else
+ val = element->params[0].data.number;
token->value.i = val;
-
- return skip;
+ if (token->type == SKIN_TOKEN_SUBLINE_TIMEOUT)
+ curr_line->timeout = val * TIMEOUT_UNIT;
+ return 0;
}
-static int parse_progressbar(const char *wps_bufptr,
- struct wps_token *token,
- struct wps_data *wps_data)
+static int parse_progressbar_tag(struct skin_element* element,
+ struct wps_token *token,
+ struct wps_data *wps_data)
{
- /* %pb or %pb|filename|x|y|width|height|
- using - for any of the params uses "sane" values */
#ifdef HAVE_LCD_BITMAP
- enum {
- PB_X = 0,
- PB_Y,
- PB_WIDTH,
- PB_HEIGHT,
- PB_FILENAME,
- };
- const char *filename;
- int x, y, height, width;
- uint32_t set = 0;
- const char *ptr = wps_bufptr;
- 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 progressbar *pb;
+ struct skin_token_list *item;
struct viewport *vp = &curr_vp->vp;
- /* we need to know what line number (viewport relative) this pb is,
- * so count them... */
- int line_num = -1;
- struct skin_line *line = curr_vp->lines;
- while (line)
- {
- line_num++;
- line = line->next;
- }
- if (curr_vp->label != VP_DEFAULT_LABEL)
- line_num--;
+ struct skin_tag_parameter *param = element->params;
+
+ if (element->params_count == 0 &&
+ element->tag->type != SKIN_TOKEN_PROGRESSBAR)
+ return 0; /* nothing to do */
+ pb = (struct progressbar*)skin_buffer_alloc(sizeof(struct progressbar));
+
+ token->value.data = pb;
+
+ if (!pb)
+ return WPS_ERROR_INVALID_PARAM;
pb->vp = vp;
pb->have_bitmap_pb = false;
pb->bm.data = NULL; /* no bitmap specified */
pb->follow_lang_direction = follow_lang_direction > 0;
- pb->draw = false;
-
- if (*wps_bufptr != '(') /* regular old style */
+
+ if (element->params_count == 0)
{
pb->x = 0;
pb->width = vp->width;
pb->height = SYSFONT_HEIGHT-2;
- pb->y = -line_num - 1; /* Will be computed during the rendering */
- if (token->type == WPS_TOKEN_VOLUME || token->type == WPS_TOKEN_BATTERY_PERCENT)
- return 0; /* dont add it, let the regular token handling do the work */
- pb->type = token->type;
- add_to_ll_chain(&wps_data->progressbars, item);
+ pb->y = -1; /* Will be computed during the rendering */
+ pb->type = element->tag->type;
return 0;
}
- ptr = wps_bufptr + 1;
-
- if (!(ptr = parse_list("dddds", &set, ',', ptr,
- &x, &y, &width, &height, &filename)))
- return WPS_ERROR_INVALID_PARAM;
-
- if (LIST_VALUE_PARSED(set, PB_FILENAME)) /* filename */
- pb->bm.data = (char*)filename;
-
- if (LIST_VALUE_PARSED(set, PB_X)) /* x */
- pb->x = x;
+
+ item = new_skin_token_list_item(token, pb);
+ if (!item)
+ return -1;
+ add_to_ll_chain(&wps_data->progressbars, item);
+
+ /* (x,y,width,height,filename) */
+ if (!isdefault(param))
+ pb->x = param->data.number;
else
pb->x = vp->x;
-
- if (LIST_VALUE_PARSED(set, PB_WIDTH)) /* width */
- {
- /* A zero width causes a divide-by-zero error later, so reject it */
- if (width == 0)
- return WPS_ERROR_INVALID_PARAM;
-
- pb->width = width;
- }
+ param++;
+
+ if (!isdefault(param))
+ pb->y = param->data.number;
+ else
+ pb->y = -1; /* computed at rendering */
+ param++;
+
+ if (!isdefault(param))
+ pb->width = param->data.number;
else
pb->width = vp->width - pb->x;
-
- if (LIST_VALUE_PARSED(set, PB_HEIGHT)) /* height, default to font height */
+ param++;
+
+ if (!isdefault(param))
{
/* A zero height makes no sense - reject it */
- if (height == 0)
+ if (param->data.number == 0)
return WPS_ERROR_INVALID_PARAM;
- pb->height = height;
+ pb->height = param->data.number;
}
else
{
@@ -1337,30 +580,26 @@ static int parse_progressbar(const char *wps_bufptr,
#endif
}
}
-
- if (LIST_VALUE_PARSED(set, PB_Y)) /* y */
- pb->y = y;
- else
- pb->y = -line_num - 1; /* Will be computed during the rendering */
-
- if (*ptr != ')')
- return WPS_ERROR_INVALID_PARAM;
-
- add_to_ll_chain(&wps_data->progressbars, item);
- if (token->type == WPS_TOKEN_VOLUME)
- token->type = WPS_TOKEN_VOLUMEBAR;
- else if (token->type == WPS_TOKEN_BATTERY_PERCENT)
- token->type = WPS_TOKEN_BATTERY_PERCENTBAR;
+ param++;
+ if (!isdefault(param))
+ pb->bm.data = param->data.text;
+
+
+ if (token->type == SKIN_TOKEN_VOLUME)
+ token->type = SKIN_TOKEN_VOLUMEBAR;
+ else if (token->type == SKIN_TOKEN_BATTERY_PERCENT)
+ token->type = SKIN_TOKEN_BATTERY_PERCENTBAR;
pb->type = token->type;
-
- return ptr+1-wps_bufptr;
+
+ return 0;
+
#else
- (void)wps_bufptr;
- if (token->type != WPS_TOKEN_VOLUME &&
- token->type != WPS_TOKEN_BATTERY_PERCENTBAR)
+ (void)element;
+ if (token->type == SKIN_TOKEN_PROGRESSBAR ||
+ token->type == SKIN_TOKEN_PLAYER_PROGRESSBAR)
{
wps_data->full_line_progressbar =
- token->type == WPS_TOKEN_PLAYER_PROGRESSBAR;
+ token->type == SKIN_TOKEN_PLAYER_PROGRESSBAR;
}
return 0;
@@ -1368,32 +607,32 @@ static int parse_progressbar(const char *wps_bufptr,
}
#ifdef HAVE_ALBUMART
-static int parse_albumart_load(const char *wps_bufptr,
+static int parse_albumart_load(struct skin_element* element,
struct wps_token *token,
struct wps_data *wps_data)
{
- const char *ptr = wps_bufptr;
struct dim dimensions;
int albumart_slot;
bool swap_for_rtl = lang_is_rtl() && follow_lang_direction;
- struct skin_albumart *aa = skin_buffer_alloc(sizeof(struct skin_albumart));
+ struct skin_albumart *aa =
+ (struct skin_albumart *)skin_buffer_alloc(sizeof(struct skin_albumart));
(void)token; /* silence warning */
if (!aa)
- return skip_end_of_line(wps_bufptr);
+ return -1;
/* reset albumart info in wps */
aa->width = -1;
aa->height = -1;
aa->xalign = WPS_ALBUMART_ALIGN_CENTER; /* default */
aa->yalign = WPS_ALBUMART_ALIGN_CENTER; /* default */
- aa->vp = &curr_vp->vp;
- if (*ptr != '(')
- return WPS_ERROR_INVALID_PARAM;
- ptr++;
- /* format: %Cl|x|y|[[l|c|r]mwidth]|[[t|c|b]mheight]| */
- if (!(ptr = parse_list("dddd", NULL,',',ptr, &aa->x, &aa->y, &aa->width, &aa->height)))
- return WPS_ERROR_INVALID_PARAM; /* malformed token: e.g. %Cl7 */
+ aa->x = element->params[0].data.number;
+ aa->y = element->params[1].data.number;
+ aa->width = element->params[2].data.number;
+ aa->height = element->params[3].data.number;
+
+ aa->vp = &curr_vp->vp;
+ aa->draw_handle = -1;
/* if we got here, we parsed everything ok .. ! */
if (aa->width < 0)
@@ -1410,7 +649,6 @@ static int parse_albumart_load(const char *wps_bufptr,
aa->x = LCD_WIDTH - (aa->x + aa->width);
aa->state = WPS_ALBUMART_LOAD;
- aa->draw = false;
wps_data->albumart = aa;
dimensions.width = aa->width;
@@ -1420,11 +658,10 @@ static int parse_albumart_load(const char *wps_bufptr,
if (0 <= albumart_slot)
wps_data->playback_aa_slot = albumart_slot;
-
- if (*ptr == ',')
+
+ if (element->params_count > 4 && !isdefault(&element->params[4]))
{
- ptr++;
- switch (*ptr)
+ switch (*element->params[4].data.text)
{
case 'l':
case 'L':
@@ -1445,12 +682,10 @@ static int parse_albumart_load(const char *wps_bufptr,
aa->xalign = WPS_ALBUMART_ALIGN_RIGHT;
break;
}
- ptr++;
}
- if (*ptr == ',')
+ if (element->params_count > 5 && !isdefault(&element->params[5]))
{
- ptr++;
- switch (*ptr)
+ switch (*element->params[5].data.text)
{
case 't':
case 'T':
@@ -1465,32 +700,10 @@ static int parse_albumart_load(const char *wps_bufptr,
aa->yalign = WPS_ALBUMART_ALIGN_BOTTOM;
break;
}
- ptr++;
}
- if (*ptr != ')')
- return WPS_ERROR_INVALID_PARAM;
-
- return skip_end_of_line(wps_bufptr);
+ return 0;
}
-static int parse_albumart_display(const char *wps_bufptr,
- struct wps_token *token,
- struct wps_data *wps_data)
-{
- (void)wps_bufptr;
- (void)token;
- if (wps_data->albumart)
- {
- wps_data->albumart->vp = &curr_vp->vp;
- }
-#if 0
- /* the old code did this so keep it here for now...
- * this is to allow the posibility to showing the next tracks AA! */
- if (wps_bufptr+1 == 'n')
- return 1;
-#endif
- return 0;
-};
#endif /* HAVE_ALBUMART */
#ifdef HAVE_TOUCHSCREEN
@@ -1520,8 +733,9 @@ static const struct touchaction touchactions[] = {
#endif
};
-static int parse_touchregion(const char *wps_bufptr,
- struct wps_token *token, struct wps_data *wps_data)
+static int parse_touchregion(struct skin_element *element,
+ struct wps_token *token,
+ struct wps_data *wps_data)
{
(void)token;
unsigned i, imax;
@@ -1533,7 +747,7 @@ static int parse_touchregion(const char *wps_bufptr,
int x,y,w,h;
char temp[20];
- /* format: %T|x|y|width|height|action|
+ /* format: %T(x,y,width,height,action)
* if action starts with & the area must be held to happen
* action is one of:
* play - play/pause playback
@@ -1554,35 +768,22 @@ static int parse_touchregion(const char *wps_bufptr,
* voldown - decrease volume by one step
*/
-
- if (*ptr != '(')
- return WPS_ERROR_INVALID_PARAM;
- ptr++;
-
- if (!(ptr = parse_list("dddds", NULL, ',', ptr, &x, &y, &w, &h, &action)))
- return WPS_ERROR_INVALID_PARAM;
-
- /* Check there is a terminating ) */
- if (*ptr != ')')
- return WPS_ERROR_INVALID_PARAM;
-
- region = skin_buffer_alloc(sizeof(struct touchregion));
+
+ region = (struct touchregion*)skin_buffer_alloc(sizeof(struct touchregion));
if (!region)
return WPS_ERROR_INVALID_PARAM;
/* should probably do some bounds checking here with the viewport... but later */
region->action = ACTION_NONE;
- region->x = x;
- region->y = y;
- region->width = w;
- region->height = h;
+ region->x = element->params[0].data.number;
+ region->y = element->params[1].data.number;
+ region->width = element->params[2].data.number;
+ region->height = element->params[3].data.number;
region->wvp = curr_vp;
region->armed = false;
region->reverse_bar = false;
+ action = element->params[4].data.text;
- end = strchr(action, ')');
- if (!end || (size_t)(end-action+1) > sizeof temp)
- return WPS_ERROR_INVALID_PARAM;
strlcpy(temp, action, end-action+1);
action = temp;
@@ -1625,449 +826,46 @@ static int parse_touchregion(const char *wps_bufptr,
if (!item)
return WPS_ERROR_INVALID_PARAM;
add_to_ll_chain(&wps_data->touchregions, item);
- return skip_end_of_line(wps_bufptr);
+ return 0;
}
#endif
-/* Parse a generic token from the given string. Return the length read */
-static int parse_token(const char *wps_bufptr, struct wps_data *wps_data)
+static bool check_feature_tag(const int type)
{
- int skip = 0, taglen = 0, ret;
- struct wps_token *token = wps_data->tokens + wps_data->num_tokens;
- const struct wps_tag *tag;
- memset(token, 0, sizeof(*token));
-
- switch(*wps_bufptr)
- {
-
- case '%':
- case '<':
- case '|':
- case '>':
- case ';':
- case '#':
- case ')':
- case '(':
- case ',':
- /* escaped characters */
- token->type = WPS_TOKEN_CHARACTER;
- token->value.c = *wps_bufptr;
- taglen = 1;
- wps_data->num_tokens++;
- break;
-
- case '?':
- /* conditional tag */
- token->type = WPS_TOKEN_CONDITIONAL;
- level++;
- condindex[level] = wps_data->num_tokens;
- numoptions[level] = 1;
- wps_data->num_tokens++;
- ret = parse_token(wps_bufptr + 1, wps_data);
- if (ret < 0) return ret;
- taglen = 1 + ret;
- break;
-
- default:
- /* find what tag we have */
- for (tag = all_tags;
- strncmp(wps_bufptr, tag->name, strlen(tag->name)) != 0;
- tag++) ;
-
- taglen = (tag->type != WPS_TOKEN_UNKNOWN) ? strlen(tag->name) : 2;
- token->type = tag->type;
- curr_line->curr_subline->line_type |= tag->refresh_type;
-
- /* if the tag has a special parsing function, we call it */
- if (tag->parse_func)
- {
- ret = tag->parse_func(wps_bufptr + taglen, token, wps_data);
- if (ret < 0) return ret;
- skip += ret;
- }
-
- /* Some tags we don't want to save as tokens */
- if (tag->type == WPS_NO_TOKEN)
- break;
-
- /* tags that start with 'F', 'I' or 'D' are for the next file */
- if ( *(tag->name) == 'I' || *(tag->name) == 'F' ||
- *(tag->name) == 'D')
- token->next = true;
-
- wps_data->num_tokens++;
- break;
- }
-
- skip += taglen;
- return skip;
-}
-
-
-/*
- * Returns the number of bytes to skip the buf pointer to access the false
- * branch in a _binary_ conditional
- *
- * That is:
- * - before the '|' if we have a false branch, (%?<true|false> -> %?<|false>)
- * - or before the closing '>' if there's no false branch (%?<true> -> %?<>)
- *
- * depending on the features of a target it's not called from check_feature_tag,
- * hence the __attribute__ or it issues compiler warnings
- *
- **/
-
-static int find_false_branch(const char *wps_bufptr) __attribute__((unused));
-static int find_false_branch(const char *wps_bufptr)
-{
- const char *buf = wps_bufptr;
- /* wps_bufptr is after the opening '<', hence level = 1*/
- int level = 1;
- char ch;
- do
- {
- ch = *buf;
- if (ch == '%')
- { /* filter out the characters we check later if they're printed
- * as literals */
- ch = *(++buf);
- if (ch == '<' || ch == '>' || ch == '|')
- continue;
- /* else: some tags/printed literals we skip over */
- }
- else if (ch == '<') /* nested conditional */
- level++;
- else if (ch == '>')
- { /* closed our or a nested conditional,
- * do NOT skip over the '>' so that wps_parse() sees it for closing
- * if it is the closing one for our conditional */
- level--;
- }
- else if (ch == '|' && level == 1)
- { /* we found our separator, point before and get out */
- break;
- }
- /* if level is 0, we don't have a false branch */
- } while (level > 0 && *(++buf));
-
- return buf - wps_bufptr;
-}
-
-/*
- * returns the number of bytes to get the appropriate branch of a binary
- * conditional
- *
- * That means:
- * - if a feature is available, it returns 0 to not skip anything
- * - if the feature is not available, skip to the false branch and don't
- * parse the true branch at all
- *
- * */
-static int check_feature_tag(const char *wps_bufptr, const int type)
-{
- (void)wps_bufptr;
switch (type)
{
- case WPS_TOKEN_RTC_PRESENT:
+ case SKIN_TOKEN_RTC_PRESENT:
#if CONFIG_RTC
- return 0;
+ return true;
#else
- return find_false_branch(wps_bufptr);
-#endif /* CONFIG_RTC */
-
- case WPS_TOKEN_HAVE_RECORDING:
+ return false;
+#endif
+ case SKIN_TOKEN_HAVE_RECORDING:
#ifdef HAVE_RECORDING
- return 0;
+ return true;
#else
- return find_false_branch(wps_bufptr);
-#endif /* HAVE_RECORDING */
-
- case WPS_TOKEN_HAVE_TUNER:
+ return false;
+#endif
+ case SKIN_TOKEN_HAVE_TUNER:
#if CONFIG_TUNER
if (radio_hardware_present())
- return 0;
-#endif /* CONFIG_TUNER */
- return find_false_branch(wps_bufptr);
+ return true;
+#endif
+ return false;
#if CONFIG_TUNER
- case WPS_TOKEN_HAVE_RDS:
+ case SKIN_TOKEN_HAVE_RDS:
#ifdef HAVE_RDS_CAP
- return 0;
+ return true;
#else
- return find_false_branch(wps_bufptr);
+ return false;
#endif /* HAVE_RDS_CAP */
#endif /* CONFIG_TUNER */
default: /* not a tag we care about, just don't skip */
- return 0;
- }
-}
-
-
-/* Parses the WPS.
- data is the pointer to the structure where the parsed WPS should be stored.
- It is initialised.
- wps_bufptr points to the string containing the WPS tags */
-#define TOKEN_BLOCK_SIZE 128
-static bool wps_parse(struct wps_data *data, const char *wps_bufptr, bool debug)
-{
- if (!data || !wps_bufptr || !*wps_bufptr)
- return false;
- enum wps_parse_error fail = PARSE_OK;
- int ret;
- int max_tokens = TOKEN_BLOCK_SIZE;
- size_t buf_free = 0;
- line_number = 0;
- level = -1;
-
- /* allocate enough RAM for a reasonable skin, grow as needed.
- * Free any used RAM before loading the images to be 100% RAM efficient */
- data->tokens = (struct wps_token *)skin_buffer_grab(&buf_free);
- if (sizeof(struct wps_token)*max_tokens >= buf_free)
- return false;
- skin_buffer_increment(max_tokens * sizeof(struct wps_token), false);
- data->num_tokens = 0;
-
-#if LCD_DEPTH > 1
- /* Backdrop defaults to the setting unless %X is used, so set it now */
- if (global_settings.backdrop_file[0])
- {
- data->backdrop = "-";
- }
-#endif
-
- while (*wps_bufptr && !fail)
- {
- if (follow_lang_direction)
- follow_lang_direction--;
- /* first make sure there is enough room for tokens */
- if (max_tokens <= data->num_tokens + 5)
- {
- int extra_tokens = TOKEN_BLOCK_SIZE;
- size_t needed = extra_tokens * sizeof(struct wps_token);
- /* do some smarts here to grow the array a bit */
- if (skin_buffer_freespace() < needed)
- {
- fail = PARSE_FAIL_LIMITS_EXCEEDED;
- break;
- }
- skin_buffer_increment(needed, false);
- max_tokens += extra_tokens;
- }
-
- switch(*wps_bufptr++)
- {
-
- /* Regular tag */
- case '%':
- if ((ret = parse_token(wps_bufptr, data)) < 0)
- {
- fail = PARSE_FAIL_COND_INVALID_PARAM;
- break;
- }
- else if (level >= WPS_MAX_COND_LEVEL - 1)
- {
- fail = PARSE_FAIL_LIMITS_EXCEEDED;
- break;
- }
- wps_bufptr += ret;
- break;
-
- /* Alternating sublines separator */
- case ';':
- if (level >= 0) /* there are unclosed conditionals */
- {
- fail = PARSE_FAIL_UNCLOSED_COND;
- break;
- }
-
- if (!skin_start_new_subline(curr_line, data->num_tokens))
- fail = PARSE_FAIL_LIMITS_EXCEEDED;
-
- break;
-
- /* Conditional list start */
- case '<':
- if (data->tokens[data->num_tokens-2].type != WPS_TOKEN_CONDITIONAL)
- {
- fail = PARSE_FAIL_COND_SYNTAX_ERROR;
- break;
- }
- wps_bufptr += check_feature_tag(wps_bufptr,
- data->tokens[data->num_tokens-1].type);
- data->tokens[data->num_tokens].type = WPS_TOKEN_CONDITIONAL_START;
- lastcond[level] = data->num_tokens++;
- break;
-
- /* Conditional list end */
- case '>':
- if (level < 0) /* not in a conditional, invalid char */
- {
- fail = PARSE_FAIL_INVALID_CHAR;
- break;
- }
-
- data->tokens[data->num_tokens].type = WPS_TOKEN_CONDITIONAL_END;
- if (lastcond[level])
- data->tokens[lastcond[level]].value.i = data->num_tokens;
- else
- {
- fail = PARSE_FAIL_COND_SYNTAX_ERROR;
- break;
- }
-
- lastcond[level] = 0;
- data->num_tokens++;
- data->tokens[condindex[level]].value.i = numoptions[level];
- level--;
- break;
-
- /* Conditional list option */
- case '|':
- if (level < 0) /* not in a conditional, invalid char */
- {
- fail = PARSE_FAIL_INVALID_CHAR;
- break;
- }
-
- data->tokens[data->num_tokens].type = WPS_TOKEN_CONDITIONAL_OPTION;
- if (lastcond[level])
- data->tokens[lastcond[level]].value.i = data->num_tokens;
- else
- {
- fail = PARSE_FAIL_COND_SYNTAX_ERROR;
- break;
- }
-
- lastcond[level] = data->num_tokens;
- numoptions[level]++;
- data->num_tokens++;
- break;
-
- /* Comment */
- case '#':
- if (level >= 0) /* there are unclosed conditionals */
- {
- fail = PARSE_FAIL_UNCLOSED_COND;
- break;
- }
-
- wps_bufptr += skip_end_of_line(wps_bufptr);
- break;
-
- /* End of this line */
- case '\n':
- if (level >= 0) /* there are unclosed conditionals */
- {
- fail = PARSE_FAIL_UNCLOSED_COND;
- break;
- }
- /* add a new token for the \n so empty lines are correct */
- data->tokens[data->num_tokens].type = WPS_TOKEN_CHARACTER;
- data->tokens[data->num_tokens].value.c = '\n';
- data->tokens[data->num_tokens].next = false;
- data->num_tokens++;
-
- if (!skin_start_new_line(curr_vp, data->num_tokens))
- {
- fail = PARSE_FAIL_LIMITS_EXCEEDED;
- break;
- }
- line_number++;
-
- break;
-
- /* String */
- default:
- {
- unsigned int len = 1;
- const char *string_start = wps_bufptr - 1;
-
- /* find the length of the string */
- while (*wps_bufptr && *wps_bufptr != '#' &&
- *wps_bufptr != '%' && *wps_bufptr != ';' &&
- *wps_bufptr != '<' && *wps_bufptr != '>' &&
- *wps_bufptr != '|' && *wps_bufptr != '\n')
- {
- wps_bufptr++;
- len++;
- }
-
- /* look if we already have that string */
- char *str;
- bool found = false;
- struct skin_token_list *list = data->strings;
- while (list)
- {
- str = (char*)list->token->value.data;
- found = (strlen(str) == len &&
- 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
- the index of the string. If not, found is false */
-
- if (!found)
- {
- /* new string */
- str = (char*)skin_buffer_alloc(len+1);
- if (!str)
- {
- fail = PARSE_FAIL_LIMITS_EXCEEDED;
- break;
- }
- strlcpy(str, string_start, len+1);
- struct skin_token_list *item =
- new_skin_token_list_item(&data->tokens[data->num_tokens], str);
- if(!item)
- {
- fail = PARSE_FAIL_LIMITS_EXCEEDED;
- break;
- }
- add_to_ll_chain(&data->strings, item);
- }
- else
- {
- /* another occurrence of an existing string */
- data->tokens[data->num_tokens].value.data = list->token->value.data;
- }
- data->tokens[data->num_tokens].type = WPS_TOKEN_STRING;
- data->num_tokens++;
- }
- break;
- }
- }
-
- if (!fail && level >= 0) /* there are unclosed conditionals */
- fail = PARSE_FAIL_UNCLOSED_COND;
-
- if (*wps_bufptr && !fail)
- /* one of the limits of the while loop was exceeded */
- fail = PARSE_FAIL_LIMITS_EXCEEDED;
-
- /* Success! */
- curr_line->curr_subline->last_token_idx = data->num_tokens;
- data->tokens[data->num_tokens++].type = WPS_NO_TOKEN;
- /* freeup unused tokens */
- skin_buffer_free_from_front(sizeof(struct wps_token)
- * (max_tokens - data->num_tokens));
-
-#ifdef DEBUG_SKIN_ENGINE
- if (debug)
- {
- print_debug_info(data, fail, line_number);
- debug_skin_usage();
+ return true;
}
-#else
- (void)debug;
-#endif
-
- return (fail == 0);
}
-
/*
* initial setup of wps_data; does reset everything
* except fields which need to survive, i.e.
@@ -2075,6 +873,7 @@ static bool wps_parse(struct wps_data *data, const char *wps_bufptr, bool debug)
**/
static void skin_data_reset(struct wps_data *wps_data)
{
+ wps_data->tree = NULL;
#ifdef HAVE_LCD_BITMAP
wps_data->images = NULL;
wps_data->progressbars = NULL;
@@ -2085,8 +884,6 @@ static void skin_data_reset(struct wps_data *wps_data)
#ifdef HAVE_TOUCHSCREEN
wps_data->touchregions = NULL;
#endif
- wps_data->viewports = NULL;
- wps_data->strings = NULL;
#ifdef HAVE_ALBUMART
wps_data->albumart = NULL;
if (wps_data->playback_aa_slot >= 0)
@@ -2095,8 +892,6 @@ static void skin_data_reset(struct wps_data *wps_data)
wps_data->playback_aa_slot = -1;
}
#endif
- wps_data->tokens = NULL;
- wps_data->num_tokens = 0;
#ifdef HAVE_LCD_BITMAP
wps_data->peak_meter_enabled = false;
@@ -2119,6 +914,7 @@ static bool load_skin_bmp(struct wps_data *wps_data, struct bitmap *bitmap, char
{
(void)wps_data; /* only needed for remote targets */
char img_path[MAX_PATH];
+ int fd;
get_image_filename(bitmap->data, bmpdir,
img_path, sizeof(img_path));
@@ -2131,14 +927,24 @@ static bool load_skin_bmp(struct wps_data *wps_data, struct bitmap *bitmap, char
#endif
format = FORMAT_ANY|FORMAT_TRANSPARENT;
- size_t max_buf;
- char* imgbuf = (char*)skin_buffer_grab(&max_buf);
+ fd = open(img_path, O_RDONLY);
+ if (fd < 0)
+ return false;
+ size_t buf_size = read_bmp_file(img_path, bitmap, 0,
+ format|FORMAT_RETURN_SIZE, NULL);
+ char* imgbuf = (char*)skin_buffer_alloc(buf_size);
+ if (!imgbuf)
+ {
+ close(fd);
+ return NULL;
+ }
+ lseek(fd, 0, SEEK_SET);
bitmap->data = imgbuf;
- int ret = read_bmp_file(img_path, bitmap, max_buf, format, NULL);
+ int ret = read_bmp_fd(fd, bitmap, buf_size, format, NULL);
+ close(fd);
if (ret > 0)
{
- skin_buffer_increment(ret, true);
return true;
}
else
@@ -2204,14 +1010,14 @@ static bool skin_load_fonts(struct wps_data *data)
{
/* don't spit out after the first failue to aid debugging */
bool success = true;
- struct skin_token_list *vp_list;
+ struct skin_element *vp_list;
int font_id;
/* walk though each viewport and assign its font */
- for(vp_list = data->viewports; vp_list; vp_list = vp_list->next)
+ for(vp_list = data->tree; vp_list; vp_list = vp_list->next)
{
/* first, find the viewports that have a non-sys/ui-font font */
struct skin_viewport *skin_vp =
- (struct skin_viewport*)vp_list->token->value.data;
+ (struct skin_viewport*)vp_list->data;
struct viewport *vp = &skin_vp->vp;
@@ -2250,6 +1056,7 @@ static bool skin_load_fonts(struct wps_data *data)
{
DEBUGF("Unable to load font %d: '%s.fnt'\n",
font_id, font->name);
+ font->name = NULL; /* to stop trying to load it again if we fail */
success = false;
font->name = NULL;
continue;
@@ -2262,6 +1069,277 @@ static bool skin_load_fonts(struct wps_data *data)
}
#endif /* HAVE_LCD_BITMAP */
+static int convert_viewport(struct wps_data *data, struct skin_element* element)
+{
+ struct skin_viewport *skin_vp =
+ (struct skin_viewport *)skin_buffer_alloc(sizeof(struct skin_viewport));
+ struct screen *display = &screens[curr_screen];
+
+ if (!skin_vp)
+ return CALLBACK_ERROR;
+
+ skin_vp->hidden_flags = 0;
+ skin_vp->label = VP_NO_LABEL;
+ element->data = skin_vp;
+ curr_vp = skin_vp;
+ curr_viewport_element = element;
+
+ viewport_set_defaults(&skin_vp->vp, curr_screen);
+
+#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
+ skin_vp->start_fgcolour = skin_vp->vp.fg_pattern;
+ skin_vp->start_bgcolour = skin_vp->vp.bg_pattern;
+#endif
+
+
+ struct skin_tag_parameter *param = element->params;
+ if (element->params_count == 0) /* default viewport */
+ {
+ if (!data->tree) /* first viewport in the skin */
+ data->tree = element;
+ skin_vp->label = VP_DEFAULT_LABEL;
+ return CALLBACK_OK;
+ }
+
+ if (element->params_count == 6)
+ {
+ if (element->tag->type == SKIN_TOKEN_UIVIEWPORT_LOAD)
+ {
+ if (isdefault(param))
+ {
+ skin_vp->hidden_flags = VP_NEVER_VISIBLE;
+ skin_vp->label = VP_INFO_LABEL|VP_DEFAULT_LABEL;
+ }
+ else
+ {
+ skin_vp->hidden_flags = VP_NEVER_VISIBLE;
+ skin_vp->label = VP_INFO_LABEL|param->data.text[0];
+ }
+ }
+ else
+ {
+ skin_vp->hidden_flags = VP_DRAW_HIDEABLE|VP_DRAW_HIDDEN;
+ skin_vp->label = param->data.text[0];
+ }
+ param++;
+ }
+ /* x */
+ if (!isdefault(param))
+ {
+ skin_vp->vp.x = param->data.number;
+ if (param->data.number < 0)
+ skin_vp->vp.x += display->lcdwidth;
+ }
+ param++;
+ /* y */
+ if (!isdefault(param))
+ {
+ skin_vp->vp.y = param->data.number;
+ if (param->data.number < 0)
+ skin_vp->vp.y += display->lcdheight;
+ }
+ param++;
+ /* width */
+ if (!isdefault(param))
+ {
+ skin_vp->vp.width = param->data.number;
+ if (param->data.number < 0)
+ skin_vp->vp.width = (skin_vp->vp.width + display->lcdwidth) - skin_vp->vp.x;
+ }
+ else
+ {
+ skin_vp->vp.width = display->lcdwidth - skin_vp->vp.x;
+ }
+ param++;
+ /* height */
+ if (!isdefault(param))
+ {
+ skin_vp->vp.height = param->data.number;
+ if (param->data.number < 0)
+ skin_vp->vp.height = (skin_vp->vp.height + display->lcdheight) - skin_vp->vp.y;
+ }
+ else
+ {
+ skin_vp->vp.height = display->lcdheight - skin_vp->vp.y;
+ }
+ param++;
+#ifdef HAVE_LCD_BITMAP
+ /* font */
+ if (!isdefault(param))
+ {
+ skin_vp->vp.font = param->data.number;
+ }
+#endif
+
+ return CALLBACK_OK;
+
+}
+
+int skin_element_callback(struct skin_element* element, void* data)
+{
+ struct wps_data *wps_data = (struct wps_data *)data;
+ struct wps_token *token;
+ parse_function function = NULL;
+
+ switch (element->type)
+ {
+ /* IMPORTANT: element params are shared, so copy them if needed
+ * or use then NOW, dont presume they have a long lifespan
+ */
+ case TAG:
+ {
+ token = (struct wps_token*)skin_buffer_alloc(sizeof(struct wps_token));
+ memset(token, 0, sizeof(*token));
+ token->type = element->tag->type;
+
+ if ((element->tag->flags&SKIN_REFRESH_ALL) == SKIN_RTC_REFRESH)
+ {
+#ifdef CONFIG_RTC
+ curr_line->update_mode |= SKIN_REFRESH_DYNAMIC;
+#else
+ curr_line->update_mode |= SKIN_REFRESH_STATIC;
+#endif
+ }
+ else
+ curr_line->update_mode |= element->tag->flags&SKIN_REFRESH_ALL;
+
+ element->data = token;
+
+ /* Some tags need special handling for the tag, so add them here */
+ switch (token->type)
+ {
+ case SKIN_TOKEN_ALIGN_LANGDIRECTION:
+ follow_lang_direction = 2;
+ break;
+ case SKIN_TOKEN_PROGRESSBAR:
+ case SKIN_TOKEN_VOLUME:
+ case SKIN_TOKEN_BATTERY_PERCENT:
+ case SKIN_TOKEN_PLAYER_PROGRESSBAR:
+ function = parse_progressbar_tag;
+ break;
+ case SKIN_TOKEN_SUBLINE_TIMEOUT:
+ case SKIN_TOKEN_BUTTON_VOLUME:
+ case SKIN_TOKEN_TRACK_STARTING:
+ case SKIN_TOKEN_TRACK_ENDING:
+ case SKIN_TOKEN_LASTTOUCH:
+ function = parse_timeout_tag;
+ break;
+#ifdef HAVE_LCD_BITMAP
+ case SKIN_TOKEN_DISABLE_THEME:
+ case SKIN_TOKEN_ENABLE_THEME:
+ case SKIN_TOKEN_DRAW_INBUILTBAR:
+ function = parse_statusbar_tags;
+ break;
+#endif
+ case SKIN_TOKEN_FILE_DIRECTORY:
+ token->value.i = element->params[0].data.number;
+ break;
+#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
+ case SKIN_TOKEN_VIEWPORT_FGCOLOUR:
+ case SKIN_TOKEN_VIEWPORT_BGCOLOUR:
+ function = parse_viewportcolour;
+ break;
+ case SKIN_TOKEN_IMAGE_BACKDROP:
+ function = parse_image_special;
+ break;
+#endif
+ case SKIN_TOKEN_TRANSLATEDSTRING:
+ case SKIN_TOKEN_SETTING:
+ function = parse_setting_and_lang;
+ break;
+#ifdef HAVE_LCD_BITMAP
+ case SKIN_TOKEN_VIEWPORT_CUSTOMLIST:
+ function = parse_playlistview;
+ break;
+ case SKIN_TOKEN_LOAD_FONT:
+ function = parse_font_load;
+ break;
+ case SKIN_TOKEN_VIEWPORT_ENABLE:
+ case SKIN_TOKEN_UIVIEWPORT_ENABLE:
+ token->value.i = element->params[0].data.text[0];
+ break;
+ case SKIN_TOKEN_IMAGE_PRELOAD_DISPLAY:
+ function = parse_image_display;
+ break;
+ case SKIN_TOKEN_IMAGE_PRELOAD:
+ case SKIN_TOKEN_IMAGE_DISPLAY:
+ function = parse_image_load;
+ break;
+#endif
+#ifdef HAVE_TOUCHSCREEN
+ case SKIN_TOKEN_TOUCHREGION:
+ function = parse_touchregion;
+ break;
+#endif
+#ifdef HAVE_ALBUMART
+ case SKIN_TOKEN_ALBUMART_DISPLAY:
+ if (wps_data->albumart)
+ wps_data->albumart->vp = &curr_vp->vp;
+ break;
+ case SKIN_TOKEN_ALBUMART_LOAD:
+ function = parse_albumart_load;
+ break;
+#endif
+ default:
+ break;
+ }
+ if (function)
+ {
+ if (function(element, token, wps_data) < 0)
+ return CALLBACK_ERROR;
+ }
+ /* tags that start with 'F', 'I' or 'D' are for the next file */
+ if ( *(element->tag->name) == 'I' || *(element->tag->name) == 'F' ||
+ *(element->tag->name) == 'D')
+ token->next = true;
+ if (follow_lang_direction > 0 )
+ follow_lang_direction--;
+ break;
+ }
+ case VIEWPORT:
+ return convert_viewport(wps_data, element);
+ case LINE:
+ {
+ struct line *line =
+ (struct line *)skin_buffer_alloc(sizeof(struct line));
+ line->update_mode = SKIN_REFRESH_STATIC;
+ line->timeout = DEFAULT_SUBLINE_TIME_MULTIPLIER * TIMEOUT_UNIT;
+ curr_line = line;
+ element->data = line;
+ }
+ break;
+ case LINE_ALTERNATOR:
+ {
+ struct line_alternator *alternator =
+ (struct line_alternator *)skin_buffer_alloc(sizeof(struct line_alternator));
+ alternator->current_line = 0;
+#ifndef __PCTOOL__
+ alternator->last_change_tick = current_tick;
+#endif
+ element->data = alternator;
+ }
+ break;
+ case CONDITIONAL:
+ {
+ struct conditional *conditional =
+ (struct conditional *)skin_buffer_alloc(sizeof(struct conditional));
+ conditional->last_value = -1;
+ conditional->token = element->data;
+ element->data = conditional;
+ if (!check_feature_tag(element->tag->type))
+ {
+ return FEATURE_NOT_AVAILABLE;
+ }
+ return CALLBACK_OK;
+ }
+ case TEXT:
+ curr_line->update_mode |= SKIN_REFRESH_STATIC;
+ break;
+ default:
+ break;
+ }
+ return CALLBACK_OK;
+}
/* to setup up the wps-data from a format-buffer (isfile = false)
from a (wps-)file (isfile = true)*/
@@ -2298,37 +1376,13 @@ bool skin_data_load(enum screen_type screen, struct wps_data *wps_data,
}
#endif
+
skin_data_reset(wps_data);
wps_data->wps_loaded = false;
curr_screen = screen;
-
- /* alloc default viewport, will be fixed up later */
- curr_vp = skin_buffer_alloc(sizeof(struct skin_viewport));
- if (!curr_vp)
- return false;
- struct skin_token_list *list = new_skin_token_list_item(NULL, curr_vp);
- if (!list)
- return false;
- add_to_ll_chain(&wps_data->viewports, list);
-
-
- /* Initialise the first (default) viewport */
- curr_vp->label = VP_DEFAULT_LABEL;
- curr_vp->hidden_flags = 0;
- curr_vp->lines = NULL;
-
- viewport_set_defaults(&curr_vp->vp, screen);
-#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
- curr_vp->start_fgcolour = curr_vp->vp.fg_pattern;
- curr_vp->start_bgcolour = curr_vp->vp.bg_pattern;
-#endif
-#ifdef HAVE_LCD_BITMAP
- curr_vp->vp.font = FONT_UI;
-#endif
-
curr_line = NULL;
- if (!skin_start_new_line(curr_vp, 0))
- return false;
+ curr_vp = NULL;
+ curr_viewport_element = NULL;
if (isfile)
{
@@ -2364,9 +1418,15 @@ bool skin_data_load(enum screen_type screen, struct wps_data *wps_data,
{
wps_buffer = (char*)buf;
}
- /* parse the WPS source */
- if (!wps_parse(wps_data, wps_buffer, isfile)) {
+#if LCD_DEPTH > 1 || defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
+ wps_data->backdrop = "-";
+#endif
+ /* parse the skin source */
+ skin_buffer_save_position();
+ wps_data->tree = skin_parse(wps_buffer, skin_element_callback, wps_data);
+ if (!wps_data->tree) {
skin_data_reset(wps_data);
+ skin_buffer_restore_position();
return false;
}
@@ -2387,6 +1447,7 @@ bool skin_data_load(enum screen_type screen, struct wps_data *wps_data,
!skin_load_fonts(wps_data))
{
skin_data_reset(wps_data);
+ skin_buffer_restore_position();
return false;
}
#endif
@@ -2410,8 +1471,8 @@ bool skin_data_load(enum screen_type screen, struct wps_data *wps_data,
#endif
wps_data->wps_loaded = true;
#ifdef DEBUG_SKIN_ENGINE
- if (isfile && debug_wps)
- debug_skin_usage();
+ // if (isfile && debug_wps)
+ // debug_skin_usage();
#endif
return true;
}
diff --git a/apps/gui/skin_engine/skin_render.c b/apps/gui/skin_engine/skin_render.c
new file mode 100644
index 0000000000..e05f97ff4e
--- /dev/null
+++ b/apps/gui/skin_engine/skin_render.c
@@ -0,0 +1,614 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id: skin_parser.c 26752 2010-06-10 21:22:16Z bieber $
+ *
+ * Copyright (C) 2010 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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdbool.h>
+#include <ctype.h>
+#include "strlcat.h"
+
+#include "config.h"
+#include "kernel.h"
+#ifdef HAVE_ALBUMART
+#include "albumart.h"
+#endif
+#include "skin_display.h"
+#include "skin_engine.h"
+#include "skin_parser.h"
+#include "tag_table.h"
+#include "skin_scan.h"
+#if CONFIG_TUNER
+#include "radio.h"
+#endif
+#include "language.h"
+#include "playback.h"
+
+
+#define MAX_LINE 1024
+
+struct skin_draw_info {
+ struct gui_wps *gwps;
+ struct skin_viewport *skin_vp;
+ int line_number;
+ unsigned long refresh_type;
+
+ char* cur_align_start;
+ struct align_pos align;
+ bool no_line_break;
+ bool line_scrolls;
+ bool force_redraw;
+
+ char *buf;
+ size_t buf_size;
+};
+
+typedef bool (*skin_render_func)(struct skin_element* alternator, struct skin_draw_info *info);
+bool skin_render_alternator(struct skin_element* alternator, struct skin_draw_info *info);
+
+
+static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info,
+ struct skin_element *element, struct viewport* vp)
+{
+#ifndef HAVE_LCD_BITMAP
+ (void)vp; /* silence warnings */
+#endif
+ struct wps_token *token = (struct wps_token *)element->data;
+ struct wps_data *data = gwps->data;
+ bool do_refresh = (element->tag->flags & info->refresh_type) > 0;
+ switch (token->type)
+ {
+#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
+ case SKIN_TOKEN_VIEWPORT_FGCOLOUR:
+ {
+ struct viewport_colour *col = token->value.data;
+ col->vp->fg_pattern = col->colour;
+ }
+ break;
+ case SKIN_TOKEN_VIEWPORT_BGCOLOUR:
+ {
+ struct viewport_colour *col = token->value.data;
+ col->vp->bg_pattern = col->colour;
+ }
+ break;
+#endif
+ case SKIN_TOKEN_VIEWPORT_ENABLE:
+ {
+ char label = token->value.i;
+ char temp = VP_DRAW_HIDEABLE;
+ struct skin_element *viewport = gwps->data->tree;
+ while (viewport)
+ {
+ struct skin_viewport *skinvp = (struct skin_viewport*)viewport->data;
+ if (skinvp->label == label)
+ {
+ if (skinvp->hidden_flags&VP_DRAW_HIDDEN)
+ {
+ temp |= VP_DRAW_WASHIDDEN;
+ }
+ skinvp->hidden_flags = temp;
+ }
+ viewport = viewport->next;
+ }
+ }
+ break;
+#ifdef HAVE_LCD_BITMAP
+ case SKIN_TOKEN_UIVIEWPORT_ENABLE:
+ sb_set_info_vp(gwps->display->screen_type,
+ token->value.i|VP_INFO_LABEL);
+ break;
+ case SKIN_TOKEN_PEAKMETER:
+ data->peak_meter_enabled = true;
+ if (do_refresh)
+ draw_peakmeters(gwps, info->line_number, vp);
+ break;
+#endif
+ case SKIN_TOKEN_VOLUMEBAR:
+ case SKIN_TOKEN_BATTERY_PERCENTBAR:
+ case SKIN_TOKEN_PROGRESSBAR:
+ {
+#ifdef HAVE_LCD_BITMAP
+ struct progressbar *bar = (struct progressbar*)token->value.data;
+ if (do_refresh)
+ draw_progressbar(gwps, info->line_number, bar);
+#else /* HAVE_LCD_CHARCELL */
+ if (do_refresh)
+ {
+ if (data->full_line_progressbar)
+ draw_player_fullbar(gwps, info->buf, info->buf_size);
+ else
+ draw_player_progress(gwps);
+ }
+#endif
+ }
+ break;
+#ifdef HAVE_LCD_BITMAP
+ case SKIN_TOKEN_IMAGE_PRELOAD_DISPLAY:
+ {
+ char n = token->value.i & 0xFF;
+ int subimage = token->value.i >> 8;
+ struct gui_img *img = find_image(n, data);
+ if (img && img->loaded)
+ img->display = subimage;
+ break;
+ }
+#ifdef HAVE_ALBUMART
+ case SKIN_TOKEN_ALBUMART_DISPLAY:
+ /* now draw the AA */
+ if (data->albumart)
+ {
+ int handle = playback_current_aa_hid(data->playback_aa_slot);
+#if CONFIG_TUNER
+ if (in_radio_screen() || (get_radio_status() != FMRADIO_OFF))
+ {
+ struct dim dim = {data->albumart->width, data->albumart->height};
+ handle = radio_get_art_hid(&dim);
+ }
+#endif
+ data->albumart->draw_handle = handle;
+ }
+ break;
+#endif
+ case SKIN_TOKEN_DRAW_INBUILTBAR:
+ gui_statusbar_draw(&(statusbars.statusbars[gwps->display->screen_type]),
+ info->refresh_type == SKIN_REFRESH_ALL,
+ token->value.data);
+ break;
+ case SKIN_TOKEN_VIEWPORT_CUSTOMLIST:
+ if (do_refresh)
+ draw_playlist_viewer_list(gwps, token->value.data);
+ break;
+
+#endif /* HAVE_LCD_BITMAP */
+ default:
+ return false;
+ }
+ return true;
+}
+
+
+
+static void do_tags_in_hidden_conditional(struct skin_element* branch,
+ struct skin_draw_info *info)
+{
+#ifdef HAVE_LCD_BITMAP
+ struct gui_wps *gwps = info->gwps;
+ struct wps_data *data = gwps->data;
+#endif
+ /* Tags here are ones which need to be "turned off" or cleared
+ * if they are in a conditional branch which isnt being used */
+ if (branch->type == LINE_ALTERNATOR)
+ {
+ int i;
+ for (i=0; i<branch->children_count; i++)
+ {
+ do_tags_in_hidden_conditional(branch->children[i], info);
+ }
+ }
+ else if (branch->type == LINE && branch->children_count)
+ {
+ struct skin_element *child = branch->children[0];
+ struct wps_token *token;
+ while (child)
+ {
+ if (child->type == CONDITIONAL)
+ {
+ int i;
+ for (i=0; i<child->children_count; i++)
+ {
+ do_tags_in_hidden_conditional(child->children[i], info);
+ }
+ child = child->next;
+ continue;
+ }
+ else if (child->type != TAG || !child->data)
+ {
+ child = child->next;
+ continue;
+ }
+ token = (struct wps_token *)child->data;
+#ifdef HAVE_LCD_BITMAP
+ /* clear all pictures in the conditional and nested ones */
+ if (token->type == SKIN_TOKEN_IMAGE_PRELOAD_DISPLAY)
+ {
+ struct gui_img *img = find_image(token->value.i&0xFF, data);
+ clear_image_pos(gwps, img);
+ }
+ else if (token->type == SKIN_TOKEN_PEAKMETER)
+ {
+ data->peak_meter_enabled = false;
+ }
+ else if (token->type == SKIN_TOKEN_VIEWPORT_ENABLE)
+ {
+ char label = token->value.i&0x7f;
+ struct skin_element *viewport;
+ for (viewport = data->tree;
+ viewport;
+ viewport = viewport->next)
+ {
+ struct skin_viewport *skin_viewport = (struct skin_viewport*)viewport->data;
+ if ((skin_viewport->label&0x7f) != label)
+ continue;
+ if (skin_viewport->hidden_flags&VP_NEVER_VISIBLE)
+ {
+ continue;
+ }
+ if (skin_viewport->hidden_flags&VP_DRAW_HIDEABLE)
+ {
+ if (skin_viewport->hidden_flags&VP_DRAW_HIDDEN)
+ skin_viewport->hidden_flags |= VP_DRAW_WASHIDDEN;
+ else
+ {
+ gwps->display->set_viewport(&skin_viewport->vp);
+ gwps->display->clear_viewport();
+ gwps->display->scroll_stop(&skin_viewport->vp);
+ gwps->display->set_viewport(&info->skin_vp->vp);
+ skin_viewport->hidden_flags |= VP_DRAW_HIDDEN;
+ }
+ }
+ }
+ }
+#endif
+#ifdef HAVE_ALBUMART
+ else if (data->albumart && token->type == SKIN_TOKEN_ALBUMART_DISPLAY)
+ {
+ draw_album_art(gwps,
+ playback_current_aa_hid(data->playback_aa_slot), true);
+ }
+#endif
+ child = child->next;
+ }
+ }
+}
+
+static void fix_line_alignment(struct skin_draw_info *info, struct skin_element *element)
+{
+ struct align_pos *align = &info->align;
+ char *cur_pos = info->cur_align_start + strlen(info->cur_align_start);
+ switch (element->tag->type)
+ {
+ case SKIN_TOKEN_ALIGN_LEFT:
+ *cur_pos = '\0'; cur_pos++; *cur_pos = '\0';
+ align->left = cur_pos;
+ info->cur_align_start = cur_pos;
+ break;
+ case SKIN_TOKEN_ALIGN_LEFT_RTL:
+ *cur_pos = '\0'; cur_pos++; *cur_pos = '\0';
+ if (lang_is_rtl())
+ align->right = cur_pos;
+ else
+ align->left = cur_pos;
+ info->cur_align_start = cur_pos;
+ break;
+ case SKIN_TOKEN_ALIGN_CENTER:
+ *cur_pos = '\0'; cur_pos++; *cur_pos = '\0';
+ align->center = cur_pos;
+ info->cur_align_start = cur_pos;
+ break;
+ case SKIN_TOKEN_ALIGN_RIGHT:
+ *cur_pos = '\0'; cur_pos++; *cur_pos = '\0';
+ align->right = cur_pos;
+ info->cur_align_start = cur_pos;
+ break;
+ case SKIN_TOKEN_ALIGN_RIGHT_RTL:
+ *cur_pos = '\0'; cur_pos++; *cur_pos = '\0';
+ if (lang_is_rtl())
+ align->left = cur_pos;
+ else
+ align->right = cur_pos;
+ info->cur_align_start = cur_pos;
+ break;
+ default:
+ break;
+ }
+}
+
+/* Draw a LINE element onto the display */
+bool skin_render_line(struct skin_element* line, struct skin_draw_info *info)
+{
+ bool needs_update = false;
+ int last_value, value;
+
+ if (line->children_count == 0)
+ return false; /* empty line, do nothing */
+
+ struct skin_element *child = line->children[0];
+ struct conditional *conditional;
+ skin_render_func func = skin_render_line;
+ char tempbuf[128];
+ int old_refresh_mode = info->refresh_type;
+ while (child)
+ {
+ tempbuf[0] = '\0';
+ switch (child->type)
+ {
+ case CONDITIONAL:
+ conditional = (struct conditional*)child->data;
+ last_value = conditional->last_value;
+ value = evaluate_conditional(info->gwps, conditional, child->children_count);
+
+ if (value != 1 && value >= child->children_count)
+ value = child->children_count-1;
+ if (child->children_count == 1)
+ {
+ /* special handling so
+ * %?aa<true> and %?<true|false> need special handlng here */
+
+ if (value == 1) /* tag is false */
+ {
+ /* we are in a false branch of a %?aa<true> conditional */
+ if (last_value == 0)
+ do_tags_in_hidden_conditional(child->children[0], info);
+ break;
+ }
+ value = 0;
+ }
+ else
+ {
+ if (last_value >= 0 && value != last_value && last_value < child->children_count)
+ do_tags_in_hidden_conditional(child->children[last_value], info);
+ }
+ if (child->children[value]->type == LINE_ALTERNATOR)
+ {
+ func = skin_render_alternator;
+ }
+ else if (child->children[value]->type == LINE)
+ func = skin_render_line;
+
+ if (value != last_value)
+ {
+ info->refresh_type = SKIN_REFRESH_ALL;
+ info->force_redraw = true;
+ }
+
+ if (func(child->children[value], info))
+ needs_update = true;
+ else
+ needs_update = needs_update || (last_value != value);
+
+ info->refresh_type = old_refresh_mode;
+ break;
+ case TAG:
+ if (child->tag->flags & NOBREAK)
+ info->no_line_break = true;
+ if (child->tag->type == SKIN_TOKEN_SUBLINE_SCROLL)
+ info->line_scrolls = true;
+
+ fix_line_alignment(info, child);
+
+ if (!child->data)
+ {
+ break;
+ }
+ if (!do_non_text_tags(info->gwps, info, child, &info->skin_vp->vp))
+ {
+ const char *value = get_token_value(info->gwps, child->data,
+ tempbuf, sizeof(tempbuf), NULL);
+ if (value)
+ {
+ needs_update = needs_update ||
+ ((child->tag->flags&info->refresh_type)!=0);
+ strlcat(info->cur_align_start, value,
+ info->buf_size - (info->cur_align_start-info->buf));
+ }
+ }
+ break;
+ case TEXT:
+ strlcat(info->cur_align_start, child->data,
+ info->buf_size - (info->cur_align_start-info->buf));
+ needs_update = needs_update ||
+ (info->refresh_type&SKIN_REFRESH_STATIC) != 0;
+ break;
+ case COMMENT:
+ default:
+ break;
+ }
+
+ child = child->next;
+ }
+ return needs_update;
+}
+
+bool skin_render_alternator(struct skin_element* element, struct skin_draw_info *info)
+{
+ bool changed_lines = false;
+ struct line_alternator *alternator = (struct line_alternator*)element->data;
+ unsigned old_refresh = info->refresh_type;
+ if (info->refresh_type == SKIN_REFRESH_ALL)
+ {
+ alternator->current_line = 0;
+ alternator->last_change_tick = current_tick;
+ changed_lines = true;
+ }
+ else
+ {
+ struct skin_element *current_line = element->children[alternator->current_line];
+ struct line *line = (struct line *)current_line->data;
+ int next_change = alternator->last_change_tick + line->timeout;
+ if (TIME_AFTER(current_tick, next_change))
+ {
+ alternator->current_line++;
+ if (alternator->current_line >= element->children_count)
+ alternator->current_line = 0;
+ alternator->last_change_tick = current_tick;
+ changed_lines = true;
+ }
+ }
+ if (element->children[alternator->current_line]->children_count == 0)
+ {
+ /* skip empty sublines */
+ alternator->current_line++;
+ if (alternator->current_line >= element->children_count)
+ alternator->current_line = 0;
+ changed_lines = true;
+ }
+
+ if (changed_lines)
+ {
+ info->refresh_type = SKIN_REFRESH_ALL;
+ info->force_redraw = true;
+ }
+ bool ret = skin_render_line(element->children[alternator->current_line], info);
+ info->refresh_type = old_refresh;
+ return changed_lines || ret;
+}
+
+void skin_render_viewport(struct skin_element* viewport, struct gui_wps *gwps,
+ struct skin_viewport* skin_viewport, unsigned long refresh_type)
+{
+ struct screen *display = gwps->display;
+ char linebuf[MAX_LINE];
+ skin_render_func func = skin_render_line;
+ struct skin_element* line = viewport;
+ struct skin_draw_info info = {
+ .gwps = gwps,
+ .buf = linebuf,
+ .buf_size = sizeof(linebuf),
+ .line_number = 0,
+ .no_line_break = false,
+ .line_scrolls = false,
+ .refresh_type = refresh_type,
+ .skin_vp = skin_viewport
+ };
+
+ struct align_pos * align = &info.align;
+ bool needs_update;
+#ifdef HAVE_LCD_BITMAP
+ /* Set images to not to be displayed */
+ struct skin_token_list *imglist = gwps->data->images;
+ while (imglist)
+ {
+ struct gui_img *img = (struct gui_img *)imglist->token->value.data;
+ img->display = -1;
+ imglist = imglist->next;
+ }
+#endif
+
+ while (line)
+ {
+ linebuf[0] = '\0';
+ info.no_line_break = false;
+ info.line_scrolls = false;
+ info.force_redraw = false;
+
+ info.cur_align_start = info.buf;
+ align->left = info.buf;
+ align->center = NULL;
+ align->right = NULL;
+
+
+ if (line->type == LINE_ALTERNATOR)
+ func = skin_render_alternator;
+ else if (line->type == LINE)
+ func = skin_render_line;
+
+ needs_update = func(line, &info);
+
+ /* only update if the line needs to be, and there is something to write */
+ if (refresh_type && needs_update)
+ {
+ if (info.line_scrolls)
+ {
+ /* if the line is a scrolling one we don't want to update
+ too often, so that it has the time to scroll */
+ if ((refresh_type & SKIN_REFRESH_SCROLL) || info.force_redraw)
+ write_line(display, align, info.line_number, true);
+ }
+ else
+ write_line(display, align, info.line_number, false);
+ }
+ if (!info.no_line_break)
+ info.line_number++;
+ line = line->next;
+ }
+#ifdef HAVE_LCD_BITMAP
+ wps_display_images(gwps, &skin_viewport->vp);
+#endif
+}
+
+void skin_render(struct gui_wps *gwps, unsigned refresh_mode)
+{
+ struct wps_data *data = gwps->data;
+ struct screen *display = gwps->display;
+
+ struct skin_element* viewport = data->tree;
+ struct skin_viewport* skin_viewport;
+
+ int old_refresh_mode = refresh_mode;
+
+#ifdef HAVE_LCD_CHARCELLS
+ int i;
+ for (i = 0; i < 8; i++)
+ {
+ if (data->wps_progress_pat[i] == 0)
+ data->wps_progress_pat[i] = display->get_locked_pattern();
+ }
+#endif
+ viewport = data->tree;
+ skin_viewport = (struct skin_viewport *)viewport->data;
+ if (skin_viewport->label == VP_DEFAULT_LABEL && viewport->next)
+ refresh_mode = 0;
+
+ for (viewport = data->tree;
+ viewport;
+ viewport = viewport->next)
+ {
+ /* SETUP */
+ skin_viewport = (struct skin_viewport*)viewport->data;
+ unsigned vp_refresh_mode = refresh_mode;
+#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
+ skin_viewport->vp.fg_pattern = skin_viewport->start_fgcolour;
+ skin_viewport->vp.bg_pattern = skin_viewport->start_bgcolour;
+#endif
+
+ /* dont redraw the viewport if its disabled */
+ if (skin_viewport->hidden_flags&VP_NEVER_VISIBLE)
+ { /* don't draw anything into this one */
+ vp_refresh_mode = 0;
+ }
+ else if ((skin_viewport->hidden_flags&VP_DRAW_HIDDEN))
+ {
+ skin_viewport->hidden_flags |= VP_DRAW_WASHIDDEN;
+ continue;
+ }
+ else if (((skin_viewport->hidden_flags&
+ (VP_DRAW_WASHIDDEN|VP_DRAW_HIDEABLE))
+ == (VP_DRAW_WASHIDDEN|VP_DRAW_HIDEABLE)))
+ {
+ vp_refresh_mode = SKIN_REFRESH_ALL;
+ skin_viewport->hidden_flags = VP_DRAW_HIDEABLE;
+ }
+
+ display->set_viewport(&skin_viewport->vp);
+ if ((vp_refresh_mode&SKIN_REFRESH_ALL) == SKIN_REFRESH_ALL)
+ {
+ display->clear_viewport();
+ }
+ /* render */
+ skin_render_viewport(viewport->children[0], gwps,
+ skin_viewport, vp_refresh_mode);
+ refresh_mode = old_refresh_mode;
+ }
+
+ /* Restore the default viewport */
+ display->set_viewport(NULL);
+ display->update();
+}
diff --git a/apps/gui/skin_engine/skin_tokens.c b/apps/gui/skin_engine/skin_tokens.c
index b0a55ca13c..c5e1ebc831 100644
--- a/apps/gui/skin_engine/skin_tokens.c
+++ b/apps/gui/skin_engine/skin_tokens.c
@@ -167,19 +167,19 @@ const char *get_id3_token(struct wps_token *token, struct mp3entry *id3,
unsigned long elapsed = id3->elapsed + state->ff_rewind_count;
switch (token->type)
{
- case WPS_TOKEN_METADATA_ARTIST:
+ case SKIN_TOKEN_METADATA_ARTIST:
return id3->artist;
- case WPS_TOKEN_METADATA_COMPOSER:
+ case SKIN_TOKEN_METADATA_COMPOSER:
return id3->composer;
- case WPS_TOKEN_METADATA_ALBUM:
+ case SKIN_TOKEN_METADATA_ALBUM:
return id3->album;
- case WPS_TOKEN_METADATA_ALBUM_ARTIST:
+ case SKIN_TOKEN_METADATA_ALBUM_ARTIST:
return id3->albumartist;
- case WPS_TOKEN_METADATA_GROUPING:
+ case SKIN_TOKEN_METADATA_GROUPING:
return id3->grouping;
- case WPS_TOKEN_METADATA_GENRE:
+ case SKIN_TOKEN_METADATA_GENRE:
return id3->genre_string;
- case WPS_TOKEN_METADATA_DISC_NUMBER:
+ case SKIN_TOKEN_METADATA_DISC_NUMBER:
if (id3->disc_string)
return id3->disc_string;
if (id3->discnum) {
@@ -187,7 +187,7 @@ const char *get_id3_token(struct wps_token *token, struct mp3entry *id3,
return buf;
}
return NULL;
- case WPS_TOKEN_METADATA_TRACK_NUMBER:
+ case SKIN_TOKEN_METADATA_TRACK_NUMBER:
if (id3->track_string)
return id3->track_string;
if (id3->tracknum) {
@@ -195,9 +195,9 @@ const char *get_id3_token(struct wps_token *token, struct mp3entry *id3,
return buf;
}
return NULL;
- case WPS_TOKEN_METADATA_TRACK_TITLE:
+ case SKIN_TOKEN_METADATA_TRACK_TITLE:
return id3->title;
- case WPS_TOKEN_METADATA_VERSION:
+ case SKIN_TOKEN_METADATA_VERSION:
switch (id3->id3version)
{
case ID3_VER_1_0:
@@ -214,7 +214,7 @@ const char *get_id3_token(struct wps_token *token, struct mp3entry *id3,
break;
}
return NULL;
- case WPS_TOKEN_METADATA_YEAR:
+ case SKIN_TOKEN_METADATA_YEAR:
if( id3->year_string )
return id3->year_string;
if (id3->year) {
@@ -222,29 +222,29 @@ const char *get_id3_token(struct wps_token *token, struct mp3entry *id3,
return buf;
}
return NULL;
- case WPS_TOKEN_METADATA_COMMENT:
+ case SKIN_TOKEN_METADATA_COMMENT:
return id3->comment;
- case WPS_TOKEN_FILE_PATH:
+ case SKIN_TOKEN_FILE_PATH:
return id3->path;
- case WPS_TOKEN_FILE_BITRATE:
+ case SKIN_TOKEN_FILE_BITRATE:
if(id3->bitrate)
snprintf(buf, buf_size, "%d", id3->bitrate);
else
return "?";
return buf;
- case WPS_TOKEN_TRACK_TIME_ELAPSED:
+ case SKIN_TOKEN_TRACK_TIME_ELAPSED:
format_time(buf, buf_size, elapsed);
return buf;
- case WPS_TOKEN_TRACK_TIME_REMAINING:
+ case SKIN_TOKEN_TRACK_TIME_REMAINING:
format_time(buf, buf_size, length - elapsed);
return buf;
- case WPS_TOKEN_TRACK_LENGTH:
+ case SKIN_TOKEN_TRACK_LENGTH:
format_time(buf, buf_size, length);
return buf;
- case WPS_TOKEN_TRACK_ELAPSED_PERCENT:
+ case SKIN_TOKEN_TRACK_ELAPSED_PERCENT:
if (length <= 0)
return NULL;
@@ -255,14 +255,14 @@ const char *get_id3_token(struct wps_token *token, struct mp3entry *id3,
snprintf(buf, buf_size, "%lu", 100 * elapsed / length);
return buf;
- case WPS_TOKEN_TRACK_STARTING:
+ case SKIN_TOKEN_TRACK_STARTING:
{
unsigned long time = token->value.i * 1000;
if (elapsed < time)
return "starting";
}
return NULL;
- case WPS_TOKEN_TRACK_ENDING:
+ case SKIN_TOKEN_TRACK_ENDING:
{
unsigned long time = token->value.i * 1000;
if (length - elapsed < time)
@@ -270,7 +270,7 @@ const char *get_id3_token(struct wps_token *token, struct mp3entry *id3,
}
return NULL;
- case WPS_TOKEN_FILE_CODEC:
+ case SKIN_TOKEN_FILE_CODEC:
if (intval)
{
if(id3->codectype == AFMT_UNKNOWN)
@@ -280,10 +280,10 @@ const char *get_id3_token(struct wps_token *token, struct mp3entry *id3,
}
return get_codectype(id3);
- case WPS_TOKEN_FILE_FREQUENCY:
+ case SKIN_TOKEN_FILE_FREQUENCY:
snprintf(buf, buf_size, "%ld", id3->frequency);
return buf;
- case WPS_TOKEN_FILE_FREQUENCY_KHZ:
+ case SKIN_TOKEN_FILE_FREQUENCY_KHZ:
/* ignore remainders < 100, so 22050 Hz becomes just 22k */
if ((id3->frequency % 1000) < 100)
snprintf(buf, buf_size, "%ld", id3->frequency / 1000);
@@ -292,7 +292,7 @@ const char *get_id3_token(struct wps_token *token, struct mp3entry *id3,
id3->frequency / 1000,
(id3->frequency % 1000) / 100);
return buf;
- case WPS_TOKEN_FILE_NAME:
+ case SKIN_TOKEN_FILE_NAME:
if (get_dir(buf, buf_size, id3->path, 0)) {
/* Remove extension */
char* sep = strrchr(buf, '.');
@@ -302,28 +302,28 @@ const char *get_id3_token(struct wps_token *token, struct mp3entry *id3,
return buf;
}
return NULL;
- case WPS_TOKEN_FILE_NAME_WITH_EXTENSION:
+ case SKIN_TOKEN_FILE_NAME_WITH_EXTENSION:
return get_dir(buf, buf_size, id3->path, 0);
- case WPS_TOKEN_FILE_SIZE:
+ case SKIN_TOKEN_FILE_SIZE:
snprintf(buf, buf_size, "%ld", id3->filesize / 1024);
return buf;
- case WPS_TOKEN_FILE_VBR:
+ case SKIN_TOKEN_FILE_VBR:
return (id3->vbr) ? "(avg)" : NULL;
- case WPS_TOKEN_FILE_DIRECTORY:
+ case SKIN_TOKEN_FILE_DIRECTORY:
return get_dir(buf, buf_size, id3->path, token->value.i);
#ifdef HAVE_TAGCACHE
- case WPS_TOKEN_DATABASE_PLAYCOUNT:
+ case SKIN_TOKEN_DATABASE_PLAYCOUNT:
if (intval)
*intval = id3->playcount + 1;
snprintf(buf, buf_size, "%ld", id3->playcount);
return buf;
- case WPS_TOKEN_DATABASE_RATING:
+ case SKIN_TOKEN_DATABASE_RATING:
if (intval)
*intval = id3->rating + 1;
snprintf(buf, buf_size, "%d", id3->rating);
return buf;
- case WPS_TOKEN_DATABASE_AUTOSCORE:
+ case SKIN_TOKEN_DATABASE_AUTOSCORE:
if (intval)
*intval = id3->score + 1;
snprintf(buf, buf_size, "%d", id3->score);
@@ -340,13 +340,13 @@ const char *get_id3_token(struct wps_token *token, struct mp3entry *id3,
{
/* Most tokens expect NULL on error so leave that for the default case,
* The ones that expect "0" need to be handled */
- case WPS_TOKEN_FILE_FREQUENCY:
- case WPS_TOKEN_FILE_FREQUENCY_KHZ:
- case WPS_TOKEN_FILE_SIZE:
+ case SKIN_TOKEN_FILE_FREQUENCY:
+ case SKIN_TOKEN_FILE_FREQUENCY_KHZ:
+ case SKIN_TOKEN_FILE_SIZE:
#ifdef HAVE_TAGCACHE
- case WPS_TOKEN_DATABASE_PLAYCOUNT:
- case WPS_TOKEN_DATABASE_RATING:
- case WPS_TOKEN_DATABASE_AUTOSCORE:
+ case SKIN_TOKEN_DATABASE_PLAYCOUNT:
+ case SKIN_TOKEN_DATABASE_RATING:
+ case SKIN_TOKEN_DATABASE_AUTOSCORE:
#endif
if (intval)
*intval = 0;
@@ -397,30 +397,30 @@ const char *get_radio_token(struct wps_token *token, int preset_offset,
switch (token->type)
{
/* Radio/tuner tokens */
- case WPS_TOKEN_TUNER_TUNED:
+ case SKIN_TOKEN_TUNER_TUNED:
if (tuner_get(RADIO_TUNED))
return "t";
return NULL;
- case WPS_TOKEN_TUNER_SCANMODE:
+ case SKIN_TOKEN_TUNER_SCANMODE:
if (radio_scan_mode())
return "s";
return NULL;
- case WPS_TOKEN_TUNER_STEREO:
+ case SKIN_TOKEN_TUNER_STEREO:
if (radio_is_stereo())
return "s";
return NULL;
- case WPS_TOKEN_TUNER_MINFREQ: /* changes based on "region" */
+ case SKIN_TOKEN_TUNER_MINFREQ: /* changes based on "region" */
return format_freq_MHz(region_data->freq_min,
region_data->freq_step, buf, buf_size);
- case WPS_TOKEN_TUNER_MAXFREQ: /* changes based on "region" */
+ case SKIN_TOKEN_TUNER_MAXFREQ: /* changes based on "region" */
return format_freq_MHz(region_data->freq_max,
region_data->freq_step, buf, buf_size);
- case WPS_TOKEN_TUNER_CURFREQ:
+ case SKIN_TOKEN_TUNER_CURFREQ:
return format_freq_MHz(radio_current_frequency(),
region_data->freq_step, buf, buf_size);
- case WPS_TOKEN_PRESET_NAME:
- case WPS_TOKEN_PRESET_FREQ:
- case WPS_TOKEN_PRESET_ID:
+ case SKIN_TOKEN_PRESET_NAME:
+ case SKIN_TOKEN_PRESET_FREQ:
+ case SKIN_TOKEN_PRESET_ID:
{
int preset_count = radio_preset_count();
int cur_preset = radio_current_preset();
@@ -431,30 +431,32 @@ const char *get_radio_token(struct wps_token *token, int preset_offset,
preset %= preset_count;
if (preset < 0)
preset += preset_count;
- if (token->type == WPS_TOKEN_PRESET_NAME)
+ if (token->type == SKIN_TOKEN_PRESET_NAME)
snprintf(buf, buf_size, "%s", radio_get_preset(preset)->name);
- else if (token->type == WPS_TOKEN_PRESET_FREQ)
+ else if (token->type == SKIN_TOKEN_PRESET_FREQ)
format_freq_MHz(radio_get_preset(preset)->frequency,
region_data->freq_step, buf, buf_size);
else
snprintf(buf, buf_size, "%d", preset + 1);
return buf;
}
- case WPS_TOKEN_PRESET_COUNT:
+ case SKIN_TOKEN_PRESET_COUNT:
snprintf(buf, buf_size, "%d", radio_preset_count());
if (intval)
*intval = radio_preset_count();
return buf;
- case WPS_TOKEN_HAVE_RDS:
+ case SKIN_TOKEN_HAVE_RDS:
#ifdef HAVE_RDS_CAP
return "rds";
- case WPS_TOKEN_RDS_NAME:
+ case SKIN_TOKEN_RDS_NAME:
return tuner_get_rds_info(RADIO_RDS_NAME);
- case WPS_TOKEN_RDS_TEXT:
+ case SKIN_TOKEN_RDS_TEXT:
return tuner_get_rds_info(RADIO_RDS_TEXT);
#else
- return NULL; /* end of the WPS_TOKEN_HAVE_RDS case */
+ return NULL; /* end of the SKIN_TOKEN_HAVE_RDS case */
#endif /* HAVE_RDS_CAP */
+ default:
+ return NULL;
}
return NULL;
}
@@ -497,8 +499,8 @@ const char *get_token_value(struct gui_wps *gwps,
/* if the token is an RTC one, update the time
and do the necessary checks */
- if (token->type >= WPS_TOKENS_RTC_BEGIN
- && token->type <= WPS_TOKENS_RTC_END)
+ if (token->type >= SKIN_TOKENS_RTC_BEGIN
+ && token->type <= SKIN_TOKENS_RTC_END)
{
tm = get_time();
@@ -531,44 +533,44 @@ const char *get_token_value(struct gui_wps *gwps,
switch (token->type)
{
- case WPS_TOKEN_CHARACTER:
+ case SKIN_TOKEN_CHARACTER:
if (token->value.c == '\n')
return NULL;
return &(token->value.c);
- case WPS_TOKEN_STRING:
+ case SKIN_TOKEN_STRING:
return (char*)token->value.data;
- case WPS_TOKEN_TRANSLATEDSTRING:
+ case SKIN_TOKEN_TRANSLATEDSTRING:
return (char*)P2STR(ID2P(token->value.i));
- case WPS_TOKEN_PLAYLIST_ENTRIES:
+ case SKIN_TOKEN_PLAYLIST_ENTRIES:
snprintf(buf, buf_size, "%d", playlist_amount());
return buf;
- case WPS_TOKEN_LIST_TITLE_TEXT:
+ case SKIN_TOKEN_LIST_TITLE_TEXT:
return (char*)token->value.data;
- case WPS_TOKEN_LIST_TITLE_ICON:
+ case SKIN_TOKEN_LIST_TITLE_ICON:
if (intval)
*intval = token->value.i;
snprintf(buf, buf_size, "%d", token->value.i);
return buf;
- case WPS_TOKEN_PLAYLIST_NAME:
+ case SKIN_TOKEN_PLAYLIST_NAME:
return playlist_name(NULL, buf, buf_size);
- case WPS_TOKEN_PLAYLIST_POSITION:
+ case SKIN_TOKEN_PLAYLIST_POSITION:
snprintf(buf, buf_size, "%d", playlist_get_display_index());
return buf;
- case WPS_TOKEN_PLAYLIST_SHUFFLE:
+ case SKIN_TOKEN_PLAYLIST_SHUFFLE:
if ( global_settings.playlist_shuffle )
return "s";
else
return NULL;
break;
- case WPS_TOKEN_VOLUME:
+ case SKIN_TOKEN_VOLUME:
snprintf(buf, buf_size, "%d", global_settings.volume);
if (intval)
{
@@ -593,7 +595,7 @@ const char *get_token_value(struct gui_wps *gwps,
}
return buf;
#ifdef HAVE_ALBUMART
- case WPS_TOKEN_ALBUMART_FOUND:
+ case SKIN_TOKEN_ALBUMART_FOUND:
if (data->albumart)
{
int handle = -1;
@@ -609,16 +611,9 @@ const char *get_token_value(struct gui_wps *gwps,
return "C";
}
return NULL;
-
- case WPS_TOKEN_ALBUMART_DISPLAY:
- if (!data->albumart)
- return NULL;
- if (!data->albumart->draw)
- data->albumart->draw = true;
- return NULL;
#endif
- case WPS_TOKEN_BATTERY_PERCENT:
+ case SKIN_TOKEN_BATTERY_PERCENT:
{
int l = battery_level();
@@ -641,14 +636,14 @@ const char *get_token_value(struct gui_wps *gwps,
}
}
- case WPS_TOKEN_BATTERY_VOLTS:
+ case SKIN_TOKEN_BATTERY_VOLTS:
{
unsigned int v = battery_voltage();
snprintf(buf, buf_size, "%d.%02d", v / 1000, (v % 1000) / 10);
return buf;
}
- case WPS_TOKEN_BATTERY_TIME:
+ case SKIN_TOKEN_BATTERY_TIME:
{
int t = battery_time();
if (t >= 0)
@@ -659,7 +654,7 @@ const char *get_token_value(struct gui_wps *gwps,
}
#if CONFIG_CHARGING
- case WPS_TOKEN_BATTERY_CHARGER_CONNECTED:
+ case SKIN_TOKEN_BATTERY_CHARGER_CONNECTED:
{
if(charger_input_state==CHARGER)
return "p";
@@ -668,7 +663,7 @@ const char *get_token_value(struct gui_wps *gwps,
}
#endif
#if CONFIG_CHARGING >= CHARGING_MONITOR
- case WPS_TOKEN_BATTERY_CHARGING:
+ case SKIN_TOKEN_BATTERY_CHARGING:
{
if (charge_state == CHARGING || charge_state == TOPOFF) {
return "c";
@@ -678,12 +673,12 @@ const char *get_token_value(struct gui_wps *gwps,
}
#endif
#ifdef HAVE_USB_POWER
- case WPS_TOKEN_USB_POWERED:
+ case SKIN_TOKEN_USB_POWERED:
if (usb_powered())
return "u";
return NULL;
#endif
- case WPS_TOKEN_BATTERY_SLEEPTIME:
+ case SKIN_TOKEN_BATTERY_SLEEPTIME:
{
if (get_sleep_timer() == 0)
return NULL;
@@ -694,7 +689,7 @@ const char *get_token_value(struct gui_wps *gwps,
}
}
- case WPS_TOKEN_PLAYBACK_STATUS:
+ case SKIN_TOKEN_PLAYBACK_STATUS:
{
int status = current_playmode();
/* music */
@@ -734,13 +729,13 @@ const char *get_token_value(struct gui_wps *gwps,
return buf;
}
- case WPS_TOKEN_REPEAT_MODE:
+ case SKIN_TOKEN_REPEAT_MODE:
if (intval)
*intval = global_settings.repeat_mode + 1;
snprintf(buf, buf_size, "%d", global_settings.repeat_mode);
return buf;
- case WPS_TOKEN_RTC_PRESENT:
+ case SKIN_TOKEN_RTC_PRESENT:
#if CONFIG_RTC
return "c";
#else
@@ -748,41 +743,41 @@ const char *get_token_value(struct gui_wps *gwps,
#endif
#if CONFIG_RTC
- case WPS_TOKEN_RTC_12HOUR_CFG:
+ case SKIN_TOKEN_RTC_12HOUR_CFG:
if (intval)
*intval = global_settings.timeformat + 1;
snprintf(buf, buf_size, "%d", global_settings.timeformat);
return buf;
- case WPS_TOKEN_RTC_DAY_OF_MONTH:
+ case SKIN_TOKEN_RTC_DAY_OF_MONTH:
/* d: day of month (01..31) */
snprintf(buf, buf_size, "%02d", tm->tm_mday);
if (intval)
*intval = tm->tm_mday - 1;
return buf;
- case WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED:
+ case SKIN_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED:
/* e: day of month, blank padded ( 1..31) */
snprintf(buf, buf_size, "%2d", tm->tm_mday);
if (intval)
*intval = tm->tm_mday - 1;
return buf;
- case WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED:
+ case SKIN_TOKEN_RTC_HOUR_24_ZERO_PADDED:
/* H: hour (00..23) */
snprintf(buf, buf_size, "%02d", tm->tm_hour);
if (intval)
*intval = tm->tm_hour;
return buf;
- case WPS_TOKEN_RTC_HOUR_24:
+ case SKIN_TOKEN_RTC_HOUR_24:
/* k: hour ( 0..23) */
snprintf(buf, buf_size, "%2d", tm->tm_hour);
if (intval)
*intval = tm->tm_hour;
return buf;
- case WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED:
+ case SKIN_TOKEN_RTC_HOUR_12_ZERO_PADDED:
/* I: hour (01..12) */
snprintf(buf, buf_size, "%02d",
(tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12);
@@ -790,7 +785,7 @@ const char *get_token_value(struct gui_wps *gwps,
*intval = (tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12;
return buf;
- case WPS_TOKEN_RTC_HOUR_12:
+ case SKIN_TOKEN_RTC_HOUR_12:
/* l: hour ( 1..12) */
snprintf(buf, buf_size, "%2d",
(tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12);
@@ -798,107 +793,107 @@ const char *get_token_value(struct gui_wps *gwps,
*intval = (tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12;
return buf;
- case WPS_TOKEN_RTC_MONTH:
+ case SKIN_TOKEN_RTC_MONTH:
/* m: month (01..12) */
if (intval)
*intval = tm->tm_mon + 1;
snprintf(buf, buf_size, "%02d", tm->tm_mon + 1);
return buf;
- case WPS_TOKEN_RTC_MINUTE:
+ case SKIN_TOKEN_RTC_MINUTE:
/* M: minute (00..59) */
snprintf(buf, buf_size, "%02d", tm->tm_min);
if (intval)
*intval = tm->tm_min;
return buf;
- case WPS_TOKEN_RTC_SECOND:
+ case SKIN_TOKEN_RTC_SECOND:
/* S: second (00..59) */
snprintf(buf, buf_size, "%02d", tm->tm_sec);
if (intval)
*intval = tm->tm_sec;
return buf;
- case WPS_TOKEN_RTC_YEAR_2_DIGITS:
+ case SKIN_TOKEN_RTC_YEAR_2_DIGITS:
/* y: last two digits of year (00..99) */
snprintf(buf, buf_size, "%02d", tm->tm_year % 100);
if (intval)
*intval = tm->tm_year % 100;
return buf;
- case WPS_TOKEN_RTC_YEAR_4_DIGITS:
+ case SKIN_TOKEN_RTC_YEAR_4_DIGITS:
/* Y: year (1970...) */
snprintf(buf, buf_size, "%04d", tm->tm_year + 1900);
if (intval)
*intval = tm->tm_year + 1900;
return buf;
- case WPS_TOKEN_RTC_AM_PM_UPPER:
+ case SKIN_TOKEN_RTC_AM_PM_UPPER:
/* p: upper case AM or PM indicator */
if (intval)
*intval = tm->tm_hour/12 == 0 ? 0 : 1;
return tm->tm_hour/12 == 0 ? "AM" : "PM";
- case WPS_TOKEN_RTC_AM_PM_LOWER:
+ case SKIN_TOKEN_RTC_AM_PM_LOWER:
/* P: lower case am or pm indicator */
if (intval)
*intval = tm->tm_hour/12 == 0 ? 0 : 1;
return tm->tm_hour/12 == 0 ? "am" : "pm";
- case WPS_TOKEN_RTC_WEEKDAY_NAME:
+ case SKIN_TOKEN_RTC_WEEKDAY_NAME:
/* a: abbreviated weekday name (Sun..Sat) */
return str(LANG_WEEKDAY_SUNDAY + tm->tm_wday);
- case WPS_TOKEN_RTC_MONTH_NAME:
+ case SKIN_TOKEN_RTC_MONTH_NAME:
/* b: abbreviated month name (Jan..Dec) */
return str(LANG_MONTH_JANUARY + tm->tm_mon);
- case WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON:
+ case SKIN_TOKEN_RTC_DAY_OF_WEEK_START_MON:
/* u: day of week (1..7); 1 is Monday */
if (intval)
*intval = (tm->tm_wday == 0) ? 7 : tm->tm_wday;
snprintf(buf, buf_size, "%1d", tm->tm_wday + 1);
return buf;
- case WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN:
+ case SKIN_TOKEN_RTC_DAY_OF_WEEK_START_SUN:
/* w: day of week (0..6); 0 is Sunday */
if (intval)
*intval = tm->tm_wday + 1;
snprintf(buf, buf_size, "%1d", tm->tm_wday);
return buf;
#else
- case WPS_TOKEN_RTC_DAY_OF_MONTH:
- case WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED:
- case WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED:
- case WPS_TOKEN_RTC_HOUR_24:
- case WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED:
- case WPS_TOKEN_RTC_HOUR_12:
- case WPS_TOKEN_RTC_MONTH:
- case WPS_TOKEN_RTC_MINUTE:
- case WPS_TOKEN_RTC_SECOND:
- case WPS_TOKEN_RTC_AM_PM_UPPER:
- case WPS_TOKEN_RTC_AM_PM_LOWER:
- case WPS_TOKEN_RTC_YEAR_2_DIGITS:
+ case SKIN_TOKEN_RTC_DAY_OF_MONTH:
+ case SKIN_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED:
+ case SKIN_TOKEN_RTC_HOUR_24_ZERO_PADDED:
+ case SKIN_TOKEN_RTC_HOUR_24:
+ case SKIN_TOKEN_RTC_HOUR_12_ZERO_PADDED:
+ case SKIN_TOKEN_RTC_HOUR_12:
+ case SKIN_TOKEN_RTC_MONTH:
+ case SKIN_TOKEN_RTC_MINUTE:
+ case SKIN_TOKEN_RTC_SECOND:
+ case SKIN_TOKEN_RTC_AM_PM_UPPER:
+ case SKIN_TOKEN_RTC_AM_PM_LOWER:
+ case SKIN_TOKEN_RTC_YEAR_2_DIGITS:
return "--";
- case WPS_TOKEN_RTC_YEAR_4_DIGITS:
+ case SKIN_TOKEN_RTC_YEAR_4_DIGITS:
return "----";
- case WPS_TOKEN_RTC_WEEKDAY_NAME:
- case WPS_TOKEN_RTC_MONTH_NAME:
+ case SKIN_TOKEN_RTC_WEEKDAY_NAME:
+ case SKIN_TOKEN_RTC_MONTH_NAME:
return "---";
- case WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON:
- case WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN:
+ case SKIN_TOKEN_RTC_DAY_OF_WEEK_START_MON:
+ case SKIN_TOKEN_RTC_DAY_OF_WEEK_START_SUN:
return "-";
#endif
#ifdef HAVE_LCD_CHARCELLS
- case WPS_TOKEN_PROGRESSBAR:
+ case SKIN_TOKEN_PROGRESSBAR:
{
char *end = utf8encode(data->wps_progress_pat[0], buf);
*end = '\0';
return buf;
}
- case WPS_TOKEN_PLAYER_PROGRESSBAR:
+ case SKIN_TOKEN_PLAYER_PROGRESSBAR:
if(is_new_player())
{
/* we need 11 characters (full line) for
@@ -916,7 +911,7 @@ const char *get_token_value(struct gui_wps *gwps,
#if (CONFIG_CODEC == SWCODEC)
- case WPS_TOKEN_CROSSFADE:
+ case SKIN_TOKEN_CROSSFADE:
#ifdef HAVE_CROSSFADE
if (intval)
*intval = global_settings.crossfade + 1;
@@ -926,7 +921,7 @@ const char *get_token_value(struct gui_wps *gwps,
#endif
return buf;
- case WPS_TOKEN_REPLAYGAIN:
+ case SKIN_TOKEN_REPLAYGAIN:
{
int val;
@@ -974,7 +969,7 @@ const char *get_token_value(struct gui_wps *gwps,
#endif /* (CONFIG_CODEC == SWCODEC) */
#if (CONFIG_CODEC != MAS3507D)
- case WPS_TOKEN_SOUND_PITCH:
+ case SKIN_TOKEN_SOUND_PITCH:
{
int32_t pitch = sound_get_pitch();
snprintf(buf, buf_size, "%ld.%ld",
@@ -989,7 +984,7 @@ const char *get_token_value(struct gui_wps *gwps,
#endif
#if CONFIG_CODEC == SWCODEC
- case WPS_TOKEN_SOUND_SPEED:
+ case SKIN_TOKEN_SOUND_SPEED:
{
int32_t pitch = sound_get_pitch();
int32_t speed;
@@ -1007,7 +1002,7 @@ const char *get_token_value(struct gui_wps *gwps,
}
#endif
- case WPS_TOKEN_MAIN_HOLD:
+ case SKIN_TOKEN_MAIN_HOLD:
#ifdef HAS_BUTTON_HOLD
if (button_hold())
#else
@@ -1018,7 +1013,7 @@ const char *get_token_value(struct gui_wps *gwps,
return NULL;
#ifdef HAS_REMOTE_BUTTON_HOLD
- case WPS_TOKEN_REMOTE_HOLD:
+ case SKIN_TOKEN_REMOTE_HOLD:
if (remote_button_hold())
return "r";
else
@@ -1026,20 +1021,20 @@ const char *get_token_value(struct gui_wps *gwps,
#endif
#if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
- case WPS_TOKEN_VLED_HDD:
+ case SKIN_TOKEN_VLED_HDD:
if(led_read(HZ/2))
return "h";
else
return NULL;
#endif
- case WPS_TOKEN_BUTTON_VOLUME:
+ case SKIN_TOKEN_BUTTON_VOLUME:
if (global_status.last_volume_change &&
TIME_BEFORE(current_tick, global_status.last_volume_change +
token->value.i * TIMEOUT_UNIT))
return "v";
return NULL;
- case WPS_TOKEN_LASTTOUCH:
+ case SKIN_TOKEN_LASTTOUCH:
{
#ifdef HAVE_TOUCHSCREEN
unsigned int last_touch = touchscreen_last_touch();
@@ -1051,7 +1046,7 @@ const char *get_token_value(struct gui_wps *gwps,
}
return NULL;
- case WPS_TOKEN_SETTING:
+ case SKIN_TOKEN_SETTING:
{
const struct settings_list *s = settings+token->value.i;
if (intval)
@@ -1120,14 +1115,14 @@ const char *get_token_value(struct gui_wps *gwps,
cfg_to_string(token->value.i,buf,buf_size);
return buf;
}
- case WPS_TOKEN_HAVE_TUNER:
+ case SKIN_TOKEN_HAVE_TUNER:
#if CONFIG_TUNER
if (radio_hardware_present())
return "r";
#endif
return NULL;
/* Recording tokens */
- case WPS_TOKEN_HAVE_RECORDING:
+ case SKIN_TOKEN_HAVE_RECORDING:
#ifdef HAVE_RECORDING
return "r";
#else
@@ -1135,11 +1130,11 @@ const char *get_token_value(struct gui_wps *gwps,
#endif
#ifdef HAVE_RECORDING
- case WPS_TOKEN_IS_RECORDING:
+ case SKIN_TOKEN_IS_RECORDING:
if (audio_status() == AUDIO_STATUS_RECORD)
return "r";
return NULL;
- case WPS_TOKEN_REC_FREQ: /* order from REC_FREQ_CFG_VAL_LIST */
+ case SKIN_TOKEN_REC_FREQ: /* order from REC_FREQ_CFG_VAL_LIST */
{
#if CONFIG_CODEC == SWCODEC
unsigned long samprk;
@@ -1227,7 +1222,7 @@ const char *get_token_value(struct gui_wps *gwps,
return buf;
}
#if CONFIG_CODEC == SWCODEC
- case WPS_TOKEN_REC_ENCODER:
+ case SKIN_TOKEN_REC_ENCODER:
{
int rec_format = global_settings.rec_format+1; /* WAV, AIFF, WV, MPEG */
if (intval)
@@ -1248,7 +1243,7 @@ const char *get_token_value(struct gui_wps *gwps,
break;
}
#endif
- case WPS_TOKEN_REC_BITRATE:
+ case SKIN_TOKEN_REC_BITRATE:
#if CONFIG_CODEC == SWCODEC
if (global_settings.rec_format == REC_FORMAT_MPA_L3)
{
@@ -1317,12 +1312,12 @@ const char *get_token_value(struct gui_wps *gwps,
snprintf(buf, buf_size, "%d", global_settings.rec_quality);
return buf;
#endif
- case WPS_TOKEN_REC_MONO:
+ case SKIN_TOKEN_REC_MONO:
if (!global_settings.rec_channels)
return "m";
return NULL;
- case WPS_TOKEN_REC_SECONDS:
+ case SKIN_TOKEN_REC_SECONDS:
{
int time = (audio_recorded_time() / HZ) % 60;
if (intval)
@@ -1330,7 +1325,7 @@ const char *get_token_value(struct gui_wps *gwps,
snprintf(buf, buf_size, "%02d", time);
return buf;
}
- case WPS_TOKEN_REC_MINUTES:
+ case SKIN_TOKEN_REC_MINUTES:
{
int time = (audio_recorded_time() / HZ) / 60;
if (intval)
@@ -1338,7 +1333,7 @@ const char *get_token_value(struct gui_wps *gwps,
snprintf(buf, buf_size, "%02d", time);
return buf;
}
- case WPS_TOKEN_REC_HOURS:
+ case SKIN_TOKEN_REC_HOURS:
{
int time = (audio_recorded_time() / HZ) / 3600;
if (intval)
@@ -1349,7 +1344,7 @@ const char *get_token_value(struct gui_wps *gwps,
#endif /* HAVE_RECORDING */
- case WPS_TOKEN_CURRENT_SCREEN:
+ case SKIN_TOKEN_CURRENT_SCREEN:
{
int curr_screen = current_screen();
@@ -1390,7 +1385,7 @@ const char *get_token_value(struct gui_wps *gwps,
return buf;
}
- case WPS_TOKEN_LANG_IS_RTL:
+ case SKIN_TOKEN_LANG_IS_RTL:
return lang_is_rtl() ? "r" : NULL;
default:
diff --git a/apps/gui/skin_engine/skin_tokens.h b/apps/gui/skin_engine/skin_tokens.h
index 47311312db..d259fe431c 100644
--- a/apps/gui/skin_engine/skin_tokens.h
+++ b/apps/gui/skin_engine/skin_tokens.h
@@ -23,243 +23,11 @@
#define _SKIN_TOKENS_H_
#include <stdbool.h>
-
-
-enum wps_token_type {
-
- TOKEN_MARKER_CONTROL_TOKENS = -1,
- WPS_NO_TOKEN = 0, /* for WPS tags we don't want to save as tokens */
- WPS_TOKEN_UNKNOWN,
-
- /* Markers */
- WPS_TOKEN_CHARACTER,
- WPS_TOKEN_STRING,
- WPS_TOKEN_TRANSLATEDSTRING,
-
- /* Alignment */
- WPS_TOKEN_ALIGN_LEFT,
- WPS_TOKEN_ALIGN_LEFT_RTL,
- WPS_TOKEN_ALIGN_CENTER,
- WPS_TOKEN_ALIGN_RIGHT,
- WPS_TOKEN_ALIGN_RIGHT_RTL,
-
- /* Sublines */
- WPS_TOKEN_SUBLINE_TIMEOUT,
-
- /* Conditional */
- WPS_TOKEN_CONDITIONAL,
- WPS_TOKEN_CONDITIONAL_START,
- WPS_TOKEN_CONDITIONAL_OPTION,
- WPS_TOKEN_CONDITIONAL_END,
-
- /* Viewport display */
- WPS_VIEWPORT_ENABLE,
- WPS_VIEWPORT_CUSTOMLIST,
- WPS_TOKEN_UIVIEWPORT_ENABLE,
- WPS_TOKEN_VIEWPORT_FGCOLOUR,
- WPS_TOKEN_VIEWPORT_BGCOLOUR,
-
- /* Battery */
- TOKEN_MARKER_BATTERY,
- WPS_TOKEN_BATTERY_PERCENT,
- WPS_TOKEN_BATTERY_PERCENTBAR,
- WPS_TOKEN_BATTERY_VOLTS,
- WPS_TOKEN_BATTERY_TIME,
- WPS_TOKEN_BATTERY_CHARGER_CONNECTED,
- WPS_TOKEN_BATTERY_CHARGING,
- WPS_TOKEN_BATTERY_SLEEPTIME,
- WPS_TOKEN_USB_POWERED,
-
- /* Sound */
- TOKEN_MARKER_SOUND,
-#if (CONFIG_CODEC != MAS3507D)
- WPS_TOKEN_SOUND_PITCH,
-#endif
-#if (CONFIG_CODEC == SWCODEC)
- WPS_TOKEN_SOUND_SPEED,
- WPS_TOKEN_REPLAYGAIN,
- WPS_TOKEN_CROSSFADE,
-#endif
-
- /* Time */
- TOKEN_MARKER_RTC,
- 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 */
-
- /* Database */
- TOKEN_MARKER_DATABASE,
-#ifdef HAVE_TAGCACHE
- WPS_TOKEN_DATABASE_PLAYCOUNT,
- WPS_TOKEN_DATABASE_RATING,
- WPS_TOKEN_DATABASE_AUTOSCORE,
-#endif
-
- /* File */
- TOKEN_MARKER_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,
-
- /* Image */
- TOKEN_MARKER_IMAGES,
-#ifdef HAVE_LCD_BITMAP
- 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 */
- TOKEN_MARKER_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,
-
- TOKEN_MARKER_PLAYBACK_INFO,
- /* Mode */
- WPS_TOKEN_REPEAT_MODE,
- WPS_TOKEN_PLAYBACK_STATUS,
- /* Progressbar */
- WPS_TOKEN_PROGRESSBAR,
-#ifdef HAVE_LCD_CHARCELLS
- WPS_TOKEN_PLAYER_PROGRESSBAR,
-#endif
-#ifdef HAVE_LCD_BITMAP
- /* Peakmeter */
- WPS_TOKEN_PEAKMETER,
-#endif
-
- /* Current track */
- WPS_TOKEN_TRACK_ELAPSED_PERCENT,
- WPS_TOKEN_TRACK_TIME_ELAPSED,
- WPS_TOKEN_TRACK_TIME_REMAINING,
- WPS_TOKEN_TRACK_LENGTH,
- WPS_TOKEN_TRACK_STARTING,
- WPS_TOKEN_TRACK_ENDING,
-
- /* Playlist */
- TOKEN_MARKER_PLAYLIST,
- WPS_TOKEN_PLAYLIST_ENTRIES,
- WPS_TOKEN_PLAYLIST_NAME,
- WPS_TOKEN_PLAYLIST_POSITION,
- WPS_TOKEN_PLAYLIST_SHUFFLE,
-
-
- /* buttons */
- TOKEN_MARKER_MISC,
- WPS_TOKEN_DRAW_INBUILTBAR,
- WPS_TOKEN_LIST_TITLE_TEXT,
- WPS_TOKEN_LIST_TITLE_ICON,
- WPS_TOKEN_BUTTON_VOLUME,
- WPS_TOKEN_LASTTOUCH,
-#if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
- /* Virtual LED */
- WPS_TOKEN_VLED_HDD,
-#endif
- /* Volume level */
- WPS_TOKEN_VOLUME,
- WPS_TOKEN_VOLUMEBAR,
- /* hold */
- WPS_TOKEN_MAIN_HOLD,
-#ifdef HAS_REMOTE_BUTTON_HOLD
- WPS_TOKEN_REMOTE_HOLD,
-#endif
-
- /* Setting option */
- WPS_TOKEN_SETTING,
- WPS_TOKEN_CURRENT_SCREEN,
- WPS_TOKEN_LANG_IS_RTL,
-
- /* Recording Tokens */
- TOKEN_MARKER_RECORDING,
- WPS_TOKEN_HAVE_RECORDING,
- WPS_TOKEN_IS_RECORDING,
- WPS_TOKEN_REC_FREQ,
- WPS_TOKEN_REC_ENCODER,
- WPS_TOKEN_REC_BITRATE, /* SWCODEC: MP3 bitrate, HWCODEC: MP3 "quality" */
- WPS_TOKEN_REC_MONO,
- WPS_TOKEN_REC_SECONDS,
- WPS_TOKEN_REC_MINUTES,
- WPS_TOKEN_REC_HOURS,
-
-
- /* Radio Tokens */
- TOKEN_MARKER_TUNER,
- WPS_TOKEN_HAVE_TUNER,
-#if CONFIG_TUNER
- WPS_TOKEN_TUNER_TUNED,
- WPS_TOKEN_TUNER_SCANMODE,
- WPS_TOKEN_TUNER_STEREO,
- WPS_TOKEN_TUNER_MINFREQ, /* changes based on "region" */
- WPS_TOKEN_TUNER_MAXFREQ, /* changes based on "region" */
- WPS_TOKEN_TUNER_CURFREQ,
- WPS_TOKEN_PRESET_ID, /* "id" of this preset.. really the array element number */
- WPS_TOKEN_PRESET_NAME,
- WPS_TOKEN_PRESET_FREQ,
- WPS_TOKEN_PRESET_COUNT,
- /* RDS tokens */
- WPS_TOKEN_HAVE_RDS,
-#ifdef HAVE_RDS_CAP
- WPS_TOKEN_RDS_NAME,
- WPS_TOKEN_RDS_TEXT,
-#endif
-#endif /* CONFIG_TUNER */
-
-
- TOKEN_MARKER_END, /* this needs to be the last value in this enum */
-};
+#include "tag_table.h"
struct wps_token {
- unsigned char type; /* enough to store the token type */
-
+ enum skin_token_type 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;
diff --git a/apps/gui/skin_engine/wps_debug.c b/apps/gui/skin_engine/wps_debug.c
index 59e8542eff..2ab7e5ab4e 100644
--- a/apps/gui/skin_engine/wps_debug.c
+++ b/apps/gui/skin_engine/wps_debug.c
@@ -26,7 +26,6 @@
#include <stdio.h>
#include <string.h>
-#include "skin_buffer.h"
#include "settings_list.h"
#ifdef __PCTOOL__
#ifdef WPSEDITOR
diff --git a/apps/gui/skin_engine/wps_internals.h b/apps/gui/skin_engine/wps_internals.h
index f3f83370f4..ec37560e79 100644
--- a/apps/gui/skin_engine/wps_internals.h
+++ b/apps/gui/skin_engine/wps_internals.h
@@ -24,6 +24,8 @@
#ifndef _WPS_ENGINE_INTERNALS_
#define _WPS_ENGINE_INTERNALS_
+
+
/* Timeout unit expressed in HZ. In WPS, all timeouts are given in seconds
(possibly with a decimal fraction) but stored as integer values.
E.g. 2.5 is stored as 25. This means 25 tenth of a second, i.e. 25 units.
@@ -32,6 +34,8 @@
#define DEFAULT_SUBLINE_TIME_MULTIPLIER 20 /* In TIMEOUT_UNIT's */
#include "skin_tokens.h"
+#include "tag_table.h"
+#include "skin_parser.h"
/* TODO: sort this mess out */
@@ -40,19 +44,6 @@
#include "statusbar.h"
#include "metadata.h"
-/* constants used in line_type and as refresh_mode for wps_refresh */
-#define WPS_REFRESH_STATIC (1u<<0) /* line doesn't change over time */
-#define WPS_REFRESH_DYNAMIC (1u<<1) /* line may change (e.g. time flag) */
-#define WPS_REFRESH_SCROLL (1u<<2) /* line scrolls */
-#define WPS_REFRESH_PLAYER_PROGRESS (1u<<3) /* line contains a progress bar */
-#define WPS_REFRESH_PEAK_METER (1u<<4) /* line contains a peak meter */
-#define WPS_REFRESH_STATUSBAR (1u<<5) /* refresh statusbar */
-#define WPS_REFRESH_ALL (0xffffffffu) /* to refresh all line types */
-
-/* to refresh only those lines that change over time */
-#define WPS_REFRESH_NON_STATIC (WPS_REFRESH_DYNAMIC| \
- WPS_REFRESH_PLAYER_PROGRESS| \
- WPS_REFRESH_PEAK_METER)
/* alignments */
#define WPS_ALIGN_RIGHT 32
#define WPS_ALIGN_CENTER 64
@@ -82,16 +73,16 @@ struct gui_img {
short int y; /* y-pos */
short int num_subimages; /* number of sub-images */
short int subimage_height; /* height of each sub-image */
- short int display; /* -1 for no display, 0..n to display a subimage */
struct bitmap bm;
char label;
bool loaded; /* load state */
bool always_display; /* not using the preload/display mechanism */
+ int display;
};
struct progressbar {
- enum wps_token_type type;
+ enum skin_token_type type;
struct viewport *vp;
/* regular pb */
short x;
@@ -105,8 +96,6 @@ struct progressbar {
/*progressbar image*/
struct bitmap bm;
bool have_bitmap_pb;
-
- bool draw;
};
#endif
@@ -157,45 +146,6 @@ enum wps_parse_error {
PARSE_FAIL_LIMITS_EXCEEDED,
};
-
-/* Description of a subline on the WPS */
-struct skin_subline {
-
- /* Index of the first token for this subline in the token array.
- Tokens of this subline end where tokens for the next subline
- begin. */
- unsigned short first_token_idx;
- unsigned short last_token_idx;
-
- /* Bit or'ed WPS_REFRESH_xxx */
- unsigned char line_type;
-
- /* How long the subline should be displayed, in 10ths of sec */
- unsigned char time_mult;
-
- /* pointer to the next subline in this line */
- struct skin_subline *next;
-};
-
-/* Description of a line on the WPS. A line is a set of sublines.
- A subline is displayed for a certain amount of time. After that,
- the next subline of the line is displayed. And so on. */
-struct skin_line {
-
- /* Linked list of all the sublines on this line,
- * a line *must* have at least one subline so no need to add an extra pointer */
- struct skin_subline sublines;
- /* pointer to the current subline */
- struct skin_subline *curr_subline;
-
- /* When the next subline of this line should be displayed
- (absolute time value in ticks) */
- long subline_expire_time;
-
- /* pointer to the next line */
- struct skin_line *next;
-};
-
#define VP_DRAW_HIDEABLE 0x1
#define VP_DRAW_HIDDEN 0x2
#define VP_DRAW_WASHIDDEN 0x4
@@ -206,7 +156,6 @@ struct skin_line {
#define VP_INFO_LABEL 0x80
struct skin_viewport {
struct viewport vp; /* The LCD viewport struct */
- struct skin_line *lines;
char hidden_flags;
char label;
unsigned start_fgcolour;
@@ -236,9 +185,6 @@ struct touchregion {
};
#endif
-#define MAX_PLAYLISTLINE_TOKENS 16
-#define MAX_PLAYLISTLINE_STRINGS 8
-#define MAX_PLAYLISTLINE_STRLEN 8
enum info_line_type {
TRACK_HAS_INFO = 0,
TRACK_HAS_NO_INFO
@@ -250,36 +196,50 @@ struct playlistviewer {
#ifdef HAVE_TC_RAMCACHE
struct mp3entry tempid3;
#endif
- struct {
- enum wps_token_type tokens[MAX_PLAYLISTLINE_TOKENS];
- char strings[MAX_PLAYLISTLINE_STRINGS][MAX_PLAYLISTLINE_STRLEN];
- int count;
- bool scroll;
- } lines[2];
+ struct skin_element *lines[2];
};
#ifdef HAVE_ALBUMART
struct skin_albumart {
/* Album art support */
- struct viewport *vp;/* The viewport this is in */
int x;
int y;
int width;
int height;
- bool draw;
unsigned char xalign; /* WPS_ALBUMART_ALIGN_LEFT, _CENTER, _RIGHT */
unsigned char yalign; /* WPS_ALBUMART_ALIGN_TOP, _CENTER, _BOTTOM */
unsigned char state; /* WPS_ALBUMART_NONE, _CHECK, _LOAD */
+
+ struct viewport *vp;
+ int draw_handle;
};
#endif
+
+struct line {
+ int timeout; /* if inside a line alternator */
+ unsigned update_mode;
+};
+
+struct line_alternator {
+ int current_line;
+ unsigned long last_change_tick;
+};
+
+struct conditional {
+ int last_value;
+ struct wps_token *token;
+};
+
+
/* wps_data
this struct holds all necessary data which describes the
viewable content of a wps */
struct wps_data
{
+ struct skin_element *tree;
#ifdef HAVE_LCD_BITMAP
struct skin_token_list *images;
struct skin_token_list *progressbars;
@@ -291,16 +251,10 @@ struct wps_data
#ifdef HAVE_TOUCHSCREEN
struct skin_token_list *touchregions;
#endif
- struct skin_token_list *viewports;
- struct skin_token_list *strings;
#ifdef HAVE_ALBUMART
struct skin_albumart *albumart;
int playback_aa_slot;
#endif
- struct wps_token *tokens;
- /* Total number of tokens in the WPS. During WPS parsing, this is
- the index of the token being parsed. */
- int num_tokens;
#ifdef HAVE_LCD_BITMAP
bool peak_meter_enabled;
diff --git a/apps/gui/statusbar-skinned.c b/apps/gui/statusbar-skinned.c
index 168b17fa38..8eb082d50f 100644
--- a/apps/gui/statusbar-skinned.c
+++ b/apps/gui/statusbar-skinned.c
@@ -27,6 +27,9 @@
#include "appevents.h"
#include "screens.h"
#include "screen_access.h"
+#include "strlcpy.h"
+#include "skin_parser.h"
+#include "skin_buffer.h"
#include "skin_engine/skin_engine.h"
#include "skin_engine/wps_internals.h"
#include "viewport.h"
@@ -45,26 +48,55 @@ static struct wps_sync_data sb_skin_sync_data = { .do_full_update = false
/* initial setup of wps_data */
static int update_delay = DEFAULT_UPDATE_DELAY;
-
-bool sb_set_title_text(char* title, enum themable_icons icon, enum screen_type screen)
+struct wps_token *found_token;
+static int set_title_worker(char* title, enum themable_icons icon,
+ struct wps_data *data, struct skin_element *root)
{
- int i;
- bool retval = false;
- for(i=0; i<sb_skin_data[screen].num_tokens; i++)
+ int retval = 0;
+ struct skin_element *element = root;
+ while (element)
{
- if (sb_skin_data[screen].tokens[i].type == WPS_TOKEN_LIST_TITLE_TEXT)
+ struct wps_token *token = NULL;
+ if (element->type == CONDITIONAL)
+ {
+ struct conditional *cond = (struct conditional *)element->data;
+ token = cond->token;
+ }
+ else if (element->type == TAG)
+ {
+ token = (struct wps_token *)element->data;
+ }
+ if (token)
{
- sb_skin_data[screen].tokens[i].value.data = title;
- retval = true;
+ if (token->type == SKIN_TOKEN_LIST_TITLE_TEXT)
+ {
+ found_token = token;
+ token->value.data = title;
+ retval = 1;
+ }
+ else if (token->type == SKIN_TOKEN_LIST_TITLE_ICON)
+ {
+ /* Icon_NOICON == -1 which the skin engine wants at position 1, so + 2 */
+ token->value.i = icon+2;
+ }
}
- else if (sb_skin_data[screen].tokens[i].type == WPS_TOKEN_LIST_TITLE_ICON)
+ if (element->children_count)
{
- /* Icon_NOICON == -1 which the skin engine wants at position 1, so + 2 */
- sb_skin_data[screen].tokens[i].value.i = icon+2;
+ int i;
+ for (i=0; i<element->children_count; i++)
+ retval |= set_title_worker(title, icon, data, element->children[i]);
}
+ element = element->next;
}
return retval;
}
+
+bool sb_set_title_text(char* title, enum themable_icons icon, enum screen_type screen)
+{
+ bool retval = set_title_worker(title, icon, &sb_skin_data[screen],
+ sb_skin_data[screen].tree) > 0;
+ return retval;
+}
void sb_skin_data_load(enum screen_type screen, const char *buf, bool isfile)
@@ -75,18 +107,22 @@ void sb_skin_data_load(enum screen_type screen, const char *buf, bool isfile)
success = buf && skin_data_load(screen, data, buf, isfile);
if (success)
- { /* hide the sb's default viewport because it has nasty effect with stuff
+ {
+ /* hide the sb's default viewport because it has nasty effect with stuff
* not part of the statusbar,
* hence .sbs's without any other vps are unsupported*/
struct skin_viewport *vp = find_viewport(VP_DEFAULT_LABEL, data);
- struct skin_token_list *next_vp = data->viewports->next;
-
- if (!next_vp)
- { /* no second viewport, let parsing fail */
- success = false;
+ struct skin_element *next_vp = data->tree->next;
+
+ if (vp)
+ {
+ if (!next_vp)
+ { /* no second viewport, let parsing fail */
+ success = false;
+ }
+ /* hide this viewport, forever */
+ vp->hidden_flags = VP_NEVER_VISIBLE;
}
- /* hide this viewport, forever */
- vp->hidden_flags = VP_NEVER_VISIBLE;
sb_set_info_vp(screen, VP_INFO_LABEL|VP_DEFAULT_LABEL);
}
@@ -135,7 +171,7 @@ bool sb_set_backdrop(enum screen_type screen, char* filename)
else
#endif
buf_size = LCD_BACKDROP_BYTES;
- sb_skin[screen].data->backdrop = skin_buffer_alloc(buf_size);
+ sb_skin[screen].data->backdrop = (char*)skin_buffer_alloc(buf_size);
if (!sb_skin[screen].data->backdrop)
return false;
}
@@ -150,6 +186,8 @@ void sb_skin_update(enum screen_type screen, bool force)
{
static long next_update[NB_SCREENS] = {0};
int i = screen;
+ if (!sb_skin_data[screen].wps_loaded)
+ return;
if (TIME_AFTER(current_tick, next_update[i]) || force)
{
#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
@@ -158,7 +196,7 @@ void sb_skin_update(enum screen_type screen, bool force)
if (lcd_active() || (i != SCREEN_MAIN))
#endif
skin_update(&sb_skin[i], force?
- WPS_REFRESH_ALL : WPS_REFRESH_NON_STATIC);
+ SKIN_REFRESH_ALL : SKIN_REFRESH_NON_STATIC);
next_update[i] = current_tick + update_delay; /* don't update too often */
sb_skin[SCREEN_MAIN].sync_data->do_full_update = false;
}
@@ -216,7 +254,30 @@ void sb_create_from_settings(enum screen_type screen)
if (ptr2[0] && ptr2[0] != '-') /* from ui viewport setting */
{
+ char *comma = ptr;
+ int param_count = 0;
len = snprintf(ptr, remaining, "%%ax%%Vi(-,%s)\n", ptr2);
+ /* The config put the colours at the end of the viewport,
+ * they need to be stripped for the skin code though */
+ do {
+ param_count++;
+ comma = strchr(comma+1, ',');
+
+ } while (comma && param_count < 6);
+ if (comma)
+ {
+ char *end = comma;
+ char fg[8], bg[8];
+ int i = 0;
+ comma++;
+ while (*comma != ',')
+ fg[i++] = *comma++;
+ fg[i] = '\0'; comma++; i=0;
+ while (*comma != ')')
+ bg[i++] = *comma++;
+ bg[i] = '\0';
+ len += snprintf(end, remaining-len, ") %%Vf(%s) %%Vb(%s)\n", fg, bg);
+ }
}
else
{
diff --git a/apps/gui/theme_settings.c b/apps/gui/theme_settings.c
index f3628f60db..e9862eda3a 100644
--- a/apps/gui/theme_settings.c
+++ b/apps/gui/theme_settings.c
@@ -30,14 +30,21 @@
#include "settings.h"
#include "wps.h"
#include "file.h"
+#include "buffer.h"
#if CONFIG_TUNER
#include "radio.h"
#endif
#include "skin_engine/skin_engine.h"
-#include "skin_engine/skin_fonts.h"
+#include "skin_buffer.h"
#include "statusbar-skinned.h"
#include "bootchart.h"
+static char *skin_buffer = NULL;
+void theme_init_buffer(void)
+{
+ skin_buffer = buffer_alloc(SKIN_BUFFER_SIZE);
+}
+
/* call this after loading a .wps/.rwps or other skin files, so that the
* skin buffer is reset properly
@@ -71,9 +78,10 @@ void settings_apply_skins(void)
{
char buf[MAX_PATH];
/* re-initialize the skin buffer before we start reloading skins */
- skin_buffer_init();
enum screen_type screen = SCREEN_MAIN;
unsigned int i;
+
+ skin_buffer_init(skin_buffer, SKIN_BUFFER_SIZE);
#ifdef HAVE_LCD_BITMAP
skin_backdrop_init();
skin_font_init();
diff --git a/apps/gui/viewport.c b/apps/gui/viewport.c
index 7d79e5f04a..2b1cc9eb05 100644
--- a/apps/gui/viewport.c
+++ b/apps/gui/viewport.c
@@ -310,13 +310,6 @@ static void set_default_align_flags(struct viewport *vp)
#endif /* HAVE_LCD_BITMAP */
#endif /* __PCTOOL__ */
-#ifdef HAVE_LCD_COLOR
-#define ARG_STRING(_depth) ((_depth) == 2 ? "dddddgg":"dddddcc")
-#else
-#define ARG_STRING(_depth) "dddddgg"
-#endif
-
-
void viewport_set_fullscreen(struct viewport *vp,
const enum screen_type screen)
{
@@ -416,81 +409,4 @@ int get_viewport_default_colour(enum screen_type screen, bool fgcolour)
#endif /* LCD_DEPTH > 1 || LCD_REMOTE_DEPTH > 1 */
}
-const char* viewport_parse_viewport(struct viewport *vp,
- enum screen_type screen,
- const char *bufptr,
- const char separator)
-{
- /* parse the list to the viewport struct */
- const char *ptr = bufptr;
- uint32_t set = 0;
-
- enum {
- PL_X = 0,
- PL_Y,
- PL_WIDTH,
- PL_HEIGHT,
- PL_FONT,
- };
-
- if (!(ptr = parse_list("ddddd", &set, separator, ptr,
- &vp->x, &vp->y, &vp->width, &vp->height, &vp->font)))
- return NULL;
-
- /* X and Y *must* be set */
- if (!LIST_VALUE_PARSED(set, PL_X) || !LIST_VALUE_PARSED(set, PL_Y))
- return NULL;
- /* check for negative values */
- if (vp->x < 0)
- vp->x += screens[screen].lcdwidth;
- if (vp->y < 0)
- vp->y += screens[screen].lcdheight;
-
- /* fix defaults,
- * and negative width/height which means "extend to edge minus value */
- if (!LIST_VALUE_PARSED(set, PL_WIDTH))
- vp->width = screens[screen].lcdwidth - vp->x;
- else if (vp->width < 0)
- vp->width = (vp->width + screens[screen].lcdwidth) - vp->x;
- if (!LIST_VALUE_PARSED(set, PL_HEIGHT))
- vp->height = screens[screen].lcdheight - vp->y;
- else if (vp->height < 0)
- vp->height = (vp->height + screens[screen].lcdheight) - vp->y;
-
-#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
- vp->fg_pattern = get_viewport_default_colour(screen, true);
- vp->bg_pattern = get_viewport_default_colour(screen, false);
-#endif /* LCD_DEPTH > 1 || LCD_REMOTE_DEPTH > 1 */
-
-#ifdef HAVE_LCD_COLOR
- vp->lss_pattern = global_settings.lss_color;
- vp->lse_pattern = global_settings.lse_color;
- vp->lst_pattern = global_settings.lst_color;
-#endif
-
- /* Validate the viewport dimensions - we know that the numbers are
- non-negative integers, ignore bars and assume the viewport takes them
- * into account */
- if ((vp->x >= screens[screen].lcdwidth) ||
- ((vp->x + vp->width) > screens[screen].lcdwidth) ||
- (vp->y >= screens[screen].lcdheight) ||
- ((vp->y + vp->height) > screens[screen].lcdheight))
- {
- return NULL;
- }
-
- /* Default to using the user font if the font was an invalid number or '-'
- * font 1 is *always* the UI font for the current screen
- * 2 is always the first extra font */
- if (!LIST_VALUE_PARSED(set, PL_FONT))
- vp->font = FONT_UI;
-
- /* Set the defaults for fields not user-specified */
- vp->drawmode = DRMODE_SOLID;
-#ifndef __PCTOOL__
- set_default_align_flags(vp);
-#endif
-
- return ptr;
-}
#endif
diff --git a/apps/gui/viewport.h b/apps/gui/viewport.h
index 943cac2451..51ab35e575 100644
--- a/apps/gui/viewport.h
+++ b/apps/gui/viewport.h
@@ -74,25 +74,4 @@ bool viewport_point_within_vp(const struct viewport *vp,
#endif /* __PCTOOL__ */
-#ifdef HAVE_LCD_BITMAP
-
-/*
- * Parse a viewport definition (vp_def), which looks like:
- *
- * Screens with depth > 1:
- * X|Y|width|height|font|foregorund color|background color
- * Screens with depth = 1:
- * X|Y|width|height|font
- *
- * | is a separator and can be specified via the parameter
- *
- * Returns the pointer to the char after the last character parsed
- * if everything went OK or NULL if an error happened (some values
- * not specified in the definition)
- */
-const char* viewport_parse_viewport(struct viewport *vp,
- enum screen_type screen,
- const char *vp_def,
- const char separator);
-#endif /* HAVE_LCD_BITMAP */
#endif /* __VIEWPORT_H__ */
diff --git a/apps/gui/wps.c b/apps/gui/wps.c
index a582afa76b..7dca6454e0 100644
--- a/apps/gui/wps.c
+++ b/apps/gui/wps.c
@@ -175,7 +175,7 @@ void fade(bool fade_in, bool updatewps)
if (updatewps)
{
FOR_NB_SCREENS(i)
- skin_update(&gui_wps[i], WPS_REFRESH_NON_STATIC);
+ skin_update(&gui_wps[i], SKIN_REFRESH_NON_STATIC);
}
sleep(1);
}
@@ -191,7 +191,7 @@ void fade(bool fade_in, bool updatewps)
if (updatewps)
{
FOR_NB_SCREENS(i)
- skin_update(&gui_wps[i], WPS_REFRESH_NON_STATIC);
+ skin_update(&gui_wps[i], SKIN_REFRESH_NON_STATIC);
}
sleep(1);
}
@@ -212,7 +212,7 @@ void fade(bool fade_in, bool updatewps)
static bool update_onvol_change(struct gui_wps * gwps)
{
- skin_update(gwps, WPS_REFRESH_NON_STATIC);
+ skin_update(gwps, SKIN_REFRESH_NON_STATIC);
#ifdef HAVE_LCD_CHARCELLS
splashf(0, "Vol: %3d dB",
@@ -372,8 +372,8 @@ bool ffwd_rew(int button)
FOR_NB_SCREENS(i)
{
skin_update(&gui_wps[i],
- WPS_REFRESH_PLAYER_PROGRESS |
- WPS_REFRESH_DYNAMIC);
+ SKIN_REFRESH_PLAYER_PROGRESS |
+ SKIN_REFRESH_DYNAMIC);
}
break;
@@ -390,7 +390,7 @@ bool ffwd_rew(int button)
#endif
#ifdef HAVE_LCD_CHARCELLS
FOR_NB_SCREENS(i)
- skin_update(&gui_wps[i], WPS_REFRESH_ALL);
+ skin_update(&gui_wps[i], SKIN_REFRESH_ALL);
#endif
exit = true;
break;
@@ -662,7 +662,7 @@ static void gwps_enter_wps(void)
display->backdrop_show(gwps->data->backdrop);
#endif
display->clear_display();
- skin_update(gwps, WPS_REFRESH_ALL);
+ skin_update(gwps, SKIN_REFRESH_ALL);
#ifdef HAVE_TOUCHSCREEN
skin_disarm_touchregions(gui_wps[i].data);
@@ -1116,7 +1116,7 @@ long gui_wps_show(void)
#endif
{
skin_update(&gui_wps[i], wps_sync_data.do_full_update ?
- WPS_REFRESH_ALL : WPS_REFRESH_NON_STATIC);
+ SKIN_REFRESH_ALL : SKIN_REFRESH_NON_STATIC);
}
}
wps_sync_data.do_full_update = false;
diff --git a/apps/main.c b/apps/main.c
index f1f30ce2b5..6c6d09cbaa 100644
--- a/apps/main.c
+++ b/apps/main.c
@@ -357,6 +357,7 @@ static void init(void)
tree_mem_init();
filetype_init();
playlist_init();
+ theme_init_buffer();
#if CONFIG_CODEC != SWCODEC
mp3_init( global_settings.volume,
@@ -639,6 +640,7 @@ static void init(void)
#if CONFIG_CODEC == SWCODEC
tdspeed_init();
#endif /* CONFIG_CODEC == SWCODEC */
+ theme_init_buffer();
#if CONFIG_CODEC != SWCODEC
/* No buffer allocation (see buffer.c) may take place after the call to
diff --git a/apps/menus/main_menu.c b/apps/menus/main_menu.c
index 2a4b344e3b..a64b1f8e47 100644
--- a/apps/menus/main_menu.c
+++ b/apps/menus/main_menu.c
@@ -48,7 +48,7 @@
#include "version.h"
#include "time.h"
#include "wps.h"
-#include "skin_engine/skin_buffer.h"
+#include "skin_buffer.h"
static const struct browse_folder_info config = {ROCKBOX_DIR, SHOW_CFG};
diff --git a/apps/misc.c b/apps/misc.c
index bae8dfbd07..c378133ab2 100644
--- a/apps/misc.c
+++ b/apps/misc.c
@@ -937,142 +937,23 @@ int hex_to_rgb(const char* hex, int* color)
#endif /* HAVE_LCD_COLOR */
#ifdef HAVE_LCD_BITMAP
-/* A simplified scanf - used (at time of writing) by wps parsing functions.
-
- fmt - char array specifying the format of each list option. Valid values
- are: d - int
- s - string (sets pointer to string, without copying)
- c - hex colour (RGB888 - e.g. ff00ff)
- g - greyscale "colour" (0-3)
- set_vals - if not NULL 1 is set in the bitplace if the item was read OK
- 0 if not read.
- first item is LSB, (max 32 items! )
- Stops parseing if an item is invalid unless the item == '-'
- sep - list separator (e.g. ',' or '|')
- str - string to parse, must be terminated by 0 or sep
- ... - pointers to store the parsed values
-
- return value - pointer to char after parsed data, 0 if there was an error.
-
-*/
-
/* '0'-'3' are ASCII 0x30 to 0x33 */
#define is0123(x) (((x) & 0xfc) == 0x30)
-const char* parse_list(const char *fmt, uint32_t *set_vals,
- const char sep, const char* str, ...)
+bool parse_color(char *text, int *value)
{
- va_list ap;
- const char* p = str, *f = fmt;
- const char** s;
- int* d;
- bool set, is_negative;
- int i=0;
-
- va_start(ap, str);
- if (set_vals)
- *set_vals = 0;
- while (*fmt)
- {
- /* Check for separator, if we're not at the start */
- if (f != fmt)
- {
- if (*p != sep)
- goto err;
- p++;
- }
- set = false;
- switch (*fmt++)
- {
- case 's': /* string - return a pointer to it (not a copy) */
- s = va_arg(ap, const char **);
-
- *s = p;
- while (*p && *p != sep && *p != ')')
- p++;
- set = (s[0][0]!='-') && (s[0][1]!=sep && s[0][1]!=')') ;
- break;
-
- case 'd': /* int */
- is_negative = false;
- d = va_arg(ap, int*);
-
- if (*p == '-' && isdigit(*(p+1)))
- {
- is_negative = true;
- p++;
- }
- if (!isdigit(*p))
- {
- if (!set_vals || *p != '-')
- goto err;
- p++;
- }
- else
- {
- *d = *p++ - '0';
- while (isdigit(*p))
- *d = (*d * 10) + (*p++ - '0');
- set = true;
- if (is_negative)
- *d *= -1;
- }
-
- break;
-
+ (void)text; (void)value; /* silence warnings on mono bitmap */
#ifdef HAVE_LCD_COLOR
- case 'c': /* colour (rrggbb - e.g. f3c1a8) */
- d = va_arg(ap, int*);
-
- if (hex_to_rgb(p, d) < 0)
- {
- if (!set_vals || *p != '-')
- goto err;
- p++;
- }
- else
- {
- p += 6;
- set = true;
- }
-
- break;
+ if (hex_to_rgb(text, value) < 0)
+ return false;
#endif
#if LCD_DEPTH == 2 || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH == 2)
- case 'g': /* greyscale colour (0-3) */
- d = va_arg(ap, int*);
-
- if (!is0123(*p))
- {
- if (!set_vals || *p != '-')
- goto err;
- p++;
- }
- else
- {
- *d = *p++ - '0';
- set = true;
- }
-
- break;
+ if (!is0123(*text))
+ return false;
+ *value = *text - '0';
#endif
-
- default: /* Unknown format type */
- goto err;
- break;
- }
- if (set_vals && set)
- *set_vals |= BIT_N(i);
- i++;
- }
-
- va_end(ap);
- return p;
-
-err:
- va_end(ap);
- return NULL;
+ return true;
}
/* only used in USB HID and set_time screen */
diff --git a/apps/misc.h b/apps/misc.h
index 34f754bda3..58a9085d55 100644
--- a/apps/misc.h
+++ b/apps/misc.h
@@ -94,16 +94,7 @@ bool dir_exists(const char *path);
char *strip_extension(char* buffer, int buffer_size, const char *filename);
#ifdef HAVE_LCD_BITMAP
-/* A simplified scanf */
-/*
- * Checks whether the value at position 'position' was really read
- * during a call to 'parse_list'
- * - position: 0-based number of the value
- * - valid_vals: value after the call to 'parse_list'
- */
-#define LIST_VALUE_PARSED(setvals, position) ((setvals) & BIT_N(position))
-const char* parse_list(const char *fmt, uint32_t *set_vals,
- const char sep, const char* str, ...);
+bool parse_color(char *text, int *value);
/* only used in USB HID and set_time screen */
#if defined(USB_ENABLE_HID) || (CONFIG_RTC != 0)
diff --git a/apps/radio/radio.c b/apps/radio/radio.c
index 65a34f1d2a..17f3d89bfc 100644
--- a/apps/radio/radio.c
+++ b/apps/radio/radio.c
@@ -800,8 +800,8 @@ int radio_screen(void)
if (restore)
fms_fix_displays(FMS_ENTER);
FOR_NB_SCREENS(i)
- skin_update(fms_get(i), restore ? WPS_REFRESH_ALL :
- WPS_REFRESH_NON_STATIC);
+ skin_update(fms_get(i), restore ? SKIN_REFRESH_ALL :
+ SKIN_REFRESH_NON_STATIC);
restore = false;
}
}
diff --git a/apps/recorder/albumart.h b/apps/recorder/albumart.h
index 51f456d175..0f50979a1a 100644
--- a/apps/recorder/albumart.h
+++ b/apps/recorder/albumart.h
@@ -35,9 +35,11 @@
bool find_albumart(const struct mp3entry *id3, char *buf, int buflen,
struct dim *dim);
-/* Draw the album art bitmap from the given handle ID onto the given WPS.
+#ifndef PLUGIN
+/* Draw the album art bitmap from the given handle ID onto the given Skin.
Call with clear = true to clear the bitmap instead of drawing it. */
void draw_album_art(struct gui_wps *gwps, int handle_id, bool clear);
+#endif
bool search_albumart_files(const struct mp3entry *id3, const char *size_string,
char *buf, int buflen);
diff --git a/apps/settings.h b/apps/settings.h
index 1cf43d9a2c..63305b5ae7 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -260,6 +260,7 @@ void sound_settings_apply(void);
* skin buffer is reset properly
*/
void settings_apply_skins(void);
+void theme_init_buffer(void);
void settings_apply(bool read_disk);
void settings_apply_pm_range(void);
diff --git a/lib/skin_parser/SOURCES b/lib/skin_parser/SOURCES
index 3024797255..37a6e9a03c 100644
--- a/lib/skin_parser/SOURCES
+++ b/lib/skin_parser/SOURCES
@@ -1,6 +1,6 @@
skin_buffer.c
skin_parser.c
-#ifndef ROCKBOX
+#if !defined(ROCKBOX) || defined(__PCTOOL__)
skin_debug.c
#endif
skin_scan.c
diff --git a/lib/skin_parser/skin_buffer.c b/lib/skin_parser/skin_buffer.c
index 05cdc0ce03..69d9d273bd 100644
--- a/lib/skin_parser/skin_buffer.c
+++ b/lib/skin_parser/skin_buffer.c
@@ -24,21 +24,19 @@
#include <string.h>
#include <stdlib.h>
+#include "skin_buffer.h"
+
#ifdef ROCKBOX
-#define SKIN_BUFFER_SIZE (400*1024) /* Excessivly large for now */
-static unsigned char buffer[SKIN_BUFFER_SIZE];
-static unsigned char *buffer_front = NULL; /* start of the free space,
- increases with allocation*/
+static size_t buf_size;
+static unsigned char *buffer_start = NULL;
+static unsigned char *buffer_front = NULL;
#endif
-void skin_buffer_init(void)
+void skin_buffer_init(char* buffer, size_t size)
{
#if defined(ROCKBOX)
- {
- /* reset the buffer.... */
- buffer_front = buffer;
- //TODO: buf_size = size;
- }
+ buffer_start = buffer_front = buffer;
+ buf_size = size;
#endif
}
@@ -46,7 +44,9 @@ void skin_buffer_init(void)
void* skin_buffer_alloc(size_t size)
{
void *retval = NULL;
-#ifdef ROCKBOX
+#ifdef ROCKBOX
+ if (size > skin_buffer_freespace())
+ return NULL;
retval = buffer_front;
buffer_front += size;
/* 32-bit aligned */
@@ -62,10 +62,22 @@ void* skin_buffer_alloc(size_t size)
/* get the number of bytes currently being used */
size_t skin_buffer_usage(void)
{
- return buffer_front - buffer;
+ return buffer_front - buffer_start;
}
size_t skin_buffer_freespace(void)
{
- return SKIN_BUFFER_SIZE - skin_buffer_usage();
+ return buf_size - skin_buffer_usage();
+}
+
+static unsigned char *saved_buffer_pos = NULL;
+void skin_buffer_save_position(void)
+{
+ saved_buffer_pos = buffer_front;
+}
+
+void skin_buffer_restore_position(void)
+{
+ if (saved_buffer_pos)
+ buffer_front = saved_buffer_pos;
}
#endif
diff --git a/lib/skin_parser/skin_buffer.h b/lib/skin_parser/skin_buffer.h
index ff477da539..1698b8afb2 100644
--- a/lib/skin_parser/skin_buffer.h
+++ b/lib/skin_parser/skin_buffer.h
@@ -25,11 +25,15 @@
#include <stdlib.h>
#ifndef _SKIN_BUFFFER_H_
#define _SKIN_BUFFFER_H_
-void skin_buffer_init(size_t size);
+void skin_buffer_init(char* buffer, size_t size);
/* Allocate size bytes from the buffer */
void* skin_buffer_alloc(size_t size);
/* get the number of bytes currently being used */
size_t skin_buffer_usage(void);
size_t skin_buffer_freespace(void);
+
+/* save and restore a buffer position incase a skin fails to load */
+void skin_buffer_save_position(void);
+void skin_buffer_restore_position(void);
#endif
diff --git a/lib/skin_parser/skin_debug.c b/lib/skin_parser/skin_debug.c
index c03b32e910..88ad209cce 100644
--- a/lib/skin_parser/skin_debug.c
+++ b/lib/skin_parser/skin_debug.c
@@ -35,6 +35,7 @@ extern char* skin_start;
/* Global error variables */
int error_line;
int error_col;
+char *error_line_start;
char* error_message;
/* Debugging functions */
@@ -48,6 +49,7 @@ void skin_error(enum skin_errorcode error, char* cursor)
cursor--;
error_col++;
}
+ error_line_start = cursor+1;
error_line = skin_line;
@@ -285,4 +287,42 @@ void skin_debug_indent()
for(i = 0; i < debug_indent_level; i++)
printf(" ");
}
+
#endif
+
+#define MIN(a,b) ((a<b)?(a):(b))
+void skin_error_format_message()
+{
+ int i;
+ char text[128];
+ char* line_end = strchr(error_line_start, '\n');
+ int len = MIN(line_end - error_line_start, 80);
+ if (!line_end)
+ len = strlen(error_line_start);
+ printf("Error on line %d.\n", error_line);
+ error_col--;
+ if (error_col <= 10)
+ {
+ strncpy(text, error_line_start, len);
+ text[len] = '\0';
+ }
+ else
+ {
+ int j;
+ /* make it fit nicely.. "<start few chars>...<10 chars><error>" */
+ strncpy(text, error_line_start, 6);
+ i = 5;
+ text[i++] = '.';
+ text[i++] = '.';
+ text[i++] = '.';
+ for (j=error_col-10; error_line_start[j] && error_line_start[j] != '\n'; j++)
+ text[i++] = error_line_start[j];
+ text[i] = '\0';
+ error_col = 18;
+ }
+ printf("%s\n", text);
+ for (i=0; i<error_col; i++)
+ text[i] = ' ';
+ snprintf(&text[i],64, "^ \'%s\' Here", error_message);
+ printf("%s\n", text);
+}
diff --git a/lib/skin_parser/skin_debug.h b/lib/skin_parser/skin_debug.h
index fbff5cbb4c..c3538083d2 100644
--- a/lib/skin_parser/skin_debug.h
+++ b/lib/skin_parser/skin_debug.h
@@ -28,8 +28,12 @@ extern "C"
{
#endif
+#if !defined(ROCKBOX) || defined(__PCTOOL__)
+#define SKINPARSER_DEBUG
+#endif
+
#include "skin_parser.h"
-#ifndef ROCKBOX
+#ifdef SKINPARSER_DEBUG
/* Debugging functions */
void skin_error(enum skin_errorcode error, char* cursor);
int skin_error_line(void);
@@ -37,6 +41,7 @@ int skin_error_col(void);
char* skin_error_message(void);
void skin_clear_errors(void);
void skin_debug_tree(struct skin_element* root);
+void skin_error_format_message();
/* Auxiliary debug functions */
void skin_debug_params(int count, struct skin_tag_parameter params[]);
@@ -46,7 +51,7 @@ void skin_debug_indent(void);
#define skin_error(...)
#define skin_clear_errors()
-#endif /* !ROCKBOX */
+#endif /* SKINPARSER_DEBUG */
#ifdef __cplusplus
diff --git a/lib/skin_parser/skin_parser.c b/lib/skin_parser/skin_parser.c
index 3e23067258..13c7b55e5e 100644
--- a/lib/skin_parser/skin_parser.c
+++ b/lib/skin_parser/skin_parser.c
@@ -21,6 +21,7 @@
#include <stdlib.h>
#include <stdio.h>
+#include <stdbool.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>
@@ -37,6 +38,11 @@ int skin_line = 0;
char* skin_start = 0;
int viewport_line = 0;
+#ifdef ROCKBOX
+static skin_callback callback = NULL;
+static void* callback_data;
+#endif
+
/* Auxiliary parsing functions (not visible at global scope) */
static struct skin_element* skin_parse_viewport(char** document);
static struct skin_element* skin_parse_line(char** document);
@@ -55,10 +61,23 @@ static int skin_parse_comment(struct skin_element* element, char** document);
static struct skin_element* skin_parse_code_as_arg(char** document);
+static void skip_whitespace(char** document)
+{
+ while(**document == ' ' || **document == '\t')
+ (*document)++;
+}
+#ifdef ROCKBOX
+struct skin_element* skin_parse(const char* document,
+ skin_callback cb, void* cb_data)
+
+{
+ callback = cb;
+ callback_data = cb_data;
+#else
struct skin_element* skin_parse(const char* document)
{
-
+#endif
struct skin_element* root = NULL;
struct skin_element* last = NULL;
@@ -94,7 +113,6 @@ struct skin_element* skin_parse(const char* document)
last = last->next;
}
-
return root;
}
@@ -107,6 +125,8 @@ static struct skin_element* skin_parse_viewport(char** document)
struct skin_element* retval = NULL;
retval = skin_alloc_element();
+ if (!retval)
+ return NULL;
retval->type = VIEWPORT;
retval->children_count = 1;
retval->line = skin_line;
@@ -129,11 +149,18 @@ static struct skin_element* skin_parse_viewport(char** document)
skin_line++;
}
}
+#ifdef ROCKBOX
+ else if (callback)
+ {
+ if (callback(retval, callback_data) == CALLBACK_ERROR)
+ return NULL;
+ }
+#endif
retval->children_count = 1;
retval->children = skin_alloc_children(1);
-
-
+ if (!retval->children)
+ return NULL;
do
{
@@ -199,7 +226,6 @@ static struct skin_element* skin_parse_viewport(char** document)
return NULL;
}
-
/* Making sure last is at the end */
while(last->next)
last = last->next;
@@ -245,6 +271,8 @@ static struct skin_element* skin_parse_line_optional(char** document,
/* A wrapper for the line */
retval = skin_alloc_element();
+ if (!retval)
+ return NULL;
retval->type = LINE;
retval->line = skin_line;
if(*cursor != '\0' && *cursor != '\n' && *cursor != MULTILINESYM
@@ -261,7 +289,24 @@ static struct skin_element* skin_parse_line_optional(char** document,
}
if(retval->children_count > 0)
+ {
retval->children = skin_alloc_children(1);
+ if (!retval->children)
+ return NULL;
+ }
+
+#ifdef ROCKBOX
+ if (callback)
+ {
+ switch (callback(retval, callback_data))
+ {
+ case CALLBACK_ERROR:
+ return NULL;
+ default:
+ break;
+ }
+ }
+#endif
while(*cursor != '\n' && *cursor != '\0' && *cursor != MULTILINESYM
&& !((*cursor == ARGLISTSEPERATESYM
@@ -275,11 +320,15 @@ static struct skin_element* skin_parse_line_optional(char** document,
if(root)
{
current->next = skin_alloc_element();
+ if (!current->next)
+ return NULL;
current = current->next;
}
else
{
current = skin_alloc_element();
+ if (!current)
+ return NULL;
root = current;
}
@@ -306,9 +355,10 @@ static struct skin_element* skin_parse_line_optional(char** document,
}
}
+
/* Moving up the calling function's pointer */
*document = cursor;
-
+
if(root)
retval->children[0] = root;
return retval;
@@ -328,6 +378,8 @@ static struct skin_element* skin_parse_sublines_optional(char** document,
int i;
retval = skin_alloc_element();
+ if (!retval)
+ return NULL;
retval->type = LINE_ALTERNATOR;
retval->next = NULL;
retval->line = skin_line;
@@ -374,6 +426,8 @@ static struct skin_element* skin_parse_sublines_optional(char** document,
/* ...and then we parse them */
retval->children_count = sublines;
retval->children = skin_alloc_children(sublines);
+ if (!retval->children)
+ return NULL;
cursor = *document;
for(i = 0; i < sublines; i++)
@@ -392,6 +446,13 @@ static struct skin_element* skin_parse_sublines_optional(char** document,
}
}
+#ifdef ROCKBOX
+ if (callback)
+ {
+ if (callback(retval, callback_data) == CALLBACK_ERROR)
+ return NULL;
+ }
+#endif
*document = cursor;
return retval;
@@ -458,6 +519,14 @@ static int skin_parse_tag(struct skin_element* element, char** document)
|| (tag_args[0] == '|' && *cursor != ARGLISTOPENSYM)
|| (star && *cursor != ARGLISTOPENSYM))
{
+
+#ifdef ROCKBOX
+ if (callback)
+ {
+ if (callback(element, callback_data) == CALLBACK_ERROR)
+ return 0;
+ }
+#endif
*document = cursor;
return 1;
}
@@ -507,6 +576,8 @@ static int skin_parse_tag(struct skin_element* element, char** document)
cursor = bookmark; /* Restoring the cursor */
element->params_count = num_args;
element->params = skin_alloc_params(num_args);
+ if (!element->params)
+ return 0;
/* Now we have to actually parse each argument */
for(i = 0; i < num_args; i++)
@@ -587,7 +658,6 @@ static int skin_parse_tag(struct skin_element* element, char** document)
}
if (have_tenth == false)
val *= 10;
-
element->params[i].type = DECIMAL;
element->params[i].data.number = val;
}
@@ -644,7 +714,13 @@ static int skin_parse_tag(struct skin_element* element, char** document)
skin_error(INSUFFICIENT_ARGS, cursor);
return 0;
}
-
+#ifdef ROCKBOX
+ if (callback)
+ {
+ if (callback(element, callback_data) == CALLBACK_ERROR)
+ return 0;
+ }
+#endif
*document = cursor;
return 1;
@@ -691,6 +767,8 @@ static int skin_parse_text(struct skin_element* element, char** document,
element->line = skin_line;
element->next = NULL;
element->data = text = skin_alloc_string(length);
+ if (!element->data)
+ return 0;
for(dest = 0; dest < length; dest++)
{
@@ -702,6 +780,14 @@ static int skin_parse_text(struct skin_element* element, char** document,
cursor++;
}
text[length] = '\0';
+
+#ifdef ROCKBOX
+ if (callback)
+ {
+ if (callback(element, callback_data) == CALLBACK_ERROR)
+ return 0;
+ }
+#endif
*document = cursor;
@@ -715,14 +801,40 @@ static int skin_parse_conditional(struct skin_element* element, char** document)
char* bookmark;
int children = 1;
int i;
+
+#ifdef ROCKBOX
+ bool feature_available = true;
+ char *false_branch = NULL;
+#endif
- element->type = CONDITIONAL;
+ /* Some conditional tags allow for target feature checking,
+ * so to handle that call the callback as usual with type == TAG
+ * then call it a second time with type == CONDITIONAL and check the return
+ * value */
+ element->type = TAG;
element->line = skin_line;
/* Parsing the tag first */
if(!skin_parse_tag(element, &cursor))
return 0;
+ element->type = CONDITIONAL;
+#ifdef ROCKBOX
+ if (callback)
+ {
+ switch (callback(element, callback_data))
+ {
+ case FEATURE_NOT_AVAILABLE:
+ feature_available = false;
+ break;
+ case CALLBACK_ERROR:
+ return 0;
+ default:
+ break;
+ }
+ }
+#endif
+
/* Counting the children */
if(*(cursor++) != ENUMLISTOPENSYM)
{
@@ -751,16 +863,35 @@ static int skin_parse_conditional(struct skin_element* element, char** document)
{
children++;
cursor++;
+#ifdef ROCKBOX
+ if (false_branch == NULL && !feature_available)
+ {
+ false_branch = cursor;
+ children--;
+ }
+#endif
}
else
{
cursor++;
}
}
+#ifdef ROCKBOX
+ if (*cursor == ENUMLISTCLOSESYM &&
+ false_branch == NULL && !feature_available)
+ {
+ false_branch = cursor+1;
+ children--;
+ }
+ /* if we are skipping the true branch fix that up */
+ cursor = false_branch ? false_branch : bookmark;
+#else
cursor = bookmark;
-
+#endif
/* Parsing the children */
element->children = skin_alloc_children(children);
+ if (!element->children)
+ return 0;
element->children_count = children;
for(i = 0; i < children; i++)
@@ -809,6 +940,8 @@ static int skin_parse_comment(struct skin_element* element, char** document)
element->data = NULL;
#else
element->data = text = skin_alloc_string(length);
+ if (!element->data)
+ return 0;
/* We copy from one char past cursor to leave out the # */
memcpy((void*)text, (void*)(cursor + 1),
sizeof(char) * (length-1));
@@ -877,6 +1010,8 @@ struct skin_element* skin_alloc_element()
{
struct skin_element* retval = (struct skin_element*)
skin_buffer_alloc(sizeof(struct skin_element));
+ if (!retval)
+ return NULL;
retval->type = UNKNOWN;
retval->next = NULL;
retval->tag = NULL;
@@ -886,9 +1021,21 @@ struct skin_element* skin_alloc_element()
return retval;
}
-
+/* On a ROCKBOX build we try to save space as much as possible
+ * so if we can, use a shared param pool which should be more then large
+ * enough for any tag. params should be used straight away by the callback
+ * so this is safe.
+ */
struct skin_tag_parameter* skin_alloc_params(int count)
{
+#ifdef ROCKBOX
+ static struct skin_tag_parameter params[MAX_TAG_PARAMS];
+ if (count <= MAX_TAG_PARAMS)
+ {
+ memset(params, 0, sizeof(params));
+ return params;
+ }
+#endif
size_t size = sizeof(struct skin_tag_parameter) * count;
return (struct skin_tag_parameter*)skin_buffer_alloc(size);
diff --git a/lib/skin_parser/skin_parser.h b/lib/skin_parser/skin_parser.h
index ad10f90125..8514dfdd0e 100644
--- a/lib/skin_parser/skin_parser.h
+++ b/lib/skin_parser/skin_parser.h
@@ -115,14 +115,27 @@ struct skin_element
struct skin_element* next;
};
+enum skin_cb_returnvalue
+{
+ CALLBACK_ERROR = -666,
+ FEATURE_NOT_AVAILABLE,
+ CALLBACK_OK = 0,
+ /* > 0 reserved for future use */
+};
+typedef int (*skin_callback)(struct skin_element* element, void* data);
+
/***********************************************************************
***** Functions *******************************************************
**********************************************************************/
/* Parses a WPS document and returns a list of skin_element
structures. */
+#ifdef ROCKBOX
+struct skin_element* skin_parse(const char* document,
+ skin_callback callback, void* callback_data);
+#else
struct skin_element* skin_parse(const char* document);
-
+#endif
/* Memory management functions */
struct skin_element* skin_alloc_element(void);
struct skin_element** skin_alloc_children(int count);
diff --git a/lib/skin_parser/skin_scan.c b/lib/skin_parser/skin_scan.c
index 6b5c189b9f..d18f2224b3 100644
--- a/lib/skin_parser/skin_scan.c
+++ b/lib/skin_parser/skin_scan.c
@@ -40,12 +40,6 @@ void skip_comment(char** document)
(*document)++;
}
-void skip_whitespace(char** document)
-{
- while(**document == ' ' || **document == '\t')
- (*document)++;
-}
-
void skip_arglist(char** document)
{
if(**document == ARGLISTOPENSYM)
@@ -132,6 +126,8 @@ char* scan_string(char** document)
/* Copying the string */
cursor = *document;
buffer = skin_alloc_string(length);
+ if (!buffer)
+ return NULL;
buffer[length] = '\0';
for(i = 0; i < length; i++)
{
diff --git a/lib/skin_parser/skin_scan.h b/lib/skin_parser/skin_scan.h
index b1d04a6e34..72d4475767 100644
--- a/lib/skin_parser/skin_scan.h
+++ b/lib/skin_parser/skin_scan.h
@@ -30,7 +30,6 @@ extern "C"
/* Scanning functions */
void skip_comment(char** document);
-void skip_whitespace(char** document);
void skip_arglist(char** document);
void skip_enumlist(char** document);
char* scan_string(char** document);
diff --git a/lib/skin_parser/tag_table.c b/lib/skin_parser/tag_table.c
index dd8df63997..a7e3378d24 100644
--- a/lib/skin_parser/tag_table.c
+++ b/lib/skin_parser/tag_table.c
@@ -33,182 +33,181 @@ struct tag_info legal_tags[] =
{ SKIN_TOKEN_ALIGN_RIGHT_RTL, "aR", "", 0 },
{ SKIN_TOKEN_ALIGN_LANGDIRECTION, "ax", "", 0 },
- { SKIN_TOKEN_BATTERY_PERCENT, "bl" , BAR_PARAMS, 0 },
- { SKIN_TOKEN_BATTERY_VOLTS, "bv", "", 0 },
- { SKIN_TOKEN_BATTERY_TIME, "bt", "", 0 },
- { SKIN_TOKEN_BATTERY_SLEEPTIME, "bs", "", 0 },
- { SKIN_TOKEN_BATTERY_CHARGING, "bc", "", 0 },
- { SKIN_TOKEN_BATTERY_CHARGER_CONNECTED, "bp", "", 0 },
- { SKIN_TOKEN_USB_POWERED, "bu", "", 0 },
-
-
- { SKIN_TOKEN_RTC_PRESENT, "cc", "", 0 },
- { SKIN_TOKEN_RTC_DAY_OF_MONTH, "cd", "", 0 },
- { SKIN_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED, "ce", "", 0 },
- { SKIN_TOKEN_RTC_12HOUR_CFG, "cf", "", 0 },
- { SKIN_TOKEN_RTC_HOUR_24_ZERO_PADDED, "cH", "", 0 },
- { SKIN_TOKEN_RTC_HOUR_24, "ck", "", 0 },
- { SKIN_TOKEN_RTC_HOUR_12_ZERO_PADDED, "cI", "", 0 },
- { SKIN_TOKEN_RTC_HOUR_12, "cl", "", 0 },
- { SKIN_TOKEN_RTC_MONTH, "cm", "", 0 },
- { SKIN_TOKEN_RTC_MINUTE, "cM", "", 0 },
- { SKIN_TOKEN_RTC_SECOND, "cS", "", 0 },
- { SKIN_TOKEN_RTC_YEAR_2_DIGITS, "cy", "", 0 },
- { SKIN_TOKEN_RTC_YEAR_4_DIGITS, "cY", "", 0 },
- { SKIN_TOKEN_RTC_AM_PM_UPPER, "cP", "", 0 },
- { SKIN_TOKEN_RTC_AM_PM_LOWER, "cp", "", 0 },
- { SKIN_TOKEN_RTC_WEEKDAY_NAME, "ca", "", 0 },
- { SKIN_TOKEN_RTC_MONTH_NAME, "cb", "", 0 },
- { SKIN_TOKEN_RTC_DAY_OF_WEEK_START_MON, "cu", "", 0 },
- { SKIN_TOKEN_RTC_DAY_OF_WEEK_START_SUN, "cw", "", 0 },
+ { SKIN_TOKEN_BATTERY_PERCENT, "bl" , BAR_PARAMS, SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_BATTERY_VOLTS, "bv", "", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_BATTERY_TIME, "bt", "", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_BATTERY_SLEEPTIME, "bs", "", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_BATTERY_CHARGING, "bc", "", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_BATTERY_CHARGER_CONNECTED, "bp", "", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_USB_POWERED, "bu", "", SKIN_REFRESH_DYNAMIC },
+
+
+ { SKIN_TOKEN_RTC_PRESENT, "cc", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_RTC_DAY_OF_MONTH, "cd", "", SKIN_RTC_REFRESH },
+ { SKIN_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED, "ce", "", SKIN_RTC_REFRESH },
+ { SKIN_TOKEN_RTC_12HOUR_CFG, "cf", "", SKIN_RTC_REFRESH },
+ { SKIN_TOKEN_RTC_HOUR_24_ZERO_PADDED, "cH", "", SKIN_RTC_REFRESH },
+ { SKIN_TOKEN_RTC_HOUR_24, "ck", "", SKIN_RTC_REFRESH },
+ { SKIN_TOKEN_RTC_HOUR_12_ZERO_PADDED, "cI", "", SKIN_RTC_REFRESH },
+ { SKIN_TOKEN_RTC_HOUR_12, "cl", "", SKIN_RTC_REFRESH },
+ { SKIN_TOKEN_RTC_MONTH, "cm", "", SKIN_RTC_REFRESH },
+ { SKIN_TOKEN_RTC_MINUTE, "cM", "", SKIN_RTC_REFRESH },
+ { SKIN_TOKEN_RTC_SECOND, "cS", "", SKIN_RTC_REFRESH },
+ { SKIN_TOKEN_RTC_YEAR_2_DIGITS, "cy", "", SKIN_RTC_REFRESH },
+ { SKIN_TOKEN_RTC_YEAR_4_DIGITS, "cY", "", SKIN_RTC_REFRESH },
+ { SKIN_TOKEN_RTC_AM_PM_UPPER, "cP", "", SKIN_RTC_REFRESH },
+ { SKIN_TOKEN_RTC_AM_PM_LOWER, "cp", "", SKIN_RTC_REFRESH },
+ { SKIN_TOKEN_RTC_WEEKDAY_NAME, "ca", "", SKIN_RTC_REFRESH },
+ { SKIN_TOKEN_RTC_MONTH_NAME, "cb", "", SKIN_RTC_REFRESH },
+ { SKIN_TOKEN_RTC_DAY_OF_WEEK_START_MON, "cu", "", SKIN_RTC_REFRESH },
+ { SKIN_TOKEN_RTC_DAY_OF_WEEK_START_SUN, "cw", "", SKIN_RTC_REFRESH },
- { SKIN_TOKEN_FILE_BITRATE, "fb", "", 0 },
- { SKIN_TOKEN_FILE_CODEC, "fc", "", 0 },
- { SKIN_TOKEN_FILE_FREQUENCY, "ff", "", 0 },
- { SKIN_TOKEN_FILE_FREQUENCY_KHZ, "fk", "", 0 },
- { SKIN_TOKEN_FILE_NAME_WITH_EXTENSION, "fm", "", 0 },
- { SKIN_TOKEN_FILE_NAME, "fn", "", 0 },
- { SKIN_TOKEN_FILE_PATH, "fp", "", 0 },
- { SKIN_TOKEN_FILE_SIZE, "fs", "", 0 },
- { SKIN_TOKEN_FILE_VBR, "fv", "", 0 },
- { SKIN_TOKEN_FILE_DIRECTORY, "d" , "I", 0 },
-
- { SKIN_TOKEN_FILE_BITRATE, "Fb", "", 0 },
- { SKIN_TOKEN_FILE_CODEC, "Fc", "", 0 },
- { SKIN_TOKEN_FILE_FREQUENCY, "Ff", "", 0 },
- { SKIN_TOKEN_FILE_FREQUENCY_KHZ, "Fk", "", 0 },
- { SKIN_TOKEN_FILE_NAME_WITH_EXTENSION, "Fm", "", 0 },
- { SKIN_TOKEN_FILE_NAME, "Fn", "", 0 },
- { SKIN_TOKEN_FILE_PATH, "Fp", "", 0 },
- { SKIN_TOKEN_FILE_SIZE, "Fs", "", 0 },
- { SKIN_TOKEN_FILE_VBR, "Fv", "", 0 },
- { SKIN_TOKEN_FILE_DIRECTORY, "D" , "I", 0 },
-
-
- { SKIN_TOKEN_METADATA_ARTIST, "ia", "", 0 },
- { SKIN_TOKEN_METADATA_COMPOSER, "ic", "", 0 },
- { SKIN_TOKEN_METADATA_ALBUM, "id", "", 0 },
- { SKIN_TOKEN_METADATA_ALBUM_ARTIST, "iA", "", 0 },
- { SKIN_TOKEN_METADATA_GROUPING, "iG", "", 0 },
- { SKIN_TOKEN_METADATA_GENRE, "ig", "", 0 },
- { SKIN_TOKEN_METADATA_DISC_NUMBER, "ik", "", 0 },
- { SKIN_TOKEN_METADATA_TRACK_NUMBER, "in", "", 0 },
- { SKIN_TOKEN_METADATA_TRACK_TITLE, "it", "", 0 },
- { SKIN_TOKEN_METADATA_VERSION, "iv", "", 0 },
- { SKIN_TOKEN_METADATA_YEAR, "iy", "", 0 },
- { SKIN_TOKEN_METADATA_COMMENT, "iC", "", 0 },
-
- { SKIN_TOKEN_METADATA_ARTIST, "Ia", "", 0 },
- { SKIN_TOKEN_METADATA_COMPOSER, "Ic", "", 0 },
- { SKIN_TOKEN_METADATA_ALBUM, "Id", "", 0 },
- { SKIN_TOKEN_METADATA_ALBUM_ARTIST, "IA", "", 0 },
- { SKIN_TOKEN_METADATA_GROUPING, "IG", "", 0 },
- { SKIN_TOKEN_METADATA_GENRE, "Ig", "", 0 },
- { SKIN_TOKEN_METADATA_DISC_NUMBER, "Ik", "", 0 },
- { SKIN_TOKEN_METADATA_TRACK_NUMBER, "In", "", 0 },
- { SKIN_TOKEN_METADATA_TRACK_TITLE, "It", "", 0 },
- { SKIN_TOKEN_METADATA_VERSION, "Iv", "", 0 },
- { SKIN_TOKEN_METADATA_YEAR, "Iy", "", 0 },
- { SKIN_TOKEN_METADATA_COMMENT, "IC", "", 0 },
-
- { SKIN_TOKEN_SOUND_PITCH, "Sp", "", 0 },
- { SKIN_TOKEN_SOUND_SPEED, "Ss", "", 0 },
-
- { SKIN_TOKEN_VLED_HDD, "lh", "", 0 },
-
- { SKIN_TOKEN_MAIN_HOLD, "mh", "", 0 },
- { SKIN_TOKEN_REMOTE_HOLD, "mr", "", 0 },
- { SKIN_TOKEN_REPEAT_MODE, "mm", "", 0 },
- { SKIN_TOKEN_PLAYBACK_STATUS, "mp", "", 0 },
- { SKIN_TOKEN_BUTTON_VOLUME, "mv", "|D", 0 },
-
- { SKIN_TOKEN_PEAKMETER, "pm", "", 0 },
- { SKIN_TOKEN_PLAYER_PROGRESSBAR, "pf", "", 0 },
- { SKIN_TOKEN_PROGRESSBAR, "pb" , BAR_PARAMS, 0 },
- { SKIN_TOKEN_VOLUME, "pv" , BAR_PARAMS, 0 },
-
- { SKIN_TOKEN_TRACK_ELAPSED_PERCENT, "px", "", 0 },
- { SKIN_TOKEN_TRACK_TIME_ELAPSED, "pc", "", 0 },
- { SKIN_TOKEN_TRACK_TIME_REMAINING, "pr", "", 0 },
- { SKIN_TOKEN_TRACK_LENGTH, "pt", "", 0 },
- { SKIN_TOKEN_TRACK_STARTING, "pS" , "|D", 0 },
- { SKIN_TOKEN_TRACK_ENDING, "pE" , "|D", 0 },
- { SKIN_TOKEN_PLAYLIST_POSITION, "pp", "", 0 },
- { SKIN_TOKEN_PLAYLIST_ENTRIES, "pe", "", 0 },
- { SKIN_TOKEN_PLAYLIST_NAME, "pn", "", 0 },
- { SKIN_TOKEN_PLAYLIST_SHUFFLE, "ps", "", 0 },
-
- { SKIN_TOKEN_DATABASE_PLAYCOUNT, "rp", "", 0 },
- { SKIN_TOKEN_DATABASE_RATING, "rr", "", 0 },
- { SKIN_TOKEN_DATABASE_AUTOSCORE, "ra", "", 0 },
-
- { SKIN_TOKEN_REPLAYGAIN, "rg", "", 0 },
- { SKIN_TOKEN_CROSSFADE, "xf", "", 0 },
-
- { SKIN_TOKEN_HAVE_TUNER, "tp", "", 0 },
- { SKIN_TOKEN_TUNER_TUNED, "tt", "", 0 },
- { SKIN_TOKEN_TUNER_SCANMODE, "tm", "", 0 },
- { SKIN_TOKEN_TUNER_STEREO, "ts", "", 0 },
- { SKIN_TOKEN_TUNER_MINFREQ, "ta", "", 0 },
- { SKIN_TOKEN_TUNER_MAXFREQ, "tb", "", 0 },
- { SKIN_TOKEN_TUNER_CURFREQ, "tf", "", 0 },
- { SKIN_TOKEN_PRESET_ID, "Ti", "", 0 },
- { SKIN_TOKEN_PRESET_NAME, "Tn", "", 0 },
- { SKIN_TOKEN_PRESET_FREQ, "Tf", "", 0 },
- { SKIN_TOKEN_PRESET_COUNT, "Tc", "", 0 },
- { SKIN_TOKEN_HAVE_RDS, "tx", "", 0 },
- { SKIN_TOKEN_RDS_NAME, "ty", "", 0 },
- { SKIN_TOKEN_RDS_TEXT, "tz", "", 0 },
-
- { SKIN_TOKEN_SUBLINE_SCROLL, "s", "", 0 },
+ { SKIN_TOKEN_FILE_BITRATE, "fb", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_FILE_CODEC, "fc", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_FILE_FREQUENCY, "ff", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_FILE_FREQUENCY_KHZ, "fk", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_FILE_NAME_WITH_EXTENSION, "fm", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_FILE_NAME, "fn", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_FILE_PATH, "fp", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_FILE_SIZE, "fs", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_FILE_VBR, "fv", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_FILE_DIRECTORY, "d" , "I", SKIN_REFRESH_STATIC },
+
+ { SKIN_TOKEN_FILE_BITRATE, "Fb", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_FILE_CODEC, "Fc", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_FILE_FREQUENCY, "Ff", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_FILE_FREQUENCY_KHZ, "Fk", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_FILE_NAME_WITH_EXTENSION, "Fm", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_FILE_NAME, "Fn", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_FILE_PATH, "Fp", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_FILE_SIZE, "Fs", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_FILE_VBR, "Fv", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_FILE_DIRECTORY, "D" , "I", SKIN_REFRESH_STATIC },
+
+
+ { SKIN_TOKEN_METADATA_ARTIST, "ia", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_METADATA_COMPOSER, "ic", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_METADATA_ALBUM, "id", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_METADATA_ALBUM_ARTIST, "iA", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_METADATA_GROUPING, "iG", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_METADATA_GENRE, "ig", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_METADATA_DISC_NUMBER, "ik", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_METADATA_TRACK_NUMBER, "in", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_METADATA_TRACK_TITLE, "it", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_METADATA_VERSION, "iv", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_METADATA_YEAR, "iy", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_METADATA_COMMENT, "iC", "", SKIN_REFRESH_STATIC },
+
+ { SKIN_TOKEN_METADATA_ARTIST, "Ia", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_METADATA_COMPOSER, "Ic", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_METADATA_ALBUM, "Id", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_METADATA_ALBUM_ARTIST, "IA", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_METADATA_GROUPING, "IG", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_METADATA_GENRE, "Ig", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_METADATA_DISC_NUMBER, "Ik", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_METADATA_TRACK_NUMBER, "In", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_METADATA_TRACK_TITLE, "It", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_METADATA_VERSION, "Iv", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_METADATA_YEAR, "Iy", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_METADATA_COMMENT, "IC", "", SKIN_REFRESH_STATIC },
+
+ { SKIN_TOKEN_SOUND_PITCH, "Sp", "", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_SOUND_SPEED, "Ss", "", SKIN_REFRESH_DYNAMIC },
+
+ { SKIN_TOKEN_VLED_HDD, "lh", "", SKIN_REFRESH_DYNAMIC },
+
+ { SKIN_TOKEN_MAIN_HOLD, "mh", "", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_REMOTE_HOLD, "mr", "", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_REPEAT_MODE, "mm", "", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_PLAYBACK_STATUS, "mp", "", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_BUTTON_VOLUME, "mv", "|D", SKIN_REFRESH_DYNAMIC },
+
+ { SKIN_TOKEN_PEAKMETER, "pm", "", SKIN_REFRESH_PEAK_METER },
+ { SKIN_TOKEN_PLAYER_PROGRESSBAR, "pf", "", SKIN_REFRESH_DYNAMIC|SKIN_REFRESH_PLAYER_PROGRESS },
+ { SKIN_TOKEN_PROGRESSBAR, "pb" , BAR_PARAMS, SKIN_REFRESH_PLAYER_PROGRESS },
+ { SKIN_TOKEN_VOLUME, "pv" , BAR_PARAMS, SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_TRACK_ELAPSED_PERCENT, "px", "", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_TRACK_TIME_ELAPSED, "pc", "", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_TRACK_TIME_REMAINING, "pr", "", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_TRACK_LENGTH, "pt", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_TRACK_STARTING, "pS" , "|D", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_TRACK_ENDING, "pE" , "|D", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_PLAYLIST_POSITION, "pp", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_PLAYLIST_ENTRIES, "pe", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_PLAYLIST_NAME, "pn", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_PLAYLIST_SHUFFLE, "ps", "", SKIN_REFRESH_DYNAMIC },
+
+ { SKIN_TOKEN_DATABASE_PLAYCOUNT, "rp", "", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_DATABASE_RATING, "rr", "", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_DATABASE_AUTOSCORE, "ra", "", SKIN_REFRESH_DYNAMIC },
+
+ { SKIN_TOKEN_REPLAYGAIN, "rg", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_CROSSFADE, "xf", "", SKIN_REFRESH_DYNAMIC },
+
+ { SKIN_TOKEN_HAVE_TUNER, "tp", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_TUNER_TUNED, "tt", "", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_TUNER_SCANMODE, "tm", "", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_TUNER_STEREO, "ts", "", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_TUNER_MINFREQ, "ta", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_TUNER_MAXFREQ, "tb", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_TUNER_CURFREQ, "tf", "", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_PRESET_ID, "Ti", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_PRESET_NAME, "Tn", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_PRESET_FREQ, "Tf", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_PRESET_COUNT, "Tc", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_HAVE_RDS, "tx", "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_RDS_NAME, "ty", "", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_RDS_TEXT, "tz", "", SKIN_REFRESH_DYNAMIC },
+
+ { SKIN_TOKEN_SUBLINE_SCROLL, "s", "", SKIN_REFRESH_SCROLL },
{ SKIN_TOKEN_SUBLINE_TIMEOUT, "t" , "D", 0 },
+
+ { SKIN_TOKEN_ENABLE_THEME, "we", "", 0|NOBREAK },
+ { SKIN_TOKEN_DISABLE_THEME, "wd", "", 0|NOBREAK },
+ { SKIN_TOKEN_DRAW_INBUILTBAR, "wi", "", SKIN_REFRESH_STATIC|NOBREAK },
- { SKIN_TOKEN_ENABLE_THEME, "we", "", NOBREAK },
- { SKIN_TOKEN_DISABLE_THEME, "wd", "", NOBREAK },
- { SKIN_TOKEN_DRAW_INBUILTBAR, "wi", "", NOBREAK },
-
- { SKIN_TOKEN_IMAGE_PRELOAD, "xl", "SFII|I", NOBREAK },
+ { SKIN_TOKEN_IMAGE_PRELOAD, "xl", "SFII|I", 0|NOBREAK },
{ SKIN_TOKEN_IMAGE_PRELOAD_DISPLAY, "xd", "S", 0 },
- { SKIN_TOKEN_IMAGE_PRELOAD, "x", "SFII", NOBREAK },
+ { SKIN_TOKEN_IMAGE_DISPLAY, "x", "SFII", 0|NOBREAK },
- { SKIN_TOKEN_LOAD_FONT, "Fl" , "IF", NOBREAK },
- { SKIN_TOKEN_ALBUMART_LOAD, "Cl" , "IIII|ss", NOBREAK },
- { SKIN_TOKEN_ALBUMART_DISPLAY, "Cd" , "", 0 },
- { SKIN_TOKEN_ALBUMART_FOUND, "C" , "", 0 },
+ { SKIN_TOKEN_LOAD_FONT, "Fl" , "IF", 0|NOBREAK },
+ { SKIN_TOKEN_ALBUMART_LOAD, "Cl" , "IIII|ss", 0|NOBREAK },
+ { SKIN_TOKEN_ALBUMART_DISPLAY, "Cd" , "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_ALBUMART_FOUND, "C" , "", SKIN_REFRESH_STATIC },
- { SKIN_TOKEN_VIEWPORT_ENABLE, "Vd" , "S", 0 },
- { SKIN_TOKEN_UIVIEWPORT_ENABLE, "VI" , "S", 0 },
+ { SKIN_TOKEN_VIEWPORT_ENABLE, "Vd" , "S", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_UIVIEWPORT_ENABLE, "VI" , "S", SKIN_REFRESH_STATIC },
- { SKIN_TOKEN_VIEWPORT_CUSTOMLIST, "Vp" , "ICC", NOBREAK },
- { SKIN_TOKEN_LIST_TITLE_TEXT, "Lt" , "", 0 },
- { SKIN_TOKEN_LIST_TITLE_ICON, "Li" , "", 0 },
+ { SKIN_TOKEN_VIEWPORT_CUSTOMLIST, "Vp" , "ICC", SKIN_REFRESH_DYNAMIC|NOBREAK },
+ { SKIN_TOKEN_LIST_TITLE_TEXT, "Lt" , "", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_LIST_TITLE_ICON, "Li" , "", SKIN_REFRESH_DYNAMIC },
- { SKIN_TOKEN_VIEWPORT_FGCOLOUR, "Vf" , "S", NOBREAK },
- { SKIN_TOKEN_VIEWPORT_BGCOLOUR, "Vb" , "S", NOBREAK },
+ { SKIN_TOKEN_VIEWPORT_FGCOLOUR, "Vf" , "s", SKIN_REFRESH_STATIC|NOBREAK },
+ { SKIN_TOKEN_VIEWPORT_BGCOLOUR, "Vb" , "s", SKIN_REFRESH_STATIC|NOBREAK },
{ SKIN_TOKEN_VIEWPORT_CONDITIONAL, "Vl" , "SIIiii", 0 },
{ SKIN_TOKEN_UIVIEWPORT_LOAD, "Vi" , "sIIiii", 0 },
{ SKIN_TOKEN_VIEWPORT_LOAD, "V" , "IIiii", 0 },
- { SKIN_TOKEN_IMAGE_BACKDROP, "X" , "f", NOBREAK },
-
- { SKIN_TOKEN_SETTING, "St" , "S", 0 },
- { SKIN_TOKEN_TRANSLATEDSTRING, "Sx" , "S", 0 },
- { SKIN_TOKEN_LANG_IS_RTL, "Sr" , "", 0 },
-
- { SKIN_TOKEN_LASTTOUCH, "Tl" , "|D", 0 },
- { SKIN_TOKEN_CURRENT_SCREEN, "cs", "", 0 },
- { SKIN_TOKEN_TOUCHREGION, "T" , "IIiiS", NOBREAK },
-
- { SKIN_TOKEN_HAVE_RECORDING, "Rp" , "", 0 },
- { SKIN_TOKEN_IS_RECORDING, "Rr" , "", 0 },
- { SKIN_TOKEN_REC_FREQ, "Rf" , "", 0 },
- { SKIN_TOKEN_REC_ENCODER, "Re" , "", 0 },
- { SKIN_TOKEN_REC_BITRATE, "Rb" , "", 0 },
- { SKIN_TOKEN_REC_MONO, "Rm" , "", 0 },
- { SKIN_TOKEN_REC_SECONDS, "Rs" , "", 0 },
- { SKIN_TOKEN_REC_MINUTES, "Rn" , "", 0 },
- { SKIN_TOKEN_REC_HOURS, "Rh" , "", 0 },
+ { SKIN_TOKEN_IMAGE_BACKDROP, "X" , "f", SKIN_REFRESH_STATIC|NOBREAK },
+
+ { SKIN_TOKEN_SETTING, "St" , "S", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_TRANSLATEDSTRING, "Sx" , "S", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_LANG_IS_RTL, "Sr" , "", SKIN_REFRESH_STATIC },
+
+ { SKIN_TOKEN_LASTTOUCH, "Tl" , "|D", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_CURRENT_SCREEN, "cs", "", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_TOUCHREGION, "T" , "IIiiS", 0|NOBREAK },
+
+ { SKIN_TOKEN_HAVE_RECORDING, "Rp" , "", SKIN_REFRESH_STATIC },
+ { SKIN_TOKEN_IS_RECORDING, "Rr" , "", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_REC_FREQ, "Rf" , "", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_REC_ENCODER, "Re" , "", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_REC_BITRATE, "Rb" , "", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_REC_MONO, "Rm" , "", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_REC_SECONDS, "Rs" , "", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_REC_MINUTES, "Rn" , "", SKIN_REFRESH_DYNAMIC },
+ { SKIN_TOKEN_REC_HOURS, "Rh" , "", SKIN_REFRESH_DYNAMIC },
{ SKIN_TOKEN_UNKNOWN, "" , "", 0 }
/* Keep this here to mark the end of the table */
diff --git a/lib/skin_parser/tag_table.h b/lib/skin_parser/tag_table.h
index f84d4ac762..dde1487d13 100644
--- a/lib/skin_parser/tag_table.h
+++ b/lib/skin_parser/tag_table.h
@@ -27,12 +27,31 @@ extern "C"
{
#endif
+#define MAX_TAG_PARAMS 12
+
+
/* Flag to tell the renderer not to insert a line break */
#define NOBREAK 0x1
+/* constants used in line_type and as refresh_mode for wps_refresh */
+#define SKIN_REFRESH_SHIFT 16
+#define SKIN_REFRESH_STATIC (1u<<SKIN_REFRESH_SHIFT) /* line doesn't change over time */
+#define SKIN_REFRESH_DYNAMIC (1u<<(SKIN_REFRESH_SHIFT+1)) /* line may change (e.g. time flag) */
+#define SKIN_REFRESH_SCROLL (1u<<(SKIN_REFRESH_SHIFT+2)) /* line scrolls */
+#define SKIN_REFRESH_PLAYER_PROGRESS (1u<<(SKIN_REFRESH_SHIFT+3)) /* line contains a progress bar */
+#define SKIN_REFRESH_PEAK_METER (1u<<(SKIN_REFRESH_SHIFT+4)) /* line contains a peak meter */
+#define SKIN_REFRESH_STATUSBAR (1u<<(SKIN_REFRESH_SHIFT+5)) /* refresh statusbar */
+#define SKIN_RTC_REFRESH (1u<<(SKIN_REFRESH_SHIFT+6)) /* refresh rtc, convert at parse time */
+#define SKIN_REFRESH_ALL (0xffffu<<SKIN_REFRESH_SHIFT) /* to refresh all line types */
+
+/* to refresh only those lines that change over time */
+#define SKIN_REFRESH_NON_STATIC (SKIN_REFRESH_DYNAMIC| \
+ SKIN_REFRESH_PLAYER_PROGRESS| \
+ SKIN_REFRESH_PEAK_METER)
enum skin_token_type {
+ SKIN_TOKEN_NO_TOKEN,
SKIN_TOKEN_UNKNOWN,
/* Markers */
@@ -91,7 +110,7 @@ enum skin_token_type {
/* The begin/end values allow us to know if a token is an RTC one.
New RTC tokens should be added between the markers. */
- SKIN_TOKENs_RTC_BEGIN, /* just the start marker, not an actual token */
+ SKIN_TOKENS_RTC_BEGIN, /* just the start marker, not an actual token */
SKIN_TOKEN_RTC_DAY_OF_MONTH,
SKIN_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED,
diff --git a/tools/checkwps/SOURCES b/tools/checkwps/SOURCES
index 48ed53b330..3e12d1f74e 100644
--- a/tools/checkwps/SOURCES
+++ b/tools/checkwps/SOURCES
@@ -1,7 +1,6 @@
../../apps/gui/skin_engine/wps_debug.c
../../apps/gui/skin_engine/skin_parser.c
../../apps/gui/skin_engine/skin_backdrops.c
-../../apps/gui/skin_engine/skin_buffer.c
#ifdef HAVE_LCD_BITMAP
../../apps/gui/skin_engine/skin_fonts.c
#endif
diff --git a/tools/checkwps/checkwps.c b/tools/checkwps/checkwps.c
index 94136e02f0..e00fb724bc 100644
--- a/tools/checkwps/checkwps.c
+++ b/tools/checkwps/checkwps.c
@@ -26,6 +26,8 @@
#include "checkwps.h"
#include "resize.h"
#include "wps.h"
+#include "skin_buffer.h"
+#include "skin_debug.h"
#include "skin_engine.h"
#include "wps_internals.h"
#include "settings.h"
@@ -237,6 +239,8 @@ int main(int argc, char **argv)
struct wps_data wps;
enum screen_type screen = SCREEN_MAIN;
struct screen* wps_screen;
+
+ char* buffer = NULL;
/* No arguments -> print the help text
* Also print the help text upon -h or --help */
@@ -261,13 +265,19 @@ int main(int argc, char **argv)
wps_verbose_level++;
}
}
+ buffer = malloc(SKIN_BUFFER_SIZE);
+ if (!buffer)
+ {
+ printf("mallloc fail!\n");
+ return 1;
+ }
- skin_buffer_init();
+ skin_buffer_init(buffer, SKIN_BUFFER_SIZE);
#ifdef HAVE_LCD_BITMAP
skin_font_init();
#endif
- /* Go through every wps that was thrown at us, error out at the first
+ /* Go through every skin that was thrown at us, error out at the first
* flawed wps */
while (argv[filearg]) {
printf("Checking %s...\n", argv[filearg]);
@@ -285,6 +295,7 @@ int main(int argc, char **argv)
if (!res) {
printf("WPS parsing failure\n");
+ skin_error_format_message();
return 3;
}
diff --git a/tools/checkwps/checkwps.make b/tools/checkwps/checkwps.make
index 0db643bc84..e09ce25aec 100644
--- a/tools/checkwps/checkwps.make
+++ b/tools/checkwps/checkwps.make
@@ -26,6 +26,6 @@ GCCOPTS+=-D__PCTOOL__
.SECONDEXPANSION: # $$(OBJ) is not populated until after this
-$(BUILDDIR)/$(BINARY): $$(OBJ)
+$(BUILDDIR)/$(BINARY): $$(OBJ) $$(SKINLIB)
@echo LD $(BINARY)
- $(SILENT)$(HOSTCC) $(INCLUDE) $(FLAGS) -o $@ $+
+ $(SILENT)$(HOSTCC) $(INCLUDE) $(FLAGS) -L$(BUILDDIR)/lib -lskin_parser -o $@ $+
diff --git a/tools/root.make b/tools/root.make
index e53c452022..d90b40f0c6 100644
--- a/tools/root.make
+++ b/tools/root.make
@@ -70,6 +70,7 @@ else ifneq (,$(findstring bootbox,$(APPSDIR)))
include $(APPSDIR)/bootbox.make
else ifneq (,$(findstring checkwps,$(APPSDIR)))
include $(APPSDIR)/checkwps.make
+ include $(ROOTDIR)/lib/skin_parser/skin_parser.make
else ifneq (,$(findstring database,$(APPSDIR)))
include $(APPSDIR)/database.make
else
@@ -170,7 +171,8 @@ $(BUILDDIR)/rockbox.elf : $$(OBJ) $$(FIRMLIB) $$(VOICESPEEXLIB) $$(SKINLIB) $$(L
$(BUILDDIR)/rombox.elf : $$(OBJ) $$(FIRMLIB) $$(VOICESPEEXLIB) $$(SKINLIB) $$(LINKROM)
$(call PRINTS,LD $(@F))$(CC) $(GCCOPTS) -Os -nostdlib -o $@ $(OBJ) \
$(VOICESPEEXLIB) $(FIRMLIB) -lgcc $(GLOBAL_LDOPTS) \
- -L$(BUILDDIR)/firmware -T$(LINKROM) -Wl,-Map,$(BUILDDIR)/rombox.map
+ -L$(BUILDDIR)/lib -lskin_parser \
+ -L$(BUILDDIR)/firmware -T$(LINKROM) -Wl,-Map,$(BUILDDIR)/rombox.map
$(BUILDDIR)/rockbox.bin : $(BUILDDIR)/rockbox.elf
$(call PRINTS,OC $(@F))$(OC) $(if $(filter yes, $(USE_ELF)), -S -x, -O binary) $< $@
diff --git a/utils/newparser/skin_render.c b/utils/newparser/skin_render.c
index 1690455086..09c9ca1355 100644
--- a/utils/newparser/skin_render.c
+++ b/utils/newparser/skin_render.c
@@ -43,7 +43,7 @@ static void do_tags_in_hidden_conditional(struct skin_element* branch)
{
/* Tags here are ones which need to be "turned off" or cleared
* if they are in a conditional branch which isnt being used */
- if (branch->type == SUBLINES)
+ if (branch->type == LINE_ALTERNATOR)
{
int i;
for (i=0; i<branch->children_count; i++)
@@ -71,7 +71,6 @@ static void do_tags_in_hidden_conditional(struct skin_element* branch)
break;
case SKIN_TOKEN_IMAGE_DISPLAY:
case SKIN_TOKEN_IMAGE_PRELOAD_DISPLAY:
- printf("disable image\n");
/* clear images */
break;
default:
@@ -109,7 +108,7 @@ void skin_render_line(struct skin_element* line,
do_tags_in_hidden_conditional(child->children[last_value]);
last_value = value;
- if (child->children[value]->type == SUBLINES)
+ if (child->children[value]->type == LINE_ALTERNATOR)
func = skin_render_alternator;
else if (child->children[value]->type == LINE)
func = skin_render_line;