summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/settings.c1792
-rw-r--r--apps/settings.h7
2 files changed, 737 insertions, 1062 deletions
diff --git a/apps/settings.c b/apps/settings.c
index c9e281dae0..abf152fdf2 100644
--- a/apps/settings.c
+++ b/apps/settings.c
@@ -18,6 +18,7 @@
18 * 18 *
19 ****************************************************************************/ 19 ****************************************************************************/
20#include <stdio.h> 20#include <stdio.h>
21#include <stddef.h>
21#include "config.h" 22#include "config.h"
22#include "kernel.h" 23#include "kernel.h"
23#include "thread.h" 24#include "thread.h"
@@ -61,6 +62,7 @@
61#include "sprintf.h" 62#include "sprintf.h"
62#include "keyboard.h" 63#include "keyboard.h"
63#include "version.h" 64#include "version.h"
65#include "rtc.h"
64#ifdef HAVE_MAS3507D 66#ifdef HAVE_MAS3507D
65void dac_line_in(bool enable); 67void dac_line_in(bool enable);
66#endif 68#endif
@@ -69,9 +71,10 @@ char rockboxdir[] = ROCKBOX_DIR; /* config/font/data file directory */
69char rec_base_directory[] = REC_BASE_DIR; 71char rec_base_directory[] = REC_BASE_DIR;
70 72
71 73
72#define CONFIG_BLOCK_VERSION 10 74#define CONFIG_BLOCK_VERSION 11
73#define CONFIG_BLOCK_SIZE 512 75#define CONFIG_BLOCK_SIZE 512
74#define RTC_BLOCK_SIZE 44 76#define RTC_BLOCK_SIZE 44
77#define MARKER 0x7FFFFFFF /* FIXME: to be removed with val2phys/phys2val */
75 78
76#ifdef HAVE_LCD_BITMAP 79#ifdef HAVE_LCD_BITMAP
77#define MAX_LINES 10 80#define MAX_LINES 10
@@ -79,6 +82,28 @@ char rec_base_directory[] = REC_BASE_DIR;
79#define MAX_LINES 2 82#define MAX_LINES 2
80#endif 83#endif
81 84
85long lasttime = 0;
86static unsigned char config_block[CONFIG_BLOCK_SIZE];
87
88
89/* descriptor for a configuration value */
90/* (watch the struct packing and member sizes to keep this small) */
91struct bit_entry
92{
93 /* how many bits within the bitfield (1-32), MSB set if value is signed */
94 unsigned char bit_size; /* min 6+1 bit */
95 /* how many bytes in the global_settings struct (1,2,4) */
96 unsigned char byte_size; /* min 2 bits */
97 /* store position in global_settings struct */
98 short settings_offset; /* min 9 bit, better 10 */
99 /* default value */
100 int default_val; /* min 15 bit */
101 /* variable name in a .cfg file, NULL if not to be saved */
102 const char* cfg_name;
103 /* set of values, or NULL for a numerical value */
104 const char* cfg_val;
105};
106
82/******************************************** 107/********************************************
83 108
84Config block as saved on the battery-packed RTC user RAM memory block 109Config block as saved on the battery-packed RTC user RAM memory block
@@ -87,89 +112,296 @@ of 44 bytes, starting at offset 0x14 of the RTC memory space.
87offset abs 112offset abs
880x00 0x14 "Roc" header signature: 0x52 0x6f 0x63 1130x00 0x14 "Roc" header signature: 0x52 0x6f 0x63
890x03 0x17 <version byte: 0x0> 1140x03 0x17 <version byte: 0x0>
900x04 0x18 <volume byte> 1150x04 0x18 start of bit-table
910x05 0x19 <balance byte> 116...
920x06 0x1a <bass byte> 1170x28,0x29 unused, not reachable by set_bits() without disturbing the next 2
930x07 0x1b <treble byte> 1180x2A,0x2B <checksum 2 bytes: xor of 0x00-0x29>
940x08 0x1c <loudness byte>
950x09 0x1d <bass boost byte>
960x0a 0x1e <contrast (bit 0-5), invert bit (bit 6), show_icons (bit 7)>
970x0b 0x1f <backlight_on_when_charging, invert_cursor, backlight_timeout>
980x0c 0x20 <poweroff timer byte>
990x0d 0x21 <resume settings byte>
1000x0e 0x22 <shuffle,dirfilter,sort_case,discharge,statusbar,show_hidden,
101 scroll bar>
1020x0f 0x23 <volume type, battery type, timeformat, scroll speed>
1030x10 0x24 <ff/rewind min step, acceleration rate>
1040x11 0x25 <AVC, channel config>
1050x12 0x26 <(short) Resume playlist index, or -1 if no playlist resume>
1060x14 0x28 <(short) Resume playlist first index>
1070x16 0x2a <(int) Byte offset into resume file>
1080x1a 0x2e <time until disk spindown>
1090x1b 0x2f <browse current, play selected, recursive dir insert>
1100x1c 0x30 <peak meter hold timeout (bit 0-4),
111 flip_display (bit 6)
112 rec_editable (bit 7)>
1130x1d 0x31 <(int) Resume shuffle seed, or -1 if no shuffle>
1140x21 0x35 <repeat mode (bit 0-1), rec. channels (bit 2),
115 mic gain (bit 4-7)>
1160x22 0x36 <rec. quality (bit 0-2), source (bit 3-4), frequency (bit 5-7)>
1170x23 0x37 <rec. left gain (bit 0-3)>
1180x24 0x38 <rec. right gain (bit 0-3)>
1190x25 0x39 <disk poweroff flag (bit 0), MP3 buffer margin (bit 1-3),
120 Trickle charge flag (bit 4), buttonbar (bit 5)>
1210x26 0x40 <runtime low byte>
1220x27 0x41 <runtime high byte>
1230x28 0x42 <topruntime low byte>
1240x29 0x43 <topruntime high byte>
125
1260x2a <checksum 2 bytes: xor of 0x0-0x29>
127 119
128Config memory is reset to 0xff and initialized with 'factory defaults' if 120Config memory is reset to 0xff and initialized with 'factory defaults' if
129a valid header & checksum is not found. Config version number is only 121a valid header & checksum is not found. Config version number is only
130increased when information is _relocated_ or space is _reused_ so that old 122increased when information is _relocated_ or space is _reused_ so that old
131versions can read and modify configuration changed by new versions. New 123versions can read and modify configuration changed by new versions.
132versions should check for the value of '0xff' in each config memory 124Memory locations not used by a given version should not be
133location used, and reset the setting in question with a factory default if
134needed. Memory locations not used by a given version should not be
135modified unless the header & checksum test fails. 125modified unless the header & checksum test fails.
136 126
137Because 0xff mean that the byte is unused, care must be taken so that
138a used byte can't have the value 0xff. Either use only 7 bits, or make sure
139that the value will never be 0xff.
140
141Rest of config block, only saved to disk: 127Rest of config block, only saved to disk:
1420xA8 (char)jump scroll mode (only for player) 1280x2C start of 2nd bit-table
1430xA9 (char)jump scroll delay (only for player) 129...
1440xAA Max number of files in playlist (1000-20000)
1450xAC Max number of files in dir (50-10000)
1460xAE fade on pause/unpause/stop setting (bit 0)
147 caption backlight (bit 1)
148 car adapter mode (bit 2)
149 line_in (Player only) (bit 3)
150 playlist viewer icons (bit 4)
151 playlist viewer indices (bit 5)
152 playlist viewer track display (bit 6)
1530xAF <most-recent-bookmarks, auto-bookmark, autoload>
1540xB0 peak meter clip hold timeout (bit 0-4), peak meter performance (bit 7)
1550xB1 peak meter release step size, peak_meter_dbfs (bit 7)
1560xB2 peak meter min either in -db or in percent
1570xB3 peak meter max either in -db or in percent
1580xB4 battery capacity
1590xB5 scroll step in pixels
1600xB6 scroll start and endpoint delay
1610xB7 bidir scroll setting (bidi if 0-200% longer than screen width)
1620xB8 (char[20]) WPS file 1300xB8 (char[20]) WPS file
1630xCC (char[20]) Lang file 1310xCC (char[20]) Lang file
1640xE0 (char[20]) Font file 1320xE0 (char[20]) Font file
1650xF4 Prerecording time (bit 0-4), Recording directory option (bit 5-6) 1330xF4-0xFF <unused>
1660xF5-0xFF <unused>
167 134
168*************************************/ 135*************************************/
169 136
170#include "rtc.h" 137/* The persistence of the global_settings members is now controlled by
171long lasttime = 0; 138 the two tables below, rtc_bits and hd_bits.
172static unsigned char config_block[CONFIG_BLOCK_SIZE]; 139 New values can just be added to the end, it will be backwards
140 compatible. If you however change order, bitsize, etc. of existing
141 entries, you need to bump CONFIG_BLOCK_VERSION to break compatibility.
142*/
143
144
145/* convenience macro for both size and offset of global_settings member */
146#define S_O(val) sizeof(global_settings.val), offsetof(struct user_settings, val)
147#define SIGNED 0x80 /* for bitsize value with signed attribute */
148
149/* some sets of values which are used more than once, to save memory */
150static const char off_on[] = "off,on";
151static const char off_on_ask[] = "off,on,ask";
152static const char graphic_numeric[] = "graphic,numeric";
153
154/* the part of the settings which ends up in the RTC RAM, where available
155 (those we either need early, save frequently, or without spinup) */
156static struct bit_entry rtc_bits[] =
157{
158 /* placeholder, containing the size information */
159 {9, 0, 0, 0, NULL, NULL }, /* 9 bit to tell how far this is populated */
160
161 /* # of bits, offset+size, default, .cfg name, .cfg values */
162 /* sound */
163 {7, S_O(volume), 70, "volume", NULL }, /* 0...100 */
164 {7 | SIGNED, S_O(balance), 0, "balance", NULL }, /* -50...50 */
165 {5, S_O(bass), 0, "bass", NULL }, /* 0...30 */
166 {5, S_O(treble), 0, "treble", NULL }, /* 0...30 */
167#ifdef HAVE_MAS3587F
168 {5, S_O(loudness), 0, "loudness", NULL }, /* 0...17 */
169 {4, S_O(bass_boost), 0, "bass boost", NULL }, /* 0...10 */
170 {2, S_O(avc), 0, "auto volume", "off,2,4,8" },
171#endif
172 {3, S_O(channel_config), 6, "channels",
173 "stereo,stereo narrow,mono,mono left,mono right,karaoke,stereo wide" },
174 /* playback */
175 {2, S_O(resume), RESUME_ASK, "resume", "off,ask,ask once,on" },
176 {1, S_O(playlist_shuffle), false, "shuffle", off_on },
177 {16 | SIGNED, S_O(resume_index), -1, NULL, NULL },
178 {16 | SIGNED, S_O(resume_first_index), 0, NULL, NULL },
179 {32 | SIGNED, S_O(resume_offset), -1, NULL, NULL },
180 {32 | SIGNED, S_O(resume_seed), -1, NULL, NULL },
181 {2, S_O(repeat_mode), REPEAT_ALL, "repeat", "off,all,one" },
182 /* LCD */
183 {6, S_O(contrast), 40, "contrast", NULL },
184 {1, S_O(backlight_on_when_charging), false,
185 "backlight when plugged", off_on },
186 {5, S_O(backlight_timeout), 5, "backlight timeout",
187 "off,on,1,2,3,4,5,6,7,8,9,10,15,20,25,30,45,60,90" },
188#ifdef HAVE_LCD_BITMAP
189 {1, S_O(invert), false, "invert", off_on },
190 {1, S_O(flip_display), false, "flip display", off_on },
191 /* display */
192 {1, S_O(invert_cursor), false, "invert cursor", off_on },
193 {1, S_O(show_icons), true, "show icons", off_on },
194 {1, S_O(statusbar), true, "statusbar", off_on },
195 {1, S_O(scrollbar), true, "scrollbar", off_on },
196 {1, S_O(buttonbar), true, "buttonbar", off_on },
197 {1, S_O(volume_type), 0, "volume display", graphic_numeric },
198 {1, S_O(battery_type), 0, "battery display", graphic_numeric },
199 {1, S_O(timeformat), 0, "time format", "24hour,12hour" },
200#endif
201 /* system */
202 {4, S_O(poweroff), 10,
203 "idle poweroff", "off,1,2,3,4,5,6,7,8,9,10,15,30,45,60" },
204 {18, S_O(runtime), 0, NULL, NULL },
205 {18, S_O(topruntime), 0, NULL, NULL },
206 {15, S_O(max_files_in_playlist), 10000,
207 "max files in playlist", NULL }, /* 1000...20000 */
208 {14, S_O(max_files_in_dir), 400,
209 "max files in dir", NULL }, /* 50...10000 */
210 /* battery */
211#ifdef HAVE_CHARGE_CTRL
212 {1, S_O(discharge), 0, "deep discharge", off_on },
213 {1, S_O(trickle_charge), true, "trickle charge", off_on },
214#endif
215#ifdef HAVE_LIION
216 {12, S_O(battery_capacity), 2200, "battery capacity", NULL }, /* 1500...3200 */
217#else
218 {12, S_O(battery_capacity), 1500, "battery capacity", NULL }, /* 1500...3200 */
219#endif
220 {1, S_O(car_adapter_mode), false, "car adapter mode", off_on },
221
222 /* new stuff to be added here */
223 /* If values are just added to the end, no need to bump the version. */
224
225 /* Current sum of bits: 254 (worst case) */
226 /* Sum of all bit sizes must not grow beyond 288! */
227};
228
229
230/* the part of the settings which ends up in HD sector only */
231static struct bit_entry hd_bits[] =
232{
233 /* This table starts after the 44 RTC bytes = 352 bits. */
234 /* Here we need 11 bits to tell how far this is populated. */
235
236 /* placeholder, containing the size information */
237 {11, 0, 0, 0, NULL, NULL }, /* 11 bit to tell how far this is populated */
238
239 /* # of bits, offset+size, default, .cfg name, .cfg values */
240 /* more display */
241 {1, S_O(caption_backlight), false, "caption backlight", off_on },
242 {4, S_O(scroll_speed), 8, "scroll speed", NULL }, /* 1...10 */
243 {7, S_O(scroll_step), 6, "scroll step", NULL }, /* 1...112 */
244 {8, S_O(scroll_delay), 100, "scroll delay", NULL }, /* 0...250 */
245 {8, S_O(bidir_limit), 50, "bidir limit", NULL }, /* 0...200 */
246#ifdef HAVE_LCD_CHARCELLS
247 {3, S_O(jump_scroll), 0, "jump scroll", NULL }, /* 0...5 */
248 {8, S_O(jump_scroll_delay), 50, "jump scroll delay", NULL }, /* 0...250 */
249#endif
250 /* more playback */
251 {1, S_O(play_selected), true, "play selected", off_on },
252 {1, S_O(fade_on_stop), true, "volume fade", off_on },
253 {4, S_O(ff_rewind_min_step), 1000,
254 "scan min step", "1,2,3,4,5,6,8,10,15,20,25,30,45,60" },
255 {4, S_O(ff_rewind_accel), 3, "scan accel", NULL },
256 {3, S_O(buffer_margin), 0, "antiskip", NULL },
257 /* disk */
258#ifdef HAVE_ATA_POWER_OFF
259 {1, S_O(disk_poweroff), false, "disk poweroff", off_on },
260#endif
261 {8, S_O(disk_spindown), 5, "disk spindown", NULL },
262 /* browser */
263 {2, S_O(dirfilter), SHOW_MUSIC,
264 "show files", "all,supported,music,playlists" },
265 {1, S_O(sort_case), false, "sort case", off_on },
266 {1, S_O(browse_current), false, "follow playlist", off_on },
267 /* playlist */
268 {1, S_O(playlist_viewer_icons), true, "playlist viewer icons", off_on },
269 {1, S_O(playlist_viewer_indices), true,
270 "playlist viewer indices", off_on },
271 {1, S_O(playlist_viewer_track_display), 0,
272 "playlist viewer track display", "track name,full path" },
273 {2, S_O(recursive_dir_insert), RECURSE_OFF,
274 "recursive directory insert", off_on_ask },
275 /* bookmarks */
276 {3, S_O(autocreatebookmark), BOOKMARK_NO, "autocreate bookmarks",
277 "off,on,ask,recent only - on,recent only - ask" },
278 {2, S_O(autoloadbookmark), BOOKMARK_NO,
279 "autoload bookmarks", off_on_ask },
280 {2, S_O(usemrb), BOOKMARK_NO,
281 "use most-recent-bookmarks", "off,on,unique only" },
282#ifdef HAVE_LCD_BITMAP
283 /* peak meter */
284 {5, S_O(peak_meter_clip_hold), 16, "peak meter clip hold", /* 0...25 */
285 "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" },
286 {1, S_O(peak_meter_performance), false, "peak meter busy", off_on },
287 {5, S_O(peak_meter_hold), 3, "peak meter hold",
288 "off,200ms,300ms,500ms,1,2,3,4,5,6,7,8,9,10,15,20,30,1min" },
289 {7, S_O(peak_meter_release), 8, "peak meter release", NULL }, /* 0...126 */
290 {1, S_O(peak_meter_dbfs), true, "peak meter dbfs", NULL },
291 {7, S_O(peak_meter_min), 60, "peak meter min", NULL }, /* 0...100 */
292 {7, S_O(peak_meter_max), 0, "peak meter max", NULL }, /* 0...100 */
293#endif
294#ifdef HAVE_MAS3587F
295 /* recording */
296 {1, S_O(rec_editable), false, "editable recordings", off_on },
297 {4, S_O(rec_timesplit), 0, "rec timesplit", /* 0...13 */
298 "off,00:05,00:10,00:15,00:30,01:00,02:00,04:00,06:00,08:00,10:00,12:00,18:00,24:00" },
299 {1, S_O(rec_channels), 0, "rec channels", "stereo,mono" },
300 {4, S_O(rec_mic_gain), 8, "rec mic gain", NULL },
301 {3, S_O(rec_quality), 5, "rec quality", NULL },
302 {2, S_O(rec_source), 0, /* 0=mic */
303 "rec source", "mic,line,spdif" },
304 {3, S_O(rec_frequency), 0, /* 0=44.1kHz */
305 "rec frequency", "44,48,32,22,24,16" },
306 {4, S_O(rec_left_gain), 2, /* 0dB */
307 "rec left gain", NULL }, /* 0...15 */
308 {4, S_O(rec_right_gain), 2, /* 0dB */
309 "rec right gain", NULL }, /* 0...15 */
310 {1, S_O(rec_prerecord_time), 0, "prerecording time", NULL }, /* 0...30 */
311 {1, S_O(rec_directory), 0, /* rec_base_directory */
312 "rec directory", REC_BASE_DIR ",current" },
313#endif
314#ifdef HAVE_MAS3507D
315 {1, S_O(line_in), false, "line in", off_on },
316#endif
317 /* voice */
318 {2, S_O(talk_dir), 0, "talk dir", "off,number,spell,enter,hover" },
319 {2, S_O(talk_file), 0, "talk file", "off,number,spell" },
320 {1, S_O(talk_menu), true, "talk menu", off_on },
321
322 /* new stuff to be added here */
323 /* If values are just added to the end, no need to bump the version. */
324
325 /* Sum of all bit sizes must not grow beyond 0xB8*8 = 1472 */
326};
327
328
329/* helper function to extract n (<=32) bits from an arbitrary position */
330static unsigned long get_bits(
331 unsigned long* p, /* the start of the bitfield array */
332 unsigned int from, /* bit no. to start reading from */
333 unsigned int size) /* how many bits to read */
334{
335 unsigned int bit_index;
336 unsigned int bits_to_use;
337
338 unsigned long mask;
339 unsigned long result;
340
341 if (size==1)
342 { /* short cut */
343 return (p[from/32] & 1<<from%32) != 0;
344 }
345
346 result = 0;
347 while (size)
348 {
349 bit_index = from % 32;
350 bits_to_use = MIN(32 - bit_index, size);
351 mask = 0xFFFFFFFF >> (32 - bits_to_use);
352 mask <<= bit_index;
353
354 result <<= bits_to_use; /* from last round */
355 result |= (p[from/32] & mask) >> bit_index;
356
357 from += bits_to_use;
358 size -= bits_to_use;
359 }
360
361 return result;
362}
363
364/* helper function to set n (<=32) bits to an arbitrary position */
365static void set_bits(
366 unsigned long* p, /* the start of the bitfield array */
367 unsigned int from, /* bit no. to start writing into */
368 unsigned int size, /* how many bits to change */
369 unsigned long value) /* content (LSBs will be taken) */
370{
371 unsigned int end;
372 unsigned int word_index, bit_index;
373 unsigned int bits_to_use;
374
375 unsigned long mask;
376
377 if (size==1)
378 { /* short cut */
379 if (value & 1)
380 p[from/32] |= 1<<from%32;
381 else
382 p[from/32] &= ~(1<<from%32);
383 return;
384 }
385
386 end = from + size - 1;
387
388 /* write back to front, least to most significant */
389 while (size)
390 {
391 word_index = end / 32;
392 bit_index = (end % 32) + 1;
393 bits_to_use = MIN(bit_index, size);
394 bit_index -= bits_to_use;
395 mask = 0xFFFFFFFF >> (32 - bits_to_use);
396 mask <<= bit_index;
397
398 p[word_index] = (p[word_index] & ~mask) | (value<<bit_index & mask);
399
400 value >>= bits_to_use;
401 size -= bits_to_use;
402 end -= bits_to_use;
403 }
404}
173 405
174/* 406/*
175 * Calculates the checksum for the config block and returns it 407 * Calculates the checksum for the config block and returns it
@@ -313,91 +545,52 @@ static int load_config_buffer( void )
313 return 0; 545 return 0;
314} 546}
315 547
548
549/* helper to save content of global_settings into a bitfield,
550 as described per table */
551static void save_bit_table(const struct bit_entry* p_table, int count, int bitstart)
552{
553 unsigned long* p_bitfield = (unsigned long*)config_block; /* 32 bit addr. */
554 unsigned long value; /* 32 bit content */
555 int i;
556 const struct bit_entry* p_run = p_table; /* start after the size info */
557 int curr_bit = bitstart + p_table->bit_size;
558 count--; /* first is excluded from loop */
559
560 for (i=0; i<count; i++)
561 {
562 p_run++;
563 /* could do a memcpy, but that would be endian-dependent */
564 switch(p_run->byte_size)
565 {
566 case 1:
567 value = ((unsigned char*)&global_settings)[p_run->settings_offset];
568 break;
569 case 2:
570 value = ((unsigned short*)&global_settings)[p_run->settings_offset/2];
571 break;
572 case 4:
573 value = ((unsigned int*)&global_settings)[p_run->settings_offset/4];
574 break;
575 default:
576 DEBUGF( "illegal size!" );
577 continue;
578 }
579 set_bits(p_bitfield, curr_bit, p_run->bit_size & 0x3F, value);
580 curr_bit += p_run->bit_size & 0x3F;
581 }
582 set_bits(p_bitfield, bitstart, p_table->bit_size, /* write size */
583 curr_bit); /* = position after last element */
584}
585
586
316/* 587/*
317 * persist all runtime user settings to disk or RTC RAM 588 * persist all runtime user settings to disk or RTC RAM
318 */ 589 */
319int settings_save( void ) 590int settings_save( void )
320{ 591{
592 int restore[6]; /* recover, FIXME: get rid of this */
321 DEBUGF( "settings_save()\n" ); 593 DEBUGF( "settings_save()\n" );
322
323 /* update the config block buffer with current
324 settings and save the block in the RTC */
325 config_block[0x4] = (unsigned char)global_settings.volume;
326 config_block[0x5] = (char)global_settings.balance;
327 config_block[0x6] = (unsigned char)global_settings.bass;
328 config_block[0x7] = (unsigned char)global_settings.treble;
329 config_block[0x8] = (unsigned char)global_settings.loudness;
330 config_block[0x9] = (unsigned char)global_settings.bass_boost;
331
332 config_block[0xa] = (unsigned char)
333 ((global_settings.contrast & 0x3f) |
334 (global_settings.invert ? 0x40 : 0) |
335 (global_settings.show_icons ? 0x80 : 0) );
336
337 config_block[0xb] = (unsigned char)
338 ((global_settings.backlight_on_when_charging?0x40:0) |
339 (global_settings.invert_cursor ? 0x20 : 0) |
340 (global_settings.backlight_timeout & 0x1f));
341 config_block[0xc] = (unsigned char)global_settings.poweroff;
342 config_block[0xd] = (unsigned char)global_settings.resume;
343
344 config_block[0xe] = (unsigned char)
345 ((global_settings.playlist_shuffle & 1) |
346 ((global_settings.dirfilter & 1) << 1) |
347 ((global_settings.sort_case & 1) << 2) |
348 ((global_settings.discharge & 1) << 3) |
349 ((global_settings.statusbar & 1) << 4) |
350 ((global_settings.dirfilter & 2) << 4) |
351 ((global_settings.scrollbar & 1) << 6));
352
353 config_block[0xf] = (unsigned char)
354 ((global_settings.volume_type & 1) |
355 ((global_settings.battery_type & 1) << 1) |
356 ((global_settings.timeformat & 1) << 2) |
357 ( global_settings.scroll_speed << 3));
358
359 config_block[0x10] = (unsigned char)
360 ((global_settings.ff_rewind_min_step & 15) << 4 |
361 (global_settings.ff_rewind_accel & 15));
362
363 config_block[0x11] = (unsigned char)
364 ((global_settings.avc & 0x03) |
365 ((global_settings.channel_config & 0x07) << 2));
366
367 *((short*)(&config_block[0x12])) = global_settings.resume_index;
368 *((short*)(&config_block[0x14])) = global_settings.resume_first_index;
369 memcpy(&config_block[0x16], &global_settings.resume_offset, 4);
370 DEBUGF( "+Resume index %X offset %X\n",
371 global_settings.resume_index,
372 global_settings.resume_offset );
373
374 config_block[0x1a] = (unsigned char)global_settings.disk_spindown;
375 config_block[0x1b] = (unsigned char)
376 (((global_settings.browse_current & 1)) |
377 ((global_settings.play_selected & 1) << 1) |
378 ((global_settings.recursive_dir_insert & 3) << 2));
379
380 config_block[0x1c] = (unsigned char)global_settings.peak_meter_hold |
381 (global_settings.flip_display ? 0x40 : 0) |
382 (global_settings.rec_editable?0x80:0);
383
384 memcpy(&config_block[0x1d], &global_settings.resume_seed, 4);
385
386 config_block[0x21] = (unsigned char)
387 ((global_settings.repeat_mode & 3) |
388 ((global_settings.rec_channels & 1) << 2) |
389 ((global_settings.rec_mic_gain & 0x0f) << 4));
390 config_block[0x22] = (unsigned char)
391 ((global_settings.rec_quality & 7) |
392 ((global_settings.rec_source & 3) << 3) |
393 ((global_settings.rec_frequency & 7) << 5));
394 config_block[0x23] = (unsigned char)global_settings.rec_left_gain;
395 config_block[0x24] = (unsigned char)global_settings.rec_right_gain;
396 config_block[0x25] = (unsigned char)
397 ((global_settings.disk_poweroff & 1) |
398 ((global_settings.buffer_margin & 7) << 1) |
399 ((global_settings.trickle_charge & 1) << 4) |
400 ((global_settings.buttonbar & 1) << 5));
401 594
402 { 595 {
403 int elapsed_secs; 596 int elapsed_secs;
@@ -408,57 +601,45 @@ int settings_save( void )
408 601
409 if ( global_settings.runtime > global_settings.topruntime ) 602 if ( global_settings.runtime > global_settings.topruntime )
410 global_settings.topruntime = global_settings.runtime; 603 global_settings.topruntime = global_settings.runtime;
411
412 config_block[0x26]=(unsigned char)(global_settings.runtime & 0xff);
413 config_block[0x27]=(unsigned char)(global_settings.runtime >> 8);
414 config_block[0x28]=(unsigned char)(global_settings.topruntime & 0xff);
415 config_block[0x29]=(unsigned char)(global_settings.topruntime >> 8);
416 } 604 }
417 605
418#ifdef HAVE_LCD_CHARCELLS 606 /* While the mpeg_val2phys business still exists: ( to be removed) */
419 config_block[0xa8]=(unsigned char)global_settings.jump_scroll; 607 /* temporarily replace the hardware levels with the MMI values */
420 config_block[0xa9]=(unsigned char)global_settings.jump_scroll_delay; 608 restore[SOUND_VOLUME] = global_settings.volume;
609 global_settings.volume = mpeg_val2phys(SOUND_VOLUME, global_settings.volume);
610 restore[SOUND_BASS] = global_settings.bass;
611 global_settings.bass = mpeg_val2phys(SOUND_BASS, global_settings.bass);
612 restore[SOUND_TREBLE] = global_settings.treble;
613 global_settings.treble = mpeg_val2phys(SOUND_TREBLE, global_settings.treble);
614 restore[SOUND_BALANCE] = global_settings.balance;
615 global_settings.balance = mpeg_val2phys(SOUND_BALANCE, global_settings.balance);
616#ifdef HAVE_MAS3587F
617 restore[SOUND_LOUDNESS] = global_settings.loudness;
618 global_settings.loudness = mpeg_val2phys(SOUND_LOUDNESS, global_settings.loudness);
619 restore[SOUND_SUPERBASS] = global_settings.bass_boost;
620 global_settings.bass_boost = mpeg_val2phys(SOUND_SUPERBASS, global_settings.bass_boost);
421#endif 621#endif
422 config_block[0xaa] = (unsigned char) 622
423 global_settings.max_files_in_playlist & 0xff; 623
424 config_block[0xab] = (unsigned char) 624 /* serialize scalar values into RTC and HD sector, specified via table */
425 (global_settings.max_files_in_playlist >> 8) & 0xff; 625 save_bit_table(rtc_bits, sizeof(rtc_bits)/sizeof(rtc_bits[0]), 4*8);
426 config_block[0xac] = (unsigned char) 626 save_bit_table(hd_bits, sizeof(hd_bits)/sizeof(hd_bits[0]), RTC_BLOCK_SIZE*8);
427 global_settings.max_files_in_dir & 0xff;
428 config_block[0xad] = (unsigned char)
429 (global_settings.max_files_in_dir >> 8) & 0xff;
430 config_block[0xae] = (unsigned char)
431 ((global_settings.fade_on_stop & 1) |
432 ((global_settings.caption_backlight & 1) << 1) |
433 ((global_settings.car_adapter_mode & 1) << 2) |
434 ((global_settings.line_in & 1) << 3) |
435 ((global_settings.playlist_viewer_icons & 1) << 4) |
436 ((global_settings.playlist_viewer_indices & 1) << 5) |
437 ((global_settings.playlist_viewer_track_display & 1) << 6));
438 config_block[0xaf] = ((global_settings.usemrb << 5) |
439 (global_settings.autocreatebookmark << 2) |
440 (global_settings.autoloadbookmark));
441 config_block[0xb0] = (unsigned char)global_settings.peak_meter_clip_hold |
442 (global_settings.peak_meter_performance ? 0x80 : 0);
443 config_block[0xb1] = global_settings.peak_meter_release |
444 (global_settings.peak_meter_dbfs ? 0x80 : 0);
445 config_block[0xb2] = (unsigned char)global_settings.peak_meter_min;
446 config_block[0xb3] = (unsigned char)global_settings.peak_meter_max;
447
448 config_block[0xb4]=(global_settings.battery_capacity - 1000) / 50;
449 config_block[0xb5]=(unsigned char)global_settings.scroll_step;
450 config_block[0xb6]=(unsigned char)global_settings.scroll_delay;
451 config_block[0xb7]=(unsigned char)global_settings.bidir_limit;
452 627
453 strncpy(&config_block[0xb8], global_settings.wps_file, MAX_FILENAME); 628 strncpy(&config_block[0xb8], global_settings.wps_file, MAX_FILENAME);
454 strncpy(&config_block[0xcc], global_settings.lang_file, MAX_FILENAME); 629 strncpy(&config_block[0xcc], global_settings.lang_file, MAX_FILENAME);
455 strncpy(&config_block[0xe0], global_settings.font_file, MAX_FILENAME); 630 strncpy(&config_block[0xe0], global_settings.font_file, MAX_FILENAME);
456 631
457 config_block[0xf4]=((unsigned char)global_settings.rec_prerecord_time | 632
458 ((unsigned char)global_settings.rec_directory << 5)); 633 /* restore the original values; to be removed with mpeg_val2phys */
459 config_block[0xf5] = (global_settings.talk_dir & 7) | 634 global_settings.volume = restore[SOUND_VOLUME];
460 ((global_settings.talk_file & 3) << 3) | 635 global_settings.bass = restore[SOUND_BASS];
461 ((global_settings.talk_menu & 1) << 5); 636 global_settings.treble = restore[SOUND_TREBLE];
637 global_settings.balance = restore[SOUND_BALANCE];
638#ifdef HAVE_MAS3587F
639 global_settings.loudness = restore[SOUND_LOUDNESS];
640 global_settings.bass_boost = restore[SOUND_SUPERBASS];
641#endif
642
462 643
463 if(save_config_buffer()) 644 if(save_config_buffer())
464 { 645 {
@@ -593,11 +774,66 @@ void settings_apply(void)
593 set_car_adapter_mode(global_settings.car_adapter_mode); 774 set_car_adapter_mode(global_settings.car_adapter_mode);
594} 775}
595 776
777
778/* helper to load global_settings from a bitfield, as described per table */
779static void load_bit_table(const struct bit_entry* p_table, int count, int bitstart)
780{
781 unsigned long* p_bitfield = (unsigned long*)config_block; /* 32 bit addr. */
782 unsigned long value; /* 32 bit content */
783 int i;
784 int maxbit; /* how many bits are valid in the saved part */
785 const struct bit_entry* p_run = p_table; /* start after the size info */
786 count--; /* first is excluded from loop */
787 maxbit = get_bits(p_bitfield, bitstart, p_table->bit_size);
788 bitstart += p_table->bit_size;
789
790 for (i=0; i<count; i++)
791 {
792 int size;
793 p_run++;
794
795 size = p_run->bit_size & 0x3F; /* mask off abused bits */
796 if (bitstart + size > maxbit)
797 break; /* exit if this is not valid any more in bitfield */
798
799 value = get_bits(p_bitfield, bitstart, size);
800 bitstart += size;
801 if (p_run->bit_size & SIGNED)
802 { // sign extend the read value
803 unsigned long mask = 0xFFFFFFFF << (size - 1);
804 if (value & mask) /* true if MSB of value is set */
805 value |= mask;
806 }
807
808 /* could do a memcpy, but that would be endian-dependent */
809 switch(p_run->byte_size)
810 {
811 case 1:
812 ((unsigned char*)&global_settings)[p_run->settings_offset] =
813 (unsigned char)value;
814 break;
815 case 2:
816 ((unsigned short*)&global_settings)[p_run->settings_offset/2] =
817 (unsigned short)value;
818 break;
819 case 4:
820 ((unsigned int*)&global_settings)[p_run->settings_offset/4] =
821 (unsigned int)value;
822 break;
823 default:
824 DEBUGF( "illegal size!" );
825 continue;
826 }
827 }
828}
829
830
596/* 831/*
597 * load settings from disk or RTC RAM 832 * load settings from disk or RTC RAM
598 */ 833 */
599void settings_load(void) 834void settings_load(void)
600{ 835{
836 int restore[6]; /* recover, FIXME: get rid of this */
601 837
602 DEBUGF( "reload_all_settings()\n" ); 838 DEBUGF( "reload_all_settings()\n" );
603 839
@@ -606,215 +842,53 @@ void settings_load(void)
606 842
607 /* load the buffer from the RTC (resets it to all-unused if the block 843 /* load the buffer from the RTC (resets it to all-unused if the block
608 is invalid) and decode the settings which are set in the block */ 844 is invalid) and decode the settings which are set in the block */
609 if (!load_config_buffer()) { 845 if (!load_config_buffer())
610 if (config_block[0x4] != 0xFF) 846 {
611 global_settings.volume = config_block[0x4]; 847 /* While the mpeg_val2phys business still exists: ( FIXME: to be removed) */
612 if (config_block[0x5] != 0xFF) 848 /* temporarily put markers into the values to detect if they got loaded */
613 global_settings.balance = (char)config_block[0x5]; 849 restore[SOUND_VOLUME] = global_settings.volume;
614 if (config_block[0x6] != 0xFF) 850 global_settings.volume = MARKER;
615 global_settings.bass = config_block[0x6]; 851 restore[SOUND_BASS] = global_settings.bass;
616 if (config_block[0x7] != 0xFF) 852 global_settings.bass = MARKER;
617 global_settings.treble = config_block[0x7]; 853 restore[SOUND_TREBLE] = global_settings.treble;
618 if (config_block[0x8] != 0xFF) 854 global_settings.treble = MARKER;
619 global_settings.loudness = config_block[0x8]; 855 restore[SOUND_BALANCE] = global_settings.balance;
620 if (config_block[0x9] != 0xFF) 856 global_settings.balance = MARKER;
621 global_settings.bass_boost = config_block[0x9]; 857#ifdef HAVE_MAS3587F
622 858 restore[SOUND_LOUDNESS] = global_settings.loudness;
623 if (config_block[0xa] != 0xFF) { 859 global_settings.loudness = MARKER;
624 global_settings.contrast = config_block[0xa] & 0x3f; 860 restore[SOUND_SUPERBASS] = global_settings.bass_boost;
625 global_settings.invert = 861 global_settings.bass_boost = MARKER;
626 config_block[0xa] & 0x40 ? true : false; 862#endif
627 if ( global_settings.contrast < MIN_CONTRAST_SETTING )
628 global_settings.contrast = lcd_default_contrast();
629 global_settings.show_icons =
630 config_block[0xa] & 0x80 ? true : false;
631 }
632
633 if (config_block[0xb] != 0xFF) {
634 /* Bit 7 is unused to be able to detect uninitialized entry */
635 global_settings.backlight_timeout = config_block[0xb] & 0x1f;
636 global_settings.invert_cursor =
637 config_block[0xb] & 0x20 ? true : false;
638 global_settings.backlight_on_when_charging =
639 config_block[0xb] & 0x40 ? true : false;
640 }
641
642 if (config_block[0xc] != 0xFF)
643 global_settings.poweroff = config_block[0xc];
644 if (config_block[0xd] != 0xFF)
645 global_settings.resume = config_block[0xd];
646 if (config_block[0xe] != 0xFF) {
647 global_settings.playlist_shuffle = config_block[0xe] & 1;
648 global_settings.dirfilter = (config_block[0xe] >> 1) & 1;
649 global_settings.sort_case = (config_block[0xe] >> 2) & 1;
650 global_settings.discharge = (config_block[0xe] >> 3) & 1;
651 global_settings.statusbar = (config_block[0xe] >> 4) & 1;
652 global_settings.dirfilter |= ((config_block[0xe] >> 5) & 1) << 1;
653 global_settings.scrollbar = (config_block[0xe] >> 6) & 1;
654 /* Don't use the last bit, it must be unused to detect
655 an uninitialized entry */
656 }
657 863
658 if (config_block[0xf] != 0xFF) { 864 /* load scalar values from RTC and HD sector, specified via table */
659 global_settings.volume_type = config_block[0xf] & 1; 865 load_bit_table(rtc_bits, sizeof(rtc_bits)/sizeof(rtc_bits[0]), 4*8);
660 global_settings.battery_type = (config_block[0xf] >> 1) & 1; 866 load_bit_table(hd_bits, sizeof(hd_bits)/sizeof(hd_bits[0]), RTC_BLOCK_SIZE*8);
661 global_settings.timeformat = (config_block[0xf] >> 2) & 1;
662 global_settings.scroll_speed = config_block[0xf] >> 3;
663 }
664
665 if (config_block[0x10] != 0xFF) {
666 global_settings.ff_rewind_min_step = (config_block[0x10] >> 4) & 15;
667 global_settings.ff_rewind_accel = config_block[0x10] & 15;
668 }
669
670 if (config_block[0x11] != 0xFF)
671 {
672 global_settings.avc = config_block[0x11] & 0x03;
673 global_settings.channel_config = (config_block[0x11] >> 2) & 0x07;
674 }
675
676 if (config_block[0x12] != 0xFF)
677 global_settings.resume_index = *((short*)(&config_block[0x12]));
678
679 if (config_block[0x14] != 0xFF)
680 global_settings.resume_first_index= *((short*)(&config_block[0x14]));
681
682 if (config_block[0x16] != 0xFF)
683 memcpy(&global_settings.resume_offset, &config_block[0x16], 4);
684
685 if (config_block[0x1a] != 0xFF)
686 global_settings.disk_spindown = config_block[0x1a];
687
688 if (config_block[0x1b] != 0xFF) {
689 global_settings.browse_current = (config_block[0x1b]) & 1;
690 global_settings.play_selected = (config_block[0x1b] >> 1) & 1;
691 global_settings.recursive_dir_insert =
692 (config_block[0x1b] >> 2) & 3;
693 }
694
695 if (config_block[0x1c] != 0xFF) {
696 global_settings.peak_meter_hold = (config_block[0x1c]) & 0x1f;
697 global_settings.flip_display =
698 (config_block[0x1c] & 0x40)?true:false;
699 global_settings.rec_editable =
700 (config_block[0x1c] & 0x80)?true:false;
701 }
702
703 if (config_block[0x1d] != 0xFF)
704 memcpy(&global_settings.resume_seed, &config_block[0x1d], 4);
705
706 if (config_block[0x21] != 0xFF)
707 {
708 global_settings.repeat_mode = config_block[0x21] & 3;
709 global_settings.rec_channels = (config_block[0x21] >> 2) & 1;
710 global_settings.rec_mic_gain = (config_block[0x21] >> 4) & 0x0f;
711 }
712
713 if (config_block[0x22] != 0xFF)
714 {
715 global_settings.rec_quality = config_block[0x22] & 7;
716 global_settings.rec_source = (config_block[0x22] >> 3) & 3;
717 global_settings.rec_frequency = (config_block[0x22] >> 5) & 7;
718 }
719
720 if (config_block[0x23] != 0xFF)
721 global_settings.rec_left_gain = config_block[0x23] & 0x0f;
722
723 if (config_block[0x24] != 0xFF)
724 global_settings.rec_right_gain = config_block[0x24] & 0x0f;
725
726 if (config_block[0x25] != 0xFF)
727 {
728 global_settings.disk_poweroff = config_block[0x25] & 1;
729 global_settings.buffer_margin = (config_block[0x25] >> 1) & 7;
730 global_settings.trickle_charge = (config_block[0x25] >> 4) & 1;
731 global_settings.buttonbar = (config_block[0x25] >> 5) & 1;
732 }
733
734 if (config_block[0x27] != 0xff)
735 global_settings.runtime =
736 config_block[0x26] | (config_block[0x27] << 8);
737
738 if (config_block[0x29] != 0xff)
739 global_settings.topruntime =
740 config_block[0x28] | (config_block[0x29] << 8);
741
742 if (config_block[0xae] != 0xff) {
743 global_settings.fade_on_stop = config_block[0xae] & 1;
744 global_settings.caption_backlight = (config_block[0xae] >> 1) & 1;
745 global_settings.car_adapter_mode = (config_block[0xae] >> 2) & 1;
746 global_settings.line_in = (config_block[0xae] >> 3) & 1;
747 global_settings.playlist_viewer_icons =
748 (config_block[0xae] >> 4) & 1;
749 global_settings.playlist_viewer_indices =
750 (config_block[0xae] >> 5) & 1;
751 global_settings.playlist_viewer_track_display =
752 (config_block[0xae] >> 6) & 1;
753 }
754
755 if(config_block[0xb0] != 0xff) {
756 global_settings.peak_meter_clip_hold = (config_block[0xb0]) & 0x1f;
757 global_settings.peak_meter_performance =
758 (config_block[0xb0] & 0x80) != 0;
759 }
760
761 if(config_block[0xb1] != 0xff) {
762 global_settings.peak_meter_release = config_block[0xb1] & 0x7f;
763 global_settings.peak_meter_dbfs = (config_block[0xb1] & 0x80) != 0;
764 }
765
766 if(config_block[0xb2] != 0xff)
767 global_settings.peak_meter_min = config_block[0xb2];
768 867
769 if(config_block[0xb3] != 0xff) 868 /* FIXME, to be removed with mpeg_val2phys: */
770 global_settings.peak_meter_max = config_block[0xb3]; 869 /* if a value got loaded, convert it, else restore it */
771 870 global_settings.volume = (global_settings.volume == MARKER) ?
772 if(config_block[0xb4] != 0xff) 871 restore[SOUND_VOLUME] : mpeg_phys2val(SOUND_VOLUME, global_settings.volume);
773 global_settings.battery_capacity = config_block[0xb4]*50 + 1000; 872 global_settings.bass = (global_settings.bass == MARKER) ?
774 873 restore[SOUND_BASS] : mpeg_phys2val(SOUND_BASS, global_settings.bass);
775 if (config_block[0xb5] != 0xff) 874 global_settings.treble = (global_settings.treble == MARKER) ?
776 global_settings.scroll_step = config_block[0xb5]; 875 restore[SOUND_TREBLE] : mpeg_phys2val(SOUND_TREBLE, global_settings.treble);
777 876 global_settings.balance = (global_settings.balance == MARKER) ?
778 if (config_block[0xb6] != 0xff) 877 restore[SOUND_BALANCE] : mpeg_phys2val(SOUND_BALANCE, global_settings.balance);
779 global_settings.scroll_delay = config_block[0xb6]; 878#ifdef HAVE_MAS3587F
780 879 global_settings.loudness = (global_settings.loudness == MARKER) ?
781 if (config_block[0xb7] != 0xff) 880 restore[SOUND_LOUDNESS] : mpeg_phys2val(SOUND_LOUDNESS, global_settings.loudness);
782 global_settings.bidir_limit = config_block[0xb7]; 881 global_settings.bass_boost = (global_settings.bass_boost == MARKER) ?
783 882 restore[SOUND_SUPERBASS] : mpeg_phys2val(SOUND_SUPERBASS, global_settings.bass_boost);
784 if (config_block[0xac] != 0xff) 883#endif
785 global_settings.max_files_in_dir =
786 config_block[0xac] | (config_block[0xad] << 8);
787 884
788 if (config_block[0xaa] != 0xff) 885 if ( global_settings.contrast < MIN_CONTRAST_SETTING )
789 global_settings.max_files_in_playlist = 886 global_settings.contrast = lcd_default_contrast();
790 config_block[0xaa] | (config_block[0xab] << 8);
791 887
792 strncpy(global_settings.wps_file, &config_block[0xb8], MAX_FILENAME); 888 strncpy(global_settings.wps_file, &config_block[0xb8], MAX_FILENAME);
793 strncpy(global_settings.lang_file, &config_block[0xcc], MAX_FILENAME); 889 strncpy(global_settings.lang_file, &config_block[0xcc], MAX_FILENAME);
794 strncpy(global_settings.font_file, &config_block[0xe0], MAX_FILENAME); 890 strncpy(global_settings.font_file, &config_block[0xe0], MAX_FILENAME);
795 891 }
796 if (config_block[0xf4] != 0xff) {
797 global_settings.rec_prerecord_time = config_block[0xf4] & 0x1f;
798 global_settings.rec_directory = (config_block[0xf4] >> 5) & 3;
799 }
800 if (config_block[0xf5] != 0xff) {
801 global_settings.talk_dir = config_block[0xf5] & 7;
802 global_settings.talk_file = (config_block[0xf5] >> 3) & 3;
803 global_settings.talk_menu = (config_block[0xf5] >> 5) & 1;
804 }
805
806#ifdef HAVE_LCD_CHARCELLS
807 if (config_block[0xa8] != 0xff)
808 global_settings.jump_scroll = config_block[0xa8];
809 if (config_block[0xa9] != 0xff)
810 global_settings.jump_scroll_delay = config_block[0xa9];
811#endif
812 if(config_block[0xaf] != 0xff) {
813 global_settings.usemrb = (config_block[0xaf] >> 5) & 3;
814 global_settings.autocreatebookmark = (config_block[0xaf] >> 2) & 7;
815 global_settings.autoloadbookmark = (config_block[0xaf]) & 3;
816 }
817 }
818 892
819 settings_apply(); 893 settings_apply();
820} 894}
@@ -882,94 +956,131 @@ void set_file(char* filename, char* setting, int maxlen)
882 settings_save(); 956 settings_save();
883} 957}
884 958
885static void set_sound(char* value, int type, int* setting) 959/* helper to sort a .cfg file entry into a global_settings member,
960 as described per table. Returns the position if found, else 0. */
961static int load_cfg_table(
962 const struct bit_entry* p_table, /* the table which describes the entries */
963 int count, /* number of entries in the table, including the first */
964 char* name, /* the item to be searched */
965 char* value, /* the value which got loaded for that item */
966 int hint) /* position to start looking */
886{ 967{
887 int num = atoi(value); 968 int i = hint;
888 969
889 num = mpeg_phys2val(type, num); 970 do
890
891 if ((num > mpeg_sound_max(type)) ||
892 (num < mpeg_sound_min(type)))
893 { 971 {
894 num = mpeg_sound_default(type); 972 if (p_table[i].cfg_name != NULL && !strcasecmp(name, p_table[i].cfg_name))
895 } 973 { /* found */
896 974 int val = 0;
897 *setting = num; 975 if (p_table[i].cfg_val == NULL)
898 mpeg_sound_set(type, num); 976 { /* numerical value, just convert the string */
899 977 val = atoi(value);
900#ifdef HAVE_MAS3507D 978 }
901 /* This is required to actually apply balance */ 979 else
902 if (SOUND_BALANCE == type) 980 { /* set of string values, find the index */
903 mpeg_sound_set(SOUND_VOLUME, global_settings.volume); 981 const char* item;
904#endif 982 const char* run;
905} 983 int len = strlen(value);
906 984
907static void set_cfg_bool(bool* variable, char* value) 985 item = run = p_table[i].cfg_val;
908{ 986
909 /* look for the 'n' in 'on' */ 987 while(1)
910 if ((value[1] & 0xdf) == 'N') 988 {
911 *variable = true; 989 /* count the length of the field */
912 else 990 while (*run != ',' && *run != '\0')
913 *variable = false; 991 run++;
914} 992
993 if (!strncasecmp(value, item, MAX(run-item, len)))
994 break; /* match, exit the search */
995
996 if (*run == '\0') /* reached the end of the choices */
997 return i; /* return the position, but don't update */
998
999 val++; /* count the item up */
1000 run++; /* behind the ',' */
1001 item = run;
1002 }
1003 }
1004
1005 /* could do a memcpy, but that would be endian-dependent */
1006 switch(p_table[i].byte_size)
1007 {
1008 case 1:
1009 ((unsigned char*)&global_settings)[p_table[i].settings_offset] =
1010 (unsigned char)val;
1011 break;
1012 case 2:
1013 ((unsigned short*)&global_settings)[p_table[i].settings_offset/2] =
1014 (unsigned short)val;
1015 break;
1016 case 4:
1017 ((unsigned int*)&global_settings)[p_table[i].settings_offset/4] =
1018 (unsigned int)val;
1019 break;
1020 default:
1021 DEBUGF( "illegal size!" );
1022 continue;
1023 }
915 1024
916static void set_cfg_int(int* variable, char* value, int min, int max ) 1025 return i; /* return the position */
917{ 1026 }
918 *variable = atoi(value);
919 1027
920 if (*variable < min) 1028 i++;
921 *variable = min; 1029 if (i==count)
922 else 1030 i=1; /* wraparound */
923 if (*variable > max) 1031 } while (i != hint); /* back where we started, all searched */
924 *variable = max; 1032
1033 return 0; /* indicate not found */
925} 1034}
926 1035
927static void set_cfg_option(int* variable, char* value,
928 char* options[], int numoptions )
929{
930 int i;
931
932 for (i=0; i<numoptions; i++) {
933 if (!strcasecmp(options[i], value)) {
934 *variable = i;
935 break;
936 }
937 }
938}
939 1036
940bool settings_load_config(char* file) 1037bool settings_load_config(char* file)
941{ 1038{
942 int fd; 1039 int fd;
943 char line[128]; 1040 char line[128];
1041 int restore[6]; /* recover, FIXME: get rid of this */
944 1042
945 fd = open(file, O_RDONLY); 1043 fd = open(file, O_RDONLY);
946 if (fd < 0) 1044 if (fd < 0)
947 return false; 1045 return false;
948 1046
1047
1048 /* While the mpeg_val2phys business still exists: ( to be removed) */
1049 /* temporarily put markers into the values to detect if they got loaded */
1050 restore[SOUND_VOLUME] = global_settings.volume;
1051 global_settings.volume = MARKER;
1052 restore[SOUND_BASS] = global_settings.bass;
1053 global_settings.bass = MARKER;
1054 restore[SOUND_TREBLE] = global_settings.treble;
1055 global_settings.treble = MARKER;
1056 restore[SOUND_BALANCE] = global_settings.balance;
1057 global_settings.balance = MARKER;
1058#ifdef HAVE_MAS3587F
1059 restore[SOUND_LOUDNESS] = global_settings.loudness;
1060 global_settings.loudness = MARKER;
1061 restore[SOUND_SUPERBASS] = global_settings.bass_boost;
1062 global_settings.bass_boost = MARKER;
1063#endif
1064
1065
949 while (read_line(fd, line, sizeof line) > 0) 1066 while (read_line(fd, line, sizeof line) > 0)
950 { 1067 {
951 char* name; 1068 char* name;
952 char* value; 1069 char* value;
1070 const struct bit_entry* table[2] = { rtc_bits, hd_bits };
1071 const int ta_size[2] = {
1072 sizeof(rtc_bits)/sizeof(rtc_bits[0]),
1073 sizeof(hd_bits)/sizeof(hd_bits[0])
1074 };
1075 int last_table = 0; /* which table was used last round */
1076 int last_pos = 1; /* at which position did we succeed */
1077 int pos; /* currently returned position */
953 1078
954 if (!settings_parseline(line, &name, &value)) 1079 if (!settings_parseline(line, &name, &value))
955 continue; 1080 continue;
956 1081
957 if (!strcasecmp(name, "volume")) 1082 /* check for the string values */
958 set_sound(value, SOUND_VOLUME, &global_settings.volume); 1083 if (!strcasecmp(name, "wps")) {
959 else if (!strcasecmp(name, "bass"))
960 set_sound(value, SOUND_BASS, &global_settings.bass);
961 else if (!strcasecmp(name, "treble"))
962 set_sound(value, SOUND_TREBLE, &global_settings.treble);
963 else if (!strcasecmp(name, "balance"))
964 set_sound(value, SOUND_BALANCE, &global_settings.balance);
965 else if (!strcasecmp(name, "channels")) {
966 static char* options[] = {
967 "stereo","stereo narrow","mono","mono left",
968 "mono right","karaoke","stereo wide"};
969 set_cfg_option(&global_settings.channel_config, value,
970 options, 7);
971 }
972 else if (!strcasecmp(name, "wps")) {
973 if (wps_load(value,false)) 1084 if (wps_load(value,false))
974 set_file(value, global_settings.wps_file, MAX_FILENAME); 1085 set_file(value, global_settings.wps_file, MAX_FILENAME);
975 } 1086 }
@@ -980,261 +1091,129 @@ bool settings_load_config(char* file)
980 talk_init(); /* use voice of same language */ 1091 talk_init(); /* use voice of same language */
981 } 1092 }
982 } 1093 }
983 else if (!strcasecmp(name, "bidir limit"))
984 set_cfg_int(&global_settings.bidir_limit, value, 0, 200);
985#ifdef HAVE_LCD_BITMAP 1094#ifdef HAVE_LCD_BITMAP
986 else if (!strcasecmp(name, "font")) { 1095 else if (!strcasecmp(name, "font")) {
987 if (font_load(value)) 1096 if (font_load(value))
988 set_file(value, global_settings.font_file, MAX_FILENAME); 1097 set_file(value, global_settings.font_file, MAX_FILENAME);
989 } 1098 }
990 else if (!strcasecmp(name, "scroll step"))
991 set_cfg_int(&global_settings.scroll_step, value, 1, LCD_WIDTH);
992 else if (!strcasecmp(name, "statusbar"))
993 set_cfg_bool(&global_settings.statusbar, value);
994 else if (!strcasecmp(name, "buttonbar"))
995 set_cfg_bool(&global_settings.buttonbar, value);
996 else if (!strcasecmp(name, "peak meter release"))
997 set_cfg_int(&global_settings.peak_meter_release, value, 1, 0x7e);
998 else if (!strcasecmp(name, "peak meter hold")) {
999 static char* options[] = {
1000 "off","200ms","300ms","500ms",
1001 "1","2","3","4","5","6","7","8","9","10",
1002 "15","20","30","1min"};
1003 set_cfg_option(&global_settings.peak_meter_hold, value,
1004 options, 18);
1005 }
1006 else if (!strcasecmp(name, "peak meter clip hold")) {
1007 static char* options[] = {
1008 "on","1","2","3","4","5","6","7","8","9","10",
1009 "15","20","25","30","45","60","90",
1010 "2min","3min","5min","10min","20min","45min","90min"};
1011 set_cfg_option(&global_settings.peak_meter_clip_hold, value,
1012 options, 25);
1013 }
1014 else if (!strcasecmp(name, "peak meter dbfs"))
1015 set_cfg_bool(&global_settings.peak_meter_dbfs, value);
1016 else if (!strcasecmp(name, "peak meter min"))
1017 set_cfg_int(&global_settings.peak_meter_min, value, 0, 100);
1018 else if (!strcasecmp(name, "peak meter max"))
1019 set_cfg_int(&global_settings.peak_meter_max, value, 0, 100);
1020 else if (!strcasecmp(name, "peak meter busy"))
1021 set_cfg_bool(&global_settings.peak_meter_performance, value);
1022 else if (!strcasecmp(name, "volume display")) {
1023 static char* options[] = {"graphic", "numeric"};
1024 set_cfg_option(&global_settings.volume_type, value, options, 2);
1025 }
1026 else if (!strcasecmp(name, "battery display")) {
1027 static char* options[] = {"graphic", "numeric"};
1028 set_cfg_option(&global_settings.battery_type, value, options, 2);
1029 }
1030 else if (!strcasecmp(name, "time format")) {
1031 static char* options[] = {"24hour", "12hour"};
1032 set_cfg_option(&global_settings.timeformat, value, options, 2);
1033 }
1034 else if (!strcasecmp(name, "scrollbar"))
1035 set_cfg_bool(&global_settings.scrollbar, value);
1036 else if (!strcasecmp(name, "invert"))
1037 set_cfg_bool(&global_settings.invert, value);
1038 else if (!strcasecmp(name, "flip display"))
1039 set_cfg_bool(&global_settings.flip_display, value);
1040 else if (!strcasecmp(name, "invert cursor"))
1041 set_cfg_bool(&global_settings.invert_cursor, value);
1042 else if (!strcasecmp(name, "show icons"))
1043 set_cfg_bool(&global_settings.show_icons, value);
1044#endif
1045 else if (!strcasecmp(name, "caption backlight"))
1046 set_cfg_bool(&global_settings.caption_backlight, value);
1047 else if (!strcasecmp(name, "shuffle"))
1048 set_cfg_bool(&global_settings.playlist_shuffle, value);
1049 else if (!strcasecmp(name, "repeat")) {
1050 static char* options[] = {"off", "all", "one"};
1051 set_cfg_option(&global_settings.repeat_mode, value, options, 3);
1052 }
1053 else if (!strcasecmp(name, "resume")) {
1054 static char* options[] = {"off", "ask", "ask once", "on"};
1055 set_cfg_option(&global_settings.resume, value, options, 4);
1056 }
1057 else if (!strcasecmp(name, "sort case"))
1058 set_cfg_bool(&global_settings.sort_case, value);
1059 else if (!strcasecmp(name, "show files")) {
1060 static char* options[] = {"all", "supported","music", "playlists"};
1061 set_cfg_option(&global_settings.dirfilter, value, options, 4);
1062 }
1063 else if (!strcasecmp(name, "follow playlist"))
1064 set_cfg_bool(&global_settings.browse_current, value);
1065 else if (!strcasecmp(name, "play selected"))
1066 set_cfg_bool(&global_settings.play_selected, value);
1067 else if (!strcasecmp(name, "contrast"))
1068 set_cfg_int(&global_settings.contrast, value,
1069 MIN_CONTRAST_SETTING, MAX_CONTRAST_SETTING);
1070 else if (!strcasecmp(name, "scroll speed"))
1071 set_cfg_int(&global_settings.scroll_speed, value, 1, 10);
1072 else if (!strcasecmp(name, "scan min step")) {
1073 static char* options[] =
1074 {"1","2","3","4","5","6","8","10",
1075 "15","20","25","30","45","60"};
1076 set_cfg_option(&global_settings.ff_rewind_min_step, value,
1077 options, 14);
1078 }
1079 else if (!strcasecmp(name, "scan accel"))
1080 set_cfg_int(&global_settings.ff_rewind_accel, value, 0, 15);
1081 else if (!strcasecmp(name, "scroll delay"))
1082 set_cfg_int(&global_settings.scroll_delay, value, 0, 250);
1083 else if (!strcasecmp(name, "backlight timeout")) {
1084 static char* options[] = {
1085 "off","on","1","2","3","4","5","6","7","8","9",
1086 "10","15","20","25","30","45","60","90"};
1087 set_cfg_option(&global_settings.backlight_timeout, value,
1088 options, 19);
1089 }
1090 else if (!strcasecmp(name, "backlight when plugged"))
1091 set_cfg_bool(&global_settings.backlight_on_when_charging, value);
1092 else if (!strcasecmp(name, "antiskip"))
1093 set_cfg_int(&global_settings.buffer_margin, value, 0, 7);
1094 else if (!strcasecmp(name, "disk spindown"))
1095 set_cfg_int(&global_settings.disk_spindown, value, 3, 254);
1096#ifdef HAVE_ATA_POWER_OFF
1097 else if (!strcasecmp(name, "disk poweroff"))
1098 set_cfg_bool(&global_settings.disk_poweroff, value);
1099#endif
1100#ifdef HAVE_MAS3587F
1101 else if (!strcasecmp(name, "loudness"))
1102 set_sound(value, SOUND_LOUDNESS, &global_settings.loudness);
1103 else if (!strcasecmp(name, "bass boost"))
1104 set_sound(value, SOUND_SUPERBASS, &global_settings.bass_boost);
1105 else if (!strcasecmp(name, "auto volume")) {
1106 static char* options[] = {"off", "2", "4", "8" };
1107 set_cfg_option(&global_settings.avc, value, options, 4);
1108 }
1109 else if (!strcasecmp(name, "rec mic gain"))
1110 set_sound(value, SOUND_MIC_GAIN, &global_settings.rec_mic_gain);
1111 else if (!strcasecmp(name, "rec left gain"))
1112 set_sound(value, SOUND_LEFT_GAIN, &global_settings.rec_left_gain);
1113 else if (!strcasecmp(name, "rec right gain"))
1114 set_sound(value, SOUND_RIGHT_GAIN, &global_settings.rec_right_gain);
1115 else if (!strcasecmp(name, "rec quality"))
1116 set_cfg_int(&global_settings.rec_quality, value, 0, 7);
1117 else if (!strcasecmp(name, "rec timesplit")){
1118 static char* options[] = {"off", "00:05","00:10","00:15",
1119 "00:30","01:00","02:00","04:00",
1120 "06:00","08:00","10:00","12:00",
1121 "18:00","24:00"};
1122 set_cfg_option(&global_settings.rec_timesplit, value,
1123 options, 14);
1124 }
1125 else if (!strcasecmp(name, "rec source")) {
1126 static char* options[] = {"mic", "line", "spdif"};
1127 set_cfg_option(&global_settings.rec_source, value, options, 3);
1128 }
1129 else if (!strcasecmp(name, "rec frequency")) {
1130 static char* options[] = {"44", "48", "32", "22", "24", "16"};
1131 set_cfg_option(&global_settings.rec_frequency, value, options, 6);
1132 }
1133 else if (!strcasecmp(name, "rec channels")) {
1134 static char* options[] = {"stereo", "mono"};
1135 set_cfg_option(&global_settings.rec_channels, value, options, 2);
1136 }
1137 else if (!strcasecmp(name, "editable recordings")) {
1138 set_cfg_bool(&global_settings.rec_editable, value);
1139 }
1140 else if (!strcasecmp(name, "prerecording time")) {
1141 set_cfg_int(&global_settings.rec_prerecord_time, value, 0, 30);
1142 }
1143 else if (!strcasecmp(name, "rec directory")) {
1144 static char* options[] = {rec_base_directory, "current"};
1145 set_cfg_option(&global_settings.rec_directory, value, options, 2);
1146 }
1147#endif
1148 else if (!strcasecmp(name, "idle poweroff")) {
1149 static char* options[] = {"off","1","2","3","4","5","6","7","8",
1150 "9","10","15","30","45","60"};
1151 set_cfg_option(&global_settings.poweroff, value, options, 15);
1152 }
1153#ifdef HAVE_MAS3507D
1154 else if (!strcasecmp(name, "line in")){
1155 set_cfg_bool(&global_settings.line_in, value);
1156 dac_line_in(global_settings.line_in);
1157 }
1158#endif
1159 else if (!strcasecmp(name, "battery capacity"))
1160 set_cfg_int(&global_settings.battery_capacity, value,
1161 1500, BATTERY_CAPACITY_MAX);
1162#ifdef HAVE_CHARGE_CTRL
1163 else if (!strcasecmp(name, "deep discharge"))
1164 set_cfg_bool(&global_settings.discharge, value);
1165 else if (!strcasecmp(name, "trickle charge"))
1166 set_cfg_bool(&global_settings.trickle_charge, value);
1167#endif 1099#endif
1168 else if (!strcasecmp(name, "volume fade")) 1100
1169 set_cfg_bool(&global_settings.fade_on_stop, value); 1101 /* check for scalar values, using the two tables */
1170 else if (!strcasecmp(name, "max files in dir")) 1102 pos = load_cfg_table(table[last_table], ta_size[last_table],
1171 set_cfg_int(&global_settings.max_files_in_dir, value, 1103 name, value, last_pos);
1172 50, 10000); 1104 if (pos) /* success */
1173 else if (!strcasecmp(name, "max files in playlist"))
1174 set_cfg_int(&global_settings.max_files_in_playlist, value,
1175 1000, 20000);
1176 else if (!strcasecmp(name, "car adapter mode"))
1177 set_cfg_bool(&global_settings.car_adapter_mode, value);
1178 else if (!strcasecmp(name, "recursive directory insert")) {
1179 static char* options[] = {"off", "on", "ask"};
1180 set_cfg_option(&global_settings.recursive_dir_insert, value,
1181 options, 3);
1182 }
1183 else if (!strcasecmp(name, "autoload bookmarks"))
1184 {
1185 static char* options[] = {"off", "on", "ask"};
1186 set_cfg_option(&global_settings.autoloadbookmark, value, options, 3);
1187 }
1188 else if (!strcasecmp(name, "autocreate bookmarks"))
1189 {
1190 static char* options[] = {"off", "on", "ask","recent only - on", "recent only - ask"};
1191 set_cfg_option(&global_settings.autocreatebookmark, value, options, 5);
1192 }
1193 else if (!strcasecmp(name, "use most-recent-bookmarks"))
1194 { 1105 {
1195 static char* options[] = {"off", "on", "unique only"}; 1106 last_pos = pos; /* remember as a position hint for next round */
1196 set_cfg_option(&global_settings.usemrb, value, options, 3); 1107 continue;
1197 } 1108 }
1198 else if (!strcasecmp(name, "playlist viewer icons")) 1109
1199 set_cfg_bool(&global_settings.playlist_viewer_icons, value); 1110 last_table = 1-last_table; /* try other table */
1200 else if (!strcasecmp(name, "playlist viewer indices")) 1111 last_pos = 1; /* search from start */
1201 set_cfg_bool(&global_settings.playlist_viewer_indices, value); 1112 pos = load_cfg_table(table[last_table], ta_size[last_table],
1202 else if (!strcasecmp(name, "playlist viewer track display")) 1113 name, value, last_pos);
1114 if (pos) /* success */
1203 { 1115 {
1204 static char* options[] = {"track name", "full path"}; 1116 last_pos = pos; /* remember as a position hint for next round */
1205 set_cfg_option(&global_settings.playlist_viewer_track_display, 1117 continue;
1206 value, options, 2);
1207 } 1118 }
1208 else if (!strcasecmp(name, "talk dir")) 1119 }
1120
1121 /* FIXME, to be removed with mpeg_val2phys: */
1122 /* if a value got loaded, convert it, else restore it */
1123 global_settings.volume = (global_settings.volume == MARKER) ?
1124 restore[SOUND_VOLUME] : mpeg_phys2val(SOUND_VOLUME, global_settings.volume);
1125 global_settings.bass = (global_settings.bass == MARKER) ?
1126 restore[SOUND_BASS] : mpeg_phys2val(SOUND_BASS, global_settings.bass);
1127 global_settings.treble = (global_settings.treble == MARKER) ?
1128 restore[SOUND_TREBLE] : mpeg_phys2val(SOUND_TREBLE, global_settings.treble);
1129 global_settings.balance = (global_settings.balance == MARKER) ?
1130 restore[SOUND_BALANCE] : mpeg_phys2val(SOUND_BALANCE, global_settings.balance);
1131#ifdef HAVE_MAS3587F
1132 global_settings.loudness = (global_settings.loudness == MARKER) ?
1133 restore[SOUND_LOUDNESS] : mpeg_phys2val(SOUND_LOUDNESS, global_settings.loudness);
1134 global_settings.bass_boost = (global_settings.bass_boost == MARKER) ?
1135 restore[SOUND_SUPERBASS] : mpeg_phys2val(SOUND_SUPERBASS, global_settings.bass_boost);
1136#endif
1137
1138 close(fd);
1139 settings_apply();
1140 settings_save();
1141 return true;
1142}
1143
1144
1145/* helper to save content of global_settings into a file,
1146 as described per table */
1147static void save_cfg_table(const struct bit_entry* p_table, int count, int fd)
1148{
1149 long value; /* 32 bit content */
1150 int i;
1151 const struct bit_entry* p_run = p_table; /* start after the size info */
1152 count--; /* first is excluded from loop */
1153
1154 for (i=0; i<count; i++)
1155 {
1156 p_run++;
1157
1158 if (p_run->cfg_name == NULL)
1159 continue; /* this value is not to be saved */
1160
1161 /* could do a memcpy, but that would be endian-dependent */
1162 switch(p_run->byte_size)
1209 { 1163 {
1210 static char* options[] = {"off", "number", "spell", "enter", "hover"}; 1164 case 1:
1211 set_cfg_option(&global_settings.talk_dir, value, options, 5); 1165 if (p_run->bit_size & SIGNED) /* signed? */
1166 value = ((char*)&global_settings)[p_run->settings_offset];
1167 else
1168 value = ((unsigned char*)&global_settings)[p_run->settings_offset];
1169 break;
1170 case 2:
1171 if (p_run->bit_size & SIGNED) /* signed? */
1172 value = ((short*)&global_settings)[p_run->settings_offset/2];
1173 else
1174 value = ((unsigned short*)&global_settings)[p_run->settings_offset/2];
1175 break;
1176 case 4:
1177 value = ((unsigned int*)&global_settings)[p_run->settings_offset/4];
1178 break;
1179 default:
1180 DEBUGF( "illegal size!" );
1181 continue;
1212 } 1182 }
1213 else if (!strcasecmp(name, "talk file")) 1183
1184 if (p_run->cfg_val == NULL) /* write as number */
1214 { 1185 {
1215 static char* options[] = {"off", "number", "spell"}; 1186 fprintf(fd, "%s: %d\r\n", p_run->cfg_name, value);
1216 set_cfg_option(&global_settings.talk_file, value, options, 3);
1217 } 1187 }
1218 else if (!strcasecmp(name, "talk menu")) 1188 else /* write as item */
1219 { 1189 {
1220 set_cfg_bool(&global_settings.talk_menu, value); 1190 const char* p = p_run->cfg_val;
1191
1192 fprintf(fd, "%s: ", p_run->cfg_name);
1193
1194 while(value >= 0)
1195 {
1196 char c = *p++; /* currently processed char */
1197 if (c == ',') /* separator */
1198 value--;
1199 else if (c == '\0') /* end of string */
1200 break; /* not found */
1201 else if (value == 0) /* the right place */
1202 write(fd, &c, 1); /* char by char, this is lame, OK */
1203 }
1204
1205 fprintf(fd, "\r\n");
1221 } 1206 }
1222 } 1207 }
1223
1224 close(fd);
1225 settings_apply();
1226 settings_save();
1227 return true;
1228} 1208}
1229 1209
1230 1210
1231bool settings_save_config(void) 1211bool settings_save_config(void)
1232{ 1212{
1233 bool done = false; 1213 bool done = false;
1234 int fd, i, value; 1214 int fd, i;
1235 char filename[MAX_PATH]; 1215 char filename[MAX_PATH];
1236 char* boolopt[] = {"off","on"}; 1216 int restore[6]; /* recover, FIXME: get rid of this */
1237 char* triopt[] = {"off","on","ask"};
1238 1217
1239 /* find unused filename */ 1218 /* find unused filename */
1240 for (i=0; ; i++) { 1219 for (i=0; ; i++) {
@@ -1248,6 +1227,9 @@ bool settings_save_config(void)
1248 /* allow user to modify filename */ 1227 /* allow user to modify filename */
1249 while (!done) { 1228 while (!done) {
1250 if (!kbd_input(filename, sizeof filename)) { 1229 if (!kbd_input(filename, sizeof filename)) {
1230#ifdef WIN32 /* test hack !!! */
1231 strcpy(filename, "C:/test.cfg");
1232#endif
1251 fd = creat(filename,0); 1233 fd = creat(filename,0);
1252 if (fd < 0) { 1234 if (fd < 0) {
1253 lcd_clear_display(); 1235 lcd_clear_display();
@@ -1289,293 +1271,37 @@ bool settings_save_config(void)
1289 global_settings.font_file); 1271 global_settings.font_file);
1290#endif 1272#endif
1291 1273
1292 fprintf(fd, "#\r\n# Sound settings\r\n#\r\n"); 1274 /* FIXME: While the mpeg_val2phys business still exists: ( to be removed) */
1293 1275 /* temporarily replace the hardware levels with the MMI values */
1294 value = mpeg_val2phys(SOUND_VOLUME, global_settings.volume); 1276 restore[SOUND_VOLUME] = global_settings.volume;
1295 fprintf(fd, "volume: %d\r\n", value); 1277 global_settings.volume = mpeg_val2phys(SOUND_VOLUME, global_settings.volume);
1296 1278 restore[SOUND_BASS] = global_settings.bass;
1297 value = mpeg_val2phys(SOUND_BASS, global_settings.bass); 1279 global_settings.bass = mpeg_val2phys(SOUND_BASS, global_settings.bass);
1298 fprintf(fd, "bass: %d\r\n", value); 1280 restore[SOUND_TREBLE] = global_settings.treble;
1299 1281 global_settings.treble = mpeg_val2phys(SOUND_TREBLE, global_settings.treble);
1300 value = mpeg_val2phys(SOUND_TREBLE, global_settings.treble); 1282 restore[SOUND_BALANCE] = global_settings.balance;
1301 fprintf(fd, "treble: %d\r\n", value); 1283 global_settings.balance = mpeg_val2phys(SOUND_BALANCE, global_settings.balance);
1302
1303 value = mpeg_val2phys(SOUND_BALANCE, global_settings.balance);
1304 fprintf(fd, "balance: %d\r\n", value);
1305
1306 {
1307 static char* options[] =
1308 {"stereo","stereo narrow","mono","mono left",
1309 "mono right","karaoke","stereo wide"};
1310 fprintf(fd, "channels: %s\r\n",
1311 options[global_settings.channel_config]);
1312 }
1313
1314#ifdef HAVE_MAS3587F 1284#ifdef HAVE_MAS3587F
1315 value = mpeg_val2phys(SOUND_LOUDNESS, global_settings.loudness); 1285 restore[SOUND_LOUDNESS] = global_settings.loudness;
1316 fprintf(fd, "loudness: %d\r\n", value); 1286 global_settings.loudness = mpeg_val2phys(SOUND_LOUDNESS, global_settings.loudness);
1317 1287 restore[SOUND_SUPERBASS] = global_settings.bass_boost;
1318 value = mpeg_val2phys(SOUND_SUPERBASS, global_settings.bass_boost); 1288 global_settings.bass_boost = mpeg_val2phys(SOUND_SUPERBASS, global_settings.bass_boost);
1319 fprintf(fd, "bass boost: %d\r\n", value);
1320
1321 {
1322 static char* options[] = {"off", "2", "4", "8" };
1323 fprintf(fd, "auto volume: %s\r\n", options[global_settings.avc]);
1324 }
1325#endif 1289#endif
1326
1327 fprintf(fd, "#\r\n# Playback\r\n#\r\n");
1328 fprintf(fd, "shuffle: %s\r\n", boolopt[global_settings.playlist_shuffle]);
1329
1330 {
1331 static char* options[] = {"off", "all", "one"};
1332 fprintf(fd, "repeat: %s\r\n", options[global_settings.repeat_mode]);
1333 }
1334
1335 fprintf(fd, "play selected: %s\r\n",
1336 boolopt[global_settings.play_selected]);
1337
1338 {
1339 static char* options[] = {"off", "ask", "ask once", "on"};
1340 fprintf(fd, "resume: %s\r\n", options[global_settings.resume]);
1341 }
1342
1343 {
1344 static char* options[] =
1345 {"1","2","3","4","5","6","8","10",
1346 "15","20","25","30","45","60"};
1347 fprintf(fd, "scan min step: %s\r\n",
1348 options[global_settings.ff_rewind_min_step]);
1349 }
1350
1351 fprintf(fd, "scan accel: %d\r\nantiskip: %d\r\n",
1352 global_settings.ff_rewind_accel,
1353 global_settings.buffer_margin);
1354 fprintf(fd, "volume fade: %s\r\n", boolopt[global_settings.fade_on_stop]);
1355 fprintf(fd, "#\r\n# File View\r\n#\r\n");
1356 fprintf(fd, "sort case: %s\r\n", boolopt[global_settings.sort_case]);
1357
1358 {
1359 static char* options[] = {"all", "supported","music", "playlists"};
1360 fprintf(fd, "show files: %s\r\n", options[global_settings.dirfilter]);
1361 }
1362
1363 fprintf(fd, "follow playlist: %s\r\n",
1364 boolopt[global_settings.browse_current]);
1365
1366 fprintf(fd, "#\r\n# Display\r\n#\r\n");
1367
1368#ifdef HAVE_LCD_BITMAP
1369 fprintf(fd, "statusbar: %s\r\nbuttonbar: %s\r\nscrollbar: %s\r\n",
1370 boolopt[global_settings.statusbar],
1371 boolopt[global_settings.buttonbar],
1372 boolopt[global_settings.scrollbar]);
1373
1374 {
1375 static char* options[] = {"graphic", "numeric"};
1376 fprintf(fd, "volume display: %s\r\nbattery display: %s\r\n",
1377 options[global_settings.volume_type],
1378 options[global_settings.battery_type]);
1379 }
1380#endif
1381
1382 fprintf(fd, "scroll speed: %d\r\nscroll delay: %d\r\n",
1383 global_settings.scroll_speed,
1384 global_settings.scroll_delay);
1385
1386#ifdef HAVE_LCD_BITMAP
1387 fprintf(fd, "scroll step: %d\r\n", global_settings.scroll_step);
1388#else
1389 fprintf(fd, "jump scroll: %d\r\n", global_settings.jump_scroll);
1390 fprintf(fd, "jump scroll delay: %d\r\n", global_settings.jump_scroll_delay);
1391#endif
1392
1393 fprintf(fd, "bidir limit: %d\r\n", global_settings.bidir_limit);
1394
1395 {
1396 static char* options[] =
1397 {"off","on","1","2","3","4","5","6","7","8","9",
1398 "10","15","20","25","30","45","60","90"};
1399 fprintf(fd, "backlight timeout: %s\r\n",
1400 options[global_settings.backlight_timeout]);
1401 }
1402
1403 fprintf(fd, "backlight when plugged: %s\r\n",
1404 boolopt[global_settings.backlight_on_when_charging]);
1405
1406 fprintf(fd, "caption backlight: %s\r\n",
1407 boolopt[global_settings.caption_backlight]);
1408 fprintf(fd, "contrast: %d\r\n", global_settings.contrast);
1409
1410#ifdef HAVE_LCD_BITMAP
1411 fprintf(fd, "invert: %s\r\n", boolopt[global_settings.invert]);
1412
1413 fprintf(fd, "flip display: %s\r\n", boolopt[global_settings.flip_display]);
1414
1415 fprintf(fd, "invert cursor: %s\r\n",
1416 boolopt[global_settings.invert_cursor]);
1417
1418 fprintf(fd, "show icons: %s\r\n",
1419 boolopt[global_settings.show_icons]);
1420
1421 fprintf(fd, "peak meter release: %d\r\n",
1422 global_settings.peak_meter_release);
1423
1424 {
1425 static char* options[] =
1426 {"off","200ms","300ms","500ms","1","2","3","4","5",
1427 "6","7","8","9","10","15","20","30","1min"};
1428 fprintf(fd, "peak meter hold: %s\r\n",
1429 options[global_settings.peak_meter_hold]);
1430 }
1431
1432 {
1433 static char* options[] =
1434 {"on","1","2","3","4","5","6","7","8","9","10","15","20","25","30",
1435 "45","60","90","2min","3min","5min","10min","20min","45min","90min"};
1436 fprintf(fd, "peak meter clip hold: %s\r\n",
1437 options[global_settings.peak_meter_clip_hold]);
1438 }
1439
1440 fprintf(fd, "peak meter busy: %s\r\npeak meter dbfs: %s\r\n",
1441 boolopt[global_settings.peak_meter_performance],
1442 boolopt[global_settings.peak_meter_dbfs]);
1443
1444 fprintf(fd, "peak meter min: %d\r\npeak meter max: %d\r\n",
1445 global_settings.peak_meter_min,
1446 global_settings.peak_meter_max);
1447#endif
1448
1449 fprintf(fd, "#\r\n# System\r\n#\r\ndisk spindown: %d\r\n",
1450 global_settings.disk_spindown);
1451
1452#ifdef HAVE_ATA_POWER_OFF
1453 fprintf(fd, "disk poweroff: %s\r\n",
1454 boolopt[global_settings.disk_poweroff]);
1455#endif
1456
1457 fprintf(fd, "battery capacity: %d\r\n", global_settings.battery_capacity);
1458
1459#ifdef HAVE_CHARGE_CTRL
1460 fprintf(fd, "deep discharge: %s\r\ntrickle charge: %s\r\n",
1461 boolopt[global_settings.discharge],
1462 boolopt[global_settings.trickle_charge]);
1463#endif
1464
1465#ifdef HAVE_LCD_BITMAP
1466 {
1467 static char* options[] = {"24hour", "12hour"};
1468 fprintf(fd, "time format: %s\r\n",
1469 options[global_settings.timeformat]);
1470 }
1471#endif
1472
1473 {
1474 static char* options[] =
1475 {"off","1","2","3","4","5","6","7","8",
1476 "9","10","15","30","45","60"};
1477 fprintf(fd, "idle poweroff: %s\r\n",
1478 options[global_settings.poweroff]);
1479 }
1480
1481 fprintf(fd, "car adapter mode: %s\r\n",
1482 boolopt[global_settings.car_adapter_mode]);
1483
1484#ifdef HAVE_MAS3507D
1485 fprintf(fd, "line in: %s\r\n", boolopt[global_settings.line_in]);
1486#endif
1487
1488 fprintf(fd, "max files in dir: %d\r\n", global_settings.max_files_in_dir);
1489 fprintf(fd, "max files in playlist: %d\r\n",
1490 global_settings.max_files_in_playlist);
1491 1290
1291 /* here's the action: write values to file, specified via table */
1292 save_cfg_table(rtc_bits, sizeof(rtc_bits)/sizeof(rtc_bits[0]), fd);
1293 save_cfg_table(hd_bits, sizeof(hd_bits)/sizeof(hd_bits[0]), fd);
1294
1295 /* FIXME to be removed with mpeg_val2phys: restore the original values */
1296 global_settings.volume = restore[SOUND_VOLUME];
1297 global_settings.bass = restore[SOUND_BASS];
1298 global_settings.treble = restore[SOUND_TREBLE];
1299 global_settings.balance = restore[SOUND_BALANCE];
1492#ifdef HAVE_MAS3587F 1300#ifdef HAVE_MAS3587F
1493 fprintf(fd, "#\r\n# Recording\r\n#\r\n"); 1301 global_settings.loudness = restore[SOUND_LOUDNESS];
1494 fprintf(fd, "rec quality: %d\r\n", global_settings.rec_quality); 1302 global_settings.bass_boost = restore[SOUND_SUPERBASS];
1495
1496 {
1497 static char* options[] = {"44", "48", "32", "22", "24", "16"};
1498 fprintf(fd, "rec frequency: %s\r\n",
1499 options[global_settings.rec_frequency]);
1500 }
1501
1502 {
1503 static char* options[] = {"mic", "line", "spdif"};
1504 fprintf(fd, "rec source: %s\r\n", options[global_settings.rec_source]);
1505 }
1506
1507 {
1508 static char* options[] = {"stereo", "mono"};
1509 fprintf(fd, "rec channels: %s\r\n",
1510 options[global_settings.rec_channels]);
1511 }
1512
1513 fprintf(fd,
1514 "rec mic gain: %d\r\nrec left gain: %d\r\nrec right gain: %d\r\n",
1515 global_settings.rec_mic_gain,
1516 global_settings.rec_left_gain,
1517 global_settings.rec_right_gain);
1518
1519 fprintf(fd, "editable recordings: %s\r\n",
1520 boolopt[global_settings.rec_editable]);
1521
1522 fprintf(fd, "prerecording time: %d\r\n",
1523 global_settings.rec_prerecord_time);
1524
1525 {
1526 static char* options[] = {rec_base_directory, "current"};
1527 fprintf(fd, "rec directory: %s\r\n",
1528 options[global_settings.rec_directory]);
1529 }
1530
1531#endif 1303#endif
1532 1304
1533 fprintf(fd, "#\r\n# Bookmarking\r\n#\r\n");
1534 {
1535 fprintf(fd, "autoload bookmarks: %s\r\n",
1536 triopt[global_settings.autoloadbookmark]);
1537 }
1538
1539 {
1540 static char* options[] = {"off", "on", "ask","recent only - on", "recent only - ask"};
1541 fprintf(fd, "autocreate bookmarks: %s\r\n",
1542 options[global_settings.autocreatebookmark]);
1543 }
1544
1545 {
1546 static char* options[] = {"off", "on", "unique only"};
1547 fprintf(fd, "use most-recent-bookmarks: %s\r\n", options[global_settings.usemrb]);
1548 }
1549
1550 fprintf(fd, "#\r\n# Playlists\r\n#\r\n");
1551 {
1552 fprintf(fd, "recursive directory insert: %s\r\n",
1553 triopt[global_settings.recursive_dir_insert]);
1554 }
1555
1556 fprintf(fd, "#\r\n# Playlist viewer\r\n#\r\n");
1557 {
1558 fprintf(fd, "playlist viewer icons: %s\r\n",
1559 boolopt[global_settings.playlist_viewer_icons]);
1560 fprintf(fd, "playlist viewer indices: %s\r\n",
1561 boolopt[global_settings.playlist_viewer_indices]);
1562 {
1563 static char* options[] = {"track name", "full path"};
1564 fprintf(fd, "playlist viewer track display: %s\r\n",
1565 options[global_settings.playlist_viewer_track_display]);
1566 }
1567 }
1568 fprintf(fd, "#\r\n# Voice\r\n#\r\n");
1569 {
1570 static char* options[] = {"off", "number", "spell", "enter", "hover"};
1571 fprintf(fd, "talk dir: %s\r\n",
1572 options[global_settings.talk_dir]);
1573 fprintf(fd, "talk file: %s\r\n", /* recycle the options, */
1574 options[global_settings.talk_file]); /* first 3 are alike */
1575 fprintf(fd, "talk menu: %s\r\n",
1576 boolopt[global_settings.talk_menu]);
1577 }
1578
1579 close(fd); 1305 close(fd);
1580 1306
1581 lcd_clear_display(); 1307 lcd_clear_display();
@@ -1586,6 +1312,37 @@ bool settings_save_config(void)
1586 return true; 1312 return true;
1587} 1313}
1588 1314
1315
1316/* helper to load defaults from table into global_settings members */
1317static void default_table(const struct bit_entry* p_table, int count)
1318{
1319 int i;
1320
1321 for (i=1; i<count; i++) /* exclude the first, the size placeholder */
1322 {
1323 /* could do a memcpy, but that would be endian-dependent */
1324 switch(p_table[i].byte_size)
1325 {
1326 case 1:
1327 ((unsigned char*)&global_settings)[p_table[i].settings_offset] =
1328 (unsigned char)p_table[i].default_val;
1329 break;
1330 case 2:
1331 ((unsigned short*)&global_settings)[p_table[i].settings_offset/2] =
1332 (unsigned short)p_table[i].default_val;
1333 break;
1334 case 4:
1335 ((unsigned int*)&global_settings)[p_table[i].settings_offset/4] =
1336 (unsigned int)p_table[i].default_val;
1337 break;
1338 default:
1339 DEBUGF( "illegal size!" );
1340 continue;
1341 }
1342 }
1343}
1344
1345
1589/* 1346/*
1590 * reset all settings to their default value 1347 * reset all settings to their default value
1591 */ 1348 */
@@ -1593,6 +1350,11 @@ void settings_reset(void) {
1593 1350
1594 DEBUGF( "settings_reset()\n" ); 1351 DEBUGF( "settings_reset()\n" );
1595 1352
1353 /* read defaults from table(s) into global_settings */
1354 default_table(rtc_bits, sizeof(rtc_bits)/sizeof(rtc_bits[0]));
1355 default_table(hd_bits, sizeof(hd_bits)/sizeof(hd_bits[0]));
1356
1357 /* do some special cases not covered by table */
1596 global_settings.volume = mpeg_sound_default(SOUND_VOLUME); 1358 global_settings.volume = mpeg_sound_default(SOUND_VOLUME);
1597 global_settings.balance = mpeg_sound_default(SOUND_BALANCE); 1359 global_settings.balance = mpeg_sound_default(SOUND_BALANCE);
1598 global_settings.bass = mpeg_sound_default(SOUND_BASS); 1360 global_settings.bass = mpeg_sound_default(SOUND_BASS);
@@ -1601,91 +1363,11 @@ void settings_reset(void) {
1601 global_settings.bass_boost = mpeg_sound_default(SOUND_SUPERBASS); 1363 global_settings.bass_boost = mpeg_sound_default(SOUND_SUPERBASS);
1602 global_settings.avc = mpeg_sound_default(SOUND_AVC); 1364 global_settings.avc = mpeg_sound_default(SOUND_AVC);
1603 global_settings.channel_config = mpeg_sound_default(SOUND_CHANNELS); 1365 global_settings.channel_config = mpeg_sound_default(SOUND_CHANNELS);
1604 global_settings.rec_quality = 5;
1605 global_settings.rec_source = 0; /* 0=mic */
1606 global_settings.rec_frequency = 0; /* 0=44.1kHz */
1607 global_settings.rec_channels = 0; /* 0=Stereo */
1608 global_settings.rec_mic_gain = 8;
1609 global_settings.rec_left_gain = 2; /* 0dB */
1610 global_settings.rec_right_gain = 2; /* 0dB */
1611 global_settings.rec_editable = false;
1612 global_settings.rec_prerecord_time = 0;
1613 global_settings.rec_directory = 0; /* rec_base_directory */
1614 global_settings.resume = RESUME_ASK;
1615 global_settings.contrast = lcd_default_contrast(); 1366 global_settings.contrast = lcd_default_contrast();
1616 global_settings.invert = DEFAULT_INVERT_SETTING; 1367 global_settings.wps_file[0] = '\0';
1617 global_settings.flip_display= false; 1368 global_settings.font_file[0] = '\0';
1618 global_settings.poweroff = DEFAULT_POWEROFF_SETTING; 1369 global_settings.lang_file[0] = '\0';
1619 global_settings.backlight_timeout = DEFAULT_BACKLIGHT_TIMEOUT_SETTING; 1370
1620 global_settings.invert_cursor = DEFAULT_INVERT_CURSOR_SETTING;
1621 global_settings.backlight_on_when_charging =
1622 DEFAULT_BACKLIGHT_ON_WHEN_CHARGING_SETTING;
1623#ifdef HAVE_LIION
1624 global_settings.battery_capacity = 2200; /* mAh */
1625#else
1626 global_settings.battery_capacity = 1500; /* mAh */
1627#endif
1628 global_settings.trickle_charge = true;
1629 global_settings.dirfilter = SHOW_MUSIC;
1630 global_settings.sort_case = false;
1631 global_settings.statusbar = true;
1632 global_settings.buttonbar = true;
1633 global_settings.scrollbar = true;
1634 global_settings.repeat_mode = REPEAT_ALL;
1635 global_settings.playlist_shuffle = false;
1636 global_settings.discharge = 0;
1637 global_settings.timeformat = 0;
1638 global_settings.volume_type = 0;
1639 global_settings.battery_type = 0;
1640 global_settings.scroll_speed = 8;
1641 global_settings.bidir_limit = 50;
1642#ifdef HAVE_LCD_CHARCELLS
1643 global_settings.jump_scroll = 0;
1644 global_settings.jump_scroll_delay = 50;
1645#endif
1646 global_settings.scroll_delay = 100;
1647 global_settings.scroll_step = 6;
1648 global_settings.ff_rewind_min_step = DEFAULT_FF_REWIND_MIN_STEP;
1649 global_settings.ff_rewind_accel = DEFAULT_FF_REWIND_ACCEL_SETTING;
1650 global_settings.resume_index = -1;
1651 global_settings.resume_first_index = 0;
1652 global_settings.resume_offset = -1;
1653 global_settings.resume_seed = -1;
1654 global_settings.disk_spindown = 5;
1655 global_settings.disk_poweroff = false;
1656 global_settings.buffer_margin = 0;
1657 global_settings.browse_current = false;
1658 global_settings.play_selected = true;
1659 global_settings.peak_meter_release = 8;
1660 global_settings.peak_meter_hold = 3;
1661 global_settings.peak_meter_clip_hold = 16;
1662 global_settings.peak_meter_dbfs = true;
1663 global_settings.peak_meter_min = 60;
1664 global_settings.peak_meter_max = 0;
1665 global_settings.peak_meter_performance = false;
1666 global_settings.wps_file[0] = 0;
1667 global_settings.font_file[0] = 0;
1668 global_settings.lang_file[0] = 0;
1669 global_settings.runtime = 0;
1670 global_settings.topruntime = 0;
1671 global_settings.autocreatebookmark = BOOKMARK_NO;
1672 global_settings.autoloadbookmark = BOOKMARK_NO;
1673 global_settings.usemrb = BOOKMARK_NO;
1674 global_settings.fade_on_stop = true;
1675 global_settings.caption_backlight = false;
1676 global_settings.car_adapter_mode = false;
1677 global_settings.max_files_in_dir = 400;
1678 global_settings.max_files_in_playlist = 10000;
1679 global_settings.show_icons = true;
1680 global_settings.recursive_dir_insert = RECURSE_OFF;
1681 global_settings.line_in = false;
1682 global_settings.playlist_viewer_icons = true;
1683 global_settings.playlist_viewer_indices = true;
1684 global_settings.playlist_viewer_track_display = 0;
1685 /* talking menu on by default, to help the blind (if voice file present) */
1686 global_settings.talk_menu = 1;
1687 global_settings.talk_dir = 0;
1688 global_settings.talk_file = 0;
1689} 1371}
1690 1372
1691bool set_bool(char* string, bool* variable ) 1373bool set_bool(char* string, bool* variable )
diff --git a/apps/settings.h b/apps/settings.h
index 2fa6be54cc..f14eb63edf 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -266,13 +266,6 @@ extern char rec_base_directory[];
266#define DEFAULT_CONTRAST_SETTING 38 266#define DEFAULT_CONTRAST_SETTING 38
267#endif 267#endif
268#define MIN_CONTRAST_SETTING 5 268#define MIN_CONTRAST_SETTING 5
269#define DEFAULT_INVERT_SETTING false
270#define DEFAULT_INVERT_CURSOR_SETTING false
271#define DEFAULT_POWEROFF_SETTING 10
272#define DEFAULT_BACKLIGHT_TIMEOUT_SETTING 5
273#define DEFAULT_BACKLIGHT_ON_WHEN_CHARGING_SETTING 0
274#define DEFAULT_FF_REWIND_MIN_STEP FF_REWIND_1000
275#define DEFAULT_FF_REWIND_ACCEL_SETTING 3
276 269
277/* repeat mode options */ 270/* repeat mode options */
278enum { REPEAT_OFF, REPEAT_ALL, REPEAT_ONE, NUM_REPEAT_MODES }; 271enum { REPEAT_OFF, REPEAT_ALL, REPEAT_ONE, NUM_REPEAT_MODES };