From 2d31d77a8ba231cb03ec35863c4c4ce2024f6509 Mon Sep 17 00:00:00 2001 From: Jonathan Gordon Date: Thu, 29 Jul 2010 12:37:48 +0000 Subject: FS#11470 - new skin code, finally svn uses the new parser from the theme editor. This means that a skin that passes the editor WILL pass svn and checkwps (unless the target runs out of skin buffer or something. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27613 a1c6a512-1295-4272-9138-f99709370657 --- apps/gui/skin_engine/skin_backdrops.c | 4 +- apps/gui/skin_engine/skin_buffer.c | 170 --- apps/gui/skin_engine/skin_buffer.h | 64 - apps/gui/skin_engine/skin_display.c | 728 ++--------- apps/gui/skin_engine/skin_display.h | 59 + apps/gui/skin_engine/skin_engine.h | 33 +- apps/gui/skin_engine/skin_fonts.c | 2 +- apps/gui/skin_engine/skin_fonts.h | 1 - apps/gui/skin_engine/skin_parser.c | 2119 +++++++++------------------------ apps/gui/skin_engine/skin_render.c | 614 ++++++++++ apps/gui/skin_engine/skin_tokens.c | 279 +++-- apps/gui/skin_engine/skin_tokens.h | 238 +--- apps/gui/skin_engine/wps_debug.c | 1 - apps/gui/skin_engine/wps_internals.h | 102 +- apps/gui/statusbar-skinned.c | 103 +- apps/gui/theme_settings.c | 12 +- apps/gui/viewport.c | 84 -- apps/gui/viewport.h | 21 - apps/gui/wps.c | 16 +- 19 files changed, 1653 insertions(+), 2997 deletions(-) delete mode 100644 apps/gui/skin_engine/skin_buffer.c delete mode 100644 apps/gui/skin_engine/skin_buffer.h create mode 100644 apps/gui/skin_engine/skin_display.h create mode 100644 apps/gui/skin_engine/skin_render.c (limited to 'apps/gui') 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 #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 -#include -#include -#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 -#include -#include - -/* 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 constructs as if they had 2 options. */ + /* treat ?xx constructs as if they had 2 options. + * (i.e ?xx) */ 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 +#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) +static bool isdefault(struct skin_tag_parameter *param) { - (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; + return param->type == DEFAULT; } -#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) -{ - (void)token; (void)wps_data; - return skip_end_of_line(wps_bufptr); -} -#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|||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|