Better endianness handling, removed some leftovers
[kugel-rb.git] / apps / settings.c
blob96bdc8a0f574318dbc6640c474d9b17bed047530
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 #include "hwcompat.h"
50 #endif
51 #include "lang.h"
52 #include "language.h"
53 #include "gwps.h"
54 #include "powermgmt.h"
55 #include "sprintf.h"
56 #include "keyboard.h"
57 #include "version.h"
58 #include "sound.h"
59 #include "rbunicode.h"
60 #include "dircache.h"
61 #include "statusbar.h"
62 #include "splash.h"
63 #include "list.h"
64 #include "settings_list.h"
65 #if LCD_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 #ifdef HAVE_WM8758
92 #include "menus/eq_menu.h"
93 #endif
95 #define NVRAM_BLOCK_SIZE 44
97 #ifdef HAVE_LCD_BITMAP
98 #define MAX_LINES 10
99 #else
100 #define MAX_LINES 2
101 #endif
103 #ifdef HAVE_REMOTE_LCD
104 #include "lcd-remote.h"
105 #endif
107 long lasttime = 0;
109 /** NVRAM stuff, if the target doesnt have NVRAM it is saved in ROCKBOX_DIR /nvram.bin **/
110 /* NVRAM is set out as
111 [0] 'R'
112 [1] 'b'
113 [2] version
114 [3] stored variable count
115 [4-7] crc32 checksum
116 [8-NVRAM_BLOCK_SIZE] data
118 #define NVRAM_DATA_START 8
119 #define NVRAM_FILE ROCKBOX_DIR "/nvram.bin"
120 static char nvram_buffer[NVRAM_BLOCK_SIZE];
122 static bool read_nvram_data(char* buf, int max_len)
124 unsigned crc32 = 0xffffffff;
125 int var_count = 0, i = 0, buf_pos = 0;
126 #ifndef HAVE_RTC_RAM
127 int fd = open(NVRAM_FILE,O_RDONLY);
128 if (fd < 0)
129 return false;
130 memset(buf,0,max_len);
131 if (read(fd,buf,max_len) < 8) /* min is 8 bytes,magic, ver, vars, crc32 */
132 return false;
133 close(fd);
134 #else
135 memset(buf,0,max_len);
136 /* read rtc block */
137 for (i=0; i < max_len; i++ )
138 buf[i] = rtc_read(0x14+i);
139 #endif
140 /* check magic, version */
141 if ((buf[0] != 'R') || (buf[1] != 'b')
142 || (buf[2] != NVRAM_CONFIG_VERSION))
143 return false;
144 /* check crc32 */
145 crc32 = crc_32(&buf[NVRAM_DATA_START],
146 max_len-NVRAM_DATA_START-1,0xffffffff);
147 if (memcmp(&crc32,&buf[4],4))
148 return false;
149 /* all good, so read in the settings */
150 var_count = buf[3];
151 buf_pos = NVRAM_DATA_START;
152 for(i=0; (i<nb_settings) && (var_count>0) && (buf_pos<max_len); i++)
154 int nvram_bytes = (settings[i].flags&F_NVRAM_BYTES_MASK)
155 >>F_NVRAM_MASK_SHIFT;
156 if (nvram_bytes)
158 memcpy(settings[i].setting,&buf[buf_pos],nvram_bytes);
159 buf_pos += nvram_bytes;
160 var_count--;
163 return true;
165 static bool write_nvram_data(char* buf, int max_len)
167 unsigned crc32 = 0xffffffff;
168 int i = 0, buf_pos = 0;
169 char var_count = 0;
170 #ifndef HAVE_RTC_RAM
171 int fd;
172 #endif
173 memset(buf,0,max_len);
174 /* magic, version */
175 buf[0] = 'R'; buf[1] = 'b';
176 buf[2] = NVRAM_CONFIG_VERSION;
177 buf_pos = NVRAM_DATA_START;
178 for(i=0; (i<nb_settings) && (buf_pos<max_len); i++)
180 int nvram_bytes = (settings[i].flags&F_NVRAM_BYTES_MASK)
181 >>F_NVRAM_MASK_SHIFT;
182 if (nvram_bytes)
184 memcpy(&buf[buf_pos],settings[i].setting,nvram_bytes);
185 buf_pos += nvram_bytes;
186 var_count++;
189 /* count and crc32 */
190 buf[3] = var_count;
191 crc32 = crc_32(&buf[NVRAM_DATA_START],
192 max_len-NVRAM_DATA_START-1,0xffffffff);
193 memcpy(&buf[4],&crc32,4);
194 #ifndef HAVE_RTC_RAM
195 fd = open(NVRAM_FILE,O_CREAT|O_TRUNC|O_WRONLY);
196 if (fd >= 0)
198 int len = write(fd,buf,max_len);
199 close(fd);
200 if (len < 8)
201 return false;
203 #else
204 /* FIXME: okay, it _would_ be cleaner and faster to implement rtc_write so
205 that it would write a number of bytes at a time since the RTC chip
206 supports that, but this will have to do for now 8-) */
207 for (i=0; i < NVRAM_BLOCK_SIZE; i++ ) {
208 int r = rtc_write(0x14+i, buf[i]);
209 if (r) {
210 DEBUGF( "save_config_buffer: rtc_write failed at addr 0x%02x: %d\n",
211 14+i, r );
212 return false;
215 #endif
216 return true;
219 /** Reading from a config file **/
221 * load settings from disk or RTC RAM
223 void settings_load(int which)
225 DEBUGF( "reload_all_settings()\n" );
226 if (which&SETTINGS_RTC)
227 read_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE);
228 if (which&SETTINGS_HD)
230 settings_load_config(CONFIGFILE,false);
231 settings_load_config(FIXEDSETTINGSFILE,false);
234 #ifdef HAVE_LCD_COLOR
236 * Helper function to convert a string of 6 hex digits to a native colour
239 #define hex2dec(c) (((c) >= '0' && ((c) <= '9')) ? (toupper(c)) - '0' : \
240 (toupper(c)) - 'A' + 10)
242 static int hex_to_rgb(const char* hex)
243 { int ok = 1;
244 int i;
245 int red, green, blue;
247 if (strlen(hex) == 6) {
248 for (i=0; i < 6; i++ ) {
249 if (!isxdigit(hex[i])) {
250 ok=0;
251 break;
255 if (ok) {
256 red = (hex2dec(hex[0]) << 4) | hex2dec(hex[1]);
257 green = (hex2dec(hex[2]) << 4) | hex2dec(hex[3]);
258 blue = (hex2dec(hex[4]) << 4) | hex2dec(hex[5]);
259 return LCD_RGBPACK(red,green,blue);
263 return 0;
265 #endif /* HAVE_LCD_COLOR */
267 static bool cfg_string_to_int(int setting_id, int* out, char* str)
269 const char* start = settings[setting_id].cfg_vals;
270 char* end = NULL;
271 char temp[MAX_PATH];
272 int count = 0;
273 while (1)
275 end = strchr(start, ',');
276 if (!end)
278 if (!strcmp(str, start))
280 *out = count;
281 return true;
283 else return false;
285 strncpy(temp, start, end-start);
286 temp[end-start] = '\0';
287 if (!strcmp(str, temp))
289 *out = count;
290 return true;
292 start = end +1;
293 count++;
295 return false;
298 bool settings_load_config(const char* file, bool apply)
300 int fd;
301 char line[128];
302 char* name;
303 char* value;
304 int i;
305 fd = open(file, O_RDONLY);
306 if (fd < 0)
307 return false;
309 while (read_line(fd, line, sizeof line) > 0)
311 if (!settings_parseline(line, &name, &value))
312 continue;
313 for(i=0; i<nb_settings; i++)
315 if (settings[i].cfg_name == NULL)
316 continue;
317 if (!strcasecmp(name,settings[i].cfg_name))
319 switch (settings[i].flags&F_T_MASK)
321 case F_T_INT:
322 case F_T_UINT:
323 #ifdef HAVE_LCD_COLOR
324 if (settings[i].flags&F_RGB)
325 *(int*)settings[i].setting = hex_to_rgb(value);
326 else
327 #endif
328 if (settings[i].cfg_vals == NULL)
330 *(int*)settings[i].setting = atoi(value);
332 else
334 cfg_string_to_int(i,(int*)settings[i].setting,value);
336 break;
337 case F_T_BOOL:
339 int temp;
340 if (cfg_string_to_int(i,&temp,value))
341 *(bool*)settings[i].setting = (temp==0?false:true);
342 break;
344 case F_T_CHARPTR:
345 case F_T_UCHARPTR:
347 char storage[MAX_PATH];
348 if (settings[i].filename_setting->prefix)
350 int len = strlen(settings[i].filename_setting->prefix);
351 if (!strncasecmp(value,
352 settings[i].filename_setting->prefix,
353 len))
355 strncpy(storage,&value[len],MAX_PATH);
357 else strncpy(storage,value,MAX_PATH);
359 else strncpy(storage,value,MAX_PATH);
360 if (settings[i].filename_setting->suffix)
362 char *s = strcasestr(storage,settings[i].filename_setting->suffix);
363 if (s) *s = '\0';
365 strncpy((char*)settings[i].setting,storage,
366 settings[i].filename_setting->max_len);
367 ((char*)settings[i].setting)
368 [settings[i].filename_setting->max_len-1] = '\0';
369 break;
372 break;
373 } /* if (!strcmp(name,settings[i].cfg_name)) */
374 } /* for(...) */
375 } /* while(...) */
377 close(fd);
378 settings_save();
379 if (apply)
380 settings_apply();
381 return true;
384 /** Writing to a config file and saving settings **/
386 bool cfg_int_to_string(int setting_id, int val, char* buf, int buf_len)
388 const char* start = settings[setting_id].cfg_vals;
389 char* end = NULL;
390 int count = 0;
391 while (count < val)
393 start = strchr(start,',');
394 if (!start)
395 return false;
396 count++;
397 start++;
399 end = strchr(start,',');
400 if (end == NULL)
401 strncpy(buf, start, buf_len);
402 else
404 int len = (buf_len > (end-start))? end-start: buf_len;
405 strncpy(buf, start, len);
406 buf[len] = '\0';
408 return true;
410 static bool is_changed(int setting_id)
412 const struct settings_list *setting = &settings[setting_id];
413 switch (setting->flags&F_T_MASK)
415 case F_T_INT:
416 case F_T_UINT:
417 if (setting->flags&F_DEF_ISFUNC)
419 if (*(int*)setting->setting == setting->default_val.func())
420 return false;
422 else if (setting->flags&F_T_SOUND)
424 if (*(int*)setting->setting ==
425 sound_default(setting->sound_setting->setting))
426 return false;
428 else if (*(int*)setting->setting == setting->default_val.int_)
429 return false;
430 break;
431 case F_T_BOOL:
432 if (*(bool*)setting->setting == setting->default_val.bool_)
433 return false;
434 break;
435 case F_T_CHARPTR:
436 case F_T_UCHARPTR:
437 if (!strcmp((char*)setting->setting, setting->default_val.charptr))
438 return false;
439 break;
441 return true;
444 static bool settings_write_config(char* filename, int options)
446 int i;
447 int fd;
448 char value[MAX_PATH];
449 fd = open(filename,O_CREAT|O_TRUNC|O_WRONLY);
450 if (fd < 0)
451 return false;
452 fdprintf(fd, "# .cfg file created by rockbox %s - "
453 "http://www.rockbox.org\r\n\r\n", appsversion);
454 for(i=0; i<nb_settings; i++)
456 if (settings[i].cfg_name == NULL)
457 continue;
458 value[0] = '\0';
460 if ((options == SETTINGS_SAVE_CHANGED) &&
461 !is_changed(i))
462 continue;
463 else if ((options == SETTINGS_SAVE_THEME) &&
464 ((settings[i].flags&F_THEMESETTING) == 0))
465 continue;
467 switch (settings[i].flags&F_T_MASK)
469 case F_T_INT:
470 case F_T_UINT:
471 #ifdef HAVE_LCD_COLOR
472 if (settings[i].flags&F_RGB)
474 int colour = *(int*)settings[i].setting;
475 snprintf(value,MAX_PATH,"%02x%02x%02x",
476 (int)RGB_UNPACK_RED(colour),
477 (int)RGB_UNPACK_GREEN(colour),
478 (int)RGB_UNPACK_BLUE(colour));
480 else
481 #endif
482 if (settings[i].cfg_vals == NULL)
484 snprintf(value,MAX_PATH,"%d",*(int*)settings[i].setting);
486 else
488 cfg_int_to_string(i, *(int*)settings[i].setting,
489 value, MAX_PATH);
491 break;
492 case F_T_BOOL:
493 cfg_int_to_string(i,
494 *(bool*)settings[i].setting==false?0:1, value, MAX_PATH);
495 break;
496 case F_T_CHARPTR:
497 case F_T_UCHARPTR:
498 if (((char*)settings[i].setting)[0] == '\0')
499 break;
500 if (settings[i].filename_setting->prefix)
502 snprintf(value,MAX_PATH,"%s%s%s",
503 settings[i].filename_setting->prefix,
504 (char*)settings[i].setting,
505 settings[i].filename_setting->suffix);
507 else strncpy(value,(char*)settings[i].setting,
508 settings[i].filename_setting->max_len);
509 break;
510 } /* switch () */
511 if (value[0])
512 fdprintf(fd,"%s: %s\r\n",settings[i].cfg_name,value);
513 } /* for(...) */
514 close(fd);
515 return true;
517 #ifndef HAVE_RTC_RAM
518 static bool flush_global_status_callback(void)
520 return write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE);
522 #endif
523 static bool flush_config_block_callback(void)
525 bool r1, r2;
526 r1 = write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE);
527 r2 = settings_write_config(CONFIGFILE, SETTINGS_SAVE_CHANGED);
528 return r1 || r2;
532 * persist all runtime user settings to disk or RTC RAM
534 static void update_runtime(void)
536 int elapsed_secs;
538 elapsed_secs = (current_tick - lasttime) / HZ;
539 global_status.runtime += elapsed_secs;
540 lasttime += (elapsed_secs * HZ);
542 if ( global_status.runtime > global_status.topruntime )
543 global_status.topruntime = global_status.runtime;
546 void status_save( void )
548 update_runtime();
549 #ifdef HAVE_RTC_RAM
550 /* this will be done in the ata_callback if
551 target doesnt have rtc ram */
552 write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE);
553 #else
554 register_ata_idle_func(flush_global_status_callback);
555 #endif
558 int settings_save( void )
560 update_runtime();
561 #ifdef HAVE_RTC_RAM
562 /* this will be done in the ata_callback if
563 target doesnt have rtc ram */
564 write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE);
565 #endif
566 if(!register_ata_idle_func(flush_config_block_callback))
568 int i;
569 FOR_NB_SCREENS(i)
571 screens[i].clear_display();
572 #ifdef HAVE_LCD_CHARCELLS
573 screens[i].puts(0, 0, str(LANG_SETTINGS_SAVE_PLAYER));
574 screens[i].puts(0, 1, str(LANG_SETTINGS_BATTERY_PLAYER));
575 #else
576 screens[i].puts(4, 2, str(LANG_SETTINGS_SAVE_RECORDER));
577 screens[i].puts(2, 4, str(LANG_SETTINGS_BATTERY_RECORDER));
578 screens[i].update();
579 #endif
581 sleep(HZ*2);
582 return -1;
584 return 0;
586 bool settings_save_config(int options)
588 char filename[MAX_PATH];
590 create_numbered_filename(filename, ROCKBOX_DIR, "config", ".cfg", 2
591 IF_CNFN_NUM_(, NULL));
593 /* allow user to modify filename */
594 while (true) {
595 if (!kbd_input(filename, sizeof filename)) {
596 break;
598 else {
599 gui_syncsplash(HZ, str(LANG_MENU_SETTING_CANCEL));
600 return false;
604 if (settings_write_config(filename, options))
605 gui_syncsplash(HZ, str(LANG_SETTINGS_SAVED));
606 else
607 gui_syncsplash(HZ, str(LANG_FAILED));
608 return true;
611 /** Apply and Reset settings **/
614 #ifdef HAVE_LCD_BITMAP
616 * Applies the range infos stored in global_settings to
617 * the peak meter.
619 void settings_apply_pm_range(void)
621 int pm_min, pm_max;
623 /* depending on the scale mode (dBfs or percent) the values
624 of global_settings.peak_meter_dbfs have different meanings */
625 if (global_settings.peak_meter_dbfs)
627 /* convert to dBfs * 100 */
628 pm_min = -(((int)global_settings.peak_meter_min) * 100);
629 pm_max = -(((int)global_settings.peak_meter_max) * 100);
631 else
633 /* percent is stored directly -> no conversion */
634 pm_min = global_settings.peak_meter_min;
635 pm_max = global_settings.peak_meter_max;
638 /* apply the range */
639 peak_meter_init_range(global_settings.peak_meter_dbfs, pm_min, pm_max);
641 #endif /* HAVE_LCD_BITMAP */
643 void sound_settings_apply(void)
645 #if CONFIG_CODEC == SWCODEC
646 sound_set_dsp_callback(dsp_callback);
647 #endif
648 sound_set(SOUND_BASS, global_settings.bass);
649 sound_set(SOUND_TREBLE, global_settings.treble);
650 sound_set(SOUND_BALANCE, global_settings.balance);
651 sound_set(SOUND_VOLUME, global_settings.volume);
652 sound_set(SOUND_CHANNELS, global_settings.channel_config);
653 sound_set(SOUND_STEREO_WIDTH, global_settings.stereo_width);
654 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
655 sound_set(SOUND_LOUDNESS, global_settings.loudness);
656 sound_set(SOUND_AVC, global_settings.avc);
657 sound_set(SOUND_MDB_STRENGTH, global_settings.mdb_strength);
658 sound_set(SOUND_MDB_HARMONICS, global_settings.mdb_harmonics);
659 sound_set(SOUND_MDB_CENTER, global_settings.mdb_center);
660 sound_set(SOUND_MDB_SHAPE, global_settings.mdb_shape);
661 sound_set(SOUND_MDB_ENABLE, global_settings.mdb_enable);
662 sound_set(SOUND_SUPERBASS, global_settings.superbass);
663 #endif
665 #ifdef HAVE_USB_POWER
666 #if CONFIG_CHARGING
667 usb_charging_enable(global_settings.usb_charging);
668 #endif
669 #endif
672 void settings_apply(void)
674 char buf[64];
675 #if CONFIG_CODEC == SWCODEC
676 int i;
677 #endif
679 DEBUGF( "settings_apply()\n" );
680 sound_settings_apply();
682 audio_set_buffer_margin(global_settings.buffer_margin);
684 #ifdef HAVE_LCD_CONTRAST
685 lcd_set_contrast(global_settings.contrast);
686 #endif
687 lcd_scroll_speed(global_settings.scroll_speed);
688 #ifdef HAVE_REMOTE_LCD
689 lcd_remote_set_contrast(global_settings.remote_contrast);
690 lcd_remote_set_invert_display(global_settings.remote_invert);
691 lcd_remote_set_flip(global_settings.remote_flip_display);
692 lcd_remote_scroll_speed(global_settings.remote_scroll_speed);
693 lcd_remote_scroll_step(global_settings.remote_scroll_step);
694 lcd_remote_scroll_delay(global_settings.remote_scroll_delay);
695 lcd_remote_bidir_scroll(global_settings.remote_bidir_limit);
696 #ifdef HAVE_REMOTE_LCD_TICKING
697 lcd_remote_emireduce(global_settings.remote_reduce_ticking);
698 #endif
699 remote_backlight_set_timeout(global_settings.remote_backlight_timeout);
700 #if CONFIG_CHARGING
701 remote_backlight_set_timeout_plugged(global_settings.remote_backlight_timeout_plugged);
702 #endif
703 #ifdef HAS_REMOTE_BUTTON_HOLD
704 remote_backlight_set_on_button_hold(global_settings.remote_backlight_on_button_hold);
705 #endif
706 #endif /* HAVE_REMOTE_LCD */
707 #if CONFIG_BACKLIGHT
708 backlight_set_timeout(global_settings.backlight_timeout);
709 #if CONFIG_CHARGING
710 backlight_set_timeout_plugged(global_settings.backlight_timeout_plugged);
711 #endif
712 #if defined(HAVE_BACKLIGHT_PWM_FADING) && !defined(SIMULATOR)
713 backlight_set_fade_in(global_settings.backlight_fade_in);
714 backlight_set_fade_out(global_settings.backlight_fade_out);
715 #endif
716 #endif
717 #ifdef HAVE_BACKLIGHT_BRIGHTNESS
718 backlight_set_brightness(global_settings.brightness);
719 #endif
720 ata_spindown(global_settings.disk_spindown);
721 #if (CONFIG_CODEC == MAS3507D) && !defined(SIMULATOR)
722 dac_line_in(global_settings.line_in);
723 #endif
724 mpeg_id3_options(global_settings.id3_v1_first);
726 set_poweroff_timeout(global_settings.poweroff);
728 set_battery_capacity(global_settings.battery_capacity);
729 #if BATTERY_TYPES_COUNT > 1
730 set_battery_type(global_settings.battery_type);
731 #endif
733 #ifdef HAVE_LCD_BITMAP
734 lcd_set_invert_display(global_settings.invert);
735 lcd_set_flip(global_settings.flip_display);
736 button_set_flip(global_settings.flip_display);
737 lcd_update(); /* refresh after flipping the screen */
738 settings_apply_pm_range();
739 peak_meter_init_times(
740 global_settings.peak_meter_release, global_settings.peak_meter_hold,
741 global_settings.peak_meter_clip_hold);
742 #endif
744 #if LCD_DEPTH > 1
745 unload_wps_backdrop();
746 #endif
747 if ( global_settings.wps_file[0] &&
748 global_settings.wps_file[0] != 0xff ) {
749 snprintf(buf, sizeof buf, WPS_DIR "/%s.wps",
750 global_settings.wps_file);
751 wps_data_load(gui_wps[0].data, buf, true);
753 else
755 wps_data_init(gui_wps[0].data);
758 #if LCD_DEPTH > 1
759 if ( global_settings.backdrop_file[0] &&
760 global_settings.backdrop_file[0] != 0xff ) {
761 snprintf(buf, sizeof buf, BACKDROP_DIR "/%s.bmp",
762 global_settings.backdrop_file);
763 load_main_backdrop(buf);
764 } else {
765 unload_main_backdrop();
767 show_main_backdrop();
768 #endif
770 #ifdef HAVE_LCD_COLOR
771 screens[SCREEN_MAIN].set_foreground(global_settings.fg_color);
772 screens[SCREEN_MAIN].set_background(global_settings.bg_color);
773 #endif
775 #if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1)
776 if ( global_settings.rwps_file[0]) {
777 snprintf(buf, sizeof buf, WPS_DIR "/%s.rwps",
778 global_settings.rwps_file);
779 wps_data_load(gui_wps[1].data, buf, true);
781 else
782 wps_data_init(gui_wps[1].data);
783 #endif
785 #ifdef HAVE_LCD_BITMAP
786 if ( global_settings.font_file[0]) {
787 snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt",
788 global_settings.font_file);
789 font_load(buf);
791 else
792 font_reset();
794 if ( global_settings.kbd_file[0]) {
795 snprintf(buf, sizeof buf, ROCKBOX_DIR "/%s.kbd",
796 global_settings.kbd_file);
797 load_kbd(buf);
799 else
800 load_kbd(NULL);
802 lcd_scroll_step(global_settings.scroll_step);
803 gui_list_screen_scroll_step(global_settings.screen_scroll_step);
804 gui_list_screen_scroll_out_of_view(global_settings.offset_out_of_view);
805 #else
806 lcd_jump_scroll(global_settings.jump_scroll);
807 lcd_jump_scroll_delay(global_settings.jump_scroll_delay);
808 #endif
809 lcd_bidir_scroll(global_settings.bidir_limit);
810 lcd_scroll_delay(global_settings.scroll_delay);
812 if ( global_settings.lang_file[0]) {
813 snprintf(buf, sizeof buf, LANG_DIR "/%s.lng",
814 global_settings.lang_file);
815 lang_load(buf);
816 talk_init(); /* use voice of same language */
819 set_codepage(global_settings.default_codepage);
821 #if CONFIG_CODEC == SWCODEC
822 audio_set_crossfade(global_settings.crossfade);
823 dsp_set_replaygain();
824 dsp_set_crossfeed(global_settings.crossfeed);
825 dsp_set_crossfeed_direct_gain(global_settings.crossfeed_direct_gain);
826 dsp_set_crossfeed_cross_params(global_settings.crossfeed_cross_gain,
827 global_settings.crossfeed_hf_attenuation,
828 global_settings.crossfeed_hf_cutoff);
830 dsp_set_eq(global_settings.eq_enabled);
831 dsp_set_eq_precut(global_settings.eq_precut);
832 /* Update all EQ bands */
833 for(i = 0; i < 5; i++) {
834 dsp_set_eq_coefs(i);
837 dsp_dither_enable(global_settings.dithering_enabled);
838 #endif
840 #ifdef HAVE_WM8758
841 eq_hw_enable(global_settings.eq_hw_enabled);
842 #endif
844 #ifdef HAVE_SPDIF_POWER
845 spdif_power_enable(global_settings.spdif_enable);
846 #endif
848 #if CONFIG_BACKLIGHT
849 set_backlight_filter_keypress(global_settings.bl_filter_first_keypress);
850 #ifdef HAVE_REMOTE_LCD
851 set_remote_backlight_filter_keypress(global_settings.remote_bl_filter_first_keypress);
852 #endif
853 #ifdef HAS_BUTTON_HOLD
854 backlight_set_on_button_hold(global_settings.backlight_on_button_hold);
855 #endif
856 #ifdef HAVE_LCD_SLEEP
857 lcd_set_sleep_after_backlight_off(global_settings.lcd_sleep_after_backlight_off);
858 #endif
859 #endif /* CONFIG_BACKLIGHT */
861 /* This should stay last */
862 #if defined(HAVE_RECORDING) && CONFIG_CODEC == SWCODEC
863 enc_global_settings_apply();
864 #endif
871 * reset all settings to their default value
873 void settings_reset(void) {
875 int i;
876 DEBUGF( "settings_reset()\n" );
878 for(i=0; i<nb_settings; i++)
880 switch (settings[i].flags&F_T_MASK)
882 case F_T_INT:
883 case F_T_UINT:
884 if (settings[i].flags&F_DEF_ISFUNC)
885 *(int*)settings[i].setting = settings[i].default_val.func();
886 else if (settings[i].flags&F_T_SOUND)
887 *(int*)settings[i].setting =
888 sound_default(settings[i].sound_setting->setting);
889 else *(int*)settings[i].setting = settings[i].default_val.int_;
890 break;
891 case F_T_BOOL:
892 *(bool*)settings[i].setting = settings[i].default_val.bool_;
893 break;
894 case F_T_CHARPTR:
895 case F_T_UCHARPTR:
896 strncpy((char*)settings[i].setting,
897 settings[i].default_val.charptr,MAX_FILENAME);
898 break;
900 } /* for(...) */
901 #if defined (HAVE_RECORDING) && CONFIG_CODEC == SWCODEC
902 enc_global_settings_reset();
903 #endif
906 /** Changing setting values **/
907 const struct settings_list* find_setting(void* variable, int *id)
909 int i;
910 for(i=0;i<nb_settings;i++)
912 if (settings[i].setting == variable)
914 if (id)
915 *id = i;
916 return &settings[i];
919 return NULL;
922 void talk_setting(void *global_settings_variable)
924 const struct settings_list *setting;
925 if (global_settings.talk_menu == 0)
926 return;
927 setting = find_setting(global_settings_variable, NULL);
928 if (setting == NULL)
929 return;
930 if (setting->lang_id)
931 talk_id(setting->lang_id,false);
934 static int selected_setting; /* Used by the callback */
936 static void dec_sound_formatter(char *buffer, int buffer_size,
937 int val, const char *unit)
939 val = sound_val2phys(selected_setting, val);
940 char sign = ' ';
941 if(val < 0)
943 sign = '-';
944 val = abs(val);
946 int integer = val / 10;
947 int dec = val % 10;
948 snprintf(buffer, buffer_size, "%c%d.%d %s", sign, integer, dec, unit);
951 bool set_sound(const unsigned char * string,
952 int* variable,
953 int setting)
955 int talkunit = UNIT_INT;
956 const char* unit = sound_unit(setting);
957 int numdec = sound_numdecimals(setting);
958 int steps = sound_steps(setting);
959 int min = sound_min(setting);
960 int max = sound_max(setting);
961 sound_set_type* sound_callback = sound_get_fn(setting);
962 if (*unit == 'd') /* crude reconstruction */
963 talkunit = UNIT_DB;
964 else if (*unit == '%')
965 talkunit = UNIT_PERCENT;
966 else if (*unit == 'H')
967 talkunit = UNIT_HERTZ;
968 if (!numdec)
969 return set_int(string, unit, talkunit, variable, sound_callback,
970 steps, min, max, NULL );
971 else
972 {/* Decimal number */
973 selected_setting=setting;
974 return set_int(string, unit, talkunit, variable, sound_callback,
975 steps, min, max, &dec_sound_formatter );
979 bool set_bool(const char* string, bool* variable )
981 return set_bool_options(string, variable,
982 (char *)STR(LANG_SET_BOOL_YES),
983 (char *)STR(LANG_SET_BOOL_NO),
984 NULL);
987 /* wrapper to convert from int param to bool param in set_option */
988 static void (*boolfunction)(bool);
989 static void bool_funcwrapper(int value)
991 if (value)
992 boolfunction(true);
993 else
994 boolfunction(false);
997 bool set_bool_options(const char* string, bool* variable,
998 const char* yes_str, int yes_voice,
999 const char* no_str, int no_voice,
1000 void (*function)(bool))
1002 struct opt_items names[] = {
1003 {(unsigned char *)no_str, no_voice},
1004 {(unsigned char *)yes_str, yes_voice}
1006 bool result;
1008 boolfunction = function;
1009 result = set_option(string, variable, BOOL, names, 2,
1010 function ? bool_funcwrapper : NULL);
1011 return result;
1014 static void talk_unit(int unit, int value, long (*get_talk_id)(int value))
1016 if (global_settings.talk_menu)
1018 if (get_talk_id)
1020 talk_id(get_talk_id(value),false);
1022 else if (unit < UNIT_LAST)
1023 { /* use the available unit definition */
1024 talk_value(value, unit, false);
1026 else
1027 { /* say the number, followed by an arbitrary voice ID */
1028 talk_number(value, false);
1029 talk_id(unit, true);
1034 struct value_setting_data {
1035 enum optiontype type;
1036 /* used for "value" settings.. */
1037 int max;
1038 int step;
1039 int voice_unit;
1040 const char * unit;
1041 void (*formatter)(char* dest, int dest_length,
1042 int value, const char* unit);
1043 long (*get_talk_id)(int value);
1044 /* used for BOOL and "choice" settings */
1045 struct opt_items* options;
1048 static char * value_setting_get_name_cb(int selected_item,void * data, char *buffer)
1050 struct value_setting_data* cb_data =
1051 (struct value_setting_data*)data;
1052 if (cb_data->type == INT && !cb_data->options)
1054 int item = cb_data->max -(selected_item*cb_data->step);
1055 if (cb_data->formatter)
1056 cb_data->formatter(buffer, MAX_PATH,item,cb_data->unit);
1057 else
1058 snprintf(buffer, MAX_PATH,"%d %s",item,cb_data->unit);
1060 else strcpy(buffer,P2STR(cb_data->options[selected_item].string));
1061 return buffer;
1063 #define type_fromvoidptr(type, value) \
1064 (type == INT)? \
1065 (int)(*(int*)(value)) \
1067 (bool)(*(bool*)(value))
1068 static bool do_set_setting(const unsigned char* string, void *variable,
1069 int nb_items,int selected,
1070 struct value_setting_data *cb_data,
1071 void (*function)(int))
1073 int action;
1074 bool done = false;
1075 struct gui_synclist lists;
1076 int oldvalue;
1077 bool allow_wrap = true;
1079 if (cb_data->type == INT)
1081 oldvalue = *(int*)variable;
1082 if (variable == &global_settings.volume)
1083 allow_wrap = false;
1085 else oldvalue = *(bool*)variable;
1087 gui_synclist_init(&lists,value_setting_get_name_cb,(void*)cb_data,false,1);
1088 gui_synclist_set_title(&lists, (char*)string,
1089 #ifdef HAVE_LCD_BITMAP
1090 bitmap_icons_6x8[Icon_Questionmark]
1091 #else
1092 NOICON
1093 #endif
1095 gui_synclist_set_icon_callback(&lists,NULL);
1096 gui_synclist_set_nb_items(&lists,nb_items);
1097 gui_synclist_limit_scroll(&lists,true);
1098 gui_synclist_select_item(&lists, selected);
1100 if (global_settings.talk_menu)
1102 if (cb_data->type == INT && !cb_data->options)
1103 talk_unit(cb_data->voice_unit, *(int*)variable, cb_data->get_talk_id);
1104 else talk_id(cb_data->options[selected].voice_id, false);
1107 gui_synclist_draw(&lists);
1108 action_signalscreenchange();
1109 while (!done)
1112 action = get_action(CONTEXT_LIST,TIMEOUT_BLOCK);
1113 if (action == ACTION_NONE)
1114 continue;
1115 if (gui_synclist_do_button(&lists,action,
1116 allow_wrap?LIST_WRAP_UNLESS_HELD:LIST_WRAP_OFF))
1118 if (global_settings.talk_menu)
1120 int value;
1121 if (cb_data->type == INT && !cb_data->options)
1123 value = cb_data->max -
1124 gui_synclist_get_sel_pos(&lists)*cb_data->step;
1125 talk_unit(cb_data->voice_unit, value, cb_data->get_talk_id);
1127 else
1129 value = gui_synclist_get_sel_pos(&lists);
1130 talk_id(cb_data->options[value].voice_id, false);
1133 if (cb_data->type == INT && !cb_data->options)
1134 *(int*)variable = cb_data->max -
1135 gui_synclist_get_sel_pos(&lists)*cb_data->step;
1136 else if (cb_data->type == BOOL)
1137 *(bool*)variable = gui_synclist_get_sel_pos(&lists) ? true : false;
1138 else *(int*)variable = gui_synclist_get_sel_pos(&lists);
1140 else if (action == ACTION_STD_CANCEL)
1142 if (cb_data->type == INT)
1144 if (*(int*)variable != oldvalue)
1146 gui_syncsplash(HZ/2, str(LANG_MENU_SETTING_CANCEL));
1147 *(int*)variable = oldvalue;
1150 else
1152 if (*(bool*)variable != (bool)oldvalue)
1154 gui_syncsplash(HZ/2, str(LANG_MENU_SETTING_CANCEL));
1155 *(bool*)variable = (bool)oldvalue;
1158 done = true;
1160 else if (action == ACTION_STD_OK)
1162 done = true;
1164 else if(default_event_handler(action) == SYS_USB_CONNECTED)
1165 return true;
1166 gui_syncstatusbar_draw(&statusbars, false);
1167 if ( function )
1168 function(type_fromvoidptr(cb_data->type,variable));
1170 if (cb_data->type == INT)
1172 if (oldvalue != *(int*)variable)
1173 settings_save();
1175 else if (oldvalue != *(bool*)variable)
1176 settings_save();
1178 action_signalscreenchange();
1179 return false;
1181 static const char *unit_strings[] =
1183 [UNIT_INT]
1184 = "",
1185 [UNIT_MS]
1186 = "ms",
1187 [UNIT_SEC]
1188 = "s",
1189 [UNIT_MIN]
1190 = "min",
1191 [UNIT_HOUR]
1192 = "hr",
1193 [UNIT_KHZ]
1194 = "KHz",
1195 [UNIT_DB]
1196 = "dB",
1197 [UNIT_PERCENT]
1198 = "%",
1199 [UNIT_MAH]
1200 = "mAh",
1201 [UNIT_PIXEL]
1202 = "px",
1203 [UNIT_PER_SEC]
1204 = "per sec",
1205 [UNIT_HERTZ]
1206 = "Hz",
1207 [UNIT_MB]
1208 = "MB",
1209 [UNIT_KBIT]
1210 = "kb/s",
1212 bool set_int_ex(const unsigned char* string,
1213 const char* unit,
1214 int voice_unit,
1215 int* variable,
1216 void (*function)(int),
1217 int step,
1218 int min,
1219 int max,
1220 void (*formatter)(char*, int, int, const char*),
1221 long (*get_talk_id)(int))
1223 int count = (max-min)/step + 1;
1224 #if CONFIG_KEYPAD != PLAYER_PAD
1225 struct value_setting_data data = {
1226 INT,max, step, voice_unit,unit,formatter,get_talk_id,NULL };
1227 if (voice_unit < UNIT_LAST)
1228 data.unit = unit_strings[voice_unit];
1229 else
1230 data.unit = str(voice_unit);
1231 return do_set_setting(string,variable,count,
1232 (max-*variable)/step, &data,function);
1233 #else
1234 struct value_setting_data data = {
1235 INT,min, -step, voice_unit,unit,formatter,get_talk_id,NULL };
1236 if (voice_unit < UNIT_LAST)
1237 data.unit = unit_strings[voice_unit];
1238 else
1239 data.unit = str(voice_unit);
1240 return do_set_setting(string,variable,count,
1241 (*variable-min)/step, &data,function);
1242 #endif
1244 bool set_int(const unsigned char* string,
1245 const char* unit,
1246 int voice_unit,
1247 int* variable,
1248 void (*function)(int),
1249 int step,
1250 int min,
1251 int max,
1252 void (*formatter)(char*, int, int, const char*) )
1254 return set_int_ex(string, unit, voice_unit, variable, function,
1255 step, min, max, formatter, NULL);
1257 /* NOTE: the 'type' parameter specifies the actual type of the variable
1258 that 'variable' points to. not the value within. Only variables with
1259 type 'bool' should use parameter BOOL.
1261 The type separation is necessary since int and bool are fundamentally
1262 different and bit-incompatible types and can not share the same access
1263 code. */
1264 bool set_option(const char* string, void* variable, enum optiontype type,
1265 const struct opt_items* options, int numoptions, void (*function)(int))
1267 struct value_setting_data data = {
1268 type,0, 0, 0,NULL,NULL,NULL,(struct opt_items*)options };
1269 int selected;
1270 if (type == BOOL)
1271 selected = *(bool*)variable ? 1 : 0;
1272 else selected = *(int*)variable;
1273 return do_set_setting(string,variable,numoptions,
1274 selected, &data,function);
1277 /** extra stuff which is probably misplaced **/
1279 void set_file(char* filename, char* setting, int maxlen)
1281 char* fptr = strrchr(filename,'/');
1282 int len;
1283 int extlen = 0;
1284 char* ptr;
1286 if (!fptr)
1287 return;
1289 *fptr = 0;
1290 fptr++;
1292 len = strlen(fptr);
1293 ptr = fptr + len;
1294 while ((*ptr != '.') && (ptr != fptr)) {
1295 extlen++;
1296 ptr--;
1298 if(ptr == fptr) extlen = 0;
1300 if (strncasecmp(ROCKBOX_DIR, filename ,strlen(ROCKBOX_DIR)) ||
1301 (len-extlen > maxlen))
1302 return;
1304 strncpy(setting, fptr, len-extlen);
1305 setting[len-extlen]=0;
1307 settings_save();
1310 #ifdef HAVE_RECORDING
1311 /* This array holds the record timer interval lengths, in seconds */
1312 static const unsigned long rec_timer_seconds[] =
1314 0, /* 0 means OFF */
1315 5*60, /* 00:05 */
1316 10*60, /* 00:10 */
1317 15*60, /* 00:15 */
1318 30*60, /* 00:30 */
1319 60*60, /* 01:00 */
1320 74*60, /* 74:00 */
1321 80*60, /* 80:00 */
1322 2*60*60, /* 02:00 */
1323 4*60*60, /* 04:00 */
1324 6*60*60, /* 06:00 */
1325 8*60*60, /* 08:00 */
1326 10L*60*60, /* 10:00 */
1327 12L*60*60, /* 12:00 */
1328 18L*60*60, /* 18:00 */
1329 24L*60*60 /* 24:00 */
1332 unsigned int rec_timesplit_seconds(void)
1334 return rec_timer_seconds[global_settings.rec_timesplit];
1337 /* This array holds the record size interval lengths, in bytes */
1338 static const unsigned long rec_size_bytes[] =
1340 0, /* 0 means OFF */
1341 5*1024*1024, /* 5MB */
1342 10*1024*1024, /* 10MB */
1343 15*1024*1024, /* 15MB */
1344 32*1024*1024, /* 32MB */
1345 64*1024*1024, /* 64MB */
1346 75*1024*1024, /* 75MB */
1347 100*1024*1024, /* 100MB */
1348 128*1024*1024, /* 128MB */
1349 256*1024*1024, /* 256MB */
1350 512*1024*1024, /* 512MB */
1351 650*1024*1024, /* 650MB */
1352 700*1024*1024, /* 700MB */
1353 1024*1024*1024, /* 1GB */
1354 1536*1024*1024, /* 1.5GB */
1355 1792*1024*1024, /* 1.75GB */
1358 unsigned long rec_sizesplit_bytes(void)
1360 return rec_size_bytes[global_settings.rec_sizesplit];
1363 * Time strings used for the trigger durations.
1364 * Keep synchronous to trigger_times in settings_apply_trigger
1366 const char * const trig_durations[TRIG_DURATION_COUNT] =
1368 "0s", "1s", "2s", "5s",
1369 "10s", "15s", "20s", "25s", "30s",
1370 "1min", "2min", "5min", "10min"
1373 void settings_apply_trigger(void)
1375 /* Keep synchronous to trig_durations and trig_durations_conf*/
1376 static const long trigger_times[TRIG_DURATION_COUNT] = {
1377 0, HZ, 2*HZ, 5*HZ,
1378 10*HZ, 15*HZ, 20*HZ, 25*HZ, 30*HZ,
1379 60*HZ, 2*60*HZ, 5*60*HZ, 10*60*HZ
1382 peak_meter_define_trigger(
1383 global_settings.rec_start_thres,
1384 trigger_times[global_settings.rec_start_duration],
1385 MIN(trigger_times[global_settings.rec_start_duration] / 2, 2*HZ),
1386 global_settings.rec_stop_thres,
1387 trigger_times[global_settings.rec_stop_postrec],
1388 trigger_times[global_settings.rec_stop_gap]
1391 #endif