diff options
Diffstat (limited to 'apps/settings.c')
-rw-r--r-- | apps/settings.c | 794 |
1 files changed, 481 insertions, 313 deletions
diff --git a/apps/settings.c b/apps/settings.c index 99cede382b..b281646686 100644 --- a/apps/settings.c +++ b/apps/settings.c @@ -19,6 +19,12 @@ * KIND, either express or implied. * ****************************************************************************/ +/* Define LOGF_ENABLE to enable logf output in this file */ +/*#define LOGF_ENABLE*/ +/*Define DEBUG_AVAIL_SETTINGS to get a list of all available settings and flags */ +/*#define DEBUG_AVAIL_SETTINGS*/ /* Needs (LOGF_ENABLE) */ +#include "logf.h" + #include <stdio.h> #include <stddef.h> #include <stdlib.h> @@ -35,8 +41,7 @@ #include "backlight.h" #include "audio.h" #include "talk.h" -#include "strlcpy.h" -#include "strcasestr.h" +#include "string-extra.h" #include "rtc.h" #include "power.h" #include "ata_idle_notify.h" @@ -83,11 +88,7 @@ struct system_status global_status; #include "pcm_sampr.h" #define NVRAM_DATA_START 8 -#ifdef HAVE_RTC_RAM -#define NVRAM_BLOCK_SIZE 44 -#else #define NVRAM_BLOCK_SIZE (sizeof(struct system_status) + NVRAM_DATA_START) -#endif #define MAX_LINES 10 @@ -100,121 +101,137 @@ struct system_status global_status; #include "usb-ibasso.h" #endif +#ifdef ROCKBOX_NO_TEMP_SETTINGS_FILE /* Overwrites same file each time */ +#define CONFIGFILE_TEMP CONFIGFILE +#define NVRAM_FILE_TEMP NVRAM_FILE +#define rename_temp_file(a,b,c) +#else /* creates temp files on save, renames next load, saves old file if desired */ +#define CONFIGFILE_TEMP CONFIGFILE".new" +#define NVRAM_FILE_TEMP NVRAM_FILE".new" + +#ifdef LOGF_ENABLE +static char *debug_get_flags(uint32_t flags); +#endif +static void debug_available_settings(void); + +static void rename_temp_file(const char *tempfile, + const char *file, + const char *oldfile) +{ + /* if tempfile does not exist -- Return + * if oldfile is supplied -- Rename file to oldfile + * if tempfile does exist -- Rename tempfile to file + */ + if (file_exists(tempfile)) + { + if (oldfile != NULL && file_exists(file)) + rename(file, oldfile); + rename(tempfile, file); + } +} +#endif long lasttime = 0; /** NVRAM stuff, if the target doesnt have NVRAM it is saved in ROCKBOX_DIR /nvram.bin **/ /* NVRAM is set out as -[0] 'R' -[1] 'b' -[2] version -[3] stored variable count -[4-7] crc32 checksum -[8-NVRAM_BLOCK_SIZE] data -*/ -static char nvram_buffer[NVRAM_BLOCK_SIZE]; - -static bool read_nvram_data(char* buf, int max_len) + * + * [0] 'R' + * [1] 'b' + * [2] version + * [3] stored variable count + * [4-7] crc32 checksum in host endian order + * [8+] data + */ + +static unsigned int nvram_crc(char *buf, int max_len) { - unsigned crc32 = 0xffffffff; - int var_count = 0, i = 0, buf_pos = 0; -#ifndef HAVE_RTC_RAM + return crc_32(&buf[NVRAM_DATA_START], max_len - NVRAM_DATA_START - 1, 0xffffffff); +} + +static void read_nvram_data(void) +{ + rename_temp_file(NVRAM_FILE_TEMP, NVRAM_FILE, NVRAM_FILE".old"); + int fd = open(NVRAM_FILE, O_RDONLY); - int bytes; if (fd < 0) - return false; - memset(buf,0,max_len); - bytes = read(fd,buf,max_len); + return; + + char buf[NVRAM_BLOCK_SIZE]; + memset(buf, 0, sizeof(buf)); + + ssize_t bytes = read(fd, buf, sizeof(buf)); close(fd); + if (bytes < 8) /* min is 8 bytes,magic, ver, vars, crc32 */ - return false; -#else - memset(buf,0,max_len); - /* read rtc block */ - for (i=0; i < max_len; i++ ) - buf[i] = rtc_read(0x14+i); -#endif + return; + /* check magic, version */ - if ((buf[0] != 'R') || (buf[1] != 'b') - || (buf[2] != NVRAM_CONFIG_VERSION)) - return false; + if (buf[0] != 'R' || buf[1] != 'b' || buf[2] != NVRAM_CONFIG_VERSION) + return; + /* check crc32 */ - crc32 = crc_32(&buf[NVRAM_DATA_START], - max_len-NVRAM_DATA_START-1,0xffffffff); - if (memcmp(&crc32,&buf[4],4)) - return false; + unsigned int crc32 = nvram_crc(buf, sizeof(buf)); + if (crc32 != load_h32(&buf[4])) + return; + /* all good, so read in the settings */ - var_count = buf[3]; - buf_pos = NVRAM_DATA_START; - for(i=0; i<nb_settings; i++) + int var_count = buf[3]; + size_t buf_pos = NVRAM_DATA_START; + for(int i = 0; i < nb_settings; i++) { - int nvram_bytes = (settings[i].flags&F_NVRAM_BYTES_MASK) - >>F_NVRAM_MASK_SHIFT; + const struct settings_list *setting = &settings[i]; + int nvram_bytes = (setting->flags & F_NVRAM_BYTES_MASK) >> F_NVRAM_MASK_SHIFT; if (nvram_bytes) { - if ((var_count>0) && (buf_pos<max_len)) + if (var_count > 0 && buf_pos < (size_t)bytes) { - memcpy(settings[i].setting,&buf[buf_pos],nvram_bytes); + memcpy(setting->setting, &buf[buf_pos], nvram_bytes); buf_pos += nvram_bytes; var_count--; } else /* should only happen when new items are added to the end */ { - memcpy(settings[i].setting, &settings[i].default_val, nvram_bytes); + memcpy(setting->setting, &setting->default_val, nvram_bytes); } } } - return true; } -static bool write_nvram_data(char* buf, int max_len) + +static void write_nvram_data(void) { - unsigned crc32 = 0xffffffff; - int i = 0, buf_pos = 0; - char var_count = 0; -#ifndef HAVE_RTC_RAM - int fd; -#endif - memset(buf,0,max_len); + char buf[NVRAM_BLOCK_SIZE]; + memset(buf, 0, sizeof(buf)); + /* magic, version */ - buf[0] = 'R'; buf[1] = 'b'; + buf[0] = 'R'; + buf[1] = 'b'; buf[2] = NVRAM_CONFIG_VERSION; - buf_pos = NVRAM_DATA_START; - for(i=0; (i<nb_settings) && (buf_pos<max_len); i++) + + size_t buf_pos = NVRAM_DATA_START; + int var_count = 0; + for(int i = 0; i < nb_settings && buf_pos < sizeof(buf); i++) { - int nvram_bytes = (settings[i].flags&F_NVRAM_BYTES_MASK) - >>F_NVRAM_MASK_SHIFT; + const struct settings_list *setting = &settings[i]; + int nvram_bytes = (setting->flags & F_NVRAM_BYTES_MASK) >> F_NVRAM_MASK_SHIFT; if (nvram_bytes) { - memcpy(&buf[buf_pos],settings[i].setting,nvram_bytes); + memcpy(&buf[buf_pos], setting->setting, nvram_bytes); buf_pos += nvram_bytes; var_count++; } } + /* count and crc32 */ buf[3] = var_count; - crc32 = crc_32(&buf[NVRAM_DATA_START], - max_len-NVRAM_DATA_START-1,0xffffffff); - memcpy(&buf[4],&crc32,4); -#ifndef HAVE_RTC_RAM - fd = open(NVRAM_FILE,O_CREAT|O_TRUNC|O_WRONLY, 0666); - if (fd >= 0) - { - int len = write(fd,buf,max_len); - close(fd); - if (len < 8) - return false; - } -#else - /* 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 < NVRAM_BLOCK_SIZE; i++ ) { - int r = rtc_write(0x14+i, buf[i]); - if (r) - return false; - } -#endif - return true; + store_h32(&buf[4], nvram_crc(buf, sizeof(buf))); + + int fd = open(NVRAM_FILE_TEMP,O_CREAT|O_TRUNC|O_WRONLY, 0666); + if (fd < 0) + return; + + write(fd, buf, sizeof(buf)); + close(fd); } /** Reading from a config file **/ @@ -223,53 +240,107 @@ static bool write_nvram_data(char* buf, int max_len) */ void settings_load(int which) { - if (which&SETTINGS_RTC) - read_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE); - if (which&SETTINGS_HD) + logf("\r\n%s()\r\n", __func__); + debug_available_settings(); + + if (which & SETTINGS_RTC) + read_nvram_data(); + if (which & SETTINGS_HD) { + rename_temp_file(CONFIGFILE_TEMP, CONFIGFILE, CONFIGFILE".old"); settings_load_config(CONFIGFILE, false); settings_load_config(FIXEDSETTINGSFILE, false); } } -bool cfg_string_to_int(int setting_id, int* out, const char* str) +bool cfg_string_to_int(const struct settings_list *setting, int* out, const char* str) { - const char* start = settings[setting_id].cfg_vals; - char* end = NULL; - char temp[MAX_PATH]; - int count = 0; - while (1) + const char* ptr = setting->cfg_vals; + size_t len = strlen(str); + int index = 0; + + while (true) { - end = strchr(start, ','); - if (!end) + if (!strncmp(ptr, str, len)) { - if (!strcmp(str, start)) + ptr += len; + /* if the next character is not a comma or end of string, + * it means the comparison was only a partial match. */ + if (*ptr == ',' || *ptr == '\0') { - *out = count; + *out = index; return true; } - else return false; } - strlcpy(temp, start, end-start+1); - if (!strcmp(str, temp)) + + while (*ptr != ',') { - *out = count; - return true; + if (!*ptr) + return false; + ptr++; + } + + ptr++; + index++; + } +} + +/** + * Copy an input string to an output buffer, stripping the prefix and + * suffix listed in the filename setting. Returns false if the output + * string does not fit in the buffer or is longer than the setting's + * max_len, and the output buffer will not be modified. + * + * Returns true if the setting was copied successfully. The input and + * output buffers are allowed to alias. + */ +bool copy_filename_setting(char *buf, size_t buflen, const char *input, + const struct filename_setting *fs) +{ + size_t input_len = strlen(input); + size_t len; + + if (fs->prefix) + { + len = strlen(fs->prefix); + if (len <= input_len && !strncasecmp(input, fs->prefix, len)) + { + input += len; + input_len -= len; + } + } + + if (fs->suffix) + { + len = strlen(fs->suffix); + if (len <= input_len && + !strcasecmp(input + input_len - len, fs->suffix)) + { + input_len -= len; } - start = end +1; - count++; } - return false; + + /* Make sure it fits the output buffer and repsects the setting's max_len. + * Note that max_len is a buffer size and thus includes a null terminator */ + if (input_len >= (size_t)fs->max_len || input_len >= buflen) + return false; + + /* Copy what remains into buf - use memmove in case of aliasing */ + memmove(buf, input, input_len); + buf[input_len] = '\0'; + return true; } bool settings_load_config(const char* file, bool apply) { + logf("%s()\r\n", __func__); + const struct settings_list *setting; int fd; char line[128]; char* name; char* value; - int i; bool theme_changed = false; + fd = open_utf8(file, O_RDONLY); if (fd < 0) return false; @@ -278,88 +349,104 @@ bool settings_load_config(const char* file, bool apply) { if (!settings_parseline(line, &name, &value)) continue; - for(i=0; i<nb_settings; i++) + + setting = find_setting_by_cfgname(name); + if (!setting) + continue; + + if (setting->flags & F_THEMESETTING) + theme_changed = true; + + switch (setting->flags & F_T_MASK) { - if (settings[i].cfg_name == NULL) - continue; - if (!strcasecmp(name,settings[i].cfg_name)) - { - if (settings[i].flags&F_THEMESETTING) - theme_changed = true; - switch (settings[i].flags&F_T_MASK) - { - case F_T_CUSTOM: - settings[i].custom_setting->load_from_cfg(settings[i].setting, value); - break; - case F_T_INT: - case F_T_UINT: + case F_T_CUSTOM: + setting->custom_setting->load_from_cfg(setting->setting, value); + logf("Val: %s\r\n",value); + break; + case F_T_INT: + case F_T_UINT: #ifdef HAVE_LCD_COLOR - if (settings[i].flags&F_RGB) - hex_to_rgb(value, (int*)settings[i].setting); - else + if (setting->flags & F_RGB) + { + hex_to_rgb(value, (int*)setting->setting); + logf("Val: %s\r\n", value); + } + else #endif - if (settings[i].cfg_vals == NULL) - { - *(int*)settings[i].setting = atoi(value); - } + if (setting->cfg_vals == NULL) + { + *(int*)setting->setting = atoi(value); + logf("Val: %s\r\n",value); + } + else + { + int temp, *v = (int*)setting->setting; + bool found = cfg_string_to_int(setting, &temp, value); + if (found) + { + if (setting->flags & F_TABLE_SETTING) + *v = setting->table_setting->values[temp]; else - { - int temp, *v = (int*)settings[i].setting; - bool found = cfg_string_to_int(i, &temp, value); - if (found) - { - if (settings[i].flags&F_TABLE_SETTING) - *v = settings[i].table_setting->values[temp]; - else - *v = temp; - } - else - { /* atoi breaks choice settings because they - * don't have int-like values, and would - * fall back to the first value (i.e. 0) - * due to atoi */ - if (!(settings[i].flags&F_CHOICE_SETTING)) - *v = atoi(value); - } - } - break; - case F_T_BOOL: + *v = temp; + logf("Val: %d\r\n", *v); + } + else if (setting->flags & F_ALLOW_ARBITRARY_VALS) { - int temp; - if (cfg_string_to_int(i,&temp,value)) - *(bool*)settings[i].setting = (temp!=0); - if (settings[i].bool_setting->option_callback) - settings[i].bool_setting->option_callback(temp!=0); - break; + *v = atoi(value); + logf("Val: %s = %d\r\n", value, *v); } - case F_T_CHARPTR: - case F_T_UCHARPTR: + else if (setting->flags & F_TABLE_SETTING) { - char storage[MAX_PATH]; - if (settings[i].filename_setting->prefix) + const struct table_setting *info = setting->table_setting; + temp = atoi(value); + *v = setting->default_val.int_; + if (info->values) { - const char *dir = settings[i].filename_setting->prefix; - size_t len = strlen(dir); - if (!strncasecmp(value, dir, len)) + for(int i = 0; i < info->count; i++) { - strlcpy(storage, &value[len], MAX_PATH); + if (info->values[i] == temp) + { + *v = temp; + break; + } } - else strlcpy(storage, value, MAX_PATH); } - else strlcpy(storage, value, MAX_PATH); - if (settings[i].filename_setting->suffix) - { - char *s = strcasestr(storage,settings[i].filename_setting->suffix); - if (s) *s = '\0'; - } - strlcpy((char*)settings[i].setting, storage, - settings[i].filename_setting->max_len); - break; + logf("Val: %s", *v == temp ? "Found":"Error Not Found"); + logf("Val: %s = %d\r\n", value, *v); + } + + else + { + logf("Error: %s: Not Found! [%s]\r\n", + setting->cfg_name, value); } } - break; - } /* if (!strcmp(name,settings[i].cfg_name)) */ - } /* for(...) */ + break; + case F_T_BOOL: + { + int temp; + if (cfg_string_to_int(setting, &temp, value)) + { + *(bool*)setting->setting = !!temp; + logf("Val: %s\r\n", value); + } + if (setting->bool_setting->option_callback) + { + setting->bool_setting->option_callback(!!temp); + } + break; + } + /* these can be plain text, filenames, or dirnames */ + case F_T_CHARPTR: + case F_T_UCHARPTR: + { + const struct filename_setting *fs = setting->filename_setting; + copy_filename_setting((char*)setting->setting, + fs->max_len, value, fs); + logf("Val: %s\r\n", value); + break; + } + } } /* while(...) */ close(fd); @@ -375,74 +462,53 @@ bool settings_load_config(const char* file, bool apply) /** Writing to a config file and saving settings **/ -bool cfg_int_to_string(int setting_id, int val, char* buf, int buf_len) +bool cfg_int_to_string(const struct settings_list *setting, int val, char* buf, int buf_len) { - int flags = settings[setting_id].flags; - const char* start = settings[setting_id].cfg_vals; - char* end = NULL; - int count = 0; + const char* ptr = setting->cfg_vals; + const int *values = NULL; + int index = 0; - if ((flags&F_T_MASK)==F_T_INT && - flags&F_TABLE_SETTING) + if (setting->flags & F_TABLE_SETTING) + values = setting->table_setting->values; + + while (true) { - const int *value = settings[setting_id].table_setting->values; - while (start) + if ((values && values[index] == val) || + (!values && index == val)) { - end = strchr(start,','); - if (value[count] == val) - { - if (end == NULL) - strlcpy(buf, start, buf_len); - else - { - int len = MIN(buf_len, (end-start) + 1); - strlcpy(buf, start, len); - } - return true; - } - count++; + char *buf_end = buf + buf_len - 1; + while (*ptr && *ptr != ',' && buf != buf_end) + *buf++ = *ptr++; - if (end) - start = end+1; - else - break; + *buf++ = '\0'; + return true; } - return false; - } - while (count < val) - { - start = strchr(start,','); - if (!start) - return false; - count++; - start++; - } - end = strchr(start,','); - if (end == NULL) - strlcpy(buf, start, buf_len); - else - { - int len = MIN(buf_len, (end-start) + 1); - strlcpy(buf, start, len); + while (*ptr != ',') + { + if (!*ptr) + return false; + ptr++; + } + + ptr++; + index++; } - return true; } -bool cfg_to_string(int i/*setting_id*/, char* buf, int buf_len) +void cfg_to_string(const struct settings_list *setting, char* buf, int buf_len) { - switch (settings[i].flags&F_T_MASK) + switch (setting->flags & F_T_MASK) { case F_T_CUSTOM: - settings[i].custom_setting->write_to_cfg(settings[i].setting, - buf, buf_len); + setting->custom_setting->write_to_cfg(setting->setting, buf, buf_len); break; case F_T_INT: case F_T_UINT: #ifdef HAVE_LCD_COLOR - if (settings[i].flags&F_RGB) + if (setting->flags & F_RGB) { - int colour = *(int*)settings[i].setting; + int colour = *(int*)setting->setting; snprintf(buf,buf_len,"%02x%02x%02x", (int)RGB_UNPACK_RED(colour), (int)RGB_UNPACK_GREEN(colour), @@ -450,57 +516,50 @@ bool cfg_to_string(int i/*setting_id*/, char* buf, int buf_len) } else #endif - if (settings[i].cfg_vals == NULL) + if (setting->cfg_vals == NULL) { - snprintf(buf,buf_len,"%d",*(int*)settings[i].setting); + snprintf(buf, buf_len, "%d", *(int*)setting->setting); } else { - if (cfg_int_to_string(i, *(int*)settings[i].setting, - buf, buf_len) == false) - { - snprintf(buf,buf_len,"%d",*(int*)settings[i].setting); - } - else - return false; + if (!cfg_int_to_string(setting, *(int*)setting->setting, + buf, buf_len)) + snprintf(buf, buf_len, "%d", *(int*)setting->setting); } break; case F_T_BOOL: - cfg_int_to_string(i, - *(bool*)settings[i].setting==false?0:1, buf, buf_len); + cfg_int_to_string(setting, *(bool*)setting->setting, buf, buf_len); break; case F_T_CHARPTR: case F_T_UCHARPTR: - if (((char*)settings[i].setting)[0] - && settings[i].filename_setting->prefix) + { + char *value = setting->setting; + const struct filename_setting *fs = setting->filename_setting; + if (value[0] && fs->prefix) { - if (((char*)settings[i].setting)[0] == '-') + if (value[0] == '-') { buf[0] = '-'; buf[1] = '\0'; } else { - snprintf(buf,buf_len,"%s%s%s", - settings[i].filename_setting->prefix, - (char*)settings[i].setting, - settings[i].filename_setting->suffix); + snprintf(buf, buf_len, "%s%s%s", + fs->prefix, value, fs->suffix); } } else { - int len = MIN(buf_len, settings[i].filename_setting->max_len); - strlcpy(buf,(char*)settings[i].setting,len); + strmemccpy(buf, value, buf_len); } break; + } } /* switch () */ - return true; } -static bool is_changed(int setting_id) +static bool is_changed(const struct settings_list *setting) { - const struct settings_list *setting = &settings[setting_id]; switch (setting->flags&F_T_MASK) { case F_T_CUSTOM: @@ -538,6 +597,7 @@ static bool is_changed(int setting_id) static bool settings_write_config(const char* filename, int options) { + logf("%s\r\n", __func__); int i; int fd; char value[MAX_PATH]; @@ -548,57 +608,57 @@ static bool settings_write_config(const char* filename, int options) "http://www.rockbox.org\r\n\r\n", rbversion); for(i=0; i<nb_settings; i++) { - if (settings[i].cfg_name == NULL) - continue; - value[0] = '\0'; - if (settings[i].flags & F_DEPRECATED) + const struct settings_list *setting = &settings[i]; + if (!setting->cfg_name || (setting->flags & F_DEPRECATED)) continue; switch (options) { case SETTINGS_SAVE_CHANGED: - if (!is_changed(i)) + if (!is_changed(setting)) continue; break; case SETTINGS_SAVE_SOUND: - if ((settings[i].flags&F_SOUNDSETTING) == 0) + if (!(setting->flags & F_SOUNDSETTING)) continue; break; case SETTINGS_SAVE_THEME: - if ((settings[i].flags&F_THEMESETTING) == 0) + if (!(setting->flags & F_THEMESETTING)) continue; break; #ifdef HAVE_RECORDING case SETTINGS_SAVE_RECPRESETS: - if ((settings[i].flags&F_RECSETTING) == 0) + if (!(setting->flags & F_RECSETTING)) continue; break; #endif case SETTINGS_SAVE_EQPRESET: - if ((settings[i].flags&F_EQSETTING) == 0) + if (!(setting->flags & F_EQSETTING)) continue; break; } + cfg_to_string(setting, value, MAX_PATH); + logf("Written: '%s: %s'\r\n",setting->cfg_name, value); - cfg_to_string(i, value, MAX_PATH); - fdprintf(fd,"%s: %s\r\n",settings[i].cfg_name,value); + fdprintf(fd,"%s: %s\r\n",setting->cfg_name,value); } /* for(...) */ close(fd); return true; } -#ifndef HAVE_RTC_RAM + static void flush_global_status_callback(void) { - write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE); + write_nvram_data(); } -#endif + static void flush_config_block_callback(void) { - write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE); - settings_write_config(CONFIGFILE, SETTINGS_SAVE_CHANGED); + write_nvram_data(); + settings_write_config(CONFIGFILE_TEMP, SETTINGS_SAVE_CHANGED); } -void reset_runtime(void) { +void reset_runtime(void) +{ lasttime = current_tick; global_status.runtime = 0; } @@ -621,29 +681,24 @@ static void update_runtime(void) void status_save(void) { update_runtime(); -#ifdef HAVE_RTC_RAM - /* this will be done in the storage_callback if - target doesnt have rtc ram */ - write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE); -#else register_storage_idle_func(flush_global_status_callback); -#endif } int settings_save(void) { + logf("%s", __func__); update_runtime(); -#ifdef HAVE_RTC_RAM - /* this will be done in the storage_callback if - target doesnt have rtc ram */ - write_nvram_data(nvram_buffer,NVRAM_BLOCK_SIZE); -#endif register_storage_idle_func(flush_config_block_callback); return 0; } bool settings_save_config(int options) { + /* if we have outstanding temp files it would be a good idea to flush + them before the user starts saving things */ + rename_temp_file(NVRAM_FILE_TEMP, NVRAM_FILE, NULL); /* dont overwrite .old */ + rename_temp_file(CONFIGFILE_TEMP, CONFIGFILE, NULL); /* files from last boot */ + char filename[MAX_PATH]; const char *folder, *namebase; switch (options) @@ -773,6 +828,7 @@ void sound_settings_apply(void) void settings_apply(bool read_disk) { + logf("%s", __func__); int rc; CHART(">set_codepage"); set_codepage(global_settings.default_codepage); @@ -840,7 +896,7 @@ void settings_apply(bool read_disk) set_keypress_restarts_sleep_timer( global_settings.keypress_restarts_sleeptimer); -#if defined(BATTERY_CAPACITY_INC) && BATTERY_CAPACITY_INC > 0 +#if BATTERY_CAPACITY_INC > 0 /* only call if it's really exchangable */ set_battery_capacity(global_settings.battery_capacity); #endif @@ -873,11 +929,9 @@ void settings_apply(bool read_disk) if (global_settings.font_file[0] && global_settings.font_file[0] != '-') { int font_ui = screens[SCREEN_MAIN].getuifont(); - const char* loaded_font = font_filename(font_ui); - snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt", global_settings.font_file); - if (!loaded_font || strcmp(loaded_font, buf)) + if (!font_filename_matches_loaded_id(font_ui, buf)) { CHART2(">font_load ", global_settings.font_file); if (font_ui >= 0) @@ -892,10 +946,9 @@ void settings_apply(bool read_disk) if ( global_settings.remote_font_file[0] && global_settings.remote_font_file[0] != '-') { int font_ui = screens[SCREEN_REMOTE].getuifont(); - const char* loaded_font = font_filename(font_ui); snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt", global_settings.remote_font_file); - if (!loaded_font || strcmp(loaded_font, buf)) + if (!font_filename_matches_loaded_id(font_ui, buf)) { CHART2(">font_load_remoteui ", global_settings.remote_font_file); if (font_ui >= 0) @@ -945,11 +998,12 @@ void settings_apply(bool read_disk) #endif lcd_scroll_step(global_settings.scroll_step); - gui_list_screen_scroll_step(global_settings.screen_scroll_step); - gui_list_screen_scroll_out_of_view(global_settings.offset_out_of_view); lcd_bidir_scroll(global_settings.bidir_limit); lcd_scroll_delay(global_settings.scroll_delay); +#ifdef HAVE_ALBUMART + set_albumart_mode(global_settings.album_art); +#endif #ifdef HAVE_PLAY_FREQ /* before crossfade */ @@ -997,9 +1051,7 @@ void settings_apply(bool read_disk) #ifdef HAVE_REMOTE_LCD set_remote_backlight_filter_keypress(global_settings.remote_bl_filter_first_keypress); #endif -#ifdef HAS_BUTTON_HOLD backlight_set_on_button_hold(global_settings.backlight_on_button_hold); -#endif #ifdef HAVE_LCD_SLEEP_SETTING lcd_set_sleep_after_backlight_off(global_settings.lcd_sleep_after_backlight_off); @@ -1010,6 +1062,7 @@ void settings_apply(bool read_disk) set_selective_softlock_actions( global_settings.bt_selective_softlock_actions, global_settings.bt_selective_softlock_actions_mask); + action_autosoftlock_init(); #endif #ifdef HAVE_TOUCHPAD_SENSITIVITY_SETTING @@ -1074,8 +1127,8 @@ void reset_setting(const struct settings_list *setting, void *var) break; case F_T_CHARPTR: case F_T_UCHARPTR: - strlcpy((char*)var, setting->default_val.charptr, - setting->filename_setting->max_len); + strmemccpy((char*)var, setting->default_val.charptr, + setting->filename_setting->max_len); break; } } @@ -1099,32 +1152,32 @@ void settings_reset(void) } /** Changing setting values **/ -const struct settings_list* find_setting(const void* variable, int *id) +const struct settings_list* find_setting(const void* variable) { - int i; - for(i=0;i<nb_settings;i++) + for(int i = 0; i < nb_settings; i++) { - if (settings[i].setting == variable) - { - if (id) - *id = i; - return &settings[i]; - } + const struct settings_list *setting = &settings[i]; + if (setting->setting == variable) + return setting; } + return NULL; } -const struct settings_list* find_setting_by_cfgname(const char* name, int *id) + +const struct settings_list* find_setting_by_cfgname(const char* name) { - int i; - for (i=0; i<nb_settings; i++) + logf("Searching for Setting: '%s'",name); + for(int i = 0; i < nb_settings; i++) { - if (settings[i].cfg_name && - !strcmp(settings[i].cfg_name, name)) + const struct settings_list *setting = &settings[i]; + if (setting->cfg_name && !strcasecmp(setting->cfg_name, name)) { - if (id) *id = i; - return &settings[i]; + logf("Found, flags: %s", debug_get_flags(settings[i].flags)); + return setting; } } + logf("Setting: '%s' Not Found!",name); + return NULL; } @@ -1148,7 +1201,7 @@ bool set_bool_options(const char* string, const bool* variable, }; bool result; - result = set_option(string, variable, BOOL, names, 2, + result = set_option(string, variable, RB_BOOL, names, 2, (void (*)(int))(void (*)(void))function); return result; } @@ -1180,9 +1233,14 @@ bool set_int_ex(const unsigned char* string, { (void)unit; struct settings_list item; - struct int_setting data = { - function, voice_unit, min, max, step, - formatter, get_talk_id + const struct int_setting data = { + .option_callback = function, + .unit = voice_unit, + .step = step, + .min = min, + .max = max, + .formatter = formatter, + .get_talk_id = get_talk_id, }; item.int_setting = &data; item.flags = F_INT_SETTING|F_T_INT; @@ -1212,9 +1270,14 @@ bool set_option(const char* string, const void* variable, enum optiontype type, { int temp; struct settings_list item; - struct int_setting data = { - function, UNIT_INT, 0, numoptions-1, 1, - set_option_formatter, set_option_get_talk_id + const struct int_setting data = { + .option_callback = function, + .unit = UNIT_INT, + .step = 1, + .min = 0, + .max = numoptions-1, + .formatter = set_option_formatter, + .get_talk_id = set_option_get_talk_id }; memset(&item, 0, sizeof(struct settings_list)); set_option_options = options; @@ -1223,13 +1286,13 @@ bool set_option(const char* string, const void* variable, enum optiontype type, item.lang_id = -1; item.cfg_vals = (char*)string; item.setting = &temp; - if (type == BOOL) + if (type == RB_BOOL) temp = *(bool*)variable? 1: 0; else temp = *(int*)variable; if (!option_screen(&item, NULL, false, NULL)) { - if (type == BOOL) + if (type == RB_BOOL) *(bool*)variable = (temp == 1); else @@ -1268,6 +1331,111 @@ void set_file(const char* filename, char* setting, const int maxlen) if (len > maxlen) return; - strlcpy(setting, fptr, len); + strmemccpy(setting, fptr, len); settings_save(); } + +#ifdef LOGF_ENABLE +static char *debug_get_flags(uint32_t flags) +{ + static char buf[256] = {0}; + uint32_t ftype = flags & F_T_MASK; /* the variable type for the setting */ + flags &= ~F_T_MASK; + switch (ftype) + { + case F_T_CUSTOM: + strlcpy(buf, "[Type CUSTOM] ", sizeof(buf)); + break; + case F_T_INT: + strlcpy(buf, "[Type INT] ", sizeof(buf)); + break; + case F_T_UINT: + strlcpy(buf, "[Type UINT] ", sizeof(buf)); + break; + case F_T_BOOL: + strlcpy(buf, "[Type BOOL] ", sizeof(buf)); + break; + case F_T_CHARPTR: + strlcpy(buf, "[Type CHARPTR] ", sizeof(buf)); + break; + case F_T_UCHARPTR: + strlcpy(buf, "[Type UCHARPTR] ", sizeof(buf)); + break; + } + +#define SETTINGFLAGS(n) \ + if(flags & n) { \ + flags &= ~n; \ + strlcat(buf, "["#n"]", sizeof(buf));} + + SETTINGFLAGS(F_T_SOUND); + SETTINGFLAGS(F_BOOL_SETTING); + SETTINGFLAGS(F_RGB); + SETTINGFLAGS(F_FILENAME); + SETTINGFLAGS(F_INT_SETTING); + SETTINGFLAGS(F_CHOICE_SETTING); + SETTINGFLAGS(F_CHOICETALKS); + SETTINGFLAGS(F_TABLE_SETTING); + SETTINGFLAGS(F_ALLOW_ARBITRARY_VALS); + SETTINGFLAGS(F_CB_ON_SELECT_ONLY); + SETTINGFLAGS(F_CB_ONLY_IF_CHANGED); + SETTINGFLAGS(F_MIN_ISFUNC); + SETTINGFLAGS(F_MAX_ISFUNC); + SETTINGFLAGS(F_DEF_ISFUNC); + SETTINGFLAGS(F_CUSTOM_SETTING); + SETTINGFLAGS(F_TIME_SETTING); + SETTINGFLAGS(F_THEMESETTING); + SETTINGFLAGS(F_RECSETTING); + SETTINGFLAGS(F_EQSETTING); + SETTINGFLAGS(F_SOUNDSETTING); + SETTINGFLAGS(F_TEMPVAR); + SETTINGFLAGS(F_PADTITLE); + SETTINGFLAGS(F_NO_WRAP); + SETTINGFLAGS(F_BANFROMQS); + SETTINGFLAGS(F_DEPRECATED); +#undef SETTINGFLAGS + + if (flags & F_NVRAM_BYTES_MASK) + { + flags &= ~F_NVRAM_BYTES_MASK; + strlcat(buf, "[NVRAM]", sizeof(buf)); + } + /* anything left is unknown */ + if (flags) + { + strlcat(buf, "[UNKNOWN FLAGS]", sizeof(buf)); + size_t len = strlen(buf); + if (len < sizeof(buf)) + snprintf(buf + len, sizeof(buf) - len - 1, "[%x]", flags); + } + return buf; +} +#endif +static void debug_available_settings(void) +{ +#if defined(DEBUG_AVAIL_SETTINGS) && defined(LOGF_ENABLE) + logf("\r\nAvailable Settings:"); + for (int i=0; i<nb_settings; i++) + { + uint32_t flags = settings[i].flags; + const char *name; + if (settings[i].cfg_name) + name = settings[i].cfg_name; + else if (settings[i].RESERVED == NULL) + { + name = "SYS (NVRAM?)"; + if (flags & F_NVRAM_BYTES_MASK) + { + flags &= ~F_NVRAM_BYTES_MASK; + flags |= 0x80000; /* unused by other flags */ + } + } + else + { + name = "?? UNKNOWN NAME ?? "; + } + logf("'%s' flags: %s",name, debug_get_flags(flags)); + } + logf("End Available Settings\r\n"); +#endif +} |