blob: adac487e27cabab4601b114aab7b6b7a4a20d85d [file] [log] [blame]
Nicolas Pennequinab90d582007-04-04 14:41:40 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 Nicolas Pennequin, Dan Everton, Matthias Mohr
Jonathan Gordon2d31d772010-07-29 12:37:48 +000011 * 2010 Jonathan Gordon
Nicolas Pennequinab90d582007-04-04 14:41:40 +000012 *
Daniel Stenberg2acc0ac2008-06-28 18:10:04 +000013 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
Nicolas Pennequinab90d582007-04-04 14:41:40 +000017 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22
Dave Chapmanb9bb7232008-03-26 18:18:22 +000023#include <stdio.h>
24#include <string.h>
Bertrik Sikken28434692008-04-28 16:18:04 +000025#include <stdlib.h>
Jonathan Gordon9f4f5db2009-09-06 16:54:04 +000026#include "config.h"
Dave Chapman78d29f52008-03-26 23:35:34 +000027#include "file.h"
28#include "misc.h"
Nils Wallméniusa21004d2008-05-19 14:37:16 +000029#include "plugin.h"
Thomas Martitz9bd7b232009-08-09 16:16:55 +000030#include "viewport.h"
Nils Wallméniusa21004d2008-05-19 14:37:16 +000031
Jonathan Gordon2d31d772010-07-29 12:37:48 +000032#include "skin_buffer.h"
33#include "skin_parser.h"
34#include "tag_table.h"
35
Dave Chapmanb9bb7232008-03-26 18:18:22 +000036#ifdef __PCTOOL__
Frank Gevaerts5d22e3c2008-08-29 21:08:38 +000037#ifdef WPSEDITOR
38#include "proxy.h"
Frank Gevaerts5d22e3c2008-08-29 21:08:38 +000039#include "sysfont.h"
Frank Gevaerts5d22e3c2008-08-29 21:08:38 +000040#else
Maurus Cuelenaere876db6c2009-08-21 18:15:20 +000041#include "action.h"
Frank Gevaerts5d22e3c2008-08-29 21:08:38 +000042#include "checkwps.h"
Maurus Cuelenaere36c71a62009-01-29 20:49:43 +000043#include "audio.h"
Jonathan Gordon669afd02010-01-07 07:47:19 +000044#define lang_is_rtl() (false)
Dave Chapmanb9bb7232008-03-26 18:18:22 +000045#define DEBUGF printf
Frank Gevaerts5d22e3c2008-08-29 21:08:38 +000046#endif /*WPSEDITOR*/
Dave Chapmanb9bb7232008-03-26 18:18:22 +000047#else
48#include "debug.h"
Jonathan Gordon340f3232009-09-26 00:58:32 +000049#include "language.h"
Frank Gevaerts5d22e3c2008-08-29 21:08:38 +000050#endif /*__PCTOOL__*/
Dave Chapmanb9bb7232008-03-26 18:18:22 +000051
Nicolas Pennequinab90d582007-04-04 14:41:40 +000052#include <ctype.h>
53#include <stdbool.h>
Dave Chapmanb9bb7232008-03-26 18:18:22 +000054#include "font.h"
55
Jonathan Gordon5e5fc642009-07-27 07:21:05 +000056#include "wps_internals.h"
Jonathan Gordon37908972009-08-06 04:33:35 +000057#include "skin_engine.h"
Nicolas Pennequinab90d582007-04-04 14:41:40 +000058#include "settings.h"
Antoine Cellerier8289b962008-12-07 16:20:35 +000059#include "settings_list.h"
Jonathan Gordona5d8d212010-05-12 11:44:09 +000060#if CONFIG_TUNER
Jonathan Gordon1bd072c2010-05-12 10:38:00 +000061#include "radio.h"
Jonathan Gordona5d8d212010-05-12 11:44:09 +000062#include "tuner.h"
63#endif
Jonathan Gordon1c2aa352010-02-14 06:26:16 +000064#include "skin_fonts.h"
Nicolas Pennequinab90d582007-04-04 14:41:40 +000065
66#ifdef HAVE_LCD_BITMAP
67#include "bmp.h"
Nicolas Pennequinab90d582007-04-04 14:41:40 +000068#endif
Nicolas Pennequin1cf2ec32007-04-25 22:08:00 +000069
Thomas Martitze9c10182009-10-16 19:14:41 +000070#ifdef HAVE_ALBUMART
71#include "playback.h"
72#endif
73
Nicolas Pennequin1cf2ec32007-04-25 22:08:00 +000074#include "backdrop.h"
Jonathan Gordoneee54232010-01-29 07:52:13 +000075#include "statusbar-skinned.h"
Nicolas Pennequinab90d582007-04-04 14:41:40 +000076
Nicolas Pennequin31f76112007-11-14 22:02:41 +000077#define WPS_ERROR_INVALID_PARAM -1
78
Jonathan Gordon2d31d772010-07-29 12:37:48 +000079
80static bool isdefault(struct skin_tag_parameter *param)
81{
82 return param->type == DEFAULT;
83}
84
85
Jonathan Gordonc8126142009-11-04 05:24:30 +000086/* which screen are we parsing for? */
87static enum screen_type curr_screen;
88
Jonathan Gordon36ca4962009-08-18 05:30:59 +000089/* the current viewport */
Jonathan Gordon2d31d772010-07-29 12:37:48 +000090static struct skin_element *curr_viewport_element;
Jonathan Gordon36ca4962009-08-18 05:30:59 +000091static struct skin_viewport *curr_vp;
Jonathan Gordon2d31d772010-07-29 12:37:48 +000092
Bertrik Sikken57933f22010-07-30 23:47:49 +000093static struct line *curr_line;
Jonathan Gordon36ca4962009-08-18 05:30:59 +000094
Jonathan Gordon91e6b062010-01-07 07:34:15 +000095static int follow_lang_direction = 0;
96
Jonathan Gordon2d31d772010-07-29 12:37:48 +000097typedef int (*parse_function)(struct skin_element *element,
98 struct wps_token *token,
99 struct wps_data *wps_data);
Thomas Martitz541dd6f2009-09-13 12:24:14 +0000100
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000101#ifdef HAVE_LCD_BITMAP
Thomas Martitz541dd6f2009-09-13 12:24:14 +0000102/* add a skin_token_list item to the list chain. ALWAYS appended because some of the
Jonathan Gordon18a8e522009-08-16 18:23:00 +0000103 * chains require the order to be kept.
104 */
105static void add_to_ll_chain(struct skin_token_list **list, struct skin_token_list *item)
106{
107 if (*list == NULL)
108 *list = item;
109 else
110 {
111 struct skin_token_list *t = *list;
112 while (t->next)
113 t = t->next;
Thomas Martitz541dd6f2009-09-13 12:24:14 +0000114 t->next = item;
Jonathan Gordon18a8e522009-08-16 18:23:00 +0000115 }
Thomas Martitz541dd6f2009-09-13 12:24:14 +0000116}
Thomas Martitz3216d322009-11-01 15:48:31 +0000117
Thomas Martitz3216d322009-11-01 15:48:31 +0000118#endif
119
Jonathan Gordone7659062011-03-07 12:56:24 +0000120
121void *skin_find_item(const char *label, enum skin_find_what what,
Jonathan Gordon87aa86c2011-03-27 08:01:58 +0000122 struct wps_data *data)
Jonathan Gordone7659062011-03-07 12:56:24 +0000123{
124 const char *itemlabel = NULL;
125 union {
126 struct skin_token_list *linkedlist;
127 struct skin_element *vplist;
Jonathan Gordon8f3feda2011-03-07 13:09:04 +0000128 } list = {NULL};
Jonathan Gordone7659062011-03-07 12:56:24 +0000129 bool isvplist = false;
130 void *ret = NULL;
131 switch (what)
132 {
133 case SKIN_FIND_UIVP:
134 case SKIN_FIND_VP:
135 list.vplist = data->tree;
136 isvplist = true;
137 break;
Jonathan Gordon8f3feda2011-03-07 13:09:04 +0000138#ifdef HAVE_LCD_BITMAP
Jonathan Gordone7659062011-03-07 12:56:24 +0000139 case SKIN_FIND_IMAGE:
140 list.linkedlist = data->images;
141 break;
Jonathan Gordon8f3feda2011-03-07 13:09:04 +0000142#endif
Jonathan Gordone7659062011-03-07 12:56:24 +0000143#ifdef HAVE_TOUCHSCREEN
144 case SKIN_FIND_TOUCHREGION:
145 list.linkedlist = data->touchregions;
146 break;
147#endif
Jonathan Gordon87aa86c2011-03-27 08:01:58 +0000148#ifdef HAVE_SKIN_VARIABLES
149 case SKIN_VARIABLE:
150 list.linkedlist = data->skinvars;
151 break;
152#endif
Jonathan Gordone7659062011-03-07 12:56:24 +0000153 }
154
155 while (list.linkedlist)
156 {
157 bool skip = false;
158 switch (what)
159 {
160 case SKIN_FIND_UIVP:
161 case SKIN_FIND_VP:
162 ret = list.vplist->data;
163 itemlabel = ((struct skin_viewport *)ret)->label;
164 skip = !(((struct skin_viewport *)ret)->is_infovp ==
165 (what==SKIN_FIND_UIVP));
166 break;
Jonathan Gordon8f3feda2011-03-07 13:09:04 +0000167#ifdef HAVE_LCD_BITMAP
Jonathan Gordone7659062011-03-07 12:56:24 +0000168 case SKIN_FIND_IMAGE:
169 ret = list.linkedlist->token->value.data;
170 itemlabel = ((struct gui_img *)ret)->label;
171 break;
Jonathan Gordon8f3feda2011-03-07 13:09:04 +0000172#endif
Jonathan Gordone7659062011-03-07 12:56:24 +0000173#ifdef HAVE_TOUCHSCREEN
174 case SKIN_FIND_TOUCHREGION:
175 ret = list.linkedlist->token->value.data;
176 itemlabel = ((struct touchregion *)ret)->label;
177 break;
178#endif
Jonathan Gordon87aa86c2011-03-27 08:01:58 +0000179#ifdef HAVE_SKIN_VARIABLES
180 case SKIN_VARIABLE:
181 ret = list.linkedlist->token->value.data;
182 itemlabel = ((struct skin_var *)ret)->label;
183 break;
184#endif
185
Jonathan Gordone7659062011-03-07 12:56:24 +0000186 }
187 if (!skip && itemlabel && !strcmp(itemlabel, label))
188 return ret;
189
190 if (isvplist)
191 list.vplist = list.vplist->next;
192 else
193 list.linkedlist = list.linkedlist->next;
194 }
195 return NULL;
196}
197
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000198#ifdef HAVE_LCD_BITMAP
Thomas Martitz3216d322009-11-01 15:48:31 +0000199
Jonathan Gordon18a8e522009-08-16 18:23:00 +0000200/* create and init a new wpsll item.
201 * passing NULL to token will alloc a new one.
Jonathan Gordon271643c2009-08-16 21:22:57 +0000202 * You should only pass NULL for the token when the token type (table above)
203 * is WPS_NO_TOKEN which means it is not stored automatically in the skins token array
Jonathan Gordon18a8e522009-08-16 18:23:00 +0000204 */
205static struct skin_token_list *new_skin_token_list_item(struct wps_token *token,
206 void* token_data)
207{
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000208 struct skin_token_list *llitem =
209 (struct skin_token_list *)skin_buffer_alloc(sizeof(struct skin_token_list));
Jonathan Gordon18a8e522009-08-16 18:23:00 +0000210 if (!token)
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000211 token = (struct wps_token*)skin_buffer_alloc(sizeof(struct wps_token));
Jonathan Gordon18a8e522009-08-16 18:23:00 +0000212 if (!llitem || !token)
213 return NULL;
214 llitem->next = NULL;
215 llitem->token = token;
Jonathan Gordon58ca43d2009-12-03 05:36:23 +0000216 if (token_data)
217 llitem->token->value.data = token_data;
Jonathan Gordon18a8e522009-08-16 18:23:00 +0000218 return llitem;
Thomas Martitz541dd6f2009-09-13 12:24:14 +0000219}
Jonathan Gordon18a8e522009-08-16 18:23:00 +0000220
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000221static int parse_statusbar_tags(struct skin_element* element,
222 struct wps_token *token,
223 struct wps_data *wps_data)
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000224{
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000225 (void)element;
226 if (token->type == SKIN_TOKEN_DRAW_INBUILTBAR)
Jonathan Gordon8cb74432009-09-02 02:55:33 +0000227 {
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000228 token->value.data = (void*)&curr_vp->vp;
Jonathan Gordon8cb74432009-09-02 02:55:33 +0000229 }
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000230 else
231 {
232 struct skin_element *def_vp = wps_data->tree;
233 struct skin_viewport *default_vp = def_vp->data;
234 if (def_vp->params_count == 0)
235 {
236 wps_data->wps_sb_tag = true;
237 wps_data->show_sb_on_wps = (token->type == SKIN_TOKEN_ENABLE_THEME);
238 }
239 if (wps_data->show_sb_on_wps)
240 {
241 viewport_set_defaults(&default_vp->vp, curr_screen);
242 }
243 else
244 {
245 viewport_set_fullscreen(&default_vp->vp, curr_screen);
246 }
Jonathan Gordon9e2cd392010-08-01 11:37:02 +0000247#ifdef HAVE_REMOTE_LCD
248 /* viewport_set_defaults() sets the font to FONT_UI+curr_screen.
249 * This parser requires font 1 to always be the UI font,
250 * so force it back to FONT_UI and handle the screen number at the end */
251 default_vp->vp.font = FONT_UI;
252#endif
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000253 }
254 return 0;
Nicolas Pennequin07696c12007-04-08 04:01:06 +0000255}
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000256
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000257static int get_image_id(int c)
258{
259 if(c >= 'a' && c <= 'z')
260 return c - 'a';
261 else if(c >= 'A' && c <= 'Z')
262 return c - 'A' + 26;
263 else
264 return -1;
265}
266
Jonathan Gordon877d3782010-02-16 05:24:27 +0000267char *get_image_filename(const char *start, const char* bmpdir,
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000268 char *buf, int buf_size)
269{
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000270 snprintf(buf, buf_size, "%s/%s", bmpdir, start);
271
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000272 return buf;
273}
274
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000275static int parse_image_display(struct skin_element *element,
Nicolas Pennequin07696c12007-04-08 04:01:06 +0000276 struct wps_token *token,
277 struct wps_data *wps_data)
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000278{
Jonathan Gordonff8d43d2010-08-14 11:40:20 +0000279 char *label = element->params[0].data.text;
Magnus Holmgrenac2c69c2010-08-15 07:08:23 +0000280 char sublabel = '\0';
Dave Chapman15ddd7a2008-03-23 20:31:00 +0000281 int subimage;
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000282 struct gui_img *img;
Jonathan Gordon3f8e7fc2010-08-05 11:28:48 +0000283 struct image_display *id = skin_buffer_alloc(sizeof(struct image_display));
Nicolas Pennequin32bd59d2007-04-14 16:20:33 +0000284
Magnus Holmgrenac2c69c2010-08-15 07:08:23 +0000285 if (element->params_count == 1 && strlen(label) <= 2)
Jonathan Gordonff8d43d2010-08-14 11:40:20 +0000286 {
287 /* backwards compatability. Allow %xd(Aa) to still work */
Magnus Holmgrenac2c69c2010-08-15 07:08:23 +0000288 sublabel = label[1];
Jonathan Gordonff8d43d2010-08-14 11:40:20 +0000289 label[1] = '\0';
290 }
Jonathan Gordondab7e162009-08-18 07:17:51 +0000291 /* sanity check */
Jonathan Gordon343001b2011-03-07 12:45:45 +0000292 img = skin_find_item(label, SKIN_FIND_IMAGE, wps_data);
Jonathan Gordon3f8e7fc2010-08-05 11:28:48 +0000293 if (!img || !id)
Nicolas Pennequin32bd59d2007-04-14 16:20:33 +0000294 {
Nicolas Pennequin31f76112007-11-14 22:02:41 +0000295 return WPS_ERROR_INVALID_PARAM;
Nicolas Pennequin32bd59d2007-04-14 16:20:33 +0000296 }
Jonathan Gordon3f8e7fc2010-08-05 11:28:48 +0000297 id->label = label;
298 id->offset = 0;
Jonathan Gordon863d2392010-08-14 11:17:49 +0000299 id->token = NULL;
Teruaki Kawashima717f0bd2010-09-29 13:23:24 +0000300 if (img->using_preloaded_icons)
Jonathan Gordon70ebe462010-08-12 13:27:10 +0000301 {
Jonathan Gordon70ebe462010-08-12 13:27:10 +0000302 token->type = SKIN_TOKEN_IMAGE_DISPLAY_LISTICON;
303 }
Jonathan Gordon3f8e7fc2010-08-05 11:28:48 +0000304
305 if (element->params_count > 1)
Dave Chapman15ddd7a2008-03-23 20:31:00 +0000306 {
Jonathan Gordon863d2392010-08-14 11:17:49 +0000307 if (element->params[1].type == CODE)
308 id->token = element->params[1].data.code->data;
309 /* specify a number. 1 being the first subimage (i.e top) NOT 0 */
310 else if (element->params[1].type == INTEGER)
311 id->subimage = element->params[1].data.number - 1;
Jonathan Gordon3f8e7fc2010-08-05 11:28:48 +0000312 if (element->params_count > 2)
313 id->offset = element->params[2].data.number;
Dave Chapman15ddd7a2008-03-23 20:31:00 +0000314 }
Jonathan Gordon3f8e7fc2010-08-05 11:28:48 +0000315 else
316 {
Jonathan Gordon3f8e7fc2010-08-05 11:28:48 +0000317 if ((subimage = get_image_id(sublabel)) != -1)
318 {
319 if (subimage >= img->num_subimages)
320 return WPS_ERROR_INVALID_PARAM;
321 id->subimage = subimage;
Jonathan Gordon3f8e7fc2010-08-05 11:28:48 +0000322 } else {
323 id->subimage = 0;
324 }
325 }
326 token->value.data = id;
327 return 0;
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000328}
329
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000330static int parse_image_load(struct skin_element *element,
Nicolas Pennequin07696c12007-04-08 04:01:06 +0000331 struct wps_token *token,
332 struct wps_data *wps_data)
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000333{
Dave Chapmane92d2c52008-03-21 13:41:35 +0000334 const char* filename;
335 const char* id;
336 int x,y;
Jonathan Gordon58ca43d2009-12-03 05:36:23 +0000337 struct gui_img *img;
Thomas Martitz541dd6f2009-09-13 12:24:14 +0000338
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000339 /* format: %x(n,filename.bmp,x,y)
340 or %xl(n,filename.bmp,x,y)
341 or %xl(n,filename.bmp,x,y,num_subimages)
Dave Chapman15ddd7a2008-03-23 20:31:00 +0000342 */
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000343
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000344 id = element->params[0].data.text;
345 filename = element->params[1].data.text;
346 x = element->params[2].data.number;
347 y = element->params[3].data.number;
Nicolas Pennequin27cbf6b2007-04-12 16:15:34 +0000348
Nicolas Pennequin27cbf6b2007-04-12 16:15:34 +0000349 /* check the image number and load state */
Jonathan Gordon343001b2011-03-07 12:45:45 +0000350 if(skin_find_item(id, SKIN_FIND_IMAGE, wps_data))
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000351 {
Nicolas Pennequin31f76112007-11-14 22:02:41 +0000352 /* Invalid image ID */
353 return WPS_ERROR_INVALID_PARAM;
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000354 }
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000355 img = (struct gui_img*)skin_buffer_alloc(sizeof(struct gui_img));
Jonathan Gordon58ca43d2009-12-03 05:36:23 +0000356 if (!img)
357 return WPS_ERROR_INVALID_PARAM;
Dave Chapmane92d2c52008-03-21 13:41:35 +0000358 /* save a pointer to the filename */
Jonathan Gordon18a8e522009-08-16 18:23:00 +0000359 img->bm.data = (char*)filename;
Jonathan Gordonff8d43d2010-08-14 11:40:20 +0000360 img->label = id;
Jonathan Gordon18a8e522009-08-16 18:23:00 +0000361 img->x = x;
362 img->y = y;
Jonathan Gordon58ca43d2009-12-03 05:36:23 +0000363 img->num_subimages = 1;
Jonathan Gordon18a8e522009-08-16 18:23:00 +0000364 img->always_display = false;
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000365 img->display = -1;
Teruaki Kawashima717f0bd2010-09-29 13:23:24 +0000366 img->using_preloaded_icons = false;
Nicolas Pennequin27cbf6b2007-04-12 16:15:34 +0000367
Dave Chapmand02c79c2008-03-21 19:38:00 +0000368 /* save current viewport */
Jonathan Gordon36ca4962009-08-18 05:30:59 +0000369 img->vp = &curr_vp->vp;
Dave Chapmand02c79c2008-03-21 19:38:00 +0000370
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000371 if (token->type == SKIN_TOKEN_IMAGE_DISPLAY)
Dave Chapman15ddd7a2008-03-23 20:31:00 +0000372 {
Jonathan Gordon18a8e522009-08-16 18:23:00 +0000373 img->always_display = true;
Dave Chapman15ddd7a2008-03-23 20:31:00 +0000374 }
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000375 else if (element->params_count == 5)
Dave Chapman15ddd7a2008-03-23 20:31:00 +0000376 {
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000377 img->num_subimages = element->params[4].data.number;
Jonathan Gordon18a8e522009-08-16 18:23:00 +0000378 if (img->num_subimages <= 0)
Dave Chapman6d9c3532008-03-24 10:13:47 +0000379 return WPS_ERROR_INVALID_PARAM;
Dave Chapman15ddd7a2008-03-23 20:31:00 +0000380 }
Teruaki Kawashima717f0bd2010-09-29 13:23:24 +0000381
382 if (!strcmp(img->bm.data, "__list_icons__"))
383 {
384 img->num_subimages = Icon_Last_Themeable;
385 img->using_preloaded_icons = true;
386 }
Jonathan Gordon70ebe462010-08-12 13:27:10 +0000387
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000388 struct skin_token_list *item =
389 (struct skin_token_list *)new_skin_token_list_item(NULL, img);
Jonathan Gordon58ca43d2009-12-03 05:36:23 +0000390 if (!item)
391 return WPS_ERROR_INVALID_PARAM;
392 add_to_ll_chain(&wps_data->images, item);
Nicolas Pennequin27cbf6b2007-04-12 16:15:34 +0000393
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000394 return 0;
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000395}
Jonathan Gordon8717c1e2010-02-28 08:36:13 +0000396struct skin_font {
397 int id; /* the id from font_load */
398 char *name; /* filename without path and extension */
Jonathan Gordonfaaf4312010-08-25 14:11:38 +0000399 int glyphs; /* how many glyphs to reserve room for */
Jonathan Gordon8717c1e2010-02-28 08:36:13 +0000400};
401static struct skin_font skinfonts[MAXUSERFONTS];
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000402static int parse_font_load(struct skin_element *element,
403 struct wps_token *token,
404 struct wps_data *wps_data)
Jonathan Gordon1c2aa352010-02-14 06:26:16 +0000405{
406 (void)wps_data; (void)token;
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000407 int id = element->params[0].data.number;
408 char *filename = element->params[1].data.text;
Jonathan Gordonfaaf4312010-08-25 14:11:38 +0000409 int glyphs;
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000410 char *ptr;
411
Jonathan Gordonfaaf4312010-08-25 14:11:38 +0000412 if(element->params_count > 2)
413 glyphs = element->params[2].data.number;
414 else
415 glyphs = GLYPHS_TO_CACHE;
Jonathan Gordon8717c1e2010-02-28 08:36:13 +0000416#if defined(DEBUG) || defined(SIMULATOR)
417 if (skinfonts[id-FONT_FIRSTUSERFONT].name != NULL)
418 {
419 DEBUGF("font id %d already being used\n", id);
420 }
421#endif
Jonathan Gordon25d97712010-03-03 05:43:02 +0000422 /* make sure the filename contains .fnt,
423 * we dont actually use it, but require it anyway */
424 ptr = strchr(filename, '.');
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000425 if (!ptr || strncmp(ptr, ".fnt", 4))
Jonathan Gordon25d97712010-03-03 05:43:02 +0000426 return WPS_ERROR_INVALID_PARAM;
Jonathan Gordon8717c1e2010-02-28 08:36:13 +0000427 skinfonts[id-FONT_FIRSTUSERFONT].id = -1;
428 skinfonts[id-FONT_FIRSTUSERFONT].name = filename;
Jonathan Gordonfaaf4312010-08-25 14:11:38 +0000429 skinfonts[id-FONT_FIRSTUSERFONT].glyphs = glyphs;
Teruaki Kawashimabc58b7d2010-06-09 14:06:42 +0000430
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000431 return 0;
Jonathan Gordon1c2aa352010-02-14 06:26:16 +0000432}
Teruaki Kawashimabc58b7d2010-06-09 14:06:42 +0000433
434
Jonathan Gordondc0ba912010-01-13 06:02:38 +0000435#ifdef HAVE_LCD_BITMAP
Teruaki Kawashima1fbdd912010-03-06 14:14:44 +0000436
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000437static int parse_playlistview(struct skin_element *element,
438 struct wps_token *token,
439 struct wps_data *wps_data)
Jonathan Gordondc0ba912010-01-13 06:02:38 +0000440{
441 (void)wps_data;
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000442 struct playlistviewer *viewer =
443 (struct playlistviewer *)skin_buffer_alloc(sizeof(struct playlistviewer));
444 if (!viewer)
Jonathan Gordondc0ba912010-01-13 06:02:38 +0000445 return WPS_ERROR_INVALID_PARAM;
446 viewer->vp = &curr_vp->vp;
447 viewer->show_icons = true;
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000448 viewer->start_offset = element->params[0].data.number;
Jonathan Gordondc3778a2010-08-14 15:17:59 +0000449 viewer->line = element->params[1].data.code;
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000450
Jonathan Gordondc0ba912010-01-13 06:02:38 +0000451 token->value.data = (void*)viewer;
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000452
453 return 0;
Jonathan Gordondc0ba912010-01-13 06:02:38 +0000454}
455#endif
Jonathan Gordon281f1a12011-08-14 13:50:07 +0000456#ifdef HAVE_LCD_COLOR
457static int parse_viewport_gradient_setup(struct skin_element *element,
458 struct wps_token *token,
459 struct wps_data *wps_data)
460{
461 (void)wps_data;
462 struct gradient_config *cfg;
463 if (element->params_count < 2) /* only start and end are required */
464 return 1;
465 cfg = (struct gradient_config *)skin_buffer_alloc(sizeof(struct gradient_config));
466 if (!cfg)
467 return 1;
468 if (!parse_color(curr_screen, element->params[0].data.text, &cfg->start) ||
469 !parse_color(curr_screen, element->params[1].data.text, &cfg->end))
470 return 1;
471 if (element->params_count > 2)
472 {
473 if (!parse_color(curr_screen, element->params[2].data.text, &cfg->text))
474 return 1;
475 }
476 else
477 {
478 cfg->text = curr_vp->vp.fg_pattern;
479 }
480
481 token->value.data = cfg;
482 return 0;
483}
484#endif
Jonathan Gordon4ed13402011-08-14 13:56:10 +0000485
486#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
Jonathan Gordon281f1a12011-08-14 13:50:07 +0000487static int parse_viewporttextstyle(struct skin_element *element,
488 struct wps_token *token,
489 struct wps_data *wps_data)
490{
491 (void)wps_data;
492 int style;
493 char *mode = element->params[0].data.text;
494 unsigned colour;
495
496 if (!strcmp(mode, "invert"))
497 {
498 style = STYLE_INVERT;
499 }
500 else if (!strcmp(mode, "colour") || !strcmp(mode, "color"))
501 {
502 if (element->params_count < 2 ||
503 !parse_color(curr_screen, element->params[1].data.text, &colour))
504 return 1;
505 style = STYLE_COLORED|(STYLE_COLOR_MASK&colour);
506 }
507#ifdef HAVE_LCD_COLOR
508 else if (!strcmp(mode, "gradient"))
509 {
510 int num_lines;
511 if (element->params_count < 2)
512 num_lines = 1;
513 else /* atoi() instead of using a number in the parser is because [si]
514 * will select the number for something which looks like a colour
515 * making the "colour" case (above) harder to parse */
516 num_lines = atoi(element->params[1].data.text);
517 style = STYLE_GRADIENT|NUMLN_PACK(num_lines)|CURLN_PACK(0);
518 }
519#endif
520 else if (!strcmp(mode, "clear"))
521 {
522 style = STYLE_DEFAULT;
523 }
524 else
525 return 1;
526 token->value.l = style;
527 return 0;
528}
Jonathan Gordondc0ba912010-01-13 06:02:38 +0000529
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000530static int parse_viewportcolour(struct skin_element *element,
531 struct wps_token *token,
532 struct wps_data *wps_data)
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000533{
534 (void)wps_data;
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000535 struct skin_tag_parameter *param = element->params;
536 struct viewport_colour *colour =
537 (struct viewport_colour *)skin_buffer_alloc(sizeof(struct viewport_colour));
538 if (!colour)
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000539 return -1;
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000540 if (isdefault(param))
541 {
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000542 colour->colour = get_viewport_default_colour(curr_screen,
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000543 token->type == SKIN_TOKEN_VIEWPORT_FGCOLOUR);
544 }
545 else
546 {
Jonathan Gordon489962d2010-08-10 14:15:03 +0000547 if (!parse_color(curr_screen, param->data.text, &colour->colour))
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000548 return -1;
549 }
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000550 colour->vp = &curr_vp->vp;
551 token->value.data = colour;
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000552 if (element->line == curr_viewport_element->line)
Jonathan Gordonfe72cbe2010-06-07 11:45:02 +0000553 {
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000554 if (token->type == SKIN_TOKEN_VIEWPORT_FGCOLOUR)
Jonathan Gordonfe72cbe2010-06-07 11:45:02 +0000555 {
556 curr_vp->start_fgcolour = colour->colour;
557 curr_vp->vp.fg_pattern = colour->colour;
558 }
559 else
560 {
561 curr_vp->start_bgcolour = colour->colour;
562 curr_vp->vp.bg_pattern = colour->colour;
563 }
564 }
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000565 return 0;
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000566}
567
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000568static int parse_image_special(struct skin_element *element,
Björn Stenberg66459fe2008-12-08 08:32:30 +0000569 struct wps_token *token,
570 struct wps_data *wps_data)
571{
572 (void)wps_data; /* kill warning */
573 (void)token;
Björn Stenberg66459fe2008-12-08 08:32:30 +0000574
Björn Stenberg66459fe2008-12-08 08:32:30 +0000575#if LCD_DEPTH > 1
Jonathan Gordon9928e342010-09-14 11:56:50 +0000576 char *filename;
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000577 if (token->type == SKIN_TOKEN_IMAGE_BACKDROP)
Björn Stenberg66459fe2008-12-08 08:32:30 +0000578 {
Jonathan Gordon9928e342010-09-14 11:56:50 +0000579 if (isdefault(&element->params[0]))
Jonathan Gordoneee54232010-01-29 07:52:13 +0000580 {
Jonathan Gordon9928e342010-09-14 11:56:50 +0000581 filename = "-";
Jonathan Gordoneee54232010-01-29 07:52:13 +0000582 }
Jonathan Gordon9928e342010-09-14 11:56:50 +0000583 else
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000584 {
Jonathan Gordon9928e342010-09-14 11:56:50 +0000585 filename = element->params[0].data.text;
586 /* format: %X(filename.bmp) or %X(d) */
587 if (!strcmp(filename, "d"))
588 filename = NULL;
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000589 }
Jonathan Gordon9928e342010-09-14 11:56:50 +0000590 wps_data->backdrop = filename;
Björn Stenberg66459fe2008-12-08 08:32:30 +0000591 }
592#endif
Jonathan Gordon9928e342010-09-14 11:56:50 +0000593
594 return 0;
Björn Stenberg66459fe2008-12-08 08:32:30 +0000595}
596#endif
597
598#endif /* HAVE_LCD_BITMAP */
599
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000600static int parse_setting_and_lang(struct skin_element *element,
601 struct wps_token *token,
602 struct wps_data *wps_data)
Antoine Cellerier8289b962008-12-07 16:20:35 +0000603{
Jonathan Gordon340f3232009-09-26 00:58:32 +0000604 /* NOTE: both the string validations that happen in here will
605 * automatically PASS on checkwps because its too hard to get
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000606 * settings_list.c and english.lang built for it.
Jonathan Gordon340f3232009-09-26 00:58:32 +0000607 * If that ever changes remove the #ifndef __PCTOOL__'s here
608 */
Antoine Cellerier8289b962008-12-07 16:20:35 +0000609 (void)wps_data;
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000610 char *temp = element->params[0].data.text;
611 int i;
Jonathan Gordon340f3232009-09-26 00:58:32 +0000612
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000613 if (token->type == SKIN_TOKEN_TRANSLATEDSTRING)
Jonathan Gordon340f3232009-09-26 00:58:32 +0000614 {
615#ifndef __PCTOOL__
616 i = lang_english_to_id(temp);
617 if (i < 0)
618 return WPS_ERROR_INVALID_PARAM;
619#endif
620 }
621 else
622 {
Jonathan Gordon340f3232009-09-26 00:58:32 +0000623#ifndef __PCTOOL__
Jonathan Gordon89973212011-09-04 13:17:09 +0000624 if (find_setting_by_cfgname(temp, &i) == NULL)
Jonathan Gordon340f3232009-09-26 00:58:32 +0000625 return WPS_ERROR_INVALID_PARAM;
626#endif
627 }
Antoine Cellerier8289b962008-12-07 16:20:35 +0000628 /* Store the setting number */
629 token->value.i = i;
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000630 return 0;
Antoine Cellerier8289b962008-12-07 16:20:35 +0000631}
Jonathan Gordon74ec0112010-08-19 13:49:32 +0000632static int parse_logical_if(struct skin_element *element,
633 struct wps_token *token,
634 struct wps_data *wps_data)
635{
636 (void)wps_data;
637 char *op = element->params[1].data.text;
638 struct logical_if *lif = skin_buffer_alloc(sizeof(struct logical_if));
639 if (!lif)
640 return -1;
641 token->value.data = lif;
642 lif->token = element->params[0].data.code->data;
643
Jonathan Gordon5ad40802010-11-30 13:12:27 +0000644 if (!strncmp(op, "=", 1))
Jonathan Gordon74ec0112010-08-19 13:49:32 +0000645 lif->op = IF_EQUALS;
Jonathan Gordon5ad40802010-11-30 13:12:27 +0000646 else if (!strncmp(op, "!=", 2))
Jonathan Gordon74ec0112010-08-19 13:49:32 +0000647 lif->op = IF_NOTEQUALS;
Jonathan Gordon5ad40802010-11-30 13:12:27 +0000648 else if (!strncmp(op, ">=", 2))
Jonathan Gordon74ec0112010-08-19 13:49:32 +0000649 lif->op = IF_GREATERTHAN_EQ;
Jonathan Gordon5ad40802010-11-30 13:12:27 +0000650 else if (!strncmp(op, "<=", 2))
651 lif->op = IF_LESSTHAN_EQ;
652 else if (!strncmp(op, ">", 2))
653 lif->op = IF_GREATERTHAN;
654 else if (!strncmp(op, "<", 1))
655 lif->op = IF_LESSTHAN;
Jonathan Gordon74ec0112010-08-19 13:49:32 +0000656
657 memcpy(&lif->operand, &element->params[2], sizeof(lif->operand));
658 if (element->params_count > 3)
659 lif->num_options = element->params[3].data.number;
660 else
661 lif->num_options = TOKEN_VALUE_ONLY;
662 return 0;
663
664}
Jonathan Gordon156b0bc2011-02-28 11:19:59 +0000665
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000666static int parse_timeout_tag(struct skin_element *element,
Nicolas Pennequin07696c12007-04-08 04:01:06 +0000667 struct wps_token *token,
668 struct wps_data *wps_data)
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000669{
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000670 (void)wps_data;
671 int val = 0;
672 if (element->params_count == 0)
Jonathan Gordon8cb74432009-09-02 02:55:33 +0000673 {
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000674 switch (token->type)
675 {
676 case SKIN_TOKEN_SUBLINE_TIMEOUT:
677 return -1;
678 case SKIN_TOKEN_BUTTON_VOLUME:
679 case SKIN_TOKEN_TRACK_STARTING:
680 case SKIN_TOKEN_TRACK_ENDING:
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000681 val = 10;
682 break;
683 default:
684 break;
685 }
Jonathan Gordon8cb74432009-09-02 02:55:33 +0000686 }
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000687 else
688 val = element->params[0].data.number;
Jonathan Gordon6dc4d652010-08-01 10:40:29 +0000689 token->value.i = val * TIMEOUT_UNIT;
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000690 return 0;
691}
692
693static int parse_progressbar_tag(struct skin_element* element,
694 struct wps_token *token,
695 struct wps_data *wps_data)
696{
697#ifdef HAVE_LCD_BITMAP
698 struct progressbar *pb;
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000699 struct viewport *vp = &curr_vp->vp;
700 struct skin_tag_parameter *param = element->params;
Jonathan Gordoneda80392010-08-15 14:13:36 +0000701 int curr_param = 0;
Jonathan Gordon9acd2422010-10-12 12:46:57 +0000702 char *image_filename = NULL;
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000703
704 if (element->params_count == 0 &&
705 element->tag->type != SKIN_TOKEN_PROGRESSBAR)
706 return 0; /* nothing to do */
707 pb = (struct progressbar*)skin_buffer_alloc(sizeof(struct progressbar));
708
709 token->value.data = pb;
710
711 if (!pb)
712 return WPS_ERROR_INVALID_PARAM;
Jonathan Gordon44217462010-04-11 11:18:45 +0000713 pb->vp = vp;
Jonathan Gordon91e6b062010-01-07 07:34:15 +0000714 pb->follow_lang_direction = follow_lang_direction > 0;
Jonathan Gordon0be24262010-08-16 12:07:39 +0000715 pb->nofill = false;
Teruaki Kawashima3eb58262010-10-12 12:17:39 +0000716 pb->nobar = false;
Jonathan Gordon9acd2422010-10-12 12:46:57 +0000717 pb->image = NULL;
Jonathan Gordon0be24262010-08-16 12:07:39 +0000718 pb->slider = NULL;
Jonathan Gordonf06f6852011-01-24 09:04:28 +0000719 pb->backdrop = NULL;
Jonathan Gordoneda80392010-08-15 14:13:36 +0000720 pb->invert_fill_direction = false;
Jonathan Gordon0be24262010-08-16 12:07:39 +0000721 pb->horizontal = true;
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000722
723 if (element->params_count == 0)
Jonathan Gordon5a169bb2008-06-23 06:04:17 +0000724 {
725 pb->x = 0;
726 pb->width = vp->width;
727 pb->height = SYSFONT_HEIGHT-2;
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000728 pb->y = -1; /* Will be computed during the rendering */
729 pb->type = element->tag->type;
Jonathan Gordon5a169bb2008-06-23 06:04:17 +0000730 return 0;
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000731 }
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000732
Jonathan Gordon69e379a2010-10-12 12:03:07 +0000733 /* (x, y, width, height, ...) */
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000734 if (!isdefault(param))
735 pb->x = param->data.number;
Jonathan Gordon5a169bb2008-06-23 06:04:17 +0000736 else
Jonathan Gordondbde63b2010-09-05 10:23:09 +0000737 pb->x = 0;
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000738 param++;
739
740 if (!isdefault(param))
741 pb->y = param->data.number;
742 else
743 pb->y = -1; /* computed at rendering */
744 param++;
745
746 if (!isdefault(param))
747 pb->width = param->data.number;
Jonathan Gordon5a169bb2008-06-23 06:04:17 +0000748 else
749 pb->width = vp->width - pb->x;
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000750 param++;
751
752 if (!isdefault(param))
Dave Chapmana42602b2008-10-22 21:35:38 +0000753 {
754 /* A zero height makes no sense - reject it */
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000755 if (param->data.number == 0)
Dave Chapmana42602b2008-10-22 21:35:38 +0000756 return WPS_ERROR_INVALID_PARAM;
757
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000758 pb->height = param->data.number;
Dave Chapmana42602b2008-10-22 21:35:38 +0000759 }
Jonathan Gordon5a169bb2008-06-23 06:04:17 +0000760 else
Jonathan Gordon04e0d6c2010-03-02 08:47:45 +0000761 {
762 if (vp->font > FONT_UI)
763 pb->height = -1; /* calculate at display time */
764 else
765 {
766#ifndef __PCTOOL__
767 pb->height = font_get(vp->font)->height;
768#else
769 pb->height = 8;
770#endif
771 }
772 }
Jonathan Gordon69e379a2010-10-12 12:03:07 +0000773 /* optional params, first is the image filename if it isnt recognised as a keyword */
774
775 curr_param = 4;
776 if (isdefault(&element->params[curr_param]))
777 {
778 param++;
779 curr_param++;
780 }
781
Jonathan Gordoneda80392010-08-15 14:13:36 +0000782 pb->horizontal = pb->width > pb->height;
783 while (curr_param < element->params_count)
784 {
785 param++;
786 if (!strcmp(param->data.text, "invert"))
787 pb->invert_fill_direction = true;
788 else if (!strcmp(param->data.text, "nofill"))
789 pb->nofill = true;
Teruaki Kawashima3eb58262010-10-12 12:17:39 +0000790 else if (!strcmp(param->data.text, "nobar"))
791 pb->nobar = true;
Jonathan Gordoneda80392010-08-15 14:13:36 +0000792 else if (!strcmp(param->data.text, "slider"))
793 {
794 if (curr_param+1 < element->params_count)
795 {
796 curr_param++;
797 param++;
Jonathan Gordon343001b2011-03-07 12:45:45 +0000798 pb->slider = skin_find_item(param->data.text,
Jonathan Gordon87aa86c2011-03-27 08:01:58 +0000799 SKIN_FIND_IMAGE, wps_data);
Jonathan Gordoneda80392010-08-15 14:13:36 +0000800 }
Jonathan Gordon69e379a2010-10-12 12:03:07 +0000801 else /* option needs the next param */
802 return -1;
803 }
804 else if (!strcmp(param->data.text, "image"))
805 {
806 if (curr_param+1 < element->params_count)
807 {
808 curr_param++;
809 param++;
Jonathan Gordon9acd2422010-10-12 12:46:57 +0000810 image_filename = param->data.text;
811
Jonathan Gordon69e379a2010-10-12 12:03:07 +0000812 }
813 else /* option needs the next param */
814 return -1;
Jonathan Gordoneda80392010-08-15 14:13:36 +0000815 }
Jonathan Gordonf06f6852011-01-24 09:04:28 +0000816 else if (!strcmp(param->data.text, "backdrop"))
817 {
818 if (curr_param+1 < element->params_count)
819 {
820 curr_param++;
821 param++;
Jonathan Gordon343001b2011-03-07 12:45:45 +0000822 pb->backdrop = skin_find_item(param->data.text,
Jonathan Gordon87aa86c2011-03-27 08:01:58 +0000823 SKIN_FIND_IMAGE, wps_data);
Jonathan Gordonf06f6852011-01-24 09:04:28 +0000824
825 }
826 else /* option needs the next param */
827 return -1;
828 }
Jonathan Gordoneda80392010-08-15 14:13:36 +0000829 else if (!strcmp(param->data.text, "vertical"))
830 {
831 pb->horizontal = false;
832 if (isdefault(&element->params[3]))
Jonathan Gordon3f7b7802010-10-09 12:18:10 +0000833 pb->height = vp->height - pb->y;
Jonathan Gordoneda80392010-08-15 14:13:36 +0000834 }
835 else if (!strcmp(param->data.text, "horizontal"))
836 pb->horizontal = true;
Jonathan Gordon69e379a2010-10-12 12:03:07 +0000837 else if (curr_param == 4)
Jonathan Gordon9acd2422010-10-12 12:46:57 +0000838 image_filename = param->data.text;
Jonathan Gordoneda80392010-08-15 14:13:36 +0000839
840 curr_param++;
841 }
Jonathan Gordon9acd2422010-10-12 12:46:57 +0000842
843 if (image_filename)
844 {
Jonathan Gordon343001b2011-03-07 12:45:45 +0000845 pb->image = skin_find_item(image_filename, SKIN_FIND_IMAGE, wps_data);
Jonathan Gordon9acd2422010-10-12 12:46:57 +0000846 if (!pb->image) /* load later */
847 {
848 struct gui_img* img = (struct gui_img*)skin_buffer_alloc(sizeof(struct gui_img));
849 if (!img)
850 return WPS_ERROR_INVALID_PARAM;
851 /* save a pointer to the filename */
852 img->bm.data = (char*)image_filename;
853 img->label = image_filename;
854 img->x = 0;
855 img->y = 0;
856 img->num_subimages = 1;
857 img->always_display = false;
858 img->display = -1;
859 img->using_preloaded_icons = false;
860 img->vp = &curr_vp->vp;
861 struct skin_token_list *item =
862 (struct skin_token_list *)new_skin_token_list_item(NULL, img);
863 if (!item)
864 return WPS_ERROR_INVALID_PARAM;
865 add_to_ll_chain(&wps_data->images, item);
866 pb->image = img;
867 }
Jonathan Gordonf06f6852011-01-24 09:04:28 +0000868 }
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000869
870 if (token->type == SKIN_TOKEN_VOLUME)
871 token->type = SKIN_TOKEN_VOLUMEBAR;
872 else if (token->type == SKIN_TOKEN_BATTERY_PERCENT)
873 token->type = SKIN_TOKEN_BATTERY_PERCENTBAR;
Jonathan Gordon1ce7ba42010-11-18 11:47:42 +0000874 else if (token->type == SKIN_TOKEN_TUNER_RSSI)
875 token->type = SKIN_TOKEN_TUNER_RSSI_BAR;
Jonathan Gordon261c56b2011-01-13 06:48:39 +0000876 else if (token->type == SKIN_TOKEN_PEAKMETER_LEFT)
877 token->type = SKIN_TOKEN_PEAKMETER_LEFTBAR;
878 else if (token->type == SKIN_TOKEN_PEAKMETER_RIGHT)
879 token->type = SKIN_TOKEN_PEAKMETER_RIGHTBAR;
Jonathan Gordon44217462010-04-11 11:18:45 +0000880 pb->type = token->type;
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000881
882 return 0;
883
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000884#else
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000885 (void)element;
886 if (token->type == SKIN_TOKEN_PROGRESSBAR ||
887 token->type == SKIN_TOKEN_PLAYER_PROGRESSBAR)
Jonathan Gordon44217462010-04-11 11:18:45 +0000888 {
889 wps_data->full_line_progressbar =
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000890 token->type == SKIN_TOKEN_PLAYER_PROGRESSBAR;
Jonathan Gordon44217462010-04-11 11:18:45 +0000891 }
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000892 return 0;
893
894#endif
895}
896
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +0000897#ifdef HAVE_ALBUMART
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000898static int parse_albumart_load(struct skin_element* element,
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +0000899 struct wps_token *token,
900 struct wps_data *wps_data)
901{
Thomas Martitze9c10182009-10-16 19:14:41 +0000902 struct dim dimensions;
903 int albumart_slot;
Jonathan Gordon91e6b062010-01-07 07:34:15 +0000904 bool swap_for_rtl = lang_is_rtl() && follow_lang_direction;
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000905 struct skin_albumart *aa =
906 (struct skin_albumart *)skin_buffer_alloc(sizeof(struct skin_albumart));
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +0000907 (void)token; /* silence warning */
Jonathan Gordonfe2f0422009-09-07 02:36:56 +0000908 if (!aa)
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000909 return -1;
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +0000910
911 /* reset albumart info in wps */
Thomas Martitzba8fbb02009-09-25 18:36:28 +0000912 aa->width = -1;
913 aa->height = -1;
914 aa->xalign = WPS_ALBUMART_ALIGN_CENTER; /* default */
915 aa->yalign = WPS_ALBUMART_ALIGN_CENTER; /* default */
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +0000916
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000917 aa->x = element->params[0].data.number;
918 aa->y = element->params[1].data.number;
919 aa->width = element->params[2].data.number;
920 aa->height = element->params[3].data.number;
921
922 aa->vp = &curr_vp->vp;
923 aa->draw_handle = -1;
Teruaki Kawashimabc58b7d2010-06-09 14:06:42 +0000924
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +0000925 /* if we got here, we parsed everything ok .. ! */
Thomas Martitzba8fbb02009-09-25 18:36:28 +0000926 if (aa->width < 0)
927 aa->width = 0;
928 else if (aa->width > LCD_WIDTH)
929 aa->width = LCD_WIDTH;
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +0000930
Thomas Martitzba8fbb02009-09-25 18:36:28 +0000931 if (aa->height < 0)
932 aa->height = 0;
933 else if (aa->height > LCD_HEIGHT)
934 aa->height = LCD_HEIGHT;
Teruaki Kawashima1fbdd912010-03-06 14:14:44 +0000935
Jonathan Gordon91e6b062010-01-07 07:34:15 +0000936 if (swap_for_rtl)
937 aa->x = LCD_WIDTH - (aa->x + aa->width);
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +0000938
Thomas Martitzba8fbb02009-09-25 18:36:28 +0000939 aa->state = WPS_ALBUMART_LOAD;
Jonathan Gordonfe2f0422009-09-07 02:36:56 +0000940 wps_data->albumart = aa;
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +0000941
Thomas Martitze9c10182009-10-16 19:14:41 +0000942 dimensions.width = aa->width;
943 dimensions.height = aa->height;
944
945 albumart_slot = playback_claim_aa_slot(&dimensions);
946
Tomer Shalev8db32dd2009-12-04 13:10:06 +0000947 if (0 <= albumart_slot)
Thomas Martitze9c10182009-10-16 19:14:41 +0000948 wps_data->playback_aa_slot = albumart_slot;
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000949
950 if (element->params_count > 4 && !isdefault(&element->params[4]))
Jonathan Gordon0d8fb602010-06-07 04:40:46 +0000951 {
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000952 switch (*element->params[4].data.text)
Teruaki Kawashimabc58b7d2010-06-09 14:06:42 +0000953 {
954 case 'l':
955 case 'L':
956 if (swap_for_rtl)
957 aa->xalign = WPS_ALBUMART_ALIGN_RIGHT;
958 else
959 aa->xalign = WPS_ALBUMART_ALIGN_LEFT;
960 break;
961 case 'c':
962 case 'C':
963 aa->xalign = WPS_ALBUMART_ALIGN_CENTER;
964 break;
965 case 'r':
966 case 'R':
967 if (swap_for_rtl)
968 aa->xalign = WPS_ALBUMART_ALIGN_LEFT;
969 else
970 aa->xalign = WPS_ALBUMART_ALIGN_RIGHT;
971 break;
972 }
Jonathan Gordon0d8fb602010-06-07 04:40:46 +0000973 }
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000974 if (element->params_count > 5 && !isdefault(&element->params[5]))
Jonathan Gordon0d8fb602010-06-07 04:40:46 +0000975 {
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000976 switch (*element->params[5].data.text)
Teruaki Kawashimabc58b7d2010-06-09 14:06:42 +0000977 {
978 case 't':
979 case 'T':
980 aa->yalign = WPS_ALBUMART_ALIGN_TOP;
981 break;
982 case 'c':
983 case 'C':
984 aa->yalign = WPS_ALBUMART_ALIGN_CENTER;
985 break;
986 case 'b':
987 case 'B':
988 aa->yalign = WPS_ALBUMART_ALIGN_BOTTOM;
989 break;
990 }
Jonathan Gordon0d8fb602010-06-07 04:40:46 +0000991 }
Jonathan Gordon2d31d772010-07-29 12:37:48 +0000992 return 0;
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +0000993}
994
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +0000995#endif /* HAVE_ALBUMART */
Jonathan Gordon87aa86c2011-03-27 08:01:58 +0000996#ifdef HAVE_SKIN_VARIABLES
997static struct skin_var* find_or_add_var(const char* label,
998 struct wps_data *data)
999{
1000 struct skin_var* ret = skin_find_item(label, SKIN_VARIABLE, data);
1001 if (!ret)
1002 {
1003 ret = (struct skin_var*)skin_buffer_alloc(sizeof(struct skin_var));
1004 if (!ret)
1005 return NULL;
1006 ret->label = label;
1007 ret->value = 1;
1008 ret->last_changed = 0xffff;
1009 struct skin_token_list *item = new_skin_token_list_item(NULL, ret);
1010 if (!item)
1011 return NULL;
1012 add_to_ll_chain(&data->skinvars, item);
1013 }
1014 return ret;
1015}
1016static int parse_skinvar( struct skin_element *element,
1017 struct wps_token *token,
1018 struct wps_data *wps_data)
1019{
1020 const char* label = element->params[0].data.text;
1021 struct skin_var* var = find_or_add_var(label, wps_data);
1022 if (!var)
1023 return WPS_ERROR_INVALID_PARAM;
1024 switch (token->type)
1025 {
1026 case SKIN_TOKEN_VAR_GETVAL:
1027 token->value.data = var;
1028 break;
1029 case SKIN_TOKEN_VAR_SET:
1030 {
1031 struct skin_var_changer *data =
1032 (struct skin_var_changer*)skin_buffer_alloc(
1033 sizeof(struct skin_var_changer));
1034 if (!data)
1035 return WPS_ERROR_INVALID_PARAM;
1036 data->var = var;
1037 data->newval = element->params[2].data.number;
1038 data->max = 0;
1039 if (!strcmp(element->params[1].data.text, "set"))
1040 data->direct = true;
1041 else if (!strcmp(element->params[1].data.text, "inc"))
1042 {
1043 data->direct = false;
1044 }
1045 else if (!strcmp(element->params[1].data.text, "dec"))
1046 {
1047 data->direct = false;
1048 data->newval *= -1;
1049 }
1050 if (element->params_count > 3)
1051 data->max = element->params[3].data.number;
1052 token->value.data = data;
1053 }
1054 break;
1055 case SKIN_TOKEN_VAR_TIMEOUT:
1056 {
1057 struct skin_var_lastchange *data =
1058 (struct skin_var_lastchange*)skin_buffer_alloc(
1059 sizeof(struct skin_var_lastchange));
1060 if (!data)
1061 return WPS_ERROR_INVALID_PARAM;
1062 data->var = var;
1063 data->timeout = 10;
1064 if (element->params_count > 1)
1065 data->timeout = element->params[1].data.number;
1066 data->timeout *= TIMEOUT_UNIT;
1067 token->value.data = data;
1068 }
1069 break;
1070 default: /* kill the warning */
1071 break;
1072 }
1073 return 0;
1074}
1075#endif /* HAVE_SKIN_VARIABLES */
Jonathan Gordon0eb5dc62009-04-20 01:41:56 +00001076#ifdef HAVE_TOUCHSCREEN
Jonathan Gordon156b0bc2011-02-28 11:19:59 +00001077static int parse_lasttouch(struct skin_element *element,
1078 struct wps_token *token,
1079 struct wps_data *wps_data)
1080{
1081 struct touchregion_lastpress *data =
1082 (struct touchregion_lastpress*)skin_buffer_alloc(
1083 sizeof(struct touchregion_lastpress));
1084 int i;
1085 if (!data)
1086 return WPS_ERROR_INVALID_PARAM;
1087 data->region = NULL;
1088 data->timeout = 10;
1089
1090 for (i=0; i<element->params_count; i++)
1091 {
1092 if (element->params[i].type == STRING)
Jonathan Gordon343001b2011-03-07 12:45:45 +00001093 data->region = skin_find_item(element->params[i].data.text,
Jonathan Gordon87aa86c2011-03-27 08:01:58 +00001094 SKIN_FIND_TOUCHREGION, wps_data);
Jonathan Gordon94257e52011-05-23 06:02:44 +00001095 else if (element->params[i].type == INTEGER ||
1096 element->params[i].type == DECIMAL)
Jonathan Gordon156b0bc2011-02-28 11:19:59 +00001097 data->timeout = element->params[i].data.number;
1098 }
1099
1100 data->timeout *= TIMEOUT_UNIT;
1101 token->value.data = data;
1102 return 0;
1103}
Thomas Martitz541dd6f2009-09-13 12:24:14 +00001104
Bertrik Sikken0201a192009-12-20 18:04:07 +00001105struct touchaction {const char* s; int action;};
1106static const struct touchaction touchactions[] = {
Jonathan Gordon9a7a5422010-06-15 08:38:23 +00001107 /* generic actions, convert to screen actions on use */
Jonathan Gordonbb618db2011-07-28 11:26:01 +00001108 {"none", ACTION_TOUCHSCREEN}, {"lock", ACTION_TOUCH_SOFTLOCK },
Jonathan Gordon9a7a5422010-06-15 08:38:23 +00001109 {"prev", ACTION_STD_PREV }, {"next", ACTION_STD_NEXT },
Jonathan Gordon8a798172010-06-20 13:21:41 +00001110 {"rwd", ACTION_STD_PREVREPEAT }, {"ffwd", ACTION_STD_NEXTREPEAT },
Jonathan Gordon9a7a5422010-06-15 08:38:23 +00001111 {"hotkey", ACTION_STD_HOTKEY}, {"select", ACTION_STD_OK },
1112 {"menu", ACTION_STD_MENU }, {"cancel", ACTION_STD_CANCEL },
1113 {"contextmenu", ACTION_STD_CONTEXT},{"quickscreen", ACTION_STD_QUICKSCREEN },
Jonathan Gordona7b1f752010-10-10 04:17:34 +00001114
1115 /* list/tree actions */
1116 { "resumeplayback", ACTION_TREE_WPS}, /* returns to previous music, WPS/FM */
Jonathan Gordon9a7a5422010-06-15 08:38:23 +00001117 /* not really WPS specific, but no equivilant ACTION_STD_* */
1118 {"voldown", ACTION_WPS_VOLDOWN}, {"volup", ACTION_WPS_VOLUP},
Jonathan Gordon605e2d02011-01-13 10:56:23 +00001119 {"mute", ACTION_TOUCH_MUTE },
Jonathan Gordon4caa8322010-09-06 13:33:49 +00001120
1121 /* generic settings changers */
Jonathan Gordon485ff792011-03-01 12:31:03 +00001122 {"setting_inc", ACTION_SETTINGS_INC}, {"setting_dec", ACTION_SETTINGS_DEC},
1123 {"setting_set", ACTION_SETTINGS_SET},
Jonathan Gordon9a7a5422010-06-15 08:38:23 +00001124
1125 /* WPS specific actions */
Jonathan Gordon98881fd2011-03-22 09:31:45 +00001126 {"wps_prev", ACTION_WPS_SKIPPREV }, {"wps_next", ACTION_WPS_SKIPNEXT },
Jonathan Gordon9a7a5422010-06-15 08:38:23 +00001127 {"browse", ACTION_WPS_BROWSE },
1128 {"play", ACTION_WPS_PLAY }, {"stop", ACTION_WPS_STOP },
Jonathan Gordon13cc6542009-05-15 06:02:50 +00001129 {"shuffle", ACTION_TOUCH_SHUFFLE }, {"repmode", ACTION_TOUCH_REPMODE },
Jonathan Gordon9a7a5422010-06-15 08:38:23 +00001130 {"pitch", ACTION_WPS_PITCHSCREEN}, {"playlist", ACTION_WPS_VIEW_PLAYLIST },
1131
1132#if CONFIG_TUNER
1133 /* FM screen actions */
1134 /* Also allow browse, play, stop from WPS codes */
1135 {"mode", ACTION_FM_MODE }, {"record", ACTION_FM_RECORD },
1136 {"presets", ACTION_FM_PRESET},
1137#endif
Jonathan Gordon0eb5dc62009-04-20 01:41:56 +00001138};
Jonathan Gordon9a7a5422010-06-15 08:38:23 +00001139
Jonathan Gordon969903b2011-07-28 12:53:22 +00001140static int touchregion_setup_setting(struct skin_element *element, int param_no,
1141 struct touchregion *region)
1142{
1143 int p = param_no;
1144 char *name = element->params[p++].data.text;
1145 int j;
Jonathan Gordon89973212011-09-04 13:17:09 +00001146
1147 region->setting_data.setting = find_setting_by_cfgname(name, &j);
1148 if (region->setting_data.setting == NULL)
Jonathan Gordon969903b2011-07-28 12:53:22 +00001149 return WPS_ERROR_INVALID_PARAM;
Jonathan Gordon969903b2011-07-28 12:53:22 +00001150 if (region->action == ACTION_SETTINGS_SET)
1151 {
1152 char* text;
1153 int temp;
1154 struct touchsetting *setting =
1155 &region->setting_data;
1156 if (element->params_count < p+1)
1157 return -1;
1158#ifndef __PCTOOL__
1159 text = element->params[p++].data.text;
1160 switch (settings[j].flags&F_T_MASK)
1161 {
1162 case F_T_CUSTOM:
1163 setting->value.text = text;
1164 break;
1165 case F_T_INT:
1166 case F_T_UINT:
1167 if (settings[j].cfg_vals == NULL)
1168 {
1169 setting->value.number = atoi(text);
1170 }
1171 else if (cfg_string_to_int(j, &temp, text))
1172 {
1173 if (settings[j].flags&F_TABLE_SETTING)
1174 setting->value.number =
1175 settings[j].table_setting->values[temp];
1176 else
1177 setting->value.number = temp;
1178 }
1179 else
1180 return -1;
1181 break;
1182 case F_T_BOOL:
1183 if (cfg_string_to_int(j, &temp, text))
1184 {
1185 setting->value.number = temp;
1186 }
1187 else
1188 return -1;
1189 break;
1190 default:
1191 return -1;
1192 }
1193#endif /* __PCTOOL__ */
1194 }
1195 return p-param_no;
1196}
1197
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001198static int parse_touchregion(struct skin_element *element,
1199 struct wps_token *token,
1200 struct wps_data *wps_data)
Jonathan Gordon0eb5dc62009-04-20 01:41:56 +00001201{
1202 (void)token;
Thomas Martitz23e46b32009-07-22 21:14:47 +00001203 unsigned i, imax;
Jonathan Gordon156b0bc2011-02-28 11:19:59 +00001204 int p;
Jonathan Gordon271643c2009-08-16 21:22:57 +00001205 struct touchregion *region = NULL;
Jonathan Gordon37d605a2010-07-29 12:48:59 +00001206 const char *action;
Jonathan Gordondc4e9032009-08-09 17:30:05 +00001207 const char pb_string[] = "progressbar";
1208 const char vol_string[] = "volume";
Thomas Martitz541dd6f2009-09-13 12:24:14 +00001209
Jonathan Gordon485ff792011-03-01 12:31:03 +00001210 /* format: %T([label,], x,y,width,height,action[, ...])
Jonathan Gordon2172c912009-05-17 06:25:18 +00001211 * if action starts with & the area must be held to happen
Jonathan Gordon485ff792011-03-01 12:31:03 +00001212 */
Jonathan Gordon0eb5dc62009-04-20 01:41:56 +00001213
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001214
1215 region = (struct touchregion*)skin_buffer_alloc(sizeof(struct touchregion));
Jonathan Gordon271643c2009-08-16 21:22:57 +00001216 if (!region)
1217 return WPS_ERROR_INVALID_PARAM;
Thomas Martitz541dd6f2009-09-13 12:24:14 +00001218
Jonathan Gordon0eb5dc62009-04-20 01:41:56 +00001219 /* should probably do some bounds checking here with the viewport... but later */
Jonathan Gordon0eb5dc62009-04-20 01:41:56 +00001220 region->action = ACTION_NONE;
Jonathan Gordon156b0bc2011-02-28 11:19:59 +00001221
1222 if (element->params[0].type == STRING)
1223 {
1224 region->label = element->params[0].data.text;
1225 p = 1;
Jonathan Gordonfb361632011-03-01 07:26:11 +00001226 /* "[SI]III[SI]|SS" is the param list. There MUST be 4 numbers
Jonathan Gordon156b0bc2011-02-28 11:19:59 +00001227 * followed by at least one string. Verify that here */
1228 if (element->params_count < 6 ||
1229 element->params[4].type != INTEGER)
1230 return WPS_ERROR_INVALID_PARAM;
1231 }
1232 else
1233 {
1234 region->label = NULL;
1235 p = 0;
1236 }
1237
1238 region->x = element->params[p++].data.number;
1239 region->y = element->params[p++].data.number;
1240 region->width = element->params[p++].data.number;
1241 region->height = element->params[p++].data.number;
Jonathan Gordon36ca4962009-08-18 05:30:59 +00001242 region->wvp = curr_vp;
Jonathan Gordon31fb4f62010-02-24 06:19:25 +00001243 region->armed = false;
Jonathan Gordonadc9cb12010-06-21 12:43:08 +00001244 region->reverse_bar = false;
Jonathan Gordon485ff792011-03-01 12:31:03 +00001245 region->value = 0;
Jonathan Gordon156b0bc2011-02-28 11:19:59 +00001246 region->last_press = 0xffff;
Jonathan Gordon443b1342011-03-27 07:23:38 +00001247 region->press_length = PRESS;
Jonathan Gordonbb618db2011-07-28 11:26:01 +00001248 region->allow_while_locked = false;
Jonathan Gordon156b0bc2011-02-28 11:19:59 +00001249 action = element->params[p++].data.text;
Thomas Martitz541dd6f2009-09-13 12:24:14 +00001250
Jonathan Gordon969903b2011-07-28 12:53:22 +00001251 /* figure out the action */
Teruaki Kawashima0a4eda42010-05-19 15:47:54 +00001252 if(!strcmp(pb_string, action))
Jonathan Gordon443b1342011-03-27 07:23:38 +00001253 region->action = ACTION_TOUCH_SCROLLBAR;
Teruaki Kawashima0a4eda42010-05-19 15:47:54 +00001254 else if(!strcmp(vol_string, action))
Jonathan Gordon443b1342011-03-27 07:23:38 +00001255 region->action = ACTION_TOUCH_VOLUME;
Jonathan Gordon3e7444f2009-08-03 04:43:34 +00001256 else
Jonathan Gordon3e7444f2009-08-03 04:43:34 +00001257 {
Jonathan Gordondc4e9032009-08-09 17:30:05 +00001258 imax = ARRAYLEN(touchactions);
Teruaki Kawashima0a4eda42010-05-19 15:47:54 +00001259 for (i = 0; i < imax; i++)
Jonathan Gordondc4e9032009-08-09 17:30:05 +00001260 {
1261 /* try to match with one of our touchregion screens */
Teruaki Kawashima0a4eda42010-05-19 15:47:54 +00001262 if (!strcmp(touchactions[i].s, action))
1263 {
Jonathan Gordondc4e9032009-08-09 17:30:05 +00001264 region->action = touchactions[i].action;
Jonathan Gordon4caa8322010-09-06 13:33:49 +00001265 if (region->action == ACTION_SETTINGS_INC ||
Jonathan Gordon485ff792011-03-01 12:31:03 +00001266 region->action == ACTION_SETTINGS_DEC ||
1267 region->action == ACTION_SETTINGS_SET)
Jonathan Gordon4caa8322010-09-06 13:33:49 +00001268 {
Jonathan Gordon969903b2011-07-28 12:53:22 +00001269 int val;
Jonathan Gordon156b0bc2011-02-28 11:19:59 +00001270 if (element->params_count < p+1)
Jonathan Gordon4caa8322010-09-06 13:33:49 +00001271 return WPS_ERROR_INVALID_PARAM;
Jonathan Gordon969903b2011-07-28 12:53:22 +00001272 val = touchregion_setup_setting(element, p, region);
1273 if (val < 0)
1274 return WPS_ERROR_INVALID_PARAM;
1275 p += val;
Jonathan Gordon4caa8322010-09-06 13:33:49 +00001276 }
Teruaki Kawashima0a4eda42010-05-19 15:47:54 +00001277 break;
1278 }
Jonathan Gordondc4e9032009-08-09 17:30:05 +00001279 }
1280 if (region->action == ACTION_NONE)
1281 return WPS_ERROR_INVALID_PARAM;
Jonathan Gordon3e7444f2009-08-03 04:43:34 +00001282 }
Jonathan Gordon969903b2011-07-28 12:53:22 +00001283 while (p < element->params_count)
1284 {
1285 char* param = element->params[p++].data.text;
1286 if (!strcmp(param, "allow_while_locked"))
1287 region->allow_while_locked = true;
1288 else if (!strcmp(param, "reverse_bar"))
1289 region->reverse_bar = true;
1290 else if (!strcmp(param, "repeat_press"))
1291 region->press_length = REPEAT;
1292 else if (!strcmp(param, "long_press"))
1293 region->press_length = LONG_PRESS;
1294 }
Jonathan Gordon271643c2009-08-16 21:22:57 +00001295 struct skin_token_list *item = new_skin_token_list_item(NULL, region);
1296 if (!item)
1297 return WPS_ERROR_INVALID_PARAM;
1298 add_to_ll_chain(&wps_data->touchregions, item);
Jonathan Gordon605e2d02011-01-13 10:56:23 +00001299
1300 if (region->action == ACTION_TOUCH_MUTE)
1301 {
1302 region->value = global_settings.volume;
1303 }
1304
1305
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001306 return 0;
Thomas Martitz541dd6f2009-09-13 12:24:14 +00001307}
1308#endif
Jonathan Gordon0eb5dc62009-04-20 01:41:56 +00001309
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001310static bool check_feature_tag(const int type)
Nicolas Pennequinab90d582007-04-04 14:41:40 +00001311{
Thomas Martitze28bfd12009-11-01 23:35:14 +00001312 switch (type)
1313 {
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001314 case SKIN_TOKEN_RTC_PRESENT:
Thomas Martitze28bfd12009-11-01 23:35:14 +00001315#if CONFIG_RTC
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001316 return true;
Thomas Martitze28bfd12009-11-01 23:35:14 +00001317#else
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001318 return false;
1319#endif
1320 case SKIN_TOKEN_HAVE_RECORDING:
Jonathan Gordonf76b2f22009-11-03 07:58:10 +00001321#ifdef HAVE_RECORDING
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001322 return true;
Jonathan Gordonf76b2f22009-11-03 07:58:10 +00001323#else
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001324 return false;
1325#endif
1326 case SKIN_TOKEN_HAVE_TUNER:
Jonathan Gordon1bd072c2010-05-12 10:38:00 +00001327#if CONFIG_TUNER
1328 if (radio_hardware_present())
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001329 return true;
1330#endif
1331 return false;
Jonathan Gordon943de3c2010-10-28 11:00:36 +00001332 case SKIN_TOKEN_HAVE_TOUCH:
1333#ifdef HAVE_TOUCHSCREEN
1334 return true;
1335#else
1336 return false;
1337#endif
Thomas Martitzee166962010-07-23 16:33:16 +00001338
1339#if CONFIG_TUNER
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001340 case SKIN_TOKEN_HAVE_RDS:
Thomas Martitza0e83f32010-07-23 16:24:12 +00001341#ifdef HAVE_RDS_CAP
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001342 return true;
Thomas Martitza0e83f32010-07-23 16:24:12 +00001343#else
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001344 return false;
Thomas Martitzee166962010-07-23 16:33:16 +00001345#endif /* HAVE_RDS_CAP */
1346#endif /* CONFIG_TUNER */
Thomas Martitze28bfd12009-11-01 23:35:14 +00001347 default: /* not a tag we care about, just don't skip */
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001348 return true;
Thomas Martitze28bfd12009-11-01 23:35:14 +00001349 }
1350}
1351
Thomas Martitz0f0d9062009-10-14 15:49:11 +00001352/*
1353 * initial setup of wps_data; does reset everything
1354 * except fields which need to survive, i.e.
1355 *
Thomas Martitz0f0d9062009-10-14 15:49:11 +00001356 **/
Bertrik Sikken56986742009-12-20 16:28:15 +00001357static void skin_data_reset(struct wps_data *wps_data)
Nicolas Pennequinab90d582007-04-04 14:41:40 +00001358{
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001359 wps_data->tree = NULL;
Thomas Martitz0f0d9062009-10-14 15:49:11 +00001360#ifdef HAVE_LCD_BITMAP
Jonathan Gordon8717c1e2010-02-28 08:36:13 +00001361 wps_data->images = NULL;
Nicolas Pennequin2a2b8d82007-04-25 13:09:56 +00001362#endif
Jonathan Gordoneee54232010-01-29 07:52:13 +00001363#if LCD_DEPTH > 1 || defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
Jonathan Gordon9928e342010-09-14 11:56:50 +00001364 if (wps_data->backdrop_id >= 0)
1365 skin_backdrop_unload(wps_data->backdrop_id);
Jonathan Gordoneee54232010-01-29 07:52:13 +00001366 wps_data->backdrop = NULL;
1367#endif
Thomas Martitz0f0d9062009-10-14 15:49:11 +00001368#ifdef HAVE_TOUCHSCREEN
1369 wps_data->touchregions = NULL;
Nicolas Pennequin2a2b8d82007-04-25 13:09:56 +00001370#endif
Jonathan Gordon87aa86c2011-03-27 08:01:58 +00001371#ifdef HAVE_SKIN_VARIABLES
Bertrik Sikkenab99e942011-05-08 20:35:29 +00001372 wps_data->skinvars = NULL;
Jonathan Gordon87aa86c2011-03-27 08:01:58 +00001373#endif
Thomas Martitz0f0d9062009-10-14 15:49:11 +00001374#ifdef HAVE_ALBUMART
1375 wps_data->albumart = NULL;
Thomas Martitze9c10182009-10-16 19:14:41 +00001376 if (wps_data->playback_aa_slot >= 0)
1377 {
1378 playback_release_aa_slot(wps_data->playback_aa_slot);
1379 wps_data->playback_aa_slot = -1;
1380 }
Thomas Martitz0f0d9062009-10-14 15:49:11 +00001381#endif
Thomas Martitz0f0d9062009-10-14 15:49:11 +00001382
1383#ifdef HAVE_LCD_BITMAP
1384 wps_data->peak_meter_enabled = false;
1385 wps_data->wps_sb_tag = false;
1386 wps_data->show_sb_on_wps = false;
1387#else /* HAVE_LCD_CHARCELLS */
1388 /* progress bars */
1389 int i;
1390 for (i = 0; i < 8; i++)
1391 {
1392 wps_data->wps_progress_pat[i] = 0;
1393 }
1394 wps_data->full_line_progressbar = false;
1395#endif
1396 wps_data->wps_loaded = false;
Nicolas Pennequinab90d582007-04-04 14:41:40 +00001397}
1398
1399#ifdef HAVE_LCD_BITMAP
Jonathan Gordon18a8e522009-08-16 18:23:00 +00001400static bool load_skin_bmp(struct wps_data *wps_data, struct bitmap *bitmap, char* bmpdir)
1401{
Jonathan Gordon58ca43d2009-12-03 05:36:23 +00001402 (void)wps_data; /* only needed for remote targets */
Jonathan Gordon18a8e522009-08-16 18:23:00 +00001403 char img_path[MAX_PATH];
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001404 int fd;
Jonathan Gordon18a8e522009-08-16 18:23:00 +00001405 get_image_filename(bitmap->data, bmpdir,
1406 img_path, sizeof(img_path));
Thomas Martitz541dd6f2009-09-13 12:24:14 +00001407
Jonathan Gordon58ca43d2009-12-03 05:36:23 +00001408 /* load the image */
Jonathan Gordon18a8e522009-08-16 18:23:00 +00001409 int format;
1410#ifdef HAVE_REMOTE_LCD
Thomas Martitzc0635ba2009-11-04 07:14:02 +00001411 if (curr_screen == SCREEN_REMOTE)
Jonathan Gordon18a8e522009-08-16 18:23:00 +00001412 format = FORMAT_ANY|FORMAT_REMOTE;
1413 else
1414#endif
1415 format = FORMAT_ANY|FORMAT_TRANSPARENT;
Thomas Martitz541dd6f2009-09-13 12:24:14 +00001416
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001417 fd = open(img_path, O_RDONLY);
1418 if (fd < 0)
Jonathan Gordonf74a1aa2010-11-11 09:57:37 +00001419 {
1420 DEBUGF("Couldn't open %s\n", img_path);
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001421 return false;
Jonathan Gordonf74a1aa2010-11-11 09:57:37 +00001422 }
Teruaki Kawashima717f0bd2010-09-29 13:23:24 +00001423 size_t buf_size = read_bmp_fd(fd, bitmap, 0,
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001424 format|FORMAT_RETURN_SIZE, NULL);
1425 char* imgbuf = (char*)skin_buffer_alloc(buf_size);
1426 if (!imgbuf)
1427 {
Thomas Martitz6c8267a2010-11-12 21:21:23 +00001428#ifndef APPLICATION
Jonathan Gordon10807e82010-11-11 10:04:41 +00001429 DEBUGF("Not enough skin buffer: need %zd more.\n",
Jonathan Gordonf74a1aa2010-11-11 09:57:37 +00001430 buf_size - skin_buffer_freespace());
Thomas Martitz6c8267a2010-11-12 21:21:23 +00001431#endif
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001432 close(fd);
1433 return NULL;
1434 }
1435 lseek(fd, 0, SEEK_SET);
Jonathan Gordon58ca43d2009-12-03 05:36:23 +00001436 bitmap->data = imgbuf;
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001437 int ret = read_bmp_fd(fd, bitmap, buf_size, format, NULL);
Jonathan Gordon18a8e522009-08-16 18:23:00 +00001438
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001439 close(fd);
Jonathan Gordon18a8e522009-08-16 18:23:00 +00001440 if (ret > 0)
1441 {
Thomas Martitza31624e2010-02-21 19:29:33 +00001442 return true;
Jonathan Gordon18a8e522009-08-16 18:23:00 +00001443 }
1444 else
Jonathan Gordon58ca43d2009-12-03 05:36:23 +00001445 {
Jonathan Gordon18a8e522009-08-16 18:23:00 +00001446 /* Abort if we can't load an image */
Jonathan Gordon6c4b80c2010-02-24 06:15:55 +00001447 DEBUGF("Couldn't load '%s'\n", img_path);
Thomas Martitza31624e2010-02-21 19:29:33 +00001448 return false;
Jonathan Gordon18a8e522009-08-16 18:23:00 +00001449 }
Jonathan Gordon18a8e522009-08-16 18:23:00 +00001450}
Nicolas Pennequinab90d582007-04-04 14:41:40 +00001451
Jonathan Gordon37908972009-08-06 04:33:35 +00001452static bool load_skin_bitmaps(struct wps_data *wps_data, char *bmpdir)
Nicolas Pennequinab90d582007-04-04 14:41:40 +00001453{
Jonathan Gordon18a8e522009-08-16 18:23:00 +00001454 struct skin_token_list *list;
Thomas Martitza31624e2010-02-21 19:29:33 +00001455 bool retval = true; /* return false if a single image failed to load */
Jonathan Gordon9acd2422010-10-12 12:46:57 +00001456
Jonathan Gordon18a8e522009-08-16 18:23:00 +00001457 /* regular images */
Jonathan Gordon58ca43d2009-12-03 05:36:23 +00001458 list = wps_data->images;
Jonathan Gordon18a8e522009-08-16 18:23:00 +00001459 while (list)
1460 {
1461 struct gui_img *img = (struct gui_img*)list->token->value.data;
1462 if (img->bm.data)
1463 {
Jonathan Gordon70ebe462010-08-12 13:27:10 +00001464 if (img->using_preloaded_icons)
1465 {
1466 img->loaded = true;
1467 list->token->type = SKIN_TOKEN_IMAGE_DISPLAY_LISTICON;
1468 }
Thomas Martitza31624e2010-02-21 19:29:33 +00001469 else
Jonathan Gordon70ebe462010-08-12 13:27:10 +00001470 {
1471 img->loaded = load_skin_bmp(wps_data, &img->bm, bmpdir);
1472 if (img->loaded)
1473 img->subimage_height = img->bm.height / img->num_subimages;
1474 else
1475 retval = false;
1476 }
Jonathan Gordon18a8e522009-08-16 18:23:00 +00001477 }
Jonathan Gordon58ca43d2009-12-03 05:36:23 +00001478 list = list->next;
Nicolas Pennequinab90d582007-04-04 14:41:40 +00001479 }
1480
Dave Chapmand746b792008-03-29 01:14:10 +00001481#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
Jonathan Gordon9928e342010-09-14 11:56:50 +00001482 wps_data->backdrop_id = skin_backdrop_assign(wps_data->backdrop, bmpdir, curr_screen);
Nicolas Pennequin7fdfa562007-04-25 21:44:56 +00001483#endif /* has backdrop support */
Thomas Martitza31624e2010-02-21 19:29:33 +00001484 return retval;
Nicolas Pennequinab90d582007-04-04 14:41:40 +00001485}
1486
Thomas Martitz22630862010-02-27 16:51:51 +00001487static bool skin_load_fonts(struct wps_data *data)
1488{
1489 /* don't spit out after the first failue to aid debugging */
1490 bool success = true;
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001491 struct skin_element *vp_list;
Jonathan Gordonf37b5072010-03-03 00:53:07 +00001492 int font_id;
Thomas Martitz22630862010-02-27 16:51:51 +00001493 /* walk though each viewport and assign its font */
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001494 for(vp_list = data->tree; vp_list; vp_list = vp_list->next)
Thomas Martitz22630862010-02-27 16:51:51 +00001495 {
1496 /* first, find the viewports that have a non-sys/ui-font font */
1497 struct skin_viewport *skin_vp =
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001498 (struct skin_viewport*)vp_list->data;
Thomas Martitz22630862010-02-27 16:51:51 +00001499 struct viewport *vp = &skin_vp->vp;
1500
1501
Jonathan Gordonf37b5072010-03-03 00:53:07 +00001502 if (vp->font <= FONT_UI)
Thomas Martitz22630862010-02-27 16:51:51 +00001503 { /* the usual case -> built-in fonts */
Jonathan Gordonf37b5072010-03-03 00:53:07 +00001504#ifdef HAVE_REMOTE_LCD
1505 if (vp->font == FONT_UI)
1506 vp->font += curr_screen;
1507#endif
Thomas Martitz22630862010-02-27 16:51:51 +00001508 continue;
1509 }
Jonathan Gordonf37b5072010-03-03 00:53:07 +00001510 font_id = vp->font;
Thomas Martitz22630862010-02-27 16:51:51 +00001511
1512 /* now find the corresponding skin_font */
Jonathan Gordonf37b5072010-03-03 00:53:07 +00001513 struct skin_font *font = &skinfonts[font_id-FONT_FIRSTUSERFONT];
1514 if (!font->name)
Thomas Martitz22630862010-02-27 16:51:51 +00001515 {
Jonathan Gordonbb236ce2010-07-16 01:05:24 +00001516 if (success)
1517 {
1518 DEBUGF("font %d not specified\n", font_id);
1519 }
Thomas Martitz22630862010-02-27 16:51:51 +00001520 success = false;
1521 continue;
1522 }
1523
1524 /* load the font - will handle loading the same font again if
1525 * multiple viewports use the same */
Jonathan Gordon8717c1e2010-02-28 08:36:13 +00001526 if (font->id < 0)
1527 {
Jonathan Gordon25d97712010-03-03 05:43:02 +00001528 char *dot = strchr(font->name, '.');
1529 *dot = '\0';
Jonathan Gordonfaaf4312010-08-25 14:11:38 +00001530 font->id = skin_font_load(font->name,
1531 skinfonts[font_id-FONT_FIRSTUSERFONT].glyphs);
Jonathan Gordon8717c1e2010-02-28 08:36:13 +00001532 }
Thomas Martitz22630862010-02-27 16:51:51 +00001533
Jonathan Gordon8717c1e2010-02-28 08:36:13 +00001534 if (font->id < 0)
Thomas Martitz22630862010-02-27 16:51:51 +00001535 {
1536 DEBUGF("Unable to load font %d: '%s.fnt'\n",
Jonathan Gordonf37b5072010-03-03 00:53:07 +00001537 font_id, font->name);
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001538 font->name = NULL; /* to stop trying to load it again if we fail */
Thomas Martitz22630862010-02-27 16:51:51 +00001539 success = false;
Jonathan Gordonbb236ce2010-07-16 01:05:24 +00001540 font->name = NULL;
Thomas Martitz22630862010-02-27 16:51:51 +00001541 continue;
1542 }
1543
1544 /* finally, assign the font_id to the viewport */
Jonathan Gordon8717c1e2010-02-28 08:36:13 +00001545 vp->font = font->id;
Thomas Martitz22630862010-02-27 16:51:51 +00001546 }
1547 return success;
1548}
1549
Nicolas Pennequinab90d582007-04-04 14:41:40 +00001550#endif /* HAVE_LCD_BITMAP */
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001551static int convert_viewport(struct wps_data *data, struct skin_element* element)
1552{
1553 struct skin_viewport *skin_vp =
1554 (struct skin_viewport *)skin_buffer_alloc(sizeof(struct skin_viewport));
1555 struct screen *display = &screens[curr_screen];
1556
1557 if (!skin_vp)
1558 return CALLBACK_ERROR;
1559
1560 skin_vp->hidden_flags = 0;
Jonathan Gordonee4f8a92010-08-02 12:50:23 +00001561 skin_vp->label = NULL;
1562 skin_vp->is_infovp = false;
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001563 element->data = skin_vp;
1564 curr_vp = skin_vp;
1565 curr_viewport_element = element;
1566
1567 viewport_set_defaults(&skin_vp->vp, curr_screen);
Jonathan Gordon9e2cd392010-08-01 11:37:02 +00001568#ifdef HAVE_REMOTE_LCD
1569 /* viewport_set_defaults() sets the font to FONT_UI+curr_screen.
1570 * This parser requires font 1 to always be the UI font,
1571 * so force it back to FONT_UI and handle the screen number at the end */
1572 skin_vp->vp.font = FONT_UI;
1573#endif
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001574
1575#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
1576 skin_vp->start_fgcolour = skin_vp->vp.fg_pattern;
1577 skin_vp->start_bgcolour = skin_vp->vp.bg_pattern;
1578#endif
Jonathan Gordon281f1a12011-08-14 13:50:07 +00001579#ifdef HAVE_LCD_COLOR
1580 skin_vp->start_gradient.start = skin_vp->vp.lss_pattern;
1581 skin_vp->start_gradient.end = skin_vp->vp.lse_pattern;
1582 skin_vp->start_gradient.text = skin_vp->vp.lst_pattern;
1583#endif
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001584
1585
1586 struct skin_tag_parameter *param = element->params;
1587 if (element->params_count == 0) /* default viewport */
1588 {
1589 if (!data->tree) /* first viewport in the skin */
1590 data->tree = element;
1591 skin_vp->label = VP_DEFAULT_LABEL;
1592 return CALLBACK_OK;
1593 }
1594
1595 if (element->params_count == 6)
1596 {
1597 if (element->tag->type == SKIN_TOKEN_UIVIEWPORT_LOAD)
1598 {
Jonathan Gordonee4f8a92010-08-02 12:50:23 +00001599 skin_vp->is_infovp = true;
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001600 if (isdefault(param))
1601 {
1602 skin_vp->hidden_flags = VP_NEVER_VISIBLE;
Jonathan Gordonee4f8a92010-08-02 12:50:23 +00001603 skin_vp->label = VP_DEFAULT_LABEL;
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001604 }
1605 else
1606 {
1607 skin_vp->hidden_flags = VP_NEVER_VISIBLE;
Jonathan Gordonee4f8a92010-08-02 12:50:23 +00001608 skin_vp->label = param->data.text;
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001609 }
1610 }
1611 else
1612 {
1613 skin_vp->hidden_flags = VP_DRAW_HIDEABLE|VP_DRAW_HIDDEN;
Jonathan Gordonee4f8a92010-08-02 12:50:23 +00001614 skin_vp->label = param->data.text;
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001615 }
1616 param++;
1617 }
1618 /* x */
1619 if (!isdefault(param))
1620 {
1621 skin_vp->vp.x = param->data.number;
1622 if (param->data.number < 0)
1623 skin_vp->vp.x += display->lcdwidth;
1624 }
1625 param++;
1626 /* y */
1627 if (!isdefault(param))
1628 {
1629 skin_vp->vp.y = param->data.number;
1630 if (param->data.number < 0)
1631 skin_vp->vp.y += display->lcdheight;
1632 }
1633 param++;
1634 /* width */
1635 if (!isdefault(param))
1636 {
1637 skin_vp->vp.width = param->data.number;
1638 if (param->data.number < 0)
1639 skin_vp->vp.width = (skin_vp->vp.width + display->lcdwidth) - skin_vp->vp.x;
1640 }
1641 else
1642 {
1643 skin_vp->vp.width = display->lcdwidth - skin_vp->vp.x;
1644 }
1645 param++;
1646 /* height */
1647 if (!isdefault(param))
1648 {
1649 skin_vp->vp.height = param->data.number;
1650 if (param->data.number < 0)
1651 skin_vp->vp.height = (skin_vp->vp.height + display->lcdheight) - skin_vp->vp.y;
1652 }
1653 else
1654 {
1655 skin_vp->vp.height = display->lcdheight - skin_vp->vp.y;
1656 }
1657 param++;
1658#ifdef HAVE_LCD_BITMAP
1659 /* font */
1660 if (!isdefault(param))
1661 {
1662 skin_vp->vp.font = param->data.number;
1663 }
Teruaki Kawashima59f48722010-10-11 13:08:49 +00001664#endif
1665 if ((unsigned) skin_vp->vp.x >= (unsigned) display->lcdwidth ||
1666 skin_vp->vp.width + skin_vp->vp.x > display->lcdwidth ||
1667 (unsigned) skin_vp->vp.y >= (unsigned) display->lcdheight ||
1668 skin_vp->vp.height + skin_vp->vp.y > display->lcdheight)
1669 return CALLBACK_ERROR;
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001670
1671 return CALLBACK_OK;
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001672}
1673
Bertrik Sikken57933f22010-07-30 23:47:49 +00001674static int skin_element_callback(struct skin_element* element, void* data)
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001675{
1676 struct wps_data *wps_data = (struct wps_data *)data;
1677 struct wps_token *token;
1678 parse_function function = NULL;
1679
1680 switch (element->type)
1681 {
1682 /* IMPORTANT: element params are shared, so copy them if needed
1683 * or use then NOW, dont presume they have a long lifespan
1684 */
1685 case TAG:
1686 {
1687 token = (struct wps_token*)skin_buffer_alloc(sizeof(struct wps_token));
1688 memset(token, 0, sizeof(*token));
1689 token->type = element->tag->type;
1690
Jonathan Gordone8bbbdf2010-08-15 14:35:34 +00001691 if (element->tag->flags&SKIN_RTC_REFRESH)
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001692 {
Jonathan Gordone8bbbdf2010-08-15 14:35:34 +00001693#if CONFIG_RTC
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001694 curr_line->update_mode |= SKIN_REFRESH_DYNAMIC;
1695#else
1696 curr_line->update_mode |= SKIN_REFRESH_STATIC;
1697#endif
1698 }
1699 else
1700 curr_line->update_mode |= element->tag->flags&SKIN_REFRESH_ALL;
1701
1702 element->data = token;
1703
1704 /* Some tags need special handling for the tag, so add them here */
1705 switch (token->type)
1706 {
1707 case SKIN_TOKEN_ALIGN_LANGDIRECTION:
1708 follow_lang_direction = 2;
1709 break;
Jonathan Gordon74ec0112010-08-19 13:49:32 +00001710 case SKIN_TOKEN_LOGICAL_IF:
1711 function = parse_logical_if;
1712 break;
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001713 case SKIN_TOKEN_PROGRESSBAR:
1714 case SKIN_TOKEN_VOLUME:
1715 case SKIN_TOKEN_BATTERY_PERCENT:
1716 case SKIN_TOKEN_PLAYER_PROGRESSBAR:
Jonathan Gordon261c56b2011-01-13 06:48:39 +00001717 case SKIN_TOKEN_PEAKMETER_LEFT:
1718 case SKIN_TOKEN_PEAKMETER_RIGHT:
Jonathan Gordon1ce7ba42010-11-18 11:47:42 +00001719#ifdef HAVE_RADIO_RSSI
1720 case SKIN_TOKEN_TUNER_RSSI:
1721#endif
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001722 function = parse_progressbar_tag;
1723 break;
1724 case SKIN_TOKEN_SUBLINE_TIMEOUT:
1725 case SKIN_TOKEN_BUTTON_VOLUME:
1726 case SKIN_TOKEN_TRACK_STARTING:
1727 case SKIN_TOKEN_TRACK_ENDING:
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001728 function = parse_timeout_tag;
1729 break;
1730#ifdef HAVE_LCD_BITMAP
1731 case SKIN_TOKEN_DISABLE_THEME:
1732 case SKIN_TOKEN_ENABLE_THEME:
1733 case SKIN_TOKEN_DRAW_INBUILTBAR:
1734 function = parse_statusbar_tags;
1735 break;
Jonathan Gordonfbb00832010-09-16 12:56:51 +00001736 case SKIN_TOKEN_LIST_TITLE_TEXT:
Jonathan Gordon10b68612010-09-16 14:01:43 +00001737#ifndef __PCTOOL__
Jonathan Gordonfbb00832010-09-16 12:56:51 +00001738 sb_skin_has_title(curr_screen);
Jonathan Gordon10b68612010-09-16 14:01:43 +00001739#endif
Jonathan Gordonfbb00832010-09-16 12:56:51 +00001740 break;
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001741#endif
1742 case SKIN_TOKEN_FILE_DIRECTORY:
1743 token->value.i = element->params[0].data.number;
1744 break;
1745#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
1746 case SKIN_TOKEN_VIEWPORT_FGCOLOUR:
1747 case SKIN_TOKEN_VIEWPORT_BGCOLOUR:
1748 function = parse_viewportcolour;
1749 break;
1750 case SKIN_TOKEN_IMAGE_BACKDROP:
1751 function = parse_image_special;
1752 break;
Jonathan Gordon281f1a12011-08-14 13:50:07 +00001753 case SKIN_TOKEN_VIEWPORT_TEXTSTYLE:
1754 function = parse_viewporttextstyle;
1755 break;
Jonathan Gordon4ed13402011-08-14 13:56:10 +00001756#endif
Jonathan Gordon281f1a12011-08-14 13:50:07 +00001757#ifdef HAVE_LCD_COLOR
1758 case SKIN_TOKEN_VIEWPORT_GRADIENT_SETUP:
1759 function = parse_viewport_gradient_setup;
1760 break;
1761#endif
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001762 case SKIN_TOKEN_TRANSLATEDSTRING:
1763 case SKIN_TOKEN_SETTING:
1764 function = parse_setting_and_lang;
1765 break;
1766#ifdef HAVE_LCD_BITMAP
1767 case SKIN_TOKEN_VIEWPORT_CUSTOMLIST:
1768 function = parse_playlistview;
1769 break;
1770 case SKIN_TOKEN_LOAD_FONT:
1771 function = parse_font_load;
1772 break;
1773 case SKIN_TOKEN_VIEWPORT_ENABLE:
1774 case SKIN_TOKEN_UIVIEWPORT_ENABLE:
Jonathan Gordonee4f8a92010-08-02 12:50:23 +00001775 token->value.data = element->params[0].data.text;
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001776 break;
1777 case SKIN_TOKEN_IMAGE_PRELOAD_DISPLAY:
1778 function = parse_image_display;
1779 break;
1780 case SKIN_TOKEN_IMAGE_PRELOAD:
1781 case SKIN_TOKEN_IMAGE_DISPLAY:
1782 function = parse_image_load;
1783 break;
1784#endif
1785#ifdef HAVE_TOUCHSCREEN
1786 case SKIN_TOKEN_TOUCHREGION:
1787 function = parse_touchregion;
1788 break;
Jonathan Gordon156b0bc2011-02-28 11:19:59 +00001789 case SKIN_TOKEN_LASTTOUCH:
1790 function = parse_lasttouch;
1791 break;
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001792#endif
1793#ifdef HAVE_ALBUMART
1794 case SKIN_TOKEN_ALBUMART_DISPLAY:
1795 if (wps_data->albumart)
1796 wps_data->albumart->vp = &curr_vp->vp;
1797 break;
1798 case SKIN_TOKEN_ALBUMART_LOAD:
1799 function = parse_albumart_load;
1800 break;
1801#endif
Jonathan Gordon87aa86c2011-03-27 08:01:58 +00001802#ifdef HAVE_SKIN_VARIABLES
1803 case SKIN_TOKEN_VAR_SET:
1804 case SKIN_TOKEN_VAR_GETVAL:
1805 case SKIN_TOKEN_VAR_TIMEOUT:
1806 function = parse_skinvar;
1807 break;
1808#endif
Jonathan Gordon2d31d772010-07-29 12:37:48 +00001809 default:
1810 break;