Allow viewport labels to be mostly free text instead of only one character. If this...
[kugel-rb.git] / apps / gui / statusbar-skinned.c
blob81eb92923dfcb83c70622430632b69ac393fe682
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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 ****************************************************************************/
22 #include "config.h"
24 #include "action.h"
25 #include "system.h"
26 #include "settings.h"
27 #include "appevents.h"
28 #include "screens.h"
29 #include "screen_access.h"
30 #include "strlcpy.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"
35 #include "viewport.h"
36 #include "statusbar.h"
37 #include "statusbar-skinned.h"
38 #include "debug.h"
39 #include "font.h"
40 #include "icon.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)
54 int retval = 0;
55 struct skin_element *element = root;
56 while (element)
58 struct wps_token *token = NULL;
59 if (element->type == CONDITIONAL)
61 struct conditional *cond = (struct conditional *)element->data;
62 token = cond->token;
64 else if (element->type == TAG)
66 token = (struct wps_token *)element->data;
68 if (token)
70 if (token->type == SKIN_TOKEN_LIST_TITLE_TEXT)
72 token->value.data = title;
73 retval = 1;
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)
83 int i;
84 for (i=0; i<element->children_count; i++)
85 retval |= set_title_worker(title, icon, data, element->children[i]);
87 element = element->next;
89 return retval;
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;
96 return retval;
100 void sb_skin_data_load(enum screen_type screen, const char *buf, bool isfile)
102 struct wps_data *data = sb_skin[screen].data;
104 int success;
105 success = buf && skin_data_load(screen, data, buf, isfile);
107 if (success)
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;
115 if (vp)
117 if (!next_vp)
118 { /* no second viewport, let parsing fail */
119 success = false;
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)
158 if (!filename)
160 sb_skin[screen].data->backdrop = NULL;
161 return true;
163 else if (!sb_skin[screen].data->backdrop)
165 /* need to make room on the buffer */
166 size_t buf_size;
167 #if defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)
168 if (screen == SCREEN_REMOTE)
169 buf_size = REMOTE_LCD_BACKDROP_BYTES;
170 else
171 #endif
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)
175 return false;
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;
183 #endif
184 void sb_skin_update(enum screen_type screen, bool force)
186 static long next_update[NB_SCREENS] = {0};
187 int i = screen;
188 if (!sb_skin_data[screen].wps_loaded)
189 return;
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))
196 #endif
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)
206 (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
221 * - colours
222 * - ui viewport
223 * - backdrop
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);
230 ptr = buf;
231 ptr[0] = '\0';
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",
242 y, height);
243 remaining -= len;
244 ptr += len;
246 /* %Vi viewport, colours handled by the parser */
247 #if NB_SCREENS > 1
248 if (screen == SCREEN_REMOTE)
249 ptr2 = global_settings.remote_ui_vp_config;
250 else
251 #endif
252 ptr2 = global_settings.ui_vp_config;
254 if (ptr2[0] && ptr2[0] != '-') /* from ui viewport setting */
256 char *comma = ptr;
257 int param_count = 0;
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 */
261 do {
262 param_count++;
263 comma = strchr(comma+1, ',');
265 } while (comma && param_count < 6);
266 if (comma)
268 char *end = comma;
269 char fg[8], bg[8];
270 int i = 0;
271 comma++;
272 while (*comma != ',')
273 fg[i++] = *comma++;
274 fg[i] = '\0'; comma++; i=0;
275 while (*comma != ')')
276 bg[i++] = *comma++;
277 bg[i] = '\0';
278 len += snprintf(end, remaining-len, ") %%Vf(%s) %%Vb(%s)\n", fg, bg);
281 else
283 int y = 0, height;
284 switch (bar_position)
286 case STATUSBAR_TOP:
287 y = STATUSBAR_HEIGHT;
288 case STATUSBAR_BOTTOM:
289 height = screens[screen].lcdheight - STATUSBAR_HEIGHT;
290 break;
291 default:
292 height = screens[screen].lcdheight;
294 len = snprintf(ptr, remaining, "%%ax%%Vi(-,0,%d,-,%d,1)\n",
295 y, height);
297 sb_skin_data_load(screen, buf, false);
300 void sb_skin_init(void)
302 int i;
303 FOR_NB_SCREENS(i)
305 oldinfovp_label[i] = NULL;
306 #ifdef HAVE_ALBUMART
307 sb_skin_data[i].albumart = NULL;
308 sb_skin_data[i].playback_aa_slot = -1;
309 #endif
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;
329 int button, offset;
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);
338 switch (button)
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;
345 #endif
346 /* TODO */
348 return button;
350 #endif