diff --git a/apps/SOURCES b/apps/SOURCES index 8c3f27d..4e7a0e4 100644 --- a/apps/SOURCES +++ b/apps/SOURCES @@ -50,6 +50,7 @@ gui/gwps.c gui/gwps-common.c #ifdef HAVE_LCD_BITMAP gui/icon.c +gui/gui_img.c #endif gui/list.c gui/option_select.c diff --git a/apps/gui/gui_img.c b/apps/gui/gui_img.c new file mode 100644 index 0000000..f068081 --- /dev/null +++ b/apps/gui/gui_img.c @@ -0,0 +1,95 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: $ + * + * Copyright (C) 2007 Mark Arigo + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "gui_img.h" +#include "bmp.h" + +int gui_image_load(char* filename, struct gui_img* img, unsigned char* buffer, + int bufsize, int format) +{ + int ret; + + img->bm.data = buffer; + ret = read_bmp_file(filename, &img->bm, bufsize, format); + + if (ret > 0) + { + img->loaded = true; + img->width = img->bm.width; + img->height = img->bm.height; + img->subimg_index = 0; + + if (img->nb_subimg > 0) + { + img->height = img->bm.height / img->nb_subimg; + } + else + img->nb_subimg = 1; + +#if LCD_DEPTH == 16 + /* Always consume an even number of bytes */ + if (ret % 2) + ret++; +#endif + } + else + img->loaded = false; + + return ret; +} + +void gui_image_draw(struct screen *display, struct gui_img* img) +{ + if(img->always_display) + display->set_drawmode(DRMODE_FG); + else + display->set_drawmode(DRMODE_SOLID); + + if (img->nb_subimg > 1) + { +#if LCD_DEPTH > 1 + if(img->bm.format == FORMAT_MONO) { +#endif + display->mono_bitmap_part(img->bm.data, 0, + img->subimg_index * img->height, img->width, + img->x, img->y, img->width, img->height); +#if LCD_DEPTH > 1 + } else { + display->transparent_bitmap_part((fb_data *)img->bm.data, 0, + img->subimg_index * img->height, img->width, + img->x, img->y, img->width, img->height); + } +#endif + return; + } + +#if LCD_DEPTH > 1 + if(img->bm.format == FORMAT_MONO) { +#endif + display->mono_bitmap(img->bm.data, img->x, img->y, img->width, + img->height); +#if LCD_DEPTH > 1 + } else { + display->transparent_bitmap((fb_data *)img->bm.data, img->x, img->y, + img->width, img->height); + } +#endif + + display->set_drawmode(DRMODE_SOLID); +} diff --git a/apps/gui/gui_img.h b/apps/gui/gui_img.h new file mode 100644 index 0000000..fabdb90 --- /dev/null +++ b/apps/gui/gui_img.h @@ -0,0 +1,51 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: $ + * + * Copyright (C) 2007 Mark Arigo + * + * All files in this archive are subject to the GNU General Public License. + * See the file COPYING in the source tree root for full license agreement. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#ifndef _GUI_IMG_H +#define _GUI_IMG_H + +#include "screen_access.h" + +struct gui_img { + struct bitmap bm; + int x; /* x-pos */ + int y; /* y-pos */ + int width; /* image width (same as bm.width) */ + int height; /* image height. If there are subimages, + then this is the height of each subimage. + The total bitmap height is bm.height. */ + unsigned short nb_subimg; /* number of sub images */ + unsigned short subimg_index;/* subimage to display (zero-based): + 0, 1, ... (nb_subimg-1) */ + unsigned short cond_index; /* the index of the conditional the image + is in */ + bool loaded; /* load state */ + bool display; /* is to be displayed */ + bool always_display; /* not using the preload/display mechanism */ + + unsigned int subimg_expire_time; + unsigned int subimg_timeout; +}; + +int gui_image_load(char* filename, struct gui_img* img, + unsigned char* buffer, int bufsize, int format); + +void gui_image_draw(struct screen *display, struct gui_img* img); + +#endif diff --git a/apps/gui/gwps-common.c b/apps/gui/gwps-common.c index fe7e1ed..bb8bc20 100644 --- a/apps/gui/gwps-common.c +++ b/apps/gui/gwps-common.c @@ -459,32 +459,25 @@ static void draw_progressbar(struct gui_wps *gwps, int line) struct wps_data *data = gwps->data; struct screen *display = gwps->display; struct wps_state *state = gwps->state; + struct gui_img *pbar = &data->img[PROGRESSBAR_BMP]; int h = font_get(FONT_UI)->height; - int sb_y; - if (data->progress_top < 0) - sb_y = line*h + display->getymargin() + - ((h > data->progress_height + 1) - ? (h - data->progress_height) / 2 : 1); - else - sb_y = data->progress_top; + if (pbar->y < 0) + pbar->y = line*h + display->getymargin() + + ( (h > pbar->height + 1) ? (h - pbar->height)/2 : 1 ); - if (!data->progress_end) - data->progress_end=display->width; + if (pbar->width <= 0) + pbar->width = display->width - pbar->x; - if (gwps->data->progressbar.have_bitmap_pb) - gui_bitmap_scrollbar_draw(display, data->progressbar.bm, - data->progress_start, sb_y, - data->progress_end-data->progress_start, - data->progressbar.bm.height, + if (pbar->loaded) + gui_bitmap_scrollbar_draw(display, pbar->bm, pbar->x, pbar->y, + pbar->width, pbar->height, state->id3->length ? state->id3->length : 1, 0, state->id3->length ? state->id3->elapsed + state->ff_rewind_count : 0, HORIZONTAL); else - gui_scrollbar_draw(display, data->progress_start, sb_y, - data->progress_end-data->progress_start, - data->progress_height, + gui_scrollbar_draw(display, pbar->x, pbar->y, pbar->width, pbar->height, state->id3->length ? state->id3->length : 1, 0, state->id3->length ? state->id3->elapsed + state->ff_rewind_count : 0, @@ -492,52 +485,15 @@ static void draw_progressbar(struct gui_wps *gwps, int line) #ifdef AB_REPEAT_ENABLE if ( ab_repeat_mode_enabled() ) - ab_draw_markers(display, state->id3->length, - data->progress_start, data->progress_end, sb_y, - data->progress_height); + ab_draw_markers(display, state->id3->length, pbar->x, + pbar->x + pbar->width, pbar->y, pbar->height); + #endif if ( cuesheet_is_enabled() && state->id3->cuesheet_type ) - cue_draw_markers(display, state->id3->length, - data->progress_start, data->progress_end, - sb_y+1, data->progress_height-2); -} - -/* clears the area where the image was shown */ -static void clear_image_pos(struct gui_wps *gwps, int n) -{ - if(!gwps) - return; - struct wps_data *data = gwps->data; - gwps->display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); - gwps->display->fillrect(data->img[n].x, data->img[n].y, - data->img[n].bm.width, data->img[n].bm.height); - gwps->display->set_drawmode(DRMODE_SOLID); -} - -static void wps_draw_image(struct gui_wps *gwps, int n) -{ - struct screen *display = gwps->display; - struct wps_data *data = gwps->data; - if(data->img[n].always_display) - display->set_drawmode(DRMODE_FG); - else - display->set_drawmode(DRMODE_SOLID); - -#if LCD_DEPTH > 1 - if(data->img[n].bm.format == FORMAT_MONO) { -#endif - display->mono_bitmap(data->img[n].bm.data, data->img[n].x, - data->img[n].y, data->img[n].bm.width, - data->img[n].bm.height); -#if LCD_DEPTH > 1 - } else { - display->transparent_bitmap((fb_data *)data->img[n].bm.data, - data->img[n].x, - data->img[n].y, data->img[n].bm.width, - data->img[n].bm.height); - } -#endif + cue_draw_markers(display, state->id3->length, pbar->x, + pbar->x + pbar->width, pbar->y + 1, + pbar->height - 2); } static void wps_display_images(struct gui_wps *gwps) @@ -546,18 +502,13 @@ static void wps_display_images(struct gui_wps *gwps) return; int n; - struct wps_data *data = gwps->data; - struct screen *display = gwps->display; + struct gui_img *img = gwps->data->img; for (n = 0; n < MAX_IMAGES; n++) { - if (data->img[n].loaded && - (data->img[n].display || data->img[n].always_display)) - { - wps_draw_image(gwps, n); - } + if (img[n].loaded && (img[n].display || img[n].always_display)) + gui_image_draw(gwps->display, &img[n]); } - display->set_drawmode(DRMODE_SOLID); } #else /* HAVE_LCD_CHARCELL */ @@ -814,6 +765,7 @@ static char *get_token_value(struct gui_wps *gwps, playlist_get_display_index()); return buf; + case WPS_TOKEN_IMAGE_ENUM_SHUFFLE: case WPS_TOKEN_PLAYLIST_SHUFFLE: if ( global_settings.playlist_shuffle ) return "s"; @@ -821,6 +773,7 @@ static char *get_token_value(struct gui_wps *gwps, return NULL; break; + case WPS_TOKEN_IMAGE_ENUM_VOLUME: case WPS_TOKEN_VOLUME: snprintf(buf, buf_size, "%d", global_settings.volume); if (intval) @@ -917,6 +870,7 @@ static char *get_token_value(struct gui_wps *gwps, snprintf(buf, buf_size, "?"); return buf; + case WPS_TOKEN_IMAGE_ENUM_CODEC: case WPS_TOKEN_FILE_CODEC: if (intval) { @@ -970,6 +924,7 @@ static char *get_token_value(struct gui_wps *gwps, case WPS_TOKEN_FILE_DIRECTORY: return get_dir(buf, buf_size, id3->path, token->value.i); + case WPS_TOKEN_IMAGE_ENUM_BATTERY: case WPS_TOKEN_BATTERY_PERCENT: { int l = battery_level(); @@ -1040,6 +995,7 @@ static char *get_token_value(struct gui_wps *gwps, } } + case WPS_TOKEN_IMAGE_ENUM_PLAYBACK: case WPS_TOKEN_PLAYBACK_STATUS: { int status = audio_status(); @@ -1063,6 +1019,7 @@ static char *get_token_value(struct gui_wps *gwps, return buf; } + case WPS_TOKEN_IMAGE_ENUM_REPEAT: case WPS_TOKEN_REPEAT_MODE: if (intval) *intval = global_settings.repeat_mode + 1; @@ -1293,6 +1250,22 @@ static char *get_token_value(struct gui_wps *gwps, } #endif +#ifdef HAS_BUTTON_HOLD + case WPS_TOKEN_IMAGE_ENUM_HOLD: + *intval = 1; + if (button_hold()) + *intval = 2; + +#ifdef HAS_REMOTE_BUTTON_HOLD + if (remote_button_hold()) + if (*intval == 2) + *intval = 3; + else + *intval = 4; +#endif + return NULL; +#endif /* HAS_BUTTON_HOLD */ + case WPS_TOKEN_MAIN_HOLD: #ifdef HAS_BUTTON_HOLD if (button_hold()) @@ -1381,7 +1354,8 @@ static int evaluate_conditional(struct gui_wps *gwps, int cond_index) for (i = 0; i < MAX_IMAGES; i++) { if (data->img[i].cond_index == cond_index) - clear_image_pos(gwps, i); + screen_clear_area(gwps->display, data->img[i].x, data->img[i].y, + data->img[i].width, data->img[i].height); } #endif @@ -1406,6 +1380,7 @@ static bool get_line(struct gui_wps *gwps, char *linebuf_end = linebuf + linebuf_size - 1; int i, last_token_idx; bool update = false; + char *value; /* alignment-related variables */ int cur_align; @@ -1437,11 +1412,65 @@ static bool get_line(struct gui_wps *gwps, #ifdef HAVE_LCD_BITMAP case WPS_TOKEN_IMAGE_PRELOAD_DISPLAY: + case WPS_TOKEN_IMAGE_ANIMATE: + case WPS_TOKEN_IMAGE_ENUM_BATTERY: + case WPS_TOKEN_IMAGE_ENUM_CODEC: + case WPS_TOKEN_IMAGE_ENUM_HOLD: + case WPS_TOKEN_IMAGE_ENUM_PLAYBACK: + case WPS_TOKEN_IMAGE_ENUM_REPEAT: + case WPS_TOKEN_IMAGE_ENUM_SHUFFLE: + case WPS_TOKEN_IMAGE_ENUM_VOLUME: { struct gui_img *img = data->img; int n = data->tokens[i].value.i; + int intval = img[n].nb_subimg; + if (n >= 0 && n < MAX_IMAGES && img[n].loaded) + { + /* If there are subimages, get the conditional value */ + if (img[n].nb_subimg > 1) + { + if (data->tokens[i].type == WPS_TOKEN_IMAGE_ANIMATE) + { + if (TIME_AFTER(current_tick, img[n].subimg_expire_time - 1)) + { + img[n].subimg_expire_time = current_tick + + BASE_SUBLINE_TIME*img[n].subimg_timeout; + img[n].subimg_index++; + if (img[n].subimg_index == img[n].nb_subimg) + img[n].subimg_index = 0; + } + } + else + { + value = get_token_value(gwps, &data->tokens[i], + temp_buf, sizeof(temp_buf), &intval); + + if (intval == -1) + { + /* No intval set, these are on/off cases. + Use the first (off) or last (on) image */ + intval = (value && *value) ? img[n].nb_subimg : 1; + } + else if (intval == 0) + { + /* default to first image */ + intval = 1; + } + else if (intval > img[n].nb_subimg) + { + /* default to last image */ + intval = img[n].nb_subimg; + } + + /* intval counts from one, but subimg_index needs + to start at zero */ + img[n].subimg_index = intval - 1; + } + } + img[n].display = true; + } break; } #endif @@ -1486,7 +1515,7 @@ static bool get_line(struct gui_wps *gwps, default: { /* get the value of the tag and copy it to the buffer */ - char *value = get_token_value(gwps, &data->tokens[i], + value = get_token_value(gwps, &data->tokens[i], temp_buf, sizeof(temp_buf), NULL); if (value) { diff --git a/apps/gui/gwps.h b/apps/gui/gwps.h index ab82581..d866d63 100644 --- a/apps/gui/gwps.h +++ b/apps/gui/gwps.h @@ -24,6 +24,10 @@ #include "id3.h" #include "playlist.h" +#ifdef HAVE_LCD_BITMAP +#include "gui_img.h" +#endif + /* constants used in line_type and as refresh_mode for wps_refresh */ #define WPS_REFRESH_STATIC 1 /* line doesn't change over time */ #define WPS_REFRESH_DYNAMIC 2 /* line may change (e.g. time flag) */ @@ -41,25 +45,6 @@ /* wps_data*/ -#ifdef HAVE_LCD_BITMAP -struct gui_img{ - struct bitmap bm; - int x; /* x-pos */ - int y; /* y-pos */ - bool loaded; /* load state */ - bool display; /* is to be displayed */ - bool always_display; /* not using the preload/display mechanism */ - - /* the index of the conditional the image is in */ - unsigned short cond_index; -}; - -struct prog_img{ /*progressbar image*/ - struct bitmap bm; - bool have_bitmap_pb; -}; -#endif - struct align_pos { char* left; char* center; @@ -71,6 +56,8 @@ struct align_pos { #define MAX_IMAGES (26*2) /* a-z and A-Z */ #define IMG_BUFSIZE ((LCD_HEIGHT*LCD_WIDTH*LCD_DEPTH/8) \ + (2*LCD_HEIGHT*LCD_WIDTH/8)) +#define PROGRESSBAR_BMP MAX_IMAGES +#define BACKDROP_BMP MAX_IMAGES+1 #define WPS_MAX_LINES (LCD_HEIGHT/5+1) #define WPS_MAX_SUBLINES (WPS_MAX_LINES*3) @@ -185,6 +172,14 @@ enum wps_token_type { WPS_TOKEN_IMAGE_PRELOAD, WPS_TOKEN_IMAGE_PRELOAD_DISPLAY, WPS_TOKEN_IMAGE_DISPLAY, + WPS_TOKEN_IMAGE_ANIMATE, + WPS_TOKEN_IMAGE_ENUM_BATTERY, + WPS_TOKEN_IMAGE_ENUM_CODEC, + WPS_TOKEN_IMAGE_ENUM_HOLD, + WPS_TOKEN_IMAGE_ENUM_PLAYBACK, + WPS_TOKEN_IMAGE_ENUM_REPEAT, + WPS_TOKEN_IMAGE_ENUM_SHUFFLE, + WPS_TOKEN_IMAGE_ENUM_VOLUME, #endif /* Metadata */ @@ -293,18 +288,13 @@ struct wps_line { struct wps_data { #ifdef HAVE_LCD_BITMAP - struct gui_img img[MAX_IMAGES]; - struct prog_img progressbar; + struct gui_img img[MAX_IMAGES+1]; /* includes progressbar */ unsigned char img_buf[IMG_BUFSIZE]; unsigned char* img_buf_ptr; int img_buf_free; bool wps_sb_tag; bool show_sb_on_wps; - short progress_top; - short progress_height; - short progress_start; - short progress_end; bool peak_meter_enabled; #else /*HAVE_LCD_CHARCELLS */ unsigned short wps_progress_pat[8]; diff --git a/apps/gui/icon.c b/apps/gui/icon.c index 968d835..52e6629 100644 --- a/apps/gui/icon.c +++ b/apps/gui/icon.c @@ -27,6 +27,7 @@ #include "settings.h" #include "bmp.h" #include "filetypes.h" +#include "gui_img.h" #include #if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1) @@ -36,57 +37,20 @@ /* These are just the file names, the full path is snprint'ed when used */ #define DEFAULT_VIEWER_BMP "viewers" #define DEFAULT_REMOTE_VIEWER_BMP "remote_viewers" +#define DEFAULT_VIEWER_NB_ICONS 13 /* These should probably be moved to config-.h */ #define MAX_ICON_HEIGHT 24 #define MAX_ICON_WIDTH 24 +#define ICON_BUFSIZE (MAX_ICON_HEIGHT * MAX_ICON_WIDTH * \ + Icon_Last_Themeable *LCD_DEPTH/8) -/* We dont actually do anything with these pointers, - but they need to be grouped like this to save code - so storing them as void* is ok. (stops compile warning) */ -static const void * inbuilt_icons[NB_SCREENS] = { - (void*)default_icons -#if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1) - , (void*)remote_default_icons -#endif -}; - -static const int default_width[NB_SCREENS] = { - BMPWIDTH_default_icons -#if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1) - , BMPWIDTH_remote_default_icons -#endif -}; +static struct gui_img standard_icons[NB_SCREENS]; +static struct gui_img viewer_icons[NB_SCREENS]; +static unsigned char standard_icons_buffer[NB_SCREENS][ICON_BUFSIZE]; +static unsigned char viewer_icons_buffer[NB_SCREENS][ICON_BUFSIZE]; -/* height of whole file */ -static const int default_height[NB_SCREENS] = { - BMPHEIGHT_default_icons -#if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1) - , BMPHEIGHT_remote_default_icons -#endif -}; - -#define IMG_BUFSIZE (MAX_ICON_HEIGHT * MAX_ICON_WIDTH * \ - Icon_Last_Themeable *LCD_DEPTH/8) -static unsigned char icon_buffer[NB_SCREENS][IMG_BUFSIZE]; -static bool custom_icons_loaded[NB_SCREENS] = {false}; -static struct bitmap user_iconset[NB_SCREENS]; - -static unsigned char viewer_icon_buffer[NB_SCREENS][IMG_BUFSIZE]; -static bool viewer_icons_loaded[NB_SCREENS] = {false}; -static struct bitmap viewer_iconset[NB_SCREENS]; - - -#define ICON_HEIGHT(screen) (!custom_icons_loaded[screen]? \ - default_height[screen] : \ - user_iconset[screen].height) \ - / Icon_Last_Themeable - -#define ICON_WIDTH(screen) (!custom_icons_loaded[screen]? \ - default_width[screen] : \ - user_iconset[screen].width) - /* x,y in letters, not pixles */ void screen_put_icon(struct screen * display, int x, int y, enum themable_icons icon) @@ -100,13 +64,27 @@ void screen_put_icon_with_offset(struct screen * display, { int xpos, ypos; int width, height; + int icon_width, icon_height; int screen = display->screen_type; display->getstringsize((unsigned char *)"M", &width, &height); - xpos = x*ICON_WIDTH(screen) + off_x; + if (icon >= Icon_Last_Themeable) + { + /* Viewer icon */ + icon_width = viewer_icons[screen].width; + icon_height = viewer_icons[screen].height; + } + else + { + /* Viewer icon */ + icon_width = standard_icons[screen].width; + icon_height = standard_icons[screen].height; + } + + xpos = x*icon_width + off_x; ypos = y*height + display->getymargin() + off_y; - if ( height > ICON_HEIGHT(screen) )/* center the cursor */ - ypos += (height - ICON_HEIGHT(screen)) / 2; + if ( height > icon_height )/* center the cursor */ + ypos += (height - icon_height) / 2; screen_put_iconxy(display, xpos, ypos, icon); } @@ -114,50 +92,45 @@ void screen_put_icon_with_offset(struct screen * display, void screen_put_iconxy(struct screen * display, int xpos, int ypos, enum themable_icons icon) { - const void *data; + struct gui_img *icons; int screen = display->screen_type; - int width = ICON_WIDTH(screen); - int height = ICON_HEIGHT(screen); - screen_bitmap_part_func *draw_func = NULL; if (icon == Icon_NOICON) { - screen_clear_area(display, xpos, ypos, width, height); + /* Take dimensions from the standard icon set. */ + screen_clear_area(display, xpos, ypos, + standard_icons[screen].width, + standard_icons[screen].height); return; } else if (icon >= Icon_Last_Themeable) { icon -= Icon_Last_Themeable; - if (!viewer_icons_loaded[screen] || - (global_status.viewer_icon_count*height - > viewer_iconset[screen].height) || - (icon * height > viewer_iconset[screen].height)) + icons = &viewer_icons[screen]; + + if ( !icons->loaded || + (global_status.viewer_icon_count * icons->height + > icons->bm.height) || + (icon * icons->height > icons->bm.height) ) { screen_put_iconxy(display, xpos, ypos, Icon_Questionmark); return; } - data = viewer_iconset[screen].data; - } - else if (custom_icons_loaded[screen]) - { - data = user_iconset[screen].data; } else { - data = inbuilt_icons[screen]; + icons = &standard_icons[screen]; } + /* add some left padding to the icons if they are on the edge */ if (xpos == 0) xpos++; - -#if (LCD_DEPTH == 16) || defined(LCD_REMOTE_DEPTH) && (LCD_REMOTE_DEPTH == 16) - if (display->depth == 16) - draw_func = display->transparent_bitmap_part; - else -#endif - draw_func = display->bitmap_part; - draw_func(data, 0, height * icon, width, xpos, ypos, width, height); + icons->x = xpos; + icons->y = ypos; + icons->subimg_index = icon; + + gui_image_draw(display, icons); } void screen_put_cursorxy(struct screen * display, int x, int y, bool on) @@ -169,99 +142,135 @@ void screen_put_cursorxy(struct screen * display, int x, int y, bool on) #endif } -enum Iconset { - Iconset_Mainscreen, - Iconset_Mainscreen_viewers, -#if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1) - Iconset_Remotescreen, - Iconset_Remotescreen_viewers, -#endif -}; -static void load_icons(const char* filename, enum Iconset iconset, - bool allow_disable) +void icons_init(void) { - int size_read; - bool *loaded_ok = NULL; - struct bitmap *bmp = NULL; - int bmpformat = (FORMAT_NATIVE|FORMAT_DITHER); - - switch (iconset) + char path[MAX_PATH]; + char *filename; + int ret = 0; + int format = FORMAT_NATIVE|FORMAT_DITHER; + + standard_icons[SCREEN_MAIN].nb_subimg = Icon_Last_Themeable; + + filename = global_settings.icon_file; + if (filename[0] && filename[0] != '-') { - case Iconset_Mainscreen: - loaded_ok = &custom_icons_loaded[SCREEN_MAIN]; - bmp = &user_iconset[SCREEN_MAIN]; - bmp->data = icon_buffer[SCREEN_MAIN]; - break; - case Iconset_Mainscreen_viewers: - loaded_ok = &viewer_icons_loaded[SCREEN_MAIN]; - bmp = &viewer_iconset[SCREEN_MAIN]; - bmp->data = viewer_icon_buffer[SCREEN_MAIN]; - break; -#if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1) - case Iconset_Remotescreen: - loaded_ok = &custom_icons_loaded[SCREEN_REMOTE]; - bmp = &user_iconset[SCREEN_REMOTE]; - bmp->data = icon_buffer[SCREEN_REMOTE]; - bmpformat |= FORMAT_REMOTE; - break; - case Iconset_Remotescreen_viewers: - loaded_ok = &viewer_icons_loaded[SCREEN_REMOTE]; - bmp = &viewer_iconset[SCREEN_REMOTE]; - bmp->data = viewer_icon_buffer[SCREEN_REMOTE]; - bmpformat |= FORMAT_REMOTE; - break; -#endif + snprintf(path, sizeof(path), "%s/%s.bmp", ICON_DIR, filename); + + ret = gui_image_load(path, &standard_icons[SCREEN_MAIN], + standard_icons_buffer[SCREEN_MAIN], + ICON_BUFSIZE, format); } - - *loaded_ok = false; - if (!allow_disable || (filename[0] && filename[0] != '-')) + + if (ret <= 0) { - char path[MAX_PATH]; - - snprintf(path, sizeof(path), "%s/%s.bmp", ICON_DIR, filename); - size_read = read_bmp_file(path, bmp, IMG_BUFSIZE, bmpformat); - if (size_read > 0) - { - *loaded_ok = true; - } + /* Default icons */ +#if (LCD_DEPTH > 1) + standard_icons[SCREEN_MAIN].bm.format = FORMAT_NATIVE; +#endif + standard_icons[SCREEN_MAIN].bm.data = (unsigned char*)default_icons; + standard_icons[SCREEN_MAIN].width = BMPWIDTH_default_icons; + standard_icons[SCREEN_MAIN].height = + BMPHEIGHT_default_icons / Icon_Last_Themeable; + standard_icons[SCREEN_MAIN].loaded = true; } -} + ret = 0; -void icons_init(void) -{ - load_icons(global_settings.icon_file, Iconset_Mainscreen, true); - if (*global_settings.viewers_icon_file) { - load_icons(global_settings.viewers_icon_file, - Iconset_Mainscreen_viewers, true); read_viewer_theme_file(); + + if (global_status.viewer_icon_count > 0) + { + snprintf(path, sizeof(path), "%s/%s.bmp", ICON_DIR, + global_settings.viewers_icon_file); + + viewer_icons[SCREEN_MAIN].nb_subimg = + global_status.viewer_icon_count + 1; + + ret = gui_image_load(path, &viewer_icons[SCREEN_MAIN], + viewer_icons_buffer[SCREEN_MAIN], + ICON_BUFSIZE, format); + } } - else + + if (ret <= 0) { - load_icons(DEFAULT_VIEWER_BMP, Iconset_Mainscreen_viewers, false); + /* Default viewer icons */ + snprintf(path, sizeof(path), "%s/%s.bmp", ICON_DIR, + DEFAULT_VIEWER_BMP); + + viewer_icons[SCREEN_MAIN].nb_subimg = DEFAULT_VIEWER_NB_ICONS; + + ret = gui_image_load(path, &viewer_icons[SCREEN_MAIN], + viewer_icons_buffer[SCREEN_MAIN], + ICON_BUFSIZE, format); } #if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1) - load_icons(global_settings.remote_icon_file, - Iconset_Remotescreen, true); - - if (*global_settings.remote_viewers_icon_file) + ret = 0; + format |= FORMAT_REMOTE; + + standard_icons[SCREEN_REMOTE].nb_subimg = Icon_Last_Themeable; + + filename = global_settings.icon_file; + if (filename[0] && filename[0] != '-') { - load_icons(global_settings.remote_viewers_icon_file, - Iconset_Remotescreen_viewers, true); + snprintf(path, sizeof(path), "%s/%s.bmp", ICON_DIR, filename); + + ret = gui_image_load(path, &standard_icons[SCREEN_REMOTE], + standard_icons_buffer[SCREEN_REMOTE], + ICON_BUFSIZE, format); } - else + + if (ret <= 0) { - load_icons(DEFAULT_REMOTE_VIEWER_BMP, - Iconset_Remotescreen_viewers, false); + /* Default remote icons */ +#if (LCD_REMOTE_DEPTH > 1) + standard_icons[SCREEN_REMOTE].bm.format = FORMAT_NATIVE; +#endif + standard_icons[SCREEN_REMOTE].bm.data = + (unsigned char*)remote_default_icons; + standard_icons[SCREEN_REMOTE].width = + BMPWIDTH_remote_default_icons; + standard_icons[SCREEN_REMOTE].height = + BMPHEIGHT_remote_default_icons / Icon_Last_Themeable; + standard_icons[SCREEN_REMOTE].loaded = true; + } + + ret = 0; + + if (*global_settings.remote_viewers_icon_file && + global_status.viewer_icon_count > 0) + { + snprintf(path, sizeof(path), "%s/%s.bmp", ICON_DIR, + global_settings.remote_viewers_icon_file); + + viewer_icons[SCREEN_REMOTE].nb_subimg = + global_status.viewer_icon_count + 1; + + ret = gui_image_load(path, &viewer_icons[SCREEN_REMOTE], + viewer_icons_buffer[SCREEN_REMOTE], + ICON_BUFSIZE, format); + } + + if (ret <= 0) + { + snprintf(path, sizeof(path), "%s/%s.bmp", ICON_DIR, + DEFAULT_REMOTE_VIEWER_BMP); + + viewer_icons[SCREEN_REMOTE].nb_subimg = DEFAULT_VIEWER_NB_ICONS; + + ret = gui_image_load(path, &viewer_icons[SCREEN_REMOTE], + viewer_icons_buffer[SCREEN_REMOTE], + ICON_BUFSIZE, format); } #endif } int get_icon_width(enum screen_type screen_type) { - return ICON_WIDTH(screen_type); + /* Return the width of the standard icon set. */ + return standard_icons[screen_type].width; } diff --git a/apps/gui/wps_parser.c b/apps/gui/wps_parser.c index 43ea516..9ddaed5 100644 --- a/apps/gui/wps_parser.c +++ b/apps/gui/wps_parser.c @@ -71,9 +71,6 @@ static int line; #define MAX_BITMAPS MAX_IMAGES+1 /* WPS images + pbar bitmap */ #endif -#define PROGRESSBAR_BMP MAX_IMAGES -#define BACKDROP_BMP MAX_IMAGES+1 - /* pointers to the bitmap filenames in the WPS source */ static const char *bmp_names[MAX_BITMAPS]; @@ -276,8 +273,26 @@ static const struct wps_tag all_tags[] = { { WPS_TOKEN_IMAGE_PRELOAD_DISPLAY, "xd", WPS_REFRESH_STATIC, parse_image_display }, + { WPS_TOKEN_IMAGE_ANIMATE, "xa", WPS_REFRESH_DYNAMIC, + parse_image_display }, + { WPS_TOKEN_IMAGE_ENUM_BATTERY, "xb", WPS_REFRESH_DYNAMIC, + parse_image_display }, + { WPS_TOKEN_IMAGE_ENUM_CODEC, "xc", WPS_REFRESH_DYNAMIC, + parse_image_display }, + { WPS_TOKEN_IMAGE_ENUM_HOLD, "xh", WPS_REFRESH_DYNAMIC, + parse_image_display }, + { WPS_TOKEN_IMAGE_ENUM_PLAYBACK, "xp", WPS_REFRESH_DYNAMIC, + parse_image_display }, + { WPS_TOKEN_IMAGE_ENUM_REPEAT, "xr", WPS_REFRESH_DYNAMIC, + parse_image_display }, + { WPS_TOKEN_IMAGE_ENUM_SHUFFLE, "xs", WPS_REFRESH_DYNAMIC, + parse_image_display }, + { WPS_TOKEN_IMAGE_ENUM_VOLUME, "xv", WPS_REFRESH_DYNAMIC, + parse_image_display }, + { WPS_TOKEN_IMAGE_DISPLAY, "x", 0, parse_image_load }, { WPS_TOKEN_IMAGE_PROGRESS_BAR, "P", 0, parse_image_special }, + #if (LCD_DEPTH > 1) || (defined(HAVE_LCD_REMOTE) && (LCD_REMOTE_DEPTH > 1)) { WPS_TOKEN_IMAGE_BACKDROP, "X", 0, parse_image_special }, #endif @@ -328,37 +343,6 @@ static int parse_statusbar_disable(const char *wps_bufptr, return skip_end_of_line(wps_bufptr); } -static bool load_bitmap(struct wps_data *wps_data, - char* filename, - struct bitmap *bm) -{ - int format; -#ifdef HAVE_REMOTE_LCD - if (wps_data->remote_wps) - format = FORMAT_ANY|FORMAT_REMOTE; - else -#endif - format = FORMAT_ANY|FORMAT_TRANSPARENT; - - int ret = read_bmp_file(filename, bm, - wps_data->img_buf_free, - format); - - if (ret > 0) - { -#if LCD_DEPTH == 16 - if (ret % 2) ret++; - /* Always consume an even number of bytes */ -#endif - wps_data->img_buf_ptr += ret; - wps_data->img_buf_free -= ret; - - return true; - } - else - return false; -} - static int get_image_id(int c) { if(c >= 'a' && c <= 'z') @@ -394,13 +378,14 @@ static int parse_image_display(const char *wps_bufptr, struct wps_token *token, struct wps_data *wps_data) { + int ret = 0; int n = get_image_id(*wps_bufptr); if (n == -1) { /* invalid picture display tag */ token->type = WPS_TOKEN_UNKNOWN; - return 0; + return ret; } token->value.i = n; @@ -409,7 +394,19 @@ static int parse_image_display(const char *wps_bufptr, if (level >= 0) wps_data->img[n].cond_index = condindex[level]; - return 1; + if (token->type == WPS_TOKEN_IMAGE_ANIMATE) + { + /* Animated image sets can be followed by a timeout time */ + ret = parse_subline_timeout(wps_bufptr + 1, token, wps_data); + if (ret > 0) + wps_data->img[n].subimg_timeout = token->value.i; + else + wps_data->img[n].subimg_timeout = BASE_SUBLINE_TIME; + + token->value.i = n; + } + + return ret + 1; } static int parse_image_load(const char *wps_bufptr, @@ -421,7 +418,7 @@ static int parse_image_load(const char *wps_bufptr, char *pos = NULL; /* format: %x|n|filename.bmp|x|y| - or %xl|n|filename.bmp|x|y| */ + or %xl|n|filename.bmp|x|y|nb_subimg| */ ptr = strchr(ptr, '|') + 1; pos = strchr(ptr, '|'); @@ -469,7 +466,17 @@ static int parse_image_load(const char *wps_bufptr, } if (token->type == WPS_TOKEN_IMAGE_DISPLAY) + { wps_data->img[n].always_display = true; + } + else + { + /* check for number of sub images (optional) */ + ptr = pos + 1; + pos = strchr(ptr, '|'); + if (pos) + wps_data->img[n].nb_subimg = atoi(ptr); + } /* Skip the rest of the line */ return skip_end_of_line(wps_bufptr); @@ -556,18 +563,12 @@ static int parse_progressbar(const char *wps_bufptr, { (void)token; /* Kill warnings */ #ifdef HAVE_LCD_BITMAP - - short *vals[] = { - &wps_data->progress_height, - &wps_data->progress_start, - &wps_data->progress_end, - &wps_data->progress_top }; - - /* default values : */ - wps_data->progress_height = 6; - wps_data->progress_start = 0; - wps_data->progress_end = 0; - wps_data->progress_top = -1; + /* vals[0] = height + vals[1] = start + vals[2] = end + vals[3] = top */ + short vals[4] = {6, 0, 0, -1}; + struct gui_img *pbar = &wps_data->img[PROGRESSBAR_BMP]; int i = 0; char *newline = strchr(wps_bufptr, '\n'); @@ -576,15 +577,23 @@ static int parse_progressbar(const char *wps_bufptr, char *next = strchr(prev+1, '|'); while (i < 4 && next && next < newline) { - *(vals[i++]) = atoi(++prev); + vals[i++] = atoi(++prev); prev = strchr(prev, '|'); next = strchr(++next, '|'); } - if (wps_data->progress_height < 3) - wps_data->progress_height = 3; - if (wps_data->progress_end < wps_data->progress_start + 3) - wps_data->progress_end = 0; + pbar->x = vals[1]; + pbar->y = vals[3]; + + if (vals[0] < 3) + pbar->height = 3; + else + pbar->height = vals[0]; + + if (vals[2] - vals[1] < 3) + pbar->width = 0; + else + pbar->width = vals[2] - vals[1]; } return newline - wps_bufptr; @@ -873,13 +882,12 @@ static void wps_images_clear(struct wps_data *data) { int i; /* set images to unloaded and not displayed */ - for (i = 0; i < MAX_IMAGES; i++) + for (i = 0; i <= MAX_IMAGES; i++) { data->img[i].loaded = false; data->img[i].display = false; data->img[i].always_display = false; } - data->progressbar.have_bitmap_pb = false; } #endif @@ -931,8 +939,15 @@ static void clear_bmp_names(void) static void load_wps_bitmaps(struct wps_data *wps_data, char *bmpdir) { char img_path[MAX_PATH]; - struct bitmap *bitmap; - bool *loaded; + int size; + int format; + +#ifdef HAVE_REMOTE_LCD + if (wps_data->remote_wps) + format = FORMAT_ANY|FORMAT_REMOTE; + else +#endif + format = FORMAT_ANY|FORMAT_TRANSPARENT; int n; for (n = 0; n < BACKDROP_BMP; n++) @@ -942,21 +957,16 @@ static void load_wps_bitmaps(struct wps_data *wps_data, char *bmpdir) get_image_filename(bmp_names[n], bmpdir, img_path, sizeof(img_path)); - if (n == PROGRESSBAR_BMP) { - /* progressbar bitmap */ - bitmap = &wps_data->progressbar.bm; - loaded = &wps_data->progressbar.have_bitmap_pb; - } else { - /* regular bitmap */ - bitmap = &wps_data->img[n].bm; - loaded = &wps_data->img[n].loaded; - } - /* load the image */ - bitmap->data = wps_data->img_buf_ptr; - if (load_bitmap(wps_data, img_path, bitmap)) + size = gui_image_load(img_path, &wps_data->img[n], + wps_data->img_buf_ptr, wps_data->img_buf_free, + format); + + if (size > 0) { - *loaded = true; + wps_data->img[n].loaded = true; + wps_data->img_buf_ptr += size; + wps_data->img_buf_free -= size; } } } diff --git a/apps/main.c b/apps/main.c index 3dfab06..e8a269c 100644 --- a/apps/main.c +++ b/apps/main.c @@ -266,6 +266,7 @@ static void init(void) settings_reset(); settings_load(SETTINGS_ALL); gui_sync_wps_init(); + filetype_init(); settings_apply(); init_dircache(true); init_dircache(false); @@ -274,7 +275,6 @@ static void init(void) #endif sleep(HZ/2); tree_mem_init(); - filetype_init(); playlist_init(); #if CONFIG_CODEC != SWCODEC @@ -488,6 +488,7 @@ static void init(void) } gui_sync_wps_init(); + filetype_init(); settings_apply(); init_dircache(false); #ifdef HAVE_TAGCACHE @@ -505,7 +506,6 @@ static void init(void) status_init(); playlist_init(); tree_mem_init(); - filetype_init(); scrobbler_init(); cuesheet_init();