1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 ****************************************************************************/
31 #include "backlight.h"
38 #include "ata_idle_notify.h"
45 #ifdef HAVE_LCD_BITMAP
48 #include "peakmeter.h"
53 #include "powermgmt.h"
58 #include "rbunicode.h"
60 #include "statusbar.h"
63 #include "settings_list.h"
65 #if (LCD_DEPTH > 1) || (defined(HAVE_LCD_REMOTE) && (LCD_REMOTE_DEPTH > 1))
73 #if CONFIG_CODEC == MAS3507D
74 void dac_line_in(bool enable
);
76 struct user_settings global_settings
;
77 struct system_status global_status
;
80 const char rec_base_directory
[] = REC_BASE_DIR
;
82 #if CONFIG_CODEC == SWCODEC
84 #include "pcm_playback.h"
87 #include "enc_config.h"
89 #endif /* CONFIG_CODEC == SWCODEC */
91 #define NVRAM_BLOCK_SIZE 44
93 #ifdef HAVE_LCD_BITMAP
99 #ifdef HAVE_REMOTE_LCD
100 #include "lcd-remote.h"
105 /** NVRAM stuff, if the target doesnt have NVRAM it is saved in ROCKBOX_DIR /nvram.bin **/
106 /* NVRAM is set out as
110 [3] stored variable count
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;
123 int fd
= open(NVRAM_FILE
,O_RDONLY
);
126 memset(buf
,0,max_len
);
127 if (read(fd
,buf
,max_len
) < 8) /* min is 8 bytes,magic, ver, vars, crc32 */
131 memset(buf
,0,max_len
);
133 for (i
=0; i
< max_len
; i
++ )
134 buf
[i
] = rtc_read(0x14+i
);
136 /* check magic, version */
137 if ((buf
[0] != 'R') || (buf
[1] != 'b')
138 || (buf
[2] != NVRAM_CONFIG_VERSION
))
141 crc32
= crc_32(&buf
[NVRAM_DATA_START
],
142 max_len
-NVRAM_DATA_START
-1,0xffffffff);
143 if (memcmp(&crc32
,&buf
[4],4))
145 /* all good, so read in the settings */
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
;
154 memcpy(settings
[i
].setting
,&buf
[buf_pos
],nvram_bytes
);
155 buf_pos
+= nvram_bytes
;
161 static bool write_nvram_data(char* buf
, int max_len
)
163 unsigned crc32
= 0xffffffff;
164 int i
= 0, buf_pos
= 0;
169 memset(buf
,0,max_len
);
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
;
180 memcpy(&buf
[buf_pos
],settings
[i
].setting
,nvram_bytes
);
181 buf_pos
+= nvram_bytes
;
185 /* count and crc32 */
187 crc32
= crc_32(&buf
[NVRAM_DATA_START
],
188 max_len
-NVRAM_DATA_START
-1,0xffffffff);
189 memcpy(&buf
[4],&crc32
,4);
191 fd
= open(NVRAM_FILE
,O_CREAT
|O_TRUNC
|O_WRONLY
);
194 int len
= write(fd
,buf
,max_len
);
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
]);
206 DEBUGF( "save_config_buffer: rtc_write failed at addr 0x%02x: %d\n",
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
)
241 int red
, green
, blue
;
243 if (strlen(hex
) == 6) {
244 for (i
=0; i
< 6; i
++ ) {
245 if (!isxdigit(hex
[i
])) {
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
);
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
;
271 end
= strchr(start
, ',');
274 if (!strcmp(str
, start
))
281 strncpy(temp
, start
, end
-start
);
282 temp
[end
-start
] = '\0';
283 if (!strcmp(str
, temp
))
294 bool settings_load_config(const char* file
, bool apply
)
301 fd
= open(file
, O_RDONLY
);
305 while (read_line(fd
, line
, sizeof line
) > 0)
307 if (!settings_parseline(line
, &name
, &value
))
309 for(i
=0; i
<nb_settings
; i
++)
311 if (settings
[i
].cfg_name
== NULL
)
313 if (!strcasecmp(name
,settings
[i
].cfg_name
))
315 switch (settings
[i
].flags
&F_T_MASK
)
319 #ifdef HAVE_LCD_COLOR
320 if (settings
[i
].flags
&F_RGB
)
321 *(int*)settings
[i
].setting
= hex_to_rgb(value
);
324 if (settings
[i
].cfg_vals
== NULL
)
326 *(int*)settings
[i
].setting
= atoi(value
);
330 cfg_string_to_int(i
,(int*)settings
[i
].setting
,value
);
336 if (cfg_string_to_int(i
,&temp
,value
))
337 *(bool*)settings
[i
].setting
= (temp
==0?false:true);
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
,
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
);
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';
369 } /* if (!strcmp(name,settings[i].cfg_name)) */
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
;
389 start
= strchr(start
,',');
395 end
= strchr(start
,',');
397 strncpy(buf
, start
, buf_len
);
400 int len
= (buf_len
> (end
-start
))? end
-start
: buf_len
;
401 strncpy(buf
, start
, len
);
406 static bool is_changed(int setting_id
)
408 const struct settings_list
*setting
= &settings
[setting_id
];
409 switch (setting
->flags
&F_T_MASK
)
413 if (setting
->flags
&F_DEF_ISFUNC
)
415 if (*(int*)setting
->setting
== setting
->default_val
.func())
418 else if (setting
->flags
&F_T_SOUND
)
420 if (*(int*)setting
->setting
==
421 sound_default(setting
->sound_setting
->setting
))
424 else if (*(int*)setting
->setting
== setting
->default_val
.int_
)
428 if (*(bool*)setting
->setting
== setting
->default_val
.bool_
)
433 if (!strcmp((char*)setting
->setting
, setting
->default_val
.charptr
))
440 static bool settings_write_config(char* filename
, int options
)
444 char value
[MAX_PATH
];
445 fd
= open(filename
,O_CREAT
|O_TRUNC
|O_WRONLY
);
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
)
456 if ((options
== SETTINGS_SAVE_CHANGED
) &&
459 else if ((options
== SETTINGS_SAVE_THEME
) &&
460 ((settings
[i
].flags
&F_THEMESETTING
) == 0))
463 switch (settings
[i
].flags
&F_T_MASK
)
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
));
478 if (settings
[i
].cfg_vals
== NULL
)
480 snprintf(value
,MAX_PATH
,"%d",*(int*)settings
[i
].setting
);
484 cfg_int_to_string(i
, *(int*)settings
[i
].setting
,
490 *(bool*)settings
[i
].setting
==false?0:1, value
, MAX_PATH
);
494 if (((char*)settings
[i
].setting
)[0] == '\0')
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
);
508 fdprintf(fd
,"%s: %s\r\n",settings
[i
].cfg_name
,value
);
514 static bool flush_global_status_callback(void)
516 return write_nvram_data(nvram_buffer
,NVRAM_BLOCK_SIZE
);
519 static bool flush_config_block_callback(void)
522 r1
= write_nvram_data(nvram_buffer
,NVRAM_BLOCK_SIZE
);
523 r2
= settings_write_config(CONFIGFILE
, SETTINGS_SAVE_CHANGED
);
528 * persist all runtime user settings to disk or RTC RAM
530 static void update_runtime(void)
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 )
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
);
550 register_ata_idle_func(flush_global_status_callback
);
554 int settings_save( void )
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
);
562 if(!register_ata_idle_func(flush_config_block_callback
))
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
));
572 screens
[i
].puts(4, 2, str(LANG_SETTINGS_SAVE_RECORDER
));
573 screens
[i
].puts(2, 4, str(LANG_SETTINGS_BATTERY_RECORDER
));
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 */
591 if (!kbd_input(filename
, sizeof filename
)) {
595 gui_syncsplash(HZ
, str(LANG_MENU_SETTING_CANCEL
));
600 if (settings_write_config(filename
, options
))
601 gui_syncsplash(HZ
, str(LANG_SETTINGS_SAVED
));
603 gui_syncsplash(HZ
, str(LANG_FAILED
));
607 /** Apply and Reset settings **/
610 #ifdef HAVE_LCD_BITMAP
612 * Applies the range infos stored in global_settings to
615 void settings_apply_pm_range(void)
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);
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
);
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
);
661 #ifdef HAVE_USB_POWER
663 usb_charging_enable(global_settings
.usb_charging
);
668 void settings_apply(void)
671 #if CONFIG_CODEC == SWCODEC
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
);
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
);
695 remote_backlight_set_timeout(global_settings
.remote_backlight_timeout
);
697 remote_backlight_set_timeout_plugged(global_settings
.remote_backlight_timeout_plugged
);
699 #ifdef HAS_REMOTE_BUTTON_HOLD
700 remote_backlight_set_on_button_hold(global_settings
.remote_backlight_on_button_hold
);
702 #endif /* HAVE_REMOTE_LCD */
703 #ifdef HAVE_BACKLIGHT_BRIGHTNESS
704 backlight_set_brightness(global_settings
.brightness
);
706 #ifdef HAVE_BACKLIGHT
707 backlight_set_timeout(global_settings
.backlight_timeout
);
709 backlight_set_timeout_plugged(global_settings
.backlight_timeout_plugged
);
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
);
716 #ifdef HAVE_BUTTONLIGHT_BRIGHTNESS
717 buttonlight_set_brightness(global_settings
.buttonlight_brightness
);
719 #ifdef HAVE_BUTTON_LIGHT
720 button_backlight_set_timeout(global_settings
.button_light_timeout
);
722 ata_spindown(global_settings
.disk_spindown
);
723 #if (CONFIG_CODEC == MAS3507D) && !defined(SIMULATOR)
724 dac_line_in(global_settings
.line_in
);
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
);
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
);
747 unload_wps_backdrop();
749 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
750 unload_remote_wps_backdrop();
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);
760 wps_data_init(gui_wps
[0].data
);
761 #ifdef HAVE_REMOTE_LCD
762 gui_wps
[0].data
->remote_wps
= false;
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
);
773 unload_main_backdrop();
775 show_main_backdrop();
777 #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1
778 show_remote_main_backdrop();
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
);
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);
794 wps_data_init(gui_wps
[1].data
);
795 gui_wps
[1].data
->remote_wps
= true;
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
);
808 if ( global_settings
.kbd_file
[0]) {
809 snprintf(buf
, sizeof buf
, ROCKBOX_DIR
"/%s.kbd",
810 global_settings
.kbd_file
);
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
);
820 lcd_jump_scroll(global_settings
.jump_scroll
);
821 lcd_jump_scroll_delay(global_settings
.jump_scroll_delay
);
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
);
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
++) {
851 dsp_dither_enable(global_settings
.dithering_enabled
);
854 #ifdef HAVE_SPDIF_POWER
855 spdif_power_enable(global_settings
.spdif_enable
);
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
);
863 #ifdef HAS_BUTTON_HOLD
864 backlight_set_on_button_hold(global_settings
.backlight_on_button_hold
);
866 #ifdef HAVE_LCD_SLEEP
867 lcd_set_sleep_after_backlight_off(global_settings
.lcd_sleep_after_backlight_off
);
869 #endif /* HAVE_BACKLIGHT */
871 /* This should stay last */
872 #if defined(HAVE_RECORDING) && CONFIG_CODEC == SWCODEC
873 enc_global_settings_apply();
875 /* load the icon set */
884 * reset all settings to their default value
886 void settings_reset(void) {
889 DEBUGF( "settings_reset()\n" );
891 for(i
=0; i
<nb_settings
; i
++)
893 switch (settings
[i
].flags
&F_T_MASK
)
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_
;
905 *(bool*)settings
[i
].setting
= settings
[i
].default_val
.bool_
;
909 strncpy((char*)settings
[i
].setting
,
910 settings
[i
].default_val
.charptr
,MAX_FILENAME
);
914 #if defined (HAVE_RECORDING) && CONFIG_CODEC == SWCODEC
915 enc_global_settings_reset();
919 /** Changing setting values **/
920 const struct settings_list
* find_setting(void* variable
, int *id
)
923 for(i
=0;i
<nb_settings
;i
++)
925 if (settings
[i
].setting
== variable
)
935 void talk_setting(void *global_settings_variable
)
937 const struct settings_list
*setting
;
938 if (global_settings
.talk_menu
== 0)
940 setting
= find_setting(global_settings_variable
, NULL
);
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
);
959 int integer
= val
/ 10;
961 snprintf(buffer
, buffer_size
, "%c%d.%d %s", sign
, integer
, dec
, unit
);
964 bool set_sound(const unsigned char * string
,
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 */
977 else if (*unit
== '%')
978 talkunit
= UNIT_PERCENT
;
979 else if (*unit
== 'H')
980 talkunit
= UNIT_HERTZ
;
982 return set_int(string
, unit
, talkunit
, variable
, sound_callback
,
983 steps
, min
, max
, NULL
);
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
),
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
)
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
}
1021 boolfunction
= function
;
1022 result
= set_option(string
, variable
, BOOL
, names
, 2,
1023 function
? bool_funcwrapper
: NULL
);
1027 static void talk_unit(int unit
, int value
, long (*get_talk_id
)(int value
))
1029 if (global_settings
.talk_menu
)
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);
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.. */
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
);
1071 snprintf(buffer
, MAX_PATH
,"%d %s",item
,cb_data
->unit
);
1073 else strcpy(buffer
,P2STR(cb_data
->options
[selected_item
].string
));
1076 #define type_fromvoidptr(type, value) \
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))
1088 struct gui_synclist lists
;
1090 bool allow_wrap
= true;
1092 if (cb_data
->type
== INT
)
1094 oldvalue
= *(int*)variable
;
1095 if (variable
== &global_settings
.volume
)
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();
1119 action
= get_action(CONTEXT_LIST
,TIMEOUT_BLOCK
);
1120 if (action
== ACTION_NONE
)
1122 if (gui_synclist_do_button(&lists
,action
,
1123 allow_wrap
?LIST_WRAP_UNLESS_HELD
:LIST_WRAP_OFF
))
1125 if (global_settings
.talk_menu
)
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
);
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
;
1159 if (*(bool*)variable
!= (bool)oldvalue
)
1161 gui_syncsplash(HZ
/2, str(LANG_MENU_SETTING_CANCEL
));
1162 *(bool*)variable
= (bool)oldvalue
;
1167 else if (action
== ACTION_STD_OK
)
1171 else if(default_event_handler(action
) == SYS_USB_CONNECTED
)
1173 gui_syncstatusbar_draw(&statusbars
, false);
1175 function(type_fromvoidptr(cb_data
->type
,variable
));
1177 if (cb_data
->type
== INT
)
1179 if (oldvalue
!= *(int*)variable
)
1182 else if (oldvalue
!= *(bool*)variable
)
1185 action_signalscreenchange();
1188 static const char *unit_strings
[] =
1219 bool set_int_ex(const unsigned char* string
,
1223 void (*function
)(int),
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
];
1237 data
.unit
= str(voice_unit
);
1238 return do_set_setting(string
,variable
,count
,
1239 (max
-*variable
)/step
, &data
,function
);
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
];
1246 data
.unit
= str(voice_unit
);
1247 return do_set_setting(string
,variable
,count
,
1248 (*variable
-min
)/step
, &data
,function
);
1251 bool set_int(const unsigned char* string
,
1255 void (*function
)(int),
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
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
};
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
,'/');
1301 while ((*ptr
!= '.') && (ptr
!= fptr
)) {
1305 if(ptr
== fptr
) extlen
= 0;
1307 if (strncasecmp(ROCKBOX_DIR
, filename
,strlen(ROCKBOX_DIR
)) ||
1308 (len
-extlen
> maxlen
))
1311 strncpy(setting
, fptr
, len
-extlen
);
1312 setting
[len
-extlen
]=0;
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 */
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
] = {
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
]