diff options
Diffstat (limited to 'apps/gui/skin_engine/skin_engine.c')
-rw-r--r-- | apps/gui/skin_engine/skin_engine.c | 245 |
1 files changed, 133 insertions, 112 deletions
diff --git a/apps/gui/skin_engine/skin_engine.c b/apps/gui/skin_engine/skin_engine.c index c6791cac09..ce6c985e16 100644 --- a/apps/gui/skin_engine/skin_engine.c +++ b/apps/gui/skin_engine/skin_engine.c | |||
@@ -38,18 +38,15 @@ | |||
38 | #include "skin_buffer.h" | 38 | #include "skin_buffer.h" |
39 | #include "statusbar-skinned.h" | 39 | #include "statusbar-skinned.h" |
40 | 40 | ||
41 | static bool skins_initialising = true; | 41 | #define FAILSAFENAME "rockbox_failsafe" |
42 | |||
43 | /* App uses the host malloc to manage the buffer */ | ||
44 | void theme_init_buffer(void) | ||
45 | { | ||
46 | skins_initialising = false; | ||
47 | } | ||
48 | 42 | ||
49 | void skin_data_free_buflib_allocs(struct wps_data *wps_data); | 43 | void skin_data_free_buflib_allocs(struct wps_data *wps_data); |
50 | char* wps_default_skin(enum screen_type screen); | 44 | char* wps_default_skin(enum screen_type screen); |
51 | char* default_radio_skin(enum screen_type screen); | 45 | char* default_radio_skin(enum screen_type screen); |
52 | 46 | ||
47 | static char* get_skin_filename(char *buf, size_t buf_size, | ||
48 | enum skinnable_screens skin, enum screen_type screen); | ||
49 | |||
53 | struct wps_state wps_state = { .id3 = NULL }; | 50 | struct wps_state wps_state = { .id3 = NULL }; |
54 | static struct gui_skin_helper { | 51 | static struct gui_skin_helper { |
55 | int (*preproccess)(enum screen_type screen, struct wps_data *data); | 52 | int (*preproccess)(enum screen_type screen, struct wps_data *data); |
@@ -62,82 +59,110 @@ static struct gui_skin_helper { | |||
62 | [FM_SCREEN] = { NULL, NULL, default_radio_skin } | 59 | [FM_SCREEN] = { NULL, NULL, default_radio_skin } |
63 | #endif | 60 | #endif |
64 | }; | 61 | }; |
65 | 62 | ||
66 | static struct gui_skin { | 63 | static struct gui_skin { |
64 | char filename[MAX_PATH]; | ||
67 | struct gui_wps gui_wps; | 65 | struct gui_wps gui_wps; |
68 | struct wps_data data; | 66 | struct wps_data data; |
69 | char *buffer_start; | 67 | char *buffer_start; |
70 | size_t buffer_usage; | 68 | size_t buffer_usage; |
71 | 69 | bool failsafe_loaded; | |
70 | |||
72 | bool needs_full_update; | 71 | bool needs_full_update; |
73 | } skins[SKINNABLE_SCREENS_COUNT][NB_SCREENS]; | 72 | } skins[SKINNABLE_SCREENS_COUNT][NB_SCREENS]; |
74 | 73 | ||
75 | 74 | ||
76 | void gui_sync_skin_init(void) | 75 | void gui_skin_reset(struct gui_skin *skin) |
77 | { | 76 | { |
78 | int j; | 77 | skin->filename[0] = '\0'; |
79 | for(j=0; j<SKINNABLE_SCREENS_COUNT; j++) | 78 | skin->buffer_start = NULL; |
80 | { | 79 | skin->failsafe_loaded = false; |
81 | FOR_NB_SCREENS(i) | 80 | skin->needs_full_update = true; |
82 | { | 81 | skin->gui_wps.data = &skin->data; |
83 | skins[j][i].buffer_start = NULL; | 82 | memset(skin->gui_wps.data, 0, sizeof(struct wps_data)); |
84 | skins[j][i].needs_full_update = true; | 83 | skin->data.wps_loaded = false; |
85 | skins[j][i].gui_wps.data = &skins[j][i].data; | 84 | skin->data.buflib_handle = -1; |
86 | skins[j][i].gui_wps.display = &screens[i]; | 85 | skin->data.tree = -1; |
87 | memset(skins[j][i].gui_wps.data, 0, sizeof(struct wps_data)); | ||
88 | skins[j][i].data.wps_loaded = false; | ||
89 | skins[j][i].data.buflib_handle = -1; | ||
90 | skins[j][i].data.tree = -1; | ||
91 | #ifdef HAVE_TOUCHSCREEN | 86 | #ifdef HAVE_TOUCHSCREEN |
92 | skins[j][i].data.touchregions = -1; | 87 | skin->data.touchregions = -1; |
93 | #endif | 88 | #endif |
94 | #ifdef HAVE_SKIN_VARIABLES | 89 | #ifdef HAVE_SKIN_VARIABLES |
95 | skins[j][i].data.skinvars = -1; | 90 | skin->data.skinvars = -1; |
96 | #endif | 91 | #endif |
97 | #ifdef HAVE_LCD_BITMAP | 92 | #ifdef HAVE_LCD_BITMAP |
98 | skins[j][i].data.font_ids = -1; | 93 | skin->data.font_ids = -1; |
99 | skins[j][i].data.images = -1; | 94 | skin->data.images = -1; |
100 | #endif | 95 | #endif |
101 | #ifdef HAVE_ALBUMART | 96 | #ifdef HAVE_ALBUMART |
102 | skins[j][i].data.albumart = -1; | 97 | skin->data.albumart = -1; |
103 | skins[j][i].data.playback_aa_slot = -1; | 98 | skin->data.playback_aa_slot = -1; |
99 | #endif | ||
100 | #ifdef HAVE_BACKDROP_IMAGE | ||
101 | skin->gui_wps.data->backdrop_id = -1; | ||
104 | #endif | 102 | #endif |
105 | } | ||
106 | } | ||
107 | } | 103 | } |
108 | 104 | ||
109 | void skin_unload_all(void) | 105 | void gui_sync_skin_init(void) |
110 | { | 106 | { |
111 | int j; | 107 | int j; |
112 | |||
113 | for(j=0; j<SKINNABLE_SCREENS_COUNT; j++) | 108 | for(j=0; j<SKINNABLE_SCREENS_COUNT; j++) |
114 | { | 109 | { |
115 | FOR_NB_SCREENS(i) | 110 | FOR_NB_SCREENS(i) |
111 | { | ||
116 | skin_data_free_buflib_allocs(&skins[j][i].data); | 112 | skin_data_free_buflib_allocs(&skins[j][i].data); |
113 | gui_skin_reset(&skins[j][i]); | ||
114 | skins[j][i].gui_wps.display = &screens[i]; | ||
115 | } | ||
117 | } | 116 | } |
117 | } | ||
118 | 118 | ||
119 | #ifdef HAVE_LCD_BITMAP | 119 | void skin_unload_all(void) |
120 | skin_backdrop_init(); | 120 | { |
121 | #endif | ||
122 | gui_sync_skin_init(); | 121 | gui_sync_skin_init(); |
123 | } | 122 | } |
124 | 123 | ||
125 | void settings_apply_skins(void) | 124 | void settings_apply_skins(void) |
126 | { | 125 | { |
127 | int i; | 126 | int i; |
127 | char filename[MAX_PATH]; | ||
128 | static bool first_run = true; | ||
128 | 129 | ||
129 | skin_unload_all(); | 130 | #ifdef HAVE_LCD_BITMAP |
131 | skin_backdrop_init(); | ||
132 | #endif | ||
130 | /* Make sure each skin is loaded */ | 133 | /* Make sure each skin is loaded */ |
131 | for (i=0; i<SKINNABLE_SCREENS_COUNT; i++) | 134 | for (i=0; i<SKINNABLE_SCREENS_COUNT; i++) |
132 | { | 135 | { |
133 | FOR_NB_SCREENS(j) | 136 | FOR_NB_SCREENS(j) |
134 | skin_get_gwps(i, j); | 137 | { |
135 | } | 138 | bool load = false; |
139 | get_skin_filename(filename, MAX_PATH, i,j); | ||
140 | |||
141 | if (filename[0] && (strcmp(filename, skins[i][j].filename) || skins[i][j].failsafe_loaded)) | ||
142 | load = true; | ||
143 | else if (first_run || (!filename[0] && !skins[i][j].failsafe_loaded)) | ||
144 | load = true; | ||
145 | |||
146 | if (load) | ||
147 | { | ||
148 | if (!first_run) | ||
149 | { | ||
150 | skin_data_free_buflib_allocs(&skins[i][j].data); | ||
136 | #ifdef HAVE_BACKDROP_IMAGE | 151 | #ifdef HAVE_BACKDROP_IMAGE |
137 | skin_backdrops_preload(); /* should maybe check the retval here... */ | 152 | if (skins[i][j].data.backdrop_id >= 0) |
153 | skin_backdrop_unload(skins[i][j].data.backdrop_id); | ||
138 | #endif | 154 | #endif |
155 | } | ||
156 | gui_skin_reset(&skins[i][j]); | ||
157 | skins[i][j].gui_wps.display = &screens[j]; | ||
158 | skin_get_gwps(i, j); | ||
159 | } | ||
160 | } | ||
161 | } | ||
162 | first_run = false; | ||
139 | viewportmanager_theme_changed(THEME_STATUSBAR); | 163 | viewportmanager_theme_changed(THEME_STATUSBAR); |
140 | #ifdef HAVE_BACKDROP_IMAGE | 164 | #ifdef HAVE_BACKDROP_IMAGE |
165 | skin_backdrops_preload(); /* should maybe check the retval here... */ | ||
141 | FOR_NB_SCREENS(i) | 166 | FOR_NB_SCREENS(i) |
142 | skin_backdrop_show(sb_get_backdrop(i)); | 167 | skin_backdrop_show(sb_get_backdrop(i)); |
143 | #endif | 168 | #endif |
@@ -147,104 +172,100 @@ void skin_load(enum skinnable_screens skin, enum screen_type screen, | |||
147 | const char *buf, bool isfile) | 172 | const char *buf, bool isfile) |
148 | { | 173 | { |
149 | bool loaded = false; | 174 | bool loaded = false; |
150 | 175 | ||
151 | if (skin_helpers[skin].preproccess) | 176 | if (skin_helpers[skin].preproccess) |
152 | skin_helpers[skin].preproccess(screen, &skins[skin][screen].data); | 177 | skin_helpers[skin].preproccess(screen, &skins[skin][screen].data); |
153 | 178 | ||
154 | if (buf && *buf) | 179 | if (buf && *buf) |
155 | loaded = skin_data_load(screen, &skins[skin][screen].data, buf, isfile); | 180 | loaded = skin_data_load(screen, &skins[skin][screen].data, buf, isfile); |
181 | if (loaded) | ||
182 | strcpy(skins[skin][screen].filename, buf); | ||
156 | 183 | ||
157 | if (!loaded && skin_helpers[skin].default_skin) | 184 | if (!loaded && skin_helpers[skin].default_skin) |
185 | { | ||
158 | loaded = skin_data_load(screen, &skins[skin][screen].data, | 186 | loaded = skin_data_load(screen, &skins[skin][screen].data, |
159 | skin_helpers[skin].default_skin(screen), false); | 187 | skin_helpers[skin].default_skin(screen), false); |
160 | 188 | skins[skin][screen].failsafe_loaded = loaded; | |
189 | } | ||
190 | |||
161 | skins[skin][screen].needs_full_update = true; | 191 | skins[skin][screen].needs_full_update = true; |
162 | if (skin_helpers[skin].postproccess) | 192 | if (skin_helpers[skin].postproccess) |
163 | skin_helpers[skin].postproccess(screen, &skins[skin][screen].data); | 193 | skin_helpers[skin].postproccess(screen, &skins[skin][screen].data); |
164 | } | 194 | } |
165 | 195 | ||
166 | static bool loading_a_sbs = false; | 196 | static char* get_skin_filename(char *buf, size_t buf_size, |
167 | struct gui_wps *skin_get_gwps(enum skinnable_screens skin, enum screen_type screen) | 197 | enum skinnable_screens skin, enum screen_type screen) |
168 | { | 198 | { |
169 | if (!loading_a_sbs && skins[skin][screen].data.wps_loaded == false) | 199 | (void)screen; |
200 | char *setting = NULL, *ext = NULL; | ||
201 | switch (skin) | ||
170 | { | 202 | { |
171 | char buf[MAX_PATH*2]; | 203 | case CUSTOM_STATUSBAR: |
172 | char *setting = NULL, *ext = NULL; | ||
173 | switch (skin) | ||
174 | { | ||
175 | case CUSTOM_STATUSBAR: | ||
176 | #ifdef HAVE_LCD_BITMAP | ||
177 | if (skins_initialising) | ||
178 | { | ||
179 | /* still loading, buffers not initialised yet, | ||
180 | * viewport manager calls into the sbs code, not really | ||
181 | * caring if the sbs has loaded or not, so just return | ||
182 | * the gwps, this is safe. */ | ||
183 | return &skins[skin][screen].gui_wps; | ||
184 | } | ||
185 | /* during the sbs load it will call skin_get_gwps() a few times | ||
186 | * which will eventually stkov the viewportmanager, so make | ||
187 | * sure we don't let that happen */ | ||
188 | loading_a_sbs = true; | ||
189 | #if defined(HAVE_REMOTE_LCD) && NB_SCREENS > 1 | 204 | #if defined(HAVE_REMOTE_LCD) && NB_SCREENS > 1 |
190 | if (screen == SCREEN_REMOTE) | 205 | if (screen == SCREEN_REMOTE) |
191 | { | 206 | { |
192 | setting = global_settings.rsbs_file; | 207 | setting = global_settings.rsbs_file; |
193 | ext = "rsbs"; | 208 | ext = "rsbs"; |
194 | } | 209 | } |
195 | else | 210 | else |
196 | #endif | 211 | #endif |
197 | { | 212 | { |
198 | setting = global_settings.sbs_file; | 213 | setting = global_settings.sbs_file; |
199 | ext = "sbs"; | 214 | ext = "sbs"; |
200 | } | 215 | } |
201 | #else | 216 | break; |
202 | return &skins[skin][screen].gui_wps; | 217 | case WPS: |
203 | #endif /* HAVE_LCD_BITMAP */ | ||
204 | break; | ||
205 | case WPS: | ||
206 | #if defined(HAVE_REMOTE_LCD) && NB_SCREENS > 1 | 218 | #if defined(HAVE_REMOTE_LCD) && NB_SCREENS > 1 |
207 | if (screen == SCREEN_REMOTE) | 219 | if (screen == SCREEN_REMOTE) |
208 | { | 220 | { |
209 | setting = global_settings.rwps_file; | 221 | setting = global_settings.rwps_file; |
210 | ext = "rwps"; | 222 | ext = "rwps"; |
211 | } | 223 | } |
212 | else | 224 | else |
213 | #endif | 225 | #endif |
214 | { | 226 | { |
215 | setting = global_settings.wps_file; | 227 | setting = global_settings.wps_file; |
216 | ext = "wps"; | 228 | ext = "wps"; |
217 | } | 229 | } |
218 | break; | 230 | break; |
219 | #if CONFIG_TUNER | 231 | #if CONFIG_TUNER |
220 | case FM_SCREEN: | 232 | case FM_SCREEN: |
221 | #if defined(HAVE_REMOTE_LCD) && NB_SCREENS > 1 | 233 | #if defined(HAVE_REMOTE_LCD) && NB_SCREENS > 1 |
222 | if (screen == SCREEN_REMOTE) | 234 | if (screen == SCREEN_REMOTE) |
223 | { | 235 | { |
224 | setting = global_settings.rfms_file; | 236 | setting = global_settings.rfms_file; |
225 | ext = "rfms"; | 237 | ext = "rfms"; |
226 | } | 238 | } |
227 | else | 239 | else |
228 | #endif | 240 | #endif |
229 | { | 241 | { |
230 | setting = global_settings.fms_file; | 242 | setting = global_settings.fms_file; |
231 | ext = "fms"; | 243 | ext = "fms"; |
232 | } | 244 | } |
233 | break; | 245 | break; |
234 | #endif | 246 | #endif |
235 | default: | 247 | default: |
236 | return NULL; | 248 | return NULL; |
237 | } | 249 | } |
238 | 250 | ||
239 | buf[0] = '\0'; /* force it to reload the default */ | 251 | buf[0] = '\0'; /* force it to reload the default */ |
240 | if (strcmp(setting, "rockbox_failsafe")) | 252 | if (strcmp(setting, FAILSAFENAME) && strcmp(setting, "-")) |
241 | { | 253 | { |
242 | snprintf(buf, sizeof buf, WPS_DIR "/%s.%s", setting, ext); | 254 | snprintf(buf, buf_size, WPS_DIR "/%s.%s", setting, ext); |
243 | } | 255 | } |
256 | return buf; | ||
257 | } | ||
258 | |||
259 | struct gui_wps *skin_get_gwps(enum skinnable_screens skin, enum screen_type screen) | ||
260 | { | ||
261 | if (skins[skin][screen].data.wps_loaded == false) | ||
262 | { | ||
263 | char filename[MAX_PATH]; | ||
264 | char *buf = get_skin_filename(filename, MAX_PATH, skin, screen); | ||
244 | cpu_boost(true); | 265 | cpu_boost(true); |
266 | skins[skin][screen].filename[0] = '\0'; | ||
245 | skin_load(skin, screen, buf, true); | 267 | skin_load(skin, screen, buf, true); |
246 | cpu_boost(false); | 268 | cpu_boost(false); |
247 | loading_a_sbs = false; | ||
248 | } | 269 | } |
249 | return &skins[skin][screen].gui_wps; | 270 | return &skins[skin][screen].gui_wps; |
250 | } | 271 | } |