Change i2c config on e200. Seems to speed things up somewhat.
[kugel-rb.git] / apps / settings.c
blobaa8afe472ca961b8000d582025cdd231e4d6a337
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 by wavey@wavey.org
11 * RTC config saving code (C) 2002 by hessu@hes.iki.fi
13 * All files in this archive are subject to the GNU General Public License.
14 * See the file COPYING in the source tree root for full license agreement.
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
19 ****************************************************************************/
20 #include <stdio.h>
21 #include <stddef.h>
22 #include <stdlib.h>
23 #include <limits.h>
24 #include "inttypes.h"
25 #include "config.h"
26 #include "action.h"
27 #include "crc32.h"
28 #include "settings.h"
29 #include "debug.h"
30 #include "usb.h"
31 #include "backlight.h"
32 #include "audio.h"
33 #include "mpeg.h"
34 #include "talk.h"
35 #include "string.h"
36 #include "rtc.h"
37 #include "power.h"
38 #include "ata_idle_notify.h"
39 #include "atoi.h"
40 #include "screens.h"
41 #include "ctype.h"
42 #include "file.h"
43 #include "system.h"
44 #include "misc.h"
45 #ifdef HAVE_LCD_BITMAP
46 #include "icons.h"
47 #include "font.h"
48 #include "peakmeter.h"
49 #endif
50 #include "lang.h"
51 #include "language.h"
52 #include "gwps.h"
53 #include "powermgmt.h"
54 #include "sprintf.h"
55 #include "keyboard.h"
56 #include "version.h"
57 #include "sound.h"
58 #include "rbunicode.h"
59 #include "dircache.h"
60 #include "statusbar.h"
61 #include "splash.h"
62 #include "list.h"
63 #include "settings_list.h"
65 #if (LCD_DEPTH > 1) || (defined(HAVE_LCD_REMOTE) && (LCD_REMOTE_DEPTH > 1))
66 #include "backdrop.h"
67 #endif
69 #if CONFIG_TUNER
70 #include "radio.h"
71 #endif
73 #if CONFIG_CODEC == MAS3507D
74 void dac_line_in(bool enable);
75 #endif
76 struct user_settings global_settings;
77 struct system_status global_status;
79 #ifdef HAVE_RECORDING
80 const char rec_base_directory[] = REC_BASE_DIR;
81 #endif
82 #if CONFIG_CODEC == SWCODEC
83 #include "pcmbuf.h"
84 #include "pcm_playback.h"
85 #include "dsp.h"
86 #ifdef HAVE_RECORDING
87 #include "enc_config.h"
88 #endif
89 #endif /* CONFIG_CODEC == SWCODEC */
91 #define NVRAM_BLOCK_SIZE 44
93 #ifdef HAVE_LCD_BITMAP
94 #define MAX_LINES 10
95 #else
96 #define MAX_LINES 2
97 #endif
99 #ifdef HAVE_REMOTE_LCD
100 #include "lcd-remote.h"
101 #endif
103 long lasttime = 0;
105 /** NVRAM stuff, if the target doesnt have NVRAM it is saved in ROCKBOX_DIR /nvram.bin **/
106 /* NVRAM is set out as
107 [0] 'R'
108 [1] 'b'
109 [2] version
110 [3] stored variable count
111 [4-7] crc32 checksum
112 [8-NVRAM_BLOCK_SIZE] data
114 #define NVRAM_DATA_START 8
115 #define NVRAM_FILE ROCKBOX_DIR "/nvram.bin"
116 static char nvram_buffer[NVRAM_BLOCK_SIZE];
118 static bool read_nvram_data(char* buf, int max_len)
120 unsigned crc32 = 0xffffffff;
121 int var_count = 0, i = 0, buf_pos = 0;
122 #ifndef HAVE_RTC_RAM
123 int fd = open(NVRAM_FILE,O_RDONLY);
124 if (fd < 0)
125 return false;
126 memset(buf,0,max_len);
127 if (read(fd,buf,max_len) < 8) /* min is 8 bytes,magic, ver, vars, crc32 */
128 return false;
129 close(fd);
130 #else
131 memset(buf,0,max_len);
132 /* read rtc block */
133 for (i=0; i < max_len; i++ )
134 buf[i] = rtc_read(0x14+i);
135 #endif
136 /* check magic, version */
137 if ((buf[0] != 'R') || (buf[1] != 'b')
138 || (buf[2] != NVRAM_CONFIG_VERSION))
139 return false;
140 /* check crc32 */
141 crc32 = crc_32(&buf[NVRAM_DATA_START],
142 max_len-NVRAM_DATA_START-1,0xffffffff);
143 if (memcmp(&crc32,&buf[4],4))
144 return false;
145 /* all good, so read in the settings */
146 var_count = buf[3];
147 buf_pos = NVRAM_DATA_START;
148 for(i=0; (i<nb_settings) && (var_count>0) && (buf_pos<max_len); i++)
150 int nvram_bytes = (settings[i].flags&F_NVRAM_BYTES_MASK)
151 >>F_NVRAM_MASK_SHIFT;
152 if (nvram_bytes)
154 memcpy(settings[i].setting,&buf[buf_pos],nvram_bytes);
155 buf_pos += nvram_bytes;
156 var_count--;
159 return true;
161 static bool write_nvram_data(char* buf, int max_len)
163 unsigned crc32 = 0xffffffff;
164 int i = 0, buf_pos = 0;
165 char var_count = 0;
166 #ifndef HAVE_RTC_RAM
167 int fd;
168 #endif
169 memset(buf,0,max_len);
170 /* magic, version */
171 buf[0] = 'R'; buf[1] = 'b';
172 buf[2] = NVRAM_CONFIG_VERSION;
173 buf_pos = NVRAM_DATA_START;
174 for(i=0; (i<nb_settings) && (buf_pos<max_len); i++)
176 int nvram_bytes = (settings[i].flags&F_NVRAM_BYTES_MASK)
177 >>F_NVRAM_MASK_SHIFT;
178 if (nvram_bytes)
180 memcpy(&buf[buf_pos],settings[i].setting,nvram_bytes);
181 buf_pos += nvram_bytes;
182 var_count++;
185 /* count and crc32 */
186 buf[3] = var_count;
187 crc32 = crc_32(&buf[NVRAM_DATA_START],
188 max_len-NVRAM_DATA_START-1,0xffffffff);
189 memcpy(&buf[4],&crc32,4);
190 #ifndef HAVE_RTC_RAM
191 fd = open(NVRAM_FILE,O_CREAT|O_TRUNC|O_WRONLY);
192 if (fd >= 0)
194 int len = write(fd,buf,max_len);
195 close(fd);
196 if (len < 8)
197 return false;
199 #else
200 /* FIXME: okay, it _would_ be cleaner and faster to implement rtc_write so
201 that it would write a number of bytes at a time since the RTC chip
202 supports that, but this will have to do for now 8-) */
203 for (i=0; i < NVRAM_BLOCK_SIZE; i++ ) {
204 int r = rtc_write(0x14+i, buf[i]);
205 if (r) {
206 DEBUGF( "save_config_buffer: rtc_write failed at addr 0x%02x: %d\n",
207 14+i, r );
208 return false;
211 #endif
212 return true;
215 /** Reading from a config file **/
217 * load settings from disk or RTC RAM
219 void settings_load(int which)
221 DEBUGF( "reload_all_settings()\n" );
222 if (which&SETTINGS_RTC)
223 read_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE);
224 if (which&SETTINGS_HD)
226 settings_load_config(CONFIGFILE,false);
227 settings_load_config(FIXEDSETTINGSFILE,false);
230 #ifdef HAVE_LCD_COLOR
232 * Helper function to convert a string of 6 hex digits to a native colour
235 #define hex2dec(c) (((c) >= '0' && ((c) <= '9')) ? (toupper(c)) - '0' : \
236 (toupper(c)) - 'A' + 10)
238 static int hex_to_rgb(const char* hex)
239 { int ok = 1;
240 int i;
241 int red, green, blue;
243 if (strlen(hex) == 6) {
244 for (i=0; i < 6; i++ ) {
245 if (!isxdigit(hex[i])) {
246 ok=0;
247 break;
251 if (ok) {
252 red = (hex2dec(hex[0]) << 4) | hex2dec(hex[1]);
253 green = (hex2dec(hex[2]) << 4) | hex2dec(hex[3]);
254 blue = (hex2dec(hex[4]) << 4) | hex2dec(hex[5]);
255 return LCD_RGBPACK(red,green,blue);
259 return 0;
261 #endif /* HAVE_LCD_COLOR */
263 static bool cfg_string_to_int(int setting_id, int* out, char* str)
265 const char* start = settings[setting_id].cfg_vals;
266 char* end = NULL;
267 char temp[MAX_PATH];
268 int count = 0;
269 while (1)
271 end = strchr(start, ',');
272 if (!end)
274 if (!strcmp(str, start))
276 *out = count;
277 return true;
279 else return false;
281 strncpy(temp, start, end-start);
282 temp[end-start] = '\0';
283 if (!strcmp(str, temp))
285 *out = count;
286 return true;
288 start = end +1;
289 count++;
291 return false;
294 bool settings_load_config(const char* file, bool apply)
296 int fd;
297 char line[128];
298 char* name;
299 char* value;
300 int i;
301 fd = open(file, O_RDONLY);
302 if (fd < 0)
303 return false;
305 while (read_line(fd, line, sizeof line) > 0)
307 if (!settings_parseline(line, &name, &value))
308 continue;
309 for(i=0; i<nb_settings; i++)
311 if (settings[i].cfg_name == NULL)
312 continue;
313 if (!strcasecmp(name,settings[i].cfg_name))
315 switch (settings[i].flags&F_T_MASK)
317 case F_T_INT:
318 case F_T_UINT:
319 #ifdef HAVE_LCD_COLOR
320 if (settings[i].flags&F_RGB)
321 *(int*)settings[i].setting = hex_to_rgb(value);
322 else
323 #endif
324 if (settings[i].cfg_vals == NULL)
326 *(int*)settings[i].setting = atoi(value);
328 else
330 cfg_string_to_int(i,(int*)settings[i].setting,value);
332 break;
333 case F_T_BOOL:
335 int temp;
336 if (cfg_string_to_int(i,&temp,value))
337 *(bool*)settings[i].setting = (temp==0?false:true);
338 break;
340 case F_T_CHARPTR:
341 case F_T_UCHARPTR:
343 char storage[MAX_PATH];
344 if (settings[i].filename_setting->prefix)
346 int len = strlen(settings[i].filename_setting->prefix);
347 if (!strncasecmp(value,
348 settings[i].filename_setting->prefix,
349 len))
351 strncpy(storage,&value[len],MAX_PATH);
353 else strncpy(storage,value,MAX_PATH);
355 else strncpy(storage,value,MAX_PATH);
356 if (settings[i].filename_setting->suffix)
358 char *s = strcasestr(storage,settings[i].filename_setting->suffix);
359 if (s) *s = '\0';
361 strncpy((char*)settings[i].setting,storage,
362 settings[i].filename_setting->max_len);
363 ((char*)settings[i].setting)
364 [settings[i].filename_setting->max_len-1] = '\0';
365 break;
368 break;
369 } /* if (!strcmp(name,settings[i].cfg_name)) */
370 } /* for(...) */
371 } /* while(...) */
373 close(fd);
374 settings_save();
375 if (apply)
376 settings_apply();
377 return true;
380 /** Writing to a config file and saving settings **/
382 bool cfg_int_to_string(int setting_id, int val, char* buf, int buf_len)
384 const char* start = settings[setting_id].cfg_vals;
385 char* end = NULL;
386 int count = 0;
387 while (count < val)
389 start = strchr(start,',');
390 if (!start)
391 return false;
392 count++;
393 start++;
395 end = strchr(start,',');
396 if (end == NULL)
397 strncpy(buf, start, buf_len);
398 else
400 int len = (buf_len > (end-start))? end-start: buf_len;
401 strncpy(buf, start, len);
402 buf[len] = '\0';
404 return true;
406 static bool is_changed(int setting_id)
408 const struct settings_list *setting = &settings[setting_id];
409 switch (setting->flags&F_T_MASK)
411 case F_T_INT:
412 case F_T_UINT:
413 if (setting->flags&F_DEF_ISFUNC)
415 if (*(int*)setting->setting == setting->default_val.func())
416 return false;
418 else if (setting->flags&F_T_SOUND)
420 if (*(int*)setting->setting ==
421 sound_default(setting->sound_setting->setting))
422 return false;
424 else if (*(int*)setting->setting == setting->default_val.int_)
425 return false;
426 break;
427 case F_T_BOOL:
428 if (*(bool*)setting->setting == setting->default_val.bool_)
429 return false;
430 break;
431 case F_T_CHARPTR:
432 case F_T_UCHARPTR:
433 if (!strcmp((char*)setting->setting, setting->default_val.charptr))
434 return false;
435 break;
437 return true;
440 static bool settings_write_config(char* filename, int options)
442 int i;
443 int fd;
444 char value[MAX_PATH];
445 fd = open(filename,O_CREAT|O_TRUNC|O_WRONLY);
446 if (fd < 0)
447 return false;
448 fdprintf(fd, "# .cfg file created by rockbox %s - "
449 "http://www.rockbox.org\r\n\r\n", appsversion);
450 for(i=0; i<nb_settings; i++)
452 if (settings[i].cfg_name == NULL)
453 continue;
454 value[0] = '\0';
456 if ((options == SETTINGS_SAVE_CHANGED) &&
457 !is_changed(i))
458 continue;
459 else if ((options == SETTINGS_SAVE_THEME) &&
460 ((settings[i].flags&F_THEMESETTING) == 0))
461 continue;
463 switch (settings[i].flags&F_T_MASK)
465 case F_T_INT:
466 case F_T_UINT:
467 #ifdef HAVE_LCD_COLOR
468 if (settings[i].flags&F_RGB)
470 int colour = *(int*)settings[i].setting;
471 snprintf(value,MAX_PATH,"%02x%02x%02x",
472 (int)RGB_UNPACK_RED(colour),
473 (int)RGB_UNPACK_GREEN(colour),
474 (int)RGB_UNPACK_BLUE(colour));
476 else
477 #endif
478 if (settings[i].cfg_vals == NULL)
480 snprintf(value,MAX_PATH,"%d",*(int*)settings[i].setting);
482 else
484 cfg_int_to_string(i, *(int*)settings[i].setting,
485 value, MAX_PATH);
487 break;
488 case F_T_BOOL:
489 cfg_int_to_string(i,
490 *(bool*)settings[i].setting==false?0:1, value, MAX_PATH);
491 break;
492 case F_T_CHARPTR:
493 case F_T_UCHARPTR:
494 if (((char*)settings[i].setting)[0] == '\0')
495 break;
496 if (settings[i].filename_setting->prefix)
498 snprintf(value,MAX_PATH,"%s%s%s",
499 settings[i].filename_setting->prefix,
500 (char*)settings[i].setting,
501 settings[i].filename_setting->suffix);
503 else strncpy(value,(char*)settings[i].setting,
504 settings[i].filename_setting->max_len);
505 break;
506 } /* switch () */
507 if (value[0])
508 fdprintf(fd,"%s: %s\r\n",settings[i].cfg_name,value);
509 } /* for(...) */
510 close(fd);
511 return true;
513 #ifndef HAVE_RTC_RAM
514 static bool flush_global_status_callback(void)
516 return write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE);
518 #endif
519 static bool flush_config_block_callback(void)
521 bool r1, r2;
522 r1 = write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE);
523 r2 = settings_write_config(CONFIGFILE, SETTINGS_SAVE_CHANGED);
524 return r1 || r2;
528 * persist all runtime user settings to disk or RTC RAM
530 static void update_runtime(void)
532 int elapsed_secs;
534 elapsed_secs = (current_tick - lasttime) / HZ;
535 global_status.runtime += elapsed_secs;
536 lasttime += (elapsed_secs * HZ);
538 if ( global_status.runtime > global_status.topruntime )
539 global_status.topruntime = global_status.runtime;
542 void status_save( void )
544 update_runtime();
545 #ifdef HAVE_RTC_RAM
546 /* this will be done in the ata_callback if
547 target doesnt have rtc ram */
548 write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE);
549 #else
550 register_ata_idle_func(flush_global_status_callback);
551 #endif
554 int settings_save( void )
556 update_runtime();
557 #ifdef HAVE_RTC_RAM
558 /* this will be done in the ata_callback if
559 target doesnt have rtc ram */
560 write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE);
561 #endif
562 if(!register_ata_idle_func(flush_config_block_callback))
564 int i;
565 FOR_NB_SCREENS(i)
567 screens[i].clear_display();
568 #ifdef HAVE_LCD_CHARCELLS
569 screens[i].puts(0, 0, str(LANG_SETTINGS_SAVE_PLAYER));
570 screens[i].puts(0, 1, str(LANG_SETTINGS_BATTERY_PLAYER));
571 #else
572 screens[i].puts(4, 2, str(LANG_SETTINGS_SAVE_RECORDER));
573 screens[i].puts(2, 4, str(LANG_SETTINGS_BATTERY_RECORDER));
574 screens[i].update();
575 #endif
577 sleep(HZ*2);
578 return -1;
580 return 0;
582 bool settings_save_config(int options)
584 char filename[MAX_PATH];
586 create_numbered_filename(filename, ROCKBOX_DIR, "config", ".cfg", 2
587 IF_CNFN_NUM_(, NULL));
589 /* allow user to modify filename */
590 while (true) {
591 if (!kbd_input(filename, sizeof filename)) {
592 break;
594 else {
595 gui_syncsplash(HZ, str(LANG_MENU_SETTING_CANCEL));
596 return false;
600 if (settings_write_config(filename, options))
601 gui_syncsplash(HZ, str(LANG_SETTINGS_SAVED));
602 else
603 gui_syncsplash(HZ, str(LANG_FAILED));
604 return true;
607 /** Apply and Reset settings **/
610 #ifdef HAVE_LCD_BITMAP
612 * Applies the range infos stored in global_settings to
613 * the peak meter.
615 void settings_apply_pm_range(void)
617 int pm_min, pm_max;
619 /* depending on the scale mode (dBfs or percent) the values
620 of global_settings.peak_meter_dbfs have different meanings */
621 if (global_settings.peak_meter_dbfs)
623 /* convert to dBfs * 100 */
624 pm_min = -(((int)global_settings.peak_meter_min) * 100);
625 pm_max = -(((int)global_settings.peak_meter_max) * 100);
627 else
629 /* percent is stored directly -> no conversion */
630 pm_min = global_settings.peak_meter_min;
631 pm_max = global_settings.peak_meter_max;
634 /* apply the range */
635 peak_meter_init_range(global_settings.peak_meter_dbfs, pm_min, pm_max);
637 #endif /* HAVE_LCD_BITMAP */
639 void sound_settings_apply(void)
641 #if CONFIG_CODEC == SWCODEC
642 sound_set_dsp_callback(dsp_callback);
643 #endif
644 sound_set(SOUND_BASS, global_settings.bass);
645 sound_set(SOUND_TREBLE, global_settings.treble);
646 sound_set(SOUND_BALANCE, global_settings.balance);
647 sound_set(SOUND_VOLUME, global_settings.volume);
648 sound_set(SOUND_CHANNELS, global_settings.channel_config);
649 sound_set(SOUND_STEREO_WIDTH, global_settings.stereo_width);
650 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
651 sound_set(SOUND_LOUDNESS, global_settings.loudness);
652 sound_set(SOUND_AVC, global_settings.avc);
653 sound_set(SOUND_MDB_STRENGTH, global_settings.mdb_strength);
654 sound_set(SOUND_MDB_HARMONICS, global_settings.mdb_harmonics);
655 sound_set(SOUND_MDB_CENTER, global_settings.mdb_center);
656 sound_set(SOUND_MDB_SHAPE, global_settings.mdb_shape);
657 sound_set(SOUND_MDB_ENABLE, global_settings.mdb_enable);
658 sound_set(SOUND_SUPERBASS, global_settings.superbass);
659 #endif
661 #ifdef HAVE_USB_POWER
662 #if CONFIG_CHARGING
663 usb_charging_enable(global_settings.usb_charging);
664 #endif
665 #endif
668 void settings_apply(void)
670 char buf[64];
671 #if CONFIG_CODEC == SWCODEC
672 int i;
673 #endif
675 DEBUGF( "settings_apply()\n" );
676 sound_settings_apply();
678 audio_set_buffer_margin(global_settings.buffer_margin);
680 #ifdef HAVE_LCD_CONTRAST
681 lcd_set_contrast(global_settings.contrast);
682 #endif
683 lcd_scroll_speed(global_settings.scroll_speed);
684 #ifdef HAVE_REMOTE_LCD
685 lcd_remote_set_contrast(global_settings.remote_contrast);
686 lcd_remote_set_invert_display(global_settings.remote_invert);
687 lcd_remote_set_flip(global_settings.remote_flip_display);
688 lcd_remote_scroll_speed(global_settings.remote_scroll_speed);
689 lcd_remote_scroll_step(global_settings.remote_scroll_step);
690 lcd_remote_scroll_delay(global_settings.remote_scroll_delay);
691 lcd_remote_bidir_scroll(global_settings.remote_bidir_limit);
692 #ifdef HAVE_REMOTE_LCD_TICKING
693 lcd_remote_emireduce(global_settings.remote_reduce_ticking);
694 #endif
695 remote_backlight_set_timeout(global_settings.remote_backlight_timeout);
696 #if CONFIG_CHARGING
697 remote_backlight_set_timeout_plugged(global_settings.remote_backlight_timeout_plugged);
698 #endif
699 #ifdef HAS_REMOTE_BUTTON_HOLD
700 remote_backlight_set_on_button_hold(global_settings.remote_backlight_on_button_hold);
701 #endif
702 #endif /* HAVE_REMOTE_LCD */
703 #ifdef HAVE_BACKLIGHT_BRIGHTNESS
704 backlight_set_brightness(global_settings.brightness);
705 #endif
706 #ifdef HAVE_BACKLIGHT
707 backlight_set_timeout(global_settings.backlight_timeout);
708 #if CONFIG_CHARGING
709 backlight_set_timeout_plugged(global_settings.backlight_timeout_plugged);
710 #endif
711 #if defined(HAVE_BACKLIGHT_PWM_FADING) && !defined(SIMULATOR)
712 backlight_set_fade_in(global_settings.backlight_fade_in);
713 backlight_set_fade_out(global_settings.backlight_fade_out);
714 #endif
715 #endif
716 #ifdef HAVE_BUTTONLIGHT_BRIGHTNESS
717 buttonlight_set_brightness(global_settings.buttonlight_brightness);
718 #endif
719 #ifdef HAVE_BUTTON_LIGHT
720 button_backlight_set_timeout(global_settings.button_light_timeout);
721 #endif
722 ata_spindown(global_settings.disk_spindown);
723 #if (CONFIG_CODEC == MAS3507D) && !defined(SIMULATOR)
724 dac_line_in(global_settings.line_in);
725 #endif
726 mpeg_id3_options(global_settings.id3_v1_first);
728 set_poweroff_timeout(global_settings.poweroff);
730 set_battery_capacity(global_settings.battery_capacity);
731 #if BATTERY_TYPES_COUNT > 1
732 set_battery_type(global_settings.battery_type);
733 #endif
735 #ifdef HAVE_LCD_BITMAP
736 lcd_set_invert_display(global_settings.invert);
737 lcd_set_flip(global_settings.flip_display);
738 button_set_flip(global_settings.flip_display);
739 lcd_update(); /* refresh after flipping the screen */
740 settings_apply_pm_range();
741 peak_meter_init_times(
742 global_settings.peak_meter_release, global_settings.peak_meter_hold,
743 global_settings.peak_meter_clip_hold);
744 #endif
746 #if LCD_DEPTH > 1
747 unload_wps_backdrop();
748 #endif
749 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
750 unload_remote_wps_backdrop();
751 #endif
752 if ( global_settings.wps_file[0] &&
753 global_settings.wps_file[0] != 0xff ) {
754 snprintf(buf, sizeof buf, WPS_DIR "/%s.wps",
755 global_settings.wps_file);
756 wps_data_load(gui_wps[0].data, buf, true);
758 else
760 wps_data_init(gui_wps[0].data);
761 #ifdef HAVE_REMOTE_LCD
762 gui_wps[0].data->remote_wps = false;
763 #endif
766 #if LCD_DEPTH > 1
767 if ( global_settings.backdrop_file[0] &&
768 global_settings.backdrop_file[0] != 0xff ) {
769 snprintf(buf, sizeof buf, BACKDROP_DIR "/%s.bmp",
770 global_settings.backdrop_file);
771 load_main_backdrop(buf);
772 } else {
773 unload_main_backdrop();
775 show_main_backdrop();
776 #endif
777 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
778 show_remote_main_backdrop();
779 #endif
781 #ifdef HAVE_LCD_COLOR
782 screens[SCREEN_MAIN].set_foreground(global_settings.fg_color);
783 screens[SCREEN_MAIN].set_background(global_settings.bg_color);
784 #endif
786 #if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1)
787 if ( global_settings.rwps_file[0]) {
788 snprintf(buf, sizeof buf, WPS_DIR "/%s.rwps",
789 global_settings.rwps_file);
790 wps_data_load(gui_wps[1].data, buf, true);
792 else
794 wps_data_init(gui_wps[1].data);
795 gui_wps[1].data->remote_wps = true;
797 #endif
799 #ifdef HAVE_LCD_BITMAP
800 if ( global_settings.font_file[0]) {
801 snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt",
802 global_settings.font_file);
803 font_load(buf);
805 else
806 font_reset();
808 if ( global_settings.kbd_file[0]) {
809 snprintf(buf, sizeof buf, ROCKBOX_DIR "/%s.kbd",
810 global_settings.kbd_file);
811 load_kbd(buf);
813 else
814 load_kbd(NULL);
816 lcd_scroll_step(global_settings.scroll_step);
817 gui_list_screen_scroll_step(global_settings.screen_scroll_step);
818 gui_list_screen_scroll_out_of_view(global_settings.offset_out_of_view);
819 #else
820 lcd_jump_scroll(global_settings.jump_scroll);
821 lcd_jump_scroll_delay(global_settings.jump_scroll_delay);
822 #endif
823 lcd_bidir_scroll(global_settings.bidir_limit);
824 lcd_scroll_delay(global_settings.scroll_delay);
826 if ( global_settings.lang_file[0]) {
827 snprintf(buf, sizeof buf, LANG_DIR "/%s.lng",
828 global_settings.lang_file);
829 lang_load(buf);
830 talk_init(); /* use voice of same language */
833 set_codepage(global_settings.default_codepage);
835 #if CONFIG_CODEC == SWCODEC
836 audio_set_crossfade(global_settings.crossfade);
837 dsp_set_replaygain();
838 dsp_set_crossfeed(global_settings.crossfeed);
839 dsp_set_crossfeed_direct_gain(global_settings.crossfeed_direct_gain);
840 dsp_set_crossfeed_cross_params(global_settings.crossfeed_cross_gain,
841 global_settings.crossfeed_hf_attenuation,
842 global_settings.crossfeed_hf_cutoff);
844 /* Configure software equalizer, hardware eq is handled in audio_init() */
845 dsp_set_eq(global_settings.eq_enabled);
846 dsp_set_eq_precut(global_settings.eq_precut);
847 for(i = 0; i < 5; i++) {
848 dsp_set_eq_coefs(i);
851 dsp_dither_enable(global_settings.dithering_enabled);
852 #endif
854 #ifdef HAVE_SPDIF_POWER
855 spdif_power_enable(global_settings.spdif_enable);
856 #endif
858 #ifdef HAVE_BACKLIGHT
859 set_backlight_filter_keypress(global_settings.bl_filter_first_keypress);
860 #ifdef HAVE_REMOTE_LCD
861 set_remote_backlight_filter_keypress(global_settings.remote_bl_filter_first_keypress);
862 #endif
863 #ifdef HAS_BUTTON_HOLD
864 backlight_set_on_button_hold(global_settings.backlight_on_button_hold);
865 #endif
866 #ifdef HAVE_LCD_SLEEP
867 lcd_set_sleep_after_backlight_off(global_settings.lcd_sleep_after_backlight_off);
868 #endif
869 #endif /* HAVE_BACKLIGHT */
871 /* This should stay last */
872 #if defined(HAVE_RECORDING) && CONFIG_CODEC == SWCODEC
873 enc_global_settings_apply();
874 #endif
875 /* load the icon set */
876 icons_init();
884 * reset all settings to their default value
886 void settings_reset(void) {
888 int i;
889 DEBUGF( "settings_reset()\n" );
891 for(i=0; i<nb_settings; i++)
893 switch (settings[i].flags&F_T_MASK)
895 case F_T_INT:
896 case F_T_UINT:
897 if (settings[i].flags&F_DEF_ISFUNC)
898 *(int*)settings[i].setting = settings[i].default_val.func();
899 else if (settings[i].flags&F_T_SOUND)
900 *(int*)settings[i].setting =
901 sound_default(settings[i].sound_setting->setting);
902 else *(int*)settings[i].setting = settings[i].default_val.int_;
903 break;
904 case F_T_BOOL:
905 *(bool*)settings[i].setting = settings[i].default_val.bool_;
906 break;
907 case F_T_CHARPTR:
908 case F_T_UCHARPTR:
909 strncpy((char*)settings[i].setting,
910 settings[i].default_val.charptr,MAX_FILENAME);
911 break;
913 } /* for(...) */
914 #if defined (HAVE_RECORDING) && CONFIG_CODEC == SWCODEC
915 enc_global_settings_reset();
916 #endif
919 /** Changing setting values **/
920 const struct settings_list* find_setting(void* variable, int *id)
922 int i;
923 for(i=0;i<nb_settings;i++)
925 if (settings[i].setting == variable)
927 if (id)
928 *id = i;
929 return &settings[i];
932 return NULL;
935 void talk_setting(void *global_settings_variable)
937 const struct settings_list *setting;
938 if (global_settings.talk_menu == 0)
939 return;
940 setting = find_setting(global_settings_variable, NULL);
941 if (setting == NULL)
942 return;
943 if (setting->lang_id)
944 talk_id(setting->lang_id,false);
947 static int selected_setting; /* Used by the callback */
949 static void dec_sound_formatter(char *buffer, int buffer_size,
950 int val, const char *unit)
952 val = sound_val2phys(selected_setting, val);
953 char sign = ' ';
954 if(val < 0)
956 sign = '-';
957 val = abs(val);
959 int integer = val / 10;
960 int dec = val % 10;
961 snprintf(buffer, buffer_size, "%c%d.%d %s", sign, integer, dec, unit);
964 bool set_sound(const unsigned char * string,
965 int* variable,
966 int setting)
968 int talkunit = UNIT_INT;
969 const char* unit = sound_unit(setting);
970 int numdec = sound_numdecimals(setting);
971 int steps = sound_steps(setting);
972 int min = sound_min(setting);
973 int max = sound_max(setting);
974 sound_set_type* sound_callback = sound_get_fn(setting);
975 if (*unit == 'd') /* crude reconstruction */
976 talkunit = UNIT_DB;
977 else if (*unit == '%')
978 talkunit = UNIT_PERCENT;
979 else if (*unit == 'H')
980 talkunit = UNIT_HERTZ;
981 if (!numdec)
982 return set_int(string, unit, talkunit, variable, sound_callback,
983 steps, min, max, NULL );
984 else
985 {/* Decimal number */
986 selected_setting=setting;
987 return set_int(string, unit, talkunit, variable, sound_callback,
988 steps, min, max, &dec_sound_formatter );
992 bool set_bool(const char* string, bool* variable )
994 return set_bool_options(string, variable,
995 (char *)STR(LANG_SET_BOOL_YES),
996 (char *)STR(LANG_SET_BOOL_NO),
997 NULL);
1000 /* wrapper to convert from int param to bool param in set_option */
1001 static void (*boolfunction)(bool);
1002 static void bool_funcwrapper(int value)
1004 if (value)
1005 boolfunction(true);
1006 else
1007 boolfunction(false);
1010 bool set_bool_options(const char* string, bool* variable,
1011 const char* yes_str, int yes_voice,
1012 const char* no_str, int no_voice,
1013 void (*function)(bool))
1015 struct opt_items names[] = {
1016 {(unsigned char *)no_str, no_voice},
1017 {(unsigned char *)yes_str, yes_voice}
1019 bool result;
1021 boolfunction = function;
1022 result = set_option(string, variable, BOOL, names, 2,
1023 function ? bool_funcwrapper : NULL);
1024 return result;
1027 static void talk_unit(int unit, int value, long (*get_talk_id)(int value))
1029 if (global_settings.talk_menu)
1031 if (get_talk_id)
1033 talk_id(get_talk_id(value),false);
1035 else if (unit < UNIT_LAST)
1036 { /* use the available unit definition */
1037 talk_value(value, unit, false);
1039 else
1040 { /* say the number, followed by an arbitrary voice ID */
1041 talk_number(value, false);
1042 talk_id(unit, true);
1047 struct value_setting_data {
1048 enum optiontype type;
1049 /* used for "value" settings.. */
1050 int max;
1051 int step;
1052 int voice_unit;
1053 const char * unit;
1054 void (*formatter)(char* dest, int dest_length,
1055 int value, const char* unit);
1056 long (*get_talk_id)(int value);
1057 /* used for BOOL and "choice" settings */
1058 struct opt_items* options;
1061 static char * value_setting_get_name_cb(int selected_item,void * data, char *buffer)
1063 struct value_setting_data* cb_data =
1064 (struct value_setting_data*)data;
1065 if (cb_data->type == INT && !cb_data->options)
1067 int item = cb_data->max -(selected_item*cb_data->step);
1068 if (cb_data->formatter)
1069 cb_data->formatter(buffer, MAX_PATH,item,cb_data->unit);
1070 else
1071 snprintf(buffer, MAX_PATH,"%d %s",item,cb_data->unit);
1073 else strcpy(buffer,P2STR(cb_data->options[selected_item].string));
1074 return buffer;
1076 #define type_fromvoidptr(type, value) \
1077 (type == INT)? \
1078 (int)(*(int*)(value)) \
1080 (bool)(*(bool*)(value))
1081 static bool do_set_setting(const unsigned char* string, void *variable,
1082 int nb_items,int selected,
1083 struct value_setting_data *cb_data,
1084 void (*function)(int))
1086 int action;
1087 bool done = false;
1088 struct gui_synclist lists;
1089 int oldvalue;
1090 bool allow_wrap = true;
1092 if (cb_data->type == INT)
1094 oldvalue = *(int*)variable;
1095 if (variable == &global_settings.volume)
1096 allow_wrap = false;
1098 else oldvalue = *(bool*)variable;
1100 gui_synclist_init(&lists,value_setting_get_name_cb,(void*)cb_data,false,1);
1101 gui_synclist_set_title(&lists, (char*)string,Icon_Questionmark);
1102 gui_synclist_set_icon_callback(&lists,NULL);
1103 gui_synclist_set_nb_items(&lists,nb_items);
1104 gui_synclist_limit_scroll(&lists,true);
1105 gui_synclist_select_item(&lists, selected);
1107 if (global_settings.talk_menu)
1109 if (cb_data->type == INT && !cb_data->options)
1110 talk_unit(cb_data->voice_unit, *(int*)variable, cb_data->get_talk_id);
1111 else talk_id(cb_data->options[selected].voice_id, false);
1114 gui_synclist_draw(&lists);
1115 action_signalscreenchange();
1116 while (!done)
1119 action = get_action(CONTEXT_LIST,TIMEOUT_BLOCK);
1120 if (action == ACTION_NONE)
1121 continue;
1122 if (gui_synclist_do_button(&lists,action,
1123 allow_wrap?LIST_WRAP_UNLESS_HELD:LIST_WRAP_OFF))
1125 if (global_settings.talk_menu)
1127 int value;
1128 if (cb_data->type == INT && !cb_data->options)
1130 value = cb_data->max -
1131 gui_synclist_get_sel_pos(&lists)*cb_data->step;
1132 talk_unit(cb_data->voice_unit, value, cb_data->get_talk_id);
1134 else
1136 value = gui_synclist_get_sel_pos(&lists);
1137 talk_id(cb_data->options[value].voice_id, false);
1140 if (cb_data->type == INT && !cb_data->options)
1141 *(int*)variable = cb_data->max -
1142 gui_synclist_get_sel_pos(&lists)*cb_data->step;
1143 else if (cb_data->type == BOOL)
1144 *(bool*)variable = gui_synclist_get_sel_pos(&lists) ? true : false;
1145 else *(int*)variable = gui_synclist_get_sel_pos(&lists);
1147 else if (action == ACTION_STD_CANCEL)
1149 if (cb_data->type == INT)
1151 if (*(int*)variable != oldvalue)
1153 gui_syncsplash(HZ/2, str(LANG_MENU_SETTING_CANCEL));
1154 *(int*)variable = oldvalue;
1157 else
1159 if (*(bool*)variable != (bool)oldvalue)
1161 gui_syncsplash(HZ/2, str(LANG_MENU_SETTING_CANCEL));
1162 *(bool*)variable = (bool)oldvalue;
1165 done = true;
1167 else if (action == ACTION_STD_OK)
1169 done = true;
1171 else if(default_event_handler(action) == SYS_USB_CONNECTED)
1172 return true;
1173 gui_syncstatusbar_draw(&statusbars, false);
1174 if ( function )
1175 function(type_fromvoidptr(cb_data->type,variable));
1177 if (cb_data->type == INT)
1179 if (oldvalue != *(int*)variable)
1180 settings_save();
1182 else if (oldvalue != *(bool*)variable)
1183 settings_save();
1185 action_signalscreenchange();
1186 return false;
1188 static const char *unit_strings[] =
1190 [UNIT_INT]
1191 = "",
1192 [UNIT_MS]
1193 = "ms",
1194 [UNIT_SEC]
1195 = "s",
1196 [UNIT_MIN]
1197 = "min",
1198 [UNIT_HOUR]
1199 = "hr",
1200 [UNIT_KHZ]
1201 = "KHz",
1202 [UNIT_DB]
1203 = "dB",
1204 [UNIT_PERCENT]
1205 = "%",
1206 [UNIT_MAH]
1207 = "mAh",
1208 [UNIT_PIXEL]
1209 = "px",
1210 [UNIT_PER_SEC]
1211 = "per sec",
1212 [UNIT_HERTZ]
1213 = "Hz",
1214 [UNIT_MB]
1215 = "MB",
1216 [UNIT_KBIT]
1217 = "kb/s",
1219 bool set_int_ex(const unsigned char* string,
1220 const char* unit,
1221 int voice_unit,
1222 int* variable,
1223 void (*function)(int),
1224 int step,
1225 int min,
1226 int max,
1227 void (*formatter)(char*, int, int, const char*),
1228 long (*get_talk_id)(int))
1230 int count = (max-min)/step + 1;
1231 #if CONFIG_KEYPAD != PLAYER_PAD
1232 struct value_setting_data data = {
1233 INT,max, step, voice_unit,unit,formatter,get_talk_id,NULL };
1234 if (voice_unit < UNIT_LAST)
1235 data.unit = unit_strings[voice_unit];
1236 else
1237 data.unit = str(voice_unit);
1238 return do_set_setting(string,variable,count,
1239 (max-*variable)/step, &data,function);
1240 #else
1241 struct value_setting_data data = {
1242 INT,min, -step, voice_unit,unit,formatter,get_talk_id,NULL };
1243 if (voice_unit < UNIT_LAST)
1244 data.unit = unit_strings[voice_unit];
1245 else
1246 data.unit = str(voice_unit);
1247 return do_set_setting(string,variable,count,
1248 (*variable-min)/step, &data,function);
1249 #endif
1251 bool set_int(const unsigned char* string,
1252 const char* unit,
1253 int voice_unit,
1254 int* variable,
1255 void (*function)(int),
1256 int step,
1257 int min,
1258 int max,
1259 void (*formatter)(char*, int, int, const char*) )
1261 return set_int_ex(string, unit, voice_unit, variable, function,
1262 step, min, max, formatter, NULL);
1264 /* NOTE: the 'type' parameter specifies the actual type of the variable
1265 that 'variable' points to. not the value within. Only variables with
1266 type 'bool' should use parameter BOOL.
1268 The type separation is necessary since int and bool are fundamentally
1269 different and bit-incompatible types and can not share the same access
1270 code. */
1271 bool set_option(const char* string, void* variable, enum optiontype type,
1272 const struct opt_items* options, int numoptions, void (*function)(int))
1274 struct value_setting_data data = {
1275 type,0, 0, 0,NULL,NULL,NULL,(struct opt_items*)options };
1276 int selected;
1277 if (type == BOOL)
1278 selected = *(bool*)variable ? 1 : 0;
1279 else selected = *(int*)variable;
1280 return do_set_setting(string,variable,numoptions,
1281 selected, &data,function);
1284 /** extra stuff which is probably misplaced **/
1286 void set_file(char* filename, char* setting, int maxlen)
1288 char* fptr = strrchr(filename,'/');
1289 int len;
1290 int extlen = 0;
1291 char* ptr;
1293 if (!fptr)
1294 return;
1296 *fptr = 0;
1297 fptr++;
1299 len = strlen(fptr);
1300 ptr = fptr + len;
1301 while ((*ptr != '.') && (ptr != fptr)) {
1302 extlen++;
1303 ptr--;
1305 if(ptr == fptr) extlen = 0;
1307 if (strncasecmp(ROCKBOX_DIR, filename ,strlen(ROCKBOX_DIR)) ||
1308 (len-extlen > maxlen))
1309 return;
1311 strncpy(setting, fptr, len-extlen);
1312 setting[len-extlen]=0;
1314 settings_save();
1317 #ifdef HAVE_RECORDING
1318 /* This array holds the record timer interval lengths, in seconds */
1319 static const unsigned long rec_timer_seconds[] =
1321 0, /* 0 means OFF */
1322 5*60, /* 00:05 */
1323 10*60, /* 00:10 */
1324 15*60, /* 00:15 */
1325 30*60, /* 00:30 */
1326 60*60, /* 01:00 */
1327 74*60, /* 74:00 */
1328 80*60, /* 80:00 */
1329 2*60*60, /* 02:00 */
1330 4*60*60, /* 04:00 */
1331 6*60*60, /* 06:00 */
1332 8*60*60, /* 08:00 */
1333 10L*60*60, /* 10:00 */
1334 12L*60*60, /* 12:00 */
1335 18L*60*60, /* 18:00 */
1336 24L*60*60 /* 24:00 */
1339 unsigned int rec_timesplit_seconds(void)
1341 return rec_timer_seconds[global_settings.rec_timesplit];
1344 /* This array holds the record size interval lengths, in bytes */
1345 static const unsigned long rec_size_bytes[] =
1347 0, /* 0 means OFF */
1348 5*1024*1024, /* 5MB */
1349 10*1024*1024, /* 10MB */
1350 15*1024*1024, /* 15MB */
1351 32*1024*1024, /* 32MB */
1352 64*1024*1024, /* 64MB */
1353 75*1024*1024, /* 75MB */
1354 100*1024*1024, /* 100MB */
1355 128*1024*1024, /* 128MB */
1356 256*1024*1024, /* 256MB */
1357 512*1024*1024, /* 512MB */
1358 650*1024*1024, /* 650MB */
1359 700*1024*1024, /* 700MB */
1360 1024*1024*1024, /* 1GB */
1361 1536*1024*1024, /* 1.5GB */
1362 1792*1024*1024, /* 1.75GB */
1365 unsigned long rec_sizesplit_bytes(void)
1367 return rec_size_bytes[global_settings.rec_sizesplit];
1370 * Time strings used for the trigger durations.
1371 * Keep synchronous to trigger_times in settings_apply_trigger
1373 const char * const trig_durations[TRIG_DURATION_COUNT] =
1375 "0s", "1s", "2s", "5s",
1376 "10s", "15s", "20s", "25s", "30s",
1377 "1min", "2min", "5min", "10min"
1380 void settings_apply_trigger(void)
1382 /* Keep synchronous to trig_durations and trig_durations_conf*/
1383 static const long trigger_times[TRIG_DURATION_COUNT] = {
1384 0, HZ, 2*HZ, 5*HZ,
1385 10*HZ, 15*HZ, 20*HZ, 25*HZ, 30*HZ,
1386 60*HZ, 2*60*HZ, 5*60*HZ, 10*60*HZ
1389 peak_meter_define_trigger(
1390 global_settings.rec_start_thres,
1391 trigger_times[global_settings.rec_start_duration],
1392 MIN(trigger_times[global_settings.rec_start_duration] / 2, 2*HZ),
1393 global_settings.rec_stop_thres,
1394 trigger_times[global_settings.rec_stop_postrec],
1395 trigger_times[global_settings.rec_stop_gap]
1398 #endif