1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 Björn Stenberg
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 ****************************************************************************/
22 #include "backlight.h"
29 #include "mp3_playback.h"
38 #include "powermgmt.h"
47 #ifdef HAVE_LCD_BITMAP
48 #define BMPHEIGHT_usb_logo 32
49 #define BMPWIDTH_usb_logo 100
50 static const unsigned char usb_logo
[] = {
51 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
52 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
53 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08,
54 0x04, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
55 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x81, 0x81, 0x81, 0x81,
56 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
57 0x01, 0x01, 0x01, 0x01, 0xf1, 0x4f, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
58 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xc0,
59 0x00, 0x00, 0xe0, 0x1c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
60 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
61 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x06, 0x81, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0,
62 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x1c,
63 0x0c, 0x0e, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0f, 0x1f, 0x1f, 0x1f, 0x1f,
64 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0x00,
65 0x00, 0x00, 0xe0, 0x1f, 0x00, 0xf8, 0x06, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
66 0x02, 0x02, 0x02, 0x82, 0x7e, 0x00, 0xc0, 0x3e, 0x01,
67 0x70, 0x4f, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
68 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
69 0x40, 0x40, 0x40, 0x40, 0x40, 0x80, 0x00, 0x07, 0x0f, 0x1f, 0x1f, 0x1f, 0x1f,
70 0x0f, 0x07, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07, 0x0f,
71 0x1f, 0x3f, 0x7b, 0xf3, 0xe3, 0xc3, 0x83, 0x83, 0x83, 0x83, 0xe3, 0xe3, 0xe3,
72 0xe3, 0xe3, 0xe3, 0x03, 0x03, 0x03, 0x3f, 0x1f, 0x1f, 0x0f, 0x0f, 0x07, 0x02,
73 0xc0, 0x3e, 0x01, 0xe0, 0x9f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
74 0x80, 0x80, 0xf0, 0x0f, 0x80, 0x78, 0x07, 0x00, 0x00,
75 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
77 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0c, 0x10, 0x20, 0x40, 0x40, 0x80, 0x80,
78 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
79 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x81, 0x81, 0x87, 0x87, 0x87,
80 0x87, 0x87, 0x87, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xf0,
81 0x0f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
82 0x04, 0x04, 0x04, 0x04, 0x07, 0x00, 0x00, 0x00, 0x00,
86 void usb_display_info(void)
90 #ifdef HAVE_LCD_BITMAP
91 lcd_bitmap(usb_logo
, 6, 16, BMPWIDTH_usb_logo
, BMPHEIGHT_usb_logo
, false);
95 lcd_puts(0, 0, "[USB Mode]");
96 status_set_param(false);
97 status_set_audio(false);
103 void usb_screen(void)
110 usb_acknowledge(SYS_USB_CONNECTED_ACK
);
112 while(usb_wait_for_disconnect_w_tmo(&button_queue
, HZ
)) {
117 #ifdef HAVE_LCD_CHARCELLS
118 status_set_usb(false);
123 #endif /* USB_NONE */
127 int mmc_remove_request(void)
132 splash(1, true, str(LANG_REMOVE_MMC
));
133 if (global_settings
.talk_menu
)
134 talk_id(LANG_REMOVE_MMC
, false);
138 queue_wait_w_tmo(&button_queue
, &ev
, HZ
/2);
141 case SYS_MMC_EXTRACTED
:
142 return SYS_MMC_EXTRACTED
;
144 case SYS_USB_DISCONNECTED
:
145 return SYS_USB_DISCONNECTED
;
152 /* some simulator dummies */
154 #define BATTERY_SCALE_FACTOR 7000
155 unsigned short adc_read(int channel
)
164 #ifdef HAVE_LCD_BITMAP
165 void charging_display_info(bool animate
)
167 unsigned char charging_logo
[36];
168 const int pox_x
= (LCD_WIDTH
- sizeof(charging_logo
)) / 2;
169 const int pox_y
= 32;
170 static unsigned phase
= 3;
175 #ifdef NEED_ATA_POWER_BATT_MEASURE
176 if (ide_powered()) /* FM and V2 can only measure when ATA power is on */
180 int batt_int
, batt_frac
;
182 battery_voltage
= (adc_read(ADC_UNREG_POWER
) * BATTERY_SCALE_FACTOR
) / 10000;
183 batt_int
= battery_voltage
/ 100;
184 batt_frac
= battery_voltage
% 100;
186 snprintf(buf
, 32, " Batt: %d.%02dV %d%% ", batt_int
, batt_frac
,
191 #ifdef HAVE_CHARGE_CTRL
193 snprintf(buf
, 32, "Charge mode:");
196 if (charge_state
== 1)
197 snprintf(buf
, 32, str(LANG_BATTERY_CHARGE
));
198 else if (charge_state
== 2)
199 snprintf(buf
, 32, str(LANG_BATTERY_TOPOFF_CHARGE
));
200 else if (charge_state
== 3)
201 snprintf(buf
, 32, str(LANG_BATTERY_TRICKLE_CHARGE
));
203 snprintf(buf
, 32, "not charging");
206 if (!charger_enabled
)
208 #endif /* HAVE_CHARGE_CTRL */
212 memset(charging_logo
+3, 0x00, 32);
213 charging_logo
[0] = 0x3C;
214 charging_logo
[1] = 0x24;
215 charging_logo
[2] = charging_logo
[35] = 0xFF;
218 { /* draw the outline */
220 lcd_bitmap(charging_logo
, pox_x
, pox_y
+ 8, sizeof(charging_logo
), 8, true);
222 charging_logo
[0] = charging_logo
[1] = 0x00;
223 memset(charging_logo
+2, 0x80, 34);
224 lcd_bitmap(charging_logo
, pox_x
, pox_y
, sizeof(charging_logo
), 8, false);
226 memset(charging_logo
+2, 0x01, 34);
227 lcd_bitmap(charging_logo
, pox_x
, pox_y
+ 16, sizeof(charging_logo
), 8, false);
230 { /* animate the middle part */
231 for (i
= 3; i
<MIN(sizeof(charging_logo
)-1, phase
); i
++)
233 if ((i
-phase
) % 8 == 0)
234 { /* draw a "bubble" here */
236 bitpos
= (phase
+ i
/8) % 15; /* "bounce" effect */
238 bitpos
= 14 - bitpos
;
239 charging_logo
[i
] = 0x01 << bitpos
;
242 lcd_bitmap(charging_logo
, pox_x
, pox_y
+ 8, sizeof(charging_logo
), 8, true);
247 #else /* not HAVE_LCD_BITMAP */
249 static unsigned char logo_chars
[5];
250 static const unsigned char logo_pattern
[] = {
251 0x07, 0x04, 0x1c, 0x14, 0x1c, 0x04, 0x07, /* char 1 */
252 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, /* char 2 */
253 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, /* char 3 */
254 0x1f, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1f, /* char 4 */
257 static void logo_lock_patterns(bool on
)
263 for (i
= 0; i
< 4; i
++)
264 logo_chars
[i
] = lcd_get_locked_pattern();
265 logo_chars
[4] = '\0';
269 for (i
= 0; i
< 4; i
++)
270 lcd_unlock_pattern(logo_chars
[i
]);
274 void charging_display_info(bool animate
)
278 static unsigned phase
= 3;
281 battery_voltage
= (adc_read(ADC_UNREG_POWER
) * BATTERY_SCALE_FACTOR
)
283 snprintf(buf
, sizeof(buf
), "%s %d.%02dV", logo_chars
,
284 battery_voltage
/ 100, battery_voltage
% 100);
287 memcpy(buf
, logo_pattern
, 28); /* copy logo patterns */
289 if (!animate
) /* build the screen */
291 lcd_double_height(false);
292 lcd_puts(0, 0, "[Charging]");
294 else /* animate the logo */
296 for (i
= 3; i
< MIN(19, phase
); i
++)
298 if ((i
- phase
) % 5 == 0)
299 { /* draw a "bubble" here */
300 ypos
= (phase
+ i
/5) % 9; /* "bounce" effect */
303 buf
[5 - ypos
+ 7 * (i
/5)] |= 0x10 >> (i
%5);
309 for (i
= 0; i
< 4; i
++)
310 lcd_define_pattern(logo_chars
[i
], buf
+ 7 * i
);
312 #endif /* (not) HAVE_LCD_BITMAP */
314 /* blocks while charging, returns on event:
315 1 if charger cable was removed
316 2 if Off/Stop key was pressed
317 3 if On key was pressed
318 4 if USB was connected */
319 int charging_screen(void)
324 const int offbutton
= BUTTON_OFF
;
326 const int offbutton
= BUTTON_STOP
;
329 ide_power_enable(false); /* power down the disk, else would be spinning */
332 backlight_set_timeout(global_settings
.backlight_timeout
);
333 backlight_set_on_when_charging(global_settings
.backlight_on_when_charging
);
336 #ifdef HAVE_LCD_CHARCELLS
337 logo_lock_patterns(true);
339 charging_display_info(false);
344 charging_display_info(true);
345 button
= button_get_w_tmo(HZ
/3);
347 if (button
== (BUTTON_ON
| BUTTON_REL
))
349 if (button
== (BUTTON_RIGHT
| BUTTON_REL
))
352 else if (button
== offbutton
)
358 else if (!charger_inserted())
363 #ifdef HAVE_LCD_CHARCELLS
364 logo_lock_patterns(false);
368 #endif /* HAVE_CHARGING */
371 #if CONFIG_KEYPAD == RECORDER_PAD
373 0 if no key was pressed
374 1 if a key was pressed (or if ON was held down long enough to repeat)
375 2 if USB was connected */
376 int pitch_screen(void)
379 static int pitch
= 1000;
391 lcd_setfont(FONT_SYSFIXED
);
393 ptr
= str(LANG_PITCH_UP
);
394 lcd_getstringsize(ptr
,&w
,&h
);
395 lcd_putsxy((LCD_WIDTH
-w
)/2, 0, ptr
);
396 lcd_bitmap(bitmap_icons_7x8
[Icon_UpArrow
],
397 LCD_WIDTH
/2 - 3, h
*2, 7, 8, true);
399 snprintf(buf
, sizeof buf
, "%d.%d%%", pitch
/ 10, pitch
% 10 );
400 lcd_getstringsize(buf
,&w
,&h
);
401 lcd_putsxy((LCD_WIDTH
-w
)/2, h
, buf
);
403 ptr
= str(LANG_PITCH_DOWN
);
404 lcd_getstringsize(ptr
,&w
,&h
);
405 lcd_putsxy((LCD_WIDTH
-w
)/2, LCD_HEIGHT
- h
, ptr
);
406 lcd_bitmap(bitmap_icons_7x8
[Icon_DownArrow
],
407 LCD_WIDTH
/2 - 3, LCD_HEIGHT
- h
*3, 7, 8, true);
409 ptr
= str(LANG_PAUSE
);
410 lcd_getstringsize(ptr
,&w
,&h
);
411 lcd_putsxy((LCD_WIDTH
-(w
/2))/2, LCD_HEIGHT
/2 - h
/2, ptr
);
412 lcd_bitmap(bitmap_icons_7x8
[Icon_Pause
],
413 (LCD_WIDTH
-(w
/2))/2-10, LCD_HEIGHT
/2 - h
/2, 7, 8, true);
418 /* use lastbutton, so the main loop can decide whether to
419 exit to browser or not */
420 button
= button_get(true);
423 case BUTTON_ON
| BUTTON_UP
:
424 case BUTTON_ON
| BUTTON_UP
| BUTTON_REPEAT
:
429 mpeg_set_pitch(pitch
);
433 case BUTTON_ON
| BUTTON_DOWN
:
434 case BUTTON_ON
| BUTTON_DOWN
| BUTTON_REPEAT
:
439 mpeg_set_pitch(pitch
);
442 case BUTTON_ON
| BUTTON_PLAY
:
447 case BUTTON_PLAY
| BUTTON_REL
:
452 case BUTTON_ON
| BUTTON_PLAY
| BUTTON_REL
:
457 case BUTTON_ON
| BUTTON_RIGHT
:
458 if ( pitch
< 2000 ) {
460 mpeg_set_pitch(pitch
);
464 case BUTTON_RIGHT
| BUTTON_REL
:
467 mpeg_set_pitch(pitch
);
471 case BUTTON_ON
| BUTTON_LEFT
:
474 mpeg_set_pitch(pitch
);
478 case BUTTON_LEFT
| BUTTON_REL
:
479 if ( pitch
< 2000 ) {
481 mpeg_set_pitch(pitch
);
488 case BUTTON_ON
| BUTTON_REL
:
489 case BUTTON_ON
| BUTTON_UP
| BUTTON_REL
:
490 case BUTTON_ON
| BUTTON_DOWN
| BUTTON_REL
:
495 case BUTTON_ON
| BUTTON_REPEAT
:
500 if(default_event_handler(button
) == SYS_USB_CONNECTED
)
506 lcd_setfont(FONT_UI
);
514 bool quick_screen(int context
, int button
)
520 int oldrepeat
= global_settings
.repeat_mode
;
522 /* just to stop compiler warning */
524 lcd_setfont(FONT_SYSFIXED
);
526 lcd_getstringsize("A",&w
,&h
);
537 lcd_putsxy(0, LCD_HEIGHT
/2 - h
*2, str(LANG_SHUFFLE
));
538 lcd_putsxy(0, LCD_HEIGHT
/2 - h
, str(LANG_F2_MODE
));
539 lcd_putsxy(0, LCD_HEIGHT
/2,
540 global_settings
.playlist_shuffle
?
541 str(LANG_ON
) : str(LANG_OFF
));
543 /* Directory Filter */
544 switch ( global_settings
.dirfilter
) {
546 ptr
= str(LANG_FILTER_ALL
);
550 ptr
= str(LANG_FILTER_SUPPORTED
);
554 ptr
= str(LANG_FILTER_MUSIC
);
558 ptr
= str(LANG_FILTER_PLAYLIST
);
562 ptr
= str(LANG_FILTER_ID3DB
);
566 snprintf(buf
, sizeof buf
, "%s:", str(LANG_FILTER
));
567 lcd_getstringsize(buf
,&w
,&h
);
568 lcd_putsxy((LCD_WIDTH
-w
)/2, LCD_HEIGHT
- h
*2, buf
);
569 lcd_getstringsize(ptr
,&w
,&h
);
570 lcd_putsxy((LCD_WIDTH
-w
)/2, LCD_HEIGHT
- h
, ptr
);
573 switch ( global_settings
.repeat_mode
) {
579 ptr
= str(LANG_REPEAT_ALL
);
583 ptr
= str(LANG_REPEAT_ONE
);
587 lcd_getstringsize(str(LANG_REPEAT
),&w
,&h
);
588 lcd_putsxy(LCD_WIDTH
- w
, LCD_HEIGHT
/2 - h
*2, str(LANG_REPEAT
));
589 lcd_putsxy(LCD_WIDTH
- w
, LCD_HEIGHT
/2 - h
, str(LANG_F2_MODE
));
590 lcd_putsxy(LCD_WIDTH
- w
, LCD_HEIGHT
/2, ptr
);
594 lcd_putsxy(0, LCD_HEIGHT
/2 - h
*2, str(LANG_F3_SCROLL
));
595 lcd_putsxy(0, LCD_HEIGHT
/2 - h
, str(LANG_F3_BAR
));
596 lcd_putsxy(0, LCD_HEIGHT
/2,
597 global_settings
.scrollbar
? str(LANG_ON
) : str(LANG_OFF
));
600 ptr
= str(LANG_F3_STATUS
);
601 lcd_getstringsize(ptr
,&w
,&h
);
602 lcd_putsxy(LCD_WIDTH
- w
, LCD_HEIGHT
/2 - h
*2, ptr
);
603 lcd_putsxy(LCD_WIDTH
- w
, LCD_HEIGHT
/2 - h
, str(LANG_F3_BAR
));
604 lcd_putsxy(LCD_WIDTH
- w
, LCD_HEIGHT
/2,
605 global_settings
.statusbar
? str(LANG_ON
) : str(LANG_OFF
));
608 ptr
= str(LANG_FLIP_DISPLAY
);
609 lcd_getstringsize(ptr
,&w
,&h
);
610 lcd_putsxy((LCD_WIDTH
-w
)/2, LCD_HEIGHT
- h
*2, str(LANG_FLIP_DISPLAY
));
611 ptr
= global_settings
.flip_display
?
612 str(LANG_SET_BOOL_YES
) : str(LANG_SET_BOOL_NO
);
613 lcd_getstringsize(ptr
,&w
,&h
);
614 lcd_putsxy((LCD_WIDTH
-w
)/2, LCD_HEIGHT
- h
, ptr
);
618 lcd_bitmap(bitmap_icons_7x8
[Icon_FastBackward
],
619 LCD_WIDTH
/2 - 16, LCD_HEIGHT
/2 - 4, 7, 8, true);
620 lcd_bitmap(bitmap_icons_7x8
[Icon_DownArrow
],
621 LCD_WIDTH
/2 - 3, LCD_HEIGHT
- h
*3, 7, 8, true);
622 lcd_bitmap(bitmap_icons_7x8
[Icon_FastForward
],
623 LCD_WIDTH
/2 + 8, LCD_HEIGHT
/2 - 4, 7, 8, true);
626 key
= button_get(true);
629 * This is a temporary kludge so that the F2 & F3 menus operate in exactly
630 * the same manner up until the full F2/F3 configurable menus are complete
633 if( key
== BUTTON_LEFT
|| key
== BUTTON_RIGHT
|| key
== BUTTON_DOWN
|| key
== ( BUTTON_LEFT
| BUTTON_REPEAT
) || key
== ( BUTTON_RIGHT
| BUTTON_REPEAT
) || key
== ( BUTTON_DOWN
| BUTTON_REPEAT
) )
637 case BUTTON_F2
| BUTTON_LEFT
:
638 case BUTTON_F2
| BUTTON_LEFT
| BUTTON_REPEAT
:
639 global_settings
.playlist_shuffle
=
640 !global_settings
.playlist_shuffle
;
642 if(mpeg_status() & MPEG_STATUS_PLAY
)
644 if (global_settings
.playlist_shuffle
)
645 playlist_randomise(NULL
, current_tick
, true);
647 playlist_sort(NULL
, true);
652 case BUTTON_F2
| BUTTON_DOWN
:
653 case BUTTON_F2
| BUTTON_DOWN
| BUTTON_REPEAT
:
654 global_settings
.dirfilter
++;
655 if ( global_settings
.dirfilter
>= NUM_FILTER_MODES
)
656 global_settings
.dirfilter
= 0;
660 case BUTTON_F2
| BUTTON_RIGHT
:
661 case BUTTON_F2
| BUTTON_RIGHT
| BUTTON_REPEAT
:
662 global_settings
.repeat_mode
++;
663 if ( global_settings
.repeat_mode
>= NUM_REPEAT_MODES
)
664 global_settings
.repeat_mode
= 0;
668 case BUTTON_F3
| BUTTON_LEFT
:
669 case BUTTON_F3
| BUTTON_LEFT
| BUTTON_REPEAT
:
670 global_settings
.scrollbar
= !global_settings
.scrollbar
;
674 case BUTTON_F3
| BUTTON_RIGHT
:
675 case BUTTON_F3
| BUTTON_RIGHT
| BUTTON_REPEAT
:
676 global_settings
.statusbar
= !global_settings
.statusbar
;
680 case BUTTON_F3
| BUTTON_DOWN
:
681 case BUTTON_F3
| BUTTON_DOWN
| BUTTON_REPEAT
:
682 case BUTTON_F3
| BUTTON_UP
:
683 case BUTTON_F3
| BUTTON_UP
| BUTTON_REPEAT
:
684 global_settings
.flip_display
= !global_settings
.flip_display
;
685 button_set_flip(global_settings
.flip_display
);
686 lcd_set_flip(global_settings
.flip_display
);
690 case BUTTON_F3
| BUTTON_REL
:
691 case BUTTON_F2
| BUTTON_REL
:
700 case BUTTON_OFF
| BUTTON_REL
:
701 lcd_setfont(FONT_UI
);
705 if(default_event_handler(key
) == SYS_USB_CONNECTED
)
717 if ( oldrepeat
!= global_settings
.repeat_mode
)
718 mpeg_flush_and_reload_tracks();
723 if (global_settings
.statusbar
)
724 lcd_setmargins(0, STATUSBAR_HEIGHT
);
726 lcd_setmargins(0, 0);
731 lcd_setfont(FONT_UI
);
737 #ifdef HAVE_LCD_BITMAP
738 #define SPACE 3 /* pixels between words */
739 #define MAXLETTERS 128 /* 16*8 */
742 #define SPACE 1 /* one letter space */
747 #define MAXLETTERS 22 /* 11 * 2 */
751 void splash(int ticks
, /* how long the splash is displayed */
752 bool center
, /* FALSE means left-justified, TRUE means
753 horizontal and vertical center */
754 const char *fmt
, /* what to say *printf style */
762 unsigned char splash_buf
[MAXLETTERS
];
764 unsigned char widths
[MAXLINES
];
767 #ifdef HAVE_LCD_BITMAP
771 #ifdef HAVE_LCD_CHARCELLS
772 lcd_double_height (false);
775 vsnprintf( splash_buf
, sizeof(splash_buf
), fmt
, ap
);
779 /* first a pass to measure sizes */
780 next
= strtok_r(splash_buf
, " ", &store
);
782 #ifdef HAVE_LCD_BITMAP
783 lcd_getstringsize(next
, &w
, &h
);
786 h
= 1; /* store height in characters */
793 if((y
> (LCD_HEIGHT
-h
)) || (line
> MAXLINES
))
803 /* think of it as if the text was written here at position x,y
804 being w pixels/chars wide and h high */
807 widths
[line
]=x
-SPACE
; /* don't count the trailing space */
808 #ifdef HAVE_LCD_BITMAP
809 /* store the widest line */
810 if(widths
[line
]>maxw
)
813 next
= strtok_r(NULL
, " ", &store
);
815 #ifdef HAVE_LCD_BITMAP
816 /* Start displaying the message at position y. The reason for the
817 added h here is that it isn't added until the end of lines in the
818 loop above and we always break the loop in the middle of a line. */
819 y
= (LCD_HEIGHT
- (y
+h
) )/2;
821 y
= 0; /* vertical center on 2 lines would be silly */
825 /* Now recreate the string again since the strtok_r() above has ruined
826 the one we already have! Here's room for improvements! */
827 vsnprintf( splash_buf
, sizeof(splash_buf
), fmt
, ap
);
833 x
= (LCD_WIDTH
-widths
[0])/2;
838 #ifdef HAVE_LCD_BITMAP
839 /* If we center the display and it wouldn't cover the full screen,
840 then just clear the box we need and put a nice little frame and
841 put the text in there! */
842 if(center
&& (y
> 2)) {
843 if(maxw
< (LCD_WIDTH
-4)) {
844 int xx
= (LCD_WIDTH
-maxw
)/2 - 2;
845 lcd_clearrect(xx
, y
-2, maxw
+4, LCD_HEIGHT
-y
*2+4);
846 lcd_drawrect(xx
, y
-2, maxw
+4, LCD_HEIGHT
-y
*2+4);
849 lcd_clearrect(0, y
-2, LCD_WIDTH
, LCD_HEIGHT
-y
*2+4);
850 lcd_drawline(0, y
-2, LCD_WIDTH
-1, y
-2);
851 lcd_drawline(0, LCD_HEIGHT
-y
+2, LCD_WIDTH
-1, LCD_HEIGHT
-y
+2);
858 next
= strtok_r(splash_buf
, " ", &store
);
860 #ifdef HAVE_LCD_BITMAP
861 lcd_getstringsize(next
, &w
, &h
);
870 line
++; /* goto next line */
872 if(y
> (LCD_HEIGHT
-h
))
876 x
= (LCD_WIDTH
-widths
[line
])/2;
886 #ifdef HAVE_LCD_BITMAP
887 lcd_putsxy(x
, y
, next
);
889 lcd_puts(x
, y
, next
);
891 x
+= w
+SPACE
; /* pixels space! */
892 next
= strtok_r(NULL
, " ", &store
);
901 void charging_splash(void)
903 splash(2*HZ
, true, str(LANG_BATTERY_CHARGE
));
904 while (button_get(false));
908 #ifdef HAVE_LCD_BITMAP
910 /* little helper function for voice output */
911 static void say_time(int cursorpos
, const struct tm
*tm
)
913 static const int unit
[] = { UNIT_HOUR
, UNIT_MIN
, UNIT_SEC
, 0, 0, 0 };
916 if (!global_settings
.talk_menu
)
931 value
= tm
->tm_year
+ 1900;
938 if (cursorpos
== 4) /* month */
939 talk_id(LANG_MONTH_JANUARY
+ tm
->tm_mon
, false);
941 talk_value(value
, unit
[cursorpos
], false);
947 #define INDEX_WIDTH 2
948 bool set_time_screen(const char* string
, struct tm
*tm
)
952 int min
= 0, steps
= 0;
954 int lastcursorpos
= !cursorpos
;
955 unsigned char buffer
[19];
959 unsigned char reffub
[5];
960 unsigned int width
, height
;
961 unsigned int separator_width
, weekday_width
;
962 unsigned int line_height
, prev_line_height
;
964 static const int dayname
[] = {
967 LANG_WEEKDAY_TUESDAY
,
968 LANG_WEEKDAY_WEDNESDAY
,
969 LANG_WEEKDAY_THURSDAY
,
971 LANG_WEEKDAY_SATURDAY
973 static const int monthname
[] = {
982 LANG_MONTH_SEPTEMBER
,
987 char cursor
[][3] = {{ 0, 8, 12}, {18, 8, 12}, {36, 8, 12},
988 {24, 16, 24}, {54, 16, 18}, {78, 16, 12}};
989 char daysinmonth
[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
991 int monthname_len
= 0, dayname_len
= 0;
995 #ifdef HAVE_LCD_BITMAP
996 if(global_settings
.statusbar
)
997 lcd_setmargins(0, STATUSBAR_HEIGHT
);
999 lcd_setmargins(0, 0);
1001 lcd_clear_display();
1002 lcd_puts_scroll(0, 0, string
);
1005 /* calculate the number of days in febuary */
1006 realyear
= tm
->tm_year
+ 1900;
1007 if((realyear
% 4 == 0 && !(realyear
% 100 == 0)) || realyear
% 400 == 0)
1008 daysinmonth
[1] = 29;
1010 daysinmonth
[1] = 28;
1012 /* fix day if month or year changed */
1013 if (tm
->tm_mday
> daysinmonth
[tm
->tm_mon
])
1014 tm
->tm_mday
= daysinmonth
[tm
->tm_mon
];
1016 /* calculate day of week */
1018 for(i
= 0; i
< tm
->tm_mon
; i
++) {
1019 julianday
+= daysinmonth
[i
];
1021 julianday
+= tm
->tm_mday
;
1022 tm
->tm_wday
= (realyear
+ julianday
+ (realyear
- 1) / 4 -
1023 (realyear
- 1) / 100 + (realyear
- 1) / 400 + 7 - 1) % 7;
1025 snprintf(buffer
, sizeof(buffer
), "%02d:%02d:%02d ",
1026 tm
->tm_hour
, tm
->tm_min
, tm
->tm_sec
);
1027 lcd_puts(0, 1, buffer
);
1029 /* recalculate the positions and offsets */
1030 lcd_getstringsize(string
, &width
, &prev_line_height
);
1031 lcd_getstringsize(buffer
, &width
, &line_height
);
1032 lcd_getstringsize(":", &separator_width
, &height
);
1035 strncpy(reffub
, buffer
, 2);
1037 lcd_getstringsize(reffub
, &width
, &height
);
1038 cursor
[0][INDEX_X
] = 0;
1039 cursor
[0][INDEX_Y
] = prev_line_height
;
1040 cursor
[0][INDEX_WIDTH
] = width
;
1043 strncpy(reffub
, buffer
+ 3, 2);
1045 lcd_getstringsize(reffub
, &width
, &height
);
1046 cursor
[1][INDEX_X
] = cursor
[0][INDEX_WIDTH
] + separator_width
;
1047 cursor
[1][INDEX_Y
] = prev_line_height
;
1048 cursor
[1][INDEX_WIDTH
] = width
;
1051 strncpy(reffub
, buffer
+ 6, 2);
1053 lcd_getstringsize(reffub
, &width
, &height
);
1054 cursor
[2][INDEX_X
] = cursor
[0][INDEX_WIDTH
] + separator_width
+
1055 cursor
[1][INDEX_WIDTH
] + separator_width
;
1056 cursor
[2][INDEX_Y
] = prev_line_height
;
1057 cursor
[2][INDEX_WIDTH
] = width
;
1059 lcd_getstringsize(buffer
, &width
, &prev_line_height
);
1061 snprintf(buffer
, sizeof(buffer
), "%s %04d %s %02d ",
1062 str(dayname
[tm
->tm_wday
]), tm
->tm_year
+1900,
1063 str(monthname
[tm
->tm_mon
]), tm
->tm_mday
);
1064 lcd_puts(0, 2, buffer
);
1066 /* recalculate the positions and offsets */
1067 lcd_getstringsize(buffer
, &width
, &line_height
);
1069 /* store these 2 to prevent _repeated_ strlen calls */
1070 monthname_len
= strlen(str(monthname
[tm
->tm_mon
]));
1071 dayname_len
= strlen(str(dayname
[tm
->tm_wday
]));
1074 strncpy(reffub
, buffer
, dayname_len
);
1075 reffub
[dayname_len
] = '\0';
1076 lcd_getstringsize(reffub
, &weekday_width
, &height
);
1077 lcd_getstringsize(" ", &separator_width
, &height
);
1080 strncpy(reffub
, buffer
+ dayname_len
+ 1, 4);
1082 lcd_getstringsize(reffub
, &width
, &height
);
1083 cursor
[3][INDEX_X
] = weekday_width
+ separator_width
;
1084 cursor
[3][INDEX_Y
] = cursor
[0][INDEX_Y
] + prev_line_height
;
1085 cursor
[3][INDEX_WIDTH
] = width
;
1088 strncpy(reffub
, buffer
+ dayname_len
+ 6, monthname_len
);
1089 reffub
[monthname_len
] = '\0';
1090 lcd_getstringsize(reffub
, &width
, &height
);
1091 cursor
[4][INDEX_X
] = weekday_width
+ separator_width
+
1092 cursor
[3][INDEX_WIDTH
] + separator_width
;
1093 cursor
[4][INDEX_Y
] = cursor
[0][INDEX_Y
] + prev_line_height
;
1094 cursor
[4][INDEX_WIDTH
] = width
;
1097 strncpy(reffub
, buffer
+ dayname_len
+ monthname_len
+ 7, 2);
1099 lcd_getstringsize(reffub
, &width
, &height
);
1100 cursor
[5][INDEX_X
] = weekday_width
+ separator_width
+
1101 cursor
[3][INDEX_WIDTH
] + separator_width
+
1102 cursor
[4][INDEX_WIDTH
] + separator_width
;
1103 cursor
[5][INDEX_Y
] = cursor
[0][INDEX_Y
] + prev_line_height
;
1104 cursor
[5][INDEX_WIDTH
] = width
;
1106 lcd_invertrect(cursor
[cursorpos
][INDEX_X
],
1107 cursor
[cursorpos
][INDEX_Y
] + lcd_getymargin(),
1108 cursor
[cursorpos
][INDEX_WIDTH
],
1111 lcd_puts(0, 4, str(LANG_TIME_SET
));
1112 lcd_puts(0, 5, str(LANG_TIME_REVERT
));
1113 #ifdef HAVE_LCD_BITMAP
1118 /* calculate the minimum and maximum for the number under cursor */
1119 if(cursorpos
!=lastcursorpos
) {
1120 lastcursorpos
=cursorpos
;
1125 valptr
= &tm
->tm_hour
;
1127 case 1: /* minute */
1130 valptr
= &tm
->tm_min
;
1132 case 2: /* second */
1135 valptr
= &tm
->tm_sec
;
1140 valptr
= &tm
->tm_year
;
1145 valptr
= &tm
->tm_mon
;
1149 steps
= daysinmonth
[tm
->tm_mon
];
1150 valptr
= &tm
->tm_mday
;
1153 say_time(cursorpos
, tm
);
1156 button
= button_get_w_tmo(HZ
/2);
1159 cursorpos
= (cursorpos
+ 6 - 1) % 6;
1162 cursorpos
= (cursorpos
+ 6 + 1) % 6;
1165 case BUTTON_UP
| BUTTON_REPEAT
:
1166 *valptr
= (*valptr
+ steps
- min
+ 1) %
1170 say_time(cursorpos
, tm
);
1173 case BUTTON_DOWN
| BUTTON_REPEAT
:
1174 *valptr
= (*valptr
+ steps
- min
- 1) %
1178 say_time(cursorpos
, tm
);
1183 #elif defined BUTTON_MENU
1195 if (default_event_handler(button
) == SYS_USB_CONNECTED
)
1205 #if CONFIG_KEYPAD == RECORDER_PAD || CONFIG_KEYPAD == IRIVER_H100_PAD
1206 bool shutdown_screen(void)
1213 splash(0, true, str(LANG_CONFIRM_SHUTDOWN
));
1217 button
= button_get_w_tmo(HZ
*2);
1225 if(default_event_handler(button
) == SYS_USB_CONNECTED
)
1228 /* Return if any other button was pushed, or if there
1229 was a timeout. We ignore RELEASE events, since we may
1230 have been called by a button down event, and the user might
1231 not have released the button yet.
1232 We also ignore REPEAT events, since we don't want to
1233 remove the splash when the user holds OFF to shut down. */
1234 if(!(button
& (BUTTON_REL
| BUTTON_REPEAT
)))
1243 bool browse_id3(void)
1245 struct mp3entry
* id3
= mpeg_current_track();
1250 char scroll_text
[MAX_PATH
];
1252 if (!(mpeg_status() & MPEG_STATUS_PLAY
))
1257 lcd_clear_display();
1262 lcd_puts(0, 0, str(LANG_ID3_TITLE
));
1263 lcd_puts_scroll(0, 1, id3
->title
? id3
->title
:
1264 (char*)str(LANG_ID3_NO_TITLE
));
1268 lcd_puts(0, 0, str(LANG_ID3_ARTIST
));
1269 lcd_puts_scroll(0, 1,
1270 id3
->artist
? id3
->artist
:
1271 (char*)str(LANG_ID3_NO_ARTIST
));
1275 lcd_puts(0, 0, str(LANG_ID3_ALBUM
));
1276 lcd_puts_scroll(0, 1, id3
->album
? id3
->album
:
1277 (char*)str(LANG_ID3_NO_ALBUM
));
1281 lcd_puts(0, 0, str(LANG_ID3_TRACKNUM
));
1283 if (id3
->tracknum
) {
1284 snprintf(scroll_text
,sizeof(scroll_text
), "%d",
1286 lcd_puts_scroll(0, 1, scroll_text
);
1289 lcd_puts_scroll(0, 1, str(LANG_ID3_NO_TRACKNUM
));
1293 lcd_puts(0, 0, str(LANG_ID3_GENRE
));
1294 lcd_puts_scroll(0, 1,
1295 id3_get_genre(id3
) ?
1296 id3_get_genre(id3
) :
1297 (char*)str(LANG_ID3_NO_INFO
));
1301 lcd_puts(0, 0, str(LANG_ID3_YEAR
));
1303 snprintf(scroll_text
,sizeof(scroll_text
), "%d",
1305 lcd_puts_scroll(0, 1, scroll_text
);
1308 lcd_puts_scroll(0, 1, str(LANG_ID3_NO_INFO
));
1312 lcd_puts(0, 0, str(LANG_ID3_LENGHT
));
1313 snprintf(scroll_text
,sizeof(scroll_text
), "%d:%02d",
1314 id3
->length
/ 60000,
1315 id3
->length
% 60000 / 1000 );
1316 lcd_puts(0, 1, scroll_text
);
1320 lcd_puts(0, 0, str(LANG_ID3_PLAYLIST
));
1321 snprintf(scroll_text
,sizeof(scroll_text
), "%d/%d",
1322 playlist_get_display_index(), playlist_amount());
1323 lcd_puts_scroll(0, 1, scroll_text
);
1328 lcd_puts(0, 0, str(LANG_ID3_BITRATE
));
1329 snprintf(scroll_text
,sizeof(scroll_text
), "%d kbps",
1331 lcd_puts(0, 1, scroll_text
);
1335 lcd_puts(0, 0, str(LANG_ID3_FRECUENCY
));
1336 snprintf(scroll_text
,sizeof(scroll_text
), "%d Hz",
1338 lcd_puts(0, 1, scroll_text
);
1342 lcd_puts(0, 0, str(LANG_ID3_PATH
));
1343 lcd_puts_scroll(0, 1, id3
->path
);
1348 button
= button_get(true);
1356 menu_pos
= menu_max
;
1360 if (menu_pos
< menu_max
)
1366 case SETTINGS_CANCEL
:
1368 /* eat release event */
1374 if(default_event_handler(button
) == SYS_USB_CONNECTED
)