Initial multi screen support by Kévin Ferrare (Patch #1318081)

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7666 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Linus Nielsen Feltzing 2005-10-28 00:00:00 +00:00
parent 3efa91ed03
commit 7da9477bc3
21 changed files with 2524 additions and 720 deletions

View File

@ -31,6 +31,15 @@ database.c
filetree.c
wps-display.c
wps.c
screen_access.c
gui/buttonbar.c
gui/icon.c
gui/list.c
gui/scrollbar.c
gui/splash.c
gui/statusbar.c
#ifdef HAVE_LCD_CHARCELLS
player/icons.c
player/keyboard.c

View File

@ -43,6 +43,7 @@
#include "lang.h"
#include "keyboard.h"
#include "autoconf.h"
#include "list.h"
static int db_play_folder(struct tree_context* c);
static int db_search(struct tree_context* c, char* string);
@ -69,17 +70,18 @@ int db_load(struct tree_context* c)
c->filesindir = 0;
return 0;
}
c->dentry_size = 2;
c->dirfull = false;
DEBUGF("db_load() table: %d extra: 0x%x firstpos: %d\n", table, extra, c->firstpos);
DEBUGF("db_load() table: %d extra: 0x%x firstpos: %d\n", table, extra,
c->firstpos);
if (!table) {
table = root;
c->currtable = table;
}
switch (table) {
case root: {
static const int tables[] = {allartists, allalbums, allsongs,
@ -138,28 +140,28 @@ int db_load(struct tree_context* c)
return i;
case allsongs:
DEBUGF("dbload table allsongs\n");
DEBUGF("dbload table allsongs\n");
offset = tagdbheader.songstart + c->firstpos * SONGENTRY_SIZE;
itemcount = tagdbheader.songcount;
stringlen = tagdbheader.songlen;
break;
case allalbums:
DEBUGF("dbload table allalbums\n");
DEBUGF("dbload table allalbums\n");
offset = tagdbheader.albumstart + c->firstpos * ALBUMENTRY_SIZE;
itemcount = tagdbheader.albumcount;
stringlen = tagdbheader.albumlen;
break;
case allartists:
DEBUGF("dbload table allartists\n");
DEBUGF("dbload table allartists\n");
offset = tagdbheader.artiststart + c->firstpos * ARTISTENTRY_SIZE;
itemcount = tagdbheader.artistcount;
stringlen = tagdbheader.artistlen;
break;
case albums4artist:
DEBUGF("dbload table albums4artist\n");
DEBUGF("dbload table albums4artist\n");
/* 'extra' is offset to the artist */
safeplacelen = tagdbheader.albumarraylen * 4;
safeplace = (void*)(end_of_nbuf - safeplacelen);
@ -199,13 +201,13 @@ int db_load(struct tree_context* c)
break;
case songs4artist:
DEBUGF("dbload table songs4artist\n");
DEBUGF("dbload table songs4artist\n");
/* 'extra' is offset to the artist, used as filter */
offset = tagdbheader.songstart + c->firstpos * SONGENTRY_SIZE;
itemcount = tagdbheader.songcount;
stringlen = tagdbheader.songlen;
break;
default:
DEBUGF("Unsupported table %d\n", table);
return -1;
@ -248,7 +250,8 @@ int db_load(struct tree_context* c)
case songs4album:
case songs4artist:
rc = read(tagdb_fd, intbuf, 12);
skip = SONGENTRY_SIZE-stringlen-12; /* skip the rest of the song info */
/* skip the rest of the song info */
skip = SONGENTRY_SIZE-stringlen-12;
if (rc < 12) {
DEBUGF("%d read(%d) returned %d\n", i, 12, rc);
return -1;
@ -287,7 +290,7 @@ int db_load(struct tree_context* c)
if(table==songs4artist)
c->dirlength=hits;
/* next name is stored immediately after this */
nptr = (void*)nptr + strlen((char*)nptr) + 1;
if ((void*)nptr + stringlen > (void*)end_of_nbuf) {
@ -314,7 +317,7 @@ int db_load(struct tree_context* c)
dptr[1] = extra; /* offset to artist */
hits++;
}
c->filesindir = hits;
return hits;
@ -350,7 +353,7 @@ static int db_search(struct tree_context* c, char* string)
count = tagdbheader.songcount;
size = SONGENTRY_SIZE;
break;
default:
DEBUGF("Invalid table %d\n", c->currtable);
return 0;
@ -384,7 +387,7 @@ static int db_search(struct tree_context* c, char* string)
c->dirfull = true;
break;
}
nptr += strlen(nptr) + 1;
while ((unsigned long)nptr & 3)
nptr++;
@ -403,25 +406,24 @@ static int db_search(struct tree_context* c, char* string)
int db_enter(struct tree_context* c)
{
int rc = 0;
int offset = (c->dircursor + c->dirstart) * c->dentry_size + 1;
int offset = (c->selected_item) * c->dentry_size + 1;
int newextra = ((int*)c->dircache)[offset];
if (c->dirlevel >= MAX_DIR_LEVELS)
return 0;
c->dirpos[c->dirlevel] = c->dirstart;
c->cursorpos[c->dirlevel] = c->dircursor;
c->selected_item_history[c->dirlevel]=c->selected_item;
c->table_history[c->dirlevel] = c->currtable;
c->extra_history[c->dirlevel] = c->currextra;
c->pos_history[c->dirlevel] = c->firstpos;
c->dirlevel++;
switch (c->currtable) {
case root:
c->currtable = newextra;
c->currextra = newextra;
break;
case allartists:
case searchartists:
c->currtable = albums4artist;
@ -457,13 +459,13 @@ int db_enter(struct tree_context* c)
else
c->currtable = newextra;
break;
default:
c->dirlevel--;
break;
}
c->dirstart = c->dircursor = c->firstpos = 0;
c->selected_item=0;
gui_synclist_select_item(&tree_lists, c->selected_item);
return rc;
}
@ -471,8 +473,8 @@ int db_enter(struct tree_context* c)
void db_exit(struct tree_context* c)
{
c->dirlevel--;
c->dirstart = c->dirpos[c->dirlevel];
c->dircursor = c->cursorpos[c->dirlevel];
c->selected_item=c->selected_item_history[c->dirlevel];
gui_synclist_select_item(&tree_lists, c->selected_item);
c->currtable = c->table_history[c->dirlevel];
c->currextra = c->extra_history[c->dirlevel];
c->firstpos = c->pos_history[c->dirlevel];
@ -481,9 +483,8 @@ void db_exit(struct tree_context* c)
int db_get_filename(struct tree_context* c, char *buf, int buflen)
{
int rc;
int filenum = c->dircursor + c->dirstart;
int pathoffset = ((int*)c->dircache)[filenum * c->dentry_size + 1];
int pathoffset = ((int*)c->dircache)[c->selected_item * c->dentry_size + 1];
lseek(tagdb_fd, pathoffset, SEEK_SET);
rc = read(tagdb_fd, buf, buflen);
@ -498,7 +499,6 @@ static int db_play_folder(struct tree_context* c)
{
char buf[MAX_PATH];
int rc, i;
int filenum = c->dircursor + c->dirstart;
if (playlist_create(NULL, NULL) < 0) {
DEBUGF("Failed creating playlist\n");
@ -506,7 +506,7 @@ static int db_play_folder(struct tree_context* c)
}
/* TODO: add support for very long tables */
for (i=0; i < c->filesindir; i++) {
int pathoffset = ((int*)c->dircache)[i * c->dentry_size + 1];
lseek(tagdb_fd, pathoffset, SEEK_SET);
@ -520,11 +520,12 @@ static int db_play_folder(struct tree_context* c)
}
if (global_settings.playlist_shuffle)
filenum = playlist_shuffle(current_tick, filenum);
c->selected_item = playlist_shuffle(current_tick, c->selected_item);
if (!global_settings.play_selected)
filenum = 0;
c->selected_item = 0;
gui_synclist_select_item(&tree_lists, c->selected_item);
playlist_start(filenum,0);
playlist_start(c->selected_item,0);
return 0;
}

View File

@ -79,12 +79,12 @@ static void check_file_thumbnails(struct tree_context* c)
struct dircache_entry *entry;
struct entry* dircache = c->dircache;
DIRCACHED *dir;
dir = opendir_cached(c->currdir);
if(!dir)
return;
for (i=0; i < c->filesindir; i++) /* mark all files as non talking, except the .talk ones */
/* mark all files as non talking, except the .talk ones */
for (i=0; i < c->filesindir; i++)
{
if (dircache[i].attr & ATTR_DIRECTORY)
continue; /* we're not touching directories */
@ -100,7 +100,7 @@ static void check_file_thumbnails(struct tree_context* c)
dircache[i].attr |= TREE_ATTR_THUMBNAIL; /* set */
}
}
while((entry = readdir_cached(dir)) != 0) /* walk directory */
{
int ext_pos;
@ -110,13 +110,13 @@ static void check_file_thumbnails(struct tree_context* c)
|| (entry->attribute & ATTR_DIRECTORY) /* no file */
|| strcasecmp(&entry->d_name[ext_pos], file_thumbnail_ext))
{ /* or doesn't end with ".talk", no candidate */
continue;
continue;
}
/* terminate the (disposable) name in dir buffer,
this truncates off the ".talk" without needing an extra buffer */
entry->d_name[ext_pos] = '\0';
/* search corresponding file in dir cache */
for (i=0; i < c->filesindir; i++)
{
@ -187,7 +187,7 @@ static int compare(const void* p1, const void* p2)
return 0; /* never reached */
}
/* load and sort directory into dircache. returns NULL on failure. */
/* load and sort directory into dircache. returns NULL on failure. */
int ft_load(struct tree_context* c, const char* tempdir)
{
int i;
@ -256,7 +256,7 @@ int ft_load(struct tree_context* c, const char* tempdir)
boot_cluster = entry->startcluster;
}
#endif
/* filter out non-visible files */
if ((!(dptr->attr & ATTR_DIRECTORY) && (
(*c->dirfilter == SHOW_PLAYLIST &&
@ -289,7 +289,7 @@ int ft_load(struct tree_context* c, const char* tempdir)
name_buffer_used += len + 1;
if (dptr->attr & ATTR_DIRECTORY) /* count the remaining dirs */
c->dirsindir++;
c->dirsindir++;
}
c->filesindir = i;
c->dirlength = i;
@ -297,7 +297,7 @@ int ft_load(struct tree_context* c, const char* tempdir)
qsort(c->dircache,i,sizeof(struct entry),compare);
/* If thumbnail talking is enabled, make an extra run to mark files with
/* If thumbnail talking is enabled, make an extra run to mark files with
associated thumbnails, so we don't do unsuccessful spinups later. */
if (global_settings.talk_file == 3)
check_file_thumbnails(c); /* map .talk to ours */
@ -310,7 +310,7 @@ int ft_enter(struct tree_context* c)
int rc = 0;
char buf[MAX_PATH];
struct entry *dircache = c->dircache;
struct entry* file = &dircache[c->dircursor + c->dirstart];
struct entry* file = &dircache[c->selected_item];
bool reload_dir = false;
bool start_wps = false;
bool exit_func = false;
@ -322,13 +322,10 @@ int ft_enter(struct tree_context* c)
if (file->attr & ATTR_DIRECTORY) {
memcpy(c->currdir, buf, sizeof(c->currdir));
if ( c->dirlevel < MAX_DIR_LEVELS ) {
c->dirpos[c->dirlevel] = c->dirstart;
c->cursorpos[c->dirlevel] = c->dircursor;
}
if ( c->dirlevel < MAX_DIR_LEVELS )
c->selected_item_history[c->dirlevel] = c->selected_item;
c->dirlevel++;
c->dircursor=0;
c->dirstart=0;
c->selected_item=0;
}
else {
int seed = current_tick;
@ -357,8 +354,7 @@ int ft_enter(struct tree_context* c)
if (playlist_create(c->currdir, NULL) != -1)
{
start_index =
ft_build_playlist(c, c->dircursor + c->dirstart);
start_index = ft_build_playlist(c, c->selected_item);
if (global_settings.playlist_shuffle)
{
start_index = playlist_shuffle(seed, start_index);
@ -497,14 +493,13 @@ int ft_exit(struct tree_context* c)
exit_func = true;
c->dirlevel--;
if ( c->dirlevel < MAX_DIR_LEVELS ) {
c->dirstart = c->dirpos[c->dirlevel];
c->dircursor = c->cursorpos[c->dirlevel];
}
if ( c->dirlevel < MAX_DIR_LEVELS )
c->selected_item=c->selected_item_history[c->dirlevel];
else
c->dirstart = c->dircursor = 0;
c->selected_item=0;
if (c->dirstart == -1)
/* if undefined position */
if (c->selected_item == -1)
strcpy(lastfile, buf);
}
else

126
apps/gui/buttonbar.c Normal file
View File

@ -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 */

81
apps/gui/buttonbar.h Normal file
View File

@ -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_ */

49
apps/gui/icon.c Normal file
View File

@ -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
}

51
apps/gui/icon.h Normal file
View File

@ -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_*/

499
apps/gui/list.c Normal file
View File

@ -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;
}

232
apps/gui/list.h Normal file
View File

@ -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_ */

106
apps/gui/scrollbar.c Normal file
View File

@ -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 */

49
apps/gui/scrollbar.h Normal file
View File

@ -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_ */

216
apps/gui/splash.c Normal file
View File

@ -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);
}

39
apps/gui/splash.h Normal file
View File

@ -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, ...);

508
apps/gui/statusbar.c Normal file
View File

@ -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 );
}
}

107
apps/gui/statusbar.h Normal file
View File

@ -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_*/

View File

@ -43,12 +43,12 @@
#endif
#include "usb.h"
static enum playmode ff_mode;
enum playmode ff_mode;
static long switch_tick;
static bool battery_state = true;
long switch_tick;
bool battery_state = true;
#ifdef HAVE_CHARGING
static int battery_charge_step = 0;
int battery_charge_step = 0;
#endif
struct status_info {
@ -123,10 +123,10 @@ int current_playmode(void)
}
#if defined(HAVE_LCD_CHARCELLS)
static bool record = false;
static bool audio = false;
static bool param = false;
static bool usb = false;
bool record = false;
bool audio = false;
bool param = false;
bool usb = false;
void status_set_record(bool b)
{

View File

@ -19,6 +19,21 @@
#ifndef _STATUS_H
#define _STATUS_H
extern enum playmode ff_mode;
extern long switch_tick;
extern bool battery_state;
#ifdef HAVE_CHARGING
extern int battery_charge_step;
#endif
#if defined(HAVE_LCD_CHARCELLS)
extern bool record;
extern bool audio;
extern bool param;
extern bool usb;
#endif
enum playmode
{
STATUS_PLAY,
@ -33,10 +48,12 @@ enum playmode
void status_init(void);
void status_set_ffmode(enum playmode mode);
enum playmode status_get_ffmode(void);
int current_playmode(void);
#ifdef HAVE_LCD_BITMAP
bool statusbar(bool state);
#if CONFIG_KEYPAD == RECORDER_PAD
void buttonbar_set(const char* caption1, const char* caption2,
void buttonbar_set(const char* caption1, const char* caption2,
const char* caption3);
void buttonbar_unset(void);
bool buttonbar_isset(void);

File diff suppressed because it is too large Load Diff

View File

@ -23,6 +23,8 @@
#include <applimits.h>
#include <file.h>
/*FIXME: don't forget to remove PGUP, PGDOW, NEXT, PREV
* when everything will be working with gui_list */
#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
(CONFIG_KEYPAD == IRIVER_H300_PAD)
#define TREE_NEXT BUTTON_DOWN
@ -43,8 +45,11 @@
#define TREE_POWER_BTN BUTTON_ON
#define TREE_QUICK (BUTTON_MODE | BUTTON_REPEAT)
/* Remote keys */
#define TREE_RC_NEXT BUTTON_RC_FF
#define TREE_RC_PREV BUTTON_RC_REW
#define TREE_RC_PGUP BUTTON_RC_SOURCE
#define TREE_RC_PGDN BUTTON_RC_BITRATE
#define TREE_RC_EXIT BUTTON_RC_STOP
#define TREE_RC_RUN (BUTTON_RC_MENU | BUTTON_REL)
#define TREE_RC_RUN_PRE BUTTON_RC_MENU
@ -137,27 +142,36 @@ struct filetype {
int icon;
int voiceclip;
};
/* browser context for file or db */
struct tree_context {
/* The directory we are browsing */
char currdir[MAX_PATH];
/* the number of directories we have crossed from / */
int dirlevel;
int dircursor;
int dirstart;
/* The currently selected file/id3dbitem index (old dircursor+dirfile) */
int selected_item;
/* The selected item in each directory crossed
* (used when we want to return back to a previouws directory)*/
int selected_item_history[MAX_DIR_LEVELS];
int firstpos; /* which dir entry is on first
position in dir buffer */
int pos_history[MAX_DIR_LEVELS];
int dirpos[MAX_DIR_LEVELS];
int cursorpos[MAX_DIR_LEVELS];
char currdir[MAX_PATH]; /* file use */
int dirpos[MAX_DIR_LEVELS]; /* the dirstart history */
int cursorpos[MAX_DIR_LEVELS]; /* the dircursor history */
int *dirfilter; /* file use */
int filesindir;
int filesindir; /* The number of files in the dircache */
int dirsindir; /* file use */
int dirlength; /* total number of entries in dir, incl. those not loaded */
int table_history[MAX_DIR_LEVELS]; /* db use */
int extra_history[MAX_DIR_LEVELS]; /* db use */
int currtable; /* db use */
int currextra; /* db use */
/* A big buffer with plenty of entry structs,
* contains all files and dirs in the current
* dir (with filters applied) */
void* dircache;
int dircache_size;
char* name_buffer;
@ -196,4 +210,7 @@ struct tree_context* tree_get_context(void);
void tree_flush(void);
void tree_restore(void);
extern struct gui_synclist tree_lists;
extern struct gui_syncstatusbar statusbars;
#endif

View File

@ -19,7 +19,7 @@
#ifndef _WPS_H
#define _WPS_H
#include "id3.h"
#include "playlist.h"
#include "playlist.h"
/* button definitions */
#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
@ -33,7 +33,7 @@
#define WPS_INCVOL BUTTON_UP
#define WPS_DECVOL BUTTON_DOWN
#define WPS_PAUSE (BUTTON_ON | BUTTON_REL)
#define WPS_PAUSE_PRE BUTTON_ON
#define WPS_PAUSE_PRE BUTTON_ON
#define WPS_MENU (BUTTON_MODE | BUTTON_REL)
#define WPS_MENU_PRE BUTTON_MODE
#define WPS_BROWSE (BUTTON_SELECT | BUTTON_REL)
@ -53,10 +53,10 @@
#define WPS_RC_INCVOL BUTTON_RC_VOL_UP
#define WPS_RC_DECVOL BUTTON_RC_VOL_DOWN
#define WPS_RC_EXIT BUTTON_RC_STOP
#define WPS_RC_MENU (BUTTON_RC_MENU | BUTTON_REL)
#define WPS_RC_MENU_PRE BUTTON_RC_MENU
#define WPS_RC_BROWSE (BUTTON_RC_MODE | BUTTON_REL)
#define WPS_RC_BROWSE_PRE BUTTON_RC_MODE
#define WPS_RC_MENU (BUTTON_RC_MODE | BUTTON_REL)
#define WPS_RC_MENU_PRE BUTTON_RC_MODE
#define WPS_RC_BROWSE (BUTTON_RC_MENU | BUTTON_REL)
#define WPS_RC_BROWSE_PRE BUTTON_RC_MENU
#elif CONFIG_KEYPAD == RECORDER_PAD
#define WPS_NEXT (BUTTON_RIGHT | BUTTON_REL)

24
tools/configure vendored
View File

@ -412,7 +412,7 @@ appsdir='\$(ROOTDIR)/apps'
shcc
tool="$rootdir/tools/scramble"
output="archos.mod"
appextra="player"
appextra="player:gui"
archosrom="$pwd/rombox.ucl"
flash="$pwd/rockbox.ucl"
plugins="yes"
@ -425,7 +425,7 @@ appsdir='\$(ROOTDIR)/apps'
shcc
tool="$rootdir/tools/scramble"
output="ajbrec.ajz"
appextra="recorder"
appextra="recorder:gui"
archosrom="$pwd/rombox.ucl"
flash="$pwd/rockbox.ucl"
plugins="yes"
@ -438,7 +438,7 @@ appsdir='\$(ROOTDIR)/apps'
shcc
tool="$rootdir/tools/scramble -fm"
output="ajbrec.ajz"
appextra="recorder"
appextra="recorder:gui"
archosrom="$pwd/rombox.ucl"
flash="$pwd/rockbox.ucl"
plugins="yes"
@ -451,7 +451,7 @@ appsdir='\$(ROOTDIR)/apps'
shcc
tool="$rootdir/tools/scramble -v2"
output="ajbrec.ajz"
appextra="recorder"
appextra="recorder:gui"
archosrom="$pwd/rombox.ucl"
flash="$pwd/rockbox.ucl"
plugins="yes"
@ -465,7 +465,7 @@ appsdir='\$(ROOTDIR)/apps'
calmrisccc
tool="cp" # might work for now!
output="rockbox.gmini"
appextra="recorder"
appextra="recorder:gui"
archosrom=""
flash=""
plugins="" # disabled for now, enable later on
@ -479,7 +479,7 @@ appsdir='\$(ROOTDIR)/apps'
calmrisccc
tool="cp" # might work for now!
output="rockbox.gmini"
appextra="recorder"
appextra="recorder:gui"
archosrom=""
flash=""
plugins="" # disabled for now, enable later on
@ -492,7 +492,7 @@ appsdir='\$(ROOTDIR)/apps'
shcc
tool="$rootdir/tools/scramble -osp"
output="ajbrec.ajz"
appextra="recorder"
appextra="recorder:gui"
archosrom="$pwd/rombox.ucl"
flash="$pwd/rockbox.ucl"
plugins="yes"
@ -505,7 +505,7 @@ appsdir='\$(ROOTDIR)/apps'
shcc
tool="$rootdir/tools/scramble -ofm"
output="ajbrec.ajz"
appextra="recorder"
appextra="recorder:gui"
archosrom="$pwd/rombox.ucl"
flash="$pwd/rockbox.ucl"
plugins="yes"
@ -519,7 +519,7 @@ appsdir='\$(ROOTDIR)/apps'
coldfirecc
tool="$rootdir/tools/scramble -add=h120"
output="rockbox.iriver"
appextra="recorder"
appextra="recorder:gui"
archosrom=""
flash=""
plugins="yes"
@ -533,7 +533,7 @@ appsdir='\$(ROOTDIR)/apps'
coldfirecc
tool="$rootdir/tools/scramble -add=h300"
output="rockbox.iriver"
appextra="recorder"
appextra="recorder:gui"
archosrom=""
flash=""
plugins="yes"
@ -547,7 +547,7 @@ appsdir='\$(ROOTDIR)/apps'
coldfirecc
tool="$rootdir/tools/scramble -add=h100"
output="rockbox.iriver"
appextra="recorder"
appextra="recorder:gui"
archosrom=""
flash=""
plugins="yes"
@ -561,7 +561,7 @@ appsdir='\$(ROOTDIR)/apps'
coldfirecc
tool="$rootdir/tools/scramble -add=x5" # wrong, must be fixed
output="rockbox.iaudio"
appextra="recorder"
appextra="recorder:gui"
archosrom=""
flash=""
plugins="yes"