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"
38 #include "skin_engine.h"
39 #include "skin_buffer.h"
40 #include "statusbar-skinned.h"
42 static bool skins_initialising
= true;
44 /* App uses the host malloc to manage the buffer */
46 #define skin_buffer NULL
47 void theme_init_buffer(void)
49 skins_initialising
= false;
52 static size_t skin_buffer_size
;
53 static char *skin_buffer
= NULL
;
54 static int buflib_move_callback(int handle
, void* current
, void* new)
58 return BUFLIB_CB_CANNOT_MOVE
;
60 static struct buflib_callbacks buflib_ops
= {buflib_move_callback
, NULL
};
62 void theme_init_buffer(void)
65 size_t size
= SKIN_BUFFER_SIZE
;
66 fd
= open_utf8(ROCKBOX_DIR
"/skin_buffer_size.txt", O_RDONLY
);
70 read(fd
, buf
, sizeof(buf
));
71 if (buf
[0] >= '0' && buf
[0] <= '9')
72 size
= atoi(buf
)*1024;
75 skin_buffer
= core_get_data(core_alloc_ex("skin buffer", size
, &buflib_ops
));
76 skin_buffer_size
= size
;
77 skins_initialising
= false;
81 void skin_data_free_buflib_allocs(struct wps_data
*wps_data
);
82 char* wps_default_skin(enum screen_type screen
);
83 char* default_radio_skin(enum screen_type screen
);
85 struct wps_state wps_state
= { .id3
= NULL
};
86 static struct gui_skin_helper
{
87 int (*preproccess
)(enum screen_type screen
, struct wps_data
*data
);
88 int (*postproccess
)(enum screen_type screen
, struct wps_data
*data
);
89 char* (*default_skin
)(enum screen_type screen
);
90 } skin_helpers
[SKINNABLE_SCREENS_COUNT
] = {
91 [CUSTOM_STATUSBAR
] = { sb_preproccess
, sb_postproccess
, sb_create_from_settings
},
92 [WPS
] = { NULL
, NULL
, wps_default_skin
},
94 [FM_SCREEN
] = { NULL
, NULL
, default_radio_skin
}
98 static struct gui_skin
{
99 struct gui_wps gui_wps
;
100 struct wps_data data
;
104 bool needs_full_update
;
105 } skins
[SKINNABLE_SCREENS_COUNT
][NB_SCREENS
];
108 void gui_sync_skin_init(void)
111 for(j
=0; j
<SKINNABLE_SCREENS_COUNT
; j
++)
115 skins
[j
][i
].buffer_start
= NULL
;
116 skins
[j
][i
].needs_full_update
= true;
117 skins
[j
][i
].gui_wps
.data
= &skins
[j
][i
].data
;
118 skins
[j
][i
].gui_wps
.display
= &screens
[i
];
119 memset(skins
[j
][i
].gui_wps
.data
, 0, sizeof(struct wps_data
));
120 skins
[j
][i
].data
.wps_loaded
= false;
122 skins
[j
][i
].data
.albumart
= NULL
;
123 skins
[j
][i
].data
.playback_aa_slot
= -1;
129 void settings_apply_skins(void)
133 for(j
=0; j
<SKINNABLE_SCREENS_COUNT
; j
++)
136 skin_data_free_buflib_allocs(&skins
[j
][i
].data
);
139 skin_buffer_init(skin_buffer
, skin_buffer_size
);
141 #ifdef HAVE_LCD_BITMAP
142 skin_backdrop_init();
144 gui_sync_skin_init();
146 /* Make sure each skin is loaded */
147 for (i
=0; i
<SKINNABLE_SCREENS_COUNT
; i
++)
152 #if LCD_DEPTH > 1 || defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
153 skin_backdrops_preload(); /* should maybe check the retval here... */
155 viewportmanager_theme_changed(THEME_STATUSBAR
);
156 #if LCD_DEPTH > 1 || defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
158 skin_backdrop_show(sb_get_backdrop(i
));
162 void skin_load(enum skinnable_screens skin
, enum screen_type screen
,
163 const char *buf
, bool isfile
)
167 if (skin_helpers
[skin
].preproccess
)
168 skin_helpers
[skin
].preproccess(screen
, &skins
[skin
][screen
].data
);
171 loaded
= skin_data_load(screen
, &skins
[skin
][screen
].data
, buf
, isfile
);
173 if (!loaded
&& skin_helpers
[skin
].default_skin
)
174 loaded
= skin_data_load(screen
, &skins
[skin
][screen
].data
,
175 skin_helpers
[skin
].default_skin(screen
), false);
177 skins
[skin
][screen
].needs_full_update
= true;
178 if (skin_helpers
[skin
].postproccess
)
179 skin_helpers
[skin
].postproccess(screen
, &skins
[skin
][screen
].data
);
182 static bool loading_a_sbs
= false;
183 struct gui_wps
*skin_get_gwps(enum skinnable_screens skin
, enum screen_type screen
)
185 if (!loading_a_sbs
&& skins
[skin
][screen
].data
.wps_loaded
== false)
187 char buf
[MAX_PATH
*2];
188 char *setting
= NULL
, *ext
= NULL
;
191 case CUSTOM_STATUSBAR
:
192 #ifdef HAVE_LCD_BITMAP
193 if (skins_initialising
)
195 /* still loading, buffers not initialised yet,
196 * viewport manager calls into the sbs code, not really
197 * caring if the sbs has loaded or not, so just return
198 * the gwps, this is safe. */
199 return &skins
[skin
][screen
].gui_wps
;
201 /* during the sbs load it will call skin_get_gwps() a few times
202 * which will eventually stkov the viewportmanager, so make
203 * sure we don't let that happen */
204 loading_a_sbs
= true;
205 #if defined(HAVE_REMOTE_LCD) && NB_SCREENS > 1
206 if (screen
== SCREEN_REMOTE
)
208 setting
= global_settings
.rsbs_file
;
214 setting
= global_settings
.sbs_file
;
218 return &skins
[skin
][screen
].gui_wps
;
219 #endif /* HAVE_LCD_BITMAP */
222 #if defined(HAVE_REMOTE_LCD) && NB_SCREENS > 1
223 if (screen
== SCREEN_REMOTE
)
225 setting
= global_settings
.rwps_file
;
231 setting
= global_settings
.wps_file
;
237 #if defined(HAVE_REMOTE_LCD) && NB_SCREENS > 1
238 if (screen
== SCREEN_REMOTE
)
240 setting
= global_settings
.rfms_file
;
246 setting
= global_settings
.fms_file
;
255 buf
[0] = '\0'; /* force it to reload the default */
256 if (strcmp(setting
, "rockbox_failsafe"))
258 snprintf(buf
, sizeof buf
, WPS_DIR
"/%s.%s", setting
, ext
);
261 skin_load(skin
, screen
, buf
, true);
263 loading_a_sbs
= false;
266 return &skins
[skin
][screen
].gui_wps
;
269 struct wps_state
*skin_get_global_state(void)
274 /* This is called to find out if we the screen needs a full update.
275 * if true you MUST do a full update as the next call will return false */
276 bool skin_do_full_update(enum skinnable_screens skin
,
277 enum screen_type screen
)
279 bool ret
= skins
[skin
][screen
].needs_full_update
;
280 skins
[skin
][screen
].needs_full_update
= false;
284 /* tell a skin to do a full update next time */
285 void skin_request_full_update(enum skinnable_screens skin
)
289 skins
[skin
][i
].needs_full_update
= true;