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 talk_id(LANG_REMOVE_MMC
, false);
137 queue_wait_w_tmo(&button_queue
, &ev
, HZ
/2);
140 case SYS_MMC_EXTRACTED
:
141 return SYS_MMC_EXTRACTED
;
143 case SYS_USB_DISCONNECTED
:
144 return SYS_USB_DISCONNECTED
;
151 /* some simulator dummies */
153 #define BATTERY_SCALE_FACTOR 7000
154 unsigned short adc_read(int channel
)
162 #ifdef HAVE_LCD_BITMAP
163 void charging_display_info(bool animate
)
165 unsigned char charging_logo
[36];
166 const int pox_x
= (LCD_WIDTH
- sizeof(charging_logo
)) / 2;
167 const int pox_y
= 32;
168 static unsigned phase
= 3;
173 #ifdef NEED_ATA_POWER_BATT_MEASURE
174 if (ide_powered()) /* FM and V2 can only measure when ATA power is on */
178 int batt_int
, batt_frac
;
180 battery_voltage
= (adc_read(ADC_UNREG_POWER
) * BATTERY_SCALE_FACTOR
) / 10000;
181 batt_int
= battery_voltage
/ 100;
182 batt_frac
= battery_voltage
% 100;
184 snprintf(buf
, 32, " Batt: %d.%02dV %d%% ", batt_int
, batt_frac
,
189 #ifdef HAVE_CHARGE_CTRL
191 snprintf(buf
, 32, "Charge mode:");
194 if (charge_state
== 1)
195 snprintf(buf
, 32, str(LANG_BATTERY_CHARGE
));
196 else if (charge_state
== 2)
197 snprintf(buf
, 32, str(LANG_BATTERY_TOPOFF_CHARGE
));
198 else if (charge_state
== 3)
199 snprintf(buf
, 32, str(LANG_BATTERY_TRICKLE_CHARGE
));
201 snprintf(buf
, 32, "not charging");
204 if (!charger_enabled
)
210 memset(charging_logo
+3, 0x00, 32);
211 charging_logo
[0] = 0x3C;
212 charging_logo
[1] = 0x24;
213 charging_logo
[2] = charging_logo
[35] = 0xFF;
216 { /* draw the outline */
218 lcd_bitmap(charging_logo
, pox_x
, pox_y
+ 8, sizeof(charging_logo
), 8, true);
220 charging_logo
[0] = charging_logo
[1] = 0x00;
221 memset(charging_logo
+2, 0x80, 34);
222 lcd_bitmap(charging_logo
, pox_x
, pox_y
, sizeof(charging_logo
), 8, false);
224 memset(charging_logo
+2, 0x01, 34);
225 lcd_bitmap(charging_logo
, pox_x
, pox_y
+ 16, sizeof(charging_logo
), 8, false);
228 { /* animate the middle part */
229 for (i
= 3; i
<MIN(sizeof(charging_logo
)-1, phase
); i
++)
231 if ((i
-phase
) % 8 == 0)
232 { /* draw a "bubble" here */
234 bitpos
= (phase
+ i
/8) % 15; /* "bounce" effect */
236 bitpos
= 14 - bitpos
;
237 charging_logo
[i
] = 0x01 << bitpos
;
240 lcd_bitmap(charging_logo
, pox_x
, pox_y
+ 8, sizeof(charging_logo
), 8, true);
245 #else /* not HAVE_LCD_BITMAP */
246 void charging_display_info(bool animate
)
248 /* ToDo for Player */
254 /* blocks while charging, returns on event:
255 1 if charger cable was removed
256 2 if Off/Stop key was pressed
257 3 if On key was pressed
258 4 if USB was connected */
259 int charging_screen(void)
264 const int offbutton
= BUTTON_OFF
;
266 const int offbutton
= BUTTON_STOP
;
269 ide_power_enable(false); /* power down the disk, else would be spinning */
272 if(global_settings
.backlight_on_when_charging
)
276 #ifdef HAVE_LCD_BITMAP
277 charging_display_info(false);
279 lcd_puts(0, 1, "[charging]");
285 charging_display_info(true);
286 button
= button_get_w_tmo(HZ
/3);
288 if (button
== (BUTTON_ON
| BUTTON_REL
))
290 if (button
== (BUTTON_RIGHT
| BUTTON_REL
))
293 else if (button
== offbutton
)
299 else if (!charger_inserted())
306 #endif /* HAVE_CHARGING */
309 #if CONFIG_KEYPAD == RECORDER_PAD
311 0 if no key was pressed
312 1 if a key was pressed (or if ON was held down long enough to repeat)
313 2 if USB was connected */
314 int pitch_screen(void)
317 static int pitch
= 1000;
329 lcd_setfont(FONT_SYSFIXED
);
331 ptr
= str(LANG_PITCH_UP
);
332 lcd_getstringsize(ptr
,&w
,&h
);
333 lcd_putsxy((LCD_WIDTH
-w
)/2, 0, ptr
);
334 lcd_bitmap(bitmap_icons_7x8
[Icon_UpArrow
],
335 LCD_WIDTH
/2 - 3, h
*2, 7, 8, true);
337 snprintf(buf
, sizeof buf
, "%d.%d%%", pitch
/ 10, pitch
% 10 );
338 lcd_getstringsize(buf
,&w
,&h
);
339 lcd_putsxy((LCD_WIDTH
-w
)/2, h
, buf
);
341 ptr
= str(LANG_PITCH_DOWN
);
342 lcd_getstringsize(ptr
,&w
,&h
);
343 lcd_putsxy((LCD_WIDTH
-w
)/2, LCD_HEIGHT
- h
, ptr
);
344 lcd_bitmap(bitmap_icons_7x8
[Icon_DownArrow
],
345 LCD_WIDTH
/2 - 3, LCD_HEIGHT
- h
*3, 7, 8, true);
347 ptr
= str(LANG_PAUSE
);
348 lcd_getstringsize(ptr
,&w
,&h
);
349 lcd_putsxy((LCD_WIDTH
-(w
/2))/2, LCD_HEIGHT
/2 - h
/2, ptr
);
350 lcd_bitmap(bitmap_icons_7x8
[Icon_Pause
],
351 (LCD_WIDTH
-(w
/2))/2-10, LCD_HEIGHT
/2 - h
/2, 7, 8, true);
356 /* use lastbutton, so the main loop can decide whether to
357 exit to browser or not */
358 button
= button_get(true);
361 case BUTTON_ON
| BUTTON_UP
:
362 case BUTTON_ON
| BUTTON_UP
| BUTTON_REPEAT
:
367 mpeg_set_pitch(pitch
);
371 case BUTTON_ON
| BUTTON_DOWN
:
372 case BUTTON_ON
| BUTTON_DOWN
| BUTTON_REPEAT
:
377 mpeg_set_pitch(pitch
);
380 case BUTTON_ON
| BUTTON_PLAY
:
385 case BUTTON_PLAY
| BUTTON_REL
:
390 case BUTTON_ON
| BUTTON_PLAY
| BUTTON_REL
:
395 case BUTTON_ON
| BUTTON_RIGHT
:
396 if ( pitch
< 2000 ) {
398 mpeg_set_pitch(pitch
);
402 case BUTTON_RIGHT
| BUTTON_REL
:
405 mpeg_set_pitch(pitch
);
409 case BUTTON_ON
| BUTTON_LEFT
:
412 mpeg_set_pitch(pitch
);
416 case BUTTON_LEFT
| BUTTON_REL
:
417 if ( pitch
< 2000 ) {
419 mpeg_set_pitch(pitch
);
426 case BUTTON_ON
| BUTTON_REL
:
427 case BUTTON_ON
| BUTTON_UP
| BUTTON_REL
:
428 case BUTTON_ON
| BUTTON_DOWN
| BUTTON_REL
:
433 case BUTTON_ON
| BUTTON_REPEAT
:
438 if(default_event_handler(button
) == SYS_USB_CONNECTED
)
444 lcd_setfont(FONT_UI
);
452 bool quick_screen(int context
, int button
)
458 int oldrepeat
= global_settings
.repeat_mode
;
460 /* just to stop compiler warning */
462 lcd_setfont(FONT_SYSFIXED
);
464 lcd_getstringsize("A",&w
,&h
);
475 lcd_putsxy(0, LCD_HEIGHT
/2 - h
*2, str(LANG_SHUFFLE
));
476 lcd_putsxy(0, LCD_HEIGHT
/2 - h
, str(LANG_F2_MODE
));
477 lcd_putsxy(0, LCD_HEIGHT
/2,
478 global_settings
.playlist_shuffle
?
479 str(LANG_ON
) : str(LANG_OFF
));
481 /* Directory Filter */
482 switch ( global_settings
.dirfilter
) {
484 ptr
= str(LANG_FILTER_ALL
);
488 ptr
= str(LANG_FILTER_SUPPORTED
);
492 ptr
= str(LANG_FILTER_MUSIC
);
496 ptr
= str(LANG_FILTER_PLAYLIST
);
500 snprintf(buf
, sizeof buf
, "%s:", str(LANG_FILTER
));
501 lcd_getstringsize(buf
,&w
,&h
);
502 lcd_putsxy((LCD_WIDTH
-w
)/2, LCD_HEIGHT
- h
*2, buf
);
503 lcd_getstringsize(ptr
,&w
,&h
);
504 lcd_putsxy((LCD_WIDTH
-w
)/2, LCD_HEIGHT
- h
, ptr
);
507 switch ( global_settings
.repeat_mode
) {
513 ptr
= str(LANG_REPEAT_ALL
);
517 ptr
= str(LANG_REPEAT_ONE
);
521 lcd_getstringsize(str(LANG_REPEAT
),&w
,&h
);
522 lcd_putsxy(LCD_WIDTH
- w
, LCD_HEIGHT
/2 - h
*2, str(LANG_REPEAT
));
523 lcd_putsxy(LCD_WIDTH
- w
, LCD_HEIGHT
/2 - h
, str(LANG_F2_MODE
));
524 lcd_putsxy(LCD_WIDTH
- w
, LCD_HEIGHT
/2, ptr
);
528 lcd_putsxy(0, LCD_HEIGHT
/2 - h
*2, str(LANG_F3_SCROLL
));
529 lcd_putsxy(0, LCD_HEIGHT
/2 - h
, str(LANG_F3_BAR
));
530 lcd_putsxy(0, LCD_HEIGHT
/2,
531 global_settings
.scrollbar
? str(LANG_ON
) : str(LANG_OFF
));
534 ptr
= str(LANG_F3_STATUS
);
535 lcd_getstringsize(ptr
,&w
,&h
);
536 lcd_putsxy(LCD_WIDTH
- w
, LCD_HEIGHT
/2 - h
*2, ptr
);
537 lcd_putsxy(LCD_WIDTH
- w
, LCD_HEIGHT
/2 - h
, str(LANG_F3_BAR
));
538 lcd_putsxy(LCD_WIDTH
- w
, LCD_HEIGHT
/2,
539 global_settings
.statusbar
? str(LANG_ON
) : str(LANG_OFF
));
542 ptr
= str(LANG_FLIP_DISPLAY
);
543 lcd_getstringsize(ptr
,&w
,&h
);
544 lcd_putsxy((LCD_WIDTH
-w
)/2, LCD_HEIGHT
- h
*2, str(LANG_FLIP_DISPLAY
));
545 ptr
= global_settings
.flip_display
?
546 str(LANG_SET_BOOL_YES
) : str(LANG_SET_BOOL_NO
);
547 lcd_getstringsize(ptr
,&w
,&h
);
548 lcd_putsxy((LCD_WIDTH
-w
)/2, LCD_HEIGHT
- h
, ptr
);
552 lcd_bitmap(bitmap_icons_7x8
[Icon_FastBackward
],
553 LCD_WIDTH
/2 - 16, LCD_HEIGHT
/2 - 4, 7, 8, true);
554 lcd_bitmap(bitmap_icons_7x8
[Icon_DownArrow
],
555 LCD_WIDTH
/2 - 3, LCD_HEIGHT
- h
*3, 7, 8, true);
556 lcd_bitmap(bitmap_icons_7x8
[Icon_FastForward
],
557 LCD_WIDTH
/2 + 8, LCD_HEIGHT
/2 - 4, 7, 8, true);
560 key
= button_get(true);
563 * This is a temporary kludge so that the F2 & F3 menus operate in exactly
564 * the same manner up until the full F2/F3 configurable menus are complete
567 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
) )
571 case BUTTON_F2
| BUTTON_LEFT
:
572 case BUTTON_F2
| BUTTON_LEFT
| BUTTON_REPEAT
:
573 global_settings
.playlist_shuffle
=
574 !global_settings
.playlist_shuffle
;
576 if(mpeg_status() & MPEG_STATUS_PLAY
)
578 if (global_settings
.playlist_shuffle
)
579 playlist_randomise(NULL
, current_tick
, true);
581 playlist_sort(NULL
, true);
586 case BUTTON_F2
| BUTTON_DOWN
:
587 case BUTTON_F2
| BUTTON_DOWN
| BUTTON_REPEAT
:
588 global_settings
.dirfilter
++;
589 if ( global_settings
.dirfilter
>= NUM_FILTER_MODES
)
590 global_settings
.dirfilter
= 0;
594 case BUTTON_F2
| BUTTON_RIGHT
:
595 case BUTTON_F2
| BUTTON_RIGHT
| BUTTON_REPEAT
:
596 global_settings
.repeat_mode
++;
597 if ( global_settings
.repeat_mode
>= NUM_REPEAT_MODES
)
598 global_settings
.repeat_mode
= 0;
602 case BUTTON_F3
| BUTTON_LEFT
:
603 case BUTTON_F3
| BUTTON_LEFT
| BUTTON_REPEAT
:
604 global_settings
.scrollbar
= !global_settings
.scrollbar
;
608 case BUTTON_F3
| BUTTON_RIGHT
:
609 case BUTTON_F3
| BUTTON_RIGHT
| BUTTON_REPEAT
:
610 global_settings
.statusbar
= !global_settings
.statusbar
;
614 case BUTTON_F3
| BUTTON_DOWN
:
615 case BUTTON_F3
| BUTTON_DOWN
| BUTTON_REPEAT
:
616 case BUTTON_F3
| BUTTON_UP
:
617 case BUTTON_F3
| BUTTON_UP
| BUTTON_REPEAT
:
618 global_settings
.flip_display
= !global_settings
.flip_display
;
619 button_set_flip(global_settings
.flip_display
);
620 lcd_set_flip(global_settings
.flip_display
);
624 case BUTTON_F3
| BUTTON_REL
:
625 case BUTTON_F2
| BUTTON_REL
:
634 case BUTTON_OFF
| BUTTON_REPEAT
:
638 if(default_event_handler(key
) == SYS_USB_CONNECTED
)
650 if ( oldrepeat
!= global_settings
.repeat_mode
)
651 mpeg_flush_and_reload_tracks();
656 if (global_settings
.statusbar
)
657 lcd_setmargins(0, STATUSBAR_HEIGHT
);
659 lcd_setmargins(0, 0);
664 lcd_setfont(FONT_UI
);
670 #ifdef HAVE_LCD_BITMAP
671 #define SPACE 3 /* pixels between words */
672 #define MAXLETTERS 128 /* 16*8 */
675 #define SPACE 1 /* one letter space */
680 #define MAXLETTERS 22 /* 11 * 2 */
684 void splash(int ticks
, /* how long the splash is displayed */
685 bool center
, /* FALSE means left-justified, TRUE means
686 horizontal and vertical center */
687 const char *fmt
, /* what to say *printf style */
695 unsigned char splash_buf
[MAXLETTERS
];
697 unsigned char widths
[MAXLINES
];
700 #ifdef HAVE_LCD_BITMAP
704 #ifdef HAVE_LCD_CHARCELLS
705 lcd_double_height (false);
708 vsnprintf( splash_buf
, sizeof(splash_buf
), fmt
, ap
);
712 /* first a pass to measure sizes */
713 next
= strtok_r(splash_buf
, " ", &store
);
715 #ifdef HAVE_LCD_BITMAP
716 lcd_getstringsize(next
, &w
, &h
);
719 h
= 1; /* store height in characters */
726 if((y
> (LCD_HEIGHT
-h
)) || (line
> MAXLINES
))
736 /* think of it as if the text was written here at position x,y
737 being w pixels/chars wide and h high */
740 widths
[line
]=x
-SPACE
; /* don't count the trailing space */
741 #ifdef HAVE_LCD_BITMAP
742 /* store the widest line */
743 if(widths
[line
]>maxw
)
746 next
= strtok_r(NULL
, " ", &store
);
748 #ifdef HAVE_LCD_BITMAP
749 /* Start displaying the message at position y. The reason for the
750 added h here is that it isn't added until the end of lines in the
751 loop above and we always break the loop in the middle of a line. */
752 y
= (LCD_HEIGHT
- (y
+h
) )/2;
754 y
= 0; /* vertical center on 2 lines would be silly */
758 /* Now recreate the string again since the strtok_r() above has ruined
759 the one we already have! Here's room for improvements! */
760 vsnprintf( splash_buf
, sizeof(splash_buf
), fmt
, ap
);
766 x
= (LCD_WIDTH
-widths
[0])/2;
771 #ifdef HAVE_LCD_BITMAP
772 /* If we center the display and it wouldn't cover the full screen,
773 then just clear the box we need and put a nice little frame and
774 put the text in there! */
775 if(center
&& (y
> 2)) {
776 if(maxw
< (LCD_WIDTH
-4)) {
777 int xx
= (LCD_WIDTH
-maxw
)/2 - 2;
778 lcd_clearrect(xx
, y
-2, maxw
+4, LCD_HEIGHT
-y
*2+4);
779 lcd_drawrect(xx
, y
-2, maxw
+4, LCD_HEIGHT
-y
*2+4);
782 lcd_clearrect(0, y
-2, LCD_WIDTH
, LCD_HEIGHT
-y
*2+4);
783 lcd_drawline(0, y
-2, LCD_WIDTH
-1, y
-2);
784 lcd_drawline(0, LCD_HEIGHT
-y
+2, LCD_WIDTH
-1, LCD_HEIGHT
-y
+2);
791 next
= strtok_r(splash_buf
, " ", &store
);
793 #ifdef HAVE_LCD_BITMAP
794 lcd_getstringsize(next
, &w
, &h
);
803 line
++; /* goto next line */
805 if(y
> (LCD_HEIGHT
-h
))
809 x
= (LCD_WIDTH
-widths
[line
])/2;
819 #ifdef HAVE_LCD_BITMAP
820 lcd_putsxy(x
, y
, next
);
822 lcd_puts(x
, y
, next
);
824 x
+= w
+SPACE
; /* pixels space! */
825 next
= strtok_r(NULL
, " ", &store
);
834 void charging_splash(void)
836 splash(2*HZ
, true, str(LANG_BATTERY_CHARGE
));
837 while (button_get(false));
841 #ifdef HAVE_LCD_BITMAP
843 /* little helper function for voice output */
844 static void say_time(int cursorpos
, const struct tm
*tm
)
846 static const int unit
[] = { UNIT_HOUR
, UNIT_MIN
, UNIT_SEC
, 0, 0, 0 };
849 if (!global_settings
.talk_menu
)
864 value
= tm
->tm_year
+ 1900;
871 if (cursorpos
== 4) /* month */
872 talk_id(LANG_MONTH_JANUARY
+ tm
->tm_mon
, false);
874 talk_value(value
, unit
[cursorpos
], false);
880 #define INDEX_WIDTH 2
881 bool set_time_screen(const char* string
, struct tm
*tm
)
885 int min
= 0, steps
= 0;
887 int lastcursorpos
= !cursorpos
;
888 unsigned char buffer
[19];
892 unsigned char reffub
[5];
893 unsigned int width
, height
;
894 unsigned int separator_width
, weekday_width
;
895 unsigned int line_height
, prev_line_height
;
897 static const int dayname
[] = {
900 LANG_WEEKDAY_TUESDAY
,
901 LANG_WEEKDAY_WEDNESDAY
,
902 LANG_WEEKDAY_THURSDAY
,
904 LANG_WEEKDAY_SATURDAY
906 static const int monthname
[] = {
915 LANG_MONTH_SEPTEMBER
,
920 char cursor
[][3] = {{ 0, 8, 12}, {18, 8, 12}, {36, 8, 12},
921 {24, 16, 24}, {54, 16, 18}, {78, 16, 12}};
922 char daysinmonth
[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
924 int monthname_len
= 0, dayname_len
= 0;
928 #ifdef HAVE_LCD_BITMAP
929 if(global_settings
.statusbar
)
930 lcd_setmargins(0, STATUSBAR_HEIGHT
);
932 lcd_setmargins(0, 0);
935 lcd_puts_scroll(0, 0, string
);
938 /* calculate the number of days in febuary */
939 realyear
= tm
->tm_year
+ 1900;
940 if((realyear
% 4 == 0 && !(realyear
% 100 == 0)) || realyear
% 400 == 0)
945 /* fix day if month or year changed */
946 if (tm
->tm_mday
> daysinmonth
[tm
->tm_mon
])
947 tm
->tm_mday
= daysinmonth
[tm
->tm_mon
];
949 /* calculate day of week */
951 for(i
= 0; i
< tm
->tm_mon
; i
++) {
952 julianday
+= daysinmonth
[i
];
954 julianday
+= tm
->tm_mday
;
955 tm
->tm_wday
= (realyear
+ julianday
+ (realyear
- 1) / 4 -
956 (realyear
- 1) / 100 + (realyear
- 1) / 400 + 7 - 1) % 7;
958 snprintf(buffer
, sizeof(buffer
), "%02d:%02d:%02d ",
959 tm
->tm_hour
, tm
->tm_min
, tm
->tm_sec
);
960 lcd_puts(0, 1, buffer
);
962 /* recalculate the positions and offsets */
963 lcd_getstringsize(string
, &width
, &prev_line_height
);
964 lcd_getstringsize(buffer
, &width
, &line_height
);
965 lcd_getstringsize(":", &separator_width
, &height
);
968 strncpy(reffub
, buffer
, 2);
970 lcd_getstringsize(reffub
, &width
, &height
);
971 cursor
[0][INDEX_X
] = 0;
972 cursor
[0][INDEX_Y
] = prev_line_height
;
973 cursor
[0][INDEX_WIDTH
] = width
;
976 strncpy(reffub
, buffer
+ 3, 2);
978 lcd_getstringsize(reffub
, &width
, &height
);
979 cursor
[1][INDEX_X
] = cursor
[0][INDEX_WIDTH
] + separator_width
;
980 cursor
[1][INDEX_Y
] = prev_line_height
;
981 cursor
[1][INDEX_WIDTH
] = width
;
984 strncpy(reffub
, buffer
+ 6, 2);
986 lcd_getstringsize(reffub
, &width
, &height
);
987 cursor
[2][INDEX_X
] = cursor
[0][INDEX_WIDTH
] + separator_width
+
988 cursor
[1][INDEX_WIDTH
] + separator_width
;
989 cursor
[2][INDEX_Y
] = prev_line_height
;
990 cursor
[2][INDEX_WIDTH
] = width
;
992 lcd_getstringsize(buffer
, &width
, &prev_line_height
);
994 snprintf(buffer
, sizeof(buffer
), "%s %04d %s %02d ",
995 str(dayname
[tm
->tm_wday
]), tm
->tm_year
+1900,
996 str(monthname
[tm
->tm_mon
]), tm
->tm_mday
);
997 lcd_puts(0, 2, buffer
);
999 /* recalculate the positions and offsets */
1000 lcd_getstringsize(buffer
, &width
, &line_height
);
1002 /* store these 2 to prevent _repeated_ strlen calls */
1003 monthname_len
= strlen(str(monthname
[tm
->tm_mon
]));
1004 dayname_len
= strlen(str(dayname
[tm
->tm_wday
]));
1007 strncpy(reffub
, buffer
, dayname_len
);
1008 reffub
[dayname_len
] = '\0';
1009 lcd_getstringsize(reffub
, &weekday_width
, &height
);
1010 lcd_getstringsize(" ", &separator_width
, &height
);
1013 strncpy(reffub
, buffer
+ dayname_len
+ 1, 4);
1015 lcd_getstringsize(reffub
, &width
, &height
);
1016 cursor
[3][INDEX_X
] = weekday_width
+ separator_width
;
1017 cursor
[3][INDEX_Y
] = cursor
[0][INDEX_Y
] + prev_line_height
;
1018 cursor
[3][INDEX_WIDTH
] = width
;
1021 strncpy(reffub
, buffer
+ dayname_len
+ 6, monthname_len
);
1022 reffub
[monthname_len
] = '\0';
1023 lcd_getstringsize(reffub
, &width
, &height
);
1024 cursor
[4][INDEX_X
] = weekday_width
+ separator_width
+
1025 cursor
[3][INDEX_WIDTH
] + separator_width
;
1026 cursor
[4][INDEX_Y
] = cursor
[0][INDEX_Y
] + prev_line_height
;
1027 cursor
[4][INDEX_WIDTH
] = width
;
1030 strncpy(reffub
, buffer
+ dayname_len
+ monthname_len
+ 7, 2);
1032 lcd_getstringsize(reffub
, &width
, &height
);
1033 cursor
[5][INDEX_X
] = weekday_width
+ separator_width
+
1034 cursor
[3][INDEX_WIDTH
] + separator_width
+
1035 cursor
[4][INDEX_WIDTH
] + separator_width
;
1036 cursor
[5][INDEX_Y
] = cursor
[0][INDEX_Y
] + prev_line_height
;
1037 cursor
[5][INDEX_WIDTH
] = width
;
1039 lcd_invertrect(cursor
[cursorpos
][INDEX_X
],
1040 cursor
[cursorpos
][INDEX_Y
] + lcd_getymargin(),
1041 cursor
[cursorpos
][INDEX_WIDTH
],
1044 lcd_puts(0, 4, str(LANG_TIME_SET
));
1045 lcd_puts(0, 5, str(LANG_TIME_REVERT
));
1046 #ifdef HAVE_LCD_BITMAP
1051 /* calculate the minimum and maximum for the number under cursor */
1052 if(cursorpos
!=lastcursorpos
) {
1053 lastcursorpos
=cursorpos
;
1058 valptr
= &tm
->tm_hour
;
1060 case 1: /* minute */
1063 valptr
= &tm
->tm_min
;
1065 case 2: /* second */
1068 valptr
= &tm
->tm_sec
;
1073 valptr
= &tm
->tm_year
;
1078 valptr
= &tm
->tm_mon
;
1082 steps
= daysinmonth
[tm
->tm_mon
];
1083 valptr
= &tm
->tm_mday
;
1086 say_time(cursorpos
, tm
);
1089 button
= button_get_w_tmo(HZ
/2);
1092 cursorpos
= (cursorpos
+ 6 - 1) % 6;
1095 cursorpos
= (cursorpos
+ 6 + 1) % 6;
1098 case BUTTON_UP
| BUTTON_REPEAT
:
1099 *valptr
= (*valptr
+ steps
- min
+ 1) %
1103 say_time(cursorpos
, tm
);
1106 case BUTTON_DOWN
| BUTTON_REPEAT
:
1107 *valptr
= (*valptr
+ steps
- min
- 1) %
1111 say_time(cursorpos
, tm
);
1116 #elif defined BUTTON_MENU
1128 if (default_event_handler(button
) == SYS_USB_CONNECTED
)
1138 #if CONFIG_KEYPAD == RECORDER_PAD
1139 bool shutdown_screen(void)
1146 splash(0, true, str(LANG_CONFIRM_SHUTDOWN
));
1150 button
= button_get_w_tmo(HZ
*2);
1158 if(default_event_handler(button
) == SYS_USB_CONNECTED
)
1161 /* Return if any other button was pushed, or if there
1162 was a timeout. We ignore RELEASE events, since we may
1163 have been called by a button down event, and the user might
1164 not have released the button yet.
1165 We also ignore REPEAT events, since we don't want to
1166 remove the splash when the user holds OFF to shut down. */
1167 if(!(button
& (BUTTON_REL
| BUTTON_REPEAT
)))
1176 bool browse_id3(void)
1178 struct mp3entry
* id3
= mpeg_current_track();
1183 char scroll_text
[MAX_PATH
];
1185 if (!(mpeg_status() & MPEG_STATUS_PLAY
))
1190 lcd_clear_display();
1195 lcd_puts(0, 0, str(LANG_ID3_TITLE
));
1196 lcd_puts_scroll(0, 1, id3
->title
? id3
->title
:
1197 (char*)str(LANG_ID3_NO_TITLE
));
1201 lcd_puts(0, 0, str(LANG_ID3_ARTIST
));
1202 lcd_puts_scroll(0, 1,
1203 id3
->artist
? id3
->artist
:
1204 (char*)str(LANG_ID3_NO_ARTIST
));
1208 lcd_puts(0, 0, str(LANG_ID3_ALBUM
));
1209 lcd_puts_scroll(0, 1, id3
->album
? id3
->album
:
1210 (char*)str(LANG_ID3_NO_ALBUM
));
1214 lcd_puts(0, 0, str(LANG_ID3_TRACKNUM
));
1216 if (id3
->tracknum
) {
1217 snprintf(scroll_text
,sizeof(scroll_text
), "%d",
1219 lcd_puts_scroll(0, 1, scroll_text
);
1222 lcd_puts_scroll(0, 1, str(LANG_ID3_NO_TRACKNUM
));
1226 lcd_puts(0, 0, str(LANG_ID3_GENRE
));
1227 lcd_puts_scroll(0, 1,
1228 id3_get_genre(id3
) ?
1229 id3_get_genre(id3
) :
1230 (char*)str(LANG_ID3_NO_INFO
));
1234 lcd_puts(0, 0, str(LANG_ID3_YEAR
));
1236 snprintf(scroll_text
,sizeof(scroll_text
), "%d",
1238 lcd_puts_scroll(0, 1, scroll_text
);
1241 lcd_puts_scroll(0, 1, str(LANG_ID3_NO_INFO
));
1245 lcd_puts(0, 0, str(LANG_ID3_LENGHT
));
1246 snprintf(scroll_text
,sizeof(scroll_text
), "%d:%02d",
1247 id3
->length
/ 60000,
1248 id3
->length
% 60000 / 1000 );
1249 lcd_puts(0, 1, scroll_text
);
1253 lcd_puts(0, 0, str(LANG_ID3_PLAYLIST
));
1254 snprintf(scroll_text
,sizeof(scroll_text
), "%d/%d",
1255 playlist_get_display_index(), playlist_amount());
1256 lcd_puts_scroll(0, 1, scroll_text
);
1261 lcd_puts(0, 0, str(LANG_ID3_BITRATE
));
1262 snprintf(scroll_text
,sizeof(scroll_text
), "%d kbps",
1264 lcd_puts(0, 1, scroll_text
);
1268 lcd_puts(0, 0, str(LANG_ID3_FRECUENCY
));
1269 snprintf(scroll_text
,sizeof(scroll_text
), "%d Hz",
1271 lcd_puts(0, 1, scroll_text
);
1275 lcd_puts(0, 0, str(LANG_ID3_PATH
));
1276 lcd_puts_scroll(0, 1, id3
->path
);
1281 button
= button_get(true);
1289 menu_pos
= menu_max
;
1293 if (menu_pos
< menu_max
)
1299 case SETTINGS_CANCEL
:
1301 /* eat release event */
1307 if(default_event_handler(button
) == SYS_USB_CONNECTED
)