1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 by wavey@wavey.org
11 * RTC config saving code (C) 2002 by hessu@hes.iki.fi
13 * All files in this archive are subject to the GNU General Public License.
14 * See the file COPYING in the source tree root for full license agreement.
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
19 ****************************************************************************/
33 #include "backlight.h"
36 #include "mp3_playback.h"
41 #include "ata_idle_notify.h"
44 #include "powermgmt.h"
53 #include "timefuncs.h"
54 #ifdef HAVE_LCD_BITMAP
57 #include "peakmeter.h"
63 #include "powermgmt.h"
70 #include "rbunicode.h"
72 #include "statusbar.h"
83 #if CONFIG_CODEC == MAS3507D
84 void dac_line_in(bool enable
);
86 struct user_settings global_settings
;
88 const char rec_base_directory
[] = REC_BASE_DIR
;
90 #if CONFIG_CODEC == SWCODEC
92 #include "pcm_playback.h"
95 #include "enc_config.h"
97 #endif /* CONFIG_CODEC == SWCODEC */
103 #define CONFIG_BLOCK_VERSION 56
104 #define CONFIG_BLOCK_SIZE 512
105 #define RTC_BLOCK_SIZE 44
107 #ifdef HAVE_LCD_BITMAP
113 #ifdef HAVE_REMOTE_LCD
114 #include "lcd-remote.h"
118 static long config_sector
= 0; /* mark uninitialized */
119 static unsigned char config_block
[CONFIG_BLOCK_SIZE
];
122 /* descriptor for a configuration value */
123 /* (watch the struct packing and member sizes to keep this small) */
126 /* how many bits within the bitfield (1-32), MSB set if value is signed */
127 unsigned char bit_size
; /* min 6+1 bit */
128 /* how many bytes in the global_settings struct (1,2,4) */
129 unsigned char byte_size
; /* min 3 bits */
130 /* store position in global_settings struct */
131 short settings_offset
; /* min 9 bit, better 10 */
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 */
140 /********************************************
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.
146 0x00 0x14 "Roc" header signature: 0x52 0x6f 0x63
147 0x03 0x17 <version byte: 0x0>
148 0x04 0x18 start of bit-table
150 0x28,0x29 unused, not reachable by set_bits() without disturbing the next 2
151 0x2A,0x2B <checksum 2 bytes: xor of 0x00-0x29>
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.
160 Rest of config block, only saved to disk:
161 0x2C start of 2nd bit-table
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)
170 ... to 0x200 <unused>
172 *************************************/
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.
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 */
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";
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";
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";
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
[] =
210 /* placeholder, containing the size information */
211 {9, 0, 0, 0, NULL
, NULL
}, /* 9 bit to tell how far this is populated */
213 /* # of bits, offset+size, default, .cfg name, .cfg values */
215 #if CONFIG_CODEC == MAS3507D
216 {8 | SIGNED
, S_O(volume
), -18, "volume", NULL
}, /* -78...+18 */
218 {8 | SIGNED
, S_O(volume
), -25, "volume", NULL
}, /* -100...+12 / -84...0 */
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 {5 | SIGNED
, S_O(bass
), 0, "bass", NULL
}, /* -6..+9 */
230 {5 | SIGNED
, S_O(treble
), 0, "treble", NULL
}, /* -6..+9 */
232 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
233 {5, S_O(loudness
), 0, "loudness", NULL
}, /* 0...17 */
234 {3, S_O(avc
), 0, "auto volume", "off,20ms,2,4,8" },
235 {1, S_O(superbass
), false, "superbass", off_on
},
237 {3, S_O(channel_config
), 0, "channels",
238 "stereo,mono,custom,mono left,mono right,karaoke" },
239 {8, S_O(stereo_width
), 100, "stereo width", NULL
},
241 {1, S_O(resume
), false, "resume", off_on
},
242 {1, S_O(playlist_shuffle
), false, "shuffle", off_on
},
243 {16 | SIGNED
, S_O(resume_index
), -1, NULL
, NULL
},
244 {16 | SIGNED
, S_O(resume_first_index
), 0, NULL
, NULL
},
245 {32 | SIGNED
, S_O(resume_offset
), -1, NULL
, NULL
},
246 {32 | SIGNED
, S_O(resume_seed
), -1, NULL
, NULL
},
247 {3, S_O(repeat_mode
), REPEAT_ALL
, "repeat", "off,all,one,shuffle,ab" },
249 #ifdef HAVE_LCD_CONTRAST
250 {6, S_O(contrast
), DEFAULT_CONTRAST_SETTING
, "contrast", NULL
},
252 #ifdef CONFIG_BACKLIGHT
253 {5, S_O(backlight_timeout
), 6, "backlight timeout", backlight_times_conf
},
254 #ifdef CONFIG_CHARGING
255 {5, S_O(backlight_timeout_plugged
), 11, "backlight timeout plugged",
256 backlight_times_conf
},
258 #endif /* CONFIG_BACKLIGHT */
259 #ifdef HAVE_LCD_BITMAP
260 {1, S_O(invert
), false, "invert", off_on
},
261 {1, S_O(flip_display
), false, "flip display", off_on
},
263 {1, S_O(invert_cursor
), true, "invert cursor", off_on
},
264 {1, S_O(statusbar
), true, "statusbar", off_on
},
265 {1, S_O(scrollbar
), true, "scrollbar", off_on
},
266 #if CONFIG_KEYPAD == RECORDER_PAD
267 {1, S_O(buttonbar
), true, "buttonbar", off_on
},
269 {1, S_O(volume_type
), 0, "volume display", graphic_numeric
},
270 {1, S_O(battery_display
), 0, "battery display", graphic_numeric
},
271 {1, S_O(timeformat
), 0, "time format", "24hour,12hour" },
272 #endif /* HAVE_LCD_BITMAP */
273 {1, S_O(show_icons
), true, "show icons", off_on
},
275 {4, S_O(poweroff
), 10,
276 "idle poweroff", "off,1,2,3,4,5,6,7,8,9,10,15,30,45,60" },
277 {18, S_O(runtime
), 0, NULL
, NULL
},
278 {18, S_O(topruntime
), 0, NULL
, NULL
},
280 {15, S_O(max_files_in_playlist
), 10000,
281 "max files in playlist", NULL
}, /* 1000...20000 */
282 {14, S_O(max_files_in_dir
), 400,
283 "max files in dir", NULL
}, /* 50...10000 */
285 {15, S_O(max_files_in_playlist
), 1000,
286 "max files in playlist", NULL
}, /* 1000...20000 */
287 {14, S_O(max_files_in_dir
), 200,
288 "max files in dir", NULL
}, /* 50...10000 */
291 {12, S_O(battery_capacity
), BATTERY_CAPACITY_DEFAULT
, "battery capacity",
292 NULL
}, /* 1500...3200 for NiMH, 2200...3200 for LiIon,
293 500...1500 for Alkaline */
294 #ifdef CONFIG_CHARGING
295 {1, S_O(car_adapter_mode
), false, "car adapter mode", off_on
},
299 {1, S_O(fm_force_mono
), false, "force fm mono", off_on
},
300 {9, S_O(last_frequency
), 0, NULL
, NULL
}, /* Default: MIN_FREQ */
303 #if BATTERY_TYPES_COUNT > 1
304 {1, S_O(battery_type
), 0, "battery type", "alkaline,nimh" },
307 #ifdef HAVE_REMOTE_LCD
309 {6, S_O(remote_contrast
), DEFAULT_REMOTE_CONTRAST_SETTING
,
310 "remote contrast", NULL
},
311 {1, S_O(remote_invert
), false, "remote invert", off_on
},
312 {1, S_O(remote_flip_display
), false, "remote flip display", off_on
},
313 {5, S_O(remote_backlight_timeout
), 6, "remote backlight timeout",
314 backlight_times_conf
},
315 #ifdef CONFIG_CHARGING
316 {5, S_O(remote_backlight_timeout_plugged
), 11,
317 "remote backlight timeout plugged", backlight_times_conf
},
319 #ifdef HAVE_REMOTE_LCD_TICKING
320 {1, S_O(remote_reduce_ticking
), false, "remote reduce ticking", off_on
},
324 #ifdef CONFIG_BACKLIGHT
325 {1, S_O(bl_filter_first_keypress
), false,
326 "backlight filters first keypress", off_on
},
327 #ifdef HAVE_REMOTE_LCD
328 {1, S_O(remote_bl_filter_first_keypress
), false,
329 "backlight filters first remote keypress", off_on
},
331 #endif /* CONFIG_BACKLIGHT */
333 /* new stuff to be added here */
334 /* If values are just added to the end, no need to bump the version. */
336 /* Current sum of bits: 277 (worst case, but w/o remote lcd) */
337 /* Sum of all bit sizes must not grow beyond 288! */
341 /* the part of the settings which ends up in HD sector only */
342 static const struct bit_entry hd_bits
[] =
344 /* This table starts after the 44 RTC bytes = 352 bits. */
345 /* Here we need 11 bits to tell how far this is populated. */
347 /* placeholder, containing the size information */
348 {11, 0, 0, 0, NULL
, NULL
}, /* 11 bit to tell how far this is populated */
350 /* # of bits, offset+size, default, .cfg name, .cfg values */
352 #ifdef CONFIG_BACKLIGHT
353 {1, S_O(caption_backlight
), false, "caption backlight", off_on
},
355 #ifdef HAVE_REMOTE_LCD
356 {1, S_O(remote_caption_backlight
), false,
357 "remote caption backlight", off_on
},
359 #ifdef HAVE_BACKLIGHT_BRIGHTNESS
360 {4, S_O(brightness
), DEFAULT_BRIGHTNESS_SETTING
, "brightness", NULL
},
362 #ifdef HAVE_BACKLIGHT_PWM_FADING
363 /* backlight fading */
364 {2, S_O(backlight_fade_in
), 1, "backlight fade in", "off,500ms,1s,2s"},
365 {3, S_O(backlight_fade_out
), 3, "backlight fade out",
366 "off,500ms,1s,2s,3s,4s,5s,10s"},
369 {4, S_O(scroll_speed
), 9, "scroll speed", NULL
}, /* 0...15 */
370 {8, S_O(scroll_delay
), 100, "scroll delay", NULL
}, /* 0...250 */
371 {8, S_O(bidir_limit
), 50, "bidir limit", NULL
}, /* 0...200 */
373 #ifdef HAVE_REMOTE_LCD
374 {4, S_O(remote_scroll_speed
), 9, "remote scroll speed", NULL
}, /* 0...15 */
375 {8, S_O(remote_scroll_step
), 6, "remote scroll step", NULL
}, /* 1...160 */
376 {8, S_O(remote_scroll_delay
), 100, "remote scroll delay", NULL
}, /* 0...250 */
377 {8, S_O(remote_bidir_limit
), 50, "remote bidir limit", NULL
}, /* 0...200 */
380 #ifdef HAVE_LCD_BITMAP
381 {1, S_O(offset_out_of_view
), false, "Screen Scrolls Out Of View", off_on
},
383 {9, S_O(scroll_step
), 6, "scroll step", NULL
},
384 {9, S_O(screen_scroll_step
), 16, "screen scroll step", NULL
},
385 #elif LCD_WIDTH > 127
386 {8, S_O(scroll_step
), 6, "scroll step", NULL
},
387 {8, S_O(screen_scroll_step
), 16, "screen scroll step", NULL
},
389 {7, S_O(scroll_step
), 6, "scroll step", NULL
},
390 {7, S_O(screen_scroll_step
), 16, "screen scroll step", NULL
},
392 #endif /* HAVE_LCD_BITMAP */
393 #ifdef HAVE_LCD_CHARCELLS
394 {3, S_O(jump_scroll
), 0, "jump scroll", NULL
}, /* 0...5 */
395 {8, S_O(jump_scroll_delay
), 50, "jump scroll delay", NULL
}, /* 0...250 */
397 {1, S_O(scroll_paginated
), false, "scroll paginated", off_on
},
399 #ifdef HAVE_LCD_COLOR
400 {LCD_DEPTH
,S_O(fg_color
),LCD_DEFAULT_FG
,"foreground color","rgb"},
401 {LCD_DEPTH
,S_O(bg_color
),LCD_DEFAULT_BG
,"background color","rgb"},
405 {1, S_O(play_selected
), true, "play selected", off_on
},
406 {1, S_O(fade_on_stop
), true, "volume fade", off_on
},
407 {4, S_O(ff_rewind_min_step
), FF_REWIND_1000
,
408 "scan min step", "1,2,3,4,5,6,8,10,15,20,25,30,45,60" },
409 {4, S_O(ff_rewind_accel
), 3, "scan accel", NULL
},
410 #if CONFIG_CODEC == SWCODEC
411 {3, S_O(buffer_margin
), 0, "antiskip",
412 "5s,15s,30s,1min,2min,3min,5min,10min" },
414 {3, S_O(buffer_margin
), 0, "antiskip", NULL
},
418 #ifdef HAVE_ATA_POWER_OFF
419 {1, S_O(disk_poweroff
), false, "disk poweroff", off_on
},
421 {8, S_O(disk_spindown
), 5, "disk spindown", NULL
},
422 #endif /* HAVE_MMC */
425 {3, S_O(dirfilter
), SHOW_SUPPORTED
,
426 "show files", "all,supported,music,playlists"
431 {1, S_O(sort_case
), false, "sort case", off_on
},
432 {1, S_O(browse_current
), false, "follow playlist", off_on
},
434 {1, S_O(playlist_viewer_icons
), true, "playlist viewer icons", off_on
},
435 {1, S_O(playlist_viewer_indices
), true,
436 "playlist viewer indices", off_on
},
437 {1, S_O(playlist_viewer_track_display
), 0,
438 "playlist viewer track display", "track name,full path" },
439 {2, S_O(recursive_dir_insert
), RECURSE_OFF
,
440 "recursive directory insert", off_on_ask
},
442 {3, S_O(autocreatebookmark
), BOOKMARK_NO
, "autocreate bookmarks",
443 "off,on,ask,recent only - on,recent only - ask" },
444 {2, S_O(autoloadbookmark
), BOOKMARK_NO
,
445 "autoload bookmarks", off_on_ask
},
446 {2, S_O(usemrb
), BOOKMARK_NO
,
447 "use most-recent-bookmarks", "off,on,unique only" },
448 #ifdef HAVE_LCD_BITMAP
450 {5, S_O(peak_meter_clip_hold
), 16, "peak meter clip hold", /* 0...25 */
451 "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" },
452 {5, S_O(peak_meter_hold
), 3, "peak meter hold",
453 "off,200ms,300ms,500ms,1,2,3,4,5,6,7,8,9,10,15,20,30,1min" },
454 {7, S_O(peak_meter_release
), 8, "peak meter release", NULL
}, /* 0...126 */
455 {1, S_O(peak_meter_dbfs
), true, "peak meter dbfs", off_on
},
456 {7, S_O(peak_meter_min
), 60, "peak meter min", NULL
}, /* 0...100 */
457 {7, S_O(peak_meter_max
), 0, "peak meter max", NULL
}, /* 0...100 */
459 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
460 {7, S_O(mdb_strength
), 0, "mdb strength", NULL
},
461 {7, S_O(mdb_harmonics
), 0, "mdb harmonics", NULL
},
462 {9, S_O(mdb_center
), 0, "mdb center", NULL
},
463 {9, S_O(mdb_shape
), 0, "mdb shape", NULL
},
464 {1, S_O(mdb_enable
), 0, "mdb enable", off_on
},
466 #if CONFIG_CODEC == MAS3507D
467 {1, S_O(line_in
), false, "line in", off_on
},
470 {2, S_O(talk_dir
), 0, "talk dir", off_number_spell_hover
},
471 {2, S_O(talk_file
), 0, "talk file", off_number_spell_hover
},
472 {1, S_O(talk_menu
), true, "talk menu", off_on
},
474 {2, S_O(sort_file
), 0, "sort files", "alpha,oldest,newest,type" },
475 {2, S_O(sort_dir
), 0, "sort dirs", "alpha,oldest,newest" },
476 {1, S_O(id3_v1_first
), 0, "id3 tag priority", "v2-v1,v1-v2"},
478 #ifdef HAVE_RECORDING
480 {1, S_O(recscreen_on
), false, "recscreen on", off_on
},
481 {1, S_O(rec_startup
), false, "rec screen on startup", off_on
},
482 {4, S_O(rec_timesplit
), 0, "rec timesplit", /* 0...15 */
483 "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" },
484 {4, S_O(rec_sizesplit
), 0, "rec sizesplit", /* 0...15 */
485 "off,5MB,10MB,15MB,32MB,64MB,75MB,100MB,128MB,256MB,512MB,650MB,700MB,1GB,1.5GB,1.75GB" },
486 {1, S_O(rec_channels
), 0, "rec channels", "stereo,mono" },
487 {1, S_O(rec_split_type
), 0, "rec split type", "Split, Stop" },
488 {1, S_O(rec_split_method
), 0, "rec split method", "Time,Filesize" },
491 #if defined(HAVE_SPDIF_IN) || defined(HAVE_FMRADIO_IN)
496 S_O(rec_source
), 0 /* 0=mic */, "rec source",
501 #ifdef HAVE_FMRADIO_IN
505 {5, S_O(rec_prerecord_time
), 0, "prerecording time", NULL
}, /* 0...30 */
506 {1, S_O(rec_directory
), 0, /* rec_base_directory */
507 "rec directory", REC_BASE_DIR
",current" },
508 #ifdef CONFIG_BACKLIGHT
509 {2, S_O(cliplight
), 0, "cliplight", "off,main,both,remote" },
511 #if CONFIG_CODEC == MAS3587F
512 {4, S_O(rec_mic_gain
), 8, "rec mic gain", NULL
},
513 {4, S_O(rec_left_gain
), 2 /* 0dB */, "rec left gain", NULL
}, /* 0...15 */
514 {4, S_O(rec_right_gain
), 2 /* 0dB */, "rec right gain", NULL
}, /* 0...15 */
515 {3, S_O(rec_frequency
), 0, /* 0=44.1kHz */
516 "rec frequency", "44,48,32,22,24,16" },
517 {3, S_O(rec_quality
), 5 /* 192 kBit/s max */, "rec quality", NULL
},
518 {1, S_O(rec_editable
), false, "editable recordings", off_on
},
519 #endif /* CONFIG_CODEC == MAS3587F */
521 #if CONFIG_CODEC == SWCODEC
523 {8|SIGNED
, S_O(rec_mic_gain
), 16 /* 8 dB */, "rec mic gain", NULL
}, /* -128...+108 */
526 /* TLV320 only has no mic boost or 20db mic boost */
527 {1, S_O(rec_mic_gain
), 0 /* 0 dB */, "rec mic gain", NULL
}, /* 0db or 20db */
529 {8|SIGNED
, S_O(rec_left_gain
), 0, "rec left gain", NULL
}, /* -128...+96 */
530 {8|SIGNED
, S_O(rec_right_gain
), 0, "rec right gain", NULL
}, /* -128...+96 */
531 {REC_FREQ_CFG_NUM_BITS
, S_O(rec_frequency
), REC_FREQ_DEFAULT
,
532 "rec frequency", REC_FREQ_CFG_VAL_LIST
},
533 {REC_FORMAT_CFG_NUM_BITS
,S_O(rec_format
), REC_FORMAT_DEFAULT
,
534 "rec format", REC_FORMAT_CFG_VAL_LIST
},
535 /** Encoder settings start - keep these together **/
537 {5,S_O(mp3_enc_config
.bitrate
), MP3_ENC_BITRATE_CFG_DEFAULT
,
538 "mp3_enc bitrate", MP3_ENC_BITRATE_CFG_VALUE_LIST
},
540 /* (no settings yet) */
542 /* (no settings yet) */
543 /** Encoder settings end **/
544 #endif /* CONFIG_CODEC == SWCODEC */
546 /* values for the trigger */
547 {8 | SIGNED
, S_O(rec_start_thres
), -35, "trigger start threshold", NULL
},
548 {8 | SIGNED
, S_O(rec_stop_thres
), -45, "trigger stop threshold", NULL
},
549 {4, S_O(rec_start_duration
), 0, "trigger start duration", trig_durations_conf
},
550 {4, S_O(rec_stop_postrec
), 2, "trigger stop postrec", trig_durations_conf
},
551 {4, S_O(rec_stop_gap
), 1, "trigger min gap", trig_durations_conf
},
552 {4, S_O(rec_trigger_mode
), 0, "trigger mode", "off,once,repeat"},
553 #endif /* HAVE_RECORDING */
555 #ifdef HAVE_SPDIF_POWER
556 {1, S_O(spdif_enable
), false, "spdif enable", off_on
},
559 {2, S_O(next_folder
), false, "folder navigation", "off,on,random" },
560 {1, S_O(runtimedb
), false, "gather runtime data", off_on
},
562 #if CONFIG_CODEC == SWCODEC
563 {1, S_O(replaygain
), false, "replaygain", off_on
},
564 {2, S_O(replaygain_type
), REPLAYGAIN_ALBUM
, "replaygain type",
565 "track,album,track shuffle" },
566 {1, S_O(replaygain_noclip
), false, "replaygain noclip", off_on
},
567 {8 | SIGNED
, S_O(replaygain_preamp
), 0, "replaygain preamp", NULL
},
568 {2, S_O(beep
), 0, "beep", "off,weak,moderate,strong" },
569 {2, S_O(crossfade
), 0, "crossfade", "off,shuffle,track skip,always"},
570 {3, S_O(crossfade_fade_in_delay
), 0, "crossfade fade in delay", NULL
},
571 {3, S_O(crossfade_fade_out_delay
), 0, "crossfade fade out delay", NULL
},
572 {4, S_O(crossfade_fade_in_duration
), 0, "crossfade fade in duration", NULL
},
573 {4, S_O(crossfade_fade_out_duration
), 0, "crossfade fade out duration", NULL
},
574 {1, S_O(crossfade_fade_out_mixmode
), 0, "crossfade fade out mode", "crossfade,mix"},
575 {1, S_O(crossfeed
), false, "crossfeed", off_on
},
576 {6, S_O(crossfeed_direct_gain
), 15, "crossfeed direct gain", NULL
},
577 {7, S_O(crossfeed_cross_gain
), 60, "crossfeed cross gain", NULL
},
578 {8, S_O(crossfeed_hf_attenuation
), 160, "crossfeed hf attenuation", NULL
},
579 {11, S_O(crossfeed_hf_cutoff
), 700, "crossfeed hf cutoff", NULL
},
582 {1, S_O(eq_enabled
), false, "eq enabled", off_on
},
583 {8, S_O(eq_precut
), 0, "eq precut", NULL
},
585 {15, S_O(eq_band0_cutoff
), 60, "eq band 0 cutoff", NULL
},
586 {15, S_O(eq_band1_cutoff
), 200, "eq band 1 cutoff", NULL
},
587 {15, S_O(eq_band2_cutoff
), 800, "eq band 2 cutoff", NULL
},
588 {15, S_O(eq_band3_cutoff
), 4000, "eq band 3 cutoff", NULL
},
589 {15, S_O(eq_band4_cutoff
), 12000, "eq band 4 cutoff", NULL
},
590 /* 0..64 (or 0.0 to 6.4) */
591 {6, S_O(eq_band0_q
), 7, "eq band 0 q", NULL
},
592 {6, S_O(eq_band1_q
), 10, "eq band 1 q", NULL
},
593 {6, S_O(eq_band2_q
), 10, "eq band 2 q", NULL
},
594 {6, S_O(eq_band3_q
), 10, "eq band 3 q", NULL
},
595 {6, S_O(eq_band4_q
), 7, "eq band 4 q", NULL
},
596 /* -240..240 (or -24db to +24db) */
597 {9|SIGNED
, S_O(eq_band0_gain
), 0, "eq band 0 gain", NULL
},
598 {9|SIGNED
, S_O(eq_band1_gain
), 0, "eq band 1 gain", NULL
},
599 {9|SIGNED
, S_O(eq_band2_gain
), 0, "eq band 2 gain", NULL
},
600 {9|SIGNED
, S_O(eq_band3_gain
), 0, "eq band 3 gain", NULL
},
601 {9|SIGNED
, S_O(eq_band4_gain
), 0, "eq band 4 gain", NULL
},
604 {1, S_O(dithering_enabled
), false, "dithering enabled", off_on
},
608 {1, S_O(dircache
), false, "dircache", off_on
},
609 {22, S_O(dircache_size
), 0, NULL
, NULL
},
613 #ifdef HAVE_TC_RAMCACHE
614 {1, S_O(tagcache_ram
), 0, "tagcache_ram", off_on
},
616 {1, S_O(tagcache_autoupdate
), 0, "tagcache_autoupdate", off_on
},
619 {4, S_O(default_codepage
), 0, "default codepage",
620 "iso8859-1,iso8859-7,iso8859-8,cp1251,iso8859-11,cp1256,iso8859-9,iso8859-2,sjis,gb2312,ksx1001,big5,utf-8,cp1256" },
622 {1, S_O(warnon_erase_dynplaylist
), false,
623 "warn when erasing dynamic playlist", off_on
},
625 #ifdef CONFIG_BACKLIGHT
626 #ifdef HAS_BUTTON_HOLD
627 {2, S_O(backlight_on_button_hold
), 0, "backlight on button hold",
631 #ifdef HAVE_LCD_SLEEP
632 {4, S_O(lcd_sleep_after_backlight_off
), 3,
633 "lcd sleep after backlight off",
634 "always,never,5,10,15,20,30,45,60,90" },
636 #endif /* CONFIG_BACKLIGHT */
639 {1, S_O(eq_hw_enabled
), false, "eq hardware enabled", off_on
},
641 {2, S_O(eq_hw_band0_cutoff
), 1, "eq hardware band 0 cutoff", "80Hz,105Hz,135Hz,175Hz" },
642 {5|SIGNED
, S_O(eq_hw_band0_gain
), 0, "eq hardware band 0 gain", NULL
},
644 {2, S_O(eq_hw_band1_center
), 1, "eq hardware band 1 center", "230Hz,300Hz,385Hz,500Hz" },
645 {1, S_O(eq_hw_band1_bandwidth
), 0, "eq hardware band 1 bandwidth", "narrow,wide" },
646 {5|SIGNED
, S_O(eq_hw_band1_gain
), 0, "eq hardware band 1 gain", NULL
},
648 {2, S_O(eq_hw_band2_center
), 1, "eq hardware band 2 center", "650Hz,850Hz,1.1kHz,1.4kHz" },
649 {1, S_O(eq_hw_band2_bandwidth
), 0, "eq hardware band 2 bandwidth", "narrow,wide" },
650 {5|SIGNED
, S_O(eq_hw_band2_gain
), 0, "eq hardware band 2 gain", NULL
},
652 {2, S_O(eq_hw_band3_center
), 1, "eq hardware band 3 center", "1.8kHz,2.4kHz,3.2kHz,4.1kHz" },
653 {1, S_O(eq_hw_band3_bandwidth
), 0, "eq hardware band 3 bandwidth", "narrow,wide" },
654 {5|SIGNED
, S_O(eq_hw_band3_gain
), 0, "eq hardware band 3 gain", NULL
},
656 {2, S_O(eq_hw_band4_cutoff
), 1, "eq hardware band 4 cutoff", "5.3kHz,6.9kHz,9kHz,11.7kHz" },
657 {5|SIGNED
, S_O(eq_hw_band4_gain
), 0, "eq hardware band 4 gain", NULL
},
659 {1, S_O(hold_lr_for_scroll_in_list
), true, "hold_lr_for_scroll_in_list", off_on
},
661 {2, S_O(show_path_in_browser
), 0, "show path in browser", "off,current directory,full path" },
663 {4, S_O(rec_agc_preset_mic
), 1, "agc mic preset", NULL
}, /* 0...5 */
664 {4, S_O(rec_agc_preset_line
), 1, "agc line preset", NULL
}, /* 0...5 */
665 {8|SIGNED
, S_O(rec_agc_maxgain_mic
), 104, "agc maximum mic gain", NULL
},
666 {8|SIGNED
, S_O(rec_agc_maxgain_line
), 96, "agc maximum line gain", NULL
},
667 {3, S_O(rec_agc_cliptime
), 1, "agc cliptime", "0.2s,0.4s,0.6s,0.8,1s"},
670 #ifdef HAVE_REMOTE_LCD
671 #ifdef HAS_REMOTE_BUTTON_HOLD
672 {2, S_O(remote_backlight_on_button_hold
), 0, "remote backlight on button hold",
677 #ifdef HAVE_HEADPHONE_DETECTION
678 {2, S_O(unplug_mode
), 0, "pause on headphone unplug", NULL
},
679 {4, S_O(unplug_rw
), 0, "rewind duration on pause", NULL
},
680 {1, S_O(unplug_autoresume
), 0, "disable autoresume if phones not present", off_on
},
683 {2, S_O(fm_region
), 0, "fm_region", "eu,us,jp,kr" },
686 {1, S_O(audioscrobbler
), false, "Last.fm Logging", off_on
},
688 /* If values are just added to the end, no need to bump the version. */
689 /* new stuff to be added at the end */
690 #ifdef HAVE_RECORDING
691 {2, S_O(rec_trigger_type
), 0, "trigger type", "stop,pause,nf stp"},
694 /* Sum of all bit sizes must not grow beyond 0xB8*8 = 1472 */
697 /* helper function to extract n (<=32) bits from an arbitrary position
698 * counting from LSB to MSB */
699 static uint32_t get_bits(
700 const uint32_t *p
, /* the start of the bitfield array */
701 unsigned int from
, /* bit no. to start reading from */
702 unsigned int size
) /* how many bits to read */
704 unsigned int long_index
= from
/ 32;
705 unsigned int bit_index
= from
% 32;
708 result
= p
[long_index
] >> bit_index
;
710 if (bit_index
+ size
> 32) /* crossing longword boundary */
711 result
|= p
[long_index
+1] << (32 - bit_index
);
713 result
&= 0xFFFFFFFF >> (32 - size
);
718 /* helper function to set n (<=32) bits to an arbitrary position,
719 * counting from LSB to MSB */
720 static void set_bits(
721 uint32_t *p
, /* the start of the bitfield array */
722 unsigned int from
, /* bit no. to start writing into */
723 unsigned int size
, /* how many bits to change */
724 uint32_t value
) /* content (LSBs will be taken) */
726 unsigned int long_index
= from
/ 32;
727 unsigned int bit_index
= from
% 32;
730 mask
= 0xFFFFFFFF >> (32 - size
);
734 if (bit_index
+ size
> 32)
736 (p
[long_index
+1] & (0xFFFFFFFF << (bit_index
+ size
- 32)))
737 | (value
>> (32 - bit_index
));
739 p
[long_index
] = (p
[long_index
] & ~mask
) | (value
<< bit_index
);
742 #ifdef HAVE_LCD_COLOR
744 * Helper function to convert a string of 6 hex digits to a native colour
747 #define hex2dec(c) (((c) >= '0' && ((c) <= '9')) ? (toupper(c)) - '0' : \
748 (toupper(c)) - 'A' + 10)
750 int hex_to_rgb(const char* hex
)
753 int red
, green
, blue
;
755 if (strlen(hex
) == 6) {
756 for (i
=0; i
< 6; i
++ ) {
757 if (!isxdigit(hex
[i
])) {
764 red
= (hex2dec(hex
[0]) << 4) | hex2dec(hex
[1]);
765 green
= (hex2dec(hex
[2]) << 4) | hex2dec(hex
[3]);
766 blue
= (hex2dec(hex
[4]) << 4) | hex2dec(hex
[5]);
767 return LCD_RGBPACK(red
,green
,blue
);
776 * Calculates the checksum for the config block and returns it
779 static unsigned short calculate_config_checksum(const unsigned char* buf
)
782 unsigned char cksum
[2];
783 cksum
[0] = cksum
[1] = 0;
785 for (i
=0; i
< RTC_BLOCK_SIZE
- 2; i
+=2 ) {
787 cksum
[1] ^= buf
[i
+1];
790 return (cksum
[0] << 8) | cksum
[1];
794 * initialize the config block buffer
796 static void init_config_buffer( void )
798 DEBUGF( "init_config_buffer()\n" );
800 /* reset to 0 - all unused */
801 memset(config_block
, 0, CONFIG_BLOCK_SIZE
);
803 config_block
[0] = 'R';
804 config_block
[1] = 'o';
805 config_block
[2] = 'c';
806 config_block
[3] = CONFIG_BLOCK_VERSION
;
809 bool flush_config_block_callback(void)
811 ata_write_sectors(IF_MV2(0,) config_sector
, 1, config_block
);
815 * save the config block buffer to disk or RTC RAM
817 static int save_config_buffer( void )
819 unsigned short chksum
;
824 /* update the checksum in the end of the block before saving */
825 chksum
= calculate_config_checksum(config_block
);
826 config_block
[ RTC_BLOCK_SIZE
- 2 ] = chksum
>> 8;
827 config_block
[ RTC_BLOCK_SIZE
- 1 ] = chksum
& 0xff;
830 /* FIXME: okay, it _would_ be cleaner and faster to implement rtc_write so
831 that it would write a number of bytes at a time since the RTC chip
832 supports that, but this will have to do for now 8-) */
833 for (i
=0; i
< RTC_BLOCK_SIZE
; i
++ ) {
834 int r
= rtc_write(0x14+i
, config_block
[i
]);
836 DEBUGF( "save_config_buffer: rtc_write failed at addr 0x%02x: %d\n",
844 if (config_sector
!= 0)
845 register_ata_idle_func(flush_config_block_callback
);
853 * load the config block buffer from disk or RTC RAM
855 static int load_config_buffer(int which
)
857 unsigned short chksum
;
858 bool correct
= false;
861 DEBUGF( "load_config_buffer()\n" );
863 if (which
& SETTINGS_HD
)
865 if (config_sector
!= 0) {
866 ata_read_sectors(IF_MV2(0,) config_sector
, 1, config_block
);
867 /* calculate the checksum, check it and the header */
868 chksum
= calculate_config_checksum(config_block
);
870 if (config_block
[0] == 'R' &&
871 config_block
[1] == 'o' &&
872 config_block
[2] == 'c' &&
873 config_block
[3] == CONFIG_BLOCK_VERSION
&&
874 (chksum
>> 8) == config_block
[RTC_BLOCK_SIZE
- 2] &&
875 (chksum
& 0xff) == config_block
[RTC_BLOCK_SIZE
- 1])
877 DEBUGF( "load_config_buffer: header & checksum test ok\n" );
886 /* If the disk sector was incorrect, reinit the buffer */
887 memset(config_block
, 0, CONFIG_BLOCK_SIZE
);
890 if (which
& SETTINGS_RTC
)
893 unsigned char rtc_block
[RTC_BLOCK_SIZE
];
896 for (i
=0; i
< RTC_BLOCK_SIZE
; i
++ )
897 rtc_block
[i
] = rtc_read(0x14+i
);
899 chksum
= calculate_config_checksum(rtc_block
);
901 /* if rtc block is ok, use that */
902 if (rtc_block
[0] == 'R' &&
903 rtc_block
[1] == 'o' &&
904 rtc_block
[2] == 'c' &&
905 rtc_block
[3] == CONFIG_BLOCK_VERSION
&&
906 (chksum
>> 8) == rtc_block
[RTC_BLOCK_SIZE
- 2] &&
907 (chksum
& 0xff) == rtc_block
[RTC_BLOCK_SIZE
- 1])
909 memcpy(config_block
, rtc_block
, RTC_BLOCK_SIZE
);
916 /* if checksum is not valid, clear the config buffer */
917 DEBUGF( "load_config_buffer: header & checksum test failed\n" );
918 init_config_buffer();
926 /* helper to save content of global_settings into a bitfield,
927 as described per table */
928 static void save_bit_table(const struct bit_entry
* p_table
, int count
, int bitstart
)
930 uint32_t *p_bitfield
= (uint32_t *)config_block
; /* 32 bit addr. */
931 uint32_t value
; /* 32 bit content */
933 const struct bit_entry
* p_run
= p_table
; /* start after the size info */
934 int curr_bit
= bitstart
+ p_table
->bit_size
;
935 count
--; /* first is excluded from loop */
937 for (i
=0; i
<count
; i
++)
940 /* could do a memcpy, but that would be endian-dependent */
941 switch(p_run
->byte_size
)
944 value
= ((uint8_t *)&global_settings
)[p_run
->settings_offset
];
947 value
= ((uint16_t *)&global_settings
)[p_run
->settings_offset
/2];
950 value
= ((uint32_t *)&global_settings
)[p_run
->settings_offset
/4];
953 DEBUGF( "save_bit_table: illegal size!\n" );
956 set_bits(p_bitfield
, curr_bit
, p_run
->bit_size
& 0x3F, value
);
957 curr_bit
+= p_run
->bit_size
& 0x3F;
959 set_bits(p_bitfield
, bitstart
, p_table
->bit_size
, /* write size */
960 curr_bit
); /* = position after last element */
964 * figure out the config sector from the partition table and the
965 * mounted file system
967 void settings_calc_config_sector(void)
973 long partition_start
;
976 if (fat_startsector(IF_MV(0)) != 0) /* There is a partition table */
979 for (i
= 0; i
< 4; i
++)
981 partition_start
= disk_partinfo(i
)->start
;
982 if (partition_start
!= 0 && (partition_start
- 2) < sector
)
983 sector
= partition_start
- 2;
989 config_sector
= sector
;
994 * persist all runtime user settings to disk or RTC RAM
996 int settings_save( void )
1003 elapsed_secs
= (current_tick
- lasttime
) / HZ
;
1004 global_settings
.runtime
+= elapsed_secs
;
1005 lasttime
+= (elapsed_secs
* HZ
);
1007 if ( global_settings
.runtime
> global_settings
.topruntime
)
1008 global_settings
.topruntime
= global_settings
.runtime
;
1011 /* serialize scalar values into RTC and HD sector, specified via table */
1012 save_bit_table(rtc_bits
, sizeof(rtc_bits
)/sizeof(rtc_bits
[0]), 4*8);
1013 save_bit_table(hd_bits
, sizeof(hd_bits
)/sizeof(hd_bits
[0]), RTC_BLOCK_SIZE
*8);
1016 strncpy((char *)&config_block
[i
], (char *)global_settings
.wps_file
,
1019 strncpy((char *)&config_block
[i
], (char *)global_settings
.lang_file
,
1022 strncpy((char *)&config_block
[i
], (char *)global_settings
.font_file
,
1025 #ifdef HAVE_REMOTE_LCD
1026 strncpy((char *)&config_block
[i
], (char *)global_settings
.rwps_file
,
1032 strncpy((char *)&config_block
[i
], (char *)global_settings
.fmr_file
,
1038 strncpy((char *)&config_block
[i
], (char *)global_settings
.backdrop_file
,
1042 #ifdef HAVE_LCD_BITMAP
1043 strncpy((char *)&config_block
[i
], (char *)global_settings
.kbd_file
,
1048 if(save_config_buffer())
1050 lcd_clear_display();
1051 #ifdef HAVE_REMOTE_LCD
1052 lcd_remote_clear_display();
1054 #ifdef HAVE_LCD_CHARCELLS
1055 lcd_puts(0, 0, str(LANG_SETTINGS_SAVE_PLAYER
));
1056 lcd_puts(0, 1, str(LANG_SETTINGS_BATTERY_PLAYER
));
1058 lcd_puts(4, 2, str(LANG_SETTINGS_SAVE_RECORDER
));
1059 lcd_puts(2, 4, str(LANG_SETTINGS_BATTERY_RECORDER
));
1061 #ifdef HAVE_REMOTE_LCD
1062 lcd_remote_puts(4, 2, str(LANG_SETTINGS_SAVE_RECORDER
));
1063 lcd_remote_puts(2, 4, str(LANG_SETTINGS_BATTERY_RECORDER
));
1064 lcd_remote_update();
1073 #ifdef HAVE_LCD_BITMAP
1075 * Applies the range infos stored in global_settings to
1078 void settings_apply_pm_range(void)
1082 /* depending on the scale mode (dBfs or percent) the values
1083 of global_settings.peak_meter_dbfs have different meanings */
1084 if (global_settings
.peak_meter_dbfs
)
1086 /* convert to dBfs * 100 */
1087 pm_min
= -(((int)global_settings
.peak_meter_min
) * 100);
1088 pm_max
= -(((int)global_settings
.peak_meter_max
) * 100);
1092 /* percent is stored directly -> no conversion */
1093 pm_min
= global_settings
.peak_meter_min
;
1094 pm_max
= global_settings
.peak_meter_max
;
1097 /* apply the range */
1098 peak_meter_init_range(global_settings
.peak_meter_dbfs
, pm_min
, pm_max
);
1100 #endif /* HAVE_LCD_BITMAP */
1102 void sound_settings_apply(void)
1104 sound_set(SOUND_BASS
, global_settings
.bass
);
1105 sound_set(SOUND_TREBLE
, global_settings
.treble
);
1106 sound_set(SOUND_BALANCE
, global_settings
.balance
);
1107 sound_set(SOUND_VOLUME
, global_settings
.volume
);
1108 #if CONFIG_CODEC == SWCODEC
1109 channels_set(global_settings
.channel_config
);
1110 stereo_width_set(global_settings
.stereo_width
);
1112 sound_set(SOUND_CHANNELS
, global_settings
.channel_config
);
1113 sound_set(SOUND_STEREO_WIDTH
, global_settings
.stereo_width
);
1115 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
1116 sound_set(SOUND_LOUDNESS
, global_settings
.loudness
);
1117 sound_set(SOUND_AVC
, global_settings
.avc
);
1118 sound_set(SOUND_MDB_STRENGTH
, global_settings
.mdb_strength
);
1119 sound_set(SOUND_MDB_HARMONICS
, global_settings
.mdb_harmonics
);
1120 sound_set(SOUND_MDB_CENTER
, global_settings
.mdb_center
);
1121 sound_set(SOUND_MDB_SHAPE
, global_settings
.mdb_shape
);
1122 sound_set(SOUND_MDB_ENABLE
, global_settings
.mdb_enable
);
1123 sound_set(SOUND_SUPERBASS
, global_settings
.superbass
);
1127 void settings_apply(void)
1130 #if CONFIG_CODEC == SWCODEC
1134 sound_settings_apply();
1136 audio_set_buffer_margin(global_settings
.buffer_margin
);
1138 #ifdef HAVE_LCD_CONTRAST
1139 lcd_set_contrast(global_settings
.contrast
);
1141 lcd_scroll_speed(global_settings
.scroll_speed
);
1142 #ifdef HAVE_REMOTE_LCD
1143 lcd_remote_set_contrast(global_settings
.remote_contrast
);
1144 lcd_remote_set_invert_display(global_settings
.remote_invert
);
1145 lcd_remote_set_flip(global_settings
.remote_flip_display
);
1146 lcd_remote_scroll_speed(global_settings
.remote_scroll_speed
);
1147 lcd_remote_scroll_step(global_settings
.remote_scroll_step
);
1148 lcd_remote_scroll_delay(global_settings
.remote_scroll_delay
* (HZ
/10));
1149 lcd_remote_bidir_scroll(global_settings
.remote_bidir_limit
);
1150 #ifdef HAVE_REMOTE_LCD_TICKING
1151 lcd_remote_emireduce(global_settings
.remote_reduce_ticking
);
1153 remote_backlight_set_timeout(global_settings
.remote_backlight_timeout
);
1154 #ifdef CONFIG_CHARGING
1155 remote_backlight_set_timeout_plugged(global_settings
.remote_backlight_timeout_plugged
);
1157 #ifdef HAS_REMOTE_BUTTON_HOLD
1158 remote_backlight_set_on_button_hold(global_settings
.remote_backlight_on_button_hold
);
1160 #endif /* HAVE_REMOTE_LCD */
1161 #ifdef CONFIG_BACKLIGHT
1162 backlight_set_timeout(global_settings
.backlight_timeout
);
1163 #ifdef CONFIG_CHARGING
1164 backlight_set_timeout_plugged(global_settings
.backlight_timeout_plugged
);
1166 #if defined(HAVE_BACKLIGHT_PWM_FADING) && !defined(SIMULATOR)
1167 backlight_set_fade_in(global_settings
.backlight_fade_in
);
1168 backlight_set_fade_out(global_settings
.backlight_fade_out
);
1171 #ifdef HAVE_BACKLIGHT_BRIGHTNESS
1172 backlight_set_brightness(global_settings
.brightness
);
1174 ata_spindown(global_settings
.disk_spindown
);
1175 #if (CONFIG_CODEC == MAS3507D) && !defined(SIMULATOR)
1176 dac_line_in(global_settings
.line_in
);
1178 mpeg_id3_options(global_settings
.id3_v1_first
);
1179 #ifdef HAVE_ATA_POWER_OFF
1180 ata_poweroff(global_settings
.disk_poweroff
);
1183 set_poweroff_timeout(global_settings
.poweroff
);
1185 set_battery_capacity(global_settings
.battery_capacity
);
1186 #if BATTERY_TYPES_COUNT > 1
1187 set_battery_type(global_settings
.battery_type
);
1190 #ifdef HAVE_LCD_BITMAP
1191 lcd_set_invert_display(global_settings
.invert
);
1192 lcd_set_flip(global_settings
.flip_display
);
1193 button_set_flip(global_settings
.flip_display
);
1194 lcd_update(); /* refresh after flipping the screen */
1195 settings_apply_pm_range();
1196 peak_meter_init_times(
1197 global_settings
.peak_meter_release
, global_settings
.peak_meter_hold
,
1198 global_settings
.peak_meter_clip_hold
);
1202 unload_wps_backdrop();
1204 if ( global_settings
.wps_file
[0] &&
1205 global_settings
.wps_file
[0] != 0xff ) {
1206 snprintf(buf
, sizeof buf
, WPS_DIR
"/%s.wps",
1207 global_settings
.wps_file
);
1208 wps_data_load(gui_wps
[0].data
, buf
, true);
1212 wps_data_init(gui_wps
[0].data
);
1216 if ( global_settings
.backdrop_file
[0] &&
1217 global_settings
.backdrop_file
[0] != 0xff ) {
1218 snprintf(buf
, sizeof buf
, BACKDROP_DIR
"/%s.bmp",
1219 global_settings
.backdrop_file
);
1220 load_main_backdrop(buf
);
1222 unload_main_backdrop();
1224 show_main_backdrop();
1227 #ifdef HAVE_LCD_COLOR
1228 screens
[SCREEN_MAIN
].set_foreground(global_settings
.fg_color
);
1229 screens
[SCREEN_MAIN
].set_background(global_settings
.bg_color
);
1232 #if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1)
1233 if ( global_settings
.rwps_file
[0] &&
1234 global_settings
.rwps_file
[0] != 0xff ) {
1235 snprintf(buf
, sizeof buf
, WPS_DIR
"/%s.rwps",
1236 global_settings
.rwps_file
);
1237 wps_data_load(gui_wps
[1].data
, buf
, true);
1240 wps_data_init(gui_wps
[1].data
);
1243 #ifdef HAVE_LCD_BITMAP
1244 if ( global_settings
.font_file
[0] &&
1245 global_settings
.font_file
[0] != 0xff ) {
1246 snprintf(buf
, sizeof buf
, FONT_DIR
"/%s.fnt",
1247 global_settings
.font_file
);
1253 if ( global_settings
.kbd_file
[0] &&
1254 global_settings
.kbd_file
[0] != 0xff ) {
1255 snprintf(buf
, sizeof buf
, ROCKBOX_DIR
"/%s.kbd",
1256 global_settings
.kbd_file
);
1262 lcd_scroll_step(global_settings
.scroll_step
);
1263 gui_list_screen_scroll_step(global_settings
.screen_scroll_step
);
1264 gui_list_screen_scroll_out_of_view(global_settings
.offset_out_of_view
);
1266 lcd_jump_scroll(global_settings
.jump_scroll
);
1267 lcd_jump_scroll_delay(global_settings
.jump_scroll_delay
* (HZ
/10));
1269 lcd_bidir_scroll(global_settings
.bidir_limit
);
1270 lcd_scroll_delay(global_settings
.scroll_delay
* (HZ
/10));
1272 if ( global_settings
.lang_file
[0] &&
1273 global_settings
.lang_file
[0] != 0xff ) {
1274 snprintf(buf
, sizeof buf
, LANG_DIR
"/%s.lng",
1275 global_settings
.lang_file
);
1277 talk_init(); /* use voice of same language */
1280 set_codepage(global_settings
.default_codepage
);
1282 #if CONFIG_CODEC == SWCODEC
1283 audio_set_crossfade(global_settings
.crossfade
);
1284 dsp_set_replaygain(true);
1285 dsp_set_crossfeed(global_settings
.crossfeed
);
1286 dsp_set_crossfeed_direct_gain(global_settings
.crossfeed_direct_gain
);
1287 dsp_set_crossfeed_cross_params(global_settings
.crossfeed_cross_gain
,
1288 global_settings
.crossfeed_cross_gain
1289 + global_settings
.crossfeed_hf_attenuation
,
1290 global_settings
.crossfeed_hf_cutoff
);
1292 dsp_set_eq(global_settings
.eq_enabled
);
1293 dsp_set_eq_precut(global_settings
.eq_precut
);
1294 /* Update all EQ bands */
1295 for(i
= 0; i
< 5; i
++) {
1296 dsp_set_eq_coefs(i
);
1299 dsp_dither_enable(global_settings
.dithering_enabled
);
1303 eq_hw_enable(global_settings
.eq_hw_enabled
);
1306 #ifdef HAVE_SPDIF_POWER
1307 spdif_power_enable(global_settings
.spdif_enable
);
1310 #ifdef CONFIG_BACKLIGHT
1311 set_backlight_filter_keypress(global_settings
.bl_filter_first_keypress
);
1312 #ifdef HAVE_REMOTE_LCD
1313 set_remote_backlight_filter_keypress(global_settings
.remote_bl_filter_first_keypress
);
1315 #ifdef HAS_BUTTON_HOLD
1316 backlight_set_on_button_hold(global_settings
.backlight_on_button_hold
);
1318 #ifdef HAVE_LCD_SLEEP
1319 lcd_set_sleep_after_backlight_off(global_settings
.lcd_sleep_after_backlight_off
);
1321 #endif /* CONFIG_BACKLIGHT */
1323 /* This should stay last */
1324 #if defined(HAVE_RECORDING) && CONFIG_CODEC == SWCODEC
1325 enc_global_settings_apply();
1330 /* helper to load global_settings from a bitfield, as described per table */
1331 static void load_bit_table(const struct bit_entry
* p_table
, int count
, int bitstart
)
1333 uint32_t *p_bitfield
= (uint32_t *)config_block
; /* 32 bit addr. */
1334 uint32_t value
; /* 32 bit content */
1336 int maxbit
; /* how many bits are valid in the saved part */
1337 const struct bit_entry
* p_run
= p_table
; /* start after the size info */
1338 count
--; /* first is excluded from loop */
1339 maxbit
= get_bits(p_bitfield
, bitstart
, p_table
->bit_size
);
1340 bitstart
+= p_table
->bit_size
;
1342 for (i
=0; i
<count
; i
++)
1347 size
= p_run
->bit_size
& 0x3F; /* mask off abused bits */
1348 if (bitstart
+ size
> maxbit
)
1349 break; /* exit if this is not valid any more in bitfield */
1351 value
= get_bits(p_bitfield
, bitstart
, size
);
1353 if (p_run
->bit_size
& SIGNED
)
1354 { // sign extend the read value
1355 unsigned long mask
= 0xFFFFFFFF << (size
- 1);
1356 if (value
& mask
) /* true if MSB of value is set */
1360 /* could do a memcpy, but that would be endian-dependent */
1361 switch(p_run
->byte_size
)
1364 ((uint8_t *)&global_settings
)[p_run
->settings_offset
] =
1365 (unsigned char)value
;
1368 ((uint16_t *)&global_settings
)[p_run
->settings_offset
/2] =
1369 (unsigned short)value
;
1372 ((uint32_t *)&global_settings
)[p_run
->settings_offset
/4] =
1373 (unsigned int)value
;
1376 DEBUGF( "load_bit_table: illegal size!\n" );
1384 * load settings from disk or RTC RAM
1386 void settings_load(int which
)
1389 DEBUGF( "reload_all_settings()\n" );
1391 /* load the buffer from the RTC (resets it to all-unused if the block
1392 is invalid) and decode the settings which are set in the block */
1393 if (!load_config_buffer(which
))
1395 /* load scalar values from RTC and HD sector, specified via table */
1396 if (which
& SETTINGS_RTC
)
1398 load_bit_table(rtc_bits
, sizeof(rtc_bits
)/sizeof(rtc_bits
[0]), 4*8);
1400 if (which
& SETTINGS_HD
)
1402 load_bit_table(hd_bits
, sizeof(hd_bits
)/sizeof(hd_bits
[0]),
1406 #ifdef HAVE_RECORDING
1407 global_settings
.recscreen_on
= false;
1410 #ifdef HAVE_LCD_CONTRAST
1411 if ( global_settings
.contrast
< MIN_CONTRAST_SETTING
||
1412 global_settings
.contrast
> MAX_CONTRAST_SETTING
)
1413 global_settings
.contrast
= lcd_default_contrast();
1416 #ifdef HAVE_LCD_REMOTE
1417 if (global_settings
.remote_contrast
< MIN_REMOTE_CONTRAST_SETTING
||
1418 global_settings
.remote_contrast
> MAX_REMOTE_CONTRAST_SETTING
)
1419 global_settings
.remote_contrast
= lcd_remote_default_contrast();
1422 strncpy((char *)global_settings
.wps_file
, (char *)&config_block
[i
],
1425 strncpy((char *)global_settings
.lang_file
, (char *)&config_block
[i
],
1428 strncpy((char *)global_settings
.font_file
, (char *)&config_block
[i
],
1431 #ifdef HAVE_REMOTE_LCD
1432 strncpy((char *)global_settings
.rwps_file
, (char *)&config_block
[i
],
1438 strncpy((char *)global_settings
.fmr_file
, (char *)&config_block
[i
],
1444 strncpy((char *)global_settings
.backdrop_file
, (char *)&config_block
[i
],
1448 #ifdef HAVE_LCD_BITMAP
1449 strncpy((char *)global_settings
.kbd_file
, (char *)&config_block
[i
],
1456 void set_file(char* filename
, char* setting
, int maxlen
)
1458 char* fptr
= strrchr(filename
,'/');
1471 while ((*ptr
!= '.') && (ptr
!= fptr
)) {
1475 if(ptr
== fptr
) extlen
= 0;
1477 if (strncasecmp(ROCKBOX_DIR
, filename
,strlen(ROCKBOX_DIR
)) ||
1478 (len
-extlen
> maxlen
))
1481 strncpy(setting
, fptr
, len
-extlen
);
1482 setting
[len
-extlen
]=0;
1487 /* helper to sort a .cfg file entry into a global_settings member,
1488 as described per table. Returns the position if found, else 0. */
1489 static int load_cfg_table(
1490 const struct bit_entry
* p_table
, /* the table which describes the entries */
1491 int count
, /* number of entries in the table, including the first */
1492 const char* name
, /* the item to be searched */
1493 const char* value
, /* the value which got loaded for that item */
1494 int hint
) /* position to start looking */
1500 if (p_table
[i
].cfg_name
!= NULL
&& !strcasecmp(name
, p_table
[i
].cfg_name
))
1503 if (p_table
[i
].cfg_val
== NULL
)
1504 { /* numerical value, just convert the string */
1508 else if (!strncasecmp(p_table
[i
].cfg_val
,"rgb",4))
1510 val
= hex_to_rgb(value
);
1514 { /* set of string values, find the index */
1517 int len
= strlen(value
);
1519 item
= run
= p_table
[i
].cfg_val
;
1523 /* count the length of the field */
1524 while (*run
!= ',' && *run
!= '\0')
1527 if (!strncasecmp(value
, item
, MAX(run
-item
, len
)))
1528 break; /* match, exit the search */
1530 if (*run
== '\0') /* reached the end of the choices */
1531 return i
; /* return the position, but don't update */
1533 val
++; /* count the item up */
1534 run
++; /* behind the ',' */
1539 /* could do a memcpy, but that would be endian-dependent */
1540 switch(p_table
[i
].byte_size
)
1543 ((unsigned char*)&global_settings
)[p_table
[i
].settings_offset
] =
1547 ((unsigned short*)&global_settings
)[p_table
[i
].settings_offset
/2] =
1548 (unsigned short)val
;
1551 ((unsigned int*)&global_settings
)[p_table
[i
].settings_offset
/4] =
1555 DEBUGF( "illegal size!" );
1559 return i
; /* return the position */
1564 i
=1; /* wraparound */
1565 } while (i
!= hint
); /* back where we started, all searched */
1567 return 0; /* indicate not found */
1571 bool settings_load_config(const char* file
)
1576 fd
= open(file
, O_RDONLY
);
1580 while (read_line(fd
, line
, sizeof line
) > 0)
1584 const struct bit_entry
* table
[2] = { rtc_bits
, hd_bits
};
1585 const int ta_size
[2] = {
1586 sizeof(rtc_bits
)/sizeof(rtc_bits
[0]),
1587 sizeof(hd_bits
)/sizeof(hd_bits
[0])
1589 int last_table
= 0; /* which table was used last round */
1590 int last_pos
= 1; /* at which position did we succeed */
1591 int pos
; /* currently returned position */
1593 if (!settings_parseline(line
, &name
, &value
))
1596 /* check for the string values */
1597 if (!strcasecmp(name
, "wps")) {
1599 unload_wps_backdrop();
1602 if ((fd2
= open(value
, O_RDONLY
)) >= 0) {
1604 set_file(value
, (char *)global_settings
.wps_file
, MAX_FILENAME
);
1607 #if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1)
1608 else if (!strcasecmp(name
, "rwps")) {
1610 if ((fd2
= open(value
, O_RDONLY
)) >= 0) {
1612 set_file(value
, (char *)global_settings
.rwps_file
, MAX_FILENAME
);
1616 else if (!strcasecmp(name
, "lang")) {
1617 if (!lang_load(value
))
1619 set_file(value
, (char *)global_settings
.lang_file
, MAX_FILENAME
);
1620 talk_init(); /* use voice of same language */
1624 else if (!strcasecmp(name
, "fmr")) {
1625 set_file(value
, global_settings
.fmr_file
, MAX_FILENAME
);
1628 #ifdef HAVE_LCD_BITMAP
1629 else if (!strcasecmp(name
, "font")) {
1630 if (font_load(value
))
1631 set_file(value
, (char *)global_settings
.font_file
, MAX_FILENAME
);
1635 else if (!strcasecmp(name
, "backdrop")) {
1636 if (load_main_backdrop(value
)) {
1637 set_file(value
, (char *)global_settings
.backdrop_file
, MAX_FILENAME
);
1638 show_main_backdrop();
1642 #ifdef HAVE_LCD_BITMAP
1643 else if (!strcasecmp(name
, "keyboard")) {
1644 if (!load_kbd(value
))
1645 set_file(value
, (char *)global_settings
.kbd_file
, MAX_FILENAME
);
1650 /* check for scalar values, using the two tables */
1651 pos
= load_cfg_table(table
[last_table
], ta_size
[last_table
],
1652 name
, value
, last_pos
);
1653 if (pos
) /* success */
1655 last_pos
= pos
; /* remember as a position hint for next round */
1659 last_table
= 1-last_table
; /* try other table */
1660 last_pos
= 1; /* search from start */
1661 pos
= load_cfg_table(table
[last_table
], ta_size
[last_table
],
1662 name
, value
, last_pos
);
1663 if (pos
) /* success */
1665 last_pos
= pos
; /* remember as a position hint for next round */
1677 /* helper to save content of global_settings into a file,
1678 as described per table */
1679 static void save_cfg_table(const struct bit_entry
* p_table
, int count
, int fd
)
1681 long value
; /* 32 bit content */
1683 const struct bit_entry
* p_run
= p_table
; /* start after the size info */
1684 count
--; /* first is excluded from loop */
1686 for (i
=0; i
<count
; i
++)
1690 if (p_run
->cfg_name
== NULL
)
1691 continue; /* this value is not to be saved */
1693 /* could do a memcpy, but that would be endian-dependent */
1694 switch(p_run
->byte_size
)
1697 if (p_run
->bit_size
& SIGNED
) /* signed? */
1698 value
= ((char*)&global_settings
)[p_run
->settings_offset
];
1700 value
= ((unsigned char*)&global_settings
)[p_run
->settings_offset
];
1703 if (p_run
->bit_size
& SIGNED
) /* signed? */
1704 value
= ((short*)&global_settings
)[p_run
->settings_offset
/2];
1706 value
= ((unsigned short*)&global_settings
)[p_run
->settings_offset
/2];
1709 value
= ((unsigned int*)&global_settings
)[p_run
->settings_offset
/4];
1712 DEBUGF( "illegal size!" );
1716 if (p_run
->cfg_val
== NULL
) /* write as number */
1718 fdprintf(fd
, "%s: %ld\r\n", p_run
->cfg_name
, value
);
1720 #ifdef HAVE_LCD_COLOR
1721 else if (!strcasecmp(p_run
->cfg_val
, "rgb"))
1723 fdprintf(fd
, "%s: %02x%02x%02x\r\n", p_run
->cfg_name
,
1724 (int)RGB_UNPACK_RED(value
),
1725 (int)RGB_UNPACK_GREEN(value
),
1726 (int)RGB_UNPACK_BLUE(value
));
1729 else /* write as item */
1731 const char* p
= p_run
->cfg_val
;
1733 fdprintf(fd
, "%s: ", p_run
->cfg_name
);
1737 char c
= *p
++; /* currently processed char */
1738 if (c
== ',') /* separator */
1740 else if (c
== '\0') /* end of string */
1741 break; /* not found */
1742 else if (value
== 0) /* the right place */
1743 write(fd
, &c
, 1); /* char by char, this is lame, OK */
1746 fdprintf(fd
, "\r\n");
1747 if (p_run
->cfg_val
!= off_on
) /* explaination for non-bool */
1748 fdprintf(fd
, "# (possible values: %s)\r\n", p_run
->cfg_val
);
1753 bool settings_save_config(void)
1756 char filename
[MAX_PATH
];
1758 create_numbered_filename(filename
, ROCKBOX_DIR
, "config", ".cfg", 2
1759 IF_CNFN_NUM_(, NULL
));
1761 /* allow user to modify filename */
1763 if (!kbd_input(filename
, sizeof filename
)) {
1764 fd
= creat(filename
, O_WRONLY
);
1766 gui_syncsplash(HZ
, true, str(LANG_FAILED
));
1771 gui_syncsplash(HZ
, true, str(LANG_MENU_SETTING_CANCEL
));
1776 fdprintf(fd
, "# .cfg file created by rockbox %s - "
1777 "http://www.rockbox.org\r\n#\r\n#\r\n# wps / rwps / language"
1778 " / font / fmpreset / backdrop \r\n#\r\n", appsversion
);
1780 if (global_settings
.wps_file
[0] != 0)
1781 fdprintf(fd
, "wps: %s/%s.wps\r\n", WPS_DIR
,
1782 global_settings
.wps_file
);
1784 #ifdef HAVE_REMOTE_LCD
1785 if (global_settings
.rwps_file
[0] != 0)
1786 fdprintf(fd
, "rwps: %s/%s.rwps\r\n", WPS_DIR
,
1787 global_settings
.rwps_file
);
1790 if (global_settings
.lang_file
[0] != 0)
1791 fdprintf(fd
, "lang: %s/%s.lng\r\n", LANG_DIR
,
1792 global_settings
.lang_file
);
1794 #ifdef HAVE_LCD_BITMAP
1795 if (global_settings
.font_file
[0] != 0)
1796 fdprintf(fd
, "font: %s/%s.fnt\r\n", FONT_DIR
,
1797 global_settings
.font_file
);
1801 if (global_settings
.backdrop_file
[0] != 0)
1802 fdprintf(fd
, "backdrop: %s/%s.bmp\r\n", BACKDROP_DIR
,
1803 global_settings
.backdrop_file
);
1807 if (global_settings
.fmr_file
[0] != 0)
1808 fdprintf(fd
, "fmr: %s/%s.fmr\r\n", FMPRESET_PATH
,
1809 global_settings
.fmr_file
);
1812 #ifdef HAVE_LCD_BITMAP
1813 if (global_settings
.kbd_file
[0] != 0)
1814 fdprintf(fd
, "keyboard: %s/%s.kbd\r\n", ROCKBOX_DIR
,
1815 global_settings
.kbd_file
);
1818 /* here's the action: write values to file, specified via table */
1819 save_cfg_table(rtc_bits
, sizeof(rtc_bits
)/sizeof(rtc_bits
[0]), fd
);
1820 save_cfg_table(hd_bits
, sizeof(hd_bits
)/sizeof(hd_bits
[0]), fd
);
1824 gui_syncsplash(HZ
, true, str(LANG_SETTINGS_SAVED
));
1829 /* helper to load defaults from table into global_settings members */
1830 static void default_table(const struct bit_entry
* p_table
, int count
)
1834 for (i
=1; i
<count
; i
++) /* exclude the first, the size placeholder */
1836 /* could do a memcpy, but that would be endian-dependent */
1837 switch(p_table
[i
].byte_size
)
1840 ((unsigned char*)&global_settings
)[p_table
[i
].settings_offset
] =
1841 (unsigned char)p_table
[i
].default_val
;
1844 ((unsigned short*)&global_settings
)[p_table
[i
].settings_offset
/2] =
1845 (unsigned short)p_table
[i
].default_val
;
1848 ((unsigned int*)&global_settings
)[p_table
[i
].settings_offset
/4] =
1849 (unsigned int)p_table
[i
].default_val
;
1852 DEBUGF( "illegal size!" );
1860 * reset all settings to their default value
1862 void settings_reset(void) {
1864 DEBUGF( "settings_reset()\n" );
1866 /* read defaults from table(s) into global_settings */
1867 default_table(rtc_bits
, sizeof(rtc_bits
)/sizeof(rtc_bits
[0]));
1868 default_table(hd_bits
, sizeof(hd_bits
)/sizeof(hd_bits
[0]));
1870 /* do some special cases not covered by table */
1871 global_settings
.volume
= sound_default(SOUND_VOLUME
);
1872 global_settings
.balance
= sound_default(SOUND_BALANCE
);
1873 global_settings
.bass
= sound_default(SOUND_BASS
);
1874 global_settings
.treble
= sound_default(SOUND_TREBLE
);
1875 global_settings
.channel_config
= sound_default(SOUND_CHANNELS
);
1876 global_settings
.stereo_width
= sound_default(SOUND_STEREO_WIDTH
);
1877 #if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
1878 global_settings
.loudness
= sound_default(SOUND_LOUDNESS
);
1879 global_settings
.avc
= sound_default(SOUND_AVC
);
1880 global_settings
.mdb_strength
= sound_default(SOUND_MDB_STRENGTH
);
1881 global_settings
.mdb_harmonics
= sound_default(SOUND_MDB_HARMONICS
);
1882 global_settings
.mdb_center
= sound_default(SOUND_MDB_CENTER
);
1883 global_settings
.mdb_shape
= sound_default(SOUND_MDB_SHAPE
);
1884 global_settings
.mdb_enable
= sound_default(SOUND_MDB_ENABLE
);
1885 global_settings
.superbass
= sound_default(SOUND_SUPERBASS
);
1887 #ifdef HAVE_LCD_CONTRAST
1888 global_settings
.contrast
= lcd_default_contrast();
1890 #ifdef HAVE_LCD_REMOTE
1891 global_settings
.remote_contrast
= lcd_remote_default_contrast();
1895 global_settings
.fmr_file
[0] = '\0';
1897 global_settings
.wps_file
[0] = '\0';
1898 #ifdef HAVE_REMOTE_LCD
1899 global_settings
.rwps_file
[0] = '\0';
1901 global_settings
.font_file
[0] = '\0';
1902 global_settings
.lang_file
[0] = '\0';
1904 global_settings
.backdrop_file
[0] = '\0';
1906 #ifdef HAVE_LCD_COLOR
1907 global_settings
.fg_color
= LCD_DEFAULT_FG
;
1908 global_settings
.bg_color
= LCD_DEFAULT_BG
;
1910 #ifdef HAVE_LCD_BITMAP
1911 global_settings
.kbd_file
[0] = '\0';
1913 global_settings
.hold_lr_for_scroll_in_list
= true;
1915 #if defined (HAVE_RECORDING) && CONFIG_CODEC == SWCODEC
1916 enc_global_settings_reset();
1920 bool set_bool(const char* string
, bool* variable
)
1922 return set_bool_options(string
, variable
,
1923 (char *)STR(LANG_SET_BOOL_YES
),
1924 (char *)STR(LANG_SET_BOOL_NO
),
1928 /* wrapper to convert from int param to bool param in set_option */
1929 static void (*boolfunction
)(bool);
1930 void bool_funcwrapper(int value
)
1935 boolfunction(false);
1938 bool set_bool_options(const char* string
, bool* variable
,
1939 const char* yes_str
, int yes_voice
,
1940 const char* no_str
, int no_voice
,
1941 void (*function
)(bool))
1943 struct opt_items names
[] = {
1944 {(unsigned char *)no_str
, no_voice
},
1945 {(unsigned char *)yes_str
, yes_voice
}
1949 boolfunction
= function
;
1950 result
= set_option(string
, variable
, BOOL
, names
, 2,
1951 function
? bool_funcwrapper
: NULL
);
1955 void talk_unit(int unit
, int value
)
1957 if (global_settings
.talk_menu
)
1959 if (unit
< UNIT_LAST
)
1960 { /* use the available unit definition */
1961 talk_value(value
, unit
, false);
1964 { /* say the number, followed by an arbitrary voice ID */
1965 talk_number(value
, false);
1966 talk_id(unit
, true);
1971 struct value_setting_data
{
1972 enum optiontype type
;
1973 /* used for "value" settings.. */
1978 void (*formatter
)(char* dest
, int dest_length
,
1979 int variable
, const char* unit
);
1980 /* used for BOOL and "choice" settings */
1981 struct opt_items
* options
;
1984 char * value_setting_get_name_cb(int selected_item
,void * data
, char *buffer
)
1986 struct value_setting_data
* cb_data
=
1987 (struct value_setting_data
*)data
;
1988 if (cb_data
->type
== INT
&& !cb_data
->options
)
1990 int item
= cb_data
->max
-(selected_item
*cb_data
->step
);
1991 if (cb_data
->formatter
)
1992 cb_data
->formatter(buffer
, MAX_PATH
,item
,cb_data
->unit
);
1994 snprintf(buffer
, MAX_PATH
,"%d %s",item
,cb_data
->unit
);
1996 else strcpy(buffer
,P2STR(cb_data
->options
[selected_item
].string
));
1999 #define type_fromvoidptr(type, value) \
2001 (int)(*(int*)(value)) \
2003 (bool)(*(bool*)(value))
2004 bool do_set_setting(const unsigned char* string
, void *variable
,
2005 int nb_items
,int selected
,
2006 struct value_setting_data
*cb_data
,
2007 void (*function
)(int))
2011 struct gui_synclist lists
;
2013 bool allow_wrap
= true;
2015 if (cb_data
->type
== INT
)
2017 oldvalue
= *(int*)variable
;
2018 if (variable
== &global_settings
.volume
)
2021 else oldvalue
= *(bool*)variable
;
2023 gui_synclist_init(&lists
,value_setting_get_name_cb
,(void*)cb_data
,false,1);
2024 gui_synclist_set_title(&lists
, (char*)string
, NOICON
);
2025 gui_synclist_set_icon_callback(&lists
,NULL
);
2026 gui_synclist_set_nb_items(&lists
,nb_items
);
2027 gui_synclist_limit_scroll(&lists
,true);
2028 gui_synclist_select_item(&lists
, selected
);
2030 if (global_settings
.talk_menu
)
2032 if (cb_data
->type
== INT
&& !cb_data
->options
)
2033 talk_unit(cb_data
->voice_unit
, *(int*)variable
);
2034 else talk_id(cb_data
->options
[selected
].voice_id
, false);
2037 gui_synclist_draw(&lists
);
2041 action
= get_action(CONTEXT_LIST
,TIMEOUT_BLOCK
);
2042 if (action
== ACTION_NONE
)
2044 if (gui_synclist_do_button(&lists
,action
,
2045 allow_wrap
?LIST_WRAP_UNLESS_HELD
:LIST_WRAP_OFF
))
2047 if (global_settings
.talk_menu
)
2050 if (cb_data
->type
== INT
&& !cb_data
->options
)
2052 value
= cb_data
->max
-
2053 gui_synclist_get_sel_pos(&lists
)*cb_data
->step
;
2054 talk_unit(cb_data
->voice_unit
, value
);
2058 value
= gui_synclist_get_sel_pos(&lists
);
2059 talk_id(cb_data
->options
[value
].voice_id
, false);
2062 if (cb_data
->type
== INT
&& !cb_data
->options
)
2063 *(int*)variable
= cb_data
->max
-
2064 gui_synclist_get_sel_pos(&lists
)*cb_data
->step
;
2065 else if (cb_data
->type
== BOOL
)
2066 *(bool*)variable
= gui_synclist_get_sel_pos(&lists
) ? true : false;
2067 else *(int*)variable
= gui_synclist_get_sel_pos(&lists
);
2069 else if (action
== ACTION_STD_CANCEL
)
2071 gui_syncsplash(HZ
/2,true,str(LANG_MENU_SETTING_CANCEL
));
2072 if (cb_data
->type
== INT
)
2073 *(int*)variable
= oldvalue
;
2074 else *(bool*)variable
= (bool)oldvalue
;
2077 else if (action
== ACTION_STD_OK
)
2081 else if(default_event_handler(action
) == SYS_USB_CONNECTED
)
2083 gui_syncstatusbar_draw(&statusbars
, false);
2085 function(type_fromvoidptr(cb_data
->type
,variable
));
2089 bool set_int(const unsigned char* string
,
2093 void (*function
)(int),
2097 void (*formatter
)(char*, int, int, const char*) )
2099 #if CONFIG_KEYPAD != PLAYER_PAD
2100 struct value_setting_data data
= {
2101 INT
,max
, step
, voice_unit
,unit
,formatter
,NULL
};
2102 return do_set_setting(string
,variable
,(max
-min
)/step
+ 1,
2103 (max
-*variable
)/step
, &data
,function
);
2105 int count
= (max
-min
)/step
+ 1;
2106 struct value_setting_data data
= {
2107 INT
,min
, -step
, voice_unit
,unit
,formatter
,NULL
};
2108 return do_set_setting(string
,variable
,count
,
2109 count
- ((max
-*variable
)/step
), &data
,function
);
2113 /* NOTE: the 'type' parameter specifies the actual type of the variable
2114 that 'variable' points to. not the value within. Only variables with
2115 type 'bool' should use parameter BOOL.
2117 The type separation is necessary since int and bool are fundamentally
2118 different and bit-incompatible types and can not share the same access
2120 bool set_option(const char* string
, void* variable
, enum optiontype type
,
2121 const struct opt_items
* options
, int numoptions
, void (*function
)(int))
2123 struct value_setting_data data
= {
2124 type
,0, 0, 0,NULL
,NULL
,(struct opt_items
*)options
};
2127 selected
= *(bool*)variable
? 1 : 0;
2128 else selected
= *(int*)variable
;
2129 return do_set_setting(string
,variable
,numoptions
,
2130 selected
, &data
,function
);
2133 #ifdef HAVE_RECORDING
2134 /* This array holds the record timer interval lengths, in seconds */
2135 static const unsigned long rec_timer_seconds
[] =
2137 0, /* 0 means OFF */
2145 2*60*60, /* 02:00 */
2146 4*60*60, /* 04:00 */
2147 6*60*60, /* 06:00 */
2148 8*60*60, /* 08:00 */
2149 10L*60*60, /* 10:00 */
2150 12L*60*60, /* 12:00 */
2151 18L*60*60, /* 18:00 */
2152 24L*60*60 /* 24:00 */
2155 unsigned int rec_timesplit_seconds(void)
2157 return rec_timer_seconds
[global_settings
.rec_timesplit
];
2160 /* This array holds the record size interval lengths, in bytes */
2161 static const unsigned long rec_size_bytes
[] =
2163 0, /* 0 means OFF */
2164 5*1024*1024, /* 5MB */
2165 10*1024*1024, /* 10MB */
2166 15*1024*1024, /* 15MB */
2167 32*1024*1024, /* 32MB */
2168 64*1024*1024, /* 64MB */
2169 75*1024*1024, /* 75MB */
2170 100*1024*1024, /* 100MB */
2171 128*1024*1024, /* 128MB */
2172 256*1024*1024, /* 256MB */
2173 512*1024*1024, /* 512MB */
2174 650*1024*1024, /* 650MB */
2175 700*1024*1024, /* 700MB */
2176 1024*1024*1024, /* 1GB */
2177 1536*1024*1024, /* 1.5GB */
2178 1792*1024*1024, /* 1.75GB */
2181 unsigned long rec_sizesplit_bytes(void)
2183 return rec_size_bytes
[global_settings
.rec_sizesplit
];
2186 * Time strings used for the trigger durations.
2187 * Keep synchronous to trigger_times in settings_apply_trigger
2189 const char * const trig_durations
[TRIG_DURATION_COUNT
] =
2191 "0s", "1s", "2s", "5s",
2192 "10s", "15s", "20s", "25s", "30s",
2193 "1min", "2min", "5min", "10min"
2196 void settings_apply_trigger(void)
2198 /* Keep synchronous to trig_durations and trig_durations_conf*/
2199 static const long trigger_times
[TRIG_DURATION_COUNT
] = {
2201 10*HZ
, 15*HZ
, 20*HZ
, 25*HZ
, 30*HZ
,
2202 60*HZ
, 2*60*HZ
, 5*60*HZ
, 10*60*HZ
2205 peak_meter_define_trigger(
2206 global_settings
.rec_start_thres
,
2207 trigger_times
[global_settings
.rec_start_duration
],
2208 MIN(trigger_times
[global_settings
.rec_start_duration
] / 2, 2*HZ
),
2209 global_settings
.rec_stop_thres
,
2210 trigger_times
[global_settings
.rec_stop_postrec
],
2211 trigger_times
[global_settings
.rec_stop_gap
]