1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 by wavey@wavey.org
11 * RTC config saving code (C) 2002 by hessu@hes.iki.fi
13 * All files in this archive are subject to the GNU General Public License.
14 * See the file COPYING in the source tree root for full license agreement.
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
19 ****************************************************************************/
33 #include "backlight.h"
36 #include "mp3_playback.h"
43 #include "powermgmt.h"
52 #include "timefuncs.h"
53 #ifdef HAVE_LCD_BITMAP
56 #include "peakmeter.h"
62 #include "powermgmt.h"
69 #include "rbunicode.h"
71 #include "statusbar.h"
82 #if CONFIG_CODEC == MAS3507D
83 void dac_line_in(bool enable
);
85 struct user_settings global_settings
;
87 const char rec_base_directory
[] = REC_BASE_DIR
;
89 #if CONFIG_CODEC == SWCODEC
91 #include "pcm_playback.h"
99 #define CONFIG_BLOCK_VERSION 55
100 #define CONFIG_BLOCK_SIZE 512
101 #define RTC_BLOCK_SIZE 44
103 #ifdef HAVE_LCD_BITMAP
109 #ifdef HAVE_REMOTE_LCD
110 #include "lcd-remote.h"
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) */
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 */
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 */
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.
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";
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";
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";
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 */
211 #if CONFIG_CODEC == MAS3507D
212 {8 | SIGNED
, S_O(volume
), -18, "volume", NULL
}, /* -78...+18 */
214 {8 | SIGNED
, S_O(volume
), -25, "volume", NULL
}, /* -100...+12 / -84...0 */
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 */
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
},
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
},
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" },
245 #ifdef HAVE_LCD_CONTRAST
246 {6, S_O(contrast
), DEFAULT_CONTRAST_SETTING
, "contrast", NULL
},
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
},
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
},
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
},
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
},
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
},
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 */
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 */
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
},
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 */
299 #if BATTERY_TYPES_COUNT > 1
300 {1, S_O(battery_type
), 0, "battery type", "alkaline,nimh" },
303 #ifdef HAVE_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
},
315 #ifdef HAVE_REMOTE_LCD_TICKING
316 {1, S_O(remote_reduce_ticking
), false, "remote reduce ticking", off_on
},
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
},
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 */
348 #ifdef CONFIG_BACKLIGHT
349 {1, S_O(caption_backlight
), false, "caption backlight", off_on
},
351 #ifdef HAVE_REMOTE_LCD
352 {1, S_O(remote_caption_backlight
), false,
353 "remote caption backlight", off_on
},
355 #ifdef HAVE_BACKLIGHT_BRIGHTNESS
356 {4, S_O(brightness
), DEFAULT_BRIGHTNESS_SETTING
, "brightness", NULL
},
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"},
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 */
376 #ifdef HAVE_LCD_BITMAP
377 {1, S_O(offset_out_of_view
), false, "Screen Scrolls Out Of View", off_on
},
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
},
385 {7, S_O(scroll_step
), 6, "scroll step", NULL
},
386 {7, S_O(screen_scroll_step
), 16, "screen scroll step", NULL
},
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 */
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"},
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" },
410 {3, S_O(buffer_margin
), 0, "antiskip", NULL
},
414 #ifdef HAVE_ATA_POWER_OFF
415 {1, S_O(disk_poweroff
), false, "disk poweroff", off_on
},
417 {8, S_O(disk_spindown
), 5, "disk spindown", NULL
},
418 #endif /* HAVE_MMC */
421 {3, S_O(dirfilter
), SHOW_SUPPORTED
,
422 "show files", "all,supported,music,playlists"
427 {1, S_O(sort_case
), false, "sort case", off_on
},
428 {1, S_O(browse_current
), false, "follow playlist", off_on
},
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
},
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
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 */
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
},
462 #if CONFIG_CODEC == MAS3507D
463 {1, S_O(line_in
), false, "line in", off_on
},
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
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)
492 S_O(rec_source
), 0 /* 0=mic */, "rec source",
497 #ifdef HAVE_FMRADIO_IN
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" },
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)
519 {8|SIGNED
, S_O(rec_mic_gain
), 16 /* 8 dB */, "rec mic gain", NULL
}, /* -128...+108 */
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 */
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" },
531 {3, S_O(rec_frequency
), 0, /* 0=44.1kHz */
532 "rec frequency", "44" },
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
},
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
},
574 {1, S_O(eq_enabled
), false, "eq enabled", off_on
},
575 {8, S_O(eq_precut
), 0, "eq precut", NULL
},
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
},
596 {1, S_O(dithering_enabled
), false, "dithering enabled", off_on
},
600 {1, S_O(dircache
), false, "dircache", off_on
},
601 {22, S_O(dircache_size
), 0, NULL
, NULL
},
605 #ifdef HAVE_TC_RAMCACHE
606 {1, S_O(tagcache_ram
), 0, "tagcache_ram", off_on
},
608 {1, S_O(tagcache_autoupdate
), 0, "tagcache_autoupdate", off_on
},
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",
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" },
628 #endif /* CONFIG_BACKLIGHT */
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
},
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" },
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"},
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",
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
},
675 {2, S_O(fm_region
), 0, "fm_region", "eu,us,jp,kr" },
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;
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
);
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;
719 mask
= 0xFFFFFFFF >> (32 - size
);
723 if (bit_index
+ size
> 32)
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
)
742 int red
, green
, blue
;
744 if (strlen(hex
) == 6) {
745 for (i
=0; i
< 6; i
++ ) {
746 if (!isxdigit(hex
[i
])) {
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
);
765 * Calculates the checksum for the config block and returns it
768 static unsigned short calculate_config_checksum(const unsigned char* buf
)
771 unsigned char cksum
[2];
772 cksum
[0] = cksum
[1] = 0;
774 for (i
=0; i
< RTC_BLOCK_SIZE
- 2; i
+=2 ) {
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
);
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
;
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;
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
]);
820 DEBUGF( "save_config_buffer: rtc_write failed at addr 0x%02x: %d\n",
828 if (config_sector
!= 0)
829 ata_delayed_write( config_sector
, config_block
);
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" );
870 /* If the disk sector was incorrect, reinit the buffer */
871 memset(config_block
, 0, CONFIG_BLOCK_SIZE
);
874 if (which
& SETTINGS_RTC
)
877 unsigned char rtc_block
[RTC_BLOCK_SIZE
];
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
);
900 /* if checksum is not valid, clear the config buffer */
901 DEBUGF( "load_config_buffer: header & checksum test failed\n" );
902 init_config_buffer();
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 */
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
++)
924 /* could do a memcpy, but that would be endian-dependent */
925 switch(p_run
->byte_size
)
928 value
= ((uint8_t *)&global_settings
)[p_run
->settings_offset
];
931 value
= ((uint16_t *)&global_settings
)[p_run
->settings_offset
/2];
934 value
= ((uint32_t *)&global_settings
)[p_run
->settings_offset
/4];
937 DEBUGF( "save_bit_table: illegal size!\n" );
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)
957 long partition_start
;
960 if (fat_startsector(IF_MV(0)) != 0) /* There is a partition table */
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;
973 config_sector
= sector
;
978 * persist all runtime user settings to disk or RTC RAM
980 int settings_save( void )
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);
1000 strncpy((char *)&config_block
[i
], (char *)global_settings
.wps_file
,
1003 strncpy((char *)&config_block
[i
], (char *)global_settings
.lang_file
,
1006 strncpy((char *)&config_block
[i
], (char *)global_settings
.font_file
,
1009 #ifdef HAVE_REMOTE_LCD
1010 strncpy((char *)&config_block
[i
], (char *)global_settings
.rwps_file
,
1016 strncpy((char *)&config_block
[i
], (char *)global_settings
.fmr_file
,
1021 #ifdef HAVE_LCD_COLOR
1022 strncpy((char *)&config_block
[i
], (char *)global_settings
.backdrop_file
,
1026 #ifdef HAVE_LCD_BITMAP
1027 strncpy((char *)&config_block
[i
], (char *)global_settings
.kbd_file
,
1032 if(save_config_buffer())
1034 lcd_clear_display();
1035 #ifdef HAVE_REMOTE_LCD
1036 lcd_remote_clear_display();
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
));
1042 lcd_puts(4, 2, str(LANG_SETTINGS_SAVE_RECORDER
));
1043 lcd_puts(2, 4, str(LANG_SETTINGS_BATTERY_RECORDER
));
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();
1057 #ifdef HAVE_LCD_BITMAP
1059 * Applies the range infos stored in global_settings to
1062 void settings_apply_pm_range(void)
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);
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
);
1096 sound_set(SOUND_CHANNELS
, global_settings
.channel_config
);
1097 sound_set(SOUND_STEREO_WIDTH
, global_settings
.stereo_width
);
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
);
1111 void settings_apply(void)
1114 #if CONFIG_CODEC == SWCODEC
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
);
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
);
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
);
1141 #ifdef HAS_REMOTE_BUTTON_HOLD
1142 remote_backlight_set_on_button_hold(global_settings
.remote_backlight_on_button_hold
);
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
);
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
);
1155 #ifdef HAVE_BACKLIGHT_BRIGHTNESS
1156 backlight_set_brightness(global_settings
.brightness
);
1158 ata_spindown(global_settings
.disk_spindown
);
1159 #if (CONFIG_CODEC == MAS3507D) && !defined(SIMULATOR)
1160 dac_line_in(global_settings
.line_in
);
1162 mpeg_id3_options(global_settings
.id3_v1_first
);
1163 #ifdef HAVE_ATA_POWER_OFF
1164 ata_poweroff(global_settings
.disk_poweroff
);
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
);
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
);
1185 #ifdef HAVE_LCD_COLOR
1186 unload_wps_backdrop();
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);
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
);
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
);
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);
1222 wps_data_init(gui_wps
[1].data
);
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
);
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
);
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
);
1248 lcd_jump_scroll(global_settings
.jump_scroll
);
1249 lcd_jump_scroll_delay(global_settings
.jump_scroll_delay
* (HZ
/10));
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
);
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
);
1285 eq_hw_enable(global_settings
.eq_hw_enabled
);
1288 #ifdef HAVE_SPDIF_POWER
1289 spdif_power_enable(global_settings
.spdif_enable
);
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
);
1297 #ifdef HAS_BUTTON_HOLD
1298 backlight_set_on_button_hold(global_settings
.backlight_on_button_hold
);
1300 #ifdef HAVE_LCD_SLEEP
1301 lcd_set_sleep_after_backlight_off(global_settings
.lcd_sleep_after_backlight_off
);
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 */
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
++)
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
);
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 */
1337 /* could do a memcpy, but that would be endian-dependent */
1338 switch(p_run
->byte_size
)
1341 ((uint8_t *)&global_settings
)[p_run
->settings_offset
] =
1342 (unsigned char)value
;
1345 ((uint16_t *)&global_settings
)[p_run
->settings_offset
/2] =
1346 (unsigned short)value
;
1349 ((uint32_t *)&global_settings
)[p_run
->settings_offset
/4] =
1350 (unsigned int)value
;
1353 DEBUGF( "load_bit_table: illegal size!\n" );
1361 * load settings from disk or RTC RAM
1363 void settings_load(int which
)
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]),
1383 #ifdef HAVE_RECORDING
1384 global_settings
.recscreen_on
= false;
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();
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();
1399 strncpy((char *)global_settings
.wps_file
, (char *)&config_block
[i
],
1402 strncpy((char *)global_settings
.lang_file
, (char *)&config_block
[i
],
1405 strncpy((char *)global_settings
.font_file
, (char *)&config_block
[i
],
1408 #ifdef HAVE_REMOTE_LCD
1409 strncpy((char *)global_settings
.rwps_file
, (char *)&config_block
[i
],
1415 strncpy((char *)global_settings
.fmr_file
, (char *)&config_block
[i
],
1420 #ifdef HAVE_LCD_COLOR
1421 strncpy((char *)global_settings
.backdrop_file
, (char *)&config_block
[i
],
1425 #ifdef HAVE_LCD_BITMAP
1426 strncpy((char *)global_settings
.kbd_file
, (char *)&config_block
[i
],
1433 void set_file(char* filename
, char* setting
, int maxlen
)
1435 char* fptr
= strrchr(filename
,'/');
1448 while ((*ptr
!= '.') && (ptr
!= fptr
)) {
1452 if(ptr
== fptr
) extlen
= 0;
1454 if (strncasecmp(ROCKBOX_DIR
, filename
,strlen(ROCKBOX_DIR
)) ||
1455 (len
-extlen
> maxlen
))
1458 strncpy(setting
, fptr
, len
-extlen
);
1459 setting
[len
-extlen
]=0;
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 */
1477 if (p_table
[i
].cfg_name
!= NULL
&& !strcasecmp(name
, p_table
[i
].cfg_name
))
1480 if (p_table
[i
].cfg_val
== NULL
)
1481 { /* numerical value, just convert the string */
1485 else if (!strncasecmp(p_table
[i
].cfg_val
,"rgb",4))
1487 val
= hex_to_rgb(value
);
1491 { /* set of string values, find the index */
1494 int len
= strlen(value
);
1496 item
= run
= p_table
[i
].cfg_val
;
1500 /* count the length of the field */
1501 while (*run
!= ',' && *run
!= '\0')
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 ',' */
1516 /* could do a memcpy, but that would be endian-dependent */
1517 switch(p_table
[i
].byte_size
)
1520 ((unsigned char*)&global_settings
)[p_table
[i
].settings_offset
] =
1524 ((unsigned short*)&global_settings
)[p_table
[i
].settings_offset
/2] =
1525 (unsigned short)val
;
1528 ((unsigned int*)&global_settings
)[p_table
[i
].settings_offset
/4] =
1532 DEBUGF( "illegal size!" );
1536 return i
; /* return the position */
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
)
1553 fd
= open(file
, O_RDONLY
);
1557 while (read_line(fd
, line
, sizeof line
) > 0)
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
))
1573 /* check for the string values */
1574 if (!strcasecmp(name
, "wps")) {
1575 #ifdef HAVE_LCD_COLOR
1576 unload_wps_backdrop();
1579 if ((fd2
= open(value
, O_RDONLY
)) >= 0) {
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")) {
1587 if ((fd2
= open(value
, O_RDONLY
)) >= 0) {
1589 set_file(value
, (char *)global_settings
.rwps_file
, MAX_FILENAME
);
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 */
1601 else if (!strcasecmp(name
, "fmr")) {
1602 set_file(value
, global_settings
.fmr_file
, MAX_FILENAME
);
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
);
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();
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
);
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 */
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 */
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 */
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
++)
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
)
1674 if (p_run
->bit_size
& SIGNED
) /* signed? */
1675 value
= ((char*)&global_settings
)[p_run
->settings_offset
];
1677 value
= ((unsigned char*)&global_settings
)[p_run
->settings_offset
];
1680 if (p_run
->bit_size
& SIGNED
) /* signed? */
1681 value
= ((short*)&global_settings
)[p_run
->settings_offset
/2];
1683 value
= ((unsigned short*)&global_settings
)[p_run
->settings_offset
/2];
1686 value
= ((unsigned int*)&global_settings
)[p_run
->settings_offset
/4];
1689 DEBUGF( "illegal size!" );
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
));
1706 else /* write as item */
1708 const char* p
= p_run
->cfg_val
;
1710 fdprintf(fd
, "%s: ", p_run
->cfg_name
);
1714 char c
= *p
++; /* currently processed char */
1715 if (c
== ',') /* separator */
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)
1734 char filename
[MAX_PATH
];
1736 create_numbered_filename(filename
, ROCKBOX_DIR
, "config", ".cfg", 2);
1738 /* allow user to modify filename */
1740 if (!kbd_input(filename
, sizeof filename
)) {
1741 fd
= creat(filename
, O_WRONLY
);
1743 gui_syncsplash(HZ
, true, str(LANG_FAILED
));
1748 gui_syncsplash(HZ
, true, str(LANG_MENU_SETTING_CANCEL
));
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
);
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
);
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
);
1784 if (global_settings
.fmr_file
[0] != 0)
1785 fdprintf(fd
, "fmr: %s/%s.fmr\r\n", FMPRESET_PATH
,
1786 global_settings
.fmr_file
);
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
);
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
);
1801 gui_syncsplash(HZ
, true, str(LANG_SETTINGS_SAVED
));
1806 /* helper to load defaults from table into global_settings members */
1807 static void default_table(const struct bit_entry
* p_table
, int count
)
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
)
1817 ((unsigned char*)&global_settings
)[p_table
[i
].settings_offset
] =
1818 (unsigned char)p_table
[i
].default_val
;
1821 ((unsigned short*)&global_settings
)[p_table
[i
].settings_offset
/2] =
1822 (unsigned short)p_table
[i
].default_val
;
1825 ((unsigned int*)&global_settings
)[p_table
[i
].settings_offset
/4] =
1826 (unsigned int)p_table
[i
].default_val
;
1829 DEBUGF( "illegal size!" );
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
);
1864 #ifdef HAVE_LCD_CONTRAST
1865 global_settings
.contrast
= lcd_default_contrast();
1867 #ifdef HAVE_LCD_REMOTE
1868 global_settings
.remote_contrast
= lcd_remote_default_contrast();
1872 global_settings
.fmr_file
[0] = '\0';
1874 global_settings
.wps_file
[0] = '\0';
1875 #ifdef HAVE_REMOTE_LCD
1876 global_settings
.rwps_file
[0] = '\0';
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
;
1886 #ifdef HAVE_LCD_BITMAP
1887 global_settings
.kbd_file
[0] = '\0';
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
),
1900 /* wrapper to convert from int param to bool param in set_option */
1901 static void (*boolfunction
)(bool);
1902 void bool_funcwrapper(int value
)
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
}
1921 boolfunction
= function
;
1922 result
= set_option(string
, variable
, BOOL
, names
, 2,
1923 function
? bool_funcwrapper
: NULL
);
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);
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.. */
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
);
1966 snprintf(buffer
, MAX_PATH
,"%d %s",item
,cb_data
->unit
);
1968 else strcpy(buffer
,P2STR(cb_data
->options
[selected_item
].string
));
1971 #define type_fromvoidptr(type, value) \
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))
1983 struct gui_synclist lists
;
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
);
2008 action
= get_action(CONTEXT_LIST
,TIMEOUT_BLOCK
);
2009 if (action
== ACTION_NONE
)
2012 if (gui_synclist_do_button(&lists
,action
))
2014 if (global_settings
.talk_menu
)
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
);
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
;
2044 else if (action
== ACTION_STD_OK
)
2048 else if(default_event_handler(action
) == SYS_USB_CONNECTED
)
2050 gui_syncstatusbar_draw(&statusbars
, false);
2052 function(type_fromvoidptr(cb_data
->type
,variable
));
2056 bool set_int(const unsigned char* string
,
2060 void (*function
)(int),
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
);
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
);
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
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
};
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 */
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
] = {
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
]