1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
28 #include "core_alloc.h"
39 #include "skin_engine.h"
40 #include "skin_buffer.h"
41 #include "statusbar-skinned.h"
43 static bool skins_initialising
= true;
45 /* App uses the host malloc to manage the buffer */
47 #define skin_buffer NULL
48 #define skin_buffer_size 0
49 void theme_init_buffer(void)
51 skins_initialising
= false;
54 static size_t skin_buffer_size
;
55 static char *skin_buffer
= NULL
;
56 static int buflib_move_callback(int handle
, void* current
, void* new)
61 return BUFLIB_CB_CANNOT_MOVE
;
63 static struct buflib_callbacks buflib_ops
= {buflib_move_callback
, NULL
};
65 void theme_init_buffer(void)
68 size_t size
= SKIN_BUFFER_SIZE
;
69 fd
= open_utf8(ROCKBOX_DIR
"/skin_buffer_size.txt", O_RDONLY
);
73 read(fd
, buf
, sizeof(buf
));
74 if (buf
[0] >= '0' && buf
[0] <= '9')
75 size
= atoi(buf
)*1024;
78 skin_buffer
= core_get_data(core_alloc_ex("skin buffer", size
, &buflib_ops
));
79 skin_buffer_size
= size
;
80 skins_initialising
= false;
84 void skin_data_free_buflib_allocs(struct wps_data
*wps_data
);
85 char* wps_default_skin(enum screen_type screen
);
86 char* default_radio_skin(enum screen_type screen
);
88 struct wps_state wps_state
= { .id3
= NULL
};
89 static struct gui_skin_helper
{
90 int (*preproccess
)(enum screen_type screen
, struct wps_data
*data
);
91 int (*postproccess
)(enum screen_type screen
, struct wps_data
*data
);
92 char* (*default_skin
)(enum screen_type screen
);
93 } skin_helpers
[SKINNABLE_SCREENS_COUNT
] = {
94 [CUSTOM_STATUSBAR
] = { sb_preproccess
, sb_postproccess
, sb_create_from_settings
},
95 [WPS
] = { NULL
, NULL
, wps_default_skin
},
97 [FM_SCREEN
] = { NULL
, NULL
, default_radio_skin
}
101 static struct gui_skin
{
102 struct gui_wps gui_wps
;
103 struct wps_data data
;
107 bool needs_full_update
;
108 } skins
[SKINNABLE_SCREENS_COUNT
][NB_SCREENS
];
111 void gui_sync_skin_init(void)
114 for(j
=0; j
<SKINNABLE_SCREENS_COUNT
; j
++)
118 skins
[j
][i
].buffer_start
= NULL
;
119 skins
[j
][i
].needs_full_update
= true;
120 skins
[j
][i
].gui_wps
.data
= &skins
[j
][i
].data
;
121 skins
[j
][i
].gui_wps
.display
= &screens
[i
];
122 memset(skins
[j
][i
].gui_wps
.data
, 0, sizeof(struct wps_data
));
123 skins
[j
][i
].data
.wps_loaded
= false;
125 skins
[j
][i
].data
.albumart
= NULL
;
126 skins
[j
][i
].data
.playback_aa_slot
= -1;
132 void skin_unload_all(void)
136 for(j
=0; j
<SKINNABLE_SCREENS_COUNT
; j
++)
139 skin_data_free_buflib_allocs(&skins
[j
][i
].data
);
142 skin_buffer_init(skin_buffer
, skin_buffer_size
);
143 #ifdef HAVE_LCD_BITMAP
144 skin_backdrop_init();
146 gui_sync_skin_init();
149 void settings_apply_skins(void)
154 /* Make sure each skin is loaded */
155 for (i
=0; i
<SKINNABLE_SCREENS_COUNT
; i
++)
160 #if LCD_DEPTH > 1 || defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
161 skin_backdrops_preload(); /* should maybe check the retval here... */
163 viewportmanager_theme_changed(THEME_STATUSBAR
);
164 #if LCD_DEPTH > 1 || defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
166 skin_backdrop_show(sb_get_backdrop(i
));
170 void skin_load(enum skinnable_screens skin
, enum screen_type screen
,
171 const char *buf
, bool isfile
)
175 if (skin_helpers
[skin
].preproccess
)
176 skin_helpers
[skin
].preproccess(screen
, &skins
[skin
][screen
].data
);
179 loaded
= skin_data_load(screen
, &skins
[skin
][screen
].data
, buf
, isfile
);
181 if (!loaded
&& skin_helpers
[skin
].default_skin
)
182 loaded
= skin_data_load(screen
, &skins
[skin
][screen
].data
,
183 skin_helpers
[skin
].default_skin(screen
), false);
185 skins
[skin
][screen
].needs_full_update
= true;
186 if (skin_helpers
[skin
].postproccess
)
187 skin_helpers
[skin
].postproccess(screen
, &skins
[skin
][screen
].data
);
190 static bool loading_a_sbs
= false;
191 struct gui_wps
*skin_get_gwps(enum skinnable_screens skin
, enum screen_type screen
)
193 if (!loading_a_sbs
&& skins
[skin
][screen
].data
.wps_loaded
== false)
195 char buf
[MAX_PATH
*2];
196 char *setting
= NULL
, *ext
= NULL
;
199 case CUSTOM_STATUSBAR
:
200 #ifdef HAVE_LCD_BITMAP
201 if (skins_initialising
)
203 /* still loading, buffers not initialised yet,
204 * viewport manager calls into the sbs code, not really
205 * caring if the sbs has loaded or not, so just return
206 * the gwps, this is safe. */
207 return &skins
[skin
][screen
].gui_wps
;
209 /* during the sbs load it will call skin_get_gwps() a few times
210 * which will eventually stkov the viewportmanager, so make
211 * sure we don't let that happen */
212 loading_a_sbs
= true;
213 #if defined(HAVE_REMOTE_LCD) && NB_SCREENS > 1
214 if (screen
== SCREEN_REMOTE
)
216 setting
= global_settings
.rsbs_file
;
222 setting
= global_settings
.sbs_file
;
226 return &skins
[skin
][screen
].gui_wps
;
227 #endif /* HAVE_LCD_BITMAP */
230 #if defined(HAVE_REMOTE_LCD) && NB_SCREENS > 1
231 if (screen
== SCREEN_REMOTE
)
233 setting
= global_settings
.rwps_file
;
239 setting
= global_settings
.wps_file
;
245 #if defined(HAVE_REMOTE_LCD) && NB_SCREENS > 1
246 if (screen
== SCREEN_REMOTE
)
248 setting
= global_settings
.rfms_file
;
254 setting
= global_settings
.fms_file
;
263 buf
[0] = '\0'; /* force it to reload the default */
264 if (strcmp(setting
, "rockbox_failsafe"))
266 snprintf(buf
, sizeof buf
, WPS_DIR
"/%s.%s", setting
, ext
);
269 skin_load(skin
, screen
, buf
, true);
271 loading_a_sbs
= false;
274 return &skins
[skin
][screen
].gui_wps
;
277 struct wps_state
*skin_get_global_state(void)
282 /* This is called to find out if we the screen needs a full update.
283 * if true you MUST do a full update as the next call will return false */
284 bool skin_do_full_update(enum skinnable_screens skin
,
285 enum screen_type screen
)
287 bool ret
= skins
[skin
][screen
].needs_full_update
;
288 skins
[skin
][screen
].needs_full_update
= false;
292 /* tell a skin to do a full update next time */
293 void skin_request_full_update(enum skinnable_screens skin
)
297 skins
[skin
][i
].needs_full_update
= true;