rockbox/apps/gui/skin_engine/skin_backdrops.c
Thomas Martitz 6cb11764e0 skin_engine/backdrops: Have to reload default backdrops from setting when it changed.
When skins use the default backdrop (via %X(-) or no %X at all) and the setting
changes it needs to be reloaded, otherwise when changing themes the new theme
could show the backdrop from the previous theme. The same needs to be
done when re-selecting the same theme after USB because the backdrop file was
potentially overwritten.

Fixes FS#12892 and FS#12942.

Change-Id: Ic2d20740cc385fa99667ce8a71507dbda2efceaf
2014-01-22 16:58:58 +01:00

312 lines
9.3 KiB
C

/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2010 Jonathan Gordon
*
* 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 <stdio.h>
#include <stdlib.h>
#include "core_alloc.h"
#include "string-extra.h"
#include "settings.h"
#include "wps_internals.h"
#include "skin_engine.h"
#if !defined(__PCTOOL__) && defined(HAVE_BACKDROP_IMAGE)
#define NB_BDROPS SKINNABLE_SCREENS_COUNT*NB_SCREENS
static struct skin_backdrop {
char name[MAX_PATH];
char *buffer;
enum screen_type screen;
bool loaded;
int buflib_handle;
int ref_count;
} backdrops[NB_BDROPS];
#define NB_BDROPS SKINNABLE_SCREENS_COUNT*NB_SCREENS
static int handle_being_loaded;
static int current_lcd_backdrop[NB_SCREENS];
bool skin_backdrop_get_debug(int index, char **path, int *ref_count, size_t *size)
{
if (index + 1 >= NB_BDROPS)
return false;
*path = backdrops[index].name;
*ref_count = backdrops[index].ref_count;
#if defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)
enum screen_type screen = backdrops[index].screen;
if (screen == SCREEN_REMOTE)
*size = REMOTE_LCD_BACKDROP_BYTES;
else
#endif
*size = LCD_BACKDROP_BYTES;
return true;
}
static int buflib_move_callback(int handle, void* current, void* new)
{
if (handle == handle_being_loaded)
return BUFLIB_CB_CANNOT_MOVE;
for (int i=0; i<NB_BDROPS; i++)
{
if (backdrops[i].buffer == current)
{
backdrops[i].buffer = new;
break;
}
}
FOR_NB_SCREENS(i)
skin_backdrop_show(current_lcd_backdrop[i]);
return BUFLIB_CB_OK;
}
static struct buflib_callbacks buflib_ops = {buflib_move_callback, NULL, NULL};
static bool first_go = true;
void skin_backdrop_init(void)
{
if (first_go)
{
for (int i=0; i<NB_BDROPS; i++)
{
backdrops[i].buflib_handle = -1;
backdrops[i].name[0] = '\0';
backdrops[i].buffer = NULL;
backdrops[i].loaded = false;
backdrops[i].ref_count = 0;
}
FOR_NB_SCREENS(i)
current_lcd_backdrop[i] = -1;
handle_being_loaded = -1;
first_go = false;
}
}
int skin_backdrop_assign(char* backdrop, char *bmpdir,
enum screen_type screen)
{
char filename[MAX_PATH];
int i, free = -1;
if (!backdrop)
return -1;
if (backdrop[0] == '-')
{
filename[0] = '-';
filename[1] = '\0';
filename[2] = '\0'; /* we check this later to see if we actually have an
image to load. != '\0' means display the image */
}
else if (!strcmp(backdrop, BACKDROP_BUFFERNAME))
{
strcpy(filename, backdrop);
}
else
{
get_image_filename(backdrop, bmpdir, filename, sizeof(filename));
}
for (i=0; i<NB_BDROPS; i++)
{
if (!backdrops[i].name[0] && free < 0)
{
free = i;
break;
}
else if (!strcmp(backdrops[i].name, filename) && backdrops[i].screen == screen)
{
backdrops[i].ref_count++;
break;
}
}
if (free >= 0)
{
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;
}
bool skin_backdrops_preload(void)
{
bool retval = true;
int i;
char *filename;
for (i=0; i<NB_BDROPS; i++)
{
if (backdrops[i].name[0] && !backdrops[i].buffer)
{
size_t buf_size;
enum screen_type screen = backdrops[i].screen;
#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;
filename = backdrops[i].name;
if (screen == SCREEN_MAIN && global_settings.backdrop_file[0] &&
global_settings.backdrop_file[0] != '-' && filename[0] == '-')
{
filename = global_settings.backdrop_file;
}
if (*filename && *filename != '-')
{
backdrops[i].buflib_handle = core_alloc_ex(filename, buf_size, &buflib_ops);
if (backdrops[i].buflib_handle > 0)
{
backdrops[i].buffer = core_get_data(backdrops[i].buflib_handle);
if (strcmp(filename, BACKDROP_BUFFERNAME))
{
handle_being_loaded = backdrops[i].buflib_handle;
backdrops[i].loaded =
screens[screen].backdrop_load(filename, backdrops[i].buffer);
if (!backdrops[i].loaded)
{
core_free(backdrops[i].buflib_handle);
backdrops[i].buflib_handle = -1;
retval = false;
}
handle_being_loaded = -1;
}
else
backdrops[i].loaded = true;
}
else
retval = false;
}
if (backdrops[i].name[0] == '-' && backdrops[i].loaded)
backdrops[i].name[2] = '.';
}
}
return retval;
}
void* skin_backdrop_get_buffer(int backdrop_id)
{
if (backdrop_id < 0)
return NULL;
return backdrops[backdrop_id].buffer;
}
void skin_backdrop_show(int backdrop_id)
{
if (backdrop_id < 0)
{
screens[0].backdrop_show(NULL);
current_lcd_backdrop[0] = -1;
return;
}
enum screen_type screen = backdrops[backdrop_id].screen;
if ((backdrops[backdrop_id].loaded == false) ||
(backdrops[backdrop_id].name[0] == '-' &&
backdrops[backdrop_id].name[2] == '\0'))
{
screens[screen].backdrop_show(NULL);
current_lcd_backdrop[screen] = -1;
}
else if (backdrops[backdrop_id].buffer)
{
screens[screen].backdrop_show(backdrops[backdrop_id].buffer);
current_lcd_backdrop[screen] = backdrop_id;
}
}
void skin_backdrop_unload(int backdrop_id)
{
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)
{
int i;
for(i=0;i<SKINNABLE_SCREENS_COUNT*NB_SCREENS;i++)
{
if (backdrops[i].name[0] == '-' && backdrops[i].screen == SCREEN_MAIN)
{
if (global_settings.backdrop_file[0] &&
global_settings.backdrop_file[0] != '-')
{
if (!backdrops[i].buflib_handle <= 0)
{
backdrops[i].buflib_handle =
core_alloc_ex(global_settings.backdrop_file,
LCD_BACKDROP_BYTES, &buflib_ops);
if (backdrops[i].buflib_handle <= 0)
return;
}
bool loaded;
backdrops[i].buffer = core_get_data(backdrops[i].buflib_handle);
handle_being_loaded = backdrops[i].buflib_handle;
loaded = screens[SCREEN_MAIN].backdrop_load(
global_settings.backdrop_file,
backdrops[i].buffer);
handle_being_loaded = -1;
backdrops[i].name[2] = loaded ? '.' : '\0';
backdrops[i].loaded = loaded;
return;
}
else
backdrops[i].name[2] = '\0';
}
#if NB_SCREENS > 1
else if (backdrops[i].name[0] == '-')
{
backdrops[i].name[2] = '\0';
return;
}
#endif
}
}
#elif defined(__PCTOOL__)
int skin_backdrop_assign(char* backdrop, char *bmpdir,
enum screen_type screen)
{
(void)backdrop;
(void)bmpdir;
(void)screen;
return 0;
}
void skin_backdrop_unload(int backdrop_id)
{
(void)backdrop_id;
}
#else
void skin_backdrop_init(void)
{
}
#endif