Now fully v1 spec compliant
[kugel-rb.git] / apps / settings_menu.c
blobab4f242816a1b04054dbd770b1650ac86aea7537
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 Robert Hak
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 "config.h"
22 #include <stdio.h>
23 #include <stdbool.h>
24 #include <string.h>
26 #include "lcd.h"
27 #include "menu.h"
28 #include "mpeg.h"
29 #include "button.h"
30 #include "kernel.h"
31 #include "thread.h"
32 #include "sprintf.h"
33 #include "settings.h"
34 #include "settings_menu.h"
35 #include "backlight.h"
36 #include "playlist.h" /* for playlist_shuffle */
37 #include "fat.h" /* For dotfile settings */
38 #include "sleeptimer.h"
39 #include "powermgmt.h"
40 #include "rtc.h"
41 #include "ata.h"
42 #include "tree.h"
43 #include "screens.h"
44 #include "talk.h"
45 #include "timefuncs.h"
46 #include "misc.h"
47 #ifdef HAVE_LCD_BITMAP
48 #include "peakmeter.h"
49 #endif
50 #include "lang.h"
51 #if CONFIG_HWCODEC == MAS3507D
52 void dac_line_in(bool enable);
53 #endif
54 #ifdef HAVE_ALARM_MOD
55 #include "alarm_menu.h"
56 #endif
58 /* This flag is set by dirbrowse() if a new language is loaded */
59 bool language_changed;
61 #ifdef HAVE_CHARGING
62 static bool car_adapter_mode(void)
64 return set_bool_options( str(LANG_CAR_ADAPTER_MODE),
65 &global_settings.car_adapter_mode,
66 STR(LANG_SET_BOOL_YES),
67 STR(LANG_SET_BOOL_NO),
68 set_car_adapter_mode);
70 #endif
72 static bool contrast(void)
74 return set_int( str(LANG_CONTRAST), "", UNIT_INT,
75 &global_settings.contrast,
76 lcd_set_contrast, 1, MIN_CONTRAST_SETTING,
77 MAX_CONTRAST_SETTING );
80 #ifdef HAVE_BACKLIGHT
81 static bool caption_backlight(void)
83 bool rc = set_bool( str(LANG_CAPTION_BACKLIGHT),
84 &global_settings.caption_backlight);
86 return rc;
88 #endif
90 /**
91 * Menu to set icon visibility
93 static bool show_icons(void)
95 return set_bool( str(LANG_SHOW_ICONS), &global_settings.show_icons );
98 #ifdef HAVE_LCD_BITMAP
101 * Menu to set LCD Mode (normal/inverse)
103 static bool invert(void)
105 bool rc = set_bool_options(str(LANG_INVERT),
106 &global_settings.invert,
107 STR(LANG_INVERT_LCD_INVERSE),
108 STR(LANG_INVERT_LCD_NORMAL),
109 lcd_set_invert_display);
110 return rc;
114 * Menu to set Line Selector Type (Pointer/Bar)
116 static bool invert_cursor(void)
118 return set_bool_options(str(LANG_INVERT_CURSOR),
119 &global_settings.invert_cursor,
120 STR(LANG_INVERT_CURSOR_BAR),
121 STR(LANG_INVERT_CURSOR_POINTER),
122 NULL);
126 * Menu to turn the display+buttons by 180 degrees
128 static bool flip_display(void)
130 bool rc = set_bool( str(LANG_FLIP_DISPLAY),
131 &global_settings.flip_display);
133 button_set_flip(global_settings.flip_display);
134 lcd_set_flip(global_settings.flip_display);
136 return rc;
140 * Menu to configure the battery display on status bar
142 static bool battery_type(void)
144 static const struct opt_items names[] = {
145 { STR(LANG_DISPLAY_GRAPHIC) },
146 { STR(LANG_DISPLAY_NUMERIC) }
148 return set_option( str(LANG_BATTERY_DISPLAY),
149 &global_settings.battery_type, INT, names, 2, NULL);
153 * Menu to configure the volume display on status bar
155 static bool volume_type(void)
157 static const struct opt_items names[] = {
158 { STR(LANG_DISPLAY_GRAPHIC) },
159 { STR(LANG_DISPLAY_NUMERIC) }
161 return set_option( str(LANG_VOLUME_DISPLAY), &global_settings.volume_type,
162 INT, names, 2, NULL);
165 #ifdef PM_DEBUG
166 static bool peak_meter_fps_menu(void) {
167 bool retval = false;
168 retval = set_int( "Refresh rate", "/s", UNIT_PER_SEC,
169 &peak_meter_fps,
170 NULL, 1, 5, 40);
171 return retval;
173 #endif /* PM_DEBUG */
176 * Menu to set the hold time of normal peaks.
178 static bool peak_meter_hold(void) {
179 bool retval = false;
180 static const struct opt_items names[] = {
181 { STR(LANG_OFF) },
182 { "200 ms " , TALK_ID(200, UNIT_MS) },
183 { "300 ms " , TALK_ID(300, UNIT_MS) },
184 { "500 ms " , TALK_ID(500, UNIT_MS) },
185 { "1 s" , TALK_ID(1, UNIT_SEC) },
186 { "2 s" , TALK_ID(2, UNIT_SEC) },
187 { "3 s" , TALK_ID(3, UNIT_SEC) },
188 { "4 s" , TALK_ID(4, UNIT_SEC) },
189 { "5 s" , TALK_ID(5, UNIT_SEC) },
190 { "6 s" , TALK_ID(6, UNIT_SEC) },
191 { "7 s" , TALK_ID(7, UNIT_SEC) },
192 { "8 s" , TALK_ID(8, UNIT_SEC) },
193 { "9 s" , TALK_ID(9, UNIT_SEC) },
194 { "10 s" , TALK_ID(10, UNIT_SEC) },
195 { "15 s" , TALK_ID(15, UNIT_SEC) },
196 { "20 s" , TALK_ID(20, UNIT_SEC) },
197 { "30 s" , TALK_ID(30, UNIT_SEC) },
198 { "1 min" , TALK_ID(1, UNIT_MIN) }
200 retval = set_option( str(LANG_PM_PEAK_HOLD),
201 &global_settings.peak_meter_hold, INT, names,
202 18, NULL);
204 peak_meter_init_times(global_settings.peak_meter_release,
205 global_settings.peak_meter_hold,
206 global_settings.peak_meter_clip_hold);
208 return retval;
212 * Menu to set the hold time of clips.
214 static bool peak_meter_clip_hold(void) {
215 bool retval = false;
217 static const struct opt_items names[] = {
218 { STR(LANG_PM_ETERNAL) },
219 { "1s " , TALK_ID(1, UNIT_SEC) },
220 { "2s " , TALK_ID(2, UNIT_SEC) },
221 { "3s " , TALK_ID(3, UNIT_SEC) },
222 { "4s " , TALK_ID(4, UNIT_SEC) },
223 { "5s " , TALK_ID(5, UNIT_SEC) },
224 { "6s " , TALK_ID(6, UNIT_SEC) },
225 { "7s " , TALK_ID(7, UNIT_SEC) },
226 { "8s " , TALK_ID(8, UNIT_SEC) },
227 { "9s " , TALK_ID(9, UNIT_SEC) },
228 { "10s" , TALK_ID(10, UNIT_SEC) },
229 { "15s" , TALK_ID(15, UNIT_SEC) },
230 { "20s" , TALK_ID(20, UNIT_SEC) },
231 { "25s" , TALK_ID(25, UNIT_SEC) },
232 { "30s" , TALK_ID(30, UNIT_SEC) },
233 { "45s" , TALK_ID(45, UNIT_SEC) },
234 { "60s" , TALK_ID(60, UNIT_SEC) },
235 { "90s" , TALK_ID(90, UNIT_SEC) },
236 { "2min" , TALK_ID(2, UNIT_MIN) },
237 { "3min" , TALK_ID(3, UNIT_MIN) },
238 { "5min" , TALK_ID(5, UNIT_MIN) },
239 { "10min" , TALK_ID(10, UNIT_MIN) },
240 { "20min" , TALK_ID(20, UNIT_MIN) },
241 { "45min" , TALK_ID(45, UNIT_MIN) },
242 { "90min" , TALK_ID(90, UNIT_MIN) }
244 retval = set_option( str(LANG_PM_CLIP_HOLD),
245 &global_settings.peak_meter_clip_hold, INT, names,
246 25, peak_meter_set_clip_hold);
248 peak_meter_init_times(global_settings.peak_meter_release,
249 global_settings.peak_meter_hold,
250 global_settings.peak_meter_clip_hold);
252 return retval;
256 * Menu to set the release time of the peak meter.
258 static bool peak_meter_release(void) {
259 bool retval = false;
261 /* The range of peak_meter_release is restricted so that it
262 fits into a 7 bit number. The 8th bit is used for storing
263 something else in the rtc ram.
264 Also, the max value is 0x7e, since the RTC value 0xff is reserved */
265 retval = set_int( str(LANG_PM_RELEASE), STR(LANG_PM_UNITS_PER_READ),
266 &global_settings.peak_meter_release,
267 NULL, 1, 1, 0x7e);
269 peak_meter_init_times(global_settings.peak_meter_release,
270 global_settings.peak_meter_hold,
271 global_settings.peak_meter_clip_hold);
273 return retval;
277 * Menu to select wether the scale of the meter
278 * displays dBfs of linear values.
280 static bool peak_meter_scale(void) {
281 bool retval = false;
282 bool use_dbfs = global_settings.peak_meter_dbfs;
283 retval = set_bool_options(str(LANG_PM_SCALE),
284 &use_dbfs,
285 STR(LANG_PM_DBFS), STR(LANG_PM_LINEAR),
286 NULL);
288 /* has the user really changed the scale? */
289 if (use_dbfs != global_settings.peak_meter_dbfs) {
291 /* store the change */
292 global_settings.peak_meter_dbfs = use_dbfs;
293 peak_meter_set_use_dbfs(use_dbfs);
295 /* If the user changed the scale mode the meaning of
296 peak_meter_min (peak_meter_max) has changed. Thus we have
297 to convert the values stored in global_settings. */
298 if (use_dbfs) {
300 /* we only store -dBfs */
301 global_settings.peak_meter_min = -peak_meter_get_min() / 100;
302 global_settings.peak_meter_max = -peak_meter_get_max() / 100;
303 } else {
304 int max;
306 /* linear percent */
307 global_settings.peak_meter_min = peak_meter_get_min();
309 /* converting dBfs -> percent results in a precision loss.
310 I assume that the user doesn't bother that conversion
311 dBfs <-> percent isn't symmetrical for odd values but that
312 he wants 0 dBfs == 100%. Thus I 'correct' the percent value
313 resulting from dBfs -> percent manually here */
314 max = peak_meter_get_max();
315 global_settings.peak_meter_max = max < 99 ? max : 100;
317 settings_apply_pm_range();
319 return retval;
323 * Adjust the min value of the value range that
324 * the peak meter shall visualize.
326 static bool peak_meter_min(void) {
327 bool retval = false;
328 if (global_settings.peak_meter_dbfs) {
330 /* for dBfs scale */
331 int range_max = -global_settings.peak_meter_max;
332 int min = -global_settings.peak_meter_min;
334 retval = set_int(str(LANG_PM_MIN), str(LANG_PM_DBFS), UNIT_DB,
335 &min, NULL, 1, -89, range_max);
337 global_settings.peak_meter_min = - min;
340 /* for linear scale */
341 else {
342 int min = global_settings.peak_meter_min;
344 retval = set_int(str(LANG_PM_MIN), "%", UNIT_PERCENT,
345 &min, NULL,
346 1, 0, global_settings.peak_meter_max - 1);
348 global_settings.peak_meter_min = (unsigned char)min;
351 settings_apply_pm_range();
352 return retval;
357 * Adjust the max value of the value range that
358 * the peak meter shall visualize.
360 static bool peak_meter_max(void) {
361 bool retval = false;
362 if (global_settings.peak_meter_dbfs) {
364 /* for dBfs scale */
365 int range_min = -global_settings.peak_meter_min;
366 int max = -global_settings.peak_meter_max;;
368 retval = set_int(str(LANG_PM_MAX), str(LANG_PM_DBFS), UNIT_DB,
369 &max, NULL, 1, range_min, 0);
371 global_settings.peak_meter_max = - max;
375 /* for linear scale */
376 else {
377 int max = global_settings.peak_meter_max;
379 retval = set_int(str(LANG_PM_MAX), "%", UNIT_PERCENT,
380 &max, NULL,
381 1, global_settings.peak_meter_min + 1, 100);
383 global_settings.peak_meter_max = (unsigned char)max;
386 settings_apply_pm_range();
387 return retval;
391 * Menu to select wether the meter is in
392 * precision or in energy saver mode
394 static bool peak_meter_performance(void) {
395 bool retval = false;
396 retval = set_bool_options(str(LANG_PM_PERFORMANCE),
397 &global_settings.peak_meter_performance,
398 STR(LANG_PM_HIGH_PERFORMANCE), STR(LANG_PM_ENERGY_SAVER),
399 NULL);
401 if (global_settings.peak_meter_performance) {
402 peak_meter_fps = 25;
403 } else {
404 peak_meter_fps = 20;
406 return retval;
410 * Menu to configure the peak meter
412 static bool peak_meter_menu(void)
414 int m;
415 bool result;
417 static const struct menu_item items[] = {
418 { ID2P(LANG_PM_RELEASE) , peak_meter_release },
419 { ID2P(LANG_PM_PEAK_HOLD), peak_meter_hold },
420 { ID2P(LANG_PM_CLIP_HOLD), peak_meter_clip_hold },
421 { ID2P(LANG_PM_PERFORMANCE), peak_meter_performance },
422 #ifdef PM_DEBUG
423 { "Refresh rate" , -1 , peak_meter_fps_menu },
424 #endif
425 { ID2P(LANG_PM_SCALE) , peak_meter_scale },
426 { ID2P(LANG_PM_MIN) , peak_meter_min },
427 { ID2P(LANG_PM_MAX) , peak_meter_max },
430 m=menu_init( items, sizeof(items) / sizeof(*items), NULL,
431 NULL, NULL, NULL );
432 result = menu_run(m);
433 menu_exit(m);
434 return result;
436 #endif /* HAVE_LCD_BITMAP */
438 static bool shuffle(void)
440 return set_bool( str(LANG_SHUFFLE), &global_settings.playlist_shuffle );
443 static bool repeat_mode(void)
445 bool result;
446 static const struct opt_items names[] = {
447 { STR(LANG_OFF) },
448 { STR(LANG_REPEAT_ALL) },
449 { STR(LANG_REPEAT_ONE) }
451 int old_repeat = global_settings.repeat_mode;
453 result = set_option( str(LANG_REPEAT), &global_settings.repeat_mode,
454 INT, names, 3, NULL );
456 if (old_repeat != global_settings.repeat_mode)
457 mpeg_flush_and_reload_tracks();
459 return result;
462 static bool play_selected(void)
464 return set_bool( str(LANG_PLAY_SELECTED), &global_settings.play_selected );
467 static bool dir_filter(void)
469 static const struct opt_items names[] = {
470 { STR(LANG_FILTER_ALL) },
471 { STR(LANG_FILTER_SUPPORTED) },
472 { STR(LANG_FILTER_MUSIC) },
473 { STR(LANG_FILTER_PLAYLIST) }
475 return set_option( str(LANG_FILTER), &global_settings.dirfilter, INT,
476 names, 4, NULL );
479 static bool sort_case(void)
481 return set_bool( str(LANG_SORT_CASE), &global_settings.sort_case );
484 static bool sort_file(void)
486 int oldval = global_settings.sort_file;
487 bool ret;
488 static const struct opt_items names[] = {
489 { STR(LANG_SORT_ALPHA) },
490 { STR(LANG_SORT_DATE) },
491 { STR(LANG_SORT_DATE_REVERSE) },
492 { STR(LANG_SORT_TYPE) }
494 ret = set_option( str(LANG_SORT_FILE), &global_settings.sort_file, INT,
495 names, 4, NULL );
496 if (global_settings.sort_file != oldval)
497 reload_directory(); /* force reload if this has changed */
498 return ret;
501 static bool sort_dir(void)
503 int oldval = global_settings.sort_dir;
504 bool ret;
505 static const struct opt_items names[] = {
506 { STR(LANG_SORT_ALPHA) },
507 { STR(LANG_SORT_DATE) },
508 { STR(LANG_SORT_DATE_REVERSE) }
510 ret = set_option( str(LANG_SORT_DIR), &global_settings.sort_dir, INT,
511 names, 3, NULL );
512 if (global_settings.sort_dir != oldval)
513 reload_directory(); /* force reload if this has changed */
514 return ret;
517 static bool resume(void)
519 static const struct opt_items names[] = {
520 { STR(LANG_SET_BOOL_NO) },
521 { STR(LANG_RESUME_SETTING_ASK) },
522 { STR(LANG_RESUME_SETTING_ASK_ONCE) },
523 { STR(LANG_SET_BOOL_YES) }
525 return set_option( str(LANG_RESUME), &global_settings.resume, INT,
526 names, 4, NULL );
529 static bool autocreatebookmark(void)
531 bool retval = false;
532 static const struct opt_items names[] = {
533 { STR(LANG_SET_BOOL_NO) },
534 { STR(LANG_SET_BOOL_YES) },
535 { STR(LANG_RESUME_SETTING_ASK) },
536 { STR(LANG_BOOKMARK_SETTINGS_RECENT_ONLY_YES) },
537 { STR(LANG_BOOKMARK_SETTINGS_RECENT_ONLY_ASK) }
540 retval = set_option( str(LANG_BOOKMARK_SETTINGS_AUTOCREATE),
541 &global_settings.autocreatebookmark, INT,
542 names, 5, NULL );
543 if(global_settings.autocreatebookmark == BOOKMARK_RECENT_ONLY_YES ||
544 global_settings.autocreatebookmark == BOOKMARK_RECENT_ONLY_ASK)
546 if(global_settings.usemrb == BOOKMARK_NO)
547 global_settings.usemrb = BOOKMARK_YES;
550 return retval;
553 static bool autoloadbookmark(void)
555 static const struct opt_items names[] = {
556 { STR(LANG_SET_BOOL_NO) },
557 { STR(LANG_SET_BOOL_YES) },
558 { STR(LANG_RESUME_SETTING_ASK) }
560 return set_option( str(LANG_BOOKMARK_SETTINGS_AUTOLOAD),
561 &global_settings.autoloadbookmark, INT,
562 names, 3, NULL );
565 static bool useMRB(void)
567 static const struct opt_items names[] = {
568 { STR(LANG_SET_BOOL_NO) },
569 { STR(LANG_SET_BOOL_YES) },
570 { STR(LANG_BOOKMARK_SETTINGS_UNIQUE_ONLY) }
572 return set_option( str(LANG_BOOKMARK_SETTINGS_MAINTAIN_RECENT_BOOKMARKS),
573 &global_settings.usemrb, INT,
574 names, 3, NULL );
577 #ifdef HAVE_BACKLIGHT
578 static bool backlight_on_when_charging(void)
580 bool result = set_bool(str(LANG_BACKLIGHT_ON_WHEN_CHARGING),
581 &global_settings.backlight_on_when_charging);
582 backlight_set_on_when_charging(global_settings.backlight_on_when_charging);
583 return result;
586 static bool backlight_timer(void)
588 static const struct opt_items names[] = {
589 { STR(LANG_OFF) },
590 { STR(LANG_ON) },
591 { "1s ", TALK_ID(1, UNIT_SEC) },
592 { "2s ", TALK_ID(2, UNIT_SEC) },
593 { "3s ", TALK_ID(3, UNIT_SEC) },
594 { "4s ", TALK_ID(4, UNIT_SEC) },
595 { "5s ", TALK_ID(5, UNIT_SEC) },
596 { "6s ", TALK_ID(6, UNIT_SEC) },
597 { "7s ", TALK_ID(7, UNIT_SEC) },
598 { "8s ", TALK_ID(8, UNIT_SEC) },
599 { "9s ", TALK_ID(9, UNIT_SEC) },
600 { "10s", TALK_ID(10, UNIT_SEC) },
601 { "15s", TALK_ID(15, UNIT_SEC) },
602 { "20s", TALK_ID(20, UNIT_SEC) },
603 { "25s", TALK_ID(25, UNIT_SEC) },
604 { "30s", TALK_ID(30, UNIT_SEC) },
605 { "45s", TALK_ID(45, UNIT_SEC) },
606 { "60s", TALK_ID(60, UNIT_SEC) },
607 { "90s", TALK_ID(90, UNIT_SEC) }
609 return set_option(str(LANG_BACKLIGHT), &global_settings.backlight_timeout,
610 INT, names, 19, backlight_set_timeout );
612 #endif /* HAVE_BACKLIGHT */
614 static bool poweroff_idle_timer(void)
616 static const struct opt_items names[] = {
617 { STR(LANG_OFF) },
618 { "1m ", TALK_ID(1, UNIT_MIN) },
619 { "2m ", TALK_ID(2, UNIT_MIN) },
620 { "3m ", TALK_ID(3, UNIT_MIN) },
621 { "4m ", TALK_ID(4, UNIT_MIN) },
622 { "5m ", TALK_ID(5, UNIT_MIN) },
623 { "6m ", TALK_ID(6, UNIT_MIN) },
624 { "7m ", TALK_ID(7, UNIT_MIN) },
625 { "8m ", TALK_ID(8, UNIT_MIN) },
626 { "9m ", TALK_ID(9, UNIT_MIN) },
627 { "10m", TALK_ID(10, UNIT_MIN) },
628 { "15m", TALK_ID(15, UNIT_MIN) },
629 { "30m", TALK_ID(30, UNIT_MIN) },
630 { "45m", TALK_ID(45, UNIT_MIN) },
631 { "60m", TALK_ID(60, UNIT_MIN) }
633 return set_option(str(LANG_POWEROFF_IDLE), &global_settings.poweroff,
634 INT, names, 15, set_poweroff_timeout);
637 static bool scroll_speed(void)
639 return set_int(str(LANG_SCROLL), "", UNIT_INT,
640 &global_settings.scroll_speed,
641 &lcd_scroll_speed, 1, 0, 15 );
645 static bool scroll_delay(void)
647 int dummy = global_settings.scroll_delay * (HZ/10);
648 int rc = set_int(str(LANG_SCROLL_DELAY), "ms", UNIT_MS,
649 &dummy,
650 &lcd_scroll_delay, 100, 0, 2500 );
651 global_settings.scroll_delay = dummy / (HZ/10);
652 return rc;
655 #ifdef HAVE_LCD_BITMAP
656 static bool scroll_step(void)
658 return set_int(str(LANG_SCROLL_STEP_EXAMPLE), "pixels", UNIT_PIXEL,
659 &global_settings.scroll_step,
660 &lcd_scroll_step, 1, 1, LCD_WIDTH );
662 #endif
664 static bool bidir_limit(void)
666 return set_int(str(LANG_BIDIR_SCROLL), "%", UNIT_PERCENT,
667 &global_settings.bidir_limit,
668 &lcd_bidir_scroll, 25, 0, 200 );
671 #ifdef HAVE_LCD_CHARCELLS
672 static bool jump_scroll(void)
674 static const struct opt_items names[] = {
675 { STR(LANG_OFF) },
676 { STR(LANG_ONE_TIME) },
677 { "2", TALK_ID(2, UNIT_INT) },
678 { "3", TALK_ID(3, UNIT_INT) },
679 { "4", TALK_ID(4, UNIT_INT) },
680 { STR(LANG_ALWAYS) }
682 bool ret;
683 ret=set_option(str(LANG_JUMP_SCROLL), &global_settings.jump_scroll,
684 INT, names, 6, lcd_jump_scroll);
685 return ret;
687 static bool jump_scroll_delay(void)
689 int dummy = global_settings.jump_scroll_delay * (HZ/10);
690 int rc = set_int(str(LANG_JUMP_SCROLL_DELAY), "ms", UNIT_MS,
691 &dummy,
692 &lcd_jump_scroll_delay, 100, 0, 2500 );
693 global_settings.jump_scroll_delay = dummy / (HZ/10);
694 return rc;
696 #endif
698 #ifndef SIMULATOR
700 * Menu to set the battery capacity
702 static bool battery_capacity(void)
704 return set_int(str(LANG_BATTERY_CAPACITY), "mAh", UNIT_MAH,
705 &global_settings.battery_capacity,
706 &set_battery_capacity, 50, BATTERY_CAPACITY_MIN,
707 BATTERY_CAPACITY_MAX );
709 #endif
711 #ifdef HAVE_CHARGE_CTRL
712 static bool deep_discharge(void)
714 bool result;
715 result = set_bool( str(LANG_DISCHARGE), &global_settings.discharge );
716 charge_restart_level = global_settings.discharge ?
717 CHARGE_RESTART_LO : CHARGE_RESTART_HI;
718 return result;
720 static bool trickle_charge(void)
722 bool result;
723 result = set_bool( str(LANG_TRICKLE_CHARGE), &global_settings.trickle_charge );
724 enable_trickle_charge(global_settings.trickle_charge);
725 return result;
727 #endif
729 #ifdef HAVE_RTC
730 static bool timedate_set(void)
732 struct tm tm;
733 int timedate[8];
734 bool result;
736 timedate[0] = rtc_read(0x03); /* hour */
737 timedate[1] = rtc_read(0x02); /* minute */
738 timedate[2] = rtc_read(0x01); /* second */
739 timedate[3] = rtc_read(0x07); /* year */
740 timedate[4] = rtc_read(0x06); /* month */
741 timedate[5] = rtc_read(0x05); /* day */
743 /* Make a local copy of the time struct */
744 memcpy(&tm, get_time(), sizeof(struct tm));
746 /* do some range checks */
747 /* This prevents problems with time/date setting after a power loss */
748 if (!valid_time(&tm))
750 /* hour */
751 tm.tm_hour = 0;
752 tm.tm_min = 0;
753 tm.tm_sec = 0;
754 tm.tm_mday = 1;
755 tm.tm_mon = 0;
756 tm.tm_wday = 1;
757 tm.tm_year = 100;
760 result = set_time_screen(str(LANG_TIME), &tm);
762 if(tm.tm_year != -1) {
763 set_time(&tm);
765 return result;
768 static bool timeformat_set(void)
770 static const struct opt_items names[] = {
771 { STR(LANG_24_HOUR_CLOCK) },
772 { STR(LANG_12_HOUR_CLOCK) }
774 return set_option(str(LANG_TIMEFORMAT), &global_settings.timeformat,
775 INT, names, 2, NULL);
777 #endif
779 #ifndef HAVE_MMC
780 static bool spindown(void)
782 return set_int(str(LANG_SPINDOWN), "s", UNIT_SEC,
783 &global_settings.disk_spindown,
784 ata_spindown, 1, 3, 254 );
787 #ifdef HAVE_ATA_POWER_OFF
788 static bool poweroff(void)
790 bool rc = set_bool(str(LANG_POWEROFF), &global_settings.disk_poweroff);
791 ata_poweroff(global_settings.disk_poweroff);
792 return rc;
794 #endif /* HAVE_ATA_POWEROFF */
795 #endif /* !HAVE_MMC */
797 #if CONFIG_HWCODEC == MAS3507D
798 static bool line_in(void)
800 bool rc = set_bool(str(LANG_LINE_IN), &global_settings.line_in);
801 dac_line_in(global_settings.line_in);
802 return rc;
804 #endif
806 static bool max_files_in_dir(void)
808 return set_int(str(LANG_MAX_FILES_IN_DIR), "", UNIT_INT,
809 &global_settings.max_files_in_dir,
810 NULL, 50, 50, 10000 );
813 static bool max_files_in_playlist(void)
815 return set_int(str(LANG_MAX_FILES_IN_PLAYLIST), "", UNIT_INT,
816 &global_settings.max_files_in_playlist,
817 NULL, 1000, 1000, 20000 );
820 static bool buffer_margin(void)
822 return set_int(str(LANG_MP3BUFFER_MARGIN), "s", UNIT_SEC,
823 &global_settings.buffer_margin,
824 mpeg_set_buffer_margin, 1, 0, 7 );
827 static bool ff_rewind_min_step(void)
829 static const struct opt_items names[] = {
830 { "1s", TALK_ID(1, UNIT_SEC) },
831 { "2s", TALK_ID(2, UNIT_SEC) },
832 { "3s", TALK_ID(3, UNIT_SEC) },
833 { "4s", TALK_ID(4, UNIT_SEC) },
834 { "5s", TALK_ID(5, UNIT_SEC) },
835 { "6s", TALK_ID(6, UNIT_SEC) },
836 { "8s", TALK_ID(8, UNIT_SEC) },
837 { "10s", TALK_ID(10, UNIT_SEC) },
838 { "15s", TALK_ID(15, UNIT_SEC) },
839 { "20s", TALK_ID(20, UNIT_SEC) },
840 { "25s", TALK_ID(25, UNIT_SEC) },
841 { "30s", TALK_ID(30, UNIT_SEC) },
842 { "45s", TALK_ID(45, UNIT_SEC) },
843 { "60s", TALK_ID(60, UNIT_SEC) }
845 return set_option(str(LANG_FFRW_STEP), &global_settings.ff_rewind_min_step,
846 INT, names, 14, NULL );
849 static bool set_fade_on_stop(void)
851 return set_bool( str(LANG_FADE_ON_STOP), &global_settings.fade_on_stop );
855 static bool ff_rewind_accel(void)
857 static const struct opt_items names[] = {
858 { STR(LANG_OFF) },
859 { "2x/1s", TALK_ID(1, UNIT_SEC) },
860 { "2x/2s", TALK_ID(2, UNIT_SEC) },
861 { "2x/3s", TALK_ID(3, UNIT_SEC) },
862 { "2x/4s", TALK_ID(4, UNIT_SEC) },
863 { "2x/5s", TALK_ID(5, UNIT_SEC) },
864 { "2x/6s", TALK_ID(6, UNIT_SEC) },
865 { "2x/7s", TALK_ID(7, UNIT_SEC) },
866 { "2x/8s", TALK_ID(8, UNIT_SEC) },
867 { "2x/9s", TALK_ID(9, UNIT_SEC) },
868 { "2x/10s", TALK_ID(10, UNIT_SEC) },
869 { "2x/11s", TALK_ID(11, UNIT_SEC) },
870 { "2x/12s", TALK_ID(12, UNIT_SEC) },
871 { "2x/13s", TALK_ID(13, UNIT_SEC) },
872 { "2x/14s", TALK_ID(14, UNIT_SEC) },
873 { "2x/15s", TALK_ID(15, UNIT_SEC) }
875 return set_option(str(LANG_FFRW_ACCEL), &global_settings.ff_rewind_accel,
876 INT, names, 16, NULL );
879 static bool browse_current(void)
881 return set_bool( str(LANG_FOLLOW), &global_settings.browse_current );
884 static bool custom_wps_browse(void)
886 return rockbox_browse(ROCKBOX_DIR, SHOW_WPS);
889 static bool custom_cfg_browse(void)
891 return rockbox_browse(ROCKBOX_DIR, SHOW_CFG);
894 static bool language_browse(void)
896 language_changed = false;
897 rockbox_browse(ROCKBOX_DIR LANG_DIR, SHOW_LNG);
898 return language_changed;
901 static bool voice_menus(void)
903 bool ret;
904 bool temp = global_settings.talk_menu;
905 /* work on a temp variable first, avoid "life" disabling */
906 ret = set_bool( str(LANG_VOICE_MENU), &temp );
907 global_settings.talk_menu = temp;
908 return ret;
911 /* this is used 2 times below, so it saves memory to put it in global scope */
912 static const struct opt_items voice_names[] = {
913 { STR(LANG_OFF) },
914 { STR(LANG_VOICE_NUMBER) },
915 { STR(LANG_VOICE_SPELL) },
916 { STR(LANG_VOICE_DIR_HOVER) }
919 static bool voice_dirs(void)
921 return set_option( str(LANG_VOICE_DIR),
922 &global_settings.talk_dir, INT, voice_names, 4, NULL);
925 static bool voice_files(void)
927 int oldval = global_settings.talk_file;
928 bool ret;
929 ret = set_option( str(LANG_VOICE_FILE),
930 &global_settings.talk_file, INT, voice_names, 4, NULL);
931 if (oldval != 3 && global_settings.talk_file == 3)
932 { /* force reload if newly talking thumbnails,
933 because the clip presence is cached only if enabled */
934 reload_directory();
936 return ret;
939 static bool voice_menu(void)
941 int m;
942 bool result;
944 static const struct menu_item items[] = {
945 { ID2P(LANG_VOICE_MENU), voice_menus },
946 { ID2P(LANG_VOICE_DIR), voice_dirs },
947 { ID2P(LANG_VOICE_FILE), voice_files }
950 m=menu_init( items, sizeof(items) / sizeof(*items), NULL,
951 NULL, NULL, NULL);
952 result = menu_run(m);
953 menu_exit(m);
954 return result;
957 #ifdef HAVE_LCD_BITMAP
958 static bool font_browse(void)
960 return rockbox_browse(ROCKBOX_DIR FONT_DIR, SHOW_FONT);
963 static bool scroll_bar(void)
965 return set_bool( str(LANG_SCROLL_BAR), &global_settings.scrollbar );
968 static bool status_bar(void)
970 return set_bool( str(LANG_STATUS_BAR), &global_settings.statusbar );
973 #if CONFIG_KEYPAD == RECORDER_PAD
974 static bool button_bar(void)
976 return set_bool( str(LANG_BUTTON_BAR), &global_settings.buttonbar );
978 #endif /* CONFIG_KEYPAD == RECORDER_PAD */
979 #endif /* HAVE_LCD_BITMAP */
981 static bool ff_rewind_settings_menu(void)
983 int m;
984 bool result;
986 static const struct menu_item items[] = {
987 { ID2P(LANG_FFRW_STEP), ff_rewind_min_step },
988 { ID2P(LANG_FFRW_ACCEL), ff_rewind_accel },
991 m=menu_init( items, sizeof(items) / sizeof(*items), NULL,
992 NULL, NULL, NULL);
993 result = menu_run(m);
994 menu_exit(m);
996 return result;
999 static bool id3_order(void)
1001 return set_bool_options( str(LANG_ID3_ORDER),
1002 &global_settings.id3_v1_first,
1003 STR(LANG_ID3_V1_FIRST),
1004 STR(LANG_ID3_V2_FIRST),
1005 mpeg_id3_options);
1008 static bool playback_settings_menu(void)
1010 int m;
1011 bool result;
1013 static const struct menu_item items[] = {
1014 { ID2P(LANG_SHUFFLE), shuffle },
1015 { ID2P(LANG_REPEAT), repeat_mode },
1016 { ID2P(LANG_PLAY_SELECTED), play_selected },
1017 { ID2P(LANG_RESUME), resume },
1018 { ID2P(LANG_WIND_MENU), ff_rewind_settings_menu },
1019 { ID2P(LANG_MP3BUFFER_MARGIN), buffer_margin },
1020 { ID2P(LANG_FADE_ON_STOP), set_fade_on_stop },
1021 { ID2P(LANG_ID3_ORDER), id3_order },
1024 bool old_shuffle = global_settings.playlist_shuffle;
1026 m=menu_init( items, sizeof(items) / sizeof(*items), NULL,
1027 NULL, NULL, NULL);
1028 result = menu_run(m);
1029 menu_exit(m);
1031 if (old_shuffle != global_settings.playlist_shuffle)
1033 if (global_settings.playlist_shuffle)
1035 playlist_randomise(NULL, current_tick, true);
1037 else
1039 playlist_sort(NULL, true);
1042 return result;
1045 static bool bookmark_settings_menu(void)
1047 int m;
1048 bool result;
1050 static const struct menu_item items[] = {
1051 { ID2P(LANG_BOOKMARK_SETTINGS_AUTOCREATE), autocreatebookmark},
1052 { ID2P(LANG_BOOKMARK_SETTINGS_AUTOLOAD), autoloadbookmark},
1053 { ID2P(LANG_BOOKMARK_SETTINGS_MAINTAIN_RECENT_BOOKMARKS), useMRB},
1056 m=menu_init( items, sizeof(items) / sizeof(*items), NULL,
1057 NULL, NULL, NULL);
1058 result = menu_run(m);
1059 menu_exit(m);
1061 return result;
1063 static bool reset_settings(void)
1065 bool done=false;
1066 int line;
1067 int button;
1069 lcd_clear_display();
1071 #ifdef HAVE_LCD_CHARCELLS
1072 line = 0;
1073 #else
1074 line = 1;
1075 lcd_puts(0,0,str(LANG_RESET_ASK_RECORDER));
1076 #endif
1077 lcd_puts(0,line,str(LANG_RESET_CONFIRM));
1078 lcd_puts(0,line+1,str(LANG_RESET_CANCEL));
1080 lcd_update();
1082 while(!done) {
1083 button = button_get(true);
1084 switch(button) {
1085 case SETTINGS_OK:
1086 settings_reset();
1087 settings_apply();
1088 lcd_clear_display();
1089 lcd_puts(0,1,str(LANG_RESET_DONE_CLEAR));
1090 done = true;
1091 break;
1093 case SETTINGS_CANCEL:
1094 lcd_clear_display();
1095 lcd_puts(0,1,str(LANG_RESET_DONE_CANCEL));
1096 done = true;
1097 break;
1099 default:
1100 if(default_event_handler(button) == SYS_USB_CONNECTED)
1101 return true;
1105 lcd_puts(0,0,str(LANG_RESET_DONE_SETTING));
1106 lcd_update();
1107 sleep(HZ);
1108 return false;
1111 static bool fileview_settings_menu(void)
1113 int m;
1114 bool result;
1116 static const struct menu_item items[] = {
1117 { ID2P(LANG_SORT_CASE), sort_case },
1118 { ID2P(LANG_SORT_DIR), sort_dir },
1119 { ID2P(LANG_SORT_FILE), sort_file },
1120 { ID2P(LANG_FILTER), dir_filter },
1121 { ID2P(LANG_FOLLOW), browse_current },
1122 { ID2P(LANG_SHOW_ICONS), show_icons },
1125 m=menu_init( items, sizeof(items) / sizeof(*items), NULL,
1126 NULL, NULL, NULL);
1127 result = menu_run(m);
1128 menu_exit(m);
1129 return result;
1133 static bool scroll_settings_menu(void)
1135 int m;
1136 bool result;
1138 static const struct menu_item items[] = {
1139 { ID2P(LANG_SCROLL_SPEED), scroll_speed },
1140 { ID2P(LANG_SCROLL_DELAY), scroll_delay },
1141 #ifdef HAVE_LCD_BITMAP
1142 { ID2P(LANG_SCROLL_STEP), scroll_step },
1143 #endif
1144 { ID2P(LANG_BIDIR_SCROLL), bidir_limit },
1145 #ifdef HAVE_LCD_CHARCELLS
1146 { ID2P(LANG_JUMP_SCROLL), jump_scroll },
1147 { ID2P(LANG_JUMP_SCROLL_DELAY), jump_scroll_delay },
1148 #endif
1151 m=menu_init( items, sizeof(items) / sizeof(*items), NULL,
1152 NULL, NULL, NULL);
1153 result = menu_run(m);
1154 menu_exit(m);
1155 return result;
1158 static bool lcd_settings_menu(void)
1160 int m;
1161 bool result;
1163 static const struct menu_item items[] = {
1164 #ifdef HAVE_BACKLIGHT
1165 { ID2P(LANG_BACKLIGHT), backlight_timer },
1166 { ID2P(LANG_BACKLIGHT_ON_WHEN_CHARGING), backlight_on_when_charging },
1167 { ID2P(LANG_CAPTION_BACKLIGHT), caption_backlight },
1168 #endif
1169 { ID2P(LANG_CONTRAST), contrast },
1170 #ifdef HAVE_LCD_BITMAP
1171 { ID2P(LANG_INVERT), invert },
1172 { ID2P(LANG_FLIP_DISPLAY), flip_display },
1173 { ID2P(LANG_INVERT_CURSOR), invert_cursor },
1174 #endif
1177 m=menu_init( items, sizeof(items) / sizeof(*items), NULL,
1178 NULL, NULL, NULL);
1179 result = menu_run(m);
1180 menu_exit(m);
1181 return result;
1184 #ifdef HAVE_LCD_BITMAP
1185 static bool bars_settings_menu(void)
1187 int m;
1188 bool result;
1190 static const struct menu_item items[] = {
1191 { ID2P(LANG_SCROLL_BAR), scroll_bar },
1192 { ID2P(LANG_STATUS_BAR), status_bar },
1193 #if CONFIG_KEYPAD == RECORDER_PAD
1194 { ID2P(LANG_BUTTON_BAR), button_bar },
1195 #endif
1196 { ID2P(LANG_VOLUME_DISPLAY), volume_type },
1197 { ID2P(LANG_BATTERY_DISPLAY), battery_type },
1200 m=menu_init( items, sizeof(items) / sizeof(*items), NULL,
1201 NULL, NULL, NULL);
1202 result = menu_run(m);
1203 menu_exit(m);
1204 return result;
1206 #endif
1209 static bool display_settings_menu(void)
1211 int m;
1212 bool result;
1214 static const struct menu_item items[] = {
1215 #ifdef HAVE_LCD_BITMAP
1216 { ID2P(LANG_CUSTOM_FONT), font_browse },
1217 #endif
1218 { ID2P(LANG_WHILE_PLAYING), custom_wps_browse },
1219 { ID2P(LANG_LCD_MENU), lcd_settings_menu },
1220 { ID2P(LANG_SCROLL_MENU), scroll_settings_menu },
1221 #ifdef HAVE_LCD_BITMAP
1222 { ID2P(LANG_BARS_MENU), bars_settings_menu },
1223 { ID2P(LANG_PM_MENU), peak_meter_menu },
1224 #endif
1227 m=menu_init( items, sizeof(items) / sizeof(*items), NULL,
1228 NULL, NULL, NULL);
1229 result = menu_run(m);
1230 menu_exit(m);
1231 return result;
1235 static bool firmware_browse(void)
1237 return rockbox_browse(ROCKBOX_DIR, SHOW_MOD);
1240 static bool battery_settings_menu(void)
1242 int m;
1243 bool result;
1245 static const struct menu_item items[] = {
1246 #ifdef HAVE_CHARGE_CTRL
1247 { ID2P(LANG_DISCHARGE), deep_discharge },
1248 { ID2P(LANG_TRICKLE_CHARGE), trickle_charge },
1249 #endif
1250 #ifndef SIMULATOR
1251 { ID2P(LANG_BATTERY_CAPACITY), battery_capacity },
1252 #else
1253 #ifndef HAVE_CHARGE_CTRL
1254 { "Dummy", NULL }, /* to have an entry at all, in the simulator */
1255 #endif
1256 #endif
1259 m=menu_init( items, sizeof(items) / sizeof(*items), NULL,
1260 NULL, NULL, NULL);
1261 result = menu_run(m);
1262 menu_exit(m);
1263 return result;
1266 #ifndef HAVE_MMC
1267 static bool disk_settings_menu(void)
1269 int m;
1270 bool result;
1272 static const struct menu_item items[] = {
1273 { ID2P(LANG_SPINDOWN), spindown },
1274 #ifdef HAVE_ATA_POWER_OFF
1275 { ID2P(LANG_POWEROFF), poweroff },
1276 #endif
1279 m=menu_init( items, sizeof(items) / sizeof(*items), NULL,
1280 NULL, NULL, NULL);
1281 result = menu_run(m);
1282 menu_exit(m);
1283 return result;
1285 #endif /* !HAVE_MMC */
1287 #ifdef HAVE_RTC
1288 static bool time_settings_menu(void)
1290 int m;
1291 bool result;
1293 static const struct menu_item items[] = {
1294 { ID2P(LANG_TIME), timedate_set },
1295 { ID2P(LANG_TIMEFORMAT), timeformat_set },
1298 m=menu_init( items, sizeof(items) / sizeof(*items), NULL,
1299 NULL, NULL, NULL);
1300 result = menu_run(m);
1301 menu_exit(m);
1302 return result;
1304 #endif
1306 static bool manage_settings_menu(void)
1308 int m;
1309 bool result;
1311 static const struct menu_item items[] = {
1312 { ID2P(LANG_CUSTOM_CFG), custom_cfg_browse },
1313 { ID2P(LANG_FIRMWARE), firmware_browse },
1314 { ID2P(LANG_RESET), reset_settings },
1315 { ID2P(LANG_SAVE_SETTINGS), settings_save_config },
1318 m=menu_init( items, sizeof(items) / sizeof(*items), NULL,
1319 NULL, NULL, NULL);
1320 result = menu_run(m);
1321 menu_exit(m);
1322 return result;
1325 static bool limits_settings_menu(void)
1327 int m;
1328 bool result;
1330 static const struct menu_item items[] = {
1331 { ID2P(LANG_MAX_FILES_IN_DIR), max_files_in_dir },
1332 { ID2P(LANG_MAX_FILES_IN_PLAYLIST), max_files_in_playlist },
1335 m=menu_init( items, sizeof(items) / sizeof(*items), NULL,
1336 NULL, NULL, NULL);
1337 result = menu_run(m);
1338 menu_exit(m);
1339 return result;
1343 static bool system_settings_menu(void)
1345 int m;
1346 bool result;
1348 static const struct menu_item items[] = {
1349 { ID2P(LANG_BATTERY_MENU), battery_settings_menu },
1350 #ifndef HAVE_MMC
1351 { ID2P(LANG_DISK_MENU), disk_settings_menu },
1352 #endif
1353 #ifdef HAVE_RTC
1354 { ID2P(LANG_TIME_MENU), time_settings_menu },
1355 #endif
1356 { ID2P(LANG_POWEROFF_IDLE), poweroff_idle_timer },
1357 { ID2P(LANG_SLEEP_TIMER), sleeptimer_screen },
1358 #ifdef HAVE_ALARM_MOD
1359 { ID2P(LANG_ALARM_MOD_ALARM_MENU), alarm_screen },
1360 #endif
1361 { ID2P(LANG_LIMITS_MENU), limits_settings_menu },
1362 #if CONFIG_HWCODEC == MAS3507D
1363 { ID2P(LANG_LINE_IN), line_in },
1364 #endif
1365 #ifdef HAVE_CHARGING
1366 { ID2P(LANG_CAR_ADAPTER_MODE), car_adapter_mode },
1367 #endif
1368 { ID2P(LANG_MANAGE_MENU), manage_settings_menu },
1371 m=menu_init( items, sizeof(items) / sizeof(*items), NULL,
1372 NULL, NULL, NULL);
1373 result = menu_run(m);
1374 menu_exit(m);
1375 return result;
1378 bool settings_menu(void)
1380 int m;
1381 bool result;
1383 static const struct menu_item items[] = {
1384 { ID2P(LANG_PLAYBACK), playback_settings_menu },
1385 { ID2P(LANG_FILE), fileview_settings_menu },
1386 { ID2P(LANG_DISPLAY), display_settings_menu },
1387 { ID2P(LANG_SYSTEM), system_settings_menu },
1388 { ID2P(LANG_BOOKMARK_SETTINGS),bookmark_settings_menu },
1389 { ID2P(LANG_LANGUAGE), language_browse },
1390 { ID2P(LANG_VOICE), voice_menu },
1393 m=menu_init( items, sizeof(items) / sizeof(*items), NULL,
1394 NULL, NULL, NULL);
1395 result = menu_run(m);
1396 menu_exit(m);
1397 return result;