summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/SOURCES11
-rw-r--r--apps/filetree.c3
-rw-r--r--apps/gui/music_screen.c (renamed from apps/gui/gwps.c)233
-rw-r--r--apps/gui/music_screen.h (renamed from apps/gui/gwps-common.h)34
-rw-r--r--apps/gui/wps_engine/gwps.h (renamed from apps/gui/gwps.h)0
-rw-r--r--apps/gui/wps_engine/wps_debug.c (renamed from apps/gui/wps_debug.c)2
-rw-r--r--apps/gui/wps_engine/wps_display.c (renamed from apps/gui/gwps-common.c)976
-rw-r--r--apps/gui/wps_engine/wps_engine.h49
-rw-r--r--apps/gui/wps_engine/wps_internals.h556
-rw-r--r--apps/gui/wps_engine/wps_parser.c (renamed from apps/gui/wps_parser.c)2
-rw-r--r--apps/gui/wps_engine/wps_tokens.c807
-rw-r--r--apps/iap.c2
-rw-r--r--apps/main.c2
-rw-r--r--apps/menu.c1
-rw-r--r--apps/menus/main_menu.c2
-rw-r--r--apps/misc.c3
-rw-r--r--apps/recorder/albumart.c1
-rw-r--r--apps/recorder/albumart.h2
-rw-r--r--apps/root_menu.c2
-rw-r--r--apps/settings.c2
-rw-r--r--apps/tree.c3
21 files changed, 1672 insertions, 1021 deletions
diff --git a/apps/SOURCES b/apps/SOURCES
index 8166dbe4e2..e1d85a75f0 100644
--- a/apps/SOURCES
+++ b/apps/SOURCES
@@ -60,8 +60,6 @@ screen_access.c
60#ifdef HAVE_BUTTONBAR 60#ifdef HAVE_BUTTONBAR
61gui/buttonbar.c 61gui/buttonbar.c
62#endif 62#endif
63gui/gwps.c
64gui/gwps-common.c
65#ifdef HAVE_LCD_BITMAP 63#ifdef HAVE_LCD_BITMAP
66gui/icon.c 64gui/icon.c
67#endif 65#endif
@@ -78,14 +76,19 @@ gui/pitchscreen.c
78#ifdef HAVE_QUICKSCREEN 76#ifdef HAVE_QUICKSCREEN
79gui/quickscreen.c 77gui/quickscreen.c
80#endif 78#endif
79
80gui/music_screen.c
81gui/scrollbar.c 81gui/scrollbar.c
82gui/splash.c 82gui/splash.c
83gui/statusbar.c 83gui/statusbar.c
84gui/yesno.c 84gui/yesno.c
85gui/wps_debug.c
86gui/wps_parser.c
87gui/viewport.c 85gui/viewport.c
88 86
87gui/wps_engine/wps_debug.c
88gui/wps_engine/wps_display.c
89gui/wps_engine/wps_parser.c
90gui/wps_engine/wps_tokens.c
91
89#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)) 92#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
90gui/backdrop.c 93gui/backdrop.c
91#endif 94#endif
diff --git a/apps/filetree.c b/apps/filetree.c
index 87ac37c2e0..458d553e27 100644
--- a/apps/filetree.c
+++ b/apps/filetree.c
@@ -33,7 +33,6 @@
33#include "filetypes.h" 33#include "filetypes.h"
34#include "talk.h" 34#include "talk.h"
35#include "playlist.h" 35#include "playlist.h"
36#include "gwps.h"
37#include "lang.h" 36#include "lang.h"
38#include "language.h" 37#include "language.h"
39#include "screens.h" 38#include "screens.h"
@@ -52,7 +51,7 @@
52#if CONFIG_TUNER 51#if CONFIG_TUNER
53#include "radio.h" 52#include "radio.h"
54#endif 53#endif
55 54#include "wps_engine/wps_internals.h" /* FIXME: REMOVE ME */
56#include "backdrop.h" 55#include "backdrop.h"
57 56
58static int compare_sort_dir; /* qsort key for sorting directories */ 57static int compare_sort_dir; /* qsort key for sorting directories */
diff --git a/apps/gui/gwps.c b/apps/gui/music_screen.c
index 10c2a6806b..39d5e0e85b 100644
--- a/apps/gui/gwps.c
+++ b/apps/gui/music_screen.c
@@ -34,8 +34,8 @@
34#include "debug.h" 34#include "debug.h"
35#include "sprintf.h" 35#include "sprintf.h"
36#include "settings.h" 36#include "settings.h"
37#include "gwps.h" 37#include "wps_engine/wps_engine.h"
38#include "gwps-common.h" 38#include "mp3_playback.h"
39#include "audio.h" 39#include "audio.h"
40#include "usb.h" 40#include "usb.h"
41#include "status.h" 41#include "status.h"
@@ -66,6 +66,7 @@
66#include "option_select.h" 66#include "option_select.h"
67#include "dsp.h" 67#include "dsp.h"
68#include "playlist_viewer.h" 68#include "playlist_viewer.h"
69#include "music_screen.h"
69 70
70#define RESTORE_WPS_INSTANTLY 0l 71#define RESTORE_WPS_INSTANTLY 0l
71#define RESTORE_WPS_NEXT_SECOND ((long)(HZ+current_tick)) 72#define RESTORE_WPS_NEXT_SECOND ((long)(HZ+current_tick))
@@ -84,6 +85,234 @@ static void track_changed_callback(void *param);
84static void nextid3available_callback(void* param); 85static void nextid3available_callback(void* param);
85 86
86 87
88
89#define FF_REWIND_MAX_PERCENT 3 /* cap ff/rewind step size at max % of file */
90 /* 3% of 30min file == 54s step size */
91#define MIN_FF_REWIND_STEP 500
92
93bool wps_fading_out = false;
94void fade(bool fade_in, bool updatewps)
95{
96 int fp_global_vol = global_settings.volume << 8;
97 int fp_min_vol = sound_min(SOUND_VOLUME) << 8;
98 int fp_step = (fp_global_vol - fp_min_vol) / 30;
99 int i;
100 wps_fading_out = !fade_in;
101 if (fade_in) {
102 /* fade in */
103 int fp_volume = fp_min_vol;
104
105 /* zero out the sound */
106 sound_set_volume(fp_min_vol >> 8);
107
108 sleep(HZ/10); /* let audio thread run */
109 audio_resume();
110
111 while (fp_volume < fp_global_vol - fp_step) {
112 fp_volume += fp_step;
113 sound_set_volume(fp_volume >> 8);
114 if (updatewps)
115 {
116 FOR_NB_SCREENS(i)
117 gui_wps_redraw(&gui_wps[i], 0, WPS_REFRESH_NON_STATIC);
118 }
119 sleep(1);
120 }
121 sound_set_volume(global_settings.volume);
122 }
123 else {
124 /* fade out */
125 int fp_volume = fp_global_vol;
126
127 while (fp_volume > fp_min_vol + fp_step) {
128 fp_volume -= fp_step;
129 sound_set_volume(fp_volume >> 8);
130 if (updatewps)
131 {
132 FOR_NB_SCREENS(i)
133 gui_wps_redraw(&gui_wps[i], 0, WPS_REFRESH_NON_STATIC);
134 }
135 sleep(1);
136 }
137 audio_pause();
138 wps_fading_out = false;
139#if CONFIG_CODEC != SWCODEC
140#ifndef SIMULATOR
141 /* let audio thread run and wait for the mas to run out of data */
142 while (!mp3_pause_done())
143#endif
144 sleep(HZ/10);
145#endif
146
147 /* reset volume to what it was before the fade */
148 sound_set_volume(global_settings.volume);
149 }
150}
151bool is_wps_fading(void)
152{
153 return wps_fading_out;
154}
155
156bool update_onvol_change(struct gui_wps * gwps)
157{
158 gui_wps_redraw(gwps, 0, WPS_REFRESH_NON_STATIC);
159
160#ifdef HAVE_LCD_CHARCELLS
161 splashf(0, "Vol: %3d dB",
162 sound_val2phys(SOUND_VOLUME, global_settings.volume));
163 return true;
164#endif
165 return false;
166}
167
168bool ffwd_rew(int button)
169{
170 unsigned int step = 0; /* current ff/rewind step */
171 unsigned int max_step = 0; /* maximum ff/rewind step */
172 int ff_rewind_count = 0; /* current ff/rewind count (in ticks) */
173 int direction = -1; /* forward=1 or backward=-1 */
174 bool exit = false;
175 bool usb = false;
176 int i = 0;
177 const long ff_rw_accel = (global_settings.ff_rewind_accel + 3);
178
179 if (button == ACTION_NONE)
180 {
181 status_set_ffmode(0);
182 return usb;
183 }
184 while (!exit)
185 {
186 switch ( button )
187 {
188 case ACTION_WPS_SEEKFWD:
189 direction = 1;
190 case ACTION_WPS_SEEKBACK:
191 if (wps_state.ff_rewind)
192 {
193 if (direction == 1)
194 {
195 /* fast forwarding, calc max step relative to end */
196 max_step = (wps_state.id3->length -
197 (wps_state.id3->elapsed +
198 ff_rewind_count)) *
199 FF_REWIND_MAX_PERCENT / 100;
200 }
201 else
202 {
203 /* rewinding, calc max step relative to start */
204 max_step = (wps_state.id3->elapsed + ff_rewind_count) *
205 FF_REWIND_MAX_PERCENT / 100;
206 }
207
208 max_step = MAX(max_step, MIN_FF_REWIND_STEP);
209
210 if (step > max_step)
211 step = max_step;
212
213 ff_rewind_count += step * direction;
214
215 /* smooth seeking by multiplying step by: 1 + (2 ^ -accel) */
216 step += step >> ff_rw_accel;
217 }
218 else
219 {
220 if ( (audio_status() & AUDIO_STATUS_PLAY) &&
221 wps_state.id3 && wps_state.id3->length )
222 {
223 if (!wps_state.paused)
224#if (CONFIG_CODEC == SWCODEC)
225 audio_pre_ff_rewind();
226#else
227 audio_pause();
228#endif
229#if CONFIG_KEYPAD == PLAYER_PAD
230 FOR_NB_SCREENS(i)
231 gui_wps[i].display->stop_scroll();
232#endif
233 if (direction > 0)
234 status_set_ffmode(STATUS_FASTFORWARD);
235 else
236 status_set_ffmode(STATUS_FASTBACKWARD);
237
238 wps_state.ff_rewind = true;
239
240 step = 1000 * global_settings.ff_rewind_min_step;
241 }
242 else
243 break;
244 }
245
246 if (direction > 0) {
247 if ((wps_state.id3->elapsed + ff_rewind_count) >
248 wps_state.id3->length)
249 ff_rewind_count = wps_state.id3->length -
250 wps_state.id3->elapsed;
251 }
252 else {
253 if ((int)(wps_state.id3->elapsed + ff_rewind_count) < 0)
254 ff_rewind_count = -wps_state.id3->elapsed;
255 }
256
257 FOR_NB_SCREENS(i)
258 gui_wps_redraw(&gui_wps[i],
259 (wps_state.wps_time_countup == false)?
260 ff_rewind_count:-ff_rewind_count,
261 WPS_REFRESH_PLAYER_PROGRESS |
262 WPS_REFRESH_DYNAMIC);
263
264 break;
265
266 case ACTION_WPS_STOPSEEK:
267 wps_state.id3->elapsed = wps_state.id3->elapsed+ff_rewind_count;
268 audio_ff_rewind(wps_state.id3->elapsed);
269 ff_rewind_count = 0;
270 wps_state.ff_rewind = false;
271 status_set_ffmode(0);
272#if (CONFIG_CODEC != SWCODEC)
273 if (!wps_state.paused)
274 audio_resume();
275#endif
276#ifdef HAVE_LCD_CHARCELLS
277 FOR_NB_SCREENS(i)
278 gui_wps_redraw(&gui_wps[i],0, WPS_REFRESH_ALL);
279#endif
280 exit = true;
281 break;
282
283 default:
284 if(default_event_handler(button) == SYS_USB_CONNECTED) {
285 status_set_ffmode(0);
286 usb = true;
287 exit = true;
288 }
289 break;
290 }
291 if (!exit)
292 {
293 button = get_action(CONTEXT_WPS|ALLOW_SOFTLOCK,TIMEOUT_BLOCK);
294#ifdef HAVE_TOUCHSCREEN
295 if (button == ACTION_TOUCHSCREEN)
296 button = wps_get_touchaction(gui_wps[SCREEN_MAIN].data);
297#endif
298 }
299 }
300 return usb;
301}
302
303
304void display_keylock_text(bool locked)
305{
306 int i;
307 FOR_NB_SCREENS(i)
308 gui_wps[i].display->stop_scroll();
309
310 splash(HZ, locked ? ID2P(LANG_KEYLOCK_ON) : ID2P(LANG_KEYLOCK_OFF));
311}
312
313
314
315
87#if defined(HAVE_BACKLIGHT) || defined(HAVE_REMOTE_LCD) 316#if defined(HAVE_BACKLIGHT) || defined(HAVE_REMOTE_LCD)
88static void gwps_caption_backlight(struct wps_state *state) 317static void gwps_caption_backlight(struct wps_state *state)
89{ 318{
diff --git a/apps/gui/gwps-common.h b/apps/gui/music_screen.h
index 0d196b28e4..90614cb65b 100644
--- a/apps/gui/gwps-common.h
+++ b/apps/gui/music_screen.h
@@ -5,7 +5,7 @@
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < 5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ 6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/ 7 * \/ \/ \/ \/ \/
8 * $Id$ 8 * $Id: gwps-common.h 20492 2009-03-23 17:19:48Z alle $
9 * 9 *
10 * Copyright (C) 2002 Björn Stenberg 10 * Copyright (C) 2002 Björn Stenberg
11 * 11 *
@@ -18,36 +18,20 @@
18 * KIND, either express or implied. 18 * KIND, either express or implied.
19 * 19 *
20 ****************************************************************************/ 20 ****************************************************************************/
21#ifndef _GWPS_COMMON_ 21#ifndef _MUSICSCREEN_H_
22#define _GWPS_COMMON_ 22#define _MUSICSCREEN_H_
23#include <stdbool.h> 23#include <stdbool.h>
24#include <sys/types.h> /* for size_t */ 24
25 25long gui_wps_show(void);
26#include "gwps.h" 26
27
28void gui_sync_wps_init(void);
27 29
28/* fades the volume, e.g. on pause or stop */ 30/* fades the volume, e.g. on pause or stop */
29void fade(bool fade_in, bool updatewps); 31void fade(bool fade_in, bool updatewps);
30 32
31/* Initially display the wps, can fall back to the built-in wps
32 * if the chosen wps is invalid.
33 *
34 * Return true on success, otherwise false */
35bool gui_wps_display(struct gui_wps *gui_wps);
36
37/* return true if screen restore is needed
38 return false otherwise */
39bool update_onvol_change(struct gui_wps * gwps);
40
41/* Update track info related stuff, handle cue sheets as well, and redraw */
42bool gui_wps_update(struct gui_wps *gwps);
43
44bool ffwd_rew(int button); 33bool ffwd_rew(int button);
45void display_keylock_text(bool locked); 34void display_keylock_text(bool locked);
46 35
47/* Refresh the WPS according to refresh_mode. 36bool is_wps_fading(void);
48 *
49 * Return true on success, otherwise false */
50bool gui_wps_redraw(struct gui_wps *gwps,
51 int ffwd_offset,
52 unsigned refresh_mode);
53#endif 37#endif
diff --git a/apps/gui/gwps.h b/apps/gui/wps_engine/gwps.h
index 2acde0dc39..2acde0dc39 100644
--- a/apps/gui/gwps.h
+++ b/apps/gui/wps_engine/gwps.h
diff --git a/apps/gui/wps_debug.c b/apps/gui/wps_engine/wps_debug.c
index 727d9078c6..a89f61af9d 100644
--- a/apps/gui/wps_debug.c
+++ b/apps/gui/wps_engine/wps_debug.c
@@ -23,7 +23,7 @@
23 23
24#include <stdio.h> 24#include <stdio.h>
25#include <string.h> 25#include <string.h>
26#include "gwps.h" 26#include "wps_internals.h"
27#ifdef __PCTOOL__ 27#ifdef __PCTOOL__
28#ifdef WPSEDITOR 28#ifdef WPSEDITOR
29#include "proxy.h" 29#include "proxy.h"
diff --git a/apps/gui/gwps-common.c b/apps/gui/wps_engine/wps_display.c
index 721682f248..c74e2cedfa 100644
--- a/apps/gui/gwps-common.c
+++ b/apps/gui/wps_engine/wps_display.c
@@ -19,7 +19,6 @@
19 * KIND, either express or implied. 19 * KIND, either express or implied.
20 * 20 *
21 ****************************************************************************/ 21 ****************************************************************************/
22#include "gwps-common.h"
23#include "font.h" 22#include "font.h"
24#include <stdio.h> 23#include <stdio.h>
25#include <string.h> 24#include <string.h>
@@ -62,222 +61,9 @@
62#include "backdrop.h" 61#include "backdrop.h"
63#include "viewport.h" 62#include "viewport.h"
64 63
65#define FF_REWIND_MAX_PERCENT 3 /* cap ff/rewind step size at max % of file */
66 /* 3% of 30min file == 54s step size */
67#define MIN_FF_REWIND_STEP 500
68 64
69/* Timeout unit expressed in HZ. In WPS, all timeouts are given in seconds 65#include "wps_internals.h"
70 (possibly with a decimal fraction) but stored as integer values. 66#include "wps_engine.h"
71 E.g. 2.5 is stored as 25. This means 25 tenth of a second, i.e. 25 units.
72*/
73#define TIMEOUT_UNIT (HZ/10) /* I.e. 0.1 sec */
74#define DEFAULT_SUBLINE_TIME_MULTIPLIER 20 /* In TIMEOUT_UNIT's */
75
76bool wps_fading_out = false;
77void fade(bool fade_in, bool updatewps)
78{
79 int fp_global_vol = global_settings.volume << 8;
80 int fp_min_vol = sound_min(SOUND_VOLUME) << 8;
81 int fp_step = (fp_global_vol - fp_min_vol) / 30;
82 int i;
83 wps_fading_out = !fade_in;
84 if (fade_in) {
85 /* fade in */
86 int fp_volume = fp_min_vol;
87
88 /* zero out the sound */
89 sound_set_volume(fp_min_vol >> 8);
90
91 sleep(HZ/10); /* let audio thread run */
92 audio_resume();
93
94 while (fp_volume < fp_global_vol - fp_step) {
95 fp_volume += fp_step;
96 sound_set_volume(fp_volume >> 8);
97 if (updatewps)
98 {
99 FOR_NB_SCREENS(i)
100 gui_wps_redraw(&gui_wps[i], 0, WPS_REFRESH_NON_STATIC);
101 }
102 sleep(1);
103 }
104 sound_set_volume(global_settings.volume);
105 }
106 else {
107 /* fade out */
108 int fp_volume = fp_global_vol;
109
110 while (fp_volume > fp_min_vol + fp_step) {
111 fp_volume -= fp_step;
112 sound_set_volume(fp_volume >> 8);
113 if (updatewps)
114 {
115 FOR_NB_SCREENS(i)
116 gui_wps_redraw(&gui_wps[i], 0, WPS_REFRESH_NON_STATIC);
117 }
118 sleep(1);
119 }
120 audio_pause();
121 wps_fading_out = false;
122#if CONFIG_CODEC != SWCODEC
123#ifndef SIMULATOR
124 /* let audio thread run and wait for the mas to run out of data */
125 while (!mp3_pause_done())
126#endif
127 sleep(HZ/10);
128#endif
129
130 /* reset volume to what it was before the fade */
131 sound_set_volume(global_settings.volume);
132 }
133}
134
135bool update_onvol_change(struct gui_wps * gwps)
136{
137 gui_wps_redraw(gwps, 0, WPS_REFRESH_NON_STATIC);
138
139#ifdef HAVE_LCD_CHARCELLS
140 splashf(0, "Vol: %3d dB",
141 sound_val2phys(SOUND_VOLUME, global_settings.volume));
142 return true;
143#endif
144 return false;
145}
146
147bool ffwd_rew(int button)
148{
149 unsigned int step = 0; /* current ff/rewind step */
150 unsigned int max_step = 0; /* maximum ff/rewind step */
151 int ff_rewind_count = 0; /* current ff/rewind count (in ticks) */
152 int direction = -1; /* forward=1 or backward=-1 */
153 bool exit = false;
154 bool usb = false;
155 int i = 0;
156 const long ff_rw_accel = (global_settings.ff_rewind_accel + 3);
157
158 if (button == ACTION_NONE)
159 {
160 status_set_ffmode(0);
161 return usb;
162 }
163 while (!exit)
164 {
165 switch ( button )
166 {
167 case ACTION_WPS_SEEKFWD:
168 direction = 1;
169 case ACTION_WPS_SEEKBACK:
170 if (wps_state.ff_rewind)
171 {
172 if (direction == 1)
173 {
174 /* fast forwarding, calc max step relative to end */
175 max_step = (wps_state.id3->length -
176 (wps_state.id3->elapsed +
177 ff_rewind_count)) *
178 FF_REWIND_MAX_PERCENT / 100;
179 }
180 else
181 {
182 /* rewinding, calc max step relative to start */
183 max_step = (wps_state.id3->elapsed + ff_rewind_count) *
184 FF_REWIND_MAX_PERCENT / 100;
185 }
186
187 max_step = MAX(max_step, MIN_FF_REWIND_STEP);
188
189 if (step > max_step)
190 step = max_step;
191
192 ff_rewind_count += step * direction;
193
194 /* smooth seeking by multiplying step by: 1 + (2 ^ -accel) */
195 step += step >> ff_rw_accel;
196 }
197 else
198 {
199 if ( (audio_status() & AUDIO_STATUS_PLAY) &&
200 wps_state.id3 && wps_state.id3->length )
201 {
202 if (!wps_state.paused)
203#if (CONFIG_CODEC == SWCODEC)
204 audio_pre_ff_rewind();
205#else
206 audio_pause();
207#endif
208#if CONFIG_KEYPAD == PLAYER_PAD
209 FOR_NB_SCREENS(i)
210 gui_wps[i].display->stop_scroll();
211#endif
212 if (direction > 0)
213 status_set_ffmode(STATUS_FASTFORWARD);
214 else
215 status_set_ffmode(STATUS_FASTBACKWARD);
216
217 wps_state.ff_rewind = true;
218
219 step = 1000 * global_settings.ff_rewind_min_step;
220 }
221 else
222 break;
223 }
224
225 if (direction > 0) {
226 if ((wps_state.id3->elapsed + ff_rewind_count) >
227 wps_state.id3->length)
228 ff_rewind_count = wps_state.id3->length -
229 wps_state.id3->elapsed;
230 }
231 else {
232 if ((int)(wps_state.id3->elapsed + ff_rewind_count) < 0)
233 ff_rewind_count = -wps_state.id3->elapsed;
234 }
235
236 FOR_NB_SCREENS(i)
237 gui_wps_redraw(&gui_wps[i],
238 (wps_state.wps_time_countup == false)?
239 ff_rewind_count:-ff_rewind_count,
240 WPS_REFRESH_PLAYER_PROGRESS |
241 WPS_REFRESH_DYNAMIC);
242
243 break;
244
245 case ACTION_WPS_STOPSEEK:
246 wps_state.id3->elapsed = wps_state.id3->elapsed+ff_rewind_count;
247 audio_ff_rewind(wps_state.id3->elapsed);
248 ff_rewind_count = 0;
249 wps_state.ff_rewind = false;
250 status_set_ffmode(0);
251#if (CONFIG_CODEC != SWCODEC)
252 if (!wps_state.paused)
253 audio_resume();
254#endif
255#ifdef HAVE_LCD_CHARCELLS
256 FOR_NB_SCREENS(i)
257 gui_wps_redraw(&gui_wps[i],0, WPS_REFRESH_ALL);
258#endif
259 exit = true;
260 break;
261
262 default:
263 if(default_event_handler(button) == SYS_USB_CONNECTED) {
264 status_set_ffmode(0);
265 usb = true;
266 exit = true;
267 }
268 break;
269 }
270 if (!exit)
271 {
272 button = get_action(CONTEXT_WPS|ALLOW_SOFTLOCK,TIMEOUT_BLOCK);
273#ifdef HAVE_TOUCHSCREEN
274 if (button == ACTION_TOUCHSCREEN)
275 button = wps_get_touchaction(gui_wps[SCREEN_MAIN].data);
276#endif
277 }
278 }
279 return usb;
280}
281 67
282bool gui_wps_display(struct gui_wps *gwps) 68bool gui_wps_display(struct gui_wps *gwps)
283{ 69{
@@ -364,15 +150,6 @@ bool gui_wps_update(struct gui_wps *gwps)
364} 150}
365 151
366 152
367void display_keylock_text(bool locked)
368{
369 int i;
370 FOR_NB_SCREENS(i)
371 gui_wps[i].display->stop_scroll();
372
373 splash(HZ, locked ? ID2P(LANG_KEYLOCK_ON) : ID2P(LANG_KEYLOCK_OFF));
374}
375
376#ifdef HAVE_LCD_BITMAP 153#ifdef HAVE_LCD_BITMAP
377 154
378static void draw_progressbar(struct gui_wps *gwps, 155static void draw_progressbar(struct gui_wps *gwps,
@@ -605,755 +382,6 @@ static void draw_player_fullbar(struct gui_wps *gwps, char* buf, int buf_size)
605 382
606#endif /* HAVE_LCD_CHARCELL */ 383#endif /* HAVE_LCD_CHARCELL */
607 384
608static char* get_codectype(const struct mp3entry* id3)
609{
610 if (id3->codectype < AFMT_NUM_CODECS) {
611 return (char*)audio_formats[id3->codectype].label;
612 } else {
613 return NULL;
614 }
615}
616
617/* Extract a part from a path.
618 *
619 * buf - buffer extract part to.
620 * buf_size - size of buffer.
621 * path - path to extract from.
622 * level - what to extract. 0 is file name, 1 is parent of file, 2 is
623 * parent of parent, etc.
624 *
625 * Returns buf if the desired level was found, NULL otherwise.
626 */
627static char* get_dir(char* buf, int buf_size, const char* path, int level)
628{
629 const char* sep;
630 const char* last_sep;
631 int len;
632
633 sep = path + strlen(path);
634 last_sep = sep;
635
636 while (sep > path)
637 {
638 if ('/' == *(--sep))
639 {
640 if (!level)
641 break;
642
643 level--;
644 last_sep = sep - 1;
645 }
646 }
647
648 if (level || (last_sep <= sep))
649 return NULL;
650
651 len = MIN(last_sep - sep, buf_size - 1);
652 strlcpy(buf, sep + 1, len + 1);
653 return buf;
654}
655
656/* Return the tag found at index i and write its value in buf.
657 The return value is buf if the tag had a value, or NULL if not.
658
659 intval is used with conditionals/enums: when this function is called,
660 intval should contain the number of options in the conditional/enum.
661 When this function returns, intval is -1 if the tag is non numeric or,
662 if the tag is numeric, *intval is the enum case we want to go to (between 1
663 and the original value of *intval, inclusive).
664 When not treating a conditional/enum, intval should be NULL.
665*/
666static const char *get_token_value(struct gui_wps *gwps,
667 struct wps_token *token,
668 char *buf, int buf_size,
669 int *intval)
670{
671 if (!gwps)
672 return NULL;
673
674 struct wps_data *data = gwps->data;
675 struct wps_state *state = gwps->state;
676
677 if (!data || !state)
678 return NULL;
679
680 struct mp3entry *id3;
681
682 if (token->next)
683 id3 = state->nid3;
684 else
685 id3 = state->id3;
686
687 if (!id3)
688 return NULL;
689
690#if CONFIG_RTC
691 struct tm* tm = NULL;
692
693 /* if the token is an RTC one, update the time
694 and do the necessary checks */
695 if (token->type >= WPS_TOKENS_RTC_BEGIN
696 && token->type <= WPS_TOKENS_RTC_END)
697 {
698 tm = get_time();
699
700 if (!valid_time(tm))
701 return NULL;
702 }
703#endif
704
705 int limit = 1;
706 if (intval)
707 {
708 limit = *intval;
709 *intval = -1;
710 }
711
712 switch (token->type)
713 {
714 case WPS_TOKEN_CHARACTER:
715 return &(token->value.c);
716
717 case WPS_TOKEN_STRING:
718 return data->strings[token->value.i];
719
720 case WPS_TOKEN_TRACK_TIME_ELAPSED:
721 format_time(buf, buf_size,
722 id3->elapsed + state->ff_rewind_count);
723 return buf;
724
725 case WPS_TOKEN_TRACK_TIME_REMAINING:
726 format_time(buf, buf_size,
727 id3->length - id3->elapsed -
728 state->ff_rewind_count);
729 return buf;
730
731 case WPS_TOKEN_TRACK_LENGTH:
732 format_time(buf, buf_size, id3->length);
733 return buf;
734
735 case WPS_TOKEN_PLAYLIST_ENTRIES:
736 snprintf(buf, buf_size, "%d", playlist_amount());
737 return buf;
738
739 case WPS_TOKEN_PLAYLIST_NAME:
740 return playlist_name(NULL, buf, buf_size);
741
742 case WPS_TOKEN_PLAYLIST_POSITION:
743 snprintf(buf, buf_size, "%d", playlist_get_display_index());
744 return buf;
745
746 case WPS_TOKEN_PLAYLIST_SHUFFLE:
747 if ( global_settings.playlist_shuffle )
748 return "s";
749 else
750 return NULL;
751 break;
752
753 case WPS_TOKEN_VOLUME:
754 snprintf(buf, buf_size, "%d", global_settings.volume);
755 if (intval)
756 {
757 if (global_settings.volume == sound_min(SOUND_VOLUME))
758 {
759 *intval = 1;
760 }
761 else if (global_settings.volume == 0)
762 {
763 *intval = limit - 1;
764 }
765 else if (global_settings.volume > 0)
766 {
767 *intval = limit;
768 }
769 else
770 {
771 *intval = (limit - 3) * (global_settings.volume
772 - sound_min(SOUND_VOLUME) - 1)
773 / (-1 - sound_min(SOUND_VOLUME)) + 2;
774 }
775 }
776 return buf;
777
778 case WPS_TOKEN_TRACK_ELAPSED_PERCENT:
779 if (id3->length <= 0)
780 return NULL;
781
782 if (intval)
783 {
784 *intval = limit * (id3->elapsed + state->ff_rewind_count)
785 / id3->length + 1;
786 }
787 snprintf(buf, buf_size, "%d",
788 100*(id3->elapsed + state->ff_rewind_count) / id3->length);
789 return buf;
790
791 case WPS_TOKEN_METADATA_ARTIST:
792 return id3->artist;
793
794 case WPS_TOKEN_METADATA_COMPOSER:
795 return id3->composer;
796
797 case WPS_TOKEN_METADATA_ALBUM:
798 return id3->album;
799
800 case WPS_TOKEN_METADATA_ALBUM_ARTIST:
801 return id3->albumartist;
802
803 case WPS_TOKEN_METADATA_GROUPING:
804 return id3->grouping;
805
806 case WPS_TOKEN_METADATA_GENRE:
807 return id3->genre_string;
808
809 case WPS_TOKEN_METADATA_DISC_NUMBER:
810 if (id3->disc_string)
811 return id3->disc_string;
812 if (id3->discnum) {
813 snprintf(buf, buf_size, "%d", id3->discnum);
814 return buf;
815 }
816 return NULL;
817
818 case WPS_TOKEN_METADATA_TRACK_NUMBER:
819 if (id3->track_string)
820 return id3->track_string;
821
822 if (id3->tracknum) {
823 snprintf(buf, buf_size, "%d", id3->tracknum);
824 return buf;
825 }
826 return NULL;
827
828 case WPS_TOKEN_METADATA_TRACK_TITLE:
829 return id3->title;
830
831 case WPS_TOKEN_METADATA_VERSION:
832 switch (id3->id3version)
833 {
834 case ID3_VER_1_0:
835 return "1";
836
837 case ID3_VER_1_1:
838 return "1.1";
839
840 case ID3_VER_2_2:
841 return "2.2";
842
843 case ID3_VER_2_3:
844 return "2.3";
845
846 case ID3_VER_2_4:
847 return "2.4";
848
849 default:
850 return NULL;
851 }
852
853 case WPS_TOKEN_METADATA_YEAR:
854 if( id3->year_string )
855 return id3->year_string;
856
857 if (id3->year) {
858 snprintf(buf, buf_size, "%d", id3->year);
859 return buf;
860 }
861 return NULL;
862
863 case WPS_TOKEN_METADATA_COMMENT:
864 return id3->comment;
865
866#ifdef HAVE_ALBUMART
867 case WPS_TOKEN_ALBUMART_DISPLAY:
868 draw_album_art(gwps, audio_current_aa_hid(), false);
869 return NULL;
870
871 case WPS_TOKEN_ALBUMART_FOUND:
872 if (audio_current_aa_hid() >= 0) {
873 return "C";
874 }
875 return NULL;
876#endif
877
878 case WPS_TOKEN_FILE_BITRATE:
879 if(id3->bitrate)
880 snprintf(buf, buf_size, "%d", id3->bitrate);
881 else
882 return "?";
883 return buf;
884
885 case WPS_TOKEN_FILE_CODEC:
886 if (intval)
887 {
888 if(id3->codectype == AFMT_UNKNOWN)
889 *intval = AFMT_NUM_CODECS;
890 else
891 *intval = id3->codectype;
892 }
893 return get_codectype(id3);
894
895 case WPS_TOKEN_FILE_FREQUENCY:
896 snprintf(buf, buf_size, "%ld", id3->frequency);
897 return buf;
898
899 case WPS_TOKEN_FILE_FREQUENCY_KHZ:
900 /* ignore remainders < 100, so 22050 Hz becomes just 22k */
901 if ((id3->frequency % 1000) < 100)
902 snprintf(buf, buf_size, "%ld", id3->frequency / 1000);
903 else
904 snprintf(buf, buf_size, "%ld.%d",
905 id3->frequency / 1000,
906 (id3->frequency % 1000) / 100);
907 return buf;
908
909 case WPS_TOKEN_FILE_NAME:
910 if (get_dir(buf, buf_size, id3->path, 0)) {
911 /* Remove extension */
912 char* sep = strrchr(buf, '.');
913 if (NULL != sep) {
914 *sep = 0;
915 }
916 return buf;
917 }
918 else {
919 return NULL;
920 }
921
922 case WPS_TOKEN_FILE_NAME_WITH_EXTENSION:
923 return get_dir(buf, buf_size, id3->path, 0);
924
925 case WPS_TOKEN_FILE_PATH:
926 return id3->path;
927
928 case WPS_TOKEN_FILE_SIZE:
929 snprintf(buf, buf_size, "%ld", id3->filesize / 1024);
930 return buf;
931
932 case WPS_TOKEN_FILE_VBR:
933 return id3->vbr ? "(avg)" : NULL;
934
935 case WPS_TOKEN_FILE_DIRECTORY:
936 return get_dir(buf, buf_size, id3->path, token->value.i);
937
938 case WPS_TOKEN_BATTERY_PERCENT:
939 {
940 int l = battery_level();
941
942 if (intval)
943 {
944 limit = MAX(limit, 2);
945 if (l > -1) {
946 /* First enum is used for "unknown level". */
947 *intval = (limit - 1) * l / 100 + 2;
948 } else {
949 *intval = 1;
950 }
951 }
952
953 if (l > -1) {
954 snprintf(buf, buf_size, "%d", l);
955 return buf;
956 } else {
957 return "?";
958 }
959 }
960
961 case WPS_TOKEN_BATTERY_VOLTS:
962 {
963 unsigned int v = battery_voltage();
964 snprintf(buf, buf_size, "%d.%02d", v / 1000, (v % 1000) / 10);
965 return buf;
966 }
967
968 case WPS_TOKEN_BATTERY_TIME:
969 {
970 int t = battery_time();
971 if (t >= 0)
972 snprintf(buf, buf_size, "%dh %dm", t / 60, t % 60);
973 else
974 return "?h ?m";
975 return buf;
976 }
977
978#if CONFIG_CHARGING
979 case WPS_TOKEN_BATTERY_CHARGER_CONNECTED:
980 {
981 if(charger_input_state==CHARGER)
982 return "p";
983 else
984 return NULL;
985 }
986#endif
987#if CONFIG_CHARGING >= CHARGING_MONITOR
988 case WPS_TOKEN_BATTERY_CHARGING:
989 {
990 if (charge_state == CHARGING || charge_state == TOPOFF) {
991 return "c";
992 } else {
993 return NULL;
994 }
995 }
996#endif
997 case WPS_TOKEN_BATTERY_SLEEPTIME:
998 {
999 if (get_sleep_timer() == 0)
1000 return NULL;
1001 else
1002 {
1003 format_time(buf, buf_size, get_sleep_timer() * 1000);
1004 return buf;
1005 }
1006 }
1007
1008 case WPS_TOKEN_PLAYBACK_STATUS:
1009 {
1010 int status = audio_status();
1011 int mode = 1;
1012 if (status == AUDIO_STATUS_PLAY)
1013 mode = 2;
1014 if (wps_fading_out ||
1015 (status & AUDIO_STATUS_PAUSE && !status_get_ffmode()))
1016 mode = 3;
1017 if (status_get_ffmode() == STATUS_FASTFORWARD)
1018 mode = 4;
1019 if (status_get_ffmode() == STATUS_FASTBACKWARD)
1020 mode = 5;
1021
1022 if (intval) {
1023 *intval = mode;
1024 }
1025
1026 snprintf(buf, buf_size, "%d", mode-1);
1027 return buf;
1028 }
1029
1030 case WPS_TOKEN_REPEAT_MODE:
1031 if (intval)
1032 *intval = global_settings.repeat_mode + 1;
1033 snprintf(buf, buf_size, "%d", global_settings.repeat_mode);
1034 return buf;
1035
1036 case WPS_TOKEN_RTC_PRESENT:
1037#if CONFIG_RTC
1038 return "c";
1039#else
1040 return NULL;
1041#endif
1042
1043#if CONFIG_RTC
1044 case WPS_TOKEN_RTC_12HOUR_CFG:
1045 if (intval)
1046 *intval = global_settings.timeformat + 1;
1047 snprintf(buf, buf_size, "%d", global_settings.timeformat);
1048 return buf;
1049
1050 case WPS_TOKEN_RTC_DAY_OF_MONTH:
1051 /* d: day of month (01..31) */
1052 snprintf(buf, buf_size, "%02d", tm->tm_mday);
1053 return buf;
1054
1055 case WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED:
1056 /* e: day of month, blank padded ( 1..31) */
1057 snprintf(buf, buf_size, "%2d", tm->tm_mday);
1058 return buf;
1059
1060 case WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED:
1061 /* H: hour (00..23) */
1062 snprintf(buf, buf_size, "%02d", tm->tm_hour);
1063 return buf;
1064
1065 case WPS_TOKEN_RTC_HOUR_24:
1066 /* k: hour ( 0..23) */
1067 snprintf(buf, buf_size, "%2d", tm->tm_hour);
1068 return buf;
1069
1070 case WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED:
1071 /* I: hour (01..12) */
1072 snprintf(buf, buf_size, "%02d",
1073 (tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12);
1074 return buf;
1075
1076 case WPS_TOKEN_RTC_HOUR_12:
1077 /* l: hour ( 1..12) */
1078 snprintf(buf, buf_size, "%2d",
1079 (tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12);
1080 return buf;
1081
1082 case WPS_TOKEN_RTC_MONTH:
1083 /* m: month (01..12) */
1084 if (intval)
1085 *intval = tm->tm_mon + 1;
1086 snprintf(buf, buf_size, "%02d", tm->tm_mon + 1);
1087 return buf;
1088
1089 case WPS_TOKEN_RTC_MINUTE:
1090 /* M: minute (00..59) */
1091 snprintf(buf, buf_size, "%02d", tm->tm_min);
1092 return buf;
1093
1094 case WPS_TOKEN_RTC_SECOND:
1095 /* S: second (00..59) */
1096 snprintf(buf, buf_size, "%02d", tm->tm_sec);
1097 return buf;
1098
1099 case WPS_TOKEN_RTC_YEAR_2_DIGITS:
1100 /* y: last two digits of year (00..99) */
1101 snprintf(buf, buf_size, "%02d", tm->tm_year % 100);
1102 return buf;
1103
1104 case WPS_TOKEN_RTC_YEAR_4_DIGITS:
1105 /* Y: year (1970...) */
1106 snprintf(buf, buf_size, "%04d", tm->tm_year + 1900);
1107 return buf;
1108
1109 case WPS_TOKEN_RTC_AM_PM_UPPER:
1110 /* p: upper case AM or PM indicator */
1111 return tm->tm_hour/12 == 0 ? "AM" : "PM";
1112
1113 case WPS_TOKEN_RTC_AM_PM_LOWER:
1114 /* P: lower case am or pm indicator */
1115 return tm->tm_hour/12 == 0 ? "am" : "pm";
1116
1117 case WPS_TOKEN_RTC_WEEKDAY_NAME:
1118 /* a: abbreviated weekday name (Sun..Sat) */
1119 return str(LANG_WEEKDAY_SUNDAY + tm->tm_wday);
1120
1121 case WPS_TOKEN_RTC_MONTH_NAME:
1122 /* b: abbreviated month name (Jan..Dec) */
1123 return str(LANG_MONTH_JANUARY + tm->tm_mon);
1124
1125 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON:
1126 /* u: day of week (1..7); 1 is Monday */
1127 if (intval)
1128 *intval = (tm->tm_wday == 0) ? 7 : tm->tm_wday;
1129 snprintf(buf, buf_size, "%1d", tm->tm_wday + 1);
1130 return buf;
1131
1132 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN:
1133 /* w: day of week (0..6); 0 is Sunday */
1134 if (intval)
1135 *intval = tm->tm_wday + 1;
1136 snprintf(buf, buf_size, "%1d", tm->tm_wday);
1137 return buf;
1138#else
1139 case WPS_TOKEN_RTC_DAY_OF_MONTH:
1140 case WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED:
1141 case WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED:
1142 case WPS_TOKEN_RTC_HOUR_24:
1143 case WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED:
1144 case WPS_TOKEN_RTC_HOUR_12:
1145 case WPS_TOKEN_RTC_MONTH:
1146 case WPS_TOKEN_RTC_MINUTE:
1147 case WPS_TOKEN_RTC_SECOND:
1148 case WPS_TOKEN_RTC_AM_PM_UPPER:
1149 case WPS_TOKEN_RTC_AM_PM_LOWER:
1150 case WPS_TOKEN_RTC_YEAR_2_DIGITS:
1151 return "--";
1152 case WPS_TOKEN_RTC_YEAR_4_DIGITS:
1153 return "----";
1154 case WPS_TOKEN_RTC_WEEKDAY_NAME:
1155 case WPS_TOKEN_RTC_MONTH_NAME:
1156 return "---";
1157 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON:
1158 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN:
1159 return "-";
1160#endif
1161
1162#ifdef HAVE_LCD_CHARCELLS
1163 case WPS_TOKEN_PROGRESSBAR:
1164 {
1165 char *end = utf8encode(data->wps_progress_pat[0], buf);
1166 *end = '\0';
1167 return buf;
1168 }
1169
1170 case WPS_TOKEN_PLAYER_PROGRESSBAR:
1171 if(is_new_player())
1172 {
1173 /* we need 11 characters (full line) for
1174 progress-bar */
1175 strlcpy(buf, " ", buf_size);
1176 }
1177 else
1178 {
1179 /* Tell the user if we have an OldPlayer */
1180 strlcpy(buf, " <Old LCD> ", buf_size);
1181 }
1182 return buf;
1183#endif
1184
1185#ifdef HAVE_TAGCACHE
1186 case WPS_TOKEN_DATABASE_PLAYCOUNT:
1187 if (intval) {
1188 *intval = id3->playcount + 1;
1189 }
1190 snprintf(buf, buf_size, "%ld", id3->playcount);
1191 return buf;
1192
1193 case WPS_TOKEN_DATABASE_RATING:
1194 if (intval) {
1195 *intval = id3->rating + 1;
1196 }
1197 snprintf(buf, buf_size, "%d", id3->rating);
1198 return buf;
1199
1200 case WPS_TOKEN_DATABASE_AUTOSCORE:
1201 if (intval)
1202 *intval = id3->score + 1;
1203
1204 snprintf(buf, buf_size, "%d", id3->score);
1205 return buf;
1206#endif
1207
1208#if (CONFIG_CODEC == SWCODEC)
1209 case WPS_TOKEN_CROSSFADE:
1210 if (intval)
1211 *intval = global_settings.crossfade + 1;
1212 snprintf(buf, buf_size, "%d", global_settings.crossfade);
1213 return buf;
1214
1215 case WPS_TOKEN_REPLAYGAIN:
1216 {
1217 int val;
1218
1219 if (global_settings.replaygain_type == REPLAYGAIN_OFF)
1220 val = 1; /* off */
1221 else
1222 {
1223 int type =
1224 get_replaygain_mode(id3->track_gain_string != NULL,
1225 id3->album_gain_string != NULL);
1226 if (type < 0)
1227 val = 6; /* no tag */
1228 else
1229 val = type + 2;
1230
1231 if (global_settings.replaygain_type == REPLAYGAIN_SHUFFLE)
1232 val += 2;
1233 }
1234
1235 if (intval)
1236 *intval = val;
1237
1238 switch (val)
1239 {
1240 case 1:
1241 case 6:
1242 return "+0.00 dB";
1243 break;
1244 case 2:
1245 case 4:
1246 strlcpy(buf, id3->track_gain_string, buf_size);
1247 break;
1248 case 3:
1249 case 5:
1250 strlcpy(buf, id3->album_gain_string, buf_size);
1251 break;
1252 }
1253 return buf;
1254 }
1255#endif /* (CONFIG_CODEC == SWCODEC) */
1256
1257#if (CONFIG_CODEC != MAS3507D)
1258 case WPS_TOKEN_SOUND_PITCH:
1259 {
1260 int val = sound_get_pitch();
1261 snprintf(buf, buf_size, "%d.%d",
1262 val / 10, val % 10);
1263 return buf;
1264 }
1265#endif
1266
1267 case WPS_TOKEN_MAIN_HOLD:
1268#ifdef HAS_BUTTON_HOLD
1269 if (button_hold())
1270#else
1271 if (is_keys_locked())
1272#endif /*hold switch or softlock*/
1273 return "h";
1274 else
1275 return NULL;
1276
1277#ifdef HAS_REMOTE_BUTTON_HOLD
1278 case WPS_TOKEN_REMOTE_HOLD:
1279 if (remote_button_hold())
1280 return "r";
1281 else
1282 return NULL;
1283#endif
1284
1285#if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
1286 case WPS_TOKEN_VLED_HDD:
1287 if(led_read(HZ/2))
1288 return "h";
1289 else
1290 return NULL;
1291#endif
1292 case WPS_TOKEN_BUTTON_VOLUME:
1293 if (data->button_time_volume &&
1294 TIME_BEFORE(current_tick, data->button_time_volume +
1295 token->value.i * TIMEOUT_UNIT))
1296 return "v";
1297 return NULL;
1298 case WPS_TOKEN_LASTTOUCH:
1299#ifdef HAVE_TOUCHSCREEN
1300 if (TIME_BEFORE(current_tick, token->value.i * TIMEOUT_UNIT +
1301 touchscreen_last_touch()))
1302 return "t";
1303#endif
1304 return NULL;
1305
1306 case WPS_TOKEN_SETTING:
1307 {
1308 if (intval)
1309 {
1310 /* Handle contionals */
1311 const struct settings_list *s = settings+token->value.i;
1312 switch (s->flags&F_T_MASK)
1313 {
1314 case F_T_INT:
1315 case F_T_UINT:
1316 if (s->flags&F_RGB)
1317 /* %?St|name|<#000000|#000001|...|#FFFFFF> */
1318 /* shouldn't overflow since colors are stored
1319 * on 16 bits ...
1320 * but this is pretty useless anyway */
1321 *intval = *(int*)s->setting + 1;
1322 else if (s->cfg_vals == NULL)
1323 /* %?St|name|<1st choice|2nd choice|...> */
1324 *intval = (*(int*)s->setting-s->int_setting->min)
1325 /s->int_setting->step + 1;
1326 else
1327 /* %?St|name|<1st choice|2nd choice|...> */
1328 /* Not sure about this one. cfg_name/vals are
1329 * indexed from 0 right? */
1330 *intval = *(int*)s->setting + 1;
1331 break;
1332 case F_T_BOOL:
1333 /* %?St|name|<if true|if false> */
1334 *intval = *(bool*)s->setting?1:2;
1335 break;
1336 case F_T_CHARPTR:
1337 /* %?St|name|<if non empty string|if empty>
1338 * The string's emptyness discards the setting's
1339 * prefix and suffix */
1340 *intval = ((char*)s->setting)[0]?1:2;
1341 break;
1342 default:
1343 /* This shouldn't happen ... but you never know */
1344 *intval = -1;
1345 break;
1346 }
1347 }
1348 cfg_to_string(token->value.i,buf,buf_size);
1349 return buf;
1350 }
1351
1352 default:
1353 return NULL;
1354 }
1355}
1356
1357/* Return the index to the end token for the conditional token at index. 385/* Return the index to the end token for the conditional token at index.
1358 The conditional token can be either a start token or a separator 386 The conditional token can be either a start token or a separator
1359 (i.e. option) token. 387 (i.e. option) token.
diff --git a/apps/gui/wps_engine/wps_engine.h b/apps/gui/wps_engine/wps_engine.h
new file mode 100644
index 0000000000..fe034f9138
--- /dev/null
+++ b/apps/gui/wps_engine/wps_engine.h
@@ -0,0 +1,49 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id: gwps.h 22003 2009-07-22 22:10:25Z kugel $
9 *
10 * Copyright (C) 2007 Nicolas Pennequin
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22 /** Use this for stuff which external code needs to include **/
23
24#ifndef _WPS_ENGINE_H
25#define _WPS_ENGINE_H
26#include <stdbool.h>
27#include "wps_internals.h" /* TODO: remove this line.. shoudlnt be needed */
28
29
30#ifdef HAVE_TOUCHSCREEN
31int wps_get_touchaction(struct wps_data *data);
32#endif
33
34#ifdef HAVE_ALBUMART
35/* gives back if WPS contains an albumart tag */
36bool gui_sync_wps_uses_albumart(void);
37#endif
38
39/* setup and display a WPS for the first time */
40bool gui_wps_display(struct gui_wps *gwps);
41/* do a requested redraw */
42bool gui_wps_redraw(struct gui_wps *gwps,
43 int ffwd_offset,
44 unsigned refresh_mode);
45/* do a partial redraw, or full if required, also do any housekeeping
46 * which might be needed */
47bool gui_wps_update(struct gui_wps *gwps);
48
49#endif
diff --git a/apps/gui/wps_engine/wps_internals.h b/apps/gui/wps_engine/wps_internals.h
new file mode 100644
index 0000000000..581763fb9a
--- /dev/null
+++ b/apps/gui/wps_engine/wps_internals.h
@@ -0,0 +1,556 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2007 Nicolas Pennequin
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22 /* This stuff is for the wps engine only.. anyone caught using this outside
23 * of apps/gui/wps_engine will be shot on site! */
24
25#ifndef _WPS_ENGINE_INTERNALS_
26#define _WPS_ENGINE_INTERNALS_
27/* Timeout unit expressed in HZ. In WPS, all timeouts are given in seconds
28 (possibly with a decimal fraction) but stored as integer values.
29 E.g. 2.5 is stored as 25. This means 25 tenth of a second, i.e. 25 units.
30*/
31#define TIMEOUT_UNIT (HZ/10) /* I.e. 0.1 sec */
32#define DEFAULT_SUBLINE_TIME_MULTIPLIER 20 /* In TIMEOUT_UNIT's */
33
34
35
36
37/* TODO: sort this mess out */
38
39#include "screen_access.h"
40#include "statusbar.h"
41#include "metadata.h"
42
43/* constants used in line_type and as refresh_mode for wps_refresh */
44#define WPS_REFRESH_STATIC (1u<<0) /* line doesn't change over time */
45#define WPS_REFRESH_DYNAMIC (1u<<1) /* line may change (e.g. time flag) */
46#define WPS_REFRESH_SCROLL (1u<<2) /* line scrolls */
47#define WPS_REFRESH_PLAYER_PROGRESS (1u<<3) /* line contains a progress bar */
48#define WPS_REFRESH_PEAK_METER (1u<<4) /* line contains a peak meter */
49#define WPS_REFRESH_STATUSBAR (1u<<5) /* refresh statusbar */
50#define WPS_REFRESH_ALL (0xffffffffu) /* to refresh all line types */
51
52/* to refresh only those lines that change over time */
53#define WPS_REFRESH_NON_STATIC (WPS_REFRESH_DYNAMIC| \
54 WPS_REFRESH_PLAYER_PROGRESS| \
55 WPS_REFRESH_PEAK_METER)
56/* alignments */
57#define WPS_ALIGN_RIGHT 32
58#define WPS_ALIGN_CENTER 64
59#define WPS_ALIGN_LEFT 128
60
61#ifdef HAVE_ALBUMART
62
63/* albumart definitions */
64#define WPS_ALBUMART_NONE 0 /* WPS does not contain AA tag */
65#define WPS_ALBUMART_CHECK 1 /* WPS contains AA conditional tag */
66#define WPS_ALBUMART_LOAD 2 /* WPS contains AA tag */
67
68#define WPS_ALBUMART_ALIGN_RIGHT 1 /* x align: right */
69#define WPS_ALBUMART_ALIGN_CENTER 2 /* x/y align: center */
70#define WPS_ALBUMART_ALIGN_LEFT 4 /* x align: left */
71#define WPS_ALBUMART_ALIGN_TOP 1 /* y align: top */
72#define WPS_ALBUMART_ALIGN_BOTTOM 4 /* y align: bottom */
73
74#endif /* HAVE_ALBUMART */
75
76/* wps_data*/
77
78#ifdef HAVE_LCD_BITMAP
79struct gui_img {
80 struct bitmap bm;
81 struct viewport* vp; /* The viewport to display this image in */
82 short int x; /* x-pos */
83 short int y; /* y-pos */
84 short int num_subimages; /* number of sub-images */
85 short int subimage_height; /* height of each sub-image */
86 short int display; /* -1 for no display, 0..n to display a subimage */
87 bool loaded; /* load state */
88 bool always_display; /* not using the preload/display mechanism */
89};
90
91struct progressbar {
92 /* regular pb */
93 short x;
94 /* >=0: explicitly set in the tag -> y-coord within the viewport
95 <0 : not set in the tag -> negated 1-based line number within
96 the viewport. y-coord will be computed based on the font height */
97 short y;
98 short width;
99 short height;
100 /*progressbar image*/
101 struct bitmap bm;
102 bool have_bitmap_pb;
103};
104#endif
105
106
107
108struct align_pos {
109 char* left;
110 char* center;
111 char* right;
112};
113
114#ifdef HAVE_LCD_BITMAP
115
116#define MAX_IMAGES (26*2) /* a-z and A-Z */
117#define MAX_PROGRESSBARS 3
118
119/* The image buffer is big enough to store one full-screen native bitmap,
120 plus two full-screen mono bitmaps. */
121
122#define IMG_BUFSIZE ((LCD_HEIGHT*LCD_WIDTH*LCD_DEPTH/8) \
123 + (2*LCD_HEIGHT*LCD_WIDTH/8))
124
125#define WPS_MAX_VIEWPORTS 24
126#define WPS_MAX_LINES ((LCD_HEIGHT/5+1) * 2)
127#define WPS_MAX_SUBLINES (WPS_MAX_LINES*3)
128#define WPS_MAX_TOKENS 1024
129#define WPS_MAX_STRINGS 128
130#define STRING_BUFFER_SIZE 1024
131#define WPS_MAX_COND_LEVEL 10
132
133#else
134
135#define WPS_MAX_VIEWPORTS 2
136#define WPS_MAX_LINES 2
137#define WPS_MAX_SUBLINES 12
138#define WPS_MAX_TOKENS 64
139#define WPS_MAX_STRINGS 32
140#define STRING_BUFFER_SIZE 64
141#define WPS_MAX_COND_LEVEL 5
142
143#endif
144
145#define SUBLINE_RESET -1
146
147enum wps_parse_error {
148 PARSE_OK,
149 PARSE_FAIL_UNCLOSED_COND,
150 PARSE_FAIL_INVALID_CHAR,
151 PARSE_FAIL_COND_SYNTAX_ERROR,
152 PARSE_FAIL_COND_INVALID_PARAM,
153 PARSE_FAIL_LIMITS_EXCEEDED,
154};
155
156enum wps_token_type {
157 WPS_NO_TOKEN, /* for WPS tags we don't want to save as tokens */
158 WPS_TOKEN_UNKNOWN,
159
160 /* Markers */
161 WPS_TOKEN_CHARACTER,
162 WPS_TOKEN_STRING,
163
164 /* Alignment */
165 WPS_TOKEN_ALIGN_LEFT,
166 WPS_TOKEN_ALIGN_CENTER,
167 WPS_TOKEN_ALIGN_RIGHT,
168
169 /* Sublines */
170 WPS_TOKEN_SUBLINE_TIMEOUT,
171
172 /* Battery */
173 WPS_TOKEN_BATTERY_PERCENT,
174 WPS_TOKEN_BATTERY_VOLTS,
175 WPS_TOKEN_BATTERY_TIME,
176 WPS_TOKEN_BATTERY_CHARGER_CONNECTED,
177 WPS_TOKEN_BATTERY_CHARGING,
178 WPS_TOKEN_BATTERY_SLEEPTIME,
179
180 /* Sound */
181#if (CONFIG_CODEC != MAS3507D)
182 WPS_TOKEN_SOUND_PITCH,
183#endif
184#if (CONFIG_CODEC == SWCODEC)
185 WPS_TOKEN_REPLAYGAIN,
186 WPS_TOKEN_CROSSFADE,
187#endif
188
189 /* Time */
190
191 WPS_TOKEN_RTC_PRESENT,
192
193 /* The begin/end values allow us to know if a token is an RTC one.
194 New RTC tokens should be added between the markers. */
195
196 WPS_TOKENS_RTC_BEGIN, /* just the start marker, not an actual token */
197
198 WPS_TOKEN_RTC_DAY_OF_MONTH,
199 WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED,
200 WPS_TOKEN_RTC_12HOUR_CFG,
201 WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED,
202 WPS_TOKEN_RTC_HOUR_24,
203 WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED,
204 WPS_TOKEN_RTC_HOUR_12,
205 WPS_TOKEN_RTC_MONTH,
206 WPS_TOKEN_RTC_MINUTE,
207 WPS_TOKEN_RTC_SECOND,
208 WPS_TOKEN_RTC_YEAR_2_DIGITS,
209 WPS_TOKEN_RTC_YEAR_4_DIGITS,
210 WPS_TOKEN_RTC_AM_PM_UPPER,
211 WPS_TOKEN_RTC_AM_PM_LOWER,
212 WPS_TOKEN_RTC_WEEKDAY_NAME,
213 WPS_TOKEN_RTC_MONTH_NAME,
214 WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON,
215 WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN,
216
217 WPS_TOKENS_RTC_END, /* just the end marker, not an actual token */
218
219 /* Conditional */
220 WPS_TOKEN_CONDITIONAL,
221 WPS_TOKEN_CONDITIONAL_START,
222 WPS_TOKEN_CONDITIONAL_OPTION,
223 WPS_TOKEN_CONDITIONAL_END,
224
225 /* Database */
226#ifdef HAVE_TAGCACHE
227 WPS_TOKEN_DATABASE_PLAYCOUNT,
228 WPS_TOKEN_DATABASE_RATING,
229 WPS_TOKEN_DATABASE_AUTOSCORE,
230#endif
231
232 /* File */
233 WPS_TOKEN_FILE_BITRATE,
234 WPS_TOKEN_FILE_CODEC,
235 WPS_TOKEN_FILE_FREQUENCY,
236 WPS_TOKEN_FILE_FREQUENCY_KHZ,
237 WPS_TOKEN_FILE_NAME,
238 WPS_TOKEN_FILE_NAME_WITH_EXTENSION,
239 WPS_TOKEN_FILE_PATH,
240 WPS_TOKEN_FILE_SIZE,
241 WPS_TOKEN_FILE_VBR,
242 WPS_TOKEN_FILE_DIRECTORY,
243
244#ifdef HAVE_LCD_BITMAP
245 /* Image */
246 WPS_TOKEN_IMAGE_BACKDROP,
247 WPS_TOKEN_IMAGE_PROGRESS_BAR,
248 WPS_TOKEN_IMAGE_PRELOAD,
249 WPS_TOKEN_IMAGE_PRELOAD_DISPLAY,
250 WPS_TOKEN_IMAGE_DISPLAY,
251#endif
252
253#ifdef HAVE_ALBUMART
254 /* Albumart */
255 WPS_TOKEN_ALBUMART_DISPLAY,
256 WPS_TOKEN_ALBUMART_FOUND,
257#endif
258
259 /* Metadata */
260 WPS_TOKEN_METADATA_ARTIST,
261 WPS_TOKEN_METADATA_COMPOSER,
262 WPS_TOKEN_METADATA_ALBUM_ARTIST,
263 WPS_TOKEN_METADATA_GROUPING,
264 WPS_TOKEN_METADATA_ALBUM,
265 WPS_TOKEN_METADATA_GENRE,
266 WPS_TOKEN_METADATA_DISC_NUMBER,
267 WPS_TOKEN_METADATA_TRACK_NUMBER,
268 WPS_TOKEN_METADATA_TRACK_TITLE,
269 WPS_TOKEN_METADATA_VERSION,
270 WPS_TOKEN_METADATA_YEAR,
271 WPS_TOKEN_METADATA_COMMENT,
272
273 /* Mode */
274 WPS_TOKEN_REPEAT_MODE,
275 WPS_TOKEN_PLAYBACK_STATUS,
276
277 WPS_TOKEN_MAIN_HOLD,
278
279#ifdef HAS_REMOTE_BUTTON_HOLD
280 WPS_TOKEN_REMOTE_HOLD,
281#endif
282
283 /* Progressbar */
284 WPS_TOKEN_PROGRESSBAR,
285#ifdef HAVE_LCD_CHARCELLS
286 WPS_TOKEN_PLAYER_PROGRESSBAR,
287#endif
288
289#ifdef HAVE_LCD_BITMAP
290 /* Peakmeter */
291 WPS_TOKEN_PEAKMETER,
292#endif
293
294 /* Volume level */
295 WPS_TOKEN_VOLUME,
296
297 /* Current track */
298 WPS_TOKEN_TRACK_ELAPSED_PERCENT,
299 WPS_TOKEN_TRACK_TIME_ELAPSED,
300 WPS_TOKEN_TRACK_TIME_REMAINING,
301 WPS_TOKEN_TRACK_LENGTH,
302
303 /* Playlist */
304 WPS_TOKEN_PLAYLIST_ENTRIES,
305 WPS_TOKEN_PLAYLIST_NAME,
306 WPS_TOKEN_PLAYLIST_POSITION,
307 WPS_TOKEN_PLAYLIST_SHUFFLE,
308
309#if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
310 /* Virtual LED */
311 WPS_TOKEN_VLED_HDD,
312#endif
313
314 /* Viewport display */
315 WPS_VIEWPORT_ENABLE,
316
317 /* buttons */
318 WPS_TOKEN_BUTTON_VOLUME,
319 WPS_TOKEN_LASTTOUCH,
320
321 /* Setting option */
322 WPS_TOKEN_SETTING,
323};
324
325struct wps_token {
326 unsigned char type; /* enough to store the token type */
327
328 /* Whether the tag (e.g. track name or the album) refers the
329 current or the next song (false=current, true=next) */
330 bool next;
331
332 union {
333 char c;
334 unsigned short i;
335 } value;
336};
337
338/* Description of a subline on the WPS */
339struct wps_subline {
340
341 /* Index of the first token for this subline in the token array.
342 Tokens of this subline end where tokens for the next subline
343 begin. */
344 unsigned short first_token_idx;
345
346 /* Bit or'ed WPS_REFRESH_xxx */
347 unsigned char line_type;
348
349 /* How long the subline should be displayed, in 10ths of sec */
350 unsigned char time_mult;
351};
352
353/* Description of a line on the WPS. A line is a set of sublines.
354 A subline is displayed for a certain amount of time. After that,
355 the next subline of the line is displayed. And so on. */
356struct wps_line {
357
358 /* Number of sublines in this line */
359 signed char num_sublines;
360
361 /* Number (0-based) of the subline within this line currently being displayed */
362 signed char curr_subline;
363
364 /* Index of the first subline of this line in the subline array.
365 Sublines for this line end where sublines for the next line begin. */
366 unsigned short first_subline_idx;
367
368 /* When the next subline of this line should be displayed
369 (absolute time value in ticks) */
370 long subline_expire_time;
371};
372
373#define VP_DRAW_HIDEABLE 0x1
374#define VP_DRAW_HIDDEN 0x2
375#define VP_DRAW_WASHIDDEN 0x4
376struct wps_viewport {
377 struct viewport vp; /* The LCD viewport struct */
378 struct progressbar *pb;
379 /* Indexes of the first and last lines belonging to this viewport in the
380 lines[] array */
381 int first_line, last_line;
382 char hidden_flags;
383 char label;
384};
385
386#ifdef HAVE_TOUCHSCREEN
387struct touchregion {
388 struct wps_viewport* wvp;/* The viewport this region is in */
389 short int x; /* x-pos */
390 short int y; /* y-pos */
391 short int width; /* width */
392 short int height; /* height */
393 bool repeat; /* requires the area be held for the action */
394 int action; /* action this button will return */
395};
396#define MAX_TOUCHREGIONS 15
397#endif
398/* wps_data
399 this struct holds all necessary data which describes the
400 viewable content of a wps */
401struct wps_data
402{
403#ifdef HAVE_LCD_BITMAP
404 struct gui_img img[MAX_IMAGES];
405 unsigned char img_buf[IMG_BUFSIZE];
406 unsigned char* img_buf_ptr;
407 int img_buf_free;
408 bool wps_sb_tag;
409 bool show_sb_on_wps;
410
411 struct progressbar progressbar[MAX_PROGRESSBARS];
412 short progressbar_count;
413
414 bool peak_meter_enabled;
415
416#ifdef HAVE_ALBUMART
417 /* Album art support */
418 unsigned char wps_uses_albumart; /* WPS_ALBUMART_NONE, _CHECK, _LOAD */
419 short albumart_x;
420 short albumart_y;
421 unsigned char albumart_xalign; /* WPS_ALBUMART_ALIGN_LEFT, _CENTER, _RIGHT */
422 unsigned char albumart_yalign; /* WPS_ALBUMART_ALIGN_TOP, _CENTER, _BOTTOM */
423 short albumart_max_width;
424 short albumart_max_height;
425
426 int albumart_cond_index;
427#endif
428
429#else /*HAVE_LCD_CHARCELLS */
430 unsigned short wps_progress_pat[8];
431 bool full_line_progressbar;
432#endif
433
434#ifdef HAVE_TOUCHSCREEN
435 struct touchregion touchregion[MAX_TOUCHREGIONS];
436 short touchregion_count;
437#endif
438
439#ifdef HAVE_REMOTE_LCD
440 bool remote_wps;
441#endif
442
443 /* Number of lines in the WPS. During WPS parsing, this is
444 the index of the line being parsed. */
445 int num_lines;
446
447 /* Number of viewports in the WPS */
448 int num_viewports;
449 struct wps_viewport viewports[WPS_MAX_VIEWPORTS];
450
451 struct wps_line lines[WPS_MAX_LINES];
452
453 /* Total number of sublines in the WPS. During WPS parsing, this is
454 the index of the subline where the parsed tokens are added to. */
455 int num_sublines;
456 struct wps_subline sublines[WPS_MAX_SUBLINES];
457
458 /* Total number of tokens in the WPS. During WPS parsing, this is
459 the index of the token being parsed. */
460 int num_tokens;
461 struct wps_token tokens[WPS_MAX_TOKENS];
462
463 char string_buffer[STRING_BUFFER_SIZE];
464 char *strings[WPS_MAX_STRINGS];
465 int num_strings;
466
467 bool wps_loaded;
468
469 /* tick the volume button was last pressed */
470 unsigned int button_time_volume;
471};
472
473/* initial setup of wps_data */
474void wps_data_init(struct wps_data *wps_data);
475
476/* to setup up the wps-data from a format-buffer (isfile = false)
477 from a (wps-)file (isfile = true)*/
478bool wps_data_load(struct wps_data *wps_data,
479 struct screen *display,
480 const char *buf,
481 bool isfile);
482
483/* Redraw statusbars if necessary */
484void gwps_draw_statusbars(void);
485
486/* Returns the index of the subline in the subline array
487 line - 0-based line number
488 subline - 0-based subline number within the line
489 */
490int wps_subline_index(struct wps_data *wps_data, int line, int subline);
491
492/* Returns the index of the first subline's token in the token array
493 line - 0-based line number
494 subline - 0-based subline number within the line
495 */
496int wps_first_token_index(struct wps_data *data, int line, int subline);
497
498/* Returns the index of the last subline's token in the token array.
499 line - 0-based line number
500 subline - 0-based subline number within the line
501 */
502int wps_last_token_index(struct wps_data *data, int line, int subline);
503
504/* wps_data end */
505
506/* wps_state
507 holds the data which belongs to the current played track,
508 the track which will be played afterwards, current path to the track
509 and some status infos */
510struct wps_state
511{
512 bool ff_rewind;
513 bool paused;
514 int ff_rewind_count;
515 bool wps_time_countup;
516 struct mp3entry* id3;
517 struct mp3entry* nid3;
518 bool do_full_update;
519};
520
521
522/* change the ff/rew-status
523 if ff_rew = true then we are in skipping mode
524 else we are in normal mode */
525/* void wps_state_update_ff_rew(bool ff_rew); Currently unused */
526
527/* change the tag-information of the current played track
528 and the following track */
529/* void wps_state_update_id3_nid3(struct mp3entry *id3, struct mp3entry *nid3); Currently unused */
530/* wps_state end*/
531
532/* gui_wps
533 defines a wps with its data, state,
534 and the screen on which the wps-content should be drawn */
535struct gui_wps
536{
537 struct screen *display;
538 struct wps_data *data;
539 struct wps_state *state;
540};
541
542/* gui_wps end */
543
544
545/* currently only on wps_state is needed */
546extern struct wps_state wps_state;
547extern struct gui_wps gui_wps[NB_SCREENS];
548
549/***** wps_tokens.c ******/
550
551const char *get_token_value(struct gui_wps *gwps,
552 struct wps_token *token,
553 char *buf, int buf_size,
554 int *intval);
555
556#endif
diff --git a/apps/gui/wps_parser.c b/apps/gui/wps_engine/wps_parser.c
index fb0b3ac4c6..15acc1401d 100644
--- a/apps/gui/wps_parser.c
+++ b/apps/gui/wps_engine/wps_parser.c
@@ -43,7 +43,7 @@
43#include <stdbool.h> 43#include <stdbool.h>
44#include "font.h" 44#include "font.h"
45 45
46#include "gwps.h" 46#include "wps_internals.h"
47#include "settings.h" 47#include "settings.h"
48#include "settings_list.h" 48#include "settings_list.h"
49 49
diff --git a/apps/gui/wps_engine/wps_tokens.c b/apps/gui/wps_engine/wps_tokens.c
new file mode 100644
index 0000000000..3852251916
--- /dev/null
+++ b/apps/gui/wps_engine/wps_tokens.c
@@ -0,0 +1,807 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002-2007 Björn Stenberg
11 * Copyright (C) 2007-2008 Nicolas Pennequin
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22#include "font.h"
23#include <stdio.h>
24#include <string.h>
25#include <stdlib.h>
26#include "action.h"
27#include "system.h"
28#include "settings.h"
29#include "settings_list.h"
30#include "rbunicode.h"
31#include "timefuncs.h"
32#include "audio.h"
33#include "status.h"
34#include "power.h"
35#include "powermgmt.h"
36#include "sound.h"
37#include "debug.h"
38#ifdef HAVE_LCD_CHARCELLS
39#include "hwcompat.h"
40#endif
41#include "abrepeat.h"
42#include "mp3_playback.h"
43#include "lang.h"
44#include "misc.h"
45#include "led.h"
46#ifdef HAVE_LCD_BITMAP
47/* Image stuff */
48#include "albumart.h"
49#endif
50#include "dsp.h"
51#include "playlist.h"
52#if CONFIG_CODEC == SWCODEC
53#include "playback.h"
54#endif
55#include "viewport.h"
56
57#include "wps_internals.h"
58#include "music_screen.h"
59
60static char* get_codectype(const struct mp3entry* id3)
61{
62 if (id3->codectype < AFMT_NUM_CODECS) {
63 return (char*)audio_formats[id3->codectype].label;
64 } else {
65 return NULL;
66 }
67}
68
69/* Extract a part from a path.
70 *
71 * buf - buffer extract part to.
72 * buf_size - size of buffer.
73 * path - path to extract from.
74 * level - what to extract. 0 is file name, 1 is parent of file, 2 is
75 * parent of parent, etc.
76 *
77 * Returns buf if the desired level was found, NULL otherwise.
78 */
79static char* get_dir(char* buf, int buf_size, const char* path, int level)
80{
81 const char* sep;
82 const char* last_sep;
83 int len;
84
85 sep = path + strlen(path);
86 last_sep = sep;
87
88 while (sep > path)
89 {
90 if ('/' == *(--sep))
91 {
92 if (!level)
93 break;
94
95 level--;
96 last_sep = sep - 1;
97 }
98 }
99
100 if (level || (last_sep <= sep))
101 return NULL;
102
103 len = MIN(last_sep - sep, buf_size - 1);
104 strlcpy(buf, sep + 1, len + 1);
105 return buf;
106}
107
108/* Return the tag found at index i and write its value in buf.
109 The return value is buf if the tag had a value, or NULL if not.
110
111 intval is used with conditionals/enums: when this function is called,
112 intval should contain the number of options in the conditional/enum.
113 When this function returns, intval is -1 if the tag is non numeric or,
114 if the tag is numeric, *intval is the enum case we want to go to (between 1
115 and the original value of *intval, inclusive).
116 When not treating a conditional/enum, intval should be NULL.
117*/
118const char *get_token_value(struct gui_wps *gwps,
119 struct wps_token *token,
120 char *buf, int buf_size,
121 int *intval)
122{
123 if (!gwps)
124 return NULL;
125
126 struct wps_data *data = gwps->data;
127 struct wps_state *state = gwps->state;
128
129 if (!data || !state)
130 return NULL;
131
132 struct mp3entry *id3;
133
134 if (token->next)
135 id3 = state->nid3;
136 else
137 id3 = state->id3;
138
139 if (!id3)
140 return NULL;
141
142#if CONFIG_RTC
143 struct tm* tm = NULL;
144
145 /* if the token is an RTC one, update the time
146 and do the necessary checks */
147 if (token->type >= WPS_TOKENS_RTC_BEGIN
148 && token->type <= WPS_TOKENS_RTC_END)
149 {
150 tm = get_time();
151
152 if (!valid_time(tm))
153 return NULL;
154 }
155#endif
156
157 int limit = 1;
158 if (intval)
159 {
160 limit = *intval;
161 *intval = -1;
162 }
163
164 switch (token->type)
165 {
166 case WPS_TOKEN_CHARACTER:
167 return &(token->value.c);
168
169 case WPS_TOKEN_STRING:
170 return data->strings[token->value.i];
171
172 case WPS_TOKEN_TRACK_TIME_ELAPSED:
173 format_time(buf, buf_size,
174 id3->elapsed + state->ff_rewind_count);
175 return buf;
176
177 case WPS_TOKEN_TRACK_TIME_REMAINING:
178 format_time(buf, buf_size,
179 id3->length - id3->elapsed -
180 state->ff_rewind_count);
181 return buf;
182
183 case WPS_TOKEN_TRACK_LENGTH:
184 format_time(buf, buf_size, id3->length);
185 return buf;
186
187 case WPS_TOKEN_PLAYLIST_ENTRIES:
188 snprintf(buf, buf_size, "%d", playlist_amount());
189 return buf;
190
191 case WPS_TOKEN_PLAYLIST_NAME:
192 return playlist_name(NULL, buf, buf_size);
193
194 case WPS_TOKEN_PLAYLIST_POSITION:
195 snprintf(buf, buf_size, "%d", playlist_get_display_index());
196 return buf;
197
198 case WPS_TOKEN_PLAYLIST_SHUFFLE:
199 if ( global_settings.playlist_shuffle )
200 return "s";
201 else
202 return NULL;
203 break;
204
205 case WPS_TOKEN_VOLUME:
206 snprintf(buf, buf_size, "%d", global_settings.volume);
207 if (intval)
208 {
209 if (global_settings.volume == sound_min(SOUND_VOLUME))
210 {
211 *intval = 1;
212 }
213 else if (global_settings.volume == 0)
214 {
215 *intval = limit - 1;
216 }
217 else if (global_settings.volume > 0)
218 {
219 *intval = limit;
220 }
221 else
222 {
223 *intval = (limit - 3) * (global_settings.volume
224 - sound_min(SOUND_VOLUME) - 1)
225 / (-1 - sound_min(SOUND_VOLUME)) + 2;
226 }
227 }
228 return buf;
229
230 case WPS_TOKEN_TRACK_ELAPSED_PERCENT:
231 if (id3->length <= 0)
232 return NULL;
233
234 if (intval)
235 {
236 *intval = limit * (id3->elapsed + state->ff_rewind_count)
237 / id3->length + 1;
238 }
239 snprintf(buf, buf_size, "%d",
240 100*(id3->elapsed + state->ff_rewind_count) / id3->length);
241 return buf;
242
243 case WPS_TOKEN_METADATA_ARTIST:
244 return id3->artist;
245
246 case WPS_TOKEN_METADATA_COMPOSER:
247 return id3->composer;
248
249 case WPS_TOKEN_METADATA_ALBUM:
250 return id3->album;
251
252 case WPS_TOKEN_METADATA_ALBUM_ARTIST:
253 return id3->albumartist;
254
255 case WPS_TOKEN_METADATA_GROUPING:
256 return id3->grouping;
257
258 case WPS_TOKEN_METADATA_GENRE:
259 return id3->genre_string;
260
261 case WPS_TOKEN_METADATA_DISC_NUMBER:
262 if (id3->disc_string)
263 return id3->disc_string;
264 if (id3->discnum) {
265 snprintf(buf, buf_size, "%d", id3->discnum);
266 return buf;
267 }
268 return NULL;
269
270 case WPS_TOKEN_METADATA_TRACK_NUMBER:
271 if (id3->track_string)
272 return id3->track_string;
273
274 if (id3->tracknum) {
275 snprintf(buf, buf_size, "%d", id3->tracknum);
276 return buf;
277 }
278 return NULL;
279
280 case WPS_TOKEN_METADATA_TRACK_TITLE:
281 return id3->title;
282
283 case WPS_TOKEN_METADATA_VERSION:
284 switch (id3->id3version)
285 {
286 case ID3_VER_1_0:
287 return "1";
288
289 case ID3_VER_1_1:
290 return "1.1";
291
292 case ID3_VER_2_2:
293 return "2.2";
294
295 case ID3_VER_2_3:
296 return "2.3";
297
298 case ID3_VER_2_4:
299 return "2.4";
300
301 default:
302 return NULL;
303 }
304
305 case WPS_TOKEN_METADATA_YEAR:
306 if( id3->year_string )
307 return id3->year_string;
308
309 if (id3->year) {
310 snprintf(buf, buf_size, "%d", id3->year);
311 return buf;
312 }
313 return NULL;
314
315 case WPS_TOKEN_METADATA_COMMENT:
316 return id3->comment;
317
318#ifdef HAVE_ALBUMART
319 case WPS_TOKEN_ALBUMART_DISPLAY:
320 draw_album_art(gwps, audio_current_aa_hid(), false);
321 return NULL;
322
323 case WPS_TOKEN_ALBUMART_FOUND:
324 if (audio_current_aa_hid() >= 0) {
325 return "C";
326 }
327 return NULL;
328#endif
329
330 case WPS_TOKEN_FILE_BITRATE:
331 if(id3->bitrate)
332 snprintf(buf, buf_size, "%d", id3->bitrate);
333 else
334 return "?";
335 return buf;
336
337 case WPS_TOKEN_FILE_CODEC:
338 if (intval)
339 {
340 if(id3->codectype == AFMT_UNKNOWN)
341 *intval = AFMT_NUM_CODECS;
342 else
343 *intval = id3->codectype;
344 }
345 return get_codectype(id3);
346
347 case WPS_TOKEN_FILE_FREQUENCY:
348 snprintf(buf, buf_size, "%ld", id3->frequency);
349 return buf;
350
351 case WPS_TOKEN_FILE_FREQUENCY_KHZ:
352 /* ignore remainders < 100, so 22050 Hz becomes just 22k */
353 if ((id3->frequency % 1000) < 100)
354 snprintf(buf, buf_size, "%ld", id3->frequency / 1000);
355 else
356 snprintf(buf, buf_size, "%ld.%d",
357 id3->frequency / 1000,
358 (id3->frequency % 1000) / 100);
359 return buf;
360
361 case WPS_TOKEN_FILE_NAME:
362 if (get_dir(buf, buf_size, id3->path, 0)) {
363 /* Remove extension */
364 char* sep = strrchr(buf, '.');
365 if (NULL != sep) {
366 *sep = 0;
367 }
368 return buf;
369 }
370 else {
371 return NULL;
372 }
373
374 case WPS_TOKEN_FILE_NAME_WITH_EXTENSION:
375 return get_dir(buf, buf_size, id3->path, 0);
376
377 case WPS_TOKEN_FILE_PATH:
378 return id3->path;
379
380 case WPS_TOKEN_FILE_SIZE:
381 snprintf(buf, buf_size, "%ld", id3->filesize / 1024);
382 return buf;
383
384 case WPS_TOKEN_FILE_VBR:
385 return id3->vbr ? "(avg)" : NULL;
386
387 case WPS_TOKEN_FILE_DIRECTORY:
388 return get_dir(buf, buf_size, id3->path, token->value.i);
389
390 case WPS_TOKEN_BATTERY_PERCENT:
391 {
392 int l = battery_level();
393
394 if (intval)
395 {
396 limit = MAX(limit, 2);
397 if (l > -1) {
398 /* First enum is used for "unknown level". */
399 *intval = (limit - 1) * l / 100 + 2;
400 } else {
401 *intval = 1;
402 }
403 }
404
405 if (l > -1) {
406 snprintf(buf, buf_size, "%d", l);
407 return buf;
408 } else {
409 return "?";
410 }
411 }
412
413 case WPS_TOKEN_BATTERY_VOLTS:
414 {
415 unsigned int v = battery_voltage();
416 snprintf(buf, buf_size, "%d.%02d", v / 1000, (v % 1000) / 10);
417 return buf;
418 }
419
420 case WPS_TOKEN_BATTERY_TIME:
421 {
422 int t = battery_time();
423 if (t >= 0)
424 snprintf(buf, buf_size, "%dh %dm", t / 60, t % 60);
425 else
426 return "?h ?m";
427 return buf;
428 }
429
430#if CONFIG_CHARGING
431 case WPS_TOKEN_BATTERY_CHARGER_CONNECTED:
432 {
433 if(charger_input_state==CHARGER)
434 return "p";
435 else
436 return NULL;
437 }
438#endif
439#if CONFIG_CHARGING >= CHARGING_MONITOR
440 case WPS_TOKEN_BATTERY_CHARGING:
441 {
442 if (charge_state == CHARGING || charge_state == TOPOFF) {
443 return "c";
444 } else {
445 return NULL;
446 }
447 }
448#endif
449 case WPS_TOKEN_BATTERY_SLEEPTIME:
450 {
451 if (get_sleep_timer() == 0)
452 return NULL;
453 else
454 {
455 format_time(buf, buf_size, get_sleep_timer() * 1000);
456 return buf;
457 }
458 }
459
460 case WPS_TOKEN_PLAYBACK_STATUS:
461 {
462 int status = audio_status();
463 int mode = 1;
464 if (status == AUDIO_STATUS_PLAY)
465 mode = 2;
466 if (is_wps_fading() ||
467 (status & AUDIO_STATUS_PAUSE && !status_get_ffmode()))
468 mode = 3;
469 if (status_get_ffmode() == STATUS_FASTFORWARD)
470 mode = 4;
471 if (status_get_ffmode() == STATUS_FASTBACKWARD)
472 mode = 5;
473
474 if (intval) {
475 *intval = mode;
476 }
477
478 snprintf(buf, buf_size, "%d", mode-1);
479 return buf;
480 }
481
482 case WPS_TOKEN_REPEAT_MODE:
483 if (intval)
484 *intval = global_settings.repeat_mode + 1;
485 snprintf(buf, buf_size, "%d", global_settings.repeat_mode);
486 return buf;
487
488 case WPS_TOKEN_RTC_PRESENT:
489#if CONFIG_RTC
490 return "c";
491#else
492 return NULL;
493#endif
494
495#if CONFIG_RTC
496 case WPS_TOKEN_RTC_12HOUR_CFG:
497 if (intval)
498 *intval = global_settings.timeformat + 1;
499 snprintf(buf, buf_size, "%d", global_settings.timeformat);
500 return buf;
501
502 case WPS_TOKEN_RTC_DAY_OF_MONTH:
503 /* d: day of month (01..31) */
504 snprintf(buf, buf_size, "%02d", tm->tm_mday);
505 return buf;
506
507 case WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED:
508 /* e: day of month, blank padded ( 1..31) */
509 snprintf(buf, buf_size, "%2d", tm->tm_mday);
510 return buf;
511
512 case WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED:
513 /* H: hour (00..23) */
514 snprintf(buf, buf_size, "%02d", tm->tm_hour);
515 return buf;
516
517 case WPS_TOKEN_RTC_HOUR_24:
518 /* k: hour ( 0..23) */
519 snprintf(buf, buf_size, "%2d", tm->tm_hour);
520 return buf;
521
522 case WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED:
523 /* I: hour (01..12) */
524 snprintf(buf, buf_size, "%02d",
525 (tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12);
526 return buf;
527
528 case WPS_TOKEN_RTC_HOUR_12:
529 /* l: hour ( 1..12) */
530 snprintf(buf, buf_size, "%2d",
531 (tm->tm_hour % 12 == 0) ? 12 : tm->tm_hour % 12);
532 return buf;
533
534 case WPS_TOKEN_RTC_MONTH:
535 /* m: month (01..12) */
536 if (intval)
537 *intval = tm->tm_mon + 1;
538 snprintf(buf, buf_size, "%02d", tm->tm_mon + 1);
539 return buf;
540
541 case WPS_TOKEN_RTC_MINUTE:
542 /* M: minute (00..59) */
543 snprintf(buf, buf_size, "%02d", tm->tm_min);
544 return buf;
545
546 case WPS_TOKEN_RTC_SECOND:
547 /* S: second (00..59) */
548 snprintf(buf, buf_size, "%02d", tm->tm_sec);
549 return buf;
550
551 case WPS_TOKEN_RTC_YEAR_2_DIGITS:
552 /* y: last two digits of year (00..99) */
553 snprintf(buf, buf_size, "%02d", tm->tm_year % 100);
554 return buf;
555
556 case WPS_TOKEN_RTC_YEAR_4_DIGITS:
557 /* Y: year (1970...) */
558 snprintf(buf, buf_size, "%04d", tm->tm_year + 1900);
559 return buf;
560
561 case WPS_TOKEN_RTC_AM_PM_UPPER:
562 /* p: upper case AM or PM indicator */
563 return tm->tm_hour/12 == 0 ? "AM" : "PM";
564
565 case WPS_TOKEN_RTC_AM_PM_LOWER:
566 /* P: lower case am or pm indicator */
567 return tm->tm_hour/12 == 0 ? "am" : "pm";
568
569 case WPS_TOKEN_RTC_WEEKDAY_NAME:
570 /* a: abbreviated weekday name (Sun..Sat) */
571 return str(LANG_WEEKDAY_SUNDAY + tm->tm_wday);
572
573 case WPS_TOKEN_RTC_MONTH_NAME:
574 /* b: abbreviated month name (Jan..Dec) */
575 return str(LANG_MONTH_JANUARY + tm->tm_mon);
576
577 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON:
578 /* u: day of week (1..7); 1 is Monday */
579 if (intval)
580 *intval = (tm->tm_wday == 0) ? 7 : tm->tm_wday;
581 snprintf(buf, buf_size, "%1d", tm->tm_wday + 1);
582 return buf;
583
584 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN:
585 /* w: day of week (0..6); 0 is Sunday */
586 if (intval)
587 *intval = tm->tm_wday + 1;
588 snprintf(buf, buf_size, "%1d", tm->tm_wday);
589 return buf;
590#else
591 case WPS_TOKEN_RTC_DAY_OF_MONTH:
592 case WPS_TOKEN_RTC_DAY_OF_MONTH_BLANK_PADDED:
593 case WPS_TOKEN_RTC_HOUR_24_ZERO_PADDED:
594 case WPS_TOKEN_RTC_HOUR_24:
595 case WPS_TOKEN_RTC_HOUR_12_ZERO_PADDED:
596 case WPS_TOKEN_RTC_HOUR_12:
597 case WPS_TOKEN_RTC_MONTH:
598 case WPS_TOKEN_RTC_MINUTE:
599 case WPS_TOKEN_RTC_SECOND:
600 case WPS_TOKEN_RTC_AM_PM_UPPER:
601 case WPS_TOKEN_RTC_AM_PM_LOWER:
602 case WPS_TOKEN_RTC_YEAR_2_DIGITS:
603 return "--";
604 case WPS_TOKEN_RTC_YEAR_4_DIGITS:
605 return "----";
606 case WPS_TOKEN_RTC_WEEKDAY_NAME:
607 case WPS_TOKEN_RTC_MONTH_NAME:
608 return "---";
609 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_MON:
610 case WPS_TOKEN_RTC_DAY_OF_WEEK_START_SUN:
611 return "-";
612#endif
613
614#ifdef HAVE_LCD_CHARCELLS
615 case WPS_TOKEN_PROGRESSBAR:
616 {
617 char *end = utf8encode(data->wps_progress_pat[0], buf);
618 *end = '\0';
619 return buf;
620 }
621
622 case WPS_TOKEN_PLAYER_PROGRESSBAR:
623 if(is_new_player())
624 {
625 /* we need 11 characters (full line) for
626 progress-bar */
627 strlcpy(buf, " ", buf_size);
628 }
629 else
630 {
631 /* Tell the user if we have an OldPlayer */
632 strlcpy(buf, " <Old LCD> ", buf_size);
633 }
634 return buf;
635#endif
636
637#ifdef HAVE_TAGCACHE
638 case WPS_TOKEN_DATABASE_PLAYCOUNT:
639 if (intval) {
640 *intval = id3->playcount + 1;
641 }
642 snprintf(buf, buf_size, "%ld", id3->playcount);
643 return buf;
644
645 case WPS_TOKEN_DATABASE_RATING:
646 if (intval) {
647 *intval = id3->rating + 1;
648 }
649 snprintf(buf, buf_size, "%d", id3->rating);
650 return buf;
651
652 case WPS_TOKEN_DATABASE_AUTOSCORE:
653 if (intval)
654 *intval = id3->score + 1;
655
656 snprintf(buf, buf_size, "%d", id3->score);
657 return buf;
658#endif
659
660#if (CONFIG_CODEC == SWCODEC)
661 case WPS_TOKEN_CROSSFADE:
662 if (intval)
663 *intval = global_settings.crossfade + 1;
664 snprintf(buf, buf_size, "%d", global_settings.crossfade);
665 return buf;
666
667 case WPS_TOKEN_REPLAYGAIN:
668 {
669 int val;
670
671 if (global_settings.replaygain_type == REPLAYGAIN_OFF)
672 val = 1; /* off */
673 else
674 {
675 int type =
676 get_replaygain_mode(id3->track_gain_string != NULL,
677 id3->album_gain_string != NULL);
678 if (type < 0)
679 val = 6; /* no tag */
680 else
681 val = type + 2;
682
683 if (global_settings.replaygain_type == REPLAYGAIN_SHUFFLE)
684 val += 2;
685 }
686
687 if (intval)
688 *intval = val;
689
690 switch (val)
691 {
692 case 1:
693 case 6:
694 return "+0.00 dB";
695 break;
696 case 2:
697 case 4:
698 strlcpy(buf, id3->track_gain_string, buf_size);
699 break;
700 case 3:
701 case 5:
702 strlcpy(buf, id3->album_gain_string, buf_size);
703 break;
704 }
705 return buf;
706 }
707#endif /* (CONFIG_CODEC == SWCODEC) */
708
709#if (CONFIG_CODEC != MAS3507D)
710 case WPS_TOKEN_SOUND_PITCH:
711 {
712 int val = sound_get_pitch();
713 snprintf(buf, buf_size, "%d.%d",
714 val / 10, val % 10);
715 return buf;
716 }
717#endif
718
719 case WPS_TOKEN_MAIN_HOLD:
720#ifdef HAS_BUTTON_HOLD
721 if (button_hold())
722#else
723 if (is_keys_locked())
724#endif /*hold switch or softlock*/
725 return "h";
726 else
727 return NULL;
728
729#ifdef HAS_REMOTE_BUTTON_HOLD
730 case WPS_TOKEN_REMOTE_HOLD:
731 if (remote_button_hold())
732 return "r";
733 else
734 return NULL;
735#endif
736
737#if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
738 case WPS_TOKEN_VLED_HDD:
739 if(led_read(HZ/2))
740 return "h";
741 else
742 return NULL;
743#endif
744 case WPS_TOKEN_BUTTON_VOLUME:
745 if (data->button_time_volume &&
746 TIME_BEFORE(current_tick, data->button_time_volume +
747 token->value.i * TIMEOUT_UNIT))
748 return "v";
749 return NULL;
750 case WPS_TOKEN_LASTTOUCH:
751#ifdef HAVE_TOUCHSCREEN
752 if (TIME_BEFORE(current_tick, token->value.i * TIMEOUT_UNIT +
753 touchscreen_last_touch()))
754 return "t";
755#endif
756 return NULL;
757
758 case WPS_TOKEN_SETTING:
759 {
760 if (intval)
761 {
762 /* Handle contionals */
763 const struct settings_list *s = settings+token->value.i;
764 switch (s->flags&F_T_MASK)
765 {
766 case F_T_INT:
767 case F_T_UINT:
768 if (s->flags&F_RGB)
769 /* %?St|name|<#000000|#000001|...|#FFFFFF> */
770 /* shouldn't overflow since colors are stored
771 * on 16 bits ...
772 * but this is pretty useless anyway */
773 *intval = *(int*)s->setting + 1;
774 else if (s->cfg_vals == NULL)
775 /* %?St|name|<1st choice|2nd choice|...> */
776 *intval = (*(int*)s->setting-s->int_setting->min)
777 /s->int_setting->step + 1;
778 else
779 /* %?St|name|<1st choice|2nd choice|...> */
780 /* Not sure about this one. cfg_name/vals are
781 * indexed from 0 right? */
782 *intval = *(int*)s->setting + 1;
783 break;
784 case F_T_BOOL:
785 /* %?St|name|<if true|if false> */
786 *intval = *(bool*)s->setting?1:2;
787 break;
788 case F_T_CHARPTR:
789 /* %?St|name|<if non empty string|if empty>
790 * The string's emptyness discards the setting's
791 * prefix and suffix */
792 *intval = ((char*)s->setting)[0]?1:2;
793 break;
794 default:
795 /* This shouldn't happen ... but you never know */
796 *intval = -1;
797 break;
798 }
799 }
800 cfg_to_string(token->value.i,buf,buf_size);
801 return buf;
802 }
803
804 default:
805 return NULL;
806 }
807}
diff --git a/apps/iap.c b/apps/iap.c
index 592bbdbbf8..f7a808d8b2 100644
--- a/apps/iap.c
+++ b/apps/iap.c
@@ -36,7 +36,7 @@
36#include "audio.h" 36#include "audio.h"
37#include "settings.h" 37#include "settings.h"
38#include "metadata.h" 38#include "metadata.h"
39#include "gwps.h" 39#include "wps_engine/wps_engine.h"
40 40
41#include "action.h" 41#include "action.h"
42 42
diff --git a/apps/main.c b/apps/main.c
index 929c946334..2cf9ce7175 100644
--- a/apps/main.c
+++ b/apps/main.c
@@ -52,7 +52,7 @@
52#include "sprintf.h" 52#include "sprintf.h"
53#include "font.h" 53#include "font.h"
54#include "language.h" 54#include "language.h"
55#include "gwps.h" 55#include "music_screen.h"
56#include "playlist.h" 56#include "playlist.h"
57#include "buffer.h" 57#include "buffer.h"
58#include "rolo.h" 58#include "rolo.h"
diff --git a/apps/menu.c b/apps/menu.c
index f6d0ef967d..6690972e50 100644
--- a/apps/menu.c
+++ b/apps/menu.c
@@ -48,7 +48,6 @@
48#include "string.h" 48#include "string.h"
49#include "root_menu.h" 49#include "root_menu.h"
50#include "bookmark.h" 50#include "bookmark.h"
51#include "gwps-common.h" /* for fade() */
52#include "audio.h" 51#include "audio.h"
53#include "viewport.h" 52#include "viewport.h"
54#include "quickscreen.h" 53#include "quickscreen.h"
diff --git a/apps/menus/main_menu.c b/apps/menus/main_menu.c
index 76ed01d9ba..4009566c44 100644
--- a/apps/menus/main_menu.c
+++ b/apps/menus/main_menu.c
@@ -50,7 +50,7 @@
50#endif 50#endif
51#include "version.h" 51#include "version.h"
52#include "time.h" 52#include "time.h"
53#include "gwps.h" 53#include "gui/wps_engine/wps_engine.h"
54 54
55static const struct browse_folder_info config = {ROCKBOX_DIR, SHOW_CFG}; 55static const struct browse_folder_info config = {ROCKBOX_DIR, SHOW_CFG};
56 56
diff --git a/apps/misc.c b/apps/misc.c
index e6f8ca840b..2e7051cbd3 100644
--- a/apps/misc.c
+++ b/apps/misc.c
@@ -75,9 +75,8 @@
75#include "bmp.h" 75#include "bmp.h"
76#include "icons.h" 76#include "icons.h"
77#endif /* End HAVE_LCD_BITMAP */ 77#endif /* End HAVE_LCD_BITMAP */
78#include "gui/gwps-common.h"
79#include "bookmark.h" 78#include "bookmark.h"
80 79#include "music_screen.h"
81#include "playback.h" 80#include "playback.h"
82 81
83#ifdef BOOTFILE 82#ifdef BOOTFILE
diff --git a/apps/recorder/albumart.c b/apps/recorder/albumart.c
index a378c332b3..f1315da71f 100644
--- a/apps/recorder/albumart.c
+++ b/apps/recorder/albumart.c
@@ -24,7 +24,6 @@
24#include "system.h" 24#include "system.h"
25#include "albumart.h" 25#include "albumart.h"
26#include "metadata.h" 26#include "metadata.h"
27#include "gwps.h"
28#include "buffering.h" 27#include "buffering.h"
29#include "dircache.h" 28#include "dircache.h"
30#include "misc.h" 29#include "misc.h"
diff --git a/apps/recorder/albumart.h b/apps/recorder/albumart.h
index edf464fb7a..82e0b79aec 100644
--- a/apps/recorder/albumart.h
+++ b/apps/recorder/albumart.h
@@ -26,7 +26,7 @@
26 26
27#include <stdbool.h> 27#include <stdbool.h>
28#include "metadata.h" 28#include "metadata.h"
29#include "gwps.h" 29#include "wps_engine/wps_engine.h"
30 30
31/* Look for albumart bitmap in the same dir as the track and in its parent dir. 31/* Look for albumart bitmap in the same dir as the track and in its parent dir.
32 * Stores the found filename in the buf parameter. 32 * Stores the found filename in the buf parameter.
diff --git a/apps/root_menu.c b/apps/root_menu.c
index 15bc524cce..37fda98cb3 100644
--- a/apps/root_menu.c
+++ b/apps/root_menu.c
@@ -53,7 +53,7 @@
53#ifdef HAVE_RECORDING 53#ifdef HAVE_RECORDING
54#include "recording.h" 54#include "recording.h"
55#endif 55#endif
56#include "gwps-common.h" 56#include "music_screen.h"
57#include "bookmark.h" 57#include "bookmark.h"
58#include "playlist.h" 58#include "playlist.h"
59#include "tagtree.h" 59#include "tagtree.h"
diff --git a/apps/settings.c b/apps/settings.c
index 29360f14d3..800cc59a56 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -52,7 +52,6 @@
52#endif 52#endif
53#include "lang.h" 53#include "lang.h"
54#include "language.h" 54#include "language.h"
55#include "gwps.h"
56#include "powermgmt.h" 55#include "powermgmt.h"
57#include "sprintf.h" 56#include "sprintf.h"
58#include "keyboard.h" 57#include "keyboard.h"
@@ -70,6 +69,7 @@
70#if CONFIG_TUNER 69#if CONFIG_TUNER
71#include "radio.h" 70#include "radio.h"
72#endif 71#endif
72#include "wps_engine/wps_engine.h"
73 73
74#if CONFIG_CODEC == MAS3507D 74#if CONFIG_CODEC == MAS3507D
75void dac_line_in(bool enable); 75void dac_line_in(bool enable);
diff --git a/apps/tree.c b/apps/tree.c
index 576453a3ad..2c6c85f2a8 100644
--- a/apps/tree.c
+++ b/apps/tree.c
@@ -36,7 +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 "gwps.h" 39#include "wps_engine/wps_engine.h"
40#include "settings.h" 40#include "settings.h"
41#include "debug.h" 41#include "debug.h"
42#include "storage.h" 42#include "storage.h"
@@ -64,7 +64,6 @@
64#include "tagcache.h" 64#include "tagcache.h"
65#endif 65#endif
66#include "yesno.h" 66#include "yesno.h"
67#include "gwps-common.h"
68#include "eeprom_settings.h" 67#include "eeprom_settings.h"
69#include "playlist_catalog.h" 68#include "playlist_catalog.h"
70 69