Moved lcd default contrast knowledge from settings.c to lcd driver. Now lcd_init...
[kugel-rb.git] / apps / settings.c
blob06a44a34ccf86078f821376991284c551dc92bc5
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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 ****************************************************************************/
21 #include <stdio.h>
22 #include "config.h"
23 #include "kernel.h"
24 #include "thread.h"
25 #include "settings.h"
26 #include "disk.h"
27 #include "panic.h"
28 #include "debug.h"
29 #include "button.h"
30 #include "usb.h"
31 #include "backlight.h"
32 #include "lcd.h"
33 #include "mpeg.h"
34 #include "string.h"
35 #include "ata.h"
36 #include "fat.h"
37 #include "power.h"
38 #include "backlight.h"
39 #include "powermgmt.h"
40 #include "status.h"
41 #include "atoi.h"
42 #include "screens.h"
43 #include "ctype.h"
44 #include "file.h"
45 #include "errno.h"
46 #include "system.h"
47 #include "misc.h"
48 #ifdef HAVE_LCD_BITMAP
49 #include "icons.h"
50 #include "font.h"
51 #include "peakmeter.h"
52 #include "hwcompat.h"
53 #endif
54 #include "lang.h"
55 #include "language.h"
56 #include "wps-display.h"
57 #include "powermgmt.h"
58 #include "sprintf.h"
59 #include "keyboard.h"
60 #include "version.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
70 #define MAX_LINES 10
71 #else
72 #define MAX_LINES 2
73 #endif
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.
80 offset abs
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>
85 0x06 0x1a <bass 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,
94 scroll bar>
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)>
104 0x1d 0x31 <unused>
105 0x21 0x35 <repeat mode (bit 0-1), rec. channels (bit 2),
106 mic gain (bit 4-7)>
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
147 0xF4 <unused>
148 0xF8 <unused>
149 0xFC <unused>
151 *************************************/
153 #include "rtc.h"
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)
162 unsigned int i;
163 unsigned char cksum[2];
164 cksum[0] = cksum[1] = 0;
166 for (i=0; i < RTC_BLOCK_SIZE - 2; i+=2 ) {
167 cksum[0] ^= buf[i];
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);
183 /* insert header */
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;
196 #ifdef HAVE_RTC
197 unsigned int i;
198 #endif
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;
207 #ifdef HAVE_RTC
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]);
213 if (r) {
214 DEBUGF( "save_config_buffer: rtc_write failed at addr 0x%02x: %d\n",
215 14+i, r );
216 return r;
220 #endif
222 if (fat_startsector() != 0)
223 ata_delayed_write( 61, config_block);
224 else
225 return -1;
227 return 0;
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;
238 #ifdef HAVE_RTC
239 unsigned int i;
240 unsigned char rtc_block[RTC_BLOCK_SIZE];
241 #endif
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" );
259 correct = true;
263 #ifdef HAVE_RTC
264 /* read rtc block */
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);
279 correct = true;
281 #endif
283 if ( !correct ) {
284 /* if checksum is not valid, clear the config buffer */
285 DEBUGF( "load_config_buffer: header & checksum test failed\n" );
286 init_config_buffer();
287 return -1;
290 return 0;
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;
376 int elapsed_secs;
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;
394 #endif
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())
424 lcd_clear_display();
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));
428 #else
429 lcd_puts(4, 2, str(LANG_SETTINGS_SAVE_RECORDER));
430 lcd_puts(2, 4, str(LANG_SETTINGS_BATTERY_RECORDER));
431 lcd_update();
432 #endif
433 sleep(HZ*2);
434 return -1;
436 return 0;
439 #ifdef HAVE_LCD_BITMAP
441 * Applies the range infos stored in global_settings to
442 * the peak meter.
444 void settings_apply_pm_range(void)
446 int pm_min, pm_max;
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);
456 else
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)
470 char buf[64];
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);
477 #ifdef HAVE_MAS3587F
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);
481 #endif
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);
491 #endif
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);
498 #endif
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);
508 #endif
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);
516 else
517 wps_reset();
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);
524 font_load(buf);
526 else
527 font_reset();
529 lcd_scroll_step(global_settings.scroll_step);
530 #else
531 lcd_jump_scroll(global_settings.jump_scroll);
532 lcd_jump_scroll_delay(global_settings.jump_scroll_delay * (HZ/10));
533 #endif
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);
541 lang_load(buf);
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 */
554 settings_reset();
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];
732 #endif
735 settings_apply();
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)
750 char* ptr;
752 while ( isspace(*line) )
753 line++;
755 if ( *line == '#' )
756 return false;
758 ptr = strchr(line, ':');
759 if ( !ptr )
760 return false;
762 *name = line;
763 *ptr = 0;
764 ptr++;
765 while (isspace(*ptr))
766 ptr++;
767 *value = ptr;
768 return true;
771 void set_file(char* filename, char* setting, int maxlen)
773 char* fptr = strrchr(filename,'/');
774 int len;
775 int extlen = 0;
776 char* ptr;
778 if (!fptr)
779 return;
781 *fptr = 0;
782 fptr++;
784 len = strlen(fptr);
785 ptr = fptr + len;
786 while (*ptr != '.') {
787 extlen++;
788 ptr--;
791 if (strcmp(ROCKBOX_DIR, filename) || (len-extlen > maxlen))
792 return;
794 strncpy(setting, fptr, len-extlen);
795 setting[len-extlen]=0;
797 settings_save();
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);
812 *setting = num;
813 mpeg_sound_set(type, num);
815 #ifdef HAVE_MAS3507D
816 /* This is required to actually apply balance */
817 if (SOUND_BALANCE == type)
818 mpeg_sound_set(SOUND_VOLUME, global_settings.volume);
819 #endif
822 static void set_cfg_bool(bool* variable, char* value)
824 /* look for the 'n' in 'on' */
825 if ((value[1] & 0xdf) == 'N')
826 *variable = true;
827 else
828 *variable = false;
831 static void set_cfg_int(int* variable, char* value, int min, int max )
833 *variable = atoi(value);
835 if (*variable < min)
836 *variable = min;
837 else
838 if (*variable > max)
839 *variable = max;
842 static void set_cfg_option(int* variable, char* value,
843 char* options[], int numoptions )
845 int i;
847 for (i=0; i<numoptions; i++) {
848 if (!strcasecmp(options[i], value)) {
849 *variable = i;
850 break;
855 bool settings_load_config(char* file)
857 int fd;
858 char line[128];
860 fd = open(file, O_RDONLY);
861 if (fd < 0)
862 return false;
864 while (read_line(fd, line, sizeof line) > 0)
866 char* name;
867 char* value;
869 if (!settings_parseline(line, &name, &value))
870 continue;
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,
885 options, 7);
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,
914 options, 18);
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,
922 options, 25);
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);
952 #endif
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,
985 options, 14);
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,
996 options, 19);
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);
1007 #endif
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",
1029 "18:00","24:00"};
1030 set_cfg_option(&global_settings.rec_timesplit, value,
1031 options, 14);
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);
1048 #endif
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);
1062 #endif
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,
1067 50, 10000);
1068 else if (!strcasecmp(name, "max files in playlist"))
1069 set_cfg_int(&global_settings.max_files_in_playlist, value,
1070 1000, 20000);
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,
1074 options, 3);
1078 close(fd);
1079 settings_apply();
1080 settings_save();
1081 return true;
1085 bool settings_save_config(void)
1087 bool done = false;
1088 int fd, i, value;
1089 char filename[MAX_PATH];
1090 char* boolopt[] = {"off","on"};
1092 /* find unused filename */
1093 for (i=0; ; i++) {
1094 snprintf(filename, sizeof filename, "/.rockbox/config%02d.cfg", i);
1095 fd = open(filename, O_RDONLY);
1096 if (fd < 0)
1097 break;
1098 close(fd);
1101 /* allow user to modify filename */
1102 while (!done) {
1103 if (!kbd_input(filename, sizeof filename)) {
1104 fd = creat(filename,0);
1105 if (fd < 0) {
1106 lcd_clear_display();
1107 lcd_puts(0,0,str(LANG_FAILED));
1108 lcd_update();
1109 sleep(HZ);
1111 else
1112 done = true;
1114 else
1115 break;
1118 /* abort if file couldn't be created */
1119 if (!done) {
1120 lcd_clear_display();
1121 lcd_puts(0,0,str(LANG_RESET_DONE_CANCEL));
1122 lcd_update();
1123 sleep(HZ);
1124 return false;
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);
1140 #endif
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]);
1175 #endif
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]);
1229 #endif
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);
1237 #else
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);
1240 #endif
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);
1294 #endif
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]);
1302 #endif
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]);
1310 #endif
1312 #ifdef HAVE_LCD_BITMAP
1314 static char* options[] = {"24hour", "12hour"};
1315 fprintf(fd, "time format: %s\r\n",
1316 options[global_settings.timeformat]);
1318 #endif
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]);
1349 fprintf(fd,
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]);
1358 #endif
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]);
1370 close(fd);
1372 lcd_clear_display();
1373 lcd_puts(0,0,str(LANG_SETTINGS_SAVED1));
1374 lcd_puts(0,1,str(LANG_SETTINGS_SAVED2));
1375 lcd_update();
1376 sleep(HZ);
1377 return true;
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;
1428 #endif
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)
1470 if (value)
1471 boolfunction(true);
1472 else
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 };
1480 bool result;
1482 boolfunction = function;
1483 result = set_option(string, variable, BOOL, names, 2,
1484 function ? bool_funcwrapper : NULL);
1485 return result;
1488 bool set_int(char* string,
1489 char* unit,
1490 int* variable,
1491 void (*function)(int),
1492 int step,
1493 int min,
1494 int max )
1496 bool done = false;
1497 int button;
1498 int org_value=*variable;
1500 #ifdef HAVE_LCD_BITMAP
1501 if(global_settings.statusbar)
1502 lcd_setmargins(0, STATUSBAR_HEIGHT);
1503 else
1504 lcd_setmargins(0, 0);
1505 #endif
1507 lcd_clear_display();
1508 lcd_puts_scroll(0, 0, string);
1510 while (!done) {
1511 char str[32];
1512 snprintf(str,sizeof str,"%d %s ", *variable, unit);
1513 lcd_puts(0, 1, str);
1514 #ifdef HAVE_LCD_BITMAP
1515 status_draw(true);
1516 #endif
1517 lcd_update();
1519 button = button_get_w_tmo(HZ/2);
1520 switch(button) {
1521 #ifdef HAVE_RECORDER_KEYPAD
1522 case BUTTON_UP:
1523 case BUTTON_UP | BUTTON_REPEAT:
1524 #else
1525 case BUTTON_RIGHT:
1526 case BUTTON_RIGHT | BUTTON_REPEAT:
1527 #endif
1528 *variable += step;
1529 break;
1531 #ifdef HAVE_RECORDER_KEYPAD
1532 case BUTTON_DOWN:
1533 case BUTTON_DOWN | BUTTON_REPEAT:
1534 #else
1535 case BUTTON_LEFT:
1536 case BUTTON_LEFT | BUTTON_REPEAT:
1537 #endif
1538 *variable -= step;
1539 break;
1541 #ifdef HAVE_RECORDER_KEYPAD
1542 case BUTTON_LEFT:
1543 case BUTTON_PLAY:
1544 #else
1545 case BUTTON_PLAY:
1546 #endif
1547 done = true;
1548 break;
1550 #ifdef HAVE_RECORDER_KEYPAD
1551 case BUTTON_OFF:
1552 #else
1553 case BUTTON_STOP:
1554 case BUTTON_MENU:
1555 #endif
1556 if (*variable != org_value) {
1557 *variable=org_value;
1558 lcd_stop_scroll();
1559 lcd_puts(0, 0, str(LANG_MENU_SETTING_CANCEL));
1560 lcd_update();
1561 sleep(HZ/2);
1563 done = true;
1564 break;
1566 case SYS_USB_CONNECTED:
1567 usb_screen();
1568 return true;
1571 if(*variable > max )
1572 *variable = max;
1574 if(*variable < min )
1575 *variable = min;
1577 if ( function && button != BUTTON_NONE)
1578 function(*variable);
1580 lcd_stop_scroll();
1582 return false;
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
1591 code. */
1593 bool set_option(char* string, void* variable, enum optiontype type,
1594 char* options[], int numoptions, void (*function)(int))
1596 bool done = false;
1597 int button;
1598 int* intvar = (int*)variable;
1599 bool* boolvar = (bool*)variable;
1600 int oldval = 0;
1602 if (type==INT)
1603 oldval=*intvar;
1604 else
1605 oldval=*boolvar;
1607 #ifdef HAVE_LCD_BITMAP
1608 if(global_settings.statusbar)
1609 lcd_setmargins(0, STATUSBAR_HEIGHT);
1610 else
1611 lcd_setmargins(0, 0);
1612 #endif
1614 lcd_clear_display();
1615 lcd_puts_scroll(0, 0, string);
1617 while ( !done ) {
1618 lcd_puts(0, 1, options[type==INT ? *intvar : (int)*boolvar]);
1619 #ifdef HAVE_LCD_BITMAP
1620 status_draw(true);
1621 #endif
1622 lcd_update();
1624 button = button_get_w_tmo(HZ/2);
1625 switch (button) {
1626 #ifdef HAVE_RECORDER_KEYPAD
1627 case BUTTON_UP:
1628 case BUTTON_UP | BUTTON_REPEAT:
1629 #else
1630 case BUTTON_RIGHT:
1631 case BUTTON_RIGHT | BUTTON_REPEAT:
1632 #endif
1633 if (type == INT) {
1634 if ( *intvar < (numoptions-1) )
1635 (*intvar)++;
1636 else
1637 (*intvar) -= (numoptions-1);
1639 else
1640 *boolvar = !*boolvar;
1641 break;
1643 #ifdef HAVE_RECORDER_KEYPAD
1644 case BUTTON_DOWN:
1645 case BUTTON_DOWN | BUTTON_REPEAT:
1646 #else
1647 case BUTTON_LEFT:
1648 case BUTTON_LEFT | BUTTON_REPEAT:
1649 #endif
1650 if (type == INT) {
1651 if ( *intvar > 0 )
1652 (*intvar)--;
1653 else
1654 (*intvar) += (numoptions-1);
1656 else
1657 *boolvar = !*boolvar;
1658 break;
1660 #ifdef HAVE_RECORDER_KEYPAD
1661 case BUTTON_LEFT:
1662 case BUTTON_PLAY:
1663 #else
1664 case BUTTON_PLAY:
1665 #endif
1666 done = true;
1667 break;
1669 #ifdef HAVE_RECORDER_KEYPAD
1670 case BUTTON_OFF:
1671 #else
1672 case BUTTON_STOP:
1673 case BUTTON_MENU:
1674 #endif
1675 if (((type==INT) && (*intvar != oldval)) ||
1676 ((type==BOOL) && (*boolvar != (bool)oldval))) {
1677 if (type==INT)
1678 *intvar=oldval;
1679 else
1680 *boolvar=oldval;
1681 lcd_stop_scroll();
1682 lcd_puts(0, 0, str(LANG_MENU_SETTING_CANCEL));
1683 lcd_update();
1684 sleep(HZ/2);
1686 done = true;
1687 break;
1689 case SYS_USB_CONNECTED:
1690 usb_screen();
1691 return true;
1694 if ( function && button != BUTTON_NONE) {
1695 if (type == INT)
1696 function(*intvar);
1697 else
1698 function(*boolvar);
1701 lcd_stop_scroll();
1702 return false;
1705 #ifdef HAVE_LCD_BITMAP
1706 #define INDEX_X 0
1707 #define INDEX_Y 1
1708 #define INDEX_WIDTH 2
1709 bool set_time(char* string, int timedate[])
1711 bool done = false;
1712 int button;
1713 int min = 0, steps = 0;
1714 int cursorpos = 0;
1715 int lastcursorpos = !cursorpos;
1716 unsigned char buffer[19];
1717 int realyear;
1718 int julianday;
1719 int i;
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,
1733 LANG_MONTH_MARCH,
1734 LANG_MONTH_APRIL,
1735 LANG_MONTH_MAY,
1736 LANG_MONTH_JUNE,
1737 LANG_MONTH_JULY,
1738 LANG_MONTH_AUGUST,
1739 LANG_MONTH_SEPTEMBER,
1740 LANG_MONTH_OCTOBER,
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);
1753 else
1754 lcd_setmargins(0, 0);
1755 #endif
1756 lcd_clear_display();
1757 lcd_puts_scroll(0, 0, string);
1759 while ( !done ) {
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;
1764 else
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 */
1772 julianday = 0;
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);
1789 /* hour */
1790 strncpy(reffub, buffer, 2);
1791 reffub[2] = '\0';
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;
1797 /* minute */
1798 strncpy(reffub, buffer + 3, 2);
1799 reffub[2] = '\0';
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;
1805 /* second */
1806 strncpy(reffub, buffer + 6, 2);
1807 reffub[2] = '\0';
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]]));
1828 /* weekday */
1829 strncpy(reffub, buffer, dayname_len);
1830 reffub[dayname_len] = '\0';
1831 lcd_getstringsize(reffub, &weekday_width, &height);
1832 lcd_getstringsize(" ", &separator_width, &height);
1834 /* year */
1835 strncpy(reffub, buffer + dayname_len + 1, 4);
1836 reffub[4] = '\0';
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;
1842 /* month */
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;
1851 /* day */
1852 strncpy(reffub, buffer + dayname_len + monthname_len + 7, 2);
1853 reffub[2] = '\0';
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],
1864 line_height);
1866 lcd_puts(0, 4, str(LANG_TIME_SET));
1867 lcd_puts(0, 5, str(LANG_TIME_REVERT));
1868 #ifdef HAVE_LCD_BITMAP
1869 status_draw(true);
1870 #endif
1871 lcd_update();
1873 /* calculate the minimum and maximum for the number under cursor */
1874 if(cursorpos!=lastcursorpos) {
1875 lastcursorpos=cursorpos;
1876 switch(cursorpos) {
1877 case 0: /* hour */
1878 min = 0;
1879 steps = 24;
1880 break;
1881 case 1: /* minute */
1882 case 2: /* second */
1883 min = 0;
1884 steps = 60;
1885 break;
1886 case 3: /* year */
1887 min = 0;
1888 steps = 100;
1889 break;
1890 case 4: /* month */
1891 min = 1;
1892 steps = 12;
1893 break;
1894 case 5: /* day */
1895 min = 1;
1896 steps = daysinmonth[timedate[4] - 1];
1897 break;
1901 button = button_get_w_tmo(HZ/2);
1902 switch ( button ) {
1903 case BUTTON_LEFT:
1904 cursorpos = (cursorpos + 6 - 1) % 6;
1905 break;
1906 case BUTTON_RIGHT:
1907 cursorpos = (cursorpos + 6 + 1) % 6;
1908 break;
1909 case BUTTON_UP:
1910 case BUTTON_UP | BUTTON_REPEAT:
1911 timedate[cursorpos] = (timedate[cursorpos] + steps - min + 1) %
1912 steps + min;
1913 if(timedate[cursorpos] == 0)
1914 timedate[cursorpos] += min;
1915 break;
1916 case BUTTON_DOWN:
1917 case BUTTON_DOWN | BUTTON_REPEAT:
1918 timedate[cursorpos]=(timedate[cursorpos]+steps - min - 1) %
1919 steps + min;
1920 if(timedate[cursorpos] == 0)
1921 timedate[cursorpos] += min;
1922 break;
1923 case BUTTON_ON:
1924 done = true;
1925 if (timedate[6] == 0) /* rtc needs 1 .. 7 */
1926 timedate[6] = 7;
1927 break;
1928 case BUTTON_OFF:
1929 done = true;
1930 timedate[0] = -1;
1931 break;
1932 #ifdef HAVE_RECORDER_KEYPAD
1933 case BUTTON_F3:
1934 #ifdef HAVE_LCD_BITMAP
1935 global_settings.statusbar = !global_settings.statusbar;
1936 settings_save();
1937 if(global_settings.statusbar)
1938 lcd_setmargins(0, STATUSBAR_HEIGHT);
1939 else
1940 lcd_setmargins(0, 0);
1941 lcd_clear_display();
1942 lcd_puts_scroll(0, 0, string);
1943 #endif
1944 break;
1945 #endif
1947 case SYS_USB_CONNECTED:
1948 usb_screen();
1949 return true;
1953 return false;
1955 #endif