rockbox/apps/gui/statusbar-skinned.c
Jonathan Gordon 5b0521c9aa Changeover to the new skin format. SkinBreakingChange in the wiki has the runown of the changes.
Major changes are paramerterised tags now use %tag(param,param), colours are removed from the %V() tag, %Vi gets a required (but can be -) label as its first param).

utils/skinupdater/ has a program to update individual skins, and a perl script to update a whole zip.
Themesite will be unusable for the time being (you should be able to upload new themes once it updates checkwps though).

I obviously havnt tested every updated wps in this change so let me know if one doesnt load


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26641 a1c6a512-1295-4272-9138-f99709370657
2010-06-07 03:44:11 +00:00

255 lines
7.9 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2009 Thomas Martitz
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "config.h"
#include "system.h"
#include "settings.h"
#include "appevents.h"
#include "screens.h"
#include "screen_access.h"
#include "skin_engine/skin_engine.h"
#include "skin_engine/wps_internals.h"
#include "viewport.h"
#include "statusbar.h"
#include "statusbar-skinned.h"
#include "debug.h"
#include "font.h"
#include "icon.h"
/* currently only one wps_state is needed */
extern struct wps_state wps_state; /* from wps.c */
static struct gui_wps sb_skin[NB_SCREENS] = {{ .data = NULL }};
static struct wps_data sb_skin_data[NB_SCREENS] = {{ .wps_loaded = 0 }};
static struct wps_sync_data sb_skin_sync_data = { .do_full_update = false };
/* initial setup of wps_data */
static int update_delay = DEFAULT_UPDATE_DELAY;
bool sb_set_title_text(char* title, enum themable_icons icon, enum screen_type screen)
{
int i;
bool retval = false;
for(i=0; i<sb_skin_data[screen].num_tokens; i++)
{
if (sb_skin_data[screen].tokens[i].type == WPS_TOKEN_LIST_TITLE_TEXT)
{
sb_skin_data[screen].tokens[i].value.data = title;
retval = true;
}
else if (sb_skin_data[screen].tokens[i].type == WPS_TOKEN_LIST_TITLE_ICON)
{
/* Icon_NOICON == -1 which the skin engine wants at position 1, so + 2 */
sb_skin_data[screen].tokens[i].value.i = icon+2;
}
}
return retval;
}
void sb_skin_data_load(enum screen_type screen, const char *buf, bool isfile)
{
struct wps_data *data = sb_skin[screen].data;
int success;
success = buf && skin_data_load(screen, data, buf, isfile);
if (success)
{ /* hide the sb's default viewport because it has nasty effect with stuff
* not part of the statusbar,
* hence .sbs's without any other vps are unsupported*/
struct skin_viewport *vp = find_viewport(VP_DEFAULT_LABEL, data);
struct skin_token_list *next_vp = data->viewports->next;
if (!next_vp)
{ /* no second viewport, let parsing fail */
success = false;
}
/* hide this viewport, forever */
vp->hidden_flags = VP_NEVER_VISIBLE;
sb_set_info_vp(screen, VP_INFO_LABEL|VP_DEFAULT_LABEL);
}
if (!success && isfile)
sb_create_from_settings(screen);
}
static char infovp_label[NB_SCREENS];
static char oldinfovp_label[NB_SCREENS];
void sb_set_info_vp(enum screen_type screen, char label)
{
infovp_label[screen] = label;
}
struct viewport *sb_skin_get_info_vp(enum screen_type screen)
{
if (oldinfovp_label[screen] != infovp_label[screen])
{
/* UI viewport changed, so force a redraw */
oldinfovp_label[screen] = infovp_label[screen];
viewportmanager_theme_enable(screen, false, NULL);
viewportmanager_theme_undo(screen, true);
}
return &find_viewport(infovp_label[screen], sb_skin[screen].data)->vp;
}
#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1)
char* sb_get_backdrop(enum screen_type screen)
{
return sb_skin[screen].data->backdrop;
}
bool sb_set_backdrop(enum screen_type screen, char* filename)
{
if (!filename)
{
sb_skin[screen].data->backdrop = NULL;
return true;
}
else if (!sb_skin[screen].data->backdrop)
{
/* need to make room on the buffer */
size_t buf_size;
#if defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)
if (screen == SCREEN_REMOTE)
buf_size = REMOTE_LCD_BACKDROP_BYTES;
else
#endif
buf_size = LCD_BACKDROP_BYTES;
sb_skin[screen].data->backdrop = skin_buffer_alloc(buf_size);
if (!sb_skin[screen].data->backdrop)
return false;
}
if (!screens[screen].backdrop_load(filename, sb_skin[screen].data->backdrop))
sb_skin[screen].data->backdrop = NULL;
return sb_skin[screen].data->backdrop != NULL;
}
#endif
void sb_skin_update(enum screen_type screen, bool force)
{
static long next_update[NB_SCREENS] = {0};
int i = screen;
if (TIME_AFTER(current_tick, next_update[i]) || force)
{
#if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
/* currently, all remotes are readable without backlight
* so still update those */
if (lcd_active() || (i != SCREEN_MAIN))
#endif
skin_update(&sb_skin[i], force?
WPS_REFRESH_ALL : WPS_REFRESH_NON_STATIC);
next_update[i] = current_tick + update_delay; /* don't update too often */
sb_skin[SCREEN_MAIN].sync_data->do_full_update = false;
}
}
void do_sbs_update_callback(void *param)
{
(void)param;
/* the WPS handles changing the actual id3 data in the id3 pointers
* we imported, we just want a full update */
sb_skin_sync_data.do_full_update = true;
/* force timeout in wps main loop, so that the update is instantly */
queue_post(&button_queue, BUTTON_NONE, 0);
}
void sb_skin_set_update_delay(int delay)
{
update_delay = delay;
}
/* This creates and loads a ".sbs" based on the user settings for:
* - regular statusbar
* - colours
* - ui viewport
* - backdrop
*/
void sb_create_from_settings(enum screen_type screen)
{
char buf[128], *ptr, *ptr2;
int len, remaining = sizeof(buf);
int bar_position = statusbar_position(screen);
ptr = buf;
ptr[0] = '\0';
/* setup the inbuilt statusbar */
if (bar_position != STATUSBAR_OFF)
{
int y = 0, height = STATUSBAR_HEIGHT;
if (bar_position == STATUSBAR_BOTTOM)
{
y = screens[screen].lcdheight - STATUSBAR_HEIGHT;
}
len = snprintf(ptr, remaining, "%%V(0,%d,-,%d,0)\n%%wi\n",
y, height);
remaining -= len;
ptr += len;
}
/* %Vi viewport, colours handled by the parser */
#if NB_SCREENS > 1
if (screen == SCREEN_REMOTE)
ptr2 = global_settings.remote_ui_vp_config;
else
#endif
ptr2 = global_settings.ui_vp_config;
if (ptr2[0] && ptr2[0] != '-') /* from ui viewport setting */
{
len = snprintf(ptr, remaining, "%%ax%%Vi(-,%s)\n", ptr2);
}
else
{
int y = 0, height;
switch (bar_position)
{
case STATUSBAR_TOP:
y = STATUSBAR_HEIGHT;
case STATUSBAR_BOTTOM:
height = screens[screen].lcdheight - STATUSBAR_HEIGHT;
break;
default:
height = screens[screen].lcdheight;
}
len = snprintf(ptr, remaining, "%%ax%%Vi(-,0,%d,-,%d,1)\n",
y, height);
}
sb_skin_data_load(screen, buf, false);
}
void sb_skin_init(void)
{
int i;
FOR_NB_SCREENS(i)
{
#ifdef HAVE_ALBUMART
sb_skin_data[i].albumart = NULL;
sb_skin_data[i].playback_aa_slot = -1;
#endif
sb_skin[i].data = &sb_skin_data[i];
sb_skin[i].display = &screens[i];
/* Currently no seperate wps_state needed/possible
so use the only available ( "global" ) one */
sb_skin[i].state = &wps_state;
sb_skin[i].sync_data = &sb_skin_sync_data;
}
}