1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2009 Thomas Martitz
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
27 #include "appevents.h"
29 #include "screen_access.h"
31 #include "skin_parser.h"
32 #include "skin_buffer.h"
33 #include "skin_engine/skin_engine.h"
34 #include "skin_engine/wps_internals.h"
36 #include "statusbar.h"
37 #include "statusbar-skinned.h"
43 /* currently only one wps_state is needed */
44 extern struct wps_state wps_state
; /* from wps.c */
45 static struct gui_wps sb_skin
[NB_SCREENS
] = {{ .data
= NULL
}};
46 static struct wps_data sb_skin_data
[NB_SCREENS
] = {{ .wps_loaded
= 0 }};
47 static struct wps_sync_data sb_skin_sync_data
= { .do_full_update
= false };
49 /* initial setup of wps_data */
50 static int update_delay
= DEFAULT_UPDATE_DELAY
;
51 static int set_title_worker(char* title
, enum themable_icons icon
,
52 struct wps_data
*data
, struct skin_element
*root
)
55 struct skin_element
*element
= root
;
58 struct wps_token
*token
= NULL
;
59 if (element
->type
== CONDITIONAL
)
61 struct conditional
*cond
= (struct conditional
*)element
->data
;
64 else if (element
->type
== TAG
)
66 token
= (struct wps_token
*)element
->data
;
70 if (token
->type
== SKIN_TOKEN_LIST_TITLE_TEXT
)
72 token
->value
.data
= title
;
75 else if (token
->type
== SKIN_TOKEN_LIST_TITLE_ICON
)
77 /* Icon_NOICON == -1 which the skin engine wants at position 1, so + 2 */
78 token
->value
.i
= icon
+2;
81 if (element
->children_count
)
84 for (i
=0; i
<element
->children_count
; i
++)
85 retval
|= set_title_worker(title
, icon
, data
, element
->children
[i
]);
87 element
= element
->next
;
92 bool sb_set_title_text(char* title
, enum themable_icons icon
, enum screen_type screen
)
94 bool retval
= set_title_worker(title
, icon
, &sb_skin_data
[screen
],
95 sb_skin_data
[screen
].tree
) > 0;
100 void sb_skin_data_load(enum screen_type screen
, const char *buf
, bool isfile
)
102 struct wps_data
*data
= sb_skin
[screen
].data
;
105 success
= buf
&& skin_data_load(screen
, data
, buf
, isfile
);
109 /* hide the sb's default viewport because it has nasty effect with stuff
110 * not part of the statusbar,
111 * hence .sbs's without any other vps are unsupported*/
112 struct skin_viewport
*vp
= find_viewport(VP_DEFAULT_LABEL
, false, data
);
113 struct skin_element
*next_vp
= data
->tree
->next
;
118 { /* no second viewport, let parsing fail */
121 /* hide this viewport, forever */
122 vp
->hidden_flags
= VP_NEVER_VISIBLE
;
124 sb_set_info_vp(screen
, VP_DEFAULT_LABEL
);
127 if (!success
&& isfile
)
128 sb_create_from_settings(screen
);
130 static char *infovp_label
[NB_SCREENS
];
131 static char *oldinfovp_label
[NB_SCREENS
];
132 void sb_set_info_vp(enum screen_type screen
, char *label
)
134 infovp_label
[screen
] = label
;
137 struct viewport
*sb_skin_get_info_vp(enum screen_type screen
)
139 if (oldinfovp_label
[screen
] &&
140 strcmp(oldinfovp_label
[screen
], infovp_label
[screen
]))
142 /* UI viewport changed, so force a redraw */
143 oldinfovp_label
[screen
] = infovp_label
[screen
];
144 viewportmanager_theme_enable(screen
, false, NULL
);
145 viewportmanager_theme_undo(screen
, true);
147 return &find_viewport(infovp_label
[screen
], true, sb_skin
[screen
].data
)->vp
;
150 #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
151 char* sb_get_backdrop(enum screen_type screen
)
153 return sb_skin
[screen
].data
->backdrop
;
156 bool sb_set_backdrop(enum screen_type screen
, char* filename
)
160 sb_skin
[screen
].data
->backdrop
= NULL
;
163 else if (!sb_skin
[screen
].data
->backdrop
)
165 /* need to make room on the buffer */
167 #if defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)
168 if (screen
== SCREEN_REMOTE
)
169 buf_size
= REMOTE_LCD_BACKDROP_BYTES
;
172 buf_size
= LCD_BACKDROP_BYTES
;
173 sb_skin
[screen
].data
->backdrop
= (char*)skin_buffer_alloc(buf_size
);
174 if (!sb_skin
[screen
].data
->backdrop
)
178 if (!screens
[screen
].backdrop_load(filename
, sb_skin
[screen
].data
->backdrop
))
179 sb_skin
[screen
].data
->backdrop
= NULL
;
180 return sb_skin
[screen
].data
->backdrop
!= NULL
;
184 void sb_skin_update(enum screen_type screen
, bool force
)
186 static long next_update
[NB_SCREENS
] = {0};
188 if (!sb_skin_data
[screen
].wps_loaded
)
190 if (TIME_AFTER(current_tick
, next_update
[i
]) || force
)
192 #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
193 /* currently, all remotes are readable without backlight
194 * so still update those */
195 if (lcd_active() || (i
!= SCREEN_MAIN
))
197 skin_update(&sb_skin
[i
], force
?
198 SKIN_REFRESH_ALL
: SKIN_REFRESH_NON_STATIC
);
199 next_update
[i
] = current_tick
+ update_delay
; /* don't update too often */
200 sb_skin
[SCREEN_MAIN
].sync_data
->do_full_update
= false;
204 void do_sbs_update_callback(void *param
)
207 /* the WPS handles changing the actual id3 data in the id3 pointers
208 * we imported, we just want a full update */
209 sb_skin_sync_data
.do_full_update
= true;
210 /* force timeout in wps main loop, so that the update is instantly */
211 queue_post(&button_queue
, BUTTON_NONE
, 0);
214 void sb_skin_set_update_delay(int delay
)
216 update_delay
= delay
;
219 /* This creates and loads a ".sbs" based on the user settings for:
220 * - regular statusbar
225 void sb_create_from_settings(enum screen_type screen
)
227 char buf
[128], *ptr
, *ptr2
;
228 int len
, remaining
= sizeof(buf
);
229 int bar_position
= statusbar_position(screen
);
233 /* setup the inbuilt statusbar */
234 if (bar_position
!= STATUSBAR_OFF
)
236 int y
= 0, height
= STATUSBAR_HEIGHT
;
237 if (bar_position
== STATUSBAR_BOTTOM
)
239 y
= screens
[screen
].lcdheight
- STATUSBAR_HEIGHT
;
241 len
= snprintf(ptr
, remaining
, "%%V(0,%d,-,%d,0)\n%%wi\n",
246 /* %Vi viewport, colours handled by the parser */
248 if (screen
== SCREEN_REMOTE
)
249 ptr2
= global_settings
.remote_ui_vp_config
;
252 ptr2
= global_settings
.ui_vp_config
;
254 if (ptr2
[0] && ptr2
[0] != '-') /* from ui viewport setting */
258 len
= snprintf(ptr
, remaining
, "%%ax%%Vi(-,%s)\n", ptr2
);
259 /* The config put the colours at the end of the viewport,
260 * they need to be stripped for the skin code though */
263 comma
= strchr(comma
+1, ',');
265 } while (comma
&& param_count
< 6);
272 while (*comma
!= ',')
274 fg
[i
] = '\0'; comma
++; i
=0;
275 while (*comma
!= ')')
278 len
+= snprintf(end
, remaining
-len
, ") %%Vf(%s) %%Vb(%s)\n", fg
, bg
);
284 switch (bar_position
)
287 y
= STATUSBAR_HEIGHT
;
288 case STATUSBAR_BOTTOM
:
289 height
= screens
[screen
].lcdheight
- STATUSBAR_HEIGHT
;
292 height
= screens
[screen
].lcdheight
;
294 len
= snprintf(ptr
, remaining
, "%%ax%%Vi(-,0,%d,-,%d,1)\n",
297 sb_skin_data_load(screen
, buf
, false);
300 void sb_skin_init(void)
305 oldinfovp_label
[i
] = NULL
;
307 sb_skin_data
[i
].albumart
= NULL
;
308 sb_skin_data
[i
].playback_aa_slot
= -1;
310 sb_skin
[i
].data
= &sb_skin_data
[i
];
311 sb_skin
[i
].display
= &screens
[i
];
312 /* Currently no seperate wps_state needed/possible
313 so use the only available ( "global" ) one */
314 sb_skin
[i
].state
= &wps_state
;
315 sb_skin
[i
].sync_data
= &sb_skin_sync_data
;
319 #ifdef HAVE_TOUCHSCREEN
320 static bool bypass_sb_touchregions
= true;
321 void sb_bypass_touchregions(bool enable
)
323 bypass_sb_touchregions
= enable
;
326 int sb_touch_to_button(int context
)
328 static int last_context
= -1;
330 if (bypass_sb_touchregions
)
331 return ACTION_TOUCHSCREEN
;
333 if (last_context
!= context
)
334 skin_disarm_touchregions(&sb_skin_data
[SCREEN_MAIN
]);
335 last_context
= context
;
336 button
= skin_get_touchaction(&sb_skin_data
[SCREEN_MAIN
], &offset
);
340 #ifdef HAVE_VOLUME_IN_LIST
341 case ACTION_WPS_VOLUP
:
342 return ACTION_LIST_VOLUP
;
343 case ACTION_WPS_VOLDOWN
:
344 return ACTION_LIST_VOLDOWN
;