Fix redraw issues when the statusbar setting was changed with an UI viewport. Now...
[kugel-rb.git] / apps / gui / statusbar.c
blob1a724406ef9458bc3452ea6f16eceaea6e368189
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) Robert E. Hak (2002), Linus Nielsen Feltzing (2002)
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.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "screen_access.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 "settings.h"
29 #include "viewport.h"
30 #if CONFIG_CODEC == SWCODEC
31 #include "metadata.h"
32 #endif
33 #include "icons.h"
34 #include "powermgmt.h"
35 #include "usb.h"
36 #include "led.h"
37 #include "screen_access.h"
39 #include "status.h" /* needed for battery_state global var */
40 #include "action.h" /* for keys_locked */
41 #include "statusbar.h"
42 #ifdef HAVE_RECORDING
43 #include "audio.h"
44 #include "recording.h"
45 #include "pcm_record.h"
46 #endif
47 #include "appevents.h"
48 #include "timefuncs.h"
50 /* FIXME: should be removed from icon.h to avoid redefinition,
51 but still needed for compatibility with old system */
52 #define ICONS_SPACING 2
53 #define STATUSBAR_BATTERY_X_POS 0*ICONS_SPACING
54 #define STATUSBAR_BATTERY_WIDTH 18
55 #define STATUSBAR_PLUG_X_POS STATUSBAR_X_POS + \
56 STATUSBAR_BATTERY_WIDTH + \
57 ICONS_SPACING
58 #define STATUSBAR_PLUG_WIDTH 7
59 #define STATUSBAR_VOLUME_X_POS STATUSBAR_X_POS + \
60 STATUSBAR_BATTERY_WIDTH + \
61 STATUSBAR_PLUG_WIDTH + \
62 2*ICONS_SPACING
63 #define STATUSBAR_VOLUME_WIDTH 16
64 #define STATUSBAR_ENCODER_X_POS STATUSBAR_X_POS + \
65 STATUSBAR_BATTERY_WIDTH + \
66 STATUSBAR_PLUG_WIDTH + \
67 2*ICONS_SPACING - 1
68 #define STATUSBAR_ENCODER_WIDTH 18
69 #define STATUSBAR_PLAY_STATE_X_POS STATUSBAR_X_POS + \
70 STATUSBAR_BATTERY_WIDTH + \
71 STATUSBAR_PLUG_WIDTH + \
72 STATUSBAR_VOLUME_WIDTH + \
73 3*ICONS_SPACING
74 #define STATUSBAR_PLAY_STATE_WIDTH 7
75 #define STATUSBAR_PLAY_MODE_X_POS STATUSBAR_X_POS + \
76 STATUSBAR_BATTERY_WIDTH + \
77 STATUSBAR_PLUG_WIDTH + \
78 STATUSBAR_VOLUME_WIDTH + \
79 STATUSBAR_PLAY_STATE_WIDTH + \
80 4*ICONS_SPACING
81 #define STATUSBAR_PLAY_MODE_WIDTH 7
82 #define STATUSBAR_RECFREQ_X_POS STATUSBAR_X_POS + \
83 STATUSBAR_BATTERY_WIDTH + \
84 STATUSBAR_PLUG_WIDTH + \
85 STATUSBAR_VOLUME_WIDTH + \
86 STATUSBAR_PLAY_STATE_WIDTH + \
87 3*ICONS_SPACING
88 #define STATUSBAR_RECFREQ_WIDTH 12
89 #define STATUSBAR_RECCHANNELS_X_POS STATUSBAR_X_POS + \
90 STATUSBAR_BATTERY_WIDTH + \
91 STATUSBAR_PLUG_WIDTH + \
92 STATUSBAR_VOLUME_WIDTH + \
93 STATUSBAR_PLAY_STATE_WIDTH + \
94 STATUSBAR_RECFREQ_WIDTH + \
95 4*ICONS_SPACING
96 #define STATUSBAR_RECCHANNELS_WIDTH 5
97 #define STATUSBAR_SHUFFLE_X_POS STATUSBAR_X_POS + \
98 STATUSBAR_BATTERY_WIDTH + \
99 STATUSBAR_PLUG_WIDTH + \
100 STATUSBAR_VOLUME_WIDTH + \
101 STATUSBAR_PLAY_STATE_WIDTH + \
102 STATUSBAR_PLAY_MODE_WIDTH + \
103 5*ICONS_SPACING
104 #define STATUSBAR_SHUFFLE_WIDTH 7
105 #define STATUSBAR_LOCKM_X_POS STATUSBAR_X_POS + \
106 STATUSBAR_BATTERY_WIDTH + \
107 STATUSBAR_PLUG_WIDTH + \
108 STATUSBAR_VOLUME_WIDTH + \
109 STATUSBAR_PLAY_STATE_WIDTH + \
110 STATUSBAR_PLAY_MODE_WIDTH + \
111 STATUSBAR_SHUFFLE_WIDTH + \
112 6*ICONS_SPACING
113 #define STATUSBAR_LOCKM_WIDTH 5
114 #define STATUSBAR_LOCKR_X_POS STATUSBAR_X_POS + \
115 STATUSBAR_BATTERY_WIDTH + \
116 STATUSBAR_PLUG_WIDTH + \
117 STATUSBAR_VOLUME_WIDTH + \
118 STATUSBAR_PLAY_STATE_WIDTH + \
119 STATUSBAR_PLAY_MODE_WIDTH + \
120 STATUSBAR_SHUFFLE_WIDTH + \
121 STATUSBAR_LOCKM_WIDTH + \
122 7*ICONS_SPACING
123 #define STATUSBAR_LOCKR_WIDTH 5
125 #if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
126 #define STATUSBAR_DISK_WIDTH 12
127 #define STATUSBAR_DISK_X_POS(statusbar_width) statusbar_width - \
128 STATUSBAR_DISK_WIDTH
129 #else
130 #define STATUSBAR_DISK_WIDTH 0
131 #endif
132 #define STATUSBAR_TIME_X_END(statusbar_width) statusbar_width - 1 - \
133 STATUSBAR_DISK_WIDTH
134 struct gui_syncstatusbar statusbars;
136 /* Prototypes */
137 #ifdef HAVE_LCD_BITMAP
138 static void gui_statusbar_icon_battery(struct screen * display, int percent,
139 int batt_charge_step);
140 static bool gui_statusbar_icon_volume(struct gui_statusbar * bar, int volume);
141 static void gui_statusbar_icon_play_state(struct screen * display, int state);
142 static void gui_statusbar_icon_play_mode(struct screen * display, int mode);
143 static void gui_statusbar_icon_shuffle(struct screen * display);
144 static void gui_statusbar_icon_lock(struct screen * display);
145 #ifdef HAS_REMOTE_BUTTON_HOLD
146 static void gui_statusbar_icon_lock_remote(struct screen * display);
147 #endif
148 #if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
149 static void gui_statusbar_led(struct screen * display);
150 #endif
151 #ifdef HAVE_RECORDING
152 static void gui_statusbar_icon_recording_info(struct screen * display);
153 #endif
154 #if CONFIG_RTC
155 static void gui_statusbar_time(struct screen * display, struct tm *time);
156 #endif
157 #endif
159 /* End prototypes */
163 * Initializes a status bar
164 * - bar : the bar to initialize
166 static void gui_statusbar_init(struct gui_statusbar * bar)
168 bar->redraw_volume = true;
169 bar->volume_icon_switch_tick = bar->battery_icon_switch_tick = current_tick;
170 memset((void*)&(bar->lastinfo), 0, sizeof(struct status_info));
171 #if CONFIG_RTC
172 bar->last_tm_min = 0;
173 #endif
176 #define GET_RECT(vp, vals,display) do { \
177 viewport_set_fullscreen(&(vp), (display)->screen_type); \
178 (vp).height = STATUSBAR_HEIGHT; \
179 (vp).x = STATUSBAR_X_POS; \
180 if ((vals) != STATUSBAR_BOTTOM) \
181 (vp).y = 0; \
182 else \
183 (vp).y = (display)->lcdheight - STATUSBAR_HEIGHT; \
184 } while(0)
186 void gui_statusbar_draw(struct gui_statusbar * bar, bool force_redraw)
188 struct screen * display = bar->display;
190 #ifdef HAVE_LCD_CHARCELLS
191 int val;
192 (void)force_redraw; /* The Player always has "redraw" */
193 #endif /* HAVE_LCD_CHARCELLS */
195 bar->info.battlevel = battery_level();
196 #ifdef HAVE_USB_POWER
197 bar->info.usb_inserted = usb_inserted();
198 #endif
199 #if CONFIG_CHARGING
200 bar->info.inserted = (charger_input_state == CHARGER);
201 if (bar->info.inserted)
203 bar->info.battery_state = true;
205 #if CONFIG_CHARGING >= CHARGING_MONITOR
207 /* zero battery run time if charging */
208 if (charge_state > DISCHARGING)
209 lasttime = current_tick;
211 /* animate battery if charging */
212 if ((charge_state == DISCHARGING) || (charge_state == TRICKLE))
214 bar->info.batt_charge_step = -1;
216 else
218 #else /* CONFIG_CHARGING < CHARGING_MONITOR */
219 lasttime = current_tick;
221 #endif /* CONFIG_CHARGING < CHARGING_MONITOR */
222 /* animate in (max.) 4 steps, starting near the current charge level */
223 if (TIME_AFTER(current_tick, bar->battery_icon_switch_tick))
225 if (++bar->info.batt_charge_step > 3)
226 bar->info.batt_charge_step = bar->info.battlevel / 34;
227 bar->battery_icon_switch_tick = current_tick + HZ;
231 else
232 #endif /* CONFIG_CHARGING */
234 bar->info.batt_charge_step = -1;
235 if (battery_level_safe())
236 bar->info.battery_state = true;
237 else
238 /* blink battery if level is low */
239 if (TIME_AFTER(current_tick, bar->battery_icon_switch_tick) &&
240 (bar->info.battlevel > -1))
242 bar->info.battery_state = !bar->info.battery_state;
243 bar->battery_icon_switch_tick = current_tick + HZ;
247 bar->info.volume = global_settings.volume;
248 #ifdef HAVE_LCD_BITMAP
249 bar->info.shuffle = global_settings.playlist_shuffle;
250 #ifdef HAS_BUTTON_HOLD
251 bar->info.keylock = button_hold();
252 #else
253 bar->info.keylock = is_keys_locked();
254 #endif /* HAS_BUTTON_HOLD */
255 #ifdef HAS_REMOTE_BUTTON_HOLD
256 bar->info.keylockremote = remote_button_hold();
257 #endif
258 bar->info.repeat = global_settings.repeat_mode;
259 bar->info.playmode = current_playmode();
261 #if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
262 if(!display->has_disk_led)
263 bar->info.led = led_read(HZ/2); /* delay should match polling interval */
264 #endif
265 #if CONFIG_RTC
266 bar->time = get_time();
267 #endif /* CONFIG_RTC */
269 /* only redraw if forced to, or info has changed */
270 if (force_redraw || bar->redraw_volume ||
271 #if CONFIG_RTC
272 (bar->time->tm_min != bar->last_tm_min) ||
273 #endif
274 memcmp(&(bar->info), &(bar->lastinfo), sizeof(struct status_info)))
276 struct viewport vp;
278 GET_RECT(vp,statusbar_position(display->screen_type),display);
279 display->set_viewport(&vp);
280 display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
281 display->fillrect(0, 0, display->getwidth(), STATUSBAR_HEIGHT);
282 display->set_drawmode(DRMODE_SOLID);
284 if (bar->info.battery_state)
285 gui_statusbar_icon_battery(display, bar->info.battlevel,
286 bar->info.batt_charge_step);
287 #ifdef HAVE_USB_POWER
288 if (bar->info.usb_inserted)
289 display->mono_bitmap(bitmap_icons_7x8[Icon_USBPlug],
290 STATUSBAR_PLUG_X_POS,
291 STATUSBAR_Y_POS, STATUSBAR_PLUG_WIDTH,
292 STATUSBAR_HEIGHT);
293 #endif /* HAVE_USB_POWER */
294 #if CONFIG_CHARGING
295 #ifdef HAVE_USB_POWER
296 else
297 #endif
298 /* draw power plug if charging */
299 if (bar->info.inserted)
300 display->mono_bitmap(bitmap_icons_7x8[Icon_Plug],
301 STATUSBAR_PLUG_X_POS,
302 STATUSBAR_Y_POS, STATUSBAR_PLUG_WIDTH,
303 STATUSBAR_HEIGHT);
304 #endif /* CONFIG_CHARGING */
305 #ifdef HAVE_RECORDING
306 /* turn off volume display in recording screen */
307 bool recscreen_on = in_recording_screen();
308 if (!recscreen_on)
309 #endif
310 bar->redraw_volume = gui_statusbar_icon_volume(bar, bar->info.volume);
311 gui_statusbar_icon_play_state(display, current_playmode() + Icon_Play);
313 #ifdef HAVE_RECORDING
314 /* If in recording screen, replace repeat mode, volume
315 and shuffle icons with recording info */
316 if (recscreen_on)
317 gui_statusbar_icon_recording_info(display);
318 else
319 #endif
321 switch (bar->info.repeat) {
322 #ifdef AB_REPEAT_ENABLE
323 case REPEAT_AB:
324 gui_statusbar_icon_play_mode(display, Icon_RepeatAB);
325 break;
326 #endif /* AB_REPEAT_ENABLE == 1 */
328 case REPEAT_ONE:
329 gui_statusbar_icon_play_mode(display, Icon_RepeatOne);
330 break;
332 case REPEAT_ALL:
333 case REPEAT_SHUFFLE:
334 gui_statusbar_icon_play_mode(display, Icon_Repeat);
335 break;
337 if (bar->info.shuffle)
338 gui_statusbar_icon_shuffle(display);
340 if (bar->info.keylock)
341 gui_statusbar_icon_lock(display);
342 #ifdef HAS_REMOTE_BUTTON_HOLD
343 if (bar->info.keylockremote)
344 gui_statusbar_icon_lock_remote(display);
345 #endif
346 #if CONFIG_RTC
347 gui_statusbar_time(display, bar->time);
348 bar->last_tm_min = bar->time->tm_min;
349 #endif /* CONFIG_RTC */
350 #if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
351 if(!display->has_disk_led && bar->info.led)
352 gui_statusbar_led(display);
353 #endif
354 display->update_viewport();
355 display->set_viewport(NULL);
356 bar->lastinfo = bar->info;
358 #endif /* HAVE_LCD_BITMAP */
361 #ifdef HAVE_LCD_CHARCELLS
362 display->icon(ICON_BATTERY, bar->info.battery_state);
364 if (bar->info.batt_charge_step > -1)
365 val = bar->info.batt_charge_step;
366 else
367 val = (bar->info.battlevel * 3 + 50) / 100;
368 display->icon(ICON_BATTERY_1, val >= 1);
369 display->icon(ICON_BATTERY_2, val >= 2);
370 display->icon(ICON_BATTERY_3, val >= 3);
372 val = 10 * (bar->info.volume - sound_min(SOUND_VOLUME))
373 / (sound_max(SOUND_VOLUME) - sound_min(SOUND_VOLUME));
374 display->icon(ICON_VOLUME, true);
375 display->icon(ICON_VOLUME_1, val >= 1);
376 display->icon(ICON_VOLUME_2, val >= 3);
377 display->icon(ICON_VOLUME_3, val >= 5);
378 display->icon(ICON_VOLUME_4, val >= 7);
379 display->icon(ICON_VOLUME_5, val >= 9);
381 display->icon(ICON_PLAY, current_playmode() == STATUS_PLAY);
382 display->icon(ICON_PAUSE, current_playmode() == STATUS_PAUSE);
384 display->icon(ICON_REPEAT, global_settings.repeat_mode != REPEAT_OFF);
385 display->icon(ICON_1, global_settings.repeat_mode == REPEAT_ONE);
387 display->icon(ICON_RECORD, record);
388 display->icon(ICON_AUDIO, audio);
389 display->icon(ICON_PARAM, param);
390 display->icon(ICON_USB, usb);
391 #endif /* HAVE_LCD_CHARCELLS */
394 #ifdef HAVE_LCD_BITMAP
395 /* from icon.c */
397 * Print battery icon to status bar
399 static void gui_statusbar_icon_battery(struct screen * display, int percent,
400 int batt_charge_step)
402 int fill, endfill;
403 char buffer[5];
404 unsigned int width, height;
405 #if LCD_DEPTH > 1
406 unsigned int prevfg = 0;
407 #endif
409 #if CONFIG_CHARGING
410 if (batt_charge_step >= 0)
412 fill = percent * (STATUSBAR_BATTERY_WIDTH-3) / 100;
413 endfill = 34 * batt_charge_step * (STATUSBAR_BATTERY_WIDTH-3) / 100;
415 else
416 #else
417 (void)batt_charge_step;
418 #endif
420 fill = endfill = (percent * (STATUSBAR_BATTERY_WIDTH-3) + 50) / 100;
423 #if CONFIG_CHARGING == CHARGING_MONITOR && !defined(SIMULATOR)
424 /* Certain charge controlled targets */
425 /* show graphical animation when charging instead of numbers */
426 if ((global_settings.battery_display) &&
427 (charge_state != CHARGING) &&
428 (percent > -1)) {
429 #else /* all others */
430 if (global_settings.battery_display && (percent > -1)) {
431 #endif
432 /* Numeric display */
433 display->setfont(FONT_SYSFIXED);
434 snprintf(buffer, sizeof(buffer), "%3d", percent);
435 display->getstringsize(buffer, &width, &height);
436 if (height <= STATUSBAR_HEIGHT)
437 display->putsxy(STATUSBAR_BATTERY_X_POS
438 + STATUSBAR_BATTERY_WIDTH / 2
439 - width/2, STATUSBAR_Y_POS, buffer);
440 display->setfont(FONT_UI);
443 else {
444 /* draw battery */
445 display->drawrect(STATUSBAR_BATTERY_X_POS, STATUSBAR_Y_POS, 17, 7);
446 display->vline(STATUSBAR_BATTERY_X_POS + 17, STATUSBAR_Y_POS + 2,
447 STATUSBAR_Y_POS + 4);
449 display->fillrect(STATUSBAR_BATTERY_X_POS + 1, STATUSBAR_Y_POS + 1,
450 fill, 5);
451 #if LCD_DEPTH > 1
452 if (display->depth > 1)
454 prevfg = display->get_foreground();
455 display->set_foreground(LCD_DARKGRAY);
457 #endif
458 display->fillrect(STATUSBAR_BATTERY_X_POS + 1 + fill,
459 STATUSBAR_Y_POS + 1, endfill - fill, 5);
460 #if LCD_DEPTH > 1
461 if (display->depth > 1)
462 display->set_foreground(prevfg);
463 #endif
466 if (percent == -1) {
467 display->setfont(FONT_SYSFIXED);
468 display->putsxy(STATUSBAR_BATTERY_X_POS + STATUSBAR_BATTERY_WIDTH / 2
469 - 4, STATUSBAR_Y_POS, "?");
470 display->setfont(FONT_UI);
475 * Print volume gauge to status bar
477 static bool gui_statusbar_icon_volume(struct gui_statusbar * bar, int volume)
479 int i;
480 int vol;
481 char buffer[4];
482 unsigned int width, height;
483 bool needs_redraw = false;
484 int type = global_settings.volume_type;
485 struct screen * display=bar->display;
486 const int minvol = sound_min(SOUND_VOLUME);
487 const int maxvol = sound_max(SOUND_VOLUME);
489 if (volume < minvol)
490 volume = minvol;
491 if (volume > maxvol)
492 volume = maxvol;
494 if (volume == minvol) {
495 display->mono_bitmap(bitmap_icons_7x8[Icon_Mute],
496 STATUSBAR_VOLUME_X_POS + STATUSBAR_VOLUME_WIDTH / 2 - 4,
497 STATUSBAR_Y_POS, 7, STATUSBAR_HEIGHT);
499 else {
500 /* We want to redraw the icon later on */
501 if (bar->last_volume != volume && bar->last_volume >= minvol) {
502 bar->volume_icon_switch_tick = current_tick + HZ;
505 /* If the timeout hasn't yet been reached, we show it numerically
506 and tell the caller that we want to be called again */
507 if (TIME_BEFORE(current_tick,bar->volume_icon_switch_tick)) {
508 type = 1;
509 needs_redraw = true;
512 /* display volume level numerical? */
513 if (type)
515 display->setfont(FONT_SYSFIXED);
516 snprintf(buffer, sizeof(buffer), "%2d", volume);
517 display->getstringsize(buffer, &width, &height);
518 if (height <= STATUSBAR_HEIGHT)
520 display->putsxy(STATUSBAR_VOLUME_X_POS
521 + STATUSBAR_VOLUME_WIDTH / 2
522 - width/2, STATUSBAR_Y_POS, buffer);
524 display->setfont(FONT_UI);
525 } else {
526 /* display volume bar */
527 vol = (volume - minvol) * 14 / (maxvol - minvol);
528 for(i=0; i < vol; i++) {
529 display->vline(STATUSBAR_VOLUME_X_POS + i,
530 STATUSBAR_Y_POS + 6 - i / 2,
531 STATUSBAR_Y_POS + 6);
535 bar->last_volume = volume;
537 return needs_redraw;
541 * Print play state to status bar
543 static void gui_statusbar_icon_play_state(struct screen * display, int state)
545 display->mono_bitmap(bitmap_icons_7x8[state], STATUSBAR_PLAY_STATE_X_POS,
546 STATUSBAR_Y_POS, STATUSBAR_PLAY_STATE_WIDTH,
547 STATUSBAR_HEIGHT);
551 * Print play mode to status bar
553 static void gui_statusbar_icon_play_mode(struct screen * display, int mode)
555 display->mono_bitmap(bitmap_icons_7x8[mode], STATUSBAR_PLAY_MODE_X_POS,
556 STATUSBAR_Y_POS, STATUSBAR_PLAY_MODE_WIDTH,
557 STATUSBAR_HEIGHT);
561 * Print shuffle mode to status bar
563 static void gui_statusbar_icon_shuffle(struct screen * display)
565 display->mono_bitmap(bitmap_icons_7x8[Icon_Shuffle],
566 STATUSBAR_SHUFFLE_X_POS, STATUSBAR_Y_POS,
567 STATUSBAR_SHUFFLE_WIDTH, STATUSBAR_HEIGHT);
571 * Print lock when keys are locked
573 static void gui_statusbar_icon_lock(struct screen * display)
575 display->mono_bitmap(bitmap_icons_5x8[Icon_Lock_Main],
576 STATUSBAR_LOCKM_X_POS, STATUSBAR_Y_POS,
577 STATUSBAR_LOCKM_WIDTH, STATUSBAR_HEIGHT);
580 #ifdef HAS_REMOTE_BUTTON_HOLD
582 * Print remote lock when remote hold is enabled
584 static void gui_statusbar_icon_lock_remote(struct screen * display)
586 display->mono_bitmap(bitmap_icons_5x8[Icon_Lock_Remote],
587 STATUSBAR_LOCKR_X_POS, STATUSBAR_Y_POS,
588 STATUSBAR_LOCKR_WIDTH, STATUSBAR_HEIGHT);
590 #endif
592 #if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
594 * no real LED: disk activity in status bar
596 static void gui_statusbar_led(struct screen * display)
598 display->mono_bitmap(bitmap_icon_disk,
599 STATUSBAR_DISK_X_POS(display->getwidth()),
600 STATUSBAR_Y_POS, STATUSBAR_DISK_WIDTH,
601 STATUSBAR_HEIGHT);
603 #endif
605 #if CONFIG_RTC
607 * Print time to status bar
609 static void gui_statusbar_time(struct screen * display, struct tm *time)
611 unsigned char buffer[6];
612 unsigned int width, height;
613 int hour, minute;
614 if ( valid_time(time) ) {
615 hour = time->tm_hour;
616 minute = time->tm_min;
617 if ( global_settings.timeformat ) { /* 12 hour clock */
618 hour %= 12;
619 if ( hour == 0 ) {
620 hour += 12;
623 snprintf(buffer, sizeof(buffer), "%02d:%02d", hour, minute);
625 else {
626 strlcpy(buffer, "--:--", sizeof(buffer));
628 display->setfont(FONT_SYSFIXED);
629 display->getstringsize(buffer, &width, &height);
630 if (height <= STATUSBAR_HEIGHT) {
631 display->putsxy(STATUSBAR_TIME_X_END(display->getwidth()) - width,
632 STATUSBAR_Y_POS, buffer);
634 display->setfont(FONT_UI);
636 #endif
638 #ifdef HAVE_RECORDING
639 #if CONFIG_CODEC == SWCODEC
641 * Write a number to the display using bitmaps and return new position
643 static int write_bitmap_number(struct screen * display, int value,
644 int x, int y)
646 char buf[12], *ptr;
647 snprintf(buf, sizeof(buf), "%d", value);
649 for (ptr = buf; *ptr != '\0'; ptr++, x += BM_GLYPH_WIDTH)
650 display->mono_bitmap(bitmap_glyphs_4x8[*ptr - '0'], x, y,
651 BM_GLYPH_WIDTH, STATUSBAR_HEIGHT);
652 return x;
656 * Write format info bitmaps - right justified
658 static void gui_statusbar_write_format_info(struct screen * display)
660 /* Can't fit info for sw codec targets in statusbar using FONT_SYSFIXED
661 so must use icons */
662 int rec_format = global_settings.rec_format;
663 unsigned bitrk = 0; /* compiler warns about unitialized use !! */
664 int xpos = STATUSBAR_ENCODER_X_POS;
665 int width = STATUSBAR_ENCODER_WIDTH;
666 const unsigned char *bm = bitmap_formats_18x8[rec_format];
668 if (rec_format == REC_FORMAT_MPA_L3)
670 /* Special handling for mp3 */
671 bitrk = global_settings.mp3_enc_config.bitrate;
672 bitrk = mp3_enc_bitr[bitrk];
674 width = BM_MPA_L3_M_WIDTH;
676 /* Slide 'M' to right if fewer than three digits used */
677 if (bitrk > 999)
678 bitrk = 999; /* neurotic safety check if corrupted */
679 else
681 if (bitrk < 100)
682 xpos += BM_GLYPH_WIDTH;
683 if (bitrk < 10)
684 xpos += BM_GLYPH_WIDTH;
689 /* Show bitmap - clipping right edge if needed */
690 display->mono_bitmap_part(bm, 0, 0, STATUSBAR_ENCODER_WIDTH,
691 xpos, STATUSBAR_Y_POS, width, STATUSBAR_HEIGHT);
693 if (rec_format == REC_FORMAT_MPA_L3)
695 xpos += BM_MPA_L3_M_WIDTH; /* to right of 'M' */
696 write_bitmap_number(display, bitrk, xpos, STATUSBAR_Y_POS);
701 * Write sample rate using bitmaps - left justified
703 static void gui_statusbar_write_samplerate_info(struct screen * display)
705 unsigned long samprk;
706 int xpos;
708 #ifdef SIMULATOR
709 samprk = 44100;
710 #else
711 #ifdef HAVE_SPDIF_REC
712 if (global_settings.rec_source == AUDIO_SRC_SPDIF)
713 /* Use rate in use, not current measured rate if it changed */
714 samprk = pcm_rec_sample_rate();
715 else
716 #endif
717 samprk = rec_freq_sampr[global_settings.rec_frequency];
718 #endif /* SIMULATOR */
720 samprk /= 1000;
721 if (samprk > 99)
722 samprk = 99; /* Limit to 3 glyphs */
724 xpos = write_bitmap_number(display, (unsigned)samprk,
725 STATUSBAR_RECFREQ_X_POS, STATUSBAR_Y_POS);
727 /* write the 'k' */
728 display->mono_bitmap(bitmap_glyphs_4x8[Glyph_4x8_k], xpos,
729 STATUSBAR_Y_POS, BM_GLYPH_WIDTH,
730 STATUSBAR_HEIGHT);
732 #endif /* CONFIG_CODEC == SWCODEC */
734 static void gui_statusbar_icon_recording_info(struct screen * display)
736 #if CONFIG_CODEC != SWCODEC
737 char buffer[3];
738 int width, height;
739 display->setfont(FONT_SYSFIXED);
740 #endif /* CONFIG_CODEC != SWCODEC */
742 /* Display Codec info in statusbar */
743 #if CONFIG_CODEC == SWCODEC
744 gui_statusbar_write_format_info(display);
745 #else /* !SWCODEC */
746 display->mono_bitmap(bitmap_icons_5x8[Icon_q],
747 STATUSBAR_ENCODER_X_POS + 8, STATUSBAR_Y_POS,
748 5, STATUSBAR_HEIGHT);
750 snprintf(buffer, sizeof(buffer), "%d", global_settings.rec_quality);
751 display->getstringsize(buffer, &width, &height);
752 if (height <= STATUSBAR_HEIGHT)
753 display->putsxy(STATUSBAR_ENCODER_X_POS + 13, STATUSBAR_Y_POS, buffer);
754 #endif /* CONFIG_CODEC == SWCODEC */
756 /* Display Samplerate info in statusbar */
757 #if CONFIG_CODEC == SWCODEC
758 /* SWCODEC targets use bitmaps for glyphs */
759 gui_statusbar_write_samplerate_info(display);
760 #else /* !SWCODEC */
761 /* hwcodec targets have sysfont characters */
762 #ifdef HAVE_SPDIF_REC
763 if (global_settings.rec_source == AUDIO_SRC_SPDIF)
765 /* Can't measure S/PDIF sample rate on Archos/Sim yet */
766 strlcpy(buffer, "--", sizeof(buffer));
768 else
769 #endif /* HAVE_SPDIF_IN */
771 static char const * const freq_strings[12] =
772 { "44", "48", "32", "22", "24", "16" };
773 strlcpy(buffer, freq_strings[global_settings.rec_frequency],
774 sizeof(buffer));
777 display->getstringsize(buffer, &width, &height);
779 if (height <= STATUSBAR_HEIGHT)
780 display->putsxy(STATUSBAR_RECFREQ_X_POS, STATUSBAR_Y_POS, buffer);
782 display->setfont(FONT_UI);
783 #endif /* CONFIG_CODEC == SWCODEC */
785 /* Display Channel status in status bar */
786 if(global_settings.rec_channels)
788 display->mono_bitmap(bitmap_icons_5x8[Icon_Mono],
789 STATUSBAR_RECCHANNELS_X_POS , STATUSBAR_Y_POS,
790 STATUSBAR_RECCHANNELS_WIDTH, STATUSBAR_HEIGHT);
792 else
794 display->mono_bitmap(bitmap_icons_5x8[Icon_Stereo],
795 STATUSBAR_RECCHANNELS_X_POS, STATUSBAR_Y_POS,
796 STATUSBAR_RECCHANNELS_WIDTH, STATUSBAR_HEIGHT);
799 #endif /* HAVE_RECORDING */
801 #endif /* HAVE_LCD_BITMAP */
803 void gui_syncstatusbar_init(struct gui_syncstatusbar * bars)
805 int i;
806 FOR_NB_SCREENS(i) {
807 gui_statusbar_init( &(bars->statusbars[i]) );
808 gui_statusbar_set_screen( &(bars->statusbars[i]), &(screens[i]) );
812 void gui_syncstatusbar_draw(struct gui_syncstatusbar * bars,
813 bool force_redraw)
815 #ifdef HAVE_LCD_BITMAP
816 if(!global_settings.statusbar)
817 return;
818 #endif /* HAVE_LCD_BITMAP */
819 int i;
820 FOR_NB_SCREENS(i) {
821 gui_statusbar_draw( &(bars->statusbars[i]), force_redraw );
825 #ifdef HAVE_LCD_BITMAP
826 void gui_statusbar_changed( enum screen_type screen,
827 enum statusbar_values old)
829 /* clear and update the statusbar area to remove old parts */
830 enum statusbar_values bar;
831 #ifdef HAVE_REMOTE_LCD
832 if (screen == SCREEN_REMOTE)
833 bar = global_settings.remote_statusbar;
834 else
835 #endif
836 bar = global_settings.statusbar;
838 struct screen *display = &screens[screen];
839 struct viewport vp;
841 if (old != STATUSBAR_OFF && old != bar)
843 GET_RECT(vp, old, display);
844 display->set_viewport(&vp);
845 display->clear_viewport();
846 display->update_viewport();
847 display->set_viewport(NULL);
850 #endif
852 #ifdef HAVE_REMOTE_LCD
853 int statusbar_position(int screen)
855 if (screen == SCREEN_REMOTE)
856 return global_settings.remote_statusbar;
857 return global_settings.statusbar;
859 #endif