Undo the part of r28480 that caused the simulator to also use host malloc.
[kugel-rb.git] / apps / gui / skin_engine / skin_engine.c
blob25baeb2c3c76fbbd922ecb1e295d446fb887bf51
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 by Stuart Martin
11 * RTC config saving code (C) 2002 by hessu@hes.iki.fi
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.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
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"
41 static bool skins_initialising = true;
43 /* App uses the host malloc to manage the buffer */
44 #ifdef APPLICATION
45 #define skin_buffer NULL
46 void theme_init_buffer(void)
48 skins_initialising = false;
50 #else
51 static char *skin_buffer = NULL;
52 void theme_init_buffer(void)
54 skin_buffer = buffer_alloc(SKIN_BUFFER_SIZE);
55 skins_initialising = false;
57 #endif
59 void settings_apply_skins(void)
61 int i, j;
62 skin_buffer_init(skin_buffer, SKIN_BUFFER_SIZE);
64 #ifdef HAVE_LCD_BITMAP
65 skin_backdrop_init();
66 skin_font_init();
67 #endif
68 gui_sync_skin_init();
70 /* Make sure each skin is loaded */
71 for (i=0; i<SKINNABLE_SCREENS_COUNT; i++)
73 FOR_NB_SCREENS(j)
74 skin_get_gwps(i, j);
76 #if LCD_DEPTH > 1 || defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
77 skin_backdrops_preload(); /* should maybe check the retval here... */
78 #endif
79 viewportmanager_theme_changed(THEME_STATUSBAR);
80 #if LCD_DEPTH > 1 || defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
81 FOR_NB_SCREENS(i)
82 skin_backdrop_show(sb_get_backdrop(i));
83 #endif
87 char* wps_default_skin(enum screen_type screen);
88 char* default_radio_skin(enum screen_type screen);
90 struct wps_state wps_state = { .id3 = NULL };
91 static struct gui_skin_helper {
92 int (*preproccess)(enum screen_type screen, struct wps_data *data);
93 int (*postproccess)(enum screen_type screen, struct wps_data *data);
94 char* (*default_skin)(enum screen_type screen);
95 } skin_helpers[SKINNABLE_SCREENS_COUNT] = {
96 [CUSTOM_STATUSBAR] = { sb_preproccess, sb_postproccess, sb_create_from_settings },
97 [WPS] = { NULL, NULL, wps_default_skin },
98 #if CONFIG_TUNER
99 [FM_SCREEN] = { NULL, NULL, default_radio_skin }
100 #endif
103 static struct gui_skin {
104 struct gui_wps gui_wps;
105 struct wps_data data;
106 char *buffer_start;
107 size_t buffer_usage;
109 bool needs_full_update;
110 } skins[SKINNABLE_SCREENS_COUNT][NB_SCREENS];
113 void gui_sync_skin_init(void)
115 int i, j;
116 for(j=0; j<SKINNABLE_SCREENS_COUNT; j++)
118 FOR_NB_SCREENS(i)
120 skins[j][i].buffer_start = NULL;
121 skins[j][i].needs_full_update = true;
122 #ifdef HAVE_ALBUMART
123 skins[j][i].data.albumart = NULL;
124 skins[j][i].data.playback_aa_slot = -1;
125 #endif
126 skins[j][i].gui_wps.data = &skins[j][i].data;
127 skins[j][i].data.wps_loaded = false;
128 skins[j][i].gui_wps.display = &screens[i];
133 void skin_load(enum skinnable_screens skin, enum screen_type screen,
134 const char *buf, bool isfile)
136 bool loaded = false;
138 if (skin_helpers[skin].preproccess)
139 skin_helpers[skin].preproccess(screen, &skins[skin][screen].data);
141 if (buf && *buf)
142 loaded = skin_data_load(screen, &skins[skin][screen].data, buf, isfile);
144 if (!loaded && skin_helpers[skin].default_skin)
145 loaded = skin_data_load(screen, &skins[skin][screen].data,
146 skin_helpers[skin].default_skin(screen), false);
148 skins[skin][screen].needs_full_update = true;
149 if (skin_helpers[skin].postproccess)
150 skin_helpers[skin].postproccess(screen, &skins[skin][screen].data);
153 static bool loading_a_sbs = false;
154 struct gui_wps *skin_get_gwps(enum skinnable_screens skin, enum screen_type screen)
156 if (!loading_a_sbs && skins[skin][screen].data.wps_loaded == false)
158 char buf[MAX_PATH*2], path[MAX_PATH];
159 char *setting = NULL, *ext = NULL;
160 switch (skin)
162 case CUSTOM_STATUSBAR:
163 #ifdef HAVE_LCD_BITMAP
164 if (skins_initialising)
166 /* still loading, buffers not initialised yet,
167 * viewport manager calls into the sbs code, not really
168 * caring if the sbs has loaded or not, so just return
169 * the gwps, this is safe. */
170 return &skins[skin][screen].gui_wps;
172 /* during the sbs load it will call skin_get_gwps() a few times
173 * which will eventually stkov the viewportmanager, so make
174 * sure we don't let that happen */
175 loading_a_sbs = true;
176 #if defined(HAVE_REMOTE_LCD) && NB_SCREENS > 1
177 if (screen == SCREEN_REMOTE)
179 setting = global_settings.rsbs_file;
180 ext = "rsbs";
182 else
183 #endif
185 setting = global_settings.sbs_file;
186 ext = "sbs";
188 #else
189 return &skins[skin][screen].gui_wps;
190 #endif /* HAVE_LCD_BITMAP */
191 break;
192 case WPS:
193 #if defined(HAVE_REMOTE_LCD) && NB_SCREENS > 1
194 if (screen == SCREEN_REMOTE)
196 setting = global_settings.rwps_file;
197 ext = "rwps";
199 else
200 #endif
202 setting = global_settings.wps_file;
203 ext = "wps";
205 break;
206 #if CONFIG_TUNER
207 case FM_SCREEN:
208 #if defined(HAVE_REMOTE_LCD) && NB_SCREENS > 1
209 if (screen == SCREEN_REMOTE)
211 setting = global_settings.rfms_file;
212 ext = "rfms";
214 else
215 #endif
217 setting = global_settings.fms_file;
218 ext = "fms";
220 break;
221 #endif
222 default:
223 return NULL;
226 buf[0] = '\0'; /* force it to reload the default */
227 if (strcmp(setting, "rockbox_failsafe"))
229 snprintf(buf, sizeof buf, "%s/%s.%s",
230 get_user_file_path(WPS_DIR, false, path, sizeof(path)),
231 setting, ext);
233 cpu_boost(true);
234 skin_load(skin, screen, buf, true);
235 cpu_boost(false);
236 loading_a_sbs = false;
239 return &skins[skin][screen].gui_wps;
242 struct wps_state *skin_get_global_state(void)
244 return &wps_state;
247 /* This is called to find out if we the screen needs a full update.
248 * if true you MUST do a full update as the next call will return false */
249 bool skin_do_full_update(enum skinnable_screens skin,
250 enum screen_type screen)
252 bool ret = skins[skin][screen].needs_full_update;
253 skins[skin][screen].needs_full_update = false;
254 return ret;
257 /* tell a skin to do a full update next time */
258 void skin_request_full_update(enum skinnable_screens skin)
260 int i;
261 FOR_NB_SCREENS(i)
262 skins[skin][i].needs_full_update = true;