Update several codec Makefiles so that the codec libs build again on Coldfire targets...
[Rockbox.git] / apps / screens.c
blobb81932b94187c0ed34b0017b396a84ac486a7939
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 Bj�n 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 ****************************************************************************/
20 #include <stdbool.h>
21 #include <string.h>
22 #include <stdio.h>
23 #include "backlight.h"
24 #include "action.h"
25 #include "lcd.h"
26 #ifdef HAVE_REMOTE_LCD
27 #include "lcd-remote.h"
28 #endif
29 #include "lang.h"
30 #include "icons.h"
31 #include "font.h"
32 #include "audio.h"
33 #include "mp3_playback.h"
34 #include "usb.h"
35 #include "settings.h"
36 #include "status.h"
37 #include "playlist.h"
38 #include "sprintf.h"
39 #include "kernel.h"
40 #include "power.h"
41 #include "system.h"
42 #include "powermgmt.h"
43 #include "adc.h"
44 #include "action.h"
45 #include "talk.h"
46 #include "misc.h"
47 #include "id3.h"
48 #include "screens.h"
49 #include "debug.h"
50 #include "led.h"
51 #include "sound.h"
52 #include "gwps-common.h"
53 #include "splash.h"
54 #include "statusbar.h"
55 #include "screen_access.h"
56 #include "quickscreen.h"
57 #include "pcmbuf.h"
58 #include "list.h"
60 #ifdef HAVE_LCD_BITMAP
61 #include <bitmaps/usblogo.h>
62 #endif
64 #ifdef HAVE_REMOTE_LCD
65 #include <bitmaps/remote_usblogo.h>
66 #endif
68 #if defined(HAVE_LCD_BITMAP)
69 #include "widgets.h"
70 #endif
71 #ifdef HAVE_MMC
72 #include "ata_mmc.h"
73 #endif
74 #if CONFIG_CODEC == SWCODEC
75 #include "dsp.h"
76 #endif
78 #ifdef HAVE_LCD_COLOR
79 #include "backdrop.h"
80 #endif
82 #ifdef HAVE_LCD_BITMAP
83 #define SCROLLBAR_WIDTH 6
84 #endif
86 void usb_screen(void)
88 #ifdef USB_NONE
89 /* nothing here! */
90 #else
91 int i;
92 #ifdef HAVE_LCD_COLOR
93 show_main_backdrop();
94 #endif
96 FOR_NB_SCREENS(i)
97 screens[i].backlight_on();
99 #ifdef HAVE_REMOTE_LCD
100 lcd_remote_clear_display();
101 lcd_remote_bitmap(remote_usblogo,
102 (LCD_REMOTE_WIDTH-BMPWIDTH_remote_usblogo)/2,
103 (LCD_REMOTE_HEIGHT-BMPHEIGHT_remote_usblogo)/2,
104 BMPWIDTH_remote_usblogo, BMPHEIGHT_remote_usblogo);
105 lcd_remote_update();
106 #endif
108 lcd_clear_display();
109 #ifdef HAVE_LCD_BITMAP
110 lcd_bitmap(usblogo, (LCD_WIDTH-BMPWIDTH_usblogo)/2,
111 (LCD_HEIGHT-BMPHEIGHT_usblogo)/2,
112 BMPWIDTH_usblogo, BMPHEIGHT_usblogo);
113 lcd_update();
114 #else
115 lcd_double_height(false);
116 lcd_puts_scroll(0, 0, "[USB Mode]");
117 status_set_param(false);
118 status_set_audio(false);
119 status_set_usb(true);
120 #endif /* HAVE_LCD_BITMAP */
122 gui_syncstatusbar_draw(&statusbars, true);
123 #ifdef SIMULATOR
124 while (button_get(true) & BUTTON_REL);
125 #else
126 usb_acknowledge(SYS_USB_CONNECTED_ACK);
127 while(usb_wait_for_disconnect_w_tmo(&button_queue, HZ)) {
128 if(usb_inserted()) {
129 #ifdef HAVE_MMC /* USB-MMC bridge can report activity */
130 led(mmc_usb_active(HZ));
131 #endif /* HAVE_MMC */
132 gui_syncstatusbar_draw(&statusbars, false);
135 #endif /* SIMULATOR */
136 #ifdef HAVE_LCD_CHARCELLS
137 status_set_usb(false);
138 #endif /* HAVE_LCD_CHARCELLS */
139 FOR_NB_SCREENS(i)
140 screens[i].backlight_on();
141 #endif /* USB_NONE */
144 #ifdef HAVE_MMC
145 int mmc_remove_request(void)
147 struct event ev;
148 int i;
149 FOR_NB_SCREENS(i)
150 screens[i].clear_display();
151 gui_syncsplash(1, true, str(LANG_REMOVE_MMC));
152 if (global_settings.talk_menu)
153 talk_id(LANG_REMOVE_MMC, false);
155 while (1)
157 queue_wait_w_tmo(&button_queue, &ev, HZ/2);
158 switch (ev.id)
160 case SYS_MMC_EXTRACTED:
161 return SYS_MMC_EXTRACTED;
163 case SYS_USB_DISCONNECTED:
164 return SYS_USB_DISCONNECTED;
168 #endif
170 #if defined(CONFIG_CHARGING) && !defined(HAVE_POWEROFF_WHILE_CHARGING)
172 #ifdef HAVE_LCD_BITMAP
173 void charging_display_info(bool animate)
175 unsigned char charging_logo[36];
176 const int pox_x = (LCD_WIDTH - sizeof(charging_logo)) / 2;
177 const int pox_y = 32;
178 static unsigned phase = 3;
179 unsigned i;
180 char buf[32];
181 (void)buf;
183 #ifdef NEED_ATA_POWER_BATT_MEASURE
184 if (ide_powered()) /* FM and V2 can only measure when ATA power is on */
185 #endif
187 int battv = battery_voltage();
188 snprintf(buf, 32, " Batt: %d.%02dV %d%% ", battv / 100,
189 battv % 100, battery_level());
190 lcd_puts(0, 7, buf);
193 #if CONFIG_CHARGING == CHARGING_CONTROL
195 snprintf(buf, 32, "Charge mode:");
196 lcd_puts(0, 2, buf);
198 if (charge_state == CHARGING)
199 snprintf(buf, 32, str(LANG_BATTERY_CHARGE));
200 else if (charge_state == TOPOFF)
201 snprintf(buf, 32, str(LANG_BATTERY_TOPOFF_CHARGE));
202 else if (charge_state == TRICKLE)
203 snprintf(buf, 32, str(LANG_BATTERY_TRICKLE_CHARGE));
204 else
205 snprintf(buf, 32, "not charging");
207 lcd_puts(0, 3, buf);
208 if (!charger_enabled)
209 animate = false;
210 #endif /* CONFIG_CHARGING == CHARGING_CONTROL */
213 /* middle part */
214 memset(charging_logo+3, 0x00, 32);
215 charging_logo[0] = 0x3C;
216 charging_logo[1] = 0x24;
217 charging_logo[2] = charging_logo[35] = 0xFF;
219 if (!animate)
220 { /* draw the outline */
221 /* middle part */
222 lcd_mono_bitmap(charging_logo, pox_x, pox_y + 8, sizeof(charging_logo), 8);
223 lcd_set_drawmode(DRMODE_FG);
224 /* upper line */
225 charging_logo[0] = charging_logo[1] = 0x00;
226 memset(charging_logo+2, 0x80, 34);
227 lcd_mono_bitmap(charging_logo, pox_x, pox_y, sizeof(charging_logo), 8);
228 /* lower line */
229 memset(charging_logo+2, 0x01, 34);
230 lcd_mono_bitmap(charging_logo, pox_x, pox_y + 16, sizeof(charging_logo), 8);
231 lcd_set_drawmode(DRMODE_SOLID);
233 else
234 { /* animate the middle part */
235 for (i = 3; i<MIN(sizeof(charging_logo)-1, phase); i++)
237 if ((i-phase) % 8 == 0)
238 { /* draw a "bubble" here */
239 unsigned bitpos;
240 bitpos = (phase + i/8) % 15; /* "bounce" effect */
241 if (bitpos > 7)
242 bitpos = 14 - bitpos;
243 charging_logo[i] = 0x01 << bitpos;
246 lcd_mono_bitmap(charging_logo, pox_x, pox_y + 8, sizeof(charging_logo), 8);
247 phase++;
249 lcd_update();
251 #else /* not HAVE_LCD_BITMAP */
253 static unsigned char logo_chars[5];
254 static const unsigned char logo_pattern[] = {
255 0x07, 0x04, 0x1c, 0x14, 0x1c, 0x04, 0x07, /* char 1 */
256 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, /* char 2 */
257 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, /* char 3 */
258 0x1f, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1f, /* char 4 */
261 static void logo_lock_patterns(bool on)
263 int i;
265 if (on)
267 for (i = 0; i < 4; i++)
268 logo_chars[i] = lcd_get_locked_pattern();
269 logo_chars[4] = '\0';
271 else
273 for (i = 0; i < 4; i++)
274 lcd_unlock_pattern(logo_chars[i]);
278 void charging_display_info(bool animate)
280 int battv;
281 unsigned i, ypos;
282 static unsigned phase = 3;
283 char buf[28];
285 battv = battery_voltage();
286 snprintf(buf, sizeof(buf), "%s %d.%02dV", logo_chars,
287 battv / 100, battv % 100);
288 lcd_puts(0, 1, buf);
290 memcpy(buf, logo_pattern, 28); /* copy logo patterns */
292 if (!animate) /* build the screen */
294 lcd_double_height(false);
295 lcd_puts(0, 0, "[Charging]");
297 else /* animate the logo */
299 for (i = 3; i < MIN(19, phase); i++)
301 if ((i - phase) % 5 == 0)
302 { /* draw a "bubble" here */
303 ypos = (phase + i/5) % 9; /* "bounce" effect */
304 if (ypos > 4)
305 ypos = 8 - ypos;
306 buf[5 - ypos + 7 * (i/5)] |= 0x10 >> (i%5);
309 phase++;
312 for (i = 0; i < 4; i++)
313 lcd_define_pattern(logo_chars[i], buf + 7 * i);
315 #endif /* (not) HAVE_LCD_BITMAP */
317 /* blocks while charging, returns on event:
318 1 if charger cable was removed
319 2 if Off/Stop key was pressed
320 3 if On key was pressed
321 4 if USB was connected */
323 int charging_screen(void)
325 unsigned int button;
326 int rc = 0;
328 ide_power_enable(false); /* power down the disk, else would be spinning */
330 lcd_clear_display();
331 backlight_set_timeout(global_settings.backlight_timeout);
332 #ifdef HAVE_REMOTE_LCD
333 remote_backlight_set_timeout(global_settings.remote_backlight_timeout);
334 #endif
335 backlight_set_timeout_plugged(global_settings.backlight_timeout_plugged);
336 gui_syncstatusbar_draw(&statusbars, true);
338 #ifdef HAVE_LCD_CHARCELLS
339 logo_lock_patterns(true);
340 #endif
341 charging_display_info(false);
345 gui_syncstatusbar_draw(&statusbars, false);
346 charging_display_info(true);
347 button = get_action(CONTEXT_STD,HZ/3);
348 if (button == ACTION_STD_OK)
349 rc = 2;
350 else if (usb_detect())
351 rc = 3;
352 else if (!charger_inserted())
353 rc = 1;
354 } while (!rc);
356 #ifdef HAVE_LCD_CHARCELLS
357 logo_lock_patterns(false);
358 #endif
359 action_signalscreenchange();
360 return rc;
362 #endif /* CONFIG_CHARGING && !HAVE_POWEROFF_WHILE_CHARGING */
364 #ifdef HAVE_PITCHSCREEN
365 /* returns:
366 0 if no key was pressed
367 1 if USB was connected */
369 void pitch_screen_draw(struct screen *display, int pitch)
371 unsigned char* ptr;
372 unsigned char buf[32];
373 int w, h;
375 display->clear_display();
377 if (display->nb_lines < 4) /* very small screen, just show the pitch value */
379 w = snprintf((char *)buf, sizeof(buf), "%s: %d.%d%%",str(LANG_SYSFONT_PITCH),
380 pitch / 10, pitch % 10 );
381 display->putsxy((display->width-(w*display->char_width))/2,
382 display->nb_lines/2,buf);
384 else /* bigger screen, show everything... */
387 /* UP: Pitch Up */
388 ptr = str(LANG_SYSFONT_PITCH_UP);
389 display->getstringsize(ptr,&w,&h);
390 display->putsxy((display->width-w)/2, 0, ptr);
391 display->mono_bitmap(bitmap_icons_7x8[Icon_UpArrow],
392 display->width/2 - 3, h, 7, 8);
394 /* DOWN: Pitch Down */
395 ptr = str(LANG_SYSFONT_PITCH_DOWN);
396 display->getstringsize(ptr,&w,&h);
397 display->putsxy((display->width-w)/2, display->height - h, ptr);
398 display->mono_bitmap(bitmap_icons_7x8[Icon_DownArrow],
399 display->width/2 - 3, display->height - h*2, 7, 8);
401 /* RIGHT: +2% */
402 ptr = "+2%";
403 display->getstringsize(ptr,&w,&h);
404 display->putsxy(display->width-w, (display->height-h)/2, ptr);
405 display->mono_bitmap(bitmap_icons_7x8[Icon_FastForward],
406 display->width-w-8, (display->height-h)/2, 7, 8);
408 /* LEFT: -2% */
409 ptr = "-2%";
410 display->getstringsize(ptr,&w,&h);
411 display->putsxy(0, (display->height-h)/2, ptr);
412 display->mono_bitmap(bitmap_icons_7x8[Icon_FastBackward],
413 w+1, (display->height-h)/2, 7, 8);
415 /* "Pitch" */
416 snprintf((char *)buf, sizeof(buf), str(LANG_SYSFONT_PITCH));
417 display->getstringsize(buf,&w,&h);
418 display->putsxy((display->width-w)/2, (display->height/2)-h, buf);
419 /* "XX.X%" */
420 snprintf((char *)buf, sizeof(buf), "%d.%d%%",
421 pitch / 10, pitch % 10 );
422 display->getstringsize(buf,&w,&h);
423 display->putsxy((display->width-w)/2, display->height/2, buf);
426 display->update();
429 bool pitch_screen(void)
431 int button;
432 int pitch = sound_get_pitch();
433 bool exit = false;
434 int i;
436 #if CONFIG_CODEC == SWCODEC
437 pcmbuf_set_low_latency(true);
438 #endif
440 action_signalscreenchange();
441 while (!exit)
443 FOR_NB_SCREENS(i)
444 pitch_screen_draw(&screens[i],pitch);
446 button = get_action(CONTEXT_PITCHSCREEN,TIMEOUT_BLOCK);
447 switch (button) {
448 case ACTION_PS_INC_SMALL:
449 if ( pitch < 2000 )
450 pitch++;
451 sound_set_pitch(pitch);
452 break;
454 case ACTION_PS_INC_BIG:
455 if ( pitch < 1990 )
456 pitch += 10;
457 else
458 pitch = 2000;
459 sound_set_pitch(pitch);
460 break;
462 case ACTION_PS_DEC_SMALL:
463 if ( pitch > 500 )
464 pitch--;
465 sound_set_pitch(pitch);
466 break;
468 case ACTION_PS_DEC_BIG:
469 if ( pitch > 510 )
470 pitch -= 10;
471 else
472 pitch = 500;
473 sound_set_pitch(pitch);
474 break;
476 case ACTION_PS_NUDGE_RIGHT:
477 if ( pitch < 1980 )
479 pitch += 20;
480 sound_set_pitch(pitch);
481 FOR_NB_SCREENS(i)
482 pitch_screen_draw(&screens[i],pitch);
484 break;
485 case ACTION_PS_NUDGE_RIGHTOFF:
486 pitch -= 20;
487 sound_set_pitch(pitch);
488 break;
490 case ACTION_PS_NUDGE_LEFT:
491 if ( pitch > 520 )
493 pitch -= 20;
494 sound_set_pitch(pitch);
495 FOR_NB_SCREENS(i)
496 pitch_screen_draw(&screens[i],pitch);
498 break;
499 case ACTION_PS_NUDGE_LEFTOFF:
500 pitch += 20;
501 sound_set_pitch(pitch);
502 break;
504 case ACTION_PS_RESET:
505 pitch = 1000;
506 sound_set_pitch( pitch );
507 break;
509 case ACTION_PS_EXIT:
510 exit = true;
511 break;
513 default:
514 if(default_event_handler(button) == SYS_USB_CONNECTED)
515 return 1;
516 break;
519 #if CONFIG_CODEC == SWCODEC
520 pcmbuf_set_low_latency(false);
521 #endif
522 lcd_setfont(FONT_UI);
523 action_signalscreenchange();
524 return 0;
526 #endif /* HAVE_PITCHSCREEN */
528 #ifdef HAVE_QUICKSCREEN
530 #define bool_to_int(b)\
531 b?1:0
532 #define int_to_bool(i)\
533 i==0?false:true
535 void quick_screen_quick_apply(struct gui_quickscreen *qs)
537 global_settings.playlist_shuffle=int_to_bool(qs->left_option->option);
538 global_settings.dirfilter=qs->bottom_option->option;
539 global_settings.repeat_mode=qs->right_option->option;
542 bool quick_screen_quick(int button_enter)
544 bool res, oldshuffle;
545 struct option_select left_option;
546 struct option_select bottom_option;
547 struct option_select right_option;
548 int oldrepeat, old_x_margin, old_y_margin;
550 static const struct opt_items left_items[] = {
551 [0]={ STR(LANG_SYSFONT_OFF) },
552 [1]={ STR(LANG_SYSFONT_ON) }
554 static const struct opt_items bottom_items[] = {
555 [SHOW_ALL]={ STR(LANG_SYSFONT_FILTER_ALL) },
556 [SHOW_SUPPORTED]={ STR(LANG_SYSFONT_FILTER_SUPPORTED) },
557 [SHOW_MUSIC]={ STR(LANG_SYSFONT_FILTER_MUSIC) },
558 [SHOW_PLAYLIST]={ STR(LANG_SYSFONT_FILTER_PLAYLIST) },
559 #ifdef HAVE_TAGCACHE
560 [SHOW_ID3DB]={ STR(LANG_SYSFONT_FILTER_ID3DB) }
561 #endif
563 static const struct opt_items right_items[] = {
564 [REPEAT_OFF]={ STR(LANG_SYSFONT_OFF) },
565 [REPEAT_ALL]={ STR(LANG_SYSFONT_REPEAT_ALL) },
566 [REPEAT_ONE]={ STR(LANG_SYSFONT_REPEAT_ONE) },
567 [REPEAT_SHUFFLE]={ STR(LANG_SYSFONT_SHUFFLE) },
568 #if (AB_REPEAT_ENABLE == 1)
569 [REPEAT_AB]={ STR(LANG_SYSFONT_REPEAT_AB) }
570 #endif
572 struct gui_quickscreen qs;
574 old_x_margin = lcd_getxmargin();
575 old_y_margin = lcd_getymargin();
576 lcd_setmargins(0, 0);
578 option_select_init_items(&left_option,
579 (char *)str(LANG_SYSFONT_SHUFFLE),
580 bool_to_int(global_settings.playlist_shuffle),
581 left_items,
583 option_select_init_items(&bottom_option,
584 (char *)str(LANG_SYSFONT_FILTER),
585 global_settings.dirfilter,
586 bottom_items,
587 sizeof(bottom_items)/sizeof(struct opt_items));
588 option_select_init_items(&right_option,
589 (char *)str(LANG_SYSFONT_REPEAT),
590 global_settings.repeat_mode,
591 right_items,
592 sizeof(right_items)/sizeof(struct opt_items));
594 gui_quickscreen_init(&qs, &left_option, &bottom_option, &right_option,
595 &quick_screen_quick_apply);
596 oldrepeat=global_settings.repeat_mode;
597 oldshuffle=global_settings.playlist_shuffle;
598 res=gui_syncquickscreen_run(&qs, button_enter);
599 if(!res)
601 if ( oldrepeat != global_settings.repeat_mode &&
602 (audio_status() & AUDIO_STATUS_PLAY) )
603 audio_flush_and_reload_tracks();
604 if(oldshuffle != global_settings.playlist_shuffle
605 && audio_status() & AUDIO_STATUS_PLAY)
607 #if CONFIG_CODEC == SWCODEC
608 dsp_set_replaygain(true);
609 #endif
610 if (global_settings.playlist_shuffle)
611 playlist_randomise(NULL, current_tick, true);
612 else
613 playlist_sort(NULL, true);
615 settings_save();
617 lcd_setmargins(old_x_margin, old_y_margin);
618 return(res);
621 #ifdef BUTTON_F3
622 void quick_screen_f3_apply(struct gui_quickscreen *qs)
624 global_settings.scrollbar=int_to_bool(qs->left_option->option);
626 global_settings.flip_display=int_to_bool(qs->bottom_option->option);
627 button_set_flip(global_settings.flip_display);
628 lcd_set_flip(global_settings.flip_display);
630 global_settings.statusbar=int_to_bool(qs->right_option->option);
631 gui_syncstatusbar_draw(&statusbars, true);
634 bool quick_screen_f3(int button_enter)
636 bool res;
637 struct option_select left_option;
638 struct option_select bottom_option;
639 struct option_select right_option;
640 int old_x_margin, old_y_margin;
642 static const struct opt_items onoff_items[] = {
643 [0]={ STR(LANG_SYSFONT_OFF) },
644 [1]={ STR(LANG_SYSFONT_ON) }
646 static const struct opt_items yesno_items[] = {
647 [0]={ STR(LANG_SYSFONT_SET_BOOL_NO) },
648 [1]={ STR(LANG_SYSFONT_SET_BOOL_YES) }
651 struct gui_quickscreen qs;
653 old_x_margin = lcd_getxmargin();
654 old_y_margin = lcd_getymargin();
655 lcd_setmargins(0, 0);
657 option_select_init_items(&left_option,
658 str(LANG_SYSFONT_SCROLL_BAR),
659 bool_to_int(global_settings.scrollbar),
660 onoff_items,
662 option_select_init_items(&bottom_option,
663 str(LANG_SYSFONT_FLIP_DISPLAY),
664 bool_to_int(global_settings.flip_display),
665 yesno_items,
667 option_select_init_items(&right_option,
668 str(LANG_SYSFONT_STATUS_BAR),
669 bool_to_int(global_settings.statusbar),
670 onoff_items,
672 gui_quickscreen_init(&qs, &left_option, &bottom_option, &right_option,
673 &quick_screen_f3_apply);
674 res=gui_syncquickscreen_run(&qs, button_enter);
675 if(!res)
676 settings_save();
677 lcd_setmargins(old_x_margin, old_y_margin);
678 return(res);
680 #endif /* BUTTON_F3 */
681 #endif /* CONFIG_KEYPAD in (RECORDER_PAD |IRIVER_H100_PAD | IRIVER_H300_PAD) */
683 #if defined(CONFIG_CHARGING) || defined(SIMULATOR)
684 void charging_splash(void)
686 gui_syncsplash(2*HZ, true, (unsigned char *)str(LANG_BATTERY_CHARGE));
687 button_clear_queue();
689 #endif
692 #if defined(HAVE_LCD_BITMAP) && defined (CONFIG_RTC)
694 const int dayname[] = {
695 LANG_WEEKDAY_SUNDAY,
696 LANG_WEEKDAY_MONDAY,
697 LANG_WEEKDAY_TUESDAY,
698 LANG_WEEKDAY_WEDNESDAY,
699 LANG_WEEKDAY_THURSDAY,
700 LANG_WEEKDAY_FRIDAY,
701 LANG_WEEKDAY_SATURDAY
704 const int monthname[] = {
705 LANG_MONTH_JANUARY,
706 LANG_MONTH_FEBRUARY,
707 LANG_MONTH_MARCH,
708 LANG_MONTH_APRIL,
709 LANG_MONTH_MAY,
710 LANG_MONTH_JUNE,
711 LANG_MONTH_JULY,
712 LANG_MONTH_AUGUST,
713 LANG_MONTH_SEPTEMBER,
714 LANG_MONTH_OCTOBER,
715 LANG_MONTH_NOVEMBER,
716 LANG_MONTH_DECEMBER
719 /* little helper function for voice output */
720 static void say_time(int cursorpos, const struct tm *tm)
722 static const int unit[] = { UNIT_HOUR, UNIT_MIN, UNIT_SEC, 0, 0, 0 };
723 int value = 0;
725 if (!global_settings.talk_menu)
726 return;
728 switch(cursorpos)
730 case 0:
731 value = tm->tm_hour;
732 break;
733 case 1:
734 value = tm->tm_min;
735 break;
736 case 2:
737 value = tm->tm_sec;
738 break;
739 case 3:
740 value = tm->tm_year + 1900;
741 break;
742 case 5:
743 value = tm->tm_mday;
744 break;
747 if (cursorpos == 4) /* month */
748 talk_id(LANG_MONTH_JANUARY + tm->tm_mon, false);
749 else
750 talk_value(value, unit[cursorpos], false);
754 #define INDEX_X 0
755 #define INDEX_Y 1
756 #define INDEX_WIDTH 2
757 bool set_time_screen(const char* string, struct tm *tm)
759 bool done = false;
760 int button;
761 int min = 0, steps = 0;
762 int cursorpos = 0;
763 int lastcursorpos = !cursorpos;
764 unsigned char buffer[19];
765 int realyear;
766 int julianday;
767 int i;
768 unsigned char reffub[5];
769 unsigned int width, height;
770 unsigned int separator_width, weekday_width;
771 unsigned int line_height, prev_line_height;
772 int lastmode = lcd_get_drawmode();
774 char cursor[][3] = {{ 0, 8, 12}, {18, 8, 12}, {36, 8, 12},
775 {24, 16, 24}, {54, 16, 18}, {78, 16, 12}};
776 char daysinmonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
778 int monthname_len = 0, dayname_len = 0;
780 int *valptr = NULL;
782 #ifdef HAVE_LCD_BITMAP
783 if(global_settings.statusbar)
784 lcd_setmargins(0, STATUSBAR_HEIGHT);
785 else
786 lcd_setmargins(0, 0);
787 #endif
788 lcd_clear_display();
789 lcd_puts_scroll(0, 0, string);
791 while ( !done ) {
792 /* calculate the number of days in febuary */
793 realyear = tm->tm_year + 1900;
794 if((realyear % 4 == 0 && !(realyear % 100 == 0)) || realyear % 400 == 0)
795 daysinmonth[1] = 29;
796 else
797 daysinmonth[1] = 28;
799 /* fix day if month or year changed */
800 if (tm->tm_mday > daysinmonth[tm->tm_mon])
801 tm->tm_mday = daysinmonth[tm->tm_mon];
803 /* calculate day of week */
804 julianday = 0;
805 for(i = 0; i < tm->tm_mon; i++) {
806 julianday += daysinmonth[i];
808 julianday += tm->tm_mday;
809 tm->tm_wday = (realyear + julianday + (realyear - 1) / 4 -
810 (realyear - 1) / 100 + (realyear - 1) / 400 + 7 - 1) % 7;
812 snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d ",
813 tm->tm_hour, tm->tm_min, tm->tm_sec);
814 lcd_puts(0, 1, buffer);
816 /* recalculate the positions and offsets */
817 lcd_getstringsize(string, &width, &prev_line_height);
818 lcd_getstringsize(buffer, &width, &line_height);
819 lcd_getstringsize(":", &separator_width, &height);
821 /* hour */
822 strncpy(reffub, buffer, 2);
823 reffub[2] = '\0';
824 lcd_getstringsize(reffub, &width, &height);
825 cursor[0][INDEX_X] = 0;
826 cursor[0][INDEX_Y] = prev_line_height;
827 cursor[0][INDEX_WIDTH] = width;
829 /* minute */
830 strncpy(reffub, buffer + 3, 2);
831 reffub[2] = '\0';
832 lcd_getstringsize(reffub, &width, &height);
833 cursor[1][INDEX_X] = cursor[0][INDEX_WIDTH] + separator_width;
834 cursor[1][INDEX_Y] = prev_line_height;
835 cursor[1][INDEX_WIDTH] = width;
837 /* second */
838 strncpy(reffub, buffer + 6, 2);
839 reffub[2] = '\0';
840 lcd_getstringsize(reffub, &width, &height);
841 cursor[2][INDEX_X] = cursor[0][INDEX_WIDTH] + separator_width +
842 cursor[1][INDEX_WIDTH] + separator_width;
843 cursor[2][INDEX_Y] = prev_line_height;
844 cursor[2][INDEX_WIDTH] = width;
846 lcd_getstringsize(buffer, &width, &prev_line_height);
848 snprintf(buffer, sizeof(buffer), "%s %04d %s %02d ",
849 str(dayname[tm->tm_wday]), tm->tm_year+1900,
850 str(monthname[tm->tm_mon]), tm->tm_mday);
851 lcd_puts(0, 2, buffer);
853 /* recalculate the positions and offsets */
854 lcd_getstringsize(buffer, &width, &line_height);
856 /* store these 2 to prevent _repeated_ strlen calls */
857 monthname_len = strlen(str(monthname[tm->tm_mon]));
858 dayname_len = strlen(str(dayname[tm->tm_wday]));
860 /* weekday */
861 strncpy(reffub, buffer, dayname_len);
862 reffub[dayname_len] = '\0';
863 lcd_getstringsize(reffub, &weekday_width, &height);
864 lcd_getstringsize(" ", &separator_width, &height);
866 /* year */
867 strncpy(reffub, buffer + dayname_len + 1, 4);
868 reffub[4] = '\0';
869 lcd_getstringsize(reffub, &width, &height);
870 cursor[3][INDEX_X] = weekday_width + separator_width;
871 cursor[3][INDEX_Y] = cursor[0][INDEX_Y] + prev_line_height;
872 cursor[3][INDEX_WIDTH] = width;
874 /* month */
875 strncpy(reffub, buffer + dayname_len + 6, monthname_len);
876 reffub[monthname_len] = '\0';
877 lcd_getstringsize(reffub, &width, &height);
878 cursor[4][INDEX_X] = weekday_width + separator_width +
879 cursor[3][INDEX_WIDTH] + separator_width;
880 cursor[4][INDEX_Y] = cursor[0][INDEX_Y] + prev_line_height;
881 cursor[4][INDEX_WIDTH] = width;
883 /* day */
884 strncpy(reffub, buffer + dayname_len + monthname_len + 7, 2);
885 reffub[2] = '\0';
886 lcd_getstringsize(reffub, &width, &height);
887 cursor[5][INDEX_X] = weekday_width + separator_width +
888 cursor[3][INDEX_WIDTH] + separator_width +
889 cursor[4][INDEX_WIDTH] + separator_width;
890 cursor[5][INDEX_Y] = cursor[0][INDEX_Y] + prev_line_height;
891 cursor[5][INDEX_WIDTH] = width;
893 lcd_set_drawmode(DRMODE_COMPLEMENT);
894 lcd_fillrect(cursor[cursorpos][INDEX_X],
895 cursor[cursorpos][INDEX_Y] + lcd_getymargin(),
896 cursor[cursorpos][INDEX_WIDTH],
897 line_height);
898 lcd_set_drawmode(DRMODE_SOLID);
900 lcd_puts(0, 4, str(LANG_TIME_SET));
901 lcd_puts(0, 5, str(LANG_TIME_REVERT));
902 #ifdef HAVE_LCD_BITMAP
903 gui_syncstatusbar_draw(&statusbars, true);
904 #endif
905 lcd_update();
907 /* calculate the minimum and maximum for the number under cursor */
908 if(cursorpos!=lastcursorpos) {
909 lastcursorpos=cursorpos;
910 switch(cursorpos) {
911 case 0: /* hour */
912 min = 0;
913 steps = 24;
914 valptr = &tm->tm_hour;
915 break;
916 case 1: /* minute */
917 min = 0;
918 steps = 60;
919 valptr = &tm->tm_min;
920 break;
921 case 2: /* second */
922 min = 0;
923 steps = 60;
924 valptr = &tm->tm_sec;
925 break;
926 case 3: /* year */
927 min = 1;
928 steps = 200;
929 valptr = &tm->tm_year;
930 break;
931 case 4: /* month */
932 min = 0;
933 steps = 12;
934 valptr = &tm->tm_mon;
935 break;
936 case 5: /* day */
937 min = 1;
938 steps = daysinmonth[tm->tm_mon];
939 valptr = &tm->tm_mday;
940 break;
942 say_time(cursorpos, tm);
945 button = get_action(CONTEXT_SETTINGS_TIME,HZ/2);
946 switch ( button ) {
947 case ACTION_STD_PREV:
948 cursorpos = (cursorpos + 6 - 1) % 6;
949 break;
950 case ACTION_STD_NEXT:
951 cursorpos = (cursorpos + 6 + 1) % 6;
952 break;
953 case ACTION_SETTINGS_INC:
954 case ACTION_SETTINGS_INCREPEAT:
955 *valptr = (*valptr + steps - min + 1) %
956 steps + min;
957 if(*valptr == 0)
958 *valptr = min;
959 say_time(cursorpos, tm);
960 break;
961 case ACTION_SETTINGS_DEC:
962 case ACTION_SETTINGS_DECREPEAT:
963 *valptr = (*valptr + steps - min - 1) %
964 steps + min;
965 if(*valptr == 0)
966 *valptr = min;
967 say_time(cursorpos, tm);
968 break;
970 case ACTION_STD_OK:
971 done = true;
972 break;
974 case ACTION_STD_CANCEL:
975 done = true;
976 tm->tm_year = -1;
977 break;
979 default:
980 if (default_event_handler(button) == SYS_USB_CONNECTED)
981 return true;
982 break;
985 action_signalscreenchange();
986 lcd_set_drawmode(lastmode);
987 return false;
989 #endif /* defined(HAVE_LCD_BITMAP) && defined (CONFIG_RTC) */
991 #if (CONFIG_KEYPAD == RECORDER_PAD) && !defined(HAVE_SW_POWEROFF)
992 bool shutdown_screen(void)
994 int button;
995 bool done = false;
996 long time_entered = current_tick;
998 lcd_stop_scroll();
1000 gui_syncsplash(0, true, str(LANG_CONFIRM_SHUTDOWN));
1002 while(!done && TIME_BEFORE(current_tick,time_entered+HZ*2))
1004 button = get_action(CONTEXT_STD,HZ);
1005 switch(button)
1007 case ACTION_STD_CANCEL:
1008 sys_poweroff();
1009 break;
1011 /* do nothing here, because ACTION_UNKNOWN might be caused
1012 * by timeout or button release. In case of timeout the loop
1013 * is terminated by TIME_BEFORE */
1014 case ACTION_UNKNOWN:
1015 break;
1017 default:
1018 if(default_event_handler(button) == SYS_USB_CONNECTED)
1019 return true;
1020 done = true;
1021 break;
1024 action_signalscreenchange();
1025 return false;
1027 #endif
1029 #if CONFIG_CODEC == SWCODEC
1030 #define ID3_ITEMS 13
1031 #else
1032 #define ID3_ITEMS 11
1033 #endif
1035 char * id3_get_info(int selected_item, void* data, char *buffer)
1037 struct mp3entry* id3 =(struct mp3entry*)data;
1038 int info_no=selected_item/2;
1039 if(!(selected_item%2))
1040 {/* header */
1041 static const int headers[]=
1043 LANG_ID3_TITLE,
1044 LANG_ID3_ARTIST,
1045 LANG_ID3_ALBUM,
1046 LANG_ID3_TRACKNUM,
1047 LANG_ID3_GENRE,
1048 LANG_ID3_YEAR,
1049 LANG_ID3_LENGTH,
1050 LANG_ID3_PLAYLIST,
1051 LANG_ID3_BITRATE,
1052 LANG_ID3_FRECUENCY,
1053 #if CONFIG_CODEC == SWCODEC
1054 LANG_ID3_TRACK_GAIN,
1055 LANG_ID3_ALBUM_GAIN,
1056 #endif
1057 LANG_ID3_PATH,
1059 return( str(headers[info_no]));
1061 else
1062 {/* data */
1064 char * info=NULL;
1065 switch(info_no)
1067 case 0:/*LANG_ID3_TITLE*/
1068 info=id3->title;
1069 break;
1070 case 1:/*LANG_ID3_ARTIST*/
1071 info=id3->artist;
1072 break;
1073 case 2:/*LANG_ID3_ALBUM*/
1074 info=id3->album;
1075 break;
1076 case 3:/*LANG_ID3_TRACKNUM*/
1077 if (id3->track_string)
1078 info = id3->track_string;
1079 else if (id3->tracknum)
1081 snprintf(buffer, MAX_PATH, "%d", id3->tracknum);
1082 info = buffer;
1084 break;
1085 case 4:/*LANG_ID3_GENRE*/
1086 info = id3_get_genre(id3);
1087 break;
1088 case 5:/*LANG_ID3_YEAR*/
1089 if (id3->year_string)
1090 info = id3->year_string;
1091 else if (id3->year)
1093 snprintf(buffer, MAX_PATH, "%d", id3->year);
1094 info = buffer;
1096 break;
1097 case 6:/*LANG_ID3_LENGTH*/
1098 gui_wps_format_time(buffer, MAX_PATH, id3->length);
1099 info=buffer;
1100 break;
1101 case 7:/*LANG_ID3_PLAYLIST*/
1102 snprintf(buffer, MAX_PATH, "%d/%d", playlist_get_display_index(),
1103 playlist_amount());
1104 info=buffer;
1105 break;
1106 case 8:/*LANG_ID3_BITRATE*/
1107 snprintf(buffer, MAX_PATH, "%d kbps%s", id3->bitrate,
1108 id3->vbr ? str(LANG_ID3_VBR) : (const unsigned char*) "");
1109 info=buffer;
1110 break;
1111 case 9:/*LANG_ID3_FRECUENCY*/
1112 snprintf(buffer, MAX_PATH, "%ld Hz", id3->frequency);
1113 info=buffer;
1114 break;
1115 #if CONFIG_CODEC == SWCODEC
1116 case 10:/*LANG_ID3_TRACK_GAIN*/
1117 info=id3->track_gain_string;
1118 break;
1119 case 11:/*LANG_ID3_ALBUM_GAIN*/
1120 info=id3->album_gain_string;
1121 break;
1122 case 12:/*LANG_ID3_PATH*/
1123 #else
1124 case 10:/*LANG_ID3_PATH*/
1125 #endif
1126 info=id3->path;
1127 break;
1129 if(info==NULL)
1130 return(str(LANG_ID3_NO_INFO));
1131 return(info);
1135 bool browse_id3(void)
1137 struct gui_synclist id3_lists;
1138 struct mp3entry* id3 = audio_current_track();
1139 int key;
1141 gui_synclist_init(&id3_lists, &id3_get_info, id3, true, 2);
1142 gui_synclist_set_nb_items(&id3_lists, ID3_ITEMS*2);
1143 gui_synclist_draw(&id3_lists);
1144 gui_syncstatusbar_draw(&statusbars, true);
1145 action_signalscreenchange();
1146 while (true) {
1147 gui_syncstatusbar_draw(&statusbars, false);
1148 key = get_action(CONTEXT_LIST,HZ/2);
1149 if(key!=ACTION_NONE && key!=ACTION_UNKNOWN
1150 && !gui_synclist_do_button(&id3_lists, key))
1152 action_signalscreenchange();
1153 return(default_event_handler(key) == SYS_USB_CONNECTED);
1159 bool set_rating(void)
1161 struct mp3entry* id3 = audio_current_track();
1162 int button;
1163 bool exit = false;
1164 char rating_text[20];
1166 if (!(audio_status() & AUDIO_STATUS_PLAY)||id3==NULL)
1167 return false;
1168 while (!exit)
1170 lcd_clear_display();
1171 lcd_puts(0, 0, str(LANG_RATING));
1172 snprintf(rating_text, sizeof(rating_text), "%d", id3->rating);
1173 lcd_puts(0, 1, (unsigned char *)rating_text);
1174 lcd_update();
1175 button = get_action(CONTEXT_SETTINGS,TIMEOUT_BLOCK);
1177 switch(button)
1179 case ACTION_SETTINGS_DEC:
1180 if (id3->rating > 0)
1181 id3->rating--;
1182 else
1183 id3->rating = 10;
1184 break;
1186 case ACTION_SETTINGS_INC:
1187 if (id3->rating < 10)
1188 id3->rating++;
1189 else
1190 id3->rating = 0;
1191 break;
1192 case ACTION_STD_CANCEL:
1193 exit = true;
1194 break;
1196 default:
1197 if(default_event_handler(button) == SYS_USB_CONNECTED)
1198 return true;
1199 break;
1202 action_signalscreenchange();
1203 return false;