1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) Robert E. Hak (2002), Linus Nielsen Feltzing (2002), Kevin FERRARE (2005)
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.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
21 #include "screen_access.h"
25 #include "string.h" /* for memcmp oO*/
31 #include "powermgmt.h"
36 #include "status.h" /* needed for battery_state global var */
37 #include "wps.h" /* for keys_locked */
38 #include "statusbar.h"
41 /* FIXME: should be removed from icon.h to avoid redefinition,
42 but still needed for compatibility with old system */
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 + \
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 + \
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 + \
81 #define STATUSBAR_LOCK_WIDTH 5
82 #define STATUSBAR_DISK_WIDTH 12
83 #define STATUSBAR_DISK_X_POS(statusbar_width) statusbar_width - \
85 #define STATUSBAR_TIME_X_END(statusbar_width) statusbar_width-1
87 void gui_statusbar_init(struct gui_statusbar
* bar
)
89 bar
->last_volume
= -1; /* -1 means "first update ever" */
90 bar
->battery_icon_switch_tick
= 0;
92 bar
->battery_charge_step
= 0;
96 void gui_statusbar_set_screen(struct gui_statusbar
* bar
,
97 struct screen
* display
)
99 bar
->display
= display
;
100 gui_statusbar_draw(bar
, false);
103 void gui_statusbar_draw(struct gui_statusbar
* bar
, bool force_redraw
)
105 #ifdef HAVE_LCD_BITMAP
106 if(!global_settings
.statusbar
)
110 struct screen
* display
= bar
->display
;
113 struct tm
* tm
; /* For Time */
116 #ifdef HAVE_LCD_CHARCELLS
117 (void)force_redraw
; /* players always "redraw" */
120 bar
->info
.volume
= sound_val2phys(SOUND_VOLUME
, global_settings
.volume
);
121 bar
->info
.inserted
= charger_inserted();
122 bar
->info
.battlevel
= battery_level();
123 bar
->info
.battery_safe
= battery_level_safe();
125 #ifdef HAVE_LCD_BITMAP
128 bar
->info
.hour
= tm
->tm_hour
;
129 bar
->info
.minute
= tm
->tm_min
;
132 bar
->info
.shuffle
= global_settings
.playlist_shuffle
;
133 #if CONFIG_KEYPAD == IRIVER_H100_PAD
134 bar
->info
.keylock
= button_hold();
136 bar
->info
.keylock
= keys_locked
;
138 bar
->info
.repeat
= global_settings
.repeat_mode
;
139 bar
->info
.playmode
= current_playmode();
140 #if CONFIG_LED == LED_VIRTUAL
141 bar
->info
.led
= led_read(HZ
/2); /* delay should match polling interval */
143 #ifdef HAVE_USB_POWER
144 bar
->info
.usb_power
= usb_powered();
147 /* only redraw if forced to, or info has changed */
149 bar
->info
.inserted
||
150 !bar
->info
.battery_safe
||
151 bar
->info
.redraw_volume
||
152 memcmp(&(bar
->info
), &(bar
->lastinfo
), sizeof(struct status_info
)))
154 display
->set_drawmode(DRMODE_SOLID
|DRMODE_INVERSEVID
);
155 display
->fillrect(0,0,display
->width
,8);
156 display
->set_drawmode(DRMODE_SOLID
);
160 /* players always "redraw" */
165 if (bar
->info
.inserted
) {
166 battery_state
= true;
167 #if defined(HAVE_CHARGE_CTRL) || CONFIG_BATTERY == BATT_LIION2200
168 /* zero battery run time if charging */
169 if (charge_state
> 0) {
170 global_settings
.runtime
= 0;
171 lasttime
= current_tick
;
174 /* animate battery if charging */
175 if ((charge_state
== 1) ||
176 (charge_state
== 2)) {
178 global_settings
.runtime
= 0;
179 lasttime
= current_tick
;
182 /* animate in three steps (34% per step for a better look) */
183 bar
->info
.battlevel
= bar
->battery_charge_step
* 34;
184 if (bar
->info
.battlevel
> 100)
185 bar
->info
.battlevel
= 100;
186 if(TIME_AFTER(current_tick
, bar
->battery_icon_switch_tick
)) {
187 bar
->battery_charge_step
=(bar
->battery_charge_step
+1)%4;
188 bar
->battery_icon_switch_tick
= current_tick
+ HZ
;
193 #endif /* HAVE_CHARGING */
195 if (bar
->info
.battery_safe
)
196 battery_state
= true;
198 /* blink battery if level is low */
199 if(TIME_AFTER(current_tick
, bar
->battery_icon_switch_tick
) &&
200 (bar
->info
.battlevel
> -1)) {
201 bar
->battery_icon_switch_tick
= current_tick
+HZ
;
202 battery_state
= !battery_state
;
206 #ifdef HAVE_LCD_BITMAP
208 gui_statusbar_icon_battery(display
, bar
->info
.battlevel
);
209 /* draw power plug if charging */
210 if (bar
->info
.inserted
)
211 display
->mono_bitmap(bitmap_icons_7x8
[Icon_Plug
],
212 STATUSBAR_PLUG_X_POS
,
213 STATUSBAR_Y_POS
, STATUSBAR_PLUG_WIDTH
,
215 #ifdef HAVE_USB_POWER
216 else if (bar
->info
.usb_power
)
217 display
->mono_bitmap(bitmap_icons_7x8
[Icon_USBPlug
],
218 STATUSBAR_PLUG_X_POS
,
219 STATUSBAR_Y_POS
, STATUSBAR_PLUG_WIDTH
,
223 bar
->info
.redraw_volume
= gui_statusbar_icon_volume(bar
,
225 gui_statusbar_icon_play_state(display
, current_playmode() +
227 switch (bar
->info
.repeat
) {
228 #ifdef AB_REPEAT_ENABLE
230 gui_statusbar_icon_play_mode(display
, Icon_RepeatAB
);
235 gui_statusbar_icon_play_mode(display
, Icon_RepeatOne
);
240 gui_statusbar_icon_play_mode(display
, Icon_Repeat
);
243 if (bar
->info
.shuffle
)
244 gui_statusbar_icon_shuffle(display
);
245 if (bar
->info
.keylock
)
246 gui_statusbar_icon_lock(display
);
248 gui_statusbar_time(display
, bar
->info
.hour
, bar
->info
.minute
);
250 #if CONFIG_LED == LED_VIRTUAL
254 display
->update_rect(0, 0, display
->width
, STATUSBAR_HEIGHT
);
255 bar
->lastinfo
= bar
->info
;
260 #ifdef HAVE_LCD_CHARCELLS
261 if (bar
->info
.battlevel
> -1)
262 display
->icon(ICON_BATTERY
, battery_state
);
263 display
->icon(ICON_BATTERY_1
, bar
->info
.battlevel
> 25);
264 display
->icon(ICON_BATTERY_2
, bar
->info
.battlevel
> 50);
265 display
->icon(ICON_BATTERY_3
, bar
->info
.battlevel
> 75);
267 display
->icon(ICON_VOLUME
, true);
268 display
->icon(ICON_VOLUME_1
, bar
->info
.volume
> 10);
269 display
->icon(ICON_VOLUME_2
, bar
->info
.volume
> 30);
270 display
->icon(ICON_VOLUME_3
, bar
->info
.volume
> 50);
271 display
->icon(ICON_VOLUME_4
, bar
->info
.volume
> 70);
272 display
->icon(ICON_VOLUME_5
, bar
->info
.volume
> 90);
274 display
->icon(ICON_PLAY
, current_playmode() == STATUS_PLAY
);
275 display
->icon(ICON_PAUSE
, current_playmode() == STATUS_PAUSE
);
277 display
->icon(ICON_REPEAT
, global_settings
.repeat_mode
!= REPEAT_OFF
);
278 display
->icon(ICON_1
, global_settings
.repeat_mode
== REPEAT_ONE
);
280 display
->icon(ICON_RECORD
, record
);
281 display
->icon(ICON_AUDIO
, audio
);
282 display
->icon(ICON_PARAM
, param
);
283 display
->icon(ICON_USB
, usb
);
287 #ifdef HAVE_LCD_BITMAP
290 * Print battery icon to status bar
292 void gui_statusbar_icon_battery(struct screen
* display
, int percent
)
296 unsigned int width
, height
;
305 #if defined(HAVE_CHARGE_CTRL) && !defined(SIMULATOR) /* Rec v1 target only */
306 /* show graphical animation when charging instead of numbers */
307 if ((global_settings
.battery_display
) &&
308 (charge_state
!= 1) &&
310 #else /* all others */
311 if (global_settings
.battery_display
&& (percent
> -1)) {
313 /* Numeric display */
314 display
->setfont(FONT_SYSFIXED
);
315 snprintf(buffer
, sizeof(buffer
), "%3d", fill
);
316 display
->getstringsize(buffer
, &width
, &height
);
317 if (height
<= STATUSBAR_HEIGHT
)
318 display
->putsxy(STATUSBAR_BATTERY_X_POS
319 + STATUSBAR_BATTERY_WIDTH
/ 2
320 - width
/2, STATUSBAR_Y_POS
, buffer
);
321 display
->setfont(FONT_UI
);
326 display
->drawrect(STATUSBAR_BATTERY_X_POS
, STATUSBAR_Y_POS
, 17, 7);
327 display
->vline(STATUSBAR_BATTERY_X_POS
+ 17, STATUSBAR_Y_POS
+ 2,
328 STATUSBAR_Y_POS
+ 4);
330 fill
= fill
* 15 / 100;
331 display
->fillrect(STATUSBAR_BATTERY_X_POS
+ 1, STATUSBAR_Y_POS
+ 1,
336 display
->setfont(FONT_SYSFIXED
);
337 display
->putsxy(STATUSBAR_BATTERY_X_POS
+ STATUSBAR_BATTERY_WIDTH
/ 2
338 - 4, STATUSBAR_Y_POS
, "?");
339 display
->setfont(FONT_UI
);
344 * Print volume gauge to status bar
346 bool gui_statusbar_icon_volume(struct gui_statusbar
* bar
, int percent
)
352 unsigned int width
, height
;
353 bool needs_redraw
= false;
354 int type
= global_settings
.volume_type
;
355 struct screen
* display
=bar
->display
;
364 display
->mono_bitmap(bitmap_icons_7x8
[Icon_Mute
],
365 STATUSBAR_VOLUME_X_POS
+ STATUSBAR_VOLUME_WIDTH
/ 2 - 4,
366 STATUSBAR_Y_POS
, 7, STATUSBAR_HEIGHT
);
369 /* We want to redraw the icon later on */
370 if (bar
->last_volume
!= volume
&& bar
->last_volume
>= 0) {
371 bar
->volume_icon_switch_tick
= current_tick
+ HZ
;
374 /* If the timeout hasn't yet been reached, we show it numerically
375 and tell the caller that we want to be called again */
376 if (TIME_BEFORE(current_tick
,bar
->volume_icon_switch_tick
)) {
381 /* display volume level numerical? */
384 display
->setfont(FONT_SYSFIXED
);
385 snprintf(buffer
, sizeof(buffer
), "%2d", percent
);
386 display
->getstringsize(buffer
, &width
, &height
);
387 if (height
<= STATUSBAR_HEIGHT
)
389 display
->putsxy(STATUSBAR_VOLUME_X_POS
390 + STATUSBAR_VOLUME_WIDTH
/ 2
391 - width
/2, STATUSBAR_Y_POS
, buffer
);
393 display
->setfont(FONT_UI
);
395 /* display volume bar */
396 vol
= volume
* 14 / 100;
397 for(i
=0; i
< vol
; i
++) {
398 display
->vline(STATUSBAR_VOLUME_X_POS
+ i
,
399 STATUSBAR_Y_POS
+ 6 - i
/ 2,
400 STATUSBAR_Y_POS
+ 6);
404 bar
->last_volume
= volume
;
410 * Print play state to status bar
412 void gui_statusbar_icon_play_state(struct screen
* display
, int state
)
414 display
->mono_bitmap(bitmap_icons_7x8
[state
], STATUSBAR_PLAY_STATE_X_POS
,
415 STATUSBAR_Y_POS
, STATUSBAR_PLAY_STATE_WIDTH
,
420 * Print play mode to status bar
422 void gui_statusbar_icon_play_mode(struct screen
* display
, int mode
)
424 display
->mono_bitmap(bitmap_icons_7x8
[mode
], STATUSBAR_PLAY_MODE_X_POS
,
425 STATUSBAR_Y_POS
, STATUSBAR_PLAY_MODE_WIDTH
,
430 * Print shuffle mode to status bar
432 void gui_statusbar_icon_shuffle(struct screen
* display
)
434 display
->mono_bitmap(bitmap_icons_7x8
[Icon_Shuffle
],
435 STATUSBAR_SHUFFLE_X_POS
, STATUSBAR_Y_POS
,
436 STATUSBAR_SHUFFLE_WIDTH
, STATUSBAR_HEIGHT
);
440 * Print lock when keys are locked
442 void gui_statusbar_icon_lock(struct screen
* display
)
444 display
->mono_bitmap(bitmap_icons_5x8
[Icon_Lock
], STATUSBAR_LOCK_X_POS
,
445 STATUSBAR_Y_POS
, 5, 8);
448 #if CONFIG_LED == LED_VIRTUAL
450 * no real LED: disk activity in status bar
452 void gui_statusbar_led(struct screen
* display
)
454 display
->mono_bitmap(bitmap_icon_disk
,
455 STATUSBAR_DISK_X_POS(display
->width
),
456 STATUSBAR_Y_POS
, STATUSBAR_DISK_WIDTH
,
464 * Print time to status bar
466 void gui_statusbar_time(struct screen
* display
, int hour
, int minute
)
468 unsigned char buffer
[6];
469 unsigned int width
, height
;
474 if ( global_settings
.timeformat
) { /* 12 hour clock */
480 snprintf(buffer
, sizeof(buffer
), "%02d:%02d", hour
, minute
);
483 strncpy(buffer
, "--:--", sizeof buffer
);
485 display
->setfont(FONT_SYSFIXED
);
486 display
->getstringsize(buffer
, &width
, &height
);
487 if (height
<= STATUSBAR_HEIGHT
) {
488 display
->putsxy(STATUSBAR_TIME_X_END(display
->width
) - width
,
489 STATUSBAR_Y_POS
, buffer
);
491 display
->setfont(FONT_UI
);
496 #endif /* HAVE_LCD_BITMAP */
498 void gui_syncstatusbar_init(struct gui_syncstatusbar
* bars
)
501 for(i
= 0;i
< NB_SCREENS
;i
++) {
502 gui_statusbar_init( &(bars
->statusbars
[i
]) );
503 gui_statusbar_set_screen( &(bars
->statusbars
[i
]), &(screens
[i
]) );
507 void gui_syncstatusbar_draw(struct gui_syncstatusbar
* bars
,
511 for(i
= 0;i
< NB_SCREENS
;i
++) {
512 gui_statusbar_draw( &(bars
->statusbars
[i
]), force_redraw
);