blob: d136f90aa5cebe33b3885ad9635768403a83c86e [file] [log] [blame]
Jonathan Gordon46142b92010-09-14 11:59:52 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Stuart Martin
11 * RTC config saving code (C) 2002 by hessu@hes.iki.fi
12 *
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.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22#include <stdio.h>
23#include <stddef.h>
24#include <stdlib.h>
25#include <limits.h>
26#include "inttypes.h"
27#include "config.h"
28#include "action.h"
29#include "crc32.h"
30#include "settings.h"
31#include "wps.h"
32#include "file.h"
33#include "buffer.h"
34#if CONFIG_TUNER
35#include "radio.h"
36#endif
37#include "skin_engine.h"
38#include "skin_buffer.h"
39#include "statusbar-skinned.h"
40
Jonathan Gordon97857322010-11-04 10:15:33 +000041static bool skins_initialising = true;
42
Thomas Martitz5411e142010-11-05 19:12:23 +000043/* App uses the host malloc to manage the buffer */
44#ifdef APPLICATION
45#define skin_buffer NULL
46void theme_init_buffer(void)
47{
48 skins_initialising = false;
49}
50#else
Thomas Martitzd0b72e22011-08-30 14:01:33 +000051static char skin_buffer[SKIN_BUFFER_SIZE];
Jonathan Gordon46142b92010-09-14 11:59:52 +000052void theme_init_buffer(void)
53{
Jonathan Gordon97857322010-11-04 10:15:33 +000054 skins_initialising = false;
Jonathan Gordon46142b92010-09-14 11:59:52 +000055}
Jonathan Gordon97857322010-11-04 10:15:33 +000056#endif
Jonathan Gordon46142b92010-09-14 11:59:52 +000057
58void settings_apply_skins(void)
59{
60 int i, j;
61 skin_buffer_init(skin_buffer, SKIN_BUFFER_SIZE);
62
63#ifdef HAVE_LCD_BITMAP
64 skin_backdrop_init();
65 skin_font_init();
66#endif
67 gui_sync_skin_init();
68
69 /* Make sure each skin is loaded */
70 for (i=0; i<SKINNABLE_SCREENS_COUNT; i++)
71 {
72 FOR_NB_SCREENS(j)
73 skin_get_gwps(i, j);
74 }
Jonathan Gordon71379ca2010-09-14 12:21:56 +000075#if LCD_DEPTH > 1 || defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
Jonathan Gordon46142b92010-09-14 11:59:52 +000076 skin_backdrops_preload(); /* should maybe check the retval here... */
Jonathan Gordon71379ca2010-09-14 12:21:56 +000077#endif
Jonathan Gordon46142b92010-09-14 11:59:52 +000078 viewportmanager_theme_changed(THEME_STATUSBAR);
79#if LCD_DEPTH > 1 || defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
80 FOR_NB_SCREENS(i)
81 skin_backdrop_show(sb_get_backdrop(i));
82#endif
83}
84
85
86char* wps_default_skin(enum screen_type screen);
87char* default_radio_skin(enum screen_type screen);
Jonathan Gordon71379ca2010-09-14 12:21:56 +000088
Jonathan Gordon46142b92010-09-14 11:59:52 +000089struct wps_state wps_state = { .id3 = NULL };
90static struct gui_skin_helper {
91 int (*preproccess)(enum screen_type screen, struct wps_data *data);
92 int (*postproccess)(enum screen_type screen, struct wps_data *data);
93 char* (*default_skin)(enum screen_type screen);
94} skin_helpers[SKINNABLE_SCREENS_COUNT] = {
95 [CUSTOM_STATUSBAR] = { sb_preproccess, sb_postproccess, sb_create_from_settings },
96 [WPS] = { NULL, NULL, wps_default_skin },
97#if CONFIG_TUNER
98 [FM_SCREEN] = { NULL, NULL, default_radio_skin }
99#endif
100};
101
Bertrik Sikken91453fb2010-10-16 15:23:41 +0000102static struct gui_skin {
Jonathan Gordon46142b92010-09-14 11:59:52 +0000103 struct gui_wps gui_wps;
104 struct wps_data data;
105 char *buffer_start;
106 size_t buffer_usage;
107
108 bool needs_full_update;
109} skins[SKINNABLE_SCREENS_COUNT][NB_SCREENS];
110
111
112void gui_sync_skin_init(void)
113{
114 int i, j;
115 for(j=0; j<SKINNABLE_SCREENS_COUNT; j++)
116 {
117 FOR_NB_SCREENS(i)
118 {
119 skins[j][i].buffer_start = NULL;
120 skins[j][i].needs_full_update = true;
121#ifdef HAVE_ALBUMART
122 skins[j][i].data.albumart = NULL;
123 skins[j][i].data.playback_aa_slot = -1;
124#endif
125 skins[j][i].gui_wps.data = &skins[j][i].data;
126 skins[j][i].data.wps_loaded = false;
127 skins[j][i].gui_wps.display = &screens[i];
128 }
129 }
130}
131
132void skin_load(enum skinnable_screens skin, enum screen_type screen,
133 const char *buf, bool isfile)
134{
135 bool loaded = false;
136
137 if (skin_helpers[skin].preproccess)
138 skin_helpers[skin].preproccess(screen, &skins[skin][screen].data);
139
140 if (buf && *buf)
141 loaded = skin_data_load(screen, &skins[skin][screen].data, buf, isfile);
142
143 if (!loaded && skin_helpers[skin].default_skin)
144 loaded = skin_data_load(screen, &skins[skin][screen].data,
145 skin_helpers[skin].default_skin(screen), false);
146
147 skins[skin][screen].needs_full_update = true;
148 if (skin_helpers[skin].postproccess)
149 skin_helpers[skin].postproccess(screen, &skins[skin][screen].data);
150}
151
152static bool loading_a_sbs = false;
153struct gui_wps *skin_get_gwps(enum skinnable_screens skin, enum screen_type screen)
154{
155 if (!loading_a_sbs && skins[skin][screen].data.wps_loaded == false)
156 {
Thomas Martitz2c241602010-12-06 22:26:31 +0000157 char buf[MAX_PATH*2];
Jonathan Gordon71379ca2010-09-14 12:21:56 +0000158 char *setting = NULL, *ext = NULL;
Jonathan Gordon46142b92010-09-14 11:59:52 +0000159 switch (skin)
160 {
161 case CUSTOM_STATUSBAR:
Jonathan Gordon71379ca2010-09-14 12:21:56 +0000162#ifdef HAVE_LCD_BITMAP
Jonathan Gordon97857322010-11-04 10:15:33 +0000163 if (skins_initialising)
Jonathan Gordon46142b92010-09-14 11:59:52 +0000164 {
165 /* still loading, buffers not initialised yet,
166 * viewport manager calls into the sbs code, not really
167 * caring if the sbs has loaded or not, so just return
168 * the gwps, this is safe. */
169 return &skins[skin][screen].gui_wps;
170 }
171 /* during the sbs load it will call skin_get_gwps() a few times
172 * which will eventually stkov the viewportmanager, so make
173 * sure we don't let that happen */
174 loading_a_sbs = true;
175#if defined(HAVE_REMOTE_LCD) && NB_SCREENS > 1
176 if (screen == SCREEN_REMOTE)
177 {
178 setting = global_settings.rsbs_file;
179 ext = "rsbs";
180 }
181 else
182#endif
183 {
184 setting = global_settings.sbs_file;
185 ext = "sbs";
186 }
Jonathan Gordon71379ca2010-09-14 12:21:56 +0000187#else
188 return &skins[skin][screen].gui_wps;
189#endif /* HAVE_LCD_BITMAP */
Jonathan Gordon46142b92010-09-14 11:59:52 +0000190 break;
191 case WPS:
192#if defined(HAVE_REMOTE_LCD) && NB_SCREENS > 1
193 if (screen == SCREEN_REMOTE)
194 {
195 setting = global_settings.rwps_file;
196 ext = "rwps";
197 }
198 else
199#endif
200 {
201 setting = global_settings.wps_file;
202 ext = "wps";
203 }
204 break;
205#if CONFIG_TUNER
206 case FM_SCREEN:
207#if defined(HAVE_REMOTE_LCD) && NB_SCREENS > 1
208 if (screen == SCREEN_REMOTE)
209 {
210 setting = global_settings.rfms_file;
211 ext = "rfms";
212 }
213 else
214#endif
215 {
216 setting = global_settings.fms_file;
217 ext = "fms";
218 }
219 break;
220#endif
221 default:
222 return NULL;
223 }
224
225 buf[0] = '\0'; /* force it to reload the default */
226 if (strcmp(setting, "rockbox_failsafe"))
227 {
Thomas Martitz2c241602010-12-06 22:26:31 +0000228 snprintf(buf, sizeof buf, WPS_DIR "/%s.%s", setting, ext);
Jonathan Gordon46142b92010-09-14 11:59:52 +0000229 }
230 cpu_boost(true);
231 skin_load(skin, screen, buf, true);
232 cpu_boost(false);
233 loading_a_sbs = false;
234 }
235
236 return &skins[skin][screen].gui_wps;
237}
238
239struct wps_state *skin_get_global_state(void)
240{
241 return &wps_state;
242}
243
244/* This is called to find out if we the screen needs a full update.
245 * if true you MUST do a full update as the next call will return false */
246bool skin_do_full_update(enum skinnable_screens skin,
247 enum screen_type screen)
248{
249 bool ret = skins[skin][screen].needs_full_update;
250 skins[skin][screen].needs_full_update = false;
251 return ret;
252}
253
254/* tell a skin to do a full update next time */
255void skin_request_full_update(enum skinnable_screens skin)
256{
257 int i;
258 FOR_NB_SCREENS(i)
259 skins[skin][i].needs_full_update = true;
260}