diff options
Diffstat (limited to 'apps/gui')
| -rw-r--r-- | apps/gui/buttonbar.c | 126 | ||||
| -rw-r--r-- | apps/gui/buttonbar.h | 81 | ||||
| -rw-r--r-- | apps/gui/icon.c | 49 | ||||
| -rw-r--r-- | apps/gui/icon.h | 51 | ||||
| -rw-r--r-- | apps/gui/list.c | 499 | ||||
| -rw-r--r-- | apps/gui/list.h | 232 | ||||
| -rw-r--r-- | apps/gui/scrollbar.c | 106 | ||||
| -rw-r--r-- | apps/gui/scrollbar.h | 49 | ||||
| -rw-r--r-- | apps/gui/splash.c | 216 | ||||
| -rw-r--r-- | apps/gui/splash.h | 39 | ||||
| -rw-r--r-- | apps/gui/statusbar.c | 508 | ||||
| -rw-r--r-- | apps/gui/statusbar.h | 107 |
12 files changed, 2063 insertions, 0 deletions
diff --git a/apps/gui/buttonbar.c b/apps/gui/buttonbar.c new file mode 100644 index 0000000..be87b1b --- /dev/null +++ b/apps/gui/buttonbar.c @@ -0,0 +1,126 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) Linus Nielsen Feltzing (2002), Kévin FERRARE (2005) + * + * 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 "config.h" +#include "buttonbar.h" + +#ifdef HAS_BUTTONBAR + +#include "lcd.h" +#include "font.h" +#include "string.h" +#include "settings.h" + +void gui_buttonbar_init(struct gui_buttonbar * buttonbar) +{ + gui_buttonbar_unset(buttonbar); +} + +void gui_buttonbar_set_display(struct gui_buttonbar * buttonbar, + struct screen * display) +{ + buttonbar->display = display; +} + +void gui_buttonbar_draw_button(struct gui_buttonbar * buttonbar, int num) +{ + int xpos, ypos, button_width, text_width; + int fw, fh; + struct screen * display = buttonbar->display; + + display->setfont(FONT_SYSFIXED); + display->getstringsize("M", &fw, &fh); + + button_width = display->width/BUTTONBAR_MAX_BUTTONS; + xpos = num * button_width; + ypos = display->height - fh; + + if(buttonbar->caption[num][0] != 0) + { + /* center the text */ + text_width = fw * strlen(buttonbar->caption[num]); + display->putsxy(xpos + (button_width - text_width)/2, + ypos, buttonbar->caption[num]); + } + + display->set_drawmode(DRMODE_COMPLEMENT); + display->fillrect(xpos, ypos, button_width - 1, fh); + display->set_drawmode(DRMODE_SOLID); + display->setfont(FONT_UI); +} + +void gui_buttonbar_set(struct gui_buttonbar * buttonbar, + const char *caption1, + const char *caption2, + const char *caption3) +{ + gui_buttonbar_unset(buttonbar); + if(caption1) + { + strncpy(buttonbar->caption[0], caption1, 7); + buttonbar->caption[0][7] = 0; + } + if(caption2) + { + strncpy(buttonbar->caption[1], caption2, 7); + buttonbar->caption[1][7] = 0; + } + if(caption3) + { + strncpy(buttonbar->caption[2], caption3, 7); + buttonbar->caption[2][7] = 0; + } +} + +void gui_buttonbar_unset(struct gui_buttonbar * buttonbar) +{ + int i; + for(i = 0;i < BUTTONBAR_MAX_BUTTONS;++i) + buttonbar->caption[i][0] = 0; +} + +void gui_buttonbar_draw(struct gui_buttonbar * buttonbar) +{ + struct screen * display = buttonbar->display; + int i; + + display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); + display->fillrect(0, display->height - BUTTONBAR_HEIGHT, + display->width, BUTTONBAR_HEIGHT); + display->set_drawmode(DRMODE_SOLID); + + for(i = 0;i < BUTTONBAR_MAX_BUTTONS;++i) + gui_buttonbar_draw_button(buttonbar, i); + display->update_rect(0, display->height - BUTTONBAR_HEIGHT, + display->width, BUTTONBAR_HEIGHT); +} + +bool gui_buttonbar_isset(struct gui_buttonbar * buttonbar) +{ + /* If all buttons are unset, the button bar is considered disabled */ + if(!global_settings.buttonbar) + return(false); + int i; + for(i = 0;i < BUTTONBAR_MAX_BUTTONS;++i) + if(buttonbar->caption[i] != 0) + return true; + return false; +} + +#endif /* HAS_BUTTONBAR */ diff --git a/apps/gui/buttonbar.h b/apps/gui/buttonbar.h new file mode 100644 index 0000000..ee7b8d0 --- /dev/null +++ b/apps/gui/buttonbar.h @@ -0,0 +1,81 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2005 by Kévin FERRARE + * + * 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_BUTTONBAR_H_ +#define _GUI_BUTTONBAR_H_ +#include "config.h" +#include "button.h" +#if CONFIG_KEYPAD == RECORDER_PAD + +#define HAS_BUTTONBAR +#define BUTTONBAR_HEIGHT 8 +#define BUTTONBAR_MAX_BUTTONS 3 +#define BUTTONBAR_CAPTION_LENGTH 8 +#include "screen_access.h" + +struct gui_buttonbar +{ + char caption[BUTTONBAR_MAX_BUTTONS][BUTTONBAR_CAPTION_LENGTH]; + struct screen * display; +}; + +/* + * Initializes the buttonbar + * - buttonbar : the buttonbar + */ +extern void gui_buttonbar_init(struct gui_buttonbar * buttonbar); + +/* + * Attach the buttonbar to a screen + * - buttonbar : the buttonbar + * - display : the display to attach the buttonbar + */ +extern void gui_buttonbar_set_display(struct gui_buttonbar * buttonbar, + struct screen * display); + +/* + * Set the caption of the items of the buttonbar + * - buttonbar : the buttonbar + * - caption1,2,3 : the first, second and thirds items of the bar + */ +extern void gui_buttonbar_set(struct gui_buttonbar * buttonbar, + const char *caption1, + const char *caption2, + const char *caption3); + +/* + * Disable the buttonbar + * - buttonbar : the buttonbar + */ +extern void gui_buttonbar_unset(struct gui_buttonbar * buttonbar); + +/* + * Draw the buttonbar on it's attached screen + * - buttonbar : the buttonbar + */ +extern void gui_buttonbar_draw(struct gui_buttonbar * buttonbar); + +/* + * Returns true if the buttonbar has something to display, false otherwise + * - buttonbar : the buttonbar + */ +extern bool gui_buttonbar_isset(struct gui_buttonbar * buttonbar); + +#endif /* CONFIG_KEYPAD == RECORDER_PAD */ +#endif /* _GUI_BUTTONBAR_H_ */ diff --git a/apps/gui/icon.c b/apps/gui/icon.c new file mode 100644 index 0000000..4d174d3 --- /dev/null +++ b/apps/gui/icon.c @@ -0,0 +1,49 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) Robert E. Hak(2002), Kévin FERRARE (2005) + * + * 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 "config.h" +#include "icon.h" +#include "screen_access.h" +#include "icons.h" + +/* Count in letter positions, NOT pixels */ +void screen_put_iconxy(struct screen * display, int x, int y, ICON icon) +{ +#ifdef HAVE_LCD_BITMAP + if(icon==0)/* Don't display invalid icons */ + return; + int xpos, ypos; + xpos = x*CURSOR_WIDTH; + ypos = y*display->char_height + display->getymargin(); + if ( display->char_height > CURSOR_HEIGHT )/* center the cursor */ + ypos += (display->char_height - CURSOR_HEIGHT) / 2; + display->mono_bitmap(icon, xpos, ypos, CURSOR_WIDTH, CURSOR_HEIGHT); +#else + display->putc(x, y, icon); +#endif +} + +void screen_put_cursorxy(struct screen * display, int x, int y) +{ +#ifdef HAVE_LCD_BITMAP + screen_put_iconxy(display, x, y, bitmap_icons_6x8[Icon_Cursor]); +#else + screen_put_iconxy(display, x, y, CURSOR_CHAR); +#endif +} diff --git a/apps/gui/icon.h b/apps/gui/icon.h new file mode 100644 index 0000000..46faf09 --- /dev/null +++ b/apps/gui/icon.h @@ -0,0 +1,51 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2005 by Kévin FERRARE + * + * 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_ICON_H_ +#define _GUI_ICON_H_ +#include "lcd.h" +#include "screen_access.h" +/* Defines a type for the icons since it's not the same thing on + * char-based displays and bitmap displays */ +#ifdef HAVE_LCD_BITMAP + #define ICON const unsigned char * +#else + #define ICON unsigned short +#endif + +#define CURSOR_CHAR 0x92 +#define CURSOR_WIDTH 6 +#define CURSOR_HEIGHT 8 +/* + * Draws a cursor at a given position + * - screen : the screen where we put the cursor + * - x, y : the position, in character, not in pixel !! + */ +extern void screen_put_cursorxy(struct screen * screen, int x, int y); + +/* + * Put an icon on a screen at a given position + * (the position is given in characters) + * - screen : the screen where we put our icon + * - x, y : the position, in character, not in pixel !! + * - icon : the icon to put + */ +extern void screen_put_iconxy(struct screen * screen, int x, int y, ICON icon); + +#endif /*_GUI_ICON_H_*/ diff --git a/apps/gui/list.c b/apps/gui/list.c new file mode 100644 index 0000000..bb3eb7c --- /dev/null +++ b/apps/gui/list.c @@ -0,0 +1,499 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2005 by Kévin FERRARE + * + * 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 "config.h" +#include "lcd.h" +#include "font.h" +#include "button.h" +#include "sprintf.h" +#include "settings.h" +#include "kernel.h" + +#include "screen_access.h" +#include "list.h" +#include "scrollbar.h" +#include "statusbar.h" + +#ifdef HAVE_LCD_CHARCELLS +#define SCROLL_LIMIT 1 +#else +#define SCROLL_LIMIT 2 +#endif + + + +void gui_list_init(struct gui_list * gui_list, + void (*callback_get_item_icon)(int selected_item, ICON * icon), + char * (*callback_get_item_name)(int selected_item, char *buffer)) +{ + gui_list->callback_get_item_icon = callback_get_item_icon; + gui_list->callback_get_item_name = callback_get_item_name; + gui_list->display = NULL; + gui_list_set_nb_items(gui_list, 0); + gui_list->selected_item = 0; + gui_list->start_item = 0; +} + +void gui_list_set_nb_items(struct gui_list * gui_list, int nb_items) +{ + gui_list->nb_items = nb_items; +} + +void gui_list_set_display(struct gui_list * gui_list, struct screen * display) +{ + if(gui_list->display != 0) /* we switched from a previous display */ + gui_list->display->stop_scroll(); + gui_list->display = display; +#ifdef HAVE_LCD_CHARCELLS + display->double_height(false); +#endif + gui_list_put_selection_in_screen(gui_list, false); +} + +void gui_list_put_selection_in_screen(struct gui_list * gui_list, + bool put_from_end) +{ + struct screen * display = gui_list->display; + if(put_from_end) + { + int list_end = gui_list->selected_item + SCROLL_LIMIT - 1; + if(list_end > gui_list->nb_items) + list_end = gui_list->nb_items; + gui_list->start_item = list_end - display->nb_lines; + } + else + { + int list_start = gui_list->selected_item - SCROLL_LIMIT + 1; + if(list_start + display->nb_lines > gui_list->nb_items) + list_start = gui_list->nb_items - display->nb_lines; + gui_list->start_item = list_start; + } + if(gui_list->start_item < 0) + gui_list->start_item = 0; +} + +void gui_list_get_selected_item_name(struct gui_list * gui_list, char *buffer) +{ + gui_list->callback_get_item_name(gui_list->selected_item, buffer); +} + +int gui_list_get_selected_item_position(struct gui_list * gui_list) +{ + return gui_list->selected_item; +} + +void gui_list_draw(struct gui_list * gui_list) +{ + struct screen * display=gui_list->display; + int cursor_pos = 0; + int icon_pos = 1; + int text_pos; + bool draw_icons = (gui_list->callback_get_item_icon != NULL && + global_settings.show_icons) ; + bool draw_cursor; + int i; + + /* Adjust the position of icon, cursor, text */ +#ifdef HAVE_LCD_BITMAP + bool draw_scrollbar = (global_settings.scrollbar && + display->nb_lines < gui_list->nb_items); + + int list_y_start = screen_get_text_y_start(gui_list->display); + int list_y_end = screen_get_text_y_end(gui_list->display); + + draw_cursor = !global_settings.invert_cursor; + text_pos = 0; /* here it's in pixels */ + if(draw_scrollbar) + { + ++cursor_pos; + ++icon_pos; + text_pos += SCROLLBAR_WIDTH; + } + if(!draw_cursor) + { + --icon_pos; + } + else + text_pos += CURSOR_WIDTH; + + if(draw_icons) + text_pos += 8; +#else + draw_cursor = true; + if(draw_icons) + text_pos = 2; /* here it's in chars */ + else + text_pos = 1; +#endif + /* The drawing part */ +#ifdef HAVE_LCD_BITMAP + /* clear the drawing area */ + display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); + display->fillrect(0, list_y_start, + display->width, list_y_end - list_y_start); + display->set_drawmode(DRMODE_SOLID); + + /* FIXME: should not be handled here, but rather in the + * code that changes fonts */ + screen_update_nblines(display); + + display->stop_scroll(); + display->setmargins(text_pos, list_y_start); +#else + display->clear_display(); +#endif + + for(i = 0;i < display->nb_lines;++i) + { + char entry_buffer[MAX_PATH]; + char * entry_name; + int current_item = gui_list->start_item + i; + + /* When there are less items to display than the + * current available space on the screen, we stop*/ + if(current_item >= gui_list->nb_items) + break; + entry_name = gui_list->callback_get_item_name(current_item, + entry_buffer); + if(current_item == gui_list->selected_item) + { + /* The selected item must be displayed scrolling */ +#ifdef HAVE_LCD_BITMAP + if (global_settings.invert_cursor)/* Display inverted-line-style*/ + display->puts_scroll_style(0, i, entry_name, STYLE_INVERT); + else + display->puts_scroll(0, i, entry_name); +#else + display->puts_scroll(text_pos, i, entry_name); +#endif + + if(draw_cursor) + screen_put_cursorxy(display, cursor_pos, i); + } + else + {/* normal item */ +#ifdef HAVE_LCD_BITMAP + display->puts(0, i, entry_name); +#else + display->puts(text_pos, i, entry_name); +#endif + } + /* Icons display */ + if(draw_icons) + { + ICON icon; + gui_list->callback_get_item_icon(current_item, &icon); + screen_put_iconxy(display, icon_pos, i, icon); + } + } +#ifdef HAVE_LCD_BITMAP + /* Draw the scrollbar if needed*/ + if(draw_scrollbar) + { + int scrollbar_y_end = display->char_height * + display->nb_lines + list_y_start; + gui_scrollbar_draw(display, 0, list_y_start, SCROLLBAR_WIDTH-1, + scrollbar_y_end - list_y_start, gui_list->nb_items, + gui_list->start_item, + gui_list->start_item + display->nb_lines, VERTICAL); + } + display->update_rect(0, list_y_start, display->width, + list_y_end - list_y_start); +#else +#ifdef SIMULATOR + display->update(); +#endif +#endif +} + +void gui_list_select_item(struct gui_list * gui_list, int item_number) +{ + if( item_number > gui_list->nb_items-1 || item_number < 0 ) + return; + gui_list->selected_item = item_number; + gui_list_put_selection_in_screen(gui_list, false); +} + +void gui_list_select_next(struct gui_list * gui_list) +{ + int item_pos; + int end_item; + int nb_lines = gui_list->display->nb_lines; + + ++gui_list->selected_item; + + if( gui_list->selected_item >= gui_list->nb_items ) + { + /* we have already reached the bottom of the list */ + gui_list->selected_item = 0; + gui_list->start_item = 0; + } + else + { + item_pos = gui_list->selected_item - gui_list->start_item; + end_item = gui_list->start_item + nb_lines; + /* we start scrolling vertically when reaching the line + * (nb_lines-SCROLL_LIMIT) + * and when we are not in the last part of the list*/ + if( item_pos > nb_lines-SCROLL_LIMIT && end_item < gui_list->nb_items ) + ++gui_list->start_item; + } +} + +void gui_list_select_previous(struct gui_list * gui_list) +{ + int item_pos; + int nb_lines = gui_list->display->nb_lines; + + --gui_list->selected_item; + if( gui_list->selected_item < 0 ) + { + /* we have aleady reached the top of the list */ + int start; + gui_list->selected_item = gui_list->nb_items-1; + start = gui_list->nb_items-nb_lines; + if( start < 0 ) + gui_list->start_item = 0; + else + gui_list->start_item = start; + } + else + { + item_pos = gui_list->selected_item - gui_list->start_item; + if( item_pos < SCROLL_LIMIT-1 && gui_list->start_item > 0 ) + --gui_list->start_item; + } +} + +void gui_list_select_next_page(struct gui_list * gui_list, int nb_lines) +{ + if(gui_list->selected_item == gui_list->nb_items-1) + gui_list->selected_item = 0; + else + { + gui_list->selected_item += nb_lines; + if(gui_list->selected_item > gui_list->nb_items-1) + gui_list->selected_item = gui_list->nb_items-1; + } + gui_list_put_selection_in_screen(gui_list, true); +} + +void gui_list_select_previous_page(struct gui_list * gui_list, int nb_lines) +{ + if(gui_list->selected_item == 0) + gui_list->selected_item = gui_list->nb_items - 1; + else + { + gui_list->selected_item -= nb_lines; + if(gui_list->selected_item < 0) + gui_list->selected_item = 0; + } + gui_list_put_selection_in_screen(gui_list, false); +} + +void gui_list_add_item(struct gui_list * gui_list) +{ + ++gui_list->nb_items; + /* if only one item in the list, select it */ + if(gui_list->nb_items == 1) + gui_list->selected_item = 0; +} + +void gui_list_del_item(struct gui_list * gui_list) +{ + int nb_lines = gui_list->display->nb_lines; + + if(gui_list->nb_items > 0) + { + int dist_selected_from_end = gui_list->nb_items + - gui_list->selected_item - 1; + int dist_start_from_end = gui_list->nb_items + - gui_list->start_item - 1; + if(dist_selected_from_end == 0) + { + /* Oops we are removing the selected item, + select the previous one */ + --gui_list->selected_item; + } + --gui_list->nb_items; + + /* scroll the list if needed */ + if( (dist_start_from_end < nb_lines) && (gui_list->start_item != 0) ) + --gui_list->start_item; + } +} + +/* + * Synchronized lists stuffs + */ +void gui_synclist_init( + struct gui_synclist * lists, + void (*callback_get_item_icon)(int selected_item, ICON * icon), + char * (*callback_get_item_name)(int selected_item, char *buffer) + ) +{ + int i; + for(i = 0;i < NB_SCREENS;i++) + { + gui_list_init(&(lists->gui_list[i]), callback_get_item_icon, + callback_get_item_name); + gui_list_set_display(&(lists->gui_list[i]), &(screens[i])); + } +} + +void gui_synclist_set_nb_items(struct gui_synclist * lists, int nb_items) +{ + int i; + for(i = 0;i < NB_SCREENS;i++) + { + gui_list_set_nb_items(&(lists->gui_list[i]), nb_items); + } +} + +void gui_synclist_get_selected_item_name(struct gui_synclist * lists, + char *buffer) +{ + gui_list_get_selected_item_name(&(lists->gui_list[0]), buffer); +} + +int gui_synclist_get_selected_item_position(struct gui_synclist * lists) +{ + return gui_list_get_selected_item_position(&(lists->gui_list[0])); +} + +void gui_synclist_draw(struct gui_synclist * lists) +{ + int i; + for(i = 0;i < NB_SCREENS;i++) + gui_list_draw(&(lists->gui_list[i])); +} + +void gui_synclist_select_item(struct gui_synclist * lists, int item_number) +{ + int i; + for(i = 0;i < NB_SCREENS;i++) + gui_list_select_item(&(lists->gui_list[i]), item_number); +} + +void gui_synclist_select_next(struct gui_synclist * lists) +{ + int i; + for(i = 0;i < NB_SCREENS;i++) + gui_list_select_next(&(lists->gui_list[i])); +} + +void gui_synclist_select_previous(struct gui_synclist * lists) +{ + int i; + for(i = 0;i < NB_SCREENS;i++) + gui_list_select_previous(&(lists->gui_list[i])); +} + +void gui_synclist_select_next_page(struct gui_synclist * lists, + enum screen_type screen) +{ + int i; + for(i = 0;i < NB_SCREENS;i++) + gui_list_select_next_page(&(lists->gui_list[i]), + screens[screen].nb_lines); +} + +void gui_synclist_select_previous_page(struct gui_synclist * lists, + enum screen_type screen) +{ + int i; + for(i = 0;i < NB_SCREENS;i++) + gui_list_select_previous_page(&(lists->gui_list[i]), + screens[screen].nb_lines); +} + +void gui_synclist_add_item(struct gui_synclist * lists) +{ + int i; + for(i = 0;i < NB_SCREENS;i++) + gui_list_add_item(&(lists->gui_list[i])); +} + +void gui_synclist_del_item(struct gui_synclist * lists) +{ + int i; + for(i = 0;i < NB_SCREENS;i++) + gui_list_del_item(&(lists->gui_list[i])); +} + +bool gui_synclist_do_button(struct gui_synclist * lists, unsigned button) +{ + switch(button) + { + case LIST_PREV: + case LIST_PREV | BUTTON_REPEAT: +#ifdef LIST_RC_PREV + case LIST_RC_PREV: + case LIST_RC_PREV | BUTTON_REPEAT: +#endif + gui_synclist_select_previous(lists); + gui_synclist_draw(lists); + return true; + + case LIST_NEXT: + case LIST_NEXT | BUTTON_REPEAT: +#ifdef LIST_RC_NEXT + case LIST_RC_NEXT: + case LIST_RC_NEXT | BUTTON_REPEAT: +#endif + gui_synclist_select_next(lists); + gui_synclist_draw(lists); + return true; +/* for pgup / pgdown, we are obliged to have a different behaviour depending on the screen + * for which the user pressed the key since for example, remote and main screen doesn't + * have the same number of lines*/ +#ifdef LIST_PGUP + case LIST_PGUP: + case LIST_PGUP | BUTTON_REPEAT: + gui_synclist_select_previous_page(lists, SCREEN_MAIN); + gui_synclist_draw(lists); + return true; +#endif + +#ifdef LIST_RC_PGUP + case LIST_RC_PGUP: + case LIST_RC_PGUP | BUTTON_REPEAT: + gui_synclist_select_previous_page(lists, SCREEN_REMOTE); + gui_synclist_draw(lists); + return true; +#endif + +#ifdef LIST_PGDN + case LIST_PGDN: + case LIST_PGDN | BUTTON_REPEAT: + gui_synclist_select_next_page(lists, SCREEN_MAIN); + gui_synclist_draw(lists); + return true; +#endif + +#ifdef LIST_RC_PGDN + case LIST_RC_PGDN: + case LIST_RC_PGDN | BUTTON_REPEAT: + gui_synclist_select_next_page(lists, SCREEN_REMOTE); + gui_synclist_draw(lists); + return true; +#endif + } + return false; +} diff --git a/apps/gui/list.h b/apps/gui/list.h new file mode 100644 index 0000000..fd553f3 --- /dev/null +++ b/apps/gui/list.h @@ -0,0 +1,232 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2005 by Kévin FERRARE + * + * 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_LIST_H_ +#define _GUI_LIST_H_ + +#include "config.h" +#include "icon.h" +#include "screen_access.h" + +#define SCROLLBAR_WIDTH 6 + +/* Key assignement */ +#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ + (CONFIG_KEYPAD == IRIVER_H300_PAD) +#define LIST_NEXT BUTTON_DOWN +#define LIST_PREV BUTTON_UP +#define LIST_PGUP (BUTTON_ON | BUTTON_UP) +#define LIST_PGDN (BUTTON_ON | BUTTON_DOWN) +#define LIST_RC_NEXT BUTTON_RC_FF +#define LIST_RC_PREV BUTTON_RC_REW +#define LIST_RC_PGUP BUTTON_RC_SOURCE +#define LIST_RC_PGDN BUTTON_RC_BITRATE + +#elif CONFIG_KEYPAD == RECORDER_PAD +#define LIST_NEXT BUTTON_DOWN +#define LIST_PREV BUTTON_UP +#define LIST_PGUP (BUTTON_ON | BUTTON_UP) +#define LIST_PGDN (BUTTON_ON | BUTTON_DOWN) +#define LIST_RC_NEXT BUTTON_RC_RIGHT +#define LIST_RC_PREV BUTTON_RC_LEFT + +#elif CONFIG_KEYPAD == PLAYER_PAD +#define LIST_NEXT BUTTON_RIGHT +#define LIST_PREV BUTTON_LEFT +#define LIST_RC_NEXT BUTTON_RC_RIGHT +#define LIST_RC_PREV BUTTON_RC_LEFT + +#elif CONFIG_KEYPAD == ONDIO_PAD +#define LIST_NEXT BUTTON_DOWN +#define LIST_PREV BUTTON_UP + +#elif CONFIG_KEYPAD == GMINI100_PAD +#define LIST_NEXT BUTTON_DOWN +#define LIST_PREV BUTTON_UP +#define LIST_PGUP (BUTTON_ON | BUTTON_UP) +#define LIST_PGDN (BUTTON_ON | BUTTON_DOWN) +#endif + + +struct gui_list +{ + int nb_items; + int selected_item; + int start_item; /* the item that is displayed at the top of the screen */ + + void (*callback_get_item_icon)(int selected_item, ICON * icon); + char * (*callback_get_item_name)(int selected_item, char *buffer); + + struct screen * display; + int line_scroll_limit; +}; + +/* + * Initializes a scrolling list + * - gui_list : the list structure to initialize + * - callback_get_item_icon : pointer to a function that associates an icon + * to a given item number + * - callback_get_item_name : pointer to a function that associates a label + * to a given item number + */ +extern void gui_list_init(struct gui_list * gui_list, + void (*callback_get_item_icon)(int selected_item, ICON * icon), + char * (*callback_get_item_name)(int selected_item, char *buffer) + ); + +/* + * Sets the numburs of items the list can currently display + * note that the list's context like the currently pointed item is resetted + * - gui_list : the list structure to initialize + * - nb_items : the numbers of items you want + */ +extern void gui_list_set_nb_items(struct gui_list * gui_list, int nb_items); + +/* + * Puts the selection in the screen + * - gui_list : the list structure + * - put_from_end : if true, selection will be put as close from + * the end of the list as possible, else, it's + * from the beginning + */ +extern void gui_list_put_selection_in_screen(struct gui_list * gui_list, + bool put_from_end); + +/* + * Attach the scrolling list to a screen + * (The previous screen attachement is lost) + * - gui_list : the list structure + * - display : the screen to attach + */ +extern void gui_list_set_display(struct gui_list * gui_list, + struct screen * display); + +/* + * Gives the name of the selected object + * - gui_list : the list structure + * - buffer : a buffer which is filled with the name + */ +extern void gui_list_get_selected_item_name(struct gui_list * gui_list, + char *buffer); + +/* + * Gives the position of the selected item + * - gui_list : the list structure + * Returns the position + */ +extern int gui_list_get_selected_item_position(struct gui_list * gui_list); + +/* + * Selects an item in the list + * - gui_list : the list structure + * - item_number : the number of the item which will be selected + */ +extern void gui_list_select_item(struct gui_list * gui_list, int item_number); + +/* + * Draws the list on the attached screen + * - gui_list : the list structure + */ +extern void gui_list_draw(struct gui_list * gui_list); + +/* + * Selects the next item in the list + * (Item 0 gets selected if the end of the list is reached) + * - gui_list : the list structure + */ +extern void gui_list_select_next(struct gui_list * gui_list); + +/* + * Selects the previous item in the list + * (Last item in the list gets selected if the list beginning is reached) + * - gui_list : the list structure + */ +extern void gui_list_select_previous(struct gui_list * gui_list); + +/* + * Go to next page if any, else selects the last item in the list + * - gui_list : the list structure + * - nb_lines : the number of lines to try to move the cursor + */ +extern void gui_list_select_next_page(struct gui_list * gui_list, + int nb_lines); + +/* + * Go to previous page if any, else selects the first item in the list + * - gui_list : the list structure + * - nb_lines : the number of lines to try to move the cursor + */ +extern void gui_list_select_previous_page(struct gui_list * gui_list, + int nb_lines); + +/* + * Adds an item to the list (the callback will be asked for one more item) + * - gui_list : the list structure + */ +extern void gui_list_add_item(struct gui_list * gui_list); + +/* + * Removes an item to the list (the callback will be asked for one less item) + * - gui_list : the list structure + */ +extern void gui_list_del_item(struct gui_list * gui_list); + + +/* + * This part handles as many lists as there are connected screens + * (the api is similar to the ones above) + * The lists on the screens are synchronized ; + * theirs items and selected items are the same, but of course, + * they can be displayed on screens with different sizes + * The final aim is to let the programmer handle many lists in one + * function call and make its code independant from the number of screens + */ +struct gui_synclist +{ + struct gui_list gui_list[NB_SCREENS]; +}; + +extern void gui_synclist_init(struct gui_synclist * lists, + void (*callback_get_item_icon)(int selected_item, ICON * icon), + char * (*callback_get_item_name)(int selected_item, char *buffer) + ); +extern void gui_synclist_set_nb_items(struct gui_synclist * lists, int nb_items); +extern void gui_synclist_get_selected_item_name(struct gui_synclist * lists, + char *buffer); +extern int gui_synclist_get_selected_item_position(struct gui_synclist * lists); +extern void gui_synclist_draw(struct gui_synclist * lists); +extern void gui_synclist_select_item(struct gui_synclist * lists, + int item_number); +extern void gui_synclist_select_next(struct gui_synclist * lists); +extern void gui_synclist_select_previous(struct gui_synclist * lists); +extern void gui_synclist_select_next_page(struct gui_synclist * lists, + enum screen_type screen); +extern void gui_synclist_select_previous_page(struct gui_synclist * lists, + enum screen_type screen); +extern void gui_synclist_add_item(struct gui_synclist * lists); +extern void gui_synclist_del_item(struct gui_synclist * lists); +/* + * Do the action implied by the given button, + * returns true if something has been done, false otherwise + * - lists : the synchronized lists + * - button : the keycode of a pressed button + */ +extern bool gui_synclist_do_button(struct gui_synclist * lists, unsigned button); + +#endif /* _GUI_LIST_H_ */ diff --git a/apps/gui/scrollbar.c b/apps/gui/scrollbar.c new file mode 100644 index 0000000..9d5717f --- /dev/null +++ b/apps/gui/scrollbar.c @@ -0,0 +1,106 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) Markus Braun (2002), Kévin FERRARE (2005) + * + * 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 "config.h" +#include "lcd.h" +#ifdef HAVE_LCD_BITMAP +#include "limits.h" +#include "scrollbar.h" +#include "screen_access.h" + +void gui_scrollbar_draw(struct screen * screen, int x, int y, + int width, int height, int items, + int min_shown, int max_shown, + enum orientation orientation) +{ + int min; + int max; + int inner_len; + int start; + int size; + + /* draw box */ + screen->drawrect(x, y, width, height); + + screen->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); + + /* clear edge pixels */ + screen->drawpixel(x, y); + screen->drawpixel((x + width - 1), y); + screen->drawpixel(x, (y + height - 1)); + screen->drawpixel((x + width - 1), (y + height - 1)); + + /* clear pixels in progress bar */ + screen->fillrect(x + 1, y + 1, width - 2, height - 2); + + /* min should be min */ + if(min_shown < max_shown) { + min = min_shown; + max = max_shown; + } + else { + min = max_shown; + max = min_shown; + } + + /* limit min and max */ + if(min < 0) + min = 0; + if(min > items) + min = items; + + if(max < 0) + max = 0; + if(max > items) + max = items; + + if (orientation == VERTICAL) + inner_len = height - 2; + else + inner_len = width - 2; + + /* avoid overflows */ + while (items > (INT_MAX / inner_len)) { + items >>= 1; + min >>= 1; + max >>= 1; + } + + /* calc start and end of the knob */ + if (items > 0 && items > (max - min)) { + size = inner_len * (max - min) / items; + if (size == 0) { /* width of knob is null */ + size = 1; + start = (inner_len - 1) * min / items; + } else { + start = (inner_len - size) * min / (items - (max - min)); + } + } else { /* if null draw full bar */ + size = inner_len; + start = 0; + } + + screen->set_drawmode(DRMODE_SOLID); + + if(orientation == VERTICAL) + screen->fillrect(x + 1, y + start + 1, width - 2, size); + else + screen->fillrect(x + start + 1, y + 1, size, height - 2); +} +#endif /* HAVE_LCD_BITMAP */ diff --git a/apps/gui/scrollbar.h b/apps/gui/scrollbar.h new file mode 100644 index 0000000..51c0835 --- /dev/null +++ b/apps/gui/scrollbar.h @@ -0,0 +1,49 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2005 Kévin FERRARE + * + * 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_SCROLLBAR_H_ +#define _GUI_SCROLLBAR_H_ +#include <lcd.h> +#ifdef HAVE_LCD_BITMAP + +struct screen; + +enum orientation { + VERTICAL, + HORIZONTAL +}; + +/* + * Draws a scrollbar on the given screen + * - screen : the screen to put the scrollbar on + * - x : x start position of the scrollbar + * - y : y start position of the scrollbar + * - width : you won't guess =(^o^)= + * - height : I won't tell you either ! + * - items : total number of items on the screen + * - min_shown : index of the starting item on the screen + * - max_shown : index of the last item on the screen + * - orientation : either VERTICAL or HORIZONTAL + */ +extern void gui_scrollbar_draw(struct screen * screen, int x, int y, + int width, int height, int items, + int min_shown, int max_shown, + enum orientation orientation); +#endif /* HAVE_LCD_BITMAP */ +#endif /* _GUI_SCROLLBAR_H_ */ diff --git a/apps/gui/splash.c b/apps/gui/splash.c new file mode 100644 index 0000000..a3cbb19 --- /dev/null +++ b/apps/gui/splash.c @@ -0,0 +1,216 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) Daniel Stenberg (2002), Kévin FERRARE (2005) + * + * 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 "screen_access.h" + + +#ifdef HAVE_LCD_BITMAP + +#define SPACE 3 /* pixels between words */ +#define MAXLETTERS 128 /* 16*8 */ +#define MAXLINES 10 + +#else + +#define SPACE 1 /* one letter space */ +#define MAXLETTERS 22 /* 11 * 2 */ +#define MAXLINES 2 + +#endif + + +void internal_splash(struct screen * screen, + bool center, const char *fmt, va_list ap) +{ + char *next; + char *store=NULL; + int x=0; + int y=0; + int w, h; + unsigned char splash_buf[MAXLETTERS]; + unsigned char widths[MAXLINES]; + int line=0; + bool first=true; +#ifdef HAVE_LCD_BITMAP + int maxw=0; +#endif + +#ifdef HAVE_LCD_CHARCELLS + screen->double_height (false); +#endif + vsnprintf( splash_buf, sizeof(splash_buf), fmt, ap ); + + if(center) { + /* first a pass to measure sizes */ + next = strtok_r(splash_buf, " ", &store); + while (next) { +#ifdef HAVE_LCD_BITMAP + screen->getstringsize(next, &w, &h); +#else + w = strlen(next); + h = 1; /* store height in characters */ +#endif + if(!first) { + if(x+w> screen->width) { + /* Too wide, wrap */ + y+=h; + line++; + if((y > (screen->height-h)) || (line > screen->nb_lines)) + /* STOP */ + break; + x=0; + first=true; + } + } + else + first = false; + + /* think of it as if the text was written here at position x,y + being w pixels/chars wide and h high */ + + x += w+SPACE; + widths[line]=x-SPACE; /* don't count the trailing space */ +#ifdef HAVE_LCD_BITMAP + /* store the widest line */ + if(widths[line]>maxw) + maxw = widths[line]; +#endif + next = strtok_r(NULL, " ", &store); + } + +#ifdef HAVE_LCD_BITMAP + /* Start displaying the message at position y. The reason for the + added h here is that it isn't added until the end of lines in the + loop above and we always break the loop in the middle of a line. */ + y = (screen->height - (y+h) )/2; +#else + y = 0; /* vertical center on 2 lines would be silly */ +#endif + first=true; + + /* Now recreate the string again since the strtok_r() above has ruined + the one we already have! Here's room for improvements! */ + vsnprintf( splash_buf, sizeof(splash_buf), fmt, ap ); + } + va_end( ap ); + + if(center) + { + x = (screen->width-widths[0])/2; + if(x < 0) + x = 0; + } + +#ifdef HAVE_LCD_BITMAP + /* If we center the display, then just clear the box we need and put + a nice little frame and put the text in there! */ + if(center && (y > 2)) { + int xx = (screen->width-maxw)/2 - 2; + /* The new graphics routines handle clipping, so no need to check */ +#if LCD_DEPTH > 1 +#ifdef HAVE_LCD_COLOR + screen->set_background((struct rgb){LCD_MAX_RED-1, LCD_MAX_GREEN-1, + LCD_MAX_BLUE-1}); +#else + if(screen->depth>1) + screen->set_background(LCD_MAX_LEVEL-1); +#endif +#endif + screen->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); + screen->fillrect(xx, y-2, maxw+4, screen->height-y*2+4); + screen->set_drawmode(DRMODE_SOLID); + screen->drawrect(xx, y-2, maxw+4, screen->height-y*2+4); + } + else +#endif + screen->clear_display(); + line=0; + next = strtok_r(splash_buf, " ", &store); + while (next) { +#ifdef HAVE_LCD_BITMAP + screen->getstringsize(next, &w, &h); +#else + w = strlen(next); + h = 1; +#endif + if(!first) { + if(x+w> screen->width) { + /* too wide */ + y+=h; + line++; /* goto next line */ + first=true; + if(y > (screen->height-h)) + /* STOP */ + break; + if(center) { + x = (screen->width-widths[line])/2; + if(x < 0) + x = 0; + } + else + x=0; + } + } + else + first=false; +#ifdef HAVE_LCD_BITMAP + screen->putsxy(x, y, next); +#else + screen->puts(x, y, next); +#endif + x += w+SPACE; /* pixels space! */ + next = strtok_r(NULL, " ", &store); + } + +#if defined(HAVE_LCD_BITMAP) && (LCD_DEPTH > 1) + if(screen->depth > 1) + screen->set_background(LCD_WHITE); +#endif +#if defined(HAVE_LCD_BITMAP) || defined(SIMULATOR) + screen->update(); +#endif +} + +void gui_splash(struct screen * screen, int ticks, + bool center, const char *fmt, ...) +{ + va_list ap; + va_start( ap, fmt ); + internal_splash(screen, center, fmt, ap); + va_end( ap ); + + if(ticks) + sleep(ticks); +} + +void gui_syncsplash(int ticks, bool center, const char *fmt, ...) +{ + va_list ap; + int i; + va_start( ap, fmt ); + for(i=0;i<NB_SCREENS;++i) + internal_splash(&(screens[i]), center, fmt, ap); + va_end( ap ); + + if(ticks) + sleep(ticks); +} diff --git a/apps/gui/splash.h b/apps/gui/splash.h new file mode 100644 index 0000000..b0d55db --- /dev/null +++ b/apps/gui/splash.h @@ -0,0 +1,39 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2005 by Kévin FERRARE + * + * 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. + * + ****************************************************************************/ + +/* + * Puts a splash message on the given screen for a given period + * - screen : the screen to put the splash on + * - ticks : how long the splash is displayed (in rb ticks) + * - center : FALSE means left-justified, TRUE means + * horizontal and vertical center + * - fmt : what to say *printf style + */ +extern void gui_splash(struct screen * screen, int ticks, + bool center, const char *fmt, ...); + +/* + * Puts a splash message on all the screens for a given period + * - ticks : how long the splash is displayed (in rb ticks) + * - center : FALSE means left-justified, TRUE means + * horizontal and vertical center + * - fmt : what to say *printf style + */ +extern void gui_syncsplash(int ticks, bool center, + const char *fmt, ...); diff --git a/apps/gui/statusbar.c b/apps/gui/statusbar.c new file mode 100644 index 0000000..5ddc194 --- /dev/null +++ b/apps/gui/statusbar.c @@ -0,0 +1,508 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) Robert E. Hak (2002), Linus Nielsen Feltzing (2002), Kévin FERRARE (2005) + * + * 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 "config.h" +#include "screen_access.h" +#include "lcd.h" +#include "font.h" +#include "kernel.h" +#include "string.h" /* for memcmp oO*/ +#include "sprintf.h" +#include "sound.h" +#include "power.h" +#include "settings.h" +#include "icons.h" +#include "powermgmt.h" +#include "button.h" + +#include "status.h" /* needed for battery_state global var */ +#include "wps.h" /* for keys_locked */ +#include "statusbar.h" + + +/* FIXME: should be removed from icon.h to avoid redefinition, + but still needed for compatibility with old system */ +#define STATUSBAR_X_POS 0 +#define STATUSBAR_Y_POS 0 /* MUST be a multiple of 8 */ +#define STATUSBAR_HEIGHT 8 +#define STATUSBAR_BATTERY_X_POS 0 +#define STATUSBAR_BATTERY_WIDTH 18 +#define STATUSBAR_PLUG_X_POS STATUSBAR_X_POS + \ + STATUSBAR_BATTERY_WIDTH +2 +#define STATUSBAR_PLUG_WIDTH 7 +#define STATUSBAR_VOLUME_X_POS STATUSBAR_X_POS + \ + STATUSBAR_BATTERY_WIDTH + \ + STATUSBAR_PLUG_WIDTH +2+2 +#define STATUSBAR_VOLUME_WIDTH 16 +#define STATUSBAR_PLAY_STATE_X_POS STATUSBAR_X_POS + \ + STATUSBAR_BATTERY_WIDTH + \ + STATUSBAR_PLUG_WIDTH + \ + STATUSBAR_VOLUME_WIDTH+2+2+2 +#define STATUSBAR_PLAY_STATE_WIDTH 7 +#define STATUSBAR_PLAY_MODE_X_POS STATUSBAR_X_POS + \ + STATUSBAR_BATTERY_WIDTH + \ + STATUSBAR_PLUG_WIDTH + \ + STATUSBAR_VOLUME_WIDTH + \ + STATUSBAR_PLAY_STATE_WIDTH + \ + 2+2+2+2 +#define STATUSBAR_PLAY_MODE_WIDTH 7 +#define STATUSBAR_SHUFFLE_X_POS STATUSBAR_X_POS + \ + STATUSBAR_BATTERY_WIDTH + \ + STATUSBAR_PLUG_WIDTH + \ + STATUSBAR_VOLUME_WIDTH + \ + STATUSBAR_PLAY_STATE_WIDTH + \ + STATUSBAR_PLAY_MODE_WIDTH + \ + 2+2+2+2+2 +#define STATUSBAR_SHUFFLE_WIDTH 7 +#define STATUSBAR_LOCK_X_POS STATUSBAR_X_POS + \ + STATUSBAR_BATTERY_WIDTH + \ + STATUSBAR_PLUG_WIDTH + \ + STATUSBAR_VOLUME_WIDTH + \ + STATUSBAR_PLAY_STATE_WIDTH + \ + STATUSBAR_PLAY_MODE_WIDTH + \ + STATUSBAR_SHUFFLE_WIDTH + \ + 2+2+2+2+2+2 +#define STATUSBAR_LOCK_WIDTH 5 +#define STATUSBAR_DISK_WIDTH 12 +#define STATUSBAR_DISK_X_POS(statusbar_width) statusbar_width - \ + STATUSBAR_DISK_WIDTH +#define STATUSBAR_TIME_X_END(statusbar_width) statusbar_width-1 + +void gui_statusbar_init(struct gui_statusbar * bar) +{ + bar->last_volume = -1; /* -1 means "first update ever" */ + bar->battery_icon_switch_tick = 0; +#ifdef HAVE_USB_POWER + bar->battery_charge_step = 0; +#endif +} + +void gui_statusbar_set_screen(struct gui_statusbar * bar, + struct screen * display) +{ + bar->display = display; + gui_statusbar_draw(bar, false); +} + +void gui_statusbar_draw(struct gui_statusbar * bar, bool force_redraw) +{ +#ifdef HAVE_LCD_BITMAP + if(!global_settings.statusbar) + return; +#endif + + struct screen * display = bar->display; + +#ifdef HAVE_LCD_BITMAP + struct tm* tm; /* For Time */ +#else + (void)force_redraw; /* players always "redraw" */ +#endif + + bar->info.volume = sound_val2phys(SOUND_VOLUME, global_settings.volume); + bar->info.inserted = charger_inserted(); + bar->info.battlevel = battery_level(); + bar->info.battery_safe = battery_level_safe(); + +#ifdef HAVE_LCD_BITMAP + tm = get_time(); + bar->info.hour = tm->tm_hour; + bar->info.minute = tm->tm_min; + bar->info.shuffle = global_settings.playlist_shuffle; +#if CONFIG_KEYPAD == IRIVER_H100_PAD + bar->info.keylock = button_hold(); +#else + bar->info.keylock = keys_locked; +#endif + bar->info.repeat = global_settings.repeat_mode; + bar->info.playmode = current_playmode(); +#if CONFIG_LED == LED_VIRTUAL + bar->info.led = led_read(HZ/2); /* delay should match polling interval */ +#endif +#ifdef HAVE_USB_POWER + bar->info.usb_power = usb_powered(); +#endif + + /* only redraw if forced to, or info has changed */ + if (force_redraw || + bar->info.inserted || + !bar->info.battery_safe || + bar->info.redraw_volume || + memcmp(&(bar->info), &(bar->lastinfo), sizeof(struct status_info))) + { + display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); + display->fillrect(0,0,display->width,8); + display->set_drawmode(DRMODE_SOLID); + +#else + + /* players always "redraw" */ + { +#endif + +#ifdef HAVE_CHARGING + if (bar->info.inserted) { + battery_state = true; +#if defined(HAVE_CHARGE_CTRL) || CONFIG_BATTERY == BATT_LIION2200 + /* zero battery run time if charging */ + if (charge_state > 0) { + global_settings.runtime = 0; + lasttime = current_tick; + } + + /* animate battery if charging */ + if ((charge_state == 1) || + (charge_state == 2)) { +#else + global_settings.runtime = 0; + lasttime = current_tick; + { +#endif + /* animate in three steps (34% per step for a better look) */ + bar->info.battlevel = bar->battery_charge_step * 34; + if (bar->info.battlevel > 100) + bar->info.battlevel = 100; + if(TIME_AFTER(current_tick, bar->battery_icon_switch_tick)) { + bar->battery_charge_step=(bar->battery_charge_step+1)%4; + bar->battery_icon_switch_tick = current_tick + HZ; + } + } + } + else +#endif /* HAVE_CHARGING */ + { + if (bar->info.battery_safe) + battery_state = true; + else { + /* blink battery if level is low */ + if(TIME_AFTER(current_tick, bar->battery_icon_switch_tick) && + (bar->info.battlevel > -1)) { + bar->battery_icon_switch_tick = current_tick+HZ; + battery_state = !battery_state; + } + } + } +#ifdef HAVE_LCD_BITMAP + if (battery_state) + gui_statusbar_icon_battery(display, bar->info.battlevel); + /* draw power plug if charging */ + if (bar->info.inserted) + display->mono_bitmap(bitmap_icons_7x8[Icon_Plug], + STATUSBAR_PLUG_X_POS, + STATUSBAR_Y_POS, STATUSBAR_PLUG_WIDTH, + STATUSBAR_HEIGHT); +#ifdef HAVE_USB_POWER + else if (bar->info.usb_power) + display->mono_bitmap(bitmap_icons_7x8[Icon_USBPlug], + STATUSBAR_PLUG_X_POS, + STATUSBAR_Y_POS, STATUSBAR_PLUG_WIDTH, + STATUSBAR_HEIGHT); +#endif + + bar->info.redraw_volume = gui_statusbar_icon_volume(bar, + bar->info.volume); + gui_statusbar_icon_play_state(display, current_playmode() + + Icon_Play); + switch (bar->info.repeat) { +#ifdef AB_REPEAT_ENABLE + case REPEAT_AB: + gui_statusbar_icon_play_mode(display, Icon_RepeatAB); + break; +#endif + + case REPEAT_ONE: + gui_statusbar_icon_play_mode(display, Icon_RepeatOne); + break; + + case REPEAT_ALL: + case REPEAT_SHUFFLE: + gui_statusbar_icon_play_mode(display, Icon_Repeat); + break; + } + if (bar->info.shuffle) + gui_statusbar_icon_shuffle(display); + if (bar->info.keylock) + gui_statusbar_icon_lock(display); +#ifdef HAVE_RTC + gui_statusbar_time(display, bar->info.hour, bar->info.minute); +#endif +#if CONFIG_LED == LED_VIRTUAL + if (bar->info.led) + statusbar_led(); +#endif + display->update_rect(0, 0, display->width, STATUSBAR_HEIGHT); + bar->lastinfo = bar->info; +#endif + } + + +#ifndef HAVE_LCD_BITMAP + if (bar->info.battlevel > -1) + display->icon(ICON_BATTERY, battery_state); + display->icon(ICON_BATTERY_1, bar->info.battlevel > 25); + display->icon(ICON_BATTERY_2, bar->info.battlevel > 50); + display->icon(ICON_BATTERY_3, bar->info.battlevel > 75); + + display->icon(ICON_VOLUME, true); + display->icon(ICON_VOLUME_1, bar->info.volume > 10); + display->icon(ICON_VOLUME_2, bar->info.volume > 30); + display->icon(ICON_VOLUME_3, bar->info.volume > 50); + display->icon(ICON_VOLUME_4, bar->info.volume > 70); + display->icon(ICON_VOLUME_5, bar->info.volume > 90); + + display->icon(ICON_PLAY, current_playmode() == STATUS_PLAY); + display->icon(ICON_PAUSE, current_playmode() == STATUS_PAUSE); + + display->icon(ICON_REPEAT, global_settings.repeat_mode != REPEAT_OFF); + display->icon(ICON_1, global_settings.repeat_mode == REPEAT_ONE); + + display->icon(ICON_RECORD, record); + display->icon(ICON_AUDIO, audio); + display->icon(ICON_PARAM, param); + display->icon(ICON_USB, usb); +#endif +} + +#ifdef HAVE_LCD_BITMAP +/* from icon.c */ +/* + * Print battery icon to status bar + */ +void gui_statusbar_icon_battery(struct screen * display, int percent) +{ + int fill; + char buffer[5]; + unsigned int width, height; + + /* fill battery */ + fill = percent; + if (fill < 0) + fill = 0; + if (fill > 100) + fill = 100; + +#if defined(HAVE_CHARGE_CTRL) && !defined(SIMULATOR) /* Rec v1 target only */ + /* show graphical animation when charging instead of numbers */ + if ((global_settings.battery_display) && + (charge_state != 1) && + (percent > -1)) { +#else /* all others */ + if (global_settings.battery_display && (percent > -1)) { +#endif + /* Numeric display */ + display->setfont(FONT_SYSFIXED); + snprintf(buffer, sizeof(buffer), "%3d", fill); + display->getstringsize(buffer, &width, &height); + if (height <= STATUSBAR_HEIGHT) + display->putsxy(STATUSBAR_BATTERY_X_POS + + STATUSBAR_BATTERY_WIDTH / 2 + - width/2, STATUSBAR_Y_POS, buffer); + display->setfont(FONT_UI); + + } + else { + /* draw battery */ + display->drawrect(STATUSBAR_BATTERY_X_POS, STATUSBAR_Y_POS, 17, 7); + display->vline(STATUSBAR_BATTERY_X_POS + 17, STATUSBAR_Y_POS + 2, + STATUSBAR_Y_POS + 4); + + fill = fill * 15 / 100; + display->fillrect(STATUSBAR_BATTERY_X_POS + 1, STATUSBAR_Y_POS + 1, + fill, 5); + } + + if (percent == -1) { + display->setfont(FONT_SYSFIXED); + display->putsxy(STATUSBAR_BATTERY_X_POS + STATUSBAR_BATTERY_WIDTH / 2 + - 4, STATUSBAR_Y_POS, "?"); + display->setfont(FONT_UI); + } +} + +/* + * Print volume gauge to status bar + */ +bool gui_statusbar_icon_volume(struct gui_statusbar * bar, int percent) +{ + int i; + int volume; + int vol; + char buffer[4]; + unsigned int width, height; + bool needs_redraw = false; + int type = global_settings.volume_type; + struct screen * display=bar->display; + + volume = percent; + if (volume < 0) + volume = 0; + if (volume > 100) + volume = 100; + + if (volume == 0) { + display->mono_bitmap(bitmap_icons_7x8[Icon_Mute], + STATUSBAR_VOLUME_X_POS + STATUSBAR_VOLUME_WIDTH / 2 - 4, + STATUSBAR_Y_POS, 7, STATUSBAR_HEIGHT); + } + else { + /* We want to redraw the icon later on */ + if (bar->last_volume != volume && bar->last_volume >= 0) { + bar->volume_icon_switch_tick = current_tick + HZ; + } + + /* If the timeout hasn't yet been reached, we show it numerically + and tell the caller that we want to be called again */ + if (TIME_BEFORE(current_tick,bar->volume_icon_switch_tick)) { + type = 1; + needs_redraw = true; + } + + /* display volume level numerical? */ + if (type) + { + display->setfont(FONT_SYSFIXED); + snprintf(buffer, sizeof(buffer), "%2d", percent); + display->getstringsize(buffer, &width, &height); + if (height <= STATUSBAR_HEIGHT) + { + display->putsxy(STATUSBAR_VOLUME_X_POS + + STATUSBAR_VOLUME_WIDTH / 2 + - width/2, STATUSBAR_Y_POS, buffer); + } + display->setfont(FONT_UI); + } else { + /* display volume bar */ + vol = volume * 14 / 100; + for(i=0; i < vol; i++) { + display->vline(STATUSBAR_VOLUME_X_POS + i, + STATUSBAR_Y_POS + 6 - i / 2, + STATUSBAR_Y_POS + 6); + } + } + } + bar->last_volume = volume; + + return needs_redraw; +} + +/* + * Print play state to status bar + */ +void gui_statusbar_icon_play_state(struct screen * display, int state) +{ + display->mono_bitmap(bitmap_icons_7x8[state], STATUSBAR_PLAY_STATE_X_POS, + STATUSBAR_Y_POS, STATUSBAR_PLAY_STATE_WIDTH, + STATUSBAR_HEIGHT); +} + +/* + * Print play mode to status bar + */ +void gui_statusbar_icon_play_mode(struct screen * display, int mode) +{ + display->mono_bitmap(bitmap_icons_7x8[mode], STATUSBAR_PLAY_MODE_X_POS, + STATUSBAR_Y_POS, STATUSBAR_PLAY_MODE_WIDTH, + STATUSBAR_HEIGHT); +} + +/* + * Print shuffle mode to status bar + */ +void gui_statusbar_icon_shuffle(struct screen * display) +{ + display->mono_bitmap(bitmap_icons_7x8[Icon_Shuffle], + STATUSBAR_SHUFFLE_X_POS, STATUSBAR_Y_POS, + STATUSBAR_SHUFFLE_WIDTH, STATUSBAR_HEIGHT); +} + +/* + * Print lock when keys are locked + */ +void gui_statusbar_icon_lock(struct screen * display) +{ + display->mono_bitmap(bitmap_icons_5x8[Icon_Lock], STATUSBAR_LOCK_X_POS, + STATUSBAR_Y_POS, 5, 8); +} + +#if CONFIG_LED == LED_VIRTUAL +/* + * no real LED: disk activity in status bar + */ +void gui_statusbar_led(struct screen * display) +{ + display->mono_bitmap(bitmap_icon_disk, STATUSBAR_DISK_X_POS, + STATUSBAR_Y_POS, STATUSBAR_DISK_WIDTH(screen->width), + STATUSBAR_HEIGHT); +} +#endif + + +#ifdef HAVE_RTC +/* + * Print time to status bar + */ +void gui_statusbar_time(struct screen * display, int hour, int minute) +{ + unsigned char buffer[6]; + unsigned int width, height; + if ( hour >= 0 && + hour <= 23 && + minute >= 0 && + minute <= 59 ) { + if ( global_settings.timeformat ) { /* 12 hour clock */ + hour %= 12; + if ( hour == 0 ) { + hour += 12; + } + } + snprintf(buffer, sizeof(buffer), "%02d:%02d", hour, minute); + } + else { + strncpy(buffer, "--:--", sizeof buffer); + } + display->setfont(FONT_SYSFIXED); + display->getstringsize(buffer, &width, &height); + if (height <= STATUSBAR_HEIGHT) { + display->putsxy(STATUSBAR_TIME_X_END(display->width) - width, + STATUSBAR_Y_POS, buffer); + } + display->setfont(FONT_UI); + +} +#endif + +#endif /* HAVE_LCD_BITMAP */ + +void gui_syncstatusbar_init(struct gui_syncstatusbar * bars) +{ + int i; + for(i = 0;i < NB_SCREENS;++i) { + gui_statusbar_init( &(bars->statusbars[i]) ); + gui_statusbar_set_screen( &(bars->statusbars[i]), &(screens[i]) ); + } +} + +void gui_syncstatusbar_draw(struct gui_syncstatusbar * bars, + bool force_redraw) +{ + int i; + for(i = 0;i < NB_SCREENS;++i) { + gui_statusbar_draw( &(bars->statusbars[i]), force_redraw ); + } +} diff --git a/apps/gui/statusbar.h b/apps/gui/statusbar.h new file mode 100644 index 0000000..434d679 --- /dev/null +++ b/apps/gui/statusbar.h @@ -0,0 +1,107 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2005 by Kévin FERRARE + * + * 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_STATUSBAR_H_ +#define _GUI_STATUSBAR_H_ + +#include "config.h" +#include "status.h" + +struct status_info { + int battlevel; + int volume; + int hour; + int minute; + int playmode; + int repeat; + bool inserted; + bool shuffle; + bool keylock; + bool battery_safe; + bool redraw_volume; /* true if the volume gauge needs updating */ +#if CONFIG_LED == LED_VIRTUAL + bool led; /* disk LED simulation in the status bar */ +#endif +#ifdef HAVE_USB_POWER + bool usb_power; +#endif +}; + +struct gui_statusbar +{ + /* Volume icon stuffs */ + long volume_icon_switch_tick; + int last_volume; + + long battery_icon_switch_tick; + +#ifdef HAVE_CHARGING + int battery_charge_step; +#endif + + struct status_info info; + struct status_info lastinfo; + + struct screen * display; +}; + +/* + * Initializes a status bar + * - bar : the bar to initialize + */ +extern void gui_statusbar_init(struct gui_statusbar * bar); + +/* + * Attach the status bar to a screen + * (The previous screen attachement is lost) + * - bar : the statusbar structure + * - display : the screen to attach + */ +extern void gui_statusbar_set_screen(struct gui_statusbar * bar, struct screen * display); + +/* + * Draws the status bar on the attached screen + * - bar : the statusbar structure + */ +extern void gui_statusbar_draw(struct gui_statusbar * bar, bool force_redraw); + +void gui_statusbar_icon_battery(struct screen * display, int percent); +bool gui_statusbar_icon_volume(struct gui_statusbar * bar, int percent); +void gui_statusbar_icon_play_state(struct screen * display, int state); +void gui_statusbar_icon_play_mode(struct screen * display, int mode); +void gui_statusbar_icon_shuffle(struct screen * display); +void gui_statusbar_icon_lock(struct screen * display); +#if CONFIG_LED == LED_VIRTUAL +void gui_statusbar_led(struct screen * display); +#endif + +#ifdef HAVE_RTC +void gui_statusbar_time(struct screen * display, int hour, int minute); +#endif + + +struct gui_syncstatusbar +{ + struct gui_statusbar statusbars[NB_SCREENS]; +}; + +extern void gui_syncstatusbar_init(struct gui_syncstatusbar * bars); +extern void gui_syncstatusbar_draw(struct gui_syncstatusbar * bars, bool force_redraw); + +#endif /*_GUI_STATUSBAR_H_*/ |