Remove tabs (I wonder why Anjuta decided to insert them there)
[maemo-rb.git] / apps / settings.c
blob8adc9637d8dfb6bd772e95d8fd5f90695d54851e
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"
64 #include "filetypes.h"
66 #if (LCD_DEPTH > 1) || (defined(HAVE_LCD_REMOTE) && (LCD_REMOTE_DEPTH > 1))
67 #include "backdrop.h"
68 #endif
70 #if CONFIG_TUNER
71 #include "radio.h"
72 #endif
74 #if CONFIG_CODEC == MAS3507D
75 void dac_line_in(bool enable);
76 #endif
77 struct user_settings global_settings;
78 struct system_status global_status;
80 #ifdef HAVE_RECORDING
81 const char rec_base_directory[] = REC_BASE_DIR;
82 #endif
83 #if CONFIG_CODEC == SWCODEC
84 #include "pcmbuf.h"
85 #include "pcm_playback.h"
86 #include "dsp.h"
87 #ifdef HAVE_RECORDING
88 #include "enc_config.h"
89 #endif
90 #endif /* CONFIG_CODEC == SWCODEC */
92 #define NVRAM_BLOCK_SIZE 44
94 #ifdef HAVE_LCD_BITMAP
95 #define MAX_LINES 10
96 #else
97 #define MAX_LINES 2
98 #endif
100 #ifdef HAVE_REMOTE_LCD
101 #include "lcd-remote.h"
102 #endif
104 long lasttime = 0;
106 /** NVRAM stuff, if the target doesnt have NVRAM it is saved in ROCKBOX_DIR /nvram.bin **/
107 /* NVRAM is set out as
108 [0] 'R'
109 [1] 'b'
110 [2] version
111 [3] stored variable count
112 [4-7] crc32 checksum
113 [8-NVRAM_BLOCK_SIZE] data
115 #define NVRAM_DATA_START 8
116 #define NVRAM_FILE ROCKBOX_DIR "/nvram.bin"
117 static char nvram_buffer[NVRAM_BLOCK_SIZE];
119 static bool read_nvram_data(char* buf, int max_len)
121 unsigned crc32 = 0xffffffff;
122 int var_count = 0, i = 0, buf_pos = 0;
123 #ifndef HAVE_RTC_RAM
124 int fd = open(NVRAM_FILE,O_RDONLY);
125 if (fd < 0)
126 return false;
127 memset(buf,0,max_len);
128 if (read(fd,buf,max_len) < 8) /* min is 8 bytes,magic, ver, vars, crc32 */
129 return false;
130 close(fd);
131 #else
132 memset(buf,0,max_len);
133 /* read rtc block */
134 for (i=0; i < max_len; i++ )
135 buf[i] = rtc_read(0x14+i);
136 #endif
137 /* check magic, version */
138 if ((buf[0] != 'R') || (buf[1] != 'b')
139 || (buf[2] != NVRAM_CONFIG_VERSION))
140 return false;
141 /* check crc32 */
142 crc32 = crc_32(&buf[NVRAM_DATA_START],
143 max_len-NVRAM_DATA_START-1,0xffffffff);
144 if (memcmp(&crc32,&buf[4],4))
145 return false;
146 /* all good, so read in the settings */
147 var_count = buf[3];
148 buf_pos = NVRAM_DATA_START;
149 for(i=0; (i<nb_settings) && (var_count>0) && (buf_pos<max_len); i++)
151 int nvram_bytes = (settings[i].flags&F_NVRAM_BYTES_MASK)
152 >>F_NVRAM_MASK_SHIFT;
153 if (nvram_bytes)
155 memcpy(settings[i].setting,&buf[buf_pos],nvram_bytes);
156 buf_pos += nvram_bytes;
157 var_count--;
160 return true;
162 static bool write_nvram_data(char* buf, int max_len)
164 unsigned crc32 = 0xffffffff;
165 int i = 0, buf_pos = 0;
166 char var_count = 0;
167 #ifndef HAVE_RTC_RAM
168 int fd;
169 #endif
170 memset(buf,0,max_len);
171 /* magic, version */
172 buf[0] = 'R'; buf[1] = 'b';
173 buf[2] = NVRAM_CONFIG_VERSION;
174 buf_pos = NVRAM_DATA_START;
175 for(i=0; (i<nb_settings) && (buf_pos<max_len); i++)
177 int nvram_bytes = (settings[i].flags&F_NVRAM_BYTES_MASK)
178 >>F_NVRAM_MASK_SHIFT;
179 if (nvram_bytes)
181 memcpy(&buf[buf_pos],settings[i].setting,nvram_bytes);
182 buf_pos += nvram_bytes;
183 var_count++;
186 /* count and crc32 */
187 buf[3] = var_count;
188 crc32 = crc_32(&buf[NVRAM_DATA_START],
189 max_len-NVRAM_DATA_START-1,0xffffffff);
190 memcpy(&buf[4],&crc32,4);
191 #ifndef HAVE_RTC_RAM
192 fd = open(NVRAM_FILE,O_CREAT|O_TRUNC|O_WRONLY);
193 if (fd >= 0)
195 int len = write(fd,buf,max_len);
196 close(fd);
197 if (len < 8)
198 return false;
200 #else
201 /* FIXME: okay, it _would_ be cleaner and faster to implement rtc_write so
202 that it would write a number of bytes at a time since the RTC chip
203 supports that, but this will have to do for now 8-) */
204 for (i=0; i < NVRAM_BLOCK_SIZE; i++ ) {
205 int r = rtc_write(0x14+i, buf[i]);
206 if (r) {
207 DEBUGF( "save_config_buffer: rtc_write failed at addr 0x%02x: %d\n",
208 14+i, r );
209 return false;
212 #endif
213 return true;
216 /** Reading from a config file **/
218 * load settings from disk or RTC RAM
220 void settings_load(int which)
222 DEBUGF( "reload_all_settings()\n" );
223 if (which&SETTINGS_RTC)
224 read_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE);
225 if (which&SETTINGS_HD)
227 settings_load_config(CONFIGFILE,false);
228 settings_load_config(FIXEDSETTINGSFILE,false);
232 static bool cfg_string_to_int(int setting_id, int* out, char* str)
234 const char* start = settings[setting_id].cfg_vals;
235 char* end = NULL;
236 char temp[MAX_PATH];
237 int count = 0;
238 while (1)
240 end = strchr(start, ',');
241 if (!end)
243 if (!strcmp(str, start))
245 *out = count;
246 return true;
248 else return false;
250 strncpy(temp, start, end-start);
251 temp[end-start] = '\0';
252 if (!strcmp(str, temp))
254 *out = count;
255 return true;
257 start = end +1;
258 count++;
260 return false;
263 bool settings_load_config(const char* file, bool apply)
265 int fd;
266 char line[128];
267 char* name;
268 char* value;
269 int i;
270 fd = open(file, O_RDONLY);
271 if (fd < 0)
272 return false;
274 while (read_line(fd, line, sizeof line) > 0)
276 if (!settings_parseline(line, &name, &value))
277 continue;
278 for(i=0; i<nb_settings; i++)
280 if (settings[i].cfg_name == NULL)
281 continue;
282 if (!strcasecmp(name,settings[i].cfg_name))
284 switch (settings[i].flags&F_T_MASK)
286 case F_T_INT:
287 case F_T_UINT:
288 #ifdef HAVE_LCD_COLOR
289 if (settings[i].flags&F_RGB)
290 *(int*)settings[i].setting = hex_to_rgb(value);
291 else
292 #endif
293 if (settings[i].cfg_vals == NULL)
295 *(int*)settings[i].setting = atoi(value);
297 else
299 cfg_string_to_int(i,(int*)settings[i].setting,value);
301 break;
302 case F_T_BOOL:
304 int temp;
305 if (cfg_string_to_int(i,&temp,value))
306 *(bool*)settings[i].setting = (temp==0?false:true);
307 break;
309 case F_T_CHARPTR:
310 case F_T_UCHARPTR:
312 char storage[MAX_PATH];
313 if (settings[i].filename_setting->prefix)
315 int len = strlen(settings[i].filename_setting->prefix);
316 if (!strncasecmp(value,
317 settings[i].filename_setting->prefix,
318 len))
320 strncpy(storage,&value[len],MAX_PATH);
322 else strncpy(storage,value,MAX_PATH);
324 else strncpy(storage,value,MAX_PATH);
325 if (settings[i].filename_setting->suffix)
327 char *s = strcasestr(storage,settings[i].filename_setting->suffix);
328 if (s) *s = '\0';
330 strncpy((char*)settings[i].setting,storage,
331 settings[i].filename_setting->max_len);
332 ((char*)settings[i].setting)
333 [settings[i].filename_setting->max_len-1] = '\0';
334 break;
337 break;
338 } /* if (!strcmp(name,settings[i].cfg_name)) */
339 } /* for(...) */
340 } /* while(...) */
342 close(fd);
343 settings_save();
344 if (apply)
345 settings_apply();
346 return true;
349 /** Writing to a config file and saving settings **/
351 bool cfg_int_to_string(int setting_id, int val, char* buf, int buf_len)
353 const char* start = settings[setting_id].cfg_vals;
354 char* end = NULL;
355 int count = 0;
356 while (count < val)
358 start = strchr(start,',');
359 if (!start)
360 return false;
361 count++;
362 start++;
364 end = strchr(start,',');
365 if (end == NULL)
366 strncpy(buf, start, buf_len);
367 else
369 int len = (buf_len > (end-start))? end-start: buf_len;
370 strncpy(buf, start, len);
371 buf[len] = '\0';
373 return true;
375 static bool is_changed(int setting_id)
377 const struct settings_list *setting = &settings[setting_id];
378 switch (setting->flags&F_T_MASK)
380 case F_T_INT:
381 case F_T_UINT:
382 if (setting->flags&F_DEF_ISFUNC)
384 if (*(int*)setting->setting == setting->default_val.func())
385 return false;
387 else if (setting->flags&F_T_SOUND)
389 if (*(int*)setting->setting ==
390 sound_default(setting->sound_setting->setting))
391 return false;
393 else if (*(int*)setting->setting == setting->default_val.int_)
394 return false;
395 break;
396 case F_T_BOOL:
397 if (*(bool*)setting->setting == setting->default_val.bool_)
398 return false;
399 break;
400 case F_T_CHARPTR:
401 case F_T_UCHARPTR:
402 if (!strcmp((char*)setting->setting, setting->default_val.charptr))
403 return false;
404 break;
406 return true;
409 static bool settings_write_config(char* filename, int options)
411 int i;
412 int fd;
413 char value[MAX_PATH];
414 fd = open(filename,O_CREAT|O_TRUNC|O_WRONLY);
415 if (fd < 0)
416 return false;
417 fdprintf(fd, "# .cfg file created by rockbox %s - "
418 "http://www.rockbox.org\r\n\r\n", appsversion);
419 for(i=0; i<nb_settings; i++)
421 if (settings[i].cfg_name == NULL)
422 continue;
423 value[0] = '\0';
425 if ((options == SETTINGS_SAVE_CHANGED) &&
426 !is_changed(i))
427 continue;
428 else if ((options == SETTINGS_SAVE_THEME) &&
429 ((settings[i].flags&F_THEMESETTING) == 0))
430 continue;
431 #ifdef HAVE_RECORDING
432 else if ((options == SETTINGS_SAVE_RECPRESETS) &&
433 ((settings[i].flags&F_RECSETTING) == 0))
434 continue;
435 #endif
436 switch (settings[i].flags&F_T_MASK)
438 case F_T_INT:
439 case F_T_UINT:
440 #ifdef HAVE_LCD_COLOR
441 if (settings[i].flags&F_RGB)
443 int colour = *(int*)settings[i].setting;
444 snprintf(value,MAX_PATH,"%02x%02x%02x",
445 (int)RGB_UNPACK_RED(colour),
446 (int)RGB_UNPACK_GREEN(colour),
447 (int)RGB_UNPACK_BLUE(colour));
449 else
450 #endif
451 if (settings[i].cfg_vals == NULL)
453 snprintf(value,MAX_PATH,"%d",*(int*)settings[i].setting);
455 else
457 cfg_int_to_string(i, *(int*)settings[i].setting,
458 value, MAX_PATH);
460 break;
461 case F_T_BOOL:
462 cfg_int_to_string(i,
463 *(bool*)settings[i].setting==false?0:1, value, MAX_PATH);
464 break;
465 case F_T_CHARPTR:
466 case F_T_UCHARPTR:
467 if (((char*)settings[i].setting)[0] == '\0')
468 break;
469 if (settings[i].filename_setting->prefix)
471 snprintf(value,MAX_PATH,"%s%s%s",
472 settings[i].filename_setting->prefix,
473 (char*)settings[i].setting,
474 settings[i].filename_setting->suffix);
476 else strncpy(value,(char*)settings[i].setting,
477 settings[i].filename_setting->max_len);
478 break;
479 } /* switch () */
480 if (value[0])
481 fdprintf(fd,"%s: %s\r\n",settings[i].cfg_name,value);
482 } /* for(...) */
483 close(fd);
484 return true;
486 #ifndef HAVE_RTC_RAM
487 static bool flush_global_status_callback(void)
489 return write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE);
491 #endif
492 static bool flush_config_block_callback(void)
494 bool r1, r2;
495 r1 = write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE);
496 r2 = settings_write_config(CONFIGFILE, SETTINGS_SAVE_CHANGED);
497 return r1 || r2;
501 * persist all runtime user settings to disk or RTC RAM
503 static void update_runtime(void)
505 int elapsed_secs;
507 elapsed_secs = (current_tick - lasttime) / HZ;
508 global_status.runtime += elapsed_secs;
509 lasttime += (elapsed_secs * HZ);
511 if ( global_status.runtime > global_status.topruntime )
512 global_status.topruntime = global_status.runtime;
515 void status_save( void )
517 update_runtime();
518 #ifdef HAVE_RTC_RAM
519 /* this will be done in the ata_callback if
520 target doesnt have rtc ram */
521 write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE);
522 #else
523 register_ata_idle_func(flush_global_status_callback);
524 #endif
527 int settings_save( void )
529 update_runtime();
530 #ifdef HAVE_RTC_RAM
531 /* this will be done in the ata_callback if
532 target doesnt have rtc ram */
533 write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE);
534 #endif
535 if(!register_ata_idle_func(flush_config_block_callback))
537 int i;
538 FOR_NB_SCREENS(i)
540 screens[i].clear_display();
541 #ifdef HAVE_LCD_CHARCELLS
542 screens[i].puts(0, 0, str(LANG_SETTINGS_SAVE_PLAYER));
543 screens[i].puts(0, 1, str(LANG_SETTINGS_BATTERY_PLAYER));
544 #else
545 screens[i].puts(4, 2, str(LANG_SETTINGS_SAVE_RECORDER));
546 screens[i].puts(2, 4, str(LANG_SETTINGS_BATTERY_RECORDER));
547 screens[i].update();
548 #endif
550 sleep(HZ*2);
551 return -1;
553 return 0;
555 bool settings_save_config(int options)
557 char filename[MAX_PATH];
558 char *folder;
559 switch (options)
561 case SETTINGS_SAVE_THEME:
562 folder = THEME_DIR;
563 break;
564 #ifdef HAVE_RECORDING
565 case SETTINGS_SAVE_RECPRESETS:
566 folder = RECPRESETS_DIR;
567 break;
568 #endif
569 default:
570 folder = ROCKBOX_DIR;
572 create_numbered_filename(filename, folder, "config", ".cfg", 2
573 IF_CNFN_NUM_(, NULL));
575 /* allow user to modify filename */
576 while (true) {
577 if (!kbd_input(filename, sizeof filename)) {
578 break;
580 else {
581 gui_syncsplash(HZ, str(LANG_MENU_SETTING_CANCEL));
582 return false;
586 if (settings_write_config(filename, options))
587 gui_syncsplash(HZ, str(LANG_SETTINGS_SAVED));
588 else
589 gui_syncsplash(HZ, str(LANG_FAILED));
590 return true;
593 /** Apply and Reset settings **/
596 #ifdef HAVE_LCD_BITMAP
598 * Applies the range infos stored in global_settings to
599 * the peak meter.
601 void settings_apply_pm_range(void)
603 int pm_min, pm_max;
605 /* depending on the scale mode (dBfs or percent) the values
606 of global_settings.peak_meter_dbfs have different meanings */
607 if (global_settings.peak_meter_dbfs)
609 /* convert to dBfs * 100 */
610 pm_min = -(((int)global_settings.peak_meter_min) * 100);
611 pm_max = -(((int)global_settings.peak_meter_max) * 100);
613 else
615 /* percent is stored directly -> no conversion */
616 pm_min = global_settings.peak_meter_min;
617 pm_max = global_settings.peak_meter_max;
620 /* apply the range */
621 peak_meter_init_range(global_settings.peak_meter_dbfs, pm_min, pm_max);
623 #endif /* HAVE_LCD_BITMAP */
625 void sound_settings_apply(void)
627 #if CONFIG_CODEC == SWCODEC
628 sound_set_dsp_callback(dsp_callback);
629 #endif
630 sound_set(SOUND_BASS, global_settings.bass);
631 sound_set(SOUND_TREBLE, global_settings.treble);
632 sound_set(SOUND_BALANCE, global_settings.balance);
633 sound_set(SOUND_VOLUME, global_settings.volume);
634 sound_set(SOUND_CHANNELS, global_settings.channel_config);
635 sound_set(SOUND_STEREO_WIDTH, global_settings.stereo_width);
636 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
637 sound_set(SOUND_LOUDNESS, global_settings.loudness);
638 sound_set(SOUND_AVC, global_settings.avc);
639 sound_set(SOUND_MDB_STRENGTH, global_settings.mdb_strength);
640 sound_set(SOUND_MDB_HARMONICS, global_settings.mdb_harmonics);
641 sound_set(SOUND_MDB_CENTER, global_settings.mdb_center);
642 sound_set(SOUND_MDB_SHAPE, global_settings.mdb_shape);
643 sound_set(SOUND_MDB_ENABLE, global_settings.mdb_enable);
644 sound_set(SOUND_SUPERBASS, global_settings.superbass);
645 #endif
647 #ifdef HAVE_USB_POWER
648 #if CONFIG_CHARGING
649 usb_charging_enable(global_settings.usb_charging);
650 #endif
651 #endif
654 void settings_apply(void)
656 char buf[64];
657 #if CONFIG_CODEC == SWCODEC
658 int i;
659 #endif
661 DEBUGF( "settings_apply()\n" );
662 sound_settings_apply();
664 audio_set_buffer_margin(global_settings.buffer_margin);
666 #ifdef HAVE_LCD_CONTRAST
667 lcd_set_contrast(global_settings.contrast);
668 #endif
669 lcd_scroll_speed(global_settings.scroll_speed);
670 #ifdef HAVE_REMOTE_LCD
671 lcd_remote_set_contrast(global_settings.remote_contrast);
672 lcd_remote_set_invert_display(global_settings.remote_invert);
673 lcd_remote_set_flip(global_settings.remote_flip_display);
674 lcd_remote_scroll_speed(global_settings.remote_scroll_speed);
675 lcd_remote_scroll_step(global_settings.remote_scroll_step);
676 lcd_remote_scroll_delay(global_settings.remote_scroll_delay);
677 lcd_remote_bidir_scroll(global_settings.remote_bidir_limit);
678 #ifdef HAVE_REMOTE_LCD_TICKING
679 lcd_remote_emireduce(global_settings.remote_reduce_ticking);
680 #endif
681 remote_backlight_set_timeout(global_settings.remote_backlight_timeout);
682 #if CONFIG_CHARGING
683 remote_backlight_set_timeout_plugged(global_settings.remote_backlight_timeout_plugged);
684 #endif
685 #ifdef HAS_REMOTE_BUTTON_HOLD
686 remote_backlight_set_on_button_hold(global_settings.remote_backlight_on_button_hold);
687 #endif
688 #endif /* HAVE_REMOTE_LCD */
689 #ifdef HAVE_BACKLIGHT_BRIGHTNESS
690 backlight_set_brightness(global_settings.brightness);
691 #endif
692 #ifdef HAVE_BACKLIGHT
693 backlight_set_timeout(global_settings.backlight_timeout);
694 #if CONFIG_CHARGING
695 backlight_set_timeout_plugged(global_settings.backlight_timeout_plugged);
696 #endif
697 #if defined(HAVE_BACKLIGHT_PWM_FADING) && !defined(SIMULATOR)
698 backlight_set_fade_in(global_settings.backlight_fade_in);
699 backlight_set_fade_out(global_settings.backlight_fade_out);
700 #endif
701 #endif
702 #ifdef HAVE_BUTTONLIGHT_BRIGHTNESS
703 buttonlight_set_brightness(global_settings.buttonlight_brightness);
704 #endif
705 #ifdef HAVE_BUTTON_LIGHT
706 button_backlight_set_timeout(global_settings.button_light_timeout);
707 #endif
708 ata_spindown(global_settings.disk_spindown);
709 #if (CONFIG_CODEC == MAS3507D) && !defined(SIMULATOR)
710 dac_line_in(global_settings.line_in);
711 #endif
712 mpeg_id3_options(global_settings.id3_v1_first);
714 set_poweroff_timeout(global_settings.poweroff);
716 set_battery_capacity(global_settings.battery_capacity);
717 #if BATTERY_TYPES_COUNT > 1
718 set_battery_type(global_settings.battery_type);
719 #endif
721 #ifdef HAVE_LCD_BITMAP
722 lcd_set_invert_display(global_settings.invert);
723 lcd_set_flip(global_settings.flip_display);
724 button_set_flip(global_settings.flip_display);
725 lcd_update(); /* refresh after flipping the screen */
726 settings_apply_pm_range();
727 peak_meter_init_times(
728 global_settings.peak_meter_release, global_settings.peak_meter_hold,
729 global_settings.peak_meter_clip_hold);
730 #endif
732 #if LCD_DEPTH > 1
733 unload_wps_backdrop();
734 #endif
735 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
736 unload_remote_wps_backdrop();
737 #endif
738 if ( global_settings.wps_file[0] &&
739 global_settings.wps_file[0] != 0xff ) {
740 snprintf(buf, sizeof buf, WPS_DIR "/%s.wps",
741 global_settings.wps_file);
742 wps_data_load(gui_wps[0].data, buf, true);
744 else
746 wps_data_init(gui_wps[0].data);
747 #ifdef HAVE_REMOTE_LCD
748 gui_wps[0].data->remote_wps = false;
749 #endif
752 #if LCD_DEPTH > 1
753 if ( global_settings.backdrop_file[0] &&
754 global_settings.backdrop_file[0] != 0xff ) {
755 snprintf(buf, sizeof buf, BACKDROP_DIR "/%s.bmp",
756 global_settings.backdrop_file);
757 load_main_backdrop(buf);
758 } else {
759 unload_main_backdrop();
761 show_main_backdrop();
762 #endif
763 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
764 show_remote_main_backdrop();
765 #endif
767 #ifdef HAVE_LCD_COLOR
768 screens[SCREEN_MAIN].set_foreground(global_settings.fg_color);
769 screens[SCREEN_MAIN].set_background(global_settings.bg_color);
770 #endif
772 #if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1)
773 if ( global_settings.rwps_file[0]) {
774 snprintf(buf, sizeof buf, WPS_DIR "/%s.rwps",
775 global_settings.rwps_file);
776 wps_data_load(gui_wps[1].data, buf, true);
778 else
780 wps_data_init(gui_wps[1].data);
781 gui_wps[1].data->remote_wps = true;
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 /* Configure software equalizer, hardware eq is handled in audio_init() */
831 dsp_set_eq(global_settings.eq_enabled);
832 dsp_set_eq_precut(global_settings.eq_precut);
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_SPDIF_POWER
841 spdif_power_enable(global_settings.spdif_enable);
842 #endif
844 #ifdef HAVE_BACKLIGHT
845 set_backlight_filter_keypress(global_settings.bl_filter_first_keypress);
846 #ifdef HAVE_REMOTE_LCD
847 set_remote_backlight_filter_keypress(global_settings.remote_bl_filter_first_keypress);
848 #endif
849 #ifdef HAS_BUTTON_HOLD
850 backlight_set_on_button_hold(global_settings.backlight_on_button_hold);
851 #endif
852 #ifdef HAVE_LCD_SLEEP
853 lcd_set_sleep_after_backlight_off(global_settings.lcd_sleep_after_backlight_off);
854 #endif
855 #endif /* HAVE_BACKLIGHT */
857 /* This should stay last */
858 #if defined(HAVE_RECORDING) && CONFIG_CODEC == SWCODEC
859 enc_global_settings_apply();
860 #endif
861 /* load the icon set */
862 icons_init();
864 #ifdef HAVE_LCD_COLOR
865 if (global_settings.colors_file)
866 read_color_theme_file();
867 #endif
875 * reset all settings to their default value
877 void settings_reset(void) {
879 int i;
880 DEBUGF( "settings_reset()\n" );
882 for(i=0; i<nb_settings; i++)
884 switch (settings[i].flags&F_T_MASK)
886 case F_T_INT:
887 case F_T_UINT:
888 if (settings[i].flags&F_DEF_ISFUNC)
889 *(int*)settings[i].setting = settings[i].default_val.func();
890 else if (settings[i].flags&F_T_SOUND)
891 *(int*)settings[i].setting =
892 sound_default(settings[i].sound_setting->setting);
893 else *(int*)settings[i].setting = settings[i].default_val.int_;
894 break;
895 case F_T_BOOL:
896 *(bool*)settings[i].setting = settings[i].default_val.bool_;
897 break;
898 case F_T_CHARPTR:
899 case F_T_UCHARPTR:
900 strncpy((char*)settings[i].setting,
901 settings[i].default_val.charptr,MAX_FILENAME);
902 break;
904 } /* for(...) */
905 #if defined (HAVE_RECORDING) && CONFIG_CODEC == SWCODEC
906 enc_global_settings_reset();
907 #endif
910 /** Changing setting values **/
911 const struct settings_list* find_setting(void* variable, int *id)
913 int i;
914 for(i=0;i<nb_settings;i++)
916 if (settings[i].setting == variable)
918 if (id)
919 *id = i;
920 return &settings[i];
923 return NULL;
926 void talk_setting(void *global_settings_variable)
928 const struct settings_list *setting;
929 if (!talk_menus_enabled())
930 return;
931 setting = find_setting(global_settings_variable, NULL);
932 if (setting == NULL)
933 return;
934 if (setting->lang_id)
935 talk_id(setting->lang_id,false);
938 static int selected_setting; /* Used by the callback */
940 static void dec_sound_formatter(char *buffer, int buffer_size,
941 int val, const char *unit)
943 val = sound_val2phys(selected_setting, val);
944 char sign = ' ';
945 if(val < 0)
947 sign = '-';
948 val = abs(val);
950 int integer = val / 10;
951 int dec = val % 10;
952 snprintf(buffer, buffer_size, "%c%d.%d %s", sign, integer, dec, unit);
955 bool set_sound(const unsigned char * string,
956 int* variable,
957 int setting)
959 int talkunit = UNIT_INT;
960 const char* unit = sound_unit(setting);
961 int numdec = sound_numdecimals(setting);
962 int steps = sound_steps(setting);
963 int min = sound_min(setting);
964 int max = sound_max(setting);
965 sound_set_type* sound_callback = sound_get_fn(setting);
966 if (*unit == 'd') /* crude reconstruction */
967 talkunit = UNIT_DB;
968 else if (*unit == '%')
969 talkunit = UNIT_PERCENT;
970 else if (*unit == 'H')
971 talkunit = UNIT_HERTZ;
972 if (!numdec)
973 return set_int(string, unit, talkunit, variable, sound_callback,
974 steps, min, max, NULL );
975 else
976 {/* Decimal number */
977 selected_setting=setting;
978 return set_int(string, unit, talkunit, variable, sound_callback,
979 steps, min, max, &dec_sound_formatter );
983 bool set_bool(const char* string, bool* variable )
985 return set_bool_options(string, variable,
986 (char *)STR(LANG_SET_BOOL_YES),
987 (char *)STR(LANG_SET_BOOL_NO),
988 NULL);
991 /* wrapper to convert from int param to bool param in set_option */
992 static void (*boolfunction)(bool);
993 static void bool_funcwrapper(int value)
995 if (value)
996 boolfunction(true);
997 else
998 boolfunction(false);
1001 bool set_bool_options(const char* string, bool* variable,
1002 const char* yes_str, int yes_voice,
1003 const char* no_str, int no_voice,
1004 void (*function)(bool))
1006 struct opt_items names[] = {
1007 {(unsigned char *)no_str, no_voice},
1008 {(unsigned char *)yes_str, yes_voice}
1010 bool result;
1012 boolfunction = function;
1013 result = set_option(string, variable, BOOL, names, 2,
1014 function ? bool_funcwrapper : NULL);
1015 return result;
1018 static void talk_unit(int unit, int value, long (*get_talk_id)(int value))
1020 if (talk_menus_enabled())
1022 if (get_talk_id)
1024 talk_id(get_talk_id(value),false);
1026 else if (unit < UNIT_LAST)
1027 { /* use the available unit definition */
1028 talk_value(value, unit, false);
1030 else
1031 { /* say the number, followed by an arbitrary voice ID */
1032 talk_number(value, false);
1033 talk_id(unit, true);
1038 struct value_setting_data {
1039 enum optiontype type;
1040 /* used for "value" settings.. */
1041 int max;
1042 int step;
1043 int voice_unit;
1044 const char * unit;
1045 void (*formatter)(char* dest, int dest_length,
1046 int value, const char* unit);
1047 long (*get_talk_id)(int value);
1048 /* used for BOOL and "choice" settings */
1049 struct opt_items* options;
1052 static char * value_setting_get_name_cb(int selected_item,void * data, char *buffer)
1054 struct value_setting_data* cb_data =
1055 (struct value_setting_data*)data;
1056 if (cb_data->type == INT && !cb_data->options)
1058 int item = cb_data->max -(selected_item*cb_data->step);
1059 if (cb_data->formatter)
1060 cb_data->formatter(buffer, MAX_PATH,item,cb_data->unit);
1061 else
1062 snprintf(buffer, MAX_PATH,"%d %s",item,cb_data->unit);
1064 else strcpy(buffer,P2STR(cb_data->options[selected_item].string));
1065 return buffer;
1067 #define type_fromvoidptr(type, value) \
1068 (type == INT)? \
1069 (int)(*(int*)(value)) \
1071 (bool)(*(bool*)(value))
1072 static bool do_set_setting(const unsigned char* string, void *variable,
1073 int nb_items,int selected,
1074 struct value_setting_data *cb_data,
1075 void (*function)(int))
1077 int action;
1078 bool done = false;
1079 struct gui_synclist lists;
1080 int oldvalue;
1081 bool allow_wrap = true;
1083 if (cb_data->type == INT)
1085 oldvalue = *(int*)variable;
1086 if (variable == &global_settings.volume)
1087 allow_wrap = false;
1089 else oldvalue = *(bool*)variable;
1091 gui_synclist_init(&lists,value_setting_get_name_cb,(void*)cb_data,false,1);
1092 gui_synclist_set_title(&lists, (char*)string,Icon_Questionmark);
1093 gui_synclist_set_icon_callback(&lists,NULL);
1094 gui_synclist_set_nb_items(&lists,nb_items);
1095 gui_synclist_limit_scroll(&lists,true);
1096 gui_synclist_select_item(&lists, selected);
1098 if (talk_menus_enabled())
1100 if (cb_data->type == INT && !cb_data->options)
1101 talk_unit(cb_data->voice_unit, *(int*)variable, cb_data->get_talk_id);
1102 else
1103 talk_id(cb_data->options[selected].voice_id, false);
1106 gui_synclist_draw(&lists);
1107 action_signalscreenchange();
1108 while (!done)
1111 action = get_action(CONTEXT_LIST,TIMEOUT_BLOCK);
1112 if (action == ACTION_NONE)
1113 continue;
1114 if (gui_synclist_do_button(&lists,action,
1115 allow_wrap?LIST_WRAP_UNLESS_HELD:LIST_WRAP_OFF))
1117 if (talk_menus_enabled())
1119 int value;
1120 if (cb_data->type == INT && !cb_data->options)
1122 value = cb_data->max -
1123 gui_synclist_get_sel_pos(&lists)*cb_data->step;
1124 talk_unit(cb_data->voice_unit, value, cb_data->get_talk_id);
1126 else
1128 value = gui_synclist_get_sel_pos(&lists);
1129 talk_id(cb_data->options[value].voice_id, false);
1132 if (cb_data->type == INT && !cb_data->options)
1133 *(int*)variable = cb_data->max -
1134 gui_synclist_get_sel_pos(&lists)*cb_data->step;
1135 else if (cb_data->type == BOOL)
1136 *(bool*)variable = gui_synclist_get_sel_pos(&lists) ? true : false;
1137 else *(int*)variable = gui_synclist_get_sel_pos(&lists);
1139 else if (action == ACTION_STD_CANCEL)
1141 if (cb_data->type == INT)
1143 if (*(int*)variable != oldvalue)
1145 gui_syncsplash(HZ/2, str(LANG_MENU_SETTING_CANCEL));
1146 *(int*)variable = oldvalue;
1149 else
1151 if (*(bool*)variable != (bool)oldvalue)
1153 gui_syncsplash(HZ/2, str(LANG_MENU_SETTING_CANCEL));
1154 *(bool*)variable = (bool)oldvalue;
1157 done = true;
1159 else if (action == ACTION_STD_OK)
1161 done = true;
1163 else if(default_event_handler(action) == SYS_USB_CONNECTED)
1164 return true;
1165 gui_syncstatusbar_draw(&statusbars, false);
1166 if ( function )
1167 function(type_fromvoidptr(cb_data->type,variable));
1169 if (cb_data->type == INT)
1171 if (oldvalue != *(int*)variable)
1172 settings_save();
1174 else if (oldvalue != *(bool*)variable)
1175 settings_save();
1177 action_signalscreenchange();
1178 return false;
1180 static const char *unit_strings[] =
1182 [UNIT_INT]
1183 = "",
1184 [UNIT_MS]
1185 = "ms",
1186 [UNIT_SEC]
1187 = "s",
1188 [UNIT_MIN]
1189 = "min",
1190 [UNIT_HOUR]
1191 = "hr",
1192 [UNIT_KHZ]
1193 = "KHz",
1194 [UNIT_DB]
1195 = "dB",
1196 [UNIT_PERCENT]
1197 = "%",
1198 [UNIT_MAH]
1199 = "mAh",
1200 [UNIT_PIXEL]
1201 = "px",
1202 [UNIT_PER_SEC]
1203 = "per sec",
1204 [UNIT_HERTZ]
1205 = "Hz",
1206 [UNIT_MB]
1207 = "MB",
1208 [UNIT_KBIT]
1209 = "kb/s",
1211 bool set_int_ex(const unsigned char* string,
1212 const char* unit,
1213 int voice_unit,
1214 int* variable,
1215 void (*function)(int),
1216 int step,
1217 int min,
1218 int max,
1219 void (*formatter)(char*, int, int, const char*),
1220 long (*get_talk_id)(int))
1222 int count = (max-min)/step + 1;
1223 #if CONFIG_KEYPAD != PLAYER_PAD
1224 struct value_setting_data data = {
1225 INT,max, step, voice_unit,unit,formatter,get_talk_id,NULL };
1226 if (voice_unit < UNIT_LAST)
1227 data.unit = unit_strings[voice_unit];
1228 else
1229 data.unit = str(voice_unit);
1230 return do_set_setting(string,variable,count,
1231 (max-*variable)/step, &data,function);
1232 #else
1233 struct value_setting_data data = {
1234 INT,min, -step, voice_unit,unit,formatter,get_talk_id,NULL };
1235 if (voice_unit < UNIT_LAST)
1236 data.unit = unit_strings[voice_unit];
1237 else
1238 data.unit = str(voice_unit);
1239 return do_set_setting(string,variable,count,
1240 (*variable-min)/step, &data,function);
1241 #endif
1243 bool set_int(const unsigned char* string,
1244 const char* unit,
1245 int voice_unit,
1246 int* variable,
1247 void (*function)(int),
1248 int step,
1249 int min,
1250 int max,
1251 void (*formatter)(char*, int, int, const char*) )
1253 return set_int_ex(string, unit, voice_unit, variable, function,
1254 step, min, max, formatter, NULL);
1256 /* NOTE: the 'type' parameter specifies the actual type of the variable
1257 that 'variable' points to. not the value within. Only variables with
1258 type 'bool' should use parameter BOOL.
1260 The type separation is necessary since int and bool are fundamentally
1261 different and bit-incompatible types and can not share the same access
1262 code. */
1263 bool set_option(const char* string, void* variable, enum optiontype type,
1264 const struct opt_items* options, int numoptions, void (*function)(int))
1266 struct value_setting_data data = {
1267 type,0, 0, 0,NULL,NULL,NULL,(struct opt_items*)options };
1268 int selected;
1269 if (type == BOOL)
1270 selected = *(bool*)variable ? 1 : 0;
1271 else selected = *(int*)variable;
1272 return do_set_setting(string,variable,numoptions,
1273 selected, &data,function);
1276 /** extra stuff which is probably misplaced **/
1278 void set_file(char* filename, char* setting, int maxlen)
1280 char* fptr = strrchr(filename,'/');
1281 int len;
1282 int extlen = 0;
1283 char* ptr;
1285 if (!fptr)
1286 return;
1288 *fptr = 0;
1289 fptr++;
1291 len = strlen(fptr);
1292 ptr = fptr + len;
1293 while ((*ptr != '.') && (ptr != fptr)) {
1294 extlen++;
1295 ptr--;
1297 if(ptr == fptr) extlen = 0;
1299 if (strncasecmp(ROCKBOX_DIR, filename ,strlen(ROCKBOX_DIR)) ||
1300 (len-extlen > maxlen))
1301 return;
1303 strncpy(setting, fptr, len-extlen);
1304 setting[len-extlen]=0;
1306 settings_save();
1309 #ifdef HAVE_RECORDING
1310 /* This array holds the record timer interval lengths, in seconds */
1311 static const unsigned long rec_timer_seconds[] =
1313 0, /* 0 means OFF */
1314 5*60, /* 00:05 */
1315 10*60, /* 00:10 */
1316 15*60, /* 00:15 */
1317 30*60, /* 00:30 */
1318 60*60, /* 01:00 */
1319 74*60, /* 74:00 */
1320 80*60, /* 80:00 */
1321 2*60*60, /* 02:00 */
1322 4*60*60, /* 04:00 */
1323 6*60*60, /* 06:00 */
1324 8*60*60, /* 08:00 */
1325 10L*60*60, /* 10:00 */
1326 12L*60*60, /* 12:00 */
1327 18L*60*60, /* 18:00 */
1328 24L*60*60 /* 24:00 */
1331 unsigned int rec_timesplit_seconds(void)
1333 return rec_timer_seconds[global_settings.rec_timesplit];
1336 /* This array holds the record size interval lengths, in bytes */
1337 static const unsigned long rec_size_bytes[] =
1339 0, /* 0 means OFF */
1340 5*1024*1024, /* 5MB */
1341 10*1024*1024, /* 10MB */
1342 15*1024*1024, /* 15MB */
1343 32*1024*1024, /* 32MB */
1344 64*1024*1024, /* 64MB */
1345 75*1024*1024, /* 75MB */
1346 100*1024*1024, /* 100MB */
1347 128*1024*1024, /* 128MB */
1348 256*1024*1024, /* 256MB */
1349 512*1024*1024, /* 512MB */
1350 650*1024*1024, /* 650MB */
1351 700*1024*1024, /* 700MB */
1352 1024*1024*1024, /* 1GB */
1353 1536*1024*1024, /* 1.5GB */
1354 1792*1024*1024, /* 1.75GB */
1357 unsigned long rec_sizesplit_bytes(void)
1359 return rec_size_bytes[global_settings.rec_sizesplit];
1362 * Time strings used for the trigger durations.
1363 * Keep synchronous to trigger_times in settings_apply_trigger
1365 const char * const trig_durations[TRIG_DURATION_COUNT] =
1367 "0s", "1s", "2s", "5s",
1368 "10s", "15s", "20s", "25s", "30s",
1369 "1min", "2min", "5min", "10min"
1372 void settings_apply_trigger(void)
1374 /* Keep synchronous to trig_durations and trig_durations_conf*/
1375 static const long trigger_times[TRIG_DURATION_COUNT] = {
1376 0, HZ, 2*HZ, 5*HZ,
1377 10*HZ, 15*HZ, 20*HZ, 25*HZ, 30*HZ,
1378 60*HZ, 2*60*HZ, 5*60*HZ, 10*60*HZ
1381 peak_meter_define_trigger(
1382 global_settings.rec_start_thres,
1383 trigger_times[global_settings.rec_start_duration],
1384 MIN(trigger_times[global_settings.rec_start_duration] / 2, 2*HZ),
1385 global_settings.rec_stop_thres,
1386 trigger_times[global_settings.rec_stop_postrec],
1387 trigger_times[global_settings.rec_stop_gap]
1390 #endif