From 0ca4b38b1b04e6b7d6f5ad1f3654f8f361d8933f Mon Sep 17 00:00:00 2001 From: Jonathan Gordon Date: Mon, 21 Nov 2011 10:02:23 +0000 Subject: [PATCH] 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 | 58 +++--- apps/gui/skin_engine/skin_engine.c | 269 ++++++++++++++------------ apps/gui/skin_engine/skin_parser.c | 4 +- apps/gui/statusbar-skinned.c | 5 + apps/main.c | 2 - apps/settings.h | 1 - apps/settings_list.c | 2 +- 7 files changed, 188 insertions(+), 153 deletions(-) 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,17 +59,49 @@ 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_skin_reset(struct gui_skin *skin) +{ + skin->filename[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 + skin->data.touchregions = -1; +#endif +#ifdef HAVE_SKIN_VARIABLES + skin->data.skinvars = -1; +#endif +#ifdef HAVE_LCD_BITMAP + skin->data.font_ids = -1; + skin->data.images = -1; +#endif +#ifdef HAVE_ALBUMART + skin->data.albumart = -1; + skin->data.playback_aa_slot = -1; +#endif +#ifdef HAVE_BACKDROP_IMAGE + skin->gui_wps.data->backdrop_id = -1; +#endif +} + void gui_sync_skin_init(void) { int j; @@ -80,64 +109,60 @@ void gui_sync_skin_init(void) { FOR_NB_SCREENS(i) { - skins[j][i].buffer_start = NULL; - skins[j][i].needs_full_update = true; - skins[j][i].gui_wps.data = &skins[j][i].data; + skin_data_free_buflib_allocs(&skins[j][i].data); + gui_skin_reset(&skins[j][i]); skins[j][i].gui_wps.display = &screens[i]; - memset(skins[j][i].gui_wps.data, 0, sizeof(struct wps_data)); - skins[j][i].data.wps_loaded = false; - skins[j][i].data.buflib_handle = -1; - skins[j][i].data.tree = -1; -#ifdef HAVE_TOUCHSCREEN - skins[j][i].data.touchregions = -1; -#endif -#ifdef HAVE_SKIN_VARIABLES - skins[j][i].data.skinvars = -1; -#endif -#ifdef HAVE_LCD_BITMAP - skins[j][i].data.font_ids = -1; - skins[j][i].data.images = -1; -#endif -#ifdef HAVE_ALBUMART - skins[j][i].data.albumart = -1; - skins[j][i].data.playback_aa_slot = -1; -#endif } } } void skin_unload_all(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; +static char* get_skin_filename(char *buf, size_t buf_size, + enum skinnable_screens skin, enum screen_type screen) +{ + (void)screen; + char *setting = NULL, *ext = NULL; + switch (skin) + { + case CUSTOM_STATUSBAR: +#if defined(HAVE_REMOTE_LCD) && NB_SCREENS > 1 + if (screen == SCREEN_REMOTE) + { + setting = global_settings.rsbs_file; + ext = "rsbs"; + } + else +#endif + { + 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 +#endif + { + setting = global_settings.wps_file; + ext = "wps"; + } + break; +#if CONFIG_TUNER + case FM_SCREEN: +#if defined(HAVE_REMOTE_LCD) && NB_SCREENS > 1 + if (screen == SCREEN_REMOTE) + { + setting = global_settings.rfms_file; + ext = "rfms"; + } + else +#endif + { + setting = global_settings.fms_file; + ext = "fms"; + } + break; +#endif + 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 (!loading_a_sbs && skins[skin][screen].data.wps_loaded == false) + if (skins[skin][screen].data.wps_loaded == false) { - 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; -#if defined(HAVE_REMOTE_LCD) && NB_SCREENS > 1 - 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: -#if defined(HAVE_REMOTE_LCD) && NB_SCREENS > 1 - if (screen == SCREEN_REMOTE) - { - setting = global_settings.rwps_file; - ext = "rwps"; - } - else -#endif - { - setting = global_settings.wps_file; - ext = "wps"; - } - break; -#if CONFIG_TUNER - case FM_SCREEN: -#if defined(HAVE_REMOTE_LCD) && NB_SCREENS > 1 - if (screen == SCREEN_REMOTE) - { - setting = global_settings.rfms_file; - ext = "rfms"; - } - else -#endif - { - 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); - } + 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; diff --git a/apps/gui/statusbar-skinned.c b/apps/gui/statusbar-skinned.c index 960cf67d4d..fc9735da21 100644 --- a/apps/gui/statusbar-skinned.c +++ b/apps/gui/statusbar-skinned.c @@ -50,6 +50,7 @@ static int update_delay = DEFAULT_UPDATE_DELAY; static bool sbs_has_title[NB_SCREENS]; static char* sbs_title[NB_SCREENS]; static enum themable_icons sbs_icon[NB_SCREENS]; +static bool sbs_loaded[NB_SCREENS] = { false }; bool sb_set_title_text(char* title, enum themable_icons icon, enum screen_type screen) { @@ -76,6 +77,7 @@ enum themable_icons sb_get_icon(enum screen_type screen) int sb_preproccess(enum screen_type screen, struct wps_data *data) { (void)data; + sbs_loaded[screen] = false; sbs_has_title[screen] = false; viewportmanager_theme_enable(screen, false, NULL); return 1; @@ -101,6 +103,7 @@ int sb_postproccess(enum screen_type screen, struct wps_data *data) vp->hidden_flags = VP_NEVER_VISIBLE; } sb_set_info_vp(screen, VP_DEFAULT_LABEL); + sbs_loaded[screen] = true; } viewportmanager_theme_undo(screen, false); return 1; @@ -115,6 +118,8 @@ void sb_set_info_vp(enum screen_type screen, OFFSETTYPE(char*) label) struct viewport *sb_skin_get_info_vp(enum screen_type screen) { + if (sbs_loaded[screen] == false) + return NULL; struct wps_data *data = skin_get_gwps(CUSTOM_STATUSBAR, screen)->data; struct skin_viewport *vp = NULL; char *label; diff --git a/apps/main.c b/apps/main.c index 50da787b17..5715057ee2 100644 --- a/apps/main.c +++ b/apps/main.c @@ -393,7 +393,6 @@ static void init(void) tree_mem_init(); filetype_init(); playlist_init(); - theme_init_buffer(); shortcuts_init(); #if CONFIG_CODEC != SWCODEC @@ -678,7 +677,6 @@ static void init(void) tree_mem_init(); filetype_init(); scrobbler_init(); - theme_init_buffer(); shortcuts_init(); #if CONFIG_CODEC != SWCODEC diff --git a/apps/settings.h b/apps/settings.h index 34d65416dd..2524dcc909 100644 --- a/apps/settings.h +++ b/apps/settings.h @@ -222,7 +222,6 @@ void sound_settings_apply(void); * skin buffer is reset properly */ void settings_apply_skins(void); -void theme_init_buffer(void); void settings_apply(bool read_disk); void settings_apply_pm_range(void); diff --git a/apps/settings_list.c b/apps/settings_list.c index dbf0f41952..31721d6840 100644 --- a/apps/settings_list.c +++ b/apps/settings_list.c @@ -203,7 +203,7 @@ static const char graphic_numeric[] = "graphic,numeric"; /* Default theme settings */ #define DEFAULT_WPSNAME "cabbiev2" #define DEFAULT_SBSNAME "-" -#define DEFAULT_FMS_NAME DEFAULT_WPSNAME +#define DEFAULT_FMS_NAME "-" #ifdef HAVE_LCD_BITMAP