| /*************************************************************************** |
| * __________ __ ___. |
| * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| * \/ \/ \/ \/ \/ |
| * $Id$ |
| * |
| * Copyright (C) 2002 by wavey@wavey.org |
| * RTC config saving code (C) 2002 by hessu@hes.iki.fi |
| * |
| * All files in this archive are subject to the GNU General Public License. |
| * See the file COPYING in the source tree root for full license agreement. |
| * |
| * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| * KIND, either express or implied. |
| * |
| ****************************************************************************/ |
| |
| #include <stdio.h> |
| #include "config.h" |
| #include "kernel.h" |
| #include "thread.h" |
| #include "settings.h" |
| #include "disk.h" |
| #include "panic.h" |
| #include "debug.h" |
| #include "button.h" |
| #include "usb.h" |
| #include "backlight.h" |
| #include "lcd.h" |
| #include "mpeg.h" |
| #include "mp3_playback.h" |
| #include "talk.h" |
| #include "string.h" |
| #include "ata.h" |
| #include "fat.h" |
| #include "power.h" |
| #include "backlight.h" |
| #include "powermgmt.h" |
| #include "status.h" |
| #include "atoi.h" |
| #include "screens.h" |
| #include "ctype.h" |
| #include "file.h" |
| #include "errno.h" |
| #include "system.h" |
| #include "misc.h" |
| #ifdef HAVE_LCD_BITMAP |
| #include "icons.h" |
| #include "font.h" |
| #include "peakmeter.h" |
| #include "hwcompat.h" |
| #endif |
| #include "lang.h" |
| #include "language.h" |
| #include "wps-display.h" |
| #include "powermgmt.h" |
| #include "bookmark.h" |
| #include "sprintf.h" |
| #include "keyboard.h" |
| #include "version.h" |
| #ifdef HAVE_MAS3507D |
| void dac_line_in(bool enable); |
| #endif |
| struct user_settings global_settings; |
| char rockboxdir[] = ROCKBOX_DIR; /* config/font/data file directory */ |
| char rec_base_directory[] = REC_BASE_DIR; |
| |
| |
| #define CONFIG_BLOCK_VERSION 10 |
| #define CONFIG_BLOCK_SIZE 512 |
| #define RTC_BLOCK_SIZE 44 |
| |
| #ifdef HAVE_LCD_BITMAP |
| #define MAX_LINES 10 |
| #else |
| #define MAX_LINES 2 |
| #endif |
| |
| /******************************************** |
| |
| Config block as saved on the battery-packed RTC user RAM memory block |
| of 44 bytes, starting at offset 0x14 of the RTC memory space. |
| |
| offset abs |
| 0x00 0x14 "Roc" header signature: 0x52 0x6f 0x63 |
| 0x03 0x17 <version byte: 0x0> |
| 0x04 0x18 <volume byte> |
| 0x05 0x19 <balance byte> |
| 0x06 0x1a <bass byte> |
| 0x07 0x1b <treble byte> |
| 0x08 0x1c <loudness byte> |
| 0x09 0x1d <bass boost byte> |
| 0x0a 0x1e <contrast (bit 0-5), invert bit (bit 6), show_icons (bit 7)> |
| 0x0b 0x1f <backlight_on_when_charging, invert_cursor, backlight_timeout> |
| 0x0c 0x20 <poweroff timer byte> |
| 0x0d 0x21 <resume settings byte> |
| 0x0e 0x22 <shuffle,dirfilter,sort_case,discharge,statusbar,show_hidden, |
| scroll bar> |
| 0x0f 0x23 <volume type, battery type, timeformat, scroll speed> |
| 0x10 0x24 <ff/rewind min step, acceleration rate> |
| 0x11 0x25 <AVC, channel config> |
| 0x12 0x26 <(short) Resume playlist index, or -1 if no playlist resume> |
| 0x14 0x28 <(short) Resume playlist first index> |
| 0x16 0x2a <(int) Byte offset into resume file> |
| 0x1a 0x2e <time until disk spindown> |
| 0x1b 0x2f <browse current, play selected, recursive dir insert> |
| 0x1c 0x30 <peak meter hold timeout (bit 0-4), |
| flip_display (bit 6) |
| rec_editable (bit 7)> |
| 0x1d 0x31 <(int) Resume shuffle seed, or -1 if no shuffle> |
| 0x21 0x35 <repeat mode (bit 0-1), rec. channels (bit 2), |
| mic gain (bit 4-7)> |
| 0x22 0x36 <rec. quality (bit 0-2), source (bit 3-4), frequency (bit 5-7)> |
| 0x23 0x37 <rec. left gain (bit 0-3)> |
| 0x24 0x38 <rec. right gain (bit 0-3)> |
| 0x25 0x39 <disk poweroff flag (bit 0), MP3 buffer margin (bit 1-3), |
| Trickle charge flag (bit 4), buttonbar (bit 5)> |
| 0x26 0x40 <runtime low byte> |
| 0x27 0x41 <runtime high byte> |
| 0x28 0x42 <topruntime low byte> |
| 0x29 0x43 <topruntime high byte> |
| |
| 0x2a <checksum 2 bytes: xor of 0x0-0x29> |
| |
| Config memory is reset to 0xff and initialized with 'factory defaults' if |
| a valid header & checksum is not found. Config version number is only |
| increased when information is _relocated_ or space is _reused_ so that old |
| versions can read and modify configuration changed by new versions. New |
| versions should check for the value of '0xff' in each config memory |
| location used, and reset the setting in question with a factory default if |
| needed. Memory locations not used by a given version should not be |
| modified unless the header & checksum test fails. |
| |
| Because 0xff mean that the byte is unused, care must be taken so that |
| a used byte can't have the value 0xff. Either use only 7 bits, or make sure |
| that the value will never be 0xff. |
| |
| Rest of config block, only saved to disk: |
| 0xA8 (char)jump scroll mode (only for player) |
| 0xA9 (char)jump scroll delay (only for player) |
| 0xAA Max number of files in playlist (1000-20000) |
| 0xAC Max number of files in dir (50-10000) |
| 0xAE fade on pause/unpause/stop setting (bit 0) |
| caption backlight (bit 1) |
| car adapter mode (bit 2) |
| line_in (Player only) (bit 3) |
| playlist viewer icons (bit 4) |
| playlist viewer indices (bit 5) |
| playlist viewer track display (bit 6) |
| 0xAF <most-recent-bookmarks, auto-bookmark, autoload> |
| 0xB0 peak meter clip hold timeout (bit 0-4), peak meter performance (bit 7) |
| 0xB1 peak meter release step size, peak_meter_dbfs (bit 7) |
| 0xB2 peak meter min either in -db or in percent |
| 0xB3 peak meter max either in -db or in percent |
| 0xB4 battery capacity |
| 0xB5 scroll step in pixels |
| 0xB6 scroll start and endpoint delay |
| 0xB7 bidir scroll setting (bidi if 0-200% longer than screen width) |
| 0xB8 (char[20]) WPS file |
| 0xCC (char[20]) Lang file |
| 0xE0 (char[20]) Font file |
| 0xF4 Prerecording time (bit 0-4), Recording directory option (bit 5-6) |
| 0xF5-0xFF <unused> |
| |
| *************************************/ |
| |
| #include "rtc.h" |
| long lasttime = 0; |
| static unsigned char config_block[CONFIG_BLOCK_SIZE]; |
| |
| /* |
| * Calculates the checksum for the config block and returns it |
| */ |
| |
| static unsigned short calculate_config_checksum(unsigned char* buf) |
| { |
| unsigned int i; |
| unsigned char cksum[2]; |
| cksum[0] = cksum[1] = 0; |
| |
| for (i=0; i < RTC_BLOCK_SIZE - 2; i+=2 ) { |
| cksum[0] ^= buf[i]; |
| cksum[1] ^= buf[i+1]; |
| } |
| |
| return (cksum[0] << 8) | cksum[1]; |
| } |
| |
| /* |
| * initialize the config block buffer |
| */ |
| static void init_config_buffer( void ) |
| { |
| DEBUGF( "init_config_buffer()\n" ); |
| |
| /* reset to 0xff - all unused */ |
| memset(config_block, 0xff, CONFIG_BLOCK_SIZE); |
| /* insert header */ |
| config_block[0] = 'R'; |
| config_block[1] = 'o'; |
| config_block[2] = 'c'; |
| config_block[3] = CONFIG_BLOCK_VERSION; |
| } |
| |
| /* |
| * save the config block buffer to disk or RTC RAM |
| */ |
| static int save_config_buffer( void ) |
| { |
| unsigned short chksum; |
| #ifdef HAVE_RTC |
| unsigned int i; |
| #endif |
| |
| DEBUGF( "save_config_buffer()\n" ); |
| |
| /* update the checksum in the end of the block before saving */ |
| chksum = calculate_config_checksum(config_block); |
| config_block[ RTC_BLOCK_SIZE - 2 ] = chksum >> 8; |
| config_block[ RTC_BLOCK_SIZE - 1 ] = chksum & 0xff; |
| |
| #ifdef HAVE_RTC |
| /* FIXME: okay, it _would_ be cleaner and faster to implement rtc_write so |
| that it would write a number of bytes at a time since the RTC chip |
| supports that, but this will have to do for now 8-) */ |
| for (i=0; i < RTC_BLOCK_SIZE; i++ ) { |
| int r = rtc_write(0x14+i, config_block[i]); |
| if (r) { |
| DEBUGF( "save_config_buffer: rtc_write failed at addr 0x%02x: %d\n", |
| 14+i, r ); |
| return r; |
| } |
| } |
| |
| #endif |
| |
| if (fat_startsector() != 0) |
| ata_delayed_write( 61, config_block); |
| else |
| return -1; |
| |
| return 0; |
| } |
| |
| /* |
| * load the config block buffer from disk or RTC RAM |
| */ |
| static int load_config_buffer( void ) |
| { |
| unsigned short chksum; |
| bool correct = false; |
| |
| #ifdef HAVE_RTC |
| unsigned int i; |
| unsigned char rtc_block[RTC_BLOCK_SIZE]; |
| #endif |
| |
| DEBUGF( "load_config_buffer()\n" ); |
| |
| if (fat_startsector() != 0) { |
| ata_read_sectors( 61, 1, config_block); |
| |
| /* calculate the checksum, check it and the header */ |
| chksum = calculate_config_checksum(config_block); |
| |
| if (config_block[0] == 'R' && |
| config_block[1] == 'o' && |
| config_block[2] == 'c' && |
| config_block[3] == CONFIG_BLOCK_VERSION && |
| (chksum >> 8) == config_block[RTC_BLOCK_SIZE - 2] && |
| (chksum & 0xff) == config_block[RTC_BLOCK_SIZE - 1]) |
| { |
| DEBUGF( "load_config_buffer: header & checksum test ok\n" ); |
| correct = true; |
| } |
| } |
| |
| #ifdef HAVE_RTC |
| if(!correct) |
| { |
| /* If the disk sector was incorrect, reinit the buffer */ |
| memset(config_block, 0xff, CONFIG_BLOCK_SIZE); |
| } |
| /* read rtc block */ |
| for (i=0; i < RTC_BLOCK_SIZE; i++ ) |
| rtc_block[i] = rtc_read(0x14+i); |
| |
| chksum = calculate_config_checksum(rtc_block); |
| |
| /* if rtc block is ok, use that */ |
| if (rtc_block[0] == 'R' && |
| rtc_block[1] == 'o' && |
| rtc_block[2] == 'c' && |
| rtc_block[3] == CONFIG_BLOCK_VERSION && |
| (chksum >> 8) == rtc_block[RTC_BLOCK_SIZE - 2] && |
| (chksum & 0xff) == rtc_block[RTC_BLOCK_SIZE - 1]) |
| { |
| memcpy(config_block, rtc_block, RTC_BLOCK_SIZE); |
| correct = true; |
| } |
| #endif |
| |
| if ( !correct ) { |
| /* if checksum is not valid, clear the config buffer */ |
| DEBUGF( "load_config_buffer: header & checksum test failed\n" ); |
| init_config_buffer(); |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| /* |
| * persist all runtime user settings to disk or RTC RAM |
| */ |
| int settings_save( void ) |
| { |
| DEBUGF( "settings_save()\n" ); |
| |
| /* update the config block buffer with current |
| settings and save the block in the RTC */ |
| config_block[0x4] = (unsigned char)global_settings.volume; |
| config_block[0x5] = (char)global_settings.balance; |
| config_block[0x6] = (unsigned char)global_settings.bass; |
| config_block[0x7] = (unsigned char)global_settings.treble; |
| config_block[0x8] = (unsigned char)global_settings.loudness; |
| config_block[0x9] = (unsigned char)global_settings.bass_boost; |
| |
| config_block[0xa] = (unsigned char) |
| ((global_settings.contrast & 0x3f) | |
| (global_settings.invert ? 0x40 : 0) | |
| (global_settings.show_icons ? 0x80 : 0) ); |
| |
| config_block[0xb] = (unsigned char) |
| ((global_settings.backlight_on_when_charging?0x40:0) | |
| (global_settings.invert_cursor ? 0x20 : 0) | |
| (global_settings.backlight_timeout & 0x1f)); |
| config_block[0xc] = (unsigned char)global_settings.poweroff; |
| config_block[0xd] = (unsigned char)global_settings.resume; |
| |
| config_block[0xe] = (unsigned char) |
| ((global_settings.playlist_shuffle & 1) | |
| ((global_settings.dirfilter & 1) << 1) | |
| ((global_settings.sort_case & 1) << 2) | |
| ((global_settings.discharge & 1) << 3) | |
| ((global_settings.statusbar & 1) << 4) | |
| ((global_settings.dirfilter & 2) << 4) | |
| ((global_settings.scrollbar & 1) << 6)); |
| |
| config_block[0xf] = (unsigned char) |
| ((global_settings.volume_type & 1) | |
| ((global_settings.battery_type & 1) << 1) | |
| ((global_settings.timeformat & 1) << 2) | |
| ( global_settings.scroll_speed << 3)); |
| |
| config_block[0x10] = (unsigned char) |
| ((global_settings.ff_rewind_min_step & 15) << 4 | |
| (global_settings.ff_rewind_accel & 15)); |
| |
| config_block[0x11] = (unsigned char) |
| ((global_settings.avc & 0x03) | |
| ((global_settings.channel_config & 0x07) << 2)); |
| |
| *((short*)(&config_block[0x12])) = global_settings.resume_index; |
| *((short*)(&config_block[0x14])) = global_settings.resume_first_index; |
| memcpy(&config_block[0x16], &global_settings.resume_offset, 4); |
| DEBUGF( "+Resume index %X offset %X\n", |
| global_settings.resume_index, |
| global_settings.resume_offset ); |
| |
| config_block[0x1a] = (unsigned char)global_settings.disk_spindown; |
| config_block[0x1b] = (unsigned char) |
| (((global_settings.browse_current & 1)) | |
| ((global_settings.play_selected & 1) << 1) | |
| ((global_settings.recursive_dir_insert & 3) << 2)); |
| |
| config_block[0x1c] = (unsigned char)global_settings.peak_meter_hold | |
| (global_settings.flip_display ? 0x40 : 0) | |
| (global_settings.rec_editable?0x80:0); |
| |
| memcpy(&config_block[0x1d], &global_settings.resume_seed, 4); |
| |
| config_block[0x21] = (unsigned char) |
| ((global_settings.repeat_mode & 3) | |
| ((global_settings.rec_channels & 1) << 2) | |
| ((global_settings.rec_mic_gain & 0x0f) << 4)); |
| config_block[0x22] = (unsigned char) |
| ((global_settings.rec_quality & 7) | |
| ((global_settings.rec_source & 3) << 3) | |
| ((global_settings.rec_frequency & 7) << 5)); |
| config_block[0x23] = (unsigned char)global_settings.rec_left_gain; |
| config_block[0x24] = (unsigned char)global_settings.rec_right_gain; |
| config_block[0x25] = (unsigned char) |
| ((global_settings.disk_poweroff & 1) | |
| ((global_settings.buffer_margin & 7) << 1) | |
| ((global_settings.trickle_charge & 1) << 4) | |
| ((global_settings.buttonbar & 1) << 5)); |
| |
| { |
| int elapsed_secs; |
| |
| elapsed_secs = (current_tick - lasttime) / HZ; |
| global_settings.runtime += elapsed_secs; |
| lasttime += (elapsed_secs * HZ); |
| |
| if ( global_settings.runtime > global_settings.topruntime ) |
| global_settings.topruntime = global_settings.runtime; |
| |
| config_block[0x26]=(unsigned char)(global_settings.runtime & 0xff); |
| config_block[0x27]=(unsigned char)(global_settings.runtime >> 8); |
| config_block[0x28]=(unsigned char)(global_settings.topruntime & 0xff); |
| config_block[0x29]=(unsigned char)(global_settings.topruntime >> 8); |
| } |
| |
| #ifdef HAVE_LCD_CHARCELLS |
| config_block[0xa8]=(unsigned char)global_settings.jump_scroll; |
| config_block[0xa9]=(unsigned char)global_settings.jump_scroll_delay; |
| #endif |
| config_block[0xaa] = (unsigned char) |
| global_settings.max_files_in_playlist & 0xff; |
| config_block[0xab] = (unsigned char) |
| (global_settings.max_files_in_playlist >> 8) & 0xff; |
| config_block[0xac] = (unsigned char) |
| global_settings.max_files_in_dir & 0xff; |
| config_block[0xad] = (unsigned char) |
| (global_settings.max_files_in_dir >> 8) & 0xff; |
| config_block[0xae] = (unsigned char) |
| ((global_settings.fade_on_stop & 1) | |
| ((global_settings.caption_backlight & 1) << 1) | |
| ((global_settings.car_adapter_mode & 1) << 2) | |
| ((global_settings.line_in & 1) << 3) | |
| ((global_settings.playlist_viewer_icons & 1) << 4) | |
| ((global_settings.playlist_viewer_indices & 1) << 5) | |
| ((global_settings.playlist_viewer_track_display & 1) << 6)); |
| config_block[0xaf] = ((global_settings.usemrb << 5) | |
| (global_settings.autocreatebookmark << 2) | |
| (global_settings.autoloadbookmark)); |
| config_block[0xb0] = (unsigned char)global_settings.peak_meter_clip_hold | |
| (global_settings.peak_meter_performance ? 0x80 : 0); |
| config_block[0xb1] = global_settings.peak_meter_release | |
| (global_settings.peak_meter_dbfs ? 0x80 : 0); |
| config_block[0xb2] = (unsigned char)global_settings.peak_meter_min; |
| config_block[0xb3] = (unsigned char)global_settings.peak_meter_max; |
| |
| config_block[0xb4]=(global_settings.battery_capacity - 1000) / 50; |
| config_block[0xb5]=(unsigned char)global_settings.scroll_step; |
| config_block[0xb6]=(unsigned char)global_settings.scroll_delay; |
| config_block[0xb7]=(unsigned char)global_settings.bidir_limit; |
| |
| strncpy(&config_block[0xb8], global_settings.wps_file, MAX_FILENAME); |
| strncpy(&config_block[0xcc], global_settings.lang_file, MAX_FILENAME); |
| strncpy(&config_block[0xe0], global_settings.font_file, MAX_FILENAME); |
| |
| config_block[0xf4]=((unsigned char)global_settings.rec_prerecord_time | |
| ((unsigned char)global_settings.rec_directory << 5)); |
| config_block[0xf5] = (global_settings.talk_dir & 7) | |
| ((global_settings.talk_file & 3) << 3) | |
| ((global_settings.talk_menu & 1) << 5); |
| |
| if(save_config_buffer()) |
| { |
| lcd_clear_display(); |
| #ifdef HAVE_LCD_CHARCELLS |
| lcd_puts(0, 0, str(LANG_SETTINGS_SAVE_PLAYER)); |
| lcd_puts(0, 1, str(LANG_SETTINGS_BATTERY_PLAYER)); |
| #else |
| lcd_puts(4, 2, str(LANG_SETTINGS_SAVE_RECORDER)); |
| lcd_puts(2, 4, str(LANG_SETTINGS_BATTERY_RECORDER)); |
| lcd_update(); |
| #endif |
| sleep(HZ*2); |
| return -1; |
| } |
| return 0; |
| } |
| |
| #ifdef HAVE_LCD_BITMAP |
| /** |
| * Applies the range infos stored in global_settings to |
| * the peak meter. |
| */ |
| void settings_apply_pm_range(void) |
| { |
| int pm_min, pm_max; |
| |
| /* depending on the scale mode (dBfs or percent) the values |
| of global_settings.peak_meter_dbfs have different meanings */ |
| if (global_settings.peak_meter_dbfs) |
| { |
| /* convert to dBfs * 100 */ |
| pm_min = -(((int)global_settings.peak_meter_min) * 100); |
| pm_max = -(((int)global_settings.peak_meter_max) * 100); |
| } |
| else |
| { |
| /* percent is stored directly -> no conversion */ |
| pm_min = global_settings.peak_meter_min; |
| pm_max = global_settings.peak_meter_max; |
| } |
| |
| /* apply the range */ |
| peak_meter_init_range(global_settings.peak_meter_dbfs, pm_min, pm_max); |
| } |
| #endif /* HAVE_LCD_BITMAP */ |
| |
| void settings_apply(void) |
| { |
| char buf[64]; |
| |
| mpeg_sound_set(SOUND_BASS, global_settings.bass); |
| mpeg_sound_set(SOUND_TREBLE, global_settings.treble); |
| mpeg_sound_set(SOUND_BALANCE, global_settings.balance); |
| mpeg_sound_set(SOUND_VOLUME, global_settings.volume); |
| mpeg_sound_set(SOUND_CHANNELS, global_settings.channel_config); |
| #ifdef HAVE_MAS3587F |
| mpeg_sound_set(SOUND_LOUDNESS, global_settings.loudness); |
| mpeg_sound_set(SOUND_SUPERBASS, global_settings.bass_boost); |
| mpeg_sound_set(SOUND_AVC, global_settings.avc); |
| #endif |
| |
| mpeg_set_buffer_margin(global_settings.buffer_margin); |
| |
| lcd_set_contrast(global_settings.contrast); |
| lcd_scroll_speed(global_settings.scroll_speed); |
| backlight_set_timeout(global_settings.backlight_timeout); |
| backlight_set_on_when_charging(global_settings.backlight_on_when_charging); |
| ata_spindown(global_settings.disk_spindown); |
| #ifdef HAVE_MAS3507D |
| dac_line_in(global_settings.line_in); |
| #endif |
| #ifdef HAVE_ATA_POWER_OFF |
| ata_poweroff(global_settings.disk_poweroff); |
| #endif |
| |
| set_poweroff_timeout(global_settings.poweroff); |
| #ifdef HAVE_CHARGE_CTRL |
| charge_restart_level = global_settings.discharge ? |
| CHARGE_RESTART_LO : CHARGE_RESTART_HI; |
| enable_trickle_charge(global_settings.trickle_charge); |
| #endif |
| |
| set_battery_capacity(global_settings.battery_capacity); |
| |
| #ifdef HAVE_LCD_BITMAP |
| lcd_set_invert_display(global_settings.invert); |
| lcd_set_flip(global_settings.flip_display); |
| button_set_flip(global_settings.flip_display); |
| lcd_update(); /* refresh after flipping the screen */ |
| settings_apply_pm_range(); |
| peak_meter_init_times( |
| global_settings.peak_meter_release, global_settings.peak_meter_hold, |
| global_settings.peak_meter_clip_hold); |
| #endif |
| |
| if ( global_settings.wps_file[0] && |
| global_settings.wps_file[0] != 0xff ) { |
| snprintf(buf, sizeof buf, ROCKBOX_DIR "/%s.wps", |
| global_settings.wps_file); |
| wps_load(buf, false); |
| } |
| else |
| wps_reset(); |
| |
| #ifdef HAVE_LCD_BITMAP |
| if ( global_settings.font_file[0] && |
| global_settings.font_file[0] != 0xff ) { |
| snprintf(buf, sizeof buf, ROCKBOX_DIR FONT_DIR "/%s.fnt", |
| global_settings.font_file); |
| font_load(buf); |
| } |
| else |
| font_reset(); |
| |
| lcd_scroll_step(global_settings.scroll_step); |
| #else |
| lcd_jump_scroll(global_settings.jump_scroll); |
| lcd_jump_scroll_delay(global_settings.jump_scroll_delay * (HZ/10)); |
| #endif |
| lcd_bidir_scroll(global_settings.bidir_limit); |
| lcd_scroll_delay(global_settings.scroll_delay * (HZ/10)); |
| |
| if ( global_settings.lang_file[0] && |
| global_settings.lang_file[0] != 0xff ) { |
| snprintf(buf, sizeof buf, ROCKBOX_DIR LANG_DIR "/%s.lng", |
| global_settings.lang_file); |
| lang_load(buf); |
| } |
| |
| set_car_adapter_mode(global_settings.car_adapter_mode); |
| } |
| |
| /* |
| * load settings from disk or RTC RAM |
| */ |
| void settings_load(void) |
| { |
| |
| DEBUGF( "reload_all_settings()\n" ); |
| |
| /* populate settings with default values */ |
| settings_reset(); |
| |
| /* load the buffer from the RTC (resets it to all-unused if the block |
| is invalid) and decode the settings which are set in the block */ |
| if (!load_config_buffer()) { |
| if (config_block[0x4] != 0xFF) |
| global_settings.volume = config_block[0x4]; |
| if (config_block[0x5] != 0xFF) |
| global_settings.balance = (char)config_block[0x5]; |
| if (config_block[0x6] != 0xFF) |
| global_settings.bass = config_block[0x6]; |
| if (config_block[0x7] != 0xFF) |
| global_settings.treble = config_block[0x7]; |
| if (config_block[0x8] != 0xFF) |
| global_settings.loudness = config_block[0x8]; |
| if (config_block[0x9] != 0xFF) |
| global_settings.bass_boost = config_block[0x9]; |
| |
| if (config_block[0xa] != 0xFF) { |
| global_settings.contrast = config_block[0xa] & 0x3f; |
| global_settings.invert = |
| config_block[0xa] & 0x40 ? true : false; |
| if ( global_settings.contrast < MIN_CONTRAST_SETTING ) |
| global_settings.contrast = lcd_default_contrast(); |
| global_settings.show_icons = |
| config_block[0xa] & 0x80 ? true : false; |
| } |
| |
| if (config_block[0xb] != 0xFF) { |
| /* Bit 7 is unused to be able to detect uninitialized entry */ |
| global_settings.backlight_timeout = config_block[0xb] & 0x1f; |
| global_settings.invert_cursor = |
| config_block[0xb] & 0x20 ? true : false; |
| global_settings.backlight_on_when_charging = |
| config_block[0xb] & 0x40 ? true : false; |
| } |
| |
| if (config_block[0xc] != 0xFF) |
| global_settings.poweroff = config_block[0xc]; |
| if (config_block[0xd] != 0xFF) |
| global_settings.resume = config_block[0xd]; |
| if (config_block[0xe] != 0xFF) { |
| global_settings.playlist_shuffle = config_block[0xe] & 1; |
| global_settings.dirfilter = (config_block[0xe] >> 1) & 1; |
| global_settings.sort_case = (config_block[0xe] >> 2) & 1; |
| global_settings.discharge = (config_block[0xe] >> 3) & 1; |
| global_settings.statusbar = (config_block[0xe] >> 4) & 1; |
| global_settings.dirfilter |= ((config_block[0xe] >> 5) & 1) << 1; |
| global_settings.scrollbar = (config_block[0xe] >> 6) & 1; |
| /* Don't use the last bit, it must be unused to detect |
| an uninitialized entry */ |
| } |
| |
| if (config_block[0xf] != 0xFF) { |
| global_settings.volume_type = config_block[0xf] & 1; |
| global_settings.battery_type = (config_block[0xf] >> 1) & 1; |
| global_settings.timeformat = (config_block[0xf] >> 2) & 1; |
| global_settings.scroll_speed = config_block[0xf] >> 3; |
| } |
| |
| if (config_block[0x10] != 0xFF) { |
| global_settings.ff_rewind_min_step = (config_block[0x10] >> 4) & 15; |
| global_settings.ff_rewind_accel = config_block[0x10] & 15; |
| } |
| |
| if (config_block[0x11] != 0xFF) |
| { |
| global_settings.avc = config_block[0x11] & 0x03; |
| global_settings.channel_config = (config_block[0x11] >> 2) & 0x07; |
| } |
| |
| if (config_block[0x12] != 0xFF) |
| global_settings.resume_index = *((short*)(&config_block[0x12])); |
| |
| if (config_block[0x14] != 0xFF) |
| global_settings.resume_first_index= *((short*)(&config_block[0x14])); |
| |
| if (config_block[0x16] != 0xFF) |
| memcpy(&global_settings.resume_offset, &config_block[0x16], 4); |
| |
| if (config_block[0x1a] != 0xFF) |
| global_settings.disk_spindown = config_block[0x1a]; |
| |
| if (config_block[0x1b] != 0xFF) { |
| global_settings.browse_current = (config_block[0x1b]) & 1; |
| global_settings.play_selected = (config_block[0x1b] >> 1) & 1; |
| global_settings.recursive_dir_insert = |
| (config_block[0x1b] >> 2) & 3; |
| } |
| |
| if (config_block[0x1c] != 0xFF) { |
| global_settings.peak_meter_hold = (config_block[0x1c]) & 0x1f; |
| global_settings.flip_display = |
| (config_block[0x1c] & 0x40)?true:false; |
| global_settings.rec_editable = |
| (config_block[0x1c] & 0x80)?true:false; |
| } |
| |
| if (config_block[0x1d] != 0xFF) |
| memcpy(&global_settings.resume_seed, &config_block[0x1d], 4); |
| |
| if (config_block[0x21] != 0xFF) |
| { |
| global_settings.repeat_mode = config_block[0x21] & 3; |
| global_settings.rec_channels = (config_block[0x21] >> 2) & 1; |
| global_settings.rec_mic_gain = (config_block[0x21] >> 4) & 0x0f; |
| } |
| |
| if (config_block[0x22] != 0xFF) |
| { |
| global_settings.rec_quality = config_block[0x22] & 7; |
| global_settings.rec_source = (config_block[0x22] >> 3) & 3; |
| global_settings.rec_frequency = (config_block[0x22] >> 5) & 7; |
| } |
| |
| if (config_block[0x23] != 0xFF) |
| global_settings.rec_left_gain = config_block[0x23] & 0x0f; |
| |
| if (config_block[0x24] != 0xFF) |
| global_settings.rec_right_gain = config_block[0x24] & 0x0f; |
| |
| if (config_block[0x25] != 0xFF) |
| { |
| global_settings.disk_poweroff = config_block[0x25] & 1; |
| global_settings.buffer_margin = (config_block[0x25] >> 1) & 7; |
| global_settings.trickle_charge = (config_block[0x25] >> 4) & 1; |
| global_settings.buttonbar = (config_block[0x25] >> 5) & 1; |
| } |
| |
| if (config_block[0x27] != 0xff) |
| global_settings.runtime = |
| config_block[0x26] | (config_block[0x27] << 8); |
| |
| if (config_block[0x29] != 0xff) |
| global_settings.topruntime = |
| config_block[0x28] | (config_block[0x29] << 8); |
| |
| if (config_block[0xae] != 0xff) { |
| global_settings.fade_on_stop = config_block[0xae] & 1; |
| global_settings.caption_backlight = (config_block[0xae] >> 1) & 1; |
| global_settings.car_adapter_mode = (config_block[0xae] >> 2) & 1; |
| global_settings.line_in = (config_block[0xae] >> 3) & 1; |
| global_settings.playlist_viewer_icons = |
| (config_block[0xae] >> 4) & 1; |
| global_settings.playlist_viewer_indices = |
| (config_block[0xae] >> 5) & 1; |
| global_settings.playlist_viewer_track_display = |
| (config_block[0xae] >> 6) & 1; |
| } |
| |
| if(config_block[0xb0] != 0xff) { |
| global_settings.peak_meter_clip_hold = (config_block[0xb0]) & 0x1f; |
| global_settings.peak_meter_performance = |
| (config_block[0xb0] & 0x80) != 0; |
| } |
| |
| if(config_block[0xb1] != 0xff) { |
| global_settings.peak_meter_release = config_block[0xb1] & 0x7f; |
| global_settings.peak_meter_dbfs = (config_block[0xb1] & 0x80) != 0; |
| } |
| |
| if(config_block[0xb2] != 0xff) |
| global_settings.peak_meter_min = config_block[0xb2]; |
| |
| if(config_block[0xb3] != 0xff) |
| global_settings.peak_meter_max = config_block[0xb3]; |
| |
| if(config_block[0xb4] != 0xff) |
| global_settings.battery_capacity = config_block[0xb4]*50 + 1000; |
| |
| if (config_block[0xb5] != 0xff) |
| global_settings.scroll_step = config_block[0xb5]; |
| |
| if (config_block[0xb6] != 0xff) |
| global_settings.scroll_delay = config_block[0xb6]; |
| |
| if (config_block[0xb7] != 0xff) |
| global_settings.bidir_limit = config_block[0xb7]; |
| |
| if (config_block[0xac] != 0xff) |
| global_settings.max_files_in_dir = |
| config_block[0xac] | (config_block[0xad] << 8); |
| |
| if (config_block[0xaa] != 0xff) |
| global_settings.max_files_in_playlist = |
| config_block[0xaa] | (config_block[0xab] << 8); |
| |
| strncpy(global_settings.wps_file, &config_block[0xb8], MAX_FILENAME); |
| strncpy(global_settings.lang_file, &config_block[0xcc], MAX_FILENAME); |
| strncpy(global_settings.font_file, &config_block[0xe0], MAX_FILENAME); |
| |
| if (config_block[0xf4] != 0xff) { |
| global_settings.rec_prerecord_time = config_block[0xf4] & 0x1f; |
| global_settings.rec_directory = (config_block[0xf4] >> 5) & 3; |
| } |
| if (config_block[0xf5] != 0xff) { |
| global_settings.talk_dir = config_block[0xf5] & 7; |
| global_settings.talk_file = (config_block[0xf5] >> 3) & 3; |
| global_settings.talk_menu = (config_block[0xf5] >> 5) & 1; |
| } |
| |
| #ifdef HAVE_LCD_CHARCELLS |
| if (config_block[0xa8] != 0xff) |
| global_settings.jump_scroll = config_block[0xa8]; |
| if (config_block[0xa9] != 0xff) |
| global_settings.jump_scroll_delay = config_block[0xa9]; |
| #endif |
| if(config_block[0xaf] != 0xff) { |
| global_settings.usemrb = (config_block[0xaf] >> 5) & 3; |
| global_settings.autocreatebookmark = (config_block[0xaf] >> 2) & 7; |
| global_settings.autoloadbookmark = (config_block[0xaf]) & 3; |
| } |
| } |
| |
| settings_apply(); |
| } |
| |
| /* parse a line from a configuration file. the line format is: |
| |
| setting name: setting value |
| |
| Any whitespace before setting name or value (after ':') is ignored. |
| A # as first non-whitespace character discards the whole line. |
| Function sets pointers to null-terminated setting name and value. |
| Returns false if no valid config entry was found. |
| */ |
| |
| static bool settings_parseline(char* line, char** name, char** value) |
| { |
| char* ptr; |
| |
| while ( isspace(*line) ) |
| line++; |
| |
| if ( *line == '#' ) |
| return false; |
| |
| ptr = strchr(line, ':'); |
| if ( !ptr ) |
| return false; |
| |
| *name = line; |
| *ptr = 0; |
| ptr++; |
| while (isspace(*ptr)) |
| ptr++; |
| *value = ptr; |
| return true; |
| } |
| |
| void set_file(char* filename, char* setting, int maxlen) |
| { |
| char* fptr = strrchr(filename,'/'); |
| int len; |
| int extlen = 0; |
| char* ptr; |
| |
| if (!fptr) |
| return; |
| |
| *fptr = 0; |
| fptr++; |
| |
| len = strlen(fptr); |
| ptr = fptr + len; |
| while (*ptr != '.') { |
| extlen++; |
| ptr--; |
| } |
| |
| if (strncmp(ROCKBOX_DIR, filename ,strlen(ROCKBOX_DIR)) || |
| (len-extlen > maxlen)) |
| return; |
| |
| strncpy(setting, fptr, len-extlen); |
| setting[len-extlen]=0; |
| |
| settings_save(); |
| } |
| |
| static void set_sound(char* value, int type, int* setting) |
| { |
| int num = atoi(value); |
| |
| num = mpeg_phys2val(type, num); |
| |
| if ((num > mpeg_sound_max(type)) || |
| (num < mpeg_sound_min(type))) |
| { |
| num = mpeg_sound_default(type); |
| } |
| |
| *setting = num; |
| mpeg_sound_set(type, num); |
| |
| #ifdef HAVE_MAS3507D |
| /* This is required to actually apply balance */ |
| if (SOUND_BALANCE == type) |
| mpeg_sound_set(SOUND_VOLUME, global_settings.volume); |
| #endif |
| } |
| |
| static void set_cfg_bool(bool* variable, char* value) |
| { |
| /* look for the 'n' in 'on' */ |
| if ((value[1] & 0xdf) == 'N') |
| *variable = true; |
| else |
| *variable = false; |
| } |
| |
| static void set_cfg_int(int* variable, char* value, int min, int max ) |
| { |
| *variable = atoi(value); |
| |
| if (*variable < min) |
| *variable = min; |
| else |
| if (*variable > max) |
| *variable = max; |
| } |
| |
| static void set_cfg_option(int* variable, char* value, |
| char* options[], int numoptions ) |
| { |
| int i; |
| |
| for (i=0; i<numoptions; i++) { |
| if (!strcasecmp(options[i], value)) { |
| *variable = i; |
| break; |
| } |
| } |
| } |
| |
| bool settings_load_config(char* file) |
| { |
| int fd; |
| char line[128]; |
| |
| fd = open(file, O_RDONLY); |
| if (fd < 0) |
| return false; |
| |
| while (read_line(fd, line, sizeof line) > 0) |
| { |
| char* name; |
| char* value; |
| |
| if (!settings_parseline(line, &name, &value)) |
| continue; |
| |
| if (!strcasecmp(name, "volume")) |
| set_sound(value, SOUND_VOLUME, &global_settings.volume); |
| else if (!strcasecmp(name, "bass")) |
| set_sound(value, SOUND_BASS, &global_settings.bass); |
| else if (!strcasecmp(name, "treble")) |
| set_sound(value, SOUND_TREBLE, &global_settings.treble); |
| else if (!strcasecmp(name, "balance")) |
| set_sound(value, SOUND_BALANCE, &global_settings.balance); |
| else if (!strcasecmp(name, "channels")) { |
| static char* options[] = { |
| "stereo","stereo narrow","mono","mono left", |
| "mono right","karaoke","stereo wide"}; |
| set_cfg_option(&global_settings.channel_config, value, |
| options, 7); |
| } |
| else if (!strcasecmp(name, "wps")) { |
| if (wps_load(value,false)) |
| set_file(value, global_settings.wps_file, MAX_FILENAME); |
| } |
| else if (!strcasecmp(name, "lang")) { |
| if (!lang_load(value)) |
| set_file(value, global_settings.lang_file, MAX_FILENAME); |
| } |
| else if (!strcasecmp(name, "bidir limit")) |
| set_cfg_int(&global_settings.bidir_limit, value, 0, 200); |
| #ifdef HAVE_LCD_BITMAP |
| else if (!strcasecmp(name, "font")) { |
| if (font_load(value)) |
| set_file(value, global_settings.font_file, MAX_FILENAME); |
| } |
| else if (!strcasecmp(name, "scroll step")) |
| set_cfg_int(&global_settings.scroll_step, value, 1, LCD_WIDTH); |
| else if (!strcasecmp(name, "statusbar")) |
| set_cfg_bool(&global_settings.statusbar, value); |
| else if (!strcasecmp(name, "buttonbar")) |
| set_cfg_bool(&global_settings.buttonbar, value); |
| else if (!strcasecmp(name, "peak meter release")) |
| set_cfg_int(&global_settings.peak_meter_release, value, 1, 0x7e); |
| else if (!strcasecmp(name, "peak meter hold")) { |
| static char* options[] = { |
| "off","200ms","300ms","500ms", |
| "1","2","3","4","5","6","7","8","9","10", |
| "15","20","30","1min"}; |
| set_cfg_option(&global_settings.peak_meter_hold, value, |
| options, 18); |
| } |
| else if (!strcasecmp(name, "peak meter clip hold")) { |
| static char* options[] = { |
| "on","1","2","3","4","5","6","7","8","9","10", |
| "15","20","25","30","45","60","90", |
| "2min","3min","5min","10min","20min","45min","90min"}; |
| set_cfg_option(&global_settings.peak_meter_clip_hold, value, |
| options, 25); |
| } |
| else if (!strcasecmp(name, "peak meter dbfs")) |
| set_cfg_bool(&global_settings.peak_meter_dbfs, value); |
| else if (!strcasecmp(name, "peak meter min")) |
| set_cfg_int(&global_settings.peak_meter_min, value, 0, 100); |
| else if (!strcasecmp(name, "peak meter max")) |
| set_cfg_int(&global_settings.peak_meter_max, value, 0, 100); |
| else if (!strcasecmp(name, "peak meter busy")) |
| set_cfg_bool(&global_settings.peak_meter_performance, value); |
| else if (!strcasecmp(name, "volume display")) { |
| static char* options[] = {"graphic", "numeric"}; |
| set_cfg_option(&global_settings.volume_type, value, options, 2); |
| } |
| else if (!strcasecmp(name, "battery display")) { |
| static char* options[] = {"graphic", "numeric"}; |
| set_cfg_option(&global_settings.battery_type, value, options, 2); |
| } |
| else if (!strcasecmp(name, "time format")) { |
| static char* options[] = {"24hour", "12hour"}; |
| set_cfg_option(&global_settings.timeformat, value, options, 2); |
| } |
| else if (!strcasecmp(name, "scrollbar")) |
| set_cfg_bool(&global_settings.scrollbar, value); |
| else if (!strcasecmp(name, "invert")) |
| set_cfg_bool(&global_settings.invert, value); |
| else if (!strcasecmp(name, "flip display")) |
| set_cfg_bool(&global_settings.flip_display, value); |
| else if (!strcasecmp(name, "invert cursor")) |
| set_cfg_bool(&global_settings.invert_cursor, value); |
| else if (!strcasecmp(name, "show icons")) |
| set_cfg_bool(&global_settings.show_icons, value); |
| #endif |
| else if (!strcasecmp(name, "caption backlight")) |
| set_cfg_bool(&global_settings.caption_backlight, value); |
| else if (!strcasecmp(name, "shuffle")) |
| set_cfg_bool(&global_settings.playlist_shuffle, value); |
| else if (!strcasecmp(name, "repeat")) { |
| static char* options[] = {"off", "all", "one"}; |
| set_cfg_option(&global_settings.repeat_mode, value, options, 3); |
| } |
| else if (!strcasecmp(name, "resume")) { |
| static char* options[] = {"off", "ask", "ask once", "on"}; |
| set_cfg_option(&global_settings.resume, value, options, 4); |
| } |
| else if (!strcasecmp(name, "sort case")) |
| set_cfg_bool(&global_settings.sort_case, value); |
| else if (!strcasecmp(name, "show files")) { |
| static char* options[] = {"all", "supported","music", "playlists"}; |
| set_cfg_option(&global_settings.dirfilter, value, options, 4); |
| } |
| else if (!strcasecmp(name, "follow playlist")) |
| set_cfg_bool(&global_settings.browse_current, value); |
| else if (!strcasecmp(name, "play selected")) |
| set_cfg_bool(&global_settings.play_selected, value); |
| else if (!strcasecmp(name, "contrast")) |
| set_cfg_int(&global_settings.contrast, value, |
| MIN_CONTRAST_SETTING, MAX_CONTRAST_SETTING); |
| else if (!strcasecmp(name, "scroll speed")) |
| set_cfg_int(&global_settings.scroll_speed, value, 1, 10); |
| else if (!strcasecmp(name, "scan min step")) { |
| static char* options[] = |
| {"1","2","3","4","5","6","8","10", |
| "15","20","25","30","45","60"}; |
| set_cfg_option(&global_settings.ff_rewind_min_step, value, |
| options, 14); |
| } |
| else if (!strcasecmp(name, "scan accel")) |
| set_cfg_int(&global_settings.ff_rewind_accel, value, 0, 15); |
| else if (!strcasecmp(name, "scroll delay")) |
| set_cfg_int(&global_settings.scroll_delay, value, 0, 250); |
| else if (!strcasecmp(name, "backlight timeout")) { |
| static char* options[] = { |
| "off","on","1","2","3","4","5","6","7","8","9", |
| "10","15","20","25","30","45","60","90"}; |
| set_cfg_option(&global_settings.backlight_timeout, value, |
| options, 19); |
| } |
| else if (!strcasecmp(name, "backlight when plugged")) |
| set_cfg_bool(&global_settings.backlight_on_when_charging, value); |
| else if (!strcasecmp(name, "antiskip")) |
| set_cfg_int(&global_settings.buffer_margin, value, 0, 7); |
| else if (!strcasecmp(name, "disk spindown")) |
| set_cfg_int(&global_settings.disk_spindown, value, 3, 254); |
| #ifdef HAVE_ATA_POWER_OFF |
| else if (!strcasecmp(name, "disk poweroff")) |
| set_cfg_bool(&global_settings.disk_poweroff, value); |
| #endif |
| #ifdef HAVE_MAS3587F |
| else if (!strcasecmp(name, "loudness")) |
| set_sound(value, SOUND_LOUDNESS, &global_settings.loudness); |
| else if (!strcasecmp(name, "bass boost")) |
| set_sound(value, SOUND_SUPERBASS, &global_settings.bass_boost); |
| else if (!strcasecmp(name, "auto volume")) { |
| static char* options[] = {"off", "2", "4", "8" }; |
| set_cfg_option(&global_settings.avc, value, options, 4); |
| } |
| else if (!strcasecmp(name, "rec mic gain")) |
| set_sound(value, SOUND_MIC_GAIN, &global_settings.rec_mic_gain); |
| else if (!strcasecmp(name, "rec left gain")) |
| set_sound(value, SOUND_LEFT_GAIN, &global_settings.rec_left_gain); |
| else if (!strcasecmp(name, "rec right gain")) |
| set_sound(value, SOUND_RIGHT_GAIN, &global_settings.rec_right_gain); |
| else if (!strcasecmp(name, "rec quality")) |
| set_cfg_int(&global_settings.rec_quality, value, 0, 7); |
| else if (!strcasecmp(name, "rec timesplit")){ |
| static char* options[] = {"off", "00:05","00:10","00:15", |
| "00:30","01:00","02:00","04:00", |
| "06:00","08:00","10:00","12:00", |
| "18:00","24:00"}; |
| set_cfg_option(&global_settings.rec_timesplit, value, |
| options, 14); |
| } |
| else if (!strcasecmp(name, "rec source")) { |
| static char* options[] = {"mic", "line", "spdif"}; |
| set_cfg_option(&global_settings.rec_source, value, options, 3); |
| } |
| else if (!strcasecmp(name, "rec frequency")) { |
| static char* options[] = {"44", "48", "32", "22", "24", "16"}; |
| set_cfg_option(&global_settings.rec_frequency, value, options, 6); |
| } |
| else if (!strcasecmp(name, "rec channels")) { |
| static char* options[] = {"stereo", "mono"}; |
| set_cfg_option(&global_settings.rec_channels, value, options, 2); |
| } |
| else if (!strcasecmp(name, "editable recordings")) { |
| set_cfg_bool(&global_settings.rec_editable, value); |
| } |
| else if (!strcasecmp(name, "prerecording time")) { |
| set_cfg_int(&global_settings.rec_prerecord_time, value, 0, 30); |
| } |
| else if (!strcasecmp(name, "rec directory")) { |
| static char* options[] = {rec_base_directory, "current"}; |
| set_cfg_option(&global_settings.rec_directory, value, options, 2); |
| } |
| #endif |
| else if (!strcasecmp(name, "idle poweroff")) { |
| static char* options[] = {"off","1","2","3","4","5","6","7","8", |
| "9","10","15","30","45","60"}; |
| set_cfg_option(&global_settings.poweroff, value, options, 15); |
| } |
| #ifdef HAVE_MAS3507D |
| else if (!strcasecmp(name, "line in")){ |
| set_cfg_bool(&global_settings.line_in, value); |
| dac_line_in(global_settings.line_in); |
| } |
| #endif |
| else if (!strcasecmp(name, "battery capacity")) |
| set_cfg_int(&global_settings.battery_capacity, value, |
| 1500, BATTERY_CAPACITY_MAX); |
| #ifdef HAVE_CHARGE_CTRL |
| else if (!strcasecmp(name, "deep discharge")) |
| set_cfg_bool(&global_settings.discharge, value); |
| else if (!strcasecmp(name, "trickle charge")) |
| set_cfg_bool(&global_settings.trickle_charge, value); |
| #endif |
| else if (!strcasecmp(name, "volume fade")) |
| set_cfg_bool(&global_settings.fade_on_stop, value); |
| else if (!strcasecmp(name, "max files in dir")) |
| set_cfg_int(&global_settings.max_files_in_dir, value, |
| 50, 10000); |
| else if (!strcasecmp(name, "max files in playlist")) |
| set_cfg_int(&global_settings.max_files_in_playlist, value, |
| 1000, 20000); |
| else if (!strcasecmp(name, "car adapter mode")) |
| set_cfg_bool(&global_settings.car_adapter_mode, value); |
| else if (!strcasecmp(name, "recursive directory insert")) { |
| static char* options[] = {"off", "on", "ask"}; |
| set_cfg_option(&global_settings.recursive_dir_insert, value, |
| options, 3); |
| } |
| else if (!strcasecmp(name, "autoload bookmarks")) |
| { |
| static char* options[] = {"off", "on", "ask"}; |
| set_cfg_option(&global_settings.autoloadbookmark, value, options, 3); |
| } |
| else if (!strcasecmp(name, "autocreate bookmarks")) |
| { |
| static char* options[] = {"off", "on", "ask","recent only - on", "recent only - ask"}; |
| set_cfg_option(&global_settings.autocreatebookmark, value, options, 5); |
| } |
| else if (!strcasecmp(name, "use most-recent-bookmarks")) |
| { |
| static char* options[] = {"off", "on", "unique only"}; |
| set_cfg_option(&global_settings.usemrb, value, options, 3); |
| } |
| else if (!strcasecmp(name, "playlist viewer icons")) |
| set_cfg_bool(&global_settings.playlist_viewer_icons, value); |
| else if (!strcasecmp(name, "playlist viewer indices")) |
| set_cfg_bool(&global_settings.playlist_viewer_indices, value); |
| else if (!strcasecmp(name, "playlist viewer track display")) |
| { |
| static char* options[] = {"track name", "full path"}; |
| set_cfg_option(&global_settings.playlist_viewer_track_display, |
| value, options, 2); |
| } |
| else if (!strcasecmp(name, "talk dir")) |
| { |
| static char* options[] = {"off", "number", "spell", "enter", "hover"}; |
| set_cfg_option(&global_settings.talk_dir, value, options, 5); |
| } |
| else if (!strcasecmp(name, "talk file")) |
| { |
| static char* options[] = {"off", "number", "spell"}; |
| set_cfg_option(&global_settings.talk_file, value, options, 3); |
| } |
| else if (!strcasecmp(name, "talk menu")) |
| { |
| set_cfg_bool(&global_settings.talk_menu, value); |
| } |
| } |
| |
| close(fd); |
| settings_apply(); |
| settings_save(); |
| return true; |
| } |
| |
| |
| bool settings_save_config(void) |
| { |
| bool done = false; |
| int fd, i, value; |
| char filename[MAX_PATH]; |
| char* boolopt[] = {"off","on"}; |
| char* triopt[] = {"off","on","ask"}; |
| |
| /* find unused filename */ |
| for (i=0; ; i++) { |
| snprintf(filename, sizeof filename, ROCKBOX_DIR "/config%02d.cfg", i); |
| fd = open(filename, O_RDONLY); |
| if (fd < 0) |
| break; |
| close(fd); |
| } |
| |
| /* allow user to modify filename */ |
| while (!done) { |
| if (!kbd_input(filename, sizeof filename)) { |
| fd = creat(filename,0); |
| if (fd < 0) { |
| lcd_clear_display(); |
| lcd_puts(0,0,str(LANG_FAILED)); |
| lcd_update(); |
| sleep(HZ); |
| } |
| else |
| done = true; |
| } |
| else |
| break; |
| } |
| |
| /* abort if file couldn't be created */ |
| if (!done) { |
| lcd_clear_display(); |
| lcd_puts(0,0,str(LANG_RESET_DONE_CANCEL)); |
| lcd_update(); |
| sleep(HZ); |
| return false; |
| } |
| |
| fprintf(fd, "# >>> .cfg file created by rockbox %s <<<\r\n", appsversion); |
| fprintf(fd, "# >>> http://rockbox.haxx.se <<<\r\n#\r\n"); |
| fprintf(fd, "#\r\n# wps / language / font \r\n#\r\n"); |
| |
| if (global_settings.wps_file[0] != 0) |
| fprintf(fd, "wps: %s/%s.wps\r\n", ROCKBOX_DIR, |
| global_settings.wps_file); |
| |
| if (global_settings.lang_file[0] != 0) |
| fprintf(fd, "lang: %s/%s.lng\r\n", ROCKBOX_DIR LANG_DIR, |
| global_settings.lang_file); |
| |
| #ifdef HAVE_LCD_BITMAP |
| if (global_settings.font_file[0] != 0) |
| fprintf(fd, "font: %s/%s.fnt\r\n", ROCKBOX_DIR FONT_DIR, |
| global_settings.font_file); |
| #endif |
| |
| fprintf(fd, "#\r\n# Sound settings\r\n#\r\n"); |
| |
| value = mpeg_val2phys(SOUND_VOLUME, global_settings.volume); |
| fprintf(fd, "volume: %d\r\n", value); |
| |
| value = mpeg_val2phys(SOUND_BASS, global_settings.bass); |
| fprintf(fd, "bass: %d\r\n", value); |
| |
| value = mpeg_val2phys(SOUND_TREBLE, global_settings.treble); |
| fprintf(fd, "treble: %d\r\n", value); |
| |
| value = mpeg_val2phys(SOUND_BALANCE, global_settings.balance); |
| fprintf(fd, "balance: %d\r\n", value); |
| |
| { |
| static char* options[] = |
| {"stereo","stereo narrow","mono","mono left", |
| "mono right","karaoke","stereo wide"}; |
| fprintf(fd, "channels: %s\r\n", |
| options[global_settings.channel_config]); |
| } |
| |
| #ifdef HAVE_MAS3587F |
| value = mpeg_val2phys(SOUND_LOUDNESS, global_settings.loudness); |
| fprintf(fd, "loudness: %d\r\n", value); |
| |
| value = mpeg_val2phys(SOUND_SUPERBASS, global_settings.bass_boost); |
| fprintf(fd, "bass boost: %d\r\n", value); |
| |
| { |
| static char* options[] = {"off", "2", "4", "8" }; |
| fprintf(fd, "auto volume: %s\r\n", options[global_settings.avc]); |
| } |
| #endif |
| |
| fprintf(fd, "#\r\n# Playback\r\n#\r\n"); |
| fprintf(fd, "shuffle: %s\r\n", boolopt[global_settings.playlist_shuffle]); |
| |
| { |
| static char* options[] = {"off", "all", "one"}; |
| fprintf(fd, "repeat: %s\r\n", options[global_settings.repeat_mode]); |
| } |
| |
| fprintf(fd, "play selected: %s\r\n", |
| boolopt[global_settings.play_selected]); |
| |
| { |
| static char* options[] = {"off", "ask", "ask once", "on"}; |
| fprintf(fd, "resume: %s\r\n", options[global_settings.resume]); |
| } |
| |
| { |
| static char* options[] = |
| {"1","2","3","4","5","6","8","10", |
| "15","20","25","30","45","60"}; |
| fprintf(fd, "scan min step: %s\r\n", |
| options[global_settings.ff_rewind_min_step]); |
| } |
| |
| fprintf(fd, "scan accel: %d\r\nantiskip: %d\r\n", |
| global_settings.ff_rewind_accel, |
| global_settings.buffer_margin); |
| fprintf(fd, "volume fade: %s\r\n", boolopt[global_settings.fade_on_stop]); |
| fprintf(fd, "#\r\n# File View\r\n#\r\n"); |
| fprintf(fd, "sort case: %s\r\n", boolopt[global_settings.sort_case]); |
| |
| { |
| static char* options[] = {"all", "supported","music", "playlists"}; |
| fprintf(fd, "show files: %s\r\n", options[global_settings.dirfilter]); |
| } |
| |
| fprintf(fd, "follow playlist: %s\r\n", |
| boolopt[global_settings.browse_current]); |
| |
| fprintf(fd, "#\r\n# Display\r\n#\r\n"); |
| |
| #ifdef HAVE_LCD_BITMAP |
| fprintf(fd, "statusbar: %s\r\nbuttonbar: %s\r\nscrollbar: %s\r\n", |
| boolopt[global_settings.statusbar], |
| boolopt[global_settings.buttonbar], |
| boolopt[global_settings.scrollbar]); |
| |
| { |
| static char* options[] = {"graphic", "numeric"}; |
| fprintf(fd, "volume display: %s\r\nbattery display: %s\r\n", |
| options[global_settings.volume_type], |
| options[global_settings.battery_type]); |
| } |
| #endif |
| |
| fprintf(fd, "scroll speed: %d\r\nscroll delay: %d\r\n", |
| global_settings.scroll_speed, |
| global_settings.scroll_delay); |
| |
| #ifdef HAVE_LCD_BITMAP |
| fprintf(fd, "scroll step: %d\r\n", global_settings.scroll_step); |
| #else |
| fprintf(fd, "jump scroll: %d\r\n", global_settings.jump_scroll); |
| fprintf(fd, "jump scroll delay: %d\r\n", global_settings.jump_scroll_delay); |
| #endif |
| |
| fprintf(fd, "bidir limit: %d\r\n", global_settings.bidir_limit); |
| |
| { |
| static char* options[] = |
| {"off","on","1","2","3","4","5","6","7","8","9", |
| "10","15","20","25","30","45","60","90"}; |
| fprintf(fd, "backlight timeout: %s\r\n", |
| options[global_settings.backlight_timeout]); |
| } |
| |
| fprintf(fd, "backlight when plugged: %s\r\n", |
| boolopt[global_settings.backlight_on_when_charging]); |
| |
| fprintf(fd, "caption backlight: %s\r\n", |
| boolopt[global_settings.caption_backlight]); |
| fprintf(fd, "contrast: %d\r\n", global_settings.contrast); |
| |
| #ifdef HAVE_LCD_BITMAP |
| fprintf(fd, "invert: %s\r\n", boolopt[global_settings.invert]); |
| |
| fprintf(fd, "flip display: %s\r\n", boolopt[global_settings.flip_display]); |
| |
| fprintf(fd, "invert cursor: %s\r\n", |
| boolopt[global_settings.invert_cursor]); |
| |
| fprintf(fd, "show icons: %s\r\n", |
| boolopt[global_settings.show_icons]); |
| |
| fprintf(fd, "peak meter release: %d\r\n", |
| global_settings.peak_meter_release); |
| |
| { |
| static char* options[] = |
| {"off","200ms","300ms","500ms","1","2","3","4","5", |
| "6","7","8","9","10","15","20","30","1min"}; |
| fprintf(fd, "peak meter hold: %s\r\n", |
| options[global_settings.peak_meter_hold]); |
| } |
| |
| { |
| static char* options[] = |
| {"on","1","2","3","4","5","6","7","8","9","10","15","20","25","30", |
| "45","60","90","2min","3min","5min","10min","20min","45min","90min"}; |
| fprintf(fd, "peak meter clip hold: %s\r\n", |
| options[global_settings.peak_meter_clip_hold]); |
| } |
| |
| fprintf(fd, "peak meter busy: %s\r\npeak meter dbfs: %s\r\n", |
| boolopt[global_settings.peak_meter_performance], |
| boolopt[global_settings.peak_meter_dbfs]); |
| |
| fprintf(fd, "peak meter min: %d\r\npeak meter max: %d\r\n", |
| global_settings.peak_meter_min, |
| global_settings.peak_meter_max); |
| #endif |
| |
| fprintf(fd, "#\r\n# System\r\n#\r\ndisk spindown: %d\r\n", |
| global_settings.disk_spindown); |
| |
| #ifdef HAVE_ATA_POWER_OFF |
| fprintf(fd, "disk poweroff: %s\r\n", |
| boolopt[global_settings.disk_poweroff]); |
| #endif |
| |
| fprintf(fd, "battery capacity: %d\r\n", global_settings.battery_capacity); |
| |
| #ifdef HAVE_CHARGE_CTRL |
| fprintf(fd, "deep discharge: %s\r\ntrickle charge: %s\r\n", |
| boolopt[global_settings.discharge], |
| boolopt[global_settings.trickle_charge]); |
| #endif |
| |
| #ifdef HAVE_LCD_BITMAP |
| { |
| static char* options[] = {"24hour", "12hour"}; |
| fprintf(fd, "time format: %s\r\n", |
| options[global_settings.timeformat]); |
| } |
| #endif |
| |
| { |
| static char* options[] = |
| {"off","1","2","3","4","5","6","7","8", |
| "9","10","15","30","45","60"}; |
| fprintf(fd, "idle poweroff: %s\r\n", |
| options[global_settings.poweroff]); |
| } |
| |
| fprintf(fd, "car adapter mode: %s\r\n", |
| boolopt[global_settings.car_adapter_mode]); |
| |
| #ifdef HAVE_MAS3507D |
| fprintf(fd, "line in: %s\r\n", boolopt[global_settings.line_in]); |
| #endif |
| |
| fprintf(fd, "max files in dir: %d\r\n", global_settings.max_files_in_dir); |
| fprintf(fd, "max files in playlist: %d\r\n", |
| global_settings.max_files_in_playlist); |
| |
| #ifdef HAVE_MAS3587F |
| fprintf(fd, "#\r\n# Recording\r\n#\r\n"); |
| fprintf(fd, "rec quality: %d\r\n", global_settings.rec_quality); |
| |
| { |
| static char* options[] = {"44", "48", "32", "22", "24", "16"}; |
| fprintf(fd, "rec frequency: %s\r\n", |
| options[global_settings.rec_frequency]); |
| } |
| |
| { |
| static char* options[] = {"mic", "line", "spdif"}; |
| fprintf(fd, "rec source: %s\r\n", options[global_settings.rec_source]); |
| } |
| |
| { |
| static char* options[] = {"stereo", "mono"}; |
| fprintf(fd, "rec channels: %s\r\n", |
| options[global_settings.rec_channels]); |
| } |
| |
| fprintf(fd, |
| "rec mic gain: %d\r\nrec left gain: %d\r\nrec right gain: %d\r\n", |
| global_settings.rec_mic_gain, |
| global_settings.rec_left_gain, |
| global_settings.rec_right_gain); |
| |
| fprintf(fd, "editable recordings: %s\r\n", |
| boolopt[global_settings.rec_editable]); |
| |
| fprintf(fd, "prerecording time: %d\r\n", |
| global_settings.rec_prerecord_time); |
| |
| { |
| static char* options[] = {rec_base_directory, "current"}; |
| fprintf(fd, "rec directory: %s\r\n", |
| options[global_settings.rec_directory]); |
| } |
| |
| #endif |
| |
| fprintf(fd, "#\r\n# Bookmarking\r\n#\r\n"); |
| { |
| fprintf(fd, "autoload bookmarks: %s\r\n", |
| triopt[global_settings.autoloadbookmark]); |
| } |
| |
| { |
| static char* options[] = {"off", "on", "ask","recent only - on", "recent only - ask"}; |
| fprintf(fd, "autocreate bookmarks: %s\r\n", |
| options[global_settings.autocreatebookmark]); |
| } |
| |
| { |
| static char* options[] = {"off", "on", "unique only"}; |
| fprintf(fd, "use most-recent-bookmarks: %s\r\n", options[global_settings.usemrb]); |
| } |
| |
| fprintf(fd, "#\r\n# Playlists\r\n#\r\n"); |
| { |
| fprintf(fd, "recursive directory insert: %s\r\n", |
| triopt[global_settings.recursive_dir_insert]); |
| } |
| |
| fprintf(fd, "#\r\n# Playlist viewer\r\n#\r\n"); |
| { |
| fprintf(fd, "playlist viewer icons: %s\r\n", |
| boolopt[global_settings.playlist_viewer_icons]); |
| fprintf(fd, "playlist viewer indices: %s\r\n", |
| boolopt[global_settings.playlist_viewer_indices]); |
| { |
| static char* options[] = {"track name", "full path"}; |
| fprintf(fd, "playlist viewer track display: %s\r\n", |
| options[global_settings.playlist_viewer_track_display]); |
| } |
| } |
| fprintf(fd, "#\r\n# Voice\r\n#\r\n"); |
| { |
| static char* options[] = {"off", "number", "spell", "enter", "hover"}; |
| fprintf(fd, "talk dir: %s\r\n", |
| options[global_settings.talk_dir]); |
| fprintf(fd, "talk file: %s\r\n", /* recycle the options, */ |
| options[global_settings.talk_file]); /* first 3 are alike */ |
| fprintf(fd, "talk menu: %s\r\n", |
| boolopt[global_settings.talk_menu]); |
| } |
| |
| close(fd); |
| |
| lcd_clear_display(); |
| lcd_puts(0,0,str(LANG_SETTINGS_SAVED1)); |
| lcd_puts(0,1,str(LANG_SETTINGS_SAVED2)); |
| lcd_update(); |
| sleep(HZ); |
| return true; |
| } |
| |
| /* |
| * reset all settings to their default value |
| */ |
| void settings_reset(void) { |
| |
| DEBUGF( "settings_reset()\n" ); |
| |
| global_settings.volume = mpeg_sound_default(SOUND_VOLUME); |
| global_settings.balance = mpeg_sound_default(SOUND_BALANCE); |
| global_settings.bass = mpeg_sound_default(SOUND_BASS); |
| global_settings.treble = mpeg_sound_default(SOUND_TREBLE); |
| global_settings.loudness = mpeg_sound_default(SOUND_LOUDNESS); |
| global_settings.bass_boost = mpeg_sound_default(SOUND_SUPERBASS); |
| global_settings.avc = mpeg_sound_default(SOUND_AVC); |
| global_settings.channel_config = mpeg_sound_default(SOUND_CHANNELS); |
| global_settings.rec_quality = 5; |
| global_settings.rec_source = 0; /* 0=mic */ |
| global_settings.rec_frequency = 0; /* 0=44.1kHz */ |
| global_settings.rec_channels = 0; /* 0=Stereo */ |
| global_settings.rec_mic_gain = 8; |
| global_settings.rec_left_gain = 2; /* 0dB */ |
| global_settings.rec_right_gain = 2; /* 0dB */ |
| global_settings.rec_editable = false; |
| global_settings.rec_prerecord_time = 0; |
| global_settings.rec_directory = 0; /* rec_base_directory */ |
| global_settings.resume = RESUME_ASK; |
| global_settings.contrast = lcd_default_contrast(); |
| global_settings.invert = DEFAULT_INVERT_SETTING; |
| global_settings.flip_display= false; |
| global_settings.poweroff = DEFAULT_POWEROFF_SETTING; |
| global_settings.backlight_timeout = DEFAULT_BACKLIGHT_TIMEOUT_SETTING; |
| global_settings.invert_cursor = DEFAULT_INVERT_CURSOR_SETTING; |
| global_settings.backlight_on_when_charging = |
| DEFAULT_BACKLIGHT_ON_WHEN_CHARGING_SETTING; |
| #ifdef HAVE_LIION |
| global_settings.battery_capacity = 2200; /* mAh */ |
| #else |
| global_settings.battery_capacity = 1500; /* mAh */ |
| #endif |
| global_settings.trickle_charge = true; |
| global_settings.dirfilter = SHOW_MUSIC; |
| global_settings.sort_case = false; |
| global_settings.statusbar = true; |
| global_settings.buttonbar = true; |
| global_settings.scrollbar = true; |
| global_settings.repeat_mode = REPEAT_ALL; |
| global_settings.playlist_shuffle = false; |
| global_settings.discharge = 0; |
| global_settings.timeformat = 0; |
| global_settings.volume_type = 0; |
| global_settings.battery_type = 0; |
| global_settings.scroll_speed = 8; |
| global_settings.bidir_limit = 50; |
| #ifdef HAVE_LCD_CHARCELLS |
| global_settings.jump_scroll = 0; |
| global_settings.jump_scroll_delay = 50; |
| #endif |
| global_settings.scroll_delay = 100; |
| global_settings.scroll_step = 6; |
| global_settings.ff_rewind_min_step = DEFAULT_FF_REWIND_MIN_STEP; |
| global_settings.ff_rewind_accel = DEFAULT_FF_REWIND_ACCEL_SETTING; |
| global_settings.resume_index = -1; |
| global_settings.resume_first_index = 0; |
| global_settings.resume_offset = -1; |
| global_settings.resume_seed = -1; |
| global_settings.disk_spindown = 5; |
| global_settings.disk_poweroff = false; |
| global_settings.buffer_margin = 0; |
| global_settings.browse_current = false; |
| global_settings.play_selected = true; |
| global_settings.peak_meter_release = 8; |
| global_settings.peak_meter_hold = 3; |
| global_settings.peak_meter_clip_hold = 16; |
| global_settings.peak_meter_dbfs = true; |
| global_settings.peak_meter_min = 60; |
| global_settings.peak_meter_max = 0; |
| global_settings.peak_meter_performance = false; |
| global_settings.wps_file[0] = 0; |
| global_settings.font_file[0] = 0; |
| global_settings.lang_file[0] = 0; |
| global_settings.runtime = 0; |
| global_settings.topruntime = 0; |
| global_settings.autocreatebookmark = BOOKMARK_NO; |
| global_settings.autoloadbookmark = BOOKMARK_NO; |
| global_settings.usemrb = BOOKMARK_NO; |
| global_settings.fade_on_stop = true; |
| global_settings.caption_backlight = false; |
| global_settings.car_adapter_mode = false; |
| global_settings.max_files_in_dir = 400; |
| global_settings.max_files_in_playlist = 10000; |
| global_settings.show_icons = true; |
| global_settings.recursive_dir_insert = RECURSE_OFF; |
| global_settings.line_in = false; |
| global_settings.playlist_viewer_icons = true; |
| global_settings.playlist_viewer_indices = true; |
| global_settings.playlist_viewer_track_display = 0; |
| /* talking menu on by default, to help the blind (if voice file present) */ |
| global_settings.talk_menu = 1; |
| global_settings.talk_dir = 0; |
| global_settings.talk_file = 0; |
| } |
| |
| bool set_bool(char* string, bool* variable ) |
| { |
| return set_bool_options(string, variable, |
| STR(LANG_SET_BOOL_YES), |
| STR(LANG_SET_BOOL_NO), |
| NULL); |
| } |
| |
| /* wrapper to convert from int param to bool param in set_option */ |
| static void (*boolfunction)(bool); |
| void bool_funcwrapper(int value) |
| { |
| if (value) |
| boolfunction(true); |
| else |
| boolfunction(false); |
| } |
| |
| bool set_bool_options(char* string, bool* variable, |
| char* yes_str, int yes_voice, |
| char* no_str, int no_voice, |
| void (*function)(bool)) |
| { |
| struct opt_items names[] = { {no_str, no_voice}, {yes_str, yes_voice} }; |
| bool result; |
| |
| boolfunction = function; |
| result = set_option(string, variable, BOOL, names, 2, |
| function ? bool_funcwrapper : NULL); |
| return result; |
| } |
| |
| bool set_int(char* string, |
| char* unit, |
| int voice_unit, |
| int* variable, |
| void (*function)(int), |
| int step, |
| int min, |
| int max ) |
| { |
| bool done = false; |
| int button; |
| int org_value=*variable; |
| int last_value = 0x7FFFFFFF; /* out of range init */ |
| |
| #ifdef HAVE_LCD_BITMAP |
| if(global_settings.statusbar) |
| lcd_setmargins(0, STATUSBAR_HEIGHT); |
| else |
| lcd_setmargins(0, 0); |
| #endif |
| |
| lcd_clear_display(); |
| lcd_puts_scroll(0, 0, string); |
| |
| while (!done) { |
| char str[32]; |
| snprintf(str,sizeof str,"%d %s ", *variable, unit); |
| lcd_puts(0, 1, str); |
| #ifdef HAVE_LCD_BITMAP |
| status_draw(true); |
| #endif |
| lcd_update(); |
| |
| if (global_settings.talk_menu && *variable != last_value) |
| { |
| if (voice_unit < UNIT_LAST) |
| { /* use the available unit definition */ |
| talk_value(*variable, voice_unit, false); |
| } |
| else |
| { /* say the number, followed by an arbitrary voice ID */ |
| talk_number(*variable, false); |
| talk_id(voice_unit, true); |
| } |
| last_value = *variable; |
| } |
| |
| button = button_get_w_tmo(HZ/2); |
| switch(button) { |
| #ifdef HAVE_RECORDER_KEYPAD |
| case BUTTON_UP: |
| case BUTTON_UP | BUTTON_REPEAT: |
| #else |
| case BUTTON_RIGHT: |
| case BUTTON_RIGHT | BUTTON_REPEAT: |
| #endif |
| *variable += step; |
| break; |
| |
| #ifdef HAVE_RECORDER_KEYPAD |
| case BUTTON_DOWN: |
| case BUTTON_DOWN | BUTTON_REPEAT: |
| #else |
| case BUTTON_LEFT: |
| case BUTTON_LEFT | BUTTON_REPEAT: |
| #endif |
| *variable -= step; |
| break; |
| |
| #ifdef HAVE_RECORDER_KEYPAD |
| case BUTTON_LEFT: |
| case BUTTON_PLAY: |
| #else |
| case BUTTON_PLAY: |
| #endif |
| done = true; |
| break; |
| |
| #ifdef HAVE_RECORDER_KEYPAD |
| case BUTTON_OFF: |
| #else |
| case BUTTON_STOP: |
| case BUTTON_MENU: |
| #endif |
| if (*variable != org_value) { |
| *variable=org_value; |
| lcd_stop_scroll(); |
| lcd_puts(0, 0, str(LANG_MENU_SETTING_CANCEL)); |
| lcd_update(); |
| sleep(HZ/2); |
| } |
| done = true; |
| break; |
| |
| case SYS_USB_CONNECTED: |
| usb_screen(); |
| return true; |
| |
| } |
| if(*variable > max ) |
| *variable = max; |
| |
| if(*variable < min ) |
| *variable = min; |
| |
| if ( function && button != BUTTON_NONE) |
| function(*variable); |
| } |
| lcd_stop_scroll(); |
| |
| return false; |
| } |
| |
| /* NOTE: the 'type' parameter specifies the actual type of the variable |
| that 'variable' points to. not the value within. Only variables with |
| type 'bool' should use parameter BOOL. |
| |
| The type separation is necessary since int and bool are fundamentally |
| different and bit-incompatible types and can not share the same access |
| code. */ |
| |
| bool set_option(char* string, void* variable, enum optiontype type, |
| struct opt_items* options, int numoptions, void (*function)(int)) |
| { |
| bool done = false; |
| int button; |
| int* intvar = (int*)variable; |
| bool* boolvar = (bool*)variable; |
| int oldval = 0; |
| int index, oldindex = -1; /* remember what we said */ |
| |
| if (type==INT) |
| oldval=*intvar; |
| else |
| oldval=*boolvar; |
| |
| #ifdef HAVE_LCD_BITMAP |
| if(global_settings.statusbar) |
| lcd_setmargins(0, STATUSBAR_HEIGHT); |
| else |
| lcd_setmargins(0, 0); |
| #endif |
| |
| lcd_clear_display(); |
| lcd_puts_scroll(0, 0, string); |
| |
| while ( !done ) { |
| index = type==INT ? *intvar : (int)*boolvar; |
| lcd_puts(0, 1, options[index].string); |
| if (global_settings.talk_menu && index != oldindex) |
| { |
| talk_id(options[index].voice_id, false); |
| oldindex = index; |
| } |
| #ifdef HAVE_LCD_BITMAP |
| status_draw(true); |
| #endif |
| lcd_update(); |
| |
| button = button_get_w_tmo(HZ/2); |
| switch (button) { |
| #ifdef HAVE_RECORDER_KEYPAD |
| case BUTTON_UP: |
| case BUTTON_UP | BUTTON_REPEAT: |
| #else |
| case BUTTON_RIGHT: |
| case BUTTON_RIGHT | BUTTON_REPEAT: |
| #endif |
| if (type == INT) { |
| if ( *intvar < (numoptions-1) ) |
| (*intvar)++; |
| else |
| (*intvar) -= (numoptions-1); |
| } |
| else |
| *boolvar = !*boolvar; |
| break; |
| |
| #ifdef HAVE_RECORDER_KEYPAD |
| case BUTTON_DOWN: |
| case BUTTON_DOWN | BUTTON_REPEAT: |
| #else |
| case BUTTON_LEFT: |
| case BUTTON_LEFT | BUTTON_REPEAT: |
| #endif |
| if (type == INT) { |
| if ( *intvar > 0 ) |
| (*intvar)--; |
| else |
| (*intvar) += (numoptions-1); |
| } |
| else |
| *boolvar = !*boolvar; |
| break; |
| |
| #ifdef HAVE_RECORDER_KEYPAD |
| case BUTTON_LEFT: |
| case BUTTON_PLAY: |
| #else |
| case BUTTON_PLAY: |
| #endif |
| done = true; |
| break; |
| |
| #ifdef HAVE_RECORDER_KEYPAD |
| case BUTTON_OFF: |
| #else |
| case BUTTON_STOP: |
| case BUTTON_MENU: |
| #endif |
| if (((type==INT) && (*intvar != oldval)) || |
| ((type==BOOL) && (*boolvar != (bool)oldval))) { |
| if (type==INT) |
| *intvar=oldval; |
| else |
| *boolvar=oldval; |
| lcd_stop_scroll(); |
| lcd_puts(0, 0, str(LANG_MENU_SETTING_CANCEL)); |
| lcd_update(); |
| sleep(HZ/2); |
| } |
| done = true; |
| break; |
| |
| case SYS_USB_CONNECTED: |
| usb_screen(); |
| return true; |
| } |
| |
| if ( function && button != BUTTON_NONE) { |
| if (type == INT) |
| function(*intvar); |
| else |
| function(*boolvar); |
| } |
| } |
| lcd_stop_scroll(); |
| return false; |
| } |
| |
| #ifdef HAVE_LCD_BITMAP |
| #define INDEX_X 0 |
| #define INDEX_Y 1 |
| #define INDEX_WIDTH 2 |
| bool set_time(char* string, int timedate[]) |
| { |
| bool done = false; |
| int button; |
| int min = 0, steps = 0; |
| int cursorpos = 0; |
| int lastcursorpos = !cursorpos; |
| unsigned char buffer[19]; |
| int realyear; |
| int julianday; |
| int i; |
| unsigned char reffub[5]; |
| unsigned int width, height; |
| unsigned int separator_width, weekday_width; |
| unsigned int line_height, prev_line_height; |
| int dayname[] = {LANG_WEEKDAY_SUNDAY, |
| LANG_WEEKDAY_MONDAY, |
| LANG_WEEKDAY_TUESDAY, |
| LANG_WEEKDAY_WEDNESDAY, |
| LANG_WEEKDAY_THURSDAY, |
| LANG_WEEKDAY_FRIDAY, |
| LANG_WEEKDAY_SATURDAY}; |
| int monthname[] = {LANG_MONTH_JANUARY, |
| LANG_MONTH_FEBRUARY, |
| LANG_MONTH_MARCH, |
| LANG_MONTH_APRIL, |
| LANG_MONTH_MAY, |
| LANG_MONTH_JUNE, |
| LANG_MONTH_JULY, |
| LANG_MONTH_AUGUST, |
| LANG_MONTH_SEPTEMBER, |
| LANG_MONTH_OCTOBER, |
| LANG_MONTH_NOVEMBER, |
| LANG_MONTH_DECEMBER}; |
| char cursor[][3] = {{ 0, 8, 12}, {18, 8, 12}, {36, 8, 12}, |
| {24, 16, 24}, {54, 16, 18}, {78, 16, 12}}; |
| char daysinmonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; |
| |
| int monthname_len = 0, dayname_len = 0; |
| |
| |
| #ifdef HAVE_LCD_BITMAP |
| if(global_settings.statusbar) |
| lcd_setmargins(0, STATUSBAR_HEIGHT); |
| else |
| lcd_setmargins(0, 0); |
| #endif |
| lcd_clear_display(); |
| lcd_puts_scroll(0, 0, string); |
| |
| while ( !done ) { |
| /* calculate the number of days in febuary */ |
| realyear = timedate[3] + 2000; |
| if((realyear % 4 == 0 && !(realyear % 100 == 0)) || realyear % 400 == 0) |
| daysinmonth[1] = 29; |
| else |
| daysinmonth[1] = 28; |
| |
| /* fix day if month or year changed */ |
| if (timedate[5] > daysinmonth[timedate[4] - 1]) |
| timedate[5] = daysinmonth[timedate[4] - 1]; |
| |
| /* calculate day of week */ |
| julianday = 0; |
| for(i = 0; i < timedate[4] - 1; i++) { |
| julianday += daysinmonth[i]; |
| } |
| julianday += timedate[5]; |
| timedate[6] = (realyear + julianday + (realyear - 1) / 4 - |
| (realyear - 1) / 100 + (realyear - 1) / 400 + 7 - 1) % 7; |
| |
| snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d ", |
| timedate[0], timedate[1], timedate[2]); |
| lcd_puts(0, 1, buffer); |
| |
| /* recalculate the positions and offsets */ |
| lcd_getstringsize(string, &width, &prev_line_height); |
| lcd_getstringsize(buffer, &width, &line_height); |
| lcd_getstringsize(":", &separator_width, &height); |
| |
| /* hour */ |
| strncpy(reffub, buffer, 2); |
| reffub[2] = '\0'; |
| lcd_getstringsize(reffub, &width, &height); |
| cursor[0][INDEX_X] = 0; |
| cursor[0][INDEX_Y] = prev_line_height; |
| cursor[0][INDEX_WIDTH] = width; |
| |
| /* minute */ |
| strncpy(reffub, buffer + 3, 2); |
| reffub[2] = '\0'; |
| lcd_getstringsize(reffub, &width, &height); |
| cursor[1][INDEX_X] = cursor[0][INDEX_WIDTH] + separator_width; |
| cursor[1][INDEX_Y] = prev_line_height; |
| cursor[1][INDEX_WIDTH] = width; |
| |
| /* second */ |
| strncpy(reffub, buffer + 6, 2); |
| reffub[2] = '\0'; |
| lcd_getstringsize(reffub, &width, &height); |
| cursor[2][INDEX_X] = cursor[0][INDEX_WIDTH] + separator_width + |
| cursor[1][INDEX_WIDTH] + separator_width; |
| cursor[2][INDEX_Y] = prev_line_height; |
| cursor[2][INDEX_WIDTH] = width; |
| |
| lcd_getstringsize(buffer, &width, &prev_line_height); |
| |
| snprintf(buffer, sizeof(buffer), "%s 20%02d %s %02d ", |
| str(dayname[timedate[6]]), timedate[3], |
| str(monthname[timedate[4] - 1]), timedate[5]); |
| lcd_puts(0, 2, buffer); |
| |
| /* recalculate the positions and offsets */ |
| lcd_getstringsize(buffer, &width, &line_height); |
| |
| /* store these 2 to prevent _repeated_ strlen calls */ |
| monthname_len = strlen(str(monthname[timedate[4] - 1])); |
| dayname_len = strlen(str(dayname[timedate[6]])); |
| |
| /* weekday */ |
| strncpy(reffub, buffer, dayname_len); |
| reffub[dayname_len] = '\0'; |
| lcd_getstringsize(reffub, &weekday_width, &height); |
| lcd_getstringsize(" ", &separator_width, &height); |
| |
| /* year */ |
| strncpy(reffub, buffer + dayname_len + 1, 4); |
| reffub[4] = '\0'; |
| lcd_getstringsize(reffub, &width, &height); |
| cursor[3][INDEX_X] = weekday_width + separator_width; |
| cursor[3][INDEX_Y] = cursor[0][INDEX_Y] + prev_line_height; |
| cursor[3][INDEX_WIDTH] = width; |
| |
| /* month */ |
| strncpy(reffub, buffer + dayname_len + 6, monthname_len); |
| reffub[monthname_len] = '\0'; |
| lcd_getstringsize(reffub, &width, &height); |
| cursor[4][INDEX_X] = weekday_width + separator_width + |
| cursor[3][INDEX_WIDTH] + separator_width; |
| cursor[4][INDEX_Y] = cursor[0][INDEX_Y] + prev_line_height; |
| cursor[4][INDEX_WIDTH] = width; |
| |
| /* day */ |
| strncpy(reffub, buffer + dayname_len + monthname_len + 7, 2); |
| reffub[2] = '\0'; |
| lcd_getstringsize(reffub, &width, &height); |
| cursor[5][INDEX_X] = weekday_width + separator_width + |
| cursor[3][INDEX_WIDTH] + separator_width + |
| cursor[4][INDEX_WIDTH] + separator_width; |
| cursor[5][INDEX_Y] = cursor[0][INDEX_Y] + prev_line_height; |
| cursor[5][INDEX_WIDTH] = width; |
| |
| lcd_invertrect(cursor[cursorpos][INDEX_X], |
| cursor[cursorpos][INDEX_Y] + lcd_getymargin(), |
| cursor[cursorpos][INDEX_WIDTH], |
| line_height); |
| |
| lcd_puts(0, 4, str(LANG_TIME_SET)); |
| lcd_puts(0, 5, str(LANG_TIME_REVERT)); |
| #ifdef HAVE_LCD_BITMAP |
| status_draw(true); |
| #endif |
| lcd_update(); |
| |
| /* calculate the minimum and maximum for the number under cursor */ |
| if(cursorpos!=lastcursorpos) { |
| lastcursorpos=cursorpos; |
| switch(cursorpos) { |
| case 0: /* hour */ |
| min = 0; |
| steps = 24; |
| break; |
| case 1: /* minute */ |
| case 2: /* second */ |
| min = 0; |
| steps = 60; |
| break; |
| case 3: /* year */ |
| min = 0; |
| steps = 100; |
| break; |
| case 4: /* month */ |
| min = 1; |
| steps = 12; |
| break; |
| case 5: /* day */ |
| min = 1; |
| steps = daysinmonth[timedate[4] - 1]; |
| break; |
| } |
| } |
| |
| button = button_get_w_tmo(HZ/2); |
| switch ( button ) { |
| case BUTTON_LEFT: |
| cursorpos = (cursorpos + 6 - 1) % 6; |
| break; |
| case BUTTON_RIGHT: |
| cursorpos = (cursorpos + 6 + 1) % 6; |
| break; |
| case BUTTON_UP: |
| case BUTTON_UP | BUTTON_REPEAT: |
| timedate[cursorpos] = (timedate[cursorpos] + steps - min + 1) % |
| steps + min; |
| if(timedate[cursorpos] == 0) |
| timedate[cursorpos] += min; |
| break; |
| case BUTTON_DOWN: |
| case BUTTON_DOWN | BUTTON_REPEAT: |
| timedate[cursorpos]=(timedate[cursorpos]+steps - min - 1) % |
| steps + min; |
| if(timedate[cursorpos] == 0) |
| timedate[cursorpos] += min; |
| break; |
| case BUTTON_ON: |
| done = true; |
| if (timedate[6] == 0) /* rtc needs 1 .. 7 */ |
| timedate[6] = 7; |
| break; |
| case BUTTON_OFF: |
| done = true; |
| timedate[0] = -1; |
| break; |
| #ifdef HAVE_RECORDER_KEYPAD |
| case BUTTON_F3: |
| #ifdef HAVE_LCD_BITMAP |
| global_settings.statusbar = !global_settings.statusbar; |
| settings_save(); |
| if(global_settings.statusbar) |
| lcd_setmargins(0, STATUSBAR_HEIGHT); |
| else |
| lcd_setmargins(0, 0); |
| lcd_clear_display(); |
| lcd_puts_scroll(0, 0, string); |
| #endif |
| break; |
| #endif |
| |
| case SYS_USB_CONNECTED: |
| usb_screen(); |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| #endif |
| |
| #ifdef HAVE_MAS3587F |
| /* This array holds the record timer interval lengths, in seconds */ |
| static unsigned long rec_timer_seconds[] = |
| { |
| 24*60*60, /* OFF really means 24 hours, to avoid >2Gbyte files */ |
| 5*60, /* 00:05 */ |
| 10*60, /* 00:10 */ |
| 15*60, /* 00:15 */ |
| 30*60, /* 00:30 */ |
| 60*60, /* 01:00 */ |
| 2*60*60, /* 02:00 */ |
| 4*60*60, /* 04:00 */ |
| 6*60*60, /* 06:00 */ |
| 8*60*60, /* 08:00 */ |
| 10*60*60, /* 10:00 */ |
| 12*60*60, /* 12:00 */ |
| 18*60*60, /* 18:00 */ |
| 24*60*60 /* 24:00 */ |
| }; |
| |
| unsigned int rec_timesplit_seconds(void) |
| { |
| return rec_timer_seconds[global_settings.rec_timesplit]; |
| } |
| #endif |