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 ****************************************************************************/
33 #include "backlight.h"
36 #include "mp3_playback.h"
43 #include "powermgmt.h"
52 #include "timefuncs.h"
53 #ifdef HAVE_LCD_BITMAP
56 #include "peakmeter.h"
62 #include "powermgmt.h"
69 #include "rbunicode.h"
71 #include "statusbar.h"
82 #if CONFIG_CODEC == MAS3507D
83 void dac_line_in(bool enable
);
85 struct user_settings global_settings
;
87 const char rec_base_directory
[] = REC_BASE_DIR
;
89 #if CONFIG_CODEC == SWCODEC
91 #include "pcm_playback.h"
95 #define CONFIG_BLOCK_VERSION 50
96 #define CONFIG_BLOCK_SIZE 512
97 #define RTC_BLOCK_SIZE 44
99 #ifdef HAVE_LCD_BITMAP
105 #ifdef HAVE_REMOTE_LCD
106 #include "lcd-remote.h"
110 static long config_sector
= 0; /* mark uninitialized */
111 static unsigned char config_block
[CONFIG_BLOCK_SIZE
];
114 /* descriptor for a configuration value */
115 /* (watch the struct packing and member sizes to keep this small) */
118 /* how many bits within the bitfield (1-32), MSB set if value is signed */
119 unsigned char bit_size
; /* min 6+1 bit */
120 /* how many bytes in the global_settings struct (1,2,4) */
121 unsigned char byte_size
; /* min 3 bits */
122 /* store position in global_settings struct */
123 short settings_offset
; /* min 9 bit, better 10 */
125 int default_val
; /* min 15 bit */
126 /* variable name in a .cfg file, NULL if not to be saved */
127 const char* cfg_name
;
128 /* set of values, "rgb" for a color, or NULL for a numerical value */
132 /********************************************
134 Config block as saved on the battery-packed RTC user RAM memory block
135 of 44 bytes, starting at offset 0x14 of the RTC memory space.
138 0x00 0x14 "Roc" header signature: 0x52 0x6f 0x63
139 0x03 0x17 <version byte: 0x0>
140 0x04 0x18 start of bit-table
142 0x28,0x29 unused, not reachable by set_bits() without disturbing the next 2
143 0x2A,0x2B <checksum 2 bytes: xor of 0x00-0x29>
145 Config memory is reset to 0xff and initialized with 'factory defaults' if
146 a valid header & checksum is not found. Config version number is only
147 increased when information is _relocated_ or space is _reused_ so that old
148 versions can read and modify configuration changed by new versions.
149 Memory locations not used by a given version should not be
150 modified unless the header & checksum test fails.
152 Rest of config block, only saved to disk:
153 0x2C start of 2nd bit-table
155 0xA4 (char[20]) FMR Preset file
156 0xB8 (char[20]) WPS file
157 0xCC (char[20]) Lang file
158 0xE0 (char[20]) Font file
159 ... (char[20]) RWPS file (on targets supporting a Remote WPS)
160 ... (char[20]) Main backdrop file (on color LCD targets)
162 ... to 0x200 <unused>
164 *************************************/
166 /* The persistence of the global_settings members is now controlled by
167 the two tables below, rtc_bits and hd_bits.
168 New values can just be added to the end, it will be backwards
169 compatible. If you however change order, bitsize, etc. of existing
170 entries, you need to bump CONFIG_BLOCK_VERSION to break compatibility.
174 /* convenience macro for both size and offset of global_settings member */
175 #define S_O(val) sizeof(global_settings.val), offsetof(struct user_settings, val)
176 #define SIGNED 0x80 /* for bitsize value with signed attribute */
178 /* some sets of values which are used more than once, to save memory */
179 static const char off_on
[] = "off,on";
180 static const char off_on_ask
[] = "off,on,ask";
181 static const char off_number_spell_hover
[] = "off,number,spell,hover";
182 #ifdef HAVE_LCD_BITMAP
183 static const char graphic_numeric
[] = "graphic,numeric";
186 #ifdef HAVE_RECORDING
187 /* keep synchronous to trig_durations and
188 trigger_times in settings_apply_trigger */
189 static const char trig_durations_conf
[] =
190 "0s,1s,2s,5s,10s,15s,20s,25s,30s,1min,2min,5min,10min";
193 #if defined(CONFIG_BACKLIGHT)
194 static const char backlight_times_conf
[] =
195 "off,on,1,2,3,4,5,6,7,8,9,10,15,20,25,30,45,60,90";
198 /* the part of the settings which ends up in the RTC RAM, where available
199 (those we either need early, save frequently, or without spinup) */
200 static const struct bit_entry rtc_bits
[] =
202 /* placeholder, containing the size information */
203 {9, 0, 0, 0, NULL
, NULL
}, /* 9 bit to tell how far this is populated */
205 /* # of bits, offset+size, default, .cfg name, .cfg values */
207 #if CONFIG_CODEC == MAS3507D
208 {8 | SIGNED
, S_O(volume
), -18, "volume", NULL
}, /* -78...+18 */
210 {8 | SIGNED
, S_O(volume
), -25, "volume", NULL
}, /* -100...+12 / -84...0 */
212 {8 | SIGNED
, S_O(balance
), 0, "balance", NULL
}, /* -100...100 */
213 #if CONFIG_CODEC != SWCODEC /* any MAS */
214 {5 | SIGNED
, S_O(bass
), 0, "bass", NULL
}, /* -15..+15 / -12..+12 */
215 {5 | SIGNED
, S_O(treble
), 0, "treble", NULL
}, /* -15..+15 / -12..+12 */
216 #elif defined HAVE_UDA1380
217 {5, S_O(bass
), 0, "bass", NULL
}, /* 0..+24 */
218 {3, S_O(treble
), 0, "treble", NULL
}, /* 0..+6 */
219 #elif defined(HAVE_WM8975) || defined(HAVE_WM8758) \
220 || defined(HAVE_WM8731) || defined(HAVE_WM8721)
221 {5 | SIGNED
, S_O(bass
), 0, "bass", NULL
}, /* -6..+9 */
222 {5 | SIGNED
, S_O(treble
), 0, "treble", NULL
}, /* -6..+9 */
224 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
225 {5, S_O(loudness
), 0, "loudness", NULL
}, /* 0...17 */
226 {3, S_O(avc
), 0, "auto volume", "off,20ms,2,4,8" },
227 {1, S_O(superbass
), false, "superbass", off_on
},
229 {3, S_O(channel_config
), 0, "channels",
230 "stereo,mono,custom,mono left,mono right,karaoke" },
231 {8, S_O(stereo_width
), 100, "stereo width", NULL
},
233 {1, S_O(resume
), false, "resume", off_on
},
234 {1, S_O(playlist_shuffle
), false, "shuffle", off_on
},
235 {16 | SIGNED
, S_O(resume_index
), -1, NULL
, NULL
},
236 {16 | SIGNED
, S_O(resume_first_index
), 0, NULL
, NULL
},
237 {32 | SIGNED
, S_O(resume_offset
), -1, NULL
, NULL
},
238 {32 | SIGNED
, S_O(resume_seed
), -1, NULL
, NULL
},
239 {3, S_O(repeat_mode
), REPEAT_ALL
, "repeat", "off,all,one,shuffle,ab" },
241 #ifdef HAVE_LCD_CONTRAST
242 {6, S_O(contrast
), DEFAULT_CONTRAST_SETTING
, "contrast", NULL
},
244 #ifdef CONFIG_BACKLIGHT
245 {5, S_O(backlight_timeout
), 6, "backlight timeout", backlight_times_conf
},
246 #ifdef CONFIG_CHARGING
247 {5, S_O(backlight_timeout_plugged
), 11, "backlight timeout plugged",
248 backlight_times_conf
},
250 #endif /* CONFIG_BACKLIGHT */
251 #ifdef HAVE_LCD_BITMAP
252 {1, S_O(invert
), false, "invert", off_on
},
253 {1, S_O(flip_display
), false, "flip display", off_on
},
255 {1, S_O(invert_cursor
), true, "invert cursor", off_on
},
256 {1, S_O(statusbar
), true, "statusbar", off_on
},
257 {1, S_O(scrollbar
), true, "scrollbar", off_on
},
258 #if CONFIG_KEYPAD == RECORDER_PAD
259 {1, S_O(buttonbar
), true, "buttonbar", off_on
},
261 {1, S_O(volume_type
), 0, "volume display", graphic_numeric
},
262 {1, S_O(battery_display
), 0, "battery display", graphic_numeric
},
263 {1, S_O(timeformat
), 0, "time format", "24hour,12hour" },
264 #endif /* HAVE_LCD_BITMAP */
265 {1, S_O(show_icons
), true, "show icons", off_on
},
267 {4, S_O(poweroff
), 10,
268 "idle poweroff", "off,1,2,3,4,5,6,7,8,9,10,15,30,45,60" },
269 {18, S_O(runtime
), 0, NULL
, NULL
},
270 {18, S_O(topruntime
), 0, NULL
, NULL
},
272 {15, S_O(max_files_in_playlist
), 10000,
273 "max files in playlist", NULL
}, /* 1000...20000 */
274 {14, S_O(max_files_in_dir
), 400,
275 "max files in dir", NULL
}, /* 50...10000 */
277 {15, S_O(max_files_in_playlist
), 1000,
278 "max files in playlist", NULL
}, /* 1000...20000 */
279 {14, S_O(max_files_in_dir
), 200,
280 "max files in dir", NULL
}, /* 50...10000 */
283 {12, S_O(battery_capacity
), BATTERY_CAPACITY_DEFAULT
, "battery capacity",
284 NULL
}, /* 1500...3200 for NiMH, 2200...3200 for LiIon,
285 500...1500 for Alkaline */
286 #ifdef CONFIG_CHARGING
287 {1, S_O(car_adapter_mode
), false, "car adapter mode", off_on
},
291 {1, S_O(fm_force_mono
), false, "force fm mono", off_on
},
292 {8, S_O(last_frequency
), 0, NULL
, NULL
}, /* Default: MIN_FREQ */
295 #if BATTERY_TYPES_COUNT > 1
296 {1, S_O(battery_type
), 0, "battery type", "alkaline,nimh" },
299 #ifdef HAVE_REMOTE_LCD
301 {6, S_O(remote_contrast
), 42, "remote contrast", NULL
},
302 {1, S_O(remote_invert
), false, "remote invert", off_on
},
303 {1, S_O(remote_flip_display
), false, "remote flip display", off_on
},
304 {5, S_O(remote_backlight_timeout
), 6, "remote backlight timeout",
305 backlight_times_conf
},
306 #ifdef CONFIG_CHARGING
307 {5, S_O(remote_backlight_timeout_plugged
), 11,
308 "remote backlight timeout plugged", backlight_times_conf
},
310 #ifdef HAVE_REMOTE_LCD_TICKING
311 {1, S_O(remote_reduce_ticking
), false, "remote reduce ticking", off_on
},
315 #ifdef CONFIG_BACKLIGHT
316 {1, S_O(bl_filter_first_keypress
), false,
317 "backlight filters first keypress", off_on
},
318 #ifdef HAVE_REMOTE_LCD
319 {1, S_O(remote_bl_filter_first_keypress
), false,
320 "backlight filters first remote keypress", off_on
},
322 #endif /* CONFIG_BACKLIGHT */
324 /* new stuff to be added here */
325 /* If values are just added to the end, no need to bump the version. */
327 /* Current sum of bits: 277 (worst case, but w/o remote lcd) */
328 /* Sum of all bit sizes must not grow beyond 288! */
332 /* the part of the settings which ends up in HD sector only */
333 static const struct bit_entry hd_bits
[] =
335 /* This table starts after the 44 RTC bytes = 352 bits. */
336 /* Here we need 11 bits to tell how far this is populated. */
338 /* placeholder, containing the size information */
339 {11, 0, 0, 0, NULL
, NULL
}, /* 11 bit to tell how far this is populated */
341 /* # of bits, offset+size, default, .cfg name, .cfg values */
343 #ifdef CONFIG_BACKLIGHT
344 {1, S_O(caption_backlight
), false, "caption backlight", off_on
},
346 #ifdef HAVE_REMOTE_LCD
347 {1, S_O(remote_caption_backlight
), false,
348 "remote caption backlight", off_on
},
350 #ifdef HAVE_BACKLIGHT_BRIGHTNESS
351 {4, S_O(brightness
), DEFAULT_BRIGHTNESS_SETTING
, "brightness", NULL
},
353 #ifdef HAVE_BACKLIGHT_PWM_FADING
354 /* backlight fading */
355 {2, S_O(backlight_fade_in
), 1, "backlight fade in", "off,500ms,1s,2s"},
356 {3, S_O(backlight_fade_out
), 3, "backlight fade out",
357 "off,500ms,1s,2s,3s,4s,5s,10s"},
360 {4, S_O(scroll_speed
), 9, "scroll speed", NULL
}, /* 0...15 */
361 {8, S_O(scroll_delay
), 100, "scroll delay", NULL
}, /* 0...250 */
362 {8, S_O(bidir_limit
), 50, "bidir limit", NULL
}, /* 0...200 */
364 #ifdef HAVE_REMOTE_LCD
365 {4, S_O(remote_scroll_speed
), 9, "remote scroll speed", NULL
}, /* 0...15 */
366 {8, S_O(remote_scroll_step
), 6, "remote scroll step", NULL
}, /* 1...160 */
367 {8, S_O(remote_scroll_delay
), 100, "remote scroll delay", NULL
}, /* 0...250 */
368 {8, S_O(remote_bidir_limit
), 50, "remote bidir limit", NULL
}, /* 0...200 */
371 #ifdef HAVE_LCD_BITMAP
372 {1, S_O(offset_out_of_view
), false, "Screen Scrolls Out Of View", off_on
},
374 {9, S_O(scroll_step
), 6, "scroll step", NULL
},
375 {9, S_O(screen_scroll_step
), 16, "screen scroll step", NULL
},
376 #elif LCD_WIDTH > 127
377 {8, S_O(scroll_step
), 6, "scroll step", NULL
},
378 {8, S_O(screen_scroll_step
), 16, "screen scroll step", NULL
},
380 {7, S_O(scroll_step
), 6, "scroll step", NULL
},
381 {7, S_O(screen_scroll_step
), 16, "screen scroll step", NULL
},
383 #endif /* HAVE_LCD_BITMAP */
384 #ifdef HAVE_LCD_CHARCELLS
385 {3, S_O(jump_scroll
), 0, "jump scroll", NULL
}, /* 0...5 */
386 {8, S_O(jump_scroll_delay
), 50, "jump scroll delay", NULL
}, /* 0...250 */
388 {1, S_O(scroll_paginated
), false, "scroll paginated", off_on
},
390 #ifdef HAVE_LCD_COLOR
391 {LCD_DEPTH
,S_O(fg_color
),LCD_DEFAULT_FG
,"foreground color","rgb"},
392 {LCD_DEPTH
,S_O(bg_color
),LCD_DEFAULT_BG
,"background color","rgb"},
396 {1, S_O(play_selected
), true, "play selected", off_on
},
397 {1, S_O(fade_on_stop
), true, "volume fade", off_on
},
398 {4, S_O(ff_rewind_min_step
), FF_REWIND_1000
,
399 "scan min step", "1,2,3,4,5,6,8,10,15,20,25,30,45,60" },
400 {4, S_O(ff_rewind_accel
), 3, "scan accel", NULL
},
401 #if CONFIG_CODEC == SWCODEC
402 {3, S_O(buffer_margin
), 0, "antiskip",
403 "5s,15s,30s,1min,2min,3min,5min,10min" },
405 {3, S_O(buffer_margin
), 0, "antiskip", NULL
},
409 #ifdef HAVE_ATA_POWER_OFF
410 {1, S_O(disk_poweroff
), false, "disk poweroff", off_on
},
412 {8, S_O(disk_spindown
), 5, "disk spindown", NULL
},
413 #endif /* HAVE_MMC */
416 {3, S_O(dirfilter
), SHOW_SUPPORTED
,
417 "show files", "all,supported,music,playlists,id3 database" },
418 {1, S_O(sort_case
), false, "sort case", off_on
},
419 {1, S_O(browse_current
), false, "follow playlist", off_on
},
421 {1, S_O(playlist_viewer_icons
), true, "playlist viewer icons", off_on
},
422 {1, S_O(playlist_viewer_indices
), true,
423 "playlist viewer indices", off_on
},
424 {1, S_O(playlist_viewer_track_display
), 0,
425 "playlist viewer track display", "track name,full path" },
426 {2, S_O(recursive_dir_insert
), RECURSE_OFF
,
427 "recursive directory insert", off_on_ask
},
429 {3, S_O(autocreatebookmark
), BOOKMARK_NO
, "autocreate bookmarks",
430 "off,on,ask,recent only - on,recent only - ask" },
431 {2, S_O(autoloadbookmark
), BOOKMARK_NO
,
432 "autoload bookmarks", off_on_ask
},
433 {2, S_O(usemrb
), BOOKMARK_NO
,
434 "use most-recent-bookmarks", "off,on,unique only" },
435 #ifdef HAVE_LCD_BITMAP
437 {5, S_O(peak_meter_clip_hold
), 16, "peak meter clip hold", /* 0...25 */
438 "on,1,2,3,4,5,6,7,8,9,10,15,20,25,30,45,60,90,2min,3min,5min,10min,20min,45min,90min" },
439 {5, S_O(peak_meter_hold
), 3, "peak meter hold",
440 "off,200ms,300ms,500ms,1,2,3,4,5,6,7,8,9,10,15,20,30,1min" },
441 {7, S_O(peak_meter_release
), 8, "peak meter release", NULL
}, /* 0...126 */
442 {1, S_O(peak_meter_dbfs
), true, "peak meter dbfs", off_on
},
443 {7, S_O(peak_meter_min
), 60, "peak meter min", NULL
}, /* 0...100 */
444 {7, S_O(peak_meter_max
), 0, "peak meter max", NULL
}, /* 0...100 */
446 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
447 {7, S_O(mdb_strength
), 0, "mdb strength", NULL
},
448 {7, S_O(mdb_harmonics
), 0, "mdb harmonics", NULL
},
449 {9, S_O(mdb_center
), 0, "mdb center", NULL
},
450 {9, S_O(mdb_shape
), 0, "mdb shape", NULL
},
451 {1, S_O(mdb_enable
), 0, "mdb enable", off_on
},
453 #if CONFIG_CODEC == MAS3507D
454 {1, S_O(line_in
), false, "line in", off_on
},
457 {2, S_O(talk_dir
), 0, "talk dir", off_number_spell_hover
},
458 {2, S_O(talk_file
), 0, "talk file", off_number_spell_hover
},
459 {1, S_O(talk_menu
), true, "talk menu", off_on
},
461 {2, S_O(sort_file
), 0, "sort files", "alpha,oldest,newest,type" },
462 {2, S_O(sort_dir
), 0, "sort dirs", "alpha,oldest,newest" },
463 {1, S_O(id3_v1_first
), 0, "id3 tag priority", "v2-v1,v1-v2"},
465 #ifdef HAVE_RECORDING
467 {1, S_O(rec_startup
), false, "rec screen on startup", off_on
},
468 {4, S_O(rec_timesplit
), 0, "rec timesplit", /* 0...15 */
469 "off,00:05,00:10,00:15,00:30,01:00,01:14,01:20,02:00,04:00,06:00,08:00,10:00,12:00,18:00,24:00" },
470 {4, S_O(rec_sizesplit
), 0, "rec sizesplit", /* 0...15 */
471 "off,5MB,10MB,15MB,32MB,64MB,75MB,100MB,128MB,256MB,512MB,650MB,700MB,1GB,1.5GB,1.75GB" },
472 {1, S_O(rec_channels
), 0, "rec channels", "stereo,mono" },
473 {1, S_O(rec_split_type
), 0, "rec split type", "Split, Stop" },
474 {1, S_O(rec_split_method
), 0, "rec split method", "Time,Filesize" },
477 {2, S_O(rec_source
), 0 /* 0=mic */, "rec source", "mic,line,spdif" },
479 {1, S_O(rec_source
), 0 /* 0=mic */, "rec source", "mic,line" },
481 {5, S_O(rec_prerecord_time
), 0, "prerecording time", NULL
}, /* 0...30 */
482 {1, S_O(rec_directory
), 0, /* rec_base_directory */
483 "rec directory", REC_BASE_DIR
",current" },
484 #ifdef CONFIG_BACKLIGHT
485 {2, S_O(cliplight
), 0, "cliplight", "off,main,both,remote" },
487 #if CONFIG_CODEC == MAS3587F
488 {4, S_O(rec_mic_gain
), 8, "rec mic gain", NULL
},
489 {4, S_O(rec_left_gain
), 2 /* 0dB */, "rec left gain", NULL
}, /* 0...15 */
490 {4, S_O(rec_right_gain
), 2 /* 0dB */, "rec right gain", NULL
}, /* 0...15 */
491 {3, S_O(rec_frequency
), 0, /* 0=44.1kHz */
492 "rec frequency", "44,48,32,22,24,16" },
493 {1, S_O(rec_editable
), false, "editable recordings", off_on
},
494 {3, S_O(rec_quality
), 5, "rec quality", NULL
},
495 #elif defined(HAVE_UDA1380)
496 {8|SIGNED
, S_O(rec_mic_gain
), 16 /* 8 dB */, "rec mic gain", NULL
}, /* -128...+108 */
497 {8|SIGNED
, S_O(rec_left_gain
), 0, "rec left gain", NULL
}, /* -128...+96 */
498 {8|SIGNED
, S_O(rec_right_gain
), 0, "rec right gain", NULL
}, /* -128...+96 */
499 {3, S_O(rec_frequency
), 0, /* 0=44.1kHz */
500 "rec frequency", "44,48,32,22,24,16" },
503 /* values for the trigger */
504 {8 | SIGNED
, S_O(rec_start_thres
), -35, "trigger start threshold", NULL
},
505 {8 | SIGNED
, S_O(rec_stop_thres
), -45, "trigger stop threshold", NULL
},
506 {4, S_O(rec_start_duration
), 0, "trigger start duration", trig_durations_conf
},
507 {4, S_O(rec_stop_postrec
), 2, "trigger stop postrec", trig_durations_conf
},
508 {4, S_O(rec_stop_gap
), 1, "trigger min gap", trig_durations_conf
},
509 {4, S_O(rec_trigger_mode
), 0, "trigger mode", "off,once,repeat"},
510 #endif /* HAVE_RECORDING */
512 #ifdef HAVE_SPDIF_POWER
513 {1, S_O(spdif_enable
), false, "spdif enable", off_on
},
516 {1, S_O(next_folder
), false, "folder navigation", off_on
},
517 {1, S_O(runtimedb
), false, "gather runtime data", off_on
},
519 #if CONFIG_CODEC == SWCODEC
520 {1, S_O(replaygain
), false, "replaygain", off_on
},
521 {2, S_O(replaygain_type
), REPLAYGAIN_ALBUM
, "replaygain type",
522 "track,album,track shuffle" },
523 {1, S_O(replaygain_noclip
), false, "replaygain noclip", off_on
},
524 {8 | SIGNED
, S_O(replaygain_preamp
), 0, "replaygain preamp", NULL
},
525 {2, S_O(beep
), 0, "beep", "off,weak,moderate,strong" },
526 {2, S_O(crossfade
), 0, "crossfade", "off,shuffle,track skip,always"},
527 {3, S_O(crossfade_fade_in_delay
), 0, "crossfade fade in delay", NULL
},
528 {3, S_O(crossfade_fade_out_delay
), 0, "crossfade fade out delay", NULL
},
529 {4, S_O(crossfade_fade_in_duration
), 0, "crossfade fade in duration", NULL
},
530 {4, S_O(crossfade_fade_out_duration
), 0, "crossfade fade out duration", NULL
},
531 {1, S_O(crossfade_fade_out_mixmode
), 0, "crossfade fade out mode", "crossfade,mix"},
532 {1, S_O(crossfeed
), false, "crossfeed", off_on
},
533 {6, S_O(crossfeed_direct_gain
), 15, "crossfeed direct gain", NULL
},
534 {7, S_O(crossfeed_cross_gain
), 60, "crossfeed cross gain", NULL
},
535 {8, S_O(crossfeed_hf_attenuation
), 160, "crossfeed hf attenuation", NULL
},
536 {11, S_O(crossfeed_hf_cutoff
), 700, "crossfeed hf cutoff", NULL
},
539 {1, S_O(eq_enabled
), false, "eq enabled", off_on
},
540 {8, S_O(eq_precut
), 0, "eq precut", NULL
},
542 {15, S_O(eq_band0_cutoff
), 60, "eq band 0 cutoff", NULL
},
543 {15, S_O(eq_band1_cutoff
), 200, "eq band 1 cutoff", NULL
},
544 {15, S_O(eq_band2_cutoff
), 800, "eq band 2 cutoff", NULL
},
545 {15, S_O(eq_band3_cutoff
), 4000, "eq band 3 cutoff", NULL
},
546 {15, S_O(eq_band4_cutoff
), 12000, "eq band 4 cutoff", NULL
},
547 /* 0..64 (or 0.0 to 6.4) */
548 {6, S_O(eq_band0_q
), 7, "eq band 0 q", NULL
},
549 {6, S_O(eq_band1_q
), 10, "eq band 1 q", NULL
},
550 {6, S_O(eq_band2_q
), 10, "eq band 2 q", NULL
},
551 {6, S_O(eq_band3_q
), 10, "eq band 3 q", NULL
},
552 {6, S_O(eq_band4_q
), 7, "eq band 4 q", NULL
},
553 /* -240..240 (or -24db to +24db) */
554 {9|SIGNED
, S_O(eq_band0_gain
), 0, "eq band 0 gain", NULL
},
555 {9|SIGNED
, S_O(eq_band1_gain
), 0, "eq band 1 gain", NULL
},
556 {9|SIGNED
, S_O(eq_band2_gain
), 0, "eq band 2 gain", NULL
},
557 {9|SIGNED
, S_O(eq_band3_gain
), 0, "eq band 3 gain", NULL
},
558 {9|SIGNED
, S_O(eq_band4_gain
), 0, "eq band 4 gain", NULL
},
562 {1, S_O(dircache
), false, "dircache", off_on
},
563 {22, S_O(dircache_size
), 0, NULL
, NULL
},
565 #ifdef HAVE_TC_RAMCACHE
566 {1, S_O(tagcache_ram
), 0, "tagcache_ram", off_on
},
568 {1, S_O(tagcache_autoupdate
), 0, "tagcache_autoupdate", off_on
},
570 {4, S_O(default_codepage
), 0, "default codepage",
571 "iso8859-1,iso8859-7,iso8859-8,cp1251,iso8859-11,cp1256,iso8859-9,iso8859-2,sjis,gb2312,ksx1001,big5,utf-8,cp1256" },
573 {1, S_O(warnon_erase_dynplaylist
), false,
574 "warn when erasing dynamic playlist", off_on
},
576 #ifdef CONFIG_BACKLIGHT
577 #ifdef HAS_BUTTON_HOLD
578 {2, S_O(backlight_on_button_hold
), 0, "backlight on button hold",
582 #ifdef HAVE_LCD_SLEEP
583 {4, S_O(lcd_sleep_after_backlight_off
), 3,
584 "lcd sleep after backlight off",
585 "always,never,5,10,15,20,30,45,60,90" },
587 #endif /* CONFIG_BACKLIGHT */
590 {1, S_O(eq_hw_enabled
), false, "eq hardware enabled", off_on
},
592 {2, S_O(eq_hw_band0_cutoff
), 1, "eq hardware band 0 cutoff", "80Hz,105Hz,135Hz,175Hz" },
593 {5|SIGNED
, S_O(eq_hw_band0_gain
), 12, "eq hardware band 0 gain", NULL
},
595 {2, S_O(eq_hw_band1_center
), 1, "eq hardware band 1 center", "230Hz,300Hz,385Hz,500Hz" },
596 {1, S_O(eq_hw_band1_bandwidth
), 0, "eq hardware band 1 bandwidth", "narrow,wide" },
597 {5|SIGNED
, S_O(eq_hw_band1_gain
), 12, "eq hardware band 1 gain", NULL
},
599 {2, S_O(eq_hw_band2_center
), 1, "eq hardware band 2 center", "650Hz,850Hz,1.1kHz,1.4kHz" },
600 {1, S_O(eq_hw_band2_bandwidth
), 0, "eq hardware band 2 bandwidth", "narrow,wide" },
601 {5|SIGNED
, S_O(eq_hw_band2_gain
), 12, "eq hardware band 2 gain", NULL
},
603 {2, S_O(eq_hw_band3_center
), 1, "eq hardware band 3 center", "1.8kHz,2.4kHz,3.2kHz,4.1kHz" },
604 {1, S_O(eq_hw_band3_bandwidth
), 0, "eq hardware band 3 bandwidth", "narrow,wide" },
605 {5|SIGNED
, S_O(eq_hw_band3_gain
), 12, "eq hardware band 3 gain", NULL
},
607 {2, S_O(eq_hw_band4_cutoff
), 1, "eq hardware band 4 cutoff", "5.3kHz,6.9kHz,9kHz,11.7kHz" },
608 {5|SIGNED
, S_O(eq_hw_band4_gain
), 12, "eq hardware band 4 gain", NULL
},
610 {1, S_O(hold_lr_for_scroll_in_list
), true, "hold_lr_for_scroll_in_list", off_on
},
612 {2, S_O(show_path_in_browser
), 0, "show path in browser", "off,current directory,full path" },
614 {4, S_O(rec_agc_preset_mic
), 1, "agc mic preset", NULL
}, /* 0...5 */
615 {4, S_O(rec_agc_preset_line
), 1, "agc line preset", NULL
}, /* 0...5 */
616 {8|SIGNED
, S_O(rec_agc_maxgain_mic
), 104, "agc maximum mic gain", NULL
},
617 {8|SIGNED
, S_O(rec_agc_maxgain_line
), 96, "agc maximum line gain", NULL
},
618 {3, S_O(rec_agc_cliptime
), 1, "agc cliptime", "0.2s,0.4s,0.6s,0.8,1s"},
620 /* If values are just added to the end, no need to bump the version. */
621 /* new stuff to be added at the end */
623 /* Sum of all bit sizes must not grow beyond 0xB8*8 = 1472 */
626 /* helper function to extract n (<=32) bits from an arbitrary position
627 * counting from LSB to MSB */
628 static uint32_t get_bits(
629 const uint32_t *p
, /* the start of the bitfield array */
630 unsigned int from
, /* bit no. to start reading from */
631 unsigned int size
) /* how many bits to read */
633 unsigned int long_index
= from
/ 32;
634 unsigned int bit_index
= from
% 32;
637 result
= p
[long_index
] >> bit_index
;
639 if (bit_index
+ size
> 32) /* crossing longword boundary */
640 result
|= p
[long_index
+1] << (32 - bit_index
);
642 result
&= 0xFFFFFFFF >> (32 - size
);
647 /* helper function to set n (<=32) bits to an arbitrary position,
648 * counting from LSB to MSB */
649 static void set_bits(
650 uint32_t *p
, /* the start of the bitfield array */
651 unsigned int from
, /* bit no. to start writing into */
652 unsigned int size
, /* how many bits to change */
653 uint32_t value
) /* content (LSBs will be taken) */
655 unsigned int long_index
= from
/ 32;
656 unsigned int bit_index
= from
% 32;
659 mask
= 0xFFFFFFFF >> (32 - size
);
663 if (bit_index
+ size
> 32)
665 (p
[long_index
+1] & (0xFFFFFFFF << (bit_index
+ size
- 32)))
666 | (value
>> (32 - bit_index
));
668 p
[long_index
] = (p
[long_index
] & ~mask
) | (value
<< bit_index
);
671 #ifdef HAVE_LCD_COLOR
673 * Helper function to convert a string of 6 hex digits to a native colour
676 #define hex2dec(c) (((c) >= '0' && ((c) <= '9')) ? (toupper(c)) - '0' : \
677 (toupper(c)) - 'A' + 10)
679 int hex_to_rgb(const char* hex
)
682 int red
, green
, blue
;
684 if (strlen(hex
) == 6) {
685 for (i
=0; i
< 6; i
++ ) {
686 if (!isxdigit(hex
[i
])) {
693 red
= (hex2dec(hex
[0]) << 4) | hex2dec(hex
[1]);
694 green
= (hex2dec(hex
[2]) << 4) | hex2dec(hex
[3]);
695 blue
= (hex2dec(hex
[4]) << 4) | hex2dec(hex
[5]);
696 return LCD_RGBPACK(red
,green
,blue
);
705 * Calculates the checksum for the config block and returns it
708 static unsigned short calculate_config_checksum(const unsigned char* buf
)
711 unsigned char cksum
[2];
712 cksum
[0] = cksum
[1] = 0;
714 for (i
=0; i
< RTC_BLOCK_SIZE
- 2; i
+=2 ) {
716 cksum
[1] ^= buf
[i
+1];
719 return (cksum
[0] << 8) | cksum
[1];
723 * initialize the config block buffer
725 static void init_config_buffer( void )
727 DEBUGF( "init_config_buffer()\n" );
729 /* reset to 0 - all unused */
730 memset(config_block
, 0, CONFIG_BLOCK_SIZE
);
732 config_block
[0] = 'R';
733 config_block
[1] = 'o';
734 config_block
[2] = 'c';
735 config_block
[3] = CONFIG_BLOCK_VERSION
;
739 * save the config block buffer to disk or RTC RAM
741 static int save_config_buffer( void )
743 unsigned short chksum
;
748 /* update the checksum in the end of the block before saving */
749 chksum
= calculate_config_checksum(config_block
);
750 config_block
[ RTC_BLOCK_SIZE
- 2 ] = chksum
>> 8;
751 config_block
[ RTC_BLOCK_SIZE
- 1 ] = chksum
& 0xff;
754 /* FIXME: okay, it _would_ be cleaner and faster to implement rtc_write so
755 that it would write a number of bytes at a time since the RTC chip
756 supports that, but this will have to do for now 8-) */
757 for (i
=0; i
< RTC_BLOCK_SIZE
; i
++ ) {
758 int r
= rtc_write(0x14+i
, config_block
[i
]);
760 DEBUGF( "save_config_buffer: rtc_write failed at addr 0x%02x: %d\n",
768 if (config_sector
!= 0)
769 ata_delayed_write( config_sector
, config_block
);
777 * load the config block buffer from disk or RTC RAM
779 static int load_config_buffer(int which
)
781 unsigned short chksum
;
782 bool correct
= false;
785 DEBUGF( "load_config_buffer()\n" );
787 if (which
& SETTINGS_HD
)
789 if (config_sector
!= 0) {
790 ata_read_sectors(IF_MV2(0,) config_sector
, 1, config_block
);
791 /* calculate the checksum, check it and the header */
792 chksum
= calculate_config_checksum(config_block
);
794 if (config_block
[0] == 'R' &&
795 config_block
[1] == 'o' &&
796 config_block
[2] == 'c' &&
797 config_block
[3] == CONFIG_BLOCK_VERSION
&&
798 (chksum
>> 8) == config_block
[RTC_BLOCK_SIZE
- 2] &&
799 (chksum
& 0xff) == config_block
[RTC_BLOCK_SIZE
- 1])
801 DEBUGF( "load_config_buffer: header & checksum test ok\n" );
810 /* If the disk sector was incorrect, reinit the buffer */
811 memset(config_block
, 0, CONFIG_BLOCK_SIZE
);
814 if (which
& SETTINGS_RTC
)
817 unsigned char rtc_block
[RTC_BLOCK_SIZE
];
820 for (i
=0; i
< RTC_BLOCK_SIZE
; i
++ )
821 rtc_block
[i
] = rtc_read(0x14+i
);
823 chksum
= calculate_config_checksum(rtc_block
);
825 /* if rtc block is ok, use that */
826 if (rtc_block
[0] == 'R' &&
827 rtc_block
[1] == 'o' &&
828 rtc_block
[2] == 'c' &&
829 rtc_block
[3] == CONFIG_BLOCK_VERSION
&&
830 (chksum
>> 8) == rtc_block
[RTC_BLOCK_SIZE
- 2] &&
831 (chksum
& 0xff) == rtc_block
[RTC_BLOCK_SIZE
- 1])
833 memcpy(config_block
, rtc_block
, RTC_BLOCK_SIZE
);
840 /* if checksum is not valid, clear the config buffer */
841 DEBUGF( "load_config_buffer: header & checksum test failed\n" );
842 init_config_buffer();
850 /* helper to save content of global_settings into a bitfield,
851 as described per table */
852 static void save_bit_table(const struct bit_entry
* p_table
, int count
, int bitstart
)
854 uint32_t *p_bitfield
= (uint32_t *)config_block
; /* 32 bit addr. */
855 uint32_t value
; /* 32 bit content */
857 const struct bit_entry
* p_run
= p_table
; /* start after the size info */
858 int curr_bit
= bitstart
+ p_table
->bit_size
;
859 count
--; /* first is excluded from loop */
861 for (i
=0; i
<count
; i
++)
864 /* could do a memcpy, but that would be endian-dependent */
865 switch(p_run
->byte_size
)
868 value
= ((uint8_t *)&global_settings
)[p_run
->settings_offset
];
871 value
= ((uint16_t *)&global_settings
)[p_run
->settings_offset
/2];
874 value
= ((uint32_t *)&global_settings
)[p_run
->settings_offset
/4];
877 DEBUGF( "save_bit_table: illegal size!\n" );
880 set_bits(p_bitfield
, curr_bit
, p_run
->bit_size
& 0x3F, value
);
881 curr_bit
+= p_run
->bit_size
& 0x3F;
883 set_bits(p_bitfield
, bitstart
, p_table
->bit_size
, /* write size */
884 curr_bit
); /* = position after last element */
888 * figure out the config sector from the partition table and the
889 * mounted file system
891 void settings_calc_config_sector(void)
897 long partition_start
;
900 if (fat_startsector(IF_MV(0)) != 0) /* There is a partition table */
903 for (i
= 0; i
< 4; i
++)
905 partition_start
= disk_partinfo(i
)->start
;
906 if (partition_start
!= 0 && (partition_start
- 2) < sector
)
907 sector
= partition_start
- 2;
913 config_sector
= sector
;
918 * persist all runtime user settings to disk or RTC RAM
920 int settings_save( void )
927 elapsed_secs
= (current_tick
- lasttime
) / HZ
;
928 global_settings
.runtime
+= elapsed_secs
;
929 lasttime
+= (elapsed_secs
* HZ
);
931 if ( global_settings
.runtime
> global_settings
.topruntime
)
932 global_settings
.topruntime
= global_settings
.runtime
;
935 /* serialize scalar values into RTC and HD sector, specified via table */
936 save_bit_table(rtc_bits
, sizeof(rtc_bits
)/sizeof(rtc_bits
[0]), 4*8);
937 save_bit_table(hd_bits
, sizeof(hd_bits
)/sizeof(hd_bits
[0]), RTC_BLOCK_SIZE
*8);
940 strncpy((char *)&config_block
[i
], (char *)global_settings
.wps_file
,
943 strncpy((char *)&config_block
[i
], (char *)global_settings
.lang_file
,
946 strncpy((char *)&config_block
[i
], (char *)global_settings
.font_file
,
949 #ifdef HAVE_REMOTE_LCD
950 strncpy((char *)&config_block
[i
], (char *)global_settings
.rwps_file
,
956 strncpy((char *)&config_block
[i
], (char *)global_settings
.fmr_file
,
961 #ifdef HAVE_LCD_COLOR
962 strncpy((char *)&config_block
[i
], (char *)global_settings
.backdrop_file
,
966 #ifdef HAVE_LCD_BITMAP
967 strncpy((char *)&config_block
[i
], (char *)global_settings
.kbd_file
,
972 if(save_config_buffer())
975 #ifdef HAVE_REMOTE_LCD
976 lcd_remote_clear_display();
978 #ifdef HAVE_LCD_CHARCELLS
979 lcd_puts(0, 0, str(LANG_SETTINGS_SAVE_PLAYER
));
980 lcd_puts(0, 1, str(LANG_SETTINGS_BATTERY_PLAYER
));
982 lcd_puts(4, 2, str(LANG_SETTINGS_SAVE_RECORDER
));
983 lcd_puts(2, 4, str(LANG_SETTINGS_BATTERY_RECORDER
));
985 #ifdef HAVE_REMOTE_LCD
986 lcd_remote_puts(4, 2, str(LANG_SETTINGS_SAVE_RECORDER
));
987 lcd_remote_puts(2, 4, str(LANG_SETTINGS_BATTERY_RECORDER
));
997 #ifdef HAVE_LCD_BITMAP
999 * Applies the range infos stored in global_settings to
1002 void settings_apply_pm_range(void)
1006 /* depending on the scale mode (dBfs or percent) the values
1007 of global_settings.peak_meter_dbfs have different meanings */
1008 if (global_settings
.peak_meter_dbfs
)
1010 /* convert to dBfs * 100 */
1011 pm_min
= -(((int)global_settings
.peak_meter_min
) * 100);
1012 pm_max
= -(((int)global_settings
.peak_meter_max
) * 100);
1016 /* percent is stored directly -> no conversion */
1017 pm_min
= global_settings
.peak_meter_min
;
1018 pm_max
= global_settings
.peak_meter_max
;
1021 /* apply the range */
1022 peak_meter_init_range(global_settings
.peak_meter_dbfs
, pm_min
, pm_max
);
1024 #endif /* HAVE_LCD_BITMAP */
1026 void sound_settings_apply(void)
1028 sound_set(SOUND_BASS
, global_settings
.bass
);
1029 sound_set(SOUND_TREBLE
, global_settings
.treble
);
1030 sound_set(SOUND_BALANCE
, global_settings
.balance
);
1031 sound_set(SOUND_VOLUME
, global_settings
.volume
);
1032 #if CONFIG_CODEC == SWCODEC
1033 channels_set(global_settings
.channel_config
);
1034 stereo_width_set(global_settings
.stereo_width
);
1036 sound_set(SOUND_CHANNELS
, global_settings
.channel_config
);
1037 sound_set(SOUND_STEREO_WIDTH
, global_settings
.stereo_width
);
1039 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
1040 sound_set(SOUND_LOUDNESS
, global_settings
.loudness
);
1041 sound_set(SOUND_AVC
, global_settings
.avc
);
1042 sound_set(SOUND_MDB_STRENGTH
, global_settings
.mdb_strength
);
1043 sound_set(SOUND_MDB_HARMONICS
, global_settings
.mdb_harmonics
);
1044 sound_set(SOUND_MDB_CENTER
, global_settings
.mdb_center
);
1045 sound_set(SOUND_MDB_SHAPE
, global_settings
.mdb_shape
);
1046 sound_set(SOUND_MDB_ENABLE
, global_settings
.mdb_enable
);
1047 sound_set(SOUND_SUPERBASS
, global_settings
.superbass
);
1051 void settings_apply(void)
1054 #if CONFIG_CODEC == SWCODEC
1058 sound_settings_apply();
1060 audio_set_buffer_margin(global_settings
.buffer_margin
);
1062 #ifdef HAVE_LCD_CONTRAST
1063 lcd_set_contrast(global_settings
.contrast
);
1065 lcd_scroll_speed(global_settings
.scroll_speed
);
1066 #ifdef HAVE_REMOTE_LCD
1067 lcd_remote_set_contrast(global_settings
.remote_contrast
);
1068 lcd_remote_set_invert_display(global_settings
.remote_invert
);
1069 lcd_remote_set_flip(global_settings
.remote_flip_display
);
1070 lcd_remote_scroll_speed(global_settings
.remote_scroll_speed
);
1071 lcd_remote_scroll_step(global_settings
.remote_scroll_step
);
1072 lcd_remote_scroll_delay(global_settings
.remote_scroll_delay
* (HZ
/10));
1073 lcd_remote_bidir_scroll(global_settings
.remote_bidir_limit
);
1074 #ifdef HAVE_REMOTE_LCD_TICKING
1075 lcd_remote_emireduce(global_settings
.remote_reduce_ticking
);
1077 remote_backlight_set_timeout(global_settings
.remote_backlight_timeout
);
1078 #ifdef CONFIG_CHARGING
1079 remote_backlight_set_timeout_plugged(global_settings
.remote_backlight_timeout_plugged
);
1082 #ifdef CONFIG_BACKLIGHT
1083 backlight_set_timeout(global_settings
.backlight_timeout
);
1084 #ifdef CONFIG_CHARGING
1085 backlight_set_timeout_plugged(global_settings
.backlight_timeout_plugged
);
1087 #if defined(HAVE_BACKLIGHT_PWM_FADING) && !defined(SIMULATOR)
1088 backlight_set_fade_in(global_settings
.backlight_fade_in
);
1089 backlight_set_fade_out(global_settings
.backlight_fade_out
);
1092 #ifdef HAVE_BACKLIGHT_BRIGHTNESS
1093 backlight_set_brightness(global_settings
.brightness
);
1095 ata_spindown(global_settings
.disk_spindown
);
1096 #if (CONFIG_CODEC == MAS3507D) && !defined(SIMULATOR)
1097 dac_line_in(global_settings
.line_in
);
1099 mpeg_id3_options(global_settings
.id3_v1_first
);
1100 #ifdef HAVE_ATA_POWER_OFF
1101 ata_poweroff(global_settings
.disk_poweroff
);
1104 set_poweroff_timeout(global_settings
.poweroff
);
1106 set_battery_capacity(global_settings
.battery_capacity
);
1107 #if BATTERY_TYPES_COUNT > 1
1108 set_battery_type(global_settings
.battery_type
);
1111 #ifdef HAVE_LCD_BITMAP
1112 lcd_set_invert_display(global_settings
.invert
);
1113 lcd_set_flip(global_settings
.flip_display
);
1114 button_set_flip(global_settings
.flip_display
);
1115 lcd_update(); /* refresh after flipping the screen */
1116 settings_apply_pm_range();
1117 peak_meter_init_times(
1118 global_settings
.peak_meter_release
, global_settings
.peak_meter_hold
,
1119 global_settings
.peak_meter_clip_hold
);
1122 #ifdef HAVE_LCD_COLOR
1123 unload_wps_backdrop();
1125 if ( global_settings
.wps_file
[0] &&
1126 global_settings
.wps_file
[0] != 0xff ) {
1127 snprintf(buf
, sizeof buf
, WPS_DIR
"/%s.wps",
1128 global_settings
.wps_file
);
1129 wps_data_load(gui_wps
[0].data
, buf
, true);
1133 wps_data_init(gui_wps
[0].data
);
1136 #ifdef HAVE_LCD_COLOR
1137 if ( global_settings
.backdrop_file
[0] &&
1138 global_settings
.backdrop_file
[0] != 0xff ) {
1139 snprintf(buf
, sizeof buf
, BACKDROP_DIR
"/%s.bmp",
1140 global_settings
.backdrop_file
);
1141 load_main_backdrop(buf
);
1143 unload_main_backdrop();
1145 show_main_backdrop();
1147 screens
[SCREEN_MAIN
].set_foreground(global_settings
.fg_color
);
1148 screens
[SCREEN_MAIN
].set_background(global_settings
.bg_color
);
1151 #if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1)
1152 if ( global_settings
.rwps_file
[0] &&
1153 global_settings
.rwps_file
[0] != 0xff ) {
1154 snprintf(buf
, sizeof buf
, WPS_DIR
"/%s.rwps",
1155 global_settings
.rwps_file
);
1156 wps_data_load(gui_wps
[1].data
, buf
, true);
1159 wps_data_init(gui_wps
[1].data
);
1162 #ifdef HAVE_LCD_BITMAP
1163 if ( global_settings
.font_file
[0] &&
1164 global_settings
.font_file
[0] != 0xff ) {
1165 snprintf(buf
, sizeof buf
, ROCKBOX_DIR FONT_DIR
"/%s.fnt",
1166 global_settings
.font_file
);
1172 if ( global_settings
.kbd_file
[0] &&
1173 global_settings
.kbd_file
[0] != 0xff ) {
1174 snprintf(buf
, sizeof buf
, ROCKBOX_DIR
"/%s.kbd",
1175 global_settings
.kbd_file
);
1181 lcd_scroll_step(global_settings
.scroll_step
);
1182 gui_list_screen_scroll_step(global_settings
.screen_scroll_step
);
1183 gui_list_screen_scroll_out_of_view(global_settings
.offset_out_of_view
);
1185 lcd_jump_scroll(global_settings
.jump_scroll
);
1186 lcd_jump_scroll_delay(global_settings
.jump_scroll_delay
* (HZ
/10));
1188 lcd_bidir_scroll(global_settings
.bidir_limit
);
1189 lcd_scroll_delay(global_settings
.scroll_delay
* (HZ
/10));
1191 if ( global_settings
.lang_file
[0] &&
1192 global_settings
.lang_file
[0] != 0xff ) {
1193 snprintf(buf
, sizeof buf
, ROCKBOX_DIR LANG_DIR
"/%s.lng",
1194 global_settings
.lang_file
);
1196 talk_init(); /* use voice of same language */
1199 set_codepage(global_settings
.default_codepage
);
1201 #if CONFIG_CODEC == SWCODEC
1202 audio_set_crossfade(global_settings
.crossfade
);
1203 dsp_set_replaygain(true);
1204 dsp_set_crossfeed(global_settings
.crossfeed
);
1205 dsp_set_crossfeed_direct_gain(global_settings
.crossfeed_direct_gain
);
1206 dsp_set_crossfeed_cross_params(global_settings
.crossfeed_cross_gain
,
1207 global_settings
.crossfeed_cross_gain
1208 + global_settings
.crossfeed_hf_attenuation
,
1209 global_settings
.crossfeed_hf_cutoff
);
1211 dsp_set_eq(global_settings
.eq_enabled
);
1212 dsp_set_eq_precut(global_settings
.eq_precut
);
1213 /* Update all EQ bands */
1214 for(i
= 0; i
< 5; i
++) {
1215 dsp_set_eq_coefs(i
);
1219 #ifdef HAVE_SPDIF_POWER
1220 spdif_power_enable(global_settings
.spdif_enable
);
1223 #ifdef CONFIG_BACKLIGHT
1224 set_backlight_filter_keypress(global_settings
.bl_filter_first_keypress
);
1225 #ifdef HAVE_REMOTE_LCD
1226 set_remote_backlight_filter_keypress(global_settings
.remote_bl_filter_first_keypress
);
1228 #ifdef HAS_BUTTON_HOLD
1229 backlight_set_on_button_hold(global_settings
.backlight_on_button_hold
);
1231 #ifdef HAVE_LCD_SLEEP
1232 lcd_set_sleep_after_backlight_off(global_settings
.lcd_sleep_after_backlight_off
);
1234 #endif /* CONFIG_BACKLIGHT */
1238 /* helper to load global_settings from a bitfield, as described per table */
1239 static void load_bit_table(const struct bit_entry
* p_table
, int count
, int bitstart
)
1241 uint32_t *p_bitfield
= (uint32_t *)config_block
; /* 32 bit addr. */
1242 uint32_t value
; /* 32 bit content */
1244 int maxbit
; /* how many bits are valid in the saved part */
1245 const struct bit_entry
* p_run
= p_table
; /* start after the size info */
1246 count
--; /* first is excluded from loop */
1247 maxbit
= get_bits(p_bitfield
, bitstart
, p_table
->bit_size
);
1248 bitstart
+= p_table
->bit_size
;
1250 for (i
=0; i
<count
; i
++)
1255 size
= p_run
->bit_size
& 0x3F; /* mask off abused bits */
1256 if (bitstart
+ size
> maxbit
)
1257 break; /* exit if this is not valid any more in bitfield */
1259 value
= get_bits(p_bitfield
, bitstart
, size
);
1261 if (p_run
->bit_size
& SIGNED
)
1262 { // sign extend the read value
1263 unsigned long mask
= 0xFFFFFFFF << (size
- 1);
1264 if (value
& mask
) /* true if MSB of value is set */
1268 /* could do a memcpy, but that would be endian-dependent */
1269 switch(p_run
->byte_size
)
1272 ((uint8_t *)&global_settings
)[p_run
->settings_offset
] =
1273 (unsigned char)value
;
1276 ((uint16_t *)&global_settings
)[p_run
->settings_offset
/2] =
1277 (unsigned short)value
;
1280 ((uint32_t *)&global_settings
)[p_run
->settings_offset
/4] =
1281 (unsigned int)value
;
1284 DEBUGF( "load_bit_table: illegal size!\n" );
1292 * load settings from disk or RTC RAM
1294 void settings_load(int which
)
1297 DEBUGF( "reload_all_settings()\n" );
1299 /* load the buffer from the RTC (resets it to all-unused if the block
1300 is invalid) and decode the settings which are set in the block */
1301 if (!load_config_buffer(which
))
1303 /* load scalar values from RTC and HD sector, specified via table */
1304 if (which
& SETTINGS_RTC
)
1306 load_bit_table(rtc_bits
, sizeof(rtc_bits
)/sizeof(rtc_bits
[0]), 4*8);
1308 if (which
& SETTINGS_HD
)
1310 load_bit_table(hd_bits
, sizeof(hd_bits
)/sizeof(hd_bits
[0]),
1314 #ifdef HAVE_LCD_CONTRAST
1315 if ( global_settings
.contrast
< MIN_CONTRAST_SETTING
)
1316 global_settings
.contrast
= lcd_default_contrast();
1320 strncpy((char *)global_settings
.wps_file
, (char *)&config_block
[i
],
1323 strncpy((char *)global_settings
.lang_file
, (char *)&config_block
[i
],
1326 strncpy((char *)global_settings
.font_file
, (char *)&config_block
[i
],
1329 #ifdef HAVE_REMOTE_LCD
1330 strncpy((char *)global_settings
.rwps_file
, (char *)&config_block
[i
],
1336 strncpy((char *)global_settings
.fmr_file
, (char *)&config_block
[i
],
1341 #ifdef HAVE_LCD_COLOR
1342 strncpy((char *)global_settings
.backdrop_file
, (char *)&config_block
[i
],
1346 #ifdef HAVE_LCD_BITMAP
1347 strncpy((char *)global_settings
.kbd_file
, (char *)&config_block
[i
],
1354 void set_file(char* filename
, char* setting
, int maxlen
)
1356 char* fptr
= strrchr(filename
,'/');
1369 while ((*ptr
!= '.') && (ptr
!= fptr
)) {
1373 if(ptr
== fptr
) extlen
= 0;
1375 if (strncasecmp(ROCKBOX_DIR
, filename
,strlen(ROCKBOX_DIR
)) ||
1376 (len
-extlen
> maxlen
))
1379 strncpy(setting
, fptr
, len
-extlen
);
1380 setting
[len
-extlen
]=0;
1385 /* helper to sort a .cfg file entry into a global_settings member,
1386 as described per table. Returns the position if found, else 0. */
1387 static int load_cfg_table(
1388 const struct bit_entry
* p_table
, /* the table which describes the entries */
1389 int count
, /* number of entries in the table, including the first */
1390 const char* name
, /* the item to be searched */
1391 const char* value
, /* the value which got loaded for that item */
1392 int hint
) /* position to start looking */
1398 if (p_table
[i
].cfg_name
!= NULL
&& !strcasecmp(name
, p_table
[i
].cfg_name
))
1401 if (p_table
[i
].cfg_val
== NULL
)
1402 { /* numerical value, just convert the string */
1406 else if (!strncasecmp(p_table
[i
].cfg_val
,"rgb",4))
1408 val
= hex_to_rgb(value
);
1412 { /* set of string values, find the index */
1415 int len
= strlen(value
);
1417 item
= run
= p_table
[i
].cfg_val
;
1421 /* count the length of the field */
1422 while (*run
!= ',' && *run
!= '\0')
1425 if (!strncasecmp(value
, item
, MAX(run
-item
, len
)))
1426 break; /* match, exit the search */
1428 if (*run
== '\0') /* reached the end of the choices */
1429 return i
; /* return the position, but don't update */
1431 val
++; /* count the item up */
1432 run
++; /* behind the ',' */
1437 /* could do a memcpy, but that would be endian-dependent */
1438 switch(p_table
[i
].byte_size
)
1441 ((unsigned char*)&global_settings
)[p_table
[i
].settings_offset
] =
1445 ((unsigned short*)&global_settings
)[p_table
[i
].settings_offset
/2] =
1446 (unsigned short)val
;
1449 ((unsigned int*)&global_settings
)[p_table
[i
].settings_offset
/4] =
1453 DEBUGF( "illegal size!" );
1457 return i
; /* return the position */
1462 i
=1; /* wraparound */
1463 } while (i
!= hint
); /* back where we started, all searched */
1465 return 0; /* indicate not found */
1469 bool settings_load_config(const char* file
)
1474 fd
= open(file
, O_RDONLY
);
1478 while (read_line(fd
, line
, sizeof line
) > 0)
1482 const struct bit_entry
* table
[2] = { rtc_bits
, hd_bits
};
1483 const int ta_size
[2] = {
1484 sizeof(rtc_bits
)/sizeof(rtc_bits
[0]),
1485 sizeof(hd_bits
)/sizeof(hd_bits
[0])
1487 int last_table
= 0; /* which table was used last round */
1488 int last_pos
= 1; /* at which position did we succeed */
1489 int pos
; /* currently returned position */
1491 if (!settings_parseline(line
, &name
, &value
))
1494 /* check for the string values */
1495 if (!strcasecmp(name
, "wps")) {
1496 #ifdef HAVE_LCD_COLOR
1497 unload_wps_backdrop();
1499 if (wps_data_load(gui_wps
[0].data
, value
, true))
1500 set_file(value
, (char *)global_settings
.wps_file
, MAX_FILENAME
);
1502 #if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1)
1503 else if (!strcasecmp(name
, "rwps")) {
1504 if (wps_data_load(gui_wps
[1].data
, value
, true))
1505 set_file(value
, (char *)global_settings
.rwps_file
, MAX_FILENAME
);
1508 else if (!strcasecmp(name
, "lang")) {
1509 if (!lang_load(value
))
1511 set_file(value
, (char *)global_settings
.lang_file
, MAX_FILENAME
);
1512 talk_init(); /* use voice of same language */
1516 else if (!strcasecmp(name
, "fmr")) {
1517 set_file(value
, global_settings
.fmr_file
, MAX_FILENAME
);
1520 #ifdef HAVE_LCD_BITMAP
1521 else if (!strcasecmp(name
, "font")) {
1522 if (font_load(value
))
1523 set_file(value
, (char *)global_settings
.font_file
, MAX_FILENAME
);
1526 #ifdef HAVE_LCD_COLOR
1527 else if (!strcasecmp(name
, "backdrop")) {
1528 if (load_main_backdrop(value
)) {
1529 set_file(value
, (char *)global_settings
.backdrop_file
, MAX_FILENAME
);
1530 show_main_backdrop();
1534 #ifdef HAVE_LCD_BITMAP
1535 else if (!strcasecmp(name
, "keyboard")) {
1536 if (!load_kbd(value
))
1537 set_file(value
, (char *)global_settings
.kbd_file
, MAX_FILENAME
);
1542 /* check for scalar values, using the two tables */
1543 pos
= load_cfg_table(table
[last_table
], ta_size
[last_table
],
1544 name
, value
, last_pos
);
1545 if (pos
) /* success */
1547 last_pos
= pos
; /* remember as a position hint for next round */
1551 last_table
= 1-last_table
; /* try other table */
1552 last_pos
= 1; /* search from start */
1553 pos
= load_cfg_table(table
[last_table
], ta_size
[last_table
],
1554 name
, value
, last_pos
);
1555 if (pos
) /* success */
1557 last_pos
= pos
; /* remember as a position hint for next round */
1569 /* helper to save content of global_settings into a file,
1570 as described per table */
1571 static void save_cfg_table(const struct bit_entry
* p_table
, int count
, int fd
)
1573 long value
; /* 32 bit content */
1575 const struct bit_entry
* p_run
= p_table
; /* start after the size info */
1576 count
--; /* first is excluded from loop */
1578 for (i
=0; i
<count
; i
++)
1582 if (p_run
->cfg_name
== NULL
)
1583 continue; /* this value is not to be saved */
1585 /* could do a memcpy, but that would be endian-dependent */
1586 switch(p_run
->byte_size
)
1589 if (p_run
->bit_size
& SIGNED
) /* signed? */
1590 value
= ((char*)&global_settings
)[p_run
->settings_offset
];
1592 value
= ((unsigned char*)&global_settings
)[p_run
->settings_offset
];
1595 if (p_run
->bit_size
& SIGNED
) /* signed? */
1596 value
= ((short*)&global_settings
)[p_run
->settings_offset
/2];
1598 value
= ((unsigned short*)&global_settings
)[p_run
->settings_offset
/2];
1601 value
= ((unsigned int*)&global_settings
)[p_run
->settings_offset
/4];
1604 DEBUGF( "illegal size!" );
1608 if (p_run
->cfg_val
== NULL
) /* write as number */
1610 fdprintf(fd
, "%s: %ld\r\n", p_run
->cfg_name
, value
);
1612 #ifdef HAVE_LCD_COLOR
1613 else if (!strcasecmp(p_run
->cfg_val
, "rgb"))
1615 fdprintf(fd
, "%s: %02x%02x%02x\r\n", p_run
->cfg_name
,
1616 (int)RGB_UNPACK_RED(value
),
1617 (int)RGB_UNPACK_GREEN(value
),
1618 (int)RGB_UNPACK_BLUE(value
));
1621 else /* write as item */
1623 const char* p
= p_run
->cfg_val
;
1625 fdprintf(fd
, "%s: ", p_run
->cfg_name
);
1629 char c
= *p
++; /* currently processed char */
1630 if (c
== ',') /* separator */
1632 else if (c
== '\0') /* end of string */
1633 break; /* not found */
1634 else if (value
== 0) /* the right place */
1635 write(fd
, &c
, 1); /* char by char, this is lame, OK */
1638 fdprintf(fd
, "\r\n");
1639 if (p_run
->cfg_val
!= off_on
) /* explaination for non-bool */
1640 fdprintf(fd
, "# (possible values: %s)\r\n", p_run
->cfg_val
);
1646 bool settings_save_config(void)
1649 char filename
[MAX_PATH
];
1651 create_numbered_filename(filename
, ROCKBOX_DIR
, "config", ".cfg", 2);
1653 /* allow user to modify filename */
1655 if (!kbd_input(filename
, sizeof filename
)) {
1656 fd
= creat(filename
, O_WRONLY
);
1658 gui_syncsplash(HZ
, true, str(LANG_FAILED
));
1663 gui_syncsplash(HZ
, true, str(LANG_MENU_SETTING_CANCEL
));
1668 fdprintf(fd
, "# .cfg file created by rockbox %s - "
1669 "http://www.rockbox.org\r\n#\r\n#\r\n# wps / rwps / language"
1670 " / font / fmpreset / backdrop \r\n#\r\n", appsversion
);
1672 if (global_settings
.wps_file
[0] != 0)
1673 fdprintf(fd
, "wps: %s/%s.wps\r\n", WPS_DIR
,
1674 global_settings
.wps_file
);
1676 #ifdef HAVE_REMOTE_LCD
1677 if (global_settings
.rwps_file
[0] != 0)
1678 fdprintf(fd
, "rwps: %s/%s.rwps\r\n", WPS_DIR
,
1679 global_settings
.rwps_file
);
1682 if (global_settings
.lang_file
[0] != 0)
1683 fdprintf(fd
, "lang: %s/%s.lng\r\n", ROCKBOX_DIR LANG_DIR
,
1684 global_settings
.lang_file
);
1686 #ifdef HAVE_LCD_BITMAP
1687 if (global_settings
.font_file
[0] != 0)
1688 fdprintf(fd
, "font: %s/%s.fnt\r\n", ROCKBOX_DIR FONT_DIR
,
1689 global_settings
.font_file
);
1692 #ifdef HAVE_LCD_COLOR
1693 if (global_settings
.backdrop_file
[0] != 0)
1694 fdprintf(fd
, "backdrop: %s/%s.bmp\r\n", BACKDROP_DIR
,
1695 global_settings
.backdrop_file
);
1699 if (global_settings
.fmr_file
[0] != 0)
1700 fdprintf(fd
, "fmr: %s/%s.fmr\r\n", FMPRESET_PATH
,
1701 global_settings
.fmr_file
);
1704 #ifdef HAVE_LCD_BITMAP
1705 if (global_settings
.kbd_file
[0] != 0)
1706 fdprintf(fd
, "keyboard: %s/%s.kbd\r\n", ROCKBOX_DIR
,
1707 global_settings
.kbd_file
);
1710 /* here's the action: write values to file, specified via table */
1711 save_cfg_table(rtc_bits
, sizeof(rtc_bits
)/sizeof(rtc_bits
[0]), fd
);
1712 save_cfg_table(hd_bits
, sizeof(hd_bits
)/sizeof(hd_bits
[0]), fd
);
1716 gui_syncsplash(HZ
, true, str(LANG_SETTINGS_SAVED
));
1721 /* helper to load defaults from table into global_settings members */
1722 static void default_table(const struct bit_entry
* p_table
, int count
)
1726 for (i
=1; i
<count
; i
++) /* exclude the first, the size placeholder */
1728 /* could do a memcpy, but that would be endian-dependent */
1729 switch(p_table
[i
].byte_size
)
1732 ((unsigned char*)&global_settings
)[p_table
[i
].settings_offset
] =
1733 (unsigned char)p_table
[i
].default_val
;
1736 ((unsigned short*)&global_settings
)[p_table
[i
].settings_offset
/2] =
1737 (unsigned short)p_table
[i
].default_val
;
1740 ((unsigned int*)&global_settings
)[p_table
[i
].settings_offset
/4] =
1741 (unsigned int)p_table
[i
].default_val
;
1744 DEBUGF( "illegal size!" );
1752 * reset all settings to their default value
1754 void settings_reset(void) {
1756 DEBUGF( "settings_reset()\n" );
1758 /* read defaults from table(s) into global_settings */
1759 default_table(rtc_bits
, sizeof(rtc_bits
)/sizeof(rtc_bits
[0]));
1760 default_table(hd_bits
, sizeof(hd_bits
)/sizeof(hd_bits
[0]));
1762 /* do some special cases not covered by table */
1763 global_settings
.volume
= sound_default(SOUND_VOLUME
);
1764 global_settings
.balance
= sound_default(SOUND_BALANCE
);
1765 global_settings
.bass
= sound_default(SOUND_BASS
);
1766 global_settings
.treble
= sound_default(SOUND_TREBLE
);
1767 global_settings
.channel_config
= sound_default(SOUND_CHANNELS
);
1768 global_settings
.stereo_width
= sound_default(SOUND_STEREO_WIDTH
);
1769 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
1770 global_settings
.loudness
= sound_default(SOUND_LOUDNESS
);
1771 global_settings
.avc
= sound_default(SOUND_AVC
);
1772 global_settings
.mdb_strength
= sound_default(SOUND_MDB_STRENGTH
);
1773 global_settings
.mdb_harmonics
= sound_default(SOUND_MDB_HARMONICS
);
1774 global_settings
.mdb_center
= sound_default(SOUND_MDB_CENTER
);
1775 global_settings
.mdb_shape
= sound_default(SOUND_MDB_SHAPE
);
1776 global_settings
.mdb_enable
= sound_default(SOUND_MDB_ENABLE
);
1777 global_settings
.superbass
= sound_default(SOUND_SUPERBASS
);
1779 #ifdef HAVE_LCD_CONTRAST
1780 global_settings
.contrast
= lcd_default_contrast();
1782 #ifdef HAVE_LCD_REMOTE
1783 global_settings
.remote_contrast
= lcd_remote_default_contrast();
1787 global_settings
.fmr_file
[0] = '\0';
1789 global_settings
.wps_file
[0] = '\0';
1790 #ifdef HAVE_REMOTE_LCD
1791 global_settings
.rwps_file
[0] = '\0';
1793 global_settings
.font_file
[0] = '\0';
1794 global_settings
.lang_file
[0] = '\0';
1795 #ifdef HAVE_LCD_COLOR
1796 global_settings
.backdrop_file
[0] = '\0';
1798 global_settings
.fg_color
= LCD_DEFAULT_FG
;
1799 global_settings
.bg_color
= LCD_DEFAULT_BG
;
1801 #ifdef HAVE_LCD_BITMAP
1802 global_settings
.kbd_file
[0] = '\0';
1804 global_settings
.hold_lr_for_scroll_in_list
= true;
1807 bool set_bool(const char* string
, bool* variable
)
1809 return set_bool_options(string
, variable
,
1810 (char *)STR(LANG_SET_BOOL_YES
),
1811 (char *)STR(LANG_SET_BOOL_NO
),
1815 /* wrapper to convert from int param to bool param in set_option */
1816 static void (*boolfunction
)(bool);
1817 void bool_funcwrapper(int value
)
1822 boolfunction(false);
1825 bool set_bool_options(const char* string
, bool* variable
,
1826 const char* yes_str
, int yes_voice
,
1827 const char* no_str
, int no_voice
,
1828 void (*function
)(bool))
1830 struct opt_items names
[] = {
1831 {(unsigned char *)no_str
, no_voice
},
1832 {(unsigned char *)yes_str
, yes_voice
}
1836 boolfunction
= function
;
1837 result
= set_option(string
, variable
, BOOL
, names
, 2,
1838 function
? bool_funcwrapper
: NULL
);
1842 void talk_unit(int unit
, int value
)
1844 if (global_settings
.talk_menu
)
1846 if (unit
< UNIT_LAST
)
1847 { /* use the available unit definition */
1848 talk_value(value
, unit
, false);
1851 { /* say the number, followed by an arbitrary voice ID */
1852 talk_number(value
, false);
1853 talk_id(unit
, true);
1858 struct value_setting_data
{
1859 enum optiontype type
;
1860 /* used for "value" settings.. */
1865 void (*formatter
)(char* dest
, int dest_length
,
1866 int variable
, const char* unit
);
1867 /* used for BOOL and "choice" settings */
1868 struct opt_items
* options
;
1871 char * value_setting_get_name_cb(int selected_item
,void * data
, char *buffer
)
1873 struct value_setting_data
* cb_data
=
1874 (struct value_setting_data
*)data
;
1875 if (cb_data
->type
== INT
&& !cb_data
->options
)
1877 int item
= cb_data
->max
-(selected_item
*cb_data
->step
);
1878 if (cb_data
->formatter
)
1879 cb_data
->formatter(buffer
, MAX_PATH
,item
,cb_data
->unit
);
1881 snprintf(buffer
, MAX_PATH
,"%d %s",item
,cb_data
->unit
);
1883 else strcpy(buffer
,P2STR(cb_data
->options
[selected_item
].string
));
1886 #define type_fromvoidptr(type, value) \
1888 (int)(*(int*)(value)) \
1890 (bool)(*(bool*)(value))
1891 bool do_set_setting(const unsigned char* string
, void *variable
,
1892 int nb_items
,int selected
,
1893 struct value_setting_data
*cb_data
,
1894 void (*function
)(int))
1898 struct gui_synclist lists
;
1901 if (cb_data
->type
== INT
)
1902 oldvalue
= *(int*)variable
;
1903 else oldvalue
= *(bool*)variable
;
1905 gui_synclist_init(&lists
,value_setting_get_name_cb
,(void*)cb_data
,false,1);
1906 gui_synclist_set_title(&lists
, (char*)string
, NOICON
);
1907 gui_synclist_set_icon_callback(&lists
,NULL
);
1908 gui_synclist_set_nb_items(&lists
,nb_items
);
1909 gui_synclist_limit_scroll(&lists
,true);
1910 gui_synclist_select_item(&lists
, selected
);
1912 if (global_settings
.talk_menu
)
1914 if (cb_data
->type
== INT
&& !cb_data
->options
)
1915 talk_unit(cb_data
->voice_unit
, *(int*)variable
);
1916 else talk_id(cb_data
->options
[selected
].voice_id
, false);
1919 gui_synclist_draw(&lists
);
1923 action
= get_action(CONTEXT_LIST
,TIMEOUT_BLOCK
);
1924 if (action
== ACTION_NONE
)
1927 if (gui_synclist_do_button(&lists
,action
))
1929 if (global_settings
.talk_menu
)
1932 if (cb_data
->type
== INT
&& !cb_data
->options
)
1934 value
= cb_data
->max
-
1935 gui_synclist_get_sel_pos(&lists
)*cb_data
->step
;
1936 talk_unit(cb_data
->voice_unit
, value
);
1940 value
= gui_synclist_get_sel_pos(&lists
);
1941 talk_id(cb_data
->options
[value
].voice_id
, false);
1944 if (cb_data
->type
== INT
&& !cb_data
->options
)
1945 *(int*)variable
= cb_data
->max
-
1946 gui_synclist_get_sel_pos(&lists
)*cb_data
->step
;
1947 else if (cb_data
->type
== BOOL
)
1948 *(bool*)variable
= gui_synclist_get_sel_pos(&lists
) ? true : false;
1949 else *(int*)variable
= gui_synclist_get_sel_pos(&lists
);
1951 else if (action
== ACTION_STD_CANCEL
)
1953 gui_syncsplash(HZ
/2,true,str(LANG_MENU_SETTING_CANCEL
));
1954 if (cb_data
->type
== INT
)
1955 *(int*)variable
= oldvalue
;
1956 else *(bool*)variable
= (bool)oldvalue
;
1959 else if (action
== ACTION_STD_OK
)
1963 else if(default_event_handler(action
) == SYS_USB_CONNECTED
)
1965 gui_syncstatusbar_draw(&statusbars
, false);
1967 function(type_fromvoidptr(cb_data
->type
,variable
));
1971 bool set_int(const unsigned char* string
,
1975 void (*function
)(int),
1979 void (*formatter
)(char*, int, int, const char*) )
1981 struct value_setting_data data
= {
1982 INT
,max
, step
, voice_unit
,unit
,formatter
,NULL
};
1983 return do_set_setting(string
,variable
,(max
-min
)/step
+ 1,
1984 (max
-*variable
)/step
, &data
,function
);
1987 /* NOTE: the 'type' parameter specifies the actual type of the variable
1988 that 'variable' points to. not the value within. Only variables with
1989 type 'bool' should use parameter BOOL.
1991 The type separation is necessary since int and bool are fundamentally
1992 different and bit-incompatible types and can not share the same access
1994 bool set_option(const char* string
, void* variable
, enum optiontype type
,
1995 const struct opt_items
* options
, int numoptions
, void (*function
)(int))
1997 struct value_setting_data data
= {
1998 type
,0, 0, 0,NULL
,NULL
,(struct opt_items
*)options
};
2001 selected
= *(bool*)variable
? 1 : 0;
2002 else selected
= *(int*)variable
;
2003 return do_set_setting(string
,variable
,numoptions
,
2004 selected
, &data
,function
);
2007 #ifdef HAVE_RECORDING
2008 /* This array holds the record timer interval lengths, in seconds */
2009 static const unsigned long rec_timer_seconds
[] =
2011 0, /* 0 means OFF */
2019 2*60*60, /* 02:00 */
2020 4*60*60, /* 04:00 */
2021 6*60*60, /* 06:00 */
2022 8*60*60, /* 08:00 */
2023 10L*60*60, /* 10:00 */
2024 12L*60*60, /* 12:00 */
2025 18L*60*60, /* 18:00 */
2026 24L*60*60 /* 24:00 */
2029 unsigned int rec_timesplit_seconds(void)
2031 return rec_timer_seconds
[global_settings
.rec_timesplit
];
2034 /* This array holds the record size interval lengths, in bytes */
2035 static const unsigned long rec_size_bytes
[] =
2037 0, /* 0 means OFF */
2038 5*1024*1024, /* 5MB */
2039 10*1024*1024, /* 10MB */
2040 15*1024*1024, /* 15MB */
2041 32*1024*1024, /* 32MB */
2042 64*1024*1024, /* 64MB */
2043 75*1024*1024, /* 75MB */
2044 100*1024*1024, /* 100MB */
2045 128*1024*1024, /* 128MB */
2046 256*1024*1024, /* 256MB */
2047 512*1024*1024, /* 512MB */
2048 650*1024*1024, /* 650MB */
2049 700*1024*1024, /* 700MB */
2050 1024*1024*1024, /* 1GB */
2051 1536*1024*1024, /* 1.5GB */
2052 1792*1024*1024, /* 1.75GB */
2055 unsigned long rec_sizesplit_bytes(void)
2057 return rec_size_bytes
[global_settings
.rec_sizesplit
];
2060 * Time strings used for the trigger durations.
2061 * Keep synchronous to trigger_times in settings_apply_trigger
2063 const char * const trig_durations
[TRIG_DURATION_COUNT
] =
2065 "0s", "1s", "2s", "5s",
2066 "10s", "15s", "20s", "25s", "30s",
2067 "1min", "2min", "5min", "10min"
2070 void settings_apply_trigger(void)
2072 /* Keep synchronous to trig_durations and trig_durations_conf*/
2073 static const long trigger_times
[TRIG_DURATION_COUNT
] = {
2075 10*HZ
, 15*HZ
, 20*HZ
, 25*HZ
, 30*HZ
,
2076 60*HZ
, 2*60*HZ
, 5*60*HZ
, 10*60*HZ
2079 peak_meter_define_trigger(
2080 global_settings
.rec_start_thres
,
2081 trigger_times
[global_settings
.rec_start_duration
],
2082 MIN(trigger_times
[global_settings
.rec_start_duration
] / 2, 2*HZ
),
2083 global_settings
.rec_stop_thres
,
2084 trigger_times
[global_settings
.rec_stop_postrec
],
2085 trigger_times
[global_settings
.rec_stop_gap
]