1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2007 Nicolas Pennequin, Dan Everton, Matthias Mohr
11 * 2010 Jonathan Gordon
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
28 #include "core_alloc.h"
35 #include "skin_buffer.h"
36 #include "skin_parser.h"
37 #include "tag_table.h"
47 #define lang_is_rtl() (false)
59 #include "wps_internals.h"
60 #include "skin_engine.h"
62 #include "settings_list.h"
68 #ifdef HAVE_LCD_BITMAP
77 #include "statusbar-skinned.h"
79 #define WPS_ERROR_INVALID_PARAM -1
81 static char* skin_buffer
= NULL
;
82 void skinparser_set_buffer(char* pointer
)
84 skin_buffer
= pointer
;
87 #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
88 static char *backdrop_filename
;
91 static bool isdefault(struct skin_tag_parameter
*param
)
93 return param
->type
== DEFAULT
;
97 get_param_text(struct skin_element
*element
, int param_number
)
99 struct skin_tag_parameter
* params
= SKINOFFSETTOPTR(skin_buffer
, element
->params
);
100 return SKINOFFSETTOPTR(skin_buffer
, params
[param_number
].data
.text
);
103 static inline struct skin_element
*
104 get_param_code(struct skin_element
*element
, int param_number
)
106 struct skin_tag_parameter
* params
= SKINOFFSETTOPTR(skin_buffer
, element
->params
);
107 return SKINOFFSETTOPTR(skin_buffer
, params
[param_number
].data
.code
);
110 static inline struct skin_tag_parameter
*
111 get_param(struct skin_element
*element
, int param_number
)
113 struct skin_tag_parameter
* params
= SKINOFFSETTOPTR(skin_buffer
, element
->params
);
114 return ¶ms
[param_number
];
117 /* which screen are we parsing for? */
118 static enum screen_type curr_screen
;
120 /* the current viewport */
121 static struct skin_element
*curr_viewport_element
;
122 static struct skin_viewport
*curr_vp
;
123 static struct skin_element
*first_viewport
;
125 static struct line
*curr_line
;
127 static int follow_lang_direction
= 0;
129 typedef int (*parse_function
)(struct skin_element
*element
,
130 struct wps_token
*token
,
131 struct wps_data
*wps_data
);
133 #ifdef HAVE_LCD_BITMAP
134 /* add a skin_token_list item to the list chain. ALWAYS appended because some of the
135 * chains require the order to be kept.
137 static void add_to_ll_chain(OFFSETTYPE(struct skin_token_list
*) *listoffset
,
138 struct skin_token_list
*item
)
140 struct skin_token_list
*list
= SKINOFFSETTOPTR(skin_buffer
, *listoffset
);
143 *listoffset
= PTRTOSKINOFFSET(skin_buffer
, item
);
147 while (SKINOFFSETTOPTR(skin_buffer
, list
->next
))
148 list
= SKINOFFSETTOPTR(skin_buffer
, list
->next
);
149 list
->next
= PTRTOSKINOFFSET(skin_buffer
, item
);
156 void *skin_find_item(const char *label
, enum skin_find_what what
,
157 struct wps_data
*data
)
159 const char *itemlabel
= NULL
;
160 char *old_skin_buffer
= skin_buffer
;
161 char *databuf
= get_skin_buffer(data
);
163 struct skin_token_list
*linkedlist
;
164 struct skin_element
*vplist
;
166 bool isvplist
= false;
168 if (databuf
&& databuf
!= skin_buffer
)
169 skin_buffer
= get_skin_buffer(data
);
174 list
.vplist
= SKINOFFSETTOPTR(skin_buffer
, data
->tree
);
177 #ifdef HAVE_LCD_BITMAP
178 case SKIN_FIND_IMAGE
:
179 list
.linkedlist
= SKINOFFSETTOPTR(skin_buffer
, data
->images
);
182 #ifdef HAVE_TOUCHSCREEN
183 case SKIN_FIND_TOUCHREGION
:
184 list
.linkedlist
= SKINOFFSETTOPTR(skin_buffer
, data
->touchregions
);
187 #ifdef HAVE_SKIN_VARIABLES
189 list
.linkedlist
= SKINOFFSETTOPTR(skin_buffer
, data
->skinvars
);
194 while (list
.linkedlist
)
197 #ifdef HAVE_LCD_BITMAP
198 struct wps_token
*token
= NULL
;
200 token
= SKINOFFSETTOPTR(skin_buffer
, list
.linkedlist
->token
);
206 ret
= SKINOFFSETTOPTR(skin_buffer
, list
.vplist
->data
);
207 if (((struct skin_viewport
*)ret
)->label
== VP_DEFAULT_LABEL
)
208 itemlabel
= VP_DEFAULT_LABEL_STRING
;
210 itemlabel
= SKINOFFSETTOPTR(skin_buffer
, ((struct skin_viewport
*)ret
)->label
);
211 skip
= !(((struct skin_viewport
*)ret
)->is_infovp
==
212 (what
==SKIN_FIND_UIVP
));
214 #ifdef HAVE_LCD_BITMAP
215 case SKIN_FIND_IMAGE
:
216 ret
= SKINOFFSETTOPTR(skin_buffer
, token
->value
.data
);
217 itemlabel
= SKINOFFSETTOPTR(skin_buffer
, ((struct gui_img
*)ret
)->label
);
220 #ifdef HAVE_TOUCHSCREEN
221 case SKIN_FIND_TOUCHREGION
:
222 ret
= SKINOFFSETTOPTR(skin_buffer
, token
->value
.data
);
223 itemlabel
= SKINOFFSETTOPTR(skin_buffer
, ((struct touchregion
*)ret
)->label
);
226 #ifdef HAVE_SKIN_VARIABLES
228 ret
= SKINOFFSETTOPTR(skin_buffer
, token
->value
.data
);
229 itemlabel
= SKINOFFSETTOPTR(skin_buffer
, ((struct skin_var
*)ret
)->label
);
234 if (!skip
&& itemlabel
&& !strcmp(itemlabel
, label
))
236 if (old_skin_buffer
!= skin_buffer
)
237 skin_buffer
= old_skin_buffer
;
242 list
.vplist
= SKINOFFSETTOPTR(skin_buffer
, list
.vplist
->next
);
244 list
.linkedlist
= SKINOFFSETTOPTR(skin_buffer
, list
.linkedlist
->next
);
246 if (old_skin_buffer
!= skin_buffer
)
247 skin_buffer
= old_skin_buffer
;
251 #ifdef HAVE_LCD_BITMAP
253 /* create and init a new wpsll item.
254 * passing NULL to token will alloc a new one.
255 * You should only pass NULL for the token when the token type (table above)
256 * is WPS_NO_TOKEN which means it is not stored automatically in the skins token array
258 static struct skin_token_list
*new_skin_token_list_item(struct wps_token
*token
,
261 struct skin_token_list
*llitem
=
262 (struct skin_token_list
*)skin_buffer_alloc(sizeof(struct skin_token_list
));
264 token
= (struct wps_token
*)skin_buffer_alloc(sizeof(struct wps_token
));
265 if (!llitem
|| !token
)
267 llitem
->next
= PTRTOSKINOFFSET(skin_buffer
, NULL
);
268 llitem
->token
= PTRTOSKINOFFSET(skin_buffer
, token
);
270 token
->value
.data
= PTRTOSKINOFFSET(skin_buffer
, token_data
);
274 static int parse_statusbar_tags(struct skin_element
* element
,
275 struct wps_token
*token
,
276 struct wps_data
*wps_data
)
279 if (token
->type
== SKIN_TOKEN_DRAW_INBUILTBAR
)
281 token
->value
.data
= PTRTOSKINOFFSET(skin_buffer
, (void*)&curr_vp
->vp
);
285 struct skin_viewport
*default_vp
= SKINOFFSETTOPTR(skin_buffer
, first_viewport
->data
);
286 if (first_viewport
->params_count
== 0)
288 wps_data
->wps_sb_tag
= true;
289 wps_data
->show_sb_on_wps
= (token
->type
== SKIN_TOKEN_ENABLE_THEME
);
291 if (wps_data
->show_sb_on_wps
)
293 viewport_set_defaults(&default_vp
->vp
, curr_screen
);
297 viewport_set_fullscreen(&default_vp
->vp
, curr_screen
);
299 #ifdef HAVE_REMOTE_LCD
300 /* This parser requires viewports which will use the settings font to
301 * have font == 1, but the above viewport_set() calls set font to
302 * the current real font id. So force 1 here it will be set correctly
305 default_vp
->vp
.font
= 1;
311 static int get_image_id(int c
)
313 if(c
>= 'a' && c
<= 'z')
315 else if(c
>= 'A' && c
<= 'Z')
321 char *get_image_filename(const char *start
, const char* bmpdir
,
322 char *buf
, int buf_size
)
324 snprintf(buf
, buf_size
, "%s/%s", bmpdir
, start
);
329 static int parse_image_display(struct skin_element
*element
,
330 struct wps_token
*token
,
331 struct wps_data
*wps_data
)
333 char *label
= get_param_text(element
, 0);
334 char sublabel
= '\0';
337 struct image_display
*id
= skin_buffer_alloc(sizeof(struct image_display
));
339 if (element
->params_count
== 1 && strlen(label
) <= 2)
341 /* backwards compatability. Allow %xd(Aa) to still work */
346 img
= skin_find_item(label
, SKIN_FIND_IMAGE
, wps_data
);
349 return WPS_ERROR_INVALID_PARAM
;
351 id
->label
= img
->label
;
353 id
->token
= PTRTOSKINOFFSET(skin_buffer
, NULL
);
354 if (img
->using_preloaded_icons
)
356 token
->type
= SKIN_TOKEN_IMAGE_DISPLAY_LISTICON
;
359 if (element
->params_count
> 1)
361 if (get_param(element
, 1)->type
== CODE
)
362 id
->token
= get_param_code(element
, 1)->data
;
363 /* specify a number. 1 being the first subimage (i.e top) NOT 0 */
364 else if (get_param(element
, 1)->type
== INTEGER
)
365 id
->subimage
= get_param(element
, 1)->data
.number
- 1;
366 if (element
->params_count
> 2)
367 id
->offset
= get_param(element
, 2)->data
.number
;
371 if ((subimage
= get_image_id(sublabel
)) != -1)
373 if (subimage
>= img
->num_subimages
)
374 return WPS_ERROR_INVALID_PARAM
;
375 id
->subimage
= subimage
;
380 token
->value
.data
= PTRTOSKINOFFSET(skin_buffer
, id
);
384 static int parse_image_load(struct skin_element
*element
,
385 struct wps_token
*token
,
386 struct wps_data
*wps_data
)
388 const char* filename
;
390 int x
= 0,y
= 0, subimages
= 1;
393 /* format: %x(n,filename.bmp[,x,y])
394 or %xl(n,filename.bmp[,x,y])
395 or %xl(n,filename.bmp[,x,y,num_subimages])
398 id
= get_param_text(element
, 0);
399 filename
= get_param_text(element
, 1);
400 /* x,y,num_subimages handling:
401 * If all 3 are left out use sane defaults.
402 * If there are 2 params it must be x,y
403 * if there is only 1 param it must be the num_subimages
405 if (element
->params_count
== 3)
406 subimages
= get_param(element
, 2)->data
.number
;
407 else if (element
->params_count
> 3)
409 x
= get_param(element
, 2)->data
.number
;
410 y
= get_param(element
, 3)->data
.number
;
411 if (element
->params_count
== 5)
412 subimages
= get_param(element
, 4)->data
.number
;
414 /* check the image number and load state */
415 if(skin_find_item(id
, SKIN_FIND_IMAGE
, wps_data
))
417 /* Invalid image ID */
418 return WPS_ERROR_INVALID_PARAM
;
420 img
= (struct gui_img
*)skin_buffer_alloc(sizeof(struct gui_img
));
422 return WPS_ERROR_INVALID_PARAM
;
423 /* save a pointer to the filename */
424 img
->bm
.data
= (char*)filename
;
425 img
->label
= PTRTOSKINOFFSET(skin_buffer
, (void*)id
);
428 img
->num_subimages
= subimages
;
430 img
->using_preloaded_icons
= false;
431 img
->buflib_handle
= -1;
433 /* save current viewport */
434 img
->vp
= PTRTOSKINOFFSET(skin_buffer
, &curr_vp
->vp
);
436 if (token
->type
== SKIN_TOKEN_IMAGE_DISPLAY
)
437 token
->value
.data
= PTRTOSKINOFFSET(skin_buffer
, img
);
439 if (!strcmp(img
->bm
.data
, "__list_icons__"))
441 img
->num_subimages
= Icon_Last_Themeable
;
442 img
->using_preloaded_icons
= true;
445 struct skin_token_list
*item
=
446 (struct skin_token_list
*)new_skin_token_list_item(NULL
, img
);
448 return WPS_ERROR_INVALID_PARAM
;
449 add_to_ll_chain(&wps_data
->images
, item
);
454 int id
; /* the id from font_load */
455 char *name
; /* filename without path and extension */
456 int glyphs
; /* how many glyphs to reserve room for */
458 static struct skin_font skinfonts
[MAXUSERFONTS
];
459 static int parse_font_load(struct skin_element
*element
,
460 struct wps_token
*token
,
461 struct wps_data
*wps_data
)
463 (void)wps_data
; (void)token
;
464 int id
= get_param(element
, 0)->data
.number
;
465 char *filename
= get_param_text(element
, 1);
469 if(element
->params_count
> 2)
470 glyphs
= get_param(element
, 2)->data
.number
;
472 glyphs
= global_settings
.glyphs_to_cache
;
475 DEBUGF("font id must be >= 2\n");
478 #if defined(DEBUG) || defined(SIMULATOR)
479 if (skinfonts
[id
-2].name
!= NULL
)
481 DEBUGF("font id %d already being used\n", id
);
484 /* make sure the filename contains .fnt,
485 * we dont actually use it, but require it anyway */
486 ptr
= strchr(filename
, '.');
487 if (!ptr
|| strncmp(ptr
, ".fnt", 4))
488 return WPS_ERROR_INVALID_PARAM
;
489 skinfonts
[id
-2].id
= -1;
490 skinfonts
[id
-2].name
= filename
;
491 skinfonts
[id
-2].glyphs
= glyphs
;
497 #ifdef HAVE_LCD_BITMAP
499 static int parse_playlistview(struct skin_element
*element
,
500 struct wps_token
*token
,
501 struct wps_data
*wps_data
)
504 struct playlistviewer
*viewer
=
505 (struct playlistviewer
*)skin_buffer_alloc(sizeof(struct playlistviewer
));
507 return WPS_ERROR_INVALID_PARAM
;
508 viewer
->vp
= PTRTOSKINOFFSET(skin_buffer
, &curr_vp
->vp
);
509 viewer
->show_icons
= true;
510 viewer
->start_offset
= get_param(element
, 0)->data
.number
;
511 viewer
->line
= PTRTOSKINOFFSET(skin_buffer
, get_param_code(element
, 1));
513 token
->value
.data
= PTRTOSKINOFFSET(skin_buffer
, (void*)viewer
);
518 #ifdef HAVE_LCD_COLOR
519 static int parse_viewport_gradient_setup(struct skin_element
*element
,
520 struct wps_token
*token
,
521 struct wps_data
*wps_data
)
524 struct gradient_config
*cfg
;
525 if (element
->params_count
< 2) /* only start and end are required */
527 cfg
= (struct gradient_config
*)skin_buffer_alloc(sizeof(struct gradient_config
));
530 if (!parse_color(curr_screen
, get_param_text(element
, 0), &cfg
->start
) ||
531 !parse_color(curr_screen
, get_param_text(element
, 1), &cfg
->end
))
533 if (element
->params_count
> 2)
535 if (!parse_color(curr_screen
, get_param_text(element
, 2), &cfg
->text
))
540 cfg
->text
= curr_vp
->vp
.fg_pattern
;
543 token
->value
.data
= PTRTOSKINOFFSET(skin_buffer
, cfg
);
548 static int parse_listitem(struct skin_element
*element
,
549 struct wps_token
*token
,
550 struct wps_data
*wps_data
)
553 struct listitem
*li
= (struct listitem
*)skin_buffer_alloc(sizeof(struct listitem
));
556 token
->value
.data
= PTRTOSKINOFFSET(skin_buffer
, li
);
557 if (element
->params_count
== 0)
561 li
->offset
= get_param(element
, 0)->data
.number
;
562 if (element
->params_count
> 1)
563 li
->wrap
= strcasecmp(get_param_text(element
, 1), "nowrap") != 0;
570 static int parse_listitemviewport(struct skin_element
*element
,
571 struct wps_token
*token
,
572 struct wps_data
*wps_data
)
575 struct listitem_viewport_cfg
*cfg
=
576 (struct listitem_viewport_cfg
*)skin_buffer_alloc(
577 sizeof(struct listitem_viewport_cfg
));
580 cfg
->data
= wps_data
;
582 cfg
->label
= PTRTOSKINOFFSET(skin_buffer
, get_param_text(element
, 0));
585 if (!isdefault(get_param(element
, 1)))
586 cfg
->width
= get_param(element
, 1)->data
.number
;
587 if (!isdefault(get_param(element
, 2)))
588 cfg
->height
= get_param(element
, 2)->data
.number
;
589 if (element
->params_count
> 3 &&
590 !strcmp(get_param_text(element
, 3), "tile"))
592 token
->value
.data
= PTRTOSKINOFFSET(skin_buffer
, (void*)cfg
);
597 #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
598 static int parse_viewporttextstyle(struct skin_element
*element
,
599 struct wps_token
*token
,
600 struct wps_data
*wps_data
)
604 char *mode
= get_param_text(element
, 0);
607 if (!strcmp(mode
, "invert"))
609 style
= STYLE_INVERT
;
611 else if (!strcmp(mode
, "colour") || !strcmp(mode
, "color"))
613 if (element
->params_count
< 2 ||
614 !parse_color(curr_screen
, get_param_text(element
, 1), &colour
))
616 style
= STYLE_COLORED
|(STYLE_COLOR_MASK
&colour
);
618 #ifdef HAVE_LCD_COLOR
619 else if (!strcmp(mode
, "gradient"))
622 if (element
->params_count
< 2)
624 else /* atoi() instead of using a number in the parser is because [si]
625 * will select the number for something which looks like a colour
626 * making the "colour" case (above) harder to parse */
627 num_lines
= atoi(get_param_text(element
, 1));
628 style
= STYLE_GRADIENT
|NUMLN_PACK(num_lines
)|CURLN_PACK(0);
631 else if (!strcmp(mode
, "clear"))
633 style
= STYLE_DEFAULT
;
637 token
->value
.l
= style
;
641 static int parse_drawrectangle( struct skin_element
*element
,
642 struct wps_token
*token
,
643 struct wps_data
*wps_data
)
646 struct draw_rectangle
*rect
=
647 (struct draw_rectangle
*)skin_buffer_alloc(sizeof(struct draw_rectangle
));
652 rect
->x
= get_param(element
, 0)->data
.number
;
653 rect
->y
= get_param(element
, 1)->data
.number
;
655 if (isdefault(get_param(element
, 2)))
656 rect
->width
= curr_vp
->vp
.width
- rect
->x
;
658 rect
->width
= get_param(element
, 2)->data
.number
;
660 if (isdefault(get_param(element
, 3)))
661 rect
->height
= curr_vp
->vp
.height
- rect
->y
;
663 rect
->height
= get_param(element
, 3)->data
.number
;
665 rect
->start_colour
= curr_vp
->vp
.fg_pattern
;
666 rect
->end_colour
= curr_vp
->vp
.fg_pattern
;
668 if (element
->params_count
> 4)
670 if (!parse_color(curr_screen
, get_param_text(element
, 4),
671 &rect
->start_colour
))
673 rect
->end_colour
= rect
->start_colour
;
675 if (element
->params_count
> 5)
677 if (!parse_color(curr_screen
, get_param_text(element
, 5),
681 token
->value
.data
= PTRTOSKINOFFSET(skin_buffer
, rect
);
686 static int parse_viewportcolour(struct skin_element
*element
,
687 struct wps_token
*token
,
688 struct wps_data
*wps_data
)
691 struct skin_tag_parameter
*param
= get_param(element
, 0);
692 struct viewport_colour
*colour
=
693 (struct viewport_colour
*)skin_buffer_alloc(sizeof(struct viewport_colour
));
696 if (isdefault(param
))
698 colour
->colour
= get_viewport_default_colour(curr_screen
,
699 token
->type
== SKIN_TOKEN_VIEWPORT_FGCOLOUR
);
703 if (!parse_color(curr_screen
, SKINOFFSETTOPTR(skin_buffer
, param
->data
.text
),
707 colour
->vp
= PTRTOSKINOFFSET(skin_buffer
, &curr_vp
->vp
);
708 token
->value
.data
= PTRTOSKINOFFSET(skin_buffer
, colour
);
709 if (element
->line
== curr_viewport_element
->line
)
711 if (token
->type
== SKIN_TOKEN_VIEWPORT_FGCOLOUR
)
713 curr_vp
->start_fgcolour
= colour
->colour
;
714 curr_vp
->vp
.fg_pattern
= colour
->colour
;
718 curr_vp
->start_bgcolour
= colour
->colour
;
719 curr_vp
->vp
.bg_pattern
= colour
->colour
;
725 static int parse_image_special(struct skin_element
*element
,
726 struct wps_token
*token
,
727 struct wps_data
*wps_data
)
729 (void)wps_data
; /* kill warning */
734 if (token
->type
== SKIN_TOKEN_IMAGE_BACKDROP
)
736 if (isdefault(get_param(element
, 0)))
742 filename
= get_param_text(element
, 0);
743 /* format: %X(filename.bmp) or %X(d) */
744 if (!strcmp(filename
, "d"))
747 backdrop_filename
= filename
;
755 #endif /* HAVE_LCD_BITMAP */
757 static int parse_setting_and_lang(struct skin_element
*element
,
758 struct wps_token
*token
,
759 struct wps_data
*wps_data
)
761 /* NOTE: both the string validations that happen in here will
762 * automatically PASS on checkwps because its too hard to get
763 * settings_list.c and english.lang built for it.
764 * If that ever changes remove the #ifndef __PCTOOL__'s here
767 char *temp
= get_param_text(element
, 0);
770 if (token
->type
== SKIN_TOKEN_TRANSLATEDSTRING
)
773 i
= lang_english_to_id(temp
);
775 return WPS_ERROR_INVALID_PARAM
;
781 if (find_setting_by_cfgname(temp
, &i
) == NULL
)
782 return WPS_ERROR_INVALID_PARAM
;
785 /* Store the setting number */
790 static int parse_logical_andor(struct skin_element
*element
,
791 struct wps_token
*token
,
792 struct wps_data
*wps_data
)
795 token
->value
.data
= PTRTOSKINOFFSET(skin_buffer
, element
);
799 static int parse_logical_if(struct skin_element
*element
,
800 struct wps_token
*token
,
801 struct wps_data
*wps_data
)
804 char *op
= get_param_text(element
, 1);
805 struct logical_if
*lif
= skin_buffer_alloc(sizeof(struct logical_if
));
808 token
->value
.data
= PTRTOSKINOFFSET(skin_buffer
, lif
);
809 lif
->token
= get_param_code(element
, 0)->data
;
811 if (!strncmp(op
, "=", 1))
813 else if (!strncmp(op
, "!=", 2))
814 lif
->op
= IF_NOTEQUALS
;
815 else if (!strncmp(op
, ">=", 2))
816 lif
->op
= IF_GREATERTHAN_EQ
;
817 else if (!strncmp(op
, "<=", 2))
818 lif
->op
= IF_LESSTHAN_EQ
;
819 else if (!strncmp(op
, ">", 2))
820 lif
->op
= IF_GREATERTHAN
;
821 else if (!strncmp(op
, "<", 1))
822 lif
->op
= IF_LESSTHAN
;
824 memcpy(&lif
->operand
, get_param(element
, 2), sizeof(lif
->operand
));
825 if (element
->params_count
> 3)
826 lif
->num_options
= get_param(element
, 3)->data
.number
;
828 lif
->num_options
= TOKEN_VALUE_ONLY
;
833 static int parse_timeout_tag(struct skin_element
*element
,
834 struct wps_token
*token
,
835 struct wps_data
*wps_data
)
839 if (element
->params_count
== 0)
843 case SKIN_TOKEN_SUBLINE_TIMEOUT
:
845 case SKIN_TOKEN_BUTTON_VOLUME
:
846 case SKIN_TOKEN_TRACK_STARTING
:
847 case SKIN_TOKEN_TRACK_ENDING
:
855 val
= get_param(element
, 0)->data
.number
;
856 token
->value
.i
= val
* TIMEOUT_UNIT
;
860 static int parse_substring_tag(struct skin_element
* element
,
861 struct wps_token
*token
,
862 struct wps_data
*wps_data
)
865 struct substring
*ss
= (struct substring
*)skin_buffer_alloc(sizeof(struct substring
));
868 ss
->start
= get_param(element
, 0)->data
.number
;
869 if (get_param(element
, 1)->type
== DEFAULT
)
872 ss
->length
= get_param(element
, 1)->data
.number
;
873 ss
->token
= get_param_code(element
, 2)->data
;
874 if (element
->params_count
> 3)
875 ss
->expect_number
= !strcmp(get_param_text(element
, 3), "number");
877 ss
->expect_number
= false;
878 token
->value
.data
= PTRTOSKINOFFSET(skin_buffer
, ss
);
882 static int parse_progressbar_tag(struct skin_element
* element
,
883 struct wps_token
*token
,
884 struct wps_data
*wps_data
)
886 #ifdef HAVE_LCD_BITMAP
887 struct progressbar
*pb
;
888 struct viewport
*vp
= &curr_vp
->vp
;
889 struct skin_tag_parameter
*param
= get_param(element
, 0);
891 char *image_filename
= NULL
;
893 if (element
->params_count
== 0 &&
894 element
->tag
->type
!= SKIN_TOKEN_PROGRESSBAR
)
895 return 0; /* nothing to do */
896 pb
= (struct progressbar
*)skin_buffer_alloc(sizeof(struct progressbar
));
898 token
->value
.data
= PTRTOSKINOFFSET(skin_buffer
, pb
);
901 return WPS_ERROR_INVALID_PARAM
;
902 pb
->vp
= PTRTOSKINOFFSET(skin_buffer
, vp
);
903 pb
->follow_lang_direction
= follow_lang_direction
> 0;
906 pb
->image
= PTRTOSKINOFFSET(skin_buffer
, NULL
);
907 pb
->slider
= PTRTOSKINOFFSET(skin_buffer
, NULL
);
908 pb
->backdrop
= PTRTOSKINOFFSET(skin_buffer
, NULL
);
909 pb
->invert_fill_direction
= false;
910 pb
->horizontal
= true;
912 if (element
->params_count
== 0)
915 pb
->width
= vp
->width
;
916 pb
->height
= SYSFONT_HEIGHT
-2;
917 pb
->y
= -1; /* Will be computed during the rendering */
918 pb
->type
= element
->tag
->type
;
922 /* (x, y, width, height, ...) */
923 if (!isdefault(param
))
924 pb
->x
= param
->data
.number
;
929 if (!isdefault(param
))
930 pb
->y
= param
->data
.number
;
932 pb
->y
= -1; /* computed at rendering */
935 if (!isdefault(param
))
936 pb
->width
= param
->data
.number
;
938 pb
->width
= vp
->width
- pb
->x
;
941 if (!isdefault(param
))
943 /* A zero height makes no sense - reject it */
944 if (param
->data
.number
== 0)
945 return WPS_ERROR_INVALID_PARAM
;
947 pb
->height
= param
->data
.number
;
951 if (vp
->font
> FONT_UI
)
952 pb
->height
= -1; /* calculate at display time */
956 pb
->height
= font_get(vp
->font
)->height
;
962 /* optional params, first is the image filename if it isnt recognised as a keyword */
965 if (isdefault(get_param(element
, curr_param
)))
971 pb
->horizontal
= pb
->width
> pb
->height
;
972 while (curr_param
< element
->params_count
)
976 text
= SKINOFFSETTOPTR(skin_buffer
, param
->data
.text
);
977 if (!strcmp(text
, "invert"))
978 pb
->invert_fill_direction
= true;
979 else if (!strcmp(text
, "nofill"))
981 else if (!strcmp(text
, "nobar"))
983 else if (!strcmp(text
, "slider"))
985 if (curr_param
+1 < element
->params_count
)
989 text
= SKINOFFSETTOPTR(skin_buffer
, param
->data
.text
);
990 pb
->slider
= PTRTOSKINOFFSET(skin_buffer
,
991 skin_find_item(text
, SKIN_FIND_IMAGE
, wps_data
));
993 else /* option needs the next param */
996 else if (!strcmp(text
, "image"))
998 if (curr_param
+1 < element
->params_count
)
1002 image_filename
= SKINOFFSETTOPTR(skin_buffer
, param
->data
.text
);
1004 else /* option needs the next param */
1007 else if (!strcmp(text
, "backdrop"))
1009 if (curr_param
+1 < element
->params_count
)
1013 text
= SKINOFFSETTOPTR(skin_buffer
, param
->data
.text
);
1014 pb
->backdrop
= PTRTOSKINOFFSET(skin_buffer
,
1015 skin_find_item(text
, SKIN_FIND_IMAGE
, wps_data
));
1018 else /* option needs the next param */
1021 else if (!strcmp(text
, "vertical"))
1023 pb
->horizontal
= false;
1024 if (isdefault(get_param(element
, 3)))
1025 pb
->height
= vp
->height
- pb
->y
;
1027 else if (!strcmp(text
, "horizontal"))
1028 pb
->horizontal
= true;
1029 else if (curr_param
== 4)
1030 image_filename
= text
;
1037 pb
->image
= PTRTOSKINOFFSET(skin_buffer
,
1038 skin_find_item(image_filename
, SKIN_FIND_IMAGE
, wps_data
));
1039 if (!SKINOFFSETTOPTR(skin_buffer
, pb
->image
)) /* load later */
1041 struct gui_img
* img
= (struct gui_img
*)skin_buffer_alloc(sizeof(struct gui_img
));
1043 return WPS_ERROR_INVALID_PARAM
;
1044 /* save a pointer to the filename */
1045 img
->bm
.data
= (char*)image_filename
;
1046 img
->label
= PTRTOSKINOFFSET(skin_buffer
, image_filename
);
1049 img
->num_subimages
= 1;
1051 img
->using_preloaded_icons
= false;
1052 img
->buflib_handle
= -1;
1053 img
->vp
= PTRTOSKINOFFSET(skin_buffer
, &curr_vp
->vp
);
1054 struct skin_token_list
*item
=
1055 (struct skin_token_list
*)new_skin_token_list_item(NULL
, img
);
1057 return WPS_ERROR_INVALID_PARAM
;
1058 add_to_ll_chain(&wps_data
->images
, item
);
1059 pb
->image
= PTRTOSKINOFFSET(skin_buffer
, img
);
1063 if (token
->type
== SKIN_TOKEN_VOLUME
)
1064 token
->type
= SKIN_TOKEN_VOLUMEBAR
;
1065 else if (token
->type
== SKIN_TOKEN_BATTERY_PERCENT
)
1066 token
->type
= SKIN_TOKEN_BATTERY_PERCENTBAR
;
1067 else if (token
->type
== SKIN_TOKEN_TUNER_RSSI
)
1068 token
->type
= SKIN_TOKEN_TUNER_RSSI_BAR
;
1069 else if (token
->type
== SKIN_TOKEN_PEAKMETER_LEFT
)
1070 token
->type
= SKIN_TOKEN_PEAKMETER_LEFTBAR
;
1071 else if (token
->type
== SKIN_TOKEN_PEAKMETER_RIGHT
)
1072 token
->type
= SKIN_TOKEN_PEAKMETER_RIGHTBAR
;
1073 else if (token
->type
== SKIN_TOKEN_LIST_NEEDS_SCROLLBAR
)
1074 token
->type
= SKIN_TOKEN_LIST_SCROLLBAR
;
1075 pb
->type
= token
->type
;
1081 if (token
->type
== SKIN_TOKEN_PROGRESSBAR
||
1082 token
->type
== SKIN_TOKEN_PLAYER_PROGRESSBAR
)
1084 wps_data
->full_line_progressbar
=
1085 token
->type
== SKIN_TOKEN_PLAYER_PROGRESSBAR
;
1092 #ifdef HAVE_ALBUMART
1093 static int parse_albumart_load(struct skin_element
* element
,
1094 struct wps_token
*token
,
1095 struct wps_data
*wps_data
)
1097 struct dim dimensions
;
1099 bool swap_for_rtl
= lang_is_rtl() && follow_lang_direction
;
1100 struct skin_albumart
*aa
=
1101 (struct skin_albumart
*)skin_buffer_alloc(sizeof(struct skin_albumart
));
1102 (void)token
; /* silence warning */
1106 /* reset albumart info in wps */
1109 aa
->xalign
= WPS_ALBUMART_ALIGN_CENTER
; /* default */
1110 aa
->yalign
= WPS_ALBUMART_ALIGN_CENTER
; /* default */
1112 aa
->x
= get_param(element
, 0)->data
.number
;
1113 aa
->y
= get_param(element
, 1)->data
.number
;
1114 aa
->width
= get_param(element
, 2)->data
.number
;
1115 aa
->height
= get_param(element
, 3)->data
.number
;
1117 aa
->vp
= PTRTOSKINOFFSET(skin_buffer
, &curr_vp
->vp
);
1118 aa
->draw_handle
= -1;
1120 /* if we got here, we parsed everything ok .. ! */
1123 else if (aa
->width
> LCD_WIDTH
)
1124 aa
->width
= LCD_WIDTH
;
1128 else if (aa
->height
> LCD_HEIGHT
)
1129 aa
->height
= LCD_HEIGHT
;
1132 aa
->x
= LCD_WIDTH
- (aa
->x
+ aa
->width
);
1134 aa
->state
= WPS_ALBUMART_LOAD
;
1135 wps_data
->albumart
= PTRTOSKINOFFSET(skin_buffer
, aa
);
1137 dimensions
.width
= aa
->width
;
1138 dimensions
.height
= aa
->height
;
1140 albumart_slot
= playback_claim_aa_slot(&dimensions
);
1142 if (0 <= albumart_slot
)
1143 wps_data
->playback_aa_slot
= albumart_slot
;
1145 if (element
->params_count
> 4 && !isdefault(get_param(element
, 4)))
1147 switch (*get_param_text(element
, 4))
1152 aa
->xalign
= WPS_ALBUMART_ALIGN_RIGHT
;
1154 aa
->xalign
= WPS_ALBUMART_ALIGN_LEFT
;
1158 aa
->xalign
= WPS_ALBUMART_ALIGN_CENTER
;
1163 aa
->xalign
= WPS_ALBUMART_ALIGN_LEFT
;
1165 aa
->xalign
= WPS_ALBUMART_ALIGN_RIGHT
;
1169 if (element
->params_count
> 5 && !isdefault(get_param(element
, 5)))
1171 switch (*get_param_text(element
, 5))
1175 aa
->yalign
= WPS_ALBUMART_ALIGN_TOP
;
1179 aa
->yalign
= WPS_ALBUMART_ALIGN_CENTER
;
1183 aa
->yalign
= WPS_ALBUMART_ALIGN_BOTTOM
;
1190 #endif /* HAVE_ALBUMART */
1191 #ifdef HAVE_SKIN_VARIABLES
1192 static struct skin_var
* find_or_add_var(const char* label
,
1193 struct wps_data
*data
)
1195 struct skin_var
* ret
= skin_find_item(label
, SKIN_VARIABLE
, data
);
1198 ret
= (struct skin_var
*)skin_buffer_alloc(sizeof(struct skin_var
));
1201 ret
->label
= PTRTOSKINOFFSET(skin_buffer
, label
);
1203 ret
->last_changed
= 0xffff;
1204 struct skin_token_list
*item
= new_skin_token_list_item(NULL
, ret
);
1207 add_to_ll_chain(&data
->skinvars
, item
);
1211 static int parse_skinvar( struct skin_element
*element
,
1212 struct wps_token
*token
,
1213 struct wps_data
*wps_data
)
1215 const char* label
= get_param_text(element
, 0);
1216 struct skin_var
* var
= find_or_add_var(label
, wps_data
);
1218 return WPS_ERROR_INVALID_PARAM
;
1219 switch (token
->type
)
1221 case SKIN_TOKEN_VAR_GETVAL
:
1222 token
->value
.data
= PTRTOSKINOFFSET(skin_buffer
, var
);
1224 case SKIN_TOKEN_VAR_SET
:
1226 struct skin_var_changer
*data
=
1227 (struct skin_var_changer
*)skin_buffer_alloc(
1228 sizeof(struct skin_var_changer
));
1230 return WPS_ERROR_INVALID_PARAM
;
1231 data
->var
= PTRTOSKINOFFSET(skin_buffer
, var
);
1232 if (!isdefault(get_param(element
, 2)))
1233 data
->newval
= get_param(element
, 2)->data
.number
;
1234 else if (strcmp(get_param_text(element
, 1), "touch"))
1235 return WPS_ERROR_INVALID_PARAM
;
1237 if (!strcmp(get_param_text(element
, 1), "set"))
1238 data
->direct
= true;
1239 else if (!strcmp(get_param_text(element
, 1), "inc"))
1241 data
->direct
= false;
1243 else if (!strcmp(get_param_text(element
, 1), "dec"))
1245 data
->direct
= false;
1248 else if (!strcmp(get_param_text(element
, 1), "touch"))
1250 data
->direct
= false;
1253 if (element
->params_count
> 3)
1254 data
->max
= get_param(element
, 3)->data
.number
;
1255 token
->value
.data
= PTRTOSKINOFFSET(skin_buffer
, data
);
1258 case SKIN_TOKEN_VAR_TIMEOUT
:
1260 struct skin_var_lastchange
*data
=
1261 (struct skin_var_lastchange
*)skin_buffer_alloc(
1262 sizeof(struct skin_var_lastchange
));
1264 return WPS_ERROR_INVALID_PARAM
;
1265 data
->var
= PTRTOSKINOFFSET(skin_buffer
, var
);
1267 if (element
->params_count
> 1)
1268 data
->timeout
= get_param(element
, 1)->data
.number
;
1269 data
->timeout
*= TIMEOUT_UNIT
;
1270 token
->value
.data
= PTRTOSKINOFFSET(skin_buffer
, data
);
1273 default: /* kill the warning */
1278 #endif /* HAVE_SKIN_VARIABLES */
1279 #ifdef HAVE_TOUCHSCREEN
1280 static int parse_lasttouch(struct skin_element
*element
,
1281 struct wps_token
*token
,
1282 struct wps_data
*wps_data
)
1284 struct touchregion_lastpress
*data
=
1285 (struct touchregion_lastpress
*)skin_buffer_alloc(
1286 sizeof(struct touchregion_lastpress
));
1288 struct touchregion
*region
= NULL
;
1290 return WPS_ERROR_INVALID_PARAM
;
1294 for (i
=0; i
<element
->params_count
; i
++)
1296 if (get_param(element
, i
)->type
== STRING
)
1297 region
= skin_find_item(get_param_text(element
, i
),
1298 SKIN_FIND_TOUCHREGION
, wps_data
);
1299 else if (get_param(element
, i
)->type
== INTEGER
||
1300 get_param(element
, i
)->type
== DECIMAL
)
1301 data
->timeout
= get_param(element
, i
)->data
.number
;
1304 data
->region
= PTRTOSKINOFFSET(skin_buffer
, region
);
1305 data
->timeout
*= TIMEOUT_UNIT
;
1306 token
->value
.data
= PTRTOSKINOFFSET(skin_buffer
, data
);
1310 struct touchaction
{const char* s
; int action
;};
1311 static const struct touchaction touchactions
[] = {
1312 /* generic actions, convert to screen actions on use */
1313 {"none", ACTION_TOUCHSCREEN_IGNORE
},{"lock", ACTION_TOUCH_SOFTLOCK
},
1314 {"prev", ACTION_STD_PREV
}, {"next", ACTION_STD_NEXT
},
1315 {"hotkey", ACTION_STD_HOTKEY
}, {"select", ACTION_STD_OK
},
1316 {"menu", ACTION_STD_MENU
}, {"cancel", ACTION_STD_CANCEL
},
1317 {"contextmenu", ACTION_STD_CONTEXT
},{"quickscreen", ACTION_STD_QUICKSCREEN
},
1319 /* list/tree actions */
1320 { "resumeplayback", ACTION_TREE_WPS
}, /* returns to previous music, WPS/FM */
1321 /* not really WPS specific, but no equivilant ACTION_STD_* */
1322 {"voldown", ACTION_WPS_VOLDOWN
}, {"volup", ACTION_WPS_VOLUP
},
1323 {"mute", ACTION_TOUCH_MUTE
},
1325 /* generic settings changers */
1326 {"setting_inc", ACTION_SETTINGS_INC
}, {"setting_dec", ACTION_SETTINGS_DEC
},
1327 {"setting_set", ACTION_SETTINGS_SET
},
1329 /* WPS specific actions */
1330 {"rwd", ACTION_WPS_SEEKBACK
}, {"ffwd", ACTION_WPS_SEEKFWD
},
1331 {"wps_prev", ACTION_WPS_SKIPPREV
}, {"wps_next", ACTION_WPS_SKIPNEXT
},
1332 {"browse", ACTION_WPS_BROWSE
},
1333 {"play", ACTION_WPS_PLAY
}, {"stop", ACTION_WPS_STOP
},
1334 {"shuffle", ACTION_TOUCH_SHUFFLE
}, {"repmode", ACTION_TOUCH_REPMODE
},
1335 {"pitch", ACTION_WPS_PITCHSCREEN
}, {"trackinfo", ACTION_WPS_ID3SCREEN
},
1336 {"playlist", ACTION_WPS_VIEW_PLAYLIST
},
1337 {"listbookmarks", ACTION_WPS_LIST_BOOKMARKS
},
1338 {"createbookmark", ACTION_WPS_CREATE_BOOKMARK
},
1341 /* FM screen actions */
1342 /* Also allow browse, play, stop from WPS codes */
1343 {"mode", ACTION_FM_MODE
}, {"record", ACTION_FM_RECORD
},
1344 {"presets", ACTION_FM_PRESET
},
1348 static int touchregion_setup_setting(struct skin_element
*element
, int param_no
,
1349 struct touchregion
*region
)
1353 char *name
= get_param_text(element
, p
++);
1356 region
->setting_data
.setting
= find_setting_by_cfgname(name
, &j
);
1357 if (region
->setting_data
.setting
== NULL
)
1358 return WPS_ERROR_INVALID_PARAM
;
1360 if (region
->action
== ACTION_SETTINGS_SET
)
1364 struct touchsetting
*setting
=
1365 ®ion
->setting_data
;
1366 if (element
->params_count
< p
+1)
1369 text
= get_param_text(element
, p
++);
1370 switch (settings
[j
].flags
&F_T_MASK
)
1373 setting
->value
.text
= PTRTOSKINOFFSET(skin_buffer
, text
);
1377 if (settings
[j
].cfg_vals
== NULL
)
1379 setting
->value
.number
= atoi(text
);
1381 else if (cfg_string_to_int(j
, &temp
, text
))
1383 if (settings
[j
].flags
&F_TABLE_SETTING
)
1384 setting
->value
.number
=
1385 settings
[j
].table_setting
->values
[temp
];
1387 setting
->value
.number
= temp
;
1393 if (cfg_string_to_int(j
, &temp
, text
))
1395 setting
->value
.number
= temp
;
1405 #endif /* __PCTOOL__ */
1409 static int parse_touchregion(struct skin_element
*element
,
1410 struct wps_token
*token
,
1411 struct wps_data
*wps_data
)
1416 struct touchregion
*region
= NULL
;
1418 const char pb_string
[] = "progressbar";
1419 const char vol_string
[] = "volume";
1421 /* format: %T([label,], x,y,width,height,action[, ...])
1422 * if action starts with & the area must be held to happen
1426 region
= (struct touchregion
*)skin_buffer_alloc(sizeof(struct touchregion
));
1428 return WPS_ERROR_INVALID_PARAM
;
1430 /* should probably do some bounds checking here with the viewport... but later */
1431 region
->action
= ACTION_NONE
;
1433 if (get_param(element
, 0)->type
== STRING
)
1435 region
->label
= PTRTOSKINOFFSET(skin_buffer
, get_param_text(element
, 0));
1437 /* "[SI]III[SI]|SS" is the param list. There MUST be 4 numbers
1438 * followed by at least one string. Verify that here */
1439 if (element
->params_count
< 6 ||
1440 get_param(element
, 4)->type
!= INTEGER
)
1441 return WPS_ERROR_INVALID_PARAM
;
1445 region
->label
= PTRTOSKINOFFSET(skin_buffer
, NULL
);
1449 region
->x
= get_param(element
, p
++)->data
.number
;
1450 region
->y
= get_param(element
, p
++)->data
.number
;
1451 region
->width
= get_param(element
, p
++)->data
.number
;
1452 region
->height
= get_param(element
, p
++)->data
.number
;
1453 region
->wvp
= PTRTOSKINOFFSET(skin_buffer
, curr_vp
);
1454 region
->armed
= false;
1455 region
->reverse_bar
= false;
1457 region
->last_press
= 0xffff;
1458 region
->press_length
= PRESS
;
1459 region
->allow_while_locked
= false;
1460 action
= get_param_text(element
, p
++);
1462 /* figure out the action */
1463 if(!strcmp(pb_string
, action
))
1464 region
->action
= ACTION_TOUCH_SCROLLBAR
;
1465 else if(!strcmp(vol_string
, action
))
1466 region
->action
= ACTION_TOUCH_VOLUME
;
1469 imax
= ARRAYLEN(touchactions
);
1470 for (i
= 0; i
< imax
; i
++)
1472 /* try to match with one of our touchregion screens */
1473 if (!strcmp(touchactions
[i
].s
, action
))
1475 region
->action
= touchactions
[i
].action
;
1476 if (region
->action
== ACTION_SETTINGS_INC
||
1477 region
->action
== ACTION_SETTINGS_DEC
||
1478 region
->action
== ACTION_SETTINGS_SET
)
1481 if (element
->params_count
< p
+1)
1482 return WPS_ERROR_INVALID_PARAM
;
1483 val
= touchregion_setup_setting(element
, p
, region
);
1485 return WPS_ERROR_INVALID_PARAM
;
1491 if (region
->action
== ACTION_NONE
)
1492 return WPS_ERROR_INVALID_PARAM
;
1494 while (p
< element
->params_count
)
1496 char* param
= get_param_text(element
, p
++);
1497 if (!strcmp(param
, "allow_while_locked"))
1498 region
->allow_while_locked
= true;
1499 else if (!strcmp(param
, "reverse_bar"))
1500 region
->reverse_bar
= true;
1501 else if (!strcmp(param
, "repeat_press"))
1502 region
->press_length
= REPEAT
;
1503 else if (!strcmp(param
, "long_press"))
1504 region
->press_length
= LONG_PRESS
;
1506 struct skin_token_list
*item
= new_skin_token_list_item(NULL
, region
);
1508 return WPS_ERROR_INVALID_PARAM
;
1509 add_to_ll_chain(&wps_data
->touchregions
, item
);
1511 if (region
->action
== ACTION_TOUCH_MUTE
)
1513 region
->value
= global_settings
.volume
;
1521 static bool check_feature_tag(const int type
)
1525 case SKIN_TOKEN_RTC_PRESENT
:
1531 case SKIN_TOKEN_HAVE_RECORDING
:
1532 #ifdef HAVE_RECORDING
1537 case SKIN_TOKEN_HAVE_TUNER
:
1539 if (radio_hardware_present())
1543 case SKIN_TOKEN_HAVE_TOUCH
:
1544 #ifdef HAVE_TOUCHSCREEN
1551 case SKIN_TOKEN_HAVE_RDS
:
1556 #endif /* HAVE_RDS_CAP */
1557 #endif /* CONFIG_TUNER */
1558 default: /* not a tag we care about, just don't skip */
1563 /* This is used to free any buflib allocations before the rest of
1564 * wps_data is reset.
1565 * The call to this in settings_apply_skins() is the last chance to do
1566 * any core_free()'s before wps_data is trashed and those handles lost
1568 void skin_data_free_buflib_allocs(struct wps_data
*wps_data
)
1570 if (wps_data
->wps_loaded
)
1571 skin_buffer
= get_skin_buffer(wps_data
);
1572 #ifdef HAVE_LCD_BITMAP
1574 struct skin_token_list
*list
= SKINOFFSETTOPTR(skin_buffer
, wps_data
->images
);
1575 int *font_ids
= SKINOFFSETTOPTR(skin_buffer
, wps_data
->font_ids
);
1578 struct wps_token
*token
= SKINOFFSETTOPTR(skin_buffer
, list
->token
);
1579 struct gui_img
*img
= (struct gui_img
*)SKINOFFSETTOPTR(skin_buffer
, token
->value
.data
);
1580 if (img
->buflib_handle
> 0)
1581 core_free(img
->buflib_handle
);
1582 list
= SKINOFFSETTOPTR(skin_buffer
, list
->next
);
1584 wps_data
->images
= PTRTOSKINOFFSET(skin_buffer
, NULL
);
1585 if (font_ids
!= NULL
)
1587 while (wps_data
->font_count
> 0)
1588 font_unload(font_ids
[--wps_data
->font_count
]);
1590 wps_data
->font_ids
= PTRTOSKINOFFSET(skin_buffer
, NULL
);
1591 if (wps_data
->buflib_handle
> 0)
1592 core_free(wps_data
->buflib_handle
);
1593 wps_data
->buflib_handle
= -1;
1599 * initial setup of wps_data; does reset everything
1600 * except fields which need to survive, i.e.
1601 * Also called if the load fails
1603 static void skin_data_reset(struct wps_data
*wps_data
)
1605 skin_data_free_buflib_allocs(wps_data
);
1606 #ifdef HAVE_LCD_BITMAP
1607 wps_data
->images
= INVALID_OFFSET
;
1609 wps_data
->tree
= INVALID_OFFSET
;
1610 #ifdef HAVE_BACKDROP_IMAGE
1611 if (wps_data
->backdrop_id
>= 0)
1612 skin_backdrop_unload(wps_data
->backdrop_id
);
1613 backdrop_filename
= NULL
;
1615 #ifdef HAVE_TOUCHSCREEN
1616 wps_data
->touchregions
= INVALID_OFFSET
;
1618 #ifdef HAVE_SKIN_VARIABLES
1619 wps_data
->skinvars
= INVALID_OFFSET
;
1621 #ifdef HAVE_ALBUMART
1622 wps_data
->albumart
= INVALID_OFFSET
;
1623 if (wps_data
->playback_aa_slot
>= 0)
1625 playback_release_aa_slot(wps_data
->playback_aa_slot
);
1626 wps_data
->playback_aa_slot
= -1;
1630 #ifdef HAVE_LCD_BITMAP
1631 wps_data
->peak_meter_enabled
= false;
1632 wps_data
->wps_sb_tag
= false;
1633 wps_data
->show_sb_on_wps
= false;
1634 #else /* HAVE_LCD_CHARCELLS */
1637 for (i
= 0; i
< 8; i
++)
1639 wps_data
->wps_progress_pat
[i
] = 0;
1641 wps_data
->full_line_progressbar
= false;
1643 wps_data
->wps_loaded
= false;
1646 #ifdef HAVE_LCD_BITMAP
1648 static int currently_loading_handle
= -1;
1649 static int buflib_move_callback(int handle
, void* current
, void* new)
1653 if (handle
== currently_loading_handle
)
1654 return BUFLIB_CB_CANNOT_MOVE
;
1655 return BUFLIB_CB_OK
;
1657 static struct buflib_callbacks buflib_ops
= {buflib_move_callback
, NULL
};
1658 static void lock_handle(int handle
)
1660 currently_loading_handle
= handle
;
1662 static void unlock_handle(void)
1664 currently_loading_handle
= -1;
1668 static int load_skin_bmp(struct wps_data
*wps_data
, struct bitmap
*bitmap
, char* bmpdir
)
1670 (void)wps_data
; /* only needed for remote targets */
1671 char img_path
[MAX_PATH
];
1674 get_image_filename(bitmap
->data
, bmpdir
,
1675 img_path
, sizeof(img_path
));
1677 /* load the image */
1679 #ifdef HAVE_REMOTE_LCD
1680 if (curr_screen
== SCREEN_REMOTE
)
1681 format
= FORMAT_ANY
|FORMAT_REMOTE
;
1684 format
= FORMAT_ANY
|FORMAT_TRANSPARENT
;
1686 fd
= open(img_path
, O_RDONLY
);
1689 DEBUGF("Couldn't open %s\n", img_path
);
1693 size_t buf_size
= read_bmp_fd(fd
, bitmap
, 0,
1694 format
|FORMAT_RETURN_SIZE
, NULL
);
1695 handle
= core_alloc_ex(bitmap
->data
, buf_size
, &buflib_ops
);
1698 DEBUGF("Not enough skin buffer: need %zd more.\n",
1699 buf_size
- skin_buffer_freespace());
1703 lseek(fd
, 0, SEEK_SET
);
1704 lock_handle(handle
);
1705 bitmap
->data
= core_get_data(handle
);
1706 int ret
= read_bmp_fd(fd
, bitmap
, buf_size
, format
, NULL
);
1707 bitmap
->data
= NULL
; /* do this to force a crash later if the
1708 caller doesnt call core_get_data() */
1713 /* free unused alpha channel, if any */
1714 core_shrink(handle
, core_get_data(handle
), ret
);
1719 /* Abort if we can't load an image */
1720 DEBUGF("Couldn't load '%s'\n", img_path
);
1724 #else /* !__PCTOOL__ */
1730 static bool load_skin_bitmaps(struct wps_data
*wps_data
, char *bmpdir
)
1732 struct skin_token_list
*list
;
1733 bool retval
= true; /* return false if a single image failed to load */
1735 /* regular images */
1736 list
= SKINOFFSETTOPTR(skin_buffer
, wps_data
->images
);
1739 struct wps_token
*token
= SKINOFFSETTOPTR(skin_buffer
, list
->token
);
1740 struct gui_img
*img
= (struct gui_img
*)SKINOFFSETTOPTR(skin_buffer
, token
->value
.data
);
1743 if (img
->using_preloaded_icons
)
1746 token
->type
= SKIN_TOKEN_IMAGE_DISPLAY_LISTICON
;
1750 img
->buflib_handle
= load_skin_bmp(wps_data
, &img
->bm
, bmpdir
);
1751 img
->loaded
= img
->buflib_handle
>= 0;
1753 img
->subimage_height
= img
->bm
.height
/ img
->num_subimages
;
1758 list
= SKINOFFSETTOPTR(skin_buffer
, list
->next
);
1761 #ifdef HAVE_BACKDROP_IMAGE
1762 wps_data
->backdrop_id
= skin_backdrop_assign(backdrop_filename
, bmpdir
, curr_screen
);
1763 #endif /* has backdrop support */
1767 static bool skin_load_fonts(struct wps_data
*data
)
1769 /* don't spit out after the first failue to aid debugging */
1770 int id_array
[MAXUSERFONTS
];
1772 bool success
= true;
1773 struct skin_element
*vp_list
;
1775 /* walk though each viewport and assign its font */
1776 for(vp_list
= SKINOFFSETTOPTR(skin_buffer
, data
->tree
);
1777 vp_list
; vp_list
= SKINOFFSETTOPTR(skin_buffer
, vp_list
->next
))
1779 /* first, find the viewports that have a non-sys/ui-font font */
1780 struct skin_viewport
*skin_vp
=
1781 SKINOFFSETTOPTR(skin_buffer
, vp_list
->data
);
1782 struct viewport
*vp
= &skin_vp
->vp
;
1784 font_id
= skin_vp
->parsed_fontid
;
1786 { /* the usual case -> built-in fonts */
1787 vp
->font
= screens
[curr_screen
].getuifont();
1790 else if (font_id
<= 0)
1792 vp
->font
= FONT_SYSFIXED
;
1796 /* now find the corresponding skin_font */
1797 struct skin_font
*font
= &skinfonts
[font_id
-2];
1802 DEBUGF("font %d not specified\n", font_id
);
1808 /* load the font - will handle loading the same font again if
1809 * multiple viewports use the same */
1812 char path
[MAX_PATH
];
1813 snprintf(path
, sizeof path
, FONT_DIR
"/%s", font
->name
);
1815 font
->id
= font_load_ex(path
, 0, skinfonts
[font_id
-2].glyphs
);
1818 font
->id
= font_load(path
);
1820 //printf("[%d] %s -> %d\n",font_id, font->name, font->id);
1821 id_array
[font_count
++] = font
->id
;
1826 DEBUGF("Unable to load font %d: '%s.fnt'\n",
1827 font_id
, font
->name
);
1828 font
->name
= NULL
; /* to stop trying to load it again if we fail */
1833 /* finally, assign the font_id to the viewport */
1834 vp
->font
= font
->id
;
1838 int *font_ids
= skin_buffer_alloc(font_count
* sizeof(int));
1839 if (!success
|| font_ids
== NULL
)
1841 while (font_count
> 0)
1843 if(id_array
[--font_count
] != -1)
1844 font_unload(id_array
[font_count
]);
1846 data
->font_ids
= PTRTOSKINOFFSET(skin_buffer
, NULL
);
1849 memcpy(font_ids
, id_array
, sizeof(int)*font_count
);
1850 data
->font_count
= font_count
;
1851 data
->font_ids
= PTRTOSKINOFFSET(skin_buffer
, font_ids
);
1855 data
->font_count
= 0;
1856 data
->font_ids
= PTRTOSKINOFFSET(skin_buffer
, NULL
);
1861 #endif /* HAVE_LCD_BITMAP */
1862 static int convert_viewport(struct wps_data
*data
, struct skin_element
* element
)
1864 struct skin_viewport
*skin_vp
=
1865 (struct skin_viewport
*)skin_buffer_alloc(sizeof(struct skin_viewport
));
1866 struct screen
*display
= &screens
[curr_screen
];
1869 return CALLBACK_ERROR
;
1871 skin_vp
->hidden_flags
= 0;
1872 skin_vp
->label
= PTRTOSKINOFFSET(skin_buffer
, NULL
);
1873 skin_vp
->is_infovp
= false;
1874 skin_vp
->parsed_fontid
= 1;
1875 element
->data
= PTRTOSKINOFFSET(skin_buffer
, skin_vp
);
1877 curr_viewport_element
= element
;
1878 if (!first_viewport
)
1879 first_viewport
= element
;
1881 viewport_set_defaults(&skin_vp
->vp
, curr_screen
);
1883 #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
1884 skin_vp
->output_to_backdrop_buffer
= false;
1885 skin_vp
->start_fgcolour
= skin_vp
->vp
.fg_pattern
;
1886 skin_vp
->start_bgcolour
= skin_vp
->vp
.bg_pattern
;
1888 #ifdef HAVE_LCD_COLOR
1889 skin_vp
->start_gradient
.start
= skin_vp
->vp
.lss_pattern
;
1890 skin_vp
->start_gradient
.end
= skin_vp
->vp
.lse_pattern
;
1891 skin_vp
->start_gradient
.text
= skin_vp
->vp
.lst_pattern
;
1895 struct skin_tag_parameter
*param
= get_param(element
, 0);
1896 if (element
->params_count
== 0) /* default viewport */
1898 if (data
->tree
< 0) /* first viewport in the skin */
1899 data
->tree
= PTRTOSKINOFFSET(skin_buffer
, element
);
1900 skin_vp
->label
= VP_DEFAULT_LABEL
;
1904 if (element
->params_count
== 6)
1906 if (element
->tag
->type
== SKIN_TOKEN_UIVIEWPORT_LOAD
)
1908 skin_vp
->is_infovp
= true;
1909 if (isdefault(param
))
1911 skin_vp
->hidden_flags
= VP_NEVER_VISIBLE
;
1912 skin_vp
->label
= VP_DEFAULT_LABEL
;
1916 skin_vp
->hidden_flags
= VP_NEVER_VISIBLE
;
1917 skin_vp
->label
= param
->data
.text
;
1922 skin_vp
->hidden_flags
= VP_DRAW_HIDEABLE
|VP_DRAW_HIDDEN
;
1923 skin_vp
->label
= param
->data
.text
;
1928 if (!isdefault(param
))
1930 skin_vp
->vp
.x
= param
->data
.number
;
1931 if (param
->data
.number
< 0)
1932 skin_vp
->vp
.x
+= display
->lcdwidth
;
1936 if (!isdefault(param
))
1938 skin_vp
->vp
.y
= param
->data
.number
;
1939 if (param
->data
.number
< 0)
1940 skin_vp
->vp
.y
+= display
->lcdheight
;
1944 if (!isdefault(param
))
1946 skin_vp
->vp
.width
= param
->data
.number
;
1947 if (param
->data
.number
< 0)
1948 skin_vp
->vp
.width
= (skin_vp
->vp
.width
+ display
->lcdwidth
) - skin_vp
->vp
.x
;
1952 skin_vp
->vp
.width
= display
->lcdwidth
- skin_vp
->vp
.x
;
1956 if (!isdefault(param
))
1958 skin_vp
->vp
.height
= param
->data
.number
;
1959 if (param
->data
.number
< 0)
1960 skin_vp
->vp
.height
= (skin_vp
->vp
.height
+ display
->lcdheight
) - skin_vp
->vp
.y
;
1964 skin_vp
->vp
.height
= display
->lcdheight
- skin_vp
->vp
.y
;
1967 #ifdef HAVE_LCD_BITMAP
1969 if (!isdefault(param
))
1970 skin_vp
->parsed_fontid
= param
->data
.number
;
1972 if ((unsigned) skin_vp
->vp
.x
>= (unsigned) display
->lcdwidth
||
1973 skin_vp
->vp
.width
+ skin_vp
->vp
.x
> display
->lcdwidth
||
1974 (unsigned) skin_vp
->vp
.y
>= (unsigned) display
->lcdheight
||
1975 skin_vp
->vp
.height
+ skin_vp
->vp
.y
> display
->lcdheight
)
1976 return CALLBACK_ERROR
;
1981 static int skin_element_callback(struct skin_element
* element
, void* data
)
1983 struct wps_data
*wps_data
= (struct wps_data
*)data
;
1984 struct wps_token
*token
;
1985 parse_function function
= NULL
;
1987 switch (element
->type
)
1989 /* IMPORTANT: element params are shared, so copy them if needed
1990 * or use then NOW, dont presume they have a long lifespan
1994 token
= (struct wps_token
*)skin_buffer_alloc(sizeof(struct wps_token
));
1995 memset(token
, 0, sizeof(*token
));
1996 token
->type
= element
->tag
->type
;
1997 token
->value
.data
= INVALID_OFFSET
;
1999 if (element
->tag
->flags
&SKIN_RTC_REFRESH
)
2002 curr_line
->update_mode
|= SKIN_REFRESH_DYNAMIC
;
2004 curr_line
->update_mode
|= SKIN_REFRESH_STATIC
;
2008 curr_line
->update_mode
|= element
->tag
->flags
&SKIN_REFRESH_ALL
;
2010 element
->data
= PTRTOSKINOFFSET(skin_buffer
, token
);
2012 /* Some tags need special handling for the tag, so add them here */
2013 switch (token
->type
)
2015 case SKIN_TOKEN_ALIGN_LANGDIRECTION
:
2016 follow_lang_direction
= 2;
2018 case SKIN_TOKEN_LOGICAL_IF
:
2019 function
= parse_logical_if
;
2021 case SKIN_TOKEN_LOGICAL_AND
:
2022 case SKIN_TOKEN_LOGICAL_OR
:
2023 function
= parse_logical_andor
;
2025 case SKIN_TOKEN_SUBSTRING
:
2026 function
= parse_substring_tag
;
2028 case SKIN_TOKEN_PROGRESSBAR
:
2029 case SKIN_TOKEN_VOLUME
:
2030 case SKIN_TOKEN_BATTERY_PERCENT
:
2031 case SKIN_TOKEN_PLAYER_PROGRESSBAR
:
2032 case SKIN_TOKEN_PEAKMETER_LEFT
:
2033 case SKIN_TOKEN_PEAKMETER_RIGHT
:
2034 case SKIN_TOKEN_LIST_NEEDS_SCROLLBAR
:
2035 #ifdef HAVE_RADIO_RSSI
2036 case SKIN_TOKEN_TUNER_RSSI
:
2038 function
= parse_progressbar_tag
;
2040 case SKIN_TOKEN_SUBLINE_TIMEOUT
:
2041 case SKIN_TOKEN_BUTTON_VOLUME
:
2042 case SKIN_TOKEN_TRACK_STARTING
:
2043 case SKIN_TOKEN_TRACK_ENDING
:
2044 function
= parse_timeout_tag
;
2046 #ifdef HAVE_LCD_BITMAP
2047 case SKIN_TOKEN_LIST_ITEM_TEXT
:
2048 case SKIN_TOKEN_LIST_ITEM_ICON
:
2049 function
= parse_listitem
;
2051 case SKIN_TOKEN_DISABLE_THEME
:
2052 case SKIN_TOKEN_ENABLE_THEME
:
2053 case SKIN_TOKEN_DRAW_INBUILTBAR
:
2054 function
= parse_statusbar_tags
;
2056 case SKIN_TOKEN_LIST_TITLE_TEXT
:
2058 sb_skin_has_title(curr_screen
);
2061 case SKIN_TOKEN_DRAWRECTANGLE
:
2062 function
= parse_drawrectangle
;
2065 case SKIN_TOKEN_FILE_DIRECTORY
:
2066 token
->value
.i
= get_param(element
, 0)->data
.number
;
2068 #ifdef HAVE_BACKDROP_IMAGE
2069 case SKIN_TOKEN_VIEWPORT_FGCOLOUR
:
2070 case SKIN_TOKEN_VIEWPORT_BGCOLOUR
:
2071 function
= parse_viewportcolour
;
2073 case SKIN_TOKEN_IMAGE_BACKDROP
:
2074 function
= parse_image_special
;
2076 case SKIN_TOKEN_VIEWPORT_TEXTSTYLE
:
2077 function
= parse_viewporttextstyle
;
2079 case SKIN_TOKEN_VIEWPORT_DRAWONBG
:
2080 curr_vp
->output_to_backdrop_buffer
= true;
2081 backdrop_filename
= BACKDROP_BUFFERNAME
;
2082 wps_data
->use_extra_framebuffer
= true;
2085 #ifdef HAVE_LCD_COLOR
2086 case SKIN_TOKEN_VIEWPORT_GRADIENT_SETUP
:
2087 function
= parse_viewport_gradient_setup
;
2090 case SKIN_TOKEN_TRANSLATEDSTRING
:
2091 case SKIN_TOKEN_SETTING
:
2092 function
= parse_setting_and_lang
;
2094 #ifdef HAVE_LCD_BITMAP
2095 case SKIN_TOKEN_VIEWPORT_CUSTOMLIST
:
2096 function
= parse_playlistview
;
2098 case SKIN_TOKEN_LOAD_FONT
:
2099 function
= parse_font_load
;
2101 case SKIN_TOKEN_VIEWPORT_ENABLE
:
2102 case SKIN_TOKEN_UIVIEWPORT_ENABLE
:
2103 token
->value
.data
= get_param(element
, 0)->data
.text
;
2105 case SKIN_TOKEN_IMAGE_PRELOAD_DISPLAY
:
2106 function
= parse_image_display
;
2108 case SKIN_TOKEN_IMAGE_PRELOAD
:
2109 case SKIN_TOKEN_IMAGE_DISPLAY
:
2110 function
= parse_image_load
;
2112 case SKIN_TOKEN_LIST_ITEM_CFG
:
2113 function
= parse_listitemviewport
;
2116 #ifdef HAVE_TOUCHSCREEN
2117 case SKIN_TOKEN_TOUCHREGION
:
2118 function
= parse_touchregion
;
2120 case SKIN_TOKEN_LASTTOUCH
:
2121 function
= parse_lasttouch
;
2124 #ifdef HAVE_ALBUMART
2125 case SKIN_TOKEN_ALBUMART_DISPLAY
:
2126 if (SKINOFFSETTOPTR(skin_buffer
, wps_data
->albumart
))
2128 struct skin_albumart
*aa
= SKINOFFSETTOPTR(skin_buffer
, wps_data
->albumart
);
2129 aa
->vp
= PTRTOSKINOFFSET(skin_buffer
, &curr_vp
->vp
);
2132 case SKIN_TOKEN_ALBUMART_LOAD
:
2133 function
= parse_albumart_load
;
2136 #ifdef HAVE_SKIN_VARIABLES
2137 case SKIN_TOKEN_VAR_SET
:
2138 case SKIN_TOKEN_VAR_GETVAL
:
2139 case SKIN_TOKEN_VAR_TIMEOUT
:
2140 function
= parse_skinvar
;
2148 if (function(element
, token
, wps_data
) < 0)
2149 return CALLBACK_ERROR
;
2151 /* tags that start with 'F', 'I' or 'D' are for the next file */
2152 if ( *(element
->tag
->name
) == 'I' || *(element
->tag
->name
) == 'F' ||
2153 *(element
->tag
->name
) == 'D')
2155 if (follow_lang_direction
> 0 )
2156 follow_lang_direction
--;
2160 return convert_viewport(wps_data
, element
);
2164 (struct line
*)skin_buffer_alloc(sizeof(struct line
));
2165 line
->update_mode
= SKIN_REFRESH_STATIC
;
2167 element
->data
= PTRTOSKINOFFSET(skin_buffer
, line
);
2170 case LINE_ALTERNATOR
:
2172 struct line_alternator
*alternator
=
2173 (struct line_alternator
*)skin_buffer_alloc(sizeof(struct line_alternator
));
2174 alternator
->current_line
= 0;
2176 alternator
->next_change_tick
= current_tick
;
2178 element
->data
= PTRTOSKINOFFSET(skin_buffer
, alternator
);
2183 struct conditional
*conditional
=
2184 (struct conditional
*)skin_buffer_alloc(sizeof(struct conditional
));
2185 conditional
->last_value
= -1;
2186 conditional
->token
= element
->data
;
2187 element
->data
= PTRTOSKINOFFSET(skin_buffer
, conditional
);
2188 if (!check_feature_tag(element
->tag
->type
))
2190 return FEATURE_NOT_AVAILABLE
;
2195 curr_line
->update_mode
|= SKIN_REFRESH_STATIC
;
2203 /* to setup up the wps-data from a format-buffer (isfile = false)
2204 from a (wps-)file (isfile = true)*/
2205 bool skin_data_load(enum screen_type screen
, struct wps_data
*wps_data
,
2206 const char *buf
, bool isfile
)
2208 char *wps_buffer
= NULL
;
2209 if (!wps_data
|| !buf
)
2211 #ifdef HAVE_ALBUMART
2213 struct mp3entry
*curtrack
;
2215 struct skin_albumart old_aa
= {.state
= WPS_ALBUMART_NONE
};
2216 struct skin_albumart
*aa
= SKINOFFSETTOPTR(skin_buffer
, wps_data
->albumart
);
2219 old_aa
.state
= aa
->state
;
2220 old_aa
.height
= aa
->height
;
2221 old_aa
.width
= aa
->width
;
2224 #ifdef HAVE_LCD_BITMAP
2226 for (i
=0;i
<MAXUSERFONTS
;i
++)
2228 skinfonts
[i
].id
= -1;
2229 skinfonts
[i
].name
= NULL
;
2232 #ifdef DEBUG_SKIN_ENGINE
2233 if (isfile
&& debug_wps
)
2235 DEBUGF("\n=====================\nLoading '%s'\n=====================\n", buf
);
2240 /* get buffer space from the plugin buffer */
2241 size_t buffersize
= 0;
2242 wps_buffer
= (char *)plugin_get_buffer(&buffersize
);
2247 skin_data_reset(wps_data
);
2248 wps_data
->wps_loaded
= false;
2249 curr_screen
= screen
;
2252 curr_viewport_element
= NULL
;
2253 first_viewport
= NULL
;
2257 int fd
= open_utf8(buf
, O_RDONLY
);
2261 /* copy the file's content to the buffer for parsing,
2262 ensuring that every line ends with a newline char. */
2263 unsigned int start
= 0;
2264 while(read_line(fd
, wps_buffer
+ start
, buffersize
- start
) > 0)
2266 start
+= strlen(wps_buffer
+ start
);
2267 if (start
< buffersize
- 1)
2269 wps_buffer
[start
++] = '\n';
2270 wps_buffer
[start
] = 0;
2277 skin_buffer
= &wps_buffer
[start
];
2278 buffersize
-= start
;
2282 skin_buffer
= wps_buffer
;
2283 wps_buffer
= (char*)buf
;
2285 skin_buffer
= (void *)(((unsigned long)skin_buffer
+ 3) & ~3);
2287 #ifdef HAVE_BACKDROP_IMAGE
2288 backdrop_filename
= "-";
2289 wps_data
->backdrop_id
= -1;
2291 /* parse the skin source */
2292 skin_buffer_init(skin_buffer
, buffersize
);
2293 struct skin_element
*tree
= skin_parse(wps_buffer
, skin_element_callback
, wps_data
);
2294 wps_data
->tree
= PTRTOSKINOFFSET(skin_buffer
, tree
);
2295 if (!SKINOFFSETTOPTR(skin_buffer
, wps_data
->tree
)) {
2296 skin_data_reset(wps_data
);
2300 #ifdef HAVE_LCD_BITMAP
2301 char bmpdir
[MAX_PATH
];
2304 /* get the bitmap dir */
2305 char *dot
= strrchr(buf
, '.');
2306 strlcpy(bmpdir
, buf
, dot
- buf
+ 1);
2310 snprintf(bmpdir
, MAX_PATH
, "%s", BACKDROP_DIR
);
2312 /* load the bitmaps that were found by the parsing */
2313 if (!load_skin_bitmaps(wps_data
, bmpdir
) ||
2314 !skin_load_fonts(wps_data
))
2316 skin_data_reset(wps_data
);
2320 #if defined(HAVE_ALBUMART) && !defined(__PCTOOL__)
2321 status
= audio_status();
2322 if (status
& AUDIO_STATUS_PLAY
)
2324 struct skin_albumart
*aa
= SKINOFFSETTOPTR(skin_buffer
, wps_data
->albumart
);
2325 if (aa
&& ((aa
->state
&& !old_aa
.state
) ||
2327 (((old_aa
.height
!= aa
->height
) ||
2328 (old_aa
.width
!= aa
->width
))))))
2330 curtrack
= audio_current_track();
2331 offset
= curtrack
->offset
;
2333 if (!(status
& AUDIO_STATUS_PAUSE
))
2339 wps_data
->buflib_handle
= core_alloc(isfile
? buf
: "failsafe skin",
2340 skin_buffer_usage());
2341 if (wps_data
->buflib_handle
>= 0)
2343 wps_data
->wps_loaded
= true;
2344 memcpy(core_get_data(wps_data
->buflib_handle
), skin_buffer
,
2345 skin_buffer_usage());
2348 wps_data
->wps_loaded
= wps_data
->tree
>= 0;
2350 #ifdef DEBUG_SKIN_ENGINE
2351 // if (isfile && debug_wps)
2352 // debug_skin_usage();