summaryrefslogtreecommitdiff
path: root/apps/gui/statusbar.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/gui/statusbar.c')
-rw-r--r--apps/gui/statusbar.c508
1 files changed, 508 insertions, 0 deletions
diff --git a/apps/gui/statusbar.c b/apps/gui/statusbar.c
new file mode 100644
index 0000000000..5ddc194610
--- /dev/null
+++ b/apps/gui/statusbar.c
@@ -0,0 +1,508 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) Robert E. Hak (2002), Linus Nielsen Feltzing (2002), Kévin FERRARE (2005)
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19
20#include "config.h"
21#include "screen_access.h"
22#include "lcd.h"
23#include "font.h"
24#include "kernel.h"
25#include "string.h" /* for memcmp oO*/
26#include "sprintf.h"
27#include "sound.h"
28#include "power.h"
29#include "settings.h"
30#include "icons.h"
31#include "powermgmt.h"
32#include "button.h"
33
34#include "status.h" /* needed for battery_state global var */
35#include "wps.h" /* for keys_locked */
36#include "statusbar.h"
37
38
39/* FIXME: should be removed from icon.h to avoid redefinition,
40 but still needed for compatibility with old system */
41#define STATUSBAR_X_POS 0
42#define STATUSBAR_Y_POS 0 /* MUST be a multiple of 8 */
43#define STATUSBAR_HEIGHT 8
44#define STATUSBAR_BATTERY_X_POS 0
45#define STATUSBAR_BATTERY_WIDTH 18
46#define STATUSBAR_PLUG_X_POS STATUSBAR_X_POS + \
47 STATUSBAR_BATTERY_WIDTH +2
48#define STATUSBAR_PLUG_WIDTH 7
49#define STATUSBAR_VOLUME_X_POS STATUSBAR_X_POS + \
50 STATUSBAR_BATTERY_WIDTH + \
51 STATUSBAR_PLUG_WIDTH +2+2
52#define STATUSBAR_VOLUME_WIDTH 16
53#define STATUSBAR_PLAY_STATE_X_POS STATUSBAR_X_POS + \
54 STATUSBAR_BATTERY_WIDTH + \
55 STATUSBAR_PLUG_WIDTH + \
56 STATUSBAR_VOLUME_WIDTH+2+2+2
57#define STATUSBAR_PLAY_STATE_WIDTH 7
58#define STATUSBAR_PLAY_MODE_X_POS STATUSBAR_X_POS + \
59 STATUSBAR_BATTERY_WIDTH + \
60 STATUSBAR_PLUG_WIDTH + \
61 STATUSBAR_VOLUME_WIDTH + \
62 STATUSBAR_PLAY_STATE_WIDTH + \
63 2+2+2+2
64#define STATUSBAR_PLAY_MODE_WIDTH 7
65#define STATUSBAR_SHUFFLE_X_POS STATUSBAR_X_POS + \
66 STATUSBAR_BATTERY_WIDTH + \
67 STATUSBAR_PLUG_WIDTH + \
68 STATUSBAR_VOLUME_WIDTH + \
69 STATUSBAR_PLAY_STATE_WIDTH + \
70 STATUSBAR_PLAY_MODE_WIDTH + \
71 2+2+2+2+2
72#define STATUSBAR_SHUFFLE_WIDTH 7
73#define STATUSBAR_LOCK_X_POS STATUSBAR_X_POS + \
74 STATUSBAR_BATTERY_WIDTH + \
75 STATUSBAR_PLUG_WIDTH + \
76 STATUSBAR_VOLUME_WIDTH + \
77 STATUSBAR_PLAY_STATE_WIDTH + \
78 STATUSBAR_PLAY_MODE_WIDTH + \
79 STATUSBAR_SHUFFLE_WIDTH + \
80 2+2+2+2+2+2
81#define STATUSBAR_LOCK_WIDTH 5
82#define STATUSBAR_DISK_WIDTH 12
83#define STATUSBAR_DISK_X_POS(statusbar_width) statusbar_width - \
84 STATUSBAR_DISK_WIDTH
85#define STATUSBAR_TIME_X_END(statusbar_width) statusbar_width-1
86
87void gui_statusbar_init(struct gui_statusbar * bar)
88{
89 bar->last_volume = -1; /* -1 means "first update ever" */
90 bar->battery_icon_switch_tick = 0;
91#ifdef HAVE_USB_POWER
92 bar->battery_charge_step = 0;
93#endif
94}
95
96void gui_statusbar_set_screen(struct gui_statusbar * bar,
97 struct screen * display)
98{
99 bar->display = display;
100 gui_statusbar_draw(bar, false);
101}
102
103void gui_statusbar_draw(struct gui_statusbar * bar, bool force_redraw)
104{
105#ifdef HAVE_LCD_BITMAP
106 if(!global_settings.statusbar)
107 return;
108#endif
109
110 struct screen * display = bar->display;
111
112#ifdef HAVE_LCD_BITMAP
113 struct tm* tm; /* For Time */
114#else
115 (void)force_redraw; /* players always "redraw" */
116#endif
117
118 bar->info.volume = sound_val2phys(SOUND_VOLUME, global_settings.volume);
119 bar->info.inserted = charger_inserted();
120 bar->info.battlevel = battery_level();
121 bar->info.battery_safe = battery_level_safe();
122
123#ifdef HAVE_LCD_BITMAP
124 tm = get_time();
125 bar->info.hour = tm->tm_hour;
126 bar->info.minute = tm->tm_min;
127 bar->info.shuffle = global_settings.playlist_shuffle;
128#if CONFIG_KEYPAD == IRIVER_H100_PAD
129 bar->info.keylock = button_hold();
130#else
131 bar->info.keylock = keys_locked;
132#endif
133 bar->info.repeat = global_settings.repeat_mode;
134 bar->info.playmode = current_playmode();
135#if CONFIG_LED == LED_VIRTUAL
136 bar->info.led = led_read(HZ/2); /* delay should match polling interval */
137#endif
138#ifdef HAVE_USB_POWER
139 bar->info.usb_power = usb_powered();
140#endif
141
142 /* only redraw if forced to, or info has changed */
143 if (force_redraw ||
144 bar->info.inserted ||
145 !bar->info.battery_safe ||
146 bar->info.redraw_volume ||
147 memcmp(&(bar->info), &(bar->lastinfo), sizeof(struct status_info)))
148 {
149 display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
150 display->fillrect(0,0,display->width,8);
151 display->set_drawmode(DRMODE_SOLID);
152
153#else
154
155 /* players always "redraw" */
156 {
157#endif
158
159#ifdef HAVE_CHARGING
160 if (bar->info.inserted) {
161 battery_state = true;
162#if defined(HAVE_CHARGE_CTRL) || CONFIG_BATTERY == BATT_LIION2200
163 /* zero battery run time if charging */
164 if (charge_state > 0) {
165 global_settings.runtime = 0;
166 lasttime = current_tick;
167 }
168
169 /* animate battery if charging */
170 if ((charge_state == 1) ||
171 (charge_state == 2)) {
172#else
173 global_settings.runtime = 0;
174 lasttime = current_tick;
175 {
176#endif
177 /* animate in three steps (34% per step for a better look) */
178 bar->info.battlevel = bar->battery_charge_step * 34;
179 if (bar->info.battlevel > 100)
180 bar->info.battlevel = 100;
181 if(TIME_AFTER(current_tick, bar->battery_icon_switch_tick)) {
182 bar->battery_charge_step=(bar->battery_charge_step+1)%4;
183 bar->battery_icon_switch_tick = current_tick + HZ;
184 }
185 }
186 }
187 else
188#endif /* HAVE_CHARGING */
189 {
190 if (bar->info.battery_safe)
191 battery_state = true;
192 else {
193 /* blink battery if level is low */
194 if(TIME_AFTER(current_tick, bar->battery_icon_switch_tick) &&
195 (bar->info.battlevel > -1)) {
196 bar->battery_icon_switch_tick = current_tick+HZ;
197 battery_state = !battery_state;
198 }
199 }
200 }
201#ifdef HAVE_LCD_BITMAP
202 if (battery_state)
203 gui_statusbar_icon_battery(display, bar->info.battlevel);
204 /* draw power plug if charging */
205 if (bar->info.inserted)
206 display->mono_bitmap(bitmap_icons_7x8[Icon_Plug],
207 STATUSBAR_PLUG_X_POS,
208 STATUSBAR_Y_POS, STATUSBAR_PLUG_WIDTH,
209 STATUSBAR_HEIGHT);
210#ifdef HAVE_USB_POWER
211 else if (bar->info.usb_power)
212 display->mono_bitmap(bitmap_icons_7x8[Icon_USBPlug],
213 STATUSBAR_PLUG_X_POS,
214 STATUSBAR_Y_POS, STATUSBAR_PLUG_WIDTH,
215 STATUSBAR_HEIGHT);
216#endif
217
218 bar->info.redraw_volume = gui_statusbar_icon_volume(bar,
219 bar->info.volume);
220 gui_statusbar_icon_play_state(display, current_playmode() +
221 Icon_Play);
222 switch (bar->info.repeat) {
223#ifdef AB_REPEAT_ENABLE
224 case REPEAT_AB:
225 gui_statusbar_icon_play_mode(display, Icon_RepeatAB);
226 break;
227#endif
228
229 case REPEAT_ONE:
230 gui_statusbar_icon_play_mode(display, Icon_RepeatOne);
231 break;
232
233 case REPEAT_ALL:
234 case REPEAT_SHUFFLE:
235 gui_statusbar_icon_play_mode(display, Icon_Repeat);
236 break;
237 }
238 if (bar->info.shuffle)
239 gui_statusbar_icon_shuffle(display);
240 if (bar->info.keylock)
241 gui_statusbar_icon_lock(display);
242#ifdef HAVE_RTC
243 gui_statusbar_time(display, bar->info.hour, bar->info.minute);
244#endif
245#if CONFIG_LED == LED_VIRTUAL
246 if (bar->info.led)
247 statusbar_led();
248#endif
249 display->update_rect(0, 0, display->width, STATUSBAR_HEIGHT);
250 bar->lastinfo = bar->info;
251#endif
252 }
253
254
255#ifndef HAVE_LCD_BITMAP
256 if (bar->info.battlevel > -1)
257 display->icon(ICON_BATTERY, battery_state);
258 display->icon(ICON_BATTERY_1, bar->info.battlevel > 25);
259 display->icon(ICON_BATTERY_2, bar->info.battlevel > 50);
260 display->icon(ICON_BATTERY_3, bar->info.battlevel > 75);
261
262 display->icon(ICON_VOLUME, true);
263 display->icon(ICON_VOLUME_1, bar->info.volume > 10);
264 display->icon(ICON_VOLUME_2, bar->info.volume > 30);
265 display->icon(ICON_VOLUME_3, bar->info.volume > 50);
266 display->icon(ICON_VOLUME_4, bar->info.volume > 70);
267 display->icon(ICON_VOLUME_5, bar->info.volume > 90);
268
269 display->icon(ICON_PLAY, current_playmode() == STATUS_PLAY);
270 display->icon(ICON_PAUSE, current_playmode() == STATUS_PAUSE);
271
272 display->icon(ICON_REPEAT, global_settings.repeat_mode != REPEAT_OFF);
273 display->icon(ICON_1, global_settings.repeat_mode == REPEAT_ONE);
274
275 display->icon(ICON_RECORD, record);
276 display->icon(ICON_AUDIO, audio);
277 display->icon(ICON_PARAM, param);
278 display->icon(ICON_USB, usb);
279#endif
280}
281
282#ifdef HAVE_LCD_BITMAP
283/* from icon.c */
284/*
285 * Print battery icon to status bar
286 */
287void gui_statusbar_icon_battery(struct screen * display, int percent)
288{
289 int fill;
290 char buffer[5];
291 unsigned int width, height;
292
293 /* fill battery */
294 fill = percent;
295 if (fill < 0)
296 fill = 0;
297 if (fill > 100)
298 fill = 100;
299
300#if defined(HAVE_CHARGE_CTRL) && !defined(SIMULATOR) /* Rec v1 target only */
301 /* show graphical animation when charging instead of numbers */
302 if ((global_settings.battery_display) &&
303 (charge_state != 1) &&
304 (percent > -1)) {
305#else /* all others */
306 if (global_settings.battery_display && (percent > -1)) {
307#endif
308 /* Numeric display */
309 display->setfont(FONT_SYSFIXED);
310 snprintf(buffer, sizeof(buffer), "%3d", fill);
311 display->getstringsize(buffer, &width, &height);
312 if (height <= STATUSBAR_HEIGHT)
313 display->putsxy(STATUSBAR_BATTERY_X_POS
314 + STATUSBAR_BATTERY_WIDTH / 2
315 - width/2, STATUSBAR_Y_POS, buffer);
316 display->setfont(FONT_UI);
317
318 }
319 else {
320 /* draw battery */
321 display->drawrect(STATUSBAR_BATTERY_X_POS, STATUSBAR_Y_POS, 17, 7);
322 display->vline(STATUSBAR_BATTERY_X_POS + 17, STATUSBAR_Y_POS + 2,
323 STATUSBAR_Y_POS + 4);
324
325 fill = fill * 15 / 100;
326 display->fillrect(STATUSBAR_BATTERY_X_POS + 1, STATUSBAR_Y_POS + 1,
327 fill, 5);
328 }
329
330 if (percent == -1) {
331 display->setfont(FONT_SYSFIXED);
332 display->putsxy(STATUSBAR_BATTERY_X_POS + STATUSBAR_BATTERY_WIDTH / 2
333 - 4, STATUSBAR_Y_POS, "?");
334 display->setfont(FONT_UI);
335 }
336}
337
338/*
339 * Print volume gauge to status bar
340 */
341bool gui_statusbar_icon_volume(struct gui_statusbar * bar, int percent)
342{
343 int i;
344 int volume;
345 int vol;
346 char buffer[4];
347 unsigned int width, height;
348 bool needs_redraw = false;
349 int type = global_settings.volume_type;
350 struct screen * display=bar->display;
351
352 volume = percent;
353 if (volume < 0)
354 volume = 0;
355 if (volume > 100)
356 volume = 100;
357
358 if (volume == 0) {
359 display->mono_bitmap(bitmap_icons_7x8[Icon_Mute],
360 STATUSBAR_VOLUME_X_POS + STATUSBAR_VOLUME_WIDTH / 2 - 4,
361 STATUSBAR_Y_POS, 7, STATUSBAR_HEIGHT);
362 }
363 else {
364 /* We want to redraw the icon later on */
365 if (bar->last_volume != volume && bar->last_volume >= 0) {
366 bar->volume_icon_switch_tick = current_tick + HZ;
367 }
368
369 /* If the timeout hasn't yet been reached, we show it numerically
370 and tell the caller that we want to be called again */
371 if (TIME_BEFORE(current_tick,bar->volume_icon_switch_tick)) {
372 type = 1;
373 needs_redraw = true;
374 }
375
376 /* display volume level numerical? */
377 if (type)
378 {
379 display->setfont(FONT_SYSFIXED);
380 snprintf(buffer, sizeof(buffer), "%2d", percent);
381 display->getstringsize(buffer, &width, &height);
382 if (height <= STATUSBAR_HEIGHT)
383 {
384 display->putsxy(STATUSBAR_VOLUME_X_POS
385 + STATUSBAR_VOLUME_WIDTH / 2
386 - width/2, STATUSBAR_Y_POS, buffer);
387 }
388 display->setfont(FONT_UI);
389 } else {
390 /* display volume bar */
391 vol = volume * 14 / 100;
392 for(i=0; i < vol; i++) {
393 display->vline(STATUSBAR_VOLUME_X_POS + i,
394 STATUSBAR_Y_POS + 6 - i / 2,
395 STATUSBAR_Y_POS + 6);
396 }
397 }
398 }
399 bar->last_volume = volume;
400
401 return needs_redraw;
402}
403
404/*
405 * Print play state to status bar
406 */
407void gui_statusbar_icon_play_state(struct screen * display, int state)
408{
409 display->mono_bitmap(bitmap_icons_7x8[state], STATUSBAR_PLAY_STATE_X_POS,
410 STATUSBAR_Y_POS, STATUSBAR_PLAY_STATE_WIDTH,
411 STATUSBAR_HEIGHT);
412}
413
414/*
415 * Print play mode to status bar
416 */
417void gui_statusbar_icon_play_mode(struct screen * display, int mode)
418{
419 display->mono_bitmap(bitmap_icons_7x8[mode], STATUSBAR_PLAY_MODE_X_POS,
420 STATUSBAR_Y_POS, STATUSBAR_PLAY_MODE_WIDTH,
421 STATUSBAR_HEIGHT);
422}
423
424/*
425 * Print shuffle mode to status bar
426 */
427void gui_statusbar_icon_shuffle(struct screen * display)
428{
429 display->mono_bitmap(bitmap_icons_7x8[Icon_Shuffle],
430 STATUSBAR_SHUFFLE_X_POS, STATUSBAR_Y_POS,
431 STATUSBAR_SHUFFLE_WIDTH, STATUSBAR_HEIGHT);
432}
433
434/*
435 * Print lock when keys are locked
436 */
437void gui_statusbar_icon_lock(struct screen * display)
438{
439 display->mono_bitmap(bitmap_icons_5x8[Icon_Lock], STATUSBAR_LOCK_X_POS,
440 STATUSBAR_Y_POS, 5, 8);
441}
442
443#if CONFIG_LED == LED_VIRTUAL
444/*
445 * no real LED: disk activity in status bar
446 */
447void gui_statusbar_led(struct screen * display)
448{
449 display->mono_bitmap(bitmap_icon_disk, STATUSBAR_DISK_X_POS,
450 STATUSBAR_Y_POS, STATUSBAR_DISK_WIDTH(screen->width),
451 STATUSBAR_HEIGHT);
452}
453#endif
454
455
456#ifdef HAVE_RTC
457/*
458 * Print time to status bar
459 */
460void gui_statusbar_time(struct screen * display, int hour, int minute)
461{
462 unsigned char buffer[6];
463 unsigned int width, height;
464 if ( hour >= 0 &&
465 hour <= 23 &&
466 minute >= 0 &&
467 minute <= 59 ) {
468 if ( global_settings.timeformat ) { /* 12 hour clock */
469 hour %= 12;
470 if ( hour == 0 ) {
471 hour += 12;
472 }
473 }
474 snprintf(buffer, sizeof(buffer), "%02d:%02d", hour, minute);
475 }
476 else {
477 strncpy(buffer, "--:--", sizeof buffer);
478 }
479 display->setfont(FONT_SYSFIXED);
480 display->getstringsize(buffer, &width, &height);
481 if (height <= STATUSBAR_HEIGHT) {
482 display->putsxy(STATUSBAR_TIME_X_END(display->width) - width,
483 STATUSBAR_Y_POS, buffer);
484 }
485 display->setfont(FONT_UI);
486
487}
488#endif
489
490#endif /* HAVE_LCD_BITMAP */
491
492void gui_syncstatusbar_init(struct gui_syncstatusbar * bars)
493{
494 int i;
495 for(i = 0;i < NB_SCREENS;++i) {
496 gui_statusbar_init( &(bars->statusbars[i]) );
497 gui_statusbar_set_screen( &(bars->statusbars[i]), &(screens[i]) );
498 }
499}
500
501void gui_syncstatusbar_draw(struct gui_syncstatusbar * bars,
502 bool force_redraw)
503{
504 int i;
505 for(i = 0;i < NB_SCREENS;++i) {
506 gui_statusbar_draw( &(bars->statusbars[i]), force_redraw );
507 }
508}