diff options
author | Jonathan Gordon <rockbox@jdgordon.info> | 2009-04-20 01:41:56 +0000 |
---|---|---|
committer | Jonathan Gordon <rockbox@jdgordon.info> | 2009-04-20 01:41:56 +0000 |
commit | 0eb5dc649f34ca136d0160bf5d43961a2c3cea05 (patch) | |
tree | 5082fcd0d0479979a51891e082e742e2cf769266 | |
parent | 88b509b7d258c820f2eeda513524acbf76dcaaf5 (diff) | |
download | rockbox-0eb5dc649f34ca136d0160bf5d43961a2c3cea05.tar.gz rockbox-0eb5dc649f34ca136d0160bf5d43961a2c3cea05.zip |
beginings of a working touchscreen interface for the WPS. 2 new tags:
%T|x|y|width|height|action| <- setup a region (relative to the current viewport) where if pressed the "action" will be done (currently play/stop/prev/next/menu/browse work, suggestions for others to add and better names welcome)
%Tl<timeout> <- used as a conditional to say if the touchscreen was touched in the last <timeout>, use this to enable/disable button viewports or something... same syntax as other timeout tags
cabbiev2 for the mr500 has been modified to demonstrate the new tags. press the pause/play button to pause playback. press the rockbox logo to get back to the menu. pretty icons needed to make this more usable :)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20753 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | apps/gui/gwps-common.c | 7 | ||||
-rw-r--r-- | apps/gui/gwps.c | 37 | ||||
-rw-r--r-- | apps/gui/gwps.h | 19 | ||||
-rw-r--r-- | apps/gui/wps_parser.c | 86 | ||||
-rw-r--r-- | firmware/drivers/button.c | 19 | ||||
-rw-r--r-- | firmware/export/button.h | 2 | ||||
-rw-r--r-- | uisimulator/sdl/button.c | 6 | ||||
-rw-r--r-- | wps/cabbiev2.320x240x16.mrobe500.wps | 47 |
8 files changed, 215 insertions, 8 deletions
diff --git a/apps/gui/gwps-common.c b/apps/gui/gwps-common.c index 5ab0097b2c..1fef9e02cb 100644 --- a/apps/gui/gwps-common.c +++ b/apps/gui/gwps-common.c | |||
@@ -1292,6 +1292,13 @@ static const char *get_token_value(struct gui_wps *gwps, | |||
1292 | token->value.i * TIMEOUT_UNIT)) | 1292 | token->value.i * TIMEOUT_UNIT)) |
1293 | return "v"; | 1293 | return "v"; |
1294 | return NULL; | 1294 | return NULL; |
1295 | case WPS_TOKEN_LASTTOUCH: | ||
1296 | #ifdef HAVE_TOUCHSCREEN | ||
1297 | if (TIME_BEFORE(current_tick, token->value.i * TIMEOUT_UNIT + | ||
1298 | touchscreen_last_touch())) | ||
1299 | return "t"; | ||
1300 | #endif | ||
1301 | return NULL; | ||
1295 | 1302 | ||
1296 | case WPS_TOKEN_SETTING: | 1303 | case WPS_TOKEN_SETTING: |
1297 | { | 1304 | { |
diff --git a/apps/gui/gwps.c b/apps/gui/gwps.c index 0c8a3aa2b1..26b531e332 100644 --- a/apps/gui/gwps.c +++ b/apps/gui/gwps.c | |||
@@ -293,7 +293,38 @@ void gwps_draw_statusbars(void) | |||
293 | { | 293 | { |
294 | viewportmanager_set_statusbar(wpsbars); | 294 | viewportmanager_set_statusbar(wpsbars); |
295 | } | 295 | } |
296 | 296 | #ifdef HAVE_TOUCHSCREEN | |
297 | static int wps_get_touchaction(struct wps_data *data) | ||
298 | { | ||
299 | short x,y; | ||
300 | short vx, vy; | ||
301 | int type = action_get_touchscreen_press(&x, &y); | ||
302 | int i; | ||
303 | struct touchregion *r; | ||
304 | if (type != BUTTON_REL) | ||
305 | return ACTION_TOUCHSCREEN; | ||
306 | for (i=0; i<data->touchregion_count; i++) | ||
307 | { | ||
308 | r = &data->touchregion[i]; | ||
309 | /* make sure this region's viewport is visible */ | ||
310 | if (r->wvp->hidden_flags&VP_DRAW_HIDDEN) | ||
311 | continue; | ||
312 | /* reposition the touch inside the viewport */ | ||
313 | vx = x - r->wvp->vp.x; | ||
314 | vy = y - r->wvp->vp.y; | ||
315 | /* check if its inside this viewport */ | ||
316 | if (vx >= 0 && vx < r->wvp->vp.x + r->wvp->vp.width && | ||
317 | vy >= 0 && vy < r->wvp->vp.y + r->wvp->vp.height) | ||
318 | { | ||
319 | /* now see if the point is inside this region */ | ||
320 | if (vx >= r->x && vx < r->x+r->width && | ||
321 | vy >= r->y && vy < r->y+r->height) | ||
322 | return r->action; | ||
323 | } | ||
324 | } | ||
325 | return ACTION_TOUCHSCREEN; | ||
326 | } | ||
327 | #endif | ||
297 | /* The WPS can be left in two ways: | 328 | /* The WPS can be left in two ways: |
298 | * a) call a function, which draws over the wps. In this case, the wps | 329 | * a) call a function, which draws over the wps. In this case, the wps |
299 | * will be still active (i.e. the below function didn't return) | 330 | * will be still active (i.e. the below function didn't return) |
@@ -393,6 +424,10 @@ long gui_wps_show(void) | |||
393 | playlist or if using the sleep timer. */ | 424 | playlist or if using the sleep timer. */ |
394 | if (!(audio_status() & AUDIO_STATUS_PLAY)) | 425 | if (!(audio_status() & AUDIO_STATUS_PLAY)) |
395 | exit = true; | 426 | exit = true; |
427 | #ifdef HAVE_TOUCHSCREEN | ||
428 | if (button == ACTION_TOUCHSCREEN) | ||
429 | button = wps_get_touchaction(gui_wps[SCREEN_MAIN].data); | ||
430 | #endif | ||
396 | /* The iPods/X5/M5 use a single button for the A-B mode markers, | 431 | /* The iPods/X5/M5 use a single button for the A-B mode markers, |
397 | defined as ACTION_WPSAB_SINGLE in their config files. */ | 432 | defined as ACTION_WPSAB_SINGLE in their config files. */ |
398 | #ifdef ACTION_WPSAB_SINGLE | 433 | #ifdef ACTION_WPSAB_SINGLE |
diff --git a/apps/gui/gwps.h b/apps/gui/gwps.h index 1042e1a795..935e015c93 100644 --- a/apps/gui/gwps.h +++ b/apps/gui/gwps.h | |||
@@ -88,6 +88,8 @@ struct progressbar { | |||
88 | }; | 88 | }; |
89 | #endif | 89 | #endif |
90 | 90 | ||
91 | |||
92 | |||
91 | struct align_pos { | 93 | struct align_pos { |
92 | char* left; | 94 | char* left; |
93 | char* center; | 95 | char* center; |
@@ -297,6 +299,7 @@ enum wps_token_type { | |||
297 | 299 | ||
298 | /* buttons */ | 300 | /* buttons */ |
299 | WPS_TOKEN_BUTTON_VOLUME, | 301 | WPS_TOKEN_BUTTON_VOLUME, |
302 | WPS_TOKEN_LASTTOUCH, | ||
300 | 303 | ||
301 | /* Setting option */ | 304 | /* Setting option */ |
302 | WPS_TOKEN_SETTING, | 305 | WPS_TOKEN_SETTING, |
@@ -363,6 +366,17 @@ struct wps_viewport { | |||
363 | char label; | 366 | char label; |
364 | }; | 367 | }; |
365 | 368 | ||
369 | #ifdef HAVE_TOUCHSCREEN | ||
370 | struct touchregion { | ||
371 | struct wps_viewport* wvp;/* The viewport this region is in */ | ||
372 | short int x; /* x-pos */ | ||
373 | short int y; /* y-pos */ | ||
374 | short int width; /* width */ | ||
375 | short int height; /* height */ | ||
376 | int action; /* action this button will return */ | ||
377 | }; | ||
378 | #define MAX_TOUCHREGIONS 12 | ||
379 | #endif | ||
366 | /* wps_data | 380 | /* wps_data |
367 | this struct holds all necessary data which describes the | 381 | this struct holds all necessary data which describes the |
368 | viewable content of a wps */ | 382 | viewable content of a wps */ |
@@ -399,6 +413,11 @@ struct wps_data | |||
399 | bool full_line_progressbar; | 413 | bool full_line_progressbar; |
400 | #endif | 414 | #endif |
401 | 415 | ||
416 | #ifdef HAVE_TOUCHSCREEN | ||
417 | struct touchregion touchregion[MAX_TOUCHREGIONS]; | ||
418 | short touchregion_count; | ||
419 | #endif | ||
420 | |||
402 | #ifdef HAVE_REMOTE_LCD | 421 | #ifdef HAVE_REMOTE_LCD |
403 | bool remote_wps; | 422 | bool remote_wps; |
404 | #endif | 423 | #endif |
diff --git a/apps/gui/wps_parser.c b/apps/gui/wps_parser.c index 390df56cbb..290f370fe7 100644 --- a/apps/gui/wps_parser.c +++ b/apps/gui/wps_parser.c | |||
@@ -121,7 +121,7 @@ struct wps_tag { | |||
121 | unsigned char refresh_type; | 121 | unsigned char refresh_type; |
122 | const wps_tag_parse_func parse_func; | 122 | const wps_tag_parse_func parse_func; |
123 | }; | 123 | }; |
124 | 124 | static int skip_end_of_line(const char *wps_bufptr); | |
125 | /* prototypes of all special parse functions : */ | 125 | /* prototypes of all special parse functions : */ |
126 | static int parse_timeout(const char *wps_bufptr, | 126 | static int parse_timeout(const char *wps_bufptr, |
127 | struct wps_token *token, struct wps_data *wps_data); | 127 | struct wps_token *token, struct wps_data *wps_data); |
@@ -131,7 +131,7 @@ static int parse_dir_level(const char *wps_bufptr, | |||
131 | struct wps_token *token, struct wps_data *wps_data); | 131 | struct wps_token *token, struct wps_data *wps_data); |
132 | static int parse_setting(const char *wps_bufptr, | 132 | static int parse_setting(const char *wps_bufptr, |
133 | struct wps_token *token, struct wps_data *wps_data); | 133 | struct wps_token *token, struct wps_data *wps_data); |
134 | 134 | ||
135 | #ifdef HAVE_LCD_BITMAP | 135 | #ifdef HAVE_LCD_BITMAP |
136 | static int parse_viewport_display(const char *wps_bufptr, | 136 | static int parse_viewport_display(const char *wps_bufptr, |
137 | struct wps_token *token, struct wps_data *wps_data); | 137 | struct wps_token *token, struct wps_data *wps_data); |
@@ -156,7 +156,18 @@ static int parse_albumart_load(const char *wps_bufptr, | |||
156 | static int parse_albumart_conditional(const char *wps_bufptr, | 156 | static int parse_albumart_conditional(const char *wps_bufptr, |
157 | struct wps_token *token, struct wps_data *wps_data); | 157 | struct wps_token *token, struct wps_data *wps_data); |
158 | #endif /* HAVE_ALBUMART */ | 158 | #endif /* HAVE_ALBUMART */ |
159 | 159 | #ifdef HAVE_TOUCHSCREEN | |
160 | static int parse_touchregion(const char *wps_bufptr, | ||
161 | struct wps_token *token, struct wps_data *wps_data); | ||
162 | #else | ||
163 | static int fulline_tag_not_supported(const char *wps_bufptr, | ||
164 | struct wps_token *token, struct wps_data *wps_data) | ||
165 | { | ||
166 | (void)token; (void)wps_data; | ||
167 | return skip_end_of_line(wps_bufptr); | ||
168 | } | ||
169 | #define parse_touchregion fulline_tag_not_supported | ||
170 | #endif | ||
160 | #ifdef CONFIG_RTC | 171 | #ifdef CONFIG_RTC |
161 | #define WPS_RTC_REFRESH WPS_REFRESH_DYNAMIC | 172 | #define WPS_RTC_REFRESH WPS_REFRESH_DYNAMIC |
162 | #else | 173 | #else |
@@ -337,7 +348,10 @@ static const struct wps_tag all_tags[] = { | |||
337 | #endif | 348 | #endif |
338 | 349 | ||
339 | { WPS_TOKEN_SETTING, "St", WPS_REFRESH_DYNAMIC, parse_setting }, | 350 | { WPS_TOKEN_SETTING, "St", WPS_REFRESH_DYNAMIC, parse_setting }, |
340 | 351 | ||
352 | { WPS_TOKEN_LASTTOUCH, "Tl", WPS_REFRESH_DYNAMIC, parse_timeout }, | ||
353 | { WPS_NO_TOKEN, "T", 0, parse_touchregion }, | ||
354 | |||
341 | { WPS_TOKEN_UNKNOWN, "", 0, NULL } | 355 | { WPS_TOKEN_UNKNOWN, "", 0, NULL } |
342 | /* the array MUST end with an empty string (first char is \0) */ | 356 | /* the array MUST end with an empty string (first char is \0) */ |
343 | }; | 357 | }; |
@@ -1142,6 +1156,70 @@ static int parse_albumart_conditional(const char *wps_bufptr, | |||
1142 | }; | 1156 | }; |
1143 | #endif /* HAVE_ALBUMART */ | 1157 | #endif /* HAVE_ALBUMART */ |
1144 | 1158 | ||
1159 | #ifdef HAVE_TOUCHSCREEN | ||
1160 | |||
1161 | struct touchaction {char* s; int action;}; | ||
1162 | static struct touchaction touchactions[] = { | ||
1163 | {"play", ACTION_WPS_PLAY }, {"stop", ACTION_WPS_STOP }, | ||
1164 | {"prev", ACTION_WPS_SKIPPREV }, {"next", ACTION_WPS_SKIPNEXT }, | ||
1165 | {"menu", ACTION_WPS_MENU }, {"browse", ACTION_WPS_BROWSE } | ||
1166 | }; | ||
1167 | static int parse_touchregion(const char *wps_bufptr, | ||
1168 | struct wps_token *token, struct wps_data *wps_data) | ||
1169 | { | ||
1170 | (void)token; | ||
1171 | unsigned i; | ||
1172 | struct touchregion *region; | ||
1173 | const char *ptr = wps_bufptr; | ||
1174 | const char *action; | ||
1175 | int x,y,w,h; | ||
1176 | |||
1177 | /* format: %T|x|y|width|height|action| | ||
1178 | * action is one of: | ||
1179 | * play - play/pause playback | ||
1180 | * stop - stop playback, exit the wps | ||
1181 | * prev - prev track | ||
1182 | * next - next track | ||
1183 | * ffwd | ||
1184 | * rwd | ||
1185 | * menu - go back to the main menu | ||
1186 | * browse - go back to the file/db browser | ||
1187 | */ | ||
1188 | |||
1189 | if ((wps_data->touchregion_count +1 >= MAX_TOUCHREGIONS) || (*ptr != '|')) | ||
1190 | return WPS_ERROR_INVALID_PARAM; | ||
1191 | ptr++; | ||
1192 | |||
1193 | if (!(ptr = parse_list("dddds", NULL, '|', ptr, &x, &y, &w, &h, &action))) | ||
1194 | return WPS_ERROR_INVALID_PARAM; | ||
1195 | |||
1196 | /* Check there is a terminating | */ | ||
1197 | if (*ptr != '|') | ||
1198 | return WPS_ERROR_INVALID_PARAM; | ||
1199 | |||
1200 | /* should probably do some bounds checking here with the viewport... but later */ | ||
1201 | region = &wps_data->touchregion[wps_data->touchregion_count]; | ||
1202 | region->action = ACTION_NONE; | ||
1203 | region->x = x; | ||
1204 | region->y = y; | ||
1205 | region->width = w; | ||
1206 | region->height = h; | ||
1207 | region->wvp = &wps_data->viewports[wps_data->num_viewports]; | ||
1208 | i = 0; | ||
1209 | while ((region->action == ACTION_NONE) && | ||
1210 | (i < sizeof(touchactions)/sizeof(*touchactions))) | ||
1211 | { | ||
1212 | if (!strncmp(touchactions[i].s, action, strlen(touchactions[i].s))) | ||
1213 | region->action = touchactions[i].action; | ||
1214 | i++; | ||
1215 | } | ||
1216 | if (region->action == ACTION_NONE) | ||
1217 | return WPS_ERROR_INVALID_PARAM; | ||
1218 | wps_data->touchregion_count++; | ||
1219 | return skip_end_of_line(wps_bufptr); | ||
1220 | } | ||
1221 | #endif | ||
1222 | |||
1145 | /* Parse a generic token from the given string. Return the length read */ | 1223 | /* Parse a generic token from the given string. Return the length read */ |
1146 | static int parse_token(const char *wps_bufptr, struct wps_data *wps_data) | 1224 | static int parse_token(const char *wps_bufptr, struct wps_data *wps_data) |
1147 | { | 1225 | { |
diff --git a/firmware/drivers/button.c b/firmware/drivers/button.c index 7d4daafdc2..6fbe5de229 100644 --- a/firmware/drivers/button.c +++ b/firmware/drivers/button.c | |||
@@ -81,6 +81,9 @@ static int button_read(int *data); | |||
81 | static int button_read(void); | 81 | static int button_read(void); |
82 | #endif | 82 | #endif |
83 | 83 | ||
84 | #ifdef HAVE_TOUCHSCREEN | ||
85 | int last_touchscreen_touch; | ||
86 | #endif | ||
84 | #if defined(HAVE_HEADPHONE_DETECTION) | 87 | #if defined(HAVE_HEADPHONE_DETECTION) |
85 | static struct timeout hp_detect_timeout; /* Debouncer for headphone plug/unplug */ | 88 | static struct timeout hp_detect_timeout; /* Debouncer for headphone plug/unplug */ |
86 | /* This callback can be used for many different functions if needed - | 89 | /* This callback can be used for many different functions if needed - |
@@ -406,7 +409,9 @@ void button_init(void) | |||
406 | remote_filter_first_keypress = false; | 409 | remote_filter_first_keypress = false; |
407 | #endif | 410 | #endif |
408 | #endif | 411 | #endif |
409 | 412 | #ifdef HAVE_TOUCHSCREEN | |
413 | last_touchscreen_touch = 0xffff; | ||
414 | #endif | ||
410 | /* Start polling last */ | 415 | /* Start polling last */ |
411 | tick_add_task(button_tick); | 416 | tick_add_task(button_tick); |
412 | } | 417 | } |
@@ -522,7 +527,10 @@ static int button_read(void) | |||
522 | if (btn && flipped) | 527 | if (btn && flipped) |
523 | btn = button_flip(btn); /* swap upside down */ | 528 | btn = button_flip(btn); /* swap upside down */ |
524 | #endif | 529 | #endif |
525 | 530 | #ifdef HAVE_TOUCHSCREEN | |
531 | if (btn & BUTTON_TOUCHSCREEN) | ||
532 | last_touchscreen_touch = current_tick; | ||
533 | #endif | ||
526 | /* Filter the button status. It is only accepted if we get the same | 534 | /* Filter the button status. It is only accepted if we get the same |
527 | status twice in a row. */ | 535 | status twice in a row. */ |
528 | #ifndef HAVE_TOUCHSCREEN | 536 | #ifndef HAVE_TOUCHSCREEN |
@@ -536,7 +544,6 @@ static int button_read(void) | |||
536 | return retval; | 544 | return retval; |
537 | } | 545 | } |
538 | 546 | ||
539 | |||
540 | int button_status(void) | 547 | int button_status(void) |
541 | { | 548 | { |
542 | return lastbtn; | 549 | return lastbtn; |
@@ -547,6 +554,12 @@ void button_clear_queue(void) | |||
547 | queue_clear(&button_queue); | 554 | queue_clear(&button_queue); |
548 | } | 555 | } |
549 | 556 | ||
557 | #ifdef HAVE_TOUCHSCREEN | ||
558 | int touchscreen_last_touch(void) | ||
559 | { | ||
560 | return last_touchscreen_touch; | ||
561 | } | ||
562 | #endif | ||
550 | #endif /* SIMULATOR */ | 563 | #endif /* SIMULATOR */ |
551 | 564 | ||
552 | #ifdef HAVE_WHEEL_ACCELERATION | 565 | #ifdef HAVE_WHEEL_ACCELERATION |
diff --git a/firmware/export/button.h b/firmware/export/button.h index d5a8001fb7..3947f07207 100644 --- a/firmware/export/button.h +++ b/firmware/export/button.h | |||
@@ -68,6 +68,8 @@ int button_apply_acceleration(const unsigned int data); | |||
68 | #define BUTTON_TOUCHSCREEN 0x08000000 | 68 | #define BUTTON_TOUCHSCREEN 0x08000000 |
69 | 69 | ||
70 | #ifdef HAVE_TOUCHSCREEN | 70 | #ifdef HAVE_TOUCHSCREEN |
71 | int touchscreen_last_touch(void); | ||
72 | |||
71 | #if (!defined(BUTTON_TOPLEFT) || !defined(BUTTON_TOPMIDDLE) \ | 73 | #if (!defined(BUTTON_TOPLEFT) || !defined(BUTTON_TOPMIDDLE) \ |
72 | || !defined(BUTTON_TOPRIGHT) || !defined(BUTTON_MIDLEFT) \ | 74 | || !defined(BUTTON_TOPRIGHT) || !defined(BUTTON_MIDLEFT) \ |
73 | || !defined(BUTTON_CENTER) || !defined(BUTTON_MIDRIGHT) \ | 75 | || !defined(BUTTON_CENTER) || !defined(BUTTON_MIDRIGHT) \ |
diff --git a/uisimulator/sdl/button.c b/uisimulator/sdl/button.c index e9fa03cbef..9c8f334b43 100644 --- a/uisimulator/sdl/button.c +++ b/uisimulator/sdl/button.c | |||
@@ -36,6 +36,7 @@ static intptr_t button_data; /* data value from last message dequeued */ | |||
36 | #ifdef HAVE_TOUCHSCREEN | 36 | #ifdef HAVE_TOUCHSCREEN |
37 | #include "touchscreen.h" | 37 | #include "touchscreen.h" |
38 | static int mouse_coords = 0; | 38 | static int mouse_coords = 0; |
39 | static int last_touchscreen_touch = 0xffff; | ||
39 | #endif | 40 | #endif |
40 | /* how long until repeat kicks in */ | 41 | /* how long until repeat kicks in */ |
41 | #define REPEAT_START 6 | 42 | #define REPEAT_START 6 |
@@ -1310,11 +1311,16 @@ void mouse_tick_task(void) | |||
1310 | } | 1311 | } |
1311 | 1312 | ||
1312 | mouse_coords = (x<<16)|y; | 1313 | mouse_coords = (x<<16)|y; |
1314 | last_touchscreen_touch = current_tick; | ||
1313 | button_event(BUTTON_TOUCHSCREEN, true); | 1315 | button_event(BUTTON_TOUCHSCREEN, true); |
1314 | if (debug_wps) | 1316 | if (debug_wps) |
1315 | printf("Mouse at: (%d, %d)\n", x, y); | 1317 | printf("Mouse at: (%d, %d)\n", x, y); |
1316 | } | 1318 | } |
1317 | } | 1319 | } |
1320 | int touchscreen_last_touch(void) | ||
1321 | { | ||
1322 | return last_touchscreen_touch; | ||
1323 | } | ||
1318 | #endif | 1324 | #endif |
1319 | void button_init(void) | 1325 | void button_init(void) |
1320 | { | 1326 | { |
diff --git a/wps/cabbiev2.320x240x16.mrobe500.wps b/wps/cabbiev2.320x240x16.mrobe500.wps new file mode 100644 index 0000000000..222f51bc41 --- /dev/null +++ b/wps/cabbiev2.320x240x16.mrobe500.wps | |||
@@ -0,0 +1,47 @@ | |||
1 | # cabbie 2.0 default | ||
2 | # (C) 2007, Johannes Voggenthaler (Zinc Alloy) | ||
3 | #derived from "cabbie" (C) Yohann Misquitta | ||
4 | %wd | ||
5 | %T|286|207|24|24|play| | ||
6 | %T|0|207|84|24|menu| | ||
7 | %X|wpsbackdrop-320x240x16.bmp| | ||
8 | %xl|A|lock-320x240x16.bmp|91|207|2| | ||
9 | %xl|B|battery-320x240x16.bmp|126|207|10| | ||
10 | %xl|C|volume-320x240x16.bmp|177|207|10| | ||
11 | %xl|D|shuffle-320x240x16.bmp|218|211| | ||
12 | %xl|E|repeat-320x240x16.bmp|261|207|4| | ||
13 | %xl|F|playmode-320x240x16.bmp|286|207|5| | ||
14 | %Cl|16|32|s120|s120| | ||
15 | %pb|pb-320x240x16.bmp|10|162|300|15| | ||
16 | %?mh<%xdAa|%xdAb> | ||
17 | %?bp<%?bc<%xdBa|%xdBb>|%?bl<|%xdBc|%xdBd|%xdBe|%xdBf|%xdBg|%xdBh|%xdBi|%xdBj>> | ||
18 | %?pv<%xdCa|%xdCb|%xdCc|%xdCd|%xdCe|%xdCf|%xdCg|%xdCh|%xdCi|%xdCj> | ||
19 | %?ps<%xdD> | ||
20 | %?mm<|%xdEa|%xdEb|%xdEc|%xdEd> | ||
21 | %?mp<%xdFa|%xdFc|%xdFb|%xdFd|%xdFe> | ||
22 | %?C<%Vda%C|%Vdb> | ||
23 | #NowPlaying | ||
24 | |||
25 | %Vl|a|153|30|-|130|1|-|-| | ||
26 | %s%al%?it<%it|%fn> | ||
27 | %s%al%?ia<%ia|%?d2<%d2|(root)>> | ||
28 | %s%al%?id<%id|%?d1<%d1|(root)>> | ||
29 | #%s%al%iy | ||
30 | |||
31 | %s%alNext Track: | ||
32 | %s%al%?It<%It|%Fn> | ||
33 | %s%al%Ia | ||
34 | |||
35 | %Vl|b|0|30|-|130|1|-|-| | ||
36 | %s%ac%?it<%it|%fn> | ||
37 | %s%ac%?ia<%ia|%?d2<%d2|(root)>> | ||
38 | %s%ac%?id<%id|%?d1<%d1|(root)>> | ||
39 | %s%ac%iy | ||
40 | |||
41 | %acNext Track: | ||
42 | %s%ac%?It<%It|%Fn> | ||
43 | %s%ac%Ia | ||
44 | |||
45 | %V|0|180|-|20|1|-|-| | ||
46 | %al %pc%ac%pp of %pe%ar%pr | ||
47 | |||