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"
54 #include "powermgmt.h"
59 #include "rbunicode.h"
61 #include "statusbar.h"
64 #include "settings_list.h"
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 */
92 #include "menus/eq_menu.h"
95 #define NVRAM_BLOCK_SIZE 44
97 #ifdef HAVE_LCD_BITMAP
103 #ifdef HAVE_REMOTE_LCD
104 #include "lcd-remote.h"
109 /** NVRAM stuff, if the target doesnt have NVRAM it is saved in ROCKBOX_DIR /nvram.bin **/
110 /* NVRAM is set out as
114 [3] stored variable count
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;
127 int fd
= open(NVRAM_FILE
,O_RDONLY
);
130 memset(buf
,0,max_len
);
131 if (read(fd
,buf
,max_len
) < 8) /* min is 8 bytes,magic, ver, vars, crc32 */
135 memset(buf
,0,max_len
);
137 for (i
=0; i
< max_len
; i
++ )
138 buf
[i
] = rtc_read(0x14+i
);
140 /* check magic, version */
141 if ((buf
[0] != 'R') || (buf
[1] != 'b')
142 || (buf
[2] != NVRAM_CONFIG_VERSION
))
145 crc32
= crc_32(&buf
[NVRAM_DATA_START
],
146 max_len
-NVRAM_DATA_START
-1,0xffffffff);
147 if (memcmp(&crc32
,&buf
[4],4))
149 /* all good, so read in the settings */
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
;
158 memcpy(settings
[i
].setting
,&buf
[buf_pos
],nvram_bytes
);
159 buf_pos
+= nvram_bytes
;
165 static bool write_nvram_data(char* buf
, int max_len
)
167 unsigned crc32
= 0xffffffff;
168 int i
= 0, buf_pos
= 0;
173 memset(buf
,0,max_len
);
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
;
184 memcpy(&buf
[buf_pos
],settings
[i
].setting
,nvram_bytes
);
185 buf_pos
+= nvram_bytes
;
189 /* count and crc32 */
191 crc32
= crc_32(&buf
[NVRAM_DATA_START
],
192 max_len
-NVRAM_DATA_START
-1,0xffffffff);
193 memcpy(&buf
[4],&crc32
,4);
195 fd
= open(NVRAM_FILE
,O_CREAT
|O_TRUNC
|O_WRONLY
);
198 int len
= write(fd
,buf
,max_len
);
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
]);
210 DEBUGF( "save_config_buffer: rtc_write failed at addr 0x%02x: %d\n",
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
)
245 int red
, green
, blue
;
247 if (strlen(hex
) == 6) {
248 for (i
=0; i
< 6; i
++ ) {
249 if (!isxdigit(hex
[i
])) {
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
);
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
;
275 end
= strchr(start
, ',');
278 if (!strcmp(str
, start
))
285 strncpy(temp
, start
, end
-start
);
286 temp
[end
-start
] = '\0';
287 if (!strcmp(str
, temp
))
298 bool settings_load_config(const char* file
, bool apply
)
305 fd
= open(file
, O_RDONLY
);
309 while (read_line(fd
, line
, sizeof line
) > 0)
311 if (!settings_parseline(line
, &name
, &value
))
313 for(i
=0; i
<nb_settings
; i
++)
315 if (settings
[i
].cfg_name
== NULL
)
317 if (!strcasecmp(name
,settings
[i
].cfg_name
))
319 switch (settings
[i
].flags
&F_T_MASK
)
323 #ifdef HAVE_LCD_COLOR
324 if (settings
[i
].flags
&F_RGB
)
325 *(int*)settings
[i
].setting
= hex_to_rgb(value
);
328 if (settings
[i
].cfg_vals
== NULL
)
330 *(int*)settings
[i
].setting
= atoi(value
);
334 cfg_string_to_int(i
,(int*)settings
[i
].setting
,value
);
340 if (cfg_string_to_int(i
,&temp
,value
))
341 *(bool*)settings
[i
].setting
= (temp
==0?false:true);
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
,
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
);
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';
373 } /* if (!strcmp(name,settings[i].cfg_name)) */
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
;
393 start
= strchr(start
,',');
399 end
= strchr(start
,',');
401 strncpy(buf
, start
, buf_len
);
404 int len
= (buf_len
> (end
-start
))? end
-start
: buf_len
;
405 strncpy(buf
, start
, len
);
410 static bool is_changed(int setting_id
)
412 const struct settings_list
*setting
= &settings
[setting_id
];
413 switch (setting
->flags
&F_T_MASK
)
417 if (setting
->flags
&F_DEF_ISFUNC
)
419 if (*(int*)setting
->setting
== setting
->default_val
.func())
422 else if (setting
->flags
&F_T_SOUND
)
424 if (*(int*)setting
->setting
==
425 sound_default(setting
->sound_setting
->setting
))
428 else if (*(int*)setting
->setting
== setting
->default_val
.int_
)
432 if (*(bool*)setting
->setting
== setting
->default_val
.bool_
)
437 if (!strcmp((char*)setting
->setting
, setting
->default_val
.charptr
))
444 static bool settings_write_config(char* filename
, int options
)
448 char value
[MAX_PATH
];
449 fd
= open(filename
,O_CREAT
|O_TRUNC
|O_WRONLY
);
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
)
460 if ((options
== SETTINGS_SAVE_CHANGED
) &&
463 else if ((options
== SETTINGS_SAVE_THEME
) &&
464 ((settings
[i
].flags
&F_THEMESETTING
) == 0))
467 switch (settings
[i
].flags
&F_T_MASK
)
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
));
482 if (settings
[i
].cfg_vals
== NULL
)
484 snprintf(value
,MAX_PATH
,"%d",*(int*)settings
[i
].setting
);
488 cfg_int_to_string(i
, *(int*)settings
[i
].setting
,
494 *(bool*)settings
[i
].setting
==false?0:1, value
, MAX_PATH
);
498 if (((char*)settings
[i
].setting
)[0] == '\0')
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
);
512 fdprintf(fd
,"%s: %s\r\n",settings
[i
].cfg_name
,value
);
518 static bool flush_global_status_callback(void)
520 return write_nvram_data(nvram_buffer
,NVRAM_BLOCK_SIZE
);
523 static bool flush_config_block_callback(void)
526 r1
= write_nvram_data(nvram_buffer
,NVRAM_BLOCK_SIZE
);
527 r2
= settings_write_config(CONFIGFILE
, SETTINGS_SAVE_CHANGED
);
532 * persist all runtime user settings to disk or RTC RAM
534 static void update_runtime(void)
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 )
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
);
554 register_ata_idle_func(flush_global_status_callback
);
558 int settings_save( void )
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
);
566 if(!register_ata_idle_func(flush_config_block_callback
))
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
));
576 screens
[i
].puts(4, 2, str(LANG_SETTINGS_SAVE_RECORDER
));
577 screens
[i
].puts(2, 4, str(LANG_SETTINGS_BATTERY_RECORDER
));
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 */
595 if (!kbd_input(filename
, sizeof filename
)) {
599 gui_syncsplash(HZ
, str(LANG_MENU_SETTING_CANCEL
));
604 if (settings_write_config(filename
, options
))
605 gui_syncsplash(HZ
, str(LANG_SETTINGS_SAVED
));
607 gui_syncsplash(HZ
, str(LANG_FAILED
));
611 /** Apply and Reset settings **/
614 #ifdef HAVE_LCD_BITMAP
616 * Applies the range infos stored in global_settings to
619 void settings_apply_pm_range(void)
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);
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
);
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
);
665 #ifdef HAVE_USB_POWER
667 usb_charging_enable(global_settings
.usb_charging
);
672 void settings_apply(void)
675 #if CONFIG_CODEC == SWCODEC
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
);
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
);
699 remote_backlight_set_timeout(global_settings
.remote_backlight_timeout
);
701 remote_backlight_set_timeout_plugged(global_settings
.remote_backlight_timeout_plugged
);
703 #ifdef HAS_REMOTE_BUTTON_HOLD
704 remote_backlight_set_on_button_hold(global_settings
.remote_backlight_on_button_hold
);
706 #endif /* HAVE_REMOTE_LCD */
708 backlight_set_timeout(global_settings
.backlight_timeout
);
710 backlight_set_timeout_plugged(global_settings
.backlight_timeout_plugged
);
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
);
717 #ifdef HAVE_BACKLIGHT_BRIGHTNESS
718 backlight_set_brightness(global_settings
.brightness
);
720 ata_spindown(global_settings
.disk_spindown
);
721 #if (CONFIG_CODEC == MAS3507D) && !defined(SIMULATOR)
722 dac_line_in(global_settings
.line_in
);
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
);
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
);
745 unload_wps_backdrop();
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);
755 wps_data_init(gui_wps
[0].data
);
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
);
765 unload_main_backdrop();
767 show_main_backdrop();
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
);
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);
782 wps_data_init(gui_wps
[1].data
);
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
);
794 if ( global_settings
.kbd_file
[0]) {
795 snprintf(buf
, sizeof buf
, ROCKBOX_DIR
"/%s.kbd",
796 global_settings
.kbd_file
);
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
);
806 lcd_jump_scroll(global_settings
.jump_scroll
);
807 lcd_jump_scroll_delay(global_settings
.jump_scroll_delay
);
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
);
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
++) {
837 dsp_dither_enable(global_settings
.dithering_enabled
);
841 eq_hw_enable(global_settings
.eq_hw_enabled
);
844 #ifdef HAVE_SPDIF_POWER
845 spdif_power_enable(global_settings
.spdif_enable
);
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
);
853 #ifdef HAS_BUTTON_HOLD
854 backlight_set_on_button_hold(global_settings
.backlight_on_button_hold
);
856 #ifdef HAVE_LCD_SLEEP
857 lcd_set_sleep_after_backlight_off(global_settings
.lcd_sleep_after_backlight_off
);
859 #endif /* CONFIG_BACKLIGHT */
861 /* This should stay last */
862 #if defined(HAVE_RECORDING) && CONFIG_CODEC == SWCODEC
863 enc_global_settings_apply();
871 * reset all settings to their default value
873 void settings_reset(void) {
876 DEBUGF( "settings_reset()\n" );
878 for(i
=0; i
<nb_settings
; i
++)
880 switch (settings
[i
].flags
&F_T_MASK
)
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_
;
892 *(bool*)settings
[i
].setting
= settings
[i
].default_val
.bool_
;
896 strncpy((char*)settings
[i
].setting
,
897 settings
[i
].default_val
.charptr
,MAX_FILENAME
);
901 #if defined (HAVE_RECORDING) && CONFIG_CODEC == SWCODEC
902 enc_global_settings_reset();
906 /** Changing setting values **/
907 const struct settings_list
* find_setting(void* variable
, int *id
)
910 for(i
=0;i
<nb_settings
;i
++)
912 if (settings
[i
].setting
== variable
)
922 void talk_setting(void *global_settings_variable
)
924 const struct settings_list
*setting
;
925 if (global_settings
.talk_menu
== 0)
927 setting
= find_setting(global_settings_variable
, NULL
);
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
);
946 int integer
= val
/ 10;
948 snprintf(buffer
, buffer_size
, "%c%d.%d %s", sign
, integer
, dec
, unit
);
951 bool set_sound(const unsigned char * string
,
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 */
964 else if (*unit
== '%')
965 talkunit
= UNIT_PERCENT
;
966 else if (*unit
== 'H')
967 talkunit
= UNIT_HERTZ
;
969 return set_int(string
, unit
, talkunit
, variable
, sound_callback
,
970 steps
, min
, max
, NULL
);
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
),
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
)
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
}
1008 boolfunction
= function
;
1009 result
= set_option(string
, variable
, BOOL
, names
, 2,
1010 function
? bool_funcwrapper
: NULL
);
1014 static void talk_unit(int unit
, int value
, long (*get_talk_id
)(int value
))
1016 if (global_settings
.talk_menu
)
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);
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.. */
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
);
1058 snprintf(buffer
, MAX_PATH
,"%d %s",item
,cb_data
->unit
);
1060 else strcpy(buffer
,P2STR(cb_data
->options
[selected_item
].string
));
1063 #define type_fromvoidptr(type, value) \
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))
1075 struct gui_synclist lists
;
1077 bool allow_wrap
= true;
1079 if (cb_data
->type
== INT
)
1081 oldvalue
= *(int*)variable
;
1082 if (variable
== &global_settings
.volume
)
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
]
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();
1112 action
= get_action(CONTEXT_LIST
,TIMEOUT_BLOCK
);
1113 if (action
== ACTION_NONE
)
1115 if (gui_synclist_do_button(&lists
,action
,
1116 allow_wrap
?LIST_WRAP_UNLESS_HELD
:LIST_WRAP_OFF
))
1118 if (global_settings
.talk_menu
)
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
);
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
;
1152 if (*(bool*)variable
!= (bool)oldvalue
)
1154 gui_syncsplash(HZ
/2, str(LANG_MENU_SETTING_CANCEL
));
1155 *(bool*)variable
= (bool)oldvalue
;
1160 else if (action
== ACTION_STD_OK
)
1164 else if(default_event_handler(action
) == SYS_USB_CONNECTED
)
1166 gui_syncstatusbar_draw(&statusbars
, false);
1168 function(type_fromvoidptr(cb_data
->type
,variable
));
1170 if (cb_data
->type
== INT
)
1172 if (oldvalue
!= *(int*)variable
)
1175 else if (oldvalue
!= *(bool*)variable
)
1178 action_signalscreenchange();
1181 static const char *unit_strings
[] =
1212 bool set_int_ex(const unsigned char* string
,
1216 void (*function
)(int),
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
];
1230 data
.unit
= str(voice_unit
);
1231 return do_set_setting(string
,variable
,count
,
1232 (max
-*variable
)/step
, &data
,function
);
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
];
1239 data
.unit
= str(voice_unit
);
1240 return do_set_setting(string
,variable
,count
,
1241 (*variable
-min
)/step
, &data
,function
);
1244 bool set_int(const unsigned char* string
,
1248 void (*function
)(int),
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
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
};
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
,'/');
1294 while ((*ptr
!= '.') && (ptr
!= fptr
)) {
1298 if(ptr
== fptr
) extlen
= 0;
1300 if (strncasecmp(ROCKBOX_DIR
, filename
,strlen(ROCKBOX_DIR
)) ||
1301 (len
-extlen
> maxlen
))
1304 strncpy(setting
, fptr
, len
-extlen
);
1305 setting
[len
-extlen
]=0;
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 */
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
] = {
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
]