Some changes to the remote code : some one lines function turned into macros ; change...
[Rockbox.git] / apps / gui / statusbar.c
blob0f24208d331fc5e21fc17ab2085cd8ec009616b4
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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 ****************************************************************************/
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 #include "usb.h"
34 #include "led.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 + \
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
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;
91 #ifdef HAVE_CHARGING
92 bar->battery_charge_step = 0;
93 #endif
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)
107 return;
108 #endif
110 struct screen * display = bar->display;
112 #ifdef HAVE_RTC
113 struct tm* tm; /* For Time */
114 #endif
116 #ifdef HAVE_LCD_CHARCELLS
117 (void)force_redraw; /* players always "redraw" */
118 #endif
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
126 #ifdef HAVE_RTC
127 tm = get_time();
128 bar->info.hour = tm->tm_hour;
129 bar->info.minute = tm->tm_min;
130 #endif
132 bar->info.shuffle = global_settings.playlist_shuffle;
133 #if CONFIG_KEYPAD == IRIVER_H100_PAD
134 bar->info.keylock = button_hold();
135 #else
136 bar->info.keylock = keys_locked;
137 #endif
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 */
142 #endif
143 #ifdef HAVE_USB_POWER
144 bar->info.usb_power = usb_powered();
145 #endif
147 /* only redraw if forced to, or info has changed */
148 if (force_redraw ||
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);
158 #else
160 /* players always "redraw" */
162 #endif
164 #ifdef HAVE_CHARGING
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)) {
177 #else
178 global_settings.runtime = 0;
179 lasttime = current_tick;
181 #endif
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;
192 else
193 #endif /* HAVE_CHARGING */
195 if (bar->info.battery_safe)
196 battery_state = true;
197 else {
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
207 if (battery_state)
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,
214 STATUSBAR_HEIGHT);
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,
220 STATUSBAR_HEIGHT);
221 #endif
223 bar->info.redraw_volume = gui_statusbar_icon_volume(bar,
224 bar->info.volume);
225 gui_statusbar_icon_play_state(display, current_playmode() +
226 Icon_Play);
227 switch (bar->info.repeat) {
228 #ifdef AB_REPEAT_ENABLE
229 case REPEAT_AB:
230 gui_statusbar_icon_play_mode(display, Icon_RepeatAB);
231 break;
232 #endif
234 case REPEAT_ONE:
235 gui_statusbar_icon_play_mode(display, Icon_RepeatOne);
236 break;
238 case REPEAT_ALL:
239 case REPEAT_SHUFFLE:
240 gui_statusbar_icon_play_mode(display, Icon_Repeat);
241 break;
243 if (bar->info.shuffle)
244 gui_statusbar_icon_shuffle(display);
245 if (bar->info.keylock)
246 gui_statusbar_icon_lock(display);
247 #ifdef HAVE_RTC
248 gui_statusbar_time(display, bar->info.hour, bar->info.minute);
249 #endif
250 #if CONFIG_LED == LED_VIRTUAL
251 if (bar->info.led)
252 statusbar_led();
253 #endif
254 display->update_rect(0, 0, display->width, STATUSBAR_HEIGHT);
255 bar->lastinfo = bar->info;
256 #endif
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);
284 #endif
287 #ifdef HAVE_LCD_BITMAP
288 /* from icon.c */
290 * Print battery icon to status bar
292 void gui_statusbar_icon_battery(struct screen * display, int percent)
294 int fill;
295 char buffer[5];
296 unsigned int width, height;
298 /* fill battery */
299 fill = percent;
300 if (fill < 0)
301 fill = 0;
302 if (fill > 100)
303 fill = 100;
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) &&
309 (percent > -1)) {
310 #else /* all others */
311 if (global_settings.battery_display && (percent > -1)) {
312 #endif
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);
324 else {
325 /* draw battery */
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,
332 fill, 5);
335 if (percent == -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)
348 int i;
349 int volume;
350 int vol;
351 char buffer[4];
352 unsigned int width, height;
353 bool needs_redraw = false;
354 int type = global_settings.volume_type;
355 struct screen * display=bar->display;
357 volume = percent;
358 if (volume < 0)
359 volume = 0;
360 if (volume > 100)
361 volume = 100;
363 if (volume == 0) {
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);
368 else {
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)) {
377 type = 1;
378 needs_redraw = true;
381 /* display volume level numerical? */
382 if (type)
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);
394 } else {
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;
406 return needs_redraw;
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,
416 STATUSBAR_HEIGHT);
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,
426 STATUSBAR_HEIGHT);
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,
457 STATUSBAR_HEIGHT);
459 #endif
462 #ifdef HAVE_RTC
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;
470 if ( hour >= 0 &&
471 hour <= 23 &&
472 minute >= 0 &&
473 minute <= 59 ) {
474 if ( global_settings.timeformat ) { /* 12 hour clock */
475 hour %= 12;
476 if ( hour == 0 ) {
477 hour += 12;
480 snprintf(buffer, sizeof(buffer), "%02d:%02d", hour, minute);
482 else {
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);
494 #endif
496 #endif /* HAVE_LCD_BITMAP */
498 void gui_syncstatusbar_init(struct gui_syncstatusbar * bars)
500 int i;
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,
508 bool force_redraw)
510 int i;
511 for(i = 0;i < NB_SCREENS;i++) {
512 gui_statusbar_draw( &(bars->statusbars[i]), force_redraw );