implement smooth seeking acceleration for audio playback and mpegplayer
[Rockbox.git] / apps / gui / statusbar.c
blob436e3d6ccac535d783abb05ae3a5f02d719ccbec
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 * 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 "screen_access.h"
21 #include "font.h"
22 #include "kernel.h"
23 #include "string.h" /* for memcmp oO*/
24 #include "sprintf.h"
25 #include "sound.h"
26 #include "settings.h"
27 #include "icons.h"
28 #include "powermgmt.h"
29 #include "usb.h"
30 #include "led.h"
32 #include "status.h" /* needed for battery_state global var */
33 #include "action.h" /* for keys_locked */
34 #include "statusbar.h"
35 #ifdef HAVE_RECORDING
36 #include "audio.h"
37 #include "recording.h"
38 #endif
40 /* FIXME: should be removed from icon.h to avoid redefinition,
41 but still needed for compatibility with old system */
42 #define ICONS_SPACING 2
43 #define STATUSBAR_BATTERY_X_POS 0*ICONS_SPACING
44 #define STATUSBAR_BATTERY_WIDTH 18
45 #define STATUSBAR_PLUG_X_POS STATUSBAR_X_POS + \
46 STATUSBAR_BATTERY_WIDTH + \
47 ICONS_SPACING
48 #define STATUSBAR_PLUG_WIDTH 7
49 #define STATUSBAR_VOLUME_X_POS STATUSBAR_X_POS + \
50 STATUSBAR_BATTERY_WIDTH + \
51 STATUSBAR_PLUG_WIDTH + \
52 2*ICONS_SPACING
53 #define STATUSBAR_VOLUME_WIDTH 16
54 #define STATUSBAR_ENCODER_X_POS STATUSBAR_X_POS + \
55 STATUSBAR_BATTERY_WIDTH + \
56 STATUSBAR_PLUG_WIDTH + \
57 2*ICONS_SPACING - 1
58 #define STATUSBAR_ENCODER_WIDTH 18
59 #define STATUSBAR_PLAY_STATE_X_POS STATUSBAR_X_POS + \
60 STATUSBAR_BATTERY_WIDTH + \
61 STATUSBAR_PLUG_WIDTH + \
62 STATUSBAR_VOLUME_WIDTH + \
63 3*ICONS_SPACING
64 #define STATUSBAR_PLAY_STATE_WIDTH 7
65 #define STATUSBAR_PLAY_MODE_X_POS STATUSBAR_X_POS + \
66 STATUSBAR_BATTERY_WIDTH + \
67 STATUSBAR_PLUG_WIDTH + \
68 STATUSBAR_VOLUME_WIDTH + \
69 STATUSBAR_PLAY_STATE_WIDTH + \
70 4*ICONS_SPACING
71 #define STATUSBAR_PLAY_MODE_WIDTH 7
72 #define STATUSBAR_RECFREQ_X_POS STATUSBAR_X_POS + \
73 STATUSBAR_BATTERY_WIDTH + \
74 STATUSBAR_PLUG_WIDTH + \
75 STATUSBAR_VOLUME_WIDTH + \
76 STATUSBAR_PLAY_STATE_WIDTH + \
77 3*ICONS_SPACING
78 #define STATUSBAR_RECFREQ_WIDTH 12
79 #define STATUSBAR_RECCHANNELS_X_POS STATUSBAR_X_POS + \
80 STATUSBAR_BATTERY_WIDTH + \
81 STATUSBAR_PLUG_WIDTH + \
82 STATUSBAR_VOLUME_WIDTH + \
83 STATUSBAR_PLAY_STATE_WIDTH + \
84 STATUSBAR_RECFREQ_WIDTH + \
85 4*ICONS_SPACING
86 #define STATUSBAR_RECCHANNELS_WIDTH 5
87 #define STATUSBAR_SHUFFLE_X_POS STATUSBAR_X_POS + \
88 STATUSBAR_BATTERY_WIDTH + \
89 STATUSBAR_PLUG_WIDTH + \
90 STATUSBAR_VOLUME_WIDTH + \
91 STATUSBAR_PLAY_STATE_WIDTH + \
92 STATUSBAR_PLAY_MODE_WIDTH + \
93 5*ICONS_SPACING
94 #define STATUSBAR_SHUFFLE_WIDTH 7
95 #define STATUSBAR_LOCKM_X_POS STATUSBAR_X_POS + \
96 STATUSBAR_BATTERY_WIDTH + \
97 STATUSBAR_PLUG_WIDTH + \
98 STATUSBAR_VOLUME_WIDTH + \
99 STATUSBAR_PLAY_STATE_WIDTH + \
100 STATUSBAR_PLAY_MODE_WIDTH + \
101 STATUSBAR_SHUFFLE_WIDTH + \
102 6*ICONS_SPACING
103 #define STATUSBAR_LOCKM_WIDTH 5
104 #define STATUSBAR_LOCKR_X_POS STATUSBAR_X_POS + \
105 STATUSBAR_BATTERY_WIDTH + \
106 STATUSBAR_PLUG_WIDTH + \
107 STATUSBAR_VOLUME_WIDTH + \
108 STATUSBAR_PLAY_STATE_WIDTH + \
109 STATUSBAR_PLAY_MODE_WIDTH + \
110 STATUSBAR_SHUFFLE_WIDTH + \
111 STATUSBAR_LOCKM_WIDTH + \
112 7*ICONS_SPACING
113 #define STATUSBAR_LOCKR_WIDTH 5
115 #if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
116 #define STATUSBAR_DISK_WIDTH 12
117 #define STATUSBAR_DISK_X_POS(statusbar_width) statusbar_width - \
118 STATUSBAR_DISK_WIDTH
119 #else
120 #define STATUSBAR_DISK_WIDTH 0
121 #endif
122 #define STATUSBAR_TIME_X_END(statusbar_width) statusbar_width - 1 - \
123 STATUSBAR_DISK_WIDTH
124 struct gui_syncstatusbar statusbars;
126 /* Prototypes */
127 #ifdef HAVE_LCD_BITMAP
128 static void gui_statusbar_icon_battery(struct screen * display, int percent,
129 int batt_charge_step);
130 static bool gui_statusbar_icon_volume(struct gui_statusbar * bar, int volume);
131 static void gui_statusbar_icon_play_state(struct screen * display, int state);
132 static void gui_statusbar_icon_play_mode(struct screen * display, int mode);
133 static void gui_statusbar_icon_shuffle(struct screen * display);
134 static void gui_statusbar_icon_lock(struct screen * display);
135 #ifdef HAS_REMOTE_BUTTON_HOLD
136 static void gui_statusbar_icon_lock_remote(struct screen * display);
137 #endif
138 #if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
139 static void gui_statusbar_led(struct screen * display);
140 #endif
141 #ifdef HAVE_RECORDING
142 static void gui_statusbar_icon_recording_info(struct screen * display);
143 #endif
144 #if CONFIG_RTC
145 static void gui_statusbar_time(struct screen * display, struct tm *time);
146 #endif
147 #endif
149 /* End prototypes */
153 * Initializes a status bar
154 * - bar : the bar to initialize
156 static void gui_statusbar_init(struct gui_statusbar * bar)
158 bar->redraw_volume = true;
159 bar->volume_icon_switch_tick = bar->battery_icon_switch_tick = current_tick;
160 memset((void*)&(bar->lastinfo), 0, sizeof(struct status_info));
161 #if CONFIG_RTC
162 bar->last_tm_min = 0;
163 #endif
166 void gui_statusbar_draw(struct gui_statusbar * bar, bool force_redraw)
168 struct screen * display = bar->display;
170 #ifdef HAVE_LCD_CHARCELLS
171 int val;
172 (void)force_redraw; /* players always "redraw" */
173 #endif /* HAVE_LCD_CHARCELLS */
175 bar->info.battlevel = battery_level();
176 #ifdef HAVE_USB_POWER
177 bar->info.usb_inserted = usb_inserted();
178 #endif
179 #if CONFIG_CHARGING
180 bar->info.inserted = (charger_input_state == CHARGER);
181 if (bar->info.inserted)
183 bar->info.battery_state = true;
185 #if CONFIG_CHARGING >= CHARGING_MONITOR
187 /* zero battery run time if charging */
188 if (charge_state > DISCHARGING)
189 lasttime = current_tick;
191 /* animate battery if charging */
192 if ((charge_state == DISCHARGING) || (charge_state == TRICKLE))
194 bar->info.batt_charge_step = -1;
196 else
198 #else /* CONFIG_CHARGING < CHARGING_MONITOR */
199 lasttime = current_tick;
201 #endif /* CONFIG_CHARGING < CHARGING_MONITOR */
202 /* animate in (max.) 4 steps, starting near the current charge level */
203 if (TIME_AFTER(current_tick, bar->battery_icon_switch_tick))
205 if (++bar->info.batt_charge_step > 3)
206 bar->info.batt_charge_step = bar->info.battlevel / 34;
207 bar->battery_icon_switch_tick = current_tick + HZ;
211 else
212 #endif /* CONFIG_CHARGING */
214 bar->info.batt_charge_step = -1;
215 if (battery_level_safe())
216 bar->info.battery_state = true;
217 else
218 /* blink battery if level is low */
219 if (TIME_AFTER(current_tick, bar->battery_icon_switch_tick) &&
220 (bar->info.battlevel > -1))
222 bar->info.battery_state = !bar->info.battery_state;
223 bar->battery_icon_switch_tick = current_tick + HZ;
227 bar->info.volume = global_settings.volume;
228 #ifdef HAVE_LCD_BITMAP
229 bar->info.shuffle = global_settings.playlist_shuffle;
230 #ifdef HAS_BUTTON_HOLD
231 bar->info.keylock = button_hold();
232 #else
233 bar->info.keylock = is_keys_locked();
234 #endif /* HAS_BUTTON_HOLD */
235 #ifdef HAS_REMOTE_BUTTON_HOLD
236 bar->info.keylockremote = remote_button_hold();
237 #endif
238 bar->info.repeat = global_settings.repeat_mode;
239 bar->info.playmode = current_playmode();
241 #if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
242 if(!display->has_disk_led)
243 bar->info.led = led_read(HZ/2); /* delay should match polling interval */
244 #endif
245 #if CONFIG_RTC
246 bar->time = get_time();
247 #endif /* CONFIG_RTC */
249 /* only redraw if forced to, or info has changed */
250 if (force_redraw || bar->redraw_volume ||
251 #if CONFIG_RTC
252 (bar->time->tm_min != bar->last_tm_min) ||
253 #endif
254 memcmp(&(bar->info), &(bar->lastinfo), sizeof(struct status_info)))
256 display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
257 display->fillrect(0, 0, display->width, STATUSBAR_HEIGHT);
258 display->set_drawmode(DRMODE_SOLID);
260 if (bar->info.battery_state)
261 gui_statusbar_icon_battery(display, bar->info.battlevel,
262 bar->info.batt_charge_step);
263 #ifdef HAVE_USB_POWER
264 if (bar->info.usb_inserted)
265 display->mono_bitmap(bitmap_icons_7x8[Icon_USBPlug],
266 STATUSBAR_PLUG_X_POS,
267 STATUSBAR_Y_POS, STATUSBAR_PLUG_WIDTH,
268 STATUSBAR_HEIGHT);
269 #endif /* HAVE_USB_POWER */
270 #if CONFIG_CHARGING
271 #ifdef HAVE_USB_POWER
272 else
273 #endif
274 /* draw power plug if charging */
275 if (bar->info.inserted)
276 display->mono_bitmap(bitmap_icons_7x8[Icon_Plug],
277 STATUSBAR_PLUG_X_POS,
278 STATUSBAR_Y_POS, STATUSBAR_PLUG_WIDTH,
279 STATUSBAR_HEIGHT);
280 #endif /* CONFIG_CHARGING */
281 #ifdef HAVE_RECORDING
282 /* turn off volume display in recording screen */
283 bool recscreen_on = in_recording_screen();
284 if (!recscreen_on)
285 #endif
286 bar->redraw_volume = gui_statusbar_icon_volume(bar, bar->info.volume);
287 gui_statusbar_icon_play_state(display, current_playmode() + Icon_Play);
289 #ifdef HAVE_RECORDING
290 /* If in recording screen, replace repeat mode, volume
291 and shuffle icons with recording info */
292 if (recscreen_on)
293 gui_statusbar_icon_recording_info(display);
294 else
295 #endif
297 switch (bar->info.repeat) {
298 #ifdef AB_REPEAT_ENABLE
299 case REPEAT_AB:
300 gui_statusbar_icon_play_mode(display, Icon_RepeatAB);
301 break;
302 #endif /* AB_REPEAT_ENABLE == 1 */
304 case REPEAT_ONE:
305 gui_statusbar_icon_play_mode(display, Icon_RepeatOne);
306 break;
308 case REPEAT_ALL:
309 case REPEAT_SHUFFLE:
310 gui_statusbar_icon_play_mode(display, Icon_Repeat);
311 break;
313 if (bar->info.shuffle)
314 gui_statusbar_icon_shuffle(display);
316 if (bar->info.keylock)
317 gui_statusbar_icon_lock(display);
318 #ifdef HAS_REMOTE_BUTTON_HOLD
319 if (bar->info.keylockremote)
320 gui_statusbar_icon_lock_remote(display);
321 #endif
322 #if CONFIG_RTC
323 gui_statusbar_time(display, bar->time);
324 bar->last_tm_min = bar->time->tm_min;
325 #endif /* CONFIG_RTC */
326 #if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
327 if(!display->has_disk_led && bar->info.led)
328 gui_statusbar_led(display);
329 #endif
330 display->update_rect(0, 0, display->width, STATUSBAR_HEIGHT);
331 bar->lastinfo = bar->info;
333 #endif /* HAVE_LCD_BITMAP */
336 #ifdef HAVE_LCD_CHARCELLS
337 display->icon(ICON_BATTERY, bar->info.battery_state);
339 if (bar->info.batt_charge_step > -1)
340 val = bar->info.batt_charge_step;
341 else
342 val = (bar->info.battlevel * 3 + 50) / 100;
343 display->icon(ICON_BATTERY_1, val >= 1);
344 display->icon(ICON_BATTERY_2, val >= 2);
345 display->icon(ICON_BATTERY_3, val >= 3);
347 val = 10 * (bar->info.volume - sound_min(SOUND_VOLUME))
348 / (sound_max(SOUND_VOLUME) - sound_min(SOUND_VOLUME));
349 display->icon(ICON_VOLUME, true);
350 display->icon(ICON_VOLUME_1, val >= 1);
351 display->icon(ICON_VOLUME_2, val >= 3);
352 display->icon(ICON_VOLUME_3, val >= 5);
353 display->icon(ICON_VOLUME_4, val >= 7);
354 display->icon(ICON_VOLUME_5, val >= 9);
356 display->icon(ICON_PLAY, current_playmode() == STATUS_PLAY);
357 display->icon(ICON_PAUSE, current_playmode() == STATUS_PAUSE);
359 display->icon(ICON_REPEAT, global_settings.repeat_mode != REPEAT_OFF);
360 display->icon(ICON_1, global_settings.repeat_mode == REPEAT_ONE);
362 display->icon(ICON_RECORD, record);
363 display->icon(ICON_AUDIO, audio);
364 display->icon(ICON_PARAM, param);
365 display->icon(ICON_USB, usb);
366 #endif /* HAVE_LCD_CHARCELLS */
369 #ifdef HAVE_LCD_BITMAP
370 /* from icon.c */
372 * Print battery icon to status bar
374 static void gui_statusbar_icon_battery(struct screen * display, int percent,
375 int batt_charge_step)
377 int fill, endfill;
378 char buffer[5];
379 unsigned int width, height;
380 #if LCD_DEPTH > 1
381 unsigned int prevfg = 0;
382 #endif
384 #if CONFIG_CHARGING
385 if (batt_charge_step >= 0)
387 fill = percent * (STATUSBAR_BATTERY_WIDTH-3) / 100;
388 endfill = 34 * batt_charge_step * (STATUSBAR_BATTERY_WIDTH-3) / 100;
390 else
391 #else
392 (void)batt_charge_step;
393 #endif
395 fill = endfill = (percent * (STATUSBAR_BATTERY_WIDTH-3) + 50) / 100;
398 #if CONFIG_CHARGING == CHARGING_MONITOR && !defined(SIMULATOR)
399 /* Certain charge controlled targets */
400 /* show graphical animation when charging instead of numbers */
401 if ((global_settings.battery_display) &&
402 (charge_state != CHARGING) &&
403 (percent > -1)) {
404 #else /* all others */
405 if (global_settings.battery_display && (percent > -1)) {
406 #endif
407 /* Numeric display */
408 display->setfont(FONT_SYSFIXED);
409 snprintf(buffer, sizeof(buffer), "%3d", percent);
410 display->getstringsize(buffer, &width, &height);
411 if (height <= STATUSBAR_HEIGHT)
412 display->putsxy(STATUSBAR_BATTERY_X_POS
413 + STATUSBAR_BATTERY_WIDTH / 2
414 - width/2, STATUSBAR_Y_POS, buffer);
415 display->setfont(FONT_UI);
418 else {
419 /* draw battery */
420 display->drawrect(STATUSBAR_BATTERY_X_POS, STATUSBAR_Y_POS, 17, 7);
421 display->vline(STATUSBAR_BATTERY_X_POS + 17, STATUSBAR_Y_POS + 2,
422 STATUSBAR_Y_POS + 4);
424 display->fillrect(STATUSBAR_BATTERY_X_POS + 1, STATUSBAR_Y_POS + 1,
425 fill, 5);
426 #if LCD_DEPTH > 1
427 if (display->depth > 1)
429 prevfg = display->get_foreground();
430 display->set_foreground(LCD_DARKGRAY);
432 #endif
433 display->fillrect(STATUSBAR_BATTERY_X_POS + 1 + fill,
434 STATUSBAR_Y_POS + 1, endfill - fill, 5);
435 #if LCD_DEPTH > 1
436 if (display->depth > 1)
437 display->set_foreground(prevfg);
438 #endif
441 if (percent == -1) {
442 display->setfont(FONT_SYSFIXED);
443 display->putsxy(STATUSBAR_BATTERY_X_POS + STATUSBAR_BATTERY_WIDTH / 2
444 - 4, STATUSBAR_Y_POS, "?");
445 display->setfont(FONT_UI);
450 * Print volume gauge to status bar
452 static bool gui_statusbar_icon_volume(struct gui_statusbar * bar, int volume)
454 int i;
455 int vol;
456 char buffer[4];
457 unsigned int width, height;
458 bool needs_redraw = false;
459 int type = global_settings.volume_type;
460 struct screen * display=bar->display;
461 const int minvol = sound_min(SOUND_VOLUME);
462 const int maxvol = sound_max(SOUND_VOLUME);
464 if (volume < minvol)
465 volume = minvol;
466 if (volume > maxvol)
467 volume = maxvol;
469 if (volume == minvol) {
470 display->mono_bitmap(bitmap_icons_7x8[Icon_Mute],
471 STATUSBAR_VOLUME_X_POS + STATUSBAR_VOLUME_WIDTH / 2 - 4,
472 STATUSBAR_Y_POS, 7, STATUSBAR_HEIGHT);
474 else {
475 /* We want to redraw the icon later on */
476 if (bar->last_volume != volume && bar->last_volume >= minvol) {
477 bar->volume_icon_switch_tick = current_tick + HZ;
480 /* If the timeout hasn't yet been reached, we show it numerically
481 and tell the caller that we want to be called again */
482 if (TIME_BEFORE(current_tick,bar->volume_icon_switch_tick)) {
483 type = 1;
484 needs_redraw = true;
487 /* display volume level numerical? */
488 if (type)
490 display->setfont(FONT_SYSFIXED);
491 snprintf(buffer, sizeof(buffer), "%2d", volume);
492 display->getstringsize(buffer, &width, &height);
493 if (height <= STATUSBAR_HEIGHT)
495 display->putsxy(STATUSBAR_VOLUME_X_POS
496 + STATUSBAR_VOLUME_WIDTH / 2
497 - width/2, STATUSBAR_Y_POS, buffer);
499 display->setfont(FONT_UI);
500 } else {
501 /* display volume bar */
502 vol = (volume - minvol) * 14 / (maxvol - minvol);
503 for(i=0; i < vol; i++) {
504 display->vline(STATUSBAR_VOLUME_X_POS + i,
505 STATUSBAR_Y_POS + 6 - i / 2,
506 STATUSBAR_Y_POS + 6);
510 bar->last_volume = volume;
512 return needs_redraw;
516 * Print play state to status bar
518 static void gui_statusbar_icon_play_state(struct screen * display, int state)
520 display->mono_bitmap(bitmap_icons_7x8[state], STATUSBAR_PLAY_STATE_X_POS,
521 STATUSBAR_Y_POS, STATUSBAR_PLAY_STATE_WIDTH,
522 STATUSBAR_HEIGHT);
526 * Print play mode to status bar
528 static void gui_statusbar_icon_play_mode(struct screen * display, int mode)
530 display->mono_bitmap(bitmap_icons_7x8[mode], STATUSBAR_PLAY_MODE_X_POS,
531 STATUSBAR_Y_POS, STATUSBAR_PLAY_MODE_WIDTH,
532 STATUSBAR_HEIGHT);
536 * Print shuffle mode to status bar
538 static void gui_statusbar_icon_shuffle(struct screen * display)
540 display->mono_bitmap(bitmap_icons_7x8[Icon_Shuffle],
541 STATUSBAR_SHUFFLE_X_POS, STATUSBAR_Y_POS,
542 STATUSBAR_SHUFFLE_WIDTH, STATUSBAR_HEIGHT);
546 * Print lock when keys are locked
548 static void gui_statusbar_icon_lock(struct screen * display)
550 display->mono_bitmap(bitmap_icons_5x8[Icon_Lock_Main],
551 STATUSBAR_LOCKM_X_POS, STATUSBAR_Y_POS,
552 STATUSBAR_LOCKM_WIDTH, STATUSBAR_HEIGHT);
555 #ifdef HAS_REMOTE_BUTTON_HOLD
557 * Print remote lock when remote hold is enabled
559 static void gui_statusbar_icon_lock_remote(struct screen * display)
561 display->mono_bitmap(bitmap_icons_5x8[Icon_Lock_Remote],
562 STATUSBAR_LOCKR_X_POS, STATUSBAR_Y_POS,
563 STATUSBAR_LOCKR_WIDTH, STATUSBAR_HEIGHT);
565 #endif
567 #if (CONFIG_LED == LED_VIRTUAL) || defined(HAVE_REMOTE_LCD)
569 * no real LED: disk activity in status bar
571 static void gui_statusbar_led(struct screen * display)
573 display->mono_bitmap(bitmap_icon_disk,
574 STATUSBAR_DISK_X_POS(display->width),
575 STATUSBAR_Y_POS, STATUSBAR_DISK_WIDTH,
576 STATUSBAR_HEIGHT);
578 #endif
580 #if CONFIG_RTC
582 * Print time to status bar
584 static void gui_statusbar_time(struct screen * display, struct tm *time)
586 unsigned char buffer[6];
587 unsigned int width, height;
588 int hour, minute;
589 if ( valid_time(time) ) {
590 hour = time->tm_hour;
591 minute = time->tm_min;
592 if ( global_settings.timeformat ) { /* 12 hour clock */
593 hour %= 12;
594 if ( hour == 0 ) {
595 hour += 12;
598 snprintf(buffer, sizeof(buffer), "%02d:%02d", hour, minute);
600 else {
601 strncpy(buffer, "--:--", sizeof buffer);
603 display->setfont(FONT_SYSFIXED);
604 display->getstringsize(buffer, &width, &height);
605 if (height <= STATUSBAR_HEIGHT) {
606 display->putsxy(STATUSBAR_TIME_X_END(display->width) - width,
607 STATUSBAR_Y_POS, buffer);
609 display->setfont(FONT_UI);
612 #endif
614 #ifdef HAVE_RECORDING
615 #if CONFIG_CODEC == SWCODEC
617 * Write a number to the display using bitmaps and return new position
619 static int write_bitmap_number(struct screen * display, int value,
620 int x, int y)
622 char buf[12], *ptr;
623 snprintf(buf, sizeof(buf), "%d", value);
625 for (ptr = buf; *ptr != '\0'; ptr++, x += BM_GLYPH_WIDTH)
626 display->mono_bitmap(bitmap_glyphs_4x8[*ptr - '0'], x, y,
627 BM_GLYPH_WIDTH, STATUSBAR_HEIGHT);
628 return x;
632 * Write format info bitmaps - right justified
634 static void gui_statusbar_write_format_info(struct screen * display)
636 /* Can't fit info for sw codec targets in statusbar using FONT_SYSFIXED
637 so must use icons */
638 int rec_format = global_settings.rec_format;
639 unsigned bitrk = 0; /* compiler warns about unitialized use !! */
640 int xpos = STATUSBAR_ENCODER_X_POS;
641 int width = STATUSBAR_ENCODER_WIDTH;
642 const unsigned char *bm = bitmap_formats_18x8[rec_format];
644 if (rec_format == REC_FORMAT_MPA_L3)
646 /* Special handling for mp3 */
647 bitrk = global_settings.mp3_enc_config.bitrate;
648 bitrk = mp3_enc_bitr[bitrk];
650 width = BM_MPA_L3_M_WIDTH;
652 /* Slide 'M' to right if fewer than three digits used */
653 if (bitrk > 999)
654 bitrk = 999; /* neurotic safety check if corrupted */
655 else
657 if (bitrk < 100)
658 xpos += BM_GLYPH_WIDTH;
659 if (bitrk < 10)
660 xpos += BM_GLYPH_WIDTH;
665 /* Show bitmap - clipping right edge if needed */
666 display->mono_bitmap_part(bm, 0, 0, STATUSBAR_ENCODER_WIDTH,
667 xpos, STATUSBAR_Y_POS, width, STATUSBAR_HEIGHT);
669 if (rec_format == REC_FORMAT_MPA_L3)
671 xpos += BM_MPA_L3_M_WIDTH; /* to right of 'M' */
672 write_bitmap_number(display, bitrk, xpos, STATUSBAR_Y_POS);
677 * Write sample rate using bitmaps - left justified
679 static void gui_statusbar_write_samplerate_info(struct screen * display)
681 unsigned long samprk;
682 int xpos;
684 #ifdef SIMULATOR
685 samprk = 44100;
686 #else
687 #ifdef HAVE_SPDIF_REC
688 if (global_settings.rec_source == AUDIO_SRC_SPDIF)
689 /* Use rate in use, not current measured rate if it changed */
690 samprk = pcm_rec_sample_rate();
691 else
692 #endif
693 samprk = rec_freq_sampr[global_settings.rec_frequency];
694 #endif /* SIMULATOR */
696 samprk /= 1000;
697 if (samprk > 99)
698 samprk = 99; /* Limit to 3 glyphs */
700 xpos = write_bitmap_number(display, (unsigned)samprk,
701 STATUSBAR_RECFREQ_X_POS, STATUSBAR_Y_POS);
703 /* write the 'k' */
704 display->mono_bitmap(bitmap_glyphs_4x8[Glyph_4x8_k], xpos,
705 STATUSBAR_Y_POS, BM_GLYPH_WIDTH,
706 STATUSBAR_HEIGHT);
708 #endif /* CONFIG_CODEC == SWCODEC */
710 static void gui_statusbar_icon_recording_info(struct screen * display)
712 #if CONFIG_CODEC != SWCODEC
713 char buffer[3];
714 int width, height;
715 display->setfont(FONT_SYSFIXED);
716 #endif /* CONFIG_CODEC != SWCODEC */
718 /* Display Codec info in statusbar */
719 #if CONFIG_CODEC == SWCODEC
720 gui_statusbar_write_format_info(display);
721 #else /* !SWCODEC */
722 display->mono_bitmap(bitmap_icons_5x8[Icon_q],
723 STATUSBAR_ENCODER_X_POS + 8, STATUSBAR_Y_POS,
724 5, STATUSBAR_HEIGHT);
726 snprintf(buffer, sizeof(buffer), "%d", global_settings.rec_quality);
727 display->getstringsize(buffer, &width, &height);
728 if (height <= STATUSBAR_HEIGHT)
729 display->putsxy(STATUSBAR_ENCODER_X_POS + 13, STATUSBAR_Y_POS, buffer);
730 #endif /* CONFIG_CODEC == SWCODEC */
732 /* Display Samplerate info in statusbar */
733 #if CONFIG_CODEC == SWCODEC
734 /* SWCODEC targets use bitmaps for glyphs */
735 gui_statusbar_write_samplerate_info(display);
736 #else /* !SWCODEC */
737 /* hwcodec targets have sysfont characters */
738 #ifdef HAVE_SPDIF_REC
739 if (global_settings.rec_source == AUDIO_SRC_SPDIF)
741 /* Can't measure S/PDIF sample rate on Archos/Sim yet */
742 snprintf(buffer, sizeof(buffer), "--");
744 else
745 #endif /* HAVE_SPDIF_IN */
747 static char const * const freq_strings[12] =
748 { "44", "48", "32", "22", "24", "16" };
749 snprintf(buffer, sizeof(buffer), "%s",
750 freq_strings[global_settings.rec_frequency]);
753 display->getstringsize(buffer, &width, &height);
755 if (height <= STATUSBAR_HEIGHT)
756 display->putsxy(STATUSBAR_RECFREQ_X_POS, STATUSBAR_Y_POS, buffer);
758 display->setfont(FONT_UI);
759 #endif /* CONFIG_CODEC == SWCODEC */
761 /* Display Channel status in status bar */
762 if(global_settings.rec_channels)
764 display->mono_bitmap(bitmap_icons_5x8[Icon_Mono],
765 STATUSBAR_RECCHANNELS_X_POS , STATUSBAR_Y_POS,
766 STATUSBAR_RECCHANNELS_WIDTH, STATUSBAR_HEIGHT);
768 else
770 display->mono_bitmap(bitmap_icons_5x8[Icon_Stereo],
771 STATUSBAR_RECCHANNELS_X_POS, STATUSBAR_Y_POS,
772 STATUSBAR_RECCHANNELS_WIDTH, STATUSBAR_HEIGHT);
775 #endif /* HAVE_RECORDING */
777 #endif /* HAVE_LCD_BITMAP */
779 void gui_syncstatusbar_init(struct gui_syncstatusbar * bars)
781 int i;
782 FOR_NB_SCREENS(i) {
783 gui_statusbar_init( &(bars->statusbars[i]) );
784 gui_statusbar_set_screen( &(bars->statusbars[i]), &(screens[i]) );
788 void gui_syncstatusbar_draw(struct gui_syncstatusbar * bars,
789 bool force_redraw)
791 #ifdef HAVE_LCD_BITMAP
792 if(!global_settings.statusbar)
793 return;
794 #endif /* HAVE_LCD_BITMAP */
795 int i;
796 FOR_NB_SCREENS(i) {
797 gui_statusbar_draw( &(bars->statusbars[i]), force_redraw );
801 int gui_statusbar_height(void)
803 return global_settings.statusbar ? STATUSBAR_HEIGHT : 0;