blob: 4bf098d1d126defae44954bb92a9d573c1a7712b [file] [log] [blame]
Björn Stenbergf80d8a702002-06-27 00:20:00 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by wavey@wavey.org
Björn Stenberg6b25f792002-07-15 11:02:12 +000011 * RTC config saving code (C) 2002 by hessu@hes.iki.fi
Björn Stenbergf80d8a702002-06-27 00:20:00 +000012 *
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.
15 *
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
18 *
19 ****************************************************************************/
Björn Stenbergf80d8a702002-06-27 00:20:00 +000020#include <stdio.h>
Jörg Hohensohn44171b92004-06-18 20:41:59 +000021#include <stddef.h>
Jean-Philippe Bernardy00cf0da2005-02-15 15:30:19 +000022#include <limits.h>
Björn Stenbergf80d8a702002-06-27 00:20:00 +000023#include "config.h"
Linus Nielsen Feltzingd0abfe82002-07-28 16:09:44 +000024#include "kernel.h"
Björn Stenbergc4d8d972003-02-14 09:44:34 +000025#include "thread.h"
Björn Stenbergf80d8a702002-06-27 00:20:00 +000026#include "settings.h"
27#include "disk.h"
28#include "panic.h"
29#include "debug.h"
Björn Stenberg60b356e2002-06-27 01:08:11 +000030#include "button.h"
Justin Heinerb5025a82002-08-31 04:58:35 +000031#include "usb.h"
32#include "backlight.h"
Björn Stenberg60b356e2002-06-27 01:08:11 +000033#include "lcd.h"
Linus Nielsen Feltzing8a237a82005-04-04 12:06:29 +000034#include "audio.h"
Jörg Hohensohnf9933652004-01-05 20:42:51 +000035#include "mp3_playback.h"
Jens Arnold61a25502005-09-11 12:07:13 +000036#include "mpeg.h"
Jörg Hohensohn42ffbf92004-03-15 08:27:51 +000037#include "talk.h"
Björn Stenberg6b25f792002-07-15 11:02:12 +000038#include "string.h"
Linus Nielsen Feltzingd0abfe82002-07-28 16:09:44 +000039#include "ata.h"
Björn Stenbergcd7691d2002-08-13 17:16:09 +000040#include "fat.h"
Linus Nielsen Feltzingd0abfe82002-07-28 16:09:44 +000041#include "power.h"
Linus Nielsen Feltzing17cf49a2002-07-30 07:56:16 +000042#include "backlight.h"
Heikki Hannikainen6eb42542002-08-06 10:52:51 +000043#include "powermgmt.h"
Markus Braun5e4c1d22002-08-20 19:37:00 +000044#include "status.h"
Justin Heinerc4207f12002-09-05 16:30:07 +000045#include "atoi.h"
Björn Stenbergb1b8bd42002-09-24 17:22:12 +000046#include "screens.h"
Björn Stenberg0e6088f2002-10-02 16:33:26 +000047#include "ctype.h"
48#include "file.h"
Linus Nielsen Feltzingc843ba42002-10-29 12:16:36 +000049#include "errno.h"
50#include "system.h"
Linus Nielsen Feltzing75b41a82003-05-04 02:04:31 +000051#include "misc.h"
Linus Nielsen Feltzing7ddf0d62004-04-20 10:23:57 +000052#include "timefuncs.h"
Markus Braun5e4c1d22002-08-20 19:37:00 +000053#ifdef HAVE_LCD_BITMAP
54#include "icons.h"
Daniel Stenberg93b231c2002-09-12 13:33:59 +000055#include "font.h"
Linus Nielsen Feltzingfd0cc3b2002-10-29 12:09:15 +000056#include "peakmeter.h"
Linus Nielsen Feltzing9fb2d342003-06-25 23:24:47 +000057#include "hwcompat.h"
Markus Braun5e4c1d22002-08-20 19:37:00 +000058#endif
Björn Stenberg505eca72002-09-18 14:08:05 +000059#include "lang.h"
Björn Stenbergdea31222002-10-08 15:42:40 +000060#include "language.h"
Christi Scarborough4c0b83f2005-11-17 20:14:59 +000061#include "gwps.h"
Björn Stenbergae22de22002-12-02 16:07:56 +000062#include "powermgmt.h"
Björn Stenberga108ec22004-01-14 00:13:04 +000063#include "bookmark.h"
Daniel Stenberg79a6cb62003-02-15 00:03:23 +000064#include "sprintf.h"
Björn Stenbergc5aaab42003-03-10 16:31:02 +000065#include "keyboard.h"
Björn Stenberga6b8bdf2003-04-25 10:33:38 +000066#include "version.h"
Jörg Hohensohn44171b92004-06-18 20:41:59 +000067#include "rtc.h"
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +000068#include "sound.h"
Marcoen Hirschbergb0fee172005-12-06 13:27:15 +000069#include "rbunicode.h"
Miika Pekkarinenab78b042005-10-07 17:38:05 +000070#include "dircache.h"
Kevin Ferrarecbbdc952005-11-04 07:18:36 +000071#include "select.h"
72#include "statusbar.h"
Kevin Ferrare9ccca4a2005-11-04 17:25:29 +000073#include "splash.h"
Miika Pekkarinenab78b042005-10-07 17:38:05 +000074
Jens Arnoldd6c05452005-08-29 21:15:27 +000075#if CONFIG_CODEC == MAS3507D
Linus Nielsen Feltzing54a7e202003-11-04 00:18:19 +000076void dac_line_in(bool enable);
Linus Nielsen Feltzingc22b4112003-11-03 23:36:36 +000077#endif
Björn Stenbergf80d8a702002-06-27 00:20:00 +000078struct user_settings global_settings;
Jens Arnolda559cf22005-05-08 13:41:24 +000079#ifdef HAVE_RECORDING
Jens Arnoldabe77a12004-08-01 21:50:57 +000080const char rec_base_directory[] = REC_BASE_DIR;
Jens Arnolda559cf22005-05-08 13:41:24 +000081#endif
Jens Arnoldd6c05452005-08-29 21:15:27 +000082#if CONFIG_CODEC == SWCODEC
Miika Pekkarinen20b38972005-07-13 12:48:22 +000083#include "pcmbuf.h"
Linus Nielsen Feltzing6271b2b2005-06-09 09:47:00 +000084#include "pcm_playback.h"
Magnus Holmgren4b711c22005-09-24 15:22:48 +000085#include "dsp.h"
Linus Nielsen Feltzing6271b2b2005-06-09 09:47:00 +000086#endif
Björn Stenberg6c33c512004-09-19 21:58:37 +000087
Marcoen Hirschbergb0fee172005-12-06 13:27:15 +000088#define CONFIG_BLOCK_VERSION 35
Björn Stenberg6224cdb2002-08-16 14:41:47 +000089#define CONFIG_BLOCK_SIZE 512
90#define RTC_BLOCK_SIZE 44
Björn Stenbergcd7691d2002-08-13 17:16:09 +000091
Linus Nielsen Feltzingbb572c42002-09-27 09:31:31 +000092#ifdef HAVE_LCD_BITMAP
93#define MAX_LINES 10
94#else
95#define MAX_LINES 2
96#endif
97
Christian Gmeiner7c1879b2005-04-15 12:08:49 +000098#ifdef HAVE_REMOTE_LCD
99#include "lcd-remote.h"
100#endif
101
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000102long lasttime = 0;
Jean-Philippe Bernardy2860c5e2005-02-11 18:41:40 +0000103static long config_sector = 0; /* mark uninitialized */
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000104static unsigned char config_block[CONFIG_BLOCK_SIZE];
105
106
107/* descriptor for a configuration value */
108/* (watch the struct packing and member sizes to keep this small) */
109struct bit_entry
110{
111 /* how many bits within the bitfield (1-32), MSB set if value is signed */
112 unsigned char bit_size; /* min 6+1 bit */
113 /* how many bytes in the global_settings struct (1,2,4) */
Jörg Hohensohn75e7e502004-06-19 09:39:25 +0000114 unsigned char byte_size; /* min 3 bits */
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000115 /* store position in global_settings struct */
116 short settings_offset; /* min 9 bit, better 10 */
117 /* default value */
Kevin Ferrarecbbdc952005-11-04 07:18:36 +0000118 int default_val; /* min 15 bit */
Jörg Hohensohn75e7e502004-06-19 09:39:25 +0000119 /* variable name in a .cfg file, NULL if not to be saved */
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000120 const char* cfg_name;
Jörg Hohensohn75e7e502004-06-19 09:39:25 +0000121 /* set of values, or NULL for a numerical value */
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000122 const char* cfg_val;
123};
124
Björn Stenberg6b25f792002-07-15 11:02:12 +0000125/********************************************
126
127Config block as saved on the battery-packed RTC user RAM memory block
128of 44 bytes, starting at offset 0x14 of the RTC memory space.
129
130offset abs
1310x00 0x14 "Roc" header signature: 0x52 0x6f 0x63
1320x03 0x17 <version byte: 0x0>
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001330x04 0x18 start of bit-table
134...
1350x28,0x29 unused, not reachable by set_bits() without disturbing the next 2
1360x2A,0x2B <checksum 2 bytes: xor of 0x00-0x29>
Björn Stenberg6b25f792002-07-15 11:02:12 +0000137
138Config memory is reset to 0xff and initialized with 'factory defaults' if
139a valid header & checksum is not found. Config version number is only
140increased when information is _relocated_ or space is _reused_ so that old
Kevin Ferrarecbbdc952005-11-04 07:18:36 +0000141versions can read and modify configuration changed by new versions.
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000142Memory locations not used by a given version should not be
Björn Stenberg6b25f792002-07-15 11:02:12 +0000143modified unless the header & checksum test fails.
144
Björn Stenberg6224cdb2002-08-16 14:41:47 +0000145Rest of config block, only saved to disk:
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001460x2C start of 2nd bit-table
147...
Björn Stenbergdea31222002-10-08 15:42:40 +00001480xB8 (char[20]) WPS file
1490xCC (char[20]) Lang file
1500xE0 (char[20]) Font file
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001510xF4-0xFF <unused>
Björn Stenberg6224cdb2002-08-16 14:41:47 +0000152
Björn Stenberg6b25f792002-07-15 11:02:12 +0000153*************************************/
154
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000155/* The persistence of the global_settings members is now controlled by
Kevin Ferrarecbbdc952005-11-04 07:18:36 +0000156 the two tables below, rtc_bits and hd_bits.
157 New values can just be added to the end, it will be backwards
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000158 compatible. If you however change order, bitsize, etc. of existing
159 entries, you need to bump CONFIG_BLOCK_VERSION to break compatibility.
160*/
161
162
163/* convenience macro for both size and offset of global_settings member */
164#define S_O(val) sizeof(global_settings.val), offsetof(struct user_settings, val)
165#define SIGNED 0x80 /* for bitsize value with signed attribute */
166
167/* some sets of values which are used more than once, to save memory */
168static const char off_on[] = "off,on";
169static const char off_on_ask[] = "off,on,ask";
Jörg Hohensohnd4844202004-10-06 21:37:46 +0000170static const char off_number_spell_hover[] = "off,number,spell,hover";
Jens Arnolda559cf22005-05-08 13:41:24 +0000171#ifdef HAVE_LCD_BITMAP
172static const char graphic_numeric[] = "graphic,numeric";
173#endif
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000174
Jens Arnoldcf986e82005-04-04 20:16:01 +0000175#ifdef HAVE_RECORDING
Linus Nielsen Feltzing68482bb2005-04-04 09:12:12 +0000176/* keep synchronous to trig_durations and
177 trigger_times in settings_apply_trigger */
178static const char trig_durations_conf [] =
179 "0s,1s,2s,5s,10s,15s,20s,25s,30s,1min,2min,5min,10min";
Jens Arnoldcf986e82005-04-04 20:16:01 +0000180#endif
Linus Nielsen Feltzing68482bb2005-04-04 09:12:12 +0000181
Jens Arnolda6d409d2005-11-23 20:12:33 +0000182#if defined(CONFIG_BACKLIGHT)
183static const char backlight_times_conf [] =
184 "off,on,1,2,3,4,5,6,7,8,9,10,15,20,25,30,45,60,90";
185#endif
186
Kevin Ferrarecbbdc952005-11-04 07:18:36 +0000187/* the part of the settings which ends up in the RTC RAM, where available
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000188 (those we either need early, save frequently, or without spinup) */
Jens Arnoldc50a0692004-07-20 19:13:46 +0000189static const struct bit_entry rtc_bits[] =
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000190{
191 /* placeholder, containing the size information */
192 {9, 0, 0, 0, NULL, NULL }, /* 9 bit to tell how far this is populated */
193
194 /* # of bits, offset+size, default, .cfg name, .cfg values */
195 /* sound */
196 {7, S_O(volume), 70, "volume", NULL }, /* 0...100 */
Linus Nielsen Feltzing3db9c832004-06-21 13:42:37 +0000197 {8 | SIGNED, S_O(balance), 0, "balance", NULL }, /* -100...100 */
Jens Arnoldd6c05452005-08-29 21:15:27 +0000198#if CONFIG_CODEC != SWCODEC /* any MAS */
Linus Nielsen Feltzing3db9c832004-06-21 13:42:37 +0000199 {5 | SIGNED, S_O(bass), 0, "bass", NULL }, /* -15..+15 / -12..+12 */
200 {5 | SIGNED, S_O(treble), 0, "treble", NULL }, /* -15..+15 / -12..+12 */
Jens Arnold17f6d652005-06-16 21:20:00 +0000201#elif defined HAVE_UDA1380
202 {5, S_O(bass), 0, "bass", NULL }, /* 0..+24 */
203 {3, S_O(treble), 0, "treble", NULL }, /* 0..+6 */
204#endif
Jens Arnoldd6c05452005-08-29 21:15:27 +0000205#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000206 {5, S_O(loudness), 0, "loudness", NULL }, /* 0...17 */
Linus Nielsen Feltzing94da3b52004-06-22 12:37:42 +0000207 {3, S_O(avc), 0, "auto volume", "off,20ms,2,4,8" },
Linus Nielsen Feltzing7bade1a2004-07-06 12:17:14 +0000208 {1, S_O(superbass), false, "superbass", off_on },
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000209#endif
Jens Arnold76b257f2005-01-12 00:24:15 +0000210 {3, S_O(channel_config), 0, "channels",
211 "stereo,mono,custom,mono left,mono right,karaoke" },
212 {8, S_O(stereo_width), 100, "stereo width", NULL},
Anton Oleynikov2654d912005-12-04 14:33:10 +0000213#ifdef HAVE_UDA1380
214 {2, S_O(sound_scaling), SOUND_SCALE_VOLUME, "prevent clipping", "adjust volume,adjust bass,adjust current,off"},
215#endif
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000216 /* playback */
Miika Pekkarinenf090dc32005-07-21 11:44:00 +0000217 {1, S_O(resume), false, "resume", off_on },
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000218 {1, S_O(playlist_shuffle), false, "shuffle", off_on },
219 {16 | SIGNED, S_O(resume_index), -1, NULL, NULL },
220 {16 | SIGNED, S_O(resume_first_index), 0, NULL, NULL },
221 {32 | SIGNED, S_O(resume_offset), -1, NULL, NULL },
222 {32 | SIGNED, S_O(resume_seed), -1, NULL, NULL },
Linus Nielsen Feltzing0ad617c2005-08-21 23:01:12 +0000223 {3, S_O(repeat_mode), REPEAT_ALL, "repeat", "off,all,one,shuffle,ab" },
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000224 /* LCD */
225 {6, S_O(contrast), 40, "contrast", NULL },
Jörg Hohensohnfee86172004-12-18 10:29:47 +0000226#ifdef CONFIG_BACKLIGHT
Jens Arnolda6d409d2005-11-23 20:12:33 +0000227 {5, S_O(backlight_timeout), 5, "backlight timeout", backlight_times_conf },
Jörg Hohensohnfee86172004-12-18 10:29:47 +0000228#ifdef HAVE_CHARGING
Jens Arnolda6d409d2005-11-23 20:12:33 +0000229 {5, S_O(backlight_timeout_plugged), 11, "backlight timeout plugged",
230 backlight_times_conf },
Jörg Hohensohnfee86172004-12-18 10:29:47 +0000231#endif
Jörg Hohensohnfee86172004-12-18 10:29:47 +0000232#endif /* CONFIG_BACKLIGHT */
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000233#ifdef HAVE_LCD_BITMAP
234 {1, S_O(invert), false, "invert", off_on },
235 {1, S_O(flip_display), false, "flip display", off_on },
236 /* display */
Kevin Ferrareed956452005-11-20 03:18:00 +0000237 {1, S_O(invert_cursor), true, "invert cursor", off_on },
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000238 {1, S_O(statusbar), true, "statusbar", off_on },
239 {1, S_O(scrollbar), true, "scrollbar", off_on },
Jens Arnold1f0908d2004-10-09 20:54:15 +0000240#if CONFIG_KEYPAD == RECORDER_PAD
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000241 {1, S_O(buttonbar), true, "buttonbar", off_on },
Jens Arnold1f0908d2004-10-09 20:54:15 +0000242#endif
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000243 {1, S_O(volume_type), 0, "volume display", graphic_numeric },
Jens Arnold9d42e2b2005-01-30 13:48:44 +0000244 {1, S_O(battery_display), 0, "battery display", graphic_numeric },
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000245 {1, S_O(timeformat), 0, "time format", "24hour,12hour" },
Jens Arnold05af2802005-07-28 08:36:24 +0000246#endif /* HAVE_LCD_BITMAP */
Hardeep Sidhuea598c72004-07-12 22:02:53 +0000247 {1, S_O(show_icons), true, "show icons", off_on },
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000248 /* system */
Jens Arnold76b257f2005-01-12 00:24:15 +0000249 {4, S_O(poweroff), 10,
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000250 "idle poweroff", "off,1,2,3,4,5,6,7,8,9,10,15,30,45,60" },
251 {18, S_O(runtime), 0, NULL, NULL },
252 {18, S_O(topruntime), 0, NULL, NULL },
Kevin Ferrarecbbdc952005-11-04 07:18:36 +0000253 {15, S_O(max_files_in_playlist), 10000,
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000254 "max files in playlist", NULL }, /* 1000...20000 */
Kevin Ferrarecbbdc952005-11-04 07:18:36 +0000255 {14, S_O(max_files_in_dir), 400,
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000256 "max files in dir", NULL }, /* 50...10000 */
257 /* battery */
Jens Arnoldfe324562004-10-10 10:28:21 +0000258 {12, S_O(battery_capacity), BATTERY_CAPACITY_MIN, "battery capacity",
259 NULL }, /* 1500...3200 for NiMH, 2200...3200 for LiIon,
Jens Arnold76b257f2005-01-12 00:24:15 +0000260 500...1500 for Alkaline */
Jens Arnoldccfa4cd2004-10-10 01:25:32 +0000261#ifdef HAVE_CHARGING
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000262 {1, S_O(car_adapter_mode), false, "car adapter mode", off_on },
Jens Arnoldccfa4cd2004-10-10 01:25:32 +0000263#endif
Jens Arnold76b257f2005-01-12 00:24:15 +0000264 /* tuner */
Jörg Hohensohn593cc002004-09-28 22:13:26 +0000265#ifdef CONFIG_TUNER
Linus Nielsen Feltzing6e95efd2004-07-05 14:27:50 +0000266 {1, S_O(fm_force_mono), false, "force fm mono", off_on },
Linus Nielsen Feltzing4a7784a2004-07-12 15:06:48 +0000267 {8, S_O(last_frequency), 0, NULL, NULL }, /* Default: MIN_FREQ */
Linus Nielsen Feltzing09a17252004-07-05 18:09:00 +0000268#endif
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000269
Jens Arnold91846a12005-01-30 16:25:46 +0000270#if BATTERY_TYPES_COUNT > 1
271 {1, S_O(battery_type), 0, "battery type", "alkaline,nimh" },
272#endif
273
Christian Gmeiner7c1879b2005-04-15 12:08:49 +0000274#ifdef HAVE_REMOTE_LCD
275 /* remote lcd */
Christian Gmeiner7477c092005-05-30 00:00:22 +0000276 {6, S_O(remote_contrast), 42, "remote contrast", NULL },
277 {1, S_O(remote_invert), false, "remote invert", off_on },
Jens Arnoldbd1bb5f2005-06-17 21:43:00 +0000278 {1, S_O(remote_flip_display), false, "remote flip display", off_on },
Jens Arnolda6d409d2005-11-23 20:12:33 +0000279 {5, S_O(remote_backlight_timeout), 5, "remote backlight timeout",
280 backlight_times_conf },
281#ifdef HAVE_CHARGING
282 {5, S_O(remote_backlight_timeout_plugged), 11,
283 "remote backlight timeout plugged", backlight_times_conf },
Christian Gmeiner7c1879b2005-04-15 12:08:49 +0000284#endif
Jens Arnoldb51f7df2005-11-21 23:55:39 +0000285#ifdef HAVE_REMOTE_LCD_TICKING
Miika Pekkarinen05fdb1a2005-11-19 07:58:20 +0000286 {1, S_O(remote_reduce_ticking), false, "remote reduce ticking", off_on },
287#endif
Jens Arnoldb51f7df2005-11-21 23:55:39 +0000288#endif
Miika Pekkarinen05fdb1a2005-11-19 07:58:20 +0000289
Jens Arnold05af2802005-07-28 08:36:24 +0000290 /* new stuff to be added here */
291 /* If values are just added to the end, no need to bump the version. */
292
Linus Nielsen Feltzing41a53d22005-08-08 19:23:28 +0000293 /* Current sum of bits: 277 (worst case, but w/o remote lcd) */
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000294 /* Sum of all bit sizes must not grow beyond 288! */
295};
296
297
298/* the part of the settings which ends up in HD sector only */
Jens Arnoldc50a0692004-07-20 19:13:46 +0000299static const struct bit_entry hd_bits[] =
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000300{
301 /* This table starts after the 44 RTC bytes = 352 bits. */
302 /* Here we need 11 bits to tell how far this is populated. */
303
304 /* placeholder, containing the size information */
305 {11, 0, 0, 0, NULL, NULL }, /* 11 bit to tell how far this is populated */
306
307 /* # of bits, offset+size, default, .cfg name, .cfg values */
308 /* more display */
Jörg Hohensohnfee86172004-12-18 10:29:47 +0000309#ifdef CONFIG_BACKLIGHT
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000310 {1, S_O(caption_backlight), false, "caption backlight", off_on },
Jens Arnolda1a08d02004-10-09 19:56:27 +0000311#endif
Jens Arnold566eae22004-10-15 20:30:29 +0000312 {4, S_O(scroll_speed), 9, "scroll speed", NULL }, /* 0...15 */
Jens Arnold05af2802005-07-28 08:36:24 +0000313#ifdef HAVE_LCD_BITMAP
314#if LCD_WIDTH > 127
315 {8, S_O(scroll_step), 6, "scroll step", NULL }, /* 1...160 */
316#else
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000317 {7, S_O(scroll_step), 6, "scroll step", NULL }, /* 1...112 */
Jens Arnold05af2802005-07-28 08:36:24 +0000318#endif
319#endif /* HAVE_LCD_BITMAP */
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000320 {8, S_O(scroll_delay), 100, "scroll delay", NULL }, /* 0...250 */
321 {8, S_O(bidir_limit), 50, "bidir limit", NULL }, /* 0...200 */
322#ifdef HAVE_LCD_CHARCELLS
323 {3, S_O(jump_scroll), 0, "jump scroll", NULL }, /* 0...5 */
324 {8, S_O(jump_scroll_delay), 50, "jump scroll delay", NULL }, /* 0...250 */
325#endif
326 /* more playback */
327 {1, S_O(play_selected), true, "play selected", off_on },
328 {1, S_O(fade_on_stop), true, "volume fade", off_on },
Kevin Ferrarecbbdc952005-11-04 07:18:36 +0000329 {4, S_O(ff_rewind_min_step), FF_REWIND_1000,
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000330 "scan min step", "1,2,3,4,5,6,8,10,15,20,25,30,45,60" },
331 {4, S_O(ff_rewind_accel), 3, "scan accel", NULL },
Jens Arnoldd6c05452005-08-29 21:15:27 +0000332#if CONFIG_CODEC == SWCODEC
Miika Pekkarinenf090dc32005-07-21 11:44:00 +0000333 {3, S_O(buffer_margin), 0, "antiskip",
334 "5s,15s,30s,1min,2min,3min,5min,10min" },
335#else
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000336 {3, S_O(buffer_margin), 0, "antiskip", NULL },
Miika Pekkarinenf090dc32005-07-21 11:44:00 +0000337#endif
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000338 /* disk */
Jens Arnolddd937dc2004-10-09 22:04:47 +0000339#ifndef HAVE_MMC
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000340#ifdef HAVE_ATA_POWER_OFF
341 {1, S_O(disk_poweroff), false, "disk poweroff", off_on },
342#endif
343 {8, S_O(disk_spindown), 5, "disk spindown", NULL },
Jens Arnold05af2802005-07-28 08:36:24 +0000344#endif /* HAVE_MMC */
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000345 /* browser */
Kevin Ferrarecbbdc952005-11-04 07:18:36 +0000346 {3, S_O(dirfilter), SHOW_SUPPORTED,
Björn Stenbergfc53fd72005-01-17 11:37:36 +0000347 "show files", "all,supported,music,playlists,id3 database" },
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000348 {1, S_O(sort_case), false, "sort case", off_on },
Björn Stenbergc34d0462005-11-04 12:49:42 +0000349 {1, S_O(browse_current), false, "follow playlist", off_on },
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000350 /* playlist */
351 {1, S_O(playlist_viewer_icons), true, "playlist viewer icons", off_on },
Jens Arnoldccfa4cd2004-10-10 01:25:32 +0000352 {1, S_O(playlist_viewer_indices), true,
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000353 "playlist viewer indices", off_on },
Kevin Ferrarecbbdc952005-11-04 07:18:36 +0000354 {1, S_O(playlist_viewer_track_display), 0,
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000355 "playlist viewer track display", "track name,full path" },
Kevin Ferrarecbbdc952005-11-04 07:18:36 +0000356 {2, S_O(recursive_dir_insert), RECURSE_OFF,
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000357 "recursive directory insert", off_on_ask },
358 /* bookmarks */
Kevin Ferrarecbbdc952005-11-04 07:18:36 +0000359 {3, S_O(autocreatebookmark), BOOKMARK_NO, "autocreate bookmarks",
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000360 "off,on,ask,recent only - on,recent only - ask" },
361 {2, S_O(autoloadbookmark), BOOKMARK_NO,
362 "autoload bookmarks", off_on_ask },
Kevin Ferrarecbbdc952005-11-04 07:18:36 +0000363 {2, S_O(usemrb), BOOKMARK_NO,
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000364 "use most-recent-bookmarks", "off,on,unique only" },
365#ifdef HAVE_LCD_BITMAP
366 /* peak meter */
367 {5, S_O(peak_meter_clip_hold), 16, "peak meter clip hold", /* 0...25 */
368 "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" },
Jens Arnold99a05982005-08-29 20:07:17 +0000369 {5, S_O(peak_meter_hold), 3, "peak meter hold",
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000370 "off,200ms,300ms,500ms,1,2,3,4,5,6,7,8,9,10,15,20,30,1min" },
371 {7, S_O(peak_meter_release), 8, "peak meter release", NULL }, /* 0...126 */
Jens Arnoldbb187c32004-06-23 07:15:22 +0000372 {1, S_O(peak_meter_dbfs), true, "peak meter dbfs", off_on },
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000373 {7, S_O(peak_meter_min), 60, "peak meter min", NULL }, /* 0...100 */
374 {7, S_O(peak_meter_max), 0, "peak meter max", NULL }, /* 0...100 */
375#endif
Jens Arnoldd6c05452005-08-29 21:15:27 +0000376#if CONFIG_CODEC == MAS3587F
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000377 /* recording */
378 {1, S_O(rec_editable), false, "editable recordings", off_on },
Linus Nielsen Feltzingfb60a292004-10-27 09:24:02 +0000379 {4, S_O(rec_timesplit), 0, "rec timesplit", /* 0...15 */
380 "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" },
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000381 {1, S_O(rec_channels), 0, "rec channels", "stereo,mono" },
382 {4, S_O(rec_mic_gain), 8, "rec mic gain", NULL },
383 {3, S_O(rec_quality), 5, "rec quality", NULL },
Jens Arnold8fd5b172005-09-06 20:48:28 +0000384#ifdef HAVE_SPDIF_IN
385 {2, S_O(rec_source), 0 /* 0=mic */, "rec source", "mic,line,spdif" },
386#else
387 {1, S_O(rec_source), 0 /* 0=mic */, "rec source", "mic,line" },
388#endif
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000389 {3, S_O(rec_frequency), 0, /* 0=44.1kHz */
390 "rec frequency", "44,48,32,22,24,16" },
391 {4, S_O(rec_left_gain), 2, /* 0dB */
392 "rec left gain", NULL }, /* 0...15 */
393 {4, S_O(rec_right_gain), 2, /* 0dB */
394 "rec right gain", NULL }, /* 0...15 */
Linus Nielsen Feltzing0bc2c6c2004-10-04 13:12:31 +0000395 {5, S_O(rec_prerecord_time), 0, "prerecording time", NULL }, /* 0...30 */
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000396 {1, S_O(rec_directory), 0, /* rec_base_directory */
397 "rec directory", REC_BASE_DIR ",current" },
398#endif
Jens Arnoldd6c05452005-08-29 21:15:27 +0000399#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
Jens Arnold05af2802005-07-28 08:36:24 +0000400 {7, S_O(mdb_strength), 0, "mdb strength", NULL},
401 {7, S_O(mdb_harmonics), 0, "mdb harmonics", NULL},
402 {9, S_O(mdb_center), 0, "mdb center", NULL},
403 {9, S_O(mdb_shape), 0, "mdb shape", NULL},
404 {1, S_O(mdb_enable), 0, "mdb enable", off_on},
405#endif
Jens Arnoldd6c05452005-08-29 21:15:27 +0000406#if CONFIG_CODEC == MAS3507D
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000407 {1, S_O(line_in), false, "line in", off_on },
408#endif
409 /* voice */
Jörg Hohensohnd4844202004-10-06 21:37:46 +0000410 {2, S_O(talk_dir), 0, "talk dir", off_number_spell_hover },
411 {2, S_O(talk_file), 0, "talk file", off_number_spell_hover },
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000412 {1, S_O(talk_menu), true, "talk menu", off_on },
413
Jörg Hohensohn5c8a2f52004-06-22 09:16:44 +0000414 {2, S_O(sort_file), 0, "sort files", "alpha,oldest,newest,type" },
415 {2, S_O(sort_dir), 0, "sort dirs", "alpha,oldest,newest" },
Linus Nielsen Feltzing8036acc2004-07-27 22:23:01 +0000416 {1, S_O(id3_v1_first), 0, "id3 tag priority", "v2-v1,v1-v2"},
Linus Nielsen Feltzing4cdcbb92004-07-27 19:20:51 +0000417
Christi Scarborough8a8bd912005-02-04 10:37:21 +0000418#ifdef HAVE_RECORDING
419 {1, S_O(rec_startup), false, "rec screen on startup", off_on },
Linus Nielsen Feltzing68482bb2005-04-04 09:12:12 +0000420
421 /* values for the trigger */
422 {8 | SIGNED, S_O(rec_start_thres), -35, "trigger start threshold", NULL},
423 {8 | SIGNED, S_O(rec_stop_thres), -45, "trigger stop threshold", NULL},
424 {4, S_O(rec_start_duration), 0, "trigger start duration", trig_durations_conf},
425 {4, S_O(rec_stop_postrec), 2, "trigger stop postrec", trig_durations_conf},
426 {4, S_O(rec_stop_gap), 1, "trigger min gap", trig_durations_conf},
Linus Nielsen Feltzingc35f6a02005-09-02 07:27:07 +0000427 {4, S_O(rec_trigger_mode ), 0, "trigger mode", "off,once,repeat"},
Christi Scarborough8a8bd912005-02-04 10:37:21 +0000428#endif
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000429
Daniel Stenberg6b569d32005-11-14 23:37:19 +0000430#if CONFIG_BACKLIGHT == BL_IRIVER_H100
Jens Arnold61b9d342005-06-20 17:03:09 +0000431 /* backlight fading */
432 {2, S_O(backlight_fade_in), 1, "backlight fade in", "off,500ms,1s,2s"},
433 {3, S_O(backlight_fade_out), 3, "backlight fade out",
434 "off,500ms,1s,2s,3s,4s,5s,10s"},
435#endif
Kevin Ferrarecbbdc952005-11-04 07:18:36 +0000436
Linus Nielsen Feltzing8782bc82005-07-01 09:42:39 +0000437#ifdef HAVE_SPDIF_POWER
438 {1, S_O(spdif_enable), false, "spdif enable", off_on},
439#endif
Hardeep Sidhu71d22812005-07-01 11:25:16 +0000440
Jens Arnold5acbd3e2005-11-07 00:40:58 +0000441 {1, S_O(next_folder), false, "folder navigation", off_on },
Jens Arnold8102f3d2005-07-02 10:50:42 +0000442 {1, S_O(runtimedb), false, "gather runtime data", off_on },
Hardeep Sidhu71d22812005-07-01 11:25:16 +0000443
Jens Arnoldd6c05452005-08-29 21:15:27 +0000444#if CONFIG_CODEC == SWCODEC
Magnus Holmgren4a537872005-07-24 15:32:28 +0000445 {1, S_O(replaygain), false, "replaygain", off_on },
Kevin Ferrarecbbdc952005-11-04 07:18:36 +0000446 {2, S_O(replaygain_type), REPLAYGAIN_ALBUM, "replaygain type",
Magnus Holmgren4b711c22005-09-24 15:22:48 +0000447 "track,album,track shuffle" },
Magnus Holmgren4a537872005-07-24 15:32:28 +0000448 {1, S_O(replaygain_noclip), false, "replaygain noclip", off_on },
Magnus Holmgrenc78c2292005-08-14 06:22:53 +0000449 {8 | SIGNED, S_O(replaygain_preamp), 0, "replaygain preamp", NULL },
Jens Arnold49608082005-10-16 11:15:51 +0000450 {2, S_O(beep), 0, "beep", "off,weak,moderate,strong" },
Miika Pekkarinene7461b32005-11-06 16:40:20 +0000451 {2, S_O(crossfade), 0, "crossfade", "off,shuffle,always"},
452 {3, S_O(crossfade_fade_in_delay), 0, "crossfade fade in delay", NULL},
453 {3, S_O(crossfade_fade_out_delay), 0, "crossfade fade out delay", NULL},
454 {4, S_O(crossfade_fade_in_duration), 0, "crossfade fade in duration", NULL},
455 {4, S_O(crossfade_fade_out_duration), 0, "crossfade fade out duration", NULL},
456 {1, S_O(crossfade_fade_out_mixmode), 0, "crossfade fade out mode", "crossfade,mix"},
Marcoen Hirschberge13fad32005-11-14 21:56:56 +0000457 {1, S_O(crossfeed), false, "crossfeed", off_on },
Miika Pekkarinen90161c92005-07-22 16:46:27 +0000458#endif
Miika Pekkarinenab78b042005-10-07 17:38:05 +0000459#ifdef HAVE_DIRCACHE
460 {1, S_O(dircache), false, "dircache", off_on },
461 {22, S_O(dircache_size), 0, NULL, NULL },
462#endif
Kevin Ferrarecbbdc952005-11-04 07:18:36 +0000463
Andye6e54962005-11-12 04:00:56 +0000464#if defined(HAVE_UDA1380)
465 /* recording settings for iriver */
466 {4, S_O(rec_timesplit), 0, "rec timesplit", /* 0...15 */
467 "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" },
468 {1, S_O(rec_channels), 0, "rec channels", "stereo,mono" },
469 {4, S_O(rec_mic_gain), 4, "rec mic gain", NULL },
470 {1, S_O(rec_source), 0 /* 0=mic */, "rec source", "mic,line" },
471 {3, S_O(rec_frequency), 0, /* 0=44.1kHz */
472 "rec frequency", "44,48,32,22,24,16" },
473 {4, S_O(rec_left_gain), 2, /* 0dB */
474 "rec left gain", NULL }, /* 0...15 */
475 {4, S_O(rec_right_gain), 2, /* 0dB */
476 "rec right gain", NULL }, /* 0...15 */
477 {5, S_O(rec_prerecord_time), 0, "prerecording time", NULL }, /* 0...30 */
478 {1, S_O(rec_directory), 0, /* rec_base_directory */
479 "rec directory", REC_BASE_DIR ",current" },
480 {8|SIGNED, S_O(rec_adc_left_gain), 0, /* 0dB */ "adc left gain", NULL }, /* -128...48 */
481 {8|SIGNED, S_O(rec_adc_right_gain), 0, /* 0dB */ "adc right gain", NULL }, /* -128...48 */
482#endif
483
Jens Arnoldb51f7df2005-11-21 23:55:39 +0000484#ifdef HAVE_REMOTE_LCD
485 {1, S_O(remote_caption_backlight), false,
486 "remote caption backlight", off_on },
487#endif
Jens Arnold05af2802005-07-28 08:36:24 +0000488 /* If values are just added to the end, no need to bump the version. */
Christi Scarborough8a8bd912005-02-04 10:37:21 +0000489 /* new stuff to be added at the end */
Jens Arnold05af2802005-07-28 08:36:24 +0000490
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000491 /* Sum of all bit sizes must not grow beyond 0xB8*8 = 1472 */
492};
493
Jens Arnold251deaa2005-05-04 22:30:36 +0000494/* helper function to extract n (<=32) bits from an arbitrary position
495 * counting from LSB to MSB */
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000496static unsigned long get_bits(
Jens Arnold8fb33612004-08-18 01:09:31 +0000497 const unsigned long* p, /* the start of the bitfield array */
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000498 unsigned int from, /* bit no. to start reading from */
499 unsigned int size) /* how many bits to read */
500{
Jens Arnold251deaa2005-05-04 22:30:36 +0000501 unsigned int long_index = from / 32;
502 unsigned int bit_index = from % 32;
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000503 unsigned long result;
504
Jens Arnold251deaa2005-05-04 22:30:36 +0000505 result = p[long_index] >> bit_index;
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000506
Jens Arnold251deaa2005-05-04 22:30:36 +0000507 if (bit_index + size > 32) /* crossing longword boundary */
508 result |= p[long_index+1] << (32 - bit_index);
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000509
Jens Arnold251deaa2005-05-04 22:30:36 +0000510 result &= 0xFFFFFFFF >> (32 - size);
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000511
512 return result;
513}
514
Jens Arnold251deaa2005-05-04 22:30:36 +0000515/* helper function to set n (<=32) bits to an arbitrary position,
516 * counting from LSB to MSB */
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000517static void set_bits(
518 unsigned long* p, /* the start of the bitfield array */
519 unsigned int from, /* bit no. to start writing into */
520 unsigned int size, /* how many bits to change */
521 unsigned long value) /* content (LSBs will be taken) */
522{
Jens Arnold251deaa2005-05-04 22:30:36 +0000523 unsigned int long_index = from / 32;
524 unsigned int bit_index = from % 32;
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000525 unsigned long mask;
526
Jens Arnold251deaa2005-05-04 22:30:36 +0000527 mask = 0xFFFFFFFF >> (32 - size);
528 value &= mask;
529 mask <<= bit_index;
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000530
Jens Arnold251deaa2005-05-04 22:30:36 +0000531 if (bit_index + size > 32)
Kevin Ferrarecbbdc952005-11-04 07:18:36 +0000532 p[long_index+1] =
Jens Arnold251deaa2005-05-04 22:30:36 +0000533 (p[long_index+1] & (0xFFFFFFFF << (bit_index + size - 32)))
534 | (value >> (32 - bit_index));
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000535
Jens Arnold251deaa2005-05-04 22:30:36 +0000536 p[long_index] = (p[long_index] & ~mask) | (value << bit_index);
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000537}
Björn Stenberg6b25f792002-07-15 11:02:12 +0000538
Björn Stenbergf80d8a702002-06-27 00:20:00 +0000539/*
Björn Stenberg6224cdb2002-08-16 14:41:47 +0000540 * Calculates the checksum for the config block and returns it
Björn Stenbergf80d8a702002-06-27 00:20:00 +0000541 */
Björn Stenberg6b25f792002-07-15 11:02:12 +0000542
Jens Arnold8fb33612004-08-18 01:09:31 +0000543static unsigned short calculate_config_checksum(const unsigned char* buf)
Björn Stenbergf80d8a702002-06-27 00:20:00 +0000544{
Björn Stenbergcd7691d2002-08-13 17:16:09 +0000545 unsigned int i;
546 unsigned char cksum[2];
Björn Stenberg6b25f792002-07-15 11:02:12 +0000547 cksum[0] = cksum[1] = 0;
Kevin Ferrarecbbdc952005-11-04 07:18:36 +0000548
Björn Stenberg6224cdb2002-08-16 14:41:47 +0000549 for (i=0; i < RTC_BLOCK_SIZE - 2; i+=2 ) {
550 cksum[0] ^= buf[i];
551 cksum[1] ^= buf[i+1];
Björn Stenberg6b25f792002-07-15 11:02:12 +0000552 }
Björn Stenbergcd7691d2002-08-13 17:16:09 +0000553
554 return (cksum[0] << 8) | cksum[1];
Björn Stenberg6b25f792002-07-15 11:02:12 +0000555}
556
557/*
558 * initialize the config block buffer
559 */
560static void init_config_buffer( void )
561{
562 DEBUGF( "init_config_buffer()\n" );
Kevin Ferrarecbbdc952005-11-04 07:18:36 +0000563
Jörg Hohensohn6ff6d212004-06-19 15:50:02 +0000564 /* reset to 0 - all unused */
565 memset(config_block, 0, CONFIG_BLOCK_SIZE);
Björn Stenberg6b25f792002-07-15 11:02:12 +0000566 /* insert header */
Björn Stenberg6224cdb2002-08-16 14:41:47 +0000567 config_block[0] = 'R';
568 config_block[1] = 'o';
569 config_block[2] = 'c';
570 config_block[3] = CONFIG_BLOCK_VERSION;
Björn Stenberg6b25f792002-07-15 11:02:12 +0000571}
572
573/*
Björn Stenbergcd7691d2002-08-13 17:16:09 +0000574 * save the config block buffer to disk or RTC RAM
Björn Stenberg6b25f792002-07-15 11:02:12 +0000575 */
576static int save_config_buffer( void )
577{
Björn Stenbergcd7691d2002-08-13 17:16:09 +0000578 unsigned short chksum;
Dave Chapman5009c9c2005-12-04 13:05:56 +0000579#ifdef HAVE_RTC_RAM
Björn Stenbergcd7691d2002-08-13 17:16:09 +0000580 unsigned int i;
Björn Stenbergcd7691d2002-08-13 17:16:09 +0000581#endif
582
Björn Stenberg6b25f792002-07-15 11:02:12 +0000583 /* update the checksum in the end of the block before saving */
Björn Stenberg6224cdb2002-08-16 14:41:47 +0000584 chksum = calculate_config_checksum(config_block);
585 config_block[ RTC_BLOCK_SIZE - 2 ] = chksum >> 8;
586 config_block[ RTC_BLOCK_SIZE - 1 ] = chksum & 0xff;
Björn Stenbergcd7691d2002-08-13 17:16:09 +0000587
Dave Chapman5009c9c2005-12-04 13:05:56 +0000588#ifdef HAVE_RTC_RAM
Björn Stenberg6b25f792002-07-15 11:02:12 +0000589 /* FIXME: okay, it _would_ be cleaner and faster to implement rtc_write so
590 that it would write a number of bytes at a time since the RTC chip
591 supports that, but this will have to do for now 8-) */
Björn Stenberg6224cdb2002-08-16 14:41:47 +0000592 for (i=0; i < RTC_BLOCK_SIZE; i++ ) {
593 int r = rtc_write(0x14+i, config_block[i]);
Björn Stenberg6b25f792002-07-15 11:02:12 +0000594 if (r) {
Robert Hak36dc9c12002-10-14 09:11:59 +0000595 DEBUGF( "save_config_buffer: rtc_write failed at addr 0x%02x: %d\n",
596 14+i, r );
Björn Stenberg6b25f792002-07-15 11:02:12 +0000597 return r;
598 }
Björn Stenberg6b25f792002-07-15 11:02:12 +0000599 }
Björn Stenberg6b25f792002-07-15 11:02:12 +0000600
Björn Stenberg6224cdb2002-08-16 14:41:47 +0000601#endif
Björn Stenberg6b25f792002-07-15 11:02:12 +0000602
Jens Arnoldc12e87d2004-09-28 18:09:10 +0000603 if (config_sector != 0)
604 ata_delayed_write( config_sector, config_block);
Linus Nielsen Feltzingd0abfe82002-07-28 16:09:44 +0000605 else
606 return -1;
Björn Stenbergcd7691d2002-08-13 17:16:09 +0000607
Björn Stenbergcd7691d2002-08-13 17:16:09 +0000608 return 0;
Linus Nielsen Feltzingd0abfe82002-07-28 16:09:44 +0000609}
610
611/*
Björn Stenbergcd7691d2002-08-13 17:16:09 +0000612 * load the config block buffer from disk or RTC RAM
Linus Nielsen Feltzingd0abfe82002-07-28 16:09:44 +0000613 */
Jörg Hohensohn6ff6d212004-06-19 15:50:02 +0000614static int load_config_buffer(int which)
Linus Nielsen Feltzingd0abfe82002-07-28 16:09:44 +0000615{
Björn Stenbergcd7691d2002-08-13 17:16:09 +0000616 unsigned short chksum;
Björn Stenberg6224cdb2002-08-16 14:41:47 +0000617 bool correct = false;
Björn Stenbergcd7691d2002-08-13 17:16:09 +0000618
Kevin Ferrarecbbdc952005-11-04 07:18:36 +0000619
Linus Nielsen Feltzingd0abfe82002-07-28 16:09:44 +0000620 DEBUGF( "load_config_buffer()\n" );
Linus Nielsen Feltzingd0abfe82002-07-28 16:09:44 +0000621
Jörg Hohensohn6ff6d212004-06-19 15:50:02 +0000622 if (which & SETTINGS_HD)
623 {
Jens Arnoldc12e87d2004-09-28 18:09:10 +0000624 if (config_sector != 0) {
Jörg Hohensohnda848572004-12-28 22:16:07 +0000625 ata_read_sectors(IF_MV2(0,) config_sector, 1, config_block);
Jörg Hohensohn6ff6d212004-06-19 15:50:02 +0000626 /* calculate the checksum, check it and the header */
627 chksum = calculate_config_checksum(config_block);
Kevin Ferrarecbbdc952005-11-04 07:18:36 +0000628
Jörg Hohensohn6ff6d212004-06-19 15:50:02 +0000629 if (config_block[0] == 'R' &&
630 config_block[1] == 'o' &&
631 config_block[2] == 'c' &&
632 config_block[3] == CONFIG_BLOCK_VERSION &&
633 (chksum >> 8) == config_block[RTC_BLOCK_SIZE - 2] &&
634 (chksum & 0xff) == config_block[RTC_BLOCK_SIZE - 1])
635 {
636 DEBUGF( "load_config_buffer: header & checksum test ok\n" );
637 correct = true;
638 }
Björn Stenberg6224cdb2002-08-16 14:41:47 +0000639 }
640 }
641
Dave Chapman5009c9c2005-12-04 13:05:56 +0000642#ifdef HAVE_RTC_RAM
Linus Nielsen Feltzinge8db0032004-03-13 00:04:58 +0000643 if(!correct)
644 {
645 /* If the disk sector was incorrect, reinit the buffer */
Jörg Hohensohn6ff6d212004-06-19 15:50:02 +0000646 memset(config_block, 0, CONFIG_BLOCK_SIZE);
Linus Nielsen Feltzinge8db0032004-03-13 00:04:58 +0000647 }
Björn Stenberg6224cdb2002-08-16 14:41:47 +0000648
Jörg Hohensohn6ff6d212004-06-19 15:50:02 +0000649 if (which & SETTINGS_RTC)
Björn Stenberg6224cdb2002-08-16 14:41:47 +0000650 {
Jörg Hohensohn6ff6d212004-06-19 15:50:02 +0000651 unsigned int i;
652 unsigned char rtc_block[RTC_BLOCK_SIZE];
653
654 /* read rtc block */
655 for (i=0; i < RTC_BLOCK_SIZE; i++ )
656 rtc_block[i] = rtc_read(0x14+i);
657
658 chksum = calculate_config_checksum(rtc_block);
Kevin Ferrarecbbdc952005-11-04 07:18:36 +0000659
Jörg Hohensohn6ff6d212004-06-19 15:50:02 +0000660 /* if rtc block is ok, use that */
661 if (rtc_block[0] == 'R' &&
662 rtc_block[1] == 'o' &&
663 rtc_block[2] == 'c' &&
664 rtc_block[3] == CONFIG_BLOCK_VERSION &&
665 (chksum >> 8) == rtc_block[RTC_BLOCK_SIZE - 2] &&
666 (chksum & 0xff) == rtc_block[RTC_BLOCK_SIZE - 1])
667 {
668 memcpy(config_block, rtc_block, RTC_BLOCK_SIZE);
669 correct = true;
670 }
Björn Stenberg6224cdb2002-08-16 14:41:47 +0000671 }
Linus Nielsen Feltzingd0abfe82002-07-28 16:09:44 +0000672#endif
Kevin Ferrarecbbdc952005-11-04 07:18:36 +0000673
Björn Stenberg6224cdb2002-08-16 14:41:47 +0000674 if ( !correct ) {
675 /* if checksum is not valid, clear the config buffer */
676 DEBUGF( "load_config_buffer: header & checksum test failed\n" );
677 init_config_buffer();
678 return -1;
Björn Stenbergcd7691d2002-08-13 17:16:09 +0000679 }
Björn Stenberg6224cdb2002-08-16 14:41:47 +0000680
681 return 0;
Linus Nielsen Feltzingd0abfe82002-07-28 16:09:44 +0000682}
683
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000684
685/* helper to save content of global_settings into a bitfield,
Kevin Ferrarecbbdc952005-11-04 07:18:36 +0000686 as described per table */
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000687static void save_bit_table(const struct bit_entry* p_table, int count, int bitstart)
688{
689 unsigned long* p_bitfield = (unsigned long*)config_block; /* 32 bit addr. */
690 unsigned long value; /* 32 bit content */
691 int i;
692 const struct bit_entry* p_run = p_table; /* start after the size info */
693 int curr_bit = bitstart + p_table->bit_size;
694 count--; /* first is excluded from loop */
695
696 for (i=0; i<count; i++)
697 {
698 p_run++;
699 /* could do a memcpy, but that would be endian-dependent */
700 switch(p_run->byte_size)
701 {
702 case 1:
703 value = ((unsigned char*)&global_settings)[p_run->settings_offset];
704 break;
705 case 2:
706 value = ((unsigned short*)&global_settings)[p_run->settings_offset/2];
707 break;
708 case 4:
709 value = ((unsigned int*)&global_settings)[p_run->settings_offset/4];
710 break;
711 default:
712 DEBUGF( "illegal size!" );
713 continue;
714 }
715 set_bits(p_bitfield, curr_bit, p_run->bit_size & 0x3F, value);
716 curr_bit += p_run->bit_size & 0x3F;
717 }
718 set_bits(p_bitfield, bitstart, p_table->bit_size, /* write size */
719 curr_bit); /* = position after last element */
720}
721
Jens Arnoldc12e87d2004-09-28 18:09:10 +0000722/*
723 * figure out the config sector from the partition table and the
Kevin Ferrarecbbdc952005-11-04 07:18:36 +0000724 * mounted file system
Jens Arnoldc12e87d2004-09-28 18:09:10 +0000725 */
726void settings_calc_config_sector(void)
727{
728#ifdef SIMULATOR
729 config_sector = 61;
730#else
Jean-Philippe Bernardy2860c5e2005-02-11 18:41:40 +0000731 int i;
732 long partition_start;
733 long sector = 0;
Jens Arnoldc12e87d2004-09-28 18:09:10 +0000734
Jörg Hohensohnda848572004-12-28 22:16:07 +0000735 if (fat_startsector(IF_MV(0)) != 0) /* There is a partition table */
Jens Arnoldc12e87d2004-09-28 18:09:10 +0000736 {
737 sector = 61;
738 for (i = 0; i < 4; i++)
739 {
740 partition_start = disk_partinfo(i)->start;
741 if (partition_start != 0 && (partition_start - 2) < sector)
742 sector = partition_start - 2;
743 }
744 if (sector < 0)
745 sector = 0;
746 }
Kevin Ferrarecbbdc952005-11-04 07:18:36 +0000747
Jens Arnoldc12e87d2004-09-28 18:09:10 +0000748 config_sector = sector;
749#endif
750}
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000751
Björn Stenberg6b25f792002-07-15 11:02:12 +0000752/*
753 * persist all runtime user settings to disk or RTC RAM
754 */
755int settings_save( void )
756{
Björn Stenbergae22de22002-12-02 16:07:56 +0000757 {
Björn Stenberg745eed62003-07-04 08:20:30 +0000758 int elapsed_secs;
Björn Stenbergae22de22002-12-02 16:07:56 +0000759
Björn Stenberg745eed62003-07-04 08:20:30 +0000760 elapsed_secs = (current_tick - lasttime) / HZ;
761 global_settings.runtime += elapsed_secs;
762 lasttime += (elapsed_secs * HZ);
Björn Stenberg34351e82002-12-04 11:25:56 +0000763
Björn Stenbergae22de22002-12-02 16:07:56 +0000764 if ( global_settings.runtime > global_settings.topruntime )
765 global_settings.topruntime = global_settings.runtime;
Björn Stenbergae22de22002-12-02 16:07:56 +0000766 }
Björn Stenbergc78e1b02003-01-09 00:55:00 +0000767
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000768 /* serialize scalar values into RTC and HD sector, specified via table */
769 save_bit_table(rtc_bits, sizeof(rtc_bits)/sizeof(rtc_bits[0]), 4*8);
770 save_bit_table(hd_bits, sizeof(hd_bits)/sizeof(hd_bits[0]), RTC_BLOCK_SIZE*8);
Björn Stenberga2e98c12002-12-12 15:20:37 +0000771
Daniel Stenbergf981ea92005-12-05 22:44:42 +0000772 strncpy((char *)&config_block[0xb8], (char *)global_settings.wps_file,
773 MAX_FILENAME);
774 strncpy((char *)&config_block[0xcc], (char *)global_settings.lang_file,
775 MAX_FILENAME);
776 strncpy((char *)&config_block[0xe0], (char *)global_settings.font_file,
777 MAX_FILENAME);
Christi Scarborough4c0b83f2005-11-17 20:14:59 +0000778#ifdef HAVE_REMOTE_LCD
Daniel Stenbergf981ea92005-12-05 22:44:42 +0000779 strncpy((char *)&config_block[0xf4], (char *)global_settings.rwps_file,
780 MAX_FILENAME);
Christi Scarborough4c0b83f2005-11-17 20:14:59 +0000781#endif
Björn Stenberg6224cdb2002-08-16 14:41:47 +0000782
Linus Nielsen Feltzingd0abfe82002-07-28 16:09:44 +0000783 if(save_config_buffer())
784 {
785 lcd_clear_display();
Christi Scarborough4c0b83f2005-11-17 20:14:59 +0000786#ifdef HAVE_REMOTE_LCD
787 lcd_remote_clear_display();
788#endif
Linus Nielsen Feltzingd0abfe82002-07-28 16:09:44 +0000789#ifdef HAVE_LCD_CHARCELLS
Björn Stenberg505eca72002-09-18 14:08:05 +0000790 lcd_puts(0, 0, str(LANG_SETTINGS_SAVE_PLAYER));
791 lcd_puts(0, 1, str(LANG_SETTINGS_BATTERY_PLAYER));
Linus Nielsen Feltzingd0abfe82002-07-28 16:09:44 +0000792#else
Björn Stenberg505eca72002-09-18 14:08:05 +0000793 lcd_puts(4, 2, str(LANG_SETTINGS_SAVE_RECORDER));
794 lcd_puts(2, 4, str(LANG_SETTINGS_BATTERY_RECORDER));
Linus Nielsen Feltzingd0abfe82002-07-28 16:09:44 +0000795 lcd_update();
Christi Scarborough4c0b83f2005-11-17 20:14:59 +0000796#ifdef HAVE_REMOTE_LCD
797 lcd_remote_puts(4, 2, str(LANG_SETTINGS_SAVE_RECORDER));
798 lcd_remote_puts(2, 4, str(LANG_SETTINGS_BATTERY_RECORDER));
799 lcd_remote_update();
800#endif
Linus Nielsen Feltzingd0abfe82002-07-28 16:09:44 +0000801#endif
802 sleep(HZ*2);
803 return -1;
804 }
805 return 0;
Björn Stenbergf80d8a702002-06-27 00:20:00 +0000806}
807
Linus Nielsen Feltzingfd0cc3b2002-10-29 12:09:15 +0000808#ifdef HAVE_LCD_BITMAP
809/**
Kevin Ferrarecbbdc952005-11-04 07:18:36 +0000810 * Applies the range infos stored in global_settings to
811 * the peak meter.
Linus Nielsen Feltzingfd0cc3b2002-10-29 12:09:15 +0000812 */
813void settings_apply_pm_range(void)
814{
815 int pm_min, pm_max;
816
817 /* depending on the scale mode (dBfs or percent) the values
818 of global_settings.peak_meter_dbfs have different meanings */
Kevin Ferrarecbbdc952005-11-04 07:18:36 +0000819 if (global_settings.peak_meter_dbfs)
Linus Nielsen Feltzingfd0cc3b2002-10-29 12:09:15 +0000820 {
821 /* convert to dBfs * 100 */
822 pm_min = -(((int)global_settings.peak_meter_min) * 100);
823 pm_max = -(((int)global_settings.peak_meter_max) * 100);
824 }
Kevin Ferrarecbbdc952005-11-04 07:18:36 +0000825 else
Linus Nielsen Feltzingfd0cc3b2002-10-29 12:09:15 +0000826 {
827 /* percent is stored directly -> no conversion */
828 pm_min = global_settings.peak_meter_min;
829 pm_max = global_settings.peak_meter_max;
830 }
831
832 /* apply the range */
833 peak_meter_init_range(global_settings.peak_meter_dbfs, pm_min, pm_max);
834}
835#endif /* HAVE_LCD_BITMAP */
836
Linus Nielsen Feltzing7bade1a2004-07-06 12:17:14 +0000837void sound_settings_apply(void)
Linus Nielsen Feltzing40ffbb12002-10-03 09:31:01 +0000838{
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000839 sound_set(SOUND_BASS, global_settings.bass);
840 sound_set(SOUND_TREBLE, global_settings.treble);
841 sound_set(SOUND_BALANCE, global_settings.balance);
842 sound_set(SOUND_VOLUME, global_settings.volume);
843 sound_set(SOUND_CHANNELS, global_settings.channel_config);
844 sound_set(SOUND_STEREO_WIDTH, global_settings.stereo_width);
Anton Oleynikov2654d912005-12-04 14:33:10 +0000845#ifdef HAVE_UDA1380
846 sound_set(SOUND_SCALING, global_settings.sound_scaling);
847#endif
Jens Arnoldd6c05452005-08-29 21:15:27 +0000848#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +0000849 sound_set(SOUND_LOUDNESS, global_settings.loudness);
850 sound_set(SOUND_AVC, global_settings.avc);
851 sound_set(SOUND_MDB_STRENGTH, global_settings.mdb_strength);
852 sound_set(SOUND_MDB_HARMONICS, global_settings.mdb_harmonics);
853 sound_set(SOUND_MDB_CENTER, global_settings.mdb_center);
854 sound_set(SOUND_MDB_SHAPE, global_settings.mdb_shape);
855 sound_set(SOUND_MDB_ENABLE, global_settings.mdb_enable);
856 sound_set(SOUND_SUPERBASS, global_settings.superbass);
Linus Nielsen Feltzing40ffbb12002-10-03 09:31:01 +0000857#endif
Linus Nielsen Feltzing7bade1a2004-07-06 12:17:14 +0000858}
859
860void settings_apply(void)
861{
862 char buf[64];
863
864 sound_settings_apply();
Linus Nielsen Feltzing40ffbb12002-10-03 09:31:01 +0000865
Linus Nielsen Feltzing8a237a82005-04-04 12:06:29 +0000866 audio_set_buffer_margin(global_settings.buffer_margin);
Kevin Ferrarecbbdc952005-11-04 07:18:36 +0000867
Linus Nielsen Feltzing40ffbb12002-10-03 09:31:01 +0000868 lcd_set_contrast(global_settings.contrast);
869 lcd_scroll_speed(global_settings.scroll_speed);
Christian Gmeiner7c1879b2005-04-15 12:08:49 +0000870#ifdef HAVE_REMOTE_LCD
Jens Arnoldbd1bb5f2005-06-17 21:43:00 +0000871 lcd_remote_set_contrast(global_settings.remote_contrast);
872 lcd_remote_set_invert_display(global_settings.remote_invert);
873 lcd_remote_set_flip(global_settings.remote_flip_display);
Linus Nielsen Feltzing062a0b32005-11-20 09:54:57 +0000874 lcd_remote_scroll_speed(global_settings.scroll_speed);
875 lcd_remote_scroll_step(global_settings.scroll_step);
Anton Oleynikov67078922005-11-20 11:15:32 +0000876 lcd_remote_scroll_delay(global_settings.scroll_delay * (HZ/10));
Miika Pekkarinen93d8ca52005-11-19 09:26:02 +0000877#ifdef HAVE_REMOTE_LCD_TICKING
Miika Pekkarinenf9234b32005-11-19 08:05:03 +0000878 lcd_remote_emireduce(global_settings.remote_reduce_ticking);
Miika Pekkarinen93d8ca52005-11-19 09:26:02 +0000879#endif
Christian Gmeiner7477c092005-05-30 00:00:22 +0000880 remote_backlight_set_timeout(global_settings.remote_backlight_timeout);
Jens Arnolda6d409d2005-11-23 20:12:33 +0000881#ifdef HAVE_CHARGING
882 remote_backlight_set_timeout_plugged(global_settings.remote_backlight_timeout_plugged);
883#endif
Jens Arnoldbd1bb5f2005-06-17 21:43:00 +0000884#endif
Jens Arnoldb51f7df2005-11-21 23:55:39 +0000885#ifdef CONFIG_BACKLIGHT
Linus Nielsen Feltzing40ffbb12002-10-03 09:31:01 +0000886 backlight_set_timeout(global_settings.backlight_timeout);
Jens Arnoldb51f7df2005-11-21 23:55:39 +0000887#ifdef HAVE_CHARGING
Jens Arnolda6d409d2005-11-23 20:12:33 +0000888 backlight_set_timeout_plugged(global_settings.backlight_timeout_plugged);
Jens Arnoldb51f7df2005-11-21 23:55:39 +0000889#endif
890#if (CONFIG_BACKLIGHT == BL_IRIVER_H100) && !defined(SIMULATOR)
Jens Arnold61b9d342005-06-20 17:03:09 +0000891 backlight_set_fade_in(global_settings.backlight_fade_in);
892 backlight_set_fade_out(global_settings.backlight_fade_out);
893#endif
Jens Arnoldb51f7df2005-11-21 23:55:39 +0000894#endif
Linus Nielsen Feltzing40ffbb12002-10-03 09:31:01 +0000895 ata_spindown(global_settings.disk_spindown);
Jens Arnold8051a0b2005-11-06 23:12:11 +0000896#if (CONFIG_CODEC == MAS3507D) && !defined(SIMULATOR)
Linus Nielsen Feltzingc22b4112003-11-03 23:36:36 +0000897 dac_line_in(global_settings.line_in);
898#endif
Jens Arnold61a25502005-09-11 12:07:13 +0000899 mpeg_id3_options(global_settings.id3_v1_first);
Björn Stenbergf1a68552003-02-12 09:02:55 +0000900#ifdef HAVE_ATA_POWER_OFF
Björn Stenberg3d4cc9b2002-11-29 13:57:00 +0000901 ata_poweroff(global_settings.disk_poweroff);
Robert Hak0789d422002-11-30 09:42:13 +0000902#endif
903
Linus Nielsen Feltzing40ffbb12002-10-03 09:31:01 +0000904 set_poweroff_timeout(global_settings.poweroff);
Björn Stenbergdea31222002-10-08 15:42:40 +0000905
Uwe Freese0bf70e62002-12-16 22:58:48 +0000906 set_battery_capacity(global_settings.battery_capacity);
Jens Arnold91846a12005-01-30 16:25:46 +0000907#if BATTERY_TYPES_COUNT > 1
908 set_battery_type(global_settings.battery_type);
909#endif
Uwe Freese0bf70e62002-12-16 22:58:48 +0000910
Linus Nielsen Feltzingfd0cc3b2002-10-29 12:09:15 +0000911#ifdef HAVE_LCD_BITMAP
Björn Stenbergb1079202003-02-27 14:22:30 +0000912 lcd_set_invert_display(global_settings.invert);
Jörg Hohensohna5e1d062003-12-20 10:00:37 +0000913 lcd_set_flip(global_settings.flip_display);
914 button_set_flip(global_settings.flip_display);
915 lcd_update(); /* refresh after flipping the screen */
Linus Nielsen Feltzingfd0cc3b2002-10-29 12:09:15 +0000916 settings_apply_pm_range();
917 peak_meter_init_times(
Kevin Ferrarecbbdc952005-11-04 07:18:36 +0000918 global_settings.peak_meter_release, global_settings.peak_meter_hold,
Linus Nielsen Feltzingfd0cc3b2002-10-29 12:09:15 +0000919 global_settings.peak_meter_clip_hold);
920#endif
921
Kevin Ferrarecbbdc952005-11-04 07:18:36 +0000922 if ( global_settings.wps_file[0] &&
Björn Stenberg746501f2002-10-09 08:51:08 +0000923 global_settings.wps_file[0] != 0xff ) {
Daniel Stenberg0b4576c2005-11-12 21:48:06 +0000924 snprintf(buf, sizeof buf, WPS_DIR "/%s.wps",
Björn Stenbergdea31222002-10-08 15:42:40 +0000925 global_settings.wps_file);
Daniel Stenberg09fce702005-11-18 09:03:25 +0000926 wps_data_load(gui_wps[0].data, buf, true, false);
Björn Stenbergdea31222002-10-08 15:42:40 +0000927 }
Björn Stenberg227253c2002-10-09 23:13:25 +0000928 else
Daniel Stenberg09fce702005-11-18 09:03:25 +0000929 wps_data_init(gui_wps[0].data);
Christi Scarborough4c0b83f2005-11-17 20:14:59 +0000930
Magnus Holmgrenf9fa33f2005-12-04 12:11:08 +0000931#if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1)
Christi Scarborough4c0b83f2005-11-17 20:14:59 +0000932 if ( global_settings.rwps_file[0] &&
933 global_settings.rwps_file[0] != 0xff ) {
934 snprintf(buf, sizeof buf, WPS_DIR "/%s.rwps",
935 global_settings.rwps_file);
Daniel Stenberg09fce702005-11-18 09:03:25 +0000936 wps_data_load(gui_wps[1].data, buf, true, false);
Christi Scarborough4c0b83f2005-11-17 20:14:59 +0000937 }
938 else
Daniel Stenberg09fce702005-11-18 09:03:25 +0000939 wps_data_init(gui_wps[1].data);
Christi Scarborough4c0b83f2005-11-17 20:14:59 +0000940#endif
Björn Stenberg227253c2002-10-09 23:13:25 +0000941
Björn Stenbergdea31222002-10-08 15:42:40 +0000942#ifdef HAVE_LCD_BITMAP
Björn Stenberg746501f2002-10-09 08:51:08 +0000943 if ( global_settings.font_file[0] &&
944 global_settings.font_file[0] != 0xff ) {
Daniel Stenberg0f689582004-01-08 12:40:25 +0000945 snprintf(buf, sizeof buf, ROCKBOX_DIR FONT_DIR "/%s.fnt",
Björn Stenbergdea31222002-10-08 15:42:40 +0000946 global_settings.font_file);
947 font_load(buf);
948 }
Björn Stenberg227253c2002-10-09 23:13:25 +0000949 else
950 font_reset();
Björn Stenberga2e98c12002-12-12 15:20:37 +0000951
Björn Stenberga2e98c12002-12-12 15:20:37 +0000952 lcd_scroll_step(global_settings.scroll_step);
Kjell Ericson53f156a2003-05-22 06:42:14 +0000953#else
954 lcd_jump_scroll(global_settings.jump_scroll);
Kjell Ericson849469a2003-05-28 09:00:27 +0000955 lcd_jump_scroll_delay(global_settings.jump_scroll_delay * (HZ/10));
Björn Stenbergdea31222002-10-08 15:42:40 +0000956#endif
Björn Stenbergf0d02aa2003-02-12 09:07:48 +0000957 lcd_bidir_scroll(global_settings.bidir_limit);
Björn Stenberga2e98c12002-12-12 15:20:37 +0000958 lcd_scroll_delay(global_settings.scroll_delay * (HZ/10));
Björn Stenberg227253c2002-10-09 23:13:25 +0000959
Björn Stenberg746501f2002-10-09 08:51:08 +0000960 if ( global_settings.lang_file[0] &&
961 global_settings.lang_file[0] != 0xff ) {
Daniel Stenberg0f689582004-01-08 12:40:25 +0000962 snprintf(buf, sizeof buf, ROCKBOX_DIR LANG_DIR "/%s.lng",
Björn Stenbergdea31222002-10-08 15:42:40 +0000963 global_settings.lang_file);
964 lang_load(buf);
Jörg Hohensohn6e77d1f2004-04-06 07:06:59 +0000965 talk_init(); /* use voice of same language */
Björn Stenbergdea31222002-10-08 15:42:40 +0000966 }
Linus Nielsen Feltzing6271b2b2005-06-09 09:47:00 +0000967
Marcoen Hirschbergb0fee172005-12-06 13:27:15 +0000968 set_codepage(global_settings.default_codepage);
969
Jens Arnoldd6c05452005-08-29 21:15:27 +0000970#if CONFIG_CODEC == SWCODEC
Miika Pekkarinen90161c92005-07-22 16:46:27 +0000971 audio_set_crossfade(global_settings.crossfade);
Magnus Holmgren4b711c22005-09-24 15:22:48 +0000972 dsp_set_replaygain(true);
Marcoen Hirschberge13fad32005-11-14 21:56:56 +0000973 dsp_set_crossfeed(global_settings.crossfeed);
Linus Nielsen Feltzing6271b2b2005-06-09 09:47:00 +0000974#endif
Linus Nielsen Feltzing8782bc82005-07-01 09:42:39 +0000975
976#ifdef HAVE_SPDIF_POWER
977 spdif_power_enable(global_settings.spdif_enable);
978#endif
Linus Nielsen Feltzing40ffbb12002-10-03 09:31:01 +0000979}
980
Jörg Hohensohn44171b92004-06-18 20:41:59 +0000981
982/* helper to load global_settings from a bitfield, as described per table */
983static void load_bit_table(const struct bit_entry* p_table, int count, int bitstart)
984{
985 unsigned long* p_bitfield = (unsigned long*)config_block; /* 32 bit addr. */
986 unsigned long value; /* 32 bit content */
987 int i;
988 int maxbit; /* how many bits are valid in the saved part */
989 const struct bit_entry* p_run = p_table; /* start after the size info */
990 count--; /* first is excluded from loop */
991 maxbit = get_bits(p_bitfield, bitstart, p_table->bit_size);
992 bitstart += p_table->bit_size;
993
994 for (i=0; i<count; i++)
995 {
996 int size;
997 p_run++;
998
999 size = p_run->bit_size & 0x3F; /* mask off abused bits */
1000 if (bitstart + size > maxbit)
1001 break; /* exit if this is not valid any more in bitfield */
1002
1003 value = get_bits(p_bitfield, bitstart, size);
1004 bitstart += size;
1005 if (p_run->bit_size & SIGNED)
1006 { // sign extend the read value
1007 unsigned long mask = 0xFFFFFFFF << (size - 1);
1008 if (value & mask) /* true if MSB of value is set */
1009 value |= mask;
1010 }
1011
1012 /* could do a memcpy, but that would be endian-dependent */
1013 switch(p_run->byte_size)
1014 {
1015 case 1:
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001016 ((unsigned char*)&global_settings)[p_run->settings_offset] =
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001017 (unsigned char)value;
1018 break;
1019 case 2:
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001020 ((unsigned short*)&global_settings)[p_run->settings_offset/2] =
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001021 (unsigned short)value;
1022 break;
1023 case 4:
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001024 ((unsigned int*)&global_settings)[p_run->settings_offset/4] =
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001025 (unsigned int)value;
1026 break;
1027 default:
1028 DEBUGF( "illegal size!" );
1029 continue;
1030 }
1031 }
1032}
1033
1034
Björn Stenbergf80d8a702002-06-27 00:20:00 +00001035/*
Björn Stenberg6b25f792002-07-15 11:02:12 +00001036 * load settings from disk or RTC RAM
Björn Stenbergf80d8a702002-06-27 00:20:00 +00001037 */
Jörg Hohensohn6ff6d212004-06-19 15:50:02 +00001038void settings_load(int which)
Björn Stenbergf80d8a702002-06-27 00:20:00 +00001039{
Björn Stenbergf80d8a702002-06-27 00:20:00 +00001040 DEBUGF( "reload_all_settings()\n" );
1041
Björn Stenberg6b25f792002-07-15 11:02:12 +00001042 /* load the buffer from the RTC (resets it to all-unused if the block
1043 is invalid) and decode the settings which are set in the block */
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001044 if (!load_config_buffer(which))
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001045 {
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001046 /* load scalar values from RTC and HD sector, specified via table */
Jörg Hohensohn6ff6d212004-06-19 15:50:02 +00001047 if (which & SETTINGS_RTC)
1048 {
1049 load_bit_table(rtc_bits, sizeof(rtc_bits)/sizeof(rtc_bits[0]), 4*8);
1050 }
1051 if (which & SETTINGS_HD)
1052 {
Jens Arnold05af2802005-07-28 08:36:24 +00001053 load_bit_table(hd_bits, sizeof(hd_bits)/sizeof(hd_bits[0]),
Jörg Hohensohn6ff6d212004-06-19 15:50:02 +00001054 RTC_BLOCK_SIZE*8);
1055 }
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001056
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001057 if ( global_settings.contrast < MIN_CONTRAST_SETTING )
1058 global_settings.contrast = lcd_default_contrast();
Linus Nielsen Feltzing20d031f2003-05-09 16:01:21 +00001059
Daniel Stenbergf981ea92005-12-05 22:44:42 +00001060 strncpy((char *)global_settings.wps_file, (char *)&config_block[0xb8],
1061 MAX_FILENAME);
1062 strncpy((char *)global_settings.lang_file, (char *)&config_block[0xcc],
1063 MAX_FILENAME);
1064 strncpy((char *)global_settings.font_file, (char *)&config_block[0xe0],
1065 MAX_FILENAME);
Christi Scarborough4c0b83f2005-11-17 20:14:59 +00001066#ifdef HAVE_REMOTE_LCD
Daniel Stenbergf981ea92005-12-05 22:44:42 +00001067 strncpy((char *)global_settings.rwps_file, (char *)&config_block[0xf4],
1068 MAX_FILENAME);
Christi Scarborough4c0b83f2005-11-17 20:14:59 +00001069#endif
Jörg Hohensohn6ff6d212004-06-19 15:50:02 +00001070 }
Björn Stenbergf80d8a702002-06-27 00:20:00 +00001071}
1072
Björn Stenbergbda4ec12003-02-17 09:53:11 +00001073void set_file(char* filename, char* setting, int maxlen)
1074{
1075 char* fptr = strrchr(filename,'/');
1076 int len;
1077 int extlen = 0;
1078 char* ptr;
1079
1080 if (!fptr)
1081 return;
1082
1083 *fptr = 0;
1084 fptr++;
1085
1086 len = strlen(fptr);
1087 ptr = fptr + len;
1088 while (*ptr != '.') {
1089 extlen++;
1090 ptr--;
1091 }
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001092
Henrik Backec8e27912004-09-05 16:43:31 +00001093 if (strncasecmp(ROCKBOX_DIR, filename ,strlen(ROCKBOX_DIR)) ||
Daniel Stenberg0f689582004-01-08 12:40:25 +00001094 (len-extlen > maxlen))
Björn Stenbergbda4ec12003-02-17 09:53:11 +00001095 return;
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001096
Björn Stenbergbda4ec12003-02-17 09:53:11 +00001097 strncpy(setting, fptr, len-extlen);
1098 setting[len-extlen]=0;
1099
1100 settings_save();
1101}
1102
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001103/* helper to sort a .cfg file entry into a global_settings member,
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001104 as described per table. Returns the position if found, else 0. */
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001105static int load_cfg_table(
1106 const struct bit_entry* p_table, /* the table which describes the entries */
1107 int count, /* number of entries in the table, including the first */
Jens Arnold8fb33612004-08-18 01:09:31 +00001108 const char* name, /* the item to be searched */
1109 const char* value, /* the value which got loaded for that item */
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001110 int hint) /* position to start looking */
Björn Stenberg0e6088f2002-10-02 16:33:26 +00001111{
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001112 int i = hint;
Björn Stenberg0e6088f2002-10-02 16:33:26 +00001113
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001114 do
Björn Stenberg0e6088f2002-10-02 16:33:26 +00001115 {
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001116 if (p_table[i].cfg_name != NULL && !strcasecmp(name, p_table[i].cfg_name))
1117 { /* found */
1118 int val = 0;
1119 if (p_table[i].cfg_val == NULL)
1120 { /* numerical value, just convert the string */
1121 val = atoi(value);
1122 }
1123 else
1124 { /* set of string values, find the index */
1125 const char* item;
1126 const char* run;
1127 int len = strlen(value);
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001128
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001129 item = run = p_table[i].cfg_val;
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001130
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001131 while(1)
1132 {
1133 /* count the length of the field */
1134 while (*run != ',' && *run != '\0')
1135 run++;
Björn Stenberg0e6088f2002-10-02 16:33:26 +00001136
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001137 if (!strncasecmp(value, item, MAX(run-item, len)))
1138 break; /* match, exit the search */
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001139
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001140 if (*run == '\0') /* reached the end of the choices */
1141 return i; /* return the position, but don't update */
Linus Nielsen Feltzingc843ba42002-10-29 12:16:36 +00001142
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001143 val++; /* count the item up */
1144 run++; /* behind the ',' */
1145 item = run;
1146 }
1147 }
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001148
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001149 /* could do a memcpy, but that would be endian-dependent */
1150 switch(p_table[i].byte_size)
1151 {
1152 case 1:
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001153 ((unsigned char*)&global_settings)[p_table[i].settings_offset] =
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001154 (unsigned char)val;
1155 break;
1156 case 2:
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001157 ((unsigned short*)&global_settings)[p_table[i].settings_offset/2] =
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001158 (unsigned short)val;
1159 break;
1160 case 4:
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001161 ((unsigned int*)&global_settings)[p_table[i].settings_offset/4] =
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001162 (unsigned int)val;
1163 break;
1164 default:
1165 DEBUGF( "illegal size!" );
1166 continue;
1167 }
Björn Stenberg0e6088f2002-10-02 16:33:26 +00001168
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001169 return i; /* return the position */
Björn Stenberg9c16e122003-02-14 14:14:55 +00001170 }
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001171
1172 i++;
1173 if (i==count)
1174 i=1; /* wraparound */
1175 } while (i != hint); /* back where we started, all searched */
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001176
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001177 return 0; /* indicate not found */
Björn Stenberg9c16e122003-02-14 14:14:55 +00001178}
1179
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001180
Jens Arnold8fb33612004-08-18 01:09:31 +00001181bool settings_load_config(const char* file)
Justin Heinere4a27612002-09-05 01:20:10 +00001182{
Justin Heinere4a27612002-09-05 01:20:10 +00001183 int fd;
Björn Stenberg0e6088f2002-10-02 16:33:26 +00001184 char line[128];
Justin Heinere4a27612002-09-05 01:20:10 +00001185
1186 fd = open(file, O_RDONLY);
Björn Stenbergf0c07652003-04-11 07:47:30 +00001187 if (fd < 0)
Björn Stenberg0e6088f2002-10-02 16:33:26 +00001188 return false;
Eric Linenberg8d47c5c2002-09-17 12:48:56 +00001189
Linus Nielsen Feltzingc843ba42002-10-29 12:16:36 +00001190 while (read_line(fd, line, sizeof line) > 0)
Björn Stenberg0e6088f2002-10-02 16:33:26 +00001191 {
1192 char* name;
1193 char* value;
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001194 const struct bit_entry* table[2] = { rtc_bits, hd_bits };
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001195 const int ta_size[2] = {
1196 sizeof(rtc_bits)/sizeof(rtc_bits[0]),
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001197 sizeof(hd_bits)/sizeof(hd_bits[0])
1198 };
1199 int last_table = 0; /* which table was used last round */
1200 int last_pos = 1; /* at which position did we succeed */
1201 int pos; /* currently returned position */
Björn Stenberg0e6088f2002-10-02 16:33:26 +00001202
1203 if (!settings_parseline(line, &name, &value))
1204 continue;
1205
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001206 /* check for the string values */
1207 if (!strcasecmp(name, "wps")) {
Daniel Stenberg09fce702005-11-18 09:03:25 +00001208 if (wps_data_load(gui_wps[0].data,value,true, false))
Daniel Stenbergf981ea92005-12-05 22:44:42 +00001209 set_file(value, (char *)global_settings.wps_file, MAX_FILENAME);
Björn Stenbergbda4ec12003-02-17 09:53:11 +00001210 }
Magnus Holmgrenf9fa33f2005-12-04 12:11:08 +00001211#if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1)
Christi Scarborough4c0b83f2005-11-17 20:14:59 +00001212 else if (!strcasecmp(name, "rwps")) {
Daniel Stenberg09fce702005-11-18 09:03:25 +00001213 if (wps_data_load(gui_wps[1].data,value,true, false))
Daniel Stenbergf981ea92005-12-05 22:44:42 +00001214 set_file(value, (char *)global_settings.rwps_file, MAX_FILENAME);
Christi Scarborough4c0b83f2005-11-17 20:14:59 +00001215 }
1216#endif
Björn Stenbergbda4ec12003-02-17 09:53:11 +00001217 else if (!strcasecmp(name, "lang")) {
1218 if (!lang_load(value))
Jörg Hohensohn6e77d1f2004-04-06 07:06:59 +00001219 {
Daniel Stenbergf981ea92005-12-05 22:44:42 +00001220 set_file(value, (char *)global_settings.lang_file, MAX_FILENAME);
Jörg Hohensohn6e77d1f2004-04-06 07:06:59 +00001221 talk_init(); /* use voice of same language */
1222 }
Björn Stenbergbda4ec12003-02-17 09:53:11 +00001223 }
Björn Stenberg9c16e122003-02-14 14:14:55 +00001224#ifdef HAVE_LCD_BITMAP
Björn Stenberg82054dc2003-02-23 18:54:28 +00001225 else if (!strcasecmp(name, "font")) {
Björn Stenberg45a84132003-02-24 23:47:21 +00001226 if (font_load(value))
Daniel Stenbergf981ea92005-12-05 22:44:42 +00001227 set_file(value, (char *)global_settings.font_file, MAX_FILENAME);
Björn Stenberg82054dc2003-02-23 18:54:28 +00001228 }
Björn Stenbergbda4ec12003-02-17 09:53:11 +00001229#endif
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001230
1231 /* check for scalar values, using the two tables */
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001232 pos = load_cfg_table(table[last_table], ta_size[last_table],
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001233 name, value, last_pos);
1234 if (pos) /* success */
Björn Stenberga108ec22004-01-14 00:13:04 +00001235 {
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001236 last_pos = pos; /* remember as a position hint for next round */
1237 continue;
Björn Stenberga108ec22004-01-14 00:13:04 +00001238 }
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001239
1240 last_table = 1-last_table; /* try other table */
1241 last_pos = 1; /* search from start */
1242 pos = load_cfg_table(table[last_table], ta_size[last_table],
1243 name, value, last_pos);
1244 if (pos) /* success */
Björn Stenberga108ec22004-01-14 00:13:04 +00001245 {
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001246 last_pos = pos; /* remember as a position hint for next round */
1247 continue;
Jörg Hohensohn3aa99e12004-03-27 00:11:01 +00001248 }
Justin Heinere4a27612002-09-05 01:20:10 +00001249 }
Björn Stenberg0e6088f2002-10-02 16:33:26 +00001250
1251 close(fd);
Björn Stenberg9c16e122003-02-14 14:14:55 +00001252 settings_apply();
Björn Stenbergf9d34862002-10-02 16:37:05 +00001253 settings_save();
Björn Stenberg0e6088f2002-10-02 16:33:26 +00001254 return true;
Justin Heinere4a27612002-09-05 01:20:10 +00001255}
Justin Heinere4a27612002-09-05 01:20:10 +00001256
Björn Stenbergc5aaab42003-03-10 16:31:02 +00001257
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001258/* helper to save content of global_settings into a file,
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001259 as described per table */
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001260static void save_cfg_table(const struct bit_entry* p_table, int count, int fd)
1261{
1262 long value; /* 32 bit content */
1263 int i;
1264 const struct bit_entry* p_run = p_table; /* start after the size info */
1265 count--; /* first is excluded from loop */
1266
1267 for (i=0; i<count; i++)
1268 {
1269 p_run++;
1270
1271 if (p_run->cfg_name == NULL)
1272 continue; /* this value is not to be saved */
1273
1274 /* could do a memcpy, but that would be endian-dependent */
1275 switch(p_run->byte_size)
1276 {
1277 case 1:
1278 if (p_run->bit_size & SIGNED) /* signed? */
1279 value = ((char*)&global_settings)[p_run->settings_offset];
1280 else
1281 value = ((unsigned char*)&global_settings)[p_run->settings_offset];
1282 break;
1283 case 2:
1284 if (p_run->bit_size & SIGNED) /* signed? */
1285 value = ((short*)&global_settings)[p_run->settings_offset/2];
1286 else
1287 value = ((unsigned short*)&global_settings)[p_run->settings_offset/2];
1288 break;
1289 case 4:
1290 value = ((unsigned int*)&global_settings)[p_run->settings_offset/4];
1291 break;
1292 default:
1293 DEBUGF( "illegal size!" );
1294 continue;
1295 }
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001296
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001297 if (p_run->cfg_val == NULL) /* write as number */
1298 {
Daniel Stenberg22b77012005-02-22 12:19:12 +00001299 fdprintf(fd, "%s: %ld\r\n", p_run->cfg_name, value);
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001300 }
1301 else /* write as item */
1302 {
1303 const char* p = p_run->cfg_val;
1304
Daniel Stenberg22b77012005-02-22 12:19:12 +00001305 fdprintf(fd, "%s: ", p_run->cfg_name);
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001306
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001307 while(value >= 0)
1308 {
1309 char c = *p++; /* currently processed char */
1310 if (c == ',') /* separator */
1311 value--;
1312 else if (c == '\0') /* end of string */
1313 break; /* not found */
1314 else if (value == 0) /* the right place */
1315 write(fd, &c, 1); /* char by char, this is lame, OK */
1316 }
1317
Daniel Stenberg22b77012005-02-22 12:19:12 +00001318 fdprintf(fd, "\r\n");
Jörg Hohensohn986675d2004-06-23 08:12:19 +00001319 if (p_run->cfg_val != off_on) /* explaination for non-bool */
Daniel Stenberg22b77012005-02-22 12:19:12 +00001320 fdprintf(fd, "# (possible values: %s)\r\n", p_run->cfg_val);
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001321 }
1322 }
1323}
1324
1325
Björn Stenbergc5aaab42003-03-10 16:31:02 +00001326bool settings_save_config(void)
1327{
Jens Arnold58e94122005-09-02 01:15:35 +00001328 int fd;
Björn Stenbergc5aaab42003-03-10 16:31:02 +00001329 char filename[MAX_PATH];
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001330
Jens Arnold58e94122005-09-02 01:15:35 +00001331 create_numbered_filename(filename, ROCKBOX_DIR, "config", ".cfg", 2);
Björn Stenbergc5aaab42003-03-10 16:31:02 +00001332
1333 /* allow user to modify filename */
Jens Arnold58e94122005-09-02 01:15:35 +00001334 while (true) {
Björn Stenbergc5aaab42003-03-10 16:31:02 +00001335 if (!kbd_input(filename, sizeof filename)) {
1336 fd = creat(filename,0);
Kevin Ferrare9ccca4a2005-11-04 17:25:29 +00001337 if (fd < 0)
1338 gui_syncsplash(HZ, true, str(LANG_FAILED));
Björn Stenbergc5aaab42003-03-10 16:31:02 +00001339 else
Jens Arnold58e94122005-09-02 01:15:35 +00001340 break;
Björn Stenbergc5aaab42003-03-10 16:31:02 +00001341 }
Jens Arnold58e94122005-09-02 01:15:35 +00001342 else {
Kevin Ferrare9ccca4a2005-11-04 17:25:29 +00001343 gui_syncsplash(HZ, true, str(LANG_RESET_DONE_CANCEL));
Jens Arnold58e94122005-09-02 01:15:35 +00001344 return false;
1345 }
Björn Stenbergc5aaab42003-03-10 16:31:02 +00001346 }
1347
Jens Arnold58e94122005-09-02 01:15:35 +00001348 fdprintf(fd, "# .cfg file created by rockbox %s - "
1349 "http://www.rockbox.org\r\n#\r\n"
1350 "#\r\n# wps / language / font \r\n#\r\n", appsversion);
Björn Stenbergc5aaab42003-03-10 16:31:02 +00001351
Björn Stenberge4e46652003-04-24 17:53:17 +00001352 if (global_settings.wps_file[0] != 0)
Daniel Stenberg0b4576c2005-11-12 21:48:06 +00001353 fdprintf(fd, "wps: %s/%s.wps\r\n", WPS_DIR,
Jens Arnold58e94122005-09-02 01:15:35 +00001354 global_settings.wps_file);
Björn Stenbergc5aaab42003-03-10 16:31:02 +00001355
Christi Scarborough4c0b83f2005-11-17 20:14:59 +00001356#ifdef HAVE_REMOTE_LCD
1357 if (global_settings.rwps_file[0] != 0)
1358 fdprintf(fd, "rwps: %s/%s.rwps\r\n", WPS_DIR,
1359 global_settings.rwps_file);
1360#endif
1361
Björn Stenberge4e46652003-04-24 17:53:17 +00001362 if (global_settings.lang_file[0] != 0)
Jens Arnold58e94122005-09-02 01:15:35 +00001363 fdprintf(fd, "lang: %s/%s.lng\r\n", ROCKBOX_DIR LANG_DIR,
1364 global_settings.lang_file);
Björn Stenbergc5aaab42003-03-10 16:31:02 +00001365
1366#ifdef HAVE_LCD_BITMAP
Björn Stenberge4e46652003-04-24 17:53:17 +00001367 if (global_settings.font_file[0] != 0)
Daniel Stenberg22b77012005-02-22 12:19:12 +00001368 fdprintf(fd, "font: %s/%s.fnt\r\n", ROCKBOX_DIR FONT_DIR,
Jens Arnold58e94122005-09-02 01:15:35 +00001369 global_settings.font_file);
Björn Stenbergc5aaab42003-03-10 16:31:02 +00001370#endif
1371
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001372 /* here's the action: write values to file, specified via table */
1373 save_cfg_table(rtc_bits, sizeof(rtc_bits)/sizeof(rtc_bits[0]), fd);
1374 save_cfg_table(hd_bits, sizeof(hd_bits)/sizeof(hd_bits[0]), fd);
Björn Stenbergc5aaab42003-03-10 16:31:02 +00001375
Björn Stenbergc5aaab42003-03-10 16:31:02 +00001376 close(fd);
1377
Daniel Stenbergf981ea92005-12-05 22:44:42 +00001378 gui_syncsplash(HZ, true, (unsigned char *)"%s %s", str(LANG_SETTINGS_SAVED1),
Jens Arnold58e94122005-09-02 01:15:35 +00001379 str(LANG_SETTINGS_SAVED2));
Björn Stenbergc5aaab42003-03-10 16:31:02 +00001380 return true;
1381}
1382
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001383
1384/* helper to load defaults from table into global_settings members */
1385static void default_table(const struct bit_entry* p_table, int count)
1386{
1387 int i;
1388
1389 for (i=1; i<count; i++) /* exclude the first, the size placeholder */
1390 {
1391 /* could do a memcpy, but that would be endian-dependent */
1392 switch(p_table[i].byte_size)
1393 {
1394 case 1:
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001395 ((unsigned char*)&global_settings)[p_table[i].settings_offset] =
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001396 (unsigned char)p_table[i].default_val;
1397 break;
1398 case 2:
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001399 ((unsigned short*)&global_settings)[p_table[i].settings_offset/2] =
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001400 (unsigned short)p_table[i].default_val;
1401 break;
1402 case 4:
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001403 ((unsigned int*)&global_settings)[p_table[i].settings_offset/4] =
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001404 (unsigned int)p_table[i].default_val;
1405 break;
1406 default:
1407 DEBUGF( "illegal size!" );
1408 continue;
1409 }
1410 }
1411}
1412
1413
Björn Stenbergf80d8a702002-06-27 00:20:00 +00001414/*
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001415 * reset all settings to their default value
Björn Stenbergf80d8a702002-06-27 00:20:00 +00001416 */
Björn Stenberg6b25f792002-07-15 11:02:12 +00001417void settings_reset(void) {
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001418
Björn Stenberg6b25f792002-07-15 11:02:12 +00001419 DEBUGF( "settings_reset()\n" );
Björn Stenbergf80d8a702002-06-27 00:20:00 +00001420
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001421 /* read defaults from table(s) into global_settings */
1422 default_table(rtc_bits, sizeof(rtc_bits)/sizeof(rtc_bits[0]));
1423 default_table(hd_bits, sizeof(hd_bits)/sizeof(hd_bits[0]));
1424
1425 /* do some special cases not covered by table */
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +00001426 global_settings.volume = sound_default(SOUND_VOLUME);
1427 global_settings.balance = sound_default(SOUND_BALANCE);
1428 global_settings.bass = sound_default(SOUND_BASS);
1429 global_settings.treble = sound_default(SOUND_TREBLE);
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +00001430 global_settings.channel_config = sound_default(SOUND_CHANNELS);
1431 global_settings.stereo_width = sound_default(SOUND_STEREO_WIDTH);
Anton Oleynikov2654d912005-12-04 14:33:10 +00001432#ifdef HAVE_UDA1380
1433 global_settings.sound_scaling = sound_default(SOUND_SCALING);
1434#endif
Jens Arnold8051a0b2005-11-06 23:12:11 +00001435#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
1436 global_settings.loudness = sound_default(SOUND_LOUDNESS);
1437 global_settings.avc = sound_default(SOUND_AVC);
Linus Nielsen Feltzing674eaca2005-04-01 13:41:03 +00001438 global_settings.mdb_strength = sound_default(SOUND_MDB_STRENGTH);
1439 global_settings.mdb_harmonics = sound_default(SOUND_MDB_HARMONICS);
1440 global_settings.mdb_center = sound_default(SOUND_MDB_CENTER);
1441 global_settings.mdb_shape = sound_default(SOUND_MDB_SHAPE);
1442 global_settings.mdb_enable = sound_default(SOUND_MDB_ENABLE);
1443 global_settings.superbass = sound_default(SOUND_SUPERBASS);
Jens Arnold8051a0b2005-11-06 23:12:11 +00001444#endif
Björn Stenberg067262d2003-07-09 23:07:49 +00001445 global_settings.contrast = lcd_default_contrast();
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001446 global_settings.wps_file[0] = '\0';
Christi Scarborough4c0b83f2005-11-17 20:14:59 +00001447#ifdef HAVE_REMOTE_LCD
1448 global_settings.rwps_file[0] = '\0';
1449#endif
Jörg Hohensohn44171b92004-06-18 20:41:59 +00001450 global_settings.font_file[0] = '\0';
1451 global_settings.lang_file[0] = '\0';
1452
Björn Stenbergf80d8a702002-06-27 00:20:00 +00001453}
Björn Stenberg60b356e2002-06-27 01:08:11 +00001454
Jens Arnold8fb33612004-08-18 01:09:31 +00001455bool set_bool(const char* string, bool* variable )
Björn Stenberg60b356e2002-06-27 01:08:11 +00001456{
Jens Arnold49608082005-10-16 11:15:51 +00001457 return set_bool_options(string, variable,
Daniel Stenbergf981ea92005-12-05 22:44:42 +00001458 (char *)STR(LANG_SET_BOOL_YES),
1459 (char *)STR(LANG_SET_BOOL_NO),
1460 NULL);
Björn Stenberg26712d52003-06-05 11:11:10 +00001461}
1462
1463/* wrapper to convert from int param to bool param in set_option */
1464static void (*boolfunction)(bool);
1465void bool_funcwrapper(int value)
1466{
1467 if (value)
1468 boolfunction(true);
1469 else
1470 boolfunction(false);
Eric Linenbergc5b645b2002-09-05 04:42:12 +00001471}
Björn Stenberg60b356e2002-06-27 01:08:11 +00001472
Jens Arnold8fb33612004-08-18 01:09:31 +00001473bool set_bool_options(const char* string, bool* variable,
1474 const char* yes_str, int yes_voice,
1475 const char* no_str, int no_voice,
Jörg Hohensohn42ffbf92004-03-15 08:27:51 +00001476 void (*function)(bool))
Eric Linenbergc5b645b2002-09-05 04:42:12 +00001477{
Daniel Stenbergf981ea92005-12-05 22:44:42 +00001478 struct opt_items names[] = {
1479 {(unsigned char *)no_str, no_voice},
1480 {(unsigned char *)yes_str, yes_voice}
1481 };
Björn Stenbergb1b8bd42002-09-24 17:22:12 +00001482 bool result;
1483
Björn Stenberg26712d52003-06-05 11:11:10 +00001484 boolfunction = function;
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001485 result = set_option(string, variable, BOOL, names, 2,
Björn Stenberg26712d52003-06-05 11:11:10 +00001486 function ? bool_funcwrapper : NULL);
Björn Stenbergb1b8bd42002-09-24 17:22:12 +00001487 return result;
Björn Stenberg60b356e2002-06-27 01:08:11 +00001488}
1489
Kevin Ferrare81411a82005-11-05 02:19:21 +00001490void talk_unit(int unit, int value)
1491{
1492 if (global_settings.talk_menu)
1493 {
1494 if (unit < UNIT_LAST)
1495 { /* use the available unit definition */
1496 talk_value(value, unit, false);
1497 }
1498 else
1499 { /* say the number, followed by an arbitrary voice ID */
1500 talk_number(value, false);
1501 talk_id(unit, true);
1502 }
1503 }
1504}
1505
Daniel Stenbergf981ea92005-12-05 22:44:42 +00001506bool set_int(const unsigned char* string,
Jens Arnold8fb33612004-08-18 01:09:31 +00001507 const char* unit,
Jörg Hohensohnbeec2e92004-03-20 16:49:58 +00001508 int voice_unit,
Björn Stenberg60b356e2002-06-27 01:08:11 +00001509 int* variable,
1510 void (*function)(int),
1511 int step,
1512 int min,
Magnus Holmgren5a8eac12005-08-11 18:56:20 +00001513 int max,
1514 void (*formatter)(char*, int, int, const char*) )
Björn Stenberg60b356e2002-06-27 01:08:11 +00001515{
Linus Nielsen Feltzingc3eb83c2002-09-19 09:00:25 +00001516 int button;
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001517 int oldvalue=*variable;
1518 struct gui_select select;
Daniel Stenbergf981ea92005-12-05 22:44:42 +00001519 gui_select_init_numeric(&select, (char *)string, *variable, min, max, step, unit,
1520 formatter);
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001521 gui_syncselect_draw(&select);
Kevin Ferrare81411a82005-11-05 02:19:21 +00001522 talk_unit(voice_unit, *variable);
Daniel Stenbergb05eec82005-12-05 23:37:14 +00001523 while (!select.validated)
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001524 {
Linus Nielsen Feltzingc3eb83c2002-09-19 09:00:25 +00001525 button = button_get_w_tmo(HZ/2);
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001526 if(gui_syncselect_do_button(&select, button))
1527 {
Daniel Stenbergb05eec82005-12-05 23:37:14 +00001528 *variable=select.options.option;
Kevin Ferrare80c0f992005-11-04 16:07:50 +00001529 gui_syncselect_draw(&select);
Kevin Ferrare81411a82005-11-05 02:19:21 +00001530 talk_unit(voice_unit, *variable);
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001531 if ( function )
Kevin Ferrare9b5264d2005-11-06 03:18:34 +00001532 function(*variable);
Björn Stenberg60b356e2002-06-27 01:08:11 +00001533 }
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001534 gui_syncstatusbar_draw(&statusbars, false);
Daniel Stenbergb05eec82005-12-05 23:37:14 +00001535 if(select.canceled)
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001536 {
1537 *variable=oldvalue;
Kevin Ferrare9b5264d2005-11-06 03:18:34 +00001538 if ( function )
1539 function(*variable);
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001540 return false;
1541 }
1542 if(default_event_handler(button) == SYS_USB_CONNECTED)
1543 return true;
Björn Stenberg60b356e2002-06-27 01:08:11 +00001544 }
Björn Stenbergb1b8bd42002-09-24 17:22:12 +00001545 return false;
Björn Stenberg60b356e2002-06-27 01:08:11 +00001546}
1547
Björn Stenberg26712d52003-06-05 11:11:10 +00001548/* NOTE: the 'type' parameter specifies the actual type of the variable
1549 that 'variable' points to. not the value within. Only variables with
1550 type 'bool' should use parameter BOOL.
1551
Björn Stenberg9a82b232003-06-05 14:22:03 +00001552 The type separation is necessary since int and bool are fundamentally
Björn Stenberg26712d52003-06-05 11:11:10 +00001553 different and bit-incompatible types and can not share the same access
1554 code. */
1555
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001556#define set_type_fromint(type, dest, value) \
1557 if (type == INT) \
1558 *(int *)dest=value; \
1559 else \
1560 *(bool *)dest=value?true:false
1561
Kevin Ferrare9b5264d2005-11-06 03:18:34 +00001562#define type_fromvoidptr(type, value) \
1563 (type == INT)? \
1564 (int)(*(int*)(value)) \
1565 : \
1566 (bool)(*(bool*)(value))
1567
1568#define get_int_fromtype(type, var) \
1569 (type == INT)?*(int *)var:(*(bool *)var?1:0)
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001570
Jens Arnold8fb33612004-08-18 01:09:31 +00001571bool set_option(const char* string, void* variable, enum optiontype type,
Jörg Hohensohnb1403ee2004-07-23 23:01:20 +00001572 const struct opt_items* options, int numoptions, void (*function)(int))
Björn Stenberg60b356e2002-06-27 01:08:11 +00001573{
Linus Nielsen Feltzingc3eb83c2002-09-19 09:00:25 +00001574 int button;
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001575 int oldvalue;
1576 /* oldvalue=*variable; */
Kevin Ferrare9b5264d2005-11-06 03:18:34 +00001577 oldvalue=get_int_fromtype(type, variable);
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001578 struct gui_select select;
1579 gui_select_init_items(&select, string, oldvalue, options, numoptions);
1580 gui_syncselect_draw(&select);
Kevin Ferrare81411a82005-11-05 02:19:21 +00001581 if (global_settings.talk_menu)
Daniel Stenbergb05eec82005-12-05 23:37:14 +00001582 talk_id(options[select.options.option].voice_id, true);
1583
1584 while ( !select.validated )
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001585 {
1586 gui_syncstatusbar_draw(&statusbars, true);
Linus Nielsen Feltzingc3eb83c2002-09-19 09:00:25 +00001587 button = button_get_w_tmo(HZ/2);
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001588 if(gui_syncselect_do_button(&select, button))
1589 {
1590 /* *variable = gui_select_get_selected(&select) */
Daniel Stenbergb05eec82005-12-05 23:37:14 +00001591 set_type_fromint(type, variable, select.options.option);
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001592 gui_syncselect_draw(&select);
1593 if (global_settings.talk_menu)
Daniel Stenbergb05eec82005-12-05 23:37:14 +00001594 talk_id(options[select.options.option].voice_id, false);
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001595 if ( function )
Kevin Ferrare9b5264d2005-11-06 03:18:34 +00001596 function(type_fromvoidptr(type, variable));
Björn Stenberg60b356e2002-06-27 01:08:11 +00001597 }
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001598 gui_syncstatusbar_draw(&statusbars, false);
Daniel Stenbergb05eec82005-12-05 23:37:14 +00001599 if(select.canceled)
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001600 {
1601 /* *variable=oldvalue; */
1602 set_type_fromint(type, variable, oldvalue);
Kevin Ferrare9b5264d2005-11-06 03:18:34 +00001603 if ( function )
1604 function(type_fromvoidptr(type, variable));
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001605 return false;
Björn Stenberg26712d52003-06-05 11:11:10 +00001606 }
Kevin Ferrarecbbdc952005-11-04 07:18:36 +00001607 if(default_event_handler(button) == SYS_USB_CONNECTED)
1608 return true;
Björn Stenberg60b356e2002-06-27 01:08:11 +00001609 }
Björn Stenbergb1b8bd42002-09-24 17:22:12 +00001610 return false;
Björn Stenberg60b356e2002-06-27 01:08:11 +00001611}
Markus Braun3181f682002-08-09 12:38:45 +00001612
Daniel Stenberg6ff399f2005-02-02 21:52:55 +00001613#ifdef HAVE_RECORDING
Linus Nielsen Feltzingaaa99e72003-11-20 00:33:43 +00001614/* This array holds the record timer interval lengths, in seconds */
Jens Arnoldabe77a12004-08-01 21:50:57 +00001615static const unsigned long rec_timer_seconds[] =
Linus Nielsen Feltzingaaa99e72003-11-20 00:33:43 +00001616{
Jens Arnold031e4b82005-06-04 12:14:46 +00001617 0, /* 0 means OFF */
Linus Nielsen Feltzingaaa99e72003-11-20 00:33:43 +00001618 5*60, /* 00:05 */
1619 10*60, /* 00:10 */
1620 15*60, /* 00:15 */
1621 30*60, /* 00:30 */
1622 60*60, /* 01:00 */
Linus Nielsen Feltzingfb60a292004-10-27 09:24:02 +00001623 74*60, /* 74:00 */
1624 80*60, /* 80:00 */
Linus Nielsen Feltzingaaa99e72003-11-20 00:33:43 +00001625 2*60*60, /* 02:00 */
1626 4*60*60, /* 04:00 */
1627 6*60*60, /* 06:00 */
1628 8*60*60, /* 08:00 */
Jean-Philippe Bernardy2860c5e2005-02-11 18:41:40 +00001629 10L*60*60, /* 10:00 */
1630 12L*60*60, /* 12:00 */
1631 18L*60*60, /* 18:00 */
1632 24L*60*60 /* 24:00 */
Linus Nielsen Feltzingaaa99e72003-11-20 00:33:43 +00001633};
1634
1635unsigned int rec_timesplit_seconds(void)
1636{
1637 return rec_timer_seconds[global_settings.rec_timesplit];
1638}
Linus Nielsen Feltzing68482bb2005-04-04 09:12:12 +00001639
1640/*
1641 * Time strings used for the trigger durations.
1642 * Keep synchronous to trigger_times in settings_apply_trigger
1643 */
Linus Nielsen Feltzingb3e49e22005-08-18 07:02:03 +00001644const char * const trig_durations[TRIG_DURATION_COUNT] =
Linus Nielsen Feltzing68482bb2005-04-04 09:12:12 +00001645{
1646 "0s", "1s", "2s", "5s",
1647 "10s", "15s", "20s", "25s", "30s",
1648 "1min", "2min", "5min", "10min"
1649};
1650
1651void settings_apply_trigger(void)
1652{
1653 /* Keep synchronous to trig_durations and trig_durations_conf*/
1654 static const long trigger_times[TRIG_DURATION_COUNT] = {
1655 0, HZ, 2*HZ, 5*HZ,
1656 10*HZ, 15*HZ, 20*HZ, 25*HZ, 30*HZ,
1657 60*HZ, 2*60*HZ, 5*60*HZ, 10*60*HZ
1658 };
1659
1660 peak_meter_define_trigger(
1661 global_settings.rec_start_thres,
1662 trigger_times[global_settings.rec_start_duration],
1663 MIN(trigger_times[global_settings.rec_start_duration] / 2, 2*HZ),
1664 global_settings