Added .S files in drivers
[kugel-rb.git] / apps / screens.c
blobb563155bdea8edae1f32592459763cf8d69e66e4
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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 ****************************************************************************/
19 #include <stdbool.h>
20 #include <string.h>
21 #include <stdio.h>
22 #include "backlight.h"
23 #include "button.h"
24 #include "lcd.h"
25 #include "lang.h"
26 #include "icons.h"
27 #include "font.h"
28 #include "mpeg.h"
29 #include "mp3_playback.h"
30 #include "usb.h"
31 #include "settings.h"
32 #include "status.h"
33 #include "playlist.h"
34 #include "sprintf.h"
35 #include "kernel.h"
36 #include "power.h"
37 #include "system.h"
38 #include "powermgmt.h"
39 #include "adc.h"
40 #include "action.h"
41 #include "talk.h"
43 #ifdef HAVE_LCD_BITMAP
44 #define BMPHEIGHT_usb_logo 32
45 #define BMPWIDTH_usb_logo 100
46 static unsigned char usb_logo[] = {
47 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
48 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
49 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0x10, 0x08,
50 0x04, 0x04, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
51 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x81, 0x81, 0x81, 0x81,
52 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
53 0x01, 0x01, 0x01, 0x01, 0xf1, 0x4f, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
54 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0xc0,
55 0x00, 0x00, 0xe0, 0x1c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
56 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
57 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x06, 0x81, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0,
58 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x1c,
59 0x0c, 0x0e, 0x0e, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0f, 0x1f, 0x1f, 0x1f, 0x1f,
60 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0x00,
61 0x00, 0x00, 0xe0, 0x1f, 0x00, 0xf8, 0x06, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
62 0x02, 0x02, 0x02, 0x82, 0x7e, 0x00, 0xc0, 0x3e, 0x01,
63 0x70, 0x4f, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
64 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
65 0x40, 0x40, 0x40, 0x40, 0x40, 0x80, 0x00, 0x07, 0x0f, 0x1f, 0x1f, 0x1f, 0x1f,
66 0x0f, 0x07, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07, 0x0f,
67 0x1f, 0x3f, 0x7b, 0xf3, 0xe3, 0xc3, 0x83, 0x83, 0x83, 0x83, 0xe3, 0xe3, 0xe3,
68 0xe3, 0xe3, 0xe3, 0x03, 0x03, 0x03, 0x3f, 0x1f, 0x1f, 0x0f, 0x0f, 0x07, 0x02,
69 0xc0, 0x3e, 0x01, 0xe0, 0x9f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
70 0x80, 0x80, 0xf0, 0x0f, 0x80, 0x78, 0x07, 0x00, 0x00,
71 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0c, 0x10, 0x20, 0x40, 0x40, 0x80, 0x80,
74 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
75 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x81, 0x81, 0x87, 0x87, 0x87,
76 0x87, 0x87, 0x87, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xf0,
77 0x0f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
78 0x04, 0x04, 0x04, 0x04, 0x07, 0x00, 0x00, 0x00, 0x00,
80 #endif
82 void usb_display_info(void)
84 lcd_clear_display();
86 #ifdef HAVE_LCD_BITMAP
87 /* lcd_bitmap() only supports 16 pixels height! */
88 lcd_bitmap(usb_logo, 6, 16,
89 BMPWIDTH_usb_logo, 8, false);
90 lcd_bitmap(usb_logo+BMPWIDTH_usb_logo, 6, 24,
91 BMPWIDTH_usb_logo, 8, false);
92 lcd_bitmap(usb_logo+BMPWIDTH_usb_logo*2, 6, 32,
93 BMPWIDTH_usb_logo, 8, false);
94 lcd_bitmap(usb_logo+BMPWIDTH_usb_logo*3, 6, 40,
95 BMPWIDTH_usb_logo, 8, false);
96 status_draw(true);
97 lcd_update();
98 #else
99 lcd_puts(0, 0, "[USB Mode]");
100 status_set_param(false);
101 status_set_audio(false);
102 status_set_usb(true);
103 status_draw(false);
104 #endif
107 void usb_screen(void)
109 #ifdef USB_NONE
110 /* nothing here! */
111 #else
112 #ifndef SIMULATOR
113 backlight_on();
114 usb_acknowledge(SYS_USB_CONNECTED_ACK);
115 usb_display_info();
116 while(usb_wait_for_disconnect_w_tmo(&button_queue, HZ)) {
117 if(usb_inserted()) {
118 status_draw(false);
121 #ifdef HAVE_LCD_CHARCELLS
122 status_set_usb(false);
123 #endif
125 backlight_on();
126 #endif
127 #endif /* USB_NONE */
131 /* some simulator dummies */
132 #ifdef SIMULATOR
133 #define BATTERY_SCALE_FACTOR 7000
134 unsigned short adc_read(int channel)
136 (void)channel;
137 return 100;
139 #endif
142 #ifdef HAVE_LCD_BITMAP
143 void charging_display_info(bool animate)
145 unsigned char charging_logo[36];
146 const int pox_x = (LCD_WIDTH - sizeof(charging_logo)) / 2;
147 const int pox_y = 32;
148 static unsigned phase = 3;
149 unsigned i;
150 char buf[32];
151 (void)buf;
153 #ifdef NEED_ATA_POWER_BATT_MEASURE
154 if (ide_powered()) /* FM and V2 can only measure when ATA power is on */
155 #endif
157 int battery_voltage;
158 int batt_int, batt_frac;
160 battery_voltage = (adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR) / 10000;
161 batt_int = battery_voltage / 100;
162 batt_frac = battery_voltage % 100;
164 snprintf(buf, 32, " Batt: %d.%02dV %d%% ", batt_int, batt_frac,
165 battery_level());
166 lcd_puts(0, 7, buf);
169 #ifdef HAVE_CHARGE_CTRL
171 snprintf(buf, 32, "Charge mode:");
172 lcd_puts(0, 2, buf);
174 if (charge_state == 1)
175 snprintf(buf, 32, str(LANG_BATTERY_CHARGE));
176 else if (charge_state == 2)
177 snprintf(buf, 32, str(LANG_BATTERY_TOPOFF_CHARGE));
178 else if (charge_state == 3)
179 snprintf(buf, 32, str(LANG_BATTERY_TRICKLE_CHARGE));
180 else
181 snprintf(buf, 32, "not charging");
183 lcd_puts(0, 3, buf);
184 if (charger_enabled)
186 backlight_on(); /* using the light gives good indication */
188 else
190 backlight_off();
191 animate = false;
193 #endif
196 /* middle part */
197 memset(charging_logo+3, 0x00, 32);
198 charging_logo[0] = 0x3C;
199 charging_logo[1] = 0x24;
200 charging_logo[2] = charging_logo[35] = 0xFF;
202 if (!animate)
203 { /* draw the outline */
204 /* middle part */
205 lcd_bitmap(charging_logo, pox_x, pox_y + 8, sizeof(charging_logo), 8, true);
206 /* upper line */
207 charging_logo[0] = charging_logo[1] = 0x00;
208 memset(charging_logo+2, 0x80, 34);
209 lcd_bitmap(charging_logo, pox_x, pox_y, sizeof(charging_logo), 8, false);
210 /* lower line */
211 memset(charging_logo+2, 0x01, 34);
212 lcd_bitmap(charging_logo, pox_x, pox_y + 16, sizeof(charging_logo), 8, false);
214 else
215 { /* animate the middle part */
216 for (i = 3; i<MIN(sizeof(charging_logo)-1, phase); i++)
218 if ((i-phase) % 8 == 0)
219 { /* draw a "bubble" here */
220 unsigned bitpos;
221 bitpos = (phase + i/8) % 15; /* "bounce" effect */
222 if (bitpos > 7)
223 bitpos = 14 - bitpos;
224 charging_logo[i] = 0x01 << bitpos;
227 lcd_bitmap(charging_logo, pox_x, pox_y + 8, sizeof(charging_logo), 8, true);
228 phase++;
230 lcd_update();
232 #else /* not HAVE_LCD_BITMAP */
233 void charging_display_info(bool animate)
235 /* ToDo for Player */
236 (void)animate;
238 #endif
240 #ifdef HAVE_BATTERIES
241 /* blocks while charging, returns on event:
242 1 if charger cable was removed
243 2 if Off/Stop key was pressed
244 3 if On key was pressed
245 4 if USB was connected */
246 int charging_screen(void)
248 int button;
249 int rc = 0;
250 #ifdef HAVE_RECORDER_KEYPAD
251 const int offbutton = BUTTON_OFF;
252 #else
253 const int offbutton = BUTTON_STOP;
254 #endif
256 ide_power_enable(false); /* power down the disk, else would be spinning */
258 lcd_clear_display();
259 backlight_on();
260 status_draw(true);
262 #ifdef HAVE_LCD_BITMAP
263 charging_display_info(false);
264 #else
265 status_set_playmode(STATUS_STOP);
266 lcd_puts(0, 1, "[charging]");
267 #endif
271 status_draw(false);
272 charging_display_info(true);
273 button = button_get_w_tmo(HZ/3);
274 if (button == (BUTTON_ON | BUTTON_REL))
275 rc = 3;
276 else if (button == offbutton)
277 rc = 2;
278 else
280 if (usb_detect())
281 rc = 4;
282 else if (!charger_inserted())
283 rc = 1;
285 } while (!rc);
287 return rc;
289 #endif /* HAVE_BATTERIES */
292 #ifdef HAVE_RECORDER_KEYPAD
293 /* returns:
294 0 if no key was pressed
295 1 if a key was pressed (or if ON was held down long enough to repeat)
296 2 if USB was connected */
297 int on_screen(void)
299 static int pitch = 1000;
300 bool exit = false;
301 bool used = false;
303 while (!exit) {
305 if ( used ) {
306 char* ptr;
307 char buf[32];
308 int w, h;
310 lcd_clear_display();
311 lcd_setfont(FONT_SYSFIXED);
313 ptr = str(LANG_PITCH_UP);
314 lcd_getstringsize(ptr,&w,&h);
315 lcd_putsxy((LCD_WIDTH-w)/2, 0, ptr);
316 lcd_bitmap(bitmap_icons_7x8[Icon_UpArrow],
317 LCD_WIDTH/2 - 3, h*2, 7, 8, true);
319 snprintf(buf, sizeof buf, "%d.%d%%", pitch / 10, pitch % 10 );
320 lcd_getstringsize(buf,&w,&h);
321 lcd_putsxy((LCD_WIDTH-w)/2, h, buf);
323 ptr = str(LANG_PITCH_DOWN);
324 lcd_getstringsize(ptr,&w,&h);
325 lcd_putsxy((LCD_WIDTH-w)/2, LCD_HEIGHT - h, ptr);
326 lcd_bitmap(bitmap_icons_7x8[Icon_DownArrow],
327 LCD_WIDTH/2 - 3, LCD_HEIGHT - h*3, 7, 8, true);
329 ptr = str(LANG_PAUSE);
330 lcd_getstringsize(ptr,&w,&h);
331 lcd_putsxy((LCD_WIDTH-(w/2))/2, LCD_HEIGHT/2 - h/2, ptr);
332 lcd_bitmap(bitmap_icons_7x8[Icon_Pause],
333 (LCD_WIDTH-(w/2))/2-10, LCD_HEIGHT/2 - h/2, 7, 8, true);
335 lcd_update();
338 /* use lastbutton, so the main loop can decide whether to
339 exit to browser or not */
340 switch (button_get(true)) {
341 case BUTTON_UP:
342 case BUTTON_ON | BUTTON_UP:
343 case BUTTON_ON | BUTTON_UP | BUTTON_REPEAT:
344 used = true;
345 pitch++;
346 if ( pitch > 2000 )
347 pitch = 2000;
348 mpeg_set_pitch(pitch);
349 break;
351 case BUTTON_DOWN:
352 case BUTTON_ON | BUTTON_DOWN:
353 case BUTTON_ON | BUTTON_DOWN | BUTTON_REPEAT:
354 used = true;
355 pitch--;
356 if ( pitch < 500 )
357 pitch = 500;
358 mpeg_set_pitch(pitch);
359 break;
361 case BUTTON_ON | BUTTON_PLAY:
362 mpeg_pause();
363 used = true;
364 break;
366 case BUTTON_PLAY | BUTTON_REL:
367 mpeg_resume();
368 used = true;
369 break;
371 case BUTTON_ON | BUTTON_PLAY | BUTTON_REL:
372 mpeg_resume();
373 exit = true;
374 break;
376 case BUTTON_ON | BUTTON_RIGHT:
377 if ( pitch < 2000 ) {
378 pitch += 20;
379 mpeg_set_pitch(pitch);
381 break;
383 case BUTTON_RIGHT | BUTTON_REL:
384 if ( pitch > 500 ) {
385 pitch -= 20;
386 mpeg_set_pitch(pitch);
388 break;
390 case BUTTON_ON | BUTTON_LEFT:
391 if ( pitch > 500 ) {
392 pitch -= 20;
393 mpeg_set_pitch(pitch);
395 break;
397 case BUTTON_LEFT | BUTTON_REL:
398 if ( pitch < 2000 ) {
399 pitch += 20;
400 mpeg_set_pitch(pitch);
402 break;
404 #ifdef SIMULATOR
405 case BUTTON_ON:
406 #else
407 case BUTTON_ON | BUTTON_REL:
408 case BUTTON_ON | BUTTON_UP | BUTTON_REL:
409 case BUTTON_ON | BUTTON_DOWN | BUTTON_REL:
410 #endif
411 exit = true;
412 break;
414 case BUTTON_ON | BUTTON_REPEAT:
415 used = true;
416 break;
418 case SYS_USB_CONNECTED:
419 usb_screen();
420 return 2;
424 lcd_setfont(FONT_UI);
426 if ( used )
427 return 1;
428 else
429 return 0;
432 bool quick_screen(int context, int button)
434 bool exit = false;
435 bool used = false;
436 int w, h, key;
437 char buf[32];
438 int oldrepeat = global_settings.repeat_mode;
440 /* just to stop compiler warning */
441 context = context;
442 lcd_setfont(FONT_SYSFIXED);
444 if(button==BUTTON_F2)
445 lcd_getstringsize("A",&w,&h);
447 while (!exit) {
448 char* ptr=NULL;
450 lcd_clear_display();
452 switch(button)
454 case BUTTON_F2:
455 /* Shuffle mode */
456 lcd_putsxy(0, LCD_HEIGHT/2 - h*2, str(LANG_SHUFFLE));
457 lcd_putsxy(0, LCD_HEIGHT/2 - h, str(LANG_F2_MODE));
458 lcd_putsxy(0, LCD_HEIGHT/2,
459 global_settings.playlist_shuffle ?
460 str(LANG_ON) : str(LANG_OFF));
462 /* Directory Filter */
463 switch ( global_settings.dirfilter ) {
464 case SHOW_ALL:
465 ptr = str(LANG_FILTER_ALL);
466 break;
468 case SHOW_SUPPORTED:
469 ptr = str(LANG_FILTER_SUPPORTED);
470 break;
472 case SHOW_MUSIC:
473 ptr = str(LANG_FILTER_MUSIC);
474 break;
476 case SHOW_PLAYLIST:
477 ptr = str(LANG_FILTER_PLAYLIST);
478 break;
481 snprintf(buf, sizeof buf, "%s:", str(LANG_FILTER));
482 lcd_getstringsize(buf,&w,&h);
483 lcd_putsxy((LCD_WIDTH-w)/2, LCD_HEIGHT - h*2, buf);
484 lcd_getstringsize(ptr,&w,&h);
485 lcd_putsxy((LCD_WIDTH-w)/2, LCD_HEIGHT - h, ptr);
487 /* Repeat Mode */
488 switch ( global_settings.repeat_mode ) {
489 case REPEAT_OFF:
490 ptr = str(LANG_OFF);
491 break;
493 case REPEAT_ALL:
494 ptr = str(LANG_REPEAT_ALL);
495 break;
497 case REPEAT_ONE:
498 ptr = str(LANG_REPEAT_ONE);
499 break;
502 lcd_getstringsize(str(LANG_REPEAT),&w,&h);
503 lcd_putsxy(LCD_WIDTH - w, LCD_HEIGHT/2 - h*2, str(LANG_REPEAT));
504 lcd_putsxy(LCD_WIDTH - w, LCD_HEIGHT/2 - h, str(LANG_F2_MODE));
505 lcd_putsxy(LCD_WIDTH - w, LCD_HEIGHT/2, ptr);
506 break;
507 case BUTTON_F3:
508 /* Scrollbar */
509 lcd_putsxy(0, LCD_HEIGHT/2 - h*2, str(LANG_F3_SCROLL));
510 lcd_putsxy(0, LCD_HEIGHT/2 - h, str(LANG_F3_BAR));
511 lcd_putsxy(0, LCD_HEIGHT/2,
512 global_settings.scrollbar ? str(LANG_ON) : str(LANG_OFF));
514 /* Status bar */
515 ptr = str(LANG_F3_STATUS);
516 lcd_getstringsize(ptr,&w,&h);
517 lcd_putsxy(LCD_WIDTH - w, LCD_HEIGHT/2 - h*2, ptr);
518 lcd_putsxy(LCD_WIDTH - w, LCD_HEIGHT/2 - h, str(LANG_F3_BAR));
519 lcd_putsxy(LCD_WIDTH - w, LCD_HEIGHT/2,
520 global_settings.statusbar ? str(LANG_ON) : str(LANG_OFF));
522 /* Flip */
523 ptr = str(LANG_FLIP_DISPLAY);
524 lcd_getstringsize(ptr,&w,&h);
525 lcd_putsxy((LCD_WIDTH-w)/2, LCD_HEIGHT - h*2, str(LANG_FLIP_DISPLAY));
526 ptr = global_settings.flip_display ?
527 str(LANG_SET_BOOL_YES) : str(LANG_SET_BOOL_NO);
528 lcd_getstringsize(ptr,&w,&h);
529 lcd_putsxy((LCD_WIDTH-w)/2, LCD_HEIGHT - h, ptr);
530 break;
533 lcd_bitmap(bitmap_icons_7x8[Icon_FastBackward],
534 LCD_WIDTH/2 - 16, LCD_HEIGHT/2 - 4, 7, 8, true);
535 lcd_bitmap(bitmap_icons_7x8[Icon_DownArrow],
536 LCD_WIDTH/2 - 3, LCD_HEIGHT - h*3, 7, 8, true);
537 lcd_bitmap(bitmap_icons_7x8[Icon_FastForward],
538 LCD_WIDTH/2 + 8, LCD_HEIGHT/2 - 4, 7, 8, true);
540 lcd_update();
541 key = button_get(true);
544 * This is a temporary kludge so that the F2 & F3 menus operate in exactly
545 * the same manner up until the full F2/F3 configurable menus are complete
548 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 ) )
549 key = button | key;
551 switch (key) {
552 case BUTTON_F2 | BUTTON_LEFT:
553 case BUTTON_F2 | BUTTON_LEFT | BUTTON_REPEAT:
554 global_settings.playlist_shuffle =
555 !global_settings.playlist_shuffle;
557 if(mpeg_status() & MPEG_STATUS_PLAY)
559 if (global_settings.playlist_shuffle)
560 playlist_randomise(NULL, current_tick, true);
561 else
562 playlist_sort(NULL, true);
564 used = true;
565 break;
567 case BUTTON_F2 | BUTTON_DOWN:
568 case BUTTON_F2 | BUTTON_DOWN | BUTTON_REPEAT:
569 global_settings.dirfilter++;
570 if ( global_settings.dirfilter >= NUM_FILTER_MODES )
571 global_settings.dirfilter = 0;
572 used = true;
573 break;
575 case BUTTON_F2 | BUTTON_RIGHT:
576 case BUTTON_F2 | BUTTON_RIGHT | BUTTON_REPEAT:
577 global_settings.repeat_mode++;
578 if ( global_settings.repeat_mode >= NUM_REPEAT_MODES )
579 global_settings.repeat_mode = 0;
580 used = true;
581 break;
583 case BUTTON_F3 | BUTTON_LEFT:
584 case BUTTON_F3 | BUTTON_LEFT | BUTTON_REPEAT:
585 global_settings.scrollbar = !global_settings.scrollbar;
586 used = true;
587 break;
589 case BUTTON_F3 | BUTTON_RIGHT:
590 case BUTTON_F3 | BUTTON_RIGHT | BUTTON_REPEAT:
591 global_settings.statusbar = !global_settings.statusbar;
592 used = true;
593 break;
595 case BUTTON_F3 | BUTTON_DOWN:
596 case BUTTON_F3 | BUTTON_DOWN | BUTTON_REPEAT:
597 case BUTTON_F3 | BUTTON_UP:
598 case BUTTON_F3 | BUTTON_UP | BUTTON_REPEAT:
599 global_settings.flip_display = !global_settings.flip_display;
600 button_set_flip(global_settings.flip_display);
601 lcd_set_flip(global_settings.flip_display);
602 used = true;
603 break;
605 case BUTTON_F3 | BUTTON_REL:
606 case BUTTON_F2 | BUTTON_REL:
608 if( used )
609 exit = true;
611 used = true;
613 break;
615 case BUTTON_OFF | BUTTON_REPEAT:
616 return false;
618 case SYS_USB_CONNECTED:
619 usb_screen();
620 return true;
624 settings_save();
626 switch( button )
628 case BUTTON_F2:
630 if ( oldrepeat != global_settings.repeat_mode )
631 mpeg_flush_and_reload_tracks();
633 break;
634 case BUTTON_F3:
636 if (global_settings.statusbar)
637 lcd_setmargins(0, STATUSBAR_HEIGHT);
638 else
639 lcd_setmargins(0, 0);
641 break;
644 lcd_setfont(FONT_UI);
646 return false;
648 #endif
650 #ifdef HAVE_LCD_BITMAP
651 #define SPACE 3 /* pixels between words */
652 #define MAXLETTERS 128 /* 16*8 */
653 #define MAXLINES 10
654 #else
655 #define SPACE 1 /* one letter space */
656 #undef LCD_WIDTH
657 #define LCD_WIDTH 11
658 #undef LCD_HEIGHT
659 #define LCD_HEIGHT 2
660 #define MAXLETTERS 22 /* 11 * 2 */
661 #define MAXLINES 2
662 #endif
664 void splash(int ticks, /* how long the splash is displayed */
665 bool center, /* FALSE means left-justified, TRUE means
666 horizontal and vertical center */
667 char *fmt, /* what to say *printf style */
668 ...)
670 char *next;
671 char *store=NULL;
672 int x=0;
673 int y=0;
674 int w, h;
675 unsigned char splash_buf[MAXLETTERS];
676 va_list ap;
677 unsigned char widths[MAXLINES];
678 int line=0;
679 bool first=true;
680 #ifdef HAVE_LCD_BITMAP
681 int maxw=0;
682 #endif
684 va_start( ap, fmt );
685 vsnprintf( splash_buf, sizeof(splash_buf), fmt, ap );
687 if(center) {
689 /* first a pass to measure sizes */
690 next = strtok_r(splash_buf, " ", &store);
691 while (next) {
692 #ifdef HAVE_LCD_BITMAP
693 lcd_getstringsize(next, &w, &h);
694 #else
695 w = strlen(next);
696 h = 1; /* store height in characters */
697 #endif
698 if(!first) {
699 if(x+w> LCD_WIDTH) {
700 /* Too wide, wrap */
701 y+=h;
702 line++;
703 if((y > (LCD_HEIGHT-h)) || (line > MAXLINES))
704 /* STOP */
705 break;
706 x=0;
707 first=true;
710 else
711 first = false;
713 /* think of it as if the text was written here at position x,y
714 being w pixels/chars wide and h high */
716 x += w+SPACE;
717 widths[line]=x-SPACE; /* don't count the trailing space */
718 #ifdef HAVE_LCD_BITMAP
719 /* store the widest line */
720 if(widths[line]>maxw)
721 maxw = widths[line];
722 #endif
723 next = strtok_r(NULL, " ", &store);
725 #ifdef HAVE_LCD_BITMAP
726 /* Start displaying the message at position y. The reason for the
727 added h here is that it isn't added until the end of lines in the
728 loop above and we always break the loop in the middle of a line. */
729 y = (LCD_HEIGHT - (y+h) )/2;
730 #else
731 y = 0; /* vertical center on 2 lines would be silly */
732 #endif
733 first=true;
735 /* Now recreate the string again since the strtok_r() above has ruined
736 the one we already have! Here's room for improvements! */
737 vsnprintf( splash_buf, sizeof(splash_buf), fmt, ap );
739 va_end( ap );
741 if(center)
743 x = (LCD_WIDTH-widths[0])/2;
744 if(x < 0)
745 x = 0;
748 #ifdef HAVE_LCD_BITMAP
749 /* If we center the display and it wouldn't cover the full screen,
750 then just clear the box we need and put a nice little frame and
751 put the text in there! */
752 if(center && (y > 2)) {
753 if(maxw < (LCD_WIDTH -4)) {
754 int xx = (LCD_WIDTH-maxw)/2 - 2;
755 lcd_clearrect(xx, y-2, maxw+4, LCD_HEIGHT-y*2+4);
756 lcd_drawrect(xx, y-2, maxw+4, LCD_HEIGHT-y*2+4);
758 else {
759 lcd_clearrect(0, y-2, LCD_WIDTH, LCD_HEIGHT-y*2+4);
760 lcd_drawline(0, y-2, LCD_WIDTH-1, y-2);
761 lcd_drawline(0, LCD_HEIGHT-y+2, LCD_WIDTH-1, LCD_HEIGHT-y+2);
764 else
765 #endif
766 lcd_clear_display();
767 line=0;
768 next = strtok_r(splash_buf, " ", &store);
769 while (next) {
770 #ifdef HAVE_LCD_BITMAP
771 lcd_getstringsize(next, &w, &h);
772 #else
773 w = strlen(next);
774 h = 1;
775 #endif
776 if(!first) {
777 if(x+w> LCD_WIDTH) {
778 /* too wide */
779 y+=h;
780 line++; /* goto next line */
781 first=true;
782 if(y > (LCD_HEIGHT-h))
783 /* STOP */
784 break;
785 if(center)
786 x = (LCD_WIDTH-widths[line])/2;
787 else
788 x=0;
791 else
792 first=false;
793 #ifdef HAVE_LCD_BITMAP
794 lcd_putsxy(x, y, next);
795 #else
796 lcd_puts(x, y, next);
797 #endif
798 x += w+SPACE; /* pixels space! */
799 next = strtok_r(NULL, " ", &store);
801 lcd_update();
803 if(ticks)
804 /* unbreakable! */
805 sleep(ticks);
808 void charging_splash(void)
810 splash(2*HZ, true, str(LANG_BATTERY_CHARGE));
811 while (button_get(false));
815 #ifdef HAVE_LCD_BITMAP
817 /* little helper function for voice output */
818 static void say_time(int cursorpos, struct tm *tm)
820 const int unit[] = { UNIT_HOUR, UNIT_MIN, UNIT_SEC, 0, 0, 0 };
821 int value = 0;
823 if (!global_settings.talk_menu)
824 return;
826 switch(cursorpos)
828 case 0:
829 value = tm->tm_hour;
830 break;
831 case 1:
832 value = tm->tm_min;
833 break;
834 case 2:
835 value = tm->tm_sec;
836 break;
837 case 3:
838 value = tm->tm_year + 1900;
839 break;
840 case 5:
841 value = tm->tm_mday;
842 break;
845 if (cursorpos == 4) /* month */
846 talk_id(LANG_MONTH_JANUARY + tm->tm_mon, false);
847 else
848 talk_value(value, unit[cursorpos], false);
852 #define INDEX_X 0
853 #define INDEX_Y 1
854 #define INDEX_WIDTH 2
855 bool set_time_screen(char* string, struct tm *tm)
857 bool done = false;
858 int button;
859 int min = 0, steps = 0;
860 int cursorpos = 0;
861 int lastcursorpos = !cursorpos;
862 unsigned char buffer[19];
863 int realyear;
864 int julianday;
865 int i;
866 unsigned char reffub[5];
867 unsigned int width, height;
868 unsigned int separator_width, weekday_width;
869 unsigned int line_height, prev_line_height;
870 const int dayname[] = {LANG_WEEKDAY_SUNDAY,
871 LANG_WEEKDAY_MONDAY,
872 LANG_WEEKDAY_TUESDAY,
873 LANG_WEEKDAY_WEDNESDAY,
874 LANG_WEEKDAY_THURSDAY,
875 LANG_WEEKDAY_FRIDAY,
876 LANG_WEEKDAY_SATURDAY};
877 const int monthname[] = {LANG_MONTH_JANUARY,
878 LANG_MONTH_FEBRUARY,
879 LANG_MONTH_MARCH,
880 LANG_MONTH_APRIL,
881 LANG_MONTH_MAY,
882 LANG_MONTH_JUNE,
883 LANG_MONTH_JULY,
884 LANG_MONTH_AUGUST,
885 LANG_MONTH_SEPTEMBER,
886 LANG_MONTH_OCTOBER,
887 LANG_MONTH_NOVEMBER,
888 LANG_MONTH_DECEMBER};
889 char cursor[][3] = {{ 0, 8, 12}, {18, 8, 12}, {36, 8, 12},
890 {24, 16, 24}, {54, 16, 18}, {78, 16, 12}};
891 char daysinmonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
893 int monthname_len = 0, dayname_len = 0;
895 int *valptr = NULL;
897 #ifdef HAVE_LCD_BITMAP
898 if(global_settings.statusbar)
899 lcd_setmargins(0, STATUSBAR_HEIGHT);
900 else
901 lcd_setmargins(0, 0);
902 #endif
903 lcd_clear_display();
904 lcd_puts_scroll(0, 0, string);
906 while ( !done ) {
907 /* calculate the number of days in febuary */
908 realyear = tm->tm_year + 1900;
909 if((realyear % 4 == 0 && !(realyear % 100 == 0)) || realyear % 400 == 0)
910 daysinmonth[1] = 29;
911 else
912 daysinmonth[1] = 28;
914 /* fix day if month or year changed */
915 if (tm->tm_mday > daysinmonth[tm->tm_mon])
916 tm->tm_mday = daysinmonth[tm->tm_mon];
918 /* calculate day of week */
919 julianday = 0;
920 for(i = 0; i < tm->tm_mon; i++) {
921 julianday += daysinmonth[i];
923 julianday += tm->tm_mday;
924 tm->tm_wday = (realyear + julianday + (realyear - 1) / 4 -
925 (realyear - 1) / 100 + (realyear - 1) / 400 + 7 - 1) % 7;
927 snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d ",
928 tm->tm_hour, tm->tm_min, tm->tm_sec);
929 lcd_puts(0, 1, buffer);
931 /* recalculate the positions and offsets */
932 lcd_getstringsize(string, &width, &prev_line_height);
933 lcd_getstringsize(buffer, &width, &line_height);
934 lcd_getstringsize(":", &separator_width, &height);
936 /* hour */
937 strncpy(reffub, buffer, 2);
938 reffub[2] = '\0';
939 lcd_getstringsize(reffub, &width, &height);
940 cursor[0][INDEX_X] = 0;
941 cursor[0][INDEX_Y] = prev_line_height;
942 cursor[0][INDEX_WIDTH] = width;
944 /* minute */
945 strncpy(reffub, buffer + 3, 2);
946 reffub[2] = '\0';
947 lcd_getstringsize(reffub, &width, &height);
948 cursor[1][INDEX_X] = cursor[0][INDEX_WIDTH] + separator_width;
949 cursor[1][INDEX_Y] = prev_line_height;
950 cursor[1][INDEX_WIDTH] = width;
952 /* second */
953 strncpy(reffub, buffer + 6, 2);
954 reffub[2] = '\0';
955 lcd_getstringsize(reffub, &width, &height);
956 cursor[2][INDEX_X] = cursor[0][INDEX_WIDTH] + separator_width +
957 cursor[1][INDEX_WIDTH] + separator_width;
958 cursor[2][INDEX_Y] = prev_line_height;
959 cursor[2][INDEX_WIDTH] = width;
961 lcd_getstringsize(buffer, &width, &prev_line_height);
963 snprintf(buffer, sizeof(buffer), "%s %04d %s %02d ",
964 str(dayname[tm->tm_wday]), tm->tm_year+1900,
965 str(monthname[tm->tm_mon]), tm->tm_mday);
966 lcd_puts(0, 2, buffer);
968 /* recalculate the positions and offsets */
969 lcd_getstringsize(buffer, &width, &line_height);
971 /* store these 2 to prevent _repeated_ strlen calls */
972 monthname_len = strlen(str(monthname[tm->tm_mon]));
973 dayname_len = strlen(str(dayname[tm->tm_wday]));
975 /* weekday */
976 strncpy(reffub, buffer, dayname_len);
977 reffub[dayname_len] = '\0';
978 lcd_getstringsize(reffub, &weekday_width, &height);
979 lcd_getstringsize(" ", &separator_width, &height);
981 /* year */
982 strncpy(reffub, buffer + dayname_len + 1, 4);
983 reffub[4] = '\0';
984 lcd_getstringsize(reffub, &width, &height);
985 cursor[3][INDEX_X] = weekday_width + separator_width;
986 cursor[3][INDEX_Y] = cursor[0][INDEX_Y] + prev_line_height;
987 cursor[3][INDEX_WIDTH] = width;
989 /* month */
990 strncpy(reffub, buffer + dayname_len + 6, monthname_len);
991 reffub[monthname_len] = '\0';
992 lcd_getstringsize(reffub, &width, &height);
993 cursor[4][INDEX_X] = weekday_width + separator_width +
994 cursor[3][INDEX_WIDTH] + separator_width;
995 cursor[4][INDEX_Y] = cursor[0][INDEX_Y] + prev_line_height;
996 cursor[4][INDEX_WIDTH] = width;
998 /* day */
999 strncpy(reffub, buffer + dayname_len + monthname_len + 7, 2);
1000 reffub[2] = '\0';
1001 lcd_getstringsize(reffub, &width, &height);
1002 cursor[5][INDEX_X] = weekday_width + separator_width +
1003 cursor[3][INDEX_WIDTH] + separator_width +
1004 cursor[4][INDEX_WIDTH] + separator_width;
1005 cursor[5][INDEX_Y] = cursor[0][INDEX_Y] + prev_line_height;
1006 cursor[5][INDEX_WIDTH] = width;
1008 lcd_invertrect(cursor[cursorpos][INDEX_X],
1009 cursor[cursorpos][INDEX_Y] + lcd_getymargin(),
1010 cursor[cursorpos][INDEX_WIDTH],
1011 line_height);
1013 lcd_puts(0, 4, str(LANG_TIME_SET));
1014 lcd_puts(0, 5, str(LANG_TIME_REVERT));
1015 #ifdef HAVE_LCD_BITMAP
1016 status_draw(true);
1017 #endif
1018 lcd_update();
1020 /* calculate the minimum and maximum for the number under cursor */
1021 if(cursorpos!=lastcursorpos) {
1022 lastcursorpos=cursorpos;
1023 switch(cursorpos) {
1024 case 0: /* hour */
1025 min = 0;
1026 steps = 24;
1027 valptr = &tm->tm_hour;
1028 break;
1029 case 1: /* minute */
1030 min = 0;
1031 steps = 60;
1032 valptr = &tm->tm_min;
1033 break;
1034 case 2: /* second */
1035 min = 0;
1036 steps = 60;
1037 valptr = &tm->tm_sec;
1038 break;
1039 case 3: /* year */
1040 min = 1;
1041 steps = 200;
1042 valptr = &tm->tm_year;
1043 break;
1044 case 4: /* month */
1045 min = 0;
1046 steps = 12;
1047 valptr = &tm->tm_mon;
1048 break;
1049 case 5: /* day */
1050 min = 1;
1051 steps = daysinmonth[tm->tm_mon];
1052 valptr = &tm->tm_mday;
1053 break;
1055 say_time(cursorpos, tm);
1058 button = button_get_w_tmo(HZ/2);
1059 switch ( button ) {
1060 case BUTTON_LEFT:
1061 cursorpos = (cursorpos + 6 - 1) % 6;
1062 break;
1063 case BUTTON_RIGHT:
1064 cursorpos = (cursorpos + 6 + 1) % 6;
1065 break;
1066 case BUTTON_UP:
1067 case BUTTON_UP | BUTTON_REPEAT:
1068 *valptr = (*valptr + steps - min + 1) %
1069 steps + min;
1070 if(*valptr == 0)
1071 *valptr = min;
1072 say_time(cursorpos, tm);
1073 break;
1074 case BUTTON_DOWN:
1075 case BUTTON_DOWN | BUTTON_REPEAT:
1076 *valptr = (*valptr + steps - min - 1) %
1077 steps + min;
1078 if(*valptr == 0)
1079 *valptr = min;
1080 say_time(cursorpos, tm);
1081 break;
1082 case BUTTON_ON:
1083 done = true;
1084 break;
1085 case BUTTON_OFF:
1086 done = true;
1087 tm->tm_year = -1;
1088 break;
1090 case SYS_USB_CONNECTED:
1091 usb_screen();
1092 return true;
1096 return false;
1098 #endif