Use buflib for all skin engine allocations.
[maemo-rb.git] / apps / gui / statusbar-skinned.c
blob960cf67d4d92d2ddd08c424899a1555df18d0228
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"
41 #include "option_select.h"
42 #ifdef HAVE_TOUCHSCREEN
43 #include "sound.h"
44 #include "misc.h"
45 #endif
47 /* initial setup of wps_data */
48 static int update_delay = DEFAULT_UPDATE_DELAY;
50 static bool sbs_has_title[NB_SCREENS];
51 static char* sbs_title[NB_SCREENS];
52 static enum themable_icons sbs_icon[NB_SCREENS];
54 bool sb_set_title_text(char* title, enum themable_icons icon, enum screen_type screen)
56 sbs_title[screen] = title;
57 /* Icon_NOICON == -1 which the skin engine wants at position 1, so + 2 */
58 sbs_icon[screen] = icon + 2;
59 return sbs_has_title[screen];
62 void sb_skin_has_title(enum screen_type screen)
64 sbs_has_title[screen] = true;
67 const char* sb_get_title(enum screen_type screen)
69 return sbs_has_title[screen] ? sbs_title[screen] : NULL;
71 enum themable_icons sb_get_icon(enum screen_type screen)
73 return sbs_has_title[screen] ? sbs_icon[screen] : Icon_NOICON + 2;
76 int sb_preproccess(enum screen_type screen, struct wps_data *data)
78 (void)data;
79 sbs_has_title[screen] = false;
80 viewportmanager_theme_enable(screen, false, NULL);
81 return 1;
83 int sb_postproccess(enum screen_type screen, struct wps_data *data)
85 if (data->wps_loaded)
87 /* hide the sb's default viewport because it has nasty effect with stuff
88 * not part of the statusbar,
89 * hence .sbs's without any other vps are unsupported*/
90 struct skin_viewport *vp = skin_find_item(VP_DEFAULT_LABEL_STRING, SKIN_FIND_VP, data);
91 struct skin_element *tree = SKINOFFSETTOPTR(get_skin_buffer(data), data->tree);
92 struct skin_element *next_vp = SKINOFFSETTOPTR(get_skin_buffer(data), tree->next);
94 if (vp)
96 if (!next_vp)
97 { /* no second viewport, let parsing fail */
98 return 0;
100 /* hide this viewport, forever */
101 vp->hidden_flags = VP_NEVER_VISIBLE;
103 sb_set_info_vp(screen, VP_DEFAULT_LABEL);
105 viewportmanager_theme_undo(screen, false);
106 return 1;
109 static OFFSETTYPE(char*) infovp_label[NB_SCREENS];
110 static OFFSETTYPE(char*) oldinfovp_label[NB_SCREENS];
111 void sb_set_info_vp(enum screen_type screen, OFFSETTYPE(char*) label)
113 infovp_label[screen] = label;
116 struct viewport *sb_skin_get_info_vp(enum screen_type screen)
118 struct wps_data *data = skin_get_gwps(CUSTOM_STATUSBAR, screen)->data;
119 struct skin_viewport *vp = NULL;
120 char *label;
121 if (oldinfovp_label[screen] &&
122 (oldinfovp_label[screen] != infovp_label[screen]))
124 /* UI viewport changed, so force a redraw */
125 oldinfovp_label[screen] = infovp_label[screen];
126 viewportmanager_theme_enable(screen, false, NULL);
127 viewportmanager_theme_undo(screen, true);
129 label = SKINOFFSETTOPTR(get_skin_buffer(data), infovp_label[screen]);
130 if (infovp_label[screen] == VP_DEFAULT_LABEL)
131 label = VP_DEFAULT_LABEL_STRING;
132 vp = skin_find_item(label, SKIN_FIND_UIVP, data);
133 if (!vp)
134 return NULL;
135 if (vp->parsed_fontid == 1)
136 vp->vp.font = screens[screen].getuifont();
137 return &vp->vp;
140 #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
141 int sb_get_backdrop(enum screen_type screen)
143 struct wps_data *data = skin_get_gwps(CUSTOM_STATUSBAR, screen)->data;
144 if (data->wps_loaded)
145 return data->backdrop_id;
146 else
147 return -1;
150 #endif
151 static bool force_waiting = false;
152 void sb_skin_update(enum screen_type screen, bool force)
154 struct wps_data *data = skin_get_gwps(CUSTOM_STATUSBAR, screen)->data;
155 static long next_update[NB_SCREENS] = {0};
156 int i = screen;
157 if (!data->wps_loaded)
158 return;
159 if (TIME_AFTER(current_tick, next_update[i]) || force || force_waiting)
161 force_waiting = false;
162 #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
163 /* currently, all remotes are readable without backlight
164 * so still update those */
165 if (lcd_active() || (i != SCREEN_MAIN))
166 #endif
168 bool full_update = skin_do_full_update(CUSTOM_STATUSBAR, screen);
169 skin_update(CUSTOM_STATUSBAR, screen, force ||
170 full_update ? SKIN_REFRESH_ALL : SKIN_REFRESH_NON_STATIC);
172 next_update[i] = current_tick + update_delay; /* don't update too often */
176 void do_sbs_update_callback(void *param)
178 (void)param;
179 /* the WPS handles changing the actual id3 data in the id3 pointers
180 * we imported, we just want a full update */
181 skin_request_full_update(CUSTOM_STATUSBAR);
182 force_waiting = true;
183 /* force timeout in wps main loop, so that the update is instantly */
184 queue_post(&button_queue, BUTTON_NONE, 0);
187 void sb_skin_set_update_delay(int delay)
189 update_delay = delay;
192 /* This creates and loads a ".sbs" based on the user settings for:
193 * - regular statusbar
194 * - colours
195 * - ui viewport
196 * - backdrop
198 char* sb_create_from_settings(enum screen_type screen)
200 static char buf[128];
201 char *ptr, *ptr2;
202 int len, remaining = sizeof(buf);
203 int bar_position = statusbar_position(screen);
204 ptr = buf;
205 ptr[0] = '\0';
207 /* setup the inbuilt statusbar */
208 if (bar_position != STATUSBAR_OFF)
210 int y = 0, height = STATUSBAR_HEIGHT;
211 if (bar_position == STATUSBAR_BOTTOM)
213 y = screens[screen].lcdheight - STATUSBAR_HEIGHT;
215 len = snprintf(ptr, remaining, "%%V(0,%d,-,%d,0)\n%%wi\n",
216 y, height);
217 remaining -= len;
218 ptr += len;
220 /* %Vi viewport, colours handled by the parser */
221 #if NB_SCREENS > 1
222 if (screen == SCREEN_REMOTE)
223 ptr2 = global_settings.remote_ui_vp_config;
224 else
225 #endif
226 ptr2 = global_settings.ui_vp_config;
228 if (ptr2[0] && ptr2[0] != '-') /* from ui viewport setting */
230 char *comma = ptr;
231 int param_count = 0;
232 len = snprintf(ptr, remaining, "%%ax%%Vi(-,%s)\n", ptr2);
233 /* The config put the colours at the end of the viewport,
234 * they need to be stripped for the skin code though */
235 do {
236 param_count++;
237 comma = strchr(comma+1, ',');
239 } while (comma && param_count < 6);
240 if (comma)
242 char *end = comma;
243 char fg[8], bg[8];
244 int i = 0;
245 comma++;
246 while (*comma != ',')
247 fg[i++] = *comma++;
248 fg[i] = '\0'; comma++; i=0;
249 while (*comma != ')')
250 bg[i++] = *comma++;
251 bg[i] = '\0';
252 len += snprintf(end, remaining-len, ") %%Vf(%s) %%Vb(%s)\n", fg, bg);
255 else
257 int y = 0, height;
258 switch (bar_position)
260 case STATUSBAR_TOP:
261 y = STATUSBAR_HEIGHT;
262 case STATUSBAR_BOTTOM:
263 height = screens[screen].lcdheight - STATUSBAR_HEIGHT;
264 break;
265 default:
266 height = screens[screen].lcdheight;
268 len = snprintf(ptr, remaining, "%%ax%%Vi(-,0,%d,-,%d,1)\n",
269 y, height);
271 return buf;
274 void sb_skin_init(void)
276 FOR_NB_SCREENS(i)
278 oldinfovp_label[i] = VP_DEFAULT_LABEL;
282 #ifdef HAVE_TOUCHSCREEN
283 static bool bypass_sb_touchregions = true;
284 void sb_bypass_touchregions(bool enable)
286 bypass_sb_touchregions = enable;
289 int sb_touch_to_button(int context)
291 struct touchregion *region;
292 static int last_context = -1;
293 int button, offset;
294 if (bypass_sb_touchregions)
295 return ACTION_TOUCHSCREEN;
297 if (last_context != context)
298 skin_disarm_touchregions(skin_get_gwps(CUSTOM_STATUSBAR, SCREEN_MAIN)->data);
299 last_context = context;
300 button = skin_get_touchaction(skin_get_gwps(CUSTOM_STATUSBAR, SCREEN_MAIN)->data,
301 &offset, &region);
303 switch (button)
305 #ifdef HAVE_VOLUME_IN_LIST
306 case ACTION_WPS_VOLUP:
307 return ACTION_LIST_VOLUP;
308 case ACTION_WPS_VOLDOWN:
309 return ACTION_LIST_VOLDOWN;
310 #endif
311 /* TODO */
313 return button;
315 #endif