summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristi Scarborough <christi@coraline.org>2005-11-17 20:14:59 +0000
committerChristi Scarborough <christi@coraline.org>2005-11-17 20:14:59 +0000
commit4c0b83f5e913820bbcf203fee1606d9910925946 (patch)
treec4e9cdcb1cf8196f60a3ff8b68ebc5d1a514e967
parentbc1fb0f5d91084d3e06ef3526533324108bf1de7 (diff)
downloadrockbox-4c0b83f5e913820bbcf203fee1606d9910925946.tar.gz
rockbox-4c0b83f5e913820bbcf203fee1606d9910925946.zip
Remote WPS support (and some WPS bugfixes) by Stephan Wezel
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7934 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--apps/SOURCES4
-rw-r--r--apps/bookmark.c2
-rw-r--r--apps/database.c1
-rw-r--r--apps/dbtree.c2
-rw-r--r--apps/filetree.c16
-rw-r--r--apps/gui/statusbar.c2
-rw-r--r--apps/lang/english.lang12
-rw-r--r--apps/main.c7
-rw-r--r--apps/onplay.c1
-rw-r--r--apps/playback.c2
-rw-r--r--apps/recorder/peakmeter.c2
-rw-r--r--apps/screen_access.c2
-rw-r--r--apps/screen_access.h2
-rw-r--r--apps/screens.c4
-rw-r--r--apps/settings.c50
-rw-r--r--apps/settings.h5
-rw-r--r--apps/settings_menu.c10
-rw-r--r--apps/status.c2
-rw-r--r--apps/tree.c9
-rw-r--r--apps/tree.h1
-rw-r--r--apps/wps-display.c1841
-rw-r--r--apps/wps-display.h48
-rw-r--r--apps/wps.c882
-rw-r--r--apps/wps.h205
-rw-r--r--docs/CREDITS1
-rw-r--r--wps/rockbox_default.rwps2
26 files changed, 113 insertions, 3002 deletions
diff --git a/apps/SOURCES b/apps/SOURCES
index 2d32156cf8..67e09ed53d 100644
--- a/apps/SOURCES
+++ b/apps/SOURCES
@@ -29,8 +29,6 @@ tree.c
29dbtree.c 29dbtree.c
30database.c 30database.c
31filetree.c 31filetree.c
32wps-display.c
33wps.c
34 32
35screen_access.c 33screen_access.c
36gui/buttonbar.c 34gui/buttonbar.c
@@ -40,6 +38,8 @@ gui/scrollbar.c
40gui/select.c 38gui/select.c
41gui/splash.c 39gui/splash.c
42gui/statusbar.c 40gui/statusbar.c
41gui/gwps.c
42gui/gwps-common.c
43gui/textarea.c 43gui/textarea.c
44 44
45#ifdef HAVE_LCD_CHARCELLS 45#ifdef HAVE_LCD_CHARCELLS
diff --git a/apps/bookmark.c b/apps/bookmark.c
index 788aebe582..c42f466283 100644
--- a/apps/bookmark.c
+++ b/apps/bookmark.c
@@ -27,7 +27,7 @@
27#include "button.h" 27#include "button.h"
28#include "usb.h" 28#include "usb.h"
29#include "audio.h" 29#include "audio.h"
30#include "wps.h" 30#include "playlist.h"
31#include "settings.h" 31#include "settings.h"
32#include "tree.h" 32#include "tree.h"
33#include "bookmark.h" 33#include "bookmark.h"
diff --git a/apps/database.c b/apps/database.c
index 6d74ce88a9..97fb2d70cc 100644
--- a/apps/database.c
+++ b/apps/database.c
@@ -35,7 +35,6 @@
35#include "mpeg.h" 35#include "mpeg.h"
36#include "misc.h" 36#include "misc.h"
37#include "ata.h" 37#include "ata.h"
38#include "wps.h"
39#include "filetypes.h" 38#include "filetypes.h"
40#include "applimits.h" 39#include "applimits.h"
41#include "icons.h" 40#include "icons.h"
diff --git a/apps/dbtree.c b/apps/dbtree.c
index 9115c5902c..b8a4c4703e 100644
--- a/apps/dbtree.c
+++ b/apps/dbtree.c
@@ -35,7 +35,7 @@
35#include "mpeg.h" 35#include "mpeg.h"
36#include "misc.h" 36#include "misc.h"
37#include "ata.h" 37#include "ata.h"
38#include "wps.h" 38#include "playlist.h"
39#include "filetypes.h" 39#include "filetypes.h"
40#include "applimits.h" 40#include "applimits.h"
41#include "dbtree.h" 41#include "dbtree.h"
diff --git a/apps/filetree.c b/apps/filetree.c
index a9670e1be7..6855d3ec5d 100644
--- a/apps/filetree.c
+++ b/apps/filetree.c
@@ -31,7 +31,7 @@
31#include "filetypes.h" 31#include "filetypes.h"
32#include "talk.h" 32#include "talk.h"
33#include "playlist.h" 33#include "playlist.h"
34#include "wps-display.h" 34#include "gwps.h"
35#include "lang.h" 35#include "lang.h"
36#include "language.h" 36#include "language.h"
37#include "screens.h" 37#include "screens.h"
@@ -273,6 +273,9 @@ int ft_load(struct tree_context* c, const char* tempdir)
273 (dptr->attr & TREE_ATTR_MASK) != TREE_ATTR_M3U) || 273 (dptr->attr & TREE_ATTR_MASK) != TREE_ATTR_M3U) ||
274 (*c->dirfilter == SHOW_SUPPORTED && !filetype_supported(dptr->attr)))) || 274 (*c->dirfilter == SHOW_SUPPORTED && !filetype_supported(dptr->attr)))) ||
275 (*c->dirfilter == SHOW_WPS && (dptr->attr & TREE_ATTR_MASK) != TREE_ATTR_WPS) || 275 (*c->dirfilter == SHOW_WPS && (dptr->attr & TREE_ATTR_MASK) != TREE_ATTR_WPS) ||
276#ifdef HAVE_REMOTE_LCD
277 (*c->dirfilter == SHOW_RWPS && (dptr->attr & TREE_ATTR_MASK) != TREE_ATTR_RWPS) ||
278#endif
276 (*c->dirfilter == SHOW_CFG && (dptr->attr & TREE_ATTR_MASK) != TREE_ATTR_CFG) || 279 (*c->dirfilter == SHOW_CFG && (dptr->attr & TREE_ATTR_MASK) != TREE_ATTR_CFG) ||
277 (*c->dirfilter == SHOW_LNG && (dptr->attr & TREE_ATTR_MASK) != TREE_ATTR_LNG) || 280 (*c->dirfilter == SHOW_LNG && (dptr->attr & TREE_ATTR_MASK) != TREE_ATTR_LNG) ||
278 (*c->dirfilter == SHOW_MOD && (dptr->attr & TREE_ATTR_MASK) != TREE_ATTR_MOD) || 281 (*c->dirfilter == SHOW_MOD && (dptr->attr & TREE_ATTR_MASK) != TREE_ATTR_MOD) ||
@@ -381,11 +384,20 @@ int ft_enter(struct tree_context* c)
381 384
382 /* wps config file */ 385 /* wps config file */
383 case TREE_ATTR_WPS: 386 case TREE_ATTR_WPS:
384 wps_load(buf,true); 387 wps_data_load(gui_syncwps.gui_wps[0].data, buf, true, true);
385 set_file(buf, global_settings.wps_file, 388 set_file(buf, global_settings.wps_file,
386 MAX_FILENAME); 389 MAX_FILENAME);
387 break; 390 break;
388 391
392#ifdef HAVE_REMOTE_LCD
393 /* remote-wps config file */
394 case TREE_ATTR_RWPS:
395 wps_data_load(gui_syncwps.gui_wps[1].data, buf, true, true);
396 set_file(buf, global_settings.rwps_file,
397 MAX_FILENAME);
398 break;
399#endif
400
389 case TREE_ATTR_CFG: 401 case TREE_ATTR_CFG:
390 if (!settings_load_config(buf)) 402 if (!settings_load_config(buf))
391 break; 403 break;
diff --git a/apps/gui/statusbar.c b/apps/gui/statusbar.c
index efc74d50af..d279c220cc 100644
--- a/apps/gui/statusbar.c
+++ b/apps/gui/statusbar.c
@@ -34,7 +34,7 @@
34#include "led.h" 34#include "led.h"
35 35
36#include "status.h" /* needed for battery_state global var */ 36#include "status.h" /* needed for battery_state global var */
37#include "wps.h" /* for keys_locked */ 37#include "gwps.h" /* for keys_locked */
38#include "statusbar.h" 38#include "statusbar.h"
39 39
40 40
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index d601f7175e..469e4cb033 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -3437,3 +3437,15 @@ eng: "=== Please Wait ==="
3437voice: 3437voice:
3438new: 3438new:
3439 3439
3440id: VOICE_EXT_RWPS
3441desc: spoken only, for file extension
3442eng: ""
3443voice: "remote while-playing-screen"
3444new:
3445
3446id: LANG_REMOTE_WHILE_PLAYING
3447desc: in settings_menu()
3448eng: "Browse .rwps files"
3449voice: "Browse remote while-playing-screen files"
3450new:
3451
diff --git a/apps/main.c b/apps/main.c
index ab802d5e24..d84aa25d0f 100644
--- a/apps/main.c
+++ b/apps/main.c
@@ -49,7 +49,7 @@
49#include "sprintf.h" 49#include "sprintf.h"
50#include "font.h" 50#include "font.h"
51#include "language.h" 51#include "language.h"
52#include "wps-display.h" 52#include "gwps.h"
53#include "playlist.h" 53#include "playlist.h"
54#include "buffer.h" 54#include "buffer.h"
55#include "rolo.h" 55#include "rolo.h"
@@ -138,6 +138,8 @@ void init(void)
138 settings_reset(); 138 settings_reset();
139 settings_calc_config_sector(); 139 settings_calc_config_sector();
140 settings_load(SETTINGS_ALL); 140 settings_load(SETTINGS_ALL);
141 gui_sync_data_wps_init();
142 gui_sync_wps_init();
141 settings_apply(); 143 settings_apply();
142 init_dircache(); 144 init_dircache();
143 sleep(HZ/2); 145 sleep(HZ/2);
@@ -295,7 +297,8 @@ void init(void)
295 settings_calc_config_sector(); 297 settings_calc_config_sector();
296 settings_load(SETTINGS_ALL); 298 settings_load(SETTINGS_ALL);
297 init_dircache(); 299 init_dircache();
298 300 gui_sync_data_wps_init();
301 gui_sync_wps_init();
299 settings_apply(); 302 settings_apply();
300 303
301 status_init(); 304 status_init();
diff --git a/apps/onplay.c b/apps/onplay.c
index 36ea95771a..704e0c04ec 100644
--- a/apps/onplay.c
+++ b/apps/onplay.c
@@ -46,7 +46,6 @@
46#include "filetypes.h" 46#include "filetypes.h"
47#include "plugin.h" 47#include "plugin.h"
48#include "bookmark.h" 48#include "bookmark.h"
49#include "wps.h"
50#include "action.h" 49#include "action.h"
51#include "splash.h" 50#include "splash.h"
52#ifdef HAVE_LCD_BITMAP 51#ifdef HAVE_LCD_BITMAP
diff --git a/apps/playback.c b/apps/playback.c
index b68cb641fe..6a944c9dc8 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -34,8 +34,6 @@
34#include "sprintf.h" 34#include "sprintf.h"
35#include "settings.h" 35#include "settings.h"
36#include "codecs.h" 36#include "codecs.h"
37#include "wps.h"
38#include "wps-display.h"
39#include "audio.h" 37#include "audio.h"
40#include "logf.h" 38#include "logf.h"
41#include "mp3_playback.h" 39#include "mp3_playback.h"
diff --git a/apps/recorder/peakmeter.c b/apps/recorder/peakmeter.c
index 2e4cea0704..a93e20ad0e 100644
--- a/apps/recorder/peakmeter.c
+++ b/apps/recorder/peakmeter.c
@@ -24,7 +24,7 @@
24#include "ata.h" 24#include "ata.h"
25#include "lcd.h" 25#include "lcd.h"
26#include "widgets.h" 26#include "widgets.h"
27#include "wps-display.h" 27#include "gwps.h"
28#include "sprintf.h" 28#include "sprintf.h"
29#include "button.h" 29#include "button.h"
30#include "system.h" 30#include "system.h"
diff --git a/apps/screen_access.c b/apps/screen_access.c
index dfaba4d0f2..b1ae9eb2b8 100644
--- a/apps/screen_access.c
+++ b/apps/screen_access.c
@@ -123,6 +123,8 @@ void screen_init(struct screen * screen, enum screen_type screen_type)
123 screen->height=2; 123 screen->height=2;
124 screen->double_height=&lcd_double_height; 124 screen->double_height=&lcd_double_height;
125 screen->putc=&lcd_putc; 125 screen->putc=&lcd_putc;
126 screen->get_locked_pattern=&lcd_get_locked_pattern;
127 screen->define_pattern=&lcd_define_pattern;
126#ifdef SIMULATOR 128#ifdef SIMULATOR
127 screen->icon=&sim_lcd_icon; 129 screen->icon=&sim_lcd_icon;
128#else 130#else
diff --git a/apps/screen_access.h b/apps/screen_access.h
index 6111de9de4..95ddcb9462 100644
--- a/apps/screen_access.h
+++ b/apps/screen_access.h
@@ -99,6 +99,8 @@ struct screen
99 void (*scroll_delay)(int ms); 99 void (*scroll_delay)(int ms);
100 void (*stop_scroll)(void); 100 void (*stop_scroll)(void);
101 void (*clear_display)(void); 101 void (*clear_display)(void);
102 unsigned char (*get_locked_pattern)(void);
103 void (*define_pattern)(int pat, const char *pattern);
102#if defined(HAVE_LCD_BITMAP) || defined(SIMULATOR) 104#if defined(HAVE_LCD_BITMAP) || defined(SIMULATOR)
103 void (*update)(void); 105 void (*update)(void);
104#endif 106#endif
diff --git a/apps/screens.c b/apps/screens.c
index 978d2a12f8..f861bb76c9 100644
--- a/apps/screens.c
+++ b/apps/screens.c
@@ -46,7 +46,7 @@
46#include "led.h" 46#include "led.h"
47#include "sound.h" 47#include "sound.h"
48#include "abrepeat.h" 48#include "abrepeat.h"
49#include "wps-display.h" 49#include "gwps-common.h"
50#include "splash.h" 50#include "splash.h"
51#if defined(HAVE_LCD_BITMAP) 51#if defined(HAVE_LCD_BITMAP)
52#include "widgets.h" 52#include "widgets.h"
@@ -1226,7 +1226,7 @@ bool browse_id3(void)
1226 1226
1227 line = draw_id3_item(line, top, LANG_ID3_YEAR, body); 1227 line = draw_id3_item(line, top, LANG_ID3_YEAR, body);
1228 1228
1229 wps_format_time(buf, sizeof(buf), id3->length); 1229 gui_wps_format_time(buf, sizeof(buf), id3->length);
1230 line = draw_id3_item(line, top, LANG_ID3_LENGHT, buf); 1230 line = draw_id3_item(line, top, LANG_ID3_LENGHT, buf);
1231 1231
1232 snprintf(buf, sizeof(buf), "%d/%d", playlist_get_display_index(), 1232 snprintf(buf, sizeof(buf), "%d/%d", playlist_get_display_index(),
diff --git a/apps/settings.c b/apps/settings.c
index 63da47e34b..2e5014fce7 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -59,7 +59,7 @@
59#endif 59#endif
60#include "lang.h" 60#include "lang.h"
61#include "language.h" 61#include "language.h"
62#include "wps-display.h" 62#include "gwps.h"
63#include "powermgmt.h" 63#include "powermgmt.h"
64#include "bookmark.h" 64#include "bookmark.h"
65#include "sprintf.h" 65#include "sprintf.h"
@@ -85,7 +85,7 @@ const char rec_base_directory[] = REC_BASE_DIR;
85#include "dsp.h" 85#include "dsp.h"
86#endif 86#endif
87 87
88#define CONFIG_BLOCK_VERSION 31 88#define CONFIG_BLOCK_VERSION 32
89#define CONFIG_BLOCK_SIZE 512 89#define CONFIG_BLOCK_SIZE 512
90#define RTC_BLOCK_SIZE 44 90#define RTC_BLOCK_SIZE 44
91 91
@@ -758,10 +758,16 @@ int settings_save( void )
758 strncpy(&config_block[0xb8], global_settings.wps_file, MAX_FILENAME); 758 strncpy(&config_block[0xb8], global_settings.wps_file, MAX_FILENAME);
759 strncpy(&config_block[0xcc], global_settings.lang_file, MAX_FILENAME); 759 strncpy(&config_block[0xcc], global_settings.lang_file, MAX_FILENAME);
760 strncpy(&config_block[0xe0], global_settings.font_file, MAX_FILENAME); 760 strncpy(&config_block[0xe0], global_settings.font_file, MAX_FILENAME);
761#ifdef HAVE_REMOTE_LCD
762 strncpy(&config_block[0xf4], global_settings.rwps_file, MAX_FILENAME);
763#endif
761 764
762 if(save_config_buffer()) 765 if(save_config_buffer())
763 { 766 {
764 lcd_clear_display(); 767 lcd_clear_display();
768#ifdef HAVE_REMOTE_LCD
769 lcd_remote_clear_display();
770#endif
765#ifdef HAVE_LCD_CHARCELLS 771#ifdef HAVE_LCD_CHARCELLS
766 lcd_puts(0, 0, str(LANG_SETTINGS_SAVE_PLAYER)); 772 lcd_puts(0, 0, str(LANG_SETTINGS_SAVE_PLAYER));
767 lcd_puts(0, 1, str(LANG_SETTINGS_BATTERY_PLAYER)); 773 lcd_puts(0, 1, str(LANG_SETTINGS_BATTERY_PLAYER));
@@ -769,6 +775,11 @@ int settings_save( void )
769 lcd_puts(4, 2, str(LANG_SETTINGS_SAVE_RECORDER)); 775 lcd_puts(4, 2, str(LANG_SETTINGS_SAVE_RECORDER));
770 lcd_puts(2, 4, str(LANG_SETTINGS_BATTERY_RECORDER)); 776 lcd_puts(2, 4, str(LANG_SETTINGS_BATTERY_RECORDER));
771 lcd_update(); 777 lcd_update();
778#ifdef HAVE_REMOTE_LCD
779 lcd_remote_puts(4, 2, str(LANG_SETTINGS_SAVE_RECORDER));
780 lcd_remote_puts(2, 4, str(LANG_SETTINGS_BATTERY_RECORDER));
781 lcd_remote_update();
782#endif
772#endif 783#endif
773 sleep(HZ*2); 784 sleep(HZ*2);
774 return -1; 785 return -1;
@@ -879,10 +890,21 @@ void settings_apply(void)
879 global_settings.wps_file[0] != 0xff ) { 890 global_settings.wps_file[0] != 0xff ) {
880 snprintf(buf, sizeof buf, WPS_DIR "/%s.wps", 891 snprintf(buf, sizeof buf, WPS_DIR "/%s.wps",
881 global_settings.wps_file); 892 global_settings.wps_file);
882 wps_load(buf, false); 893 wps_data_load(gui_syncwps.gui_wps[0].data, buf, true, false);
883 } 894 }
884 else 895 else
885 wps_reset(); 896 wps_data_init(gui_syncwps.gui_wps[0].data);
897
898#ifdef HAVE_REMOTE_LCD
899 if ( global_settings.rwps_file[0] &&
900 global_settings.rwps_file[0] != 0xff ) {
901 snprintf(buf, sizeof buf, WPS_DIR "/%s.rwps",
902 global_settings.rwps_file);
903 wps_data_load(gui_syncwps.gui_wps[1].data, buf, true, false);
904 }
905 else
906 wps_data_init(gui_syncwps.gui_wps[1].data);
907#endif
886 908
887#ifdef HAVE_LCD_BITMAP 909#ifdef HAVE_LCD_BITMAP
888 if ( global_settings.font_file[0] && 910 if ( global_settings.font_file[0] &&
@@ -1003,6 +1025,9 @@ void settings_load(int which)
1003 strncpy(global_settings.wps_file, &config_block[0xb8], MAX_FILENAME); 1025 strncpy(global_settings.wps_file, &config_block[0xb8], MAX_FILENAME);
1004 strncpy(global_settings.lang_file, &config_block[0xcc], MAX_FILENAME); 1026 strncpy(global_settings.lang_file, &config_block[0xcc], MAX_FILENAME);
1005 strncpy(global_settings.font_file, &config_block[0xe0], MAX_FILENAME); 1027 strncpy(global_settings.font_file, &config_block[0xe0], MAX_FILENAME);
1028#ifdef HAVE_REMOTE_LCD
1029 strncpy(global_settings.rwps_file, &config_block[0xf4], MAX_FILENAME);
1030#endif
1006 } 1031 }
1007} 1032}
1008 1033
@@ -1141,9 +1166,15 @@ bool settings_load_config(const char* file)
1141 1166
1142 /* check for the string values */ 1167 /* check for the string values */
1143 if (!strcasecmp(name, "wps")) { 1168 if (!strcasecmp(name, "wps")) {
1144 if (wps_load(value,false)) 1169 if (wps_data_load(gui_syncwps.gui_wps[0].data,value,true, false))
1145 set_file(value, global_settings.wps_file, MAX_FILENAME); 1170 set_file(value, global_settings.wps_file, MAX_FILENAME);
1146 } 1171 }
1172#ifdef HAVE_REMOTE_LCD
1173 else if (!strcasecmp(name, "rwps")) {
1174 if (wps_data_load(gui_syncwps.gui_wps[1].data,value,true, false))
1175 set_file(value, global_settings.rwps_file, MAX_FILENAME);
1176 }
1177#endif
1147 else if (!strcasecmp(name, "lang")) { 1178 else if (!strcasecmp(name, "lang")) {
1148 if (!lang_load(value)) 1179 if (!lang_load(value))
1149 { 1180 {
@@ -1283,6 +1314,12 @@ bool settings_save_config(void)
1283 fdprintf(fd, "wps: %s/%s.wps\r\n", WPS_DIR, 1314 fdprintf(fd, "wps: %s/%s.wps\r\n", WPS_DIR,
1284 global_settings.wps_file); 1315 global_settings.wps_file);
1285 1316
1317#ifdef HAVE_REMOTE_LCD
1318 if (global_settings.rwps_file[0] != 0)
1319 fdprintf(fd, "rwps: %s/%s.rwps\r\n", WPS_DIR,
1320 global_settings.rwps_file);
1321#endif
1322
1286 if (global_settings.lang_file[0] != 0) 1323 if (global_settings.lang_file[0] != 0)
1287 fdprintf(fd, "lang: %s/%s.lng\r\n", ROCKBOX_DIR LANG_DIR, 1324 fdprintf(fd, "lang: %s/%s.lng\r\n", ROCKBOX_DIR LANG_DIR,
1288 global_settings.lang_file); 1325 global_settings.lang_file);
@@ -1365,6 +1402,9 @@ void settings_reset(void) {
1365#endif 1402#endif
1366 global_settings.contrast = lcd_default_contrast(); 1403 global_settings.contrast = lcd_default_contrast();
1367 global_settings.wps_file[0] = '\0'; 1404 global_settings.wps_file[0] = '\0';
1405#ifdef HAVE_REMOTE_LCD
1406 global_settings.rwps_file[0] = '\0';
1407#endif
1368 global_settings.font_file[0] = '\0'; 1408 global_settings.font_file[0] = '\0';
1369 global_settings.lang_file[0] = '\0'; 1409 global_settings.lang_file[0] = '\0';
1370 1410
diff --git a/apps/settings.h b/apps/settings.h
index 50f38cab50..20b0408dfd 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -359,6 +359,9 @@ struct user_settings
359 bool dircache; /* enable directory cache */ 359 bool dircache; /* enable directory cache */
360 int dircache_size; /* directory cache structure last size, 22 bits */ 360 int dircache_size; /* directory cache structure last size, 22 bits */
361#endif 361#endif
362#ifdef HAVE_REMOTE_LCD
363 unsigned char rwps_file[MAX_FILENAME+1]; /* last remote-wps */
364#endif
362}; 365};
363 366
364enum optiontype { INT, BOOL }; 367enum optiontype { INT, BOOL };
@@ -443,7 +446,7 @@ enum
443 * must be added after NUM_FILTER_MODES. */ 446 * must be added after NUM_FILTER_MODES. */
444enum { SHOW_ALL, SHOW_SUPPORTED, SHOW_MUSIC, SHOW_PLAYLIST, SHOW_ID3DB, 447enum { SHOW_ALL, SHOW_SUPPORTED, SHOW_MUSIC, SHOW_PLAYLIST, SHOW_ID3DB,
445 NUM_FILTER_MODES, 448 NUM_FILTER_MODES,
446 SHOW_WPS, SHOW_CFG, SHOW_LNG, SHOW_MOD, SHOW_FONT, SHOW_PLUGINS}; 449 SHOW_WPS, SHOW_RWPS, SHOW_CFG, SHOW_LNG, SHOW_MOD, SHOW_FONT, SHOW_PLUGINS};
447 450
448/* recursive dir insert options */ 451/* recursive dir insert options */
449enum { RECURSE_OFF, RECURSE_ON, RECURSE_ASK }; 452enum { RECURSE_OFF, RECURSE_ON, RECURSE_ASK };
diff --git a/apps/settings_menu.c b/apps/settings_menu.c
index 4aea853f82..8695177a00 100644
--- a/apps/settings_menu.c
+++ b/apps/settings_menu.c
@@ -996,6 +996,13 @@ static bool custom_wps_browse(void)
996 return rockbox_browse(WPS_DIR, SHOW_WPS); 996 return rockbox_browse(WPS_DIR, SHOW_WPS);
997} 997}
998 998
999#ifdef HAVE_REMOTE_LCD
1000static bool custom_remote_wps_browse(void)
1001{
1002 return rockbox_browse(WPS_DIR, SHOW_RWPS);
1003}
1004#endif
1005
999static bool custom_cfg_browse(void) 1006static bool custom_cfg_browse(void)
1000{ 1007{
1001 return rockbox_browse(ROCKBOX_DIR, SHOW_CFG); 1008 return rockbox_browse(ROCKBOX_DIR, SHOW_CFG);
@@ -1602,6 +1609,9 @@ static bool display_settings_menu(void)
1602 { ID2P(LANG_CUSTOM_FONT), font_browse }, 1609 { ID2P(LANG_CUSTOM_FONT), font_browse },
1603#endif 1610#endif
1604 { ID2P(LANG_WHILE_PLAYING), custom_wps_browse }, 1611 { ID2P(LANG_WHILE_PLAYING), custom_wps_browse },
1612#ifdef HAVE_REMOTE_LCD
1613 { ID2P(LANG_REMOTE_WHILE_PLAYING), custom_remote_wps_browse },
1614#endif
1605 { ID2P(LANG_LCD_MENU), lcd_settings_menu }, 1615 { ID2P(LANG_LCD_MENU), lcd_settings_menu },
1606#ifdef HAVE_REMOTE_LCD 1616#ifdef HAVE_REMOTE_LCD
1607 { ID2P(LANG_LCD_REMOTE_MENU), lcd_remote_settings_menu }, 1617 { ID2P(LANG_LCD_REMOTE_MENU), lcd_remote_settings_menu },
diff --git a/apps/status.c b/apps/status.c
index 9f43c6551d..978341d1db 100644
--- a/apps/status.c
+++ b/apps/status.c
@@ -26,7 +26,7 @@
26#include "status.h" 26#include "status.h"
27#include "mp3_playback.h" 27#include "mp3_playback.h"
28#include "audio.h" 28#include "audio.h"
29#include "wps.h" 29#include "gwps.h"
30#include "abrepeat.h" 30#include "abrepeat.h"
31#ifdef HAVE_RTC 31#ifdef HAVE_RTC
32#include "timefuncs.h" 32#include "timefuncs.h"
diff --git a/apps/tree.c b/apps/tree.c
index bfeac6c545..39980b1b81 100644
--- a/apps/tree.c
+++ b/apps/tree.c
@@ -36,8 +36,7 @@
36#include "audio.h" 36#include "audio.h"
37#include "playlist.h" 37#include "playlist.h"
38#include "menu.h" 38#include "menu.h"
39#include "wps.h" 39#include "gwps.h"
40#include "wps-display.h"
41#include "settings.h" 40#include "settings.h"
42#include "status.h" 41#include "status.h"
43#include "debug.h" 42#include "debug.h"
@@ -97,6 +96,9 @@ const struct filetype filetypes[] = {
97 { "m3u", TREE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST }, 96 { "m3u", TREE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST },
98 { "cfg", TREE_ATTR_CFG, Icon_Config, VOICE_EXT_CFG }, 97 { "cfg", TREE_ATTR_CFG, Icon_Config, VOICE_EXT_CFG },
99 { "wps", TREE_ATTR_WPS, Icon_Wps, VOICE_EXT_WPS }, 98 { "wps", TREE_ATTR_WPS, Icon_Wps, VOICE_EXT_WPS },
99#ifdef HAVE_REMOTE_LCD
100 { "rwps", TREE_ATTR_RWPS, Icon_Wps, VOICE_EXT_RWPS },
101#endif
100 { "lng", TREE_ATTR_LNG, Icon_Language, LANG_LANGUAGE }, 102 { "lng", TREE_ATTR_LNG, Icon_Language, LANG_LANGUAGE },
101 { "rock",TREE_ATTR_ROCK,Icon_Plugin, VOICE_EXT_ROCK }, 103 { "rock",TREE_ATTR_ROCK,Icon_Plugin, VOICE_EXT_ROCK },
102#ifdef HAVE_LCD_BITMAP 104#ifdef HAVE_LCD_BITMAP
@@ -212,6 +214,7 @@ void browse_root(void)
212{ 214{
213 /* essential to all programs that wants to display things */ 215 /* essential to all programs that wants to display things */
214 screen_access_init(); 216 screen_access_init();
217 gui_sync_wps_screen_init();
215 218
216 filetype_init(); 219 filetype_init();
217 check_rockboxdir(); 220 check_rockboxdir();
@@ -885,7 +888,7 @@ static bool dirbrowse(void)
885 int i; 888 int i;
886 FOR_NB_SCREENS(i) 889 FOR_NB_SCREENS(i)
887 screens[i].stop_scroll(); 890 screens[i].stop_scroll();
888 if (wps_show() == SYS_USB_CONNECTED) 891 if (gui_wps_show() == SYS_USB_CONNECTED)
889 reload_dir = true; 892 reload_dir = true;
890#ifdef HAVE_HOTSWAP 893#ifdef HAVE_HOTSWAP
891 else 894 else
diff --git a/apps/tree.h b/apps/tree.h
index 86e95931d1..55dfc562b9 100644
--- a/apps/tree.h
+++ b/apps/tree.h
@@ -213,6 +213,7 @@ struct tree_context {
213#define TREE_ATTR_LNG 0x0700 /* binary lang file */ 213#define TREE_ATTR_LNG 0x0700 /* binary lang file */
214#define TREE_ATTR_ROCK 0x0800 /* binary rockbox plugin */ 214#define TREE_ATTR_ROCK 0x0800 /* binary rockbox plugin */
215#define TREE_ATTR_MOD 0x0900 /* firmware file */ 215#define TREE_ATTR_MOD 0x0900 /* firmware file */
216#define TREE_ATTR_RWPS 0x1000 /* remote-wps config file */
216#define TREE_ATTR_MASK 0xFF00 /* which bits tree.c uses for file types */ 217#define TREE_ATTR_MASK 0xFF00 /* which bits tree.c uses for file types */
217 218
218void tree_get_filetypes(const struct filetype**, int*); 219void tree_get_filetypes(const struct filetype**, int*);
diff --git a/apps/wps-display.c b/apps/wps-display.c
deleted file mode 100644
index 58a953e4c0..0000000000
--- a/apps/wps-display.c
+++ /dev/null
@@ -1,1841 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Björn Stenberg
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/* ID3 formatting based on code from the MAD Winamp plugin (in_mad.dll),
21 * Copyright (C) 2000-2001 Robert Leslie.
22 * See http://www.mars.org/home/rob/proj/mpeg/ for more information.
23 */
24
25#include <stdio.h>
26#include <string.h>
27#include <stdlib.h>
28
29#include "lcd.h"
30#include "hwcompat.h"
31#include "font.h"
32#include "audio.h"
33#include "id3.h"
34#include "settings.h"
35#include "playlist.h"
36#include "kernel.h"
37#include "system.h"
38#include "status.h"
39#include "wps-display.h"
40#include "debug.h"
41#include "mas.h"
42#include "lang.h"
43#include "powermgmt.h"
44#include "power.h"
45#include "sprintf.h"
46#include "backlight.h"
47#include "button.h"
48#include "abrepeat.h"
49#include "screens.h"
50#include "splash.h"
51#ifdef HAVE_LCD_BITMAP
52#include <ctype.h>
53#include "icons.h"
54#include "widgets.h"
55#include "peakmeter.h"
56
57/* Image stuff */
58#include "bmp.h"
59#include "atoi.h"
60#define MAX_IMAGES (26*2) /* a-z and A-Z */
61#define IMG_BUFSIZE (LCD_HEIGHT * LCD_WIDTH * MAX_IMAGES / 25 ) / 8
62static unsigned char img_buf[IMG_BUFSIZE]; /* image buffer */
63static unsigned char* img_buf_ptr = img_buf; /* where are in image buffer? */
64
65static int img_buf_free = IMG_BUFSIZE; /* free space in image buffer */
66
67struct {
68 unsigned char* ptr; /* pointer */
69 int x; /* x-pos */
70 int y; /* y-pos */
71 int w; /* width */
72 int h; /* height */
73 bool loaded; /* load state */
74 bool display; /* is to be displayed */
75 bool always_display; /* not using the preload/display mechanism */
76} img[MAX_IMAGES] ;
77
78
79#endif
80
81#define WPS_DEFAULTCFG WPS_DIR "/rockbox_default.wps"
82
83#ifdef HAVE_LCD_BITMAP
84#define MAX_LINES (LCD_HEIGHT/5+1)
85#define FORMAT_BUFFER_SIZE 3072
86#else
87#define MAX_LINES 2
88#define FORMAT_BUFFER_SIZE 400
89#endif
90#define MAX_SUBLINES 12
91#define DEFAULT_SUBLINE_TIME_MULTIPLIER 20 /* (10ths of sec) */
92#define BASE_SUBLINE_TIME 10 /* base time that multiplier is applied to
93 (1/HZ sec, or 100ths of sec) */
94#define SUBLINE_RESET -1
95
96#ifdef HAVE_LCD_CHARCELLS
97static unsigned char wps_progress_pat[8]={0,0,0,0,0,0,0,0};
98static bool full_line_progressbar=0;
99static bool draw_player_progress(const struct mp3entry* id3,
100 int ff_rewwind_count);
101static void draw_player_fullbar(char* buf, int buf_size,
102 const struct mp3entry* id3,
103 int ff_rewwind_count);
104static char map_fullbar_char(char ascii_val);
105#endif
106
107struct align_pos {
108 char* left;
109 char* center;
110 char* right;
111};
112static char format_buffer[FORMAT_BUFFER_SIZE];
113static char* format_lines[MAX_LINES][MAX_SUBLINES];
114static struct align_pos format_align[MAX_LINES][MAX_SUBLINES];
115static unsigned char line_type[MAX_LINES][MAX_SUBLINES];
116static unsigned short time_mult[MAX_LINES][MAX_SUBLINES];
117static long subline_expire_time[MAX_LINES];
118static int curr_subline[MAX_LINES];
119
120static int ff_rewind_count;
121bool wps_time_countup = true;
122static bool wps_loaded = false;
123
124#ifdef HAVE_LCD_BITMAP
125/* Display images */
126static void wps_display_images(void) {
127 int n;
128 for (n = 0; n < MAX_IMAGES; n++) {
129 if (img[n].loaded && img[n].display) {
130 if(img[n].always_display)
131 lcd_set_drawmode(DRMODE_FG);
132 else
133 lcd_set_drawmode(DRMODE_SOLID);
134
135 lcd_mono_bitmap(img[n].ptr, img[n].x, img[n].y, img[n].w, img[n].h);
136 lcd_update_rect(img[n].x, img[n].y, img[n].w, img[n].h);
137 }
138 }
139 lcd_set_drawmode(DRMODE_SOLID);
140}
141#endif
142
143/* Set format string to use for WPS, splitting it into lines */
144static void wps_format(const char* fmt, char *bmpdir, size_t bmpdirlen)
145{
146 char* buf = format_buffer;
147 char* start_of_line = format_buffer;
148 int line = 0;
149 int subline;
150#ifndef HAVE_LCD_BITMAP
151 /* no bitmap lcd == no bitmap loading */
152 (void)bmpdir;
153 (void)bmpdirlen;
154#endif
155
156 strncpy(format_buffer, fmt, sizeof(format_buffer));
157 format_buffer[sizeof(format_buffer) - 1] = 0;
158
159 for (line=0; line<MAX_LINES; line++)
160 {
161 for (subline=0; subline<MAX_SUBLINES; subline++)
162 {
163 format_lines[line][subline] = 0;
164 time_mult[line][subline] = 0;
165 }
166 subline_expire_time[line] = 0;
167 curr_subline[line] = SUBLINE_RESET;
168 }
169
170 line = 0;
171 subline = 0;
172 format_lines[line][subline] = buf;
173
174 while ((*buf) && (line < MAX_LINES))
175 {
176 switch (*buf)
177 {
178 /*
179 * skip % sequences so "%;" doesn't start a new subline
180 * don't skip %x lines (pre-load bitmaps)
181 */
182 case '%':
183 if (*(buf+1) != 'x')
184 buf++;
185 break;
186
187 case '\r': /* CR */
188 *buf = 0;
189 break;
190
191 case '\n': /* LF */
192 *buf = 0;
193
194 if (*start_of_line != '#') /* A comment? */
195 line++;
196
197 if (line < MAX_LINES)
198 {
199 /* the next line starts on the next byte */
200 subline = 0;
201 format_lines[line][subline] = buf+1;
202 start_of_line = format_lines[line][subline];
203 }
204 break;
205
206 case ';': /* start a new subline */
207 *buf = 0;
208 subline++;
209 if (subline < MAX_SUBLINES)
210 {
211 format_lines[line][subline] = buf+1;
212 }
213 else /* exceeded max sublines, skip rest of line */
214 {
215 while (*(++buf))
216 {
217 if ((*buf == '\r') || (*buf == '\n'))
218 {
219 break;
220 }
221 }
222 buf--;
223 subline = 0;
224 }
225 break;
226
227 case 'x':
228#ifdef HAVE_LCD_BITMAP
229 /* Preload images so the %xd# tag can display it */
230 {
231 int ret = 0;
232 int n;
233 char *ptr = buf+1;
234 char *pos = NULL;
235 char imgname[MAX_PATH];
236 char qual = *ptr;
237 if (qual == 'l' || qual == '|') /* format:
238 %x|n|filename.bmp|x|y|
239 or
240 %xl|n|filename.bmp|x|y|
241 */
242 {
243 ptr = strchr(ptr, '|') + 1;
244 pos = strchr(ptr, '|');
245 if (pos)
246 {
247 /* get the image ID */
248 n = *ptr;
249 if(n >= 'a' && n <= 'z')
250 n -= 'a';
251 if(n >= 'A' && n <= 'Z')
252 n = n - 'A' + 26;
253
254 if(n < 0 || n >= MAX_IMAGES)
255 {
256 /* Skip the rest of the line */
257 while(*buf != '\n')
258 buf++;
259 break;
260 }
261 ptr = pos+1;
262
263 /* check the image number and load state */
264 if (!img[n].loaded)
265 {
266 /* get filename */
267 pos = strchr(ptr, '|');
268 if ((pos - ptr) <
269 (int)sizeof(imgname)-ROCKBOX_DIR_LEN-2)
270 {
271 memcpy(imgname, bmpdir, bmpdirlen);
272 imgname[bmpdirlen] = '/';
273 memcpy(&imgname[bmpdirlen+1],
274 ptr, pos - ptr);
275 imgname[bmpdirlen+1+pos-ptr] = 0;
276 }
277 else
278 /* filename too long */
279 imgname[0] = 0;
280
281 ptr = pos+1;
282
283 /* get x-position */
284 pos = strchr(ptr, '|');
285 if (pos)
286 img[n].x = atoi(ptr);
287 else
288 {
289 /* weird syntax, bail out */
290 buf++;
291 break;
292 }
293
294 /* get y-position */
295 ptr = pos+1;
296 pos = strchr(ptr, '|');
297 if (pos)
298 img[n].y = atoi(ptr);
299 else
300 {
301 /* weird syntax, bail out */
302 buf++;
303 break;
304 }
305
306 pos++;
307
308 /* reposition buf pointer to next WPS element */
309 while (*pos && *pos != ';' &&
310 *pos != '\r' && *pos != '\n')
311 pos++;
312
313 buf = pos;
314
315 /* load the image */
316 ret = read_bmp_file(imgname, &img[n].w, &img[n].h,
317 img_buf_ptr, img_buf_free);
318 if (ret > 0)
319 {
320 img[n].ptr = img_buf_ptr;
321 img_buf_ptr += ret;
322 img_buf_free -= ret;
323 img[n].loaded = true;
324 if(qual == '|')
325 img[n].always_display = true;
326 }
327 }
328 buf++;
329 }
330 }
331 }
332#endif
333 break;
334 }
335 buf++;
336 }
337}
338
339/* Clear the WPS image cache */
340static void wps_clear(void)
341{
342#ifdef HAVE_LCD_BITMAP
343 int i;
344
345 /* reset image buffer */
346 img_buf_ptr = img_buf;
347 img_buf_free = IMG_BUFSIZE;
348
349 /* set images to unloaded and not displayed */
350 for (i = 0; i < MAX_IMAGES; i++) {
351 img[i].loaded = false;
352 img[i].display = false;
353 img[i].always_display = false;
354 }
355#endif
356
357}
358
359void wps_reset(void)
360{
361 wps_loaded = false;
362 memset(&format_buffer, 0, sizeof format_buffer);
363 wps_clear();
364}
365
366bool wps_load(const char* file, bool display)
367{
368 int i,s;
369 char buffer[FORMAT_BUFFER_SIZE];
370 int fd;
371 size_t bmpdirlen;
372
373 char *bmpdir = strrchr(file, '.');
374 bmpdirlen = bmpdir - file;
375
376 /*
377 * Hardcode loading WPS_DEFAULTCFG to cause a reset ideally this
378 * wants to be a virtual file. Feel free to modify dirbrowse()
379 * if you're feeling brave.
380 */
381 if (! strcmp(file, WPS_DEFAULTCFG) ) {
382 wps_reset();
383 return(false);
384 }
385
386 fd = open(file, O_RDONLY);
387
388 if (fd >= 0)
389 {
390 int numread = read(fd, buffer, sizeof(buffer) - 1);
391
392 if (numread > 0)
393 {
394 wps_clear();
395 buffer[numread] = 0;
396 wps_format(buffer, (char *)file, bmpdirlen);
397 }
398
399 close(fd);
400
401 if ( display ) {
402 bool any_defined_line;
403 lcd_clear_display();
404#ifdef HAVE_LCD_BITMAP
405 lcd_setmargins(0,0);
406#endif
407 for (s=0; s<MAX_SUBLINES; s++)
408 {
409 any_defined_line = false;
410 for (i=0; i<MAX_LINES; i++)
411 {
412 if (format_lines[i][s])
413 {
414 if (*format_lines[i][s] == 0)
415 lcd_puts(0,i," ");
416 else
417 lcd_puts(0,i,format_lines[i][s]);
418 any_defined_line = true;
419 }
420 else
421 {
422 lcd_puts(0,i," ");
423 }
424 }
425 if (any_defined_line)
426 {
427#ifdef HAVE_LCD_BITMAP
428 wps_display_images();
429#endif
430 lcd_update();
431 sleep(HZ/2);
432 }
433 }
434 }
435 wps_loaded = true;
436
437 return numread > 0;
438 }
439
440 return false;
441}
442
443/* Format time into buf.
444 *
445 * buf - buffer to format to.
446 * buf_size - size of buffer.
447 * time - time to format, in milliseconds.
448 */
449void wps_format_time(char* buf, int buf_size, long time)
450{
451 if ( time < 3600000 ) {
452 snprintf(buf, buf_size, "%d:%02d",
453 (int) (time % 3600000 / 60000), (int) (time % 60000 / 1000));
454 } else {
455 snprintf(buf, buf_size, "%d:%02d:%02d",
456 (int) (time / 3600000), (int) (time % 3600000 / 60000),
457 (int) (time % 60000 / 1000));
458 }
459}
460
461/* Extract a part from a path.
462 *
463 * buf - buffer extract part to.
464 * buf_size - size of buffer.
465 * path - path to extract from.
466 * level - what to extract. 0 is file name, 1 is parent of file, 2 is
467 * parent of parent, etc.
468 *
469 * Returns buf if the desired level was found, NULL otherwise.
470 */
471static char* get_dir(char* buf, int buf_size, const char* path, int level)
472{
473 const char* sep;
474 const char* last_sep;
475 int len;
476
477 sep = path + strlen(path);
478 last_sep = sep;
479
480 while (sep > path)
481 {
482 if ('/' == *(--sep))
483 {
484 if (!level)
485 {
486 break;
487 }
488
489 level--;
490 last_sep = sep - 1;
491 }
492 }
493
494 if (level || (last_sep <= sep))
495 {
496 return NULL;
497 }
498
499 len = MIN(last_sep - sep, buf_size - 1);
500 strncpy(buf, sep + 1, len);
501 buf[len] = 0;
502 return buf;
503}
504
505/* Get the tag specified by the two characters at fmt.
506 *
507 * cid3 - ID3 data to get tag values from.
508 * nid3 - next-song ID3 data to get tag values from.
509 * tag - string (of two characters) specifying the tag to get.
510 * buf - buffer to certain tags, such as track number, play time or
511 * directory name.
512 * buf_size - size of buffer.
513 * flags - returns the type of the line. See constants i wps-display.h
514 *
515 * Returns the tag. NULL indicates the tag wasn't available.
516 */
517static char* get_tag(struct mp3entry* cid3,
518 struct mp3entry* nid3,
519 const char* tag,
520 char* buf,
521 int buf_size,
522 unsigned char* tag_len,
523 unsigned short* subline_time_mult,
524 unsigned char* flags,
525 int *intval)
526{
527 struct mp3entry *id3 = cid3; /* default to current song */
528
529 if ((0 == tag[0]) || (0 == tag[1]))
530 {
531 *tag_len = 0;
532 return NULL;
533 }
534
535 *tag_len = 2;
536
537 *intval = 0;
538
539 switch (tag[0])
540 {
541 case 'I': /* ID3 Information */
542 id3 = nid3; /* display next-song data */
543 *flags |= WPS_REFRESH_DYNAMIC;
544 if(!id3)
545 return NULL; /* no such info (yet) */
546 /* fall-through */
547 case 'i': /* ID3 Information */
548 *flags |= WPS_REFRESH_STATIC;
549 switch (tag[1])
550 {
551 case 't': /* ID3 Title */
552 return id3->title;
553
554 case 'a': /* ID3 Artist */
555 return id3->artist;
556
557 case 'n': /* ID3 Track Number */
558 if (id3->track_string)
559 return id3->track_string;
560
561 if (id3->tracknum) {
562 snprintf(buf, buf_size, "%d", id3->tracknum);
563 return buf;
564 }
565 return NULL;
566
567 case 'd': /* ID3 Album/Disc */
568 return id3->album;
569
570 case 'c': /* ID3 Composer */
571 return id3->composer;
572
573 case 'y': /* year */
574 if( id3->year_string )
575 return id3->year_string;
576
577 if (id3->year) {
578 snprintf(buf, buf_size, "%d", id3->year);
579 return buf;
580 }
581 return NULL;
582
583 case 'g': /* genre */
584 return id3_get_genre(id3);
585
586 case 'v': /* id3 version */
587 switch (id3->id3version) {
588 case ID3_VER_1_0:
589 return "1";
590
591 case ID3_VER_1_1:
592 return "1.1";
593
594 case ID3_VER_2_2:
595 return "2.2";
596
597 case ID3_VER_2_3:
598 return "2.3";
599
600 case ID3_VER_2_4:
601 return "2.4";
602
603 default:
604 return NULL;
605 }
606 }
607 break;
608
609 case 'F': /* File Information */
610 id3 = nid3;
611 *flags |= WPS_REFRESH_DYNAMIC;
612 if(!id3)
613 return NULL; /* no such info (yet) */
614 /* fall-through */
615 case 'f': /* File Information */
616 *flags |= WPS_REFRESH_STATIC;
617 switch(tag[1])
618 {
619 case 'v': /* VBR file? */
620 return id3->vbr ? "(avg)" : NULL;
621
622 case 'b': /* File Bitrate */
623 if(id3->bitrate)
624 snprintf(buf, buf_size, "%d", id3->bitrate);
625 else
626 snprintf(buf, buf_size, "?");
627 return buf;
628
629 case 'f': /* File Frequency */
630 snprintf(buf, buf_size, "%ld", id3->frequency);
631 return buf;
632
633 case 'p': /* File Path */
634 return id3->path;
635
636 case 'm': /* File Name - With Extension */
637 return get_dir(buf, buf_size, id3->path, 0);
638
639 case 'n': /* File Name */
640 if (get_dir(buf, buf_size, id3->path, 0))
641 {
642 /* Remove extension */
643 char* sep = strrchr(buf, '.');
644
645 if (NULL != sep)
646 {
647 *sep = 0;
648 }
649
650 return buf;
651 }
652 else
653 {
654 return NULL;
655 }
656
657 case 's': /* File Size (in kilobytes) */
658 snprintf(buf, buf_size, "%ld", id3->filesize / 1024);
659 return buf;
660
661 case 'c': /* File Codec */
662 if(id3->codectype == AFMT_UNKNOWN)
663 *intval = AFMT_NUM_CODECS;
664 else
665 *intval = id3->codectype;
666 return id3_get_codec(id3);
667 }
668 break;
669
670 case 'p': /* Playlist/Song Information */
671 switch(tag[1])
672 {
673 case 'b': /* progress bar */
674 *flags |= WPS_REFRESH_PLAYER_PROGRESS;
675#ifdef HAVE_LCD_CHARCELLS
676 snprintf(buf, buf_size, "%c", wps_progress_pat[0]);
677 full_line_progressbar=0;
678 return buf;
679#else
680 return "\x01";
681#endif
682 case 'f': /* full-line progress bar */
683#ifdef HAVE_LCD_CHARCELLS
684 if(is_new_player()) {
685 *flags |= WPS_REFRESH_PLAYER_PROGRESS;
686 *flags |= WPS_REFRESH_DYNAMIC;
687 full_line_progressbar=1;
688 /* we need 11 characters (full line) for
689 progress-bar */
690 snprintf(buf, buf_size, " ");
691 }
692 else
693 {
694 /* Tell the user if we have an OldPlayer */
695 snprintf(buf, buf_size, " <Old LCD> ");
696 }
697 return buf;
698#endif
699 case 'p': /* Playlist Position */
700 *flags |= WPS_REFRESH_STATIC;
701 snprintf(buf, buf_size, "%d", playlist_get_display_index());
702 return buf;
703
704 case 'n': /* Playlist Name (without path) */
705 *flags |= WPS_REFRESH_STATIC;
706 return playlist_name(NULL, buf, buf_size);
707
708 case 'e': /* Playlist Total Entries */
709 *flags |= WPS_REFRESH_STATIC;
710 snprintf(buf, buf_size, "%d", playlist_amount());
711 return buf;
712
713 case 'c': /* Current Time in Song */
714 *flags |= WPS_REFRESH_DYNAMIC;
715 wps_format_time(buf, buf_size,
716 id3->elapsed + ff_rewind_count);
717 return buf;
718
719 case 'r': /* Remaining Time in Song */
720 *flags |= WPS_REFRESH_DYNAMIC;
721 wps_format_time(buf, buf_size,
722 id3->length - id3->elapsed - ff_rewind_count);
723 return buf;
724
725 case 't': /* Total Time */
726 *flags |= WPS_REFRESH_STATIC;
727 wps_format_time(buf, buf_size, id3->length);
728 return buf;
729
730#ifdef HAVE_LCD_BITMAP
731 case 'm': /* Peak Meter */
732 *flags |= WPS_REFRESH_PEAK_METER;
733 return "\x01";
734#endif
735 case 's': /* shuffle */
736 *flags |= WPS_REFRESH_DYNAMIC;
737 if ( global_settings.playlist_shuffle )
738 return "s";
739 else
740 return NULL;
741 break;
742
743 case 'v': /* volume */
744 *flags |= WPS_REFRESH_DYNAMIC;
745 snprintf(buf, buf_size, "%d%%", global_settings.volume);
746 *intval = global_settings.volume / 10 + 1;
747 return buf;
748
749 }
750 break;
751
752 case 'm':
753 switch (tag[1])
754 {
755 case 'm': /* playback repeat mode */
756 *flags |= WPS_REFRESH_DYNAMIC;
757 *intval = global_settings.repeat_mode + 1;
758 snprintf(buf, buf_size, "%d", *intval);
759 return buf;
760
761 /* playback status */
762 case 'p': /* play */
763 *flags |= WPS_REFRESH_DYNAMIC;
764 int status = audio_status();
765 *intval = 1;
766 if (status == AUDIO_STATUS_PLAY && \
767 !(status & AUDIO_STATUS_PAUSE))
768 *intval = 2;
769 if (audio_status() & AUDIO_STATUS_PAUSE && \
770 (! status_get_ffmode()))
771 *intval = 3;
772 if (status_get_ffmode() == STATUS_FASTFORWARD)
773 *intval = 4;
774 if (status_get_ffmode() == STATUS_FASTBACKWARD)
775 *intval = 5;
776 snprintf(buf, buf_size, "%d", *intval);
777 return buf;
778
779#if CONFIG_KEYPAD == IRIVER_H100_PAD
780 case 'h': /* hold */
781 *flags |= WPS_REFRESH_DYNAMIC;
782 if (button_hold())
783 return "h";
784 else
785 return NULL;
786 case 'r': /* remote hold */
787 *flags |= WPS_REFRESH_DYNAMIC;
788 if (remote_button_hold())
789 return "r";
790 else
791 return NULL;
792#endif
793 }
794 break;
795
796 case 'b': /* battery info */
797 *flags |= WPS_REFRESH_DYNAMIC;
798 switch (tag[1]) {
799 case 'l': /* battery level */
800 {
801 int l = battery_level();
802 if (l > -1)
803 {
804 snprintf(buf, buf_size, "%d%%", l);
805 *intval = l / 20 + 1;
806 }
807 else
808 {
809 *intval = 6;
810 return "?%";
811 }
812 return buf;
813 }
814
815 case 't': /* estimated battery time */
816 {
817 int t = battery_time();
818 if (t >= 0)
819 snprintf(buf, buf_size, "%dh %dm", t / 60, t % 60);
820 else
821 strncpy(buf, "?h ?m", buf_size);
822 return buf;
823 }
824
825 case 'p': /* External power plugged in? */
826 {
827 if(charger_inserted())
828 return "p";
829 else
830 return NULL;
831 }
832 }
833 break;
834
835 case 'D': /* Directory path information */
836 id3 = nid3; /* next song please! */
837 *flags |= WPS_REFRESH_DYNAMIC;
838 if(!id3)
839 return NULL; /* no such info (yet) */
840 /* fall-through */
841 case 'd': /* Directory path information */
842 {
843 int level = tag[1] - '0';
844 *flags |= WPS_REFRESH_STATIC;
845 /* d1 through d9 */
846 if ((0 < level) && (9 > level))
847 {
848 return get_dir(buf, buf_size, id3->path, level);
849 }
850 }
851 break;
852
853 case 't': /* set sub line time multiplier */
854 {
855 int d = 1;
856 int time_mult = 0;
857 bool have_point = false;
858 bool have_tenth = false;
859
860 while (((tag[d] >= '0') &&
861 (tag[d] <= '9')) ||
862 (tag[d] == '.'))
863 {
864 if (tag[d] != '.')
865 {
866 time_mult = time_mult * 10;
867 time_mult = time_mult + tag[d] - '0';
868 if (have_point)
869 {
870 have_tenth = true;
871 d++;
872 break;
873 }
874 }
875 else
876 {
877 have_point = true;
878 }
879 d++;
880 }
881
882 if (have_tenth == false)
883 time_mult *= 10;
884
885 *subline_time_mult = time_mult;
886 *tag_len = d;
887
888 buf[0] = 0;
889 return buf;
890 }
891 break;
892 case 'r': /* Runtime database Information */
893 switch(tag[1])
894 {
895 case 'p': /* Playcount */
896 *flags |= WPS_REFRESH_STATIC;
897 snprintf(buf, buf_size, "%ld", cid3->playcount);
898 return buf;
899 case 'r': /* Rating */
900 *flags |= WPS_REFRESH_STATIC;
901 *intval = cid3->rating+1;
902 snprintf(buf, buf_size, "%d", cid3->rating);
903 return buf;
904 }
905 break;
906 }
907 return NULL;
908}
909
910/* Skip to the end of the current %? conditional.
911 *
912 * fmt - string to skip it. Should point to somewhere after the leading
913 * "<" char (and before or at the last ">").
914 * num - number of |'s to skip, or 0 to skip to the end (the ">").
915 *
916 * Returns the new position in fmt.
917 */
918static const char* skip_conditional(const char* fmt, int num)
919{
920 int level = 1;
921 int count = num;
922 const char *last_alternative = NULL;
923
924 while (*fmt)
925 {
926 switch (*fmt++)
927 {
928 case '%':
929 break;
930
931 case '|':
932 if(1 == level) {
933 last_alternative = fmt;
934 if(num) {
935 count--;
936 if(count == 0)
937 return fmt;
938 continue;
939 }
940 }
941 continue;
942
943 case '>':
944 if (0 == --level)
945 {
946 /* We're just skipping to the end */
947 if(num == 0)
948 return fmt;
949
950 /* If we are parsing an enum, we'll return the selected
951 item. If there weren't enough items in the enum, we'll
952 return the last one found. */
953 if(count && last_alternative)
954 {
955 return last_alternative;
956 }
957 return fmt - 1;
958 }
959 continue;
960
961 default:
962 continue;
963 }
964
965 switch (*fmt++)
966 {
967 case 0:
968 case '%':
969 case '|':
970 case '<':
971 case '>':
972 break;
973
974 case '?':
975 while (*fmt && ('<' != *fmt))
976 fmt++;
977
978 if ('<' == *fmt)
979 fmt++;
980
981 level++;
982 break;
983
984 default:
985 break;
986 }
987 }
988
989 return fmt;
990}
991
992/* Generate the display based on id3 information and format string.
993 *
994 * buf - char buffer to write the display to.
995 * buf_size - the size of buffer.
996 * id3 - the ID3 data to format with.
997 * nid3 - the ID3 data of the next song (might by NULL)
998 * fmt - format description.
999 * flags - returns the type of the line. See constants i wps-display.h
1000 */
1001static void format_display(char* buf,
1002 int buf_size,
1003 struct mp3entry* id3,
1004 struct mp3entry* nid3, /* next song's id3 */
1005 const char* fmt,
1006 struct align_pos* align,
1007 unsigned short* subline_time_mult,
1008 unsigned char* flags)
1009{
1010 char temp_buf[128];
1011 char* buf_start = buf;
1012 char* buf_end = buf + buf_size - 1; /* Leave room for end null */
1013 char* value = NULL;
1014 int level = 0;
1015 unsigned char tag_length;
1016 int intval;
1017 int cur_align;
1018 char* cur_align_start;
1019#ifdef HAVE_LCD_BITMAP
1020 int n;
1021#endif
1022
1023 cur_align_start = buf;
1024 cur_align = WPS_ALIGN_LEFT;
1025 *subline_time_mult = DEFAULT_SUBLINE_TIME_MULTIPLIER;
1026
1027 align->left = 0;
1028 align->center = 0;
1029 align->right = 0;
1030
1031 while (fmt && *fmt && buf < buf_end)
1032 {
1033 switch (*fmt)
1034 {
1035 case '%':
1036 ++fmt;
1037 break;
1038
1039 case '|':
1040 case '>':
1041 if (level > 0)
1042 {
1043 fmt = skip_conditional(fmt, 0);
1044 level--;
1045 continue;
1046 }
1047 /* Else fall through */
1048
1049 default:
1050 *buf++ = *fmt++;
1051 continue;
1052 }
1053
1054 switch (*fmt)
1055 {
1056 case 0:
1057 *buf++ = '%';
1058 break;
1059 case 'a':
1060 ++fmt;
1061 /* remember where the current aligned text started */
1062 switch (cur_align)
1063 {
1064 case WPS_ALIGN_LEFT:
1065 align->left = cur_align_start;
1066 break;
1067
1068 case WPS_ALIGN_CENTER:
1069 align->center = cur_align_start;
1070 break;
1071
1072 case WPS_ALIGN_RIGHT:
1073 align->right = cur_align_start;
1074 break;
1075 }
1076 /* start a new alignment */
1077 switch (*fmt)
1078 {
1079 case 'l':
1080 cur_align = WPS_ALIGN_LEFT;
1081 break;
1082 case 'c':
1083 cur_align = WPS_ALIGN_CENTER;
1084 break;
1085 case 'r':
1086 cur_align = WPS_ALIGN_RIGHT;
1087 break;
1088 }
1089 *buf++=0;
1090 cur_align_start = buf;
1091 ++fmt;
1092 break;
1093 case 's':
1094 *flags |= WPS_REFRESH_SCROLL;
1095 ++fmt;
1096 break;
1097
1098 case 'x': /* image support */
1099#ifdef HAVE_LCD_BITMAP
1100 /* skip preload or regular image tag */
1101 if ('l' == *(fmt+1) || '|' == *(fmt+1))
1102 {
1103 while (*fmt && *fmt != '\n')
1104 fmt++;
1105 }
1106 else if ('d' == *(fmt+1))
1107 {
1108 fmt+=2;
1109
1110 /* get the image ID */
1111 n = *fmt;
1112 if(n >= 'a' && n <= 'z')
1113 n -= 'a';
1114 if(n >= 'A' && n <= 'Z')
1115 n = n - 'A' + 26;
1116
1117 if (n >= 0 && n < MAX_IMAGES && img[n].loaded) {
1118 img[n].display = true;
1119 }
1120 }
1121#endif
1122 fmt++;
1123 break;
1124
1125
1126 case '%':
1127 case '|':
1128 case '<':
1129 case '>':
1130 case ';':
1131 *buf++ = *fmt++;
1132 break;
1133
1134 case '?':
1135 fmt++;
1136 value = get_tag(id3, nid3, fmt, temp_buf, sizeof(temp_buf),
1137 &tag_length, subline_time_mult, flags,
1138 &intval);
1139
1140 while (*fmt && ('<' != *fmt))
1141 fmt++;
1142
1143 if ('<' == *fmt)
1144 fmt++;
1145
1146 /* No value, so skip to else part, using a sufficiently high
1147 value to "hit" the last part of the conditional */
1148 if ((!value) || (!strlen(value)))
1149 fmt = skip_conditional(fmt, 1000);
1150 else
1151 if(intval > 1) /* enum */
1152 fmt = skip_conditional(fmt, intval - 1);
1153
1154 level++;
1155 break;
1156
1157 default:
1158 value = get_tag(id3, nid3, fmt, temp_buf, sizeof(temp_buf),
1159 &tag_length, subline_time_mult, flags,
1160 &intval);
1161 fmt += tag_length;
1162
1163 if (value)
1164 {
1165 while (*value && (buf < buf_end))
1166 *buf++ = *value++;
1167 }
1168 }
1169 }
1170
1171 /* remember where the current aligned text started */
1172 switch (cur_align)
1173 {
1174 case WPS_ALIGN_LEFT:
1175 align->left = cur_align_start;
1176 break;
1177
1178 case WPS_ALIGN_CENTER:
1179 align->center = cur_align_start;
1180 break;
1181
1182 case WPS_ALIGN_RIGHT:
1183 align->right = cur_align_start;
1184 break;
1185 }
1186
1187 *buf = 0;
1188
1189 /* if resulting line is an empty line, set the subline time to 0 */
1190 if (buf - buf_start == 0)
1191 *subline_time_mult = 0;
1192
1193 /* If no flags have been set, the line didn't contain any format codes.
1194 We still want to refresh it. */
1195 if(*flags == 0)
1196 *flags = WPS_REFRESH_STATIC;
1197}
1198
1199bool wps_refresh(struct mp3entry* id3,
1200 struct mp3entry* nid3,
1201 int ffwd_offset,
1202 unsigned char refresh_mode)
1203{
1204 char buf[MAX_PATH];
1205 unsigned char flags;
1206 int i;
1207 bool update_line;
1208 bool only_one_subline;
1209 bool new_subline_refresh;
1210 int search;
1211 int search_start;
1212#ifdef HAVE_LCD_BITMAP
1213 int h = font_get(FONT_UI)->height;
1214 int offset = global_settings.statusbar ? STATUSBAR_HEIGHT : 0;
1215 /* to find out wether the peak meter is enabled we
1216 assume it wasn't until we find a line that contains
1217 the peak meter. We can't use peak_meter_enabled itself
1218 because that would mean to turn off the meter thread
1219 temporarily. (That shouldn't matter unless yield
1220 or sleep is called but who knows...)
1221 */
1222 bool enable_pm = false;
1223
1224 /* Set images to not to be displayed */
1225 for (i = 0; i < MAX_IMAGES; i++) {
1226 img[i].display = false;
1227 }
1228#endif
1229
1230 /* reset to first subline if refresh all flag is set */
1231 if (refresh_mode == WPS_REFRESH_ALL)
1232 {
1233 for (i=0; i<MAX_LINES; i++)
1234 {
1235 curr_subline[i] = SUBLINE_RESET;
1236 }
1237 }
1238
1239#ifdef HAVE_LCD_CHARCELLS
1240 for (i=0; i<8; i++) {
1241 if (wps_progress_pat[i]==0)
1242 wps_progress_pat[i]=lcd_get_locked_pattern();
1243 }
1244#endif
1245
1246 if (!id3)
1247 {
1248 lcd_stop_scroll();
1249 return false;
1250 }
1251
1252 ff_rewind_count = ffwd_offset;
1253
1254 for (i = 0; i < MAX_LINES; i++)
1255 {
1256 new_subline_refresh = false;
1257 only_one_subline = false;
1258
1259 /* if time to advance to next sub-line */
1260 if (TIME_AFTER(current_tick, subline_expire_time[i] - 1) ||
1261 (curr_subline[i] == SUBLINE_RESET))
1262 {
1263 /* search all sublines until the next subline with time > 0
1264 is found or we get back to the subline we started with */
1265 if (curr_subline[i] == SUBLINE_RESET)
1266 search_start = 0;
1267 else
1268 search_start = curr_subline[i];
1269 for (search=0; search<MAX_SUBLINES; search++)
1270 {
1271 curr_subline[i]++;
1272
1273 /* wrap around if beyond last defined subline or MAX_SUBLINES */
1274 if ((!format_lines[i][curr_subline[i]]) ||
1275 (curr_subline[i] == MAX_SUBLINES))
1276 {
1277 if (curr_subline[i] == 1)
1278 only_one_subline = true;
1279 curr_subline[i] = 0;
1280 }
1281
1282 /* if back where we started after search or
1283 only one subline is defined on the line */
1284 if (((search > 0) && (curr_subline[i] == search_start)) ||
1285 only_one_subline)
1286 {
1287 /* no other subline with a time > 0 exists */
1288 subline_expire_time[i] = current_tick + 100 * HZ;
1289 break;
1290 }
1291 else
1292 {
1293 /* get initial time multiplier and
1294 line type flags for this subline */
1295 format_display(buf, sizeof(buf), id3, nid3,
1296 format_lines[i][curr_subline[i]],
1297 &format_align[i][curr_subline[i]],
1298 &time_mult[i][curr_subline[i]],
1299 &line_type[i][curr_subline[i]]);
1300
1301 /* only use this subline if subline time > 0 */
1302 if (time_mult[i][curr_subline[i]] > 0)
1303 {
1304 new_subline_refresh = true;
1305 subline_expire_time[i] = current_tick +
1306 BASE_SUBLINE_TIME * time_mult[i][curr_subline[i]];
1307 break;
1308 }
1309 }
1310 }
1311
1312 }
1313
1314 update_line = false;
1315
1316 if ( !format_lines[i][curr_subline[i]] )
1317 break;
1318
1319 if ((line_type[i][curr_subline[i]] & refresh_mode) ||
1320 (refresh_mode == WPS_REFRESH_ALL) ||
1321 new_subline_refresh)
1322 {
1323 flags = 0;
1324#ifdef HAVE_LCD_BITMAP
1325 int left_width, left_xpos;
1326 int center_width, center_xpos;
1327 int right_width, right_xpos;
1328 int space_width;
1329 int string_height;
1330 int ypos;
1331#endif
1332
1333 format_display(buf, sizeof(buf), id3, nid3,
1334 format_lines[i][curr_subline[i]],
1335 &format_align[i][curr_subline[i]],
1336 &time_mult[i][curr_subline[i]],
1337 &flags);
1338 line_type[i][curr_subline[i]] = flags;
1339
1340#ifdef HAVE_LCD_BITMAP
1341 /* progress */
1342 if (flags & refresh_mode & WPS_REFRESH_PLAYER_PROGRESS)
1343 {
1344#define PROGRESS_BAR_HEIGHT 6 /* this should probably be defined elsewhere; config-*.h perhaps? */
1345 int sby = i*h + offset + (h > 7 ? (h - 6) / 2 : 1);
1346 scrollbar(0, sby, LCD_WIDTH, PROGRESS_BAR_HEIGHT,
1347 id3->length?id3->length:1, 0,
1348 id3->length?id3->elapsed + ff_rewind_count:0,
1349 HORIZONTAL);
1350#ifdef AB_REPEAT_ENABLE
1351 if ( ab_repeat_mode_enabled() )
1352 ab_draw_markers(id3->length, 0, sby, LCD_WIDTH, PROGRESS_BAR_HEIGHT);
1353#endif
1354 update_line = true;
1355 }
1356 if (flags & refresh_mode & WPS_REFRESH_PEAK_METER) {
1357 /* peak meter */
1358 int peak_meter_y;
1359
1360 update_line = true;
1361 peak_meter_y = i * h + offset;
1362
1363 /* The user might decide to have the peak meter in the last
1364 line so that it is only displayed if no status bar is
1365 visible. If so we neither want do draw nor enable the
1366 peak meter. */
1367 if (peak_meter_y + h <= LCD_HEIGHT) {
1368 /* found a line with a peak meter -> remember that we must
1369 enable it later */
1370 enable_pm = true;
1371 peak_meter_draw(0, peak_meter_y, LCD_WIDTH,
1372 MIN(h, LCD_HEIGHT - peak_meter_y));
1373 }
1374 }
1375#else
1376 /* progress */
1377 if (flags & refresh_mode & WPS_REFRESH_PLAYER_PROGRESS) {
1378 if (full_line_progressbar)
1379 draw_player_fullbar(buf, sizeof(buf),
1380 id3, ff_rewind_count);
1381 else
1382 draw_player_progress(id3, ff_rewind_count);
1383 }
1384#endif
1385#ifdef HAVE_LCD_BITMAP
1386 /* calculate different string sizes and positions */
1387 lcd_getstringsize(" ", &space_width, &string_height);
1388 if (format_align[i][curr_subline[i]].left != 0) {
1389 lcd_getstringsize(format_align[i][curr_subline[i]].left,
1390 &left_width, &string_height);
1391 }
1392 else {
1393 left_width = 0;
1394 }
1395 left_xpos = 0;
1396
1397 if (format_align[i][curr_subline[i]].center != 0) {
1398 lcd_getstringsize(format_align[i][curr_subline[i]].center,
1399 &center_width, &string_height);
1400 }
1401 else {
1402 center_width = 0;
1403 }
1404 center_xpos=(LCD_WIDTH - center_width) / 2;
1405
1406 if (format_align[i][curr_subline[i]].right != 0) {
1407 lcd_getstringsize(format_align[i][curr_subline[i]].right,
1408 &right_width, &string_height);
1409 }
1410 else {
1411 right_width = 0;
1412 }
1413 right_xpos = (LCD_WIDTH - right_width);
1414
1415 /* Checks for overlapping strings.
1416 If needed the overlapping strings will be merged, separated by a
1417 space */
1418
1419 /* CASE 1: left and centered string overlap */
1420 /* there is a left string, need to merge left and center */
1421 if ((left_width != 0 && center_width != 0) &&
1422 (left_xpos + left_width + space_width > center_xpos)) {
1423 /* replace the former separator '\0' of left and
1424 center string with a space */
1425 *(--format_align[i][curr_subline[i]].center) = ' ';
1426 /* calculate the new width and position of the merged string */
1427 left_width = left_width + space_width + center_width;
1428 left_xpos = 0;
1429 /* there is no centered string anymore */
1430 center_width = 0;
1431 }
1432 /* there is no left string, move center to left */
1433 if ((left_width == 0 && center_width != 0) &&
1434 (left_xpos + left_width > center_xpos)) {
1435 /* move the center string to the left string */
1436 format_align[i][curr_subline[i]].left = format_align[i][curr_subline[i]].center;
1437 /* calculate the new width and position of the string */
1438 left_width = center_width;
1439 left_xpos = 0;
1440 /* there is no centered string anymore */
1441 center_width = 0;
1442 }
1443
1444 /* CASE 2: centered and right string overlap */
1445 /* there is a right string, need to merge center and right */
1446 if ((center_width != 0 && right_width != 0) &&
1447 (center_xpos + center_width + space_width > right_xpos)) {
1448 /* replace the former separator '\0' of center and
1449 right string with a space */
1450 *(--format_align[i][curr_subline[i]].right) = ' ';
1451 /* move the center string to the right after merge */
1452 format_align[i][curr_subline[i]].right = format_align[i][curr_subline[i]].center;
1453 /* calculate the new width and position of the merged string */
1454 right_width = center_width + space_width + right_width;
1455 right_xpos = (LCD_WIDTH - right_width);
1456 /* there is no centered string anymore */
1457 center_width = 0;
1458 }
1459 /* there is no right string, move center to right */
1460 if ((center_width != 0 && right_width == 0) &&
1461 (center_xpos + center_width > right_xpos)) {
1462 /* move the center string to the right string */
1463 format_align[i][curr_subline[i]].right = format_align[i][curr_subline[i]].center;
1464 /* calculate the new width and position of the string */
1465 right_width = center_width;
1466 right_xpos = (LCD_WIDTH - right_width);
1467 /* there is no centered string anymore */
1468 center_width = 0;
1469 }
1470
1471 /* CASE 3: left and right overlap
1472 There is no center string anymore, either there never
1473 was one or it has been merged in case 1 or 2 */
1474 /* there is a left string, need to merge left and right */
1475 if ((left_width != 0 && center_width == 0 && right_width != 0) &&
1476 (left_xpos + left_width + space_width > right_xpos)) {
1477 /* replace the former separator '\0' of left and
1478 right string with a space */
1479 *(--format_align[i][curr_subline[i]].right) = ' ';
1480 /* calculate the new width and position of the string */
1481 left_width = left_width + space_width + right_width;
1482 left_xpos = 0;
1483 /* there is no right string anymore */
1484 right_width = 0;
1485 }
1486 /* there is no left string, move right to left */
1487 if ((left_width == 0 && center_width == 0 && right_width != 0) &&
1488 (left_xpos + left_width > right_xpos)) {
1489 /* move the right string to the left string */
1490 format_align[i][curr_subline[i]].left = format_align[i][curr_subline[i]].right;
1491 /* calculate the new width and position of the string */
1492 left_width = right_width;
1493 left_xpos = 0;
1494 /* there is no right string anymore */
1495 right_width = 0;
1496 }
1497
1498#endif
1499
1500 if (flags & WPS_REFRESH_SCROLL) {
1501
1502 /* scroll line */
1503 if ((refresh_mode & WPS_REFRESH_SCROLL) ||
1504 new_subline_refresh) {
1505#ifdef HAVE_LCD_BITMAP
1506 ypos = (i*string_height)+lcd_getymargin();
1507 update_line = true;
1508
1509 if (left_width>LCD_WIDTH) {
1510 lcd_puts_scroll(0, i, format_align[i][curr_subline[i]].left);
1511 } else {
1512 /* clear the line first */
1513 lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
1514 lcd_fillrect(0, ypos, LCD_WIDTH, string_height);
1515 lcd_set_drawmode(DRMODE_SOLID);
1516
1517 /* Nasty hack: we output an empty scrolling string,
1518 which will reset the scroller for that line */
1519 lcd_puts_scroll(0, i, "");
1520
1521 /* print aligned strings */
1522 if (left_width != 0)
1523 {
1524 lcd_putsxy(left_xpos, ypos, format_align[i][curr_subline[i]].left);
1525 }
1526 if (center_width != 0)
1527 {
1528 lcd_putsxy(center_xpos, ypos, format_align[i][curr_subline[i]].center);
1529 }
1530 if (right_width != 0)
1531 {
1532 lcd_putsxy(right_xpos, ypos, format_align[i][curr_subline[i]].right);
1533 }
1534 }
1535#else
1536 lcd_puts_scroll(0, i, buf);
1537 update_line = true;
1538#endif
1539 }
1540 }
1541 else if (flags & (WPS_REFRESH_DYNAMIC | WPS_REFRESH_STATIC))
1542 {
1543 /* dynamic / static line */
1544 if ((refresh_mode & (WPS_REFRESH_DYNAMIC|WPS_REFRESH_STATIC)) ||
1545 new_subline_refresh)
1546 {
1547#ifdef HAVE_LCD_BITMAP
1548 ypos = (i*string_height)+lcd_getymargin();
1549 update_line = true;
1550
1551 /* clear the line first */
1552 lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
1553 lcd_fillrect(0, ypos, LCD_WIDTH, string_height);
1554 lcd_set_drawmode(DRMODE_SOLID);
1555
1556 /* Nasty hack: we output an empty scrolling string,
1557 which will reset the scroller for that line */
1558 lcd_puts_scroll(0, i, "");
1559
1560 /* print aligned strings */
1561 if (left_width != 0)
1562 {
1563 lcd_putsxy(left_xpos, ypos, format_align[i][curr_subline[i]].left);
1564 }
1565 if (center_width != 0)
1566 {
1567 lcd_putsxy(center_xpos, ypos, format_align[i][curr_subline[i]].center);
1568 }
1569 if (right_width != 0)
1570 {
1571 lcd_putsxy(right_xpos, ypos, format_align[i][curr_subline[i]].right);
1572 }
1573#else
1574 update_line = true;
1575 lcd_puts(0, i, buf);
1576#endif
1577 }
1578 }
1579 }
1580#ifdef HAVE_LCD_BITMAP
1581 if (update_line) {
1582 lcd_update_rect(0, i*h + offset, LCD_WIDTH, h);
1583 }
1584#endif
1585 }
1586
1587#ifdef HAVE_LCD_BITMAP
1588 /* Display all images */
1589 for (i = 0; i < MAX_IMAGES; i++) {
1590 if(img[i].always_display)
1591 img[i].display = img[i].always_display;
1592 }
1593 wps_display_images();
1594
1595 /* Now we know wether the peak meter is used.
1596 So we can enable / disable the peak meter thread */
1597 peak_meter_enabled = enable_pm;
1598#endif
1599
1600#if defined(CONFIG_BACKLIGHT) && !defined(SIMULATOR)
1601 if (global_settings.caption_backlight && id3) {
1602 /* turn on backlight n seconds before track ends, and turn it off n
1603 seconds into the new track. n == backlight_timeout, or 5s */
1604 int n =
1605 backlight_timeout_value[global_settings.backlight_timeout] * 1000;
1606
1607 if ( n < 1000 )
1608 n = 5000; /* use 5s if backlight is always on or off */
1609
1610 if ((id3->elapsed < 1000) ||
1611 ((id3->length - id3->elapsed) < (unsigned)n))
1612 backlight_on();
1613 }
1614#endif
1615 return true;
1616}
1617
1618bool wps_display(struct mp3entry* id3,
1619 struct mp3entry* nid3)
1620{
1621 if (!id3 && !(audio_status() & AUDIO_STATUS_PLAY))
1622 {
1623 global_settings.resume_index = -1;
1624#ifdef HAVE_LCD_CHARCELLS
1625 gui_syncsplash(HZ, true, str(LANG_END_PLAYLIST_PLAYER));
1626#else
1627 status_draw(true);
1628 gui_syncsplash(HZ, true, str(LANG_END_PLAYLIST_RECORDER));
1629#endif
1630 return true;
1631 }
1632 else
1633 {
1634 lcd_clear_display();
1635
1636 if (!wps_loaded) {
1637 if ( !format_buffer[0] ) {
1638#ifdef HAVE_LCD_BITMAP
1639 wps_format("%s%?it<%?in<%in. |>%it|%fn>\n"
1640 "%s%?ia<%ia|%?d2<%d2|(root)>>\n"
1641 "%s%?id<%id|%?d1<%d1|(root)>> %?iy<(%iy)|>\n"
1642 "\n"
1643 "%al%pc/%pt%ar[%pp:%pe]\n"
1644 "%fbkBit %?fv<avg|> %?iv<(id3v%iv)|(no id3)>\n"
1645 "%pb\n"
1646 "%pm\n", NULL, 0);
1647#else
1648 wps_format("%s%pp/%pe: %?it<%it|%fn> - %?ia<%ia|%d2> - %?id<%id|%d1>\n"
1649 "%pc%?ps<*|/>%pt\n", NULL, 0);
1650#endif
1651 }
1652 }
1653 }
1654 yield();
1655 wps_refresh(id3, nid3, 0, WPS_REFRESH_ALL);
1656 status_draw(true);
1657#ifdef HAVE_LCD_BITMAP
1658 wps_display_images();
1659#endif
1660 lcd_update();
1661 return false;
1662}
1663
1664#ifdef HAVE_LCD_CHARCELLS
1665static bool draw_player_progress(const struct mp3entry* id3,
1666 int ff_rewwind_count)
1667{
1668 char player_progressbar[7];
1669 char binline[36];
1670 int songpos = 0;
1671 int i,j;
1672
1673 if (!id3)
1674 return false;
1675
1676 memset(binline, 1, sizeof binline);
1677 memset(player_progressbar, 1, sizeof player_progressbar);
1678
1679 if(id3->elapsed >= id3->length)
1680 songpos = 0;
1681 else
1682 {
1683 if(wps_time_countup == false)
1684 songpos = ((id3->elapsed - ff_rewwind_count) * 36) / id3->length;
1685 else
1686 songpos = ((id3->elapsed + ff_rewwind_count) * 36) / id3->length;
1687 }
1688 for (i=0; i < songpos; i++)
1689 binline[i] = 0;
1690
1691 for (i=0; i<=6; i++) {
1692 for (j=0;j<5;j++) {
1693 player_progressbar[i] <<= 1;
1694 player_progressbar[i] += binline[i*5+j];
1695 }
1696 }
1697 lcd_define_pattern(wps_progress_pat[0], player_progressbar);
1698 return true;
1699}
1700
1701static void draw_player_fullbar(char* buf, int buf_size,
1702 const struct mp3entry* id3,
1703 int ff_rewwind_count)
1704{
1705 int i,j,lcd_char_pos;
1706
1707 char player_progressbar[7];
1708 char binline[36];
1709 static const char numbers[12][4][3]={
1710 {{1,1,1},{1,0,1},{1,0,1},{1,1,1}},/*0*/
1711 {{0,1,0},{1,1,0},{0,1,0},{0,1,0}},/*1*/
1712 {{1,1,1},{0,0,1},{0,1,0},{1,1,1}},/*2*/
1713 {{1,1,1},{0,0,1},{0,1,1},{1,1,1}},/*3*/
1714 {{1,0,0},{1,1,0},{1,1,1},{0,1,0}},/*4*/
1715 {{1,1,1},{1,1,0},{0,0,1},{1,1,0}},/*5*/
1716 {{1,1,1},{1,0,0},{1,1,1},{1,1,1}},/*6*/
1717 {{1,1,1},{0,0,1},{0,1,0},{1,0,0}},/*7*/
1718 {{1,1,1},{1,1,1},{1,0,1},{1,1,1}},/*8*/
1719 {{1,1,1},{1,1,1},{0,0,1},{1,1,1}},/*9*/
1720 {{0,0,0},{0,1,0},{0,0,0},{0,1,0}},/*:*/
1721 {{0,0,0},{0,0,0},{0,0,0},{0,0,0}} /*<blank>*/
1722 };
1723
1724 int songpos = 0;
1725 int digits[6];
1726 int time;
1727 char timestr[7];
1728
1729 for (i=0; i < buf_size; i++)
1730 buf[i] = ' ';
1731
1732 if(id3->elapsed >= id3->length)
1733 songpos = 55;
1734 else {
1735 if(wps_time_countup == false)
1736 songpos = ((id3->elapsed - ff_rewwind_count) * 55) / id3->length;
1737 else
1738 songpos = ((id3->elapsed + ff_rewwind_count) * 55) / id3->length;
1739 }
1740
1741 time=(id3->elapsed + ff_rewind_count);
1742
1743 memset(timestr, 0, sizeof(timestr));
1744 wps_format_time(timestr, sizeof(timestr), time);
1745 for(lcd_char_pos=0; lcd_char_pos<6; lcd_char_pos++) {
1746 digits[lcd_char_pos] = map_fullbar_char(timestr[lcd_char_pos]);
1747 }
1748
1749 /* build the progressbar-icons */
1750 for (lcd_char_pos=0; lcd_char_pos<6; lcd_char_pos++) {
1751 memset(binline, 0, sizeof binline);
1752 memset(player_progressbar, 0, sizeof player_progressbar);
1753
1754 /* make the character (progressbar & digit)*/
1755 for (i=0; i<7; i++) {
1756 for (j=0;j<5;j++) {
1757 /* make the progressbar */
1758 if (lcd_char_pos==(songpos/5)) {
1759 /* partial */
1760 if ((j<(songpos%5))&&(i>4))
1761 binline[i*5+j] = 1;
1762 else
1763 binline[i*5+j] = 0;
1764 }
1765 else {
1766 if (lcd_char_pos<(songpos/5)) {
1767 /* full character */
1768 if (i>4)
1769 binline[i*5+j] = 1;
1770 }
1771 }
1772 /* insert the digit */
1773 if ((j<3)&&(i<4)) {
1774 if (numbers[digits[lcd_char_pos]][i][j]==1)
1775 binline[i*5+j] = 1;
1776 }
1777 }
1778 }
1779
1780 for (i=0; i<=6; i++) {
1781 for (j=0;j<5;j++) {
1782 player_progressbar[i] <<= 1;
1783 player_progressbar[i] += binline[i*5+j];
1784 }
1785 }
1786
1787 lcd_define_pattern(wps_progress_pat[lcd_char_pos+1],player_progressbar);
1788 buf[lcd_char_pos]=wps_progress_pat[lcd_char_pos+1];
1789
1790 }
1791
1792 /* make rest of the progressbar if necessary */
1793 if (songpos/5>5) {
1794
1795 /* set the characters positions that use the full 5 pixel wide bar */
1796 for (lcd_char_pos=6; lcd_char_pos < (songpos/5); lcd_char_pos++)
1797 buf[lcd_char_pos] = 0x86; /* '_' */
1798
1799 /* build the partial bar character for the tail character position */
1800 memset(binline, 0, sizeof binline);
1801 memset(player_progressbar, 0, sizeof player_progressbar);
1802
1803 for (i=5; i<7; i++) {
1804 for (j=0;j<5;j++) {
1805 if (j<(songpos%5)) {
1806 binline[i*5+j] = 1;
1807 }
1808 }
1809 }
1810
1811 for (i=0; i<7; i++) {
1812 for (j=0;j<5;j++) {
1813 player_progressbar[i] <<= 1;
1814 player_progressbar[i] += binline[i*5+j];
1815 }
1816 }
1817
1818 lcd_define_pattern(wps_progress_pat[7],player_progressbar);
1819
1820 buf[songpos/5]=wps_progress_pat[7];
1821 }
1822}
1823
1824static char map_fullbar_char(char ascii_val)
1825{
1826 if (ascii_val >= '0' && ascii_val <= '9') {
1827 return(ascii_val - '0');
1828 }
1829 else if (ascii_val == ':') {
1830 return(10);
1831 }
1832 else
1833 return(11); /* anything besides a number or ':' is mapped to <blank> */
1834}
1835
1836
1837#endif
1838
1839/* -----------------------------------------------------------------
1840 * vim: et sw=4 ts=8 sts=4 tw=78
1841 */
diff --git a/apps/wps-display.h b/apps/wps-display.h
deleted file mode 100644
index b23c0d603d..0000000000
--- a/apps/wps-display.h
+++ /dev/null
@@ -1,48 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Björn Stenberg
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#ifndef WPS_DISPLAY
20#define WPS_DISPLAY
21
22#include <stdbool.h>
23#include "id3.h"
24
25/* constants used in line_type and as refresh_mode for wps_refresh */
26#define WPS_REFRESH_STATIC 1 /* line doesn't change over time */
27#define WPS_REFRESH_DYNAMIC 2 /* line may change (e.g. time flag) */
28#define WPS_REFRESH_SCROLL 4 /* line scrolls */
29#define WPS_REFRESH_PLAYER_PROGRESS 8 /* line contains a progress bar */
30#define WPS_REFRESH_PEAK_METER 16 /* line contains a peak meter */
31#define WPS_REFRESH_ALL 0xff /* to refresh all line types */
32/* to refresh only those lines that change over time */
33#define WPS_REFRESH_NON_STATIC (WPS_REFRESH_ALL & ~WPS_REFRESH_STATIC & ~WPS_REFRESH_SCROLL)
34
35/* alignments */
36#define WPS_ALIGN_RIGHT 32
37#define WPS_ALIGN_CENTER 64
38#define WPS_ALIGN_LEFT 128
39
40
41void wps_format_time(char* buf, int buf_size, long time);
42bool wps_refresh(struct mp3entry* id3, struct mp3entry* nid3,
43 int ffwd_offset, unsigned char refresh_mode);
44bool wps_display(struct mp3entry* id3, struct mp3entry* nid3);
45bool wps_load(const char* file, bool display);
46void wps_reset(void);
47
48#endif
diff --git a/apps/wps.c b/apps/wps.c
deleted file mode 100644
index 573444fdc4..0000000000
--- a/apps/wps.c
+++ /dev/null
@@ -1,882 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Jerome Kuptz
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 <stdio.h>
20#include <string.h>
21#include <stdlib.h>
22
23#include "system.h"
24#include "file.h"
25#include "lcd.h"
26#include "font.h"
27#include "backlight.h"
28#include "button.h"
29#include "kernel.h"
30#include "tree.h"
31#include "debug.h"
32#include "sprintf.h"
33#include "settings.h"
34#include "wps.h"
35#include "wps-display.h"
36#include "audio.h"
37#include "mp3_playback.h"
38#include "usb.h"
39#include "status.h"
40#include "main_menu.h"
41#include "ata.h"
42#include "screens.h"
43#include "playlist.h"
44#ifdef HAVE_LCD_BITMAP
45#include "icons.h"
46#include "peakmeter.h"
47#endif
48#include "action.h"
49#include "lang.h"
50#include "bookmark.h"
51#include "misc.h"
52#include "sound.h"
53#include "onplay.h"
54#include "abrepeat.h"
55#include "playback.h"
56#include "splash.h"
57
58#define FF_REWIND_MAX_PERCENT 3 /* cap ff/rewind step size at max % of file */
59 /* 3% of 30min file == 54s step size */
60#define MIN_FF_REWIND_STEP 500
61
62bool keys_locked = false;
63static bool ff_rewind = false;
64static bool paused = false;
65static struct mp3entry* id3 = NULL;
66static struct mp3entry* nid3 = NULL;
67static char current_track_path[MAX_PATH+1];
68
69/* set volume
70 return true if screen restore is needed
71 return false otherwise
72*/
73static bool setvol(void)
74{
75 if (global_settings.volume < sound_min(SOUND_VOLUME))
76 global_settings.volume = sound_min(SOUND_VOLUME);
77 if (global_settings.volume > sound_max(SOUND_VOLUME))
78 global_settings.volume = sound_max(SOUND_VOLUME);
79 sound_set_volume(global_settings.volume);
80 status_draw(false);
81 wps_refresh(id3, nid3, 0, WPS_REFRESH_NON_STATIC);
82 settings_save();
83#ifdef HAVE_LCD_CHARCELLS
84 gui_syncsplash(0, false, "Vol: %d %% ",
85 sound_val2phys(SOUND_VOLUME, global_settings.volume));
86 return true;
87#endif
88 return false;
89}
90
91static bool ffwd_rew(int button)
92{
93 static const int ff_rew_steps[] = {
94 1000, 2000, 3000, 4000,
95 5000, 6000, 8000, 10000,
96 15000, 20000, 25000, 30000,
97 45000, 60000
98 };
99
100 unsigned int step = 0; /* current ff/rewind step */
101 unsigned int max_step = 0; /* maximum ff/rewind step */
102 int ff_rewind_count = 0; /* current ff/rewind count (in ticks) */
103 int direction = -1; /* forward=1 or backward=-1 */
104 long accel_tick = 0; /* next time at which to bump the step size */
105 bool exit = false;
106 bool usb = false;
107
108 while (!exit) {
109 switch ( button ) {
110 case WPS_FFWD:
111#ifdef WPS_RC_FFWD
112 case WPS_RC_FFWD:
113#endif
114 direction = 1;
115 case WPS_REW:
116#ifdef WPS_RC_REW
117 case WPS_RC_REW:
118#endif
119 if (ff_rewind)
120 {
121 if (direction == 1)
122 {
123 /* fast forwarding, calc max step relative to end */
124 max_step =
125 (id3->length - (id3->elapsed + ff_rewind_count)) *
126 FF_REWIND_MAX_PERCENT / 100;
127 }
128 else
129 {
130 /* rewinding, calc max step relative to start */
131 max_step = (id3->elapsed + ff_rewind_count) *
132 FF_REWIND_MAX_PERCENT / 100;
133 }
134
135 max_step = MAX(max_step, MIN_FF_REWIND_STEP);
136
137 if (step > max_step)
138 step = max_step;
139
140 ff_rewind_count += step * direction;
141
142 if (global_settings.ff_rewind_accel != 0 &&
143 current_tick >= accel_tick)
144 {
145 step *= 2;
146 accel_tick = current_tick +
147 global_settings.ff_rewind_accel*HZ;
148 }
149 }
150 else
151 {
152 if ( (audio_status() & AUDIO_STATUS_PLAY) &&
153 id3 && id3->length )
154 {
155 if (!paused)
156 audio_pause();
157#if CONFIG_KEYPAD == PLAYER_PAD
158 lcd_stop_scroll();
159#endif
160 if (direction > 0)
161 status_set_ffmode(STATUS_FASTFORWARD);
162 else
163 status_set_ffmode(STATUS_FASTBACKWARD);
164
165 ff_rewind = true;
166
167 step = ff_rew_steps[global_settings.ff_rewind_min_step];
168
169 accel_tick = current_tick +
170 global_settings.ff_rewind_accel*HZ;
171 }
172 else
173 break;
174 }
175
176 if (direction > 0) {
177 if ((id3->elapsed + ff_rewind_count) > id3->length)
178 ff_rewind_count = id3->length - id3->elapsed;
179 }
180 else {
181 if ((int)(id3->elapsed + ff_rewind_count) < 0)
182 ff_rewind_count = -id3->elapsed;
183 }
184
185 if(wps_time_countup == false)
186 wps_refresh(id3, nid3, -ff_rewind_count,
187 WPS_REFRESH_PLAYER_PROGRESS |
188 WPS_REFRESH_DYNAMIC);
189 else
190 wps_refresh(id3, nid3, ff_rewind_count,
191 WPS_REFRESH_PLAYER_PROGRESS |
192 WPS_REFRESH_DYNAMIC);
193
194 break;
195
196 case WPS_PREV:
197 case WPS_NEXT:
198#ifdef WPS_RC_PREV
199 case WPS_RC_PREV:
200 case WPS_RC_NEXT:
201#endif
202 audio_ff_rewind(id3->elapsed+ff_rewind_count);
203 ff_rewind_count = 0;
204 ff_rewind = false;
205 status_set_ffmode(0);
206 if (!paused)
207 audio_resume();
208#ifdef HAVE_LCD_CHARCELLS
209 wps_display(id3, nid3);
210#endif
211 exit = true;
212 break;
213
214 default:
215 if(default_event_handler(button) == SYS_USB_CONNECTED) {
216 status_set_ffmode(0);
217 usb = true;
218 exit = true;
219 }
220 break;
221 }
222 if (!exit)
223 button = button_get(true);
224 }
225
226 /* let audio thread update id3->elapsed before calling wps_refresh */
227 yield();
228 wps_refresh(id3, nid3, 0, WPS_REFRESH_ALL);
229 return usb;
230}
231
232static bool update(void)
233{
234 bool track_changed = audio_has_changed_track();
235 bool retcode = false;
236
237 nid3 = audio_next_track();
238 if (track_changed)
239 {
240 lcd_stop_scroll();
241 id3 = audio_current_track();
242 if (wps_display(id3, nid3))
243 retcode = true;
244 else
245 wps_refresh(id3, nid3, 0, WPS_REFRESH_ALL);
246
247 if (id3)
248 memcpy(current_track_path, id3->path, sizeof(current_track_path));
249 }
250
251 if (id3)
252 wps_refresh(id3, nid3, 0, WPS_REFRESH_NON_STATIC);
253
254 status_draw(false);
255
256 return retcode;
257}
258
259static void fade(bool fade_in)
260{
261 unsigned fp_global_vol = global_settings.volume << 8;
262 unsigned fp_step = fp_global_vol / 30;
263
264 if (fade_in) {
265 /* fade in */
266 unsigned fp_volume = 0;
267
268 /* zero out the sound */
269 sound_set_volume(0);
270
271 sleep(HZ/10); /* let audio thread run */
272 audio_resume();
273
274 while (fp_volume < fp_global_vol) {
275 fp_volume += fp_step;
276 sleep(1);
277 sound_set_volume(fp_volume >> 8);
278 }
279 sound_set_volume(global_settings.volume);
280 }
281 else {
282 /* fade out */
283 unsigned fp_volume = fp_global_vol;
284
285 while (fp_volume > fp_step) {
286 fp_volume -= fp_step;
287 sleep(1);
288 sound_set_volume(fp_volume >> 8);
289 }
290 audio_pause();
291#ifndef SIMULATOR
292 /* let audio thread run and wait for the mas to run out of data */
293 while (!mp3_pause_done())
294#endif
295 sleep(HZ/10);
296
297 /* reset volume to what it was before the fade */
298 sound_set_volume(global_settings.volume);
299 }
300}
301
302
303#ifdef WPS_KEYLOCK
304static void display_keylock_text(bool locked)
305{
306 char* s;
307 lcd_stop_scroll();
308#ifdef HAVE_LCD_CHARCELLS
309 if(locked)
310 s = str(LANG_KEYLOCK_ON_PLAYER);
311 else
312 s = str(LANG_KEYLOCK_OFF_PLAYER);
313#else
314 if(locked)
315 s = str(LANG_KEYLOCK_ON_RECORDER);
316 else
317 s = str(LANG_KEYLOCK_OFF_RECORDER);
318#endif
319 gui_syncsplash(HZ, true, s);
320}
321
322static void waitfor_nokey(void)
323{
324 /* wait until all keys are released */
325 while (button_get(false) != BUTTON_NONE)
326 yield();
327}
328#endif
329
330/* demonstrates showing different formats from playtune */
331long wps_show(void)
332{
333 long button = 0, lastbutton = 0;
334 bool ignore_keyup = true;
335 bool restore = false;
336 long restoretimer = 0; /* timer to delay screen redraw temporarily */
337 bool exit = false;
338 bool update_track = false;
339 unsigned long right_lastclick = 0;
340 unsigned long left_lastclick = 0;
341
342 id3 = nid3 = NULL;
343 current_track_path[0] = '\0';
344
345#ifdef HAVE_LCD_CHARCELLS
346 status_set_audio(true);
347 status_set_param(false);
348#else
349 if(global_settings.statusbar)
350 lcd_setmargins(0, STATUSBAR_HEIGHT);
351 else
352 lcd_setmargins(0, 0);
353#endif
354
355#ifdef AB_REPEAT_ENABLE
356 ab_repeat_init();
357 ab_reset_markers();
358#endif
359
360 ff_rewind = false;
361
362 if(audio_status() & AUDIO_STATUS_PLAY)
363 {
364 id3 = audio_current_track();
365 nid3 = audio_next_track();
366 if (id3) {
367 if (wps_display(id3, nid3))
368 return 0;
369 wps_refresh(id3, nid3, 0, WPS_REFRESH_ALL);
370
371 memcpy(current_track_path, id3->path, sizeof(current_track_path));
372 }
373
374 restore = true;
375 }
376
377 while ( 1 )
378 {
379 bool audio_paused = (audio_status() & AUDIO_STATUS_PAUSE)?true:false;
380
381 /* did someone else (i.e power thread) change audio pause mode? */
382 if (paused != audio_paused) {
383 paused = audio_paused;
384
385 /* if another thread paused audio, we are probably in car mode,
386 about to shut down. lets save the settings. */
387 if (paused) {
388 settings_save();
389#if !defined(HAVE_RTC) && !defined(HAVE_SW_POWEROFF)
390 ata_flush();
391#endif
392 }
393 }
394
395#ifdef HAVE_LCD_BITMAP
396 /* when the peak meter is enabled we want to have a
397 few extra updates to make it look smooth. On the
398 other hand we don't want to waste energy if it
399 isn't displayed */
400 if (peak_meter_enabled) {
401 long next_refresh = current_tick;
402 long next_big_refresh = current_tick + HZ / 5;
403 button = BUTTON_NONE;
404 while (TIME_BEFORE(current_tick, next_big_refresh)) {
405 button = button_get(false);
406 if (button != BUTTON_NONE) {
407 break;
408 }
409 peak_meter_peek();
410 sleep(0); /* Sleep until end of current tick. */
411
412 if (TIME_AFTER(current_tick, next_refresh)) {
413 wps_refresh(id3, nid3, 0, WPS_REFRESH_PEAK_METER);
414 next_refresh += HZ / PEAK_METER_FPS;
415 }
416 }
417
418 }
419
420 /* The peak meter is disabled
421 -> no additional screen updates needed */
422 else {
423 button = button_get_w_tmo(HZ/5);
424 }
425#else
426 button = button_get_w_tmo(HZ/5);
427#endif
428
429 /* discard first event if it's a button release */
430 if (button && ignore_keyup)
431 {
432 ignore_keyup = false;
433 /* Negative events are system events */
434 if (button >= 0 && button & BUTTON_REL )
435 continue;
436 }
437
438#ifdef WPS_KEYLOCK
439 /* ignore non-remote buttons when keys are locked */
440 if (keys_locked &&
441 ! ((button < 0) ||
442 (button == BUTTON_NONE) ||
443 ((button & WPS_KEYLOCK) == WPS_KEYLOCK) ||
444 (button & BUTTON_REMOTE)
445 ))
446 {
447 if (!(button & BUTTON_REL))
448 display_keylock_text(true);
449 restore = true;
450 button = BUTTON_NONE;
451 }
452#endif
453
454 /* Exit if audio has stopped playing. This can happen if using the
455 sleep timer with the charger plugged or if starting a recording
456 from F1 */
457 if (!audio_status())
458 exit = true;
459
460 switch(button)
461 {
462#ifdef WPS_CONTEXT
463 case WPS_CONTEXT:
464 onplay(id3->path, TREE_ATTR_MPA, CONTEXT_WPS);
465 restore = true;
466 break;
467#endif
468
469#ifdef WPS_RC_BROWSE
470 case WPS_RC_BROWSE:
471#endif
472 case WPS_BROWSE:
473#ifdef WPS_BROWSE_PRE
474 if ((lastbutton != WPS_BROWSE_PRE)
475#ifdef WPS_RC_BROWSE_PRE
476 && (lastbutton != WPS_RC_BROWSE_PRE)
477#endif
478 )
479 break;
480#endif
481#ifdef HAVE_LCD_CHARCELLS
482 status_set_record(false);
483 status_set_audio(false);
484#endif
485 lcd_stop_scroll();
486
487 /* set dir browser to current playing song */
488 if (global_settings.browse_current &&
489 current_track_path[0] != '\0')
490 set_current_file(current_track_path);
491
492 return 0;
493 break;
494
495 /* play/pause */
496 case WPS_PAUSE:
497#ifdef WPS_PAUSE_PRE
498 if (lastbutton != WPS_PAUSE_PRE)
499 break;
500#endif
501#ifdef WPS_RC_PAUSE
502 case WPS_RC_PAUSE:
503#ifdef WPS_RC_PAUSE_PRE
504 if ((button == WPS_RC_PAUSE) && (lastbutton != WPS_RC_PAUSE_PRE))
505 break;
506#endif
507#endif
508 if ( paused )
509 {
510 paused = false;
511 if ( global_settings.fade_on_stop )
512 fade(1);
513 else
514 audio_resume();
515 }
516 else
517 {
518 paused = true;
519 if ( global_settings.fade_on_stop )
520 fade(0);
521 else
522 audio_pause();
523 settings_save();
524#if !defined(HAVE_RTC) && !defined(HAVE_SW_POWEROFF)
525 ata_flush(); /* make sure resume info is saved */
526#endif
527 }
528 break;
529
530 /* volume up */
531 case WPS_INCVOL:
532 case WPS_INCVOL | BUTTON_REPEAT:
533#ifdef WPS_RC_INCVOL
534 case WPS_RC_INCVOL:
535 case WPS_RC_INCVOL | BUTTON_REPEAT:
536#endif
537 global_settings.volume++;
538 if (setvol()) {
539 restore = true;
540 restoretimer = current_tick + HZ;
541 }
542 break;
543
544 /* volume down */
545 case WPS_DECVOL:
546 case WPS_DECVOL | BUTTON_REPEAT:
547#ifdef WPS_RC_DECVOL
548 case WPS_RC_DECVOL:
549 case WPS_RC_DECVOL | BUTTON_REPEAT:
550#endif
551 global_settings.volume--;
552 if (setvol()) {
553 restore = true;
554 restoretimer = current_tick + HZ;
555 }
556 break;
557
558 /* fast forward / rewind */
559#ifdef WPS_RC_FFWD
560 case WPS_RC_FFWD:
561#endif
562 case WPS_FFWD:
563#ifdef WPS_NEXT_DIR
564 if (current_tick - right_lastclick < HZ)
565 {
566 audio_next_dir();
567 right_lastclick = 0;
568 break;
569 }
570#endif
571#ifdef WPS_RC_REW
572 case WPS_RC_REW:
573#endif
574 case WPS_REW:
575#ifdef WPS_PREV_DIR
576 if (current_tick - left_lastclick < HZ)
577 {
578 audio_prev_dir();
579 left_lastclick = 0;
580 break;
581 }
582#endif
583 ffwd_rew(button);
584 break;
585
586 /* prev / restart */
587 case WPS_PREV:
588#ifdef WPS_PREV_PRE
589 if (lastbutton != WPS_PREV_PRE)
590 break;
591#endif
592#ifdef WPS_RC_PREV
593 case WPS_RC_PREV:
594#ifdef WPS_RC_PREV_PRE
595 if ((button == WPS_RC_PREV) && (lastbutton != WPS_RC_PREV_PRE))
596 break;
597#endif
598#endif
599 left_lastclick = current_tick;
600 update_track = true;
601
602#ifdef AB_REPEAT_ENABLE
603 /* if we're in A/B repeat mode and the current position
604 is past the A marker, jump back to the A marker... */
605 if ( ab_repeat_mode_enabled() && ab_after_A_marker(id3->elapsed) )
606 {
607 ab_jump_to_A_marker();
608 break;
609 }
610 /* ...otherwise, do it normally */
611#endif
612
613 if (!id3 || (id3->elapsed < 3*1000)) {
614 audio_prev();
615 }
616 else {
617 if (!paused)
618 audio_pause();
619
620 audio_ff_rewind(0);
621
622 if (!paused)
623 audio_resume();
624 }
625 break;
626
627#ifdef WPS_NEXT_DIR
628#ifdef WPS_RC_NEXT_DIR
629 case WPS_RC_NEXT_DIR:
630#endif
631 case WPS_NEXT_DIR:
632 audio_next_dir();
633 break;
634#endif
635#ifdef WPS_PREV_DIR
636#ifdef WPS_RC_PREV_DIR
637 case WPS_RC_PREV_DIR:
638#endif
639 case WPS_PREV_DIR:
640 audio_prev_dir();
641 break;
642#endif
643
644 /* next */
645 case WPS_NEXT:
646#ifdef WPS_NEXT_PRE
647 if (lastbutton != WPS_NEXT_PRE)
648 break;
649#endif
650#ifdef WPS_RC_NEXT
651 case WPS_RC_NEXT:
652#ifdef WPS_RC_NEXT_PRE
653 if ((button == WPS_RC_NEXT) && (lastbutton != WPS_RC_NEXT_PRE))
654 break;
655#endif
656#endif
657 right_lastclick = current_tick;
658 update_track = true;
659
660#ifdef AB_REPEAT_ENABLE
661 /* if we're in A/B repeat mode and the current position is
662 before the A marker, jump to the A marker... */
663 if ( ab_repeat_mode_enabled() && ab_before_A_marker(id3->elapsed) )
664 {
665 ab_jump_to_A_marker();
666 break;
667 }
668 /* ...otherwise, do it normally */
669#endif
670
671 audio_next();
672 break;
673
674#ifdef WPS_MENU
675 /* menu key functions */
676 case WPS_MENU:
677#ifdef WPS_MENU_PRE
678 if (lastbutton != WPS_MENU_PRE)
679 break;
680#endif
681#ifdef WPS_RC_MENU
682 case WPS_RC_MENU:
683#ifdef WPS_RC_MENU_PRE
684 if ((button == WPS_RC_MENU) && (lastbutton != WPS_RC_MENU_PRE))
685 break;
686#endif
687#endif
688 lcd_stop_scroll();
689
690 if (main_menu())
691 return true;
692#ifdef HAVE_LCD_BITMAP
693 if (global_settings.statusbar)
694 lcd_setmargins(0, STATUSBAR_HEIGHT);
695 else
696 lcd_setmargins(0, 0);
697#endif
698 restore = true;
699 break;
700#endif /* WPS_MENU */
701
702#ifdef WPS_KEYLOCK
703 /* key lock */
704 case WPS_KEYLOCK:
705 case WPS_KEYLOCK | BUTTON_REPEAT:
706 keys_locked = !keys_locked;
707 display_keylock_text(keys_locked);
708 restore = true;
709 waitfor_nokey();
710 break;
711#endif
712
713#if (CONFIG_KEYPAD == RECORDER_PAD) || (CONFIG_KEYPAD == IRIVER_H100_PAD)
714 /* play settings */
715 case WPS_QUICK:
716 if (quick_screen(CONTEXT_WPS, WPS_QUICK))
717 return SYS_USB_CONNECTED;
718 restore = true;
719 lastbutton = 0;
720 break;
721
722 /* screen settings */
723#ifdef BUTTON_F3
724 case BUTTON_F3:
725 if (quick_screen(CONTEXT_WPS, BUTTON_F3))
726 return SYS_USB_CONNECTED;
727 restore = true;
728 break;
729#endif
730
731 /* pitch screen */
732#if CONFIG_KEYPAD == RECORDER_PAD
733 case BUTTON_ON | BUTTON_UP:
734 case BUTTON_ON | BUTTON_DOWN:
735 if (2 == pitch_screen())
736 return SYS_USB_CONNECTED;
737 restore = true;
738 break;
739#endif
740#endif
741
742#ifdef AB_REPEAT_ENABLE
743
744#ifdef WPS_AB_SET_A_MARKER
745 /* set A marker for A-B repeat */
746 case WPS_AB_SET_A_MARKER:
747 if (ab_repeat_mode_enabled())
748 ab_set_A_marker(id3->elapsed);
749 break;
750#endif
751
752#ifdef WPS_AB_SET_B_MARKER
753 /* set B marker for A-B repeat and jump to A */
754 case WPS_AB_SET_B_MARKER:
755 if (ab_repeat_mode_enabled())
756 {
757 ab_set_B_marker(id3->elapsed);
758 ab_jump_to_A_marker();
759 update_track = true;
760 }
761 break;
762#endif
763
764#ifdef WPS_AB_RESET_AB_MARKERS
765 /* reset A&B markers */
766 case WPS_AB_RESET_AB_MARKERS:
767 if (ab_repeat_mode_enabled())
768 {
769 ab_reset_markers();
770 update_track = true;
771 }
772 break;
773#endif
774
775#endif /* AB_REPEAT_ENABLE */
776
777 /* stop and exit wps */
778#ifdef WPS_EXIT
779 case WPS_EXIT:
780# ifdef WPS_EXIT_PRE
781 if (lastbutton != WPS_EXIT_PRE)
782 break;
783# endif
784 exit = true;
785
786# ifdef WPS_RC_EXIT
787 case WPS_RC_EXIT:
788# ifdef WPS_RC_EXIT_PRE
789 if (lastbutton != WPS_RC_EXIT_PRE)
790 break;
791# endif
792 exit = true;
793# endif
794 break;
795#endif
796
797#ifdef WPS_ID3
798 case WPS_ID3:
799 browse_id3();
800 restore = true;
801 break;
802#endif
803
804 case BUTTON_NONE: /* Timeout */
805 update_track = true;
806 break;
807
808 default:
809 if(default_event_handler(button) == SYS_USB_CONNECTED)
810 return SYS_USB_CONNECTED;
811 update_track = true;
812 break;
813 }
814
815 if (update_track)
816 {
817 if (update())
818 {
819 /* set dir browser to current playing song */
820 if (global_settings.browse_current &&
821 current_track_path[0] != '\0')
822 set_current_file(current_track_path);
823
824 return 0;
825 }
826 update_track = false;
827 }
828
829 if (exit) {
830#ifdef HAVE_LCD_CHARCELLS
831 status_set_record(false);
832 status_set_audio(false);
833#endif
834 if (global_settings.fade_on_stop)
835 fade(0);
836
837 lcd_stop_scroll();
838 bookmark_autobookmark();
839 audio_stop();
840#ifdef AB_REPEAT_ENABLE
841 ab_reset_markers();
842#endif
843
844 /* Keys can be locked when exiting, so either unlock here
845 or implement key locking in tree.c too */
846 keys_locked=false;
847
848 /* set dir browser to current playing song */
849 if (global_settings.browse_current &&
850 current_track_path[0] != '\0')
851 set_current_file(current_track_path);
852
853 return 0;
854 }
855
856 if ( button )
857 ata_spin();
858
859 if (restore &&
860 ((restoretimer == 0) ||
861 (restoretimer < current_tick)))
862 {
863 restore = false;
864 restoretimer = 0;
865 if (wps_display(id3, nid3))
866 {
867 /* set dir browser to current playing song */
868 if (global_settings.browse_current &&
869 current_track_path[0] != '\0')
870 set_current_file(current_track_path);
871
872 return 0;
873 }
874
875 if (id3)
876 wps_refresh(id3, nid3, 0, WPS_REFRESH_NON_STATIC);
877 }
878 if (button != BUTTON_NONE)
879 lastbutton = button;
880 }
881 return 0; /* unreachable - just to reduce compiler warnings */
882}
diff --git a/apps/wps.h b/apps/wps.h
deleted file mode 100644
index 61b3d002fc..0000000000
--- a/apps/wps.h
+++ /dev/null
@@ -1,205 +0,0 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 Jerome Kuptz
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#ifndef _WPS_H
20#define _WPS_H
21#include "id3.h"
22#include "playlist.h"
23
24/* button definitions */
25#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
26 (CONFIG_KEYPAD == IRIVER_H300_PAD)
27#define WPS_NEXT (BUTTON_RIGHT | BUTTON_REL)
28#define WPS_NEXT_PRE BUTTON_RIGHT
29#define WPS_PREV (BUTTON_LEFT | BUTTON_REL)
30#define WPS_PREV_PRE BUTTON_LEFT
31#define WPS_FFWD (BUTTON_RIGHT | BUTTON_REPEAT)
32#define WPS_REW (BUTTON_LEFT | BUTTON_REPEAT)
33#define WPS_INCVOL BUTTON_UP
34#define WPS_DECVOL BUTTON_DOWN
35#define WPS_PAUSE (BUTTON_ON | BUTTON_REL)
36#define WPS_PAUSE_PRE BUTTON_ON
37#define WPS_MENU (BUTTON_MODE | BUTTON_REL)
38#define WPS_MENU_PRE BUTTON_MODE
39#define WPS_BROWSE (BUTTON_SELECT | BUTTON_REL)
40#define WPS_BROWSE_PRE BUTTON_SELECT
41#define WPS_EXIT (BUTTON_OFF | BUTTON_REL)
42#define WPS_EXIT_PRE BUTTON_OFF
43#define WPS_ID3 (BUTTON_MODE | BUTTON_ON)
44#define WPS_CONTEXT (BUTTON_SELECT | BUTTON_REPEAT)
45#define WPS_QUICK (BUTTON_MODE | BUTTON_REPEAT)
46#define WPS_NEXT_DIR (BUTTON_RIGHT | BUTTON_ON)
47#define WPS_PREV_DIR (BUTTON_LEFT | BUTTON_ON)
48
49#define WPS_RC_NEXT_DIR (BUTTON_RC_BITRATE | BUTTON_REL)
50#define WPS_RC_PREV_DIR (BUTTON_RC_SOURCE | BUTTON_REL)
51#define WPS_RC_NEXT (BUTTON_RC_FF | BUTTON_REL)
52#define WPS_RC_NEXT_PRE BUTTON_RC_FF
53#define WPS_RC_PREV (BUTTON_RC_REW | BUTTON_REL)
54#define WPS_RC_PREV_PRE BUTTON_RC_REW
55#define WPS_RC_FFWD (BUTTON_RC_FF | BUTTON_REPEAT)
56#define WPS_RC_REW (BUTTON_RC_REW | BUTTON_REPEAT)
57#define WPS_RC_PAUSE BUTTON_RC_ON
58#define WPS_RC_INCVOL BUTTON_RC_VOL_UP
59#define WPS_RC_DECVOL BUTTON_RC_VOL_DOWN
60#define WPS_RC_EXIT (BUTTON_RC_STOP | BUTTON_REL)
61#define WPS_RC_EXIT_PRE BUTTON_RC_STOP
62#define WPS_RC_MENU (BUTTON_RC_MODE | BUTTON_REL)
63#define WPS_RC_MENU_PRE BUTTON_RC_MODE
64#define WPS_RC_BROWSE (BUTTON_RC_MENU | BUTTON_REL)
65#define WPS_RC_BROWSE_PRE BUTTON_RC_MENU
66
67#elif CONFIG_KEYPAD == RECORDER_PAD
68#define WPS_NEXT (BUTTON_RIGHT | BUTTON_REL)
69#define WPS_NEXT_PRE BUTTON_RIGHT
70#define WPS_PREV (BUTTON_LEFT | BUTTON_REL)
71#define WPS_PREV_PRE BUTTON_LEFT
72#define WPS_FFWD (BUTTON_RIGHT | BUTTON_REPEAT)
73#define WPS_REW (BUTTON_LEFT | BUTTON_REPEAT)
74#define WPS_INCVOL BUTTON_UP
75#define WPS_DECVOL BUTTON_DOWN
76#define WPS_PAUSE_PRE BUTTON_PLAY
77#define WPS_PAUSE (BUTTON_PLAY | BUTTON_REL)
78#define WPS_MENU (BUTTON_F1 | BUTTON_REL)
79#define WPS_MENU_PRE BUTTON_F1
80#define WPS_BROWSE (BUTTON_ON | BUTTON_REL)
81#define WPS_BROWSE_PRE BUTTON_ON
82#define WPS_EXIT BUTTON_OFF
83#define WPS_KEYLOCK (BUTTON_F1 | BUTTON_DOWN)
84#define WPS_ID3 (BUTTON_F1 | BUTTON_ON)
85#define WPS_CONTEXT (BUTTON_PLAY | BUTTON_REPEAT)
86#define WPS_QUICK BUTTON_F2
87
88#ifdef AB_REPEAT_ENABLE
89#define WPS_AB_SET_A_MARKER (BUTTON_ON | BUTTON_LEFT)
90#define WPS_AB_SET_B_MARKER (BUTTON_ON | BUTTON_RIGHT)
91#define WPS_AB_RESET_AB_MARKERS (BUTTON_ON | BUTTON_OFF)
92#endif
93
94#define WPS_RC_NEXT BUTTON_RC_RIGHT
95#define WPS_RC_PREV BUTTON_RC_LEFT
96#define WPS_RC_PAUSE BUTTON_RC_PLAY
97#define WPS_RC_INCVOL BUTTON_RC_VOL_UP
98#define WPS_RC_DECVOL BUTTON_RC_VOL_DOWN
99#define WPS_RC_EXIT BUTTON_RC_STOP
100
101#elif CONFIG_KEYPAD == PLAYER_PAD
102#define WPS_NEXT (BUTTON_RIGHT | BUTTON_REL)
103#define WPS_NEXT_PRE BUTTON_RIGHT
104#define WPS_PREV (BUTTON_LEFT | BUTTON_REL)
105#define WPS_PREV_PRE BUTTON_LEFT
106#define WPS_FFWD (BUTTON_RIGHT | BUTTON_REPEAT)
107#define WPS_REW (BUTTON_LEFT | BUTTON_REPEAT)
108#define WPS_INCVOL (BUTTON_MENU | BUTTON_RIGHT)
109#define WPS_DECVOL (BUTTON_MENU | BUTTON_LEFT)
110#define WPS_PAUSE_PRE BUTTON_PLAY
111#define WPS_PAUSE (BUTTON_PLAY | BUTTON_REL)
112#define WPS_MENU (BUTTON_MENU | BUTTON_REL)
113#define WPS_MENU_PRE BUTTON_MENU
114#define WPS_BROWSE (BUTTON_ON | BUTTON_REL)
115#define WPS_BROWSE_PRE BUTTON_ON
116#define WPS_EXIT BUTTON_STOP
117#define WPS_KEYLOCK (BUTTON_MENU | BUTTON_STOP)
118#define WPS_ID3 (BUTTON_MENU | BUTTON_ON)
119#define WPS_CONTEXT (BUTTON_PLAY | BUTTON_REPEAT)
120
121#ifdef AB_REPEAT_ENABLE
122#define WPS_AB_SET_A_MARKER (BUTTON_ON | BUTTON_LEFT)
123#define WPS_AB_SET_B_MARKER (BUTTON_ON | BUTTON_RIGHT)
124#define WPS_AB_RESET_AB_MARKERS (BUTTON_ON | BUTTON_STOP)
125#endif
126
127#define WPS_RC_NEXT BUTTON_RC_RIGHT
128#define WPS_RC_PREV BUTTON_RC_LEFT
129#define WPS_RC_PAUSE BUTTON_RC_PLAY
130#define WPS_RC_INCVOL BUTTON_RC_VOL_UP
131#define WPS_RC_DECVOL BUTTON_RC_VOL_DOWN
132#define WPS_RC_EXIT BUTTON_RC_STOP
133
134#elif CONFIG_KEYPAD == ONDIO_PAD
135#define WPS_NEXT (BUTTON_RIGHT | BUTTON_REL)
136#define WPS_NEXT_PRE BUTTON_RIGHT
137#define WPS_PREV (BUTTON_LEFT | BUTTON_REL)
138#define WPS_PREV_PRE BUTTON_LEFT
139#define WPS_FFWD (BUTTON_RIGHT | BUTTON_REPEAT)
140#define WPS_REW (BUTTON_LEFT | BUTTON_REPEAT)
141#define WPS_INCVOL BUTTON_UP
142#define WPS_DECVOL BUTTON_DOWN
143#define WPS_PAUSE BUTTON_OFF
144/* #define WPS_MENU Ondio can't have both main menu and context menu in wps */
145#define WPS_BROWSE (BUTTON_MENU | BUTTON_REL)
146#define WPS_BROWSE_PRE BUTTON_MENU
147#define WPS_KEYLOCK (BUTTON_MENU | BUTTON_DOWN)
148#define WPS_EXIT (BUTTON_OFF | BUTTON_REPEAT)
149#define WPS_CONTEXT (BUTTON_MENU | BUTTON_REPEAT)
150
151#elif CONFIG_KEYPAD == GMINI100_PAD
152#define WPS_NEXT (BUTTON_RIGHT | BUTTON_REL)
153#define WPS_NEXT_PRE BUTTON_RIGHT
154#define WPS_PREV (BUTTON_LEFT | BUTTON_REL)
155#define WPS_PREV_PRE BUTTON_LEFT
156#define WPS_FFWD (BUTTON_RIGHT | BUTTON_REPEAT)
157#define WPS_REW (BUTTON_LEFT | BUTTON_REPEAT)
158#define WPS_INCVOL BUTTON_UP
159#define WPS_DECVOL BUTTON_DOWN
160#define WPS_PAUSE BUTTON_PLAY
161#define WPS_MENU (BUTTON_MENU | BUTTON_REL)
162#define WPS_MENU_PRE BUTTON_MENU
163#define WPS_BROWSE (BUTTON_ON | BUTTON_REL)
164#define WPS_BROWSE_PRE BUTTON_ON
165#define WPS_EXIT BUTTON_OFF
166#define WPS_KEYLOCK (BUTTON_MENU | BUTTON_DOWN)
167#define WPS_ID3 (BUTTON_MENU | BUTTON_ON)
168
169#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_NANO_PAD)
170
171/* TODO: Check WPS button assignments */
172
173#define WPS_NEXT (BUTTON_RIGHT | BUTTON_REL)
174#define WPS_NEXT_PRE BUTTON_RIGHT
175#define WPS_PREV (BUTTON_LEFT | BUTTON_REL)
176#define WPS_PREV_PRE BUTTON_LEFT
177#define WPS_FFWD (BUTTON_RIGHT | BUTTON_REPEAT)
178#define WPS_REW (BUTTON_LEFT | BUTTON_REPEAT)
179#define WPS_INCVOL BUTTON_UP
180#define WPS_DECVOL BUTTON_DOWN
181#define WPS_PAUSE BUTTON_OFF
182/* #define WPS_MENU iPod can't have both main menu and context menu in wps */
183#define WPS_BROWSE (BUTTON_MENU | BUTTON_REL)
184#define WPS_BROWSE_PRE BUTTON_MENU
185#define WPS_KEYLOCK (BUTTON_MENU | BUTTON_DOWN)
186#define WPS_EXIT (BUTTON_OFF | BUTTON_REPEAT)
187#define WPS_CONTEXT (BUTTON_MENU | BUTTON_REPEAT)
188
189
190#endif
191
192extern bool keys_locked;
193extern bool wps_time_countup;
194
195long wps_show(void);
196bool refresh_wps(bool refresh_scroll);
197void handle_usb(void);
198
199#if CONFIG_KEYPAD == RECORDER_PAD
200bool f2_screen(void);
201bool f3_screen(void);
202#endif
203
204#endif
205
diff --git a/docs/CREDITS b/docs/CREDITS
index 2877fd2156..9380a0e321 100644
--- a/docs/CREDITS
+++ b/docs/CREDITS
@@ -139,3 +139,4 @@ Alyssa Milburn
139Kevin Ferrare 139Kevin Ferrare
140Anton Oleynikov 140Anton Oleynikov
141Mark Arigo 141Mark Arigo
142Magnus Westerlund
diff --git a/wps/rockbox_default.rwps b/wps/rockbox_default.rwps
new file mode 100644
index 0000000000..b1427cab84
--- /dev/null
+++ b/wps/rockbox_default.rwps
@@ -0,0 +1,2 @@
1# Dummy file to allow Rockbox to reset to the default WPS config.
2# Do not edit this file. It's never actually loaded by Rockbox.