From 0ca4b38b1b04e6b7d6f5ad1f3654f8f361d8933f Mon Sep 17 00:00:00 2001 From: Jonathan Gordon Date: Mon, 21 Nov 2011 10:02:23 +0000 Subject: skinengine: Rework skin loading so skins can be un/loaded individually. This also means that loading a .cfg which doesnt change themes shouldnt have them reloaded git-svn-id: svn://svn.rockbox.org/rockbox/trunk@31037 a1c6a512-1295-4272-9138-f99709370657 --- apps/gui/skin_engine/skin_backdrops.c | 56 +++++--- apps/gui/skin_engine/skin_engine.c | 245 ++++++++++++++++++---------------- apps/gui/skin_engine/skin_parser.c | 4 +- 3 files changed, 169 insertions(+), 136 deletions(-) (limited to 'apps/gui/skin_engine') diff --git a/apps/gui/skin_engine/skin_backdrops.c b/apps/gui/skin_engine/skin_backdrops.c index 0b67125bbf..0433d0258d 100644 --- a/apps/gui/skin_engine/skin_backdrops.c +++ b/apps/gui/skin_engine/skin_backdrops.c @@ -37,6 +37,7 @@ static struct skin_backdrop { enum screen_type screen; bool loaded; int buflib_handle; + int ref_count; } backdrops[NB_BDROPS]; #define NB_BDROPS SKINNABLE_SCREENS_COUNT*NB_SCREENS @@ -63,21 +64,21 @@ static struct buflib_callbacks buflib_ops = {buflib_move_callback, NULL}; static bool first_go = true; void skin_backdrop_init(void) { - for (int i=0; i= 0) + if (free >= 0) { - strlcpy(backdrops[free].name, filename, - sizeof (backdrops[free].name)); + strlcpy(backdrops[free].name, filename, MAX_PATH); backdrops[free].buffer = NULL; backdrops[free].screen = screen; + backdrops[free].ref_count = 1; return free; } + else if (i < NB_BDROPS) + return i; return -1; } @@ -188,10 +193,17 @@ void skin_backdrop_show(int backdrop_id) void skin_backdrop_unload(int backdrop_id) { - if (backdrops[backdrop_id].buflib_handle > 0) - core_free(backdrops[backdrop_id].buflib_handle); - backdrops[backdrop_id].buffer = NULL; - backdrops[backdrop_id].buflib_handle = -1; + backdrops[backdrop_id].ref_count--; + if (backdrops[backdrop_id].ref_count <= 0) + { + if (backdrops[backdrop_id].buflib_handle > 0) + core_free(backdrops[backdrop_id].buflib_handle); + backdrops[backdrop_id].buffer = NULL; + backdrops[backdrop_id].buflib_handle = -1; + backdrops[backdrop_id].loaded = false; + backdrops[backdrop_id].name[0] = '\0'; + backdrops[backdrop_id].ref_count = 0; + } } void skin_backdrop_load_setting(void) 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 @@ #include "skin_buffer.h" #include "statusbar-skinned.h" -static bool skins_initialising = true; - -/* App uses the host malloc to manage the buffer */ -void theme_init_buffer(void) -{ - skins_initialising = false; -} +#define FAILSAFENAME "rockbox_failsafe" void skin_data_free_buflib_allocs(struct wps_data *wps_data); char* wps_default_skin(enum screen_type screen); char* default_radio_skin(enum screen_type screen); +static char* get_skin_filename(char *buf, size_t buf_size, + enum skinnable_screens skin, enum screen_type screen); + struct wps_state wps_state = { .id3 = NULL }; static struct gui_skin_helper { int (*preproccess)(enum screen_type screen, struct wps_data *data); @@ -62,82 +59,110 @@ static struct gui_skin_helper { [FM_SCREEN] = { NULL, NULL, default_radio_skin } #endif }; - + static struct gui_skin { + char filename[MAX_PATH]; struct gui_wps gui_wps; struct wps_data data; char *buffer_start; size_t buffer_usage; - + bool failsafe_loaded; + bool needs_full_update; } skins[SKINNABLE_SCREENS_COUNT][NB_SCREENS]; -void gui_sync_skin_init(void) +void gui_skin_reset(struct gui_skin *skin) { - int j; - for(j=0; jfilename[0] = '\0'; + skin->buffer_start = NULL; + skin->failsafe_loaded = false; + skin->needs_full_update = true; + skin->gui_wps.data = &skin->data; + memset(skin->gui_wps.data, 0, sizeof(struct wps_data)); + skin->data.wps_loaded = false; + skin->data.buflib_handle = -1; + skin->data.tree = -1; #ifdef HAVE_TOUCHSCREEN - skins[j][i].data.touchregions = -1; + skin->data.touchregions = -1; #endif #ifdef HAVE_SKIN_VARIABLES - skins[j][i].data.skinvars = -1; + skin->data.skinvars = -1; #endif #ifdef HAVE_LCD_BITMAP - skins[j][i].data.font_ids = -1; - skins[j][i].data.images = -1; + skin->data.font_ids = -1; + skin->data.images = -1; #endif #ifdef HAVE_ALBUMART - skins[j][i].data.albumart = -1; - skins[j][i].data.playback_aa_slot = -1; + skin->data.albumart = -1; + skin->data.playback_aa_slot = -1; +#endif +#ifdef HAVE_BACKDROP_IMAGE + skin->gui_wps.data->backdrop_id = -1; #endif - } - } } -void skin_unload_all(void) +void gui_sync_skin_init(void) { int j; - for(j=0; j= 0) + skin_backdrop_unload(skins[i][j].data.backdrop_id); #endif + } + gui_skin_reset(&skins[i][j]); + skins[i][j].gui_wps.display = &screens[j]; + skin_get_gwps(i, j); + } + } + } + first_run = false; viewportmanager_theme_changed(THEME_STATUSBAR); #ifdef HAVE_BACKDROP_IMAGE + skin_backdrops_preload(); /* should maybe check the retval here... */ FOR_NB_SCREENS(i) skin_backdrop_show(sb_get_backdrop(i)); #endif @@ -147,104 +172,100 @@ void skin_load(enum skinnable_screens skin, enum screen_type screen, const char *buf, bool isfile) { bool loaded = false; - + if (skin_helpers[skin].preproccess) skin_helpers[skin].preproccess(screen, &skins[skin][screen].data); - + if (buf && *buf) loaded = skin_data_load(screen, &skins[skin][screen].data, buf, isfile); + if (loaded) + strcpy(skins[skin][screen].filename, buf); if (!loaded && skin_helpers[skin].default_skin) + { loaded = skin_data_load(screen, &skins[skin][screen].data, skin_helpers[skin].default_skin(screen), false); - + skins[skin][screen].failsafe_loaded = loaded; + } + skins[skin][screen].needs_full_update = true; if (skin_helpers[skin].postproccess) skin_helpers[skin].postproccess(screen, &skins[skin][screen].data); } -static bool loading_a_sbs = false; -struct gui_wps *skin_get_gwps(enum skinnable_screens skin, enum screen_type screen) +static char* get_skin_filename(char *buf, size_t buf_size, + enum skinnable_screens skin, enum screen_type screen) { - if (!loading_a_sbs && skins[skin][screen].data.wps_loaded == false) + (void)screen; + char *setting = NULL, *ext = NULL; + switch (skin) { - char buf[MAX_PATH*2]; - char *setting = NULL, *ext = NULL; - switch (skin) - { - case CUSTOM_STATUSBAR: -#ifdef HAVE_LCD_BITMAP - if (skins_initialising) - { - /* still loading, buffers not initialised yet, - * viewport manager calls into the sbs code, not really - * caring if the sbs has loaded or not, so just return - * the gwps, this is safe. */ - return &skins[skin][screen].gui_wps; - } - /* during the sbs load it will call skin_get_gwps() a few times - * which will eventually stkov the viewportmanager, so make - * sure we don't let that happen */ - loading_a_sbs = true; + case CUSTOM_STATUSBAR: #if defined(HAVE_REMOTE_LCD) && NB_SCREENS > 1 - if (screen == SCREEN_REMOTE) - { - setting = global_settings.rsbs_file; - ext = "rsbs"; - } - else + if (screen == SCREEN_REMOTE) + { + setting = global_settings.rsbs_file; + ext = "rsbs"; + } + else #endif - { - setting = global_settings.sbs_file; - ext = "sbs"; - } -#else - return &skins[skin][screen].gui_wps; -#endif /* HAVE_LCD_BITMAP */ - break; - case WPS: + { + setting = global_settings.sbs_file; + ext = "sbs"; + } + break; + case WPS: #if defined(HAVE_REMOTE_LCD) && NB_SCREENS > 1 - if (screen == SCREEN_REMOTE) - { - setting = global_settings.rwps_file; - ext = "rwps"; - } - else + if (screen == SCREEN_REMOTE) + { + setting = global_settings.rwps_file; + ext = "rwps"; + } + else #endif - { - setting = global_settings.wps_file; - ext = "wps"; - } - break; + { + setting = global_settings.wps_file; + ext = "wps"; + } + break; #if CONFIG_TUNER - case FM_SCREEN: + case FM_SCREEN: #if defined(HAVE_REMOTE_LCD) && NB_SCREENS > 1 - if (screen == SCREEN_REMOTE) - { - setting = global_settings.rfms_file; - ext = "rfms"; - } - else + if (screen == SCREEN_REMOTE) + { + setting = global_settings.rfms_file; + ext = "rfms"; + } + else #endif - { - setting = global_settings.fms_file; - ext = "fms"; - } - break; + { + setting = global_settings.fms_file; + ext = "fms"; + } + break; #endif - default: - return NULL; - } - - buf[0] = '\0'; /* force it to reload the default */ - if (strcmp(setting, "rockbox_failsafe")) - { - snprintf(buf, sizeof buf, WPS_DIR "/%s.%s", setting, ext); - } + default: + return NULL; + } + + buf[0] = '\0'; /* force it to reload the default */ + if (strcmp(setting, FAILSAFENAME) && strcmp(setting, "-")) + { + snprintf(buf, buf_size, WPS_DIR "/%s.%s", setting, ext); + } + return buf; +} + +struct gui_wps *skin_get_gwps(enum skinnable_screens skin, enum screen_type screen) +{ + if (skins[skin][screen].data.wps_loaded == false) + { + char filename[MAX_PATH]; + char *buf = get_skin_filename(filename, MAX_PATH, skin, screen); cpu_boost(true); + skins[skin][screen].filename[0] = '\0'; skin_load(skin, screen, buf, true); cpu_boost(false); - loading_a_sbs = false; } return &skins[skin][screen].gui_wps; } diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c index ef365720b4..0118977be5 100644 --- a/apps/gui/skin_engine/skin_parser.c +++ b/apps/gui/skin_engine/skin_parser.c @@ -1687,7 +1687,7 @@ static bool load_skin_bitmaps(struct wps_data *wps_data, char *bmpdir) list = SKINOFFSETTOPTR(skin_buffer, list->next); } -#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)) +#ifdef HAVE_BACKDROP_IMAGE wps_data->backdrop_id = skin_backdrop_assign(backdrop_filename, bmpdir, curr_screen); #endif /* has backdrop support */ return retval; @@ -1986,7 +1986,7 @@ static int skin_element_callback(struct skin_element* element, void* data) case SKIN_TOKEN_FILE_DIRECTORY: token->value.i = get_param(element, 0)->data.number; break; -#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)) +#ifdef HAVE_BACKDROP_IMAGE case SKIN_TOKEN_VIEWPORT_FGCOLOUR: case SKIN_TOKEN_VIEWPORT_BGCOLOUR: function = parse_viewportcolour; -- cgit v1.2.3