Corrected copyright year
[kugel-rb.git] / apps / screens.c
blobe4f44dd601e88a39616e792d7156158ea3d149d2
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"
42 #include "misc.h"
43 #include "id3.h"
44 #include "screens.h"
45 #include "debug.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,
84 #endif
86 void usb_display_info(void)
88 lcd_clear_display();
90 #ifdef HAVE_LCD_BITMAP
91 lcd_bitmap(usb_logo, 6, 16, BMPWIDTH_usb_logo, BMPHEIGHT_usb_logo, false);
92 status_draw(true);
93 lcd_update();
94 #else
95 lcd_puts(0, 0, "[USB Mode]");
96 status_set_param(false);
97 status_set_audio(false);
98 status_set_usb(true);
99 status_draw(false);
100 #endif
103 void usb_screen(void)
105 #ifdef USB_NONE
106 /* nothing here! */
107 #else
108 #ifndef SIMULATOR
109 backlight_on();
110 usb_acknowledge(SYS_USB_CONNECTED_ACK);
111 usb_display_info();
112 while(usb_wait_for_disconnect_w_tmo(&button_queue, HZ)) {
113 if(usb_inserted()) {
114 status_draw(false);
117 #ifdef HAVE_LCD_CHARCELLS
118 status_set_usb(false);
119 #endif
121 backlight_on();
122 #endif
123 #endif /* USB_NONE */
126 #ifdef HAVE_MMC
127 int mmc_remove_request(void)
129 struct event ev;
131 lcd_clear_display();
132 splash(1, true, str(LANG_REMOVE_MMC));
133 if (global_settings.talk_menu)
134 talk_id(LANG_REMOVE_MMC, false);
136 while (1)
138 queue_wait_w_tmo(&button_queue, &ev, HZ/2);
139 switch (ev.id)
141 case SYS_MMC_EXTRACTED:
142 return SYS_MMC_EXTRACTED;
144 case SYS_USB_DISCONNECTED:
145 return SYS_USB_DISCONNECTED;
149 #endif
152 /* some simulator dummies */
153 #ifdef SIMULATOR
154 #define BATTERY_SCALE_FACTOR 7000
155 unsigned short adc_read(int channel)
157 (void)channel;
158 return 100;
160 #endif
162 #ifdef HAVE_CHARGING
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;
171 unsigned i;
172 char buf[32];
173 (void)buf;
175 #ifdef NEED_ATA_POWER_BATT_MEASURE
176 if (ide_powered()) /* FM and V2 can only measure when ATA power is on */
177 #endif
179 int battery_voltage;
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,
187 battery_level());
188 lcd_puts(0, 7, buf);
191 #ifdef HAVE_CHARGE_CTRL
193 snprintf(buf, 32, "Charge mode:");
194 lcd_puts(0, 2, buf);
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));
202 else
203 snprintf(buf, 32, "not charging");
205 lcd_puts(0, 3, buf);
206 if (!charger_enabled)
207 animate = false;
208 #endif /* HAVE_CHARGE_CTRL */
211 /* middle part */
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;
217 if (!animate)
218 { /* draw the outline */
219 /* middle part */
220 lcd_bitmap(charging_logo, pox_x, pox_y + 8, sizeof(charging_logo), 8, true);
221 /* upper line */
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);
225 /* lower line */
226 memset(charging_logo+2, 0x01, 34);
227 lcd_bitmap(charging_logo, pox_x, pox_y + 16, sizeof(charging_logo), 8, false);
229 else
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 */
235 unsigned bitpos;
236 bitpos = (phase + i/8) % 15; /* "bounce" effect */
237 if (bitpos > 7)
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);
243 phase++;
245 lcd_update();
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)
259 int i;
261 if (on)
263 for (i = 0; i < 4; i++)
264 logo_chars[i] = lcd_get_locked_pattern();
265 logo_chars[4] = '\0';
267 else
269 for (i = 0; i < 4; i++)
270 lcd_unlock_pattern(logo_chars[i]);
274 void charging_display_info(bool animate)
276 int battery_voltage;
277 unsigned i, ypos;
278 static unsigned phase = 3;
279 char buf[28];
281 battery_voltage = (adc_read(ADC_UNREG_POWER) * BATTERY_SCALE_FACTOR)
282 / 10000;
283 snprintf(buf, sizeof(buf), "%s %d.%02dV", logo_chars,
284 battery_voltage / 100, battery_voltage % 100);
285 lcd_puts(0, 1, buf);
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 */
301 if (ypos > 4)
302 ypos = 8 - ypos;
303 buf[5 - ypos + 7 * (i/5)] |= 0x10 >> (i%5);
306 phase++;
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)
321 int button;
322 int rc = 0;
323 #ifdef BUTTON_OFF
324 const int offbutton = BUTTON_OFF;
325 #else
326 const int offbutton = BUTTON_STOP;
327 #endif
329 ide_power_enable(false); /* power down the disk, else would be spinning */
331 lcd_clear_display();
332 backlight_set_timeout(global_settings.backlight_timeout);
333 backlight_set_on_when_charging(global_settings.backlight_on_when_charging);
334 status_draw(true);
336 #ifdef HAVE_LCD_CHARCELLS
337 logo_lock_patterns(true);
338 #endif
339 charging_display_info(false);
343 status_draw(false);
344 charging_display_info(true);
345 button = button_get_w_tmo(HZ/3);
346 #ifdef BUTTON_ON
347 if (button == (BUTTON_ON | BUTTON_REL))
348 #else
349 if (button == (BUTTON_RIGHT | BUTTON_REL))
350 #endif
351 rc = 3;
352 else if (button == offbutton)
353 rc = 2;
354 else
356 if (usb_detect())
357 rc = 4;
358 else if (!charger_inserted())
359 rc = 1;
361 } while (!rc);
363 #ifdef HAVE_LCD_CHARCELLS
364 logo_lock_patterns(false);
365 #endif
366 return rc;
368 #endif /* HAVE_CHARGING */
371 #if CONFIG_KEYPAD == RECORDER_PAD
372 /* returns:
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)
378 int button;
379 static int pitch = 1000;
380 bool exit = false;
381 bool used = false;
383 while (!exit) {
385 if ( used ) {
386 char* ptr;
387 char buf[32];
388 int w, h;
390 lcd_clear_display();
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);
415 lcd_update();
418 /* use lastbutton, so the main loop can decide whether to
419 exit to browser or not */
420 button = button_get(true);
421 switch (button) {
422 case BUTTON_UP:
423 case BUTTON_ON | BUTTON_UP:
424 case BUTTON_ON | BUTTON_UP | BUTTON_REPEAT:
425 used = true;
426 pitch++;
427 if ( pitch > 2000 )
428 pitch = 2000;
429 mpeg_set_pitch(pitch);
430 break;
432 case BUTTON_DOWN:
433 case BUTTON_ON | BUTTON_DOWN:
434 case BUTTON_ON | BUTTON_DOWN | BUTTON_REPEAT:
435 used = true;
436 pitch--;
437 if ( pitch < 500 )
438 pitch = 500;
439 mpeg_set_pitch(pitch);
440 break;
442 case BUTTON_ON | BUTTON_PLAY:
443 mpeg_pause();
444 used = true;
445 break;
447 case BUTTON_PLAY | BUTTON_REL:
448 mpeg_resume();
449 used = true;
450 break;
452 case BUTTON_ON | BUTTON_PLAY | BUTTON_REL:
453 mpeg_resume();
454 exit = true;
455 break;
457 case BUTTON_ON | BUTTON_RIGHT:
458 if ( pitch < 2000 ) {
459 pitch += 20;
460 mpeg_set_pitch(pitch);
462 break;
464 case BUTTON_RIGHT | BUTTON_REL:
465 if ( pitch > 500 ) {
466 pitch -= 20;
467 mpeg_set_pitch(pitch);
469 break;
471 case BUTTON_ON | BUTTON_LEFT:
472 if ( pitch > 500 ) {
473 pitch -= 20;
474 mpeg_set_pitch(pitch);
476 break;
478 case BUTTON_LEFT | BUTTON_REL:
479 if ( pitch < 2000 ) {
480 pitch += 20;
481 mpeg_set_pitch(pitch);
483 break;
485 #ifdef SIMULATOR
486 case BUTTON_ON:
487 #else
488 case BUTTON_ON | BUTTON_REL:
489 case BUTTON_ON | BUTTON_UP | BUTTON_REL:
490 case BUTTON_ON | BUTTON_DOWN | BUTTON_REL:
491 #endif
492 exit = true;
493 break;
495 case BUTTON_ON | BUTTON_REPEAT:
496 used = true;
497 break;
499 default:
500 if(default_event_handler(button) == SYS_USB_CONNECTED)
501 return 2;
502 break;
506 lcd_setfont(FONT_UI);
508 if ( used )
509 return 1;
510 else
511 return 0;
514 bool quick_screen(int context, int button)
516 bool exit = false;
517 bool used = false;
518 int w, h, key;
519 char buf[32];
520 int oldrepeat = global_settings.repeat_mode;
522 /* just to stop compiler warning */
523 context = context;
524 lcd_setfont(FONT_SYSFIXED);
526 lcd_getstringsize("A",&w,&h);
528 while (!exit) {
529 char* ptr=NULL;
531 lcd_clear_display();
533 switch(button)
535 case BUTTON_F2:
536 /* Shuffle mode */
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 ) {
545 case SHOW_ALL:
546 ptr = str(LANG_FILTER_ALL);
547 break;
549 case SHOW_SUPPORTED:
550 ptr = str(LANG_FILTER_SUPPORTED);
551 break;
553 case SHOW_MUSIC:
554 ptr = str(LANG_FILTER_MUSIC);
555 break;
557 case SHOW_PLAYLIST:
558 ptr = str(LANG_FILTER_PLAYLIST);
559 break;
561 case SHOW_ID3DB:
562 ptr = str(LANG_FILTER_ID3DB);
563 break;
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);
572 /* Repeat Mode */
573 switch ( global_settings.repeat_mode ) {
574 case REPEAT_OFF:
575 ptr = str(LANG_OFF);
576 break;
578 case REPEAT_ALL:
579 ptr = str(LANG_REPEAT_ALL);
580 break;
582 case REPEAT_ONE:
583 ptr = str(LANG_REPEAT_ONE);
584 break;
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);
591 break;
592 case BUTTON_F3:
593 /* Scrollbar */
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));
599 /* Status bar */
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));
607 /* Flip */
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);
615 break;
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);
625 lcd_update();
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 ) )
634 key = button | key;
636 switch (key) {
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);
646 else
647 playlist_sort(NULL, true);
649 used = true;
650 break;
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;
657 used = true;
658 break;
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;
665 used = true;
666 break;
668 case BUTTON_F3 | BUTTON_LEFT:
669 case BUTTON_F3 | BUTTON_LEFT | BUTTON_REPEAT:
670 global_settings.scrollbar = !global_settings.scrollbar;
671 used = true;
672 break;
674 case BUTTON_F3 | BUTTON_RIGHT:
675 case BUTTON_F3 | BUTTON_RIGHT | BUTTON_REPEAT:
676 global_settings.statusbar = !global_settings.statusbar;
677 used = true;
678 break;
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);
687 used = true;
688 break;
690 case BUTTON_F3 | BUTTON_REL:
691 case BUTTON_F2 | BUTTON_REL:
693 if( used )
694 exit = true;
696 used = true;
698 break;
700 case BUTTON_OFF | BUTTON_REL:
701 lcd_setfont(FONT_UI);
702 return false;
704 default:
705 if(default_event_handler(key) == SYS_USB_CONNECTED)
706 return true;
707 break;
711 settings_save();
713 switch( button )
715 case BUTTON_F2:
717 if ( oldrepeat != global_settings.repeat_mode )
718 mpeg_flush_and_reload_tracks();
720 break;
721 case BUTTON_F3:
723 if (global_settings.statusbar)
724 lcd_setmargins(0, STATUSBAR_HEIGHT);
725 else
726 lcd_setmargins(0, 0);
728 break;
731 lcd_setfont(FONT_UI);
733 return false;
735 #endif
737 #ifdef HAVE_LCD_BITMAP
738 #define SPACE 3 /* pixels between words */
739 #define MAXLETTERS 128 /* 16*8 */
740 #define MAXLINES 10
741 #else
742 #define SPACE 1 /* one letter space */
743 #undef LCD_WIDTH
744 #define LCD_WIDTH 11
745 #undef LCD_HEIGHT
746 #define LCD_HEIGHT 2
747 #define MAXLETTERS 22 /* 11 * 2 */
748 #define MAXLINES 2
749 #endif
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 */
755 ...)
757 char *next;
758 char *store=NULL;
759 int x=0;
760 int y=0;
761 int w, h;
762 unsigned char splash_buf[MAXLETTERS];
763 va_list ap;
764 unsigned char widths[MAXLINES];
765 int line=0;
766 bool first=true;
767 #ifdef HAVE_LCD_BITMAP
768 int maxw=0;
769 #endif
771 #ifdef HAVE_LCD_CHARCELLS
772 lcd_double_height (false);
773 #endif
774 va_start( ap, fmt );
775 vsnprintf( splash_buf, sizeof(splash_buf), fmt, ap );
777 if(center) {
779 /* first a pass to measure sizes */
780 next = strtok_r(splash_buf, " ", &store);
781 while (next) {
782 #ifdef HAVE_LCD_BITMAP
783 lcd_getstringsize(next, &w, &h);
784 #else
785 w = strlen(next);
786 h = 1; /* store height in characters */
787 #endif
788 if(!first) {
789 if(x+w> LCD_WIDTH) {
790 /* Too wide, wrap */
791 y+=h;
792 line++;
793 if((y > (LCD_HEIGHT-h)) || (line > MAXLINES))
794 /* STOP */
795 break;
796 x=0;
797 first=true;
800 else
801 first = false;
803 /* think of it as if the text was written here at position x,y
804 being w pixels/chars wide and h high */
806 x += w+SPACE;
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)
811 maxw = widths[line];
812 #endif
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;
820 #else
821 y = 0; /* vertical center on 2 lines would be silly */
822 #endif
823 first=true;
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 );
829 va_end( ap );
831 if(center)
833 x = (LCD_WIDTH-widths[0])/2;
834 if(x < 0)
835 x = 0;
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);
848 else {
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);
854 else
855 #endif
856 lcd_clear_display();
857 line=0;
858 next = strtok_r(splash_buf, " ", &store);
859 while (next) {
860 #ifdef HAVE_LCD_BITMAP
861 lcd_getstringsize(next, &w, &h);
862 #else
863 w = strlen(next);
864 h = 1;
865 #endif
866 if(!first) {
867 if(x+w> LCD_WIDTH) {
868 /* too wide */
869 y+=h;
870 line++; /* goto next line */
871 first=true;
872 if(y > (LCD_HEIGHT-h))
873 /* STOP */
874 break;
875 if(center) {
876 x = (LCD_WIDTH-widths[line])/2;
877 if(x < 0)
878 x = 0;
880 else
881 x=0;
884 else
885 first=false;
886 #ifdef HAVE_LCD_BITMAP
887 lcd_putsxy(x, y, next);
888 #else
889 lcd_puts(x, y, next);
890 #endif
891 x += w+SPACE; /* pixels space! */
892 next = strtok_r(NULL, " ", &store);
894 lcd_update();
896 if(ticks)
897 /* unbreakable! */
898 sleep(ticks);
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 };
914 int value = 0;
916 if (!global_settings.talk_menu)
917 return;
919 switch(cursorpos)
921 case 0:
922 value = tm->tm_hour;
923 break;
924 case 1:
925 value = tm->tm_min;
926 break;
927 case 2:
928 value = tm->tm_sec;
929 break;
930 case 3:
931 value = tm->tm_year + 1900;
932 break;
933 case 5:
934 value = tm->tm_mday;
935 break;
938 if (cursorpos == 4) /* month */
939 talk_id(LANG_MONTH_JANUARY + tm->tm_mon, false);
940 else
941 talk_value(value, unit[cursorpos], false);
945 #define INDEX_X 0
946 #define INDEX_Y 1
947 #define INDEX_WIDTH 2
948 bool set_time_screen(const char* string, struct tm *tm)
950 bool done = false;
951 int button;
952 int min = 0, steps = 0;
953 int cursorpos = 0;
954 int lastcursorpos = !cursorpos;
955 unsigned char buffer[19];
956 int realyear;
957 int julianday;
958 int i;
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[] = {
965 LANG_WEEKDAY_SUNDAY,
966 LANG_WEEKDAY_MONDAY,
967 LANG_WEEKDAY_TUESDAY,
968 LANG_WEEKDAY_WEDNESDAY,
969 LANG_WEEKDAY_THURSDAY,
970 LANG_WEEKDAY_FRIDAY,
971 LANG_WEEKDAY_SATURDAY
973 static const int monthname[] = {
974 LANG_MONTH_JANUARY,
975 LANG_MONTH_FEBRUARY,
976 LANG_MONTH_MARCH,
977 LANG_MONTH_APRIL,
978 LANG_MONTH_MAY,
979 LANG_MONTH_JUNE,
980 LANG_MONTH_JULY,
981 LANG_MONTH_AUGUST,
982 LANG_MONTH_SEPTEMBER,
983 LANG_MONTH_OCTOBER,
984 LANG_MONTH_NOVEMBER,
985 LANG_MONTH_DECEMBER
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;
993 int *valptr = NULL;
995 #ifdef HAVE_LCD_BITMAP
996 if(global_settings.statusbar)
997 lcd_setmargins(0, STATUSBAR_HEIGHT);
998 else
999 lcd_setmargins(0, 0);
1000 #endif
1001 lcd_clear_display();
1002 lcd_puts_scroll(0, 0, string);
1004 while ( !done ) {
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;
1009 else
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 */
1017 julianday = 0;
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);
1034 /* hour */
1035 strncpy(reffub, buffer, 2);
1036 reffub[2] = '\0';
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;
1042 /* minute */
1043 strncpy(reffub, buffer + 3, 2);
1044 reffub[2] = '\0';
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;
1050 /* second */
1051 strncpy(reffub, buffer + 6, 2);
1052 reffub[2] = '\0';
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]));
1073 /* weekday */
1074 strncpy(reffub, buffer, dayname_len);
1075 reffub[dayname_len] = '\0';
1076 lcd_getstringsize(reffub, &weekday_width, &height);
1077 lcd_getstringsize(" ", &separator_width, &height);
1079 /* year */
1080 strncpy(reffub, buffer + dayname_len + 1, 4);
1081 reffub[4] = '\0';
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;
1087 /* month */
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;
1096 /* day */
1097 strncpy(reffub, buffer + dayname_len + monthname_len + 7, 2);
1098 reffub[2] = '\0';
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],
1109 line_height);
1111 lcd_puts(0, 4, str(LANG_TIME_SET));
1112 lcd_puts(0, 5, str(LANG_TIME_REVERT));
1113 #ifdef HAVE_LCD_BITMAP
1114 status_draw(true);
1115 #endif
1116 lcd_update();
1118 /* calculate the minimum and maximum for the number under cursor */
1119 if(cursorpos!=lastcursorpos) {
1120 lastcursorpos=cursorpos;
1121 switch(cursorpos) {
1122 case 0: /* hour */
1123 min = 0;
1124 steps = 24;
1125 valptr = &tm->tm_hour;
1126 break;
1127 case 1: /* minute */
1128 min = 0;
1129 steps = 60;
1130 valptr = &tm->tm_min;
1131 break;
1132 case 2: /* second */
1133 min = 0;
1134 steps = 60;
1135 valptr = &tm->tm_sec;
1136 break;
1137 case 3: /* year */
1138 min = 1;
1139 steps = 200;
1140 valptr = &tm->tm_year;
1141 break;
1142 case 4: /* month */
1143 min = 0;
1144 steps = 12;
1145 valptr = &tm->tm_mon;
1146 break;
1147 case 5: /* day */
1148 min = 1;
1149 steps = daysinmonth[tm->tm_mon];
1150 valptr = &tm->tm_mday;
1151 break;
1153 say_time(cursorpos, tm);
1156 button = button_get_w_tmo(HZ/2);
1157 switch ( button ) {
1158 case BUTTON_LEFT:
1159 cursorpos = (cursorpos + 6 - 1) % 6;
1160 break;
1161 case BUTTON_RIGHT:
1162 cursorpos = (cursorpos + 6 + 1) % 6;
1163 break;
1164 case BUTTON_UP:
1165 case BUTTON_UP | BUTTON_REPEAT:
1166 *valptr = (*valptr + steps - min + 1) %
1167 steps + min;
1168 if(*valptr == 0)
1169 *valptr = min;
1170 say_time(cursorpos, tm);
1171 break;
1172 case BUTTON_DOWN:
1173 case BUTTON_DOWN | BUTTON_REPEAT:
1174 *valptr = (*valptr + steps - min - 1) %
1175 steps + min;
1176 if(*valptr == 0)
1177 *valptr = min;
1178 say_time(cursorpos, tm);
1179 break;
1181 #ifdef BUTTON_ON
1182 case BUTTON_ON:
1183 #elif defined BUTTON_MENU
1184 case BUTTON_MENU:
1185 #endif
1186 done = true;
1187 break;
1189 case BUTTON_OFF:
1190 done = true;
1191 tm->tm_year = -1;
1192 break;
1194 default:
1195 if (default_event_handler(button) == SYS_USB_CONNECTED)
1196 return true;
1197 break;
1201 return false;
1203 #endif
1205 #if CONFIG_KEYPAD == RECORDER_PAD || CONFIG_KEYPAD == IRIVER_H100_PAD
1206 bool shutdown_screen(void)
1208 int button;
1209 bool done = false;
1211 lcd_stop_scroll();
1213 splash(0, true, str(LANG_CONFIRM_SHUTDOWN));
1215 while(!done)
1217 button = button_get_w_tmo(HZ*2);
1218 switch(button)
1220 case BUTTON_OFF:
1221 clean_shutdown();
1222 break;
1224 default:
1225 if(default_event_handler(button) == SYS_USB_CONNECTED)
1226 return true;
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)))
1235 done = true;
1236 break;
1239 return false;
1241 #endif
1243 bool browse_id3(void)
1245 struct mp3entry* id3 = mpeg_current_track();
1246 int button;
1247 int menu_pos = 0;
1248 int menu_max = 8;
1249 bool exit = false;
1250 char scroll_text[MAX_PATH];
1252 if (!(mpeg_status() & MPEG_STATUS_PLAY))
1253 return false;
1255 while (!exit)
1257 lcd_clear_display();
1259 switch (menu_pos)
1261 case 0:
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));
1265 break;
1267 case 1:
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));
1272 break;
1274 case 2:
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));
1278 break;
1280 case 3:
1281 lcd_puts(0, 0, str(LANG_ID3_TRACKNUM));
1283 if (id3->tracknum) {
1284 snprintf(scroll_text,sizeof(scroll_text), "%d",
1285 id3->tracknum);
1286 lcd_puts_scroll(0, 1, scroll_text);
1288 else
1289 lcd_puts_scroll(0, 1, str(LANG_ID3_NO_TRACKNUM));
1290 break;
1292 case 4:
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));
1298 break;
1300 case 5:
1301 lcd_puts(0, 0, str(LANG_ID3_YEAR));
1302 if (id3->year) {
1303 snprintf(scroll_text,sizeof(scroll_text), "%d",
1304 id3->year);
1305 lcd_puts_scroll(0, 1, scroll_text);
1307 else
1308 lcd_puts_scroll(0, 1, str(LANG_ID3_NO_INFO));
1309 break;
1311 case 6:
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);
1317 break;
1319 case 7:
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);
1324 break;
1327 case 8:
1328 lcd_puts(0, 0, str(LANG_ID3_BITRATE));
1329 snprintf(scroll_text,sizeof(scroll_text), "%d kbps",
1330 id3->bitrate);
1331 lcd_puts(0, 1, scroll_text);
1332 break;
1334 case 9:
1335 lcd_puts(0, 0, str(LANG_ID3_FRECUENCY));
1336 snprintf(scroll_text,sizeof(scroll_text), "%d Hz",
1337 id3->frequency);
1338 lcd_puts(0, 1, scroll_text);
1339 break;
1341 case 10:
1342 lcd_puts(0, 0, str(LANG_ID3_PATH));
1343 lcd_puts_scroll(0, 1, id3->path);
1344 break;
1346 lcd_update();
1348 button = button_get(true);
1350 switch(button)
1352 case SETTINGS_DEC:
1353 if (menu_pos > 0)
1354 menu_pos--;
1355 else
1356 menu_pos = menu_max;
1357 break;
1359 case SETTINGS_INC:
1360 if (menu_pos < menu_max)
1361 menu_pos++;
1362 else
1363 menu_pos = 0;
1364 break;
1366 case SETTINGS_CANCEL:
1367 lcd_stop_scroll();
1368 /* eat release event */
1369 button_get(true);
1370 exit = true;
1371 break;
1373 default:
1374 if(default_event_handler(button) == SYS_USB_CONNECTED)
1375 return true;
1376 break;
1379 return false;