diff --git a/apps/SOURCES b/apps/SOURCES index ef65789588..f34cac9654 100644 --- a/apps/SOURCES +++ b/apps/SOURCES @@ -58,6 +58,7 @@ recorder/peakmeter.c recorder/widgets.c #ifdef HAVE_LCD_COLOR recorder/backdrop.c +gui/color_picker.c #endif #endif #ifdef CONFIG_TUNER diff --git a/apps/gui/color_picker.c b/apps/gui/color_picker.c new file mode 100644 index 0000000000..2f851d269e --- /dev/null +++ b/apps/gui/color_picker.c @@ -0,0 +1,261 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: + * + * Copyright (C) Jonathan Gordon (2006) + * + * 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 "stdarg.h" +#include "string.h" +#include "stdio.h" +#include "kernel.h" +#include "system.h" +#include "screen_access.h" +#include "debug.h" +#include "misc.h" +#include "settings.h" +#include "scrollbar.h" +#include "lang.h" + +#define TEXT_MARGIN display->char_width+2 +#define SLIDER_START 20 + +#if (CONFIG_KEYPAD == IRIVER_H300_PAD) +#define SLIDER_UP BUTTON_UP +#define SLIDER_DOWN BUTTON_DOWN +#define SLIDER_LEFT BUTTON_LEFT +#define SLIDER_RIGHT BUTTON_RIGHT +#define SLIDER_OK BUTTON_ON +#define SLIDER_CANCEL BUTTON_OFF + +#define SLIDER_RC_UP BUTTON_RC_REW +#define SLIDER_RC_DOWN BUTTON_RC_FF +#define SLIDER_RC_LEFT BUTTON_RC_SOURCE +#define SLIDER_RC_RIGHT BUTTON_RC_BITRATE +#define SLIDER_RC_OK BUTTON_RC_ON +#define SLIDER_RC_CANCEL BUTTON_RC_STOP + +#elif (CONFIG_KEYPAD == IPOD_4G_PAD) +#define SLIDER_UP BUTTON_LEFT +#define SLIDER_DOWN BUTTON_RIGHT +#define SLIDER_LEFT BUTTON_SCROLL_BACK +#define SLIDER_RIGHT BUTTON_SCROLL_FWD +#define SLIDER_OK BUTTON_SELECT +#define SLIDER_CANCEL BUTTON_MENU +#endif + +static const int max_val[3] = {LCD_MAX_RED,LCD_MAX_GREEN,LCD_MAX_BLUE}; + +static void draw_screen(struct screen *display, char *title, + int *rgb_val, int color, int row) +{ + int i; + char *textrgb = str(LANG_COLOR_RGB_LABELS), rgb_dummy[2] = {0,0}; + int text_top; + int text_centre, bg_col; + char buf[32]; + int slider_width = (display->width-SLIDER_START-(display->char_width*5)); + int background_color = global_settings.bg_color; + int text_color = global_settings.fg_color; + + display->clear_display(); + + if (display->depth > 1) { + display->set_foreground(text_color); + } + + i = display->getstringsize(title,0,0); + display->putsxy((display->width-i)/2,6,title ); + + for (i=0;i<3;i++) + { + text_top =display->char_height*((i*2)+2); + + if (i==row) + { + if (global_settings.invert_cursor) + { + display->fillrect(0,text_top-1,display->width,display->char_height+2); + bg_col = text_color; + } + else + { + display->putsxy(0,text_top,">"); + display->putsxy(display->width-TEXT_MARGIN,text_top,"<"); + bg_col = background_color; + } + if (display->depth > 1) + { + if (i==0) + display->set_foreground(LCD_RGBPACK(255, 0, 0)); + else if (i==1) + display->set_foreground(LCD_RGBPACK(0, 255, 0)); + else if (i==2) + display->set_foreground(LCD_RGBPACK(0 ,0 ,255)); + } + } + else + { + if (display->depth > 1) + display->set_foreground(text_color); + bg_col = background_color; + } + + if (display->depth > 1) + display->set_background(bg_col); + + text_centre = text_top+(display->char_height/2); + rgb_dummy[0] = textrgb[i]; + display->putsxy(TEXT_MARGIN,text_top,rgb_dummy); + snprintf(buf,3,"%02d",rgb_val[i]); + display->putsxy(display->width-(display->char_width*4),text_top,buf); + + text_top += display->char_height/4; + + gui_scrollbar_draw(display,SLIDER_START,text_top,slider_width, + display->char_height/2, + max_val[i],0,rgb_val[i],HORIZONTAL); + } + + if (display->depth > 1) { + display->set_background(background_color); + display->set_foreground(text_color); + } + + if (text_top + (display->char_height*2) < (LCD_HEIGHT-40-display->char_height)) + text_top += (display->char_height*2); + else text_top += (display->char_height); + + /* Display RGB: #rrggbb */ + snprintf(buf,sizeof(buf),str(LANG_COLOR_RGB_VALUE), + RGB_UNPACK_RED(color), + RGB_UNPACK_GREEN(color), + RGB_UNPACK_BLUE(color)); + + display->putsxy((LCD_WIDTH-(display->char_width*21))/2,text_top,buf); + + if (display->depth > 1) { + display->set_foreground(color); + display->fillrect(SLIDER_START,LCD_HEIGHT-40,slider_width,35); + + display->set_foreground(LCD_BLACK); + display->drawrect(SLIDER_START-1,LCD_HEIGHT-41,slider_width+2,37); + } + + display->update(); +} + +/*********** + set_color + returns true if USB was inserted, false otherwise + color is a pointer to the colour (in native format) to modify + ***********/ +bool set_color(struct screen *display,char *title, int* color) +{ + int exit = 0, button, slider=0; + int rgb_val[3]; /* native depth r,g,b*/; + int fgcolor = display->get_foreground(); + int newcolor = *color; + int i; + +#if LCD_PIXELFORMAT == RGB565 + rgb_val[0] = ((*color)&0xf800) >> 11; + rgb_val[1] = ((*color)&0x07e0) >> 5; + rgb_val[2] = ((*color)&0x001f); +#elif LCD_PIXELFORMAT == RGB565SWAPPED + rgb_val[0] = ((swap16(*color))&0xf800) >> 11; + rgb_val[1] = ((swap16(*color))&0x07e0) >> 5; + rgb_val[2] = ((swap16(*color))&0x001f); +#endif + + while (!exit) + { + /* We need to maintain three versions of the colour: + + rgb_val[3] - the native depth RGB values + newcolor - the native format packed colour + */ + +#if LCD_PIXELFORMAT == RGB565 + newcolor = (rgb_val[0] << 11) | (rgb_val[1] << 5) | (rgb_val[2]); +#elif LCD_PIXELFORMAT == RGB565SWAPPED + newcolor = swap16((rgb_val[0] << 11) | (rgb_val[1] << 5) | (rgb_val[2])); +#endif + FOR_NB_SCREENS(i) + draw_screen(&screens[i], title, rgb_val, newcolor, slider); + + button = button_get(true); + switch (button) + { + case SLIDER_UP: +#ifdef HAVE_LCD_REMOTE + case SLIDER_RC_UP: +#endif + slider = (slider+2)%3; + break; + + case SLIDER_DOWN: +#ifdef HAVE_LCD_REMOTE + case SLIDER_RC_DOWN: +#endif + slider = (slider+1)%3; + break; + + case SLIDER_RIGHT: + case SLIDER_RIGHT|BUTTON_REPEAT: +#ifdef HAVE_LCD_REMOTE + case SLIDER_RC_RIGHT: + case SLIDER_RC_RIGHT|BUTTON_REPEAT: +#endif + if (rgb_val[slider] < max_val[slider]) + rgb_val[slider]++; + break; + + case SLIDER_LEFT: + case SLIDER_LEFT|BUTTON_REPEAT: +#ifdef HAVE_LCD_REMOTE + case SLIDER_RC_LEFT: + case SLIDER_RC_LEFT|BUTTON_REPEAT: +#endif + if (rgb_val[slider] > 0) + rgb_val[slider]--; + break; + + case SLIDER_OK: +#ifdef HAVE_LCD_REMOTE + case SLIDER_RC_OK: +#endif + *color = newcolor; + exit = 1; + break; + + case SLIDER_CANCEL: +#ifdef HAVE_LCD_REMOTE + case SLIDER_RC_CANCEL: +#endif + exit = 1; + break; + + default: + if(default_event_handler(button) == SYS_USB_CONNECTED) { + display->set_foreground(fgcolor); + return true; + } + break; + } + } + display->set_foreground(fgcolor); + + return false; +} diff --git a/apps/gui/color_picker.h b/apps/gui/color_picker.h new file mode 100644 index 0000000000..1fa35f0c70 --- /dev/null +++ b/apps/gui/color_picker.h @@ -0,0 +1,25 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) Jonathan Gordon (2006) + * + * 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 "screen_access.h" + +#ifdef HAVE_LCD_COLOR /* this file is a bit useless on non color lcds.. */ + +bool set_color(struct screen *display,char *title, int* color); + +#endif diff --git a/apps/gui/splash.h b/apps/gui/splash.h index 9d8def16f8..b1ac15c537 100644 --- a/apps/gui/splash.h +++ b/apps/gui/splash.h @@ -20,6 +20,7 @@ #ifndef _GUI_SPLASH_H_ #define _GUI_SPLASH_H_ #include "screen_access.h" + /* * Puts a splash message on the given screen for a given period * - screen : the screen to put the splash on diff --git a/apps/lang/english.lang b/apps/lang/english.lang index dcb7c07cc6..bd7973ef73 100644 --- a/apps/lang/english.lang +++ b/apps/lang/english.lang @@ -3748,3 +3748,33 @@ desc: in record settings menu. eng: "Main and remote unit" voice: "Main and remote unit" new: + +id: LANG_COLOR_RGB_LABELS +desc: what to show for the 'R' 'G' 'B' ONE LETTER EACH +eng: "RGB" +voice: +new: + +id: LANG_COLOR_RGB_VALUE +desc: in color screen +eng: "RGB: %02X%02X%02X" +voice: +new: + +id: LANG_BACKGROUND_COLOR +desc: menu entry to set the background color +eng: "Background Colour" +voice: +new: + +id: LANG_FOREGROUND_COLOR +desc: menu entry to set the foreground color +eng: "Foreground Colour" +voice: +new: + +id: LANG_RESET_COLORS +desc: menu +eng: "Reset Colours" +voice: +new: diff --git a/apps/plugin.c b/apps/plugin.c index c9fb0ac8f5..61396b4357 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -515,7 +515,12 @@ int plugin_load(const char* plugin, void* parameter) #ifdef HAVE_LCD_BITMAP #if LCD_DEPTH > 1 +#ifdef HAVE_LCD_COLOR + lcd_set_drawinfo(DRMODE_SOLID, global_settings.fg_color, + global_settings.bg_color); +#else lcd_set_drawinfo(DRMODE_SOLID, LCD_DEFAULT_FG, LCD_DEFAULT_BG); +#endif #else /* LCD_DEPTH == 1 */ lcd_set_drawmode(DRMODE_SOLID); #endif /* LCD_DEPTH */ diff --git a/apps/settings.c b/apps/settings.c index 72939e5aac..5a42b17651 100644 --- a/apps/settings.c +++ b/apps/settings.c @@ -89,7 +89,7 @@ const char rec_base_directory[] = REC_BASE_DIR; #include "dsp.h" #endif -#define CONFIG_BLOCK_VERSION 36 +#define CONFIG_BLOCK_VERSION 37 #define CONFIG_BLOCK_SIZE 512 #define RTC_BLOCK_SIZE 44 @@ -122,7 +122,7 @@ struct bit_entry int default_val; /* min 15 bit */ /* variable name in a .cfg file, NULL if not to be saved */ const char* cfg_name; - /* set of values, or NULL for a numerical value */ + /* set of values, "rgb" for a color, or NULL for a numerical value */ const char* cfg_val; }; @@ -545,6 +545,10 @@ static const struct bit_entry hd_bits[] = {2, S_O(cliplight), 0, "cliplight", "off,main,both,remote" }, #endif /* CONFIG_BACKLIGHT */ #endif /*HAVE_RECORDING*/ +#ifdef HAVE_LCD_COLOR + {LCD_DEPTH,S_O(fg_color),LCD_DEFAULT_FG,"foreground color","rgb"}, + {LCD_DEPTH,S_O(bg_color),LCD_DEFAULT_BG,"background color","rgb"}, +#endif /* If values are just added to the end, no need to bump the version. */ /* new stuff to be added at the end */ @@ -596,6 +600,39 @@ static void set_bits( p[long_index] = (p[long_index] & ~mask) | (value << bit_index); } +#ifdef HAVE_LCD_COLOR +/* + * Helper function to convert a string of 6 hex digits to a native colour + */ + +#define hex2dec(c) (((c) >= '0' && ((c) <= '9')) ? (toupper(c)) - '0' : \ + (toupper(c)) - 'A' + 10) + +int hex_to_rgb(const char* hex) +{ int ok = 1; + int i; + int red, green, blue; + + if (strlen(hex) == 6) { + for (i=0; i < 6; i++ ) { + if (!isxdigit(hex[i])) { + ok=0; + break; + } + } + + if (ok) { + red = (hex2dec(hex[0]) << 4) | hex2dec(hex[1]); + green = (hex2dec(hex[2]) << 4) | hex2dec(hex[3]); + blue = (hex2dec(hex[4]) << 4) | hex2dec(hex[5]); + return LCD_RGBPACK(red,green,blue); + } + } + + return 0; +} +#endif + /* * Calculates the checksum for the config block and returns it */ @@ -1013,6 +1050,8 @@ void settings_apply(void) } else { lcd_set_backdrop(NULL); } + screens[SCREEN_MAIN].set_foreground(global_settings.fg_color); + screens[SCREEN_MAIN].set_background(global_settings.bg_color); #endif #if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1) @@ -1225,6 +1264,12 @@ static int load_cfg_table( { /* numerical value, just convert the string */ val = atoi(value); } +#if HAVE_LCD_COLOR + else if (!strncasecmp(p_table[i].cfg_val,"rgb",4)) + { + val = hex_to_rgb(value); + } +#endif else { /* set of string values, find the index */ const char* item; @@ -1410,6 +1455,15 @@ static void save_cfg_table(const struct bit_entry* p_table, int count, int fd) { fdprintf(fd, "%s: %ld\r\n", p_run->cfg_name, value); } +#ifdef HAVE_LCD_COLOR + else if (!strcasecmp(p_run->cfg_val, "rgb")) + { + fdprintf(fd, "%s: %02x%02x%02x\r\n", p_run->cfg_name, + (int)RGB_UNPACK_RED(value), + (int)RGB_UNPACK_GREEN(value), + (int)RGB_UNPACK_BLUE(value)); + } +#endif else /* write as item */ { const char* p = p_run->cfg_val; @@ -1566,6 +1620,9 @@ void settings_reset(void) { global_settings.lang_file[0] = '\0'; #ifdef HAVE_LCD_COLOR global_settings.backdrop_file[0] = '\0'; + + global_settings.fg_color = LCD_DEFAULT_FG; + global_settings.bg_color = LCD_DEFAULT_BG; #endif } diff --git a/apps/settings.h b/apps/settings.h index 753f067234..87020a1094 100644 --- a/apps/settings.h +++ b/apps/settings.h @@ -465,6 +465,10 @@ struct user_settings bool warnon_erase_dynplaylist; /* warn when erasing dynamic playlist */ bool scroll_paginated; /* 0=dont 1=do */ +#ifdef HAVE_LCD_COLOR + int bg_color; /* background color native format */ + int fg_color; /* foreground color native format */ +#endif }; enum optiontype { INT, BOOL }; diff --git a/apps/settings_menu.c b/apps/settings_menu.c index 6ac0b6feb2..d089960e9d 100644 --- a/apps/settings_menu.c +++ b/apps/settings_menu.c @@ -54,6 +54,7 @@ #include "splash.h" #include "yesno.h" #include "list.h" +#include "color_picker.h" #ifdef HAVE_LCD_BITMAP #include "peakmeter.h" @@ -319,6 +320,43 @@ static bool clear_main_backdrop(void) lcd_set_backdrop(NULL); return true; } + +/** + * Menu for fore/back colors + */ +static bool set_fg_color(void) +{ + bool res; + + res = set_color(&screens[SCREEN_MAIN],str(LANG_FOREGROUND_COLOR), + &global_settings.fg_color); + + screens[SCREEN_MAIN].set_foreground(global_settings.fg_color); + + return res; +} + +static bool set_bg_color(void) +{ + bool res; + + res = set_color(&screens[SCREEN_MAIN],str(LANG_BACKGROUND_COLOR), + &global_settings.bg_color); + + screens[SCREEN_MAIN].set_background(global_settings.bg_color); + + return res; +} + +static bool reset_color(void) +{ + global_settings.fg_color = LCD_DEFAULT_FG; + global_settings.bg_color = LCD_DEFAULT_BG; + + screens[SCREEN_MAIN].set_foreground(global_settings.fg_color); + screens[SCREEN_MAIN].set_background(global_settings.bg_color); + return false; +} #endif /** @@ -1586,6 +1624,9 @@ static bool lcd_settings_menu(void) #endif #ifdef HAVE_LCD_COLOR { ID2P(LANG_CLEAR_BACKDROP), clear_main_backdrop }, + { ID2P(LANG_BACKGROUND_COLOR), set_bg_color }, + { ID2P(LANG_FOREGROUND_COLOR), set_fg_color }, + { ID2P(LANG_RESET_COLORS), reset_color }, #endif }; diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h index ba0e216990..6f7fef94ee 100644 --- a/firmware/export/lcd.h +++ b/firmware/export/lcd.h @@ -150,6 +150,9 @@ typedef void lcd_fastpixelfunc_type(fb_data *address); #define LCD_MAX_RED 31 #define LCD_MAX_GREEN 63 #define LCD_MAX_BLUE 31 +#define _RGB_UNPACK_RED(x) ((((x) >> 8) & 0xf8) | ((x) >> 13)) +#define _RGB_UNPACK_GREEN(x) ((((x) >> 3) & 0xfc) | (((x) >> 9) & 0x03)) +#define _RGB_UNPACK_BLUE(x) ((((x) << 3) & 0xf8) | (((x) >> 2) & 0x07)) #define _RGBPACK(r, g, b) ( ((((r) * (31*257) + (127*257)) >> 16) << 11) \ |((((g) * (63*257) + (127*257)) >> 16) << 5) \ | (((b) * (31*257) + (127*257)) >> 16)) @@ -158,8 +161,14 @@ typedef void lcd_fastpixelfunc_type(fb_data *address); #if (LCD_PIXELFORMAT == RGB565SWAPPED) #define LCD_RGBPACK(r, g, b) ( ((_RGBPACK((r), (g), (b)) & 0xff00) >> 8) \ |((_RGBPACK((r), (g), (b)) & 0x00ff) << 8)) +#define RGB_UNPACK_RED(x) _RGB_UNPACK_RED(swap16(x)) +#define RGB_UNPACK_GREEN(x) _RGB_UNPACK_GREEN(swap16(x)) +#define RGB_UNPACK_BLUE(x) _RGB_UNPACK_BLUE(swap16(x)) #else #define LCD_RGBPACK(r, g, b) _RGBPACK((r), (g), (b)) +#define RGB_UNPACK_RED(x) _RGB_UNPACK_RED(x) +#define RGB_UNPACK_GREEN(x) _RGB_UNPACK_GREEN(x) +#define RGB_UNPACK_BLUE(x) _RGB_UNPACK_BLUE(x) #endif #elif LCD_DEPTH == 18 #define LCD_MAX_RED 63