summaryrefslogtreecommitdiff
path: root/apps/gui
diff options
context:
space:
mode:
Diffstat (limited to 'apps/gui')
-rw-r--r--apps/gui/gwps-common.c135
-rw-r--r--apps/gui/gwps.h122
-rw-r--r--apps/gui/wps_debug.c232
-rw-r--r--apps/gui/wps_parser.c207
4 files changed, 408 insertions, 288 deletions
diff --git a/apps/gui/gwps-common.c b/apps/gui/gwps-common.c
index c96b830cf2..078e20ba44 100644
--- a/apps/gui/gwps-common.c
+++ b/apps/gui/gwps-common.c
@@ -81,12 +81,10 @@ void gui_wps_statusbar_draw(struct gui_wps *wps, bool force)
81{ 81{
82 bool draw = global_settings.statusbar; 82 bool draw = global_settings.statusbar;
83 83
84 if(wps->data->wps_sb_tag 84 if (wps->data->wps_sb_tag)
85 && wps->data->show_sb_on_wps) 85 draw = wps->data->show_sb_on_wps;
86 draw = true; 86
87 else if(wps->data->wps_sb_tag) 87 if (draw)
88 draw = false;
89 if(draw)
90 gui_statusbar_draw(wps->statusbar, force); 88 gui_statusbar_draw(wps->statusbar, force);
91} 89}
92#else 90#else
@@ -1012,15 +1010,13 @@ static char *get_tag(struct gui_wps *gwps,
1012 } 1010 }
1013 } 1011 }
1014#endif 1012#endif
1015
1016 case WPS_TOKEN_BATTERY_SLEEPTIME: 1013 case WPS_TOKEN_BATTERY_SLEEPTIME:
1017 { 1014 {
1018 if (get_sleep_timer() == 0) 1015 if (get_sleep_timer() == 0)
1019 return NULL; 1016 return NULL;
1020 else 1017 else
1021 { 1018 {
1022 format_time(buf, buf_size, \ 1019 format_time(buf, buf_size, get_sleep_timer() * 1000);
1023 get_sleep_timer() * 1000);
1024 return buf; 1020 return buf;
1025 } 1021 }
1026 } 1022 }
@@ -1377,6 +1373,7 @@ static bool get_line(struct gui_wps *gwps,
1377 char temp_buf[128]; 1373 char temp_buf[128];
1378 char *buf = linebuf; /* will always point to the writing position */ 1374 char *buf = linebuf; /* will always point to the writing position */
1379 char *linebuf_end = linebuf + linebuf_size - 1; 1375 char *linebuf_end = linebuf + linebuf_size - 1;
1376 int i, last_token_idx;
1380 bool update = false; 1377 bool update = false;
1381 1378
1382 /* alignment-related variables */ 1379 /* alignment-related variables */
@@ -1384,16 +1381,14 @@ static bool get_line(struct gui_wps *gwps,
1384 char* cur_align_start; 1381 char* cur_align_start;
1385 cur_align_start = buf; 1382 cur_align_start = buf;
1386 cur_align = WPS_ALIGN_LEFT; 1383 cur_align = WPS_ALIGN_LEFT;
1387 align->left = 0; 1384 align->left = NULL;
1388 align->center = 0; 1385 align->center = NULL;
1389 align->right = 0; 1386 align->right = NULL;
1390 1387
1391 /* start at the beginning of the current (sub)line */ 1388 /* Process all tokens of the desired subline */
1392 int i = data->format_lines[line][subline]; 1389 last_token_idx = wps_last_token_index(data, line, subline);
1393 1390 for (i = wps_first_token_index(data, line, subline);
1394 while (data->tokens[i].type != WPS_TOKEN_EOL 1391 i <= last_token_idx; i++)
1395 && data->tokens[i].type != WPS_TOKEN_SUBLINE_SEPARATOR
1396 && i < data->num_tokens)
1397 { 1392 {
1398 switch(data->tokens[i].type) 1393 switch(data->tokens[i].type)
1399 { 1394 {
@@ -1460,8 +1455,7 @@ static bool get_line(struct gui_wps *gwps,
1460 default: 1455 default:
1461 { 1456 {
1462 /* get the value of the tag and copy it to the buffer */ 1457 /* get the value of the tag and copy it to the buffer */
1463 char *value = get_tag(gwps, i, temp_buf, 1458 char *value = get_tag(gwps,i,temp_buf,sizeof(temp_buf),NULL);
1464 sizeof(temp_buf), NULL);
1465 if (value) 1459 if (value)
1466 { 1460 {
1467 update = true; 1461 update = true;
@@ -1471,7 +1465,6 @@ static bool get_line(struct gui_wps *gwps,
1471 break; 1465 break;
1472 } 1466 }
1473 } 1467 }
1474 i++;
1475 } 1468 }
1476 1469
1477 /* close the current alignment */ 1470 /* close the current alignment */
@@ -1496,13 +1489,14 @@ static bool get_line(struct gui_wps *gwps,
1496static void get_subline_timeout(struct gui_wps *gwps, int line, int subline) 1489static void get_subline_timeout(struct gui_wps *gwps, int line, int subline)
1497{ 1490{
1498 struct wps_data *data = gwps->data; 1491 struct wps_data *data = gwps->data;
1499 int i = data->format_lines[line][subline]; 1492 int i;
1493 int subline_idx = wps_subline_index(data, line, subline);
1494 int last_token_idx = wps_last_token_index(data, line, subline);
1500 1495
1501 data->time_mult[line][subline] = DEFAULT_SUBLINE_TIME_MULTIPLIER; 1496 data->sublines[subline_idx].time_mult = DEFAULT_SUBLINE_TIME_MULTIPLIER;
1502 1497
1503 while (data->tokens[i].type != WPS_TOKEN_EOL 1498 for (i = wps_first_token_index(data, line, subline);
1504 && data->tokens[i].type != WPS_TOKEN_SUBLINE_SEPARATOR 1499 i <= last_token_idx; i++)
1505 && i < data->num_tokens)
1506 { 1500 {
1507 switch(data->tokens[i].type) 1501 switch(data->tokens[i].type)
1508 { 1502 {
@@ -1518,32 +1512,33 @@ static void get_subline_timeout(struct gui_wps *gwps, int line, int subline)
1518 break; 1512 break;
1519 1513
1520 case WPS_TOKEN_SUBLINE_TIMEOUT: 1514 case WPS_TOKEN_SUBLINE_TIMEOUT:
1521 data->time_mult[line][subline] = data->tokens[i].value.i; 1515 data->sublines[subline_idx].time_mult = data->tokens[i].value.i;
1522 break; 1516 break;
1523 1517
1524 default: 1518 default:
1525 break; 1519 break;
1526 } 1520 }
1527 i++;
1528 } 1521 }
1529} 1522}
1530 1523
1531/* Calculate which subline should be displayed for each line */ 1524/* Calculates which subline should be displayed for the specified line
1532static bool get_curr_subline(struct gui_wps *gwps, int line) 1525 Returns true iff the subline must be refreshed */
1526static bool update_curr_subline(struct gui_wps *gwps, int line)
1533{ 1527{
1534 struct wps_data *data = gwps->data; 1528 struct wps_data *data = gwps->data;
1535 1529
1536 int search, search_start; 1530 int search, search_start, num_sublines;
1537 bool reset_subline; 1531 bool reset_subline;
1538 bool new_subline_refresh; 1532 bool new_subline_refresh;
1539 bool only_one_subline; 1533 bool only_one_subline;
1540 1534
1541 reset_subline = (data->curr_subline[line] == SUBLINE_RESET); 1535 num_sublines = data->lines[line].num_sublines;
1536 reset_subline = (data->lines[line].curr_subline == SUBLINE_RESET);
1542 new_subline_refresh = false; 1537 new_subline_refresh = false;
1543 only_one_subline = false; 1538 only_one_subline = false;
1544 1539
1545 /* if time to advance to next sub-line */ 1540 /* if time to advance to next sub-line */
1546 if (TIME_AFTER(current_tick, data->subline_expire_time[line] - 1) || 1541 if (TIME_AFTER(current_tick, data->lines[line].subline_expire_time - 1) ||
1547 reset_subline) 1542 reset_subline)
1548 { 1543 {
1549 /* search all sublines until the next subline with time > 0 1544 /* search all sublines until the next subline with time > 0
@@ -1551,43 +1546,45 @@ static bool get_curr_subline(struct gui_wps *gwps, int line)
1551 if (reset_subline) 1546 if (reset_subline)
1552 search_start = 0; 1547 search_start = 0;
1553 else 1548 else
1554 search_start = data->curr_subline[line]; 1549 search_start = data->lines[line].curr_subline;
1555 1550
1556 for (search = 0; search < WPS_MAX_SUBLINES; search++) 1551 for (search = 0; search < num_sublines; search++)
1557 { 1552 {
1558 data->curr_subline[line]++; 1553 data->lines[line].curr_subline++;
1559 1554
1560 /* wrap around if beyond last defined subline or WPS_MAX_SUBLINES */ 1555 /* wrap around if beyond last defined subline or WPS_MAX_SUBLINES */
1561 if ((!data->format_lines[line][data->curr_subline[line]]) || 1556 if (data->lines[line].curr_subline == num_sublines)
1562 (data->curr_subline[line] == WPS_MAX_SUBLINES))
1563 { 1557 {
1564 if (data->curr_subline[line] == 1) 1558 if (data->lines[line].curr_subline == 1)
1565 only_one_subline = true; 1559 only_one_subline = true;
1566 data->curr_subline[line] = 0; 1560 data->lines[line].curr_subline = 0;
1567 } 1561 }
1568 1562
1569 /* if back where we started after search or 1563 /* if back where we started after search or
1570 only one subline is defined on the line */ 1564 only one subline is defined on the line */
1571 if (((search > 0) && (data->curr_subline[line] == search_start)) || 1565 if (((search > 0) && (data->lines[line].curr_subline == search_start)) ||
1572 only_one_subline) 1566 only_one_subline)
1573 { 1567 {
1574 /* no other subline with a time > 0 exists */ 1568 /* no other subline with a time > 0 exists */
1575 data->subline_expire_time[line] = (reset_subline? 1569 data->lines[line].subline_expire_time = (reset_subline ?
1576 current_tick : data->subline_expire_time[line]) + 100 * HZ; 1570 current_tick : data->lines[line].subline_expire_time) + 100 * HZ;
1577 break; 1571 break;
1578 } 1572 }
1579 else 1573 else
1580 { 1574 {
1581 /* get initial time multiplier for this subline */ 1575 /* get initial time multiplier for this subline */
1582 get_subline_timeout(gwps, line, data->curr_subline[line]); 1576 get_subline_timeout(gwps, line, data->lines[line].curr_subline);
1577
1578 int subline_idx = wps_subline_index(data, line,
1579 data->lines[line].curr_subline);
1583 1580
1584 /* only use this subline if subline time > 0 */ 1581 /* only use this subline if subline time > 0 */
1585 if (data->time_mult[line][data->curr_subline[line]] > 0) 1582 if (data->sublines[subline_idx].time_mult > 0)
1586 { 1583 {
1587 new_subline_refresh = true; 1584 new_subline_refresh = true;
1588 data->subline_expire_time[line] = (reset_subline ? 1585 data->lines[line].subline_expire_time = (reset_subline ?
1589 current_tick : data->subline_expire_time[line]) + 1586 current_tick : data->lines[line].subline_expire_time) +
1590 BASE_SUBLINE_TIME * data->time_mult[line][data->curr_subline[line]]; 1587 BASE_SUBLINE_TIME * data->sublines[subline_idx].time_mult;
1591 break; 1588 break;
1592 } 1589 }
1593 } 1590 }
@@ -1779,7 +1776,7 @@ bool gui_wps_refresh(struct gui_wps *gwps,
1779 if(!gwps || !data || !state || !display) 1776 if(!gwps || !data || !state || !display)
1780 return false; 1777 return false;
1781 1778
1782 int line, i; 1779 int line, i, subline_idx;
1783 unsigned char flags; 1780 unsigned char flags;
1784 char linebuf[MAX_PATH]; 1781 char linebuf[MAX_PATH];
1785 1782
@@ -1814,7 +1811,7 @@ bool gui_wps_refresh(struct gui_wps *gwps,
1814 { 1811 {
1815 for (i = 0; i < data->num_lines; i++) 1812 for (i = 0; i < data->num_lines; i++)
1816 { 1813 {
1817 data->curr_subline[i] = SUBLINE_RESET; 1814 data->lines[i].curr_subline = SUBLINE_RESET;
1818 } 1815 }
1819 } 1816 }
1820 1817
@@ -1840,15 +1837,16 @@ bool gui_wps_refresh(struct gui_wps *gwps,
1840 update_line = false; 1837 update_line = false;
1841 1838
1842 /* get current subline for the line */ 1839 /* get current subline for the line */
1843 new_subline_refresh = get_curr_subline(gwps, line); 1840 new_subline_refresh = update_curr_subline(gwps, line);
1844 1841
1845 flags = data->line_type[line][data->curr_subline[line]]; 1842 subline_idx = wps_subline_index(data, line, data->lines[line].curr_subline);
1843 flags = data->sublines[subline_idx].line_type;
1846 1844
1847 if (refresh_mode == WPS_REFRESH_ALL || flags & refresh_mode 1845 if (refresh_mode == WPS_REFRESH_ALL || (flags & refresh_mode)
1848 || new_subline_refresh) 1846 || new_subline_refresh)
1849 { 1847 {
1850 /* get_line tells us if we need to update the line */ 1848 /* get_line tells us if we need to update the line */
1851 update_line = get_line(gwps, line, data->curr_subline[line], 1849 update_line = get_line(gwps, line, data->lines[line].curr_subline,
1852 &align, linebuf, sizeof(linebuf)); 1850 &align, linebuf, sizeof(linebuf));
1853 } 1851 }
1854 1852
@@ -1947,3 +1945,30 @@ bool gui_wps_refresh(struct gui_wps *gwps,
1947 1945
1948 return true; 1946 return true;
1949} 1947}
1948
1949int wps_subline_index(struct wps_data *data, int line, int subline)
1950{
1951 return data->lines[line].first_subline_idx + subline;
1952}
1953
1954int wps_first_token_index(struct wps_data *data, int line, int subline)
1955{
1956 int first_subline_idx = data->lines[line].first_subline_idx;
1957 return data->sublines[first_subline_idx + subline].first_token_idx;
1958}
1959
1960int wps_last_token_index(struct wps_data *data, int line, int subline)
1961{
1962 int first_subline_idx = data->lines[line].first_subline_idx;
1963 int idx = first_subline_idx + subline;
1964 if (idx < data->num_sublines - 1)
1965 {
1966 /* This subline ends where the next begins */
1967 return data->sublines[idx+1].first_token_idx - 1;
1968 }
1969 else
1970 {
1971 /* The last subline goes to the end */
1972 return data->num_tokens - 1;
1973 }
1974}
diff --git a/apps/gui/gwps.h b/apps/gui/gwps.h
index 02a83085b9..f012b3b304 100644
--- a/apps/gui/gwps.h
+++ b/apps/gui/gwps.h
@@ -71,23 +71,25 @@ struct align_pos {
71#define MAX_IMAGES (26*2) /* a-z and A-Z */ 71#define MAX_IMAGES (26*2) /* a-z and A-Z */
72#define IMG_BUFSIZE ((LCD_HEIGHT*LCD_WIDTH*LCD_DEPTH/8) \ 72#define IMG_BUFSIZE ((LCD_HEIGHT*LCD_WIDTH*LCD_DEPTH/8) \
73 + (2*LCD_HEIGHT*LCD_WIDTH/8)) 73 + (2*LCD_HEIGHT*LCD_WIDTH/8))
74#define WPS_MAX_LINES (LCD_HEIGHT/5+1) 74
75#define WPS_MAX_TOKENS 1024 75#define WPS_MAX_LINES (LCD_HEIGHT/5+1)
76#define WPS_MAX_STRINGS 128 76#define WPS_MAX_SUBLINES (WPS_MAX_LINES*3)
77#define STRING_BUFFER_SIZE 512 77#define WPS_MAX_TOKENS 1024
78#define WPS_MAX_COND_LEVEL 10 78#define WPS_MAX_STRINGS 128
79#define STRING_BUFFER_SIZE 512
80#define WPS_MAX_COND_LEVEL 10
79 81
80#else 82#else
81 83
82#define WPS_MAX_LINES 2 84#define WPS_MAX_LINES 2
83#define WPS_MAX_TOKENS 64 85#define WPS_MAX_SUBLINES 12
84#define WPS_MAX_STRINGS 32 86#define WPS_MAX_TOKENS 64
85#define STRING_BUFFER_SIZE 64 87#define WPS_MAX_STRINGS 32
86#define WPS_MAX_COND_LEVEL 5 88#define STRING_BUFFER_SIZE 64
89#define WPS_MAX_COND_LEVEL 5
87 90
88#endif 91#endif
89 92
90#define WPS_MAX_SUBLINES 12
91#define DEFAULT_SUBLINE_TIME_MULTIPLIER 20 /* (10ths of sec) */ 93#define DEFAULT_SUBLINE_TIME_MULTIPLIER 20 /* (10ths of sec) */
92#define BASE_SUBLINE_TIME 10 /* base time that multiplier is applied to 94#define BASE_SUBLINE_TIME 10 /* base time that multiplier is applied to
93 (1/HZ sec, or 100ths of sec) */ 95 (1/HZ sec, or 100ths of sec) */
@@ -100,18 +102,13 @@ enum wps_token_type {
100 /* Markers */ 102 /* Markers */
101 WPS_TOKEN_CHARACTER, 103 WPS_TOKEN_CHARACTER,
102 WPS_TOKEN_STRING, 104 WPS_TOKEN_STRING,
103 WPS_TOKEN_EOL,
104 105
105 /* Alignment */ 106 /* Alignment */
106 WPS_TOKEN_ALIGN_LEFT, 107 WPS_TOKEN_ALIGN_LEFT,
107 WPS_TOKEN_ALIGN_CENTER, 108 WPS_TOKEN_ALIGN_CENTER,
108 WPS_TOKEN_ALIGN_RIGHT, 109 WPS_TOKEN_ALIGN_RIGHT,
109 110
110 /* Scrolling */ 111 /* Sublines */
111 WPS_TOKEN_SCROLL,
112
113 /* Alternating sublines */
114 WPS_TOKEN_SUBLINE_SEPARATOR,
115 WPS_TOKEN_SUBLINE_TIMEOUT, 112 WPS_TOKEN_SUBLINE_TIMEOUT,
116 113
117 /* Battery */ 114 /* Battery */
@@ -228,12 +225,6 @@ enum wps_token_type {
228 WPS_TOKEN_PLAYLIST_POSITION, 225 WPS_TOKEN_PLAYLIST_POSITION,
229 WPS_TOKEN_PLAYLIST_SHUFFLE, 226 WPS_TOKEN_PLAYLIST_SHUFFLE,
230 227
231#ifdef HAVE_LCD_BITMAP
232 /* Statusbar */
233 WPS_TOKEN_STATUSBAR_ENABLED,
234 WPS_TOKEN_STATUSBAR_DISABLED,
235#endif
236
237#if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD) 228#if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
238 /* Virtual LED */ 229 /* Virtual LED */
239 WPS_TOKEN_VLED_HDD 230 WPS_TOKEN_VLED_HDD
@@ -242,13 +233,52 @@ enum wps_token_type {
242 233
243struct wps_token { 234struct wps_token {
244 enum wps_token_type type; 235 enum wps_token_type type;
236
237 /* Whether the tag (e.g. track name or the album) refers the
238 current or the next song (false=current, true=next) */
245 bool next; 239 bool next;
240
246 union { 241 union {
247 char c; 242 char c;
248 unsigned short i; 243 unsigned short i;
249 } value; 244 } value;
250}; 245};
251 246
247/* Description of a subline on the WPS */
248struct wps_subline {
249
250 /* Index of the first token for this subline in the token array.
251 Tokens of this subline end where tokens for the next subline
252 begin. */
253 unsigned short first_token_idx;
254
255 /* Bit or'ed WPS_REFRESH_xxx */
256 unsigned char line_type;
257
258 /* How long the subline should be displayed, in 10ths of sec */
259 unsigned char time_mult;
260};
261
262/* Description of a line on the WPS. A line is a set of sublines.
263 A subline is displayed for a certain amount of time. After that,
264 the next subline of the line is displayed. And so on. */
265struct wps_line {
266
267 /* Number of sublines in this line */
268 signed char num_sublines;
269
270 /* Number (0-based) of the subline within this line currently being displayed */
271 signed char curr_subline;
272
273 /* Index of the first subline of this line in the subline array.
274 Sublines for this line end where sublines for the next line begin. */
275 unsigned short first_subline_idx;
276
277 /* When the next subline of this line should be displayed
278 (absolute time value in ticks) */
279 long subline_expire_time;
280};
281
252 282
253/* wps_data 283/* wps_data
254 this struct holds all necessary data which describes the 284 this struct holds all necessary data which describes the
@@ -273,20 +303,24 @@ struct wps_data
273 unsigned short wps_progress_pat[8]; 303 unsigned short wps_progress_pat[8];
274 bool full_line_progressbar; 304 bool full_line_progressbar;
275#endif 305#endif
276 unsigned short format_lines[WPS_MAX_LINES][WPS_MAX_SUBLINES]; 306 /* Number of lines in the WPS. During WPS parsing, this is
277 unsigned char num_lines; 307 the index of the line being parsed. */
278 unsigned char line_type[WPS_MAX_LINES][WPS_MAX_SUBLINES]; 308 int num_lines;
279 unsigned short time_mult[WPS_MAX_LINES][WPS_MAX_SUBLINES]; 309 struct wps_line lines[WPS_MAX_LINES];
280 long subline_expire_time[WPS_MAX_LINES]; 310
281 short curr_subline[WPS_MAX_LINES]; 311 /* Total number of sublines in the WPS. During WPS parsing, this is
282 unsigned char num_sublines[WPS_MAX_LINES]; 312 the index of the subline where the parsed tokens are added to. */
283 313 int num_sublines;
314 struct wps_subline sublines[WPS_MAX_SUBLINES];
315
316 /* Total number of tokens in the WPS. During WPS parsing, this is
317 the index of the token being parsed. */
318 int num_tokens;
284 struct wps_token tokens[WPS_MAX_TOKENS]; 319 struct wps_token tokens[WPS_MAX_TOKENS];
285 unsigned short num_tokens;
286 320
287 char string_buffer[STRING_BUFFER_SIZE]; 321 char string_buffer[STRING_BUFFER_SIZE];
288 char *strings[WPS_MAX_STRINGS]; 322 char *strings[WPS_MAX_STRINGS];
289 unsigned char num_strings; 323 int num_strings;
290 324
291 bool wps_loaded; 325 bool wps_loaded;
292}; 326};
@@ -300,6 +334,24 @@ bool wps_data_load(struct wps_data *wps_data,
300 const char *buf, 334 const char *buf,
301 bool isfile); 335 bool isfile);
302 336
337/* Returns the index of the subline in the subline array
338 line - 0-based line number
339 subline - 0-based subline number within the line
340 */
341int wps_subline_index(struct wps_data *wps_data, int line, int subline);
342
343/* Returns the index of the first subline's token in the token array
344 line - 0-based line number
345 subline - 0-based subline number within the line
346 */
347int wps_first_token_index(struct wps_data *data, int line, int subline);
348
349/* Returns the index of the last subline's token in the token array.
350 line - 0-based line number
351 subline - 0-based subline number within the line
352 */
353int wps_last_token_index(struct wps_data *data, int line, int subline);
354
303/* wps_data end */ 355/* wps_data end */
304 356
305/* wps_state 357/* wps_state
@@ -329,11 +381,11 @@ struct wps_state
329/* wps_state end*/ 381/* wps_state end*/
330 382
331/* gui_wps 383/* gui_wps
332 defines a wps with it's data, state, 384 defines a wps with its data, state,
333 and the screen on which the wps-content should be drawn */ 385 and the screen on which the wps-content should be drawn */
334struct gui_wps 386struct gui_wps
335{ 387{
336 struct screen * display; 388 struct screen *display;
337 struct wps_data *data; 389 struct wps_data *data;
338 struct wps_state *state; 390 struct wps_state *state;
339 struct gui_statusbar *statusbar; 391 struct gui_statusbar *statusbar;
diff --git a/apps/gui/wps_debug.c b/apps/gui/wps_debug.c
index bcb05e0902..0e2b151551 100644
--- a/apps/gui/wps_debug.c
+++ b/apps/gui/wps_debug.c
@@ -24,107 +24,122 @@
24#include "gwps.h" 24#include "gwps.h"
25#include "debug.h" 25#include "debug.h"
26 26
27static char *next_str(bool next) {
28 return next ? "next" : "";
29}
30
27void dump_wps_tokens(struct wps_data *data) 31void dump_wps_tokens(struct wps_data *data)
28{ 32{
33 struct wps_token *token;
29 int i, j; 34 int i, j;
30 int indent = 0; 35 int indent = 0;
31 char buf[64]; 36 char buf[64];
32 bool next; 37 bool next;
33 38
34 /* Dump parsed WPS */ 39 if (data->num_tokens > WPS_MAX_TOKENS) {
35 for(i = 0; i < data->num_tokens && i < WPS_MAX_TOKENS; i++) { 40 DEBUGF("Number of tokens is too high (%d)!!!\n", data->num_tokens);
41 return;
42 }
36 43
37 next = data->tokens[i].next; 44 /* Dump parsed WPS */
45 for (i = 0, token = data->tokens; i < data->num_tokens; i++, token++) {
46 next = token->next;
38 47
39 switch(data->tokens[i].type) { 48 switch(token->type) {
40 case WPS_TOKEN_UNKNOWN: 49 case WPS_TOKEN_UNKNOWN:
41 snprintf(buf, sizeof(buf), "Unknown token"); 50 snprintf(buf, sizeof(buf), "Unknown token");
42 break; 51 break;
43 case WPS_TOKEN_CHARACTER: 52 case WPS_TOKEN_CHARACTER:
44 snprintf(buf, sizeof(buf), "Character '%c'", 53 snprintf(buf, sizeof(buf), "Character '%c'",
45 data->tokens[i].value.c); 54 token->value.c);
46 break; 55 break;
47 56
48 case WPS_TOKEN_STRING: 57 case WPS_TOKEN_STRING:
49 snprintf(buf, sizeof(buf), "String '%s'", 58 snprintf(buf, sizeof(buf), "String '%s'",
50 data->strings[data->tokens[i].value.i]); 59 data->strings[token->value.i]);
51 break;
52
53 case WPS_TOKEN_EOL:
54 snprintf(buf, sizeof(buf), "%s", "EOL");
55 break; 60 break;
56 61
57#ifdef HAVE_LCD_BITMAP 62#ifdef HAVE_LCD_BITMAP
58 case WPS_TOKEN_ALIGN_LEFT: 63 case WPS_TOKEN_ALIGN_LEFT:
59 snprintf(buf, sizeof(buf), "%s", "align left"); 64 snprintf(buf, sizeof(buf), "align left");
60 break; 65 break;
61 66
62 case WPS_TOKEN_ALIGN_CENTER: 67 case WPS_TOKEN_ALIGN_CENTER:
63 snprintf(buf, sizeof(buf), "%s", "align center"); 68 snprintf(buf, sizeof(buf), "align center");
64 break; 69 break;
65 70
66 case WPS_TOKEN_ALIGN_RIGHT: 71 case WPS_TOKEN_ALIGN_RIGHT:
67 snprintf(buf, sizeof(buf), "%s", "align right"); 72 snprintf(buf, sizeof(buf), "align right");
68 break; 73 break;
69#endif 74#endif
70 75
76 case WPS_TOKEN_SUBLINE_TIMEOUT:
77 snprintf(buf, sizeof(buf), "subline timeout value: %d",
78 token->value.i);
79 break;
80
71 case WPS_TOKEN_CONDITIONAL: 81 case WPS_TOKEN_CONDITIONAL:
72 snprintf(buf, sizeof(buf), "%s, %d options", "conditional", 82 snprintf(buf, sizeof(buf), "conditional, %d options",
73 data->tokens[i].value.i); 83 token->value.i);
74 break; 84 break;
75 85
76 case WPS_TOKEN_CONDITIONAL_START: 86 case WPS_TOKEN_CONDITIONAL_START:
77 snprintf(buf, sizeof(buf), "%s, next cond: %d", 87 snprintf(buf, sizeof(buf), "conditional start, next cond: %d",
78 "conditional start", data->tokens[i].value.i); 88 token->value.i);
79 indent++; 89 indent++;
80 break; 90 break;
81 91
82 case WPS_TOKEN_CONDITIONAL_OPTION: 92 case WPS_TOKEN_CONDITIONAL_OPTION:
83 snprintf(buf, sizeof(buf), "%s, next cond: %d", 93 snprintf(buf, sizeof(buf), "conditional option, next cond: %d",
84 "conditional option", data->tokens[i].value.i); 94 token->value.i);
85 break; 95 break;
86 96
87 case WPS_TOKEN_CONDITIONAL_END: 97 case WPS_TOKEN_CONDITIONAL_END:
88 snprintf(buf, sizeof(buf), "%s", "conditional end"); 98 snprintf(buf, sizeof(buf), "conditional end");
89 indent--; 99 indent--;
90 break; 100 break;
91 101
92#ifdef HAVE_LCD_BITMAP 102#ifdef HAVE_LCD_BITMAP
93 case WPS_TOKEN_IMAGE_PRELOAD: 103 case WPS_TOKEN_IMAGE_PRELOAD:
94 snprintf(buf, sizeof(buf), "%s", "preload image"); 104 snprintf(buf, sizeof(buf), "preload image");
95 break; 105 break;
96 106
97 case WPS_TOKEN_IMAGE_PRELOAD_DISPLAY: 107 case WPS_TOKEN_IMAGE_PRELOAD_DISPLAY:
98 snprintf(buf, sizeof(buf), "%s %d", "display preloaded image", 108 snprintf(buf, sizeof(buf), "display preloaded image %d",
99 data->tokens[i].value.i); 109 token->value.i);
100 break; 110 break;
101 111
102 case WPS_TOKEN_IMAGE_DISPLAY: 112 case WPS_TOKEN_IMAGE_DISPLAY:
103 snprintf(buf, sizeof(buf), "%s", "display image"); 113 snprintf(buf, sizeof(buf), "display image");
104 break; 114 break;
105#endif 115#endif
106 116
107#ifdef HAS_BUTTON_HOLD 117#ifdef HAS_BUTTON_HOLD
108 case WPS_TOKEN_MAIN_HOLD: 118 case WPS_TOKEN_MAIN_HOLD:
109 snprintf(buf, sizeof(buf), "%s", "mode hold"); 119 snprintf(buf, sizeof(buf), "mode hold");
110 break; 120 break;
111#endif 121#endif
112 122
113#ifdef HAS_REMOTE_BUTTON_HOLD 123#ifdef HAS_REMOTE_BUTTON_HOLD
114 case WPS_TOKEN_REMOTE_HOLD: 124 case WPS_TOKEN_REMOTE_HOLD:
115 snprintf(buf, sizeof(buf), "%s", "mode remote hold"); 125 snprintf(buf, sizeof(buf), "mode remote hold");
116 break; 126 break;
117#endif 127#endif
118 128
119 case WPS_TOKEN_REPEAT_MODE: 129 case WPS_TOKEN_REPEAT_MODE:
120 snprintf(buf, sizeof(buf), "%s", "mode repeat"); 130 snprintf(buf, sizeof(buf), "mode repeat");
121 break; 131 break;
122 132
123 case WPS_TOKEN_PLAYBACK_STATUS: 133 case WPS_TOKEN_PLAYBACK_STATUS:
124 snprintf(buf, sizeof(buf), "%s", "mode playback"); 134 snprintf(buf, sizeof(buf), "mode playback");
125 break; 135 break;
126 136
127#if CONFIG_RTC 137#if CONFIG_RTC
138 case WPS_TOKEN_RTC:
139 snprintf(buf, sizeof(buf), "real-time clock",
140 token->value.c);
141 break;
142
128 case WPS_TOKEN_RTC_DAY_OF_MONTH: 143 case WPS_TOKEN_RTC_DAY_OF_MONTH:
129 case WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED: 144 case WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED:
130 case WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED: 145 case WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED:
@@ -142,199 +157,159 @@ void dump_wps_tokens(struct wps_data *data)
142 case WPS_TOKEN_RTC_MONTH_NAME: 157 case WPS_TOKEN_RTC_MONTH_NAME:
143 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON: 158 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON:
144 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN: 159 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN:
145 case WPS_TOKEN_RTC: 160 snprintf(buf, sizeof(buf), "real-time clock tag: %c",
146 snprintf(buf, sizeof(buf), "%s %c", "real-time clock tag:", 161 token->value.c);
147 data->tokens[i].value.c);
148 break; 162 break;
149#endif 163#endif
150 164
151#ifdef HAVE_LCD_BITMAP 165#ifdef HAVE_LCD_BITMAP
152 case WPS_TOKEN_IMAGE_BACKDROP: 166 case WPS_TOKEN_IMAGE_BACKDROP:
153 snprintf(buf, sizeof(buf), "%s", "backdrop image"); 167 snprintf(buf, sizeof(buf), "backdrop image");
154 break; 168 break;
155 169
156 case WPS_TOKEN_IMAGE_PROGRESS_BAR: 170 case WPS_TOKEN_IMAGE_PROGRESS_BAR:
157 snprintf(buf, sizeof(buf), "%s", "progressbar bitmap"); 171 snprintf(buf, sizeof(buf), "progressbar bitmap");
158 break;
159
160
161 case WPS_TOKEN_STATUSBAR_ENABLED:
162 snprintf(buf, sizeof(buf), "%s", "statusbar enable");
163 break;
164
165 case WPS_TOKEN_STATUSBAR_DISABLED:
166 snprintf(buf, sizeof(buf), "%s", "statusbar disable");
167 break; 172 break;
168 173
169 case WPS_TOKEN_PEAKMETER: 174 case WPS_TOKEN_PEAKMETER:
170 snprintf(buf, sizeof(buf), "%s", "peakmeter"); 175 snprintf(buf, sizeof(buf), "peakmeter");
171 break; 176 break;
172#endif 177#endif
173 178
174 case WPS_TOKEN_PROGRESSBAR: 179 case WPS_TOKEN_PROGRESSBAR:
175 snprintf(buf, sizeof(buf), "%s", "progressbar"); 180 snprintf(buf, sizeof(buf), "progressbar");
176 break; 181 break;
177 182
178#ifdef HAVE_LCD_CHARCELLS 183#ifdef HAVE_LCD_CHARCELLS
179 case WPS_TOKEN_PLAYER_PROGRESSBAR: 184 case WPS_TOKEN_PLAYER_PROGRESSBAR:
180 snprintf(buf, sizeof(buf), "%s", "full line progressbar"); 185 snprintf(buf, sizeof(buf), "full line progressbar");
181 break; 186 break;
182#endif 187#endif
183 188
184 case WPS_TOKEN_TRACK_TIME_ELAPSED: 189 case WPS_TOKEN_TRACK_TIME_ELAPSED:
185 snprintf(buf, sizeof(buf), "%s", "time elapsed in track"); 190 snprintf(buf, sizeof(buf), "time elapsed in track");
186 break; 191 break;
187 192
188 case WPS_TOKEN_PLAYLIST_ENTRIES: 193 case WPS_TOKEN_PLAYLIST_ENTRIES:
189 snprintf(buf, sizeof(buf), "%s", "number of entries in playlist"); 194 snprintf(buf, sizeof(buf), "number of entries in playlist");
190 break; 195 break;
191 196
192 case WPS_TOKEN_PLAYLIST_NAME: 197 case WPS_TOKEN_PLAYLIST_NAME:
193 snprintf(buf, sizeof(buf), "%s", "playlist name"); 198 snprintf(buf, sizeof(buf), "playlist name");
194 break; 199 break;
195 200
196 case WPS_TOKEN_PLAYLIST_POSITION: 201 case WPS_TOKEN_PLAYLIST_POSITION:
197 snprintf(buf, sizeof(buf), "%s", "position in playlist"); 202 snprintf(buf, sizeof(buf), "position in playlist");
198 break; 203 break;
199 204
200 case WPS_TOKEN_TRACK_TIME_REMAINING: 205 case WPS_TOKEN_TRACK_TIME_REMAINING:
201 snprintf(buf, sizeof(buf), "%s", "time remaining in track"); 206 snprintf(buf, sizeof(buf), "time remaining in track");
202 break; 207 break;
203 208
204 case WPS_TOKEN_PLAYLIST_SHUFFLE: 209 case WPS_TOKEN_PLAYLIST_SHUFFLE:
205 snprintf(buf, sizeof(buf), "%s", "playlist shuffle mode"); 210 snprintf(buf, sizeof(buf), "playlist shuffle mode");
206 break; 211 break;
207 212
208 case WPS_TOKEN_TRACK_LENGTH: 213 case WPS_TOKEN_TRACK_LENGTH:
209 snprintf(buf, sizeof(buf), "%s", "track length"); 214 snprintf(buf, sizeof(buf), "track length");
210 break; 215 break;
211 216
212 case WPS_TOKEN_VOLUME: 217 case WPS_TOKEN_VOLUME:
213 snprintf(buf, sizeof(buf), "%s", "volume"); 218 snprintf(buf, sizeof(buf), "volume");
214 break; 219 break;
215 220
216 case WPS_TOKEN_METADATA_ARTIST: 221 case WPS_TOKEN_METADATA_ARTIST:
217 snprintf(buf, sizeof(buf), "%s%s", next ? "next " : "", 222 snprintf(buf, sizeof(buf), "%strack artist", next_str(next));
218 "track artist");
219 break; 223 break;
220 224
221 case WPS_TOKEN_METADATA_COMPOSER: 225 case WPS_TOKEN_METADATA_COMPOSER:
222 snprintf(buf, sizeof(buf), "%s%s", next ? "next " : "", 226 snprintf(buf, sizeof(buf), "%strack composer", next_str(next));
223 "track composer");
224 break; 227 break;
225 228
226 case WPS_TOKEN_METADATA_ALBUM: 229 case WPS_TOKEN_METADATA_ALBUM:
227 snprintf(buf, sizeof(buf), "%s%s", next ? "next " : "", 230 snprintf(buf, sizeof(buf), "%strack album", next_str(next));
228 "track album");
229 break; 231 break;
230 232
231 case WPS_TOKEN_METADATA_GENRE: 233 case WPS_TOKEN_METADATA_GENRE:
232 snprintf(buf, sizeof(buf), "%s%s", next ? "next " : "", 234 snprintf(buf, sizeof(buf), "%strack genre", next_str(next));
233 "track genre");
234 break; 235 break;
235 236
236 case WPS_TOKEN_METADATA_TRACK_NUMBER: 237 case WPS_TOKEN_METADATA_TRACK_NUMBER:
237 snprintf(buf, sizeof(buf), "%s%s", next ? "next " : "", 238 snprintf(buf, sizeof(buf), "%strack number", next_str(next));
238 "track number");
239 break; 239 break;
240 240
241 case WPS_TOKEN_METADATA_TRACK_TITLE: 241 case WPS_TOKEN_METADATA_TRACK_TITLE:
242 snprintf(buf, sizeof(buf), "%s%s", next ? "next " : "", 242 snprintf(buf, sizeof(buf), "%strack title", next_str(next));
243 "track title");
244 break; 243 break;
245 244
246 case WPS_TOKEN_METADATA_VERSION: 245 case WPS_TOKEN_METADATA_VERSION:
247 snprintf(buf, sizeof(buf), "%s%s", next ? "next " : "", 246 snprintf(buf, sizeof(buf), "%strack ID3 version", next_str(next));
248 "track ID3 version");
249 break; 247 break;
250 248
251 case WPS_TOKEN_METADATA_YEAR: 249 case WPS_TOKEN_METADATA_YEAR:
252 snprintf(buf, sizeof(buf), "%s%s", next ? "next " : "", 250 snprintf(buf, sizeof(buf), "%strack year", next_str(next));
253 "track year");
254 break; 251 break;
255 252
256 case WPS_TOKEN_BATTERY_PERCENT: 253 case WPS_TOKEN_BATTERY_PERCENT:
257 snprintf(buf, sizeof(buf), "%s", "battery percentage"); 254 snprintf(buf, sizeof(buf), "battery percentage");
258 break; 255 break;
259 256
260 case WPS_TOKEN_BATTERY_VOLTS: 257 case WPS_TOKEN_BATTERY_VOLTS:
261 snprintf(buf, sizeof(buf), "%s", "battery voltage"); 258 snprintf(buf, sizeof(buf), "battery voltage");
262 break; 259 break;
263 260
264 case WPS_TOKEN_BATTERY_TIME: 261 case WPS_TOKEN_BATTERY_TIME:
265 snprintf(buf, sizeof(buf), "%s", "battery time left"); 262 snprintf(buf, sizeof(buf), "battery time left");
266 break; 263 break;
267 264
268 case WPS_TOKEN_BATTERY_CHARGER_CONNECTED: 265 case WPS_TOKEN_BATTERY_CHARGER_CONNECTED:
269 snprintf(buf, sizeof(buf), "%s", "battery charger connected"); 266 snprintf(buf, sizeof(buf), "battery charger connected");
270 break; 267 break;
271 268
272 case WPS_TOKEN_BATTERY_CHARGING: 269 case WPS_TOKEN_BATTERY_CHARGING:
273 snprintf(buf, sizeof(buf), "%s", "battery charging"); 270 snprintf(buf, sizeof(buf), "battery charging");
274 break; 271 break;
275 272
276 case WPS_TOKEN_FILE_BITRATE: 273 case WPS_TOKEN_FILE_BITRATE:
277 snprintf(buf, sizeof(buf), "%s%s", next ? "next " : "", 274 snprintf(buf, sizeof(buf), "%sfile bitrate", next_str(next));
278 "file bitrate");
279 break; 275 break;
280 276
281 case WPS_TOKEN_FILE_CODEC: 277 case WPS_TOKEN_FILE_CODEC:
282 snprintf(buf, sizeof(buf), "%s%s", next ? "next " : "", 278 snprintf(buf, sizeof(buf), "%sfile codec", next_str(next));
283 "file codec");
284 break; 279 break;
285 280
286 case WPS_TOKEN_FILE_FREQUENCY: 281 case WPS_TOKEN_FILE_FREQUENCY:
287 snprintf(buf, sizeof(buf), "%s%s", next ? "next " : "", 282 snprintf(buf, sizeof(buf), "%sfile audio frequency", next_str(next));
288 "file audio frequency");
289 break; 283 break;
290 284
291 case WPS_TOKEN_FILE_NAME: 285 case WPS_TOKEN_FILE_NAME:
292 snprintf(buf, sizeof(buf), "%s%s", next ? "next " : "", 286 snprintf(buf, sizeof(buf), "%sfile name", next_str(next));
293 "file name");
294 break; 287 break;
295 288
296 case WPS_TOKEN_FILE_NAME_WITH_EXTENSION: 289 case WPS_TOKEN_FILE_NAME_WITH_EXTENSION:
297 snprintf(buf, sizeof(buf), "%s%s", next ? "next " : "", 290 snprintf(buf, sizeof(buf), "%sfile name with extension", next_str(next));
298 "file name with extension");
299 break; 291 break;
300 292
301 case WPS_TOKEN_FILE_PATH: 293 case WPS_TOKEN_FILE_PATH:
302 snprintf(buf, sizeof(buf), "%s%s", next ? "next " : "", 294 snprintf(buf, sizeof(buf), "%sfile path", next_str(next));
303 "file path");
304 break; 295 break;
305 296
306 case WPS_TOKEN_FILE_SIZE: 297 case WPS_TOKEN_FILE_SIZE:
307 snprintf(buf, sizeof(buf), "%s%s", next ? "next " : "", 298 snprintf(buf, sizeof(buf), "%sfile size", next_str(next));
308 "file size");
309 break; 299 break;
310 300
311 case WPS_TOKEN_FILE_VBR: 301 case WPS_TOKEN_FILE_VBR:
312 snprintf(buf, sizeof(buf), "%s%s", next ? "next " : "", 302 snprintf(buf, sizeof(buf), "%sfile is vbr", next_str(next));
313 "file is vbr");
314 break; 303 break;
315 304
316 case WPS_TOKEN_FILE_DIRECTORY: 305 case WPS_TOKEN_FILE_DIRECTORY:
317 snprintf(buf, sizeof(buf), "%s%s: %d", next ? "next " : "", 306 snprintf(buf, sizeof(buf), "%sfile directory, level: %d", next_str(next),
318 "file directory, level", 307 token->value.i);
319 data->tokens[i].value.i);
320 break;
321
322 case WPS_TOKEN_SCROLL:
323 snprintf(buf, sizeof(buf), "%s", "scrolling line");
324 break;
325
326 case WPS_TOKEN_SUBLINE_TIMEOUT:
327 snprintf(buf, sizeof(buf), "%s: %d", "subline timeout value",
328 data->tokens[i].value.i);
329 break;
330
331 case WPS_TOKEN_SUBLINE_SEPARATOR:
332 snprintf(buf, sizeof(buf), "%s", "subline separator");
333 break; 308 break;
334 309
335 default: 310 default:
336 snprintf(buf, sizeof(buf), "%s (code: %d)", "FIXME", 311 snprintf(buf, sizeof(buf), "FIXME (code: %d)",
337 data->tokens[i].type); 312 token->type);
338 break; 313 break;
339 } 314 }
340 315
@@ -342,24 +317,43 @@ void dump_wps_tokens(struct wps_data *data)
342 DEBUGF("\t"); 317 DEBUGF("\t");
343 } 318 }
344 319
345 DEBUGF("[%03d] = %s\n", i, buf); 320 DEBUGF("[%3d] = (%2d) %s\n", i, token->type, buf);
346 } 321 }
347 DEBUGF("\n"); 322 DEBUGF("\n");
348} 323}
349 324
350void print_line_info(struct wps_data *data) 325void print_line_info(struct wps_data *data)
351{ 326{
352 int line, subline; 327 int i, j;
328 struct wps_line *line;
329 struct wps_subline *subline;
353 330
354 DEBUGF("line/subline start indexes :\n"); 331 DEBUGF("Number of lines : %d\n", data->num_lines);
355 for (line = 0; line < data->num_lines; line++) 332 DEBUGF("Number of sublines: %d\n", data->num_sublines);
333 DEBUGF("Number of tokens : %d\n", data->num_tokens);
334 DEBUGF("\n");
335
336 for (i = 0, line = data->lines; i < data->num_lines; i++,line++)
356 { 337 {
357 DEBUGF("%2d. ", line); 338 DEBUGF("Line %2d (num_sublines=%d, first_subline=%d)\n",
358 for (subline = 0; subline < data->num_sublines[line]; subline++) 339 i, line->num_sublines, line->first_subline_idx);
340
341 for (j = 0, subline = data->sublines + line->first_subline_idx;
342 j < line->num_sublines; j++, subline++)
359 { 343 {
360 DEBUGF("%3d ", data->format_lines[line][subline]); 344 DEBUGF(" Subline %d: first_token=%3d, last_token=%3d",
345 j, subline->first_token_idx,
346 wps_last_token_index(data, i, j));
347
348 if (subline->line_type & WPS_REFRESH_SCROLL)
349 DEBUGF(", scrolled");
350 else if (subline->line_type & WPS_REFRESH_PLAYER_PROGRESS)
351 DEBUGF(", progressbar");
352 else if (subline->line_type & WPS_REFRESH_PEAK_METER)
353 DEBUGF(", peakmeter");
354
355 DEBUGF("\n");
361 } 356 }
362 DEBUGF("\n");
363 } 357 }
364 358
365 DEBUGF("\n"); 359 DEBUGF("\n");
@@ -367,21 +361,21 @@ void print_line_info(struct wps_data *data)
367 361
368void print_wps_strings(struct wps_data *data) 362void print_wps_strings(struct wps_data *data)
369{ 363{
370 DEBUGF("strings :\n"); 364 DEBUGF("Strings:\n");
371 int i, len = 0; 365 int i, len = 0;
372 for (i=0; i < data->num_strings; i++) 366 for (i=0; i < data->num_strings; i++)
373 { 367 {
374 len += strlen(data->strings[i]); 368 len += strlen(data->strings[i]);
375 DEBUGF("%2d: '%s'\n", i, data->strings[i]); 369 DEBUGF("%2d: '%s'\n", i, data->strings[i]);
376 } 370 }
377 DEBUGF("total length : %d\n", len); 371 DEBUGF("Total length: %d\n", len);
378 DEBUGF("\n"); 372 DEBUGF("\n");
379} 373}
380 374
381#ifdef HAVE_LCD_BITMAP 375#ifdef HAVE_LCD_BITMAP
382void print_img_cond_indexes(struct wps_data *data) 376void print_img_cond_indexes(struct wps_data *data)
383{ 377{
384 DEBUGF("image conditional indexes :\n"); 378 DEBUGF("Image conditional indexes:\n");
385 int i; 379 int i;
386 for (i=0; i < MAX_IMAGES; i++) 380 for (i=0; i < MAX_IMAGES; i++)
387 { 381 {
diff --git a/apps/gui/wps_parser.c b/apps/gui/wps_parser.c
index 2a610bdb8c..65f33447fc 100644
--- a/apps/gui/wps_parser.c
+++ b/apps/gui/wps_parser.c
@@ -69,10 +69,18 @@ extern void print_img_cond_indexes(struct wps_data *data);
69extern void print_wps_strings(struct wps_data *data); 69extern void print_wps_strings(struct wps_data *data);
70#endif 70#endif
71 71
72/* special parsing function. 72/* Function for parsing of details for a token. At the moment the
73 wps_bufptr points to the char following the tag. 73 function is called, the token type has already been set. The
74 The return value is the number of chars read. */ 74 function must fill in the details and possibly add more tokens
75typedef int (*wps_tag_parse_func)(const char *wps_bufptr, struct wps_data *wps_data); 75 to the token array. It should return the number of chars that
76 has been consumed.
77
78 wps_bufptr points to the char following the tag (i.e. where
79 details begin).
80 token is the pointer to the 'main' token being parsed
81 */
82typedef int (*wps_tag_parse_func)(const char *wps_bufptr,
83 struct wps_token *token, struct wps_data *wps_data);
76 84
77struct wps_tag { 85struct wps_tag {
78 enum wps_token_type type; 86 enum wps_token_type type;
@@ -82,17 +90,27 @@ struct wps_tag {
82}; 90};
83 91
84/* prototypes of all special parse functions : */ 92/* prototypes of all special parse functions : */
85static int parse_subline_timeout(const char *wps_bufptr, struct wps_data *wps_data); 93static int parse_subline_timeout(const char *wps_bufptr,
86static int parse_progressbar(const char *wps_bufptr, struct wps_data *wps_data); 94 struct wps_token *token, struct wps_data *wps_data);
87static int parse_dir_level(const char *wps_bufptr, struct wps_data *wps_data); 95static int parse_progressbar(const char *wps_bufptr,
96 struct wps_token *token, struct wps_data *wps_data);
97static int parse_dir_level(const char *wps_bufptr,
98 struct wps_token *token, struct wps_data *wps_data);
88#ifdef HAVE_LCD_BITMAP 99#ifdef HAVE_LCD_BITMAP
89static int parse_image_special(const char *wps_bufptr, struct wps_data *wps_data); 100static int parse_image_special(const char *wps_bufptr,
90static int parse_statusbar(const char *wps_bufptr, struct wps_data *wps_data); 101 struct wps_token *token, struct wps_data *wps_data);
91static int parse_image_display(const char *wps_bufptr, struct wps_data *wps_data); 102static int parse_statusbar_enable(const char *wps_bufptr,
92static int parse_image_load(const char *wps_bufptr, struct wps_data *wps_data); 103 struct wps_token *token, struct wps_data *wps_data);
104static int parse_statusbar_disable(const char *wps_bufptr,
105 struct wps_token *token, struct wps_data *wps_data);
106static int parse_image_display(const char *wps_bufptr,
107 struct wps_token *token, struct wps_data *wps_data);
108static int parse_image_load(const char *wps_bufptr,
109 struct wps_token *token, struct wps_data *wps_data);
93#endif /*HAVE_LCD_BITMAP */ 110#endif /*HAVE_LCD_BITMAP */
94#if CONFIG_RTC 111#if CONFIG_RTC
95static int parse_rtc_format(const char *wps_bufptr, struct wps_data *wps_data); 112static int parse_rtc_format(const char *wps_bufptr,
113 struct wps_token *token, struct wps_data *wps_data);
96 114
97/* RTC tokens array */ 115/* RTC tokens array */
98static const struct wps_tag rtc_tags[] = { 116static const struct wps_tag rtc_tags[] = {
@@ -113,8 +131,8 @@ static const struct wps_tag rtc_tags[] = {
113 { WPS_TOKEN_RTC_MONTH_NAME, "b", 0, NULL }, 131 { WPS_TOKEN_RTC_MONTH_NAME, "b", 0, NULL },
114 { WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON, "u", 0, NULL }, 132 { WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON, "u", 0, NULL },
115 { WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN, "w", 0, NULL }, 133 { WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN, "w", 0, NULL },
116 { WPS_TOKEN_CHARACTER, "\0",0, NULL } 134 { WPS_TOKEN_CHARACTER, "", 0, NULL }
117 /* the array MUST end with a "\0" token */ 135 /* the array MUST end with an empty string (first char is \0) */
118}; 136};
119#endif 137#endif
120 138
@@ -229,29 +247,30 @@ static const struct wps_tag all_tags[] = {
229 { WPS_TOKEN_REPLAYGAIN, "rg", WPS_REFRESH_STATIC, NULL }, 247 { WPS_TOKEN_REPLAYGAIN, "rg", WPS_REFRESH_STATIC, NULL },
230#endif 248#endif
231 249
232 { WPS_TOKEN_SCROLL, "s", WPS_REFRESH_SCROLL, NULL }, 250 { WPS_NO_TOKEN, "s", WPS_REFRESH_SCROLL, NULL },
233 { WPS_TOKEN_SUBLINE_TIMEOUT, "t", 0, parse_subline_timeout }, 251 { WPS_TOKEN_SUBLINE_TIMEOUT, "t", 0, parse_subline_timeout },
234 252
235#ifdef HAVE_LCD_BITMAP 253#ifdef HAVE_LCD_BITMAP
236 { WPS_TOKEN_STATUSBAR_ENABLED, "we", 0, parse_statusbar }, 254 { WPS_NO_TOKEN, "we", 0, parse_statusbar_enable },
237 { WPS_TOKEN_STATUSBAR_DISABLED, "wd", 0, parse_statusbar }, 255 { WPS_NO_TOKEN, "wd", 0, parse_statusbar_disable },
238 256
239 { WPS_NO_TOKEN, "xl", 0, parse_image_load }, 257 { WPS_NO_TOKEN, "xl", 0, parse_image_load },
240 258
241 { WPS_TOKEN_IMAGE_PRELOAD_DISPLAY, "xd", WPS_REFRESH_STATIC, parse_image_display }, 259 { WPS_TOKEN_IMAGE_PRELOAD_DISPLAY, "xd", WPS_REFRESH_STATIC, parse_image_display },
242 260
243 { WPS_TOKEN_IMAGE_DISPLAY, "x", 0, parse_image_load }, 261 { WPS_TOKEN_IMAGE_DISPLAY, "x", 0, parse_image_load },
244 { WPS_TOKEN_IMAGE_PROGRESS_BAR, "P", 0, parse_image_special }, 262 { WPS_TOKEN_IMAGE_PROGRESS_BAR, "P", 0, parse_image_special },
245#if LCD_DEPTH > 1 263#if LCD_DEPTH > 1
246 { WPS_TOKEN_IMAGE_BACKDROP, "X", 0, parse_image_special }, 264 { WPS_TOKEN_IMAGE_BACKDROP, "X", 0, parse_image_special },
247#endif 265#endif
248#endif 266#endif
249 267
250 { WPS_TOKEN_UNKNOWN, "\0", 0, NULL } 268 { WPS_TOKEN_UNKNOWN, "", 0, NULL }
251 /* the array MUST end with a "\0" token */ 269 /* the array MUST end with an empty string (first char is \0) */
252}; 270};
253 271
254 272/* Returns the number of chars that should be skipped to jump
273 immediately after the first eol, i.e. to the start of the next line */
255static int skip_end_of_line(const char *wps_bufptr) 274static int skip_end_of_line(const char *wps_bufptr)
256{ 275{
257 int skip = 0; 276 int skip = 0;
@@ -260,10 +279,20 @@ static int skip_end_of_line(const char *wps_bufptr)
260 return ++skip; 279 return ++skip;
261} 280}
262 281
282/* Starts a new subline in the current line during parsing */
283static void wps_start_new_subline(struct wps_data *data) {
284 data->num_sublines++;
285 data->sublines[data->num_sublines].first_token_idx = data->num_tokens;
286 data->lines[data->num_lines].num_sublines++;
287}
288
263#if CONFIG_RTC 289#if CONFIG_RTC
264static int parse_rtc_format(const char *wps_bufptr, struct wps_data *wps_data) 290static int parse_rtc_format(const char *wps_bufptr,
291 struct wps_token *token,
292 struct wps_data *wps_data)
265{ 293{
266 int skip = 0, i; 294 int skip = 0, i;
295 (void)token; /* kill the warning */
267 296
268 /* RTC tag format ends with a c or a newline */ 297 /* RTC tag format ends with a c or a newline */
269 while (wps_bufptr && *wps_bufptr != 'c' && *wps_bufptr != '\n') 298 while (wps_bufptr && *wps_bufptr != 'c' && *wps_bufptr != '\n')
@@ -276,7 +305,7 @@ static int parse_rtc_format(const char *wps_bufptr, struct wps_data *wps_data)
276 wps_data->num_tokens++; 305 wps_data->num_tokens++;
277 wps_data->tokens[wps_data->num_tokens].type = rtc_tags[i].type; 306 wps_data->tokens[wps_data->num_tokens].type = rtc_tags[i].type;
278 wps_data->tokens[wps_data->num_tokens].value.c = *wps_bufptr; 307 wps_data->tokens[wps_data->num_tokens].value.c = *wps_bufptr;
279 skip ++; 308 skip++;
280 wps_bufptr++; 309 wps_bufptr++;
281 } 310 }
282 311
@@ -290,16 +319,23 @@ static int parse_rtc_format(const char *wps_bufptr, struct wps_data *wps_data)
290 319
291#ifdef HAVE_LCD_BITMAP 320#ifdef HAVE_LCD_BITMAP
292 321
293static int parse_statusbar(const char *wps_bufptr, struct wps_data *wps_data) 322static int parse_statusbar_enable(const char *wps_bufptr,
323 struct wps_token *token,
324 struct wps_data *wps_data)
294{ 325{
326 (void)token; /* Kill warnings */
295 wps_data->wps_sb_tag = true; 327 wps_data->wps_sb_tag = true;
328 wps_data->show_sb_on_wps = true;
329 return skip_end_of_line(wps_bufptr);
330}
296 331
297 if (wps_data->tokens[wps_data->num_tokens].type == WPS_TOKEN_STATUSBAR_ENABLED) 332static int parse_statusbar_disable(const char *wps_bufptr,
298 wps_data->show_sb_on_wps = true; 333 struct wps_token *token,
299 else 334 struct wps_data *wps_data)
300 wps_data->show_sb_on_wps = false; 335{
301 336 (void)token; /* Kill warnings */
302 /* Skip the rest of the line */ 337 wps_data->wps_sb_tag = true;
338 wps_data->show_sb_on_wps = false;
303 return skip_end_of_line(wps_bufptr); 339 return skip_end_of_line(wps_bufptr);
304} 340}
305 341
@@ -357,10 +393,12 @@ static char *get_image_filename(const char *start, const char* bmpdir,
357 return buf; 393 return buf;
358} 394}
359 395
360static int parse_image_display(const char *wps_bufptr, struct wps_data *wps_data) 396static int parse_image_display(const char *wps_bufptr,
397 struct wps_token *token,
398 struct wps_data *wps_data)
361{ 399{
362 int n = get_image_id(*wps_bufptr); 400 int n = get_image_id(*wps_bufptr);
363 wps_data->tokens[wps_data->num_tokens].value.i = n; 401 token->value.i = n;
364 402
365 /* if the image is in a conditional, remember it */ 403 /* if the image is in a conditional, remember it */
366 if (level >= 0) 404 if (level >= 0)
@@ -369,7 +407,9 @@ static int parse_image_display(const char *wps_bufptr, struct wps_data *wps_data
369 return 1; 407 return 1;
370} 408}
371 409
372static int parse_image_load(const char *wps_bufptr, struct wps_data *wps_data) 410static int parse_image_load(const char *wps_bufptr,
411 struct wps_token *token,
412 struct wps_data *wps_data)
373{ 413{
374 int n; 414 int n;
375 const char *ptr = wps_bufptr; 415 const char *ptr = wps_bufptr;
@@ -421,7 +461,7 @@ static int parse_image_load(const char *wps_bufptr, struct wps_data *wps_data)
421 return skip_end_of_line(wps_bufptr); 461 return skip_end_of_line(wps_bufptr);
422 } 462 }
423 463
424 if (wps_data->tokens[wps_data->num_tokens].type == WPS_TOKEN_IMAGE_DISPLAY) 464 if (token->type == WPS_TOKEN_IMAGE_DISPLAY)
425 wps_data->img[n].always_display = true; 465 wps_data->img[n].always_display = true;
426 } 466 }
427 467
@@ -429,15 +469,17 @@ static int parse_image_load(const char *wps_bufptr, struct wps_data *wps_data)
429 return skip_end_of_line(wps_bufptr); 469 return skip_end_of_line(wps_bufptr);
430} 470}
431 471
432static int parse_image_special(const char *wps_bufptr, struct wps_data *wps_data) 472static int parse_image_special(const char *wps_bufptr,
473 struct wps_token *token,
474 struct wps_data *wps_data)
433{ 475{
434 if (wps_data->tokens[wps_data->num_tokens].type == WPS_TOKEN_IMAGE_PROGRESS_BAR) 476 if (token->type == WPS_TOKEN_IMAGE_PROGRESS_BAR)
435 { 477 {
436 /* format: %P|filename.bmp| */ 478 /* format: %P|filename.bmp| */
437 pb_bmp_name = wps_bufptr + 1; 479 pb_bmp_name = wps_bufptr + 1;
438 } 480 }
439#if LCD_DEPTH > 1 481#if LCD_DEPTH > 1
440 else if (wps_data->tokens[wps_data->num_tokens].type == WPS_TOKEN_IMAGE_BACKDROP) 482 else if (token->type == WPS_TOKEN_IMAGE_BACKDROP)
441 { 483 {
442 /* format: %X|filename.bmp| */ 484 /* format: %X|filename.bmp| */
443 backdrop_bmp_name = wps_bufptr + 1; 485 backdrop_bmp_name = wps_bufptr + 1;
@@ -452,20 +494,27 @@ static int parse_image_special(const char *wps_bufptr, struct wps_data *wps_data
452 494
453#endif /* HAVE_LCD_BITMAP */ 495#endif /* HAVE_LCD_BITMAP */
454 496
455static int parse_dir_level(const char *wps_bufptr, struct wps_data *wps_data) 497static int parse_dir_level(const char *wps_bufptr,
498 struct wps_token *token,
499 struct wps_data *wps_data)
456{ 500{
457 char val[] = { *wps_bufptr, '\0' }; 501 char val[] = { *wps_bufptr, '\0' };
458 wps_data->tokens[wps_data->num_tokens].value.i = atoi(val); 502 token->value.i = atoi(val);
503 (void)wps_data; /* Kill warnings */
459 return 1; 504 return 1;
460} 505}
461 506
462static int parse_subline_timeout(const char *wps_bufptr, struct wps_data *wps_data) 507static int parse_subline_timeout(const char *wps_bufptr,
508 struct wps_token *token,
509 struct wps_data *wps_data)
463{ 510{
464 int skip = 0; 511 int skip = 0;
465 int val = 0; 512 int val = 0;
466 bool have_point = false; 513 bool have_point = false;
467 bool have_tenth = false; 514 bool have_tenth = false;
468 515
516 (void)wps_data; /* Kill the warning */
517
469 while ( isdigit(*wps_bufptr) || *wps_bufptr == '.' ) 518 while ( isdigit(*wps_bufptr) || *wps_bufptr == '.' )
470 { 519 {
471 if (*wps_bufptr != '.') 520 if (*wps_bufptr != '.')
@@ -490,13 +539,16 @@ static int parse_subline_timeout(const char *wps_bufptr, struct wps_data *wps_da
490 if (have_tenth == false) 539 if (have_tenth == false)
491 val *= 10; 540 val *= 10;
492 541
493 wps_data->tokens[wps_data->num_tokens].value.i = val; 542 token->value.i = val;
494 543
495 return skip; 544 return skip;
496} 545}
497 546
498static int parse_progressbar(const char *wps_bufptr, struct wps_data *wps_data) 547static int parse_progressbar(const char *wps_bufptr,
548 struct wps_token *token,
549 struct wps_data *wps_data)
499{ 550{
551 (void)token; /* Kill warnings */
500#ifdef HAVE_LCD_BITMAP 552#ifdef HAVE_LCD_BITMAP
501 553
502 short *vals[] = { 554 short *vals[] = {
@@ -547,9 +599,8 @@ static int parse_progressbar(const char *wps_bufptr, struct wps_data *wps_data)
547static int parse_token(const char *wps_bufptr, struct wps_data *wps_data) 599static int parse_token(const char *wps_bufptr, struct wps_data *wps_data)
548{ 600{
549 int skip = 0, taglen = 0; 601 int skip = 0, taglen = 0;
550 int i = 0; 602 struct wps_token *token = wps_data->tokens + wps_data->num_tokens;
551 int line = wps_data->num_lines; 603 const struct wps_tag *tag;
552 int subline = wps_data->num_sublines[line];
553 604
554 switch(*wps_bufptr) 605 switch(*wps_bufptr)
555 { 606 {
@@ -560,47 +611,47 @@ static int parse_token(const char *wps_bufptr, struct wps_data *wps_data)
560 case '>': 611 case '>':
561 case ';': 612 case ';':
562 /* escaped characters */ 613 /* escaped characters */
563 wps_data->tokens[wps_data->num_tokens].type = WPS_TOKEN_CHARACTER; 614 token->type = WPS_TOKEN_CHARACTER;
564 wps_data->tokens[wps_data->num_tokens].value.c = *wps_bufptr; 615 token->value.c = *wps_bufptr;
565 wps_data->num_tokens++; 616 wps_data->num_tokens++;
566 skip++; 617 skip++;
567 break; 618 break;
568 619
569 case '?': 620 case '?':
570 /* conditional tag */ 621 /* conditional tag */
571 wps_data->tokens[wps_data->num_tokens].type = WPS_TOKEN_CONDITIONAL; 622 token->type = WPS_TOKEN_CONDITIONAL;
572 level++; 623 level++;
573 condindex[level] = wps_data->num_tokens; 624 condindex[level] = wps_data->num_tokens;
574 numoptions[level] = 1; 625 numoptions[level] = 1;
575 wps_data->num_tokens++; 626 wps_data->num_tokens++;
627 token++;
576 wps_bufptr++; 628 wps_bufptr++;
577 skip++; 629 skip++;
578 /* no "break" because a '?' is followed by a regular tag */ 630 /* no "break" because a '?' is followed by a regular tag */
579 631
580 default: 632 default:
581 /* find what tag we have */ 633 /* find what tag we have */
582 while (all_tags[i].name && 634 for (tag = all_tags;
583 strncmp(wps_bufptr, all_tags[i].name, strlen(all_tags[i].name))) 635 strncmp(wps_bufptr, tag->name, strlen(tag->name)) != 0;
584 i++; 636 tag++) ;
585 637
586 taglen = strlen(all_tags[i].name); 638 taglen = strlen(tag->name);
587 skip += taglen; 639 skip += taglen;
588 wps_data->tokens[wps_data->num_tokens].type = all_tags[i].type; 640 token->type = tag->type;
641 wps_data->sublines[wps_data->num_sublines].line_type |= tag->refresh_type;
589 642
590 /* if the tag has a special parsing function, we call it */ 643 /* if the tag has a special parsing function, we call it */
591 if (all_tags[i].parse_func) 644 if (tag->parse_func)
592 skip += all_tags[i].parse_func(wps_bufptr + taglen, wps_data); 645 skip += tag->parse_func(wps_bufptr + taglen, token, wps_data);
593 646
594 /* Some tags we don't want to save as tokens */ 647 /* Some tags we don't want to save as tokens */
595 if (all_tags[i].type == WPS_NO_TOKEN) 648 if (tag->type == WPS_NO_TOKEN)
596 break; 649 break;
597 650
598 /* tags that start with 'F', 'I' or 'D' are for the next file */ 651 /* tags that start with 'F', 'I' or 'D' are for the next file */
599 if ( *(all_tags[i].name) == 'I' || *(all_tags[i].name) == 'F' 652 if ( *(tag->name) == 'I' || *(tag->name) == 'F' || *(tag->name) == 'D')
600 || *(all_tags[i].name) == 'D') 653 token->next = true;
601 wps_data->tokens[wps_data->num_tokens].next = true;
602 654
603 wps_data->line_type[line][subline] |= all_tags[i].refresh_type;
604 wps_data->num_tokens++; 655 wps_data->num_tokens++;
605 break; 656 break;
606 } 657 }
@@ -608,17 +659,19 @@ static int parse_token(const char *wps_bufptr, struct wps_data *wps_data)
608 return skip; 659 return skip;
609} 660}
610 661
662/* Parses the WPS.
663 data is the pointer to the structure where the parsed WPS should be stored.
664 It is initialised.
665 wps_bufptr points to the string containing the WPS tags */
611static bool wps_parse(struct wps_data *data, const char *wps_bufptr) 666static bool wps_parse(struct wps_data *data, const char *wps_bufptr)
612{ 667{
613 if (!data || !wps_bufptr || !*wps_bufptr) 668 if (!data || !wps_bufptr || !*wps_bufptr)
614 return false; 669 return false;
615 670
616 int subline;
617 data->num_tokens = 0;
618 char *current_string = data->string_buffer; 671 char *current_string = data->string_buffer;
619 672
620 while(wps_bufptr && *wps_bufptr && data->num_tokens < WPS_MAX_TOKENS 673 while(*wps_bufptr && data->num_tokens < WPS_MAX_TOKENS - 1
621 && data->num_lines < WPS_MAX_LINES) 674 && data->num_lines < WPS_MAX_LINES)
622 { 675 {
623 switch(*wps_bufptr++) 676 switch(*wps_bufptr++)
624 { 677 {
@@ -630,12 +683,8 @@ static bool wps_parse(struct wps_data *data, const char *wps_bufptr)
630 683
631 /* Alternating sublines separator */ 684 /* Alternating sublines separator */
632 case ';': 685 case ';':
633 if (data->num_sublines[data->num_lines]+1 < WPS_MAX_SUBLINES) 686 if (data->num_sublines+1 < WPS_MAX_SUBLINES)
634 { 687 wps_start_new_subline(data);
635 data->tokens[data->num_tokens++].type = WPS_TOKEN_SUBLINE_SEPARATOR;
636 subline = ++(data->num_sublines[data->num_lines]);
637 data->format_lines[data->num_lines][subline] = data->num_tokens;
638 }
639 else 688 else
640 wps_bufptr += skip_end_of_line(wps_bufptr); 689 wps_bufptr += skip_end_of_line(wps_bufptr);
641 690
@@ -694,13 +743,14 @@ condlistend: /* close a conditional. sometimes we want to close them even when
694 goto condlistend; 743 goto condlistend;
695 break; 744 break;
696 } 745 }
697 data->tokens[data->num_tokens++].type = WPS_TOKEN_EOL; 746 wps_start_new_subline(data);
698 (data->num_sublines[data->num_lines])++; 747 data->num_lines++; /* Start a new line */
699 data->num_lines++;
700 748
701 if (data->num_lines < WPS_MAX_LINES) 749 if ((data->num_lines < WPS_MAX_LINES) &&
750 (data->num_sublines < WPS_MAX_SUBLINES))
702 { 751 {
703 data->format_lines[data->num_lines][0] = data->num_tokens; 752 data->lines[data->num_lines].first_subline_idx = data->num_sublines;
753 data->sublines[data->num_sublines].first_token_idx = data->num_tokens;
704 } 754 }
705 755
706 break; 756 break;
@@ -777,8 +827,7 @@ void wps_data_init(struct wps_data *wps_data)
777 wps_data->img_buf_free = IMG_BUFSIZE; /* free space in image buffer */ 827 wps_data->img_buf_free = IMG_BUFSIZE; /* free space in image buffer */
778 wps_data->peak_meter_enabled = false; 828 wps_data->peak_meter_enabled = false;
779#else /* HAVE_LCD_CHARCELLS */ 829#else /* HAVE_LCD_CHARCELLS */
780 int i; 830 for (i = 0; i < 8; i++)
781 for(i = 0; i < 8; i++)
782 { 831 {
783 wps_data->wps_progress_pat[i] = 0; 832 wps_data->wps_progress_pat[i] = 0;
784 } 833 }