Fix player red and remove an obsolete function call.
[kugel-rb.git] / apps / gui / viewport.c
blobd91aa4276274e5570ca593dda3fde14ca49c7687
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2008 by Jonathan Gordon
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 <stdlib.h>
23 #include "config.h"
24 #include "lcd.h"
25 #include "lcd-remote.h"
26 #include "font.h"
27 #include "viewport.h"
28 #include "screen_access.h"
29 #include "settings.h"
30 #include "misc.h"
32 /*some short cuts for fg/bg/line selector handling */
33 #ifdef HAVE_LCD_COLOR
34 #define LINE_SEL_FROM_SETTINGS(vp) \
35 do { \
36 vp->lss_pattern = global_settings.lss_color; \
37 vp->lse_pattern = global_settings.lse_color; \
38 vp->lst_pattern = global_settings.lst_color; \
39 } while (0)
40 #define FG_FALLBACK global_settings.fg_color
41 #define BG_FALLBACK global_settings.bg_color
42 #else
43 /* mono/greyscale doesn't have most of the above */
44 #define LINE_SEL_FROM_SETTINGS(vp)
45 #define FG_FALLBACK LCD_DEFAULT_FG
46 #define BG_FALLBACK LCD_DEFAULT_BG
47 #endif
49 /* all below isn't needed for pc tools (i.e. checkwps/wps editor)
50 * only viewport_parse_viewport() is */
51 #ifndef __PCTOOL__
52 #include "sprintf.h"
53 #include "string.h"
54 #include "kernel.h"
55 #include "system.h"
56 #include "statusbar.h"
57 #include "appevents.h"
58 #ifdef HAVE_LCD_BITMAP
59 #include "language.h"
60 #endif
62 static int statusbar_enabled = 0;
64 #ifdef HAVE_LCD_BITMAP
65 static void viewport_rtl_handler(struct viewport *vp);
67 static struct {
68 struct viewport* vp;
69 int active[NB_SCREENS];
70 } ui_vp_info;
72 static struct viewport custom_vp[NB_SCREENS];
74 /* callbacks for GUI_EVENT_* events */
75 static void viewportmanager_ui_vp_changed(void *param);
76 static void statusbar_toggled(void* param);
77 static unsigned viewport_init_ui_vp(void);
78 #endif
79 static void viewportmanager_redraw(void* data);
81 int viewport_get_nb_lines(struct viewport *vp)
83 #ifdef HAVE_LCD_BITMAP
84 return vp->height/font_get(vp->font)->height;
85 #else
86 (void)vp;
87 return 2;
88 #endif
91 static bool showing_bars(enum screen_type screen)
93 if (statusbar_enabled & VP_SB_ONSCREEN(screen))
95 #ifdef HAVE_LCD_BITMAP
96 bool ignore = statusbar_enabled & VP_SB_IGNORE_SETTING(screen);
97 return ignore || (statusbar_position(screen));
98 #else
99 return true;
100 #endif
102 return false;
105 void viewport_set_fullscreen(struct viewport *vp, enum screen_type screen)
107 vp->x = 0;
108 vp->width = screens[screen].lcdwidth;
110 #ifdef HAVE_LCD_BITMAP
111 viewport_rtl_handler(vp);
112 vp->drawmode = DRMODE_SOLID;
113 vp->font = FONT_UI; /* default to UI to discourage SYSFONT use */
115 vp->height = screens[screen].lcdheight;
116 if (statusbar_position(screen) != STATUSBAR_BOTTOM && showing_bars(screen))
117 vp->y = STATUSBAR_HEIGHT;
118 else
119 vp->y = 0;
120 #else
121 vp->y = 0;
122 #endif
123 vp->height = screens[screen].lcdheight - (showing_bars(screen)?STATUSBAR_HEIGHT:0);
125 #if LCD_DEPTH > 1
126 #ifdef HAVE_REMOTE_LCD
127 /* We only need this test if there is a remote LCD */
128 if (screen == SCREEN_MAIN)
129 #endif
131 vp->fg_pattern = FG_FALLBACK;
132 vp->bg_pattern = BG_FALLBACK;
133 LINE_SEL_FROM_SETTINGS(vp);
135 #endif
137 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
138 if (screen == SCREEN_REMOTE)
140 vp->fg_pattern = LCD_REMOTE_DEFAULT_FG;
141 vp->bg_pattern = LCD_REMOTE_DEFAULT_BG;
143 #endif
147 void viewport_set_defaults(struct viewport *vp, enum screen_type screen)
149 #ifdef HAVE_LCD_BITMAP
150 if (ui_vp_info.active[screen])
151 *vp = ui_vp_info.vp[screen];
152 else
153 #endif
154 viewport_set_fullscreen(vp, screen);
158 void viewportmanager_init(void)
160 #ifdef HAVE_LCD_BITMAP
161 int retval, i;
162 add_event(GUI_EVENT_STATUSBAR_TOGGLE, false, statusbar_toggled);
163 retval = viewport_init_ui_vp();
164 FOR_NB_SCREENS(i)
165 ui_vp_info.active[i] = retval & BIT_N(i);
166 ui_vp_info.vp = custom_vp;
167 #endif
168 viewportmanager_set_statusbar(VP_SB_ALLSCREENS);
171 int viewportmanager_get_statusbar(void)
173 return statusbar_enabled;
176 int viewportmanager_set_statusbar(int enabled)
178 int old = statusbar_enabled;
179 statusbar_enabled = enabled;
180 if (enabled)
182 int i;
183 FOR_NB_SCREENS(i)
185 if (showing_bars(i))
186 gui_statusbar_draw(&statusbars.statusbars[i], true);
188 add_event(GUI_EVENT_ACTIONUPDATE, false, viewportmanager_redraw);
190 else
192 remove_event(GUI_EVENT_ACTIONUPDATE, viewportmanager_redraw);
194 return old;
197 static void viewportmanager_redraw(void* data)
199 int i;
201 FOR_NB_SCREENS(i)
203 if (showing_bars(i))
204 gui_statusbar_draw(&statusbars.statusbars[i], NULL != data);
207 #ifdef HAVE_LCD_BITMAP
209 static void statusbar_toggled(void* param)
211 (void)param;
212 /* update vp manager for the new setting and reposition vps
213 * if necessary */
214 viewportmanager_theme_changed(THEME_STATUSBAR);
217 void viewportmanager_theme_changed(int which)
219 int i;
220 #ifdef HAVE_BUTTONBAR
221 if (which & THEME_BUTTONBAR)
222 { /* don't handle further, the custom ui viewport ignores the buttonbar,
223 * as does viewport_set_defaults(), since only lists use it*/
224 screens[SCREEN_MAIN].has_buttonbar = global_settings.buttonbar;
226 #endif
227 if (which & THEME_UI_VIEWPORT)
229 int retval = viewport_init_ui_vp();
230 /* reset the ui viewport */
231 FOR_NB_SCREENS(i)
232 ui_vp_info.active[i] = retval & BIT_N(i);
234 if (retval != 0)
235 add_event(GUI_EVENT_REFRESH, false, viewportmanager_ui_vp_changed);
236 else
237 remove_event(GUI_EVENT_REFRESH, viewportmanager_ui_vp_changed);
238 /* and point to it */
239 ui_vp_info.vp = custom_vp;
241 else if (which & THEME_LANGUAGE)
242 { /* THEME_UI_VIEWPORT handles rtl already */
243 FOR_NB_SCREENS(i)
244 viewport_rtl_handler(&custom_vp[i]);
246 if (which & THEME_STATUSBAR)
248 statusbar_enabled = VP_SB_HIDE_ALL;
250 FOR_NB_SCREENS(i)
252 if (statusbar_position(i) != STATUSBAR_OFF)
253 statusbar_enabled |= VP_SB_ONSCREEN(i);
256 if (statusbar_enabled != VP_SB_HIDE_ALL)
257 add_event(GUI_EVENT_ACTIONUPDATE, false, viewportmanager_redraw);
258 else
259 remove_event(GUI_EVENT_ACTIONUPDATE, viewportmanager_redraw);
261 /* reposition viewport to fit statusbar, only if not using the ui vp */
263 FOR_NB_SCREENS(i)
265 if (!ui_vp_info.active[i])
266 viewport_set_fullscreen(&custom_vp[i], i);
269 send_event(GUI_EVENT_THEME_CHANGED, NULL);
272 static void viewportmanager_ui_vp_changed(void *param)
274 /* if the user changed the theme, we need to initiate a full redraw */
275 int i;
276 /* cast param to a function */
277 void (*draw_func)(void) = ((void(*)(void))param);
278 /* start with clearing the screen */
279 FOR_NB_SCREENS(i)
280 screens[i].clear_display();
281 /* redraw the statusbar if it was enabled */
282 viewportmanager_set_statusbar(statusbar_enabled);
283 /* call the passed function which will redraw the content of
284 * the current screen */
285 if (param != NULL)
286 draw_func();
287 FOR_NB_SCREENS(i)
288 screens[i].update();
291 void viewport_set_current_vp(struct viewport* vp)
293 if (vp != NULL)
294 ui_vp_info.vp = vp;
295 else
296 ui_vp_info.vp = custom_vp;
298 /* must be done after the assignment above or event handler get old vps */
299 send_event(GUI_EVENT_THEME_CHANGED, NULL);
302 struct viewport* viewport_get_current_vp(void)
304 return ui_vp_info.vp;
307 bool viewport_ui_vp_get_state(enum screen_type screen)
309 return ui_vp_info.active[screen];
313 * (re)parse the UI vp from the settings
314 * - Returns
315 * 0 if no UI vp is used at all
316 * else the bit for the screen (1<<screen) is set
318 static unsigned viewport_init_ui_vp(void)
320 int screen;
321 unsigned ret = 0;
322 char *setting;
323 FOR_NB_SCREENS(screen)
325 #ifdef HAVE_REMOTE_LCD
326 if ((screen == SCREEN_REMOTE))
327 setting = global_settings.remote_ui_vp_config;
328 else
329 #endif
330 setting = global_settings.ui_vp_config;
333 if (!(viewport_parse_viewport(&custom_vp[screen], screen,
334 setting, ',')))
335 viewport_set_fullscreen(&custom_vp[screen], screen);
336 else
337 ret |= BIT_N(screen);
339 return ret;
342 #ifdef HAVE_TOUCHSCREEN
343 /* check if a point (x and y coordinates) are within a viewport */
344 bool viewport_point_within_vp(const struct viewport *vp, int x, int y)
346 bool is_x = (x >= vp->x && x < (vp->x + vp->width));
347 bool is_y = (y >= vp->y && y < (vp->y + vp->height));
348 return (is_x && is_y);
350 #endif /* HAVE_TOUCHSCREEN */
351 #endif /* HAVE_LCD_BITMAP */
352 #endif /* __PCTOOL__ */
354 #ifdef HAVE_LCD_COLOR
355 #define ARG_STRING(_depth) ((_depth) == 2 ? "dddddgg":"dddddcc")
356 #else
357 #define ARG_STRING(_depth) "dddddgg"
358 #endif
360 #ifdef HAVE_LCD_BITMAP
362 static void viewport_rtl_handler(struct viewport *vp)
364 #ifndef __PCTOOL__
365 if (UNLIKELY(lang_is_rtl()))
366 vp->flags |= VP_FLAG_IS_RTL;
367 else
368 #endif
369 vp->flags &= ~VP_FLAG_IS_RTL;
372 const char* viewport_parse_viewport(struct viewport *vp,
373 enum screen_type screen,
374 const char *bufptr,
375 const char separator)
377 /* parse the list to the viewport struct */
378 const char *ptr = bufptr;
379 int depth;
380 uint32_t set = 0;
382 enum {
383 PL_X = 0,
384 PL_Y,
385 PL_WIDTH,
386 PL_HEIGHT,
387 PL_FONT,
388 PL_FG,
389 PL_BG,
392 /* Work out the depth of this display */
393 depth = screens[screen].depth;
394 #if (LCD_DEPTH == 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH == 1)
395 if (depth == 1)
397 if (!(ptr = parse_list("ddddd", &set, separator, ptr,
398 &vp->x, &vp->y, &vp->width, &vp->height, &vp->font)))
399 return NULL;
401 else
402 #endif
403 #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
404 if (depth >= 2)
406 if (!(ptr = parse_list(ARG_STRING(depth), &set, separator, ptr,
407 &vp->x, &vp->y, &vp->width, &vp->height, &vp->font,
408 &vp->fg_pattern,&vp->bg_pattern)))
409 return NULL;
411 else
412 #endif
414 #undef ARG_STRING
416 /* X and Y *must* be set */
417 if (!LIST_VALUE_PARSED(set, PL_X) || !LIST_VALUE_PARSED(set, PL_Y))
418 return NULL;
420 /* fix defaults */
421 if (!LIST_VALUE_PARSED(set, PL_WIDTH))
422 vp->width = screens[screen].lcdwidth - vp->x;
423 if (!LIST_VALUE_PARSED(set, PL_HEIGHT))
424 vp->height = screens[screen].lcdheight - vp->y;
426 #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
427 if (!LIST_VALUE_PARSED(set, PL_FG))
428 vp->fg_pattern = FG_FALLBACK;
429 if (!LIST_VALUE_PARSED(set, PL_BG))
430 vp->bg_pattern = BG_FALLBACK;
431 #endif /* LCD_DEPTH > 1 || LCD_REMOTE_DEPTH > 1 */
433 LINE_SEL_FROM_SETTINGS(vp);
435 /* Validate the viewport dimensions - we know that the numbers are
436 non-negative integers, ignore bars and assume the viewport takes them
437 * into account */
438 if ((vp->x >= screens[screen].lcdwidth) ||
439 ((vp->x + vp->width) > screens[screen].lcdwidth) ||
440 (vp->y >= screens[screen].lcdheight) ||
441 ((vp->y + vp->height) > screens[screen].lcdheight))
443 return NULL;
446 /* Default to using the user font if the font was an invalid number or '-'*/
447 if (((vp->font != FONT_SYSFIXED) && (vp->font != FONT_UI))
448 || !LIST_VALUE_PARSED(set, PL_FONT)
450 vp->font = FONT_UI;
452 /* Set the defaults for fields not user-specified */
453 vp->drawmode = DRMODE_SOLID;
454 viewport_rtl_handler(vp);
456 return ptr;
458 #endif