summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Nielsen Feltzing <linus@haxx.se>2005-10-28 00:00:00 +0000
committerLinus Nielsen Feltzing <linus@haxx.se>2005-10-28 00:00:00 +0000
commit7da9477bc3401cbd90b2984f625f96f451ecaf6b (patch)
tree8aea2c154ad0f666f57c4752fa541fa539de757c
parent3efa91ed03797dd533c0add6db750ade67499587 (diff)
downloadrockbox-7da9477bc3401cbd90b2984f625f96f451ecaf6b.tar.gz
rockbox-7da9477bc3401cbd90b2984f625f96f451ecaf6b.zip
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
-rw-r--r--apps/SOURCES9
-rw-r--r--apps/dbtree.c67
-rw-r--r--apps/filetree.c47
-rw-r--r--apps/gui/buttonbar.c126
-rw-r--r--apps/gui/buttonbar.h81
-rw-r--r--apps/gui/icon.c49
-rw-r--r--apps/gui/icon.h51
-rw-r--r--apps/gui/list.c499
-rw-r--r--apps/gui/list.h232
-rw-r--r--apps/gui/scrollbar.c106
-rw-r--r--apps/gui/scrollbar.h49
-rw-r--r--apps/gui/splash.c216
-rw-r--r--apps/gui/splash.h39
-rw-r--r--apps/gui/statusbar.c508
-rw-r--r--apps/gui/statusbar.h107
-rw-r--r--apps/status.c16
-rw-r--r--apps/status.h19
-rw-r--r--apps/tree.c942
-rw-r--r--apps/tree.h33
-rw-r--r--apps/wps.h12
-rwxr-xr-xtools/configure24
21 files changed, 2518 insertions, 714 deletions
diff --git a/apps/SOURCES b/apps/SOURCES
index 26af159d5a..07c121f5a3 100644
--- a/apps/SOURCES
+++ b/apps/SOURCES
@@ -31,6 +31,15 @@ database.c
31filetree.c 31filetree.c
32wps-display.c 32wps-display.c
33wps.c 33wps.c
34
35screen_access.c
36gui/buttonbar.c
37gui/icon.c
38gui/list.c
39gui/scrollbar.c
40gui/splash.c
41gui/statusbar.c
42
34#ifdef HAVE_LCD_CHARCELLS 43#ifdef HAVE_LCD_CHARCELLS
35player/icons.c 44player/icons.c
36player/keyboard.c 45player/keyboard.c
diff --git a/apps/dbtree.c b/apps/dbtree.c
index e3704ac381..9ea0706245 100644
--- a/apps/dbtree.c
+++ b/apps/dbtree.c
@@ -43,6 +43,7 @@
43#include "lang.h" 43#include "lang.h"
44#include "keyboard.h" 44#include "keyboard.h"
45#include "autoconf.h" 45#include "autoconf.h"
46#include "list.h"
46 47
47static int db_play_folder(struct tree_context* c); 48static int db_play_folder(struct tree_context* c);
48static int db_search(struct tree_context* c, char* string); 49static int db_search(struct tree_context* c, char* string);
@@ -69,17 +70,18 @@ int db_load(struct tree_context* c)
69 c->filesindir = 0; 70 c->filesindir = 0;
70 return 0; 71 return 0;
71 } 72 }
72 73
73 c->dentry_size = 2; 74 c->dentry_size = 2;
74 c->dirfull = false; 75 c->dirfull = false;
75 76
76 DEBUGF("db_load() table: %d extra: 0x%x firstpos: %d\n", table, extra, c->firstpos); 77 DEBUGF("db_load() table: %d extra: 0x%x firstpos: %d\n", table, extra,
78 c->firstpos);
77 79
78 if (!table) { 80 if (!table) {
79 table = root; 81 table = root;
80 c->currtable = table; 82 c->currtable = table;
81 } 83 }
82 84
83 switch (table) { 85 switch (table) {
84 case root: { 86 case root: {
85 static const int tables[] = {allartists, allalbums, allsongs, 87 static const int tables[] = {allartists, allalbums, allsongs,
@@ -138,28 +140,28 @@ int db_load(struct tree_context* c)
138 return i; 140 return i;
139 141
140 case allsongs: 142 case allsongs:
141 DEBUGF("dbload table allsongs\n"); 143 DEBUGF("dbload table allsongs\n");
142 offset = tagdbheader.songstart + c->firstpos * SONGENTRY_SIZE; 144 offset = tagdbheader.songstart + c->firstpos * SONGENTRY_SIZE;
143 itemcount = tagdbheader.songcount; 145 itemcount = tagdbheader.songcount;
144 stringlen = tagdbheader.songlen; 146 stringlen = tagdbheader.songlen;
145 break; 147 break;
146 148
147 case allalbums: 149 case allalbums:
148 DEBUGF("dbload table allalbums\n"); 150 DEBUGF("dbload table allalbums\n");
149 offset = tagdbheader.albumstart + c->firstpos * ALBUMENTRY_SIZE; 151 offset = tagdbheader.albumstart + c->firstpos * ALBUMENTRY_SIZE;
150 itemcount = tagdbheader.albumcount; 152 itemcount = tagdbheader.albumcount;
151 stringlen = tagdbheader.albumlen; 153 stringlen = tagdbheader.albumlen;
152 break; 154 break;
153 155
154 case allartists: 156 case allartists:
155 DEBUGF("dbload table allartists\n"); 157 DEBUGF("dbload table allartists\n");
156 offset = tagdbheader.artiststart + c->firstpos * ARTISTENTRY_SIZE; 158 offset = tagdbheader.artiststart + c->firstpos * ARTISTENTRY_SIZE;
157 itemcount = tagdbheader.artistcount; 159 itemcount = tagdbheader.artistcount;
158 stringlen = tagdbheader.artistlen; 160 stringlen = tagdbheader.artistlen;
159 break; 161 break;
160 162
161 case albums4artist: 163 case albums4artist:
162 DEBUGF("dbload table albums4artist\n"); 164 DEBUGF("dbload table albums4artist\n");
163 /* 'extra' is offset to the artist */ 165 /* 'extra' is offset to the artist */
164 safeplacelen = tagdbheader.albumarraylen * 4; 166 safeplacelen = tagdbheader.albumarraylen * 4;
165 safeplace = (void*)(end_of_nbuf - safeplacelen); 167 safeplace = (void*)(end_of_nbuf - safeplacelen);
@@ -199,13 +201,13 @@ int db_load(struct tree_context* c)
199 break; 201 break;
200 202
201 case songs4artist: 203 case songs4artist:
202 DEBUGF("dbload table songs4artist\n"); 204 DEBUGF("dbload table songs4artist\n");
203 /* 'extra' is offset to the artist, used as filter */ 205 /* 'extra' is offset to the artist, used as filter */
204 offset = tagdbheader.songstart + c->firstpos * SONGENTRY_SIZE; 206 offset = tagdbheader.songstart + c->firstpos * SONGENTRY_SIZE;
205 itemcount = tagdbheader.songcount; 207 itemcount = tagdbheader.songcount;
206 stringlen = tagdbheader.songlen; 208 stringlen = tagdbheader.songlen;
207 break; 209 break;
208 210
209 default: 211 default:
210 DEBUGF("Unsupported table %d\n", table); 212 DEBUGF("Unsupported table %d\n", table);
211 return -1; 213 return -1;
@@ -248,7 +250,8 @@ int db_load(struct tree_context* c)
248 case songs4album: 250 case songs4album:
249 case songs4artist: 251 case songs4artist:
250 rc = read(tagdb_fd, intbuf, 12); 252 rc = read(tagdb_fd, intbuf, 12);
251 skip = SONGENTRY_SIZE-stringlen-12; /* skip the rest of the song info */ 253 /* skip the rest of the song info */
254 skip = SONGENTRY_SIZE-stringlen-12;
252 if (rc < 12) { 255 if (rc < 12) {
253 DEBUGF("%d read(%d) returned %d\n", i, 12, rc); 256 DEBUGF("%d read(%d) returned %d\n", i, 12, rc);
254 return -1; 257 return -1;
@@ -287,7 +290,7 @@ int db_load(struct tree_context* c)
287 290
288 if(table==songs4artist) 291 if(table==songs4artist)
289 c->dirlength=hits; 292 c->dirlength=hits;
290 293
291 /* next name is stored immediately after this */ 294 /* next name is stored immediately after this */
292 nptr = (void*)nptr + strlen((char*)nptr) + 1; 295 nptr = (void*)nptr + strlen((char*)nptr) + 1;
293 if ((void*)nptr + stringlen > (void*)end_of_nbuf) { 296 if ((void*)nptr + stringlen > (void*)end_of_nbuf) {
@@ -314,7 +317,7 @@ int db_load(struct tree_context* c)
314 dptr[1] = extra; /* offset to artist */ 317 dptr[1] = extra; /* offset to artist */
315 hits++; 318 hits++;
316 } 319 }
317 320
318 c->filesindir = hits; 321 c->filesindir = hits;
319 322
320 return hits; 323 return hits;
@@ -350,7 +353,7 @@ static int db_search(struct tree_context* c, char* string)
350 count = tagdbheader.songcount; 353 count = tagdbheader.songcount;
351 size = SONGENTRY_SIZE; 354 size = SONGENTRY_SIZE;
352 break; 355 break;
353 356
354 default: 357 default:
355 DEBUGF("Invalid table %d\n", c->currtable); 358 DEBUGF("Invalid table %d\n", c->currtable);
356 return 0; 359 return 0;
@@ -384,7 +387,7 @@ static int db_search(struct tree_context* c, char* string)
384 c->dirfull = true; 387 c->dirfull = true;
385 break; 388 break;
386 } 389 }
387 390
388 nptr += strlen(nptr) + 1; 391 nptr += strlen(nptr) + 1;
389 while ((unsigned long)nptr & 3) 392 while ((unsigned long)nptr & 3)
390 nptr++; 393 nptr++;
@@ -403,25 +406,24 @@ static int db_search(struct tree_context* c, char* string)
403int db_enter(struct tree_context* c) 406int db_enter(struct tree_context* c)
404{ 407{
405 int rc = 0; 408 int rc = 0;
406 int offset = (c->dircursor + c->dirstart) * c->dentry_size + 1; 409 int offset = (c->selected_item) * c->dentry_size + 1;
407 int newextra = ((int*)c->dircache)[offset]; 410 int newextra = ((int*)c->dircache)[offset];
408 411
409 if (c->dirlevel >= MAX_DIR_LEVELS) 412 if (c->dirlevel >= MAX_DIR_LEVELS)
410 return 0; 413 return 0;
411 414
412 c->dirpos[c->dirlevel] = c->dirstart; 415 c->selected_item_history[c->dirlevel]=c->selected_item;
413 c->cursorpos[c->dirlevel] = c->dircursor;
414 c->table_history[c->dirlevel] = c->currtable; 416 c->table_history[c->dirlevel] = c->currtable;
415 c->extra_history[c->dirlevel] = c->currextra; 417 c->extra_history[c->dirlevel] = c->currextra;
416 c->pos_history[c->dirlevel] = c->firstpos; 418 c->pos_history[c->dirlevel] = c->firstpos;
417 c->dirlevel++; 419 c->dirlevel++;
418 420
419 switch (c->currtable) { 421 switch (c->currtable) {
420 case root: 422 case root:
421 c->currtable = newextra; 423 c->currtable = newextra;
422 c->currextra = newextra; 424 c->currextra = newextra;
423 break; 425 break;
424 426
425 case allartists: 427 case allartists:
426 case searchartists: 428 case searchartists:
427 c->currtable = albums4artist; 429 c->currtable = albums4artist;
@@ -457,13 +459,13 @@ int db_enter(struct tree_context* c)
457 else 459 else
458 c->currtable = newextra; 460 c->currtable = newextra;
459 break; 461 break;
460 462
461 default: 463 default:
462 c->dirlevel--; 464 c->dirlevel--;
463 break; 465 break;
464 } 466 }
465 467 c->selected_item=0;
466 c->dirstart = c->dircursor = c->firstpos = 0; 468 gui_synclist_select_item(&tree_lists, c->selected_item);
467 469
468 return rc; 470 return rc;
469} 471}
@@ -471,8 +473,8 @@ int db_enter(struct tree_context* c)
471void db_exit(struct tree_context* c) 473void db_exit(struct tree_context* c)
472{ 474{
473 c->dirlevel--; 475 c->dirlevel--;
474 c->dirstart = c->dirpos[c->dirlevel]; 476 c->selected_item=c->selected_item_history[c->dirlevel];
475 c->dircursor = c->cursorpos[c->dirlevel]; 477 gui_synclist_select_item(&tree_lists, c->selected_item);
476 c->currtable = c->table_history[c->dirlevel]; 478 c->currtable = c->table_history[c->dirlevel];
477 c->currextra = c->extra_history[c->dirlevel]; 479 c->currextra = c->extra_history[c->dirlevel];
478 c->firstpos = c->pos_history[c->dirlevel]; 480 c->firstpos = c->pos_history[c->dirlevel];
@@ -481,9 +483,8 @@ void db_exit(struct tree_context* c)
481int db_get_filename(struct tree_context* c, char *buf, int buflen) 483int db_get_filename(struct tree_context* c, char *buf, int buflen)
482{ 484{
483 int rc; 485 int rc;
484 int filenum = c->dircursor + c->dirstart; 486 int pathoffset = ((int*)c->dircache)[c->selected_item * c->dentry_size + 1];
485 int pathoffset = ((int*)c->dircache)[filenum * c->dentry_size + 1]; 487
486
487 lseek(tagdb_fd, pathoffset, SEEK_SET); 488 lseek(tagdb_fd, pathoffset, SEEK_SET);
488 rc = read(tagdb_fd, buf, buflen); 489 rc = read(tagdb_fd, buf, buflen);
489 490
@@ -498,7 +499,6 @@ static int db_play_folder(struct tree_context* c)
498{ 499{
499 char buf[MAX_PATH]; 500 char buf[MAX_PATH];
500 int rc, i; 501 int rc, i;
501 int filenum = c->dircursor + c->dirstart;
502 502
503 if (playlist_create(NULL, NULL) < 0) { 503 if (playlist_create(NULL, NULL) < 0) {
504 DEBUGF("Failed creating playlist\n"); 504 DEBUGF("Failed creating playlist\n");
@@ -506,7 +506,7 @@ static int db_play_folder(struct tree_context* c)
506 } 506 }
507 507
508 /* TODO: add support for very long tables */ 508 /* TODO: add support for very long tables */
509 509
510 for (i=0; i < c->filesindir; i++) { 510 for (i=0; i < c->filesindir; i++) {
511 int pathoffset = ((int*)c->dircache)[i * c->dentry_size + 1]; 511 int pathoffset = ((int*)c->dircache)[i * c->dentry_size + 1];
512 lseek(tagdb_fd, pathoffset, SEEK_SET); 512 lseek(tagdb_fd, pathoffset, SEEK_SET);
@@ -520,11 +520,12 @@ static int db_play_folder(struct tree_context* c)
520 } 520 }
521 521
522 if (global_settings.playlist_shuffle) 522 if (global_settings.playlist_shuffle)
523 filenum = playlist_shuffle(current_tick, filenum); 523 c->selected_item = playlist_shuffle(current_tick, c->selected_item);
524 if (!global_settings.play_selected) 524 if (!global_settings.play_selected)
525 filenum = 0; 525 c->selected_item = 0;
526 gui_synclist_select_item(&tree_lists, c->selected_item);
526 527
527 playlist_start(filenum,0); 528 playlist_start(c->selected_item,0);
528 529
529 return 0; 530 return 0;
530} 531}
diff --git a/apps/filetree.c b/apps/filetree.c
index 37a66c60ee..e8b8df73ad 100644
--- a/apps/filetree.c
+++ b/apps/filetree.c
@@ -79,12 +79,12 @@ static void check_file_thumbnails(struct tree_context* c)
79 struct dircache_entry *entry; 79 struct dircache_entry *entry;
80 struct entry* dircache = c->dircache; 80 struct entry* dircache = c->dircache;
81 DIRCACHED *dir; 81 DIRCACHED *dir;
82 82
83 dir = opendir_cached(c->currdir); 83 dir = opendir_cached(c->currdir);
84 if(!dir) 84 if(!dir)
85 return; 85 return;
86 86 /* mark all files as non talking, except the .talk ones */
87 for (i=0; i < c->filesindir; i++) /* mark all files as non talking, except the .talk ones */ 87 for (i=0; i < c->filesindir; i++)
88 { 88 {
89 if (dircache[i].attr & ATTR_DIRECTORY) 89 if (dircache[i].attr & ATTR_DIRECTORY)
90 continue; /* we're not touching directories */ 90 continue; /* we're not touching directories */
@@ -100,7 +100,7 @@ static void check_file_thumbnails(struct tree_context* c)
100 dircache[i].attr |= TREE_ATTR_THUMBNAIL; /* set */ 100 dircache[i].attr |= TREE_ATTR_THUMBNAIL; /* set */
101 } 101 }
102 } 102 }
103 103
104 while((entry = readdir_cached(dir)) != 0) /* walk directory */ 104 while((entry = readdir_cached(dir)) != 0) /* walk directory */
105 { 105 {
106 int ext_pos; 106 int ext_pos;
@@ -110,13 +110,13 @@ static void check_file_thumbnails(struct tree_context* c)
110 || (entry->attribute & ATTR_DIRECTORY) /* no file */ 110 || (entry->attribute & ATTR_DIRECTORY) /* no file */
111 || strcasecmp(&entry->d_name[ext_pos], file_thumbnail_ext)) 111 || strcasecmp(&entry->d_name[ext_pos], file_thumbnail_ext))
112 { /* or doesn't end with ".talk", no candidate */ 112 { /* or doesn't end with ".talk", no candidate */
113 continue; 113 continue;
114 } 114 }
115 115
116 /* terminate the (disposable) name in dir buffer, 116 /* terminate the (disposable) name in dir buffer,
117 this truncates off the ".talk" without needing an extra buffer */ 117 this truncates off the ".talk" without needing an extra buffer */
118 entry->d_name[ext_pos] = '\0'; 118 entry->d_name[ext_pos] = '\0';
119 119
120 /* search corresponding file in dir cache */ 120 /* search corresponding file in dir cache */
121 for (i=0; i < c->filesindir; i++) 121 for (i=0; i < c->filesindir; i++)
122 { 122 {
@@ -187,7 +187,7 @@ static int compare(const void* p1, const void* p2)
187 return 0; /* never reached */ 187 return 0; /* never reached */
188} 188}
189 189
190/* load and sort directory into dircache. returns NULL on failure. */ 190/* load and sort directory into dircache. returns NULL on failure. */
191int ft_load(struct tree_context* c, const char* tempdir) 191int ft_load(struct tree_context* c, const char* tempdir)
192{ 192{
193 int i; 193 int i;
@@ -256,7 +256,7 @@ int ft_load(struct tree_context* c, const char* tempdir)
256 boot_cluster = entry->startcluster; 256 boot_cluster = entry->startcluster;
257 } 257 }
258#endif 258#endif
259 259
260 /* filter out non-visible files */ 260 /* filter out non-visible files */
261 if ((!(dptr->attr & ATTR_DIRECTORY) && ( 261 if ((!(dptr->attr & ATTR_DIRECTORY) && (
262 (*c->dirfilter == SHOW_PLAYLIST && 262 (*c->dirfilter == SHOW_PLAYLIST &&
@@ -289,7 +289,7 @@ int ft_load(struct tree_context* c, const char* tempdir)
289 name_buffer_used += len + 1; 289 name_buffer_used += len + 1;
290 290
291 if (dptr->attr & ATTR_DIRECTORY) /* count the remaining dirs */ 291 if (dptr->attr & ATTR_DIRECTORY) /* count the remaining dirs */
292 c->dirsindir++; 292 c->dirsindir++;
293 } 293 }
294 c->filesindir = i; 294 c->filesindir = i;
295 c->dirlength = i; 295 c->dirlength = i;
@@ -297,7 +297,7 @@ int ft_load(struct tree_context* c, const char* tempdir)
297 297
298 qsort(c->dircache,i,sizeof(struct entry),compare); 298 qsort(c->dircache,i,sizeof(struct entry),compare);
299 299
300 /* If thumbnail talking is enabled, make an extra run to mark files with 300 /* If thumbnail talking is enabled, make an extra run to mark files with
301 associated thumbnails, so we don't do unsuccessful spinups later. */ 301 associated thumbnails, so we don't do unsuccessful spinups later. */
302 if (global_settings.talk_file == 3) 302 if (global_settings.talk_file == 3)
303 check_file_thumbnails(c); /* map .talk to ours */ 303 check_file_thumbnails(c); /* map .talk to ours */
@@ -310,7 +310,7 @@ int ft_enter(struct tree_context* c)
310 int rc = 0; 310 int rc = 0;
311 char buf[MAX_PATH]; 311 char buf[MAX_PATH];
312 struct entry *dircache = c->dircache; 312 struct entry *dircache = c->dircache;
313 struct entry* file = &dircache[c->dircursor + c->dirstart]; 313 struct entry* file = &dircache[c->selected_item];
314 bool reload_dir = false; 314 bool reload_dir = false;
315 bool start_wps = false; 315 bool start_wps = false;
316 bool exit_func = false; 316 bool exit_func = false;
@@ -322,13 +322,10 @@ int ft_enter(struct tree_context* c)
322 322
323 if (file->attr & ATTR_DIRECTORY) { 323 if (file->attr & ATTR_DIRECTORY) {
324 memcpy(c->currdir, buf, sizeof(c->currdir)); 324 memcpy(c->currdir, buf, sizeof(c->currdir));
325 if ( c->dirlevel < MAX_DIR_LEVELS ) { 325 if ( c->dirlevel < MAX_DIR_LEVELS )
326 c->dirpos[c->dirlevel] = c->dirstart; 326 c->selected_item_history[c->dirlevel] = c->selected_item;
327 c->cursorpos[c->dirlevel] = c->dircursor;
328 }
329 c->dirlevel++; 327 c->dirlevel++;
330 c->dircursor=0; 328 c->selected_item=0;
331 c->dirstart=0;
332 } 329 }
333 else { 330 else {
334 int seed = current_tick; 331 int seed = current_tick;
@@ -357,8 +354,7 @@ int ft_enter(struct tree_context* c)
357 354
358 if (playlist_create(c->currdir, NULL) != -1) 355 if (playlist_create(c->currdir, NULL) != -1)
359 { 356 {
360 start_index = 357 start_index = ft_build_playlist(c, c->selected_item);
361 ft_build_playlist(c, c->dircursor + c->dirstart);
362 if (global_settings.playlist_shuffle) 358 if (global_settings.playlist_shuffle)
363 { 359 {
364 start_index = playlist_shuffle(seed, start_index); 360 start_index = playlist_shuffle(seed, start_index);
@@ -497,14 +493,13 @@ int ft_exit(struct tree_context* c)
497 exit_func = true; 493 exit_func = true;
498 494
499 c->dirlevel--; 495 c->dirlevel--;
500 if ( c->dirlevel < MAX_DIR_LEVELS ) { 496 if ( c->dirlevel < MAX_DIR_LEVELS )
501 c->dirstart = c->dirpos[c->dirlevel]; 497 c->selected_item=c->selected_item_history[c->dirlevel];
502 c->dircursor = c->cursorpos[c->dirlevel];
503 }
504 else 498 else
505 c->dirstart = c->dircursor = 0; 499 c->selected_item=0;
506 500
507 if (c->dirstart == -1) 501 /* if undefined position */
502 if (c->selected_item == -1)
508 strcpy(lastfile, buf); 503 strcpy(lastfile, buf);
509 } 504 }
510 else 505 else
diff --git a/apps/gui/buttonbar.c b/apps/gui/buttonbar.c
new file mode 100644
index 0000000000..be87b1b81f
--- /dev/null
+++ b/apps/gui/buttonbar.c
@@ -0,0 +1,126 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) Linus Nielsen Feltzing (2002), Kévin FERRARE (2005)
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include "config.h"
21#include "buttonbar.h"
22
23#ifdef HAS_BUTTONBAR
24
25#include "lcd.h"
26#include "font.h"
27#include "string.h"
28#include "settings.h"
29
30void gui_buttonbar_init(struct gui_buttonbar * buttonbar)
31{
32 gui_buttonbar_unset(buttonbar);
33}
34
35void gui_buttonbar_set_display(struct gui_buttonbar * buttonbar,
36 struct screen * display)
37{
38 buttonbar->display = display;
39}
40
41void gui_buttonbar_draw_button(struct gui_buttonbar * buttonbar, int num)
42{
43 int xpos, ypos, button_width, text_width;
44 int fw, fh;
45 struct screen * display = buttonbar->display;
46
47 display->setfont(FONT_SYSFIXED);
48 display->getstringsize("M", &fw, &fh);
49
50 button_width = display->width/BUTTONBAR_MAX_BUTTONS;
51 xpos = num * button_width;
52 ypos = display->height - fh;
53
54 if(buttonbar->caption[num][0] != 0)
55 {
56 /* center the text */
57 text_width = fw * strlen(buttonbar->caption[num]);
58 display->putsxy(xpos + (button_width - text_width)/2,
59 ypos, buttonbar->caption[num]);
60 }
61
62 display->set_drawmode(DRMODE_COMPLEMENT);
63 display->fillrect(xpos, ypos, button_width - 1, fh);
64 display->set_drawmode(DRMODE_SOLID);
65 display->setfont(FONT_UI);
66}
67
68void gui_buttonbar_set(struct gui_buttonbar * buttonbar,
69 const char *caption1,
70 const char *caption2,
71 const char *caption3)
72{
73 gui_buttonbar_unset(buttonbar);
74 if(caption1)
75 {
76 strncpy(buttonbar->caption[0], caption1, 7);
77 buttonbar->caption[0][7] = 0;
78 }
79 if(caption2)
80 {
81 strncpy(buttonbar->caption[1], caption2, 7);
82 buttonbar->caption[1][7] = 0;
83 }
84 if(caption3)
85 {
86 strncpy(buttonbar->caption[2], caption3, 7);
87 buttonbar->caption[2][7] = 0;
88 }
89}
90
91void gui_buttonbar_unset(struct gui_buttonbar * buttonbar)
92{
93 int i;
94 for(i = 0;i < BUTTONBAR_MAX_BUTTONS;++i)
95 buttonbar->caption[i][0] = 0;
96}
97
98void gui_buttonbar_draw(struct gui_buttonbar * buttonbar)
99{
100 struct screen * display = buttonbar->display;
101 int i;
102
103 display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
104 display->fillrect(0, display->height - BUTTONBAR_HEIGHT,
105 display->width, BUTTONBAR_HEIGHT);
106 display->set_drawmode(DRMODE_SOLID);
107
108 for(i = 0;i < BUTTONBAR_MAX_BUTTONS;++i)
109 gui_buttonbar_draw_button(buttonbar, i);
110 display->update_rect(0, display->height - BUTTONBAR_HEIGHT,
111 display->width, BUTTONBAR_HEIGHT);
112}
113
114bool gui_buttonbar_isset(struct gui_buttonbar * buttonbar)
115{
116 /* If all buttons are unset, the button bar is considered disabled */
117 if(!global_settings.buttonbar)
118 return(false);
119 int i;
120 for(i = 0;i < BUTTONBAR_MAX_BUTTONS;++i)
121 if(buttonbar->caption[i] != 0)
122 return true;
123 return false;
124}
125
126#endif /* HAS_BUTTONBAR */
diff --git a/apps/gui/buttonbar.h b/apps/gui/buttonbar.h
new file mode 100644
index 0000000000..ee7b8d02c4
--- /dev/null
+++ b/apps/gui/buttonbar.h
@@ -0,0 +1,81 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 by Kévin FERRARE
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#ifndef _GUI_BUTTONBAR_H_
21#define _GUI_BUTTONBAR_H_
22#include "config.h"
23#include "button.h"
24#if CONFIG_KEYPAD == RECORDER_PAD
25
26#define HAS_BUTTONBAR
27#define BUTTONBAR_HEIGHT 8
28#define BUTTONBAR_MAX_BUTTONS 3
29#define BUTTONBAR_CAPTION_LENGTH 8
30#include "screen_access.h"
31
32struct gui_buttonbar
33{
34 char caption[BUTTONBAR_MAX_BUTTONS][BUTTONBAR_CAPTION_LENGTH];
35 struct screen * display;
36};
37
38/*
39 * Initializes the buttonbar
40 * - buttonbar : the buttonbar
41 */
42extern void gui_buttonbar_init(struct gui_buttonbar * buttonbar);
43
44/*
45 * Attach the buttonbar to a screen
46 * - buttonbar : the buttonbar
47 * - display : the display to attach the buttonbar
48 */
49extern void gui_buttonbar_set_display(struct gui_buttonbar * buttonbar,
50 struct screen * display);
51
52/*
53 * Set the caption of the items of the buttonbar
54 * - buttonbar : the buttonbar
55 * - caption1,2,3 : the first, second and thirds items of the bar
56 */
57extern void gui_buttonbar_set(struct gui_buttonbar * buttonbar,
58 const char *caption1,
59 const char *caption2,
60 const char *caption3);
61
62/*
63 * Disable the buttonbar
64 * - buttonbar : the buttonbar
65 */
66extern void gui_buttonbar_unset(struct gui_buttonbar * buttonbar);
67
68/*
69 * Draw the buttonbar on it's attached screen
70 * - buttonbar : the buttonbar
71 */
72extern void gui_buttonbar_draw(struct gui_buttonbar * buttonbar);
73
74/*
75 * Returns true if the buttonbar has something to display, false otherwise
76 * - buttonbar : the buttonbar
77 */
78extern bool gui_buttonbar_isset(struct gui_buttonbar * buttonbar);
79
80#endif /* CONFIG_KEYPAD == RECORDER_PAD */
81#endif /* _GUI_BUTTONBAR_H_ */
diff --git a/apps/gui/icon.c b/apps/gui/icon.c
new file mode 100644
index 0000000000..4d174d3427
--- /dev/null
+++ b/apps/gui/icon.c
@@ -0,0 +1,49 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) Robert E. Hak(2002), Kévin FERRARE (2005)
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include "config.h"
21#include "icon.h"
22#include "screen_access.h"
23#include "icons.h"
24
25/* Count in letter positions, NOT pixels */
26void screen_put_iconxy(struct screen * display, int x, int y, ICON icon)
27{
28#ifdef HAVE_LCD_BITMAP
29 if(icon==0)/* Don't display invalid icons */
30 return;
31 int xpos, ypos;
32 xpos = x*CURSOR_WIDTH;
33 ypos = y*display->char_height + display->getymargin();
34 if ( display->char_height > CURSOR_HEIGHT )/* center the cursor */
35 ypos += (display->char_height - CURSOR_HEIGHT) / 2;
36 display->mono_bitmap(icon, xpos, ypos, CURSOR_WIDTH, CURSOR_HEIGHT);
37#else
38 display->putc(x, y, icon);
39#endif
40}
41
42void screen_put_cursorxy(struct screen * display, int x, int y)
43{
44#ifdef HAVE_LCD_BITMAP
45 screen_put_iconxy(display, x, y, bitmap_icons_6x8[Icon_Cursor]);
46#else
47 screen_put_iconxy(display, x, y, CURSOR_CHAR);
48#endif
49}
diff --git a/apps/gui/icon.h b/apps/gui/icon.h
new file mode 100644
index 0000000000..46faf0972f
--- /dev/null
+++ b/apps/gui/icon.h
@@ -0,0 +1,51 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 by Kévin FERRARE
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#ifndef _GUI_ICON_H_
21#define _GUI_ICON_H_
22#include "lcd.h"
23#include "screen_access.h"
24/* Defines a type for the icons since it's not the same thing on
25 * char-based displays and bitmap displays */
26#ifdef HAVE_LCD_BITMAP
27 #define ICON const unsigned char *
28#else
29 #define ICON unsigned short
30#endif
31
32#define CURSOR_CHAR 0x92
33#define CURSOR_WIDTH 6
34#define CURSOR_HEIGHT 8
35/*
36 * Draws a cursor at a given position
37 * - screen : the screen where we put the cursor
38 * - x, y : the position, in character, not in pixel !!
39 */
40extern void screen_put_cursorxy(struct screen * screen, int x, int y);
41
42/*
43 * Put an icon on a screen at a given position
44 * (the position is given in characters)
45 * - screen : the screen where we put our icon
46 * - x, y : the position, in character, not in pixel !!
47 * - icon : the icon to put
48 */
49extern void screen_put_iconxy(struct screen * screen, int x, int y, ICON icon);
50
51#endif /*_GUI_ICON_H_*/
diff --git a/apps/gui/list.c b/apps/gui/list.c
new file mode 100644
index 0000000000..bb3eb7caaa
--- /dev/null
+++ b/apps/gui/list.c
@@ -0,0 +1,499 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 by Kévin FERRARE
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include "config.h"
21#include "lcd.h"
22#include "font.h"
23#include "button.h"
24#include "sprintf.h"
25#include "settings.h"
26#include "kernel.h"
27
28#include "screen_access.h"
29#include "list.h"
30#include "scrollbar.h"
31#include "statusbar.h"
32
33#ifdef HAVE_LCD_CHARCELLS
34#define SCROLL_LIMIT 1
35#else
36#define SCROLL_LIMIT 2
37#endif
38
39
40
41void gui_list_init(struct gui_list * gui_list,
42 void (*callback_get_item_icon)(int selected_item, ICON * icon),
43 char * (*callback_get_item_name)(int selected_item, char *buffer))
44{
45 gui_list->callback_get_item_icon = callback_get_item_icon;
46 gui_list->callback_get_item_name = callback_get_item_name;
47 gui_list->display = NULL;
48 gui_list_set_nb_items(gui_list, 0);
49 gui_list->selected_item = 0;
50 gui_list->start_item = 0;
51}
52
53void gui_list_set_nb_items(struct gui_list * gui_list, int nb_items)
54{
55 gui_list->nb_items = nb_items;
56}
57
58void gui_list_set_display(struct gui_list * gui_list, struct screen * display)
59{
60 if(gui_list->display != 0) /* we switched from a previous display */
61 gui_list->display->stop_scroll();
62 gui_list->display = display;
63#ifdef HAVE_LCD_CHARCELLS
64 display->double_height(false);
65#endif
66 gui_list_put_selection_in_screen(gui_list, false);
67}
68
69void gui_list_put_selection_in_screen(struct gui_list * gui_list,
70 bool put_from_end)
71{
72 struct screen * display = gui_list->display;
73 if(put_from_end)
74 {
75 int list_end = gui_list->selected_item + SCROLL_LIMIT - 1;
76 if(list_end > gui_list->nb_items)
77 list_end = gui_list->nb_items;
78 gui_list->start_item = list_end - display->nb_lines;
79 }
80 else
81 {
82 int list_start = gui_list->selected_item - SCROLL_LIMIT + 1;
83 if(list_start + display->nb_lines > gui_list->nb_items)
84 list_start = gui_list->nb_items - display->nb_lines;
85 gui_list->start_item = list_start;
86 }
87 if(gui_list->start_item < 0)
88 gui_list->start_item = 0;
89}
90
91void gui_list_get_selected_item_name(struct gui_list * gui_list, char *buffer)
92{
93 gui_list->callback_get_item_name(gui_list->selected_item, buffer);
94}
95
96int gui_list_get_selected_item_position(struct gui_list * gui_list)
97{
98 return gui_list->selected_item;
99}
100
101void gui_list_draw(struct gui_list * gui_list)
102{
103 struct screen * display=gui_list->display;
104 int cursor_pos = 0;
105 int icon_pos = 1;
106 int text_pos;
107 bool draw_icons = (gui_list->callback_get_item_icon != NULL &&
108 global_settings.show_icons) ;
109 bool draw_cursor;
110 int i;
111
112 /* Adjust the position of icon, cursor, text */
113#ifdef HAVE_LCD_BITMAP
114 bool draw_scrollbar = (global_settings.scrollbar &&
115 display->nb_lines < gui_list->nb_items);
116
117 int list_y_start = screen_get_text_y_start(gui_list->display);
118 int list_y_end = screen_get_text_y_end(gui_list->display);
119
120 draw_cursor = !global_settings.invert_cursor;
121 text_pos = 0; /* here it's in pixels */
122 if(draw_scrollbar)
123 {
124 ++cursor_pos;
125 ++icon_pos;
126 text_pos += SCROLLBAR_WIDTH;
127 }
128 if(!draw_cursor)
129 {
130 --icon_pos;
131 }
132 else
133 text_pos += CURSOR_WIDTH;
134
135 if(draw_icons)
136 text_pos += 8;
137#else
138 draw_cursor = true;
139 if(draw_icons)
140 text_pos = 2; /* here it's in chars */
141 else
142 text_pos = 1;
143#endif
144 /* The drawing part */
145#ifdef HAVE_LCD_BITMAP
146 /* clear the drawing area */
147 display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
148 display->fillrect(0, list_y_start,
149 display->width, list_y_end - list_y_start);
150 display->set_drawmode(DRMODE_SOLID);
151
152 /* FIXME: should not be handled here, but rather in the
153 * code that changes fonts */
154 screen_update_nblines(display);
155
156 display->stop_scroll();
157 display->setmargins(text_pos, list_y_start);
158#else
159 display->clear_display();
160#endif
161
162 for(i = 0;i < display->nb_lines;++i)
163 {
164 char entry_buffer[MAX_PATH];
165 char * entry_name;
166 int current_item = gui_list->start_item + i;
167
168 /* When there are less items to display than the
169 * current available space on the screen, we stop*/
170 if(current_item >= gui_list->nb_items)
171 break;
172 entry_name = gui_list->callback_get_item_name(current_item,
173 entry_buffer);
174 if(current_item == gui_list->selected_item)
175 {
176 /* The selected item must be displayed scrolling */
177#ifdef HAVE_LCD_BITMAP
178 if (global_settings.invert_cursor)/* Display inverted-line-style*/
179 display->puts_scroll_style(0, i, entry_name, STYLE_INVERT);
180 else
181 display->puts_scroll(0, i, entry_name);
182#else
183 display->puts_scroll(text_pos, i, entry_name);
184#endif
185
186 if(draw_cursor)
187 screen_put_cursorxy(display, cursor_pos, i);
188 }
189 else
190 {/* normal item */
191#ifdef HAVE_LCD_BITMAP
192 display->puts(0, i, entry_name);
193#else
194 display->puts(text_pos, i, entry_name);
195#endif
196 }
197 /* Icons display */
198 if(draw_icons)
199 {
200 ICON icon;
201 gui_list->callback_get_item_icon(current_item, &icon);
202 screen_put_iconxy(display, icon_pos, i, icon);
203 }
204 }
205#ifdef HAVE_LCD_BITMAP
206 /* Draw the scrollbar if needed*/
207 if(draw_scrollbar)
208 {
209 int scrollbar_y_end = display->char_height *
210 display->nb_lines + list_y_start;
211 gui_scrollbar_draw(display, 0, list_y_start, SCROLLBAR_WIDTH-1,
212 scrollbar_y_end - list_y_start, gui_list->nb_items,
213 gui_list->start_item,
214 gui_list->start_item + display->nb_lines, VERTICAL);
215 }
216 display->update_rect(0, list_y_start, display->width,
217 list_y_end - list_y_start);
218#else
219#ifdef SIMULATOR
220 display->update();
221#endif
222#endif
223}
224
225void gui_list_select_item(struct gui_list * gui_list, int item_number)
226{
227 if( item_number > gui_list->nb_items-1 || item_number < 0 )
228 return;
229 gui_list->selected_item = item_number;
230 gui_list_put_selection_in_screen(gui_list, false);
231}
232
233void gui_list_select_next(struct gui_list * gui_list)
234{
235 int item_pos;
236 int end_item;
237 int nb_lines = gui_list->display->nb_lines;
238
239 ++gui_list->selected_item;
240
241 if( gui_list->selected_item >= gui_list->nb_items )
242 {
243 /* we have already reached the bottom of the list */
244 gui_list->selected_item = 0;
245 gui_list->start_item = 0;
246 }
247 else
248 {
249 item_pos = gui_list->selected_item - gui_list->start_item;
250 end_item = gui_list->start_item + nb_lines;
251 /* we start scrolling vertically when reaching the line
252 * (nb_lines-SCROLL_LIMIT)
253 * and when we are not in the last part of the list*/
254 if( item_pos > nb_lines-SCROLL_LIMIT && end_item < gui_list->nb_items )
255 ++gui_list->start_item;
256 }
257}
258
259void gui_list_select_previous(struct gui_list * gui_list)
260{
261 int item_pos;
262 int nb_lines = gui_list->display->nb_lines;
263
264 --gui_list->selected_item;
265 if( gui_list->selected_item < 0 )
266 {
267 /* we have aleady reached the top of the list */
268 int start;
269 gui_list->selected_item = gui_list->nb_items-1;
270 start = gui_list->nb_items-nb_lines;
271 if( start < 0 )
272 gui_list->start_item = 0;
273 else
274 gui_list->start_item = start;
275 }
276 else
277 {
278 item_pos = gui_list->selected_item - gui_list->start_item;
279 if( item_pos < SCROLL_LIMIT-1 && gui_list->start_item > 0 )
280 --gui_list->start_item;
281 }
282}
283
284void gui_list_select_next_page(struct gui_list * gui_list, int nb_lines)
285{
286 if(gui_list->selected_item == gui_list->nb_items-1)
287 gui_list->selected_item = 0;
288 else
289 {
290 gui_list->selected_item += nb_lines;
291 if(gui_list->selected_item > gui_list->nb_items-1)
292 gui_list->selected_item = gui_list->nb_items-1;
293 }
294 gui_list_put_selection_in_screen(gui_list, true);
295}
296
297void gui_list_select_previous_page(struct gui_list * gui_list, int nb_lines)
298{
299 if(gui_list->selected_item == 0)
300 gui_list->selected_item = gui_list->nb_items - 1;
301 else
302 {
303 gui_list->selected_item -= nb_lines;
304 if(gui_list->selected_item < 0)
305 gui_list->selected_item = 0;
306 }
307 gui_list_put_selection_in_screen(gui_list, false);
308}
309
310void gui_list_add_item(struct gui_list * gui_list)
311{
312 ++gui_list->nb_items;
313 /* if only one item in the list, select it */
314 if(gui_list->nb_items == 1)
315 gui_list->selected_item = 0;
316}
317
318void gui_list_del_item(struct gui_list * gui_list)
319{
320 int nb_lines = gui_list->display->nb_lines;
321
322 if(gui_list->nb_items > 0)
323 {
324 int dist_selected_from_end = gui_list->nb_items
325 - gui_list->selected_item - 1;
326 int dist_start_from_end = gui_list->nb_items
327 - gui_list->start_item - 1;
328 if(dist_selected_from_end == 0)
329 {
330 /* Oops we are removing the selected item,
331 select the previous one */
332 --gui_list->selected_item;
333 }
334 --gui_list->nb_items;
335
336 /* scroll the list if needed */
337 if( (dist_start_from_end < nb_lines) && (gui_list->start_item != 0) )
338 --gui_list->start_item;
339 }
340}
341
342/*
343 * Synchronized lists stuffs
344 */
345void gui_synclist_init(
346 struct gui_synclist * lists,
347 void (*callback_get_item_icon)(int selected_item, ICON * icon),
348 char * (*callback_get_item_name)(int selected_item, char *buffer)
349 )
350{
351 int i;
352 for(i = 0;i < NB_SCREENS;i++)
353 {
354 gui_list_init(&(lists->gui_list[i]), callback_get_item_icon,
355 callback_get_item_name);
356 gui_list_set_display(&(lists->gui_list[i]), &(screens[i]));
357 }
358}
359
360void gui_synclist_set_nb_items(struct gui_synclist * lists, int nb_items)
361{
362 int i;
363 for(i = 0;i < NB_SCREENS;i++)
364 {
365 gui_list_set_nb_items(&(lists->gui_list[i]), nb_items);
366 }
367}
368
369void gui_synclist_get_selected_item_name(struct gui_synclist * lists,
370 char *buffer)
371{
372 gui_list_get_selected_item_name(&(lists->gui_list[0]), buffer);
373}
374
375int gui_synclist_get_selected_item_position(struct gui_synclist * lists)
376{
377 return gui_list_get_selected_item_position(&(lists->gui_list[0]));
378}
379
380void gui_synclist_draw(struct gui_synclist * lists)
381{
382 int i;
383 for(i = 0;i < NB_SCREENS;i++)
384 gui_list_draw(&(lists->gui_list[i]));
385}
386
387void gui_synclist_select_item(struct gui_synclist * lists, int item_number)
388{
389 int i;
390 for(i = 0;i < NB_SCREENS;i++)
391 gui_list_select_item(&(lists->gui_list[i]), item_number);
392}
393
394void gui_synclist_select_next(struct gui_synclist * lists)
395{
396 int i;
397 for(i = 0;i < NB_SCREENS;i++)
398 gui_list_select_next(&(lists->gui_list[i]));
399}
400
401void gui_synclist_select_previous(struct gui_synclist * lists)
402{
403 int i;
404 for(i = 0;i < NB_SCREENS;i++)
405 gui_list_select_previous(&(lists->gui_list[i]));
406}
407
408void gui_synclist_select_next_page(struct gui_synclist * lists,
409 enum screen_type screen)
410{
411 int i;
412 for(i = 0;i < NB_SCREENS;i++)
413 gui_list_select_next_page(&(lists->gui_list[i]),
414 screens[screen].nb_lines);
415}
416
417void gui_synclist_select_previous_page(struct gui_synclist * lists,
418 enum screen_type screen)
419{
420 int i;
421 for(i = 0;i < NB_SCREENS;i++)
422 gui_list_select_previous_page(&(lists->gui_list[i]),
423 screens[screen].nb_lines);
424}
425
426void gui_synclist_add_item(struct gui_synclist * lists)
427{
428 int i;
429 for(i = 0;i < NB_SCREENS;i++)
430 gui_list_add_item(&(lists->gui_list[i]));
431}
432
433void gui_synclist_del_item(struct gui_synclist * lists)
434{
435 int i;
436 for(i = 0;i < NB_SCREENS;i++)
437 gui_list_del_item(&(lists->gui_list[i]));
438}
439
440bool gui_synclist_do_button(struct gui_synclist * lists, unsigned button)
441{
442 switch(button)
443 {
444 case LIST_PREV:
445 case LIST_PREV | BUTTON_REPEAT:
446#ifdef LIST_RC_PREV
447 case LIST_RC_PREV:
448 case LIST_RC_PREV | BUTTON_REPEAT:
449#endif
450 gui_synclist_select_previous(lists);
451 gui_synclist_draw(lists);
452 return true;
453
454 case LIST_NEXT:
455 case LIST_NEXT | BUTTON_REPEAT:
456#ifdef LIST_RC_NEXT
457 case LIST_RC_NEXT:
458 case LIST_RC_NEXT | BUTTON_REPEAT:
459#endif
460 gui_synclist_select_next(lists);
461 gui_synclist_draw(lists);
462 return true;
463/* for pgup / pgdown, we are obliged to have a different behaviour depending on the screen
464 * for which the user pressed the key since for example, remote and main screen doesn't
465 * have the same number of lines*/
466#ifdef LIST_PGUP
467 case LIST_PGUP:
468 case LIST_PGUP | BUTTON_REPEAT:
469 gui_synclist_select_previous_page(lists, SCREEN_MAIN);
470 gui_synclist_draw(lists);
471 return true;
472#endif
473
474#ifdef LIST_RC_PGUP
475 case LIST_RC_PGUP:
476 case LIST_RC_PGUP | BUTTON_REPEAT:
477 gui_synclist_select_previous_page(lists, SCREEN_REMOTE);
478 gui_synclist_draw(lists);
479 return true;
480#endif
481
482#ifdef LIST_PGDN
483 case LIST_PGDN:
484 case LIST_PGDN | BUTTON_REPEAT:
485 gui_synclist_select_next_page(lists, SCREEN_MAIN);
486 gui_synclist_draw(lists);
487 return true;
488#endif
489
490#ifdef LIST_RC_PGDN
491 case LIST_RC_PGDN:
492 case LIST_RC_PGDN | BUTTON_REPEAT:
493 gui_synclist_select_next_page(lists, SCREEN_REMOTE);
494 gui_synclist_draw(lists);
495 return true;
496#endif
497 }
498 return false;
499}
diff --git a/apps/gui/list.h b/apps/gui/list.h
new file mode 100644
index 0000000000..fd553f381c
--- /dev/null
+++ b/apps/gui/list.h
@@ -0,0 +1,232 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 by Kévin FERRARE
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#ifndef _GUI_LIST_H_
21#define _GUI_LIST_H_
22
23#include "config.h"
24#include "icon.h"
25#include "screen_access.h"
26
27#define SCROLLBAR_WIDTH 6
28
29/* Key assignement */
30#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
31 (CONFIG_KEYPAD == IRIVER_H300_PAD)
32#define LIST_NEXT BUTTON_DOWN
33#define LIST_PREV BUTTON_UP
34#define LIST_PGUP (BUTTON_ON | BUTTON_UP)
35#define LIST_PGDN (BUTTON_ON | BUTTON_DOWN)
36#define LIST_RC_NEXT BUTTON_RC_FF
37#define LIST_RC_PREV BUTTON_RC_REW
38#define LIST_RC_PGUP BUTTON_RC_SOURCE
39#define LIST_RC_PGDN BUTTON_RC_BITRATE
40
41#elif CONFIG_KEYPAD == RECORDER_PAD
42#define LIST_NEXT BUTTON_DOWN
43#define LIST_PREV BUTTON_UP
44#define LIST_PGUP (BUTTON_ON | BUTTON_UP)
45#define LIST_PGDN (BUTTON_ON | BUTTON_DOWN)
46#define LIST_RC_NEXT BUTTON_RC_RIGHT
47#define LIST_RC_PREV BUTTON_RC_LEFT
48
49#elif CONFIG_KEYPAD == PLAYER_PAD
50#define LIST_NEXT BUTTON_RIGHT
51#define LIST_PREV BUTTON_LEFT
52#define LIST_RC_NEXT BUTTON_RC_RIGHT
53#define LIST_RC_PREV BUTTON_RC_LEFT
54
55#elif CONFIG_KEYPAD == ONDIO_PAD
56#define LIST_NEXT BUTTON_DOWN
57#define LIST_PREV BUTTON_UP
58
59#elif CONFIG_KEYPAD == GMINI100_PAD
60#define LIST_NEXT BUTTON_DOWN
61#define LIST_PREV BUTTON_UP
62#define LIST_PGUP (BUTTON_ON | BUTTON_UP)
63#define LIST_PGDN (BUTTON_ON | BUTTON_DOWN)
64#endif
65
66
67struct gui_list
68{
69 int nb_items;
70 int selected_item;
71 int start_item; /* the item that is displayed at the top of the screen */
72
73 void (*callback_get_item_icon)(int selected_item, ICON * icon);
74 char * (*callback_get_item_name)(int selected_item, char *buffer);
75
76 struct screen * display;
77 int line_scroll_limit;
78};
79
80/*
81 * Initializes a scrolling list
82 * - gui_list : the list structure to initialize
83 * - callback_get_item_icon : pointer to a function that associates an icon
84 * to a given item number
85 * - callback_get_item_name : pointer to a function that associates a label
86 * to a given item number
87 */
88extern void gui_list_init(struct gui_list * gui_list,
89 void (*callback_get_item_icon)(int selected_item, ICON * icon),
90 char * (*callback_get_item_name)(int selected_item, char *buffer)
91 );
92
93/*
94 * Sets the numburs of items the list can currently display
95 * note that the list's context like the currently pointed item is resetted
96 * - gui_list : the list structure to initialize
97 * - nb_items : the numbers of items you want
98 */
99extern void gui_list_set_nb_items(struct gui_list * gui_list, int nb_items);
100
101/*
102 * Puts the selection in the screen
103 * - gui_list : the list structure
104 * - put_from_end : if true, selection will be put as close from
105 * the end of the list as possible, else, it's
106 * from the beginning
107 */
108extern void gui_list_put_selection_in_screen(struct gui_list * gui_list,
109 bool put_from_end);
110
111/*
112 * Attach the scrolling list to a screen
113 * (The previous screen attachement is lost)
114 * - gui_list : the list structure
115 * - display : the screen to attach
116 */
117extern void gui_list_set_display(struct gui_list * gui_list,
118 struct screen * display);
119
120/*
121 * Gives the name of the selected object
122 * - gui_list : the list structure
123 * - buffer : a buffer which is filled with the name
124 */
125extern void gui_list_get_selected_item_name(struct gui_list * gui_list,
126 char *buffer);
127
128/*
129 * Gives the position of the selected item
130 * - gui_list : the list structure
131 * Returns the position
132 */
133extern int gui_list_get_selected_item_position(struct gui_list * gui_list);
134
135/*
136 * Selects an item in the list
137 * - gui_list : the list structure
138 * - item_number : the number of the item which will be selected
139 */
140extern void gui_list_select_item(struct gui_list * gui_list, int item_number);
141
142/*
143 * Draws the list on the attached screen
144 * - gui_list : the list structure
145 */
146extern void gui_list_draw(struct gui_list * gui_list);
147
148/*
149 * Selects the next item in the list
150 * (Item 0 gets selected if the end of the list is reached)
151 * - gui_list : the list structure
152 */
153extern void gui_list_select_next(struct gui_list * gui_list);
154
155/*
156 * Selects the previous item in the list
157 * (Last item in the list gets selected if the list beginning is reached)
158 * - gui_list : the list structure
159 */
160extern void gui_list_select_previous(struct gui_list * gui_list);
161
162/*
163 * Go to next page if any, else selects the last item in the list
164 * - gui_list : the list structure
165 * - nb_lines : the number of lines to try to move the cursor
166 */
167extern void gui_list_select_next_page(struct gui_list * gui_list,
168 int nb_lines);
169
170/*
171 * Go to previous page if any, else selects the first item in the list
172 * - gui_list : the list structure
173 * - nb_lines : the number of lines to try to move the cursor
174 */
175extern void gui_list_select_previous_page(struct gui_list * gui_list,
176 int nb_lines);
177
178/*
179 * Adds an item to the list (the callback will be asked for one more item)
180 * - gui_list : the list structure
181 */
182extern void gui_list_add_item(struct gui_list * gui_list);
183
184/*
185 * Removes an item to the list (the callback will be asked for one less item)
186 * - gui_list : the list structure
187 */
188extern void gui_list_del_item(struct gui_list * gui_list);
189
190
191/*
192 * This part handles as many lists as there are connected screens
193 * (the api is similar to the ones above)
194 * The lists on the screens are synchronized ;
195 * theirs items and selected items are the same, but of course,
196 * they can be displayed on screens with different sizes
197 * The final aim is to let the programmer handle many lists in one
198 * function call and make its code independant from the number of screens
199 */
200struct gui_synclist
201{
202 struct gui_list gui_list[NB_SCREENS];
203};
204
205extern void gui_synclist_init(struct gui_synclist * lists,
206 void (*callback_get_item_icon)(int selected_item, ICON * icon),
207 char * (*callback_get_item_name)(int selected_item, char *buffer)
208 );
209extern void gui_synclist_set_nb_items(struct gui_synclist * lists, int nb_items);
210extern void gui_synclist_get_selected_item_name(struct gui_synclist * lists,
211 char *buffer);
212extern int gui_synclist_get_selected_item_position(struct gui_synclist * lists);
213extern void gui_synclist_draw(struct gui_synclist * lists);
214extern void gui_synclist_select_item(struct gui_synclist * lists,
215 int item_number);
216extern void gui_synclist_select_next(struct gui_synclist * lists);
217extern void gui_synclist_select_previous(struct gui_synclist * lists);
218extern void gui_synclist_select_next_page(struct gui_synclist * lists,
219 enum screen_type screen);
220extern void gui_synclist_select_previous_page(struct gui_synclist * lists,
221 enum screen_type screen);
222extern void gui_synclist_add_item(struct gui_synclist * lists);
223extern void gui_synclist_del_item(struct gui_synclist * lists);
224/*
225 * Do the action implied by the given button,
226 * returns true if something has been done, false otherwise
227 * - lists : the synchronized lists
228 * - button : the keycode of a pressed button
229 */
230extern bool gui_synclist_do_button(struct gui_synclist * lists, unsigned button);
231
232#endif /* _GUI_LIST_H_ */
diff --git a/apps/gui/scrollbar.c b/apps/gui/scrollbar.c
new file mode 100644
index 0000000000..9d5717f1a7
--- /dev/null
+++ b/apps/gui/scrollbar.c
@@ -0,0 +1,106 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) Markus Braun (2002), Kévin FERRARE (2005)
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include "config.h"
21#include "lcd.h"
22#ifdef HAVE_LCD_BITMAP
23#include "limits.h"
24#include "scrollbar.h"
25#include "screen_access.h"
26
27void gui_scrollbar_draw(struct screen * screen, int x, int y,
28 int width, int height, int items,
29 int min_shown, int max_shown,
30 enum orientation orientation)
31{
32 int min;
33 int max;
34 int inner_len;
35 int start;
36 int size;
37
38 /* draw box */
39 screen->drawrect(x, y, width, height);
40
41 screen->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
42
43 /* clear edge pixels */
44 screen->drawpixel(x, y);
45 screen->drawpixel((x + width - 1), y);
46 screen->drawpixel(x, (y + height - 1));
47 screen->drawpixel((x + width - 1), (y + height - 1));
48
49 /* clear pixels in progress bar */
50 screen->fillrect(x + 1, y + 1, width - 2, height - 2);
51
52 /* min should be min */
53 if(min_shown < max_shown) {
54 min = min_shown;
55 max = max_shown;
56 }
57 else {
58 min = max_shown;
59 max = min_shown;
60 }
61
62 /* limit min and max */
63 if(min < 0)
64 min = 0;
65 if(min > items)
66 min = items;
67
68 if(max < 0)
69 max = 0;
70 if(max > items)
71 max = items;
72
73 if (orientation == VERTICAL)
74 inner_len = height - 2;
75 else
76 inner_len = width - 2;
77
78 /* avoid overflows */
79 while (items > (INT_MAX / inner_len)) {
80 items >>= 1;
81 min >>= 1;
82 max >>= 1;
83 }
84
85 /* calc start and end of the knob */
86 if (items > 0 && items > (max - min)) {
87 size = inner_len * (max - min) / items;
88 if (size == 0) { /* width of knob is null */
89 size = 1;
90 start = (inner_len - 1) * min / items;
91 } else {
92 start = (inner_len - size) * min / (items - (max - min));
93 }
94 } else { /* if null draw full bar */
95 size = inner_len;
96 start = 0;
97 }
98
99 screen->set_drawmode(DRMODE_SOLID);
100
101 if(orientation == VERTICAL)
102 screen->fillrect(x + 1, y + start + 1, width - 2, size);
103 else
104 screen->fillrect(x + start + 1, y + 1, size, height - 2);
105}
106#endif /* HAVE_LCD_BITMAP */
diff --git a/apps/gui/scrollbar.h b/apps/gui/scrollbar.h
new file mode 100644
index 0000000000..51c08352ba
--- /dev/null
+++ b/apps/gui/scrollbar.h
@@ -0,0 +1,49 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 Kévin FERRARE
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#ifndef _GUI_SCROLLBAR_H_
21#define _GUI_SCROLLBAR_H_
22#include <lcd.h>
23#ifdef HAVE_LCD_BITMAP
24
25struct screen;
26
27enum orientation {
28 VERTICAL,
29 HORIZONTAL
30};
31
32/*
33 * Draws a scrollbar on the given screen
34 * - screen : the screen to put the scrollbar on
35 * - x : x start position of the scrollbar
36 * - y : y start position of the scrollbar
37 * - width : you won't guess =(^o^)=
38 * - height : I won't tell you either !
39 * - items : total number of items on the screen
40 * - min_shown : index of the starting item on the screen
41 * - max_shown : index of the last item on the screen
42 * - orientation : either VERTICAL or HORIZONTAL
43 */
44extern void gui_scrollbar_draw(struct screen * screen, int x, int y,
45 int width, int height, int items,
46 int min_shown, int max_shown,
47 enum orientation orientation);
48#endif /* HAVE_LCD_BITMAP */
49#endif /* _GUI_SCROLLBAR_H_ */
diff --git a/apps/gui/splash.c b/apps/gui/splash.c
new file mode 100644
index 0000000000..a3cbb198df
--- /dev/null
+++ b/apps/gui/splash.c
@@ -0,0 +1,216 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) Daniel Stenberg (2002), Kévin FERRARE (2005)
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include "stdarg.h"
20#include "string.h"
21#include "stdio.h"
22#include "kernel.h"
23#include "screen_access.h"
24
25
26#ifdef HAVE_LCD_BITMAP
27
28#define SPACE 3 /* pixels between words */
29#define MAXLETTERS 128 /* 16*8 */
30#define MAXLINES 10
31
32#else
33
34#define SPACE 1 /* one letter space */
35#define MAXLETTERS 22 /* 11 * 2 */
36#define MAXLINES 2
37
38#endif
39
40
41void internal_splash(struct screen * screen,
42 bool center, const char *fmt, va_list ap)
43{
44 char *next;
45 char *store=NULL;
46 int x=0;
47 int y=0;
48 int w, h;
49 unsigned char splash_buf[MAXLETTERS];
50 unsigned char widths[MAXLINES];
51 int line=0;
52 bool first=true;
53#ifdef HAVE_LCD_BITMAP
54 int maxw=0;
55#endif
56
57#ifdef HAVE_LCD_CHARCELLS
58 screen->double_height (false);
59#endif
60 vsnprintf( splash_buf, sizeof(splash_buf), fmt, ap );
61
62 if(center) {
63 /* first a pass to measure sizes */
64 next = strtok_r(splash_buf, " ", &store);
65 while (next) {
66#ifdef HAVE_LCD_BITMAP
67 screen->getstringsize(next, &w, &h);
68#else
69 w = strlen(next);
70 h = 1; /* store height in characters */
71#endif
72 if(!first) {
73 if(x+w> screen->width) {
74 /* Too wide, wrap */
75 y+=h;
76 line++;
77 if((y > (screen->height-h)) || (line > screen->nb_lines))
78 /* STOP */
79 break;
80 x=0;
81 first=true;
82 }
83 }
84 else
85 first = false;
86
87 /* think of it as if the text was written here at position x,y
88 being w pixels/chars wide and h high */
89
90 x += w+SPACE;
91 widths[line]=x-SPACE; /* don't count the trailing space */
92#ifdef HAVE_LCD_BITMAP
93 /* store the widest line */
94 if(widths[line]>maxw)
95 maxw = widths[line];
96#endif
97 next = strtok_r(NULL, " ", &store);
98 }
99
100#ifdef HAVE_LCD_BITMAP
101 /* Start displaying the message at position y. The reason for the
102 added h here is that it isn't added until the end of lines in the
103 loop above and we always break the loop in the middle of a line. */
104 y = (screen->height - (y+h) )/2;
105#else
106 y = 0; /* vertical center on 2 lines would be silly */
107#endif
108 first=true;
109
110 /* Now recreate the string again since the strtok_r() above has ruined
111 the one we already have! Here's room for improvements! */
112 vsnprintf( splash_buf, sizeof(splash_buf), fmt, ap );
113 }
114 va_end( ap );
115
116 if(center)
117 {
118 x = (screen->width-widths[0])/2;
119 if(x < 0)
120 x = 0;
121 }
122
123#ifdef HAVE_LCD_BITMAP
124 /* If we center the display, then just clear the box we need and put
125 a nice little frame and put the text in there! */
126 if(center && (y > 2)) {
127 int xx = (screen->width-maxw)/2 - 2;
128 /* The new graphics routines handle clipping, so no need to check */
129#if LCD_DEPTH > 1
130#ifdef HAVE_LCD_COLOR
131 screen->set_background((struct rgb){LCD_MAX_RED-1, LCD_MAX_GREEN-1,
132 LCD_MAX_BLUE-1});
133#else
134 if(screen->depth>1)
135 screen->set_background(LCD_MAX_LEVEL-1);
136#endif
137#endif
138 screen->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
139 screen->fillrect(xx, y-2, maxw+4, screen->height-y*2+4);
140 screen->set_drawmode(DRMODE_SOLID);
141 screen->drawrect(xx, y-2, maxw+4, screen->height-y*2+4);
142 }
143 else
144#endif
145 screen->clear_display();
146 line=0;
147 next = strtok_r(splash_buf, " ", &store);
148 while (next) {
149#ifdef HAVE_LCD_BITMAP
150 screen->getstringsize(next, &w, &h);
151#else
152 w = strlen(next);
153 h = 1;
154#endif
155 if(!first) {
156 if(x+w> screen->width) {
157 /* too wide */
158 y+=h;
159 line++; /* goto next line */
160 first=true;
161 if(y > (screen->height-h))
162 /* STOP */
163 break;
164 if(center) {
165 x = (screen->width-widths[line])/2;
166 if(x < 0)
167 x = 0;
168 }
169 else
170 x=0;
171 }
172 }
173 else
174 first=false;
175#ifdef HAVE_LCD_BITMAP
176 screen->putsxy(x, y, next);
177#else
178 screen->puts(x, y, next);
179#endif
180 x += w+SPACE; /* pixels space! */
181 next = strtok_r(NULL, " ", &store);
182 }
183
184#if defined(HAVE_LCD_BITMAP) && (LCD_DEPTH > 1)
185 if(screen->depth > 1)
186 screen->set_background(LCD_WHITE);
187#endif
188#if defined(HAVE_LCD_BITMAP) || defined(SIMULATOR)
189 screen->update();
190#endif
191}
192
193void gui_splash(struct screen * screen, int ticks,
194 bool center, const char *fmt, ...)
195{
196 va_list ap;
197 va_start( ap, fmt );
198 internal_splash(screen, center, fmt, ap);
199 va_end( ap );
200
201 if(ticks)
202 sleep(ticks);
203}
204
205void gui_syncsplash(int ticks, bool center, const char *fmt, ...)
206{
207 va_list ap;
208 int i;
209 va_start( ap, fmt );
210 for(i=0;i<NB_SCREENS;++i)
211 internal_splash(&(screens[i]), center, fmt, ap);
212 va_end( ap );
213
214 if(ticks)
215 sleep(ticks);
216}
diff --git a/apps/gui/splash.h b/apps/gui/splash.h
new file mode 100644
index 0000000000..b0d55db890
--- /dev/null
+++ b/apps/gui/splash.h
@@ -0,0 +1,39 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 by Kévin FERRARE
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20/*
21 * Puts a splash message on the given screen for a given period
22 * - screen : the screen to put the splash on
23 * - ticks : how long the splash is displayed (in rb ticks)
24 * - center : FALSE means left-justified, TRUE means
25 * horizontal and vertical center
26 * - fmt : what to say *printf style
27 */
28extern void gui_splash(struct screen * screen, int ticks,
29 bool center, const char *fmt, ...);
30
31/*
32 * Puts a splash message on all the screens for a given period
33 * - ticks : how long the splash is displayed (in rb ticks)
34 * - center : FALSE means left-justified, TRUE means
35 * horizontal and vertical center
36 * - fmt : what to say *printf style
37 */
38extern void gui_syncsplash(int ticks, bool center,
39 const char *fmt, ...);
diff --git a/apps/gui/statusbar.c b/apps/gui/statusbar.c
new file mode 100644
index 0000000000..5ddc194610
--- /dev/null
+++ b/apps/gui/statusbar.c
@@ -0,0 +1,508 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) Robert E. Hak (2002), Linus Nielsen Feltzing (2002), Kévin FERRARE (2005)
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include "config.h"
21#include "screen_access.h"
22#include "lcd.h"
23#include "font.h"
24#include "kernel.h"
25#include "string.h" /* for memcmp oO*/
26#include "sprintf.h"
27#include "sound.h"
28#include "power.h"
29#include "settings.h"
30#include "icons.h"
31#include "powermgmt.h"
32#include "button.h"
33
34#include "status.h" /* needed for battery_state global var */
35#include "wps.h" /* for keys_locked */
36#include "statusbar.h"
37
38
39/* FIXME: should be removed from icon.h to avoid redefinition,
40 but still needed for compatibility with old system */
41#define STATUSBAR_X_POS 0
42#define STATUSBAR_Y_POS 0 /* MUST be a multiple of 8 */
43#define STATUSBAR_HEIGHT 8
44#define STATUSBAR_BATTERY_X_POS 0
45#define STATUSBAR_BATTERY_WIDTH 18
46#define STATUSBAR_PLUG_X_POS STATUSBAR_X_POS + \
47 STATUSBAR_BATTERY_WIDTH +2
48#define STATUSBAR_PLUG_WIDTH 7
49#define STATUSBAR_VOLUME_X_POS STATUSBAR_X_POS + \
50 STATUSBAR_BATTERY_WIDTH + \
51 STATUSBAR_PLUG_WIDTH +2+2
52#define STATUSBAR_VOLUME_WIDTH 16
53#define STATUSBAR_PLAY_STATE_X_POS STATUSBAR_X_POS + \
54 STATUSBAR_BATTERY_WIDTH + \
55 STATUSBAR_PLUG_WIDTH + \
56 STATUSBAR_VOLUME_WIDTH+2+2+2
57#define STATUSBAR_PLAY_STATE_WIDTH 7
58#define STATUSBAR_PLAY_MODE_X_POS STATUSBAR_X_POS + \
59 STATUSBAR_BATTERY_WIDTH + \
60 STATUSBAR_PLUG_WIDTH + \
61 STATUSBAR_VOLUME_WIDTH + \
62 STATUSBAR_PLAY_STATE_WIDTH + \
63 2+2+2+2
64#define STATUSBAR_PLAY_MODE_WIDTH 7
65#define STATUSBAR_SHUFFLE_X_POS STATUSBAR_X_POS + \
66 STATUSBAR_BATTERY_WIDTH + \
67 STATUSBAR_PLUG_WIDTH + \
68 STATUSBAR_VOLUME_WIDTH + \
69 STATUSBAR_PLAY_STATE_WIDTH + \
70 STATUSBAR_PLAY_MODE_WIDTH + \
71 2+2+2+2+2
72#define STATUSBAR_SHUFFLE_WIDTH 7
73#define STATUSBAR_LOCK_X_POS STATUSBAR_X_POS + \
74 STATUSBAR_BATTERY_WIDTH + \
75 STATUSBAR_PLUG_WIDTH + \
76 STATUSBAR_VOLUME_WIDTH + \
77 STATUSBAR_PLAY_STATE_WIDTH + \
78 STATUSBAR_PLAY_MODE_WIDTH + \
79 STATUSBAR_SHUFFLE_WIDTH + \
80 2+2+2+2+2+2
81#define STATUSBAR_LOCK_WIDTH 5
82#define STATUSBAR_DISK_WIDTH 12
83#define STATUSBAR_DISK_X_POS(statusbar_width) statusbar_width - \
84 STATUSBAR_DISK_WIDTH
85#define STATUSBAR_TIME_X_END(statusbar_width) statusbar_width-1
86
87void gui_statusbar_init(struct gui_statusbar * bar)
88{
89 bar->last_volume = -1; /* -1 means "first update ever" */
90 bar->battery_icon_switch_tick = 0;
91#ifdef HAVE_USB_POWER
92 bar->battery_charge_step = 0;
93#endif
94}
95
96void gui_statusbar_set_screen(struct gui_statusbar * bar,
97 struct screen * display)
98{
99 bar->display = display;
100 gui_statusbar_draw(bar, false);
101}
102
103void gui_statusbar_draw(struct gui_statusbar * bar, bool force_redraw)
104{
105#ifdef HAVE_LCD_BITMAP
106 if(!global_settings.statusbar)
107 return;
108#endif
109
110 struct screen * display = bar->display;
111
112#ifdef HAVE_LCD_BITMAP
113 struct tm* tm; /* For Time */
114#else
115 (void)force_redraw; /* players always "redraw" */
116#endif
117
118 bar->info.volume = sound_val2phys(SOUND_VOLUME, global_settings.volume);
119 bar->info.inserted = charger_inserted();
120 bar->info.battlevel = battery_level();
121 bar->info.battery_safe = battery_level_safe();
122
123#ifdef HAVE_LCD_BITMAP
124 tm = get_time();
125 bar->info.hour = tm->tm_hour;
126 bar->info.minute = tm->tm_min;
127 bar->info.shuffle = global_settings.playlist_shuffle;
128#if CONFIG_KEYPAD == IRIVER_H100_PAD
129 bar->info.keylock = button_hold();
130#else
131 bar->info.keylock = keys_locked;
132#endif
133 bar->info.repeat = global_settings.repeat_mode;
134 bar->info.playmode = current_playmode();
135#if CONFIG_LED == LED_VIRTUAL
136 bar->info.led = led_read(HZ/2); /* delay should match polling interval */
137#endif
138#ifdef HAVE_USB_POWER
139 bar->info.usb_power = usb_powered();
140#endif
141
142 /* only redraw if forced to, or info has changed */
143 if (force_redraw ||
144 bar->info.inserted ||
145 !bar->info.battery_safe ||
146 bar->info.redraw_volume ||
147 memcmp(&(bar->info), &(bar->lastinfo), sizeof(struct status_info)))
148 {
149 display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
150 display->fillrect(0,0,display->width,8);
151 display->set_drawmode(DRMODE_SOLID);
152
153#else
154
155 /* players always "redraw" */
156 {
157#endif
158
159#ifdef HAVE_CHARGING
160 if (bar->info.inserted) {
161 battery_state = true;
162#if defined(HAVE_CHARGE_CTRL) || CONFIG_BATTERY == BATT_LIION2200
163 /* zero battery run time if charging */
164 if (charge_state > 0) {
165 global_settings.runtime = 0;
166 lasttime = current_tick;
167 }
168
169 /* animate battery if charging */
170 if ((charge_state == 1) ||
171 (charge_state == 2)) {
172#else
173 global_settings.runtime = 0;
174 lasttime = current_tick;
175 {
176#endif
177 /* animate in three steps (34% per step for a better look) */
178 bar->info.battlevel = bar->battery_charge_step * 34;
179 if (bar->info.battlevel > 100)
180 bar->info.battlevel = 100;
181 if(TIME_AFTER(current_tick, bar->battery_icon_switch_tick)) {
182 bar->battery_charge_step=(bar->battery_charge_step+1)%4;
183 bar->battery_icon_switch_tick = current_tick + HZ;
184 }
185 }
186 }
187 else
188#endif /* HAVE_CHARGING */
189 {
190 if (bar->info.battery_safe)
191 battery_state = true;
192 else {
193 /* blink battery if level is low */
194 if(TIME_AFTER(current_tick, bar->battery_icon_switch_tick) &&
195 (bar->info.battlevel > -1)) {
196 bar->battery_icon_switch_tick = current_tick+HZ;
197 battery_state = !battery_state;
198 }
199 }
200 }
201#ifdef HAVE_LCD_BITMAP
202 if (battery_state)
203 gui_statusbar_icon_battery(display, bar->info.battlevel);
204 /* draw power plug if charging */
205 if (bar->info.inserted)
206 display->mono_bitmap(bitmap_icons_7x8[Icon_Plug],
207 STATUSBAR_PLUG_X_POS,
208 STATUSBAR_Y_POS, STATUSBAR_PLUG_WIDTH,
209 STATUSBAR_HEIGHT);
210#ifdef HAVE_USB_POWER
211 else if (bar->info.usb_power)
212 display->mono_bitmap(bitmap_icons_7x8[Icon_USBPlug],
213 STATUSBAR_PLUG_X_POS,
214 STATUSBAR_Y_POS, STATUSBAR_PLUG_WIDTH,
215 STATUSBAR_HEIGHT);
216#endif
217
218 bar->info.redraw_volume = gui_statusbar_icon_volume(bar,
219 bar->info.volume);
220 gui_statusbar_icon_play_state(display, current_playmode() +
221 Icon_Play);
222 switch (bar->info.repeat) {
223#ifdef AB_REPEAT_ENABLE
224 case REPEAT_AB:
225 gui_statusbar_icon_play_mode(display, Icon_RepeatAB);
226 break;
227#endif
228
229 case REPEAT_ONE:
230 gui_statusbar_icon_play_mode(display, Icon_RepeatOne);
231 break;
232
233 case REPEAT_ALL:
234 case REPEAT_SHUFFLE:
235 gui_statusbar_icon_play_mode(display, Icon_Repeat);
236 break;
237 }
238 if (bar->info.shuffle)
239 gui_statusbar_icon_shuffle(display);
240 if (bar->info.keylock)
241 gui_statusbar_icon_lock(display);
242#ifdef HAVE_RTC
243 gui_statusbar_time(display, bar->info.hour, bar->info.minute);
244#endif
245#if CONFIG_LED == LED_VIRTUAL
246 if (bar->info.led)
247 statusbar_led();
248#endif
249 display->update_rect(0, 0, display->width, STATUSBAR_HEIGHT);
250 bar->lastinfo = bar->info;
251#endif
252 }
253
254
255#ifndef HAVE_LCD_BITMAP
256 if (bar->info.battlevel > -1)
257 display->icon(ICON_BATTERY, battery_state);
258 display->icon(ICON_BATTERY_1, bar->info.battlevel > 25);
259 display->icon(ICON_BATTERY_2, bar->info.battlevel > 50);
260 display->icon(ICON_BATTERY_3, bar->info.battlevel > 75);
261
262 display->icon(ICON_VOLUME, true);
263 display->icon(ICON_VOLUME_1, bar->info.volume > 10);
264 display->icon(ICON_VOLUME_2, bar->info.volume > 30);
265 display->icon(ICON_VOLUME_3, bar->info.volume > 50);
266 display->icon(ICON_VOLUME_4, bar->info.volume > 70);
267 display->icon(ICON_VOLUME_5, bar->info.volume > 90);
268
269 display->icon(ICON_PLAY, current_playmode() == STATUS_PLAY);
270 display->icon(ICON_PAUSE, current_playmode() == STATUS_PAUSE);
271
272 display->icon(ICON_REPEAT, global_settings.repeat_mode != REPEAT_OFF);
273 display->icon(ICON_1, global_settings.repeat_mode == REPEAT_ONE);
274
275 display->icon(ICON_RECORD, record);
276 display->icon(ICON_AUDIO, audio);
277 display->icon(ICON_PARAM, param);
278 display->icon(ICON_USB, usb);
279#endif
280}
281
282#ifdef HAVE_LCD_BITMAP
283/* from icon.c */
284/*
285 * Print battery icon to status bar
286 */
287void gui_statusbar_icon_battery(struct screen * display, int percent)
288{
289 int fill;
290 char buffer[5];
291 unsigned int width, height;
292
293 /* fill battery */
294 fill = percent;
295 if (fill < 0)
296 fill = 0;
297 if (fill > 100)
298 fill = 100;
299
300#if defined(HAVE_CHARGE_CTRL) && !defined(SIMULATOR) /* Rec v1 target only */
301 /* show graphical animation when charging instead of numbers */
302 if ((global_settings.battery_display) &&
303 (charge_state != 1) &&
304 (percent > -1)) {
305#else /* all others */
306 if (global_settings.battery_display && (percent > -1)) {
307#endif
308 /* Numeric display */
309 display->setfont(FONT_SYSFIXED);
310 snprintf(buffer, sizeof(buffer), "%3d", fill);
311 display->getstringsize(buffer, &width, &height);
312 if (height <= STATUSBAR_HEIGHT)
313 display->putsxy(STATUSBAR_BATTERY_X_POS
314 + STATUSBAR_BATTERY_WIDTH / 2
315 - width/2, STATUSBAR_Y_POS, buffer);
316 display->setfont(FONT_UI);
317
318 }
319 else {
320 /* draw battery */
321 display->drawrect(STATUSBAR_BATTERY_X_POS, STATUSBAR_Y_POS, 17, 7);
322 display->vline(STATUSBAR_BATTERY_X_POS + 17, STATUSBAR_Y_POS + 2,
323 STATUSBAR_Y_POS + 4);
324
325 fill = fill * 15 / 100;
326 display->fillrect(STATUSBAR_BATTERY_X_POS + 1, STATUSBAR_Y_POS + 1,
327 fill, 5);
328 }
329
330 if (percent == -1) {
331 display->setfont(FONT_SYSFIXED);
332 display->putsxy(STATUSBAR_BATTERY_X_POS + STATUSBAR_BATTERY_WIDTH / 2
333 - 4, STATUSBAR_Y_POS, "?");
334 display->setfont(FONT_UI);
335 }
336}
337
338/*
339 * Print volume gauge to status bar
340 */
341bool gui_statusbar_icon_volume(struct gui_statusbar * bar, int percent)
342{
343 int i;
344 int volume;
345 int vol;
346 char buffer[4];
347 unsigned int width, height;
348 bool needs_redraw = false;
349 int type = global_settings.volume_type;
350 struct screen * display=bar->display;
351
352 volume = percent;
353 if (volume < 0)
354 volume = 0;
355 if (volume > 100)
356 volume = 100;
357
358 if (volume == 0) {
359 display->mono_bitmap(bitmap_icons_7x8[Icon_Mute],
360 STATUSBAR_VOLUME_X_POS + STATUSBAR_VOLUME_WIDTH / 2 - 4,
361 STATUSBAR_Y_POS, 7, STATUSBAR_HEIGHT);
362 }
363 else {
364 /* We want to redraw the icon later on */
365 if (bar->last_volume != volume && bar->last_volume >= 0) {
366 bar->volume_icon_switch_tick = current_tick + HZ;
367 }
368
369 /* If the timeout hasn't yet been reached, we show it numerically
370 and tell the caller that we want to be called again */
371 if (TIME_BEFORE(current_tick,bar->volume_icon_switch_tick)) {
372 type = 1;
373 needs_redraw = true;
374 }
375
376 /* display volume level numerical? */
377 if (type)
378 {
379 display->setfont(FONT_SYSFIXED);
380 snprintf(buffer, sizeof(buffer), "%2d", percent);
381 display->getstringsize(buffer, &width, &height);
382 if (height <= STATUSBAR_HEIGHT)
383 {
384 display->putsxy(STATUSBAR_VOLUME_X_POS
385 + STATUSBAR_VOLUME_WIDTH / 2
386 - width/2, STATUSBAR_Y_POS, buffer);
387 }
388 display->setfont(FONT_UI);
389 } else {
390 /* display volume bar */
391 vol = volume * 14 / 100;
392 for(i=0; i < vol; i++) {
393 display->vline(STATUSBAR_VOLUME_X_POS + i,
394 STATUSBAR_Y_POS + 6 - i / 2,
395 STATUSBAR_Y_POS + 6);
396 }
397 }
398 }
399 bar->last_volume = volume;
400
401 return needs_redraw;
402}
403
404/*
405 * Print play state to status bar
406 */
407void gui_statusbar_icon_play_state(struct screen * display, int state)
408{
409 display->mono_bitmap(bitmap_icons_7x8[state], STATUSBAR_PLAY_STATE_X_POS,
410 STATUSBAR_Y_POS, STATUSBAR_PLAY_STATE_WIDTH,
411 STATUSBAR_HEIGHT);
412}
413
414/*
415 * Print play mode to status bar
416 */
417void gui_statusbar_icon_play_mode(struct screen * display, int mode)
418{
419 display->mono_bitmap(bitmap_icons_7x8[mode], STATUSBAR_PLAY_MODE_X_POS,
420 STATUSBAR_Y_POS, STATUSBAR_PLAY_MODE_WIDTH,
421 STATUSBAR_HEIGHT);
422}
423
424/*
425 * Print shuffle mode to status bar
426 */
427void gui_statusbar_icon_shuffle(struct screen * display)
428{
429 display->mono_bitmap(bitmap_icons_7x8[Icon_Shuffle],
430 STATUSBAR_SHUFFLE_X_POS, STATUSBAR_Y_POS,
431 STATUSBAR_SHUFFLE_WIDTH, STATUSBAR_HEIGHT);
432}
433
434/*
435 * Print lock when keys are locked
436 */
437void gui_statusbar_icon_lock(struct screen * display)
438{
439 display->mono_bitmap(bitmap_icons_5x8[Icon_Lock], STATUSBAR_LOCK_X_POS,
440 STATUSBAR_Y_POS, 5, 8);
441}
442
443#if CONFIG_LED == LED_VIRTUAL
444/*
445 * no real LED: disk activity in status bar
446 */
447void gui_statusbar_led(struct screen * display)
448{
449 display->mono_bitmap(bitmap_icon_disk, STATUSBAR_DISK_X_POS,
450 STATUSBAR_Y_POS, STATUSBAR_DISK_WIDTH(screen->width),
451 STATUSBAR_HEIGHT);
452}
453#endif
454
455
456#ifdef HAVE_RTC
457/*
458 * Print time to status bar
459 */
460void gui_statusbar_time(struct screen * display, int hour, int minute)
461{
462 unsigned char buffer[6];
463 unsigned int width, height;
464 if ( hour >= 0 &&
465 hour <= 23 &&
466 minute >= 0 &&
467 minute <= 59 ) {
468 if ( global_settings.timeformat ) { /* 12 hour clock */
469 hour %= 12;
470 if ( hour == 0 ) {
471 hour += 12;
472 }
473 }
474 snprintf(buffer, sizeof(buffer), "%02d:%02d", hour, minute);
475 }
476 else {
477 strncpy(buffer, "--:--", sizeof buffer);
478 }
479 display->setfont(FONT_SYSFIXED);
480 display->getstringsize(buffer, &width, &height);
481 if (height <= STATUSBAR_HEIGHT) {
482 display->putsxy(STATUSBAR_TIME_X_END(display->width) - width,
483 STATUSBAR_Y_POS, buffer);
484 }
485 display->setfont(FONT_UI);
486
487}
488#endif
489
490#endif /* HAVE_LCD_BITMAP */
491
492void gui_syncstatusbar_init(struct gui_syncstatusbar * bars)
493{
494 int i;
495 for(i = 0;i < NB_SCREENS;++i) {
496 gui_statusbar_init( &(bars->statusbars[i]) );
497 gui_statusbar_set_screen( &(bars->statusbars[i]), &(screens[i]) );
498 }
499}
500
501void gui_syncstatusbar_draw(struct gui_syncstatusbar * bars,
502 bool force_redraw)
503{
504 int i;
505 for(i = 0;i < NB_SCREENS;++i) {
506 gui_statusbar_draw( &(bars->statusbars[i]), force_redraw );
507 }
508}
diff --git a/apps/gui/statusbar.h b/apps/gui/statusbar.h
new file mode 100644
index 0000000000..434d679e29
--- /dev/null
+++ b/apps/gui/statusbar.h
@@ -0,0 +1,107 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 by Kévin FERRARE
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#ifndef _GUI_STATUSBAR_H_
21#define _GUI_STATUSBAR_H_
22
23#include "config.h"
24#include "status.h"
25
26struct status_info {
27 int battlevel;
28 int volume;
29 int hour;
30 int minute;
31 int playmode;
32 int repeat;
33 bool inserted;
34 bool shuffle;
35 bool keylock;
36 bool battery_safe;
37 bool redraw_volume; /* true if the volume gauge needs updating */
38#if CONFIG_LED == LED_VIRTUAL
39 bool led; /* disk LED simulation in the status bar */
40#endif
41#ifdef HAVE_USB_POWER
42 bool usb_power;
43#endif
44};
45
46struct gui_statusbar
47{
48 /* Volume icon stuffs */
49 long volume_icon_switch_tick;
50 int last_volume;
51
52 long battery_icon_switch_tick;
53
54#ifdef HAVE_CHARGING
55 int battery_charge_step;
56#endif
57
58 struct status_info info;
59 struct status_info lastinfo;
60
61 struct screen * display;
62};
63
64/*
65 * Initializes a status bar
66 * - bar : the bar to initialize
67 */
68extern void gui_statusbar_init(struct gui_statusbar * bar);
69
70/*
71 * Attach the status bar to a screen
72 * (The previous screen attachement is lost)
73 * - bar : the statusbar structure
74 * - display : the screen to attach
75 */
76extern void gui_statusbar_set_screen(struct gui_statusbar * bar, struct screen * display);
77
78/*
79 * Draws the status bar on the attached screen
80 * - bar : the statusbar structure
81 */
82extern void gui_statusbar_draw(struct gui_statusbar * bar, bool force_redraw);
83
84void gui_statusbar_icon_battery(struct screen * display, int percent);
85bool gui_statusbar_icon_volume(struct gui_statusbar * bar, int percent);
86void gui_statusbar_icon_play_state(struct screen * display, int state);
87void gui_statusbar_icon_play_mode(struct screen * display, int mode);
88void gui_statusbar_icon_shuffle(struct screen * display);
89void gui_statusbar_icon_lock(struct screen * display);
90#if CONFIG_LED == LED_VIRTUAL
91void gui_statusbar_led(struct screen * display);
92#endif
93
94#ifdef HAVE_RTC
95void gui_statusbar_time(struct screen * display, int hour, int minute);
96#endif
97
98
99struct gui_syncstatusbar
100{
101 struct gui_statusbar statusbars[NB_SCREENS];
102};
103
104extern void gui_syncstatusbar_init(struct gui_syncstatusbar * bars);
105extern void gui_syncstatusbar_draw(struct gui_syncstatusbar * bars, bool force_redraw);
106
107#endif /*_GUI_STATUSBAR_H_*/
diff --git a/apps/status.c b/apps/status.c
index ca4b21833e..9f43c6551d 100644
--- a/apps/status.c
+++ b/apps/status.c
@@ -43,12 +43,12 @@
43#endif 43#endif
44#include "usb.h" 44#include "usb.h"
45 45
46static enum playmode ff_mode; 46enum playmode ff_mode;
47 47
48static long switch_tick; 48long switch_tick;
49static bool battery_state = true; 49bool battery_state = true;
50#ifdef HAVE_CHARGING 50#ifdef HAVE_CHARGING
51static int battery_charge_step = 0; 51int battery_charge_step = 0;
52#endif 52#endif
53 53
54struct status_info { 54struct status_info {
@@ -123,10 +123,10 @@ int current_playmode(void)
123} 123}
124 124
125#if defined(HAVE_LCD_CHARCELLS) 125#if defined(HAVE_LCD_CHARCELLS)
126static bool record = false; 126bool record = false;
127static bool audio = false; 127bool audio = false;
128static bool param = false; 128bool param = false;
129static bool usb = false; 129bool usb = false;
130 130
131void status_set_record(bool b) 131void status_set_record(bool b)
132{ 132{
diff --git a/apps/status.h b/apps/status.h
index 0d8c80d7a8..29316f98b1 100644
--- a/apps/status.h
+++ b/apps/status.h
@@ -19,6 +19,21 @@
19#ifndef _STATUS_H 19#ifndef _STATUS_H
20#define _STATUS_H 20#define _STATUS_H
21 21
22extern enum playmode ff_mode;
23
24extern long switch_tick;
25extern bool battery_state;
26#ifdef HAVE_CHARGING
27extern int battery_charge_step;
28#endif
29
30#if defined(HAVE_LCD_CHARCELLS)
31extern bool record;
32extern bool audio;
33extern bool param;
34extern bool usb;
35#endif
36
22enum playmode 37enum playmode
23{ 38{
24 STATUS_PLAY, 39 STATUS_PLAY,
@@ -33,10 +48,12 @@ enum playmode
33void status_init(void); 48void status_init(void);
34void status_set_ffmode(enum playmode mode); 49void status_set_ffmode(enum playmode mode);
35enum playmode status_get_ffmode(void); 50enum playmode status_get_ffmode(void);
51int current_playmode(void);
52
36#ifdef HAVE_LCD_BITMAP 53#ifdef HAVE_LCD_BITMAP
37bool statusbar(bool state); 54bool statusbar(bool state);
38#if CONFIG_KEYPAD == RECORDER_PAD 55#if CONFIG_KEYPAD == RECORDER_PAD
39void buttonbar_set(const char* caption1, const char* caption2, 56void buttonbar_set(const char* caption1, const char* caption2,
40 const char* caption3); 57 const char* caption3);
41void buttonbar_unset(void); 58void buttonbar_unset(void);
42bool buttonbar_isset(void); 59bool buttonbar_isset(void);
diff --git a/apps/tree.c b/apps/tree.c
index 8d68814315..7d4ee7f703 100644
--- a/apps/tree.c
+++ b/apps/tree.c
@@ -63,6 +63,12 @@
63#include "rtc.h" 63#include "rtc.h"
64#include "dircache.h" 64#include "dircache.h"
65 65
66/* gui api */
67#include "list.h"
68#include "statusbar.h"
69#include "splash.h"
70#include "buttonbar.h"
71
66#ifdef HAVE_LCD_BITMAP 72#ifdef HAVE_LCD_BITMAP
67#include "widgets.h" 73#include "widgets.h"
68#endif 74#endif
@@ -99,6 +105,14 @@ const struct filetype filetypes[] = {
99#endif /* #ifndef SIMULATOR */ 105#endif /* #ifndef SIMULATOR */
100}; 106};
101 107
108struct gui_synclist tree_lists;
109
110/* I put it here because other files doesn't use it yet,
111 * but should be elsewhere since it will be used mostly everywhere */
112struct gui_syncstatusbar statusbars;
113#ifdef HAS_BUTTONBAR
114struct gui_buttonbar tree_buttonbar;
115#endif
102static struct tree_context tc; 116static struct tree_context tc;
103 117
104bool boot_changed = false; 118bool boot_changed = false;
@@ -112,17 +126,77 @@ static bool reload_dir = false;
112 126
113static bool start_wps = false; 127static bool start_wps = false;
114static bool dirbrowse(void); 128static bool dirbrowse(void);
115static int curr_context = false; 129static int curr_context = false;/* id3db or tree*/
130
131/*
132 * removes the extension of filename (if it doesn't start with a .)
133 * puts the result in buffer
134 */
135char * strip_extension(char * filename, char * buffer)
136{
137 int dotpos;
138 char * dot=strrchr(filename, '.');
139 if(dot!=0 && filename[0]!='.')
140 {
141 dotpos = dot-filename;
142 strncpy(buffer, filename, dotpos);
143 buffer[dotpos]='\0';
144 return(buffer);
145 }
146 else
147 return(filename);
148}
149char * tree_get_filename(int selected_item, char *buffer)
150{
151 char *name;
152 int attr=0;
153 bool id3db = *tc.dirfilter == SHOW_ID3DB;
154 if (id3db) {
155 name = ((char**)tc.dircache)[selected_item * tc.dentry_size];
156 }
157 else {
158 struct entry* dc = tc.dircache;
159 struct entry* e = &dc[selected_item];
160 name = e->name;
161 attr = e->attr;
162 }
163 /* if any file filter is on, and if it's not a directory,
164 * strip the extension */
165
166 if ( (*tc.dirfilter != SHOW_ID3DB) && !(attr & ATTR_DIRECTORY)
167 && (*tc.dirfilter != SHOW_ALL) )
168 {
169 return(strip_extension(name, buffer));
170 }
171 return(name);
172}
173
174
175void tree_get_fileicon(int selected_item, ICON * icon)
176{
177 bool id3db = *tc.dirfilter == SHOW_ID3DB;
178 if (id3db) {
179 *icon = db_get_icon(&tc);
180 }
181 else {
182 struct entry* dc = tc.dircache;
183 struct entry* e = &dc[selected_item];
184 *icon = filetype_get_icon(e->attr);
185 }
186}
116 187
117bool check_rockboxdir(void) 188bool check_rockboxdir(void)
118{ 189{
119 DIR *dir = opendir(ROCKBOX_DIR); 190 DIR *dir = opendir(ROCKBOX_DIR);
120 if(!dir) 191 if(!dir)
121 { 192 {
122 lcd_clear_display(); 193 int i;
123 splash(HZ*2, true, str(LANG_NO_ROCKBOX_DIR)); 194 for(i = 0;i < NB_SCREENS;++i)
124 lcd_clear_display(); 195 screens[i].clear_display();
125 splash(HZ*2, true, str(LANG_INSTALLATION_INCOMPLETE)); 196 gui_syncsplash(HZ*2, true, str(LANG_NO_ROCKBOX_DIR));
197 for(i = 0;i < NB_SCREENS;++i)
198 screens[i].clear_display();
199 gui_syncsplash(HZ*2, true, str(LANG_INSTALLATION_INCOMPLETE));
126 return false; 200 return false;
127 } 201 }
128 closedir(dir); 202 closedir(dir);
@@ -131,16 +205,28 @@ bool check_rockboxdir(void)
131 205
132void browse_root(void) 206void browse_root(void)
133{ 207{
208 /* essential to all programs that wants to display things */
209 screen_access_init();
210
134 filetype_init(); 211 filetype_init();
135 check_rockboxdir(); 212 check_rockboxdir();
136 213
137 strcpy(tc.currdir, "/"); 214 strcpy(tc.currdir, "/");
215
138#ifdef HAVE_LCD_CHARCELLS 216#ifdef HAVE_LCD_CHARCELLS
139 lcd_double_height(false); 217 int i;
218 for(i = 0;i < NB_SCREENS;++i)
219 screens[i].double_height(false);
140#endif 220#endif
221#ifdef HAS_BUTTONBAR
222 gui_buttonbar_init(&tree_buttonbar);
223 /* since archos only have one screen, no need to create more than that */
224 gui_buttonbar_set_display(&tree_buttonbar, &(screens[SCREEN_MAIN]) );
225#endif
226 gui_syncstatusbar_init(&statusbars);
227 gui_synclist_init(&tree_lists, &tree_get_fileicon, &tree_get_filename);
141#ifndef SIMULATOR 228#ifndef SIMULATOR
142 dirbrowse(); 229 dirbrowse();
143
144#else 230#else
145 if (!dirbrowse()) { 231 if (!dirbrowse()) {
146 DEBUGF("No filesystem found. Have you forgotten to create it?\n"); 232 DEBUGF("No filesystem found. Have you forgotten to create it?\n");
@@ -159,126 +245,35 @@ struct tree_context* tree_get_context(void)
159 return &tc; 245 return &tc;
160} 246}
161 247
162#ifdef HAVE_LCD_BITMAP
163
164/* pixel margins */
165#define MARGIN_X (global_settings.scrollbar && \
166 tc.filesindir > tree_max_on_screen ? SCROLLBAR_WIDTH : 0) + \
167 CURSOR_WIDTH + (global_settings.show_icons && ICON_WIDTH > 0 ? ICON_WIDTH :0)
168#define MARGIN_Y (global_settings.statusbar ? STATUSBAR_HEIGHT : 0)
169
170/* position the entry-list starts at */
171#define LINE_X 0
172#define LINE_Y (global_settings.statusbar ? 1 : 0)
173
174#define CURSOR_X (global_settings.scrollbar && \
175 tc.filesindir > tree_max_on_screen ? 1 : 0)
176#define CURSOR_Y 0 /* the cursor is not positioned in regard to
177 the margins, so this is the amount of lines
178 we add to the cursor Y position to position
179 it on a line */
180#define CURSOR_WIDTH (global_settings.invert_cursor ? 0 : 4)
181
182#define ICON_WIDTH 6
183
184#define SCROLLBAR_X 0
185#define SCROLLBAR_Y lcd_getymargin()
186#define SCROLLBAR_WIDTH 6
187
188#else /* HAVE_LCD_BITMAP */
189
190#define TREE_MAX_ON_SCREEN 2
191#define TREE_MAX_LEN_DISPLAY 11 /* max length that fits on screen */
192#define LINE_X 2 /* X position the entry-list starts at */
193#define LINE_Y 0 /* Y position the entry-list starts at */
194
195#define CURSOR_X 0
196#define CURSOR_Y 0 /* not really used for players */
197
198#endif /* HAVE_LCD_BITMAP */
199
200/* talkbox hovering delay, to avoid immediate disk activity */ 248/* talkbox hovering delay, to avoid immediate disk activity */
201#define HOVER_DELAY (HZ/2) 249#define HOVER_DELAY (HZ/2)
202 250/*
203static void showfileline(int line, char* name, int attr, bool scroll) 251 * Returns the position of a given file in the current directory
252 * returns -1 if not found
253 */
254int tree_get_file_position(char * filename)
204{ 255{
205 int xpos = LINE_X; 256 int i;
206 char* dotpos = NULL; 257 /* use lastfile to determine the selected item (default=0) */
207 258 for (i=0; i < tc.filesindir; i++)
208#ifdef HAVE_LCD_CHARCELLS
209 if (!global_settings.show_icons)
210 xpos--;
211#endif
212
213 /* if any file filter is on, strip the extension */
214 if (*tc.dirfilter != SHOW_ID3DB &&
215 *tc.dirfilter != SHOW_ALL &&
216 !(attr & ATTR_DIRECTORY))
217 { 259 {
218 dotpos = strrchr(name, '.'); 260 struct entry* dc = tc.dircache;
219 if (dotpos) { 261 struct entry* e = &dc[i];
220 *dotpos = 0; 262 if (!strcasecmp(e->name, filename))
221 } 263 return(i);
222 } 264 }
223 265 return(-1);/* no file can match, returns undefined */
224 if(scroll) {
225#ifdef HAVE_LCD_BITMAP
226 lcd_setfont(FONT_UI);
227 if (global_settings.invert_cursor)
228 lcd_puts_scroll_style(xpos, line, name, STYLE_INVERT);
229 else
230#endif
231 lcd_puts_scroll(xpos, line, name);
232 } else
233 lcd_puts(xpos, line, name);
234
235 /* Restore the dot before the extension if it was removed */
236 if (dotpos)
237 *dotpos = '.';
238}
239
240#ifdef HAVE_LCD_BITMAP
241static int recalc_screen_height(void)
242{
243 int fw, fh;
244 int height = LCD_HEIGHT;
245
246 lcd_setfont(FONT_UI);
247 lcd_getstringsize("A", &fw, &fh);
248 if(global_settings.statusbar)
249 height -= STATUSBAR_HEIGHT;
250
251#if CONFIG_KEYPAD == RECORDER_PAD
252 if(global_settings.buttonbar)
253 height -= BUTTONBAR_HEIGHT;
254#endif
255
256 return height / fh;
257} 266}
258#endif
259 267
260static int showdir(void) 268/*
269 * Called when a new dir is loaded (for example when returning from other apps ...)
270 * also completely redraws the tree
271 */
272static int update_dir(void)
261{ 273{
262 struct entry *dircache = tc.dircache;
263 int i;
264 int tree_max_on_screen;
265 int start = tc.dirstart;
266 bool id3db = *tc.dirfilter == SHOW_ID3DB; 274 bool id3db = *tc.dirfilter == SHOW_ID3DB;
267 bool newdir = false; 275 bool changed = false;
268#ifdef HAVE_LCD_BITMAP 276 /* Checks for changes */
269 const char* icon;
270 int line_height;
271 int fw, fh;
272 lcd_setfont(FONT_UI);
273 lcd_getstringsize("A", &fw, &fh);
274 tree_max_on_screen = recalc_screen_height();
275 line_height = fh;
276#else
277 int icon;
278 tree_max_on_screen = TREE_MAX_ON_SCREEN;
279#endif
280
281 /* new file dir? load it */
282 if (id3db) { 277 if (id3db) {
283 if (tc.currtable != lasttable || 278 if (tc.currtable != lasttable ||
284 tc.currextra != lastextra || 279 tc.currextra != lastextra ||
@@ -286,151 +281,73 @@ static int showdir(void)
286 { 281 {
287 if (db_load(&tc) < 0) 282 if (db_load(&tc) < 0)
288 return -1; 283 return -1;
284
289 lasttable = tc.currtable; 285 lasttable = tc.currtable;
290 lastextra = tc.currextra; 286 lastextra = tc.currextra;
291 lastfirstpos = tc.firstpos; 287 lastfirstpos = tc.firstpos;
292 newdir = true; 288 changed = true;
293 } 289 }
294 } 290 }
295 else { 291 else {
292 /* if the tc.currdir has been changed, reload it ...*/
296 if (strncmp(tc.currdir, lastdir, sizeof(lastdir)) || reload_dir) { 293 if (strncmp(tc.currdir, lastdir, sizeof(lastdir)) || reload_dir) {
297 if (ft_load(&tc, NULL) < 0) 294
295 if (ft_load(&tc, NULL) < 0)
298 return -1; 296 return -1;
299 strcpy(lastdir, tc.currdir); 297 strcpy(lastdir, tc.currdir);
300 newdir = true; 298 changed = true;
301 } 299 }
302 } 300 }
303 301 /* if selected item is undefined */
304 if (newdir && !id3db && 302 if (tc.selected_item == -1)
305 (tc.dirfull || tc.filesindir == global_settings.max_files_in_dir) )
306 { 303 {
307#ifdef HAVE_LCD_CHARCELLS 304 /* use lastfile to determine the selected item */
308 lcd_double_height(false); 305 tc.selected_item = tree_get_file_position(lastfile);
309#endif
310 lcd_clear_display();
311 lcd_puts(0,0,str(LANG_SHOWDIR_ERROR_BUFFER));
312 lcd_puts(0,1,str(LANG_SHOWDIR_ERROR_FULL));
313 lcd_update();
314 sleep(HZ*2);
315 lcd_clear_display();
316 }
317
318 if (start == -1)
319 {
320 int diff_files;
321
322 /* use lastfile to determine start (default=0) */
323 start = 0;
324
325 for (i=0; i < tc.filesindir; i++)
326 {
327 struct entry *dircache = tc.dircache;
328
329 if (!strcasecmp(dircache[i].name, lastfile))
330 {
331 start = i;
332 break;
333 }
334 }
335
336 diff_files = tc.filesindir - start;
337 if (diff_files < tree_max_on_screen)
338 {
339 int oldstart = start;
340
341 start -= (tree_max_on_screen - diff_files);
342 if (start < 0)
343 start = 0;
344 306
345 tc.dircursor = oldstart - start; 307 /* If the file doesn't exists, select the first one (default) */
346 } 308 if(tc.selected_item < 0)
347 309 tc.selected_item = 0;
348 tc.dirstart = start; 310 changed = true;
349 } 311 }
350 312 if (changed)
351 /* The cursor might point to an invalid line, for example if someone
352 deleted the last file in the dir */
353 if (tc.filesindir)
354 { 313 {
355 while (start + tc.dircursor >= tc.filesindir) 314 if(!id3db && (tc.dirfull ||
315 tc.filesindir == global_settings.max_files_in_dir) )
356 { 316 {
357 if (start) 317 /* dir full */
358 start--; 318 int i;
359 else 319 for(i = 0;i < NB_SCREENS;++i)
360 if (tc.dircursor) 320 {
361 tc.dircursor--;
362 }
363 tc.dirstart = start;
364 }
365
366#ifdef HAVE_LCD_CHARCELLS 321#ifdef HAVE_LCD_CHARCELLS
367 lcd_stop_scroll(); 322 screens[i].double_height(false);
368 lcd_double_height(false);
369#endif
370 lcd_clear_display();
371#ifdef HAVE_LCD_BITMAP
372 lcd_setmargins(MARGIN_X,MARGIN_Y); /* leave room for cursor and icon */
373 lcd_setfont(FONT_UI);
374#endif 323#endif
375 324 screens[i].clear_display();
376 325 screens[i].puts(0,0,str(LANG_SHOWDIR_ERROR_BUFFER));
377 for ( i=start; i < start+tree_max_on_screen && i < tc.filesindir; i++ ) { 326 screens[i].puts(0,1,str(LANG_SHOWDIR_ERROR_FULL));
378 int line = i - start; 327#if defined(HAVE_LCD_BITMAP) || defined(SIMULATOR)
379 char* name; 328 screens[i].update();
380 int attr = 0;
381
382 if (id3db) {
383 name = ((char**)tc.dircache)[i * tc.dentry_size];
384 icon = db_get_icon(&tc);
385 }
386 else {
387 struct entry* dc = tc.dircache;
388 struct entry* e = &dc[i];
389 name = e->name;
390 attr = e->attr;
391 icon = filetype_get_icon(dircache[i].attr);
392 }
393
394
395 if (icon && global_settings.show_icons) {
396#ifdef HAVE_LCD_BITMAP
397 int offset=0;
398 if ( line_height > 8 )
399 offset = (line_height - 8) / 2;
400 lcd_mono_bitmap(icon,
401 CURSOR_X * 6 + CURSOR_WIDTH,
402 MARGIN_Y+(i-start)*line_height + offset, 6, 8);
403#else
404 if (icon < 0 )
405 icon = Icon_Unknown;
406 lcd_putc(LINE_X-1, i-start, icon);
407#endif 329#endif
330 }
331 sleep(HZ*2);
332 for(i = 0;i < NB_SCREENS;++i)
333 screens[i].clear_display();
408 } 334 }
409
410 showfileline(line, name, attr, false); /* no scroll */
411 } 335 }
412 336 gui_synclist_set_nb_items(&tree_lists, tc.filesindir);
413#ifdef HAVE_LCD_BITMAP 337 gui_synclist_select_item(&tree_lists, tc.selected_item);
414 if (global_settings.scrollbar && (tc.dirlength > tree_max_on_screen)) 338 gui_synclist_draw(&tree_lists);
415 scrollbar(SCROLLBAR_X, SCROLLBAR_Y, SCROLLBAR_WIDTH - 1, 339 gui_syncstatusbar_draw(&statusbars, true);
416 tree_max_on_screen * line_height, tc.dirlength, 340#ifdef HAS_BUTTONBAR
417 start + tc.firstpos,
418 start + tc.firstpos + tree_max_on_screen, VERTICAL);
419
420#if CONFIG_KEYPAD == RECORDER_PAD
421 if (global_settings.buttonbar) { 341 if (global_settings.buttonbar) {
422 if (*tc.dirfilter < NUM_FILTER_MODES) 342 if (*tc.dirfilter < NUM_FILTER_MODES)
423 buttonbar_set(str(LANG_DIRBROWSE_F1), 343 gui_buttonbar_set(&tree_buttonbar, str(LANG_DIRBROWSE_F1),
424 str(LANG_DIRBROWSE_F2), 344 str(LANG_DIRBROWSE_F2),
425 str(LANG_DIRBROWSE_F3)); 345 str(LANG_DIRBROWSE_F3));
426 else 346 else
427 buttonbar_set("<<<", "", ""); 347 gui_buttonbar_set(&tree_buttonbar, "<<<", "", "");
428 buttonbar_draw(); 348 gui_buttonbar_draw(&tree_buttonbar);
429 } 349 }
430#endif 350#endif
431#endif
432 status_draw(true);
433
434 return tc.filesindir; 351 return tc.filesindir;
435} 352}
436 353
@@ -468,7 +385,6 @@ void reload_directory(void)
468static void start_resume(bool just_powered_on) 385static void start_resume(bool just_powered_on)
469{ 386{
470 bool do_resume = false; 387 bool do_resume = false;
471
472 if ( global_settings.resume_index != -1 ) { 388 if ( global_settings.resume_index != -1 ) {
473 DEBUGF("Resume index %X offset %X\n", 389 DEBUGF("Resume index %X offset %X\n",
474 global_settings.resume_index, 390 global_settings.resume_index,
@@ -486,7 +402,7 @@ static void start_resume(bool just_powered_on)
486 do_resume = true; 402 do_resume = true;
487 403
488 if (! do_resume) return; 404 if (! do_resume) return;
489 405
490 if (playlist_resume() != -1) 406 if (playlist_resume() != -1)
491 { 407 {
492 playlist_start(global_settings.resume_index, 408 playlist_start(global_settings.resume_index,
@@ -496,23 +412,23 @@ static void start_resume(bool just_powered_on)
496 } 412 }
497 else return; 413 else return;
498 } else if (! just_powered_on) { 414 } else if (! just_powered_on) {
499 splash(HZ*2, true, str(LANG_NOTHING_TO_RESUME)); 415 gui_syncsplash(HZ*2, true, str(LANG_NOTHING_TO_RESUME));
500 } 416 }
501} 417}
502 418
419/* Selects a file and update tree context properly */
503void set_current_file(char *path) 420void set_current_file(char *path)
504{ 421{
505 char *name; 422 char *name;
506 unsigned int i; 423 int i;
507 424
508 /* in ID3DB mode it is a bad idea to call this function */ 425 /* in ID3DB mode it is a bad idea to call this function */
509 /* (only happens with `follow playlist') */ 426 /* (only happens with `follow playlist') */
510 if( *tc.dirfilter == SHOW_ID3DB ) 427 if( *tc.dirfilter == SHOW_ID3DB )
511 {
512 return; 428 return;
513 }
514 429
515 /* separate directory from filename */ 430 /* separate directory from filename */
431 /* gets the directory's name and put it into tc.currdir */
516 name = strrchr(path+1,'/'); 432 name = strrchr(path+1,'/');
517 if (name) 433 if (name)
518 { 434 {
@@ -528,24 +444,27 @@ void set_current_file(char *path)
528 } 444 }
529 445
530 strcpy(lastfile, name); 446 strcpy(lastfile, name);
447
448 /* undefined item selected */
449 tc.selected_item = -1;
531 450
532 tc.dircursor = 0; 451 /* If we changed dir we must recalculate the dirlevel
533 tc.dirstart = -1; 452 and adjust the selected history properly */
534
535 if (strncmp(tc.currdir,lastdir,sizeof(lastdir))) 453 if (strncmp(tc.currdir,lastdir,sizeof(lastdir)))
536 { 454 {
537 tc.dirlevel = 0; 455 tc.dirlevel = 0;
538 tc.dirpos[tc.dirlevel] = -1; 456 tc.selected_item_history[tc.dirlevel] = -1;
539 tc.cursorpos[tc.dirlevel] = 0;
540 457
541 /* use '/' to calculate dirlevel */ 458 /* use '/' to calculate dirlevel */
542 for (i=1; i<strlen(path)+1; i++) 459 /* FIXME : strlen(path) : crazy oO better to store it at
460 the beginning */
461 int path_len = strlen(path) + 1;
462 for (i = 1; i < path_len; i++)
543 { 463 {
544 if (path[i] == '/') 464 if (path[i] == '/')
545 { 465 {
546 tc.dirlevel++; 466 tc.dirlevel++;
547 tc.dirpos[tc.dirlevel] = -1; 467 tc.selected_item_history[tc.dirlevel] = -1;
548 tc.cursorpos[tc.dirlevel] = 0;
549 } 468 }
550 } 469 }
551 } 470 }
@@ -567,24 +486,20 @@ static bool check_changed_id3mode(bool currmode)
567 } 486 }
568 return currmode; 487 return currmode;
569} 488}
570 489/* main loop, handles key events */
571static bool dirbrowse(void) 490static bool dirbrowse(void)
572{ 491{
573 int numentries=0; 492 int numentries=0;
574 char buf[MAX_PATH]; 493 char buf[MAX_PATH];
575 int i; 494 int lasti = -1;
576 int lasti=-1;
577 unsigned button; 495 unsigned button;
578 int tree_max_on_screen;
579 bool reload_root = false; 496 bool reload_root = false;
580 int lastfilter = *tc.dirfilter; 497 int lastfilter = *tc.dirfilter;
581 bool lastsortcase = global_settings.sort_case; 498 bool lastsortcase = global_settings.sort_case;
582 int lastdircursor=-1;
583 bool need_update = true; 499 bool need_update = true;
584 bool exit_func = false; 500 bool exit_func = false;
585 long thumbnail_time = -1; /* for delaying a thumbnail */ 501 long thumbnail_time = -1; /* for delaying a thumbnail */
586 bool update_all = false; /* set this to true when the whole file list 502
587 has been refreshed on screen */
588 unsigned lastbutton = 0; 503 unsigned lastbutton = 0;
589 char* currdir = tc.currdir; /* just a shortcut */ 504 char* currdir = tc.currdir; /* just a shortcut */
590 bool id3db = *tc.dirfilter == SHOW_ID3DB; 505 bool id3db = *tc.dirfilter == SHOW_ID3DB;
@@ -593,15 +508,10 @@ static bool dirbrowse(void)
593 curr_context=CONTEXT_ID3DB; 508 curr_context=CONTEXT_ID3DB;
594 else 509 else
595 curr_context=CONTEXT_TREE; 510 curr_context=CONTEXT_TREE;
596
597#ifdef HAVE_LCD_BITMAP 511#ifdef HAVE_LCD_BITMAP
598 tree_max_on_screen = recalc_screen_height(); 512 screen_access_update_nb_lines();
599#else
600 tree_max_on_screen = TREE_MAX_ON_SCREEN;
601#endif 513#endif
602 514 tc.selected_item = 0;
603 tc.dircursor=0;
604 tc.dirstart=0;
605 tc.dirlevel=0; 515 tc.dirlevel=0;
606 tc.firstpos=0; 516 tc.firstpos=0;
607 lasttable = -1; 517 lasttable = -1;
@@ -624,25 +534,21 @@ static bool dirbrowse(void)
624 start_resume(true); 534 start_resume(true);
625 535
626 } 536 }
627 537 /* If we don't need to show the wps, draw the dir */
628 if (!start_wps) { 538 if (!start_wps) {
629 numentries = showdir(); 539 numentries = update_dir();
630 if (numentries == -1) 540 if (numentries == -1)
631 return false; /* currdir is not a directory */ 541 return false; /* currdir is not a directory */
632 542
633 if (*tc.dirfilter > NUM_FILTER_MODES && numentries==0) 543 if (*tc.dirfilter > NUM_FILTER_MODES && numentries==0)
634 { 544 {
635 splash(HZ*2, true, str(LANG_NO_FILES)); 545 gui_syncsplash(HZ*2, true, str(LANG_NO_FILES));
636 return false; /* No files found for rockbox_browser() */ 546 return false; /* No files found for rockbox_browser() */
637 } 547 }
638 update_all = true;
639
640 put_cursorxy(CURSOR_X, CURSOR_Y + tc.dircursor, true);
641 } 548 }
642 549
643 while(1) { 550 while(1) {
644 struct entry *dircache = tc.dircache; 551 struct entry *dircache = tc.dircache;
645
646 bool restore = false; 552 bool restore = false;
647 553
648 button = button_get_w_tmo(HZ/5); 554 button = button_get_w_tmo(HZ/5);
@@ -651,15 +557,18 @@ static bool dirbrowse(void)
651 if (boot_changed) { 557 if (boot_changed) {
652 bool stop = false; 558 bool stop = false;
653 unsigned int button; 559 unsigned int button;
654 560 int i;
655 lcd_clear_display(); 561 for(i = 0;i < NB_SCREENS;++i)
656 lcd_puts(0,0,str(LANG_BOOT_CHANGED)); 562 {
657 lcd_puts(0,1,str(LANG_REBOOT_NOW)); 563 screens[i].clear_display();
564 screens[i].puts(0,0,str(LANG_BOOT_CHANGED));
565 screens[i].puts(0,1,str(LANG_REBOOT_NOW));
658#ifdef HAVE_LCD_BITMAP 566#ifdef HAVE_LCD_BITMAP
659 lcd_puts(0,3,str(LANG_CONFIRM_WITH_PLAY_RECORDER)); 567 screens[i].puts(0,3,str(LANG_CONFIRM_WITH_PLAY_RECORDER));
660 lcd_puts(0,4,str(LANG_CANCEL_WITH_ANY_RECORDER)); 568 screens[i].puts(0,4,str(LANG_CANCEL_WITH_ANY_RECORDER));
661 lcd_update(); 569 screens[i].update();
662#endif 570#endif
571 }
663 while (!stop) { 572 while (!stop) {
664 button = button_get(true); 573 button = button_get(true);
665 switch (button) { 574 switch (button) {
@@ -683,6 +592,7 @@ static bool dirbrowse(void)
683 boot_changed = false; 592 boot_changed = false;
684 } 593 }
685#endif 594#endif
595 need_update = gui_synclist_do_button(&tree_lists, button);
686 596
687 switch ( button ) { 597 switch ( button ) {
688#ifdef TREE_ENTER 598#ifdef TREE_ENTER
@@ -702,33 +612,17 @@ static bool dirbrowse(void)
702 && (lastbutton != TREE_RUN_PRE))) 612 && (lastbutton != TREE_RUN_PRE)))
703 break; 613 break;
704#endif 614#endif
705 if ( !numentries ) 615 /* nothing to do if no files to display */
616 if ( numentries == 0 )
706 break; 617 break;
707 618
708 if (id3db) 619 switch (id3db?db_enter(&tc):ft_enter(&tc))
709 i = db_enter(&tc);
710 else
711 i = ft_enter(&tc);
712
713 switch (i)
714 { 620 {
715 case 1: reload_dir = true; break; 621 case 1: reload_dir = true; break;
716 case 2: start_wps = true; break; 622 case 2: start_wps = true; break;
717 case 3: exit_func = true; break; 623 case 3: exit_func = true; break;
718 default: break; 624 default: break;
719 } 625 }
720
721#ifdef HAVE_LCD_BITMAP
722 /* maybe we have a new font */
723 tree_max_on_screen = recalc_screen_height();
724#endif
725 /* make sure cursor is on screen */
726 while ( tc.dircursor > tree_max_on_screen )
727 {
728 tc.dircursor--;
729 tc.dirstart++;
730 }
731
732 restore = true; 626 restore = true;
733 break; 627 break;
734 628
@@ -741,8 +635,8 @@ static bool dirbrowse(void)
741 exit_func = true; 635 exit_func = true;
742 break; 636 break;
743 } 637 }
744 638 /* if we are in /, nothing to do */
745 if (!tc.dirlevel) 639 if (tc.dirlevel == 0)
746 break; 640 break;
747 641
748 if (id3db) 642 if (id3db)
@@ -783,169 +677,6 @@ static bool dirbrowse(void)
783 break; 677 break;
784#endif 678#endif
785#endif 679#endif
786
787 case TREE_PREV:
788 case TREE_PREV | BUTTON_REPEAT:
789#ifdef TREE_RC_PREV
790 case TREE_RC_PREV:
791 case TREE_RC_PREV | BUTTON_REPEAT:
792#endif
793 if (!tc.filesindir)
794 break;
795
796 /* start scrolling when at 1/3 of the screen */
797 if (tc.dircursor >=
798 tree_max_on_screen - (2 * tree_max_on_screen) / 3
799 || (tc.dirstart == 0 && tc.dircursor > 0)) {
800 put_cursorxy(CURSOR_X, CURSOR_Y + tc.dircursor, false);
801 tc.dircursor--;
802 put_cursorxy(CURSOR_X, CURSOR_Y + tc.dircursor, true);
803 }
804 else {
805 if (tc.dirstart || tc.firstpos) {
806 if (tc.dirstart)
807 tc.dirstart--;
808 else {
809 if (tc.firstpos > max_files/2) {
810 tc.firstpos -= max_files/2;
811 tc.dirstart += max_files/2;
812 tc.dirstart--;
813 }
814 else {
815 tc.dirstart = tc.firstpos - 1;
816 tc.firstpos = 0;
817 }
818 }
819 restore = true;
820 }
821 else {
822 if (button & BUTTON_REPEAT)
823 break;
824 if (numentries < tree_max_on_screen) {
825 put_cursorxy(CURSOR_X, CURSOR_Y + tc.dircursor,
826 false);
827 tc.dircursor = numentries - 1;
828 put_cursorxy(CURSOR_X, CURSOR_Y + tc.dircursor,
829 true);
830 }
831 else if (id3db && tc.dirfull) {
832 /* load last dir segment */
833 /* use max_files/2 in case names are longer than
834 AVERAGE_FILE_LENGTH */
835 tc.firstpos = tc.dirlength - max_files/2;
836 tc.dirstart = tc.firstpos;
837 tc.dircursor = tree_max_on_screen - 1;
838 numentries = showdir();
839 update_all = true;
840 put_cursorxy(CURSOR_X, CURSOR_Y + tc.dircursor,
841 true);
842 }
843 else {
844 tc.dirstart = numentries - tree_max_on_screen;
845 tc.dircursor = tree_max_on_screen - 1;
846 restore = true;
847 }
848 }
849 }
850 need_update = true;
851 break;
852
853 case TREE_NEXT:
854 case TREE_NEXT | BUTTON_REPEAT:
855#ifdef TREE_RC_NEXT
856 case TREE_RC_NEXT:
857 case TREE_RC_NEXT | BUTTON_REPEAT:
858#endif
859 if (!tc.filesindir)
860 break;
861
862 if (tc.dircursor + tc.dirstart + 1 < numentries ) {
863 /* start scrolling when at 2/3 of the screen */
864 if(tc.dircursor < (2 * tree_max_on_screen) / 3 ||
865 numentries - tc.dirstart <= tree_max_on_screen) {
866 put_cursorxy(CURSOR_X, CURSOR_Y + tc.dircursor, false);
867 tc.dircursor++;
868 put_cursorxy(CURSOR_X, CURSOR_Y + tc.dircursor, true);
869 }
870 else {
871 tc.dirstart++;
872 restore = true;
873 }
874 }
875 else if (id3db && (tc.firstpos || tc.dirfull)) {
876 if (tc.dircursor + tc.dirstart + tc.firstpos + 1 >= tc.dirlength) {
877 /* wrap and load first dir segment */
878 if (button & BUTTON_REPEAT)
879 break;
880 tc.firstpos = tc.dirstart = tc.dircursor = 0;
881 }
882 else {
883 /* load next dir segment */
884 tc.firstpos += tc.dirstart;
885 tc.dirstart = 0;
886 }
887 restore = true;
888 }
889 else {
890 if (button & BUTTON_REPEAT)
891 break;
892 if(numentries < tree_max_on_screen) {
893 put_cursorxy(CURSOR_X, CURSOR_Y + tc.dircursor, false);
894 tc.dirstart = tc.dircursor = 0;
895 put_cursorxy(CURSOR_X, CURSOR_Y + tc.dircursor, true);
896 }
897 else {
898 tc.dirstart = tc.dircursor = 0;
899 numentries = showdir();
900 update_all=true;
901 put_cursorxy(CURSOR_X, CURSOR_Y + tc.dircursor, true);
902 }
903 }
904 need_update = true;
905 break;
906
907#ifdef TREE_PGUP
908 case TREE_PGUP:
909 case TREE_PGUP | BUTTON_REPEAT:
910 if (tc.dirstart) {
911 tc.dirstart -= tree_max_on_screen;
912 if ( tc.dirstart < 0 )
913 tc.dirstart = 0;
914 }
915 else if (tc.firstpos) {
916 if (tc.firstpos > max_files/2) {
917 tc.firstpos -= max_files/2;
918 tc.dirstart += max_files/2;
919 tc.dirstart -= tree_max_on_screen;
920 }
921 else {
922 tc.dirstart = tc.firstpos - tree_max_on_screen;
923 tc.firstpos = 0;
924 }
925 }
926 else
927 tc.dircursor = 0;
928 restore = true;
929 break;
930
931 case TREE_PGDN:
932 case TREE_PGDN | BUTTON_REPEAT:
933 if ( tc.dirstart < numentries - tree_max_on_screen ) {
934 tc.dirstart += tree_max_on_screen;
935 if ( tc.dirstart > numentries - tree_max_on_screen )
936 tc.dirstart = numentries - tree_max_on_screen;
937 }
938 else if (id3db && tc.dirfull) {
939 /* load next dir segment */
940 tc.firstpos += tc.dirstart;
941 tc.dirstart = 0;
942 }
943 else
944 tc.dircursor = numentries - tc.dirstart - 1;
945 restore = true;
946 break;
947#endif
948
949 case TREE_MENU: 680 case TREE_MENU:
950#ifdef TREE_RC_MENU 681#ifdef TREE_RC_MENU
951 case TREE_RC_MENU: 682 case TREE_RC_MENU:
@@ -957,7 +688,9 @@ static bool dirbrowse(void)
957 /* don't enter menu from plugin browser */ 688 /* don't enter menu from plugin browser */
958 if (*tc.dirfilter < NUM_FILTER_MODES) 689 if (*tc.dirfilter < NUM_FILTER_MODES)
959 { 690 {
960 lcd_stop_scroll(); 691 int i;
692 for(i = 0;i < NB_SCREENS;++i)
693 screens[i].stop_scroll();
961 if (main_menu()) 694 if (main_menu())
962 reload_dir = true; 695 reload_dir = true;
963 restore = true; 696 restore = true;
@@ -1017,7 +750,7 @@ static bool dirbrowse(void)
1017 { 750 {
1018 if (quick_screen(curr_context, BUTTON_F3)) 751 if (quick_screen(curr_context, BUTTON_F3))
1019 reload_dir = true; 752 reload_dir = true;
1020 tree_max_on_screen = recalc_screen_height(); 753 screen_access_update_nb_lines();
1021 restore = true; 754 restore = true;
1022 } 755 }
1023 break; 756 break;
@@ -1052,20 +785,19 @@ static bool dirbrowse(void)
1052 } 785 }
1053 else 786 else
1054 { 787 {
1055 attr = dircache[tc.dircursor+tc.dirstart].attr; 788 attr = dircache[tc.selected_item].attr;
1056 789
1057 if (currdir[1]) 790 if (currdir[1]) /* Not in / */
1058 snprintf(buf, sizeof buf, "%s/%s", 791 snprintf(buf, sizeof buf, "%s/%s",
1059 currdir, 792 currdir,
1060 dircache[tc.dircursor+tc.dirstart].name); 793 dircache[tc.selected_item].name);
1061 else 794 else /* In / */
1062 snprintf(buf, sizeof buf, "/%s", 795 snprintf(buf, sizeof buf, "/%s",
1063 dircache[tc.dircursor+tc.dirstart].name); 796 dircache[tc.selected_item].name);
1064 } 797 }
1065
1066 onplay_result = onplay(buf, attr, curr_context); 798 onplay_result = onplay(buf, attr, curr_context);
1067 } 799 }
1068 800
1069 switch (onplay_result) 801 switch (onplay_result)
1070 { 802 {
1071 case ONPLAY_OK: 803 case ONPLAY_OK:
@@ -1099,22 +831,22 @@ static bool dirbrowse(void)
1099 } 831 }
1100 } 832 }
1101 else 833 else
1102 { 834 {
1103 DEBUGF("Playing file thumbnail: %s/%s%s\n", 835 DEBUGF("Playing file thumbnail: %s/%s%s\n",
1104 currdir, dircache[lasti].name, file_thumbnail_ext); 836 currdir, dircache[lasti].name, file_thumbnail_ext);
1105 /* no fallback necessary, we knew in advance 837 /* no fallback necessary, we knew in advance
1106 that the file exists */ 838 that the file exists */
1107 ft_play_filename(currdir, dircache[lasti].name); 839 ft_play_filename(currdir, dircache[lasti].name);
1108 } 840 }
1109 thumbnail_time = -1; /* job done */ 841 thumbnail_time = -1; /* job done */
1110 } 842 }
1111 status_draw(false); 843 gui_syncstatusbar_draw(&statusbars, false);
1112 break; 844 break;
1113 845
1114#ifdef HAVE_HOTSWAP 846#ifdef HAVE_HOTSWAP
1115 case SYS_FS_CHANGED: 847 case SYS_FS_CHANGED:
1116 if (!id3db) 848 if (!id3db)
1117 reload_dir = true; 849 reload_dir = true;
1118 /* The 'dir no longer valid' situation will be caught later 850 /* The 'dir no longer valid' situation will be caught later
1119 * by checking the showdir() result. */ 851 * by checking the showdir() result. */
1120 break; 852 break;
@@ -1139,18 +871,20 @@ static bool dirbrowse(void)
1139 lastbutton = button; 871 lastbutton = button;
1140 } 872 }
1141 873
1142 if (start_wps) 874 if (start_wps && audio_status() )
1143 { 875 {
1144 lcd_stop_scroll(); 876 int i;
877 for(i = 0;i < NB_SCREENS;++i)
878 screens[i].stop_scroll();
1145 if (wps_show() == SYS_USB_CONNECTED) 879 if (wps_show() == SYS_USB_CONNECTED)
1146 reload_dir = true; 880 reload_dir = true;
1147#ifdef HAVE_HOTSWAP 881#ifdef HAVE_HOTSWAP
1148 else 882 else
1149 if (!id3db) /* Try reload to catch 'no longer valid' case. */ 883 if (!id3db) /* Try reload to catch 'no longer valid' case. */
1150 reload_dir = true; 884 reload_dir = true;
1151#endif 885#endif
1152#ifdef HAVE_LCD_BITMAP 886#ifdef HAVE_LCD_BITMAP
1153 tree_max_on_screen = recalc_screen_height(); 887 screen_access_update_nb_lines();
1154#endif 888#endif
1155 id3db = check_changed_id3mode(id3db); 889 id3db = check_changed_id3mode(id3db);
1156 restore = true; 890 restore = true;
@@ -1174,8 +908,9 @@ static bool dirbrowse(void)
1174 } 908 }
1175 if (! reload_dir ) 909 if (! reload_dir )
1176 { 910 {
1177 tc.dircursor = 0; 911 gui_synclist_select_item(&tree_lists, 0);
1178 tc.dirstart = 0; 912 gui_synclist_draw(&tree_lists);
913 tc.selected_item = 0;
1179 lastdir[0] = 0; 914 lastdir[0] = 0;
1180 } 915 }
1181 916
@@ -1190,132 +925,88 @@ static bool dirbrowse(void)
1190 925
1191 if (restore || reload_dir) { 926 if (restore || reload_dir) {
1192 /* restore display */ 927 /* restore display */
1193
1194#ifdef HAVE_LCD_BITMAP 928#ifdef HAVE_LCD_BITMAP
1195 tree_max_on_screen = recalc_screen_height(); 929 screen_access_update_nb_lines();
1196#endif 930#endif
1197 931 numentries = update_dir();
1198 /* We need to adjust if the number of lines on screen have
1199 changed because of a status bar change */
1200 if(CURSOR_Y+LINE_Y+tc.dircursor>tree_max_on_screen) {
1201 tc.dirstart++;
1202 tc.dircursor--;
1203 }
1204#ifdef HAVE_LCD_BITMAP
1205 /* the sub-screen might've ruined the margins */
1206 lcd_setmargins(MARGIN_X,MARGIN_Y); /* leave room for cursor and
1207 icon */
1208 lcd_setfont(FONT_UI);
1209#endif
1210 numentries = showdir();
1211 if (currdir[1] && (numentries < 0)) 932 if (currdir[1] && (numentries < 0))
1212 { /* not in root and reload failed */ 933 { /* not in root and reload failed */
1213 reload_root = true; /* try root */ 934 reload_root = true; /* try root */
1214 reload_dir = false; 935 reload_dir = false;
1215 goto check_rescan; 936 goto check_rescan;
1216 } 937 }
1217 update_all = true;
1218 put_cursorxy(CURSOR_X, CURSOR_Y + tc.dircursor, true);
1219
1220 need_update = true; 938 need_update = true;
1221 reload_dir = false; 939 reload_dir = false;
1222 } 940 }
941 if(need_update) {
942 tc.selected_item = gui_synclist_get_selected_item_position(&tree_lists);
943 need_update=false;
944 if ( numentries > 0 ) {
945 /* Voice the file if changed */
946 if(lasti != tc.selected_item || restore) {
947 lasti = tc.selected_item;
948 thumbnail_time = -1; /* Cancel whatever we were
949 about to say */
950
951 /* Directory? */
952 if (dircache[tc.selected_item].attr & ATTR_DIRECTORY)
953 {
954 /* play directory thumbnail */
955 switch (global_settings.talk_dir) {
956 case 1: /* dirs as numbers */
957 talk_id(VOICE_DIR, false);
958 talk_number(tc.selected_item+1, true);
959 break;
1223 960
1224 if ( (numentries > 0) && need_update) { 961 case 2: /* dirs spelled */
1225 i = tc.dirstart+tc.dircursor; 962 talk_spell(dircache[tc.selected_item].name,
1226 963 false);
1227 /* if MP3 filter is on, cut off the extension */ 964 break;
1228 if(lasti!=i || restore) {
1229 char* name;
1230 int attr = 0;
1231
1232 if (id3db)
1233 name = ((char**)tc.dircache)[lasti * tc.dentry_size];
1234 else {
1235 struct entry* dc = tc.dircache;
1236 struct entry* e = &dc[lasti];
1237 name = e->name;
1238 attr = e->attr;
1239 }
1240
1241 lcd_stop_scroll();
1242
1243 /* So if lastdircursor and dircursor differ, and then full
1244 screen was not refreshed, restore the previous line */
1245 if ((lastdircursor != tc.dircursor) && !update_all ) {
1246 showfileline(lastdircursor, name, attr, false); /* no scroll */
1247 }
1248 lasti=i;
1249 lastdircursor=tc.dircursor;
1250 thumbnail_time = -1; /* cancel whatever we were about to say */
1251
1252 if (id3db)
1253 name = ((char**)tc.dircache)[lasti * tc.dentry_size];
1254 else {
1255 struct entry* dc = tc.dircache;
1256 struct entry* e = &dc[lasti];
1257 name = e->name;
1258 attr = e->attr;
1259 }
1260 showfileline(tc.dircursor, name, attr, true); /* scroll please */
1261 need_update = true;
1262
1263 if (dircache[i].attr & ATTR_DIRECTORY) /* directory? */
1264 {
1265 /* play directory thumbnail */
1266 switch (global_settings.talk_dir) {
1267 case 1: /* dirs as numbers */
1268 talk_id(VOICE_DIR, false);
1269 talk_number(i+1, true);
1270 break;
1271
1272 case 2: /* dirs spelled */
1273 talk_spell(dircache[i].name, false);
1274 break;
1275 965
1276 case 3: /* thumbnail clip */ 966 case 3: /* thumbnail clip */
1277 /* "schedule" a thumbnail, to have a little dalay */ 967 /* "schedule" a thumbnail, to have a little
1278 thumbnail_time = current_tick + HOVER_DELAY; 968 delay */
1279 break; 969 thumbnail_time = current_tick + HOVER_DELAY;
970 break;
1280 971
1281 default: 972 default:
1282 break; 973 break;
974 }
1283 } 975 }
1284 } 976 else /* file */
1285 else /* file */ 977 {
1286 { 978 switch (global_settings.talk_file) {
1287 switch (global_settings.talk_file) { 979 case 1: /* files as numbers */
1288 case 1: /* files as numbers */ 980 ft_play_filenumber(
1289 ft_play_filenumber(i-tc.dirsindir+1, 981 tc.selected_item-tc.dirsindir+1,
1290 dircache[i].attr & TREE_ATTR_MASK); 982 dircache[tc.selected_item].attr &
1291 break; 983 TREE_ATTR_MASK);
984 break;
1292 985
1293 case 2: /* files spelled */ 986 case 2: /* files spelled */
1294 talk_spell(dircache[i].name, false); 987 talk_spell(dircache[tc.selected_item].name,
1295 break; 988 false);
989 break;
1296 990
1297 case 3: /* thumbnail clip */ 991 case 3: /* thumbnail clip */
1298 /* "schedule" a thumbnail, to have a little delay */ 992 /* "schedule" a thumbnail, to have a little
1299 if (dircache[i].attr & TREE_ATTR_THUMBNAIL) 993 delay */
1300 thumbnail_time = current_tick + HOVER_DELAY; 994 if (dircache[tc.selected_item].attr &
1301 else 995 TREE_ATTR_THUMBNAIL)
1302 /* spell the number as fallback */ 996 thumbnail_time = current_tick + HOVER_DELAY;
1303 talk_spell(dircache[i].name, false); 997 else
1304 break; 998 /* spell the number as fallback */
999 talk_spell(dircache[tc.selected_item].name,
1000 false);
1001 break;
1305 1002
1306 default: 1003 default:
1307 break; 1004 break;
1005 }
1308 } 1006 }
1309 } 1007 }
1310 } 1008 }
1311 } 1009 }
1312
1313 if(need_update) {
1314 lcd_update();
1315
1316 need_update = false;
1317 update_all = false;
1318 }
1319 } 1010 }
1320 1011
1321 return true; 1012 return true;
@@ -1369,7 +1060,7 @@ static bool add_dir(char* dirname, int len, int fd)
1369 int x = strlen(entry->d_name); 1060 int x = strlen(entry->d_name);
1370 unsigned int i; 1061 unsigned int i;
1371 char *cp = strrchr(entry->d_name,'.'); 1062 char *cp = strrchr(entry->d_name,'.');
1372 1063
1373 if (cp) { 1064 if (cp) {
1374 cp++; 1065 cp++;
1375 1066
@@ -1379,6 +1070,7 @@ static bool add_dir(char* dirname, int len, int fd)
1379 if (!strcasecmp(cp, filetypes[i].extension)) 1070 if (!strcasecmp(cp, filetypes[i].extension))
1380 { 1071 {
1381 char buf[8]; 1072 char buf[8];
1073 int i;
1382 write(fd, dirname, strlen(dirname)); 1074 write(fd, dirname, strlen(dirname));
1383 write(fd, "/", 1); 1075 write(fd, "/", 1);
1384 write(fd, entry->d_name, x); 1076 write(fd, entry->d_name, x);
@@ -1387,8 +1079,11 @@ static bool add_dir(char* dirname, int len, int fd)
1387 plsize++; 1079 plsize++;
1388 snprintf(buf, sizeof buf, "%d", plsize); 1080 snprintf(buf, sizeof buf, "%d", plsize);
1389#ifdef HAVE_LCD_BITMAP 1081#ifdef HAVE_LCD_BITMAP
1390 lcd_puts(0,4,buf); 1082 for(i = 0;i < NB_SCREENS;++i)
1391 lcd_update(); 1083 {
1084 screens[i].puts(0,4,buf);
1085 screens[i].update();
1086 }
1392#else 1087#else
1393 x = 10; 1088 x = 10;
1394 if (plsize > 999) 1089 if (plsize > 999)
@@ -1401,7 +1096,8 @@ static bool add_dir(char* dirname, int len, int fd)
1401 x=9; 1096 x=9;
1402 } 1097 }
1403 } 1098 }
1404 lcd_puts(x,0,buf); 1099 for(i = 0;i < NB_SCREENS;++i)
1100 screens[i].puts(x,0,buf);
1405#endif 1101#endif
1406 break; 1102 break;
1407 } 1103 }
@@ -1418,16 +1114,20 @@ static bool add_dir(char* dirname, int len, int fd)
1418bool create_playlist(void) 1114bool create_playlist(void)
1419{ 1115{
1420 int fd; 1116 int fd;
1117 int i;
1421 char filename[MAX_PATH]; 1118 char filename[MAX_PATH];
1422 1119
1423 snprintf(filename, sizeof filename, "%s.m3u", 1120 snprintf(filename, sizeof filename, "%s.m3u",
1424 tc.currdir[1] ? tc.currdir : "/root"); 1121 tc.currdir[1] ? tc.currdir : "/root");
1425 1122 for(i = 0;i < NB_SCREENS;++i)
1426 lcd_clear_display(); 1123 {
1427 lcd_puts(0,0,str(LANG_CREATING)); 1124 screens[i].clear_display();
1428 lcd_puts_scroll(0,1,filename); 1125 screens[i].puts(0,0,str(LANG_CREATING));
1429 lcd_update(); 1126 screens[i].puts_scroll(0,1,filename);
1430 1127#if defined(HAVE_LCD_BITMAP) || defined(SIMULATOR)
1128 screens[i].update();
1129#endif
1130 }
1431 fd = creat(filename,0); 1131 fd = creat(filename,0);
1432 if (fd < 0) 1132 if (fd < 0)
1433 return false; 1133 return false;
@@ -1435,7 +1135,7 @@ bool create_playlist(void)
1435#ifdef HAVE_ADJUSTABLE_CPU_FREQ 1135#ifdef HAVE_ADJUSTABLE_CPU_FREQ
1436 cpu_boost(true); 1136 cpu_boost(true);
1437#endif 1137#endif
1438 1138
1439 snprintf(filename, sizeof(filename), "%s", 1139 snprintf(filename, sizeof(filename), "%s",
1440 tc.currdir[1] ? tc.currdir : "/"); 1140 tc.currdir[1] ? tc.currdir : "/");
1441 plsize = 0; 1141 plsize = 0;
@@ -1445,7 +1145,7 @@ bool create_playlist(void)
1445#ifdef HAVE_ADJUSTABLE_CPU_FREQ 1145#ifdef HAVE_ADJUSTABLE_CPU_FREQ
1446 cpu_boost(false); 1146 cpu_boost(false);
1447#endif 1147#endif
1448 1148
1449 sleep(HZ); 1149 sleep(HZ);
1450 1150
1451 return true; 1151 return true;
@@ -1460,12 +1160,10 @@ bool rockbox_browse(const char *root, int dirfilter)
1460 memcpy(tc.currdir, root, sizeof(tc.currdir)); 1160 memcpy(tc.currdir, root, sizeof(tc.currdir));
1461 start_wps = false; 1161 start_wps = false;
1462 tc.dirfilter = &dirfilter; 1162 tc.dirfilter = &dirfilter;
1463 1163
1464 dirbrowse(); 1164 dirbrowse();
1465 1165
1466 tc = backup; 1166 tc = backup;
1467 reload_dir = true;
1468
1469 return false; 1167 return false;
1470} 1168}
1471 1169
@@ -1474,7 +1172,7 @@ void tree_init(void)
1474 /* We copy the settings value in case it is changed by the user. We can't 1172 /* We copy the settings value in case it is changed by the user. We can't
1475 use it until the next reboot. */ 1173 use it until the next reboot. */
1476 max_files = global_settings.max_files_in_dir; 1174 max_files = global_settings.max_files_in_dir;
1477 1175
1478 /* initialize tree context struct */ 1176 /* initialize tree context struct */
1479 memset(&tc, 0, sizeof(tc)); 1177 memset(&tc, 0, sizeof(tc));
1480 tc.dirfilter = &global_settings.dirfilter; 1178 tc.dirfilter = &global_settings.dirfilter;
@@ -1498,7 +1196,7 @@ void bookmark_play(char *resume_file, int index, int offset, int seed,
1498 { 1196 {
1499 /* Playlist playback */ 1197 /* Playlist playback */
1500 char* slash; 1198 char* slash;
1501 // check that the file exists 1199 /* check that the file exists */
1502 int fd = open(resume_file, O_RDONLY); 1200 int fd = open(resume_file, O_RDONLY);
1503 if(fd<0) 1201 if(fd<0)
1504 return; 1202 return;
@@ -1538,7 +1236,7 @@ void bookmark_play(char *resume_file, int index, int offset, int seed,
1538 if ((strcmp(strrchr(playlist_peek(index) + 1,'/') + 1, 1236 if ((strcmp(strrchr(playlist_peek(index) + 1,'/') + 1,
1539 filename))) 1237 filename)))
1540 { 1238 {
1541 for ( i=0; i < playlist_amount(); i++ ) 1239 for ( i=0; i < playlist_amount(); i++ )
1542 { 1240 {
1543 if ((strcmp(strrchr(playlist_peek(i) + 1,'/') + 1, 1241 if ((strcmp(strrchr(playlist_peek(i) + 1,'/') + 1,
1544 filename)) == 0) 1242 filename)) == 0)
@@ -1599,7 +1297,7 @@ int ft_play_dirname(int start_index)
1599 } 1297 }
1600 1298
1601 close(fd); 1299 close(fd);
1602 1300
1603 DEBUGF("Found: %s\n", dirname_mp3_filename); 1301 DEBUGF("Found: %s\n", dirname_mp3_filename);
1604 1302
1605 talk_file(dirname_mp3_filename, false); 1303 talk_file(dirname_mp3_filename, false);
@@ -1639,9 +1337,7 @@ void tree_flush(void)
1639 if (global_settings.dircache) 1337 if (global_settings.dircache)
1640 { 1338 {
1641 if (dircache_is_enabled()) 1339 if (dircache_is_enabled())
1642 {
1643 global_settings.dircache_size = dircache_get_cache_size(); 1340 global_settings.dircache_size = dircache_get_cache_size();
1644 }
1645 dircache_disable(); 1341 dircache_disable();
1646 } 1342 }
1647 else 1343 else
@@ -1659,21 +1355,27 @@ void tree_restore(void)
1659#ifdef HAVE_DIRCACHE 1355#ifdef HAVE_DIRCACHE
1660 if (global_settings.dircache) 1356 if (global_settings.dircache)
1661 { 1357 {
1662 int font_w, font_h;
1663
1664 /* Print "Scanning disk..." to the display. */ 1358 /* Print "Scanning disk..." to the display. */
1665 lcd_getstringsize("A", &font_w, &font_h); 1359 int i;
1666 lcd_putsxy((LCD_WIDTH/2) - ((strlen(str(LANG_DIRCACHE_BUILDING))*font_w)/2), 1360 for(i = 0;i < NB_SCREENS;++i)
1667 LCD_HEIGHT-font_h*3, str(LANG_DIRCACHE_BUILDING)); 1361 {
1668 lcd_update(); 1362 screens[i].putsxy((LCD_WIDTH/2) -
1669 1363 ((strlen(str(LANG_DIRCACHE_BUILDING)) *
1364 screens[i].char_width)/2),
1365 LCD_HEIGHT-screens[i].char_height*3,
1366 str(LANG_DIRCACHE_BUILDING));
1367 screens[i].update();
1368 }
1670 dircache_build(global_settings.dircache_size); 1369 dircache_build(global_settings.dircache_size);
1671
1672 /* Clean the text when we are done. */ 1370 /* Clean the text when we are done. */
1673 lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); 1371 for(i=0;i<NB_SCREENS;++i)
1674 lcd_fillrect(0, LCD_HEIGHT-font_h*3, LCD_WIDTH, font_h); 1372 {
1675 lcd_set_drawmode(DRMODE_SOLID); 1373 screens[i].set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
1676 lcd_update(); 1374 screens[i].fillrect(0, LCD_HEIGHT-screens[i].char_height*3,
1375 LCD_WIDTH, screens[i].char_height);
1376 screens[i].set_drawmode(DRMODE_SOLID);
1377 screens[i].update();
1378 }
1677 } 1379 }
1678#endif 1380#endif
1679} 1381}
diff --git a/apps/tree.h b/apps/tree.h
index a6c41f2af5..04532c887d 100644
--- a/apps/tree.h
+++ b/apps/tree.h
@@ -23,6 +23,8 @@
23#include <applimits.h> 23#include <applimits.h>
24#include <file.h> 24#include <file.h>
25 25
26/*FIXME: don't forget to remove PGUP, PGDOW, NEXT, PREV
27 * when everything will be working with gui_list */
26#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ 28#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
27 (CONFIG_KEYPAD == IRIVER_H300_PAD) 29 (CONFIG_KEYPAD == IRIVER_H300_PAD)
28#define TREE_NEXT BUTTON_DOWN 30#define TREE_NEXT BUTTON_DOWN
@@ -43,8 +45,11 @@
43#define TREE_POWER_BTN BUTTON_ON 45#define TREE_POWER_BTN BUTTON_ON
44#define TREE_QUICK (BUTTON_MODE | BUTTON_REPEAT) 46#define TREE_QUICK (BUTTON_MODE | BUTTON_REPEAT)
45 47
48/* Remote keys */
46#define TREE_RC_NEXT BUTTON_RC_FF 49#define TREE_RC_NEXT BUTTON_RC_FF
47#define TREE_RC_PREV BUTTON_RC_REW 50#define TREE_RC_PREV BUTTON_RC_REW
51#define TREE_RC_PGUP BUTTON_RC_SOURCE
52#define TREE_RC_PGDN BUTTON_RC_BITRATE
48#define TREE_RC_EXIT BUTTON_RC_STOP 53#define TREE_RC_EXIT BUTTON_RC_STOP
49#define TREE_RC_RUN (BUTTON_RC_MENU | BUTTON_REL) 54#define TREE_RC_RUN (BUTTON_RC_MENU | BUTTON_REL)
50#define TREE_RC_RUN_PRE BUTTON_RC_MENU 55#define TREE_RC_RUN_PRE BUTTON_RC_MENU
@@ -137,27 +142,36 @@ struct filetype {
137 int icon; 142 int icon;
138 int voiceclip; 143 int voiceclip;
139}; 144};
140 145
141/* browser context for file or db */ 146/* browser context for file or db */
142struct tree_context { 147struct tree_context {
148 /* The directory we are browsing */
149 char currdir[MAX_PATH];
150 /* the number of directories we have crossed from / */
143 int dirlevel; 151 int dirlevel;
144 int dircursor; 152 /* The currently selected file/id3dbitem index (old dircursor+dirfile) */
145 int dirstart; 153 int selected_item;
154 /* The selected item in each directory crossed
155 * (used when we want to return back to a previouws directory)*/
156 int selected_item_history[MAX_DIR_LEVELS];
157
146 int firstpos; /* which dir entry is on first 158 int firstpos; /* which dir entry is on first
147 position in dir buffer */ 159 position in dir buffer */
148 int pos_history[MAX_DIR_LEVELS]; 160 int pos_history[MAX_DIR_LEVELS];
149 int dirpos[MAX_DIR_LEVELS]; 161 int dirpos[MAX_DIR_LEVELS]; /* the dirstart history */
150 int cursorpos[MAX_DIR_LEVELS]; 162 int cursorpos[MAX_DIR_LEVELS]; /* the dircursor history */
151 char currdir[MAX_PATH]; /* file use */ 163
152 int *dirfilter; /* file use */ 164 int *dirfilter; /* file use */
153 int filesindir; 165 int filesindir; /* The number of files in the dircache */
154 int dirsindir; /* file use */ 166 int dirsindir; /* file use */
155 int dirlength; /* total number of entries in dir, incl. those not loaded */ 167 int dirlength; /* total number of entries in dir, incl. those not loaded */
156 int table_history[MAX_DIR_LEVELS]; /* db use */ 168 int table_history[MAX_DIR_LEVELS]; /* db use */
157 int extra_history[MAX_DIR_LEVELS]; /* db use */ 169 int extra_history[MAX_DIR_LEVELS]; /* db use */
158 int currtable; /* db use */ 170 int currtable; /* db use */
159 int currextra; /* db use */ 171 int currextra; /* db use */
160 172 /* A big buffer with plenty of entry structs,
173 * contains all files and dirs in the current
174 * dir (with filters applied) */
161 void* dircache; 175 void* dircache;
162 int dircache_size; 176 int dircache_size;
163 char* name_buffer; 177 char* name_buffer;
@@ -196,4 +210,7 @@ struct tree_context* tree_get_context(void);
196void tree_flush(void); 210void tree_flush(void);
197void tree_restore(void); 211void tree_restore(void);
198 212
213
214extern struct gui_synclist tree_lists;
215extern struct gui_syncstatusbar statusbars;
199#endif 216#endif
diff --git a/apps/wps.h b/apps/wps.h
index 6f0d601876..e32bd3c815 100644
--- a/apps/wps.h
+++ b/apps/wps.h
@@ -19,7 +19,7 @@
19#ifndef _WPS_H 19#ifndef _WPS_H
20#define _WPS_H 20#define _WPS_H
21#include "id3.h" 21#include "id3.h"
22#include "playlist.h" 22#include "playlist.h"
23 23
24/* button definitions */ 24/* button definitions */
25#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ 25#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
@@ -33,7 +33,7 @@
33#define WPS_INCVOL BUTTON_UP 33#define WPS_INCVOL BUTTON_UP
34#define WPS_DECVOL BUTTON_DOWN 34#define WPS_DECVOL BUTTON_DOWN
35#define WPS_PAUSE (BUTTON_ON | BUTTON_REL) 35#define WPS_PAUSE (BUTTON_ON | BUTTON_REL)
36#define WPS_PAUSE_PRE BUTTON_ON 36#define WPS_PAUSE_PRE BUTTON_ON
37#define WPS_MENU (BUTTON_MODE | BUTTON_REL) 37#define WPS_MENU (BUTTON_MODE | BUTTON_REL)
38#define WPS_MENU_PRE BUTTON_MODE 38#define WPS_MENU_PRE BUTTON_MODE
39#define WPS_BROWSE (BUTTON_SELECT | BUTTON_REL) 39#define WPS_BROWSE (BUTTON_SELECT | BUTTON_REL)
@@ -53,10 +53,10 @@
53#define WPS_RC_INCVOL BUTTON_RC_VOL_UP 53#define WPS_RC_INCVOL BUTTON_RC_VOL_UP
54#define WPS_RC_DECVOL BUTTON_RC_VOL_DOWN 54#define WPS_RC_DECVOL BUTTON_RC_VOL_DOWN
55#define WPS_RC_EXIT BUTTON_RC_STOP 55#define WPS_RC_EXIT BUTTON_RC_STOP
56#define WPS_RC_MENU (BUTTON_RC_MENU | BUTTON_REL) 56#define WPS_RC_MENU (BUTTON_RC_MODE | BUTTON_REL)
57#define WPS_RC_MENU_PRE BUTTON_RC_MENU 57#define WPS_RC_MENU_PRE BUTTON_RC_MODE
58#define WPS_RC_BROWSE (BUTTON_RC_MODE | BUTTON_REL) 58#define WPS_RC_BROWSE (BUTTON_RC_MENU | BUTTON_REL)
59#define WPS_RC_BROWSE_PRE BUTTON_RC_MODE 59#define WPS_RC_BROWSE_PRE BUTTON_RC_MENU
60 60
61#elif CONFIG_KEYPAD == RECORDER_PAD 61#elif CONFIG_KEYPAD == RECORDER_PAD
62#define WPS_NEXT (BUTTON_RIGHT | BUTTON_REL) 62#define WPS_NEXT (BUTTON_RIGHT | BUTTON_REL)
diff --git a/tools/configure b/tools/configure
index 4a0a4ee47a..ad66ba8005 100755
--- a/tools/configure
+++ b/tools/configure
@@ -412,7 +412,7 @@ appsdir='\$(ROOTDIR)/apps'
412 shcc 412 shcc
413 tool="$rootdir/tools/scramble" 413 tool="$rootdir/tools/scramble"
414 output="archos.mod" 414 output="archos.mod"
415 appextra="player" 415 appextra="player:gui"
416 archosrom="$pwd/rombox.ucl" 416 archosrom="$pwd/rombox.ucl"
417 flash="$pwd/rockbox.ucl" 417 flash="$pwd/rockbox.ucl"
418 plugins="yes" 418 plugins="yes"
@@ -425,7 +425,7 @@ appsdir='\$(ROOTDIR)/apps'
425 shcc 425 shcc
426 tool="$rootdir/tools/scramble" 426 tool="$rootdir/tools/scramble"
427 output="ajbrec.ajz" 427 output="ajbrec.ajz"
428 appextra="recorder" 428 appextra="recorder:gui"
429 archosrom="$pwd/rombox.ucl" 429 archosrom="$pwd/rombox.ucl"
430 flash="$pwd/rockbox.ucl" 430 flash="$pwd/rockbox.ucl"
431 plugins="yes" 431 plugins="yes"
@@ -438,7 +438,7 @@ appsdir='\$(ROOTDIR)/apps'
438 shcc 438 shcc
439 tool="$rootdir/tools/scramble -fm" 439 tool="$rootdir/tools/scramble -fm"
440 output="ajbrec.ajz" 440 output="ajbrec.ajz"
441 appextra="recorder" 441 appextra="recorder:gui"
442 archosrom="$pwd/rombox.ucl" 442 archosrom="$pwd/rombox.ucl"
443 flash="$pwd/rockbox.ucl" 443 flash="$pwd/rockbox.ucl"
444 plugins="yes" 444 plugins="yes"
@@ -451,7 +451,7 @@ appsdir='\$(ROOTDIR)/apps'
451 shcc 451 shcc
452 tool="$rootdir/tools/scramble -v2" 452 tool="$rootdir/tools/scramble -v2"
453 output="ajbrec.ajz" 453 output="ajbrec.ajz"
454 appextra="recorder" 454 appextra="recorder:gui"
455 archosrom="$pwd/rombox.ucl" 455 archosrom="$pwd/rombox.ucl"
456 flash="$pwd/rockbox.ucl" 456 flash="$pwd/rockbox.ucl"
457 plugins="yes" 457 plugins="yes"
@@ -465,7 +465,7 @@ appsdir='\$(ROOTDIR)/apps'
465 calmrisccc 465 calmrisccc
466 tool="cp" # might work for now! 466 tool="cp" # might work for now!
467 output="rockbox.gmini" 467 output="rockbox.gmini"
468 appextra="recorder" 468 appextra="recorder:gui"
469 archosrom="" 469 archosrom=""
470 flash="" 470 flash=""
471 plugins="" # disabled for now, enable later on 471 plugins="" # disabled for now, enable later on
@@ -479,7 +479,7 @@ appsdir='\$(ROOTDIR)/apps'
479 calmrisccc 479 calmrisccc
480 tool="cp" # might work for now! 480 tool="cp" # might work for now!
481 output="rockbox.gmini" 481 output="rockbox.gmini"
482 appextra="recorder" 482 appextra="recorder:gui"
483 archosrom="" 483 archosrom=""
484 flash="" 484 flash=""
485 plugins="" # disabled for now, enable later on 485 plugins="" # disabled for now, enable later on
@@ -492,7 +492,7 @@ appsdir='\$(ROOTDIR)/apps'
492 shcc 492 shcc
493 tool="$rootdir/tools/scramble -osp" 493 tool="$rootdir/tools/scramble -osp"
494 output="ajbrec.ajz" 494 output="ajbrec.ajz"
495 appextra="recorder" 495 appextra="recorder:gui"
496 archosrom="$pwd/rombox.ucl" 496 archosrom="$pwd/rombox.ucl"
497 flash="$pwd/rockbox.ucl" 497 flash="$pwd/rockbox.ucl"
498 plugins="yes" 498 plugins="yes"
@@ -505,7 +505,7 @@ appsdir='\$(ROOTDIR)/apps'
505 shcc 505 shcc
506 tool="$rootdir/tools/scramble -ofm" 506 tool="$rootdir/tools/scramble -ofm"
507 output="ajbrec.ajz" 507 output="ajbrec.ajz"
508 appextra="recorder" 508 appextra="recorder:gui"
509 archosrom="$pwd/rombox.ucl" 509 archosrom="$pwd/rombox.ucl"
510 flash="$pwd/rockbox.ucl" 510 flash="$pwd/rockbox.ucl"
511 plugins="yes" 511 plugins="yes"
@@ -519,7 +519,7 @@ appsdir='\$(ROOTDIR)/apps'
519 coldfirecc 519 coldfirecc
520 tool="$rootdir/tools/scramble -add=h120" 520 tool="$rootdir/tools/scramble -add=h120"
521 output="rockbox.iriver" 521 output="rockbox.iriver"
522 appextra="recorder" 522 appextra="recorder:gui"
523 archosrom="" 523 archosrom=""
524 flash="" 524 flash=""
525 plugins="yes" 525 plugins="yes"
@@ -533,7 +533,7 @@ appsdir='\$(ROOTDIR)/apps'
533 coldfirecc 533 coldfirecc
534 tool="$rootdir/tools/scramble -add=h300" 534 tool="$rootdir/tools/scramble -add=h300"
535 output="rockbox.iriver" 535 output="rockbox.iriver"
536 appextra="recorder" 536 appextra="recorder:gui"
537 archosrom="" 537 archosrom=""
538 flash="" 538 flash=""
539 plugins="yes" 539 plugins="yes"
@@ -547,7 +547,7 @@ appsdir='\$(ROOTDIR)/apps'
547 coldfirecc 547 coldfirecc
548 tool="$rootdir/tools/scramble -add=h100" 548 tool="$rootdir/tools/scramble -add=h100"
549 output="rockbox.iriver" 549 output="rockbox.iriver"
550 appextra="recorder" 550 appextra="recorder:gui"
551 archosrom="" 551 archosrom=""
552 flash="" 552 flash=""
553 plugins="yes" 553 plugins="yes"
@@ -561,7 +561,7 @@ appsdir='\$(ROOTDIR)/apps'
561 coldfirecc 561 coldfirecc
562 tool="$rootdir/tools/scramble -add=x5" # wrong, must be fixed 562 tool="$rootdir/tools/scramble -add=x5" # wrong, must be fixed
563 output="rockbox.iaudio" 563 output="rockbox.iaudio"
564 appextra="recorder" 564 appextra="recorder:gui"
565 archosrom="" 565 archosrom=""
566 flash="" 566 flash=""
567 plugins="yes" 567 plugins="yes"