diff options
author | Jonathan Gordon <rockbox@jdgordon.info> | 2007-01-23 13:40:44 +0000 |
---|---|---|
committer | Jonathan Gordon <rockbox@jdgordon.info> | 2007-01-23 13:40:44 +0000 |
commit | b2e50906a4af3176d03dff98af4a260709bdad96 (patch) | |
tree | 20aaf0305d399a1a5fef3d960b219415d2651c61 /apps/settings.c | |
parent | 9011c065a462c55627457aedff36a46a762fe5ce (diff) | |
download | rockbox-b2e50906a4af3176d03dff98af4a260709bdad96.tar.gz rockbox-b2e50906a4af3176d03dff98af4a260709bdad96.zip |
Settings are now stored in /.rockbox/config.cfg instead of the hidden sector. (FS #6557)
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12093 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/settings.c')
-rw-r--r-- | apps/settings.c | 1714 |
1 files changed, 309 insertions, 1405 deletions
diff --git a/apps/settings.c b/apps/settings.c index 4ef2f1486e..01ede41b3e 100644 --- a/apps/settings.c +++ b/apps/settings.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include "kernel.h" | 25 | #include "kernel.h" |
26 | #include "thread.h" | 26 | #include "thread.h" |
27 | #include "action.h" | 27 | #include "action.h" |
28 | #include "crc32.h" | ||
28 | #include "settings.h" | 29 | #include "settings.h" |
29 | #include "disk.h" | 30 | #include "disk.h" |
30 | #include "panic.h" | 31 | #include "panic.h" |
@@ -72,6 +73,7 @@ | |||
72 | #include "statusbar.h" | 73 | #include "statusbar.h" |
73 | #include "splash.h" | 74 | #include "splash.h" |
74 | #include "list.h" | 75 | #include "list.h" |
76 | #include "settings_list.h" | ||
75 | #if LCD_DEPTH > 1 | 77 | #if LCD_DEPTH > 1 |
76 | #include "backdrop.h" | 78 | #include "backdrop.h" |
77 | #endif | 79 | #endif |
@@ -100,9 +102,7 @@ const char rec_base_directory[] = REC_BASE_DIR; | |||
100 | #include "eq_menu.h" | 102 | #include "eq_menu.h" |
101 | #endif | 103 | #endif |
102 | 104 | ||
103 | #define CONFIG_BLOCK_VERSION 59 | 105 | #define NVRAM_BLOCK_SIZE 44 |
104 | #define CONFIG_BLOCK_SIZE 512 | ||
105 | #define RTC_BLOCK_SIZE 44 | ||
106 | 106 | ||
107 | #ifdef HAVE_LCD_BITMAP | 107 | #ifdef HAVE_LCD_BITMAP |
108 | #define MAX_LINES 10 | 108 | #define MAX_LINES 10 |
@@ -115,644 +115,115 @@ const char rec_base_directory[] = REC_BASE_DIR; | |||
115 | #endif | 115 | #endif |
116 | 116 | ||
117 | long lasttime = 0; | 117 | long lasttime = 0; |
118 | static long config_sector = 0; /* mark uninitialized */ | ||
119 | static unsigned char config_block[CONFIG_BLOCK_SIZE]; | ||
120 | 118 | ||
121 | 119 | /* NVRAM stuff, if the target doesnt have NVRAM it is saved in ROCKBOX_DIR /nvram.bin */ | |
122 | /* descriptor for a configuration value */ | 120 | /* NVRAM is set out as |
123 | /* (watch the struct packing and member sizes to keep this small) */ | 121 | [0] 'R' |
124 | struct bit_entry | 122 | [1] 'b' |
125 | { | 123 | [2] version |
126 | /* how many bits within the bitfield (1-32), MSB set if value is signed */ | 124 | [3] stored variable count |
127 | unsigned char bit_size; /* min 6+1 bit */ | 125 | [4-7] crc32 checksum |
128 | /* how many bytes in the global_settings struct (1,2,4) */ | 126 | [8-NVRAM_BLOCK_SIZE] data |
129 | unsigned char byte_size; /* min 3 bits */ | ||
130 | /* store position in global_settings struct */ | ||
131 | short settings_offset; /* min 9 bit, better 10 */ | ||
132 | /* default value */ | ||
133 | int default_val; /* min 15 bit */ | ||
134 | /* variable name in a .cfg file, NULL if not to be saved */ | ||
135 | const char* cfg_name; | ||
136 | /* set of values, "rgb" for a color, or NULL for a numerical value */ | ||
137 | const char* cfg_val; | ||
138 | }; | ||
139 | |||
140 | /******************************************** | ||
141 | |||
142 | Config block as saved on the battery-packed RTC user RAM memory block | ||
143 | of 44 bytes, starting at offset 0x14 of the RTC memory space. | ||
144 | |||
145 | offset abs | ||
146 | 0x00 0x14 "Roc" header signature: 0x52 0x6f 0x63 | ||
147 | 0x03 0x17 <version byte: 0x0> | ||
148 | 0x04 0x18 start of bit-table | ||
149 | ... | ||
150 | 0x28,0x29 unused, not reachable by set_bits() without disturbing the next 2 | ||
151 | 0x2A,0x2B <checksum 2 bytes: xor of 0x00-0x29> | ||
152 | |||
153 | Config memory is reset to 0xff and initialized with 'factory defaults' if | ||
154 | a valid header & checksum is not found. Config version number is only | ||
155 | increased when information is _relocated_ or space is _reused_ so that old | ||
156 | versions can read and modify configuration changed by new versions. | ||
157 | Memory locations not used by a given version should not be | ||
158 | modified unless the header & checksum test fails. | ||
159 | |||
160 | Rest of config block, only saved to disk: | ||
161 | 0x2C start of 2nd bit-table | ||
162 | ... | ||
163 | 0xA4 (char[20]) FMR Preset file | ||
164 | 0xB8 (char[20]) WPS file | ||
165 | 0xCC (char[20]) Lang file | ||
166 | 0xE0 (char[20]) Font file | ||
167 | ... (char[20]) RWPS file (on targets supporting a Remote WPS) | ||
168 | ... (char[20]) Main backdrop file (on color LCD targets) | ||
169 | |||
170 | ... to 0x200 <unused> | ||
171 | |||
172 | *************************************/ | ||
173 | |||
174 | /* The persistence of the global_settings members is now controlled by | ||
175 | the two tables below, rtc_bits and hd_bits. | ||
176 | New values can just be added to the end, it will be backwards | ||
177 | compatible. If you however change order, bitsize, etc. of existing | ||
178 | entries, you need to bump CONFIG_BLOCK_VERSION to break compatibility. | ||
179 | */ | 127 | */ |
128 | #define NVRAM_DATA_START 8 | ||
129 | #define NVRAM_FILE ROCKBOX_DIR "/nvram.bin" | ||
130 | static char nvram_buffer[NVRAM_BLOCK_SIZE]; | ||
180 | 131 | ||
181 | 132 | static bool read_nvram_data(char* buf, int max_len) | |
182 | /* convenience macro for both size and offset of global_settings member */ | ||
183 | #define S_O(val) sizeof(global_settings.val), offsetof(struct user_settings, val) | ||
184 | #define SIGNED 0x80 /* for bitsize value with signed attribute */ | ||
185 | |||
186 | /* some sets of values which are used more than once, to save memory */ | ||
187 | static const char off_on[] = "off,on"; | ||
188 | static const char off_on_ask[] = "off,on,ask"; | ||
189 | static const char off_number_spell_hover[] = "off,number,spell,hover"; | ||
190 | #ifdef HAVE_LCD_BITMAP | ||
191 | static const char graphic_numeric[] = "graphic,numeric"; | ||
192 | #endif | ||
193 | |||
194 | #ifdef HAVE_RECORDING | ||
195 | /* keep synchronous to trig_durations and | ||
196 | trigger_times in settings_apply_trigger */ | ||
197 | static const char trig_durations_conf [] = | ||
198 | "0s,1s,2s,5s,10s,15s,20s,25s,30s,1min,2min,5min,10min"; | ||
199 | #endif | ||
200 | |||
201 | #if defined(CONFIG_BACKLIGHT) | ||
202 | static const char backlight_times_conf [] = | ||
203 | "off,on,1,2,3,4,5,6,7,8,9,10,15,20,25,30,45,60,90"; | ||
204 | #endif | ||
205 | |||
206 | /* the part of the settings which ends up in the RTC RAM, where available | ||
207 | (those we either need early, save frequently, or without spinup) */ | ||
208 | static const struct bit_entry rtc_bits[] = | ||
209 | { | 133 | { |
210 | /* placeholder, containing the size information */ | 134 | unsigned crc32 = 0xffffffff; |
211 | {9, 0, 0, 0, NULL, NULL }, /* 9 bit to tell how far this is populated */ | 135 | int var_count = 0, i = 0, buf_pos = 0; |
212 | 136 | #ifndef HAVE_RTC_RAM | |
213 | /* # of bits, offset+size, default, .cfg name, .cfg values */ | 137 | int fd = open(NVRAM_FILE,O_RDONLY); |
214 | /* sound */ | 138 | if (fd < 0) |
215 | #if CONFIG_CODEC == MAS3507D | 139 | return false; |
216 | {8 | SIGNED, S_O(volume), -18, "volume", NULL }, /* -78...+18 */ | 140 | memset(buf,0,max_len); |
217 | #else | 141 | if (read(fd,buf,max_len) < 8) /* min is 8 bytes,magic, ver, vars, crc32 */ |
218 | {8 | SIGNED, S_O(volume), -25, "volume", NULL }, /* -100...+12 / -84...0 */ | 142 | return false; |
219 | #endif | 143 | close(fd); |
220 | {8 | SIGNED, S_O(balance), 0, "balance", NULL }, /* -100...100 */ | ||
221 | #if CONFIG_CODEC != SWCODEC /* any MAS */ | ||
222 | {5 | SIGNED, S_O(bass), 0, "bass", NULL }, /* -15..+15 / -12..+12 */ | ||
223 | {5 | SIGNED, S_O(treble), 0, "treble", NULL }, /* -15..+15 / -12..+12 */ | ||
224 | #elif defined HAVE_UDA1380 | ||
225 | {5, S_O(bass), 0, "bass", NULL }, /* 0..+24 */ | ||
226 | {3, S_O(treble), 0, "treble", NULL }, /* 0..+6 */ | ||
227 | #elif defined(HAVE_WM8975) || defined(HAVE_WM8758) \ | ||
228 | || defined(HAVE_WM8731) || defined(HAVE_WM8721) \ | ||
229 | || defined(HAVE_WM8751) | ||
230 | {5 | SIGNED, S_O(bass), 0, "bass", NULL }, /* -6..+9 */ | ||
231 | {5 | SIGNED, S_O(treble), 0, "treble", NULL }, /* -6..+9 */ | ||
232 | #endif | ||
233 | #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) | ||
234 | {5, S_O(loudness), 0, "loudness", NULL }, /* 0...17 */ | ||
235 | {3, S_O(avc), 0, "auto volume", "off,20ms,2,4,8" }, | ||
236 | {1, S_O(superbass), false, "superbass", off_on }, | ||
237 | #endif | ||
238 | {3, S_O(channel_config), 0, "channels", | ||
239 | "stereo,mono,custom,mono left,mono right,karaoke" }, | ||
240 | {8, S_O(stereo_width), 100, "stereo width", NULL}, | ||
241 | /* playback */ | ||
242 | {1, S_O(resume), false, "resume", off_on }, | ||
243 | {1, S_O(playlist_shuffle), false, "shuffle", off_on }, | ||
244 | {16 | SIGNED, S_O(resume_index), -1, NULL, NULL }, | ||
245 | {16 | SIGNED, S_O(resume_first_index), 0, NULL, NULL }, | ||
246 | {32 | SIGNED, S_O(resume_offset), -1, NULL, NULL }, | ||
247 | {32 | SIGNED, S_O(resume_seed), -1, NULL, NULL }, | ||
248 | {3, S_O(repeat_mode), REPEAT_ALL, "repeat", "off,all,one,shuffle,ab" }, | ||
249 | /* LCD */ | ||
250 | #ifdef HAVE_LCD_CONTRAST | ||
251 | {6, S_O(contrast), DEFAULT_CONTRAST_SETTING, "contrast", NULL }, | ||
252 | #endif | ||
253 | #ifdef CONFIG_BACKLIGHT | ||
254 | {5, S_O(backlight_timeout), 6, "backlight timeout", backlight_times_conf }, | ||
255 | #ifdef CONFIG_CHARGING | ||
256 | {5, S_O(backlight_timeout_plugged), 11, "backlight timeout plugged", | ||
257 | backlight_times_conf }, | ||
258 | #endif | ||
259 | #endif /* CONFIG_BACKLIGHT */ | ||
260 | #ifdef HAVE_LCD_BITMAP | ||
261 | {1, S_O(invert), false, "invert", off_on }, | ||
262 | {1, S_O(flip_display), false, "flip display", off_on }, | ||
263 | /* display */ | ||
264 | {1, S_O(invert_cursor), true, "invert cursor", off_on }, | ||
265 | {1, S_O(statusbar), true, "statusbar", off_on }, | ||
266 | {1, S_O(scrollbar), true, "scrollbar", off_on }, | ||
267 | #if CONFIG_KEYPAD == RECORDER_PAD | ||
268 | {1, S_O(buttonbar), true, "buttonbar", off_on }, | ||
269 | #endif | ||
270 | {1, S_O(volume_type), 0, "volume display", graphic_numeric }, | ||
271 | {1, S_O(battery_display), 0, "battery display", graphic_numeric }, | ||
272 | {1, S_O(timeformat), 0, "time format", "24hour,12hour" }, | ||
273 | #endif /* HAVE_LCD_BITMAP */ | ||
274 | {1, S_O(show_icons), true, "show icons", off_on }, | ||
275 | /* system */ | ||
276 | {4, S_O(poweroff), 10, | ||
277 | "idle poweroff", "off,1,2,3,4,5,6,7,8,9,10,15,30,45,60" }, | ||
278 | {18, S_O(runtime), 0, NULL, NULL }, | ||
279 | {18, S_O(topruntime), 0, NULL, NULL }, | ||
280 | #if MEM > 1 | ||
281 | {15, S_O(max_files_in_playlist), 10000, | ||
282 | "max files in playlist", NULL }, /* 1000...20000 */ | ||
283 | {14, S_O(max_files_in_dir), 400, | ||
284 | "max files in dir", NULL }, /* 50...10000 */ | ||
285 | #else | 144 | #else |
286 | {15, S_O(max_files_in_playlist), 1000, | 145 | memset(buf,0,max_len); |
287 | "max files in playlist", NULL }, /* 1000...20000 */ | 146 | /* read rtc block */ |
288 | {14, S_O(max_files_in_dir), 200, | 147 | for (i=0; i < max_len; i++ ) |
289 | "max files in dir", NULL }, /* 50...10000 */ | 148 | buf[i] = rtc_read(0x14+i); |
290 | #endif | 149 | #endif |
291 | /* battery */ | 150 | /* check magic, version */ |
292 | {12, S_O(battery_capacity), BATTERY_CAPACITY_DEFAULT, "battery capacity", | 151 | if ((buf[0] != 'R') || (buf[1] != 'b') |
293 | NULL }, /* 1500...3200 for NiMH, 2200...3200 for LiIon, | 152 | || (buf[2] != NVRAM_CONFIG_VERSION)) |
294 | 500...1500 for Alkaline */ | 153 | return false; |
295 | #ifdef CONFIG_CHARGING | 154 | /* check crc32 */ |
296 | {1, S_O(car_adapter_mode), false, "car adapter mode", off_on }, | 155 | crc32 = crc_32(&buf[NVRAM_DATA_START], |
297 | #endif | 156 | max_len-NVRAM_DATA_START-1,0xffffffff); |
298 | /* tuner */ | 157 | if (memcmp(&crc32,&buf[4],4)) |
299 | #ifdef CONFIG_TUNER | 158 | return false; |
300 | {1, S_O(fm_force_mono), false, "force fm mono", off_on }, | 159 | /* all good, so read in the settings */ |
301 | {9, S_O(last_frequency), 0, NULL, NULL }, /* Default: MIN_FREQ */ | 160 | var_count = buf[3]; |
302 | #endif | 161 | buf_pos = NVRAM_DATA_START; |
303 | 162 | for(i=0; (i<nb_settings) && (var_count>0) && (buf_pos<max_len); i++) | |
304 | #if BATTERY_TYPES_COUNT > 1 | 163 | { |
305 | {1, S_O(battery_type), 0, "battery type", "alkaline,nimh" }, | 164 | int nvram_bytes = (settings[i].flags&F_NVRAM_BYTES_MASK) |
306 | #endif | 165 | >>F_NVRAM_MASK_SHIFT; |
307 | 166 | if (nvram_bytes) | |
308 | #ifdef HAVE_REMOTE_LCD | 167 | { |
309 | /* remote lcd */ | 168 | memcpy(settings[i].setting,&buf[buf_pos],nvram_bytes); |
310 | {6, S_O(remote_contrast), DEFAULT_REMOTE_CONTRAST_SETTING, | 169 | buf_pos += nvram_bytes; |
311 | "remote contrast", NULL }, | 170 | var_count--; |
312 | {1, S_O(remote_invert), false, "remote invert", off_on }, | 171 | } |
313 | {1, S_O(remote_flip_display), false, "remote flip display", off_on }, | 172 | } |
314 | {5, S_O(remote_backlight_timeout), 6, "remote backlight timeout", | 173 | return true; |
315 | backlight_times_conf }, | 174 | } |
316 | #ifdef CONFIG_CHARGING | 175 | static bool write_nvram_data(char* buf, int max_len) |
317 | {5, S_O(remote_backlight_timeout_plugged), 11, | ||
318 | "remote backlight timeout plugged", backlight_times_conf }, | ||
319 | #endif | ||
320 | #ifdef HAVE_REMOTE_LCD_TICKING | ||
321 | {1, S_O(remote_reduce_ticking), false, "remote reduce ticking", off_on }, | ||
322 | #endif | ||
323 | #endif | ||
324 | |||
325 | #ifdef CONFIG_BACKLIGHT | ||
326 | {1, S_O(bl_filter_first_keypress), false, | ||
327 | "backlight filters first keypress", off_on }, | ||
328 | #ifdef HAVE_REMOTE_LCD | ||
329 | {1, S_O(remote_bl_filter_first_keypress), false, | ||
330 | "backlight filters first remote keypress", off_on }, | ||
331 | #endif | ||
332 | #endif /* CONFIG_BACKLIGHT */ | ||
333 | |||
334 | /* new stuff to be added here */ | ||
335 | /* If values are just added to the end, no need to bump the version. */ | ||
336 | |||
337 | /* Current sum of bits: 277 (worst case, but w/o remote lcd) */ | ||
338 | /* Sum of all bit sizes must not grow beyond 288! */ | ||
339 | }; | ||
340 | |||
341 | |||
342 | /* the part of the settings which ends up in HD sector only */ | ||
343 | static const struct bit_entry hd_bits[] = | ||
344 | { | 176 | { |
345 | /* This table starts after the 44 RTC bytes = 352 bits. */ | 177 | unsigned crc32 = 0xffffffff; |
346 | /* Here we need 11 bits to tell how far this is populated. */ | 178 | int i = 0, buf_pos = 0; |
347 | 179 | char var_count = 0; | |
348 | /* placeholder, containing the size information */ | 180 | #ifndef HAVE_RTC_RAM |
349 | {11, 0, 0, 0, NULL, NULL }, /* 11 bit to tell how far this is populated */ | 181 | int fd; |
350 | |||
351 | /* # of bits, offset+size, default, .cfg name, .cfg values */ | ||
352 | /* more display */ | ||
353 | #ifdef CONFIG_BACKLIGHT | ||
354 | {1, S_O(caption_backlight), false, "caption backlight", off_on }, | ||
355 | #endif | ||
356 | #ifdef HAVE_REMOTE_LCD | ||
357 | {1, S_O(remote_caption_backlight), false, | ||
358 | "remote caption backlight", off_on }, | ||
359 | #endif | ||
360 | #ifdef HAVE_BACKLIGHT_BRIGHTNESS | ||
361 | {6, S_O(brightness), DEFAULT_BRIGHTNESS_SETTING, "brightness", NULL }, | ||
362 | #endif | ||
363 | #ifdef HAVE_BACKLIGHT_PWM_FADING | ||
364 | /* backlight fading */ | ||
365 | {2, S_O(backlight_fade_in), 1, "backlight fade in", "off,500ms,1s,2s"}, | ||
366 | {3, S_O(backlight_fade_out), 3, "backlight fade out", | ||
367 | "off,500ms,1s,2s,3s,4s,5s,10s"}, | ||
368 | #endif | ||
369 | |||
370 | {4, S_O(scroll_speed), 9, "scroll speed", NULL }, /* 0...15 */ | ||
371 | {8, S_O(scroll_delay), 100, "scroll delay", NULL }, /* 0...250 */ | ||
372 | {8, S_O(bidir_limit), 50, "bidir limit", NULL }, /* 0...200 */ | ||
373 | |||
374 | #ifdef HAVE_REMOTE_LCD | ||
375 | {4, S_O(remote_scroll_speed), 9, "remote scroll speed", NULL }, /* 0...15 */ | ||
376 | {8, S_O(remote_scroll_step), 6, "remote scroll step", NULL }, /* 1...160 */ | ||
377 | {8, S_O(remote_scroll_delay), 100, "remote scroll delay", NULL }, /* 0...250 */ | ||
378 | {8, S_O(remote_bidir_limit), 50, "remote bidir limit", NULL }, /* 0...200 */ | ||
379 | #endif | ||
380 | |||
381 | #ifdef HAVE_LCD_BITMAP | ||
382 | {1, S_O(offset_out_of_view), false, "Screen Scrolls Out Of View", off_on }, | ||
383 | #if LCD_WIDTH > 255 | ||
384 | {9, S_O(scroll_step), 6, "scroll step", NULL }, | ||
385 | {9, S_O(screen_scroll_step), 16, "screen scroll step", NULL }, | ||
386 | #elif LCD_WIDTH > 127 | ||
387 | {8, S_O(scroll_step), 6, "scroll step", NULL }, | ||
388 | {8, S_O(screen_scroll_step), 16, "screen scroll step", NULL }, | ||
389 | #else | ||
390 | {7, S_O(scroll_step), 6, "scroll step", NULL }, | ||
391 | {7, S_O(screen_scroll_step), 16, "screen scroll step", NULL }, | ||
392 | #endif | ||
393 | #endif /* HAVE_LCD_BITMAP */ | ||
394 | #ifdef HAVE_LCD_CHARCELLS | ||
395 | {3, S_O(jump_scroll), 0, "jump scroll", NULL }, /* 0...5 */ | ||
396 | {8, S_O(jump_scroll_delay), 50, "jump scroll delay", NULL }, /* 0...250 */ | ||
397 | #endif | ||
398 | {1, S_O(scroll_paginated), false, "scroll paginated", off_on }, | ||
399 | |||
400 | #ifdef HAVE_LCD_COLOR | ||
401 | {LCD_DEPTH,S_O(fg_color),LCD_DEFAULT_FG,"foreground color","rgb"}, | ||
402 | {LCD_DEPTH,S_O(bg_color),LCD_DEFAULT_BG,"background color","rgb"}, | ||
403 | #endif | ||
404 | |||
405 | /* more playback */ | ||
406 | {1, S_O(play_selected), true, "play selected", off_on }, | ||
407 | {1, S_O(fade_on_stop), true, "volume fade", off_on }, | ||
408 | {4, S_O(ff_rewind_min_step), FF_REWIND_1000, | ||
409 | "scan min step", "1,2,3,4,5,6,8,10,15,20,25,30,45,60" }, | ||
410 | {4, S_O(ff_rewind_accel), 3, "scan accel", NULL }, | ||
411 | #if CONFIG_CODEC == SWCODEC | ||
412 | {3, S_O(buffer_margin), 0, "antiskip", | ||
413 | "5s,15s,30s,1min,2min,3min,5min,10min" }, | ||
414 | #else | ||
415 | {3, S_O(buffer_margin), 0, "antiskip", NULL }, | ||
416 | #endif | ||
417 | /* disk */ | ||
418 | #ifndef HAVE_MMC | ||
419 | #ifdef HAVE_ATA_POWER_OFF | ||
420 | {1, S_O(disk_poweroff), false, "disk poweroff", off_on }, | ||
421 | #endif | ||
422 | {8, S_O(disk_spindown), 5, "disk spindown", NULL }, | ||
423 | #endif /* HAVE_MMC */ | ||
424 | |||
425 | /* browser */ | ||
426 | {3, S_O(dirfilter), SHOW_SUPPORTED, | ||
427 | "show files", "all,supported,music,playlists" | ||
428 | #ifdef HAVE_TAGCACHE | ||
429 | ",id3 database" | ||
430 | #endif | ||
431 | }, | ||
432 | {1, S_O(sort_case), false, "sort case", off_on }, | ||
433 | {1, S_O(browse_current), false, "follow playlist", off_on }, | ||
434 | /* playlist */ | ||
435 | {1, S_O(playlist_viewer_icons), true, "playlist viewer icons", off_on }, | ||
436 | {1, S_O(playlist_viewer_indices), true, | ||
437 | "playlist viewer indices", off_on }, | ||
438 | {1, S_O(playlist_viewer_track_display), 0, | ||
439 | "playlist viewer track display", "track name,full path" }, | ||
440 | {2, S_O(recursive_dir_insert), RECURSE_OFF, | ||
441 | "recursive directory insert", off_on_ask }, | ||
442 | /* bookmarks */ | ||
443 | {3, S_O(autocreatebookmark), BOOKMARK_NO, "autocreate bookmarks", | ||
444 | "off,on,ask,recent only - on,recent only - ask" }, | ||
445 | {2, S_O(autoloadbookmark), BOOKMARK_NO, | ||
446 | "autoload bookmarks", off_on_ask }, | ||
447 | {2, S_O(usemrb), BOOKMARK_NO, | ||
448 | "use most-recent-bookmarks", "off,on,unique only" }, | ||
449 | #ifdef HAVE_LCD_BITMAP | ||
450 | /* peak meter */ | ||
451 | {5, S_O(peak_meter_clip_hold), 16, "peak meter clip hold", /* 0...25 */ | ||
452 | "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" }, | ||
453 | {5, S_O(peak_meter_hold), 3, "peak meter hold", | ||
454 | "off,200ms,300ms,500ms,1,2,3,4,5,6,7,8,9,10,15,20,30,1min" }, | ||
455 | {7, S_O(peak_meter_release), 8, "peak meter release", NULL }, /* 0...126 */ | ||
456 | {1, S_O(peak_meter_dbfs), true, "peak meter dbfs", off_on }, | ||
457 | {7, S_O(peak_meter_min), 60, "peak meter min", NULL }, /* 0...100 */ | ||
458 | {7, S_O(peak_meter_max), 0, "peak meter max", NULL }, /* 0...100 */ | ||
459 | #endif | ||
460 | #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) | ||
461 | {7, S_O(mdb_strength), 0, "mdb strength", NULL}, | ||
462 | {7, S_O(mdb_harmonics), 0, "mdb harmonics", NULL}, | ||
463 | {9, S_O(mdb_center), 0, "mdb center", NULL}, | ||
464 | {9, S_O(mdb_shape), 0, "mdb shape", NULL}, | ||
465 | {1, S_O(mdb_enable), 0, "mdb enable", off_on}, | ||
466 | #endif | ||
467 | #if CONFIG_CODEC == MAS3507D | ||
468 | {1, S_O(line_in), false, "line in", off_on }, | ||
469 | #endif | 182 | #endif |
470 | /* voice */ | 183 | memset(buf,0,max_len); |
471 | {2, S_O(talk_dir), 0, "talk dir", off_number_spell_hover }, | 184 | /* magic, version */ |
472 | {2, S_O(talk_file), 0, "talk file", off_number_spell_hover }, | 185 | buf[0] = 'R'; buf[1] = 'b'; |
473 | {1, S_O(talk_menu), true, "talk menu", off_on }, | 186 | buf[2] = NVRAM_CONFIG_VERSION; |
474 | 187 | buf_pos = NVRAM_DATA_START; | |
475 | {2, S_O(sort_file), 0, "sort files", "alpha,oldest,newest,type" }, | 188 | for(i=0; (i<nb_settings) && (buf_pos<max_len); i++) |
476 | {2, S_O(sort_dir), 0, "sort dirs", "alpha,oldest,newest" }, | 189 | { |
477 | {1, S_O(id3_v1_first), 0, "id3 tag priority", "v2-v1,v1-v2"}, | 190 | int nvram_bytes = (settings[i].flags&F_NVRAM_BYTES_MASK) |
478 | 191 | >>F_NVRAM_MASK_SHIFT; | |
479 | #ifdef HAVE_RECORDING | 192 | if (nvram_bytes) |
480 | /* recording */ | 193 | { |
481 | {1, S_O(recscreen_on), false, "recscreen on", off_on }, | 194 | memcpy(&buf[buf_pos],settings[i].setting,nvram_bytes); |
482 | {1, S_O(rec_startup), false, "rec screen on startup", off_on }, | 195 | buf_pos += nvram_bytes; |
483 | {4, S_O(rec_timesplit), 0, "rec timesplit", /* 0...15 */ | 196 | var_count++; |
484 | "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" }, | 197 | } |
485 | {4, S_O(rec_sizesplit), 0, "rec sizesplit", /* 0...15 */ | 198 | } |
486 | "off,5MB,10MB,15MB,32MB,64MB,75MB,100MB,128MB,256MB,512MB,650MB,700MB,1GB,1.5GB,1.75GB" }, | 199 | /* count and crc32 */ |
487 | {1, S_O(rec_channels), 0, "rec channels", "stereo,mono" }, | 200 | buf[3] = var_count; |
488 | {1, S_O(rec_split_type), 0, "rec split type", "Split, Stop" }, | 201 | crc32 = crc_32(&buf[NVRAM_DATA_START], |
489 | {1, S_O(rec_split_method), 0, "rec split method", "Time,Filesize" }, | 202 | max_len-NVRAM_DATA_START-1,0xffffffff); |
490 | 203 | memcpy(&buf[4],&crc32,4); | |
204 | #ifndef HAVE_RTC_RAM | ||
205 | fd = open(NVRAM_FILE,O_CREAT|O_TRUNC|O_WRONLY); | ||
206 | if (fd >= 0) | ||
491 | { | 207 | { |
492 | #if defined(HAVE_SPDIF_IN) || defined(HAVE_FMRADIO_IN) | 208 | int len = write(fd,buf,max_len); |
493 | 2, | 209 | close(fd); |
210 | if (len < 8) | ||
211 | return false; | ||
212 | } | ||
494 | #else | 213 | #else |
495 | 1, | 214 | /* FIXME: okay, it _would_ be cleaner and faster to implement rtc_write so |
496 | #endif | 215 | that it would write a number of bytes at a time since the RTC chip |
497 | S_O(rec_source), 0 /* 0=mic */, "rec source", | 216 | supports that, but this will have to do for now 8-) */ |
498 | "mic,line" | 217 | for (i=0; i < NVRAM_BLOCK_SIZE; i++ ) { |
499 | #ifdef HAVE_SPDIF_IN | 218 | int r = rtc_write(0x14+i, buf[i]); |
500 | ",spdif" | 219 | if (r) { |
501 | #endif | 220 | DEBUGF( "save_config_buffer: rtc_write failed at addr 0x%02x: %d\n", |
502 | #ifdef HAVE_FMRADIO_IN | 221 | 14+i, r ); |
503 | ",fmradio" | 222 | return false; |
504 | #endif | 223 | } |
505 | }, | 224 | } |
506 | {5, S_O(rec_prerecord_time), 0, "prerecording time", NULL }, /* 0...30 */ | ||
507 | {1, S_O(rec_directory), 0, /* rec_base_directory */ | ||
508 | "rec directory", REC_BASE_DIR ",current" }, | ||
509 | #ifdef CONFIG_BACKLIGHT | ||
510 | {2, S_O(cliplight), 0, "cliplight", "off,main,both,remote" }, | ||
511 | #endif | ||
512 | #if CONFIG_CODEC == MAS3587F | ||
513 | {4, S_O(rec_mic_gain), 8, "rec mic gain", NULL }, | ||
514 | {4, S_O(rec_left_gain), 2 /* 0dB */, "rec left gain", NULL }, /* 0...15 */ | ||
515 | {4, S_O(rec_right_gain), 2 /* 0dB */, "rec right gain", NULL }, /* 0...15 */ | ||
516 | {3, S_O(rec_frequency), 0, /* 0=44.1kHz */ | ||
517 | "rec frequency", "44,48,32,22,24,16" }, | ||
518 | {3, S_O(rec_quality), 5 /* 192 kBit/s max */, "rec quality", NULL }, | ||
519 | {1, S_O(rec_editable), false, "editable recordings", off_on }, | ||
520 | #endif /* CONFIG_CODEC == MAS3587F */ | ||
521 | |||
522 | #if CONFIG_CODEC == SWCODEC | ||
523 | #ifdef HAVE_UDA1380 | ||
524 | {8|SIGNED, S_O(rec_mic_gain), 16 /* 8 dB */, "rec mic gain", NULL }, /* -128...+108 */ | ||
525 | {8|SIGNED, S_O(rec_left_gain), 0, "rec left gain", NULL }, /* -128...+96 */ | ||
526 | {8|SIGNED, S_O(rec_right_gain), 0, "rec right gain", NULL }, /* -128...+96 */ | ||
527 | #elif defined(HAVE_TLV320) | ||
528 | /* TLV320 only has no mic boost or 20db mic boost */ | ||
529 | {1, S_O(rec_mic_gain), 0 /* 0 dB */, "rec mic gain", NULL }, /* 0db or 20db */ | ||
530 | {8|SIGNED, S_O(rec_left_gain), 0, "rec left gain", NULL }, /* -128...+96 */ | ||
531 | {8|SIGNED, S_O(rec_right_gain), 0, "rec right gain", NULL }, /* -128...+96 */ | ||
532 | #elif defined(HAVE_WM8975) | ||
533 | {8|SIGNED, S_O(rec_mic_gain), 16 /* 8 dB */, "rec mic gain", NULL }, /* -128...+108 */ | ||
534 | {8|SIGNED, S_O(rec_left_gain), 0, "rec left gain", NULL }, /* -128...+96 */ | ||
535 | {8|SIGNED, S_O(rec_right_gain), 0, "rec right gain", NULL }, /* -128...+96 */ | ||
536 | #elif defined(HAVE_WM8758) | ||
537 | {8|SIGNED, S_O(rec_mic_gain), 16 /* 8 dB */, "rec mic gain", NULL }, /* -128...+108 */ | ||
538 | {8|SIGNED, S_O(rec_left_gain), 0, "rec left gain", NULL }, /* -128...+96 */ | ||
539 | {8|SIGNED, S_O(rec_right_gain), 0, "rec right gain", NULL }, /* -128...+96 */ | ||
540 | #elif defined(HAVE_WM8731) | ||
541 | {8|SIGNED, S_O(rec_mic_gain), 16 /* 8 dB */, "rec mic gain", NULL }, /* -128...+108 */ | ||
542 | {8|SIGNED, S_O(rec_left_gain), 0, "rec left gain", NULL }, /* -128...+96 */ | ||
543 | {8|SIGNED, S_O(rec_right_gain), 0, "rec right gain", NULL }, /* -128...+96 */ | ||
544 | #endif | ||
545 | {REC_FREQ_CFG_NUM_BITS, S_O(rec_frequency), REC_FREQ_DEFAULT, | ||
546 | "rec frequency", REC_FREQ_CFG_VAL_LIST }, | ||
547 | {REC_FORMAT_CFG_NUM_BITS ,S_O(rec_format), REC_FORMAT_DEFAULT, | ||
548 | "rec format", REC_FORMAT_CFG_VAL_LIST }, | ||
549 | /** Encoder settings start - keep these together **/ | ||
550 | /* aiff_enc */ | ||
551 | /* (no settings yet) */ | ||
552 | /* mp3_enc */ | ||
553 | {5,S_O(mp3_enc_config.bitrate), MP3_ENC_BITRATE_CFG_DEFAULT, | ||
554 | "mp3_enc bitrate", MP3_ENC_BITRATE_CFG_VALUE_LIST }, | ||
555 | /* wav_enc */ | ||
556 | /* (no settings yet) */ | ||
557 | /* wavpack_enc */ | ||
558 | /* (no settings yet) */ | ||
559 | /** Encoder settings end **/ | ||
560 | #endif /* CONFIG_CODEC == SWCODEC */ | ||
561 | |||
562 | /* values for the trigger */ | ||
563 | {8 | SIGNED, S_O(rec_start_thres), -35, "trigger start threshold", NULL}, | ||
564 | {8 | SIGNED, S_O(rec_stop_thres), -45, "trigger stop threshold", NULL}, | ||
565 | {4, S_O(rec_start_duration), 0, "trigger start duration", trig_durations_conf}, | ||
566 | {4, S_O(rec_stop_postrec), 2, "trigger stop postrec", trig_durations_conf}, | ||
567 | {4, S_O(rec_stop_gap), 1, "trigger min gap", trig_durations_conf}, | ||
568 | {4, S_O(rec_trigger_mode ), 0, "trigger mode", "off,once,repeat"}, | ||
569 | #endif /* HAVE_RECORDING */ | ||
570 | |||
571 | #ifdef HAVE_SPDIF_POWER | ||
572 | {1, S_O(spdif_enable), false, "spdif enable", off_on}, | ||
573 | #endif | ||
574 | |||
575 | {2, S_O(next_folder), false, "folder navigation", "off,on,random" }, | ||
576 | {1, S_O(runtimedb), false, "gather runtime data", off_on }, | ||
577 | |||
578 | #if CONFIG_CODEC == SWCODEC | ||
579 | {1, S_O(replaygain), false, "replaygain", off_on }, | ||
580 | {2, S_O(replaygain_type), REPLAYGAIN_ALBUM, "replaygain type", | ||
581 | "track,album,track shuffle" }, | ||
582 | {1, S_O(replaygain_noclip), false, "replaygain noclip", off_on }, | ||
583 | {8 | SIGNED, S_O(replaygain_preamp), 0, "replaygain preamp", NULL }, | ||
584 | {2, S_O(beep), 0, "beep", "off,weak,moderate,strong" }, | ||
585 | {3, S_O(crossfade), 0, "crossfade", "off,shuffle,track skip,shuffle and track skip,always"}, | ||
586 | {3, S_O(crossfade_fade_in_delay), 0, "crossfade fade in delay", NULL}, | ||
587 | {3, S_O(crossfade_fade_out_delay), 0, "crossfade fade out delay", NULL}, | ||
588 | {4, S_O(crossfade_fade_in_duration), 0, "crossfade fade in duration", NULL}, | ||
589 | {4, S_O(crossfade_fade_out_duration), 0, "crossfade fade out duration", NULL}, | ||
590 | {1, S_O(crossfade_fade_out_mixmode), 0, "crossfade fade out mode", "crossfade,mix"}, | ||
591 | {1, S_O(crossfeed), false, "crossfeed", off_on }, | ||
592 | {6, S_O(crossfeed_direct_gain), 15, "crossfeed direct gain", NULL }, | ||
593 | {7, S_O(crossfeed_cross_gain), 60, "crossfeed cross gain", NULL }, | ||
594 | {8, S_O(crossfeed_hf_attenuation), 160, "crossfeed hf attenuation", NULL }, | ||
595 | {11, S_O(crossfeed_hf_cutoff), 700, "crossfeed hf cutoff", NULL }, | ||
596 | |||
597 | /* equalizer */ | ||
598 | {1, S_O(eq_enabled), false, "eq enabled", off_on }, | ||
599 | {8, S_O(eq_precut), 0, "eq precut", NULL }, | ||
600 | /* 0..32768 Hz */ | ||
601 | {15, S_O(eq_band0_cutoff), 60, "eq band 0 cutoff", NULL }, | ||
602 | {15, S_O(eq_band1_cutoff), 200, "eq band 1 cutoff", NULL }, | ||
603 | {15, S_O(eq_band2_cutoff), 800, "eq band 2 cutoff", NULL }, | ||
604 | {15, S_O(eq_band3_cutoff), 4000, "eq band 3 cutoff", NULL }, | ||
605 | {15, S_O(eq_band4_cutoff), 12000, "eq band 4 cutoff", NULL }, | ||
606 | /* 0..64 (or 0.0 to 6.4) */ | ||
607 | {6, S_O(eq_band0_q), 7, "eq band 0 q", NULL }, | ||
608 | {6, S_O(eq_band1_q), 10, "eq band 1 q", NULL }, | ||
609 | {6, S_O(eq_band2_q), 10, "eq band 2 q", NULL }, | ||
610 | {6, S_O(eq_band3_q), 10, "eq band 3 q", NULL }, | ||
611 | {6, S_O(eq_band4_q), 7, "eq band 4 q", NULL }, | ||
612 | /* -240..240 (or -24db to +24db) */ | ||
613 | {9|SIGNED, S_O(eq_band0_gain), 0, "eq band 0 gain", NULL }, | ||
614 | {9|SIGNED, S_O(eq_band1_gain), 0, "eq band 1 gain", NULL }, | ||
615 | {9|SIGNED, S_O(eq_band2_gain), 0, "eq band 2 gain", NULL }, | ||
616 | {9|SIGNED, S_O(eq_band3_gain), 0, "eq band 3 gain", NULL }, | ||
617 | {9|SIGNED, S_O(eq_band4_gain), 0, "eq band 4 gain", NULL }, | ||
618 | |||
619 | /* dithering */ | ||
620 | {1, S_O(dithering_enabled), false, "dithering enabled", off_on }, | ||
621 | #endif | ||
622 | |||
623 | #ifdef HAVE_DIRCACHE | ||
624 | {1, S_O(dircache), false, "dircache", off_on }, | ||
625 | {22, S_O(dircache_size), 0, NULL, NULL }, | ||
626 | #endif | ||
627 | |||
628 | #ifdef HAVE_TAGCACHE | ||
629 | #ifdef HAVE_TC_RAMCACHE | ||
630 | {1, S_O(tagcache_ram), 0, "tagcache_ram", off_on }, | ||
631 | #endif | ||
632 | {1, S_O(tagcache_autoupdate), 0, "tagcache_autoupdate", off_on }, | ||
633 | #endif | ||
634 | |||
635 | {4, S_O(default_codepage), 0, "default codepage", | ||
636 | "iso8859-1,iso8859-7,iso8859-8,cp1251,iso8859-11,cp1256,iso8859-9,iso8859-2,sjis,gb2312,ksx1001,big5,utf-8,cp1256" }, | ||
637 | |||
638 | {1, S_O(warnon_erase_dynplaylist), false, | ||
639 | "warn when erasing dynamic playlist", off_on }, | ||
640 | |||
641 | #ifdef CONFIG_BACKLIGHT | ||
642 | #ifdef HAS_BUTTON_HOLD | ||
643 | {2, S_O(backlight_on_button_hold), 0, "backlight on button hold", | ||
644 | "normal,off,on" }, | ||
645 | #endif | ||
646 | |||
647 | #ifdef HAVE_LCD_SLEEP | ||
648 | {4, S_O(lcd_sleep_after_backlight_off), 3, | ||
649 | "lcd sleep after backlight off", | ||
650 | "always,never,5,10,15,20,30,45,60,90" }, | ||
651 | #endif | ||
652 | #endif /* CONFIG_BACKLIGHT */ | ||
653 | |||
654 | #ifdef HAVE_WM8758 | ||
655 | {1, S_O(eq_hw_enabled), false, "eq hardware enabled", off_on }, | ||
656 | |||
657 | {2, S_O(eq_hw_band0_cutoff), 1, "eq hardware band 0 cutoff", "80Hz,105Hz,135Hz,175Hz" }, | ||
658 | {5|SIGNED, S_O(eq_hw_band0_gain), 0, "eq hardware band 0 gain", NULL }, | ||
659 | |||
660 | {2, S_O(eq_hw_band1_center), 1, "eq hardware band 1 center", "230Hz,300Hz,385Hz,500Hz" }, | ||
661 | {1, S_O(eq_hw_band1_bandwidth), 0, "eq hardware band 1 bandwidth", "narrow,wide" }, | ||
662 | {5|SIGNED, S_O(eq_hw_band1_gain), 0, "eq hardware band 1 gain", NULL }, | ||
663 | |||
664 | {2, S_O(eq_hw_band2_center), 1, "eq hardware band 2 center", "650Hz,850Hz,1.1kHz,1.4kHz" }, | ||
665 | {1, S_O(eq_hw_band2_bandwidth), 0, "eq hardware band 2 bandwidth", "narrow,wide" }, | ||
666 | {5|SIGNED, S_O(eq_hw_band2_gain), 0, "eq hardware band 2 gain", NULL }, | ||
667 | |||
668 | {2, S_O(eq_hw_band3_center), 1, "eq hardware band 3 center", "1.8kHz,2.4kHz,3.2kHz,4.1kHz" }, | ||
669 | {1, S_O(eq_hw_band3_bandwidth), 0, "eq hardware band 3 bandwidth", "narrow,wide" }, | ||
670 | {5|SIGNED, S_O(eq_hw_band3_gain), 0, "eq hardware band 3 gain", NULL }, | ||
671 | |||
672 | {2, S_O(eq_hw_band4_cutoff), 1, "eq hardware band 4 cutoff", "5.3kHz,6.9kHz,9kHz,11.7kHz" }, | ||
673 | {5|SIGNED, S_O(eq_hw_band4_gain), 0, "eq hardware band 4 gain", NULL }, | ||
674 | #endif | ||
675 | {1, S_O(hold_lr_for_scroll_in_list), true, "hold_lr_for_scroll_in_list", off_on }, | ||
676 | |||
677 | {2, S_O(show_path_in_browser), 0, "show path in browser", "off,current directory,full path" }, | ||
678 | #ifdef HAVE_AGC | ||
679 | {4, S_O(rec_agc_preset_mic), 1, "agc mic preset", NULL}, /* 0...5 */ | ||
680 | {4, S_O(rec_agc_preset_line), 1, "agc line preset", NULL}, /* 0...5 */ | ||
681 | {8|SIGNED, S_O(rec_agc_maxgain_mic), 104, "agc maximum mic gain", NULL}, | ||
682 | {8|SIGNED, S_O(rec_agc_maxgain_line), 96, "agc maximum line gain", NULL}, | ||
683 | {3, S_O(rec_agc_cliptime), 1, "agc cliptime", "0.2s,0.4s,0.6s,0.8,1s"}, | ||
684 | #endif | ||
685 | |||
686 | #ifdef HAVE_REMOTE_LCD | ||
687 | #ifdef HAS_REMOTE_BUTTON_HOLD | ||
688 | {2, S_O(remote_backlight_on_button_hold), 0, "remote backlight on button hold", | ||
689 | "normal,off,on" }, | ||
690 | #endif | ||
691 | #endif | ||
692 | |||
693 | #ifdef HAVE_HEADPHONE_DETECTION | ||
694 | {2, S_O(unplug_mode), 0, "pause on headphone unplug", NULL}, | ||
695 | {4, S_O(unplug_rw), 0, "rewind duration on pause", NULL}, | ||
696 | {1, S_O(unplug_autoresume), 0, "disable autoresume if phones not present", off_on }, | ||
697 | #endif | ||
698 | #ifdef CONFIG_TUNER | ||
699 | {2, S_O(fm_region), 0, "fm_region", "eu,us,jp,kr" }, | ||
700 | #endif | ||
701 | |||
702 | {1, S_O(audioscrobbler), false, "Last.fm Logging", off_on}, | ||
703 | |||
704 | /* If values are just added to the end, no need to bump the version. */ | ||
705 | /* new stuff to be added at the end */ | ||
706 | #ifdef HAVE_RECORDING | ||
707 | {2, S_O(rec_trigger_type), 0, "trigger type", "stop,pause,nf stp"}, | ||
708 | #endif | 225 | #endif |
709 | 226 | return true; | |
710 | /* Sum of all bit sizes must not grow beyond 0xB8*8 = 1472 */ | ||
711 | }; | ||
712 | |||
713 | /* helper function to extract n (<=32) bits from an arbitrary position | ||
714 | * counting from LSB to MSB */ | ||
715 | static uint32_t get_bits( | ||
716 | const uint32_t *p, /* the start of the bitfield array */ | ||
717 | unsigned int from, /* bit no. to start reading from */ | ||
718 | unsigned int size) /* how many bits to read */ | ||
719 | { | ||
720 | unsigned int long_index = from / 32; | ||
721 | unsigned int bit_index = from % 32; | ||
722 | uint32_t result; | ||
723 | |||
724 | result = p[long_index] >> bit_index; | ||
725 | |||
726 | if (bit_index + size > 32) /* crossing longword boundary */ | ||
727 | result |= p[long_index+1] << (32 - bit_index); | ||
728 | |||
729 | result &= 0xFFFFFFFF >> (32 - size); | ||
730 | |||
731 | return result; | ||
732 | } | ||
733 | |||
734 | /* helper function to set n (<=32) bits to an arbitrary position, | ||
735 | * counting from LSB to MSB */ | ||
736 | static void set_bits( | ||
737 | uint32_t *p, /* the start of the bitfield array */ | ||
738 | unsigned int from, /* bit no. to start writing into */ | ||
739 | unsigned int size, /* how many bits to change */ | ||
740 | uint32_t value) /* content (LSBs will be taken) */ | ||
741 | { | ||
742 | unsigned int long_index = from / 32; | ||
743 | unsigned int bit_index = from % 32; | ||
744 | uint32_t mask; | ||
745 | |||
746 | mask = 0xFFFFFFFF >> (32 - size); | ||
747 | value &= mask; | ||
748 | mask <<= bit_index; | ||
749 | |||
750 | if (bit_index + size > 32) | ||
751 | p[long_index+1] = | ||
752 | (p[long_index+1] & (0xFFFFFFFF << (bit_index + size - 32))) | ||
753 | | (value >> (32 - bit_index)); | ||
754 | |||
755 | p[long_index] = (p[long_index] & ~mask) | (value << bit_index); | ||
756 | } | 227 | } |
757 | 228 | ||
758 | #ifdef HAVE_LCD_COLOR | 229 | #ifdef HAVE_LCD_COLOR |
@@ -787,223 +258,89 @@ static int hex_to_rgb(const char* hex) | |||
787 | return 0; | 258 | return 0; |
788 | } | 259 | } |
789 | #endif | 260 | #endif |
790 | 261 | bool settings_write_config(char* filename) | |
791 | /* | ||
792 | * Calculates the checksum for the config block and returns it | ||
793 | */ | ||
794 | |||
795 | static unsigned short calculate_config_checksum(const unsigned char* buf) | ||
796 | { | ||
797 | unsigned int i; | ||
798 | unsigned char cksum[2]; | ||
799 | cksum[0] = cksum[1] = 0; | ||
800 | |||
801 | for (i=0; i < RTC_BLOCK_SIZE - 2; i+=2 ) { | ||
802 | cksum[0] ^= buf[i]; | ||
803 | cksum[1] ^= buf[i+1]; | ||
804 | } | ||
805 | |||
806 | return (cksum[0] << 8) | cksum[1]; | ||
807 | } | ||
808 | |||
809 | /* | ||
810 | * initialize the config block buffer | ||
811 | */ | ||
812 | static void init_config_buffer( void ) | ||
813 | { | 262 | { |
814 | DEBUGF( "init_config_buffer()\n" ); | ||
815 | |||
816 | /* reset to 0 - all unused */ | ||
817 | memset(config_block, 0, CONFIG_BLOCK_SIZE); | ||
818 | /* insert header */ | ||
819 | config_block[0] = 'R'; | ||
820 | config_block[1] = 'o'; | ||
821 | config_block[2] = 'c'; | ||
822 | config_block[3] = CONFIG_BLOCK_VERSION; | ||
823 | } | ||
824 | |||
825 | static bool flush_config_block_callback(void) | ||
826 | { | ||
827 | ata_write_sectors(IF_MV2(0,) config_sector, 1, config_block); | ||
828 | return true; | ||
829 | } | ||
830 | /* | ||
831 | * save the config block buffer to disk or RTC RAM | ||
832 | */ | ||
833 | static int save_config_buffer( void ) | ||
834 | { | ||
835 | unsigned short chksum; | ||
836 | #ifdef HAVE_RTC_RAM | ||
837 | unsigned int i; | ||
838 | #endif | ||
839 | |||
840 | /* update the checksum in the end of the block before saving */ | ||
841 | chksum = calculate_config_checksum(config_block); | ||
842 | config_block[ RTC_BLOCK_SIZE - 2 ] = chksum >> 8; | ||
843 | config_block[ RTC_BLOCK_SIZE - 1 ] = chksum & 0xff; | ||
844 | |||
845 | #ifdef HAVE_RTC_RAM | ||
846 | /* FIXME: okay, it _would_ be cleaner and faster to implement rtc_write so | ||
847 | that it would write a number of bytes at a time since the RTC chip | ||
848 | supports that, but this will have to do for now 8-) */ | ||
849 | for (i=0; i < RTC_BLOCK_SIZE; i++ ) { | ||
850 | int r = rtc_write(0x14+i, config_block[i]); | ||
851 | if (r) { | ||
852 | DEBUGF( "save_config_buffer: rtc_write failed at addr 0x%02x: %d\n", | ||
853 | 14+i, r ); | ||
854 | return r; | ||
855 | } | ||
856 | } | ||
857 | |||
858 | #endif | ||
859 | |||
860 | if (config_sector != 0) | ||
861 | register_ata_idle_func(flush_config_block_callback); | ||
862 | else | ||
863 | return -1; | ||
864 | |||
865 | return 0; | ||
866 | } | ||
867 | |||
868 | /* | ||
869 | * load the config block buffer from disk or RTC RAM | ||
870 | */ | ||
871 | static int load_config_buffer(int which) | ||
872 | { | ||
873 | unsigned short chksum; | ||
874 | bool correct = false; | ||
875 | |||
876 | |||
877 | DEBUGF( "load_config_buffer()\n" ); | ||
878 | |||
879 | if (which & SETTINGS_HD) | ||
880 | { | ||
881 | if (config_sector != 0) { | ||
882 | ata_read_sectors(IF_MV2(0,) config_sector, 1, config_block); | ||
883 | /* calculate the checksum, check it and the header */ | ||
884 | chksum = calculate_config_checksum(config_block); | ||
885 | |||
886 | if (config_block[0] == 'R' && | ||
887 | config_block[1] == 'o' && | ||
888 | config_block[2] == 'c' && | ||
889 | config_block[3] == CONFIG_BLOCK_VERSION && | ||
890 | (chksum >> 8) == config_block[RTC_BLOCK_SIZE - 2] && | ||
891 | (chksum & 0xff) == config_block[RTC_BLOCK_SIZE - 1]) | ||
892 | { | ||
893 | DEBUGF( "load_config_buffer: header & checksum test ok\n" ); | ||
894 | correct = true; | ||
895 | } | ||
896 | } | ||
897 | } | ||
898 | |||
899 | #ifdef HAVE_RTC_RAM | ||
900 | if(!correct) | ||
901 | { | ||
902 | /* If the disk sector was incorrect, reinit the buffer */ | ||
903 | memset(config_block, 0, CONFIG_BLOCK_SIZE); | ||
904 | } | ||
905 | |||
906 | if (which & SETTINGS_RTC) | ||
907 | { | ||
908 | unsigned int i; | ||
909 | unsigned char rtc_block[RTC_BLOCK_SIZE]; | ||
910 | |||
911 | /* read rtc block */ | ||
912 | for (i=0; i < RTC_BLOCK_SIZE; i++ ) | ||
913 | rtc_block[i] = rtc_read(0x14+i); | ||
914 | |||
915 | chksum = calculate_config_checksum(rtc_block); | ||
916 | |||
917 | /* if rtc block is ok, use that */ | ||
918 | if (rtc_block[0] == 'R' && | ||
919 | rtc_block[1] == 'o' && | ||
920 | rtc_block[2] == 'c' && | ||
921 | rtc_block[3] == CONFIG_BLOCK_VERSION && | ||
922 | (chksum >> 8) == rtc_block[RTC_BLOCK_SIZE - 2] && | ||
923 | (chksum & 0xff) == rtc_block[RTC_BLOCK_SIZE - 1]) | ||
924 | { | ||
925 | memcpy(config_block, rtc_block, RTC_BLOCK_SIZE); | ||
926 | correct = true; | ||
927 | } | ||
928 | } | ||
929 | #endif | ||
930 | |||
931 | if ( !correct ) { | ||
932 | /* if checksum is not valid, clear the config buffer */ | ||
933 | DEBUGF( "load_config_buffer: header & checksum test failed\n" ); | ||
934 | init_config_buffer(); | ||
935 | return -1; | ||
936 | } | ||
937 | |||
938 | return 0; | ||
939 | } | ||
940 | |||
941 | |||
942 | /* helper to save content of global_settings into a bitfield, | ||
943 | as described per table */ | ||
944 | static void save_bit_table(const struct bit_entry* p_table, int count, int bitstart) | ||
945 | { | ||
946 | uint32_t *p_bitfield = (uint32_t *)config_block; /* 32 bit addr. */ | ||
947 | uint32_t value; /* 32 bit content */ | ||
948 | int i; | 263 | int i; |
949 | const struct bit_entry* p_run = p_table; /* start after the size info */ | 264 | int fd; |
950 | int curr_bit = bitstart + p_table->bit_size; | 265 | char value[MAX_PATH]; |
951 | count--; /* first is excluded from loop */ | 266 | fd = open(filename,O_CREAT|O_TRUNC|O_WRONLY); |
952 | 267 | if (fd < 0) | |
953 | for (i=0; i<count; i++) | 268 | return false; |
269 | fdprintf(fd, "# .cfg file created by rockbox %s - " | ||
270 | "http://www.rockbox.org\r\n\r\n", appsversion); | ||
271 | for(i=0; i<nb_settings; i++) | ||
954 | { | 272 | { |
955 | p_run++; | 273 | if (settings[i].cfg_name == NULL) |
956 | /* could do a memcpy, but that would be endian-dependent */ | ||
957 | switch(p_run->byte_size) | ||
958 | { | ||
959 | case 1: | ||
960 | value = ((uint8_t *)&global_settings)[p_run->settings_offset]; | ||
961 | break; | ||
962 | case 2: | ||
963 | value = ((uint16_t *)&global_settings)[p_run->settings_offset/2]; | ||
964 | break; | ||
965 | case 4: | ||
966 | value = ((uint32_t *)&global_settings)[p_run->settings_offset/4]; | ||
967 | break; | ||
968 | default: | ||
969 | DEBUGF( "save_bit_table: illegal size!\n" ); | ||
970 | continue; | 274 | continue; |
971 | } | 275 | switch (settings[i].flags&F_T_MASK) |
972 | set_bits(p_bitfield, curr_bit, p_run->bit_size & 0x3F, value); | ||
973 | curr_bit += p_run->bit_size & 0x3F; | ||
974 | } | ||
975 | set_bits(p_bitfield, bitstart, p_table->bit_size, /* write size */ | ||
976 | curr_bit); /* = position after last element */ | ||
977 | } | ||
978 | |||
979 | /* | ||
980 | * figure out the config sector from the partition table and the | ||
981 | * mounted file system | ||
982 | */ | ||
983 | void settings_calc_config_sector(void) | ||
984 | { | ||
985 | #ifdef SIMULATOR | ||
986 | config_sector = 61; | ||
987 | #else | ||
988 | int i; | ||
989 | long partition_start; | ||
990 | long sector = 0; | ||
991 | |||
992 | if (fat_startsector(IF_MV(0)) != 0) /* There is a partition table */ | ||
993 | { | ||
994 | sector = 61; | ||
995 | for (i = 0; i < 4; i++) | ||
996 | { | 276 | { |
997 | partition_start = disk_partinfo(i)->start; | 277 | case F_T_INT: |
998 | if (partition_start != 0 && (partition_start - 2) < sector) | 278 | case F_T_UINT: |
999 | sector = partition_start - 2; | 279 | #ifdef HAVE_LCD_COLOR |
1000 | } | 280 | if (settings[i].flags&F_RGB) |
1001 | if (sector < 0) | 281 | { |
1002 | sector = 0; | 282 | int colour = *(int*)settings[i].setting; |
1003 | } | 283 | snprintf(value,MAX_PATH,"%02x%02x%02x", |
1004 | 284 | (int)RGB_UNPACK_RED(colour), | |
1005 | config_sector = sector; | 285 | (int)RGB_UNPACK_GREEN(colour), |
286 | (int)RGB_UNPACK_BLUE(colour)); | ||
287 | } | ||
288 | else | ||
1006 | #endif | 289 | #endif |
290 | if (settings[i].cfg_vals == NULL) | ||
291 | { | ||
292 | snprintf(value,MAX_PATH,"%d",*(int*)settings[i].setting); | ||
293 | } | ||
294 | else | ||
295 | { | ||
296 | char *s,*end; | ||
297 | char vals[MAX_PATH]; | ||
298 | int val = 0; | ||
299 | strncpy(vals,settings[i].cfg_vals,MAX_PATH); | ||
300 | s = strtok_r(vals,",",&end); | ||
301 | while (s) | ||
302 | { | ||
303 | if (val == *(int*)settings[i].setting) | ||
304 | { | ||
305 | strncpy(value,s,MAX_PATH); | ||
306 | break; | ||
307 | } | ||
308 | val++; | ||
309 | s = strtok_r(NULL,",",&end); | ||
310 | } | ||
311 | } | ||
312 | break; | ||
313 | case F_T_BOOL: | ||
314 | strcpy(value,*(bool*)settings[i].setting == true?"on":"off"); | ||
315 | break; | ||
316 | case F_T_CHARPTR: | ||
317 | case F_T_UCHARPTR: | ||
318 | if (((char*)settings[i].setting)[0] == '\0') | ||
319 | break; | ||
320 | if (settings[i].filename_setting->prefix) | ||
321 | { | ||
322 | snprintf(value,MAX_PATH,"%s%s%s", | ||
323 | settings[i].filename_setting->prefix, | ||
324 | (char*)settings[i].setting, | ||
325 | settings[i].filename_setting->suffix); | ||
326 | } | ||
327 | else strncpy(value,(char*)settings[i].setting, | ||
328 | settings[i].filename_setting->max_len); | ||
329 | break; | ||
330 | } /* switch () */ | ||
331 | if (value[0]) | ||
332 | fdprintf(fd,"%s: %s\r\n",settings[i].cfg_name,value); | ||
333 | value[0] = '\0'; | ||
334 | } /* for(...) */ | ||
335 | close(fd); | ||
336 | return true; | ||
337 | } | ||
338 | static bool flush_config_block_callback(void) | ||
339 | { | ||
340 | bool r1, r2; | ||
341 | r1 = write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE); | ||
342 | r2 = settings_write_config(CONFIGFILE); | ||
343 | return r1 || r2; | ||
1007 | } | 344 | } |
1008 | 345 | ||
1009 | /* | 346 | /* |
@@ -1011,75 +348,34 @@ void settings_calc_config_sector(void) | |||
1011 | */ | 348 | */ |
1012 | int settings_save( void ) | 349 | int settings_save( void ) |
1013 | { | 350 | { |
1014 | int i; | 351 | int elapsed_secs; |
1015 | |||
1016 | { | ||
1017 | int elapsed_secs; | ||
1018 | |||
1019 | elapsed_secs = (current_tick - lasttime) / HZ; | ||
1020 | global_settings.runtime += elapsed_secs; | ||
1021 | lasttime += (elapsed_secs * HZ); | ||
1022 | 352 | ||
1023 | if ( global_settings.runtime > global_settings.topruntime ) | 353 | elapsed_secs = (current_tick - lasttime) / HZ; |
1024 | global_settings.topruntime = global_settings.runtime; | 354 | global_settings.runtime += elapsed_secs; |
1025 | } | 355 | lasttime += (elapsed_secs * HZ); |
1026 | |||
1027 | /* serialize scalar values into RTC and HD sector, specified via table */ | ||
1028 | save_bit_table(rtc_bits, sizeof(rtc_bits)/sizeof(rtc_bits[0]), 4*8); | ||
1029 | save_bit_table(hd_bits, sizeof(hd_bits)/sizeof(hd_bits[0]), RTC_BLOCK_SIZE*8); | ||
1030 | |||
1031 | i = 0xb8; | ||
1032 | strncpy((char *)&config_block[i], (char *)global_settings.wps_file, | ||
1033 | MAX_FILENAME); | ||
1034 | i+= MAX_FILENAME; | ||
1035 | strncpy((char *)&config_block[i], (char *)global_settings.lang_file, | ||
1036 | MAX_FILENAME); | ||
1037 | i+= MAX_FILENAME; | ||
1038 | strncpy((char *)&config_block[i], (char *)global_settings.font_file, | ||
1039 | MAX_FILENAME); | ||
1040 | i+= MAX_FILENAME; | ||
1041 | #ifdef HAVE_REMOTE_LCD | ||
1042 | strncpy((char *)&config_block[i], (char *)global_settings.rwps_file, | ||
1043 | MAX_FILENAME); | ||
1044 | i+= MAX_FILENAME; | ||
1045 | #endif | ||
1046 | 356 | ||
1047 | #ifdef CONFIG_TUNER | 357 | if ( global_settings.runtime > global_settings.topruntime ) |
1048 | strncpy((char *)&config_block[i], (char *)global_settings.fmr_file, | 358 | global_settings.topruntime = global_settings.runtime; |
1049 | MAX_FILENAME); | 359 | #ifdef HAVE_RTC_RAM |
1050 | i+= MAX_FILENAME; | 360 | /* this will be done in the ata_callback if |
1051 | #endif | 361 | target doesnt have rtc ram */ |
1052 | 362 | write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE); | |
1053 | #if LCD_DEPTH > 1 | ||
1054 | strncpy((char *)&config_block[i], (char *)global_settings.backdrop_file, | ||
1055 | MAX_FILENAME); | ||
1056 | i+= MAX_FILENAME; | ||
1057 | #endif | ||
1058 | #ifdef HAVE_LCD_BITMAP | ||
1059 | strncpy((char *)&config_block[i], (char *)global_settings.kbd_file, | ||
1060 | MAX_FILENAME); | ||
1061 | i+= MAX_FILENAME; | ||
1062 | #endif | 363 | #endif |
1063 | 364 | if(!register_ata_idle_func(flush_config_block_callback)) | |
1064 | if(save_config_buffer()) | ||
1065 | { | 365 | { |
1066 | lcd_clear_display(); | 366 | int i; |
1067 | #ifdef HAVE_REMOTE_LCD | 367 | FOR_NB_SCREENS(i) |
1068 | lcd_remote_clear_display(); | 368 | { |
1069 | #endif | 369 | screens[i].clear_display(); |
1070 | #ifdef HAVE_LCD_CHARCELLS | 370 | #ifdef HAVE_LCD_CHARCELLS |
1071 | lcd_puts(0, 0, str(LANG_SETTINGS_SAVE_PLAYER)); | 371 | screens[i].puts(0, 0, str(LANG_SETTINGS_SAVE_PLAYER)); |
1072 | lcd_puts(0, 1, str(LANG_SETTINGS_BATTERY_PLAYER)); | 372 | screens[i].puts(0, 1, str(LANG_SETTINGS_BATTERY_PLAYER)); |
1073 | #else | 373 | #else |
1074 | lcd_puts(4, 2, str(LANG_SETTINGS_SAVE_RECORDER)); | 374 | screens[i].puts(4, 2, str(LANG_SETTINGS_SAVE_RECORDER)); |
1075 | lcd_puts(2, 4, str(LANG_SETTINGS_BATTERY_RECORDER)); | 375 | screens[i].puts(2, 4, str(LANG_SETTINGS_BATTERY_RECORDER)); |
1076 | lcd_update(); | 376 | screens[i].update(); |
1077 | #ifdef HAVE_REMOTE_LCD | ||
1078 | lcd_remote_puts(4, 2, str(LANG_SETTINGS_SAVE_RECORDER)); | ||
1079 | lcd_remote_puts(2, 4, str(LANG_SETTINGS_BATTERY_RECORDER)); | ||
1080 | lcd_remote_update(); | ||
1081 | #endif | ||
1082 | #endif | 377 | #endif |
378 | } | ||
1083 | sleep(HZ*2); | 379 | sleep(HZ*2); |
1084 | return -1; | 380 | return -1; |
1085 | } | 381 | } |
@@ -1147,6 +443,7 @@ void settings_apply(void) | |||
1147 | int i; | 443 | int i; |
1148 | #endif | 444 | #endif |
1149 | 445 | ||
446 | DEBUGF( "settings_apply()\n" ); | ||
1150 | sound_settings_apply(); | 447 | sound_settings_apply(); |
1151 | 448 | ||
1152 | audio_set_buffer_margin(global_settings.buffer_margin); | 449 | audio_set_buffer_margin(global_settings.buffer_margin); |
@@ -1207,8 +504,7 @@ void settings_apply(void) | |||
1207 | lcd_set_invert_display(global_settings.invert); | 504 | lcd_set_invert_display(global_settings.invert); |
1208 | lcd_set_flip(global_settings.flip_display); | 505 | lcd_set_flip(global_settings.flip_display); |
1209 | button_set_flip(global_settings.flip_display); | 506 | button_set_flip(global_settings.flip_display); |
1210 | if(global_settings.invert || global_settings.flip_display) | 507 | lcd_update(); /* refresh after flipping the screen */ |
1211 | lcd_update(); /* refresh after flipping the screen */ | ||
1212 | settings_apply_pm_range(); | 508 | settings_apply_pm_range(); |
1213 | peak_meter_init_times( | 509 | peak_meter_init_times( |
1214 | global_settings.peak_meter_release, global_settings.peak_meter_hold, | 510 | global_settings.peak_meter_release, global_settings.peak_meter_hold, |
@@ -1239,7 +535,6 @@ void settings_apply(void) | |||
1239 | unload_main_backdrop(); | 535 | unload_main_backdrop(); |
1240 | } | 536 | } |
1241 | show_main_backdrop(); | 537 | show_main_backdrop(); |
1242 | |||
1243 | #endif | 538 | #endif |
1244 | 539 | ||
1245 | #ifdef HAVE_LCD_COLOR | 540 | #ifdef HAVE_LCD_COLOR |
@@ -1344,131 +639,16 @@ void settings_apply(void) | |||
1344 | #endif | 639 | #endif |
1345 | } | 640 | } |
1346 | 641 | ||
1347 | |||
1348 | /* helper to load global_settings from a bitfield, as described per table */ | ||
1349 | static void load_bit_table(const struct bit_entry* p_table, int count, int bitstart) | ||
1350 | { | ||
1351 | uint32_t *p_bitfield = (uint32_t *)config_block; /* 32 bit addr. */ | ||
1352 | uint32_t value; /* 32 bit content */ | ||
1353 | int i; | ||
1354 | int maxbit; /* how many bits are valid in the saved part */ | ||
1355 | const struct bit_entry* p_run = p_table; /* start after the size info */ | ||
1356 | count--; /* first is excluded from loop */ | ||
1357 | maxbit = get_bits(p_bitfield, bitstart, p_table->bit_size); | ||
1358 | bitstart += p_table->bit_size; | ||
1359 | |||
1360 | for (i=0; i<count; i++) | ||
1361 | { | ||
1362 | int size; | ||
1363 | p_run++; | ||
1364 | |||
1365 | size = p_run->bit_size & 0x3F; /* mask off abused bits */ | ||
1366 | if (bitstart + size > maxbit) | ||
1367 | break; /* exit if this is not valid any more in bitfield */ | ||
1368 | |||
1369 | value = get_bits(p_bitfield, bitstart, size); | ||
1370 | bitstart += size; | ||
1371 | if (p_run->bit_size & SIGNED) | ||
1372 | { // sign extend the read value | ||
1373 | unsigned long mask = 0xFFFFFFFF << (size - 1); | ||
1374 | if (value & mask) /* true if MSB of value is set */ | ||
1375 | value |= mask; | ||
1376 | } | ||
1377 | |||
1378 | /* could do a memcpy, but that would be endian-dependent */ | ||
1379 | switch(p_run->byte_size) | ||
1380 | { | ||
1381 | case 1: | ||
1382 | ((uint8_t *)&global_settings)[p_run->settings_offset] = | ||
1383 | (unsigned char)value; | ||
1384 | break; | ||
1385 | case 2: | ||
1386 | ((uint16_t *)&global_settings)[p_run->settings_offset/2] = | ||
1387 | (unsigned short)value; | ||
1388 | break; | ||
1389 | case 4: | ||
1390 | ((uint32_t *)&global_settings)[p_run->settings_offset/4] = | ||
1391 | (unsigned int)value; | ||
1392 | break; | ||
1393 | default: | ||
1394 | DEBUGF( "load_bit_table: illegal size!\n" ); | ||
1395 | continue; | ||
1396 | } | ||
1397 | } | ||
1398 | } | ||
1399 | |||
1400 | |||
1401 | /* | 642 | /* |
1402 | * load settings from disk or RTC RAM | 643 | * load settings from disk or RTC RAM |
1403 | */ | 644 | */ |
1404 | void settings_load(int which) | 645 | void settings_load(int which) |
1405 | { | 646 | { |
1406 | int i; | ||
1407 | DEBUGF( "reload_all_settings()\n" ); | 647 | DEBUGF( "reload_all_settings()\n" ); |
1408 | 648 | if (which&SETTINGS_RTC) | |
1409 | /* load the buffer from the RTC (resets it to all-unused if the block | 649 | read_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE); |
1410 | is invalid) and decode the settings which are set in the block */ | 650 | if (which&SETTINGS_HD) |
1411 | if (!load_config_buffer(which)) | 651 | settings_load_config(CONFIGFILE,false); |
1412 | { | ||
1413 | /* load scalar values from RTC and HD sector, specified via table */ | ||
1414 | if (which & SETTINGS_RTC) | ||
1415 | { | ||
1416 | load_bit_table(rtc_bits, sizeof(rtc_bits)/sizeof(rtc_bits[0]), 4*8); | ||
1417 | } | ||
1418 | if (which & SETTINGS_HD) | ||
1419 | { | ||
1420 | load_bit_table(hd_bits, sizeof(hd_bits)/sizeof(hd_bits[0]), | ||
1421 | RTC_BLOCK_SIZE*8); | ||
1422 | } | ||
1423 | |||
1424 | #ifdef HAVE_RECORDING | ||
1425 | global_settings.recscreen_on = false; | ||
1426 | #endif | ||
1427 | |||
1428 | #ifdef HAVE_LCD_CONTRAST | ||
1429 | if ( global_settings.contrast < MIN_CONTRAST_SETTING || | ||
1430 | global_settings.contrast > MAX_CONTRAST_SETTING ) | ||
1431 | global_settings.contrast = lcd_default_contrast(); | ||
1432 | #endif | ||
1433 | |||
1434 | #ifdef HAVE_LCD_REMOTE | ||
1435 | if (global_settings.remote_contrast < MIN_REMOTE_CONTRAST_SETTING || | ||
1436 | global_settings.remote_contrast > MAX_REMOTE_CONTRAST_SETTING ) | ||
1437 | global_settings.remote_contrast = lcd_remote_default_contrast(); | ||
1438 | #endif | ||
1439 | i = 0xb8; | ||
1440 | strncpy((char *)global_settings.wps_file, (char *)&config_block[i], | ||
1441 | MAX_FILENAME); | ||
1442 | i+= MAX_FILENAME; | ||
1443 | strncpy((char *)global_settings.lang_file, (char *)&config_block[i], | ||
1444 | MAX_FILENAME); | ||
1445 | i+= MAX_FILENAME; | ||
1446 | strncpy((char *)global_settings.font_file, (char *)&config_block[i], | ||
1447 | MAX_FILENAME); | ||
1448 | i+= MAX_FILENAME; | ||
1449 | #ifdef HAVE_REMOTE_LCD | ||
1450 | strncpy((char *)global_settings.rwps_file, (char *)&config_block[i], | ||
1451 | MAX_FILENAME); | ||
1452 | i+= MAX_FILENAME; | ||
1453 | #endif | ||
1454 | |||
1455 | #ifdef CONFIG_TUNER | ||
1456 | strncpy((char *)global_settings.fmr_file, (char *)&config_block[i], | ||
1457 | MAX_FILENAME); | ||
1458 | i+= MAX_FILENAME; | ||
1459 | #endif | ||
1460 | |||
1461 | #if LCD_DEPTH > 1 | ||
1462 | strncpy((char *)global_settings.backdrop_file, (char *)&config_block[i], | ||
1463 | MAX_FILENAME); | ||
1464 | i+= MAX_FILENAME; | ||
1465 | #endif | ||
1466 | #ifdef HAVE_LCD_BITMAP | ||
1467 | strncpy((char *)global_settings.kbd_file, (char *)&config_block[i], | ||
1468 | MAX_FILENAME); | ||
1469 | i+= MAX_FILENAME; | ||
1470 | #endif | ||
1471 | } | ||
1472 | } | 652 | } |
1473 | 653 | ||
1474 | void set_file(char* filename, char* setting, int maxlen) | 654 | void set_file(char* filename, char* setting, int maxlen) |
@@ -1502,94 +682,13 @@ void set_file(char* filename, char* setting, int maxlen) | |||
1502 | settings_save(); | 682 | settings_save(); |
1503 | } | 683 | } |
1504 | 684 | ||
1505 | /* helper to sort a .cfg file entry into a global_settings member, | 685 | bool settings_load_config(const char* file, bool apply) |
1506 | as described per table. Returns the position if found, else 0. */ | ||
1507 | static int load_cfg_table( | ||
1508 | const struct bit_entry* p_table, /* the table which describes the entries */ | ||
1509 | int count, /* number of entries in the table, including the first */ | ||
1510 | const char* name, /* the item to be searched */ | ||
1511 | const char* value, /* the value which got loaded for that item */ | ||
1512 | int hint) /* position to start looking */ | ||
1513 | { | ||
1514 | int i = hint; | ||
1515 | |||
1516 | do | ||
1517 | { | ||
1518 | if (p_table[i].cfg_name != NULL && !strcasecmp(name, p_table[i].cfg_name)) | ||
1519 | { /* found */ | ||
1520 | int val = 0; | ||
1521 | if (p_table[i].cfg_val == NULL) | ||
1522 | { /* numerical value, just convert the string */ | ||
1523 | val = atoi(value); | ||
1524 | } | ||
1525 | #if HAVE_LCD_COLOR | ||
1526 | else if (!strncasecmp(p_table[i].cfg_val,"rgb",4)) | ||
1527 | { | ||
1528 | val = hex_to_rgb(value); | ||
1529 | } | ||
1530 | #endif | ||
1531 | else | ||
1532 | { /* set of string values, find the index */ | ||
1533 | const char* item; | ||
1534 | const char* run; | ||
1535 | int len = strlen(value); | ||
1536 | |||
1537 | item = run = p_table[i].cfg_val; | ||
1538 | |||
1539 | while(1) | ||
1540 | { | ||
1541 | /* count the length of the field */ | ||
1542 | while (*run != ',' && *run != '\0') | ||
1543 | run++; | ||
1544 | |||
1545 | if (!strncasecmp(value, item, MAX(run-item, len))) | ||
1546 | break; /* match, exit the search */ | ||
1547 | |||
1548 | if (*run == '\0') /* reached the end of the choices */ | ||
1549 | return i; /* return the position, but don't update */ | ||
1550 | |||
1551 | val++; /* count the item up */ | ||
1552 | run++; /* behind the ',' */ | ||
1553 | item = run; | ||
1554 | } | ||
1555 | } | ||
1556 | |||
1557 | /* could do a memcpy, but that would be endian-dependent */ | ||
1558 | switch(p_table[i].byte_size) | ||
1559 | { | ||
1560 | case 1: | ||
1561 | ((unsigned char*)&global_settings)[p_table[i].settings_offset] = | ||
1562 | (unsigned char)val; | ||
1563 | break; | ||
1564 | case 2: | ||
1565 | ((unsigned short*)&global_settings)[p_table[i].settings_offset/2] = | ||
1566 | (unsigned short)val; | ||
1567 | break; | ||
1568 | case 4: | ||
1569 | ((unsigned int*)&global_settings)[p_table[i].settings_offset/4] = | ||
1570 | (unsigned int)val; | ||
1571 | break; | ||
1572 | default: | ||
1573 | DEBUGF( "illegal size!" ); | ||
1574 | continue; | ||
1575 | } | ||
1576 | |||
1577 | return i; /* return the position */ | ||
1578 | } | ||
1579 | |||
1580 | i++; | ||
1581 | if (i==count) | ||
1582 | i=1; /* wraparound */ | ||
1583 | } while (i != hint); /* back where we started, all searched */ | ||
1584 | |||
1585 | return 0; /* indicate not found */ | ||
1586 | } | ||
1587 | |||
1588 | |||
1589 | bool settings_load_config(const char* file) | ||
1590 | { | 686 | { |
1591 | int fd; | 687 | int fd; |
1592 | char line[128]; | 688 | char line[128]; |
689 | char* name; | ||
690 | char* value; | ||
691 | int i; | ||
1593 | 692 | ||
1594 | fd = open(file, O_RDONLY); | 693 | fd = open(file, O_RDONLY); |
1595 | if (fd < 0) | 694 | if (fd < 0) |
@@ -1597,180 +696,91 @@ bool settings_load_config(const char* file) | |||
1597 | 696 | ||
1598 | while (read_line(fd, line, sizeof line) > 0) | 697 | while (read_line(fd, line, sizeof line) > 0) |
1599 | { | 698 | { |
1600 | char* name; | ||
1601 | char* value; | ||
1602 | const struct bit_entry* table[2] = { rtc_bits, hd_bits }; | ||
1603 | const int ta_size[2] = { | ||
1604 | sizeof(rtc_bits)/sizeof(rtc_bits[0]), | ||
1605 | sizeof(hd_bits)/sizeof(hd_bits[0]) | ||
1606 | }; | ||
1607 | int last_table = 0; /* which table was used last round */ | ||
1608 | int last_pos = 1; /* at which position did we succeed */ | ||
1609 | int pos; /* currently returned position */ | ||
1610 | |||
1611 | if (!settings_parseline(line, &name, &value)) | 699 | if (!settings_parseline(line, &name, &value)) |
1612 | continue; | 700 | continue; |
1613 | 701 | ||
1614 | /* check for the string values */ | 702 | for(i=0; i<nb_settings; i++) |
1615 | if (!strcasecmp(name, "wps")) { | ||
1616 | #if LCD_DEPTH > 1 | ||
1617 | unload_wps_backdrop(); | ||
1618 | #endif | ||
1619 | int fd2; | ||
1620 | if ((fd2 = open(value, O_RDONLY)) >= 0) { | ||
1621 | close(fd2); | ||
1622 | set_file(value, (char *)global_settings.wps_file, MAX_FILENAME); | ||
1623 | } | ||
1624 | } | ||
1625 | #if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1) | ||
1626 | else if (!strcasecmp(name, "rwps")) { | ||
1627 | int fd2; | ||
1628 | if ((fd2 = open(value, O_RDONLY)) >= 0) { | ||
1629 | close(fd2); | ||
1630 | set_file(value, (char *)global_settings.rwps_file, MAX_FILENAME); | ||
1631 | } | ||
1632 | } | ||
1633 | #endif | ||
1634 | else if (!strcasecmp(name, "lang")) { | ||
1635 | if (!lang_load(value)) | ||
1636 | { | ||
1637 | set_file(value, (char *)global_settings.lang_file, MAX_FILENAME); | ||
1638 | talk_init(); /* use voice of same language */ | ||
1639 | } | ||
1640 | } | ||
1641 | #ifdef CONFIG_TUNER | ||
1642 | else if (!strcasecmp(name, "fmr")) { | ||
1643 | set_file(value, global_settings.fmr_file, MAX_FILENAME); | ||
1644 | } | ||
1645 | #endif | ||
1646 | #ifdef HAVE_LCD_BITMAP | ||
1647 | else if (!strcasecmp(name, "font")) { | ||
1648 | if (font_load(value)) | ||
1649 | set_file(value, (char *)global_settings.font_file, MAX_FILENAME); | ||
1650 | } | ||
1651 | #endif | ||
1652 | #if LCD_DEPTH > 1 | ||
1653 | else if (!strcasecmp(name, "backdrop")) { | ||
1654 | if (load_main_backdrop(value)) { | ||
1655 | set_file(value, (char *)global_settings.backdrop_file, MAX_FILENAME); | ||
1656 | show_main_backdrop(); | ||
1657 | } | ||
1658 | } | ||
1659 | #endif | ||
1660 | #ifdef HAVE_LCD_BITMAP | ||
1661 | else if (!strcasecmp(name, "keyboard")) { | ||
1662 | if (!load_kbd(value)) | ||
1663 | set_file(value, (char *)global_settings.kbd_file, MAX_FILENAME); | ||
1664 | } | ||
1665 | #endif | ||
1666 | |||
1667 | |||
1668 | /* check for scalar values, using the two tables */ | ||
1669 | pos = load_cfg_table(table[last_table], ta_size[last_table], | ||
1670 | name, value, last_pos); | ||
1671 | if (pos) /* success */ | ||
1672 | { | 703 | { |
1673 | last_pos = pos; /* remember as a position hint for next round */ | 704 | if (settings[i].cfg_name == NULL) |
1674 | continue; | 705 | continue; |
1675 | } | 706 | if (!strcasecmp(name,settings[i].cfg_name)) |
1676 | 707 | { | |
1677 | last_table = 1-last_table; /* try other table */ | 708 | switch (settings[i].flags&F_T_MASK) |
1678 | last_pos = 1; /* search from start */ | 709 | { |
1679 | pos = load_cfg_table(table[last_table], ta_size[last_table], | 710 | case F_T_INT: |
1680 | name, value, last_pos); | 711 | case F_T_UINT: |
1681 | if (pos) /* success */ | 712 | #ifdef HAVE_LCD_COLOR |
1682 | { | 713 | if (settings[i].flags&F_RGB) |
1683 | last_pos = pos; /* remember as a position hint for next round */ | 714 | *(int*)settings[i].setting = hex_to_rgb(value); |
1684 | continue; | 715 | else |
1685 | } | 716 | #endif |
1686 | } | 717 | if (settings[i].cfg_vals == NULL) |
718 | { | ||
719 | *(int*)settings[i].setting = atoi(value); | ||
720 | } | ||
721 | else | ||
722 | { | ||
723 | char *s,*end; | ||
724 | char vals[MAX_PATH]; | ||
725 | int val = 0; | ||
726 | strncpy(vals,settings[i].cfg_vals,MAX_PATH); | ||
727 | s = strtok_r(vals,",",&end); | ||
728 | while (s) | ||
729 | { | ||
730 | if (!strcmp(value,s)) | ||
731 | { | ||
732 | *(int*)settings[i].setting = val; | ||
733 | break; | ||
734 | } | ||
735 | val++; | ||
736 | s = strtok_r(NULL,",",&end); | ||
737 | } | ||
738 | } | ||
739 | break; | ||
740 | case F_T_BOOL: | ||
741 | *(bool*)settings[i].setting = | ||
742 | !strncmp(value,"off",3)?false:true; | ||
743 | break; | ||
744 | case F_T_CHARPTR: | ||
745 | case F_T_UCHARPTR: | ||
746 | { | ||
747 | char storage[MAX_PATH]; | ||
748 | if (settings[i].filename_setting->prefix) | ||
749 | { | ||
750 | int len = strlen(settings[i].filename_setting->prefix); | ||
751 | if (!strncmp(value,settings[i].filename_setting->prefix,len)) | ||
752 | { | ||
753 | strncpy(storage,&value[len],MAX_PATH); | ||
754 | } | ||
755 | else strncpy(storage,value,MAX_PATH); | ||
756 | } | ||
757 | else strncpy(storage,value,MAX_PATH); | ||
758 | if (settings[i].filename_setting->suffix) | ||
759 | { | ||
760 | char *s = strcasestr(storage,settings[i].filename_setting->suffix); | ||
761 | if (s) *s = '\0'; | ||
762 | } | ||
763 | strncpy((char*)settings[i].setting,storage, | ||
764 | settings[i].filename_setting->max_len); | ||
765 | ((char*)settings[i].setting) | ||
766 | [settings[i].filename_setting->max_len-1] = '\0'; | ||
767 | break; | ||
768 | } | ||
769 | } | ||
770 | break; | ||
771 | } /* if (!strcmp(name,settings[i].cfg_name)) */ | ||
772 | } /* for(...) */ | ||
773 | } /* while(...) */ | ||
1687 | 774 | ||
1688 | close(fd); | 775 | close(fd); |
1689 | settings_apply(); | ||
1690 | settings_save(); | 776 | settings_save(); |
777 | if (apply) | ||
778 | settings_apply(); | ||
1691 | return true; | 779 | return true; |
1692 | } | 780 | } |
1693 | 781 | ||
1694 | |||
1695 | /* helper to save content of global_settings into a file, | ||
1696 | as described per table */ | ||
1697 | static void save_cfg_table(const struct bit_entry* p_table, int count, int fd) | ||
1698 | { | ||
1699 | long value; /* 32 bit content */ | ||
1700 | int i; | ||
1701 | const struct bit_entry* p_run = p_table; /* start after the size info */ | ||
1702 | count--; /* first is excluded from loop */ | ||
1703 | |||
1704 | for (i=0; i<count; i++) | ||
1705 | { | ||
1706 | p_run++; | ||
1707 | |||
1708 | if (p_run->cfg_name == NULL) | ||
1709 | continue; /* this value is not to be saved */ | ||
1710 | |||
1711 | /* could do a memcpy, but that would be endian-dependent */ | ||
1712 | switch(p_run->byte_size) | ||
1713 | { | ||
1714 | case 1: | ||
1715 | if (p_run->bit_size & SIGNED) /* signed? */ | ||
1716 | value = ((char*)&global_settings)[p_run->settings_offset]; | ||
1717 | else | ||
1718 | value = ((unsigned char*)&global_settings)[p_run->settings_offset]; | ||
1719 | break; | ||
1720 | case 2: | ||
1721 | if (p_run->bit_size & SIGNED) /* signed? */ | ||
1722 | value = ((short*)&global_settings)[p_run->settings_offset/2]; | ||
1723 | else | ||
1724 | value = ((unsigned short*)&global_settings)[p_run->settings_offset/2]; | ||
1725 | break; | ||
1726 | case 4: | ||
1727 | value = ((unsigned int*)&global_settings)[p_run->settings_offset/4]; | ||
1728 | break; | ||
1729 | default: | ||
1730 | DEBUGF( "illegal size!" ); | ||
1731 | continue; | ||
1732 | } | ||
1733 | |||
1734 | if (p_run->cfg_val == NULL) /* write as number */ | ||
1735 | { | ||
1736 | fdprintf(fd, "%s: %ld\r\n", p_run->cfg_name, value); | ||
1737 | } | ||
1738 | #ifdef HAVE_LCD_COLOR | ||
1739 | else if (!strcasecmp(p_run->cfg_val, "rgb")) | ||
1740 | { | ||
1741 | fdprintf(fd, "%s: %02x%02x%02x\r\n", p_run->cfg_name, | ||
1742 | (int)RGB_UNPACK_RED(value), | ||
1743 | (int)RGB_UNPACK_GREEN(value), | ||
1744 | (int)RGB_UNPACK_BLUE(value)); | ||
1745 | } | ||
1746 | #endif | ||
1747 | else /* write as item */ | ||
1748 | { | ||
1749 | const char* p = p_run->cfg_val; | ||
1750 | |||
1751 | fdprintf(fd, "%s: ", p_run->cfg_name); | ||
1752 | |||
1753 | while(value >= 0) | ||
1754 | { | ||
1755 | char c = *p++; /* currently processed char */ | ||
1756 | if (c == ',') /* separator */ | ||
1757 | value--; | ||
1758 | else if (c == '\0') /* end of string */ | ||
1759 | break; /* not found */ | ||
1760 | else if (value == 0) /* the right place */ | ||
1761 | write(fd, &c, 1); /* char by char, this is lame, OK */ | ||
1762 | } | ||
1763 | |||
1764 | fdprintf(fd, "\r\n"); | ||
1765 | if (p_run->cfg_val != off_on) /* explaination for non-bool */ | ||
1766 | fdprintf(fd, "# (possible values: %s)\r\n", p_run->cfg_val); | ||
1767 | } | ||
1768 | } | ||
1769 | } | ||
1770 | |||
1771 | bool settings_save_config(void) | 782 | bool settings_save_config(void) |
1772 | { | 783 | { |
1773 | int fd; | ||
1774 | char filename[MAX_PATH]; | 784 | char filename[MAX_PATH]; |
1775 | 785 | ||
1776 | create_numbered_filename(filename, ROCKBOX_DIR, "config", ".cfg", 2 | 786 | create_numbered_filename(filename, ROCKBOX_DIR, "config", ".cfg", 2 |
@@ -1779,11 +789,7 @@ bool settings_save_config(void) | |||
1779 | /* allow user to modify filename */ | 789 | /* allow user to modify filename */ |
1780 | while (true) { | 790 | while (true) { |
1781 | if (!kbd_input(filename, sizeof filename)) { | 791 | if (!kbd_input(filename, sizeof filename)) { |
1782 | fd = creat(filename, O_WRONLY); | 792 | break; |
1783 | if (fd < 0) | ||
1784 | gui_syncsplash(HZ, true, str(LANG_FAILED)); | ||
1785 | else | ||
1786 | break; | ||
1787 | } | 793 | } |
1788 | else { | 794 | else { |
1789 | gui_syncsplash(HZ, true, str(LANG_MENU_SETTING_CANCEL)); | 795 | gui_syncsplash(HZ, true, str(LANG_MENU_SETTING_CANCEL)); |
@@ -1791,145 +797,43 @@ bool settings_save_config(void) | |||
1791 | } | 797 | } |
1792 | } | 798 | } |
1793 | 799 | ||
1794 | fdprintf(fd, "# .cfg file created by rockbox %s - " | 800 | if (settings_write_config(filename)) |
1795 | "http://www.rockbox.org\r\n#\r\n#\r\n# wps / rwps / language" | 801 | gui_syncsplash(HZ, true, str(LANG_SETTINGS_SAVED)); |
1796 | " / font / fmpreset / backdrop \r\n#\r\n", appsversion); | 802 | else gui_syncsplash(HZ, true, str(LANG_FAILED)); |
1797 | |||
1798 | if (global_settings.wps_file[0] != 0) | ||
1799 | fdprintf(fd, "wps: %s/%s.wps\r\n", WPS_DIR, | ||
1800 | global_settings.wps_file); | ||
1801 | |||
1802 | #ifdef HAVE_REMOTE_LCD | ||
1803 | if (global_settings.rwps_file[0] != 0) | ||
1804 | fdprintf(fd, "rwps: %s/%s.rwps\r\n", WPS_DIR, | ||
1805 | global_settings.rwps_file); | ||
1806 | #endif | ||
1807 | |||
1808 | if (global_settings.lang_file[0] != 0) | ||
1809 | fdprintf(fd, "lang: %s/%s.lng\r\n", LANG_DIR, | ||
1810 | global_settings.lang_file); | ||
1811 | |||
1812 | #ifdef HAVE_LCD_BITMAP | ||
1813 | if (global_settings.font_file[0] != 0) | ||
1814 | fdprintf(fd, "font: %s/%s.fnt\r\n", FONT_DIR, | ||
1815 | global_settings.font_file); | ||
1816 | #endif | ||
1817 | |||
1818 | #if LCD_DEPTH > 1 | ||
1819 | if (global_settings.backdrop_file[0] != 0) | ||
1820 | fdprintf(fd, "backdrop: %s/%s.bmp\r\n", BACKDROP_DIR, | ||
1821 | global_settings.backdrop_file); | ||
1822 | #endif | ||
1823 | |||
1824 | #ifdef CONFIG_TUNER | ||
1825 | if (global_settings.fmr_file[0] != 0) | ||
1826 | fdprintf(fd, "fmr: %s/%s.fmr\r\n", FMPRESET_PATH, | ||
1827 | global_settings.fmr_file); | ||
1828 | #endif | ||
1829 | |||
1830 | #ifdef HAVE_LCD_BITMAP | ||
1831 | if (global_settings.kbd_file[0] != 0) | ||
1832 | fdprintf(fd, "keyboard: %s/%s.kbd\r\n", ROCKBOX_DIR, | ||
1833 | global_settings.kbd_file); | ||
1834 | #endif | ||
1835 | |||
1836 | /* here's the action: write values to file, specified via table */ | ||
1837 | save_cfg_table(rtc_bits, sizeof(rtc_bits)/sizeof(rtc_bits[0]), fd); | ||
1838 | save_cfg_table(hd_bits, sizeof(hd_bits)/sizeof(hd_bits[0]), fd); | ||
1839 | |||
1840 | close(fd); | ||
1841 | |||
1842 | gui_syncsplash(HZ, true, str(LANG_SETTINGS_SAVED)); | ||
1843 | return true; | 803 | return true; |
1844 | } | 804 | } |
1845 | 805 | ||
1846 | 806 | ||
1847 | /* helper to load defaults from table into global_settings members */ | ||
1848 | static void default_table(const struct bit_entry* p_table, int count) | ||
1849 | { | ||
1850 | int i; | ||
1851 | |||
1852 | for (i=1; i<count; i++) /* exclude the first, the size placeholder */ | ||
1853 | { | ||
1854 | /* could do a memcpy, but that would be endian-dependent */ | ||
1855 | switch(p_table[i].byte_size) | ||
1856 | { | ||
1857 | case 1: | ||
1858 | ((unsigned char*)&global_settings)[p_table[i].settings_offset] = | ||
1859 | (unsigned char)p_table[i].default_val; | ||
1860 | break; | ||
1861 | case 2: | ||
1862 | ((unsigned short*)&global_settings)[p_table[i].settings_offset/2] = | ||
1863 | (unsigned short)p_table[i].default_val; | ||
1864 | break; | ||
1865 | case 4: | ||
1866 | ((unsigned int*)&global_settings)[p_table[i].settings_offset/4] = | ||
1867 | (unsigned int)p_table[i].default_val; | ||
1868 | break; | ||
1869 | default: | ||
1870 | DEBUGF( "illegal size!" ); | ||
1871 | continue; | ||
1872 | } | ||
1873 | } | ||
1874 | } | ||
1875 | |||
1876 | 807 | ||
1877 | /* | 808 | /* |
1878 | * reset all settings to their default value | 809 | * reset all settings to their default value |
1879 | */ | 810 | */ |
1880 | void settings_reset(void) { | 811 | void settings_reset(void) { |
1881 | 812 | ||
813 | int i; | ||
1882 | DEBUGF( "settings_reset()\n" ); | 814 | DEBUGF( "settings_reset()\n" ); |
1883 | 815 | ||
1884 | /* read defaults from table(s) into global_settings */ | 816 | for(i=0; i<nb_settings; i++) |
1885 | default_table(rtc_bits, sizeof(rtc_bits)/sizeof(rtc_bits[0])); | 817 | { |
1886 | default_table(hd_bits, sizeof(hd_bits)/sizeof(hd_bits[0])); | 818 | switch (settings[i].flags&F_T_MASK) |
1887 | 819 | { | |
1888 | /* do some special cases not covered by table */ | 820 | case F_T_INT: |
1889 | global_settings.volume = sound_default(SOUND_VOLUME); | 821 | case F_T_UINT: |
1890 | global_settings.balance = sound_default(SOUND_BALANCE); | 822 | if (settings[i].flags&F_T_SOUND) |
1891 | global_settings.bass = sound_default(SOUND_BASS); | 823 | *(int*)settings[i].setting = |
1892 | global_settings.treble = sound_default(SOUND_TREBLE); | 824 | sound_default(settings[i].sound_setting->setting); |
1893 | global_settings.channel_config = sound_default(SOUND_CHANNELS); | 825 | else *(int*)settings[i].setting = settings[i].default_val.int_; |
1894 | global_settings.stereo_width = sound_default(SOUND_STEREO_WIDTH); | 826 | break; |
1895 | #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F) | 827 | case F_T_BOOL: |
1896 | global_settings.loudness = sound_default(SOUND_LOUDNESS); | 828 | *(bool*)settings[i].setting = settings[i].default_val.bool_; |
1897 | global_settings.avc = sound_default(SOUND_AVC); | 829 | break; |
1898 | global_settings.mdb_strength = sound_default(SOUND_MDB_STRENGTH); | 830 | case F_T_CHARPTR: |
1899 | global_settings.mdb_harmonics = sound_default(SOUND_MDB_HARMONICS); | 831 | case F_T_UCHARPTR: |
1900 | global_settings.mdb_center = sound_default(SOUND_MDB_CENTER); | 832 | strncpy((char*)settings[i].setting, |
1901 | global_settings.mdb_shape = sound_default(SOUND_MDB_SHAPE); | 833 | settings[i].default_val.charptr,MAX_FILENAME); |
1902 | global_settings.mdb_enable = sound_default(SOUND_MDB_ENABLE); | 834 | break; |
1903 | global_settings.superbass = sound_default(SOUND_SUPERBASS); | 835 | } |
1904 | #endif | 836 | } /* for(...) */ |
1905 | #ifdef HAVE_LCD_CONTRAST | ||
1906 | global_settings.contrast = lcd_default_contrast(); | ||
1907 | #endif | ||
1908 | #ifdef HAVE_LCD_REMOTE | ||
1909 | global_settings.remote_contrast = lcd_remote_default_contrast(); | ||
1910 | #endif | ||
1911 | |||
1912 | #ifdef CONFIG_TUNER | ||
1913 | global_settings.fmr_file[0] = '\0'; | ||
1914 | #endif | ||
1915 | global_settings.wps_file[0] = '\0'; | ||
1916 | #ifdef HAVE_REMOTE_LCD | ||
1917 | global_settings.rwps_file[0] = '\0'; | ||
1918 | #endif | ||
1919 | global_settings.font_file[0] = '\0'; | ||
1920 | global_settings.lang_file[0] = '\0'; | ||
1921 | #if LCD_DEPTH > 1 | ||
1922 | global_settings.backdrop_file[0] = '\0'; | ||
1923 | #endif | ||
1924 | #ifdef HAVE_LCD_COLOR | ||
1925 | global_settings.fg_color = LCD_DEFAULT_FG; | ||
1926 | global_settings.bg_color = LCD_DEFAULT_BG; | ||
1927 | #endif | ||
1928 | #ifdef HAVE_LCD_BITMAP | ||
1929 | global_settings.kbd_file[0] = '\0'; | ||
1930 | #endif | ||
1931 | global_settings.hold_lr_for_scroll_in_list = true; | ||
1932 | |||
1933 | #if defined (HAVE_RECORDING) && CONFIG_CODEC == SWCODEC | 837 | #if defined (HAVE_RECORDING) && CONFIG_CODEC == SWCODEC |
1934 | enc_global_settings_reset(); | 838 | enc_global_settings_reset(); |
1935 | #endif | 839 | #endif |