1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2002 by wavey@wavey.org
11 * RTC config saving code (C) 2002 by hessu@hes.iki.fi
13 * All files in this archive are subject to the GNU General Public License.
14 * See the file COPYING in the source tree root for full license agreement.
16 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
17 * KIND, either express or implied.
19 ****************************************************************************/
31 #include "backlight.h"
38 #include "backlight.h"
39 #include "powermgmt.h"
48 #ifdef HAVE_LCD_BITMAP
51 #include "peakmeter.h"
56 #include "wps-display.h"
57 #include "powermgmt.h"
62 struct user_settings global_settings
;
63 char rockboxdir
[] = ROCKBOX_DIR
; /* config/font/data file directory */
65 #define CONFIG_BLOCK_VERSION 7
66 #define CONFIG_BLOCK_SIZE 512
67 #define RTC_BLOCK_SIZE 44
69 #ifdef HAVE_LCD_BITMAP
75 /********************************************
77 Config block as saved on the battery-packed RTC user RAM memory block
78 of 44 bytes, starting at offset 0x14 of the RTC memory space.
81 0x00 0x14 "Roc" header signature: 0x52 0x6f 0x63
82 0x03 0x17 <version byte: 0x0>
83 0x04 0x18 <volume byte>
84 0x05 0x19 <balance byte>
86 0x07 0x1b <treble byte>
87 0x08 0x1c <loudness byte>
88 0x09 0x1d <bass boost byte>
89 0x0a 0x1e <contrast (bit 0-5), invert bit (bit 6), show_icons (bit 7)>
90 0x0b 0x1f <backlight_on_when_charging, invert_cursor, backlight_timeout>
91 0x0c 0x20 <poweroff timer byte>
92 0x0d 0x21 <resume settings byte>
93 0x0e 0x22 <shuffle,dirfilter,sort_case,discharge,statusbar,show_hidden,
95 0x0f 0x23 <volume type, battery type, timeformat, scroll speed>
96 0x10 0x24 <ff/rewind min step, acceleration rate>
97 0x11 0x25 <AVC, channel config>
98 0x12 0x26 <(int) Resume playlist index, or -1 if no playlist resume>
99 0x16 0x2a <(int) Byte offset into resume file>
100 0x1a 0x2e <time until disk spindown>
101 0x1b 0x2f <browse current, play selected, recursive dir insert>
102 0x1c 0x30 <peak meter hold timeout (bit 0-4),
103 rec_editable (bit 7)>
105 0x21 0x35 <repeat mode (bit 0-1), rec. channels (bit 2),
107 0x22 0x36 <rec. quality (bit 0-2), source (bit 3-4), frequency (bit 5-7)>
108 0x23 0x37 <rec. left gain (bit 0-3)>
109 0x24 0x38 <rec. right gain (bit 0-3)>
110 0x25 0x39 <disk poweroff flag (bit 0), MP3 buffer margin (bit 1-3),
111 Trickle charge flag (bit 4)>
112 0x26 0x40 <runtime low byte>
113 0x27 0x41 <runtime high byte>
114 0x28 0x42 <topruntime low byte>
115 0x29 0x43 <topruntime high byte>
117 0x2a <checksum 2 bytes: xor of 0x0-0x29>
119 Config memory is reset to 0xff and initialized with 'factory defaults' if
120 a valid header & checksum is not found. Config version number is only
121 increased when information is _relocated_ or space is _reused_ so that old
122 versions can read and modify configuration changed by new versions. New
123 versions should check for the value of '0xff' in each config memory
124 location used, and reset the setting in question with a factory default if
125 needed. Memory locations not used by a given version should not be
126 modified unless the header & checksum test fails.
129 Rest of config block, only saved to disk:
130 0xA8 (char)jump scroll mode (only for player)
131 0xA9 (char)jump scroll delay (only for player)
132 0xAA Max number of files in playlist (1000-20000)
133 0xAC Max number of files in dir (50-10000)
134 0xAE fade on pause/unpause/stop setting (bit 0)
135 caption backlight (bit 1)
136 0xB0 peak meter clip hold timeout (bit 0-4), peak meter performance (bit 7)
137 0xB1 peak meter release step size, peak_meter_dbfs (bit 7)
138 0xB2 peak meter min either in -db or in percent
139 0xB3 peak meter max either in -db or in percent
140 0xB4 battery capacity
141 0xB5 scroll step in pixels
142 0xB6 scroll start and endpoint delay
143 0xB7 bidir scroll setting (bidi if 0-200% longer than screen width)
144 0xB8 (char[20]) WPS file
145 0xCC (char[20]) Lang file
146 0xE0 (char[20]) Font file
151 *************************************/
154 static unsigned char config_block
[CONFIG_BLOCK_SIZE
];
157 * Calculates the checksum for the config block and returns it
160 static unsigned short calculate_config_checksum(unsigned char* buf
)
163 unsigned char cksum
[2];
164 cksum
[0] = cksum
[1] = 0;
166 for (i
=0; i
< RTC_BLOCK_SIZE
- 2; i
+=2 ) {
168 cksum
[1] ^= buf
[i
+1];
171 return (cksum
[0] << 8) | cksum
[1];
175 * initialize the config block buffer
177 static void init_config_buffer( void )
179 DEBUGF( "init_config_buffer()\n" );
181 /* reset to 0xff - all unused */
182 memset(config_block
, 0xff, CONFIG_BLOCK_SIZE
);
184 config_block
[0] = 'R';
185 config_block
[1] = 'o';
186 config_block
[2] = 'c';
187 config_block
[3] = CONFIG_BLOCK_VERSION
;
191 * save the config block buffer to disk or RTC RAM
193 static int save_config_buffer( void )
195 unsigned short chksum
;
200 DEBUGF( "save_config_buffer()\n" );
202 /* update the checksum in the end of the block before saving */
203 chksum
= calculate_config_checksum(config_block
);
204 config_block
[ RTC_BLOCK_SIZE
- 2 ] = chksum
>> 8;
205 config_block
[ RTC_BLOCK_SIZE
- 1 ] = chksum
& 0xff;
208 /* FIXME: okay, it _would_ be cleaner and faster to implement rtc_write so
209 that it would write a number of bytes at a time since the RTC chip
210 supports that, but this will have to do for now 8-) */
211 for (i
=0; i
< RTC_BLOCK_SIZE
; i
++ ) {
212 int r
= rtc_write(0x14+i
, config_block
[i
]);
214 DEBUGF( "save_config_buffer: rtc_write failed at addr 0x%02x: %d\n",
222 if (fat_startsector() != 0)
223 ata_delayed_write( 61, config_block
);
231 * load the config block buffer from disk or RTC RAM
233 static int load_config_buffer( void )
235 unsigned short chksum
;
236 bool correct
= false;
240 unsigned char rtc_block
[RTC_BLOCK_SIZE
];
243 DEBUGF( "load_config_buffer()\n" );
245 if (fat_startsector() != 0) {
246 ata_read_sectors( 61, 1, config_block
);
248 /* calculate the checksum, check it and the header */
249 chksum
= calculate_config_checksum(config_block
);
251 if (config_block
[0] == 'R' &&
252 config_block
[1] == 'o' &&
253 config_block
[2] == 'c' &&
254 config_block
[3] == CONFIG_BLOCK_VERSION
&&
255 (chksum
>> 8) == config_block
[RTC_BLOCK_SIZE
- 2] &&
256 (chksum
& 0xff) == config_block
[RTC_BLOCK_SIZE
- 1])
258 DEBUGF( "load_config_buffer: header & checksum test ok\n" );
265 for (i
=0; i
< RTC_BLOCK_SIZE
; i
++ )
266 rtc_block
[i
] = rtc_read(0x14+i
);
268 chksum
= calculate_config_checksum(rtc_block
);
270 /* if rtc block is ok, use that */
271 if (rtc_block
[0] == 'R' &&
272 rtc_block
[1] == 'o' &&
273 rtc_block
[2] == 'c' &&
274 rtc_block
[3] == CONFIG_BLOCK_VERSION
&&
275 (chksum
>> 8) == rtc_block
[RTC_BLOCK_SIZE
- 2] &&
276 (chksum
& 0xff) == rtc_block
[RTC_BLOCK_SIZE
- 1])
278 memcpy(config_block
, rtc_block
, RTC_BLOCK_SIZE
);
284 /* if checksum is not valid, clear the config buffer */
285 DEBUGF( "load_config_buffer: header & checksum test failed\n" );
286 init_config_buffer();
294 * persist all runtime user settings to disk or RTC RAM
296 int settings_save( void )
298 DEBUGF( "settings_save()\n" );
300 /* update the config block buffer with current
301 settings and save the block in the RTC */
302 config_block
[0x4] = (unsigned char)global_settings
.volume
;
303 config_block
[0x5] = (char)global_settings
.balance
;
304 config_block
[0x6] = (unsigned char)global_settings
.bass
;
305 config_block
[0x7] = (unsigned char)global_settings
.treble
;
306 config_block
[0x8] = (unsigned char)global_settings
.loudness
;
307 config_block
[0x9] = (unsigned char)global_settings
.bass_boost
;
309 config_block
[0xa] = (unsigned char)
310 ((global_settings
.contrast
& 0x3f) |
311 (global_settings
.invert
? 0x40 : 0) |
312 (global_settings
.show_icons
? 0x80 : 0) );
314 config_block
[0xb] = (unsigned char)
315 ((global_settings
.backlight_on_when_charging
?0x40:0) |
316 (global_settings
.invert_cursor
? 0x20 : 0) |
317 (global_settings
.backlight_timeout
& 0x1f));
318 config_block
[0xc] = (unsigned char)global_settings
.poweroff
;
319 config_block
[0xd] = (unsigned char)global_settings
.resume
;
321 config_block
[0xe] = (unsigned char)
322 ((global_settings
.playlist_shuffle
& 1) |
323 ((global_settings
.dirfilter
& 1) << 1) |
324 ((global_settings
.sort_case
& 1) << 2) |
325 ((global_settings
.discharge
& 1) << 3) |
326 ((global_settings
.statusbar
& 1) << 4) |
327 ((global_settings
.dirfilter
& 2) << 4) |
328 ((global_settings
.scrollbar
& 1) << 6));
330 config_block
[0xf] = (unsigned char)
331 ((global_settings
.volume_type
& 1) |
332 ((global_settings
.battery_type
& 1) << 1) |
333 ((global_settings
.timeformat
& 1) << 2) |
334 ( global_settings
.scroll_speed
<< 3));
336 config_block
[0x10] = (unsigned char)
337 ((global_settings
.ff_rewind_min_step
& 15) << 4 |
338 (global_settings
.ff_rewind_accel
& 15));
340 config_block
[0x11] = (unsigned char)
341 ((global_settings
.avc
& 0x03) |
342 ((global_settings
.channel_config
& 0x07) << 2));
344 memcpy(&config_block
[0x12], &global_settings
.resume_index
, 4);
345 memcpy(&config_block
[0x16], &global_settings
.resume_offset
, 4);
346 DEBUGF( "+Resume index %X offset %X\n",
347 global_settings
.resume_index
,
348 global_settings
.resume_offset
);
350 config_block
[0x1a] = (unsigned char)global_settings
.disk_spindown
;
351 config_block
[0x1b] = (unsigned char)
352 (((global_settings
.browse_current
& 1)) |
353 ((global_settings
.play_selected
& 1) << 1) |
354 ((global_settings
.recursive_dir_insert
& 3) << 2));
356 config_block
[0x1c] = (unsigned char)global_settings
.peak_meter_hold
|
357 (global_settings
.rec_editable
?0x80:0);
359 config_block
[0x21] = (unsigned char)
360 ((global_settings
.repeat_mode
& 3) |
361 ((global_settings
.rec_channels
& 1) << 2) |
362 ((global_settings
.rec_mic_gain
& 0x0f) << 4));
363 config_block
[0x22] = (unsigned char)
364 ((global_settings
.rec_quality
& 7) |
365 ((global_settings
.rec_source
& 1) << 3) |
366 ((global_settings
.rec_frequency
& 7) << 5));
367 config_block
[0x23] = (unsigned char)global_settings
.rec_left_gain
;
368 config_block
[0x24] = (unsigned char)global_settings
.rec_right_gain
;
369 config_block
[0x25] = (unsigned char)
370 ((global_settings
.disk_poweroff
& 1) |
371 ((global_settings
.buffer_margin
& 7) << 1) |
372 ((global_settings
.trickle_charge
& 1) << 4));
375 static long lasttime
= 0;
378 elapsed_secs
= (current_tick
- lasttime
) / HZ
;
379 global_settings
.runtime
+= elapsed_secs
;
380 lasttime
+= (elapsed_secs
* HZ
);
382 if ( global_settings
.runtime
> global_settings
.topruntime
)
383 global_settings
.topruntime
= global_settings
.runtime
;
385 config_block
[0x26]=(unsigned char)(global_settings
.runtime
& 0xff);
386 config_block
[0x27]=(unsigned char)(global_settings
.runtime
>> 8);
387 config_block
[0x28]=(unsigned char)(global_settings
.topruntime
& 0xff);
388 config_block
[0x29]=(unsigned char)(global_settings
.topruntime
>> 8);
391 #ifdef HAVE_LCD_CHARCELLS
392 config_block
[0xa8]=(unsigned char)global_settings
.jump_scroll
;
393 config_block
[0xa9]=(unsigned char)global_settings
.jump_scroll_delay
;
395 config_block
[0xaa] = (unsigned char)
396 global_settings
.max_files_in_playlist
& 0xff;
397 config_block
[0xab] = (unsigned char)
398 (global_settings
.max_files_in_playlist
>> 8) & 0xff;
399 config_block
[0xac] = (unsigned char)
400 global_settings
.max_files_in_dir
& 0xff;
401 config_block
[0xad] = (unsigned char)
402 (global_settings
.max_files_in_dir
>> 8) & 0xff;
403 config_block
[0xae] = (unsigned char)
404 ((global_settings
.fade_on_stop
& 1) |
405 ((global_settings
.caption_backlight
& 1) << 1));
406 config_block
[0xb0] = (unsigned char)global_settings
.peak_meter_clip_hold
|
407 (global_settings
.peak_meter_performance
? 0x80 : 0);
408 config_block
[0xb1] = global_settings
.peak_meter_release
|
409 (global_settings
.peak_meter_dbfs
? 0x80 : 0);
410 config_block
[0xb2] = (unsigned char)global_settings
.peak_meter_min
;
411 config_block
[0xb3] = (unsigned char)global_settings
.peak_meter_max
;
413 config_block
[0xb4]=(global_settings
.battery_capacity
- 1000) / 50;
414 config_block
[0xb5]=(unsigned char)global_settings
.scroll_step
;
415 config_block
[0xb6]=(unsigned char)global_settings
.scroll_delay
;
416 config_block
[0xb7]=(unsigned char)global_settings
.bidir_limit
;
418 strncpy(&config_block
[0xb8], global_settings
.wps_file
, MAX_FILENAME
);
419 strncpy(&config_block
[0xcc], global_settings
.lang_file
, MAX_FILENAME
);
420 strncpy(&config_block
[0xe0], global_settings
.font_file
, MAX_FILENAME
);
422 if(save_config_buffer())
425 #ifdef HAVE_LCD_CHARCELLS
426 lcd_puts(0, 0, str(LANG_SETTINGS_SAVE_PLAYER
));
427 lcd_puts(0, 1, str(LANG_SETTINGS_BATTERY_PLAYER
));
429 lcd_puts(4, 2, str(LANG_SETTINGS_SAVE_RECORDER
));
430 lcd_puts(2, 4, str(LANG_SETTINGS_BATTERY_RECORDER
));
439 #ifdef HAVE_LCD_BITMAP
441 * Applies the range infos stored in global_settings to
444 void settings_apply_pm_range(void)
448 /* depending on the scale mode (dBfs or percent) the values
449 of global_settings.peak_meter_dbfs have different meanings */
450 if (global_settings
.peak_meter_dbfs
)
452 /* convert to dBfs * 100 */
453 pm_min
= -(((int)global_settings
.peak_meter_min
) * 100);
454 pm_max
= -(((int)global_settings
.peak_meter_max
) * 100);
458 /* percent is stored directly -> no conversion */
459 pm_min
= global_settings
.peak_meter_min
;
460 pm_max
= global_settings
.peak_meter_max
;
463 /* apply the range */
464 peak_meter_init_range(global_settings
.peak_meter_dbfs
, pm_min
, pm_max
);
466 #endif /* HAVE_LCD_BITMAP */
468 void settings_apply(void)
472 mpeg_sound_set(SOUND_BASS
, global_settings
.bass
);
473 mpeg_sound_set(SOUND_TREBLE
, global_settings
.treble
);
474 mpeg_sound_set(SOUND_BALANCE
, global_settings
.balance
);
475 mpeg_sound_set(SOUND_VOLUME
, global_settings
.volume
);
476 mpeg_sound_set(SOUND_CHANNELS
, global_settings
.channel_config
);
478 mpeg_sound_set(SOUND_LOUDNESS
, global_settings
.loudness
);
479 mpeg_sound_set(SOUND_SUPERBASS
, global_settings
.bass_boost
);
480 mpeg_sound_set(SOUND_AVC
, global_settings
.avc
);
483 lcd_set_contrast(global_settings
.contrast
);
484 lcd_scroll_speed(global_settings
.scroll_speed
);
485 backlight_set_timeout(global_settings
.backlight_timeout
);
486 backlight_set_on_when_charging(global_settings
.backlight_on_when_charging
);
487 ata_spindown(global_settings
.disk_spindown
);
489 #ifdef HAVE_ATA_POWER_OFF
490 ata_poweroff(global_settings
.disk_poweroff
);
493 set_poweroff_timeout(global_settings
.poweroff
);
494 #ifdef HAVE_CHARGE_CTRL
495 charge_restart_level
= global_settings
.discharge
?
496 CHARGE_RESTART_LO
: CHARGE_RESTART_HI
;
497 enable_trickle_charge(global_settings
.trickle_charge
);
500 set_battery_capacity(global_settings
.battery_capacity
);
502 #ifdef HAVE_LCD_BITMAP
503 lcd_set_invert_display(global_settings
.invert
);
504 settings_apply_pm_range();
505 peak_meter_init_times(
506 global_settings
.peak_meter_release
, global_settings
.peak_meter_hold
,
507 global_settings
.peak_meter_clip_hold
);
510 if ( global_settings
.wps_file
[0] &&
511 global_settings
.wps_file
[0] != 0xff ) {
512 snprintf(buf
, sizeof buf
, ROCKBOX_DIR
"/%s.wps",
513 global_settings
.wps_file
);
514 wps_load(buf
, false);
519 #ifdef HAVE_LCD_BITMAP
520 if ( global_settings
.font_file
[0] &&
521 global_settings
.font_file
[0] != 0xff ) {
522 snprintf(buf
, sizeof buf
, ROCKBOX_DIR
"/%s.fnt",
523 global_settings
.font_file
);
529 lcd_scroll_step(global_settings
.scroll_step
);
531 lcd_jump_scroll(global_settings
.jump_scroll
);
532 lcd_jump_scroll_delay(global_settings
.jump_scroll_delay
* (HZ
/10));
534 lcd_bidir_scroll(global_settings
.bidir_limit
);
535 lcd_scroll_delay(global_settings
.scroll_delay
* (HZ
/10));
537 if ( global_settings
.lang_file
[0] &&
538 global_settings
.lang_file
[0] != 0xff ) {
539 snprintf(buf
, sizeof buf
, ROCKBOX_DIR
"/%s.lng",
540 global_settings
.lang_file
);
546 * load settings from disk or RTC RAM
548 void settings_load(void)
551 DEBUGF( "reload_all_settings()\n" );
553 /* populate settings with default values */
556 /* load the buffer from the RTC (resets it to all-unused if the block
557 is invalid) and decode the settings which are set in the block */
558 if (!load_config_buffer()) {
559 if (config_block
[0x4] != 0xFF)
560 global_settings
.volume
= config_block
[0x4];
561 if (config_block
[0x5] != 0xFF)
562 global_settings
.balance
= (char)config_block
[0x5];
563 if (config_block
[0x6] != 0xFF)
564 global_settings
.bass
= config_block
[0x6];
565 if (config_block
[0x7] != 0xFF)
566 global_settings
.treble
= config_block
[0x7];
567 if (config_block
[0x8] != 0xFF)
568 global_settings
.loudness
= config_block
[0x8];
569 if (config_block
[0x9] != 0xFF)
570 global_settings
.bass_boost
= config_block
[0x9];
572 if (config_block
[0xa] != 0xFF) {
573 global_settings
.contrast
= config_block
[0xa] & 0x3f;
574 global_settings
.invert
=
575 config_block
[0xa] & 0x40 ? true : false;
576 if ( global_settings
.contrast
< MIN_CONTRAST_SETTING
)
577 global_settings
.contrast
= lcd_default_contrast();
578 global_settings
.show_icons
=
579 config_block
[0xa] & 0x80 ? true : false;
582 if (config_block
[0xb] != 0xFF) {
583 /* Bit 7 is unused to be able to detect uninitialized entry */
584 global_settings
.backlight_timeout
= config_block
[0xb] & 0x1f;
585 global_settings
.invert_cursor
=
586 config_block
[0xb] & 0x20 ? true : false;
587 global_settings
.backlight_on_when_charging
=
588 config_block
[0xb] & 0x40 ? true : false;
591 if (config_block
[0xc] != 0xFF)
592 global_settings
.poweroff
= config_block
[0xc];
593 if (config_block
[0xd] != 0xFF)
594 global_settings
.resume
= config_block
[0xd];
595 if (config_block
[0xe] != 0xFF) {
596 global_settings
.playlist_shuffle
= config_block
[0xe] & 1;
597 global_settings
.dirfilter
= (config_block
[0xe] >> 1) & 1;
598 global_settings
.sort_case
= (config_block
[0xe] >> 2) & 1;
599 global_settings
.discharge
= (config_block
[0xe] >> 3) & 1;
600 global_settings
.statusbar
= (config_block
[0xe] >> 4) & 1;
601 global_settings
.dirfilter
|= ((config_block
[0xe] >> 5) & 1) << 1;
602 global_settings
.scrollbar
= (config_block
[0xe] >> 6) & 1;
603 /* Don't use the last bit, it must be unused to detect
604 an uninitialized entry */
607 if (config_block
[0xf] != 0xFF) {
608 global_settings
.volume_type
= config_block
[0xf] & 1;
609 global_settings
.battery_type
= (config_block
[0xf] >> 1) & 1;
610 global_settings
.timeformat
= (config_block
[0xf] >> 2) & 1;
611 global_settings
.scroll_speed
= config_block
[0xf] >> 3;
614 if (config_block
[0x10] != 0xFF) {
615 global_settings
.ff_rewind_min_step
= (config_block
[0x10] >> 4) & 15;
616 global_settings
.ff_rewind_accel
= config_block
[0x10] & 15;
619 if (config_block
[0x11] != 0xFF)
621 global_settings
.avc
= config_block
[0x11] & 0x03;
622 global_settings
.channel_config
= (config_block
[0x11] >> 2) & 0x07;
625 if (config_block
[0x12] != 0xFF)
626 memcpy(&global_settings
.resume_index
, &config_block
[0x12], 4);
628 if (config_block
[0x16] != 0xFF)
629 memcpy(&global_settings
.resume_offset
, &config_block
[0x16], 4);
631 if (config_block
[0x1a] != 0xFF)
632 global_settings
.disk_spindown
= config_block
[0x1a];
634 if (config_block
[0x1b] != 0xFF) {
635 global_settings
.browse_current
= (config_block
[0x1b]) & 1;
636 global_settings
.play_selected
= (config_block
[0x1b] >> 1) & 1;
637 global_settings
.recursive_dir_insert
=
638 (config_block
[0x1b] >> 2) & 3;
641 if (config_block
[0x1c] != 0xFF) {
642 global_settings
.peak_meter_hold
= (config_block
[0x1c]) & 0x1f;
643 global_settings
.rec_editable
=
644 (config_block
[0x1c] & 0x80)?true:false;
647 if (config_block
[0x21] != 0xFF)
649 global_settings
.repeat_mode
= config_block
[0x21] & 3;
650 global_settings
.rec_channels
= (config_block
[0x21] >> 2) & 1;
651 global_settings
.rec_mic_gain
= (config_block
[0x21] >> 4) & 0x0f;
654 if (config_block
[0x22] != 0xFF)
656 global_settings
.rec_quality
= config_block
[0x22] & 7;
657 global_settings
.rec_source
= (config_block
[0x22] >> 3) & 3;
658 global_settings
.rec_frequency
= (config_block
[0x22] >> 5) & 7;
661 if (config_block
[0x23] != 0xFF)
662 global_settings
.rec_left_gain
= config_block
[0x23] & 0x0f;
664 if (config_block
[0x24] != 0xFF)
665 global_settings
.rec_right_gain
= config_block
[0x24] & 0x0f;
667 if (config_block
[0x25] != 0xFF)
669 global_settings
.disk_poweroff
= config_block
[0x25] & 1;
670 global_settings
.buffer_margin
= (config_block
[0x25] >> 1) & 7;
671 global_settings
.trickle_charge
= (config_block
[0x25] >> 4) & 1;
674 if (config_block
[0x27] != 0xff)
675 global_settings
.runtime
=
676 config_block
[0x26] | (config_block
[0x27] << 8);
678 if (config_block
[0x29] != 0xff)
679 global_settings
.topruntime
=
680 config_block
[0x28] | (config_block
[0x29] << 8);
682 if (config_block
[0xae] != 0xff) {
683 global_settings
.fade_on_stop
= config_block
[0xae] & 1;
684 global_settings
.caption_backlight
= (config_block
[0xae] >> 1) & 1;
687 if(config_block
[0xb0] != 0xff) {
688 global_settings
.peak_meter_clip_hold
= (config_block
[0xb0]) & 0x1f;
689 global_settings
.peak_meter_performance
=
690 (config_block
[0xb0] & 0x80) != 0;
693 if(config_block
[0xb1] != 0xff) {
694 global_settings
.peak_meter_release
= config_block
[0xb1] & 0x7f;
695 global_settings
.peak_meter_dbfs
= (config_block
[0xb1] & 0x80) != 0;
698 if(config_block
[0xb2] != 0xff)
699 global_settings
.peak_meter_min
= config_block
[0xb2];
701 if(config_block
[0xb3] != 0xff)
702 global_settings
.peak_meter_max
= config_block
[0xb3];
704 if(config_block
[0xb4] != 0xff)
705 global_settings
.battery_capacity
= config_block
[0xb4]*50 + 1000;
707 if (config_block
[0xb5] != 0xff)
708 global_settings
.scroll_step
= config_block
[0xb5];
710 if (config_block
[0xb6] != 0xff)
711 global_settings
.scroll_delay
= config_block
[0xb6];
713 if (config_block
[0xb7] != 0xff)
714 global_settings
.bidir_limit
= config_block
[0xb7];
716 if (config_block
[0xac] != 0xff)
717 global_settings
.max_files_in_dir
=
718 config_block
[0xac] | (config_block
[0xad] << 8);
720 if (config_block
[0xaa] != 0xff)
721 global_settings
.max_files_in_playlist
=
722 config_block
[0xaa] | (config_block
[0xab] << 8);
724 strncpy(global_settings
.wps_file
, &config_block
[0xb8], MAX_FILENAME
);
725 strncpy(global_settings
.lang_file
, &config_block
[0xcc], MAX_FILENAME
);
726 strncpy(global_settings
.font_file
, &config_block
[0xe0], MAX_FILENAME
);
727 #ifdef HAVE_LCD_CHARCELLS
728 if (config_block
[0xa8] != 0xff)
729 global_settings
.jump_scroll
= config_block
[0xa8];
730 if (config_block
[0xa9] != 0xff)
731 global_settings
.jump_scroll_delay
= config_block
[0xa9];
738 /* parse a line from a configuration file. the line format is:
740 setting name: setting value
742 Any whitespace before setting name or value (after ':') is ignored.
743 A # as first non-whitespace character discards the whole line.
744 Function sets pointers to null-terminated setting name and value.
745 Returns false if no valid config entry was found.
748 static bool settings_parseline(char* line
, char** name
, char** value
)
752 while ( isspace(*line
) )
758 ptr
= strchr(line
, ':');
765 while (isspace(*ptr
))
771 void set_file(char* filename
, char* setting
, int maxlen
)
773 char* fptr
= strrchr(filename
,'/');
786 while (*ptr
!= '.') {
791 if (strcmp(ROCKBOX_DIR
, filename
) || (len
-extlen
> maxlen
))
794 strncpy(setting
, fptr
, len
-extlen
);
795 setting
[len
-extlen
]=0;
800 static void set_sound(char* value
, int type
, int* setting
)
802 int num
= atoi(value
);
804 num
= mpeg_phys2val(type
, num
);
806 if ((num
> mpeg_sound_max(type
)) ||
807 (num
< mpeg_sound_min(type
)))
809 num
= mpeg_sound_default(type
);
813 mpeg_sound_set(type
, num
);
816 /* This is required to actually apply balance */
817 if (SOUND_BALANCE
== type
)
818 mpeg_sound_set(SOUND_VOLUME
, global_settings
.volume
);
822 static void set_cfg_bool(bool* variable
, char* value
)
824 /* look for the 'n' in 'on' */
825 if ((value
[1] & 0xdf) == 'N')
831 static void set_cfg_int(int* variable
, char* value
, int min
, int max
)
833 *variable
= atoi(value
);
842 static void set_cfg_option(int* variable
, char* value
,
843 char* options
[], int numoptions
)
847 for (i
=0; i
<numoptions
; i
++) {
848 if (!strcasecmp(options
[i
], value
)) {
855 bool settings_load_config(char* file
)
860 fd
= open(file
, O_RDONLY
);
864 while (read_line(fd
, line
, sizeof line
) > 0)
869 if (!settings_parseline(line
, &name
, &value
))
872 if (!strcasecmp(name
, "volume"))
873 set_sound(value
, SOUND_VOLUME
, &global_settings
.volume
);
874 else if (!strcasecmp(name
, "bass"))
875 set_sound(value
, SOUND_BASS
, &global_settings
.bass
);
876 else if (!strcasecmp(name
, "treble"))
877 set_sound(value
, SOUND_TREBLE
, &global_settings
.treble
);
878 else if (!strcasecmp(name
, "balance"))
879 set_sound(value
, SOUND_BALANCE
, &global_settings
.balance
);
880 else if (!strcasecmp(name
, "channels")) {
881 static char* options
[] = {
882 "stereo","stereo narrow","mono","mono left",
883 "mono right","karaoke","stereo wide"};
884 set_cfg_option(&global_settings
.channel_config
, value
,
887 else if (!strcasecmp(name
, "wps")) {
888 if (wps_load(value
,false))
889 set_file(value
, global_settings
.wps_file
, MAX_FILENAME
);
891 else if (!strcasecmp(name
, "lang")) {
892 if (!lang_load(value
))
893 set_file(value
, global_settings
.lang_file
, MAX_FILENAME
);
895 else if (!strcasecmp(name
, "bidir limit"))
896 set_cfg_int(&global_settings
.bidir_limit
, value
, 0, 200);
897 #ifdef HAVE_LCD_BITMAP
898 else if (!strcasecmp(name
, "font")) {
899 if (font_load(value
))
900 set_file(value
, global_settings
.font_file
, MAX_FILENAME
);
902 else if (!strcasecmp(name
, "scroll step"))
903 set_cfg_int(&global_settings
.scroll_step
, value
, 1, LCD_WIDTH
);
904 else if (!strcasecmp(name
, "statusbar"))
905 set_cfg_bool(&global_settings
.statusbar
, value
);
906 else if (!strcasecmp(name
, "peak meter release"))
907 set_cfg_int(&global_settings
.peak_meter_release
, value
, 1, 0x7e);
908 else if (!strcasecmp(name
, "peak meter hold")) {
909 static char* options
[] = {
910 "off","200ms","300ms","500ms",
911 "1","2","3","4","5","6","7","8","9","10",
912 "15","20","30","1min"};
913 set_cfg_option(&global_settings
.peak_meter_hold
, value
,
916 else if (!strcasecmp(name
, "peak meter clip hold")) {
917 static char* options
[] = {
918 "on","1","2","3","4","5","6","7","8","9","10",
919 "15","20","25","30","45","60","90",
920 "2min","3min","5min","10min","20min","45min","90min"};
921 set_cfg_option(&global_settings
.peak_meter_clip_hold
, value
,
924 else if (!strcasecmp(name
, "peak meter dbfs"))
925 set_cfg_bool(&global_settings
.peak_meter_dbfs
, value
);
926 else if (!strcasecmp(name
, "peak meter min"))
927 set_cfg_int(&global_settings
.peak_meter_min
, value
, 0, 100);
928 else if (!strcasecmp(name
, "peak meter max"))
929 set_cfg_int(&global_settings
.peak_meter_max
, value
, 0, 100);
930 else if (!strcasecmp(name
, "peak meter busy"))
931 set_cfg_bool(&global_settings
.peak_meter_performance
, value
);
932 else if (!strcasecmp(name
, "volume display")) {
933 static char* options
[] = {"graphic", "numeric"};
934 set_cfg_option(&global_settings
.volume_type
, value
, options
, 2);
936 else if (!strcasecmp(name
, "battery display")) {
937 static char* options
[] = {"graphic", "numeric"};
938 set_cfg_option(&global_settings
.battery_type
, value
, options
, 2);
940 else if (!strcasecmp(name
, "time format")) {
941 static char* options
[] = {"24hour", "12hour"};
942 set_cfg_option(&global_settings
.timeformat
, value
, options
, 2);
944 else if (!strcasecmp(name
, "scrollbar"))
945 set_cfg_bool(&global_settings
.scrollbar
, value
);
946 else if (!strcasecmp(name
, "invert"))
947 set_cfg_bool(&global_settings
.invert
, value
);
948 else if (!strcasecmp(name
, "invert cursor"))
949 set_cfg_bool(&global_settings
.invert_cursor
, value
);
950 else if (!strcasecmp(name
, "show icons"))
951 set_cfg_bool(&global_settings
.show_icons
, value
);
953 else if (!strcasecmp(name
, "caption backlight"))
954 set_cfg_bool(&global_settings
.caption_backlight
, value
);
955 else if (!strcasecmp(name
, "shuffle"))
956 set_cfg_bool(&global_settings
.playlist_shuffle
, value
);
957 else if (!strcasecmp(name
, "repeat")) {
958 static char* options
[] = {"off", "all", "one"};
959 set_cfg_option(&global_settings
.repeat_mode
, value
, options
, 3);
961 else if (!strcasecmp(name
, "resume")) {
962 static char* options
[] = {"off", "ask", "ask once", "on"};
963 set_cfg_option(&global_settings
.resume
, value
, options
, 4);
965 else if (!strcasecmp(name
, "sort case"))
966 set_cfg_bool(&global_settings
.sort_case
, value
);
967 else if (!strcasecmp(name
, "show files")) {
968 static char* options
[] = {"all", "supported","music", "playlists"};
969 set_cfg_option(&global_settings
.dirfilter
, value
, options
, 4);
971 else if (!strcasecmp(name
, "follow playlist"))
972 set_cfg_bool(&global_settings
.browse_current
, value
);
973 else if (!strcasecmp(name
, "play selected"))
974 set_cfg_bool(&global_settings
.play_selected
, value
);
975 else if (!strcasecmp(name
, "contrast"))
976 set_cfg_int(&global_settings
.contrast
, value
,
977 MIN_CONTRAST_SETTING
, MAX_CONTRAST_SETTING
);
978 else if (!strcasecmp(name
, "scroll speed"))
979 set_cfg_int(&global_settings
.scroll_speed
, value
, 1, 10);
980 else if (!strcasecmp(name
, "scan min step")) {
981 static char* options
[] =
982 {"1","2","3","4","5","6","8","10",
983 "15","20","25","30","45","60"};
984 set_cfg_option(&global_settings
.ff_rewind_min_step
, value
,
987 else if (!strcasecmp(name
, "scan accel"))
988 set_cfg_int(&global_settings
.ff_rewind_accel
, value
, 0, 15);
989 else if (!strcasecmp(name
, "scroll delay"))
990 set_cfg_int(&global_settings
.scroll_delay
, value
, 0, 250);
991 else if (!strcasecmp(name
, "backlight timeout")) {
992 static char* options
[] = {
993 "off","on","1","2","3","4","5","6","7","8","9",
994 "10","15","20","25","30","45","60","90"};
995 set_cfg_option(&global_settings
.backlight_timeout
, value
,
998 else if (!strcasecmp(name
, "backlight when plugged"))
999 set_cfg_bool(&global_settings
.backlight_on_when_charging
, value
);
1000 else if (!strcasecmp(name
, "antiskip"))
1001 set_cfg_int(&global_settings
.buffer_margin
, value
, 0, 7);
1002 else if (!strcasecmp(name
, "disk spindown"))
1003 set_cfg_int(&global_settings
.disk_spindown
, value
, 3, 254);
1004 #ifdef HAVE_ATA_POWER_OFF
1005 else if (!strcasecmp(name
, "disk poweroff"))
1006 set_cfg_bool(&global_settings
.disk_poweroff
, value
);
1008 #ifdef HAVE_MAS3587F
1009 else if (!strcasecmp(name
, "loudness"))
1010 set_sound(value
, SOUND_LOUDNESS
, &global_settings
.loudness
);
1011 else if (!strcasecmp(name
, "bass boost"))
1012 set_sound(value
, SOUND_SUPERBASS
, &global_settings
.bass_boost
);
1013 else if (!strcasecmp(name
, "auto volume")) {
1014 static char* options
[] = {"off", "2", "4", "8" };
1015 set_cfg_option(&global_settings
.avc
, value
, options
, 4);
1017 else if (!strcasecmp(name
, "rec mic gain"))
1018 set_sound(value
, SOUND_MIC_GAIN
, &global_settings
.rec_mic_gain
);
1019 else if (!strcasecmp(name
, "rec left gain"))
1020 set_sound(value
, SOUND_LEFT_GAIN
, &global_settings
.rec_left_gain
);
1021 else if (!strcasecmp(name
, "rec right gain"))
1022 set_sound(value
, SOUND_RIGHT_GAIN
, &global_settings
.rec_right_gain
);
1023 else if (!strcasecmp(name
, "rec quality"))
1024 set_cfg_int(&global_settings
.rec_quality
, value
, 0, 7);
1025 else if (!strcasecmp(name
, "rec timesplit")){
1026 static char* options
[] = {"off", "00:05","00:10","00:15",
1027 "00:30","01:00","02:00","04:00",
1028 "06:00","08:00","10:00","12:00",
1030 set_cfg_option(&global_settings
.rec_timesplit
, value
,
1033 else if (!strcasecmp(name
, "rec source")) {
1034 static char* options
[] = {"mic", "line", "spdif"};
1035 set_cfg_option(&global_settings
.rec_source
, value
, options
, 3);
1037 else if (!strcasecmp(name
, "rec frequency")) {
1038 static char* options
[] = {"44", "48", "32", "22", "24", "16"};
1039 set_cfg_option(&global_settings
.rec_frequency
, value
, options
, 6);
1041 else if (!strcasecmp(name
, "rec channels")) {
1042 static char* options
[] = {"stereo", "mono"};
1043 set_cfg_option(&global_settings
.rec_channels
, value
, options
, 2);
1045 else if (!strcasecmp(name
, "editable recordings")) {
1046 set_cfg_bool(&global_settings
.rec_editable
, value
);
1049 else if (!strcasecmp(name
, "idle poweroff")) {
1050 static char* options
[] = {"off","1","2","3","4","5","6","7","8",
1051 "9","10","15","30","45","60"};
1052 set_cfg_option(&global_settings
.poweroff
, value
, options
, 15);
1054 else if (!strcasecmp(name
, "battery capacity"))
1055 set_cfg_int(&global_settings
.battery_capacity
, value
,
1056 1500, BATTERY_CAPACITY_MAX
);
1057 #ifdef HAVE_CHARGE_CTRL
1058 else if (!strcasecmp(name
, "deep discharge"))
1059 set_cfg_bool(&global_settings
.discharge
, value
);
1060 else if (!strcasecmp(name
, "trickle charge"))
1061 set_cfg_bool(&global_settings
.trickle_charge
, value
);
1063 else if (!strcasecmp(name
, "volume fade"))
1064 set_cfg_bool(&global_settings
.fade_on_stop
, value
);
1065 else if (!strcasecmp(name
, "max files in dir"))
1066 set_cfg_int(&global_settings
.max_files_in_dir
, value
,
1068 else if (!strcasecmp(name
, "max files in playlist"))
1069 set_cfg_int(&global_settings
.max_files_in_playlist
, value
,
1071 else if (!strcasecmp(name
, "recursive directory insert")) {
1072 static char* options
[] = {"off", "on", "ask"};
1073 set_cfg_option(&global_settings
.recursive_dir_insert
, value
,
1085 bool settings_save_config(void)
1089 char filename
[MAX_PATH
];
1090 char* boolopt
[] = {"off","on"};
1092 /* find unused filename */
1094 snprintf(filename
, sizeof filename
, "/.rockbox/config%02d.cfg", i
);
1095 fd
= open(filename
, O_RDONLY
);
1101 /* allow user to modify filename */
1103 if (!kbd_input(filename
, sizeof filename
)) {
1104 fd
= creat(filename
,0);
1106 lcd_clear_display();
1107 lcd_puts(0,0,str(LANG_FAILED
));
1118 /* abort if file couldn't be created */
1120 lcd_clear_display();
1121 lcd_puts(0,0,str(LANG_RESET_DONE_CANCEL
));
1127 fprintf(fd
, "# >>> .cfg file created by rockbox %s <<<\r\n", appsversion
);
1128 fprintf(fd
, "# >>> http://rockbox.haxx.se <<<\r\n#\r\n");
1129 fprintf(fd
, "#\r\n# wps / language / font \r\n#\r\n");
1131 if (global_settings
.wps_file
[0] != 0)
1132 fprintf(fd
, "wps: /.rockbox/%s.wps\r\n", global_settings
.wps_file
);
1134 if (global_settings
.lang_file
[0] != 0)
1135 fprintf(fd
, "lang: /.rockbox/%s.lng\r\n", global_settings
.lang_file
);
1137 #ifdef HAVE_LCD_BITMAP
1138 if (global_settings
.font_file
[0] != 0)
1139 fprintf(fd
, "font: /.rockbox/%s.fnt\r\n", global_settings
.font_file
);
1142 fprintf(fd
, "#\r\n# Sound settings\r\n#\r\n");
1144 value
= mpeg_val2phys(SOUND_VOLUME
, global_settings
.volume
);
1145 fprintf(fd
, "volume: %d\r\n", value
);
1147 value
= mpeg_val2phys(SOUND_BASS
, global_settings
.bass
);
1148 fprintf(fd
, "bass: %d\r\n", value
);
1150 value
= mpeg_val2phys(SOUND_TREBLE
, global_settings
.treble
);
1151 fprintf(fd
, "treble: %d\r\n", value
);
1153 value
= mpeg_val2phys(SOUND_BALANCE
, global_settings
.balance
);
1154 fprintf(fd
, "balance: %d\r\n", value
);
1157 static char* options
[] =
1158 {"stereo","stereo narrow","mono","mono left",
1159 "mono right","karaoke","stereo wide"};
1160 fprintf(fd
, "channels: %s\r\n",
1161 options
[global_settings
.channel_config
]);
1164 #ifdef HAVE_MAS3587F
1165 value
= mpeg_val2phys(SOUND_LOUDNESS
, global_settings
.loudness
);
1166 fprintf(fd
, "loudness: %d\r\n", value
);
1168 value
= mpeg_val2phys(SOUND_SUPERBASS
, global_settings
.bass_boost
);
1169 fprintf(fd
, "bass boost: %d\r\n", value
);
1172 static char* options
[] = {"off", "2", "4", "8" };
1173 fprintf(fd
, "auto volume: %s\r\n", options
[global_settings
.avc
]);
1177 fprintf(fd
, "#\r\n# Playback\r\n#\r\n");
1178 fprintf(fd
, "shuffle: %s\r\n", boolopt
[global_settings
.playlist_shuffle
]);
1181 static char* options
[] = {"off", "all", "one"};
1182 fprintf(fd
, "repeat: %s\r\n", options
[global_settings
.repeat_mode
]);
1185 fprintf(fd
, "play selected: %s\r\n",
1186 boolopt
[global_settings
.play_selected
]);
1189 static char* options
[] = {"off", "ask", "ask once", "on"};
1190 fprintf(fd
, "resume: %s\r\n", options
[global_settings
.resume
]);
1194 static char* options
[] =
1195 {"1","2","3","4","5","6","8","10",
1196 "15","20","25","30","45","60"};
1197 fprintf(fd
, "scan min step: %s\r\n",
1198 options
[global_settings
.ff_rewind_min_step
]);
1201 fprintf(fd
, "scan accel: %d\r\nantiskip: %d\r\n",
1202 global_settings
.ff_rewind_accel
,
1203 global_settings
.buffer_margin
);
1204 fprintf(fd
, "volume fade: %s\r\n", boolopt
[global_settings
.fade_on_stop
]);
1205 fprintf(fd
, "#\r\n# File View\r\n#\r\n");
1206 fprintf(fd
, "sort case: %s\r\n", boolopt
[global_settings
.sort_case
]);
1209 static char* options
[] = {"all", "supported","music", "playlists"};
1210 fprintf(fd
, "show files: %s\r\n", options
[global_settings
.dirfilter
]);
1213 fprintf(fd
, "follow playlist: %s\r\n",
1214 boolopt
[global_settings
.browse_current
]);
1216 fprintf(fd
, "#\r\n# Display\r\n#\r\n");
1218 #ifdef HAVE_LCD_BITMAP
1219 fprintf(fd
, "statusbar: %s\r\nscrollbar: %s\r\n",
1220 boolopt
[global_settings
.statusbar
],
1221 boolopt
[global_settings
.scrollbar
]);
1224 static char* options
[] = {"graphic", "numeric"};
1225 fprintf(fd
, "volume display: %s\r\nbattery display: %s\r\n",
1226 options
[global_settings
.volume_type
],
1227 options
[global_settings
.battery_type
]);
1231 fprintf(fd
, "scroll speed: %d\r\nscroll delay: %d\r\n",
1232 global_settings
.scroll_speed
,
1233 global_settings
.scroll_delay
);
1235 #ifdef HAVE_LCD_BITMAP
1236 fprintf(fd
, "scroll step: %d\r\n", global_settings
.scroll_step
);
1238 fprintf(fd
, "jump scroll: %d\r\n", global_settings
.jump_scroll
);
1239 fprintf(fd
, "jump scroll delay: %d\r\n", global_settings
.jump_scroll_delay
);
1242 fprintf(fd
, "bidir limit: %d\r\n", global_settings
.bidir_limit
);
1245 static char* options
[] =
1246 {"off","on","1","2","3","4","5","6","7","8","9",
1247 "10","15","20","25","30","45","60","90"};
1248 fprintf(fd
, "backlight timeout: %s\r\n",
1249 options
[global_settings
.backlight_timeout
]);
1252 fprintf(fd
, "backlight when plugged: %s\r\n",
1253 boolopt
[global_settings
.backlight_on_when_charging
]);
1255 fprintf(fd
, "caption backlight: %s\r\n",
1256 boolopt
[global_settings
.caption_backlight
]);
1257 fprintf(fd
, "contrast: %d\r\n", global_settings
.contrast
);
1259 #ifdef HAVE_LCD_BITMAP
1260 fprintf(fd
, "invert: %s\r\n", boolopt
[global_settings
.invert
]);
1262 fprintf(fd
, "invert cursor: %s\r\n",
1263 boolopt
[global_settings
.invert_cursor
]);
1265 fprintf(fd
, "show icons: %s\r\n",
1266 boolopt
[global_settings
.show_icons
]);
1268 fprintf(fd
, "peak meter release: %d\r\n",
1269 global_settings
.peak_meter_release
);
1272 static char* options
[] =
1273 {"off","200ms","300ms","500ms","1","2","3","4","5",
1274 "6","7","8","9","10","15","20","30","1min"};
1275 fprintf(fd
, "peak meter hold: %s\r\n",
1276 options
[global_settings
.peak_meter_hold
]);
1280 static char* options
[] =
1281 {"on","1","2","3","4","5","6","7","8","9","10","15","20","25","30",
1282 "45","60","90","2min","3min","5min","10min","20min","45min","90min"};
1283 fprintf(fd
, "peak meter clip hold: %s\r\n",
1284 options
[global_settings
.peak_meter_clip_hold
]);
1287 fprintf(fd
, "peak meter busy: %s\r\npeak meter dbfs: %s\r\n",
1288 boolopt
[global_settings
.peak_meter_performance
],
1289 boolopt
[global_settings
.peak_meter_dbfs
]);
1291 fprintf(fd
, "peak meter min: %d\r\npeak meter max: %d\r\n",
1292 global_settings
.peak_meter_min
,
1293 global_settings
.peak_meter_max
);
1296 fprintf(fd
, "#\r\n# System\r\n#\r\ndisk spindown: %d\r\n",
1297 global_settings
.disk_spindown
);
1299 #ifdef HAVE_ATA_POWER_OFF
1300 fprintf(fd
, "disk poweroff: %s\r\n",
1301 boolopt
[global_settings
.disk_poweroff
]);
1304 fprintf(fd
, "battery capacity: %d\r\n", global_settings
.battery_capacity
);
1306 #ifdef HAVE_CHARGE_CTRL
1307 fprintf(fd
, "deep discharge: %s\r\ntrickle charge: %s\r\n",
1308 boolopt
[global_settings
.discharge
],
1309 boolopt
[global_settings
.trickle_charge
]);
1312 #ifdef HAVE_LCD_BITMAP
1314 static char* options
[] = {"24hour", "12hour"};
1315 fprintf(fd
, "time format: %s\r\n",
1316 options
[global_settings
.timeformat
]);
1321 static char* options
[] =
1322 {"off","1","2","3","4","5","6","7","8",
1323 "9","10","15","30","45","60"};
1324 fprintf(fd
, "idle poweroff: %s\r\n",
1325 options
[global_settings
.poweroff
]);
1328 #ifdef HAVE_MAS3587F
1329 fprintf(fd
, "#\r\n# Recording\r\n#\r\n");
1330 fprintf(fd
, "rec quality: %d\r\n", global_settings
.rec_quality
);
1333 static char* options
[] = {"44", "48", "32", "22", "24", "16"};
1334 fprintf(fd
, "rec frequency: %s\r\n",
1335 options
[global_settings
.rec_frequency
]);
1339 static char* options
[] = {"mic", "line", "spdif"};
1340 fprintf(fd
, "rec source: %s\r\n", options
[global_settings
.rec_source
]);
1344 static char* options
[] = {"stereo", "mono"};
1345 fprintf(fd
, "rec channels: %s\r\n",
1346 options
[global_settings
.rec_channels
]);
1350 "rec mic gain: %d\r\nrec left gain: %d\r\nrec right gain: %d\r\n",
1351 global_settings
.rec_mic_gain
,
1352 global_settings
.rec_left_gain
,
1353 global_settings
.rec_right_gain
);
1355 fprintf(fd
, "editable recordings: %s\r\n",
1356 boolopt
[global_settings
.rec_editable
]);
1360 fprintf(fd
, "max files in dir: %d\r\n", global_settings
.max_files_in_dir
);
1361 fprintf(fd
, "max files in playlist: %d\r\n",
1362 global_settings
.max_files_in_playlist
);
1365 static char* options
[] = {"off", "on", "ask"};
1366 fprintf(fd
, "recursive directory insert: %s\r\n",
1367 options
[global_settings
.recursive_dir_insert
]);
1372 lcd_clear_display();
1373 lcd_puts(0,0,str(LANG_SETTINGS_SAVED1
));
1374 lcd_puts(0,1,str(LANG_SETTINGS_SAVED2
));
1381 * reset all settings to their default value
1383 void settings_reset(void) {
1385 DEBUGF( "settings_reset()\n" );
1387 global_settings
.volume
= mpeg_sound_default(SOUND_VOLUME
);
1388 global_settings
.balance
= mpeg_sound_default(SOUND_BALANCE
);
1389 global_settings
.bass
= mpeg_sound_default(SOUND_BASS
);
1390 global_settings
.treble
= mpeg_sound_default(SOUND_TREBLE
);
1391 global_settings
.loudness
= mpeg_sound_default(SOUND_LOUDNESS
);
1392 global_settings
.bass_boost
= mpeg_sound_default(SOUND_SUPERBASS
);
1393 global_settings
.avc
= mpeg_sound_default(SOUND_AVC
);
1394 global_settings
.channel_config
= mpeg_sound_default(SOUND_CHANNELS
);
1395 global_settings
.rec_quality
= 5;
1396 global_settings
.rec_source
= 0; /* 0=mic */
1397 global_settings
.rec_frequency
= 0; /* 0=44.1kHz */
1398 global_settings
.rec_channels
= 0; /* 0=Stereo */
1399 global_settings
.rec_mic_gain
= 8;
1400 global_settings
.rec_left_gain
= 2; /* 0dB */
1401 global_settings
.rec_right_gain
= 2; /* 0dB */
1402 global_settings
.rec_editable
= false;
1403 global_settings
.resume
= RESUME_ASK
;
1404 global_settings
.contrast
= lcd_default_contrast();
1405 global_settings
.invert
= DEFAULT_INVERT_SETTING
;
1406 global_settings
.poweroff
= DEFAULT_POWEROFF_SETTING
;
1407 global_settings
.backlight_timeout
= DEFAULT_BACKLIGHT_TIMEOUT_SETTING
;
1408 global_settings
.invert_cursor
= DEFAULT_INVERT_CURSOR_SETTING
;
1409 global_settings
.backlight_on_when_charging
=
1410 DEFAULT_BACKLIGHT_ON_WHEN_CHARGING_SETTING
;
1411 global_settings
.battery_capacity
= 1500; /* mAh */
1412 global_settings
.trickle_charge
= true;
1413 global_settings
.dirfilter
= SHOW_MUSIC
;
1414 global_settings
.sort_case
= false;
1415 global_settings
.statusbar
= true;
1416 global_settings
.scrollbar
= true;
1417 global_settings
.repeat_mode
= REPEAT_ALL
;
1418 global_settings
.playlist_shuffle
= false;
1419 global_settings
.discharge
= 0;
1420 global_settings
.timeformat
= 0;
1421 global_settings
.volume_type
= 0;
1422 global_settings
.battery_type
= 0;
1423 global_settings
.scroll_speed
= 8;
1424 global_settings
.bidir_limit
= 50;
1425 #ifdef HAVE_LCD_CHARCELLS
1426 global_settings
.jump_scroll
= 0;
1427 global_settings
.jump_scroll_delay
= 50;
1429 global_settings
.scroll_delay
= 100;
1430 global_settings
.scroll_step
= 6;
1431 global_settings
.ff_rewind_min_step
= DEFAULT_FF_REWIND_MIN_STEP
;
1432 global_settings
.ff_rewind_accel
= DEFAULT_FF_REWIND_ACCEL_SETTING
;
1433 global_settings
.resume_index
= -1;
1434 global_settings
.resume_offset
= -1;
1435 global_settings
.disk_spindown
= 5;
1436 global_settings
.disk_poweroff
= false;
1437 global_settings
.buffer_margin
= 0;
1438 global_settings
.browse_current
= false;
1439 global_settings
.play_selected
= true;
1440 global_settings
.peak_meter_release
= 8;
1441 global_settings
.peak_meter_hold
= 3;
1442 global_settings
.peak_meter_clip_hold
= 16;
1443 global_settings
.peak_meter_dbfs
= true;
1444 global_settings
.peak_meter_min
= 60;
1445 global_settings
.peak_meter_max
= 0;
1446 global_settings
.peak_meter_performance
= false;
1447 global_settings
.wps_file
[0] = 0;
1448 global_settings
.font_file
[0] = 0;
1449 global_settings
.lang_file
[0] = 0;
1450 global_settings
.runtime
= 0;
1451 global_settings
.topruntime
= 0;
1452 global_settings
.fade_on_stop
= true;
1453 global_settings
.caption_backlight
= false;
1454 global_settings
.max_files_in_dir
= 400;
1455 global_settings
.max_files_in_playlist
= 10000;
1456 global_settings
.show_icons
= true;
1457 global_settings
.recursive_dir_insert
= RECURSE_OFF
;
1460 bool set_bool(char* string
, bool* variable
)
1462 return set_bool_options(string
, variable
, str(LANG_SET_BOOL_YES
),
1463 str(LANG_SET_BOOL_NO
), NULL
);
1466 /* wrapper to convert from int param to bool param in set_option */
1467 static void (*boolfunction
)(bool);
1468 void bool_funcwrapper(int value
)
1473 boolfunction(false);
1476 bool set_bool_options(char* string
, bool* variable
,
1477 char* yes_str
, char* no_str
, void (*function
)(bool))
1479 char* names
[] = { no_str
, yes_str
};
1482 boolfunction
= function
;
1483 result
= set_option(string
, variable
, BOOL
, names
, 2,
1484 function
? bool_funcwrapper
: NULL
);
1488 bool set_int(char* string
,
1491 void (*function
)(int),
1498 int org_value
=*variable
;
1500 #ifdef HAVE_LCD_BITMAP
1501 if(global_settings
.statusbar
)
1502 lcd_setmargins(0, STATUSBAR_HEIGHT
);
1504 lcd_setmargins(0, 0);
1507 lcd_clear_display();
1508 lcd_puts_scroll(0, 0, string
);
1512 snprintf(str
,sizeof str
,"%d %s ", *variable
, unit
);
1513 lcd_puts(0, 1, str
);
1514 #ifdef HAVE_LCD_BITMAP
1519 button
= button_get_w_tmo(HZ
/2);
1521 #ifdef HAVE_RECORDER_KEYPAD
1523 case BUTTON_UP
| BUTTON_REPEAT
:
1526 case BUTTON_RIGHT
| BUTTON_REPEAT
:
1531 #ifdef HAVE_RECORDER_KEYPAD
1533 case BUTTON_DOWN
| BUTTON_REPEAT
:
1536 case BUTTON_LEFT
| BUTTON_REPEAT
:
1541 #ifdef HAVE_RECORDER_KEYPAD
1550 #ifdef HAVE_RECORDER_KEYPAD
1556 if (*variable
!= org_value
) {
1557 *variable
=org_value
;
1559 lcd_puts(0, 0, str(LANG_MENU_SETTING_CANCEL
));
1566 case SYS_USB_CONNECTED
:
1571 if(*variable
> max
)
1574 if(*variable
< min
)
1577 if ( function
&& button
!= BUTTON_NONE
)
1578 function(*variable
);
1585 /* NOTE: the 'type' parameter specifies the actual type of the variable
1586 that 'variable' points to. not the value within. Only variables with
1587 type 'bool' should use parameter BOOL.
1589 The type separation is necessary since int and bool are fundamentally
1590 different and bit-incompatible types and can not share the same access
1593 bool set_option(char* string
, void* variable
, enum optiontype type
,
1594 char* options
[], int numoptions
, void (*function
)(int))
1598 int* intvar
= (int*)variable
;
1599 bool* boolvar
= (bool*)variable
;
1607 #ifdef HAVE_LCD_BITMAP
1608 if(global_settings
.statusbar
)
1609 lcd_setmargins(0, STATUSBAR_HEIGHT
);
1611 lcd_setmargins(0, 0);
1614 lcd_clear_display();
1615 lcd_puts_scroll(0, 0, string
);
1618 lcd_puts(0, 1, options
[type
==INT
? *intvar
: (int)*boolvar
]);
1619 #ifdef HAVE_LCD_BITMAP
1624 button
= button_get_w_tmo(HZ
/2);
1626 #ifdef HAVE_RECORDER_KEYPAD
1628 case BUTTON_UP
| BUTTON_REPEAT
:
1631 case BUTTON_RIGHT
| BUTTON_REPEAT
:
1634 if ( *intvar
< (numoptions
-1) )
1637 (*intvar
) -= (numoptions
-1);
1640 *boolvar
= !*boolvar
;
1643 #ifdef HAVE_RECORDER_KEYPAD
1645 case BUTTON_DOWN
| BUTTON_REPEAT
:
1648 case BUTTON_LEFT
| BUTTON_REPEAT
:
1654 (*intvar
) += (numoptions
-1);
1657 *boolvar
= !*boolvar
;
1660 #ifdef HAVE_RECORDER_KEYPAD
1669 #ifdef HAVE_RECORDER_KEYPAD
1675 if (((type
==INT
) && (*intvar
!= oldval
)) ||
1676 ((type
==BOOL
) && (*boolvar
!= (bool)oldval
))) {
1682 lcd_puts(0, 0, str(LANG_MENU_SETTING_CANCEL
));
1689 case SYS_USB_CONNECTED
:
1694 if ( function
&& button
!= BUTTON_NONE
) {
1705 #ifdef HAVE_LCD_BITMAP
1708 #define INDEX_WIDTH 2
1709 bool set_time(char* string
, int timedate
[])
1713 int min
= 0, steps
= 0;
1715 int lastcursorpos
= !cursorpos
;
1716 unsigned char buffer
[19];
1720 unsigned char reffub
[5];
1721 unsigned int width
, height
;
1722 unsigned int separator_width
, weekday_width
;
1723 unsigned int line_height
, prev_line_height
;
1724 int dayname
[] = {LANG_WEEKDAY_SUNDAY
,
1725 LANG_WEEKDAY_MONDAY
,
1726 LANG_WEEKDAY_TUESDAY
,
1727 LANG_WEEKDAY_WEDNESDAY
,
1728 LANG_WEEKDAY_THURSDAY
,
1729 LANG_WEEKDAY_FRIDAY
,
1730 LANG_WEEKDAY_SATURDAY
};
1731 int monthname
[] = {LANG_MONTH_JANUARY
,
1732 LANG_MONTH_FEBRUARY
,
1739 LANG_MONTH_SEPTEMBER
,
1741 LANG_MONTH_NOVEMBER
,
1742 LANG_MONTH_DECEMBER
};
1743 char cursor
[][3] = {{ 0, 8, 12}, {18, 8, 12}, {36, 8, 12},
1744 {24, 16, 24}, {54, 16, 18}, {78, 16, 12}};
1745 char daysinmonth
[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
1747 int monthname_len
= 0, dayname_len
= 0;
1750 #ifdef HAVE_LCD_BITMAP
1751 if(global_settings
.statusbar
)
1752 lcd_setmargins(0, STATUSBAR_HEIGHT
);
1754 lcd_setmargins(0, 0);
1756 lcd_clear_display();
1757 lcd_puts_scroll(0, 0, string
);
1760 /* calculate the number of days in febuary */
1761 realyear
= timedate
[3] + 2000;
1762 if((realyear
% 4 == 0 && !(realyear
% 100 == 0)) || realyear
% 400 == 0)
1763 daysinmonth
[1] = 29;
1765 daysinmonth
[1] = 28;
1767 /* fix day if month or year changed */
1768 if (timedate
[5] > daysinmonth
[timedate
[4] - 1])
1769 timedate
[5] = daysinmonth
[timedate
[4] - 1];
1771 /* calculate day of week */
1773 for(i
= 0; i
< timedate
[4] - 1; i
++) {
1774 julianday
+= daysinmonth
[i
];
1776 julianday
+= timedate
[5];
1777 timedate
[6] = (realyear
+ julianday
+ (realyear
- 1) / 4 -
1778 (realyear
- 1) / 100 + (realyear
- 1) / 400 + 7 - 1) % 7;
1780 snprintf(buffer
, sizeof(buffer
), "%02d:%02d:%02d ",
1781 timedate
[0], timedate
[1], timedate
[2]);
1782 lcd_puts(0, 1, buffer
);
1784 /* recalculate the positions and offsets */
1785 lcd_getstringsize(string
, &width
, &prev_line_height
);
1786 lcd_getstringsize(buffer
, &width
, &line_height
);
1787 lcd_getstringsize(":", &separator_width
, &height
);
1790 strncpy(reffub
, buffer
, 2);
1792 lcd_getstringsize(reffub
, &width
, &height
);
1793 cursor
[0][INDEX_X
] = 0;
1794 cursor
[0][INDEX_Y
] = prev_line_height
;
1795 cursor
[0][INDEX_WIDTH
] = width
;
1798 strncpy(reffub
, buffer
+ 3, 2);
1800 lcd_getstringsize(reffub
, &width
, &height
);
1801 cursor
[1][INDEX_X
] = cursor
[0][INDEX_WIDTH
] + separator_width
;
1802 cursor
[1][INDEX_Y
] = prev_line_height
;
1803 cursor
[1][INDEX_WIDTH
] = width
;
1806 strncpy(reffub
, buffer
+ 6, 2);
1808 lcd_getstringsize(reffub
, &width
, &height
);
1809 cursor
[2][INDEX_X
] = cursor
[0][INDEX_WIDTH
] + separator_width
+
1810 cursor
[1][INDEX_WIDTH
] + separator_width
;
1811 cursor
[2][INDEX_Y
] = prev_line_height
;
1812 cursor
[2][INDEX_WIDTH
] = width
;
1814 lcd_getstringsize(buffer
, &width
, &prev_line_height
);
1816 snprintf(buffer
, sizeof(buffer
), "%s 20%02d %s %02d ",
1817 str(dayname
[timedate
[6]]), timedate
[3],
1818 str(monthname
[timedate
[4] - 1]), timedate
[5]);
1819 lcd_puts(0, 2, buffer
);
1821 /* recalculate the positions and offsets */
1822 lcd_getstringsize(buffer
, &width
, &line_height
);
1824 /* store these 2 to prevent _repeated_ strlen calls */
1825 monthname_len
= strlen(str(monthname
[timedate
[4] - 1]));
1826 dayname_len
= strlen(str(dayname
[timedate
[6]]));
1829 strncpy(reffub
, buffer
, dayname_len
);
1830 reffub
[dayname_len
] = '\0';
1831 lcd_getstringsize(reffub
, &weekday_width
, &height
);
1832 lcd_getstringsize(" ", &separator_width
, &height
);
1835 strncpy(reffub
, buffer
+ dayname_len
+ 1, 4);
1837 lcd_getstringsize(reffub
, &width
, &height
);
1838 cursor
[3][INDEX_X
] = weekday_width
+ separator_width
;
1839 cursor
[3][INDEX_Y
] = cursor
[0][INDEX_Y
] + prev_line_height
;
1840 cursor
[3][INDEX_WIDTH
] = width
;
1843 strncpy(reffub
, buffer
+ dayname_len
+ 6, monthname_len
);
1844 reffub
[monthname_len
] = '\0';
1845 lcd_getstringsize(reffub
, &width
, &height
);
1846 cursor
[4][INDEX_X
] = weekday_width
+ separator_width
+
1847 cursor
[3][INDEX_WIDTH
] + separator_width
;
1848 cursor
[4][INDEX_Y
] = cursor
[0][INDEX_Y
] + prev_line_height
;
1849 cursor
[4][INDEX_WIDTH
] = width
;
1852 strncpy(reffub
, buffer
+ dayname_len
+ monthname_len
+ 7, 2);
1854 lcd_getstringsize(reffub
, &width
, &height
);
1855 cursor
[5][INDEX_X
] = weekday_width
+ separator_width
+
1856 cursor
[3][INDEX_WIDTH
] + separator_width
+
1857 cursor
[4][INDEX_WIDTH
] + separator_width
;
1858 cursor
[5][INDEX_Y
] = cursor
[0][INDEX_Y
] + prev_line_height
;
1859 cursor
[5][INDEX_WIDTH
] = width
;
1861 lcd_invertrect(cursor
[cursorpos
][INDEX_X
],
1862 cursor
[cursorpos
][INDEX_Y
] + lcd_getymargin(),
1863 cursor
[cursorpos
][INDEX_WIDTH
],
1866 lcd_puts(0, 4, str(LANG_TIME_SET
));
1867 lcd_puts(0, 5, str(LANG_TIME_REVERT
));
1868 #ifdef HAVE_LCD_BITMAP
1873 /* calculate the minimum and maximum for the number under cursor */
1874 if(cursorpos
!=lastcursorpos
) {
1875 lastcursorpos
=cursorpos
;
1881 case 1: /* minute */
1882 case 2: /* second */
1896 steps
= daysinmonth
[timedate
[4] - 1];
1901 button
= button_get_w_tmo(HZ
/2);
1904 cursorpos
= (cursorpos
+ 6 - 1) % 6;
1907 cursorpos
= (cursorpos
+ 6 + 1) % 6;
1910 case BUTTON_UP
| BUTTON_REPEAT
:
1911 timedate
[cursorpos
] = (timedate
[cursorpos
] + steps
- min
+ 1) %
1913 if(timedate
[cursorpos
] == 0)
1914 timedate
[cursorpos
] += min
;
1917 case BUTTON_DOWN
| BUTTON_REPEAT
:
1918 timedate
[cursorpos
]=(timedate
[cursorpos
]+steps
- min
- 1) %
1920 if(timedate
[cursorpos
] == 0)
1921 timedate
[cursorpos
] += min
;
1925 if (timedate
[6] == 0) /* rtc needs 1 .. 7 */
1932 #ifdef HAVE_RECORDER_KEYPAD
1934 #ifdef HAVE_LCD_BITMAP
1935 global_settings
.statusbar
= !global_settings
.statusbar
;
1937 if(global_settings
.statusbar
)
1938 lcd_setmargins(0, STATUSBAR_HEIGHT
);
1940 lcd_setmargins(0, 0);
1941 lcd_clear_display();
1942 lcd_puts_scroll(0, 0, string
);
1947 case SYS_USB_CONNECTED
: