Update several codec Makefiles so that the codec libs build again on Coldfire targets...
[Rockbox.git] / apps / settings.c
blobda5a461d7d15c0be31b905646f18a337de29103d
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 by wavey@wavey.org
11 * RTC config saving code (C) 2002 by hessu@hes.iki.fi
13 * All files in this archive are subject to the GNU General Public License.
14 * See the file COPYING in the source tree root for full license agreement.
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
19 ****************************************************************************/
20 #include <stdio.h>
21 #include <stddef.h>
22 #include <limits.h>
23 #include "inttypes.h"
24 #include "config.h"
25 #include "kernel.h"
26 #include "thread.h"
27 #include "action.h"
28 #include "settings.h"
29 #include "disk.h"
30 #include "panic.h"
31 #include "debug.h"
32 #include "usb.h"
33 #include "backlight.h"
34 #include "lcd.h"
35 #include "audio.h"
36 #include "mp3_playback.h"
37 #include "mpeg.h"
38 #include "talk.h"
39 #include "string.h"
40 #include "ata.h"
41 #include "fat.h"
42 #include "power.h"
43 #include "powermgmt.h"
44 #include "status.h"
45 #include "atoi.h"
46 #include "screens.h"
47 #include "ctype.h"
48 #include "file.h"
49 #include "errno.h"
50 #include "system.h"
51 #include "misc.h"
52 #include "timefuncs.h"
53 #ifdef HAVE_LCD_BITMAP
54 #include "icons.h"
55 #include "font.h"
56 #include "peakmeter.h"
57 #include "hwcompat.h"
58 #endif
59 #include "lang.h"
60 #include "language.h"
61 #include "gwps.h"
62 #include "powermgmt.h"
63 #include "bookmark.h"
64 #include "sprintf.h"
65 #include "keyboard.h"
66 #include "version.h"
67 #include "rtc.h"
68 #include "sound.h"
69 #include "rbunicode.h"
70 #include "dircache.h"
71 #include "statusbar.h"
72 #include "splash.h"
73 #include "list.h"
74 #ifdef HAVE_LCD_COLOR
75 #include "backdrop.h"
76 #endif
78 #ifdef CONFIG_TUNER
79 #include "radio.h"
80 #endif
82 #if CONFIG_CODEC == MAS3507D
83 void dac_line_in(bool enable);
84 #endif
85 struct user_settings global_settings;
86 #ifdef HAVE_RECORDING
87 const char rec_base_directory[] = REC_BASE_DIR;
88 #endif
89 #if CONFIG_CODEC == SWCODEC
90 #include "pcmbuf.h"
91 #include "pcm_playback.h"
92 #include "dsp.h"
93 #endif
95 #ifdef HAVE_WM8758
96 #include "eq_menu.h"
97 #endif
99 #define CONFIG_BLOCK_VERSION 55
100 #define CONFIG_BLOCK_SIZE 512
101 #define RTC_BLOCK_SIZE 44
103 #ifdef HAVE_LCD_BITMAP
104 #define MAX_LINES 10
105 #else
106 #define MAX_LINES 2
107 #endif
109 #ifdef HAVE_REMOTE_LCD
110 #include "lcd-remote.h"
111 #endif
113 long lasttime = 0;
114 static long config_sector = 0; /* mark uninitialized */
115 static unsigned char config_block[CONFIG_BLOCK_SIZE];
118 /* descriptor for a configuration value */
119 /* (watch the struct packing and member sizes to keep this small) */
120 struct bit_entry
122 /* how many bits within the bitfield (1-32), MSB set if value is signed */
123 unsigned char bit_size; /* min 6+1 bit */
124 /* how many bytes in the global_settings struct (1,2,4) */
125 unsigned char byte_size; /* min 3 bits */
126 /* store position in global_settings struct */
127 short settings_offset; /* min 9 bit, better 10 */
128 /* default value */
129 int default_val; /* min 15 bit */
130 /* variable name in a .cfg file, NULL if not to be saved */
131 const char* cfg_name;
132 /* set of values, "rgb" for a color, or NULL for a numerical value */
133 const char* cfg_val;
136 /********************************************
138 Config block as saved on the battery-packed RTC user RAM memory block
139 of 44 bytes, starting at offset 0x14 of the RTC memory space.
141 offset abs
142 0x00 0x14 "Roc" header signature: 0x52 0x6f 0x63
143 0x03 0x17 <version byte: 0x0>
144 0x04 0x18 start of bit-table
146 0x28,0x29 unused, not reachable by set_bits() without disturbing the next 2
147 0x2A,0x2B <checksum 2 bytes: xor of 0x00-0x29>
149 Config memory is reset to 0xff and initialized with 'factory defaults' if
150 a valid header & checksum is not found. Config version number is only
151 increased when information is _relocated_ or space is _reused_ so that old
152 versions can read and modify configuration changed by new versions.
153 Memory locations not used by a given version should not be
154 modified unless the header & checksum test fails.
156 Rest of config block, only saved to disk:
157 0x2C start of 2nd bit-table
159 0xA4 (char[20]) FMR Preset file
160 0xB8 (char[20]) WPS file
161 0xCC (char[20]) Lang file
162 0xE0 (char[20]) Font file
163 ... (char[20]) RWPS file (on targets supporting a Remote WPS)
164 ... (char[20]) Main backdrop file (on color LCD targets)
166 ... to 0x200 <unused>
168 *************************************/
170 /* The persistence of the global_settings members is now controlled by
171 the two tables below, rtc_bits and hd_bits.
172 New values can just be added to the end, it will be backwards
173 compatible. If you however change order, bitsize, etc. of existing
174 entries, you need to bump CONFIG_BLOCK_VERSION to break compatibility.
178 /* convenience macro for both size and offset of global_settings member */
179 #define S_O(val) sizeof(global_settings.val), offsetof(struct user_settings, val)
180 #define SIGNED 0x80 /* for bitsize value with signed attribute */
182 /* some sets of values which are used more than once, to save memory */
183 static const char off_on[] = "off,on";
184 static const char off_on_ask[] = "off,on,ask";
185 static const char off_number_spell_hover[] = "off,number,spell,hover";
186 #ifdef HAVE_LCD_BITMAP
187 static const char graphic_numeric[] = "graphic,numeric";
188 #endif
190 #ifdef HAVE_RECORDING
191 /* keep synchronous to trig_durations and
192 trigger_times in settings_apply_trigger */
193 static const char trig_durations_conf [] =
194 "0s,1s,2s,5s,10s,15s,20s,25s,30s,1min,2min,5min,10min";
195 #endif
197 #if defined(CONFIG_BACKLIGHT)
198 static const char backlight_times_conf [] =
199 "off,on,1,2,3,4,5,6,7,8,9,10,15,20,25,30,45,60,90";
200 #endif
202 /* the part of the settings which ends up in the RTC RAM, where available
203 (those we either need early, save frequently, or without spinup) */
204 static const struct bit_entry rtc_bits[] =
206 /* placeholder, containing the size information */
207 {9, 0, 0, 0, NULL, NULL }, /* 9 bit to tell how far this is populated */
209 /* # of bits, offset+size, default, .cfg name, .cfg values */
210 /* sound */
211 #if CONFIG_CODEC == MAS3507D
212 {8 | SIGNED, S_O(volume), -18, "volume", NULL }, /* -78...+18 */
213 #else
214 {8 | SIGNED, S_O(volume), -25, "volume", NULL }, /* -100...+12 / -84...0 */
215 #endif
216 {8 | SIGNED, S_O(balance), 0, "balance", NULL }, /* -100...100 */
217 #if CONFIG_CODEC != SWCODEC /* any MAS */
218 {5 | SIGNED, S_O(bass), 0, "bass", NULL }, /* -15..+15 / -12..+12 */
219 {5 | SIGNED, S_O(treble), 0, "treble", NULL }, /* -15..+15 / -12..+12 */
220 #elif defined HAVE_UDA1380
221 {5, S_O(bass), 0, "bass", NULL }, /* 0..+24 */
222 {3, S_O(treble), 0, "treble", NULL }, /* 0..+6 */
223 #elif defined(HAVE_WM8975) || defined(HAVE_WM8758) \
224 || defined(HAVE_WM8731) || defined(HAVE_WM8721)
225 {5 | SIGNED, S_O(bass), 0, "bass", NULL }, /* -6..+9 */
226 {5 | SIGNED, S_O(treble), 0, "treble", NULL }, /* -6..+9 */
227 #endif
228 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
229 {5, S_O(loudness), 0, "loudness", NULL }, /* 0...17 */
230 {3, S_O(avc), 0, "auto volume", "off,20ms,2,4,8" },
231 {1, S_O(superbass), false, "superbass", off_on },
232 #endif
233 {3, S_O(channel_config), 0, "channels",
234 "stereo,mono,custom,mono left,mono right,karaoke" },
235 {8, S_O(stereo_width), 100, "stereo width", NULL},
236 /* playback */
237 {1, S_O(resume), false, "resume", off_on },
238 {1, S_O(playlist_shuffle), false, "shuffle", off_on },
239 {16 | SIGNED, S_O(resume_index), -1, NULL, NULL },
240 {16 | SIGNED, S_O(resume_first_index), 0, NULL, NULL },
241 {32 | SIGNED, S_O(resume_offset), -1, NULL, NULL },
242 {32 | SIGNED, S_O(resume_seed), -1, NULL, NULL },
243 {3, S_O(repeat_mode), REPEAT_ALL, "repeat", "off,all,one,shuffle,ab" },
244 /* LCD */
245 #ifdef HAVE_LCD_CONTRAST
246 {6, S_O(contrast), DEFAULT_CONTRAST_SETTING, "contrast", NULL },
247 #endif
248 #ifdef CONFIG_BACKLIGHT
249 {5, S_O(backlight_timeout), 6, "backlight timeout", backlight_times_conf },
250 #ifdef CONFIG_CHARGING
251 {5, S_O(backlight_timeout_plugged), 11, "backlight timeout plugged",
252 backlight_times_conf },
253 #endif
254 #endif /* CONFIG_BACKLIGHT */
255 #ifdef HAVE_LCD_BITMAP
256 {1, S_O(invert), false, "invert", off_on },
257 {1, S_O(flip_display), false, "flip display", off_on },
258 /* display */
259 {1, S_O(invert_cursor), true, "invert cursor", off_on },
260 {1, S_O(statusbar), true, "statusbar", off_on },
261 {1, S_O(scrollbar), true, "scrollbar", off_on },
262 #if CONFIG_KEYPAD == RECORDER_PAD
263 {1, S_O(buttonbar), true, "buttonbar", off_on },
264 #endif
265 {1, S_O(volume_type), 0, "volume display", graphic_numeric },
266 {1, S_O(battery_display), 0, "battery display", graphic_numeric },
267 {1, S_O(timeformat), 0, "time format", "24hour,12hour" },
268 #endif /* HAVE_LCD_BITMAP */
269 {1, S_O(show_icons), true, "show icons", off_on },
270 /* system */
271 {4, S_O(poweroff), 10,
272 "idle poweroff", "off,1,2,3,4,5,6,7,8,9,10,15,30,45,60" },
273 {18, S_O(runtime), 0, NULL, NULL },
274 {18, S_O(topruntime), 0, NULL, NULL },
275 #if MEM > 1
276 {15, S_O(max_files_in_playlist), 10000,
277 "max files in playlist", NULL }, /* 1000...20000 */
278 {14, S_O(max_files_in_dir), 400,
279 "max files in dir", NULL }, /* 50...10000 */
280 #else
281 {15, S_O(max_files_in_playlist), 1000,
282 "max files in playlist", NULL }, /* 1000...20000 */
283 {14, S_O(max_files_in_dir), 200,
284 "max files in dir", NULL }, /* 50...10000 */
285 #endif
286 /* battery */
287 {12, S_O(battery_capacity), BATTERY_CAPACITY_DEFAULT, "battery capacity",
288 NULL }, /* 1500...3200 for NiMH, 2200...3200 for LiIon,
289 500...1500 for Alkaline */
290 #ifdef CONFIG_CHARGING
291 {1, S_O(car_adapter_mode), false, "car adapter mode", off_on },
292 #endif
293 /* tuner */
294 #ifdef CONFIG_TUNER
295 {1, S_O(fm_force_mono), false, "force fm mono", off_on },
296 {9, S_O(last_frequency), 0, NULL, NULL }, /* Default: MIN_FREQ */
297 #endif
299 #if BATTERY_TYPES_COUNT > 1
300 {1, S_O(battery_type), 0, "battery type", "alkaline,nimh" },
301 #endif
303 #ifdef HAVE_REMOTE_LCD
304 /* remote lcd */
305 {6, S_O(remote_contrast), DEFAULT_REMOTE_CONTRAST_SETTING,
306 "remote contrast", NULL },
307 {1, S_O(remote_invert), false, "remote invert", off_on },
308 {1, S_O(remote_flip_display), false, "remote flip display", off_on },
309 {5, S_O(remote_backlight_timeout), 6, "remote backlight timeout",
310 backlight_times_conf },
311 #ifdef CONFIG_CHARGING
312 {5, S_O(remote_backlight_timeout_plugged), 11,
313 "remote backlight timeout plugged", backlight_times_conf },
314 #endif
315 #ifdef HAVE_REMOTE_LCD_TICKING
316 {1, S_O(remote_reduce_ticking), false, "remote reduce ticking", off_on },
317 #endif
318 #endif
320 #ifdef CONFIG_BACKLIGHT
321 {1, S_O(bl_filter_first_keypress), false,
322 "backlight filters first keypress", off_on },
323 #ifdef HAVE_REMOTE_LCD
324 {1, S_O(remote_bl_filter_first_keypress), false,
325 "backlight filters first remote keypress", off_on },
326 #endif
327 #endif /* CONFIG_BACKLIGHT */
329 /* new stuff to be added here */
330 /* If values are just added to the end, no need to bump the version. */
332 /* Current sum of bits: 277 (worst case, but w/o remote lcd) */
333 /* Sum of all bit sizes must not grow beyond 288! */
337 /* the part of the settings which ends up in HD sector only */
338 static const struct bit_entry hd_bits[] =
340 /* This table starts after the 44 RTC bytes = 352 bits. */
341 /* Here we need 11 bits to tell how far this is populated. */
343 /* placeholder, containing the size information */
344 {11, 0, 0, 0, NULL, NULL }, /* 11 bit to tell how far this is populated */
346 /* # of bits, offset+size, default, .cfg name, .cfg values */
347 /* more display */
348 #ifdef CONFIG_BACKLIGHT
349 {1, S_O(caption_backlight), false, "caption backlight", off_on },
350 #endif
351 #ifdef HAVE_REMOTE_LCD
352 {1, S_O(remote_caption_backlight), false,
353 "remote caption backlight", off_on },
354 #endif
355 #ifdef HAVE_BACKLIGHT_BRIGHTNESS
356 {4, S_O(brightness), DEFAULT_BRIGHTNESS_SETTING, "brightness", NULL },
357 #endif
358 #ifdef HAVE_BACKLIGHT_PWM_FADING
359 /* backlight fading */
360 {2, S_O(backlight_fade_in), 1, "backlight fade in", "off,500ms,1s,2s"},
361 {3, S_O(backlight_fade_out), 3, "backlight fade out",
362 "off,500ms,1s,2s,3s,4s,5s,10s"},
363 #endif
365 {4, S_O(scroll_speed), 9, "scroll speed", NULL }, /* 0...15 */
366 {8, S_O(scroll_delay), 100, "scroll delay", NULL }, /* 0...250 */
367 {8, S_O(bidir_limit), 50, "bidir limit", NULL }, /* 0...200 */
369 #ifdef HAVE_REMOTE_LCD
370 {4, S_O(remote_scroll_speed), 9, "remote scroll speed", NULL }, /* 0...15 */
371 {8, S_O(remote_scroll_step), 6, "remote scroll step", NULL }, /* 1...160 */
372 {8, S_O(remote_scroll_delay), 100, "remote scroll delay", NULL }, /* 0...250 */
373 {8, S_O(remote_bidir_limit), 50, "remote bidir limit", NULL }, /* 0...200 */
374 #endif
376 #ifdef HAVE_LCD_BITMAP
377 {1, S_O(offset_out_of_view), false, "Screen Scrolls Out Of View", off_on },
378 #if LCD_WIDTH > 255
379 {9, S_O(scroll_step), 6, "scroll step", NULL },
380 {9, S_O(screen_scroll_step), 16, "screen scroll step", NULL },
381 #elif LCD_WIDTH > 127
382 {8, S_O(scroll_step), 6, "scroll step", NULL },
383 {8, S_O(screen_scroll_step), 16, "screen scroll step", NULL },
384 #else
385 {7, S_O(scroll_step), 6, "scroll step", NULL },
386 {7, S_O(screen_scroll_step), 16, "screen scroll step", NULL },
387 #endif
388 #endif /* HAVE_LCD_BITMAP */
389 #ifdef HAVE_LCD_CHARCELLS
390 {3, S_O(jump_scroll), 0, "jump scroll", NULL }, /* 0...5 */
391 {8, S_O(jump_scroll_delay), 50, "jump scroll delay", NULL }, /* 0...250 */
392 #endif
393 {1, S_O(scroll_paginated), false, "scroll paginated", off_on },
395 #ifdef HAVE_LCD_COLOR
396 {LCD_DEPTH,S_O(fg_color),LCD_DEFAULT_FG,"foreground color","rgb"},
397 {LCD_DEPTH,S_O(bg_color),LCD_DEFAULT_BG,"background color","rgb"},
398 #endif
400 /* more playback */
401 {1, S_O(play_selected), true, "play selected", off_on },
402 {1, S_O(fade_on_stop), true, "volume fade", off_on },
403 {4, S_O(ff_rewind_min_step), FF_REWIND_1000,
404 "scan min step", "1,2,3,4,5,6,8,10,15,20,25,30,45,60" },
405 {4, S_O(ff_rewind_accel), 3, "scan accel", NULL },
406 #if CONFIG_CODEC == SWCODEC
407 {3, S_O(buffer_margin), 0, "antiskip",
408 "5s,15s,30s,1min,2min,3min,5min,10min" },
409 #else
410 {3, S_O(buffer_margin), 0, "antiskip", NULL },
411 #endif
412 /* disk */
413 #ifndef HAVE_MMC
414 #ifdef HAVE_ATA_POWER_OFF
415 {1, S_O(disk_poweroff), false, "disk poweroff", off_on },
416 #endif
417 {8, S_O(disk_spindown), 5, "disk spindown", NULL },
418 #endif /* HAVE_MMC */
420 /* browser */
421 {3, S_O(dirfilter), SHOW_SUPPORTED,
422 "show files", "all,supported,music,playlists"
423 #ifdef HAVE_TAGCACHE
424 ",id3 database"
425 #endif
427 {1, S_O(sort_case), false, "sort case", off_on },
428 {1, S_O(browse_current), false, "follow playlist", off_on },
429 /* playlist */
430 {1, S_O(playlist_viewer_icons), true, "playlist viewer icons", off_on },
431 {1, S_O(playlist_viewer_indices), true,
432 "playlist viewer indices", off_on },
433 {1, S_O(playlist_viewer_track_display), 0,
434 "playlist viewer track display", "track name,full path" },
435 {2, S_O(recursive_dir_insert), RECURSE_OFF,
436 "recursive directory insert", off_on_ask },
437 /* bookmarks */
438 {3, S_O(autocreatebookmark), BOOKMARK_NO, "autocreate bookmarks",
439 "off,on,ask,recent only - on,recent only - ask" },
440 {2, S_O(autoloadbookmark), BOOKMARK_NO,
441 "autoload bookmarks", off_on_ask },
442 {2, S_O(usemrb), BOOKMARK_NO,
443 "use most-recent-bookmarks", "off,on,unique only" },
444 #ifdef HAVE_LCD_BITMAP
445 /* peak meter */
446 {5, S_O(peak_meter_clip_hold), 16, "peak meter clip hold", /* 0...25 */
447 "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" },
448 {5, S_O(peak_meter_hold), 3, "peak meter hold",
449 "off,200ms,300ms,500ms,1,2,3,4,5,6,7,8,9,10,15,20,30,1min" },
450 {7, S_O(peak_meter_release), 8, "peak meter release", NULL }, /* 0...126 */
451 {1, S_O(peak_meter_dbfs), true, "peak meter dbfs", off_on },
452 {7, S_O(peak_meter_min), 60, "peak meter min", NULL }, /* 0...100 */
453 {7, S_O(peak_meter_max), 0, "peak meter max", NULL }, /* 0...100 */
454 #endif
455 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
456 {7, S_O(mdb_strength), 0, "mdb strength", NULL},
457 {7, S_O(mdb_harmonics), 0, "mdb harmonics", NULL},
458 {9, S_O(mdb_center), 0, "mdb center", NULL},
459 {9, S_O(mdb_shape), 0, "mdb shape", NULL},
460 {1, S_O(mdb_enable), 0, "mdb enable", off_on},
461 #endif
462 #if CONFIG_CODEC == MAS3507D
463 {1, S_O(line_in), false, "line in", off_on },
464 #endif
465 /* voice */
466 {2, S_O(talk_dir), 0, "talk dir", off_number_spell_hover },
467 {2, S_O(talk_file), 0, "talk file", off_number_spell_hover },
468 {1, S_O(talk_menu), true, "talk menu", off_on },
470 {2, S_O(sort_file), 0, "sort files", "alpha,oldest,newest,type" },
471 {2, S_O(sort_dir), 0, "sort dirs", "alpha,oldest,newest" },
472 {1, S_O(id3_v1_first), 0, "id3 tag priority", "v2-v1,v1-v2"},
474 #ifdef HAVE_RECORDING
475 /* recording */
476 {1, S_O(recscreen_on), false, "recscreen on", off_on },
477 {1, S_O(rec_startup), false, "rec screen on startup", off_on },
478 {4, S_O(rec_timesplit), 0, "rec timesplit", /* 0...15 */
479 "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" },
480 {4, S_O(rec_sizesplit), 0, "rec sizesplit", /* 0...15 */
481 "off,5MB,10MB,15MB,32MB,64MB,75MB,100MB,128MB,256MB,512MB,650MB,700MB,1GB,1.5GB,1.75GB" },
482 {1, S_O(rec_channels), 0, "rec channels", "stereo,mono" },
483 {1, S_O(rec_split_type), 0, "rec split type", "Split, Stop" },
484 {1, S_O(rec_split_method), 0, "rec split method", "Time,Filesize" },
487 #if defined(HAVE_SPDIF_IN) || defined(HAVE_FMRADIO_IN)
489 #else
491 #endif
492 S_O(rec_source), 0 /* 0=mic */, "rec source",
493 "mic,line"
494 #ifdef HAVE_SPDIF_IN
495 ",spdif"
496 #endif
497 #ifdef HAVE_FMRADIO_IN
498 ",fmradio"
499 #endif
501 {5, S_O(rec_prerecord_time), 0, "prerecording time", NULL }, /* 0...30 */
502 {1, S_O(rec_directory), 0, /* rec_base_directory */
503 "rec directory", REC_BASE_DIR ",current" },
504 #ifdef CONFIG_BACKLIGHT
505 {2, S_O(cliplight), 0, "cliplight", "off,main,both,remote" },
506 #endif
507 #if CONFIG_CODEC == MAS3587F
508 {4, S_O(rec_mic_gain), 8, "rec mic gain", NULL },
509 {4, S_O(rec_left_gain), 2 /* 0dB */, "rec left gain", NULL }, /* 0...15 */
510 {4, S_O(rec_right_gain), 2 /* 0dB */, "rec right gain", NULL }, /* 0...15 */
511 {3, S_O(rec_frequency), 0, /* 0=44.1kHz */
512 "rec frequency", "44,48,32,22,24,16" },
513 {3, S_O(rec_quality), 5 /* 192 kBit/s max */, "rec quality", NULL },
514 {1, S_O(rec_editable), false, "editable recordings", off_on },
515 #endif /* CONFIG_CODEC == MAS3587F */
517 #if CONFIG_CODEC == SWCODEC && defined(HAVE_RECORDING)
518 #ifdef HAVE_UDA1380
519 {8|SIGNED, S_O(rec_mic_gain), 16 /* 8 dB */, "rec mic gain", NULL }, /* -128...+108 */
520 #endif
521 #ifdef HAVE_TLV320
522 /* TLV320 only has no mic boost or 20db mic boost */
523 {1, S_O(rec_mic_gain), 0 /* 0 dB */, "rec mic gain", NULL }, /* 0db or 20db */
524 #endif
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 #if 0 /* Till samplerates are added for SWCODEC */
528 {3, S_O(rec_frequency), 0, /* 0=44.1kHz */
529 "rec frequency", "44,48,32,22,24,16" },
530 #else
531 {3, S_O(rec_frequency), 0, /* 0=44.1kHz */
532 "rec frequency", "44" },
533 #endif
535 {4, S_O(rec_quality), 4 /* MP3 L3 192 kBit/s */, "rec quality", NULL },
536 #endif /* CONFIG_CODEC == SWCODEC && defined(HAVE_RECORDING) */
538 /* values for the trigger */
539 {8 | SIGNED, S_O(rec_start_thres), -35, "trigger start threshold", NULL},
540 {8 | SIGNED, S_O(rec_stop_thres), -45, "trigger stop threshold", NULL},
541 {4, S_O(rec_start_duration), 0, "trigger start duration", trig_durations_conf},
542 {4, S_O(rec_stop_postrec), 2, "trigger stop postrec", trig_durations_conf},
543 {4, S_O(rec_stop_gap), 1, "trigger min gap", trig_durations_conf},
544 {4, S_O(rec_trigger_mode ), 0, "trigger mode", "off,once,repeat"},
545 #endif /* HAVE_RECORDING */
547 #ifdef HAVE_SPDIF_POWER
548 {1, S_O(spdif_enable), false, "spdif enable", off_on},
549 #endif
551 {2, S_O(next_folder), false, "folder navigation", "off,on,random" },
552 {1, S_O(runtimedb), false, "gather runtime data", off_on },
554 #if CONFIG_CODEC == SWCODEC
555 {1, S_O(replaygain), false, "replaygain", off_on },
556 {2, S_O(replaygain_type), REPLAYGAIN_ALBUM, "replaygain type",
557 "track,album,track shuffle" },
558 {1, S_O(replaygain_noclip), false, "replaygain noclip", off_on },
559 {8 | SIGNED, S_O(replaygain_preamp), 0, "replaygain preamp", NULL },
560 {2, S_O(beep), 0, "beep", "off,weak,moderate,strong" },
561 {2, S_O(crossfade), 0, "crossfade", "off,shuffle,track skip,always"},
562 {3, S_O(crossfade_fade_in_delay), 0, "crossfade fade in delay", NULL},
563 {3, S_O(crossfade_fade_out_delay), 0, "crossfade fade out delay", NULL},
564 {4, S_O(crossfade_fade_in_duration), 0, "crossfade fade in duration", NULL},
565 {4, S_O(crossfade_fade_out_duration), 0, "crossfade fade out duration", NULL},
566 {1, S_O(crossfade_fade_out_mixmode), 0, "crossfade fade out mode", "crossfade,mix"},
567 {1, S_O(crossfeed), false, "crossfeed", off_on },
568 {6, S_O(crossfeed_direct_gain), 15, "crossfeed direct gain", NULL },
569 {7, S_O(crossfeed_cross_gain), 60, "crossfeed cross gain", NULL },
570 {8, S_O(crossfeed_hf_attenuation), 160, "crossfeed hf attenuation", NULL },
571 {11, S_O(crossfeed_hf_cutoff), 700, "crossfeed hf cutoff", NULL },
573 /* equalizer */
574 {1, S_O(eq_enabled), false, "eq enabled", off_on },
575 {8, S_O(eq_precut), 0, "eq precut", NULL },
576 /* 0..32768 Hz */
577 {15, S_O(eq_band0_cutoff), 60, "eq band 0 cutoff", NULL },
578 {15, S_O(eq_band1_cutoff), 200, "eq band 1 cutoff", NULL },
579 {15, S_O(eq_band2_cutoff), 800, "eq band 2 cutoff", NULL },
580 {15, S_O(eq_band3_cutoff), 4000, "eq band 3 cutoff", NULL },
581 {15, S_O(eq_band4_cutoff), 12000, "eq band 4 cutoff", NULL },
582 /* 0..64 (or 0.0 to 6.4) */
583 {6, S_O(eq_band0_q), 7, "eq band 0 q", NULL },
584 {6, S_O(eq_band1_q), 10, "eq band 1 q", NULL },
585 {6, S_O(eq_band2_q), 10, "eq band 2 q", NULL },
586 {6, S_O(eq_band3_q), 10, "eq band 3 q", NULL },
587 {6, S_O(eq_band4_q), 7, "eq band 4 q", NULL },
588 /* -240..240 (or -24db to +24db) */
589 {9|SIGNED, S_O(eq_band0_gain), 0, "eq band 0 gain", NULL },
590 {9|SIGNED, S_O(eq_band1_gain), 0, "eq band 1 gain", NULL },
591 {9|SIGNED, S_O(eq_band2_gain), 0, "eq band 2 gain", NULL },
592 {9|SIGNED, S_O(eq_band3_gain), 0, "eq band 3 gain", NULL },
593 {9|SIGNED, S_O(eq_band4_gain), 0, "eq band 4 gain", NULL },
595 /* dithering */
596 {1, S_O(dithering_enabled), false, "dithering enabled", off_on },
597 #endif
599 #ifdef HAVE_DIRCACHE
600 {1, S_O(dircache), false, "dircache", off_on },
601 {22, S_O(dircache_size), 0, NULL, NULL },
602 #endif
604 #ifdef HAVE_TAGCACHE
605 #ifdef HAVE_TC_RAMCACHE
606 {1, S_O(tagcache_ram), 0, "tagcache_ram", off_on },
607 #endif
608 {1, S_O(tagcache_autoupdate), 0, "tagcache_autoupdate", off_on },
609 #endif
611 {4, S_O(default_codepage), 0, "default codepage",
612 "iso8859-1,iso8859-7,iso8859-8,cp1251,iso8859-11,cp1256,iso8859-9,iso8859-2,sjis,gb2312,ksx1001,big5,utf-8,cp1256" },
614 {1, S_O(warnon_erase_dynplaylist), false,
615 "warn when erasing dynamic playlist", off_on },
617 #ifdef CONFIG_BACKLIGHT
618 #ifdef HAS_BUTTON_HOLD
619 {2, S_O(backlight_on_button_hold), 0, "backlight on button hold",
620 "normal,off,on" },
621 #endif
623 #ifdef HAVE_LCD_SLEEP
624 {4, S_O(lcd_sleep_after_backlight_off), 3,
625 "lcd sleep after backlight off",
626 "always,never,5,10,15,20,30,45,60,90" },
627 #endif
628 #endif /* CONFIG_BACKLIGHT */
630 #ifdef HAVE_WM8758
631 {1, S_O(eq_hw_enabled), false, "eq hardware enabled", off_on },
633 {2, S_O(eq_hw_band0_cutoff), 1, "eq hardware band 0 cutoff", "80Hz,105Hz,135Hz,175Hz" },
634 {5|SIGNED, S_O(eq_hw_band0_gain), 0, "eq hardware band 0 gain", NULL },
636 {2, S_O(eq_hw_band1_center), 1, "eq hardware band 1 center", "230Hz,300Hz,385Hz,500Hz" },
637 {1, S_O(eq_hw_band1_bandwidth), 0, "eq hardware band 1 bandwidth", "narrow,wide" },
638 {5|SIGNED, S_O(eq_hw_band1_gain), 0, "eq hardware band 1 gain", NULL },
640 {2, S_O(eq_hw_band2_center), 1, "eq hardware band 2 center", "650Hz,850Hz,1.1kHz,1.4kHz" },
641 {1, S_O(eq_hw_band2_bandwidth), 0, "eq hardware band 2 bandwidth", "narrow,wide" },
642 {5|SIGNED, S_O(eq_hw_band2_gain), 0, "eq hardware band 2 gain", NULL },
644 {2, S_O(eq_hw_band3_center), 1, "eq hardware band 3 center", "1.8kHz,2.4kHz,3.2kHz,4.1kHz" },
645 {1, S_O(eq_hw_band3_bandwidth), 0, "eq hardware band 3 bandwidth", "narrow,wide" },
646 {5|SIGNED, S_O(eq_hw_band3_gain), 0, "eq hardware band 3 gain", NULL },
648 {2, S_O(eq_hw_band4_cutoff), 1, "eq hardware band 4 cutoff", "5.3kHz,6.9kHz,9kHz,11.7kHz" },
649 {5|SIGNED, S_O(eq_hw_band4_gain), 0, "eq hardware band 4 gain", NULL },
650 #endif
651 {1, S_O(hold_lr_for_scroll_in_list), true, "hold_lr_for_scroll_in_list", off_on },
653 {2, S_O(show_path_in_browser), 0, "show path in browser", "off,current directory,full path" },
654 #ifdef HAVE_AGC
655 {4, S_O(rec_agc_preset_mic), 1, "agc mic preset", NULL}, /* 0...5 */
656 {4, S_O(rec_agc_preset_line), 1, "agc line preset", NULL}, /* 0...5 */
657 {8|SIGNED, S_O(rec_agc_maxgain_mic), 104, "agc maximum mic gain", NULL},
658 {8|SIGNED, S_O(rec_agc_maxgain_line), 96, "agc maximum line gain", NULL},
659 {3, S_O(rec_agc_cliptime), 1, "agc cliptime", "0.2s,0.4s,0.6s,0.8,1s"},
660 #endif
662 #ifdef HAVE_REMOTE_LCD
663 #ifdef HAS_REMOTE_BUTTON_HOLD
664 {2, S_O(remote_backlight_on_button_hold), 0, "remote backlight on button hold",
665 "normal,off,on" },
666 #endif
667 #endif
669 #ifdef HAVE_HEADPHONE_DETECTION
670 {2, S_O(unplug_mode), 0, "pause on headphone unplug", NULL},
671 {4, S_O(unplug_rw), 0, "rewind duration on pause", NULL},
672 {1, S_O(unplug_autoresume), 0, "disable autoresume if phones not present", off_on },
673 #endif
674 #ifdef CONFIG_TUNER
675 {2, S_O(fm_region), 0, "fm_region", "eu,us,jp,kr" },
676 #endif
678 {1, S_O(audioscrobbler), false, "Last.fm Logging", off_on},
680 /* If values are just added to the end, no need to bump the version. */
681 /* new stuff to be added at the end */
683 /* Sum of all bit sizes must not grow beyond 0xB8*8 = 1472 */
686 /* helper function to extract n (<=32) bits from an arbitrary position
687 * counting from LSB to MSB */
688 static uint32_t get_bits(
689 const uint32_t *p, /* the start of the bitfield array */
690 unsigned int from, /* bit no. to start reading from */
691 unsigned int size) /* how many bits to read */
693 unsigned int long_index = from / 32;
694 unsigned int bit_index = from % 32;
695 uint32_t result;
697 result = p[long_index] >> bit_index;
699 if (bit_index + size > 32) /* crossing longword boundary */
700 result |= p[long_index+1] << (32 - bit_index);
702 result &= 0xFFFFFFFF >> (32 - size);
704 return result;
707 /* helper function to set n (<=32) bits to an arbitrary position,
708 * counting from LSB to MSB */
709 static void set_bits(
710 uint32_t *p, /* the start of the bitfield array */
711 unsigned int from, /* bit no. to start writing into */
712 unsigned int size, /* how many bits to change */
713 uint32_t value) /* content (LSBs will be taken) */
715 unsigned int long_index = from / 32;
716 unsigned int bit_index = from % 32;
717 uint32_t mask;
719 mask = 0xFFFFFFFF >> (32 - size);
720 value &= mask;
721 mask <<= bit_index;
723 if (bit_index + size > 32)
724 p[long_index+1] =
725 (p[long_index+1] & (0xFFFFFFFF << (bit_index + size - 32)))
726 | (value >> (32 - bit_index));
728 p[long_index] = (p[long_index] & ~mask) | (value << bit_index);
731 #ifdef HAVE_LCD_COLOR
733 * Helper function to convert a string of 6 hex digits to a native colour
736 #define hex2dec(c) (((c) >= '0' && ((c) <= '9')) ? (toupper(c)) - '0' : \
737 (toupper(c)) - 'A' + 10)
739 int hex_to_rgb(const char* hex)
740 { int ok = 1;
741 int i;
742 int red, green, blue;
744 if (strlen(hex) == 6) {
745 for (i=0; i < 6; i++ ) {
746 if (!isxdigit(hex[i])) {
747 ok=0;
748 break;
752 if (ok) {
753 red = (hex2dec(hex[0]) << 4) | hex2dec(hex[1]);
754 green = (hex2dec(hex[2]) << 4) | hex2dec(hex[3]);
755 blue = (hex2dec(hex[4]) << 4) | hex2dec(hex[5]);
756 return LCD_RGBPACK(red,green,blue);
760 return 0;
762 #endif
765 * Calculates the checksum for the config block and returns it
768 static unsigned short calculate_config_checksum(const unsigned char* buf)
770 unsigned int i;
771 unsigned char cksum[2];
772 cksum[0] = cksum[1] = 0;
774 for (i=0; i < RTC_BLOCK_SIZE - 2; i+=2 ) {
775 cksum[0] ^= buf[i];
776 cksum[1] ^= buf[i+1];
779 return (cksum[0] << 8) | cksum[1];
783 * initialize the config block buffer
785 static void init_config_buffer( void )
787 DEBUGF( "init_config_buffer()\n" );
789 /* reset to 0 - all unused */
790 memset(config_block, 0, CONFIG_BLOCK_SIZE);
791 /* insert header */
792 config_block[0] = 'R';
793 config_block[1] = 'o';
794 config_block[2] = 'c';
795 config_block[3] = CONFIG_BLOCK_VERSION;
799 * save the config block buffer to disk or RTC RAM
801 static int save_config_buffer( void )
803 unsigned short chksum;
804 #ifdef HAVE_RTC_RAM
805 unsigned int i;
806 #endif
808 /* update the checksum in the end of the block before saving */
809 chksum = calculate_config_checksum(config_block);
810 config_block[ RTC_BLOCK_SIZE - 2 ] = chksum >> 8;
811 config_block[ RTC_BLOCK_SIZE - 1 ] = chksum & 0xff;
813 #ifdef HAVE_RTC_RAM
814 /* FIXME: okay, it _would_ be cleaner and faster to implement rtc_write so
815 that it would write a number of bytes at a time since the RTC chip
816 supports that, but this will have to do for now 8-) */
817 for (i=0; i < RTC_BLOCK_SIZE; i++ ) {
818 int r = rtc_write(0x14+i, config_block[i]);
819 if (r) {
820 DEBUGF( "save_config_buffer: rtc_write failed at addr 0x%02x: %d\n",
821 14+i, r );
822 return r;
826 #endif
828 if (config_sector != 0)
829 ata_delayed_write( config_sector, config_block);
830 else
831 return -1;
833 return 0;
837 * load the config block buffer from disk or RTC RAM
839 static int load_config_buffer(int which)
841 unsigned short chksum;
842 bool correct = false;
845 DEBUGF( "load_config_buffer()\n" );
847 if (which & SETTINGS_HD)
849 if (config_sector != 0) {
850 ata_read_sectors(IF_MV2(0,) config_sector, 1, config_block);
851 /* calculate the checksum, check it and the header */
852 chksum = calculate_config_checksum(config_block);
854 if (config_block[0] == 'R' &&
855 config_block[1] == 'o' &&
856 config_block[2] == 'c' &&
857 config_block[3] == CONFIG_BLOCK_VERSION &&
858 (chksum >> 8) == config_block[RTC_BLOCK_SIZE - 2] &&
859 (chksum & 0xff) == config_block[RTC_BLOCK_SIZE - 1])
861 DEBUGF( "load_config_buffer: header & checksum test ok\n" );
862 correct = true;
867 #ifdef HAVE_RTC_RAM
868 if(!correct)
870 /* If the disk sector was incorrect, reinit the buffer */
871 memset(config_block, 0, CONFIG_BLOCK_SIZE);
874 if (which & SETTINGS_RTC)
876 unsigned int i;
877 unsigned char rtc_block[RTC_BLOCK_SIZE];
879 /* read rtc block */
880 for (i=0; i < RTC_BLOCK_SIZE; i++ )
881 rtc_block[i] = rtc_read(0x14+i);
883 chksum = calculate_config_checksum(rtc_block);
885 /* if rtc block is ok, use that */
886 if (rtc_block[0] == 'R' &&
887 rtc_block[1] == 'o' &&
888 rtc_block[2] == 'c' &&
889 rtc_block[3] == CONFIG_BLOCK_VERSION &&
890 (chksum >> 8) == rtc_block[RTC_BLOCK_SIZE - 2] &&
891 (chksum & 0xff) == rtc_block[RTC_BLOCK_SIZE - 1])
893 memcpy(config_block, rtc_block, RTC_BLOCK_SIZE);
894 correct = true;
897 #endif
899 if ( !correct ) {
900 /* if checksum is not valid, clear the config buffer */
901 DEBUGF( "load_config_buffer: header & checksum test failed\n" );
902 init_config_buffer();
903 return -1;
906 return 0;
910 /* helper to save content of global_settings into a bitfield,
911 as described per table */
912 static void save_bit_table(const struct bit_entry* p_table, int count, int bitstart)
914 uint32_t *p_bitfield = (uint32_t *)config_block; /* 32 bit addr. */
915 uint32_t value; /* 32 bit content */
916 int i;
917 const struct bit_entry* p_run = p_table; /* start after the size info */
918 int curr_bit = bitstart + p_table->bit_size;
919 count--; /* first is excluded from loop */
921 for (i=0; i<count; i++)
923 p_run++;
924 /* could do a memcpy, but that would be endian-dependent */
925 switch(p_run->byte_size)
927 case 1:
928 value = ((uint8_t *)&global_settings)[p_run->settings_offset];
929 break;
930 case 2:
931 value = ((uint16_t *)&global_settings)[p_run->settings_offset/2];
932 break;
933 case 4:
934 value = ((uint32_t *)&global_settings)[p_run->settings_offset/4];
935 break;
936 default:
937 DEBUGF( "save_bit_table: illegal size!\n" );
938 continue;
940 set_bits(p_bitfield, curr_bit, p_run->bit_size & 0x3F, value);
941 curr_bit += p_run->bit_size & 0x3F;
943 set_bits(p_bitfield, bitstart, p_table->bit_size, /* write size */
944 curr_bit); /* = position after last element */
948 * figure out the config sector from the partition table and the
949 * mounted file system
951 void settings_calc_config_sector(void)
953 #ifdef SIMULATOR
954 config_sector = 61;
955 #else
956 int i;
957 long partition_start;
958 long sector = 0;
960 if (fat_startsector(IF_MV(0)) != 0) /* There is a partition table */
962 sector = 61;
963 for (i = 0; i < 4; i++)
965 partition_start = disk_partinfo(i)->start;
966 if (partition_start != 0 && (partition_start - 2) < sector)
967 sector = partition_start - 2;
969 if (sector < 0)
970 sector = 0;
973 config_sector = sector;
974 #endif
978 * persist all runtime user settings to disk or RTC RAM
980 int settings_save( void )
982 int i;
985 int elapsed_secs;
987 elapsed_secs = (current_tick - lasttime) / HZ;
988 global_settings.runtime += elapsed_secs;
989 lasttime += (elapsed_secs * HZ);
991 if ( global_settings.runtime > global_settings.topruntime )
992 global_settings.topruntime = global_settings.runtime;
995 /* serialize scalar values into RTC and HD sector, specified via table */
996 save_bit_table(rtc_bits, sizeof(rtc_bits)/sizeof(rtc_bits[0]), 4*8);
997 save_bit_table(hd_bits, sizeof(hd_bits)/sizeof(hd_bits[0]), RTC_BLOCK_SIZE*8);
999 i = 0xb8;
1000 strncpy((char *)&config_block[i], (char *)global_settings.wps_file,
1001 MAX_FILENAME);
1002 i+= MAX_FILENAME;
1003 strncpy((char *)&config_block[i], (char *)global_settings.lang_file,
1004 MAX_FILENAME);
1005 i+= MAX_FILENAME;
1006 strncpy((char *)&config_block[i], (char *)global_settings.font_file,
1007 MAX_FILENAME);
1008 i+= MAX_FILENAME;
1009 #ifdef HAVE_REMOTE_LCD
1010 strncpy((char *)&config_block[i], (char *)global_settings.rwps_file,
1011 MAX_FILENAME);
1012 i+= MAX_FILENAME;
1013 #endif
1015 #ifdef CONFIG_TUNER
1016 strncpy((char *)&config_block[i], (char *)global_settings.fmr_file,
1017 MAX_FILENAME);
1018 i+= MAX_FILENAME;
1019 #endif
1021 #ifdef HAVE_LCD_COLOR
1022 strncpy((char *)&config_block[i], (char *)global_settings.backdrop_file,
1023 MAX_FILENAME);
1024 i+= MAX_FILENAME;
1025 #endif
1026 #ifdef HAVE_LCD_BITMAP
1027 strncpy((char *)&config_block[i], (char *)global_settings.kbd_file,
1028 MAX_FILENAME);
1029 i+= MAX_FILENAME;
1030 #endif
1032 if(save_config_buffer())
1034 lcd_clear_display();
1035 #ifdef HAVE_REMOTE_LCD
1036 lcd_remote_clear_display();
1037 #endif
1038 #ifdef HAVE_LCD_CHARCELLS
1039 lcd_puts(0, 0, str(LANG_SETTINGS_SAVE_PLAYER));
1040 lcd_puts(0, 1, str(LANG_SETTINGS_BATTERY_PLAYER));
1041 #else
1042 lcd_puts(4, 2, str(LANG_SETTINGS_SAVE_RECORDER));
1043 lcd_puts(2, 4, str(LANG_SETTINGS_BATTERY_RECORDER));
1044 lcd_update();
1045 #ifdef HAVE_REMOTE_LCD
1046 lcd_remote_puts(4, 2, str(LANG_SETTINGS_SAVE_RECORDER));
1047 lcd_remote_puts(2, 4, str(LANG_SETTINGS_BATTERY_RECORDER));
1048 lcd_remote_update();
1049 #endif
1050 #endif
1051 sleep(HZ*2);
1052 return -1;
1054 return 0;
1057 #ifdef HAVE_LCD_BITMAP
1059 * Applies the range infos stored in global_settings to
1060 * the peak meter.
1062 void settings_apply_pm_range(void)
1064 int pm_min, pm_max;
1066 /* depending on the scale mode (dBfs or percent) the values
1067 of global_settings.peak_meter_dbfs have different meanings */
1068 if (global_settings.peak_meter_dbfs)
1070 /* convert to dBfs * 100 */
1071 pm_min = -(((int)global_settings.peak_meter_min) * 100);
1072 pm_max = -(((int)global_settings.peak_meter_max) * 100);
1074 else
1076 /* percent is stored directly -> no conversion */
1077 pm_min = global_settings.peak_meter_min;
1078 pm_max = global_settings.peak_meter_max;
1081 /* apply the range */
1082 peak_meter_init_range(global_settings.peak_meter_dbfs, pm_min, pm_max);
1084 #endif /* HAVE_LCD_BITMAP */
1086 void sound_settings_apply(void)
1088 sound_set(SOUND_BASS, global_settings.bass);
1089 sound_set(SOUND_TREBLE, global_settings.treble);
1090 sound_set(SOUND_BALANCE, global_settings.balance);
1091 sound_set(SOUND_VOLUME, global_settings.volume);
1092 #if CONFIG_CODEC == SWCODEC
1093 channels_set(global_settings.channel_config);
1094 stereo_width_set(global_settings.stereo_width);
1095 #else
1096 sound_set(SOUND_CHANNELS, global_settings.channel_config);
1097 sound_set(SOUND_STEREO_WIDTH, global_settings.stereo_width);
1098 #endif
1099 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
1100 sound_set(SOUND_LOUDNESS, global_settings.loudness);
1101 sound_set(SOUND_AVC, global_settings.avc);
1102 sound_set(SOUND_MDB_STRENGTH, global_settings.mdb_strength);
1103 sound_set(SOUND_MDB_HARMONICS, global_settings.mdb_harmonics);
1104 sound_set(SOUND_MDB_CENTER, global_settings.mdb_center);
1105 sound_set(SOUND_MDB_SHAPE, global_settings.mdb_shape);
1106 sound_set(SOUND_MDB_ENABLE, global_settings.mdb_enable);
1107 sound_set(SOUND_SUPERBASS, global_settings.superbass);
1108 #endif
1111 void settings_apply(void)
1113 char buf[64];
1114 #if CONFIG_CODEC == SWCODEC
1115 int i;
1116 #endif
1118 sound_settings_apply();
1120 audio_set_buffer_margin(global_settings.buffer_margin);
1122 #ifdef HAVE_LCD_CONTRAST
1123 lcd_set_contrast(global_settings.contrast);
1124 #endif
1125 lcd_scroll_speed(global_settings.scroll_speed);
1126 #ifdef HAVE_REMOTE_LCD
1127 lcd_remote_set_contrast(global_settings.remote_contrast);
1128 lcd_remote_set_invert_display(global_settings.remote_invert);
1129 lcd_remote_set_flip(global_settings.remote_flip_display);
1130 lcd_remote_scroll_speed(global_settings.remote_scroll_speed);
1131 lcd_remote_scroll_step(global_settings.remote_scroll_step);
1132 lcd_remote_scroll_delay(global_settings.remote_scroll_delay * (HZ/10));
1133 lcd_remote_bidir_scroll(global_settings.remote_bidir_limit);
1134 #ifdef HAVE_REMOTE_LCD_TICKING
1135 lcd_remote_emireduce(global_settings.remote_reduce_ticking);
1136 #endif
1137 remote_backlight_set_timeout(global_settings.remote_backlight_timeout);
1138 #ifdef CONFIG_CHARGING
1139 remote_backlight_set_timeout_plugged(global_settings.remote_backlight_timeout_plugged);
1140 #endif
1141 #ifdef HAS_REMOTE_BUTTON_HOLD
1142 remote_backlight_set_on_button_hold(global_settings.remote_backlight_on_button_hold);
1143 #endif
1144 #endif /* HAVE_REMOTE_LCD */
1145 #ifdef CONFIG_BACKLIGHT
1146 backlight_set_timeout(global_settings.backlight_timeout);
1147 #ifdef CONFIG_CHARGING
1148 backlight_set_timeout_plugged(global_settings.backlight_timeout_plugged);
1149 #endif
1150 #if defined(HAVE_BACKLIGHT_PWM_FADING) && !defined(SIMULATOR)
1151 backlight_set_fade_in(global_settings.backlight_fade_in);
1152 backlight_set_fade_out(global_settings.backlight_fade_out);
1153 #endif
1154 #endif
1155 #ifdef HAVE_BACKLIGHT_BRIGHTNESS
1156 backlight_set_brightness(global_settings.brightness);
1157 #endif
1158 ata_spindown(global_settings.disk_spindown);
1159 #if (CONFIG_CODEC == MAS3507D) && !defined(SIMULATOR)
1160 dac_line_in(global_settings.line_in);
1161 #endif
1162 mpeg_id3_options(global_settings.id3_v1_first);
1163 #ifdef HAVE_ATA_POWER_OFF
1164 ata_poweroff(global_settings.disk_poweroff);
1165 #endif
1167 set_poweroff_timeout(global_settings.poweroff);
1169 set_battery_capacity(global_settings.battery_capacity);
1170 #if BATTERY_TYPES_COUNT > 1
1171 set_battery_type(global_settings.battery_type);
1172 #endif
1174 #ifdef HAVE_LCD_BITMAP
1175 lcd_set_invert_display(global_settings.invert);
1176 lcd_set_flip(global_settings.flip_display);
1177 button_set_flip(global_settings.flip_display);
1178 lcd_update(); /* refresh after flipping the screen */
1179 settings_apply_pm_range();
1180 peak_meter_init_times(
1181 global_settings.peak_meter_release, global_settings.peak_meter_hold,
1182 global_settings.peak_meter_clip_hold);
1183 #endif
1185 #ifdef HAVE_LCD_COLOR
1186 unload_wps_backdrop();
1187 #endif
1188 if ( global_settings.wps_file[0] &&
1189 global_settings.wps_file[0] != 0xff ) {
1190 snprintf(buf, sizeof buf, WPS_DIR "/%s.wps",
1191 global_settings.wps_file);
1192 wps_data_load(gui_wps[0].data, buf, true);
1194 else
1196 wps_data_init(gui_wps[0].data);
1199 #ifdef HAVE_LCD_COLOR
1200 if ( global_settings.backdrop_file[0] &&
1201 global_settings.backdrop_file[0] != 0xff ) {
1202 snprintf(buf, sizeof buf, BACKDROP_DIR "/%s.bmp",
1203 global_settings.backdrop_file);
1204 load_main_backdrop(buf);
1205 } else {
1206 unload_main_backdrop();
1208 show_main_backdrop();
1210 screens[SCREEN_MAIN].set_foreground(global_settings.fg_color);
1211 screens[SCREEN_MAIN].set_background(global_settings.bg_color);
1212 #endif
1214 #if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1)
1215 if ( global_settings.rwps_file[0] &&
1216 global_settings.rwps_file[0] != 0xff ) {
1217 snprintf(buf, sizeof buf, WPS_DIR "/%s.rwps",
1218 global_settings.rwps_file);
1219 wps_data_load(gui_wps[1].data, buf, true);
1221 else
1222 wps_data_init(gui_wps[1].data);
1223 #endif
1225 #ifdef HAVE_LCD_BITMAP
1226 if ( global_settings.font_file[0] &&
1227 global_settings.font_file[0] != 0xff ) {
1228 snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt",
1229 global_settings.font_file);
1230 font_load(buf);
1232 else
1233 font_reset();
1235 if ( global_settings.kbd_file[0] &&
1236 global_settings.kbd_file[0] != 0xff ) {
1237 snprintf(buf, sizeof buf, ROCKBOX_DIR "/%s.kbd",
1238 global_settings.kbd_file);
1239 load_kbd(buf);
1241 else
1242 load_kbd(NULL);
1244 lcd_scroll_step(global_settings.scroll_step);
1245 gui_list_screen_scroll_step(global_settings.screen_scroll_step);
1246 gui_list_screen_scroll_out_of_view(global_settings.offset_out_of_view);
1247 #else
1248 lcd_jump_scroll(global_settings.jump_scroll);
1249 lcd_jump_scroll_delay(global_settings.jump_scroll_delay * (HZ/10));
1250 #endif
1251 lcd_bidir_scroll(global_settings.bidir_limit);
1252 lcd_scroll_delay(global_settings.scroll_delay * (HZ/10));
1254 if ( global_settings.lang_file[0] &&
1255 global_settings.lang_file[0] != 0xff ) {
1256 snprintf(buf, sizeof buf, LANG_DIR "/%s.lng",
1257 global_settings.lang_file);
1258 lang_load(buf);
1259 talk_init(); /* use voice of same language */
1262 set_codepage(global_settings.default_codepage);
1264 #if CONFIG_CODEC == SWCODEC
1265 audio_set_crossfade(global_settings.crossfade);
1266 dsp_set_replaygain(true);
1267 dsp_set_crossfeed(global_settings.crossfeed);
1268 dsp_set_crossfeed_direct_gain(global_settings.crossfeed_direct_gain);
1269 dsp_set_crossfeed_cross_params(global_settings.crossfeed_cross_gain,
1270 global_settings.crossfeed_cross_gain
1271 + global_settings.crossfeed_hf_attenuation,
1272 global_settings.crossfeed_hf_cutoff);
1274 dsp_set_eq(global_settings.eq_enabled);
1275 dsp_set_eq_precut(global_settings.eq_precut);
1276 /* Update all EQ bands */
1277 for(i = 0; i < 5; i++) {
1278 dsp_set_eq_coefs(i);
1281 dsp_dither_enable(global_settings.dithering_enabled);
1282 #endif
1284 #ifdef HAVE_WM8758
1285 eq_hw_enable(global_settings.eq_hw_enabled);
1286 #endif
1288 #ifdef HAVE_SPDIF_POWER
1289 spdif_power_enable(global_settings.spdif_enable);
1290 #endif
1292 #ifdef CONFIG_BACKLIGHT
1293 set_backlight_filter_keypress(global_settings.bl_filter_first_keypress);
1294 #ifdef HAVE_REMOTE_LCD
1295 set_remote_backlight_filter_keypress(global_settings.remote_bl_filter_first_keypress);
1296 #endif
1297 #ifdef HAS_BUTTON_HOLD
1298 backlight_set_on_button_hold(global_settings.backlight_on_button_hold);
1299 #endif
1300 #ifdef HAVE_LCD_SLEEP
1301 lcd_set_sleep_after_backlight_off(global_settings.lcd_sleep_after_backlight_off);
1302 #endif
1303 #endif /* CONFIG_BACKLIGHT */
1307 /* helper to load global_settings from a bitfield, as described per table */
1308 static void load_bit_table(const struct bit_entry* p_table, int count, int bitstart)
1310 uint32_t *p_bitfield = (uint32_t *)config_block; /* 32 bit addr. */
1311 uint32_t value; /* 32 bit content */
1312 int i;
1313 int maxbit; /* how many bits are valid in the saved part */
1314 const struct bit_entry* p_run = p_table; /* start after the size info */
1315 count--; /* first is excluded from loop */
1316 maxbit = get_bits(p_bitfield, bitstart, p_table->bit_size);
1317 bitstart += p_table->bit_size;
1319 for (i=0; i<count; i++)
1321 int size;
1322 p_run++;
1324 size = p_run->bit_size & 0x3F; /* mask off abused bits */
1325 if (bitstart + size > maxbit)
1326 break; /* exit if this is not valid any more in bitfield */
1328 value = get_bits(p_bitfield, bitstart, size);
1329 bitstart += size;
1330 if (p_run->bit_size & SIGNED)
1331 { // sign extend the read value
1332 unsigned long mask = 0xFFFFFFFF << (size - 1);
1333 if (value & mask) /* true if MSB of value is set */
1334 value |= mask;
1337 /* could do a memcpy, but that would be endian-dependent */
1338 switch(p_run->byte_size)
1340 case 1:
1341 ((uint8_t *)&global_settings)[p_run->settings_offset] =
1342 (unsigned char)value;
1343 break;
1344 case 2:
1345 ((uint16_t *)&global_settings)[p_run->settings_offset/2] =
1346 (unsigned short)value;
1347 break;
1348 case 4:
1349 ((uint32_t *)&global_settings)[p_run->settings_offset/4] =
1350 (unsigned int)value;
1351 break;
1352 default:
1353 DEBUGF( "load_bit_table: illegal size!\n" );
1354 continue;
1361 * load settings from disk or RTC RAM
1363 void settings_load(int which)
1365 int i;
1366 DEBUGF( "reload_all_settings()\n" );
1368 /* load the buffer from the RTC (resets it to all-unused if the block
1369 is invalid) and decode the settings which are set in the block */
1370 if (!load_config_buffer(which))
1372 /* load scalar values from RTC and HD sector, specified via table */
1373 if (which & SETTINGS_RTC)
1375 load_bit_table(rtc_bits, sizeof(rtc_bits)/sizeof(rtc_bits[0]), 4*8);
1377 if (which & SETTINGS_HD)
1379 load_bit_table(hd_bits, sizeof(hd_bits)/sizeof(hd_bits[0]),
1380 RTC_BLOCK_SIZE*8);
1383 #ifdef HAVE_RECORDING
1384 global_settings.recscreen_on = false;
1385 #endif
1387 #ifdef HAVE_LCD_CONTRAST
1388 if ( global_settings.contrast < MIN_CONTRAST_SETTING ||
1389 global_settings.contrast > MAX_CONTRAST_SETTING )
1390 global_settings.contrast = lcd_default_contrast();
1391 #endif
1393 #ifdef HAVE_LCD_REMOTE
1394 if (global_settings.remote_contrast < MIN_REMOTE_CONTRAST_SETTING ||
1395 global_settings.remote_contrast > MAX_REMOTE_CONTRAST_SETTING )
1396 global_settings.remote_contrast = lcd_remote_default_contrast();
1397 #endif
1398 i = 0xb8;
1399 strncpy((char *)global_settings.wps_file, (char *)&config_block[i],
1400 MAX_FILENAME);
1401 i+= MAX_FILENAME;
1402 strncpy((char *)global_settings.lang_file, (char *)&config_block[i],
1403 MAX_FILENAME);
1404 i+= MAX_FILENAME;
1405 strncpy((char *)global_settings.font_file, (char *)&config_block[i],
1406 MAX_FILENAME);
1407 i+= MAX_FILENAME;
1408 #ifdef HAVE_REMOTE_LCD
1409 strncpy((char *)global_settings.rwps_file, (char *)&config_block[i],
1410 MAX_FILENAME);
1411 i+= MAX_FILENAME;
1412 #endif
1414 #ifdef CONFIG_TUNER
1415 strncpy((char *)global_settings.fmr_file, (char *)&config_block[i],
1416 MAX_FILENAME);
1417 i+= MAX_FILENAME;
1418 #endif
1420 #ifdef HAVE_LCD_COLOR
1421 strncpy((char *)global_settings.backdrop_file, (char *)&config_block[i],
1422 MAX_FILENAME);
1423 i+= MAX_FILENAME;
1424 #endif
1425 #ifdef HAVE_LCD_BITMAP
1426 strncpy((char *)global_settings.kbd_file, (char *)&config_block[i],
1427 MAX_FILENAME);
1428 i+= MAX_FILENAME;
1429 #endif
1433 void set_file(char* filename, char* setting, int maxlen)
1435 char* fptr = strrchr(filename,'/');
1436 int len;
1437 int extlen = 0;
1438 char* ptr;
1440 if (!fptr)
1441 return;
1443 *fptr = 0;
1444 fptr++;
1446 len = strlen(fptr);
1447 ptr = fptr + len;
1448 while ((*ptr != '.') && (ptr != fptr)) {
1449 extlen++;
1450 ptr--;
1452 if(ptr == fptr) extlen = 0;
1454 if (strncasecmp(ROCKBOX_DIR, filename ,strlen(ROCKBOX_DIR)) ||
1455 (len-extlen > maxlen))
1456 return;
1458 strncpy(setting, fptr, len-extlen);
1459 setting[len-extlen]=0;
1461 settings_save();
1464 /* helper to sort a .cfg file entry into a global_settings member,
1465 as described per table. Returns the position if found, else 0. */
1466 static int load_cfg_table(
1467 const struct bit_entry* p_table, /* the table which describes the entries */
1468 int count, /* number of entries in the table, including the first */
1469 const char* name, /* the item to be searched */
1470 const char* value, /* the value which got loaded for that item */
1471 int hint) /* position to start looking */
1473 int i = hint;
1477 if (p_table[i].cfg_name != NULL && !strcasecmp(name, p_table[i].cfg_name))
1478 { /* found */
1479 int val = 0;
1480 if (p_table[i].cfg_val == NULL)
1481 { /* numerical value, just convert the string */
1482 val = atoi(value);
1484 #if HAVE_LCD_COLOR
1485 else if (!strncasecmp(p_table[i].cfg_val,"rgb",4))
1487 val = hex_to_rgb(value);
1489 #endif
1490 else
1491 { /* set of string values, find the index */
1492 const char* item;
1493 const char* run;
1494 int len = strlen(value);
1496 item = run = p_table[i].cfg_val;
1498 while(1)
1500 /* count the length of the field */
1501 while (*run != ',' && *run != '\0')
1502 run++;
1504 if (!strncasecmp(value, item, MAX(run-item, len)))
1505 break; /* match, exit the search */
1507 if (*run == '\0') /* reached the end of the choices */
1508 return i; /* return the position, but don't update */
1510 val++; /* count the item up */
1511 run++; /* behind the ',' */
1512 item = run;
1516 /* could do a memcpy, but that would be endian-dependent */
1517 switch(p_table[i].byte_size)
1519 case 1:
1520 ((unsigned char*)&global_settings)[p_table[i].settings_offset] =
1521 (unsigned char)val;
1522 break;
1523 case 2:
1524 ((unsigned short*)&global_settings)[p_table[i].settings_offset/2] =
1525 (unsigned short)val;
1526 break;
1527 case 4:
1528 ((unsigned int*)&global_settings)[p_table[i].settings_offset/4] =
1529 (unsigned int)val;
1530 break;
1531 default:
1532 DEBUGF( "illegal size!" );
1533 continue;
1536 return i; /* return the position */
1539 i++;
1540 if (i==count)
1541 i=1; /* wraparound */
1542 } while (i != hint); /* back where we started, all searched */
1544 return 0; /* indicate not found */
1548 bool settings_load_config(const char* file)
1550 int fd;
1551 char line[128];
1553 fd = open(file, O_RDONLY);
1554 if (fd < 0)
1555 return false;
1557 while (read_line(fd, line, sizeof line) > 0)
1559 char* name;
1560 char* value;
1561 const struct bit_entry* table[2] = { rtc_bits, hd_bits };
1562 const int ta_size[2] = {
1563 sizeof(rtc_bits)/sizeof(rtc_bits[0]),
1564 sizeof(hd_bits)/sizeof(hd_bits[0])
1566 int last_table = 0; /* which table was used last round */
1567 int last_pos = 1; /* at which position did we succeed */
1568 int pos; /* currently returned position */
1570 if (!settings_parseline(line, &name, &value))
1571 continue;
1573 /* check for the string values */
1574 if (!strcasecmp(name, "wps")) {
1575 #ifdef HAVE_LCD_COLOR
1576 unload_wps_backdrop();
1577 #endif
1578 int fd2;
1579 if ((fd2 = open(value, O_RDONLY)) >= 0) {
1580 close(fd2);
1581 set_file(value, (char *)global_settings.wps_file, MAX_FILENAME);
1584 #if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1)
1585 else if (!strcasecmp(name, "rwps")) {
1586 int fd2;
1587 if ((fd2 = open(value, O_RDONLY)) >= 0) {
1588 close(fd2);
1589 set_file(value, (char *)global_settings.rwps_file, MAX_FILENAME);
1592 #endif
1593 else if (!strcasecmp(name, "lang")) {
1594 if (!lang_load(value))
1596 set_file(value, (char *)global_settings.lang_file, MAX_FILENAME);
1597 talk_init(); /* use voice of same language */
1600 #ifdef CONFIG_TUNER
1601 else if (!strcasecmp(name, "fmr")) {
1602 set_file(value, global_settings.fmr_file, MAX_FILENAME);
1604 #endif
1605 #ifdef HAVE_LCD_BITMAP
1606 else if (!strcasecmp(name, "font")) {
1607 if (font_load(value))
1608 set_file(value, (char *)global_settings.font_file, MAX_FILENAME);
1610 #endif
1611 #ifdef HAVE_LCD_COLOR
1612 else if (!strcasecmp(name, "backdrop")) {
1613 if (load_main_backdrop(value)) {
1614 set_file(value, (char *)global_settings.backdrop_file, MAX_FILENAME);
1615 show_main_backdrop();
1618 #endif
1619 #ifdef HAVE_LCD_BITMAP
1620 else if (!strcasecmp(name, "keyboard")) {
1621 if (!load_kbd(value))
1622 set_file(value, (char *)global_settings.kbd_file, MAX_FILENAME);
1624 #endif
1627 /* check for scalar values, using the two tables */
1628 pos = load_cfg_table(table[last_table], ta_size[last_table],
1629 name, value, last_pos);
1630 if (pos) /* success */
1632 last_pos = pos; /* remember as a position hint for next round */
1633 continue;
1636 last_table = 1-last_table; /* try other table */
1637 last_pos = 1; /* search from start */
1638 pos = load_cfg_table(table[last_table], ta_size[last_table],
1639 name, value, last_pos);
1640 if (pos) /* success */
1642 last_pos = pos; /* remember as a position hint for next round */
1643 continue;
1647 close(fd);
1648 settings_apply();
1649 settings_save();
1650 return true;
1654 /* helper to save content of global_settings into a file,
1655 as described per table */
1656 static void save_cfg_table(const struct bit_entry* p_table, int count, int fd)
1658 long value; /* 32 bit content */
1659 int i;
1660 const struct bit_entry* p_run = p_table; /* start after the size info */
1661 count--; /* first is excluded from loop */
1663 for (i=0; i<count; i++)
1665 p_run++;
1667 if (p_run->cfg_name == NULL)
1668 continue; /* this value is not to be saved */
1670 /* could do a memcpy, but that would be endian-dependent */
1671 switch(p_run->byte_size)
1673 case 1:
1674 if (p_run->bit_size & SIGNED) /* signed? */
1675 value = ((char*)&global_settings)[p_run->settings_offset];
1676 else
1677 value = ((unsigned char*)&global_settings)[p_run->settings_offset];
1678 break;
1679 case 2:
1680 if (p_run->bit_size & SIGNED) /* signed? */
1681 value = ((short*)&global_settings)[p_run->settings_offset/2];
1682 else
1683 value = ((unsigned short*)&global_settings)[p_run->settings_offset/2];
1684 break;
1685 case 4:
1686 value = ((unsigned int*)&global_settings)[p_run->settings_offset/4];
1687 break;
1688 default:
1689 DEBUGF( "illegal size!" );
1690 continue;
1693 if (p_run->cfg_val == NULL) /* write as number */
1695 fdprintf(fd, "%s: %ld\r\n", p_run->cfg_name, value);
1697 #ifdef HAVE_LCD_COLOR
1698 else if (!strcasecmp(p_run->cfg_val, "rgb"))
1700 fdprintf(fd, "%s: %02x%02x%02x\r\n", p_run->cfg_name,
1701 (int)RGB_UNPACK_RED(value),
1702 (int)RGB_UNPACK_GREEN(value),
1703 (int)RGB_UNPACK_BLUE(value));
1705 #endif
1706 else /* write as item */
1708 const char* p = p_run->cfg_val;
1710 fdprintf(fd, "%s: ", p_run->cfg_name);
1712 while(value >= 0)
1714 char c = *p++; /* currently processed char */
1715 if (c == ',') /* separator */
1716 value--;
1717 else if (c == '\0') /* end of string */
1718 break; /* not found */
1719 else if (value == 0) /* the right place */
1720 write(fd, &c, 1); /* char by char, this is lame, OK */
1723 fdprintf(fd, "\r\n");
1724 if (p_run->cfg_val != off_on) /* explaination for non-bool */
1725 fdprintf(fd, "# (possible values: %s)\r\n", p_run->cfg_val);
1731 bool settings_save_config(void)
1733 int fd;
1734 char filename[MAX_PATH];
1736 create_numbered_filename(filename, ROCKBOX_DIR, "config", ".cfg", 2);
1738 /* allow user to modify filename */
1739 while (true) {
1740 if (!kbd_input(filename, sizeof filename)) {
1741 fd = creat(filename, O_WRONLY);
1742 if (fd < 0)
1743 gui_syncsplash(HZ, true, str(LANG_FAILED));
1744 else
1745 break;
1747 else {
1748 gui_syncsplash(HZ, true, str(LANG_MENU_SETTING_CANCEL));
1749 return false;
1753 fdprintf(fd, "# .cfg file created by rockbox %s - "
1754 "http://www.rockbox.org\r\n#\r\n#\r\n# wps / rwps / language"
1755 " / font / fmpreset / backdrop \r\n#\r\n", appsversion);
1757 if (global_settings.wps_file[0] != 0)
1758 fdprintf(fd, "wps: %s/%s.wps\r\n", WPS_DIR,
1759 global_settings.wps_file);
1761 #ifdef HAVE_REMOTE_LCD
1762 if (global_settings.rwps_file[0] != 0)
1763 fdprintf(fd, "rwps: %s/%s.rwps\r\n", WPS_DIR,
1764 global_settings.rwps_file);
1765 #endif
1767 if (global_settings.lang_file[0] != 0)
1768 fdprintf(fd, "lang: %s/%s.lng\r\n", LANG_DIR,
1769 global_settings.lang_file);
1771 #ifdef HAVE_LCD_BITMAP
1772 if (global_settings.font_file[0] != 0)
1773 fdprintf(fd, "font: %s/%s.fnt\r\n", FONT_DIR,
1774 global_settings.font_file);
1775 #endif
1777 #ifdef HAVE_LCD_COLOR
1778 if (global_settings.backdrop_file[0] != 0)
1779 fdprintf(fd, "backdrop: %s/%s.bmp\r\n", BACKDROP_DIR,
1780 global_settings.backdrop_file);
1781 #endif
1783 #ifdef CONFIG_TUNER
1784 if (global_settings.fmr_file[0] != 0)
1785 fdprintf(fd, "fmr: %s/%s.fmr\r\n", FMPRESET_PATH,
1786 global_settings.fmr_file);
1787 #endif
1789 #ifdef HAVE_LCD_BITMAP
1790 if (global_settings.kbd_file[0] != 0)
1791 fdprintf(fd, "keyboard: %s/%s.kbd\r\n", ROCKBOX_DIR,
1792 global_settings.kbd_file);
1793 #endif
1795 /* here's the action: write values to file, specified via table */
1796 save_cfg_table(rtc_bits, sizeof(rtc_bits)/sizeof(rtc_bits[0]), fd);
1797 save_cfg_table(hd_bits, sizeof(hd_bits)/sizeof(hd_bits[0]), fd);
1799 close(fd);
1801 gui_syncsplash(HZ, true, str(LANG_SETTINGS_SAVED));
1802 return true;
1806 /* helper to load defaults from table into global_settings members */
1807 static void default_table(const struct bit_entry* p_table, int count)
1809 int i;
1811 for (i=1; i<count; i++) /* exclude the first, the size placeholder */
1813 /* could do a memcpy, but that would be endian-dependent */
1814 switch(p_table[i].byte_size)
1816 case 1:
1817 ((unsigned char*)&global_settings)[p_table[i].settings_offset] =
1818 (unsigned char)p_table[i].default_val;
1819 break;
1820 case 2:
1821 ((unsigned short*)&global_settings)[p_table[i].settings_offset/2] =
1822 (unsigned short)p_table[i].default_val;
1823 break;
1824 case 4:
1825 ((unsigned int*)&global_settings)[p_table[i].settings_offset/4] =
1826 (unsigned int)p_table[i].default_val;
1827 break;
1828 default:
1829 DEBUGF( "illegal size!" );
1830 continue;
1837 * reset all settings to their default value
1839 void settings_reset(void) {
1841 DEBUGF( "settings_reset()\n" );
1843 /* read defaults from table(s) into global_settings */
1844 default_table(rtc_bits, sizeof(rtc_bits)/sizeof(rtc_bits[0]));
1845 default_table(hd_bits, sizeof(hd_bits)/sizeof(hd_bits[0]));
1847 /* do some special cases not covered by table */
1848 global_settings.volume = sound_default(SOUND_VOLUME);
1849 global_settings.balance = sound_default(SOUND_BALANCE);
1850 global_settings.bass = sound_default(SOUND_BASS);
1851 global_settings.treble = sound_default(SOUND_TREBLE);
1852 global_settings.channel_config = sound_default(SOUND_CHANNELS);
1853 global_settings.stereo_width = sound_default(SOUND_STEREO_WIDTH);
1854 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
1855 global_settings.loudness = sound_default(SOUND_LOUDNESS);
1856 global_settings.avc = sound_default(SOUND_AVC);
1857 global_settings.mdb_strength = sound_default(SOUND_MDB_STRENGTH);
1858 global_settings.mdb_harmonics = sound_default(SOUND_MDB_HARMONICS);
1859 global_settings.mdb_center = sound_default(SOUND_MDB_CENTER);
1860 global_settings.mdb_shape = sound_default(SOUND_MDB_SHAPE);
1861 global_settings.mdb_enable = sound_default(SOUND_MDB_ENABLE);
1862 global_settings.superbass = sound_default(SOUND_SUPERBASS);
1863 #endif
1864 #ifdef HAVE_LCD_CONTRAST
1865 global_settings.contrast = lcd_default_contrast();
1866 #endif
1867 #ifdef HAVE_LCD_REMOTE
1868 global_settings.remote_contrast = lcd_remote_default_contrast();
1869 #endif
1871 #ifdef CONFIG_TUNER
1872 global_settings.fmr_file[0] = '\0';
1873 #endif
1874 global_settings.wps_file[0] = '\0';
1875 #ifdef HAVE_REMOTE_LCD
1876 global_settings.rwps_file[0] = '\0';
1877 #endif
1878 global_settings.font_file[0] = '\0';
1879 global_settings.lang_file[0] = '\0';
1880 #ifdef HAVE_LCD_COLOR
1881 global_settings.backdrop_file[0] = '\0';
1883 global_settings.fg_color = LCD_DEFAULT_FG;
1884 global_settings.bg_color = LCD_DEFAULT_BG;
1885 #endif
1886 #ifdef HAVE_LCD_BITMAP
1887 global_settings.kbd_file[0] = '\0';
1888 #endif
1889 global_settings.hold_lr_for_scroll_in_list = true;
1892 bool set_bool(const char* string, bool* variable )
1894 return set_bool_options(string, variable,
1895 (char *)STR(LANG_SET_BOOL_YES),
1896 (char *)STR(LANG_SET_BOOL_NO),
1897 NULL);
1900 /* wrapper to convert from int param to bool param in set_option */
1901 static void (*boolfunction)(bool);
1902 void bool_funcwrapper(int value)
1904 if (value)
1905 boolfunction(true);
1906 else
1907 boolfunction(false);
1910 bool set_bool_options(const char* string, bool* variable,
1911 const char* yes_str, int yes_voice,
1912 const char* no_str, int no_voice,
1913 void (*function)(bool))
1915 struct opt_items names[] = {
1916 {(unsigned char *)no_str, no_voice},
1917 {(unsigned char *)yes_str, yes_voice}
1919 bool result;
1921 boolfunction = function;
1922 result = set_option(string, variable, BOOL, names, 2,
1923 function ? bool_funcwrapper : NULL);
1924 return result;
1927 void talk_unit(int unit, int value)
1929 if (global_settings.talk_menu)
1931 if (unit < UNIT_LAST)
1932 { /* use the available unit definition */
1933 talk_value(value, unit, false);
1935 else
1936 { /* say the number, followed by an arbitrary voice ID */
1937 talk_number(value, false);
1938 talk_id(unit, true);
1943 struct value_setting_data {
1944 enum optiontype type;
1945 /* used for "value" settings.. */
1946 int max;
1947 int step;
1948 int voice_unit;
1949 const char * unit;
1950 void (*formatter)(char* dest, int dest_length,
1951 int variable, const char* unit);
1952 /* used for BOOL and "choice" settings */
1953 struct opt_items* options;
1956 char * value_setting_get_name_cb(int selected_item,void * data, char *buffer)
1958 struct value_setting_data* cb_data =
1959 (struct value_setting_data*)data;
1960 if (cb_data->type == INT && !cb_data->options)
1962 int item = cb_data->max -(selected_item*cb_data->step);
1963 if (cb_data->formatter)
1964 cb_data->formatter(buffer, MAX_PATH,item,cb_data->unit);
1965 else
1966 snprintf(buffer, MAX_PATH,"%d %s",item,cb_data->unit);
1968 else strcpy(buffer,P2STR(cb_data->options[selected_item].string));
1969 return buffer;
1971 #define type_fromvoidptr(type, value) \
1972 (type == INT)? \
1973 (int)(*(int*)(value)) \
1975 (bool)(*(bool*)(value))
1976 bool do_set_setting(const unsigned char* string, void *variable,
1977 int nb_items,int selected,
1978 struct value_setting_data *cb_data,
1979 void (*function)(int))
1981 int action;
1982 bool done = false;
1983 struct gui_synclist lists;
1984 int oldvalue;
1986 if (cb_data->type == INT)
1987 oldvalue = *(int*)variable;
1988 else oldvalue = *(bool*)variable;
1990 gui_synclist_init(&lists,value_setting_get_name_cb,(void*)cb_data,false,1);
1991 gui_synclist_set_title(&lists, (char*)string, NOICON);
1992 gui_synclist_set_icon_callback(&lists,NULL);
1993 gui_synclist_set_nb_items(&lists,nb_items);
1994 gui_synclist_limit_scroll(&lists,true);
1995 gui_synclist_select_item(&lists, selected);
1997 if (global_settings.talk_menu)
1999 if (cb_data->type == INT && !cb_data->options)
2000 talk_unit(cb_data->voice_unit, *(int*)variable);
2001 else talk_id(cb_data->options[selected].voice_id, false);
2004 gui_synclist_draw(&lists);
2005 while (!done)
2008 action = get_action(CONTEXT_LIST,TIMEOUT_BLOCK);
2009 if (action == ACTION_NONE)
2010 continue;
2012 if (gui_synclist_do_button(&lists,action))
2014 if (global_settings.talk_menu)
2016 int value;
2017 if (cb_data->type == INT && !cb_data->options)
2019 value = cb_data->max -
2020 gui_synclist_get_sel_pos(&lists)*cb_data->step;
2021 talk_unit(cb_data->voice_unit, value);
2023 else
2025 value = gui_synclist_get_sel_pos(&lists);
2026 talk_id(cb_data->options[value].voice_id, false);
2029 if (cb_data->type == INT && !cb_data->options)
2030 *(int*)variable = cb_data->max -
2031 gui_synclist_get_sel_pos(&lists)*cb_data->step;
2032 else if (cb_data->type == BOOL)
2033 *(bool*)variable = gui_synclist_get_sel_pos(&lists) ? true : false;
2034 else *(int*)variable = gui_synclist_get_sel_pos(&lists);
2036 else if (action == ACTION_STD_CANCEL)
2038 gui_syncsplash(HZ/2,true,str(LANG_MENU_SETTING_CANCEL));
2039 if (cb_data->type == INT)
2040 *(int*)variable = oldvalue;
2041 else *(bool*)variable = (bool)oldvalue;
2042 done = true;
2044 else if (action == ACTION_STD_OK)
2046 done = true;
2048 else if(default_event_handler(action) == SYS_USB_CONNECTED)
2049 return true;
2050 gui_syncstatusbar_draw(&statusbars, false);
2051 if ( function )
2052 function(type_fromvoidptr(cb_data->type,variable));
2054 return false;
2056 bool set_int(const unsigned char* string,
2057 const char* unit,
2058 int voice_unit,
2059 int* variable,
2060 void (*function)(int),
2061 int step,
2062 int min,
2063 int max,
2064 void (*formatter)(char*, int, int, const char*) )
2066 #if CONFIG_KEYPAD != PLAYER_PAD
2067 struct value_setting_data data = {
2068 INT,max, step, voice_unit,unit,formatter,NULL };
2069 return do_set_setting(string,variable,(max-min)/step + 1,
2070 (max-*variable)/step, &data,function);
2071 #else
2072 int count = (max-min)/step + 1;
2073 struct value_setting_data data = {
2074 INT,min, -step, voice_unit,unit,formatter,NULL };
2075 return do_set_setting(string,variable,count,
2076 count - ((max-*variable)/step), &data,function);
2077 #endif
2080 /* NOTE: the 'type' parameter specifies the actual type of the variable
2081 that 'variable' points to. not the value within. Only variables with
2082 type 'bool' should use parameter BOOL.
2084 The type separation is necessary since int and bool are fundamentally
2085 different and bit-incompatible types and can not share the same access
2086 code. */
2087 bool set_option(const char* string, void* variable, enum optiontype type,
2088 const struct opt_items* options, int numoptions, void (*function)(int))
2090 struct value_setting_data data = {
2091 type,0, 0, 0,NULL,NULL,(struct opt_items*)options };
2092 int selected;
2093 if (type == BOOL)
2094 selected = *(bool*)variable ? 1 : 0;
2095 else selected = *(int*)variable;
2096 return do_set_setting(string,variable,numoptions,
2097 selected, &data,function);
2100 #ifdef HAVE_RECORDING
2101 /* This array holds the record timer interval lengths, in seconds */
2102 static const unsigned long rec_timer_seconds[] =
2104 0, /* 0 means OFF */
2105 5*60, /* 00:05 */
2106 10*60, /* 00:10 */
2107 15*60, /* 00:15 */
2108 30*60, /* 00:30 */
2109 60*60, /* 01:00 */
2110 74*60, /* 74:00 */
2111 80*60, /* 80:00 */
2112 2*60*60, /* 02:00 */
2113 4*60*60, /* 04:00 */
2114 6*60*60, /* 06:00 */
2115 8*60*60, /* 08:00 */
2116 10L*60*60, /* 10:00 */
2117 12L*60*60, /* 12:00 */
2118 18L*60*60, /* 18:00 */
2119 24L*60*60 /* 24:00 */
2122 unsigned int rec_timesplit_seconds(void)
2124 return rec_timer_seconds[global_settings.rec_timesplit];
2127 /* This array holds the record size interval lengths, in bytes */
2128 static const unsigned long rec_size_bytes[] =
2130 0, /* 0 means OFF */
2131 5*1024*1024, /* 5MB */
2132 10*1024*1024, /* 10MB */
2133 15*1024*1024, /* 15MB */
2134 32*1024*1024, /* 32MB */
2135 64*1024*1024, /* 64MB */
2136 75*1024*1024, /* 75MB */
2137 100*1024*1024, /* 100MB */
2138 128*1024*1024, /* 128MB */
2139 256*1024*1024, /* 256MB */
2140 512*1024*1024, /* 512MB */
2141 650*1024*1024, /* 650MB */
2142 700*1024*1024, /* 700MB */
2143 1024*1024*1024, /* 1GB */
2144 1536*1024*1024, /* 1.5GB */
2145 1792*1024*1024, /* 1.75GB */
2148 unsigned long rec_sizesplit_bytes(void)
2150 return rec_size_bytes[global_settings.rec_sizesplit];
2153 * Time strings used for the trigger durations.
2154 * Keep synchronous to trigger_times in settings_apply_trigger
2156 const char * const trig_durations[TRIG_DURATION_COUNT] =
2158 "0s", "1s", "2s", "5s",
2159 "10s", "15s", "20s", "25s", "30s",
2160 "1min", "2min", "5min", "10min"
2163 void settings_apply_trigger(void)
2165 /* Keep synchronous to trig_durations and trig_durations_conf*/
2166 static const long trigger_times[TRIG_DURATION_COUNT] = {
2167 0, HZ, 2*HZ, 5*HZ,
2168 10*HZ, 15*HZ, 20*HZ, 25*HZ, 30*HZ,
2169 60*HZ, 2*60*HZ, 5*60*HZ, 10*60*HZ
2172 peak_meter_define_trigger(
2173 global_settings.rec_start_thres,
2174 trigger_times[global_settings.rec_start_duration],
2175 MIN(trigger_times[global_settings.rec_start_duration] / 2, 2*HZ),
2176 global_settings.rec_stop_thres,
2177 trigger_times[global_settings.rec_stop_postrec],
2178 trigger_times[global_settings.rec_stop_gap]
2181 #endif