blob: 2f79c99144ac5872886eac18b1ac519f823bc1c4 [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
11 *
Daniel Stenberg2acc0ac2008-06-28 18:10:04 +000012 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
Nicolas Pennequinab90d582007-04-04 14:41:40 +000016 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
Dave Chapmanb9bb7232008-03-26 18:18:22 +000022#include <stdio.h>
23#include <string.h>
Bertrik Sikken28434692008-04-28 16:18:04 +000024#include <stdlib.h>
Jonathan Gordon9f4f5db2009-09-06 16:54:04 +000025#include "config.h"
Dave Chapman78d29f52008-03-26 23:35:34 +000026#include "file.h"
27#include "misc.h"
Nils Wallméniusa21004d2008-05-19 14:37:16 +000028#include "plugin.h"
Thomas Martitz9bd7b232009-08-09 16:16:55 +000029#include "viewport.h"
Nils Wallméniusa21004d2008-05-19 14:37:16 +000030
Dave Chapmanb9bb7232008-03-26 18:18:22 +000031#ifdef __PCTOOL__
Frank Gevaerts5d22e3c2008-08-29 21:08:38 +000032#ifdef WPSEDITOR
33#include "proxy.h"
Frank Gevaerts5d22e3c2008-08-29 21:08:38 +000034#include "sysfont.h"
Frank Gevaerts5d22e3c2008-08-29 21:08:38 +000035#else
Maurus Cuelenaere876db6c2009-08-21 18:15:20 +000036#include "action.h"
Frank Gevaerts5d22e3c2008-08-29 21:08:38 +000037#include "checkwps.h"
Maurus Cuelenaere36c71a62009-01-29 20:49:43 +000038#include "audio.h"
Jonathan Gordon669afd02010-01-07 07:47:19 +000039#define lang_is_rtl() (false)
Dave Chapmanb9bb7232008-03-26 18:18:22 +000040#define DEBUGF printf
Frank Gevaerts5d22e3c2008-08-29 21:08:38 +000041#endif /*WPSEDITOR*/
Dave Chapmanb9bb7232008-03-26 18:18:22 +000042#else
43#include "debug.h"
Jonathan Gordon340f3232009-09-26 00:58:32 +000044#include "language.h"
Frank Gevaerts5d22e3c2008-08-29 21:08:38 +000045#endif /*__PCTOOL__*/
Dave Chapmanb9bb7232008-03-26 18:18:22 +000046
Nicolas Pennequinab90d582007-04-04 14:41:40 +000047#include <ctype.h>
48#include <stdbool.h>
Dave Chapmanb9bb7232008-03-26 18:18:22 +000049#include "font.h"
50
Jonathan Gordon5e5fc642009-07-27 07:21:05 +000051#include "wps_internals.h"
Jonathan Gordon37908972009-08-06 04:33:35 +000052#include "skin_engine.h"
Nicolas Pennequinab90d582007-04-04 14:41:40 +000053#include "settings.h"
Antoine Cellerier8289b962008-12-07 16:20:35 +000054#include "settings_list.h"
Jonathan Gordona5d8d212010-05-12 11:44:09 +000055#if CONFIG_TUNER
Jonathan Gordon1bd072c2010-05-12 10:38:00 +000056#include "radio.h"
Jonathan Gordona5d8d212010-05-12 11:44:09 +000057#include "tuner.h"
58#endif
Jonathan Gordon1c2aa352010-02-14 06:26:16 +000059#include "skin_fonts.h"
Nicolas Pennequinab90d582007-04-04 14:41:40 +000060
61#ifdef HAVE_LCD_BITMAP
62#include "bmp.h"
Nicolas Pennequinab90d582007-04-04 14:41:40 +000063#endif
Nicolas Pennequin1cf2ec32007-04-25 22:08:00 +000064
Thomas Martitze9c10182009-10-16 19:14:41 +000065#ifdef HAVE_ALBUMART
66#include "playback.h"
67#endif
68
Nicolas Pennequin1cf2ec32007-04-25 22:08:00 +000069#include "backdrop.h"
Jonathan Gordoneee54232010-01-29 07:52:13 +000070#include "statusbar-skinned.h"
Nicolas Pennequinab90d582007-04-04 14:41:40 +000071
Nicolas Pennequin31f76112007-11-14 22:02:41 +000072#define WPS_ERROR_INVALID_PARAM -1
73
Jonathan Gordonc8126142009-11-04 05:24:30 +000074/* which screen are we parsing for? */
75static enum screen_type curr_screen;
76
Nicolas Pennequinab90d582007-04-04 14:41:40 +000077/* level of current conditional.
78 -1 means we're not in a conditional. */
Nicolas Pennequin830a3a42007-04-04 15:47:51 +000079static int level = -1;
Nicolas Pennequinab90d582007-04-04 14:41:40 +000080
81/* index of the last WPS_TOKEN_CONDITIONAL_OPTION
82 or WPS_TOKEN_CONDITIONAL_START in current level */
Nicolas Pennequin830a3a42007-04-04 15:47:51 +000083static int lastcond[WPS_MAX_COND_LEVEL];
Nicolas Pennequinab90d582007-04-04 14:41:40 +000084
85/* index of the WPS_TOKEN_CONDITIONAL in current level */
Nicolas Pennequin830a3a42007-04-04 15:47:51 +000086static int condindex[WPS_MAX_COND_LEVEL];
Nicolas Pennequinab90d582007-04-04 14:41:40 +000087
88/* number of condtional options in current level */
Nicolas Pennequin830a3a42007-04-04 15:47:51 +000089static int numoptions[WPS_MAX_COND_LEVEL];
Nicolas Pennequinab90d582007-04-04 14:41:40 +000090
Jonathan Gordon8cb74432009-09-02 02:55:33 +000091/* line number, debug only */
92static int line_number;
Nicolas Pennequind7fd9892007-04-24 00:57:04 +000093
Jonathan Gordon36ca4962009-08-18 05:30:59 +000094/* the current viewport */
95static struct skin_viewport *curr_vp;
Jonathan Gordon8cb74432009-09-02 02:55:33 +000096/* the current line, linked to the above viewport */
Jonathan Gordon8f76e7f2009-09-02 06:23:01 +000097static struct skin_line *curr_line;
Jonathan Gordon36ca4962009-08-18 05:30:59 +000098
Jonathan Gordon91e6b062010-01-07 07:34:15 +000099static int follow_lang_direction = 0;
100
Jonas Häggqvista13c1622008-12-09 18:15:19 +0000101#if defined(DEBUG) || defined(SIMULATOR)
Nicolas Pennequin6ac306a2007-04-24 23:58:57 +0000102/* debugging function */
103extern void print_debug_info(struct wps_data *data, int fail, int line);
Jonathan Gordonc552d082009-08-19 05:07:12 +0000104extern void debug_skin_usage(void);
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000105#endif
106
Nicolas Pennequin07696c12007-04-08 04:01:06 +0000107/* Function for parsing of details for a token. At the moment the
108 function is called, the token type has already been set. The
109 function must fill in the details and possibly add more tokens
110 to the token array. It should return the number of chars that
111 has been consumed.
112
113 wps_bufptr points to the char following the tag (i.e. where
114 details begin).
115 token is the pointer to the 'main' token being parsed
116 */
117typedef int (*wps_tag_parse_func)(const char *wps_bufptr,
118 struct wps_token *token, struct wps_data *wps_data);
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000119
120struct wps_tag {
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000121 enum wps_token_type type;
Dan Everton86c0e3a2007-04-05 10:21:49 +0000122 const char name[3];
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000123 unsigned char refresh_type;
Dan Everton86c0e3a2007-04-05 10:21:49 +0000124 const wps_tag_parse_func parse_func;
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000125};
Jonathan Gordon0eb5dc62009-04-20 01:41:56 +0000126static int skip_end_of_line(const char *wps_bufptr);
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000127/* prototypes of all special parse functions : */
Jonathan Gordon85600e62008-10-11 12:20:09 +0000128static int parse_timeout(const char *wps_bufptr,
Nicolas Pennequin07696c12007-04-08 04:01:06 +0000129 struct wps_token *token, struct wps_data *wps_data);
130static int parse_progressbar(const char *wps_bufptr,
131 struct wps_token *token, struct wps_data *wps_data);
132static int parse_dir_level(const char *wps_bufptr,
133 struct wps_token *token, struct wps_data *wps_data);
Jonathan Gordon340f3232009-09-26 00:58:32 +0000134static int parse_setting_and_lang(const char *wps_bufptr,
Antoine Cellerier8289b962008-12-07 16:20:35 +0000135 struct wps_token *token, struct wps_data *wps_data);
Jonathan Gordon91e6b062010-01-07 07:34:15 +0000136
137
Bertrik Sikken552835e2010-01-18 21:20:36 +0000138static int parse_languagedirection(const char *wps_bufptr,
Jonathan Gordon91e6b062010-01-07 07:34:15 +0000139 struct wps_token *token, struct wps_data *wps_data)
140{
141 (void)wps_bufptr;
142 (void)token;
143 (void)wps_data;
144 follow_lang_direction = 2; /* 2 because it is decremented immediatly after
145 this token is parsed, after the next token it
146 will be 0 again. */
147 return 0;
148}
Thomas Martitz541dd6f2009-09-13 12:24:14 +0000149
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000150#ifdef HAVE_LCD_BITMAP
Jonathan Gordon5a169bb2008-06-23 06:04:17 +0000151static int parse_viewport_display(const char *wps_bufptr,
152 struct wps_token *token, struct wps_data *wps_data);
Jonathan Gordondc0ba912010-01-13 06:02:38 +0000153static int parse_playlistview(const char *wps_bufptr,
154 struct wps_token *token, struct wps_data *wps_data);
Dave Chapmand02c79c2008-03-21 19:38:00 +0000155static int parse_viewport(const char *wps_bufptr,
156 struct wps_token *token, struct wps_data *wps_data);
Nicolas Pennequin07696c12007-04-08 04:01:06 +0000157static int parse_statusbar_enable(const char *wps_bufptr,
158 struct wps_token *token, struct wps_data *wps_data);
159static int parse_statusbar_disable(const char *wps_bufptr,
160 struct wps_token *token, struct wps_data *wps_data);
Jonathan Gordona9b5f4d2010-03-06 00:29:46 +0000161static int parse_statusbar_inbuilt(const char *wps_bufptr,
162 struct wps_token *token, struct wps_data *wps_data);
Nicolas Pennequin07696c12007-04-08 04:01:06 +0000163static int parse_image_display(const char *wps_bufptr,
164 struct wps_token *token, struct wps_data *wps_data);
165static int parse_image_load(const char *wps_bufptr,
166 struct wps_token *token, struct wps_data *wps_data);
Jonathan Gordon1c2aa352010-02-14 06:26:16 +0000167static int parse_font_load(const char *wps_bufptr,
168 struct wps_token *token, struct wps_data *wps_data);
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000169#endif /*HAVE_LCD_BITMAP */
Jonathan Gordon082f50b2008-06-23 06:17:22 +0000170#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000171static int parse_viewportcolour(const char *wps_bufptr,
172 struct wps_token *token, struct wps_data *wps_data);
Jonathan Gordon082f50b2008-06-23 06:17:22 +0000173static int parse_image_special(const char *wps_bufptr,
174 struct wps_token *token, struct wps_data *wps_data);
175#endif
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +0000176#ifdef HAVE_ALBUMART
177static int parse_albumart_load(const char *wps_bufptr,
178 struct wps_token *token, struct wps_data *wps_data);
Jonathan Gordonfe2f0422009-09-07 02:36:56 +0000179static int parse_albumart_display(const char *wps_bufptr,
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +0000180 struct wps_token *token, struct wps_data *wps_data);
181#endif /* HAVE_ALBUMART */
Jonathan Gordon0eb5dc62009-04-20 01:41:56 +0000182#ifdef HAVE_TOUCHSCREEN
183static int parse_touchregion(const char *wps_bufptr,
184 struct wps_token *token, struct wps_data *wps_data);
185#else
186static int fulline_tag_not_supported(const char *wps_bufptr,
187 struct wps_token *token, struct wps_data *wps_data)
188{
189 (void)token; (void)wps_data;
190 return skip_end_of_line(wps_bufptr);
191}
192#define parse_touchregion fulline_tag_not_supported
Thomas Martitz541dd6f2009-09-13 12:24:14 +0000193#endif
Brandon Low9a550522007-06-16 20:33:30 +0000194#ifdef CONFIG_RTC
195#define WPS_RTC_REFRESH WPS_REFRESH_DYNAMIC
196#else
197#define WPS_RTC_REFRESH WPS_REFRESH_STATIC
198#endif
199
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000200/* array of available tags - those with more characters have to go first
201 (e.g. "xl" and "xd" before "x"). It needs to end with the unknown token. */
202static const struct wps_tag all_tags[] = {
203
Dan Everton86c0e3a2007-04-05 10:21:49 +0000204 { WPS_TOKEN_ALIGN_CENTER, "ac", 0, NULL },
205 { WPS_TOKEN_ALIGN_LEFT, "al", 0, NULL },
Jonathan Gordon91e6b062010-01-07 07:34:15 +0000206 { WPS_TOKEN_ALIGN_LEFT_RTL, "aL", 0, NULL },
Dan Everton86c0e3a2007-04-05 10:21:49 +0000207 { WPS_TOKEN_ALIGN_RIGHT, "ar", 0, NULL },
Jonathan Gordon91e6b062010-01-07 07:34:15 +0000208 { WPS_TOKEN_ALIGN_RIGHT_RTL, "aR", 0, NULL },
209 { WPS_NO_TOKEN, "ax", 0, parse_languagedirection },
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000210
Jonathan Gordon4c65a192010-04-25 11:32:51 +0000211 { WPS_TOKEN_BATTERY_PERCENT, "bl", WPS_REFRESH_DYNAMIC, parse_progressbar },
Dan Everton86c0e3a2007-04-05 10:21:49 +0000212 { WPS_TOKEN_BATTERY_VOLTS, "bv", WPS_REFRESH_DYNAMIC, NULL },
213 { WPS_TOKEN_BATTERY_TIME, "bt", WPS_REFRESH_DYNAMIC, NULL },
214 { WPS_TOKEN_BATTERY_SLEEPTIME, "bs", WPS_REFRESH_DYNAMIC, NULL },
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000215#if CONFIG_CHARGING >= CHARGING_MONITOR
Dan Everton86c0e3a2007-04-05 10:21:49 +0000216 { WPS_TOKEN_BATTERY_CHARGING, "bc", WPS_REFRESH_DYNAMIC, NULL },
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000217#endif
218#if CONFIG_CHARGING
Dan Everton86c0e3a2007-04-05 10:21:49 +0000219 { WPS_TOKEN_BATTERY_CHARGER_CONNECTED,"bp", WPS_REFRESH_DYNAMIC, NULL },
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000220#endif
Jonathan Gordon49666662009-11-22 19:09:54 +0000221#ifdef HAVE_USB_POWER
Jonathan Gordon58ca43d2009-12-03 05:36:23 +0000222 { WPS_TOKEN_USB_POWERED, "bu", WPS_REFRESH_DYNAMIC, NULL },
Jonathan Gordon49666662009-11-22 19:09:54 +0000223#endif
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000224
Marianne Arnolde435e4d2009-05-16 11:22:41 +0000225 { WPS_TOKEN_RTC_PRESENT , "cc", WPS_REFRESH_STATIC, NULL },
Brandon Low9a550522007-06-16 20:33:30 +0000226 { WPS_TOKEN_RTC_DAY_OF_MONTH, "cd", WPS_RTC_REFRESH, NULL },
227 { WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED,"ce", WPS_RTC_REFRESH, NULL },
Jonathan Gordon923cbe32007-11-27 01:41:59 +0000228 { WPS_TOKEN_RTC_12HOUR_CFG, "cf", WPS_RTC_REFRESH, NULL },
Brandon Low9a550522007-06-16 20:33:30 +0000229 { WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED, "cH", WPS_RTC_REFRESH, NULL },
230 { WPS_TOKEN_RTC_HOUR_24, "ck", WPS_RTC_REFRESH, NULL },
231 { WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED, "cI", WPS_RTC_REFRESH, NULL },
232 { WPS_TOKEN_RTC_HOUR_12, "cl", WPS_RTC_REFRESH, NULL },
233 { WPS_TOKEN_RTC_MONTH, "cm", WPS_RTC_REFRESH, NULL },
234 { WPS_TOKEN_RTC_MINUTE, "cM", WPS_RTC_REFRESH, NULL },
235 { WPS_TOKEN_RTC_SECOND, "cS", WPS_RTC_REFRESH, NULL },
236 { WPS_TOKEN_RTC_YEAR_2_DIGITS, "cy", WPS_RTC_REFRESH, NULL },
237 { WPS_TOKEN_RTC_YEAR_4_DIGITS, "cY", WPS_RTC_REFRESH, NULL },
238 { WPS_TOKEN_RTC_AM_PM_UPPER, "cP", WPS_RTC_REFRESH, NULL },
239 { WPS_TOKEN_RTC_AM_PM_LOWER, "cp", WPS_RTC_REFRESH, NULL },
240 { WPS_TOKEN_RTC_WEEKDAY_NAME, "ca", WPS_RTC_REFRESH, NULL },
241 { WPS_TOKEN_RTC_MONTH_NAME, "cb", WPS_RTC_REFRESH, NULL },
242 { WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON, "cu", WPS_RTC_REFRESH, NULL },
243 { WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN, "cw", WPS_RTC_REFRESH, NULL },
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000244
245 /* current file */
Dan Everton86c0e3a2007-04-05 10:21:49 +0000246 { WPS_TOKEN_FILE_BITRATE, "fb", WPS_REFRESH_STATIC, NULL },
247 { WPS_TOKEN_FILE_CODEC, "fc", WPS_REFRESH_STATIC, NULL },
248 { WPS_TOKEN_FILE_FREQUENCY, "ff", WPS_REFRESH_STATIC, NULL },
Nicolas Pennequin5cc98ef2007-05-21 13:41:43 +0000249 { WPS_TOKEN_FILE_FREQUENCY_KHZ, "fk", WPS_REFRESH_STATIC, NULL },
Dan Everton86c0e3a2007-04-05 10:21:49 +0000250 { WPS_TOKEN_FILE_NAME_WITH_EXTENSION, "fm", WPS_REFRESH_STATIC, NULL },
251 { WPS_TOKEN_FILE_NAME, "fn", WPS_REFRESH_STATIC, NULL },
252 { WPS_TOKEN_FILE_PATH, "fp", WPS_REFRESH_STATIC, NULL },
253 { WPS_TOKEN_FILE_SIZE, "fs", WPS_REFRESH_STATIC, NULL },
254 { WPS_TOKEN_FILE_VBR, "fv", WPS_REFRESH_STATIC, NULL },
Nicolas Pennequinaa220d52007-05-02 17:51:01 +0000255 { WPS_TOKEN_FILE_DIRECTORY, "d", WPS_REFRESH_STATIC,
256 parse_dir_level },
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000257
258 /* next file */
Jonathan Gordon843c7ef2009-04-06 00:39:43 +0000259 { WPS_TOKEN_FILE_BITRATE, "Fb", WPS_REFRESH_STATIC, NULL },
260 { WPS_TOKEN_FILE_CODEC, "Fc", WPS_REFRESH_STATIC, NULL },
261 { WPS_TOKEN_FILE_FREQUENCY, "Ff", WPS_REFRESH_STATIC, NULL },
262 { WPS_TOKEN_FILE_FREQUENCY_KHZ, "Fk", WPS_REFRESH_STATIC, NULL },
263 { WPS_TOKEN_FILE_NAME_WITH_EXTENSION, "Fm", WPS_REFRESH_STATIC, NULL },
264 { WPS_TOKEN_FILE_NAME, "Fn", WPS_REFRESH_STATIC, NULL },
265 { WPS_TOKEN_FILE_PATH, "Fp", WPS_REFRESH_STATIC, NULL },
266 { WPS_TOKEN_FILE_SIZE, "Fs", WPS_REFRESH_STATIC, NULL },
267 { WPS_TOKEN_FILE_VBR, "Fv", WPS_REFRESH_STATIC, NULL },
268 { WPS_TOKEN_FILE_DIRECTORY, "D", WPS_REFRESH_STATIC,
Nicolas Pennequinaa220d52007-05-02 17:51:01 +0000269 parse_dir_level },
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000270
271 /* current metadata */
Dan Everton86c0e3a2007-04-05 10:21:49 +0000272 { WPS_TOKEN_METADATA_ARTIST, "ia", WPS_REFRESH_STATIC, NULL },
273 { WPS_TOKEN_METADATA_COMPOSER, "ic", WPS_REFRESH_STATIC, NULL },
274 { WPS_TOKEN_METADATA_ALBUM, "id", WPS_REFRESH_STATIC, NULL },
275 { WPS_TOKEN_METADATA_ALBUM_ARTIST, "iA", WPS_REFRESH_STATIC, NULL },
Dan Evertoneecfe9f2007-08-08 10:19:56 +0000276 { WPS_TOKEN_METADATA_GROUPING, "iG", WPS_REFRESH_STATIC, NULL },
Dan Everton86c0e3a2007-04-05 10:21:49 +0000277 { WPS_TOKEN_METADATA_GENRE, "ig", WPS_REFRESH_STATIC, NULL },
Dan Evertonf4a61f02007-08-03 10:00:42 +0000278 { WPS_TOKEN_METADATA_DISC_NUMBER, "ik", WPS_REFRESH_STATIC, NULL },
Dan Everton86c0e3a2007-04-05 10:21:49 +0000279 { WPS_TOKEN_METADATA_TRACK_NUMBER, "in", WPS_REFRESH_STATIC, NULL },
280 { WPS_TOKEN_METADATA_TRACK_TITLE, "it", WPS_REFRESH_STATIC, NULL },
281 { WPS_TOKEN_METADATA_VERSION, "iv", WPS_REFRESH_STATIC, NULL },
282 { WPS_TOKEN_METADATA_YEAR, "iy", WPS_REFRESH_STATIC, NULL },
Nicolas Pennequinaa220d52007-05-02 17:51:01 +0000283 { WPS_TOKEN_METADATA_COMMENT, "iC", WPS_REFRESH_STATIC, NULL },
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000284
285 /* next metadata */
Jonathan Gordon843c7ef2009-04-06 00:39:43 +0000286 { WPS_TOKEN_METADATA_ARTIST, "Ia", WPS_REFRESH_STATIC, NULL },
287 { WPS_TOKEN_METADATA_COMPOSER, "Ic", WPS_REFRESH_STATIC, NULL },
288 { WPS_TOKEN_METADATA_ALBUM, "Id", WPS_REFRESH_STATIC, NULL },
289 { WPS_TOKEN_METADATA_ALBUM_ARTIST, "IA", WPS_REFRESH_STATIC, NULL },
290 { WPS_TOKEN_METADATA_GROUPING, "IG", WPS_REFRESH_STATIC, NULL },
291 { WPS_TOKEN_METADATA_GENRE, "Ig", WPS_REFRESH_STATIC, NULL },
292 { WPS_TOKEN_METADATA_DISC_NUMBER, "Ik", WPS_REFRESH_STATIC, NULL },
293 { WPS_TOKEN_METADATA_TRACK_NUMBER, "In", WPS_REFRESH_STATIC, NULL },
294 { WPS_TOKEN_METADATA_TRACK_TITLE, "It", WPS_REFRESH_STATIC, NULL },
295 { WPS_TOKEN_METADATA_VERSION, "Iv", WPS_REFRESH_STATIC, NULL },
296 { WPS_TOKEN_METADATA_YEAR, "Iy", WPS_REFRESH_STATIC, NULL },
297 { WPS_TOKEN_METADATA_COMMENT, "IC", WPS_REFRESH_STATIC, NULL },
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000298
Nicolas Pennequin830a3a42007-04-04 15:47:51 +0000299#if (CONFIG_CODEC != MAS3507D)
Dan Everton86c0e3a2007-04-05 10:21:49 +0000300 { WPS_TOKEN_SOUND_PITCH, "Sp", WPS_REFRESH_DYNAMIC, NULL },
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000301#endif
Frank Gevaerts8c157992009-11-09 17:57:17 +0000302#if (CONFIG_CODEC == SWCODEC)
303 { WPS_TOKEN_SOUND_SPEED, "Ss", WPS_REFRESH_DYNAMIC, NULL },
304#endif
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000305#if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
Dan Everton86c0e3a2007-04-05 10:21:49 +0000306 { WPS_TOKEN_VLED_HDD, "lh", WPS_REFRESH_DYNAMIC, NULL },
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000307#endif
308
Dan Everton86c0e3a2007-04-05 10:21:49 +0000309 { WPS_TOKEN_MAIN_HOLD, "mh", WPS_REFRESH_DYNAMIC, NULL },
Marianne Arnold74aabc82007-06-25 20:54:11 +0000310
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000311#ifdef HAS_REMOTE_BUTTON_HOLD
Dan Everton86c0e3a2007-04-05 10:21:49 +0000312 { WPS_TOKEN_REMOTE_HOLD, "mr", WPS_REFRESH_DYNAMIC, NULL },
Nicolas Pennequinf554e002007-11-14 00:45:04 +0000313#else
314 { WPS_TOKEN_UNKNOWN, "mr", 0, NULL },
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000315#endif
316
Dan Everton86c0e3a2007-04-05 10:21:49 +0000317 { WPS_TOKEN_REPEAT_MODE, "mm", WPS_REFRESH_DYNAMIC, NULL },
318 { WPS_TOKEN_PLAYBACK_STATUS, "mp", WPS_REFRESH_DYNAMIC, NULL },
Thomas Martitz541dd6f2009-09-13 12:24:14 +0000319 { WPS_TOKEN_BUTTON_VOLUME, "mv", WPS_REFRESH_DYNAMIC,
Jonathan Gordon85600e62008-10-11 12:20:09 +0000320 parse_timeout },
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000321
322#ifdef HAVE_LCD_BITMAP
Nicolas Pennequinaa220d52007-05-02 17:51:01 +0000323 { WPS_TOKEN_PEAKMETER, "pm", WPS_REFRESH_PEAK_METER, NULL },
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000324#else
Nicolas Pennequinaa220d52007-05-02 17:51:01 +0000325 { WPS_TOKEN_PLAYER_PROGRESSBAR, "pf",
326 WPS_REFRESH_DYNAMIC | WPS_REFRESH_PLAYER_PROGRESS, parse_progressbar },
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000327#endif
Nicolas Pennequinaa220d52007-05-02 17:51:01 +0000328 { WPS_TOKEN_PROGRESSBAR, "pb", WPS_REFRESH_PLAYER_PROGRESS,
329 parse_progressbar },
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000330
Jonathan Gordon44217462010-04-11 11:18:45 +0000331 { WPS_TOKEN_VOLUME, "pv", WPS_REFRESH_DYNAMIC,
332 parse_progressbar },
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000333
Nicolas Pennequin29407cb2007-07-25 14:14:47 +0000334 { WPS_TOKEN_TRACK_ELAPSED_PERCENT, "px", WPS_REFRESH_DYNAMIC, NULL },
Dan Everton86c0e3a2007-04-05 10:21:49 +0000335 { WPS_TOKEN_TRACK_TIME_ELAPSED, "pc", WPS_REFRESH_DYNAMIC, NULL },
336 { WPS_TOKEN_TRACK_TIME_REMAINING, "pr", WPS_REFRESH_DYNAMIC, NULL },
337 { WPS_TOKEN_TRACK_LENGTH, "pt", WPS_REFRESH_STATIC, NULL },
Jonathan Gordond2e2c2a2010-03-18 07:08:49 +0000338 { WPS_TOKEN_TRACK_STARTING, "pS", WPS_REFRESH_DYNAMIC, parse_timeout },
339 { WPS_TOKEN_TRACK_ENDING, "pE", WPS_REFRESH_DYNAMIC, parse_timeout },
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000340
Dan Everton86c0e3a2007-04-05 10:21:49 +0000341 { WPS_TOKEN_PLAYLIST_POSITION, "pp", WPS_REFRESH_STATIC, NULL },
342 { WPS_TOKEN_PLAYLIST_ENTRIES, "pe", WPS_REFRESH_STATIC, NULL },
343 { WPS_TOKEN_PLAYLIST_NAME, "pn", WPS_REFRESH_STATIC, NULL },
344 { WPS_TOKEN_PLAYLIST_SHUFFLE, "ps", WPS_REFRESH_DYNAMIC, NULL },
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000345
Nicolas Pennequin31f76112007-11-14 22:02:41 +0000346#ifdef HAVE_TAGCACHE
Dan Everton86c0e3a2007-04-05 10:21:49 +0000347 { WPS_TOKEN_DATABASE_PLAYCOUNT, "rp", WPS_REFRESH_DYNAMIC, NULL },
348 { WPS_TOKEN_DATABASE_RATING, "rr", WPS_REFRESH_DYNAMIC, NULL },
Miika Pekkarinenf53a8f82007-04-15 15:46:46 +0000349 { WPS_TOKEN_DATABASE_AUTOSCORE, "ra", WPS_REFRESH_DYNAMIC, NULL },
Nicolas Pennequin31f76112007-11-14 22:02:41 +0000350#endif
351
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000352#if CONFIG_CODEC == SWCODEC
Dan Everton86c0e3a2007-04-05 10:21:49 +0000353 { WPS_TOKEN_REPLAYGAIN, "rg", WPS_REFRESH_STATIC, NULL },
Nicolas Pennequin27cbf6b2007-04-12 16:15:34 +0000354 { WPS_TOKEN_CROSSFADE, "xf", WPS_REFRESH_DYNAMIC, NULL },
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000355#endif
356
Jonathan Gordon1bd072c2010-05-12 10:38:00 +0000357 { WPS_TOKEN_HAVE_TUNER, "tp", WPS_REFRESH_STATIC, NULL },
358#if CONFIG_TUNER /* Re-uses the 't' and 'T' prefixes, be careful about doubleups */
359 { WPS_TOKEN_TUNER_TUNED, "tt", WPS_REFRESH_DYNAMIC, NULL },
360 { WPS_TOKEN_TUNER_SCANMODE, "tm", WPS_REFRESH_DYNAMIC, NULL },
361 { WPS_TOKEN_TUNER_STEREO, "ts", WPS_REFRESH_DYNAMIC, NULL },
362 { WPS_TOKEN_TUNER_MINFREQ, "ta", WPS_REFRESH_STATIC, NULL },
363 { WPS_TOKEN_TUNER_MAXFREQ, "tb", WPS_REFRESH_STATIC, NULL },
364 { WPS_TOKEN_TUNER_CURFREQ, "tf", WPS_REFRESH_DYNAMIC, NULL },
365 { WPS_TOKEN_PRESET_ID, "Ti", WPS_REFRESH_STATIC, NULL },
366 { WPS_TOKEN_PRESET_NAME, "Tn", WPS_REFRESH_STATIC, NULL },
367 { WPS_TOKEN_PRESET_FREQ, "Tf", WPS_REFRESH_STATIC, NULL },
368 { WPS_TOKEN_PRESET_COUNT, "Tc", WPS_REFRESH_STATIC, NULL },
369 { WPS_TOKEN_HAVE_RDS, "tx", WPS_REFRESH_STATIC, NULL },
Jonathan Gordona5d8d212010-05-12 11:44:09 +0000370#ifdef HAVE_RDS_CAP
Jonathan Gordon1bd072c2010-05-12 10:38:00 +0000371 { WPS_TOKEN_RDS_NAME, "ty", WPS_REFRESH_DYNAMIC, NULL },
372 { WPS_TOKEN_RDS_TEXT, "tz", WPS_REFRESH_DYNAMIC, NULL },
373#endif
374#endif /* CONFIG_TUNER */
375
Nicolas Pennequin07696c12007-04-08 04:01:06 +0000376 { WPS_NO_TOKEN, "s", WPS_REFRESH_SCROLL, NULL },
Jonathan Gordon85600e62008-10-11 12:20:09 +0000377 { WPS_TOKEN_SUBLINE_TIMEOUT, "t", 0, parse_timeout },
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000378
379#ifdef HAVE_LCD_BITMAP
Nicolas Pennequin07696c12007-04-08 04:01:06 +0000380 { WPS_NO_TOKEN, "we", 0, parse_statusbar_enable },
381 { WPS_NO_TOKEN, "wd", 0, parse_statusbar_disable },
Jonathan Gordona9b5f4d2010-03-06 00:29:46 +0000382 { WPS_TOKEN_DRAW_INBUILTBAR, "wi", WPS_REFRESH_DYNAMIC, parse_statusbar_inbuilt },
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000383
Dan Everton86c0e3a2007-04-05 10:21:49 +0000384 { WPS_NO_TOKEN, "xl", 0, parse_image_load },
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000385
Nicolas Pennequinaa220d52007-05-02 17:51:01 +0000386 { WPS_TOKEN_IMAGE_PRELOAD_DISPLAY, "xd", WPS_REFRESH_STATIC,
387 parse_image_display },
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000388
Nicolas Pennequin07696c12007-04-08 04:01:06 +0000389 { WPS_TOKEN_IMAGE_DISPLAY, "x", 0, parse_image_load },
Jonathan Gordon1c2aa352010-02-14 06:26:16 +0000390 { WPS_NO_TOKEN, "Fl", 0, parse_font_load },
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +0000391#ifdef HAVE_ALBUMART
392 { WPS_NO_TOKEN, "Cl", 0, parse_albumart_load },
Jonathan Gordonfe2f0422009-09-07 02:36:56 +0000393 { WPS_TOKEN_ALBUMART_DISPLAY, "C", WPS_REFRESH_STATIC, parse_albumart_display },
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +0000394#endif
Dave Chapmand02c79c2008-03-21 19:38:00 +0000395
Thomas Martitz541dd6f2009-09-13 12:24:14 +0000396 { WPS_VIEWPORT_ENABLE, "Vd", WPS_REFRESH_DYNAMIC,
Jonathan Gordon5a169bb2008-06-23 06:04:17 +0000397 parse_viewport_display },
Jonathan Gordonefd1f4e2010-05-05 13:48:50 +0000398 { WPS_TOKEN_UIVIEWPORT_ENABLE, "VI", WPS_REFRESH_STATIC,
399 parse_viewport_display },
Jonathan Gordondc0ba912010-01-13 06:02:38 +0000400#ifdef HAVE_LCD_BITMAP
401 { WPS_VIEWPORT_CUSTOMLIST, "Vp", WPS_REFRESH_STATIC, parse_playlistview },
Jonathan Gordon466e5d92010-02-26 03:45:41 +0000402 { WPS_TOKEN_LIST_TITLE_TEXT, "Lt", WPS_REFRESH_DYNAMIC, NULL },
403 { WPS_TOKEN_LIST_TITLE_ICON, "Li", WPS_REFRESH_DYNAMIC, NULL },
Jonathan Gordondc0ba912010-01-13 06:02:38 +0000404#endif
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000405#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
406 { WPS_TOKEN_VIEWPORT_FGCOLOUR, "Vf", WPS_REFRESH_STATIC, parse_viewportcolour },
407 { WPS_TOKEN_VIEWPORT_BGCOLOUR, "Vb", WPS_REFRESH_STATIC, parse_viewportcolour },
408#endif
Dave Chapmand02c79c2008-03-21 19:38:00 +0000409 { WPS_NO_TOKEN, "V", 0, parse_viewport },
410
Dave Chapmand746b792008-03-29 01:14:10 +0000411#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
Nicolas Pennequin07696c12007-04-08 04:01:06 +0000412 { WPS_TOKEN_IMAGE_BACKDROP, "X", 0, parse_image_special },
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000413#endif
414#endif
415
Jonathan Gordon340f3232009-09-26 00:58:32 +0000416 { WPS_TOKEN_SETTING, "St", WPS_REFRESH_DYNAMIC,
Teruaki Kawashima1fbdd912010-03-06 14:14:44 +0000417 parse_setting_and_lang },
Jonathan Gordon340f3232009-09-26 00:58:32 +0000418 { WPS_TOKEN_TRANSLATEDSTRING, "Sx", WPS_REFRESH_STATIC,
419 parse_setting_and_lang },
Tomer Shalevec0f4b42009-11-15 21:39:39 +0000420 { WPS_TOKEN_LANG_IS_RTL , "Sr", WPS_REFRESH_STATIC, NULL },
Jonathan Gordon340f3232009-09-26 00:58:32 +0000421
Jonathan Gordon0eb5dc62009-04-20 01:41:56 +0000422 { WPS_TOKEN_LASTTOUCH, "Tl", WPS_REFRESH_DYNAMIC, parse_timeout },
Thomas Martitz9072a452009-10-16 19:14:33 +0000423 { WPS_TOKEN_CURRENT_SCREEN, "cs", WPS_REFRESH_DYNAMIC, NULL },
Jonathan Gordon0eb5dc62009-04-20 01:41:56 +0000424 { WPS_NO_TOKEN, "T", 0, parse_touchregion },
Teruaki Kawashima1fbdd912010-03-06 14:14:44 +0000425
426
Jonathan Gordonf76b2f22009-11-03 07:58:10 +0000427 /* Recording Tokens */
428 { WPS_TOKEN_HAVE_RECORDING, "Rp", WPS_REFRESH_STATIC, NULL },
429#ifdef HAVE_RECORDING
Jonathan Gordon1bd072c2010-05-12 10:38:00 +0000430 { WPS_TOKEN_IS_RECORDING, "Rr", WPS_REFRESH_DYNAMIC, NULL },
Jonathan Gordonf76b2f22009-11-03 07:58:10 +0000431 { WPS_TOKEN_REC_FREQ, "Rf", WPS_REFRESH_DYNAMIC, NULL },
432 { WPS_TOKEN_REC_ENCODER, "Re", WPS_REFRESH_DYNAMIC, NULL },
433 { WPS_TOKEN_REC_BITRATE, "Rb", WPS_REFRESH_DYNAMIC, NULL },
434 { WPS_TOKEN_REC_MONO, "Rm", WPS_REFRESH_DYNAMIC, NULL },
Jonathan Gordon1bd072c2010-05-12 10:38:00 +0000435 { WPS_TOKEN_REC_SECONDS, "Rs", WPS_REFRESH_DYNAMIC, NULL },
436 { WPS_TOKEN_REC_MINUTES, "Rn", WPS_REFRESH_DYNAMIC, NULL },
437 { WPS_TOKEN_REC_HOURS, "Rh", WPS_REFRESH_DYNAMIC, NULL },
Jonathan Gordonf76b2f22009-11-03 07:58:10 +0000438#endif
Nicolas Pennequin07696c12007-04-08 04:01:06 +0000439 { WPS_TOKEN_UNKNOWN, "", 0, NULL }
440 /* the array MUST end with an empty string (first char is \0) */
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000441};
442
Jonathan Gordon18a8e522009-08-16 18:23:00 +0000443
Thomas Martitz541dd6f2009-09-13 12:24:14 +0000444/* add a skin_token_list item to the list chain. ALWAYS appended because some of the
Jonathan Gordon18a8e522009-08-16 18:23:00 +0000445 * chains require the order to be kept.
446 */
447static void add_to_ll_chain(struct skin_token_list **list, struct skin_token_list *item)
448{
449 if (*list == NULL)
450 *list = item;
451 else
452 {
453 struct skin_token_list *t = *list;
454 while (t->next)
455 t = t->next;
Thomas Martitz541dd6f2009-09-13 12:24:14 +0000456 t->next = item;
Jonathan Gordon18a8e522009-08-16 18:23:00 +0000457 }
Thomas Martitz541dd6f2009-09-13 12:24:14 +0000458}
Thomas Martitz3216d322009-11-01 15:48:31 +0000459
460/* traverse the image linked-list for an image */
461#ifdef HAVE_LCD_BITMAP
462struct gui_img* find_image(char label, struct wps_data *data)
463{
464 struct skin_token_list *list = data->images;
465 while (list)
466 {
467 struct gui_img *img = (struct gui_img *)list->token->value.data;
468 if (img->label == label)
469 return img;
470 list = list->next;
471 }
472 return NULL;
473}
Thomas Martitz22630862010-02-27 16:51:51 +0000474
Thomas Martitz3216d322009-11-01 15:48:31 +0000475#endif
476
477/* traverse the viewport linked list for a viewport */
478struct skin_viewport* find_viewport(char label, struct wps_data *data)
479{
480 struct skin_token_list *list = data->viewports;
481 while (list)
482 {
483 struct skin_viewport *vp = (struct skin_viewport *)list->token->value.data;
484 if (vp->label == label)
485 return vp;
486 list = list->next;
487 }
488 return NULL;
489}
490
491
Jonathan Gordon18a8e522009-08-16 18:23:00 +0000492/* create and init a new wpsll item.
493 * passing NULL to token will alloc a new one.
Jonathan Gordon271643c2009-08-16 21:22:57 +0000494 * You should only pass NULL for the token when the token type (table above)
495 * is WPS_NO_TOKEN which means it is not stored automatically in the skins token array
Jonathan Gordon18a8e522009-08-16 18:23:00 +0000496 */
497static struct skin_token_list *new_skin_token_list_item(struct wps_token *token,
498 void* token_data)
499{
500 struct skin_token_list *llitem = skin_buffer_alloc(sizeof(struct skin_token_list));
501 if (!token)
502 token = skin_buffer_alloc(sizeof(struct wps_token));
503 if (!llitem || !token)
504 return NULL;
505 llitem->next = NULL;
506 llitem->token = token;
Jonathan Gordon58ca43d2009-12-03 05:36:23 +0000507 if (token_data)
508 llitem->token->value.data = token_data;
Jonathan Gordon18a8e522009-08-16 18:23:00 +0000509 return llitem;
Thomas Martitz541dd6f2009-09-13 12:24:14 +0000510}
Jonathan Gordon18a8e522009-08-16 18:23:00 +0000511
Nicolas Pennequin07696c12007-04-08 04:01:06 +0000512/* Returns the number of chars that should be skipped to jump
513 immediately after the first eol, i.e. to the start of the next line */
Nicolas Pennequin9cf89602007-04-05 14:09:59 +0000514static int skip_end_of_line(const char *wps_bufptr)
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000515{
Jonathan Gordon8cb74432009-09-02 02:55:33 +0000516 line_number++;
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000517 int skip = 0;
Nicolas Pennequin9cf89602007-04-05 14:09:59 +0000518 while(*(wps_bufptr + skip) != '\n')
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000519 skip++;
520 return ++skip;
521}
522
Nicolas Pennequin07696c12007-04-08 04:01:06 +0000523/* Starts a new subline in the current line during parsing */
Jonathan Gordon8f76e7f2009-09-02 06:23:01 +0000524static bool skin_start_new_subline(struct skin_line *line, int curr_token)
Nicolas Pennequin2e1169b2007-04-15 02:59:34 +0000525{
Jonathan Gordon8f76e7f2009-09-02 06:23:01 +0000526 struct skin_subline *subline = skin_buffer_alloc(sizeof(struct skin_subline));
Jonathan Gordon8cb74432009-09-02 02:55:33 +0000527 if (!subline)
528 return false;
529
530 subline->first_token_idx = curr_token;
531 subline->next = NULL;
Thomas Martitz541dd6f2009-09-13 12:24:14 +0000532
Jonathan Gordon8cb74432009-09-02 02:55:33 +0000533 subline->line_type = 0;
534 subline->time_mult = 0;
Thomas Martitz541dd6f2009-09-13 12:24:14 +0000535
Jonathan Gordon8cb74432009-09-02 02:55:33 +0000536 line->curr_subline->last_token_idx = curr_token-1;
537 line->curr_subline->next = subline;
538 line->curr_subline = subline;
539 return true;
540}
541
Jonathan Gordon8f76e7f2009-09-02 06:23:01 +0000542static bool skin_start_new_line(struct skin_viewport *vp, int curr_token)
Jonathan Gordon8cb74432009-09-02 02:55:33 +0000543{
Jonathan Gordon8f76e7f2009-09-02 06:23:01 +0000544 struct skin_line *line = skin_buffer_alloc(sizeof(struct skin_line));
545 struct skin_subline *subline = NULL;
Jonathan Gordon8cb74432009-09-02 02:55:33 +0000546 if (!line)
547 return false;
Thomas Martitz541dd6f2009-09-13 12:24:14 +0000548
549 /* init the subline */
Jonathan Gordon8cb74432009-09-02 02:55:33 +0000550 subline = &line->sublines;
551 subline->first_token_idx = curr_token;
Thomas Martitz541dd6f2009-09-13 12:24:14 +0000552 subline->next = NULL;
Jonathan Gordon8cb74432009-09-02 02:55:33 +0000553 subline->line_type = 0;
554 subline->time_mult = 0;
Thomas Martitz541dd6f2009-09-13 12:24:14 +0000555
Jonathan Gordon8cb74432009-09-02 02:55:33 +0000556 /* init the new line */
Thomas Martitz541dd6f2009-09-13 12:24:14 +0000557 line->curr_subline = &line->sublines;
Jonathan Gordon8cb74432009-09-02 02:55:33 +0000558 line->next = NULL;
559 line->subline_expire_time = 0;
Thomas Martitz541dd6f2009-09-13 12:24:14 +0000560
Jonathan Gordon8cb74432009-09-02 02:55:33 +0000561 /* connect to curr_line and vp pointers.
562 * 1) close the previous lines subline
563 * 2) connect to vp pointer
564 * 3) connect to curr_line global pointer
565 */
566 if (curr_line)
567 {
568 curr_line->curr_subline->last_token_idx = curr_token - 1;
569 curr_line->next = line;
570 curr_line->curr_subline = NULL;
571 }
572 curr_line = line;
573 if (!vp->lines)
574 vp->lines = line;
Jonathan Gordon8cb74432009-09-02 02:55:33 +0000575 return true;
Nicolas Pennequin07696c12007-04-08 04:01:06 +0000576}
577
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000578#ifdef HAVE_LCD_BITMAP
579
Nicolas Pennequin07696c12007-04-08 04:01:06 +0000580static int parse_statusbar_enable(const char *wps_bufptr,
581 struct wps_token *token,
582 struct wps_data *wps_data)
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000583{
Nicolas Pennequin07696c12007-04-08 04:01:06 +0000584 (void)token; /* Kill warnings */
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000585 wps_data->wps_sb_tag = true;
Nicolas Pennequin07696c12007-04-08 04:01:06 +0000586 wps_data->show_sb_on_wps = true;
Jonathan Gordon36ca4962009-08-18 05:30:59 +0000587 struct skin_viewport *default_vp = find_viewport(VP_DEFAULT_LABEL, wps_data);
Jonathan Gordonc8126142009-11-04 05:24:30 +0000588 viewport_set_defaults(&default_vp->vp, curr_screen);
Jonathan Gordon779d4e32010-03-03 05:57:15 +0000589 default_vp->vp.font = FONT_UI;
Nicolas Pennequin07696c12007-04-08 04:01:06 +0000590 return skip_end_of_line(wps_bufptr);
591}
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000592
Nicolas Pennequin07696c12007-04-08 04:01:06 +0000593static int parse_statusbar_disable(const char *wps_bufptr,
594 struct wps_token *token,
595 struct wps_data *wps_data)
596{
597 (void)token; /* Kill warnings */
598 wps_data->wps_sb_tag = true;
599 wps_data->show_sb_on_wps = false;
Jonathan Gordon36ca4962009-08-18 05:30:59 +0000600 struct skin_viewport *default_vp = find_viewport(VP_DEFAULT_LABEL, wps_data);
Jonathan Gordonc8126142009-11-04 05:24:30 +0000601 viewport_set_fullscreen(&default_vp->vp, curr_screen);
Jonathan Gordon779d4e32010-03-03 05:57:15 +0000602 default_vp->vp.font = FONT_UI;
Nicolas Pennequin9cf89602007-04-05 14:09:59 +0000603 return skip_end_of_line(wps_bufptr);
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000604}
605
Jonathan Gordona9b5f4d2010-03-06 00:29:46 +0000606static int parse_statusbar_inbuilt(const char *wps_bufptr,
607 struct wps_token *token, struct wps_data *wps_data)
608{
609 (void)wps_data;
610 token->value.data = (void*)&curr_vp->vp;
611 return skip_end_of_line(wps_bufptr);
612}
613
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000614static int get_image_id(int c)
615{
616 if(c >= 'a' && c <= 'z')
617 return c - 'a';
618 else if(c >= 'A' && c <= 'Z')
619 return c - 'A' + 26;
620 else
621 return -1;
622}
623
Jonathan Gordon877d3782010-02-16 05:24:27 +0000624char *get_image_filename(const char *start, const char* bmpdir,
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000625 char *buf, int buf_size)
626{
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000627 const char *end = start;
Teruaki Kawashimad1513712010-02-22 06:00:49 +0000628 int bmpdirlen = strlen(bmpdir);
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000629
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000630 while (*end && *end != ',' && *end != ')')
631 end++;
Teruaki Kawashimad1513712010-02-22 06:00:49 +0000632 if ( !end || (end - start) >= (buf_size - bmpdirlen - 2) )
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000633 {
Teruaki Kawashimad1513712010-02-22 06:00:49 +0000634 buf[0] = '\0';
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000635 return NULL;
636 }
637
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000638 strcpy(buf, bmpdir);
639 buf[bmpdirlen] = '/';
640 memcpy( &buf[bmpdirlen + 1], start, end - start);
641 buf[bmpdirlen + 1 + end - start] = 0;
642
643 return buf;
644}
645
Nicolas Pennequin07696c12007-04-08 04:01:06 +0000646static int parse_image_display(const char *wps_bufptr,
647 struct wps_token *token,
648 struct wps_data *wps_data)
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000649{
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000650 char label = wps_bufptr[1];
Dave Chapman15ddd7a2008-03-23 20:31:00 +0000651 int subimage;
Jonathan Gordon58ca43d2009-12-03 05:36:23 +0000652 struct gui_img *img;;
Nicolas Pennequin32bd59d2007-04-14 16:20:33 +0000653
Jonathan Gordondab7e162009-08-18 07:17:51 +0000654 /* sanity check */
655 img = find_image(label, wps_data);
656 if (!img)
Nicolas Pennequin32bd59d2007-04-14 16:20:33 +0000657 {
Jonathan Gordon8bf50ec2009-09-07 07:51:58 +0000658 token->value.i = label; /* so debug works */
Nicolas Pennequin31f76112007-11-14 22:02:41 +0000659 return WPS_ERROR_INVALID_PARAM;
Nicolas Pennequin32bd59d2007-04-14 16:20:33 +0000660 }
661
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000662 if ((subimage = get_image_id(wps_bufptr[2])) != -1)
Dave Chapman15ddd7a2008-03-23 20:31:00 +0000663 {
Jonathan Gordon91aa5122009-08-17 07:16:57 +0000664 if (subimage >= img->num_subimages)
Dave Chapman99c09782008-03-24 00:03:05 +0000665 return WPS_ERROR_INVALID_PARAM;
666
Dave Chapman15ddd7a2008-03-23 20:31:00 +0000667 /* Store sub-image number to display in high bits */
Jonathan Gordondab7e162009-08-18 07:17:51 +0000668 token->value.i = label | (subimage << 8);
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000669 return 4; /* We have consumed 2 bytes */
Dave Chapman15ddd7a2008-03-23 20:31:00 +0000670 } else {
Jonathan Gordondab7e162009-08-18 07:17:51 +0000671 token->value.i = label;
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000672 return 3; /* We have consumed 1 byte */
Dave Chapman15ddd7a2008-03-23 20:31:00 +0000673 }
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000674}
675
Nicolas Pennequin07696c12007-04-08 04:01:06 +0000676static int parse_image_load(const char *wps_bufptr,
677 struct wps_token *token,
678 struct wps_data *wps_data)
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000679{
Nicolas Pennequin9cf89602007-04-05 14:09:59 +0000680 const char *ptr = wps_bufptr;
Dave Chapmane92d2c52008-03-21 13:41:35 +0000681 const char* filename;
682 const char* id;
683 int x,y;
Jonathan Gordon58ca43d2009-12-03 05:36:23 +0000684 struct gui_img *img;
Thomas Martitz541dd6f2009-09-13 12:24:14 +0000685
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000686 /* format: %x|n|filename.bmp|x|y|
Thomas Martitz541dd6f2009-09-13 12:24:14 +0000687 or %xl|n|filename.bmp|x|y|
Dave Chapman15ddd7a2008-03-23 20:31:00 +0000688 or %xl|n|filename.bmp|x|y|num_subimages|
689 */
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000690
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000691 if (*ptr != '(')
Dave Chapmane92d2c52008-03-21 13:41:35 +0000692 return WPS_ERROR_INVALID_PARAM;
Nicolas Pennequin27cbf6b2007-04-12 16:15:34 +0000693
Dave Chapmane92d2c52008-03-21 13:41:35 +0000694 ptr++;
695
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000696 if (!(ptr = parse_list("ssdd", NULL, ',', ptr, &id, &filename, &x, &y)))
Dave Chapmane92d2c52008-03-21 13:41:35 +0000697 return WPS_ERROR_INVALID_PARAM;
698
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000699 /* Check there is a terminating ) */
700 if (*ptr != ')' && *ptr != ',')
Dave Chapmane92d2c52008-03-21 13:41:35 +0000701 return WPS_ERROR_INVALID_PARAM;
Nicolas Pennequin27cbf6b2007-04-12 16:15:34 +0000702
Nicolas Pennequin27cbf6b2007-04-12 16:15:34 +0000703 /* check the image number and load state */
Jonathan Gordondab7e162009-08-18 07:17:51 +0000704 if(find_image(*id, wps_data))
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000705 {
Nicolas Pennequin31f76112007-11-14 22:02:41 +0000706 /* Invalid image ID */
707 return WPS_ERROR_INVALID_PARAM;
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000708 }
Jonathan Gordon18a8e522009-08-16 18:23:00 +0000709 img = skin_buffer_alloc(sizeof(struct gui_img));
Jonathan Gordon58ca43d2009-12-03 05:36:23 +0000710 if (!img)
711 return WPS_ERROR_INVALID_PARAM;
Dave Chapmane92d2c52008-03-21 13:41:35 +0000712 /* save a pointer to the filename */
Jonathan Gordon18a8e522009-08-16 18:23:00 +0000713 img->bm.data = (char*)filename;
Jonathan Gordondab7e162009-08-18 07:17:51 +0000714 img->label = *id;
Jonathan Gordon18a8e522009-08-16 18:23:00 +0000715 img->x = x;
716 img->y = y;
Jonathan Gordon58ca43d2009-12-03 05:36:23 +0000717 img->num_subimages = 1;
Jonathan Gordon18a8e522009-08-16 18:23:00 +0000718 img->always_display = false;
Nicolas Pennequin27cbf6b2007-04-12 16:15:34 +0000719
Dave Chapmand02c79c2008-03-21 19:38:00 +0000720 /* save current viewport */
Jonathan Gordon36ca4962009-08-18 05:30:59 +0000721 img->vp = &curr_vp->vp;
Dave Chapmand02c79c2008-03-21 19:38:00 +0000722
Nicolas Pennequin27cbf6b2007-04-12 16:15:34 +0000723 if (token->type == WPS_TOKEN_IMAGE_DISPLAY)
Dave Chapman15ddd7a2008-03-23 20:31:00 +0000724 {
Jonathan Gordon18a8e522009-08-16 18:23:00 +0000725 img->always_display = true;
Dave Chapman15ddd7a2008-03-23 20:31:00 +0000726 }
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000727 else if (*ptr == ',')
Dave Chapman15ddd7a2008-03-23 20:31:00 +0000728 {
729 /* Parse the (optional) number of sub-images */
730 ptr++;
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000731 img->num_subimages = atoi(ptr);
Jonathan Gordon18a8e522009-08-16 18:23:00 +0000732 if (img->num_subimages <= 0)
Dave Chapman6d9c3532008-03-24 10:13:47 +0000733 return WPS_ERROR_INVALID_PARAM;
Dave Chapman15ddd7a2008-03-23 20:31:00 +0000734 }
Jonathan Gordon58ca43d2009-12-03 05:36:23 +0000735 struct skin_token_list *item = new_skin_token_list_item(NULL, img);
736 if (!item)
737 return WPS_ERROR_INVALID_PARAM;
738 add_to_ll_chain(&wps_data->images, item);
Nicolas Pennequin27cbf6b2007-04-12 16:15:34 +0000739
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000740 /* Skip the rest of the line */
Nicolas Pennequin9cf89602007-04-05 14:09:59 +0000741 return skip_end_of_line(wps_bufptr);
Nicolas Pennequinab90d582007-04-04 14:41:40 +0000742}
Jonathan Gordon8717c1e2010-02-28 08:36:13 +0000743struct skin_font {
744 int id; /* the id from font_load */
745 char *name; /* filename without path and extension */
746};
747static struct skin_font skinfonts[MAXUSERFONTS];
Jonathan Gordon1c2aa352010-02-14 06:26:16 +0000748static int parse_font_load(const char *wps_bufptr,
749 struct wps_token *token, struct wps_data *wps_data)
750{
751 (void)wps_data; (void)token;
752 const char *ptr = wps_bufptr;
753 int id;
Thomas Martitz22630862010-02-27 16:51:51 +0000754 char *filename;
Jonathan Gordon1c2aa352010-02-14 06:26:16 +0000755
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000756 if (*ptr != '(')
Jonathan Gordon1c2aa352010-02-14 06:26:16 +0000757 return WPS_ERROR_INVALID_PARAM;
758
759 ptr++;
760
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000761 if (!(ptr = parse_list("ds", NULL, ',', ptr, &id, &filename)))
Jonathan Gordon1c2aa352010-02-14 06:26:16 +0000762 return WPS_ERROR_INVALID_PARAM;
763
764 /* Check there is a terminating | */
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000765 if (*ptr != ')')
Jonathan Gordon1c2aa352010-02-14 06:26:16 +0000766 return WPS_ERROR_INVALID_PARAM;
767
768 if (id <= FONT_UI || id >= MAXFONTS-1)
769 return WPS_ERROR_INVALID_PARAM;
Jonathan Gordon8717c1e2010-02-28 08:36:13 +0000770#if defined(DEBUG) || defined(SIMULATOR)
771 if (skinfonts[id-FONT_FIRSTUSERFONT].name != NULL)
772 {
773 DEBUGF("font id %d already being used\n", id);
774 }
775#endif
Jonathan Gordon25d97712010-03-03 05:43:02 +0000776 /* make sure the filename contains .fnt,
777 * we dont actually use it, but require it anyway */
778 ptr = strchr(filename, '.');
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000779 if (!ptr || strncmp(ptr, ".fnt)", 5))
Jonathan Gordon25d97712010-03-03 05:43:02 +0000780 return WPS_ERROR_INVALID_PARAM;
Jonathan Gordon8717c1e2010-02-28 08:36:13 +0000781 skinfonts[id-FONT_FIRSTUSERFONT].id = -1;
782 skinfonts[id-FONT_FIRSTUSERFONT].name = filename;
783
Thomas Martitz22630862010-02-27 16:51:51 +0000784 return skip_end_of_line(wps_bufptr);
Jonathan Gordon1c2aa352010-02-14 06:26:16 +0000785}
786
787
Jonathan Gordon5a169bb2008-06-23 06:04:17 +0000788static int parse_viewport_display(const char *wps_bufptr,
789 struct wps_token *token,
790 struct wps_data *wps_data)
791{
792 (void)wps_data;
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000793 char letter = wps_bufptr[1];
Jonathan Gordon5a169bb2008-06-23 06:04:17 +0000794
795 if (letter < 'a' || letter > 'z')
796 {
797 /* invalid viewport tag */
798 return WPS_ERROR_INVALID_PARAM;
799 }
800 token->value.i = letter;
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000801 return 3;
Jonathan Gordon5a169bb2008-06-23 06:04:17 +0000802}
803
Jonathan Gordondc0ba912010-01-13 06:02:38 +0000804#ifdef HAVE_LCD_BITMAP
Jonathan Gordona1b97082010-01-13 07:47:53 +0000805static int parse_playlistview_text(struct playlistviewer *viewer,
Jonathan Gordondc0ba912010-01-13 06:02:38 +0000806 enum info_line_type line, char* text)
807{
808 int cur_string = 0;
809 const struct wps_tag *tag;
810 int taglen = 0;
811 const char *start = text;
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000812 if (*text != ',')
Jonathan Gordondc0ba912010-01-13 06:02:38 +0000813 return -1;
814 text++;
815 viewer->lines[line].count = 0;
816 viewer->lines[line].scroll = false;
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000817 while (*text != ',' && *text != ')')
Jonathan Gordondc0ba912010-01-13 06:02:38 +0000818 {
819 if (*text == '%') /* it is a token of some type */
820 {
821 text++;
822 taglen = 0;
823 switch(*text)
824 {
825 case '%':
826 case '<':
827 case '|':
828 case '>':
829 case ';':
830 case '#':
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000831 case '(':
832 case ')':
833 case ',':
Jonathan Gordondc0ba912010-01-13 06:02:38 +0000834 /* escaped characters */
835 viewer->lines[line].tokens[viewer->lines[line].count++] = WPS_TOKEN_CHARACTER;
836 viewer->lines[line].strings[cur_string][0] = *text;
Jonathan Gordona1b97082010-01-13 07:47:53 +0000837 viewer->lines[line].strings[cur_string++][1] = '\0';
Jonathan Gordon69710e52010-04-17 12:45:52 +0000838 text++;
Jonathan Gordondc0ba912010-01-13 06:02:38 +0000839 break;
840 default:
841 for (tag = all_tags;
842 strncmp(text, tag->name, strlen(tag->name)) != 0;
843 tag++) ;
844 /* %s isnt stored as a tag so manually check for it */
845 if (tag->type == WPS_NO_TOKEN)
846 {
847 if (!strncmp(tag->name, "s", 1))
848 {
849 viewer->lines[line].scroll = true;
850 taglen = 1;
851 }
852 }
853 else if (tag->type == WPS_TOKEN_UNKNOWN)
854 {
855 int i = 0;
856 /* just copy the string */
857 viewer->lines[line].tokens[viewer->lines[line].count++] = WPS_TOKEN_STRING;
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000858 while (i<(MAX_PLAYLISTLINE_STRLEN-1) && text[i] != ',' && text[i] != ')' && text[i] != '%')
Jonathan Gordondc0ba912010-01-13 06:02:38 +0000859 {
860 viewer->lines[line].strings[cur_string][i] = text[i];
861 i++;
862 }
863 viewer->lines[line].strings[cur_string][i] = '\0';
864 cur_string++;
865 taglen = i;
866 }
867 else
Teruaki Kawashima1fbdd912010-03-06 14:14:44 +0000868 {
Jonathan Gordon51630cb2010-01-15 01:26:57 +0000869 if (tag->parse_func)
870 {
871 /* unsupported tag, reject */
872 return -1;
Teruaki Kawashima1fbdd912010-03-06 14:14:44 +0000873 }
Jonathan Gordondc0ba912010-01-13 06:02:38 +0000874 taglen = strlen(tag->name);
875 viewer->lines[line].tokens[viewer->lines[line].count++] = tag->type;
876 }
877 text += taglen;
878 }
879 }
880 else
881 {
882 /* regular string */
883 int i = 0;
884 /* just copy the string */
885 viewer->lines[line].tokens[viewer->lines[line].count++] = WPS_TOKEN_STRING;
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000886 while (i<(MAX_PLAYLISTLINE_STRLEN-1) && text[i] != ',' && text[i] != ')' && text[i] != '%')
Jonathan Gordondc0ba912010-01-13 06:02:38 +0000887 {
888 viewer->lines[line].strings[cur_string][i] = text[i];
889 i++;
890 }
891 viewer->lines[line].strings[cur_string][i] = '\0';
892 cur_string++;
893 text += i;
894 }
895 }
896 return text - start;
897}
Teruaki Kawashima1fbdd912010-03-06 14:14:44 +0000898
Jonathan Gordondc0ba912010-01-13 06:02:38 +0000899static int parse_playlistview(const char *wps_bufptr,
900 struct wps_token *token, struct wps_data *wps_data)
901{
902 (void)wps_data;
903 /* %Vp|<use icons>|<start offset>|info line text|no info text| */
904 struct playlistviewer *viewer = skin_buffer_alloc(sizeof(struct playlistviewer));
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000905 char *ptr = strchr(wps_bufptr, '(');
Jonathan Gordondc0ba912010-01-13 06:02:38 +0000906 int length;
907 if (!viewer || !ptr)
908 return WPS_ERROR_INVALID_PARAM;
909 viewer->vp = &curr_vp->vp;
910 viewer->show_icons = true;
911 viewer->start_offset = atoi(ptr+1);
912 token->value.data = (void*)viewer;
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000913 ptr = strchr(ptr+1, ',');
Teruaki Kawashima1fbdd912010-03-06 14:14:44 +0000914 length = parse_playlistview_text(viewer, TRACK_HAS_INFO, ptr);
Jonathan Gordondc0ba912010-01-13 06:02:38 +0000915 if (length < 0)
916 return WPS_ERROR_INVALID_PARAM;
Teruaki Kawashima1fbdd912010-03-06 14:14:44 +0000917 length = parse_playlistview_text(viewer, TRACK_HAS_NO_INFO, ptr+length);
Jonathan Gordondc0ba912010-01-13 06:02:38 +0000918 if (length < 0)
919 return WPS_ERROR_INVALID_PARAM;
920
921 return skip_end_of_line(wps_bufptr);
922}
923#endif
924
Dave Chapmand02c79c2008-03-21 19:38:00 +0000925static int parse_viewport(const char *wps_bufptr,
926 struct wps_token *token,
927 struct wps_data *wps_data)
928{
Jonathan Gordonf002b7d2008-06-05 08:20:39 +0000929 (void)token; /* Kill warnings */
Dave Chapmand02c79c2008-03-21 19:38:00 +0000930 const char *ptr = wps_bufptr;
Thomas Martitz9bd7b232009-08-09 16:16:55 +0000931
Jonathan Gordon36ca4962009-08-18 05:30:59 +0000932 struct skin_viewport *skin_vp = skin_buffer_alloc(sizeof(struct skin_viewport));
Thomas Martitz541dd6f2009-09-13 12:24:14 +0000933
Jonathan Gordon5a169bb2008-06-23 06:04:17 +0000934 /* check for the optional letter to signify its a hideable viewport */
935 /* %Vl|<label>|<rest of tags>| */
Jonathan Gordon36ca4962009-08-18 05:30:59 +0000936 skin_vp->hidden_flags = 0;
937 skin_vp->label = VP_NO_LABEL;
Jonathan Gordon8cb74432009-09-02 02:55:33 +0000938 skin_vp->lines = NULL;
Jonathan Gordond466cb92009-09-04 06:17:38 +0000939 if (curr_line)
Thomas Martitz894c8092009-09-13 12:15:08 +0000940 {
941 curr_line->curr_subline->last_token_idx = wps_data->num_tokens
942 - (wps_data->num_tokens > 0 ? 1 : 0);
943 }
944
Jonathan Gordon8cb74432009-09-02 02:55:33 +0000945 curr_line = NULL;
Jonathan Gordon8f76e7f2009-09-02 06:23:01 +0000946 if (!skin_start_new_line(skin_vp, wps_data->num_tokens))
Jonathan Gordon8cb74432009-09-02 02:55:33 +0000947 return WPS_ERROR_INVALID_PARAM;
Teruaki Kawashima1fbdd912010-03-06 14:14:44 +0000948
Thomas Martitz1016ee42009-10-19 15:28:15 +0000949 if (*ptr == 'i')
950 {
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000951 if (*(ptr+1) == '(')
Jonathan Gordonefd1f4e2010-05-05 13:48:50 +0000952 {
953 char label = *(ptr+2);
954 if (label >= 'a' && label <= 'z')
955 {
956 skin_vp->hidden_flags = VP_NEVER_VISIBLE;
957 skin_vp->label = VP_INFO_LABEL|label;
958 ptr += 3;
959 }
960 else
961 {
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000962 if (label != '-')
963 return WPS_ERROR_INVALID_PARAM;
Jonathan Gordonefd1f4e2010-05-05 13:48:50 +0000964 skin_vp->label = VP_INFO_LABEL|VP_DEFAULT_LABEL;
965 skin_vp->hidden_flags = VP_NEVER_VISIBLE;
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000966 ptr += 3;
Jonathan Gordonefd1f4e2010-05-05 13:48:50 +0000967 }
968 }
969 else
970 return WPS_ERROR_INVALID_PARAM; /* malformed token: e.g. %Cl7 */
971
Thomas Martitz1016ee42009-10-19 15:28:15 +0000972 }
973 else if (*ptr == 'l')
Jonathan Gordon5a169bb2008-06-23 06:04:17 +0000974 {
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000975 if (*(ptr+1) == '(')
Jonathan Gordon5a169bb2008-06-23 06:04:17 +0000976 {
977 char label = *(ptr+2);
Jonathan Gordond8e56e32008-06-25 08:08:39 +0000978 if (label >= 'a' && label <= 'z')
Jonathan Gordon5a169bb2008-06-23 06:04:17 +0000979 {
Jonathan Gordon36ca4962009-08-18 05:30:59 +0000980 skin_vp->hidden_flags = VP_DRAW_HIDEABLE;
981 skin_vp->label = label;
Jonathan Gordon5a169bb2008-06-23 06:04:17 +0000982 }
983 else
984 return WPS_ERROR_INVALID_PARAM; /* malformed token: e.g. %Cl7 */
985 ptr += 3;
986 }
987 }
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000988 if (*ptr != ',' && *ptr != '(')
Jonathan Gordon5a169bb2008-06-23 06:04:17 +0000989 return WPS_ERROR_INVALID_PARAM;
Thomas Martitz541dd6f2009-09-13 12:24:14 +0000990
Jonathan Gordon5a169bb2008-06-23 06:04:17 +0000991 ptr++;
Jonathan Gordon36ca4962009-08-18 05:30:59 +0000992 struct viewport *vp = &skin_vp->vp;
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000993 /* format: %V|x|y|width|height|font| */
994 if (!(ptr = viewport_parse_viewport(vp, curr_screen, ptr, ',')))
Thomas Martitz9bd7b232009-08-09 16:16:55 +0000995 return WPS_ERROR_INVALID_PARAM;
Teruaki Kawashima1fbdd912010-03-06 14:14:44 +0000996
Jonathan Gordon5b0521c2010-06-07 03:44:11 +0000997 /* Check for trailing ) */
998 if (*ptr != ')')
Dave Chapman0bb2e052008-03-24 18:40:13 +0000999 return WPS_ERROR_INVALID_PARAM;
1000
Jonathan Gordon91e6b062010-01-07 07:34:15 +00001001 if (follow_lang_direction && lang_is_rtl())
1002 {
1003 vp->flags |= VP_FLAG_ALIGN_RIGHT;
1004 vp->x = screens[curr_screen].lcdwidth - vp->width - vp->x;
1005 }
1006 else
1007 vp->flags &= ~VP_FLAG_ALIGN_RIGHT; /* ignore right-to-left languages */
Jonathan Gordon5b0521c2010-06-07 03:44:11 +00001008
1009#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
1010 skin_vp->start_fgcolour = vp->fg_pattern;
1011 skin_vp->start_bgcolour = vp->bg_pattern;
1012#endif
Jonathan Gordon91e6b062010-01-07 07:34:15 +00001013
Jonathan Gordon36ca4962009-08-18 05:30:59 +00001014 struct skin_token_list *list = new_skin_token_list_item(NULL, skin_vp);
1015 if (!list)
1016 return WPS_ERROR_INVALID_PARAM;
1017 add_to_ll_chain(&wps_data->viewports, list);
Thomas Martitz541dd6f2009-09-13 12:24:14 +00001018 curr_vp = skin_vp;
Dave Chapmand02c79c2008-03-21 19:38:00 +00001019 /* Skip the rest of the line */
1020 return skip_end_of_line(wps_bufptr);
Dave Chapman45b2d882008-03-22 00:31:22 +00001021}
Björn Stenberg66459fe2008-12-08 08:32:30 +00001022#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
Jonathan Gordon5b0521c2010-06-07 03:44:11 +00001023static int parse_viewportcolour(const char *wps_bufptr,
1024 struct wps_token *token, struct wps_data *wps_data)
1025{
1026 (void)wps_data;
1027 const char *ptr = wps_bufptr;
1028 struct viewport_colour *colour = skin_buffer_alloc(sizeof(struct viewport_colour));
1029 int set;
1030 if (*ptr != '(' || !colour)
1031 return -1;
1032 ptr++;
1033 if (!(ptr = parse_list("c", &set, ',', ptr, &colour->colour)))
1034 return -1;
1035 if (*ptr != ')')
1036 return -1;
1037 if (!set)
1038 colour->colour = get_viewport_default_colour(curr_screen,
1039 token->type == WPS_TOKEN_VIEWPORT_FGCOLOUR);
1040 colour->vp = &curr_vp->vp;
1041 token->value.data = colour;
1042 ptr++;
1043 return ptr - wps_bufptr;
1044}
1045
Björn Stenberg66459fe2008-12-08 08:32:30 +00001046static int parse_image_special(const char *wps_bufptr,
1047 struct wps_token *token,
1048 struct wps_data *wps_data)
1049{
1050 (void)wps_data; /* kill warning */
1051 (void)token;
1052 const char *pos = NULL;
1053 const char *newline;
Jonathan Gordoneee54232010-01-29 07:52:13 +00001054 bool error = false;
Björn Stenberg66459fe2008-12-08 08:32:30 +00001055
Jonathan Gordon5b0521c2010-06-07 03:44:11 +00001056 pos = strchr(wps_bufptr + 1, ')');
Björn Stenberg66459fe2008-12-08 08:32:30 +00001057 newline = strchr(wps_bufptr, '\n');
Teruaki Kawashima1fbdd912010-03-06 14:14:44 +00001058
Jonathan Gordoneee54232010-01-29 07:52:13 +00001059 error = (pos > newline);
Björn Stenberg66459fe2008-12-08 08:32:30 +00001060
Björn Stenberg66459fe2008-12-08 08:32:30 +00001061#if LCD_DEPTH > 1
1062 if (token->type == WPS_TOKEN_IMAGE_BACKDROP)
1063 {
Jonathan Gordoneee54232010-01-29 07:52:13 +00001064 /* format: %X|filename.bmp| or %Xd */
Jonathan Gordon5b0521c2010-06-07 03:44:11 +00001065 if (*(wps_bufptr+1) == 'd')
Jonathan Gordoneee54232010-01-29 07:52:13 +00001066 {
1067 wps_data->backdrop = NULL;
1068 return skip_end_of_line(wps_bufptr);
1069 }
1070 else if (!error)
1071 wps_data->backdrop = (char*)wps_bufptr + 1;
Björn Stenberg66459fe2008-12-08 08:32:30 +00001072 }
1073#endif
Jonathan Gordoneee54232010-01-29 07:52:13 +00001074 if (error)
1075 return WPS_ERROR_INVALID_PARAM;
Björn Stenberg66459fe2008-12-08 08:32:30 +00001076 /* Skip the rest of the line */
1077 return skip_end_of_line(wps_bufptr);
1078}
1079#endif
1080
1081#endif /* HAVE_LCD_BITMAP */
1082
Jonathan Gordon340f3232009-09-26 00:58:32 +00001083static int parse_setting_and_lang(const char *wps_bufptr,
1084 struct wps_token *token,
1085 struct wps_data *wps_data)
Antoine Cellerier8289b962008-12-07 16:20:35 +00001086{
Jonathan Gordon340f3232009-09-26 00:58:32 +00001087 /* NOTE: both the string validations that happen in here will
1088 * automatically PASS on checkwps because its too hard to get
1089 * settings_list.c and englinsh.lang built for it.
1090 * If that ever changes remove the #ifndef __PCTOOL__'s here
1091 */
Antoine Cellerier8289b962008-12-07 16:20:35 +00001092 (void)wps_data;
1093 const char *ptr = wps_bufptr;
1094 const char *end;
Jonathan Gordon340f3232009-09-26 00:58:32 +00001095 int i = 0;
1096 char temp[64];
Antoine Cellerier8289b962008-12-07 16:20:35 +00001097
1098 /* Find the setting's cfg_name */
Jonathan Gordon5b0521c2010-06-07 03:44:11 +00001099 if (*ptr != '(')
Antoine Cellerier8289b962008-12-07 16:20:35 +00001100 return WPS_ERROR_INVALID_PARAM;
1101 ptr++;
Jonathan Gordon5b0521c2010-06-07 03:44:11 +00001102 end = strchr(ptr,')');
Teruaki Kawashima0a4eda42010-05-19 15:47:54 +00001103 if (!end || (size_t)(end-ptr+1) > sizeof temp)
Antoine Cellerier8289b962008-12-07 16:20:35 +00001104 return WPS_ERROR_INVALID_PARAM;
Jonathan Gordon340f3232009-09-26 00:58:32 +00001105 strlcpy(temp, ptr,end-ptr+1);
1106
1107 if (token->type == WPS_TOKEN_TRANSLATEDSTRING)
1108 {
1109#ifndef __PCTOOL__
1110 i = lang_english_to_id(temp);
1111 if (i < 0)
1112 return WPS_ERROR_INVALID_PARAM;
1113#endif
1114 }
1115 else
1116 {
1117 /* Find the setting */
1118 for (i=0; i<nb_settings; i++)
1119 if (settings[i].cfg_name &&
Teruaki Kawashima0a4eda42010-05-19 15:47:54 +00001120 !strcmp(settings[i].cfg_name, temp))
Jonathan Gordon340f3232009-09-26 00:58:32 +00001121 break;
1122#ifndef __PCTOOL__
1123 if (i == nb_settings)
1124 return WPS_ERROR_INVALID_PARAM;
1125#endif
1126 }
Antoine Cellerier8289b962008-12-07 16:20:35 +00001127 /* Store the setting number */
1128 token->value.i = i;
1129
1130 /* Skip the rest of the line */
1131 return end-ptr+2;
1132}
1133
Dave Chapmand02c79c2008-03-21 19:38:00 +00001134
Nicolas Pennequin07696c12007-04-08 04:01:06 +00001135static int parse_dir_level(const char *wps_bufptr,
1136 struct wps_token *token,
1137 struct wps_data *wps_data)
Nicolas Pennequinab90d582007-04-04 14:41:40 +00001138{
Jonathan Gordon5b0521c2010-06-07 03:44:11 +00001139 char val[] = { wps_bufptr[1], '\0' };
1140 if (wps_bufptr[0] != '(' || wps_bufptr[2] != ')')
1141 return WPS_ERROR_INVALID_PARAM;
Nicolas Pennequin07696c12007-04-08 04:01:06 +00001142 token->value.i = atoi(val);
1143 (void)wps_data; /* Kill warnings */
Jonathan Gordon5b0521c2010-06-07 03:44:11 +00001144 return 3;
Nicolas Pennequinab90d582007-04-04 14:41:40 +00001145}
1146
Jonathan Gordon85600e62008-10-11 12:20:09 +00001147static int parse_timeout(const char *wps_bufptr,
1148 struct wps_token *token,
1149 struct wps_data *wps_data)
Nicolas Pennequinab90d582007-04-04 14:41:40 +00001150{
1151 int skip = 0;
1152 int val = 0;
1153 bool have_point = false;
1154 bool have_tenth = false;
1155
Nicolas Pennequin07696c12007-04-08 04:01:06 +00001156 (void)wps_data; /* Kill the warning */
Jonathan Gordon5b0521c2010-06-07 03:44:11 +00001157 if (*wps_bufptr == '(')
Nicolas Pennequinab90d582007-04-04 14:41:40 +00001158 {
Jonathan Gordon5b0521c2010-06-07 03:44:11 +00001159 while ( isdigit(*wps_bufptr) || *wps_bufptr == '.' )
Nicolas Pennequinab90d582007-04-04 14:41:40 +00001160 {
Jonathan Gordon5b0521c2010-06-07 03:44:11 +00001161 if (*wps_bufptr != '.')
Nicolas Pennequinab90d582007-04-04 14:41:40 +00001162 {
Jonathan Gordon5b0521c2010-06-07 03:44:11 +00001163 val *= 10;
1164 val += *wps_bufptr - '0';
1165 if (have_point)
1166 {
1167 have_tenth = true;
1168 wps_bufptr++;
1169 skip++;
1170 break;
1171 }
Nicolas Pennequinab90d582007-04-04 14:41:40 +00001172 }
Jonathan Gordon5b0521c2010-06-07 03:44:11 +00001173 else
1174 have_point = true;
1175
1176 wps_bufptr++;
1177 skip++;
Nicolas Pennequinab90d582007-04-04 14:41:40 +00001178 }
Jonathan Gordon5b0521c2010-06-07 03:44:11 +00001179 if (*wps_bufptr != ')')
1180 return -1;
Nicolas Pennequinab90d582007-04-04 14:41:40 +00001181 }
Nicolas Pennequinab90d582007-04-04 14:41:40 +00001182 if (have_tenth == false)
1183 val *= 10;
1184
Jonathan Gordon61c65262008-10-11 13:49:38 +00001185 if (val == 0 && skip == 0)
1186 {
1187 /* decide what to do if no value was specified */
1188 switch (token->type)
1189 {
1190 case WPS_TOKEN_SUBLINE_TIMEOUT:
1191 return -1;
1192 case WPS_TOKEN_BUTTON_VOLUME:
Jonathan Gordond2e2c2a2010-03-18 07:08:49 +00001193 case WPS_TOKEN_TRACK_STARTING:
1194 case WPS_TOKEN_TRACK_ENDING:
Jonathan Gordon0394ebe2008-11-22 10:31:33 +00001195 val = 10;
Jonathan Gordon61c65262008-10-11 13:49:38 +00001196 break;
1197 }
1198 }
Nicolas Pennequin07696c12007-04-08 04:01:06 +00001199 token->value.i = val;
Nicolas Pennequin3954a512007-04-06 14:18:07 +00001200
Nicolas Pennequinab90d582007-04-04 14:41:40 +00001201 return skip;
1202}
Jonathan Gordon44217462010-04-11 11:18:45 +00001203
Nicolas Pennequin07696c12007-04-08 04:01:06 +00001204static int parse_progressbar(const char *wps_bufptr,
1205 struct wps_token *token,
1206 struct wps_data *wps_data)
Nicolas Pennequinab90d582007-04-04 14:41:40 +00001207{
Jonathan Gordon5a169bb2008-06-23 06:04:17 +00001208 /* %pb or %pb|filename|x|y|width|height|
1209 using - for any of the params uses "sane" values */
Nicolas Pennequinab90d582007-04-04 14:41:40 +00001210#ifdef HAVE_LCD_BITMAP
Jonathan Gordon5a169bb2008-06-23 06:04:17 +00001211 enum {
1212 PB_FILENAME = 0,
1213 PB_X,
1214 PB_Y,
1215 PB_WIDTH,
1216 PB_HEIGHT
1217 };
1218 const char *filename;
Jonathan Gordon082f50b2008-06-23 06:17:22 +00001219 int x, y, height, width;
1220 uint32_t set = 0;
Jonathan Gordon5a169bb2008-06-23 06:04:17 +00001221 const char *ptr = wps_bufptr;
Jonathan Gordon18a8e522009-08-16 18:23:00 +00001222 struct progressbar *pb = skin_buffer_alloc(sizeof(struct progressbar));
1223 struct skin_token_list *item = new_skin_token_list_item(token, pb);
Thomas Martitz541dd6f2009-09-13 12:24:14 +00001224
Jonathan Gordon58ca43d2009-12-03 05:36:23 +00001225 if (!pb || !item)
1226 return WPS_ERROR_INVALID_PARAM;
Thomas Martitz541dd6f2009-09-13 12:24:14 +00001227
Jonathan Gordon36ca4962009-08-18 05:30:59 +00001228 struct viewport *vp = &curr_vp->vp;
Jonathan Gordon8cb74432009-09-02 02:55:33 +00001229 /* we need to know what line number (viewport relative) this pb is,
1230 * so count them... */
1231 int line_num = -1;
Jonathan Gordon8f76e7f2009-09-02 06:23:01 +00001232 struct skin_line *line = curr_vp->lines;
Jonathan Gordon8cb74432009-09-02 02:55:33 +00001233 while (line)
1234 {
1235 line_num++;
1236 line = line->next;
1237 }
Jonathan Gordon44217462010-04-11 11:18:45 +00001238 pb->vp = vp;
Jonathan Gordon5a169bb2008-06-23 06:04:17 +00001239 pb->have_bitmap_pb = false;
Jonathan Gordon58ca43d2009-12-03 05:36:23 +00001240 pb->bm.data = NULL; /* no bitmap specified */
Jonathan Gordon91e6b062010-01-07 07:34:15 +00001241 pb->follow_lang_direction = follow_lang_direction > 0;
Jonathan Gordon58a03932010-04-19 08:43:42 +00001242 pb->draw = false;
Thomas Martitz541dd6f2009-09-13 12:24:14 +00001243
Jonathan Gordon5b0521c2010-06-07 03:44:11 +00001244 if (*wps_bufptr != '(') /* regular old style */
Jonathan Gordon5a169bb2008-06-23 06:04:17 +00001245 {
1246 pb->x = 0;
1247 pb->width = vp->width;
1248 pb->height = SYSFONT_HEIGHT-2;
Thomas Martitz54c2f492009-02-16 08:28:51 +00001249 pb->y = -line_num - 1; /* Will be computed during the rendering */
Jonathan Gordon4c65a192010-04-25 11:32:51 +00001250 if (token->type == WPS_TOKEN_VOLUME || token->type == WPS_TOKEN_BATTERY_PERCENT)
Jonathan Gordon44217462010-04-11 11:18:45 +00001251 return 0; /* dont add it, let the regular token handling do the work */
Jonathan Gordon22b12ca2010-05-31 11:12:15 +00001252 pb->type = token->type;
Jonathan Gordon18a8e522009-08-16 18:23:00 +00001253 add_to_ll_chain(&wps_data->progressbars, item);
Jonathan Gordon5a169bb2008-06-23 06:04:17 +00001254 return 0;
Nicolas Pennequinab90d582007-04-04 14:41:40 +00001255 }
Jonathan Gordon5a169bb2008-06-23 06:04:17 +00001256 ptr = wps_bufptr + 1;
Thomas Martitz541dd6f2009-09-13 12:24:14 +00001257
Jonathan Gordon5b0521c2010-06-07 03:44:11 +00001258 if (!(ptr = parse_list("sdddd", &set, ',', ptr, &filename,
Jonathan Gordon5a169bb2008-06-23 06:04:17 +00001259 &x, &y, &width, &height)))
Jonathan Gordon58a03932010-04-19 08:43:42 +00001260 {
Alexander Levin847a0fd2010-04-21 19:59:49 +00001261 /* If we are in a conditional then we probably don't want to fail
1262 * if the above doesnt work. So assume the | is breaking the conditional
1263 * and move on. The next token will fail if this is incorrect. */
Jonathan Gordon34cd2c32010-04-20 07:17:59 +00001264 if (level >= 0)
Jonathan Gordon58a03932010-04-19 08:43:42 +00001265 return 0;
Jonathan Gordon5a169bb2008-06-23 06:04:17 +00001266 return WPS_ERROR_INVALID_PARAM;
Jonathan Gordon58a03932010-04-19 08:43:42 +00001267 }
Dave Chapmana42602b2008-10-22 21:35:38 +00001268
Jonathan Gordon5a169bb2008-06-23 06:04:17 +00001269 if (LIST_VALUE_PARSED(set, PB_FILENAME)) /* filename */
Jonathan Gordon18a8e522009-08-16 18:23:00 +00001270 pb->bm.data = (char*)filename;
Dave Chapmana42602b2008-10-22 21:35:38 +00001271
Jonathan Gordon5a169bb2008-06-23 06:04:17 +00001272 if (LIST_VALUE_PARSED(set, PB_X)) /* x */
1273 pb->x = x;
1274 else
1275 pb->x = vp->x;
Dave Chapmana42602b2008-10-22 21:35:38 +00001276
Jonathan Gordon5a169bb2008-06-23 06:04:17 +00001277 if (LIST_VALUE_PARSED(set, PB_WIDTH)) /* width */
Dave Chapmana42602b2008-10-22 21:35:38 +00001278 {
1279 /* A zero width causes a divide-by-zero error later, so reject it */
1280 if (width == 0)
1281 return WPS_ERROR_INVALID_PARAM;
1282
Jonathan Gordon5a169bb2008-06-23 06:04:17 +00001283 pb->width = width;
Dave Chapmana42602b2008-10-22 21:35:38 +00001284 }
Jonathan Gordon5a169bb2008-06-23 06:04:17 +00001285 else
1286 pb->width = vp->width - pb->x;
Dave Chapmana42602b2008-10-22 21:35:38 +00001287
Jonathan Gordon5a169bb2008-06-23 06:04:17 +00001288 if (LIST_VALUE_PARSED(set, PB_HEIGHT)) /* height, default to font height */
Dave Chapmana42602b2008-10-22 21:35:38 +00001289 {
1290 /* A zero height makes no sense - reject it */
1291 if (height == 0)
1292 return WPS_ERROR_INVALID_PARAM;
1293
Jonathan Gordon5a169bb2008-06-23 06:04:17 +00001294 pb->height = height;
Dave Chapmana42602b2008-10-22 21:35:38 +00001295 }
Jonathan Gordon5a169bb2008-06-23 06:04:17 +00001296 else
Jonathan Gordon04e0d6c2010-03-02 08:47:45 +00001297 {
1298 if (vp->font > FONT_UI)
1299 pb->height = -1; /* calculate at display time */
1300 else
1301 {
1302#ifndef __PCTOOL__
1303 pb->height = font_get(vp->font)->height;
1304#else
1305 pb->height = 8;
1306#endif
1307 }
1308 }
Dave Chapmana42602b2008-10-22 21:35:38 +00001309
Jonathan Gordon5a169bb2008-06-23 06:04:17 +00001310 if (LIST_VALUE_PARSED(set, PB_Y)) /* y */
1311 pb->y = y;
1312 else
Thomas Martitz54c2f492009-02-16 08:28:51 +00001313 pb->y = -line_num - 1; /* Will be computed during the rendering */
Dave Chapmana42602b2008-10-22 21:35:38 +00001314
Jonathan Gordon18a8e522009-08-16 18:23:00 +00001315 add_to_ll_chain(&wps_data->progressbars, item);
Jonathan Gordon44217462010-04-11 11:18:45 +00001316 if (token->type == WPS_TOKEN_VOLUME)
1317 token->type = WPS_TOKEN_VOLUMEBAR;
Jonathan Gordon4c65a192010-04-25 11:32:51 +00001318 else if (token->type == WPS_TOKEN_BATTERY_PERCENT)
1319 token->type = WPS_TOKEN_BATTERY_PERCENTBAR;
Jonathan Gordon44217462010-04-11 11:18:45 +00001320 pb->type = token->type;
Jonathan Gordon99a22992010-04-13 07:32:00 +00001321
1322 return ptr+1-wps_bufptr;
Nicolas Pennequinab90d582007-04-04 14:41:40 +00001323#else
Jonathan Gordona1c0d552010-04-11 11:40:47 +00001324 (void)wps_bufptr;
Jonathan Gordon4c65a192010-04-25 11:32:51 +00001325 if (token->type != WPS_TOKEN_VOLUME &&
1326 token->type != WPS_TOKEN_BATTERY_PERCENTBAR)
Jonathan Gordon44217462010-04-11 11:18:45 +00001327 {
1328 wps_data->full_line_progressbar =
1329 token->type == WPS_TOKEN_PLAYER_PROGRESSBAR;
1330 }
Nicolas Pennequinab90d582007-04-04 14:41:40 +00001331 return 0;
1332
1333#endif
1334}
1335
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001336#ifdef HAVE_ALBUMART
Tomer Shaleve15a0c92009-12-29 18:14:31 +00001337static int parse_int(const char *newline, const char **_pos, int *num)
1338{
Jonathan Gordon5b0521c2010-06-07 03:44:11 +00001339 *_pos = parse_list("d", NULL, ',', *_pos, num);
1340 return (!*_pos || *_pos > newline || (**_pos != ',' && **_pos != ')'));
Tomer Shaleve15a0c92009-12-29 18:14:31 +00001341}
1342
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001343static int parse_albumart_load(const char *wps_bufptr,
1344 struct wps_token *token,
1345 struct wps_data *wps_data)
1346{
Nicolas Pennequin31f76112007-11-14 22:02:41 +00001347 const char *_pos, *newline;
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001348 bool parsing;
Thomas Martitze9c10182009-10-16 19:14:41 +00001349 struct dim dimensions;
1350 int albumart_slot;
Jonathan Gordon91e6b062010-01-07 07:34:15 +00001351 bool swap_for_rtl = lang_is_rtl() && follow_lang_direction;
Jonathan Gordonfe2f0422009-09-07 02:36:56 +00001352 struct skin_albumart *aa = skin_buffer_alloc(sizeof(struct skin_albumart));
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001353 (void)token; /* silence warning */
Jonathan Gordonfe2f0422009-09-07 02:36:56 +00001354 if (!aa)
1355 return skip_end_of_line(wps_bufptr);
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001356
1357 /* reset albumart info in wps */
Thomas Martitzba8fbb02009-09-25 18:36:28 +00001358 aa->width = -1;
1359 aa->height = -1;
1360 aa->xalign = WPS_ALBUMART_ALIGN_CENTER; /* default */
1361 aa->yalign = WPS_ALBUMART_ALIGN_CENTER; /* default */
Jonathan Gordonfe2f0422009-09-07 02:36:56 +00001362 aa->vp = &curr_vp->vp;
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001363
Andrew Mahone781421a2008-12-09 23:07:59 +00001364 /* format: %Cl|x|y|[[l|c|r]mwidth]|[[t|c|b]mheight]| */
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001365
Nicolas Pennequin31f76112007-11-14 22:02:41 +00001366 newline = strchr(wps_bufptr, '\n');
1367
Tomer Shaleve15a0c92009-12-29 18:14:31 +00001368 _pos = wps_bufptr;
1369
Jonathan Gordon5b0521c2010-06-07 03:44:11 +00001370 if (*_pos != '(')
Nicolas Pennequin31f76112007-11-14 22:02:41 +00001371 return WPS_ERROR_INVALID_PARAM; /* malformed token: e.g. %Cl7 */
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001372
Tomer Shaleve15a0c92009-12-29 18:14:31 +00001373 ++_pos;
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001374
Tomer Shaleve15a0c92009-12-29 18:14:31 +00001375 /* initial validation and parsing of x component */
1376 if (parse_int(newline, &_pos, &aa->x))
1377 return WPS_ERROR_INVALID_PARAM;
1378
1379 ++_pos;
1380
1381 /* initial validation and parsing of y component */
1382 if (parse_int(newline, &_pos, &aa->y))
1383 return WPS_ERROR_INVALID_PARAM;
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001384
1385 /* parsing width field */
1386 parsing = true;
1387 while (parsing)
1388 {
1389 /* apply each modifier in turn */
1390 ++_pos;
1391 switch (*_pos)
1392 {
1393 case 'l':
1394 case 'L':
1395 case '+':
Jonathan Gordon91e6b062010-01-07 07:34:15 +00001396 if (swap_for_rtl)
1397 aa->xalign = WPS_ALBUMART_ALIGN_RIGHT;
1398 else
1399 aa->xalign = WPS_ALBUMART_ALIGN_LEFT;
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001400 break;
1401 case 'c':
1402 case 'C':
Thomas Martitzba8fbb02009-09-25 18:36:28 +00001403 aa->xalign = WPS_ALBUMART_ALIGN_CENTER;
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001404 break;
1405 case 'r':
1406 case 'R':
1407 case '-':
Jonathan Gordon91e6b062010-01-07 07:34:15 +00001408 if (swap_for_rtl)
1409 aa->xalign = WPS_ALBUMART_ALIGN_LEFT;
1410 else
1411 aa->xalign = WPS_ALBUMART_ALIGN_RIGHT;
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001412 break;
1413 case 'd':
1414 case 'D':
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001415 case 'i':
1416 case 'I':
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001417 case 's':
1418 case 'S':
Andrew Mahone781421a2008-12-09 23:07:59 +00001419 /* simply ignored */
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001420 break;
1421 default:
1422 parsing = false;
1423 break;
1424 }
1425 }
1426 /* extract max width data */
Jonathan Gordon5b0521c2010-06-07 03:44:11 +00001427 if (*_pos != ',')
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001428 {
Tomer Shaleve15a0c92009-12-29 18:14:31 +00001429 if (parse_int(newline, &_pos, &aa->width))
Nicolas Pennequin31f76112007-11-14 22:02:41 +00001430 return WPS_ERROR_INVALID_PARAM;
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001431 }
1432
1433 /* parsing height field */
1434 parsing = true;
1435 while (parsing)
1436 {
1437 /* apply each modifier in turn */
1438 ++_pos;
1439 switch (*_pos)
1440 {
1441 case 't':
1442 case 'T':
1443 case '-':
Thomas Martitzba8fbb02009-09-25 18:36:28 +00001444 aa->yalign = WPS_ALBUMART_ALIGN_TOP;
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001445 break;
1446 case 'c':
1447 case 'C':
Thomas Martitzba8fbb02009-09-25 18:36:28 +00001448 aa->yalign = WPS_ALBUMART_ALIGN_CENTER;
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001449 break;
1450 case 'b':
1451 case 'B':
1452 case '+':
Thomas Martitzba8fbb02009-09-25 18:36:28 +00001453 aa->yalign = WPS_ALBUMART_ALIGN_BOTTOM;
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001454 break;
1455 case 'd':
1456 case 'D':
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001457 case 'i':
1458 case 'I':
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001459 case 's':
1460 case 'S':
Andrew Mahone781421a2008-12-09 23:07:59 +00001461 /* simply ignored */
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001462 break;
1463 default:
1464 parsing = false;
1465 break;
1466 }
1467 }
1468 /* extract max height data */
Jonathan Gordon5b0521c2010-06-07 03:44:11 +00001469 if (*_pos != ',')
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001470 {
Tomer Shaleve15a0c92009-12-29 18:14:31 +00001471 if (parse_int(newline, &_pos, &aa->height))
Tomer Shalev8db32dd2009-12-04 13:10:06 +00001472 return WPS_ERROR_INVALID_PARAM;
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001473 }
1474
1475 /* if we got here, we parsed everything ok .. ! */
Thomas Martitzba8fbb02009-09-25 18:36:28 +00001476 if (aa->width < 0)
1477 aa->width = 0;
1478 else if (aa->width > LCD_WIDTH)
1479 aa->width = LCD_WIDTH;
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001480
Thomas Martitzba8fbb02009-09-25 18:36:28 +00001481 if (aa->height < 0)
1482 aa->height = 0;
1483 else if (aa->height > LCD_HEIGHT)
1484 aa->height = LCD_HEIGHT;
Teruaki Kawashima1fbdd912010-03-06 14:14:44 +00001485
Jonathan Gordon91e6b062010-01-07 07:34:15 +00001486 if (swap_for_rtl)
1487 aa->x = LCD_WIDTH - (aa->x + aa->width);
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001488
Thomas Martitzba8fbb02009-09-25 18:36:28 +00001489 aa->state = WPS_ALBUMART_LOAD;
Jonathan Gordonfe2f0422009-09-07 02:36:56 +00001490 aa->draw = false;
1491 wps_data->albumart = aa;
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001492
Thomas Martitze9c10182009-10-16 19:14:41 +00001493 dimensions.width = aa->width;
1494 dimensions.height = aa->height;
1495
1496 albumart_slot = playback_claim_aa_slot(&dimensions);
1497
Tomer Shalev8db32dd2009-12-04 13:10:06 +00001498 if (0 <= albumart_slot)
Thomas Martitze9c10182009-10-16 19:14:41 +00001499 wps_data->playback_aa_slot = albumart_slot;
1500
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001501 /* Skip the rest of the line */
1502 return skip_end_of_line(wps_bufptr);
1503}
1504
Jonathan Gordonfe2f0422009-09-07 02:36:56 +00001505static int parse_albumart_display(const char *wps_bufptr,
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001506 struct wps_token *token,
1507 struct wps_data *wps_data)
1508{
Jonathan Gordonfe2f0422009-09-07 02:36:56 +00001509 (void)wps_bufptr;
Jonathan Gordon05fd9ee2009-09-18 05:45:15 +00001510 struct wps_token *prev = token-1;
Jonathan Gordonf06c98f2009-10-05 10:26:06 +00001511 if ((wps_data->num_tokens >= 1) && (prev->type == WPS_TOKEN_CONDITIONAL))
Jonathan Gordonaafeaad2009-09-18 05:15:18 +00001512 {
Jonathan Gordon05fd9ee2009-09-18 05:45:15 +00001513 token->type = WPS_TOKEN_ALBUMART_FOUND;
Jonathan Gordonaafeaad2009-09-18 05:15:18 +00001514 }
1515 else if (wps_data->albumart)
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001516 {
Jonathan Gordonfe2f0422009-09-07 02:36:56 +00001517 wps_data->albumart->vp = &curr_vp->vp;
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001518 }
Jonathan Gordonfe2f0422009-09-07 02:36:56 +00001519#if 0
1520 /* the old code did this so keep it here for now...
1521 * this is to allow the posibility to showing the next tracks AA! */
1522 if (wps_bufptr+1 == 'n')
1523 return 1;
1524#endif
1525 return 0;
Nicolas Pennequin9d4bed72007-11-11 12:29:37 +00001526};
1527#endif /* HAVE_ALBUMART */
1528
Jonathan Gordon0eb5dc62009-04-20 01:41:56 +00001529#ifdef HAVE_TOUCHSCREEN
Thomas Martitz541dd6f2009-09-13 12:24:14 +00001530
Bertrik Sikken0201a192009-12-20 18:04:07 +00001531struct touchaction {const char* s; int action;};
1532static const struct touchaction touchactions[] = {
Jonathan Gordon0eb5dc62009-04-20 01:41:56 +00001533 {"play", ACTION_WPS_PLAY }, {"stop", ACTION_WPS_STOP },
1534 {"prev", ACTION_WPS_SKIPPREV }, {"next", ACTION_WPS_SKIPNEXT },
Jonathan Gordon2172c912009-05-17 06:25:18 +00001535 {"ffwd", ACTION_WPS_SEEKFWD }, {"rwd", ACTION_WPS_SEEKBACK },
Jonathan Gordonc1267dc2009-05-15 05:36:16 +00001536 {"menu", ACTION_WPS_MENU }, {"browse", ACTION_WPS_BROWSE },
Jonathan Gordon13cc6542009-05-15 06:02:50 +00001537 {"shuffle", ACTION_TOUCH_SHUFFLE }, {"repmode", ACTION_TOUCH_REPMODE },
1538 {"quickscreen", ACTION_WPS_QUICKSCREEN },{"contextmenu", ACTION_WPS_CONTEXT },
Maurus Cuelenaere8d013f52009-08-17 12:46:21 +00001539 {"playlist", ACTION_WPS_VIEW_PLAYLIST }, {"pitch", ACTION_WPS_PITCHSCREEN},
Rob Purchase24c1c752009-11-02 21:56:48 +00001540 {"voldown", ACTION_WPS_VOLDOWN}, {"volup", ACTION_WPS_VOLUP},
Jonathan Gordon0eb5dc62009-04-20 01:41:56 +00001541};
1542static int parse_touchregion(const char *wps_bufptr,
1543 struct wps_token *token, struct wps_data *wps_data)
1544{
1545 (void)token;
Thomas Martitz23e46b32009-07-22 21:14:47 +00001546 unsigned i, imax;
Jonathan Gordon271643c2009-08-16 21:22:57 +00001547 struct touchregion *region = NULL;
Jonathan Gordon0eb5dc62009-04-20 01:41:56 +00001548 const char *ptr = wps_bufptr;
Teruaki Kawashima0a4eda42010-05-19 15:47:54 +00001549 const char *action, *end;
Jonathan Gordondc4e9032009-08-09 17:30:05 +00001550 const char pb_string[] = "progressbar";
1551 const char vol_string[] = "volume";
Jonathan Gordon0eb5dc62009-04-20 01:41:56 +00001552 int x,y,w,h;
Teruaki Kawashima0a4eda42010-05-19 15:47:54 +00001553 char temp[20];
Thomas Martitz541dd6f2009-09-13 12:24:14 +00001554
Jonathan Gordon0eb5dc62009-04-20 01:41:56 +00001555 /* format: %T|x|y|width|height|action|
Jonathan Gordon2172c912009-05-17 06:25:18 +00001556 * if action starts with & the area must be held to happen
Jonathan Gordon0eb5dc62009-04-20 01:41:56 +00001557 * action is one of:
1558 * play - play/pause playback
1559 * stop - stop playback, exit the wps
1560 * prev - prev track
1561 * next - next track
Jonathan Gordon2172c912009-05-17 06:25:18 +00001562 * ffwd - seek forward
1563 * rwd - seek backwards
Jonathan Gordon0eb5dc62009-04-20 01:41:56 +00001564 * menu - go back to the main menu
1565 * browse - go back to the file/db browser
Jonathan Gordonc1267dc2009-05-15 05:36:16 +00001566 * shuffle - toggle shuffle mode
1567 * repmode - cycle the repeat mode
Jonathan Gordon13cc6542009-05-15 06:02:50 +00001568 * quickscreen - go into the quickscreen
1569 * contextmenu - open the context menu
Maurus Cuelenaere8d013f52009-08-17 12:46:21 +00001570 * playlist - go into the playlist
1571 * pitch - go into the pitchscreen
Rob Purchase24c1c752009-11-02 21:56:48 +00001572 * volup - increase volume by one step
1573 * voldown - decrease volume by one step
Jonathan Gordon0eb5dc62009-04-20 01:41:56 +00001574 */
1575
Thomas Martitz5c9fe522009-07-22 22:10:25 +00001576
Jonathan Gordon5b0521c2010-06-07 03:44:11 +00001577 if (*ptr != '(')
Jonathan Gordon0eb5dc62009-04-20 01:41:56 +00001578 return WPS_ERROR_INVALID_PARAM;
1579 ptr++;
1580
Jonathan Gordon5b0521c2010-06-07 03:44:11 +00001581 if (!(ptr = parse_list("dddds", NULL, ',', ptr, &x, &y, &w, &h, &action)))
Jonathan Gordon0eb5dc62009-04-20 01:41:56 +00001582 return WPS_ERROR_INVALID_PARAM;
1583
1584 /* Check there is a terminating | */
Jonathan Gordon5b0521c2010-06-07 03:44:11 +00001585 if (*ptr != ')')
Jonathan Gordon0eb5dc62009-04-20 01:41:56 +00001586 return WPS_ERROR_INVALID_PARAM;
Thomas Martitz541dd6f2009-09-13 12:24:14 +00001587
Jonathan Gordon271643c2009-08-16 21:22:57 +00001588 region = skin_buffer_alloc(sizeof(struct touchregion));
1589 if (!region)
1590 return WPS_ERROR_INVALID_PARAM;
Thomas Martitz541dd6f2009-09-13 12:24:14 +00001591
Jonathan Gordon0eb5dc62009-04-20 01:41:56 +00001592 /* should probably do some bounds checking here with the viewport... but later */
Jonathan Gordon0eb5dc62009-04-20 01:41:56 +00001593 region->action = ACTION_NONE;
1594 region->x = x;
1595 region->y = y;
1596 region->width = w;
1597 region->height = h;
Jonathan Gordon36ca4962009-08-18 05:30:59 +00001598 region->wvp = curr_vp;
Jonathan Gordon31fb4f62010-02-24 06:19:25 +00001599 region->armed = false;
Thomas Martitz541dd6f2009-09-13 12:24:14 +00001600
Jonathan Gordon5b0521c2010-06-07 03:44:11 +00001601 end = strchr(action, ')');
Teruaki Kawashima0a4eda42010-05-19 15:47:54 +00001602 if (!end || (size_t)(end-action+1) > sizeof temp)
1603 return WPS_ERROR_INVALID_PARAM;
1604 strlcpy(temp, action, end-action+1);
1605 action = temp;
1606
1607 if(!strcmp(pb_string, action))
Jonathan Gordondc4e9032009-08-09 17:30:05 +00001608 region->type = WPS_TOUCHREGION_SCROLLBAR;
Teruaki Kawashima0a4eda42010-05-19 15:47:54 +00001609 else if(!strcmp(vol_string, action))
Jonathan Gordondc4e9032009-08-09 17:30:05 +00001610 region->type = WPS_TOUCHREGION_VOLUME;
Jonathan Gordon3e7444f2009-08-03 04:43:34 +00001611 else
Jonathan Gordon3e7444f2009-08-03 04:43:34 +00001612 {
Jonathan Gordondc4e9032009-08-09 17:30:05 +00001613 region->type = WPS_TOUCHREGION_ACTION;
1614
1615 if (*action == '&')
1616 {
1617 action++;
1618 region->repeat = true;
1619 }
1620 else
1621 region->repeat = false;
1622
Jonathan Gordondc4e9032009-08-09 17:30:05 +00001623 imax = ARRAYLEN(touchactions);
Teruaki Kawashima0a4eda42010-05-19 15:47:54 +00001624 for (i = 0; i < imax; i++)
Jonathan Gordondc4e9032009-08-09 17:30:05 +00001625 {
1626 /* try to match with one of our touchregion screens */
Teruaki Kawashima0a4eda42010-05-19 15:47:54 +00001627 if (!strcmp(touchactions[i].s, action))
1628 {
Jonathan Gordondc4e9032009-08-09 17:30:05 +00001629 region->action = touchactions[i].action;
Teruaki Kawashima0a4eda42010-05-19 15:47:54 +00001630 break;
1631 }
Jonathan Gordondc4e9032009-08-09 17:30:05 +00001632 }
1633 if (region->action == ACTION_NONE)
1634 return WPS_ERROR_INVALID_PARAM;
Jonathan Gordon3e7444f2009-08-03 04:43:34 +00001635 }
Jonathan Gordon271643c2009-08-16 21:22:57 +00001636 struct skin_token_list *item = new_skin_token_list_item(NULL, region);
1637 if (!item)
1638 return WPS_ERROR_INVALID_PARAM;
1639 add_to_ll_chain(&wps_data->touchregions, item);
Thomas Martitz541dd6f2009-09-13 12:24:14 +00001640 return skip_end_of_line(wps_bufptr);
1641}
1642#endif
Jonathan Gordon0eb5dc62009-04-20 01:41:56 +00001643
Nicolas Pennequinab90d582007-04-04 14:41:40 +00001644/* Parse a generic token from the given string. Return the length read */
Nicolas Pennequin9cf89602007-04-05 14:09:59 +00001645static int parse_token(const char *wps_bufptr, struct wps_data *wps_data)
Nicolas Pennequinab90d582007-04-04 14:41:40 +00001646{
Nicolas Pennequin31f76112007-11-14 22:02:41 +00001647 int skip = 0, taglen = 0, ret;
Nicolas Pennequin07696c12007-04-08 04:01:06 +00001648 struct wps_token *token = wps_data->tokens + wps_data->num_tokens;
1649 const struct wps_tag *tag;
Teruaki Kawashima246e38e2009-09-11 14:33:32 +00001650 memset(token, 0, sizeof(*token));
Nicolas Pennequinab90d582007-04-04 14:41:40 +00001651
Nicolas Pennequin9cf89602007-04-05 14:09:59 +00001652 switch(*wps_bufptr)
Nicolas Pennequinab90d582007-04-04 14:41:40 +00001653 {
1654
1655 case '%'