? h300
? h300-sim
? settings_file.patch
? uisimulator
? apps/menus
? tools/codepages
? tools/mkboot
? tools/rdf2binary
Index: apps/FILES
===================================================================
RCS file: /cvsroot/rockbox/apps/FILES,v
retrieving revision 1.51
diff -u -r1.51 FILES
--- apps/FILES	3 Nov 2006 18:22:28 -0000	1.51
+++ apps/FILES	15 Nov 2006 08:00:10 -0000
@@ -5,6 +5,7 @@
 gui/*.[ch]
 recorder/*.[ch]
 player/*.[ch]
+menus/*.[ch]
 lang/*.lang
 eqs/*.cfg
 bitmaps/mono/*
Index: apps/SOURCES
===================================================================
RCS file: /cvsroot/rockbox/apps/SOURCES,v
retrieving revision 1.57
diff -u -r1.57 SOURCES
--- apps/SOURCES	13 Nov 2006 00:45:19 -0000	1.57
+++ apps/SOURCES	15 Nov 2006 08:00:10 -0000
@@ -9,19 +9,24 @@
 filetypes.c
 language.c
 main.c
-main_menu.c
 menu.c
+
+menus/main_menu.c
+menus/playlist_menu.c
+menus/sound_menu.c
+menus/recording_menu.c
+menus/playback_menu.c
+menus/display_menu.c
+
 misc.c
 onplay.c
 playlist.c
 playlist_catalog.c
-playlist_menu.c
 playlist_viewer.c
 plugin.c
 screens.c
 settings.c
-settings_menu.c
-sound_menu.c
+settings_list.c
 status.c
 #if !defined(SIMULATOR) || CONFIG_CODEC == SWCODEC
 talk.c
Index: apps/action.h
===================================================================
RCS file: /cvsroot/rockbox/apps/action.h,v
retrieving revision 1.15
diff -u -r1.15 action.h
--- apps/action.h	6 Nov 2006 09:19:36 -0000	1.15
+++ apps/action.h	15 Nov 2006 08:00:11 -0000
@@ -150,6 +150,8 @@
     ACTION_REC_F3,
     
     /* main menu */
+    ACTION_ENTERING_MENUITEM, /* sent to the menu callback as its about to be entered */
+    ACTION_BACKOUT_MENUITEM,  /* menu callback returns this when it is called to back out of the menu item */
     
     /* id3db */
     
Index: apps/database.c
===================================================================
RCS file: /cvsroot/rockbox/apps/database.c,v
retrieving revision 1.25
diff -u -r1.25 database.c
--- apps/database.c	5 Dec 2005 23:37:14 -0000	1.25
+++ apps/database.c	15 Nov 2006 08:00:11 -0000
@@ -31,7 +31,6 @@
 #include "debug.h"
 #include "button.h"
 #include "menu.h"
-#include "main_menu.h"
 #include "mpeg.h"
 #include "misc.h"
 #include "ata.h"
Index: apps/dbtree.c
===================================================================
RCS file: /cvsroot/rockbox/apps/dbtree.c,v
retrieving revision 1.29
diff -u -r1.29 dbtree.c
--- apps/dbtree.c	1 Apr 2006 13:36:33 -0000	1.29
+++ apps/dbtree.c	15 Nov 2006 08:00:12 -0000
@@ -31,7 +31,6 @@
 #include "debug.h"
 #include "button.h"
 #include "menu.h"
-#include "main_menu.h"
 #include "mpeg.h"
 #include "misc.h"
 #include "ata.h"
Index: apps/eq_menu.c
===================================================================
RCS file: /cvsroot/rockbox/apps/eq_menu.c,v
retrieving revision 1.28
diff -u -r1.28 eq_menu.c
--- apps/eq_menu.c	6 Nov 2006 18:07:21 -0000	1.28
+++ apps/eq_menu.c	15 Nov 2006 08:00:13 -0000
@@ -49,21 +49,7 @@
 #include "wm8758.h"
 #endif
 
-/* Various user interface limits and sizes */
-#define EQ_CUTOFF_MIN        20
-#define EQ_CUTOFF_MAX     22040
-#define EQ_CUTOFF_STEP       10
-#define EQ_CUTOFF_FAST_STEP 100
-#define EQ_GAIN_MIN       (-240)
-#define EQ_GAIN_MAX         240
-#define EQ_GAIN_STEP          5
-#define EQ_GAIN_FAST_STEP    10
-#define EQ_Q_MIN              5
-#define EQ_Q_MAX             64
-#define EQ_Q_STEP             1
-#define EQ_Q_FAST_STEP       10
 
-#define EQ_USER_DIVISOR      10
 
 /*
  * Utility functions
@@ -1158,7 +1144,7 @@
 #endif
 
 /* Full equalizer menu */
-bool eq_menu(void)
+int eq_menu(void)
 {
     int m;
     bool result;
@@ -1177,6 +1163,6 @@
     result = menu_run(m);
     menu_exit(m);
 
-    return result;
+    return (int)result;
 }
 
Index: apps/eq_menu.h
===================================================================
RCS file: /cvsroot/rockbox/apps/eq_menu.h,v
retrieving revision 1.3
diff -u -r1.3 eq_menu.h
--- apps/eq_menu.h	5 Sep 2006 11:48:17 -0000	1.3
+++ apps/eq_menu.h	15 Nov 2006 08:00:13 -0000
@@ -24,10 +24,26 @@
 
 bool eq_browse_presets(void);
 bool eq_menu_graphical(void);
-bool eq_menu(void);
+int eq_menu(void);
 #ifdef HAVE_WM8758
 bool eq_hw_menu(void);
 void eq_hw_enable(bool enable);
 #endif
 
+/* Various user interface limits and sizes */
+#define EQ_CUTOFF_MIN        20
+#define EQ_CUTOFF_MAX     22040
+#define EQ_CUTOFF_STEP       10
+#define EQ_CUTOFF_FAST_STEP 100
+#define EQ_GAIN_MIN       (-240)
+#define EQ_GAIN_MAX         240
+#define EQ_GAIN_STEP          5
+#define EQ_GAIN_FAST_STEP    10
+#define EQ_Q_MIN              5
+#define EQ_Q_MAX             64
+#define EQ_Q_STEP             1
+#define EQ_Q_FAST_STEP       10
+
+#define EQ_USER_DIVISOR      10
+
 #endif
Index: apps/main.c
===================================================================
RCS file: /cvsroot/rockbox/apps/main.c,v
retrieving revision 1.195
diff -u -r1.195 main.c
--- apps/main.c	7 Nov 2006 19:03:29 -0000	1.195
+++ apps/main.c	15 Nov 2006 08:00:13 -0000
@@ -7,7 +7,7 @@
  *                     \/            \/     \/    \/            \/
  * $Id: main.c,v 1.195 2006-11-07 19:03:29 learman Exp $
  *
- * Copyright (C) 2002 by Björn Stenberg
+ * Copyright (C) 2002 by Bjï¿½n Stenberg
  *
  * 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.
@@ -232,10 +232,9 @@
     screen_access_init();
     gui_syncstatusbar_init(&statusbars);
     settings_reset();
-    settings_calc_config_sector();
     settings_load(SETTINGS_ALL);
     gui_sync_wps_init();
-    settings_apply();
+    settings_apply(true);
     init_dircache(true);
     init_dircache(false);
 #ifdef HAVE_TAGCACHE
@@ -428,7 +427,6 @@
         }
     }
 
-    settings_calc_config_sector();
     
 #if defined(SETTINGS_RESET) || (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IRIVER_H10_PAD)
 #ifdef SETTINGS_RESET
@@ -454,7 +452,7 @@
     }
     
     gui_sync_wps_init();
-    settings_apply();
+    settings_apply(false);
     init_dircache(false);
 #ifdef HAVE_TAGCACHE
     init_tagcache();
Index: apps/menu.c
===================================================================
RCS file: /cvsroot/rockbox/apps/menu.c,v
retrieving revision 1.106
diff -u -r1.106 menu.c
--- apps/menu.c	6 Nov 2006 10:11:50 -0000	1.106
+++ apps/menu.c	15 Nov 2006 08:00:14 -0000
@@ -35,12 +35,15 @@
 #include "usb.h"
 #include "panic.h"
 #include "settings.h"
+#include "settings_list.h"
 #include "status.h"
 #include "screens.h"
 #include "talk.h"
 #include "lang.h"
 #include "misc.h"
 #include "action.h"
+#include "string.h"
+#include "atoi.h"
 
 #ifdef HAVE_LCD_BITMAP
 #include "icons.h"
@@ -356,3 +359,334 @@
 #endif
     }
 }
+/******************************************************************/
+/*              New menu stuff here!!
+ ******************************************************************/
+
+/* doing this stops compile warnings... */
+#undef P2STR
+#undef P2ID
+#define P2ID(p) (((char *)p>=(char *)VIRT_PTR && \
+    (char *)p<=(char *)(VIRT_PTR+VIRT_SIZE)) ? (char *)p-(char *)VIRT_PTR : -1)
+inline char* P2STR(char* p) {
+    if (p>=(char*)VIRT_PTR && (char*)p<=(char*)(VIRT_PTR+VIRT_SIZE))
+        return str((char*)p-(char*)VIRT_PTR);
+    else return p;
+}
+
+const struct settings_list* find_setting(void* variable)
+{
+    int i;
+    for(i=0;i<nb_settings;i++)
+    {
+        if (settings[i].setting == variable)
+            return &settings[i];
+    }
+    return NULL;
+}
+#define MAX_MENU_SUBITEMS 64
+int current_subitems[MAX_MENU_SUBITEMS];
+int current_subitems_count = 0;
+
+int get_menu_selection(int selected_item, const struct menu_item_ex *menu)
+{
+    if (menu->type == MT_MENU && (selected_item<current_subitems_count))
+        return current_subitems[selected_item];
+    return selected_item;
+}
+
+char * get_menu_item_name(int selected_item,void * data, char *buffer)
+{
+    const struct menu_item_ex *menu = (const struct menu_item_ex *)data;
+    selected_item = get_menu_selection(selected_item, menu);
+    
+    (void)buffer;
+    /* only MT_MENU or MT_RETURN_ID is allowed in here */
+    if (menu->type == MT_RETURN_ID)
+    {
+        return (char*)menu->strings[selected_item];
+    }
+    
+    menu = menu->submenus[selected_item];
+    if (menu->type == MT_SETTING)
+    {
+        const struct settings_list *v
+                = find_setting(menu->global_settings_variable);
+        if (v)
+            return str(v->cfg_lang_id);
+        else return "Not Done yet!";
+    }
+    return P2STR(menu->desc);
+}
+
+void init_menu_lists(const struct menu_item_ex *menu,
+                     struct gui_synclist *lists, int selected)
+{
+    int i;
+    current_subitems_count = 0;
+    for (i=0; i<menu->item_count; i++)
+    {
+        if (menu->submenus[i]->menu_callback)
+        {
+            if (menu->submenus[i]->menu_callback(
+                            ACTION_ENTERING_MENUITEM,menu->submenus[i])
+                != ACTION_BACKOUT_MENUITEM)
+            {
+                current_subitems[current_subitems_count] = i;
+                current_subitems_count++;
+            }
+        }
+        else 
+        {
+            current_subitems[current_subitems_count] = i;
+            current_subitems_count++;
+        }
+    }
+    
+    gui_synclist_init(lists,get_menu_item_name,(void*)menu,false,1);
+    gui_synclist_set_title(lists, P2STR(menu->desc), NOICON);
+    gui_synclist_set_icon_callback(lists,NULL);
+    gui_synclist_set_nb_items(lists,current_subitems_count);
+    gui_synclist_limit_scroll(lists,true);
+    gui_synclist_select_item(lists, selected);
+}
+
+void talk_menu_item(const struct menu_item_ex *menu,
+                    struct gui_synclist *lists)
+{
+    int id = -1;
+    if (global_settings.talk_menu)
+    {
+        int sel = get_menu_selection(gui_synclist_get_sel_pos(lists),menu);
+        if (menu->type == MT_MENU)
+        {
+           if (menu->submenus[sel]->type == MT_SETTING)
+               talk_setting(menu->submenus[sel]->global_settings_variable);
+           else 
+           {
+               id = P2ID(menu->submenus[sel]->desc);
+               if (id != -1)
+                   talk_id(id,false);
+           }
+        }
+    }
+}
+
+int do_menu(const struct menu_item_ex *menu)
+{
+    int action;
+    bool done = false;
+    int selected = 0;
+    struct gui_synclist lists;
+    const struct menu_item_ex *temp;
+    
+    const struct menu_item_ex *menu_stack[MAX_MENUS];
+    int menu_stack_selected_item[MAX_MENUS];
+    int stack_top = 0;
+    bool in_stringlist;
+    if (menu == NULL)
+        menu = &main_menu_;
+
+/*    if (menu->menu_callback)
+    {
+        action = menu->menu_callback(ACTION_ENTERING_MENUITEM,menu);
+        if (action == ACTION_BACKOUT_MENUITEM)
+            return 0;
+    }
+*/    init_menu_lists(menu,&lists,selected);
+    in_stringlist = (menu->type == MT_RETURN_ID);
+    
+    talk_menu_item(menu, &lists);
+    
+    gui_synclist_draw(&lists);
+    gui_syncstatusbar_draw(&statusbars, true);
+    action_signalscreenchange();
+    
+    while (!done)
+    {
+        
+        action = get_action(CONTEXT_MAINMENU,TIMEOUT_BLOCK); 
+        if (action == ACTION_NONE)
+            continue;
+        
+        if (menu->menu_callback)
+        {
+            action = menu->menu_callback(action,menu);
+        }
+        
+        if (gui_synclist_do_button(&lists,action,LIST_WRAP_UNLESS_HELD))
+        {
+            talk_menu_item(menu, &lists);
+        }  
+        else if (action == ACTION_STD_CANCEL)
+        {
+            if (in_stringlist)
+                in_stringlist = false;
+            if (stack_top > 0)
+            {
+                stack_top--;
+                menu = menu_stack[stack_top];
+                init_menu_lists(menu,&lists,menu_stack_selected_item[stack_top]);
+                talk_menu_item(menu, &lists);
+            }
+            else 
+            {
+                done = true;
+                break;
+            }
+        }
+        else if (action == ACTION_STD_OK)
+        {
+            int type;
+            selected = get_menu_selection(gui_synclist_get_sel_pos(&lists),menu);
+            temp = menu->submenus[selected];
+            if (in_stringlist)
+                type = menu->type;
+            else type = temp->type;
+  /*          if (temp->menu_callback)
+            {
+                action = temp->menu_callback(action,menu);
+                if (action == ACTION_BACKOUT_MENUITEM)
+                    break;
+            }
+     */       switch (type)
+            {
+                case MT_MENU:
+                    if (stack_top < MAX_MENUS)
+                    {
+                        bool enter = true;
+            /*            if (temp->menu_callback)
+                        {
+                            action = 
+                                    temp->menu_callback(ACTION_ENTERING_MENUITEM,
+                                        menu);
+                            if (action == ACTION_BACKOUT_MENUITEM)
+                                enter = false;
+                        }
+                   */     if (enter)
+                        {
+                            menu_stack[stack_top] = menu;
+                            menu_stack_selected_item[stack_top]
+                                    = gui_synclist_get_sel_pos(&lists);
+                            stack_top++;
+                            init_menu_lists(temp,&lists,0);
+                            menu = temp;
+                            talk_menu_item(menu, &lists);
+                        }
+                    }
+                    break;
+                case MT_FUNCTION_CALL:
+                    action_signalscreenchange();
+                    temp->function();
+                    break;
+                case MT_SETTING:
+                {
+                    load_setting_screen(
+                            (struct settings_list *)find_setting(
+                                temp->global_settings_variable));
+                    settings_apply(true); /* always do a partial apply after returning from a setting screen */
+                    break;
+                }
+                case MT_RETURN_ID:
+                    if (in_stringlist)
+                    {
+                        action_signalscreenchange();
+                        return selected;
+                    }
+                    else if (stack_top < MAX_MENUS)
+                    {
+                        menu_stack[stack_top] = menu;
+                        menu_stack_selected_item[stack_top] = selected;
+                        stack_top++;
+                        menu = temp;
+                        init_menu_lists(menu,&lists,0);
+                        in_stringlist = true;
+                    }
+                    break;
+            }
+        }
+        else if(default_event_handler(action) == SYS_USB_CONNECTED)
+            return MENU_ATTACHED_USB;
+        gui_syncstatusbar_draw(&statusbars, true);
+        gui_synclist_draw(&lists);
+    }
+    action_signalscreenchange();
+    return 0;
+}
+#include "debug_menu.h"
+bool main_menu(void)
+{
+    bool ret = do_menu(NULL);
+//    bool ret = debug_menu();
+    return ret;
+}
+#if 0
+/* user menus, this doesnt work properly, so comment out untill after commit */
+#define MAX_USER_MENUS 32
+int user_menu_count;
+struct menu_item_ex user_menus;
+const struct menu_item_ex *user_menus_items[MAX_USER_MENUS];
+/* user menu stuff */
+int user_menu_callback(int action, const struct menu_item_ex *this_item)
+{
+    (void)this_item;
+    if ((action == ACTION_ENTERING_MENUITEM) &&
+         (user_menu_count == 0)
+       )
+        return ACTION_BACKOUT_MENUITEM;
+    return action;
+}
+int split_line(char* buffer, int* out_array, int out_len)
+{
+    char *s = buffer, *e;
+    int i=0;
+    while (i<out_len)
+    {
+        e = strchr(s,',');
+        if (e) *e = '\0';
+        out_array[i++] = atoi(s);
+        s = e;
+        if (s == NULL)
+            break;
+        s++;
+    }
+    return i;
+}
+
+void user_menu_init(void)
+{
+    int fd;
+    int i =0,j, count;
+    char buffer[MAX_PATH];
+    int menu_order[MAX_USER_MENUS];
+    const struct menu_item_ex *temp;
+    user_menu_count = 0;
+    user_menus.type = MT_MENU;
+    user_menus.item_count = 0;
+    user_menus.menu_callback = user_menu_callback;
+    user_menus.desc = ID2P(LANG_USER_MENU);
+    user_menus.submenus = user_menus_items;
+    
+    fd = open(ROCKBOX_DIR "/user_menu.config",O_RDONLY);
+    if (fd < 0)
+        return;
+    while (read_line(fd,buffer,MAX_PATH))
+    {
+        if (buffer[0] == '#') /* comment */
+            continue;
+        count = split_line(buffer,menu_order,MAX_USER_MENUS);
+        temp = &main_menu_;
+        for (j=0;j<count;j++)
+        {
+            if ((menu_order[j] >= 0) &&
+                 (menu_order[j] < temp->item_count))
+                temp = temp->submenus[menu_order[j]];
+            else break;
+        }
+        user_menus_items[i++] = temp;
+        user_menu_count++;
+    }
+    close(fd);
+    user_menus.item_count = user_menu_count;
+}
+#endif
Index: apps/menu.h
===================================================================
RCS file: /cvsroot/rockbox/apps/menu.h,v
retrieving revision 1.45
diff -u -r1.45 menu.h
--- apps/menu.h	10 Nov 2006 20:25:59 -0000	1.45
+++ apps/menu.h	15 Nov 2006 08:00:14 -0000
@@ -21,6 +21,9 @@
 #define __MENU_H__
 
 #include <stdbool.h>
+#include "config.h"
+#include "sound.h"
+#include "menus/exported_menus.h"
 
 /* button definitions */
 #if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \
@@ -126,6 +129,7 @@
 #define MENU_ATTACHED_USB -1
 #define MENU_SELECTED_EXIT -2
 
+
 bool menu_run(int menu);
 int menu_cursor(int menu);
 char* menu_description(int menu, int position);
@@ -138,4 +142,48 @@
 void menu_set_cursor(int menu, int position);
 void menu_talk_selected(int m);
 
+#define MENU_EXIT_ALL -3
+enum menu_item_type {
+    MT_MENU = 0,
+    MT_SETTING,
+    MT_FUNCTION_CALL, /* used when the standard code wont work */
+    MT_RETURN_ID, /* returns the position of the selected item on selection (starting at 0)*/
+};
+typedef int (*menu_function)(void);
+struct menu_item_ex {
+    enum menu_item_type type;
+    union {
+        const struct menu_item_ex **submenus; /* used with MT_MENU */
+        void *global_settings_variable; /* used with MT_SETTING */
+        int (*function)(void); /* used with MT_FUNCTION_CALL */
+        const char **strings; /* used with MT_RETURN_ID */
+    };
+    int item_count; /* # of submenu, options, or strings */
+    int (*menu_callback)(int action, const struct menu_item_ex *this_item);
+    
+    char *desc;
+};
+typedef int (*menu_callback_type)(int action, const struct menu_item_ex *this_item);
+int do_menu(const struct menu_item_ex *menu);
+
+#define MAKE_SETTING_OPT(var,callback) const struct menu_item_ex var = \
+{MT_SETTING, {.global_settings_variable = (void*)&global_settings.var},1,callback,0};
+
+#define MAKE_MENU( name, str, cb, ... )                                 \
+    const struct menu_item_ex *name##_[]  = {__VA_ARGS__};     \
+    const struct menu_item_ex name =                           \
+        {MT_MENU, { (void*)name##_}, sizeof( name##_)/sizeof(*name##_),cb,str};
+        
+#define MAKE_STRINGLIST(name, str, callback, ... )                            \
+    const char *name##_[] = {__VA_ARGS__};                     \
+    const struct menu_item_ex name =                           \
+{MT_RETURN_ID, { .submenus = name##_}, sizeof( name##_)/sizeof(*name##_),callback, str};
+
+#define MAKE_FUNCTION_CALL(name, str, func, callback)               \
+    const struct menu_item_ex name   =                         \
+{ MT_FUNCTION_CALL, { .function = func},0,callback,str};
+        
+void user_menu_init(void);
+extern struct menu_item_ex user_menus;
 #endif /* End __MENU_H__ */
+
Index: apps/misc.c
===================================================================
RCS file: /cvsroot/rockbox/apps/misc.c,v
retrieving revision 1.74
diff -u -r1.74 misc.c
--- apps/misc.c	11 Nov 2006 01:18:57 -0000	1.74
+++ apps/misc.c	15 Nov 2006 08:00:16 -0000
@@ -713,7 +713,7 @@
     }
 }
 #endif
-
+void write_settings_to_disk(void); /* from settings.c */
 long default_event_handler_ex(long event, void (*callback)(void *), void *parameter)
 {
     switch(event)
@@ -753,6 +753,9 @@
             unplug_change(false);
             return SYS_PHONE_UNPLUGGED;
 #endif
+        case SYS_DUMPSETTINGS:
+            write_settings_to_disk();
+            return SYS_DUMPSETTINGS;
     }
     return 0;
 }
Index: apps/onplay.c
===================================================================
RCS file: /cvsroot/rockbox/apps/onplay.c,v
retrieving revision 1.91
diff -u -r1.91 onplay.c
--- apps/onplay.c	13 Nov 2006 00:45:19 -0000	1.91
+++ apps/onplay.c	15 Nov 2006 08:00:16 -0000
@@ -56,13 +56,11 @@
 #ifdef HAVE_LCD_BITMAP
 #include "icons.h"
 #endif
-#include "main_menu.h"
-#include "sound_menu.h"
+#include "menu.h"
 #include "database.h"
 #if CONFIG_CODEC == SWCODEC
 #include "eq_menu.h"
 #endif
-#include "playlist_menu.h"
 #include "playlist_catalog.h"
 #ifdef HAVE_TAGCACHE
 #include "tagtree.h"
Index: apps/playback.c
===================================================================
RCS file: /cvsroot/rockbox/apps/playback.c,v
retrieving revision 1.392
diff -u -r1.392 playback.c
--- apps/playback.c	13 Nov 2006 09:07:18 -0000	1.392
+++ apps/playback.c	15 Nov 2006 08:00:20 -0000
@@ -48,7 +48,6 @@
 #include "mp3_playback.h"
 #include "usb.h"
 #include "status.h"
-#include "main_menu.h"
 #include "ata.h"
 #include "screens.h"
 #include "playlist.h"
Index: apps/playback.h
===================================================================
RCS file: /cvsroot/rockbox/apps/playback.h,v
retrieving revision 1.39
diff -u -r1.39 playback.h
--- apps/playback.h	25 Oct 2006 08:54:25 -0000	1.39
+++ apps/playback.h	15 Nov 2006 08:00:20 -0000
@@ -76,6 +76,7 @@
 #endif
 void audio_preinit(void);
 
+void mpeg_id3_options(bool _v1first);
 #endif
 
 
Index: apps/playlist_viewer.c
===================================================================
RCS file: /cvsroot/rockbox/apps/playlist_viewer.c,v
retrieving revision 1.54
diff -u -r1.54 playlist_viewer.c
--- apps/playlist_viewer.c	6 Nov 2006 10:11:50 -0000	1.54
+++ apps/playlist_viewer.c	15 Nov 2006 08:00:21 -0000
@@ -47,7 +47,6 @@
 #include "list.h"
 #include "statusbar.h"
 #include "splash.h"
-#include "playlist_menu.h"
 #include "action.h"
 
 /* Maximum number of tracks we can have loaded at one time */
Index: apps/settings.c
===================================================================
RCS file: /cvsroot/rockbox/apps/settings.c,v
retrieving revision 1.437
diff -u -r1.437 settings.c
--- apps/settings.c	13 Nov 2006 00:45:20 -0000	1.437
+++ apps/settings.c	15 Nov 2006 08:00:24 -0000
@@ -26,6 +26,7 @@
 #include "thread.h"
 #include "action.h"
 #include "settings.h"
+#include "settings_list.h"
 #include "disk.h"
 #include "panic.h"
 #include "debug.h"
@@ -115,629 +116,24 @@
 #endif
 
 long lasttime = 0;
-static long config_sector = 0;  /* mark uninitialized */
-static unsigned char config_block[CONFIG_BLOCK_SIZE];
 
-
-/* descriptor for a configuration value */
-/* (watch the struct packing and member sizes to keep this small) */
-struct bit_entry
-{
-    /* how many bits within the bitfield (1-32), MSB set if value is signed */
-    unsigned char bit_size; /* min 6+1 bit */
-    /* how many bytes in the global_settings struct (1,2,4) */
-    unsigned char byte_size; /* min 3 bits */
-    /* store position in global_settings struct */
-    short settings_offset; /* min 9 bit, better 10 */
-    /* default value */
-    int default_val; /* min 15 bit */
-    /* variable name in a .cfg file, NULL if not to be saved */
-    const char* cfg_name;
-    /* set of values, "rgb" for a color, or NULL for a numerical value */
-    const char* cfg_val;
-};
-
-/********************************************
-
-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    start of bit-table
-...
-0x28,0x29 unused, not reachable by set_bits() without disturbing the next 2
-0x2A,0x2B <checksum 2 bytes: xor of 0x00-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.
-Memory locations not used by a given version should not be
-modified unless the header & checksum test fails.
-
-Rest of config block, only saved to disk:
-0x2C  start of 2nd bit-table
-...
-0xA4  (char[20]) FMR Preset file
-0xB8  (char[20]) WPS file
-0xCC  (char[20]) Lang file
-0xE0  (char[20]) Font file
-...   (char[20]) RWPS file (on targets supporting a Remote WPS)
-...   (char[20]) Main backdrop file (on color LCD targets)
-
-... to 0x200  <unused>
-
-*************************************/
-
-/* The persistence of the global_settings members is now controlled by
-   the two tables below, rtc_bits and hd_bits.
-   New values can just be added to the end, it will be backwards
-   compatible. If you however change order, bitsize, etc. of existing
-   entries, you need to bump CONFIG_BLOCK_VERSION to break compatibility.
-*/
-
-
-/* convenience macro for both size and offset of global_settings member */
-#define S_O(val) sizeof(global_settings.val), offsetof(struct user_settings, val)
-#define SIGNED 0x80 /* for bitsize value with signed attribute */
-
-/* some sets of values which are used more than once, to save memory */
-static const char off_on[] = "off,on";
-static const char off_on_ask[] = "off,on,ask";
-static const char off_number_spell_hover[] = "off,number,spell,hover";
-#ifdef HAVE_LCD_BITMAP
-static const char graphic_numeric[] = "graphic,numeric";
-#endif
-
-#ifdef HAVE_RECORDING
-/* keep synchronous to trig_durations and
-   trigger_times in settings_apply_trigger */
-static const char trig_durations_conf [] =
-                  "0s,1s,2s,5s,10s,15s,20s,25s,30s,1min,2min,5min,10min";
-#endif
-
-#if defined(CONFIG_BACKLIGHT)
-static const char backlight_times_conf [] =
-                  "off,on,1,2,3,4,5,6,7,8,9,10,15,20,25,30,45,60,90";
-#endif
-
-/* the part of the settings which ends up in the RTC RAM, where available
-   (those we either need early, save frequently, or without spinup) */
-static const struct bit_entry rtc_bits[] =
-{
-    /* placeholder, containing the size information */
-    {9, 0, 0, 0, NULL, NULL }, /* 9 bit to tell how far this is populated */
-
-    /* # of bits, offset+size, default, .cfg name, .cfg values */
-    /* sound */
-#if CONFIG_CODEC == MAS3507D
-    {8 | SIGNED, S_O(volume), -18, "volume", NULL }, /* -78...+18 */
-#else
-    {8 | SIGNED, S_O(volume), -25, "volume", NULL }, /* -100...+12 / -84...0 */
-#endif
-    {8 | SIGNED, S_O(balance), 0, "balance", NULL }, /* -100...100 */
-#if CONFIG_CODEC != SWCODEC /* any MAS */
-    {5 | SIGNED, S_O(bass), 0, "bass", NULL }, /* -15..+15 / -12..+12 */
-    {5 | SIGNED, S_O(treble), 0, "treble", NULL }, /* -15..+15 / -12..+12 */
-#elif defined HAVE_UDA1380
-    {5, S_O(bass), 0, "bass", NULL }, /* 0..+24 */
-    {3, S_O(treble), 0, "treble", NULL }, /* 0..+6 */
-#elif defined(HAVE_WM8975) || defined(HAVE_WM8758) \
-   || defined(HAVE_WM8731) || defined(HAVE_WM8721)
-    {5 | SIGNED, S_O(bass), 0, "bass", NULL }, /* -6..+9 */
-    {5 | SIGNED, S_O(treble), 0, "treble", NULL }, /* -6..+9 */
-#endif
-#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
-    {5, S_O(loudness), 0, "loudness", NULL }, /* 0...17 */
-    {3, S_O(avc), 0, "auto volume", "off,20ms,2,4,8" },
-    {1, S_O(superbass), false, "superbass", off_on },
-#endif
-    {3, S_O(channel_config), 0, "channels",
-        "stereo,mono,custom,mono left,mono right,karaoke" },
-    {8, S_O(stereo_width), 100, "stereo width", NULL},
-    /* playback */
-    {1, S_O(resume), false, "resume", off_on },
-    {1, S_O(playlist_shuffle), false, "shuffle", off_on },
-    {16 | SIGNED, S_O(resume_index), -1, NULL, NULL },
-    {16 | SIGNED, S_O(resume_first_index), 0, NULL, NULL },
-    {32 | SIGNED, S_O(resume_offset), -1, NULL, NULL },
-    {32 | SIGNED, S_O(resume_seed), -1, NULL, NULL },
-    {3, S_O(repeat_mode), REPEAT_ALL, "repeat", "off,all,one,shuffle,ab" },
-    /* LCD */
-#ifdef HAVE_LCD_CONTRAST
-    {6, S_O(contrast), DEFAULT_CONTRAST_SETTING, "contrast", NULL },
-#endif
-#ifdef CONFIG_BACKLIGHT
-    {5, S_O(backlight_timeout), 6, "backlight timeout", backlight_times_conf },
-#ifdef CONFIG_CHARGING
-    {5, S_O(backlight_timeout_plugged), 11, "backlight timeout plugged",
-        backlight_times_conf },
-#endif
-#endif /* CONFIG_BACKLIGHT */
-#ifdef HAVE_LCD_BITMAP
-    {1, S_O(invert), false, "invert", off_on },
-    {1, S_O(flip_display), false, "flip display", off_on },
-    /* display */
-    {1, S_O(invert_cursor), true, "invert cursor", off_on },
-    {1, S_O(statusbar), true, "statusbar", off_on },
-    {1, S_O(scrollbar), true, "scrollbar", off_on },
-#if CONFIG_KEYPAD == RECORDER_PAD
-    {1, S_O(buttonbar), true, "buttonbar", off_on },
-#endif
-    {1, S_O(volume_type), 0, "volume display", graphic_numeric },
-    {1, S_O(battery_display), 0, "battery display", graphic_numeric },
-    {1, S_O(timeformat), 0, "time format", "24hour,12hour" },
-#endif /* HAVE_LCD_BITMAP */
-    {1, S_O(show_icons), true, "show icons", off_on },
-    /* system */
-    {4, S_O(poweroff), 10,
-        "idle poweroff", "off,1,2,3,4,5,6,7,8,9,10,15,30,45,60" },
-    {18, S_O(runtime), 0, NULL, NULL },
-    {18, S_O(topruntime), 0, NULL, NULL },
-#if MEM > 1
-    {15, S_O(max_files_in_playlist), 10000,
-        "max files in playlist", NULL }, /* 1000...20000 */
-    {14, S_O(max_files_in_dir), 400,
-        "max files in dir", NULL }, /* 50...10000 */
-#else
-    {15, S_O(max_files_in_playlist), 1000,
-        "max files in playlist", NULL }, /* 1000...20000 */
-    {14, S_O(max_files_in_dir), 200,
-        "max files in dir", NULL }, /* 50...10000 */
-#endif
-    /* battery */
-    {12, S_O(battery_capacity), BATTERY_CAPACITY_DEFAULT, "battery capacity",
-         NULL }, /* 1500...3200 for NiMH, 2200...3200 for LiIon,
-                     500...1500 for Alkaline */
-#ifdef CONFIG_CHARGING
-    {1, S_O(car_adapter_mode), false, "car adapter mode", off_on },
-#endif
-    /* tuner */
-#ifdef CONFIG_TUNER
-    {1, S_O(fm_force_mono), false, "force fm mono", off_on },
-    {9, S_O(last_frequency), 0, NULL, NULL }, /* Default: MIN_FREQ */
-#endif
-
-#if BATTERY_TYPES_COUNT > 1
-    {1, S_O(battery_type), 0, "battery type", "alkaline,nimh" },
-#endif
-
-#ifdef HAVE_REMOTE_LCD
-    /* remote lcd */
-    {6, S_O(remote_contrast), DEFAULT_REMOTE_CONTRAST_SETTING,
-        "remote contrast", NULL },
-    {1, S_O(remote_invert), false, "remote invert", off_on },
-    {1, S_O(remote_flip_display), false, "remote flip display", off_on },
-    {5, S_O(remote_backlight_timeout), 6, "remote backlight timeout",
-        backlight_times_conf },
-#ifdef CONFIG_CHARGING
-    {5, S_O(remote_backlight_timeout_plugged), 11,
-        "remote backlight timeout plugged", backlight_times_conf },
-#endif
-#ifdef HAVE_REMOTE_LCD_TICKING
-    {1, S_O(remote_reduce_ticking), false, "remote reduce ticking", off_on },
-#endif
-#endif
-
-#ifdef CONFIG_BACKLIGHT
-    {1, S_O(bl_filter_first_keypress), false,
-            "backlight filters first keypress", off_on },
-#ifdef HAVE_REMOTE_LCD
-    {1, S_O(remote_bl_filter_first_keypress), false,
-            "backlight filters first remote keypress", off_on },
-#endif
-#endif /* CONFIG_BACKLIGHT */
-
-    /* new stuff to be added here */
-    /* If values are just added to the end, no need to bump the version. */
-
-    /* Current sum of bits: 277 (worst case, but w/o remote lcd) */
-    /* Sum of all bit sizes must not grow beyond 288! */
-};
-
-
-/* the part of the settings which ends up in HD sector only */
-static const struct bit_entry hd_bits[] =
-{
-    /* This table starts after the 44 RTC bytes = 352 bits. */
-    /* Here we need 11 bits to tell how far this is populated. */
-
-    /* placeholder, containing the size information */
-    {11, 0, 0, 0, NULL, NULL }, /* 11 bit to tell how far this is populated */
-
-    /* # of bits, offset+size, default, .cfg name, .cfg values */
-    /* more display */
-#ifdef CONFIG_BACKLIGHT
-    {1, S_O(caption_backlight), false, "caption backlight", off_on },
-#endif
-#ifdef HAVE_REMOTE_LCD
-    {1, S_O(remote_caption_backlight), false,
-        "remote caption backlight", off_on },
-#endif
-#ifdef HAVE_BACKLIGHT_BRIGHTNESS
-    {4, S_O(brightness), DEFAULT_BRIGHTNESS_SETTING, "brightness", NULL },
-#endif
-#ifdef HAVE_BACKLIGHT_PWM_FADING
-    /* backlight fading */
-    {2, S_O(backlight_fade_in), 1, "backlight fade in", "off,500ms,1s,2s"},
-    {3, S_O(backlight_fade_out), 3, "backlight fade out",
-        "off,500ms,1s,2s,3s,4s,5s,10s"},
-#endif
-
-    {4, S_O(scroll_speed), 9, "scroll speed", NULL }, /* 0...15 */
-    {8, S_O(scroll_delay), 100, "scroll delay", NULL }, /* 0...250 */
-    {8, S_O(bidir_limit), 50, "bidir limit", NULL }, /* 0...200 */
-    
-#ifdef HAVE_REMOTE_LCD
-    {4, S_O(remote_scroll_speed), 9, "remote scroll speed", NULL }, /* 0...15 */
-    {8, S_O(remote_scroll_step), 6, "remote scroll step", NULL }, /* 1...160 */
-    {8, S_O(remote_scroll_delay), 100, "remote scroll delay", NULL }, /* 0...250 */
-    {8, S_O(remote_bidir_limit), 50, "remote bidir limit", NULL }, /* 0...200 */
-#endif
-
-#ifdef HAVE_LCD_BITMAP
-    {1, S_O(offset_out_of_view), false, "Screen Scrolls Out Of View", off_on },
-#if LCD_WIDTH > 255
-    {9, S_O(scroll_step), 6, "scroll step", NULL },
-    {9, S_O(screen_scroll_step), 16, "screen scroll step", NULL },
-#elif LCD_WIDTH > 127
-    {8, S_O(scroll_step), 6, "scroll step", NULL },
-    {8, S_O(screen_scroll_step), 16, "screen scroll step", NULL },
-#else
-    {7, S_O(scroll_step), 6, "scroll step", NULL },
-    {7, S_O(screen_scroll_step), 16, "screen scroll step", NULL },
-#endif
-#endif /* HAVE_LCD_BITMAP */
-#ifdef HAVE_LCD_CHARCELLS
-    {3, S_O(jump_scroll), 0, "jump scroll", NULL }, /* 0...5 */
-    {8, S_O(jump_scroll_delay), 50, "jump scroll delay", NULL }, /* 0...250 */
-#endif
-    {1, S_O(scroll_paginated), false, "scroll paginated", off_on },
-
-#ifdef HAVE_LCD_COLOR
-    {LCD_DEPTH,S_O(fg_color),LCD_DEFAULT_FG,"foreground color","rgb"},
-    {LCD_DEPTH,S_O(bg_color),LCD_DEFAULT_BG,"background color","rgb"},
-#endif
-
-    /* more playback */
-    {1, S_O(play_selected), true, "play selected", off_on },
-    {1, S_O(fade_on_stop), true, "volume fade", off_on },
-    {4, S_O(ff_rewind_min_step), FF_REWIND_1000,
-        "scan min step", "1,2,3,4,5,6,8,10,15,20,25,30,45,60" },
-    {4, S_O(ff_rewind_accel), 3, "scan accel", NULL },
-#if CONFIG_CODEC == SWCODEC
-    {3, S_O(buffer_margin), 0, "antiskip",
-        "5s,15s,30s,1min,2min,3min,5min,10min" },
-#else
-    {3, S_O(buffer_margin), 0, "antiskip", NULL },
-#endif
-    /* disk */
-#ifndef HAVE_MMC
-#ifdef HAVE_ATA_POWER_OFF
-    {1, S_O(disk_poweroff), false, "disk poweroff", off_on },
-#endif
-    {8, S_O(disk_spindown), 5, "disk spindown", NULL },
-#endif /* HAVE_MMC */
-
-    /* browser */
-    {3, S_O(dirfilter), SHOW_SUPPORTED,
-        "show files", "all,supported,music,playlists"
-#ifdef HAVE_TAGCACHE
-        ",id3 database" 
-#endif
-        },
-    {1, S_O(sort_case), false, "sort case", off_on },
-    {1, S_O(browse_current), false, "follow playlist", off_on },
-    /* playlist */
-    {1, S_O(playlist_viewer_icons), true, "playlist viewer icons", off_on },
-    {1, S_O(playlist_viewer_indices), true,
-        "playlist viewer indices", off_on },
-    {1, S_O(playlist_viewer_track_display), 0,
-        "playlist viewer track display", "track name,full path" },
-    {2, S_O(recursive_dir_insert), RECURSE_OFF,
-        "recursive directory insert", off_on_ask },
-    /* bookmarks */
-    {3, S_O(autocreatebookmark), BOOKMARK_NO, "autocreate bookmarks",
-        "off,on,ask,recent only - on,recent only - ask" },
-    {2, S_O(autoloadbookmark), BOOKMARK_NO,
-        "autoload bookmarks", off_on_ask },
-    {2, S_O(usemrb), BOOKMARK_NO,
-        "use most-recent-bookmarks", "off,on,unique only" },
-#ifdef HAVE_LCD_BITMAP
-    /* peak meter */
-    {5, S_O(peak_meter_clip_hold), 16, "peak meter clip hold", /* 0...25 */
-        "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" },
-    {5, S_O(peak_meter_hold), 3, "peak meter hold",
-        "off,200ms,300ms,500ms,1,2,3,4,5,6,7,8,9,10,15,20,30,1min" },
-    {7, S_O(peak_meter_release), 8, "peak meter release", NULL }, /* 0...126 */
-    {1, S_O(peak_meter_dbfs), true, "peak meter dbfs", off_on },
-    {7, S_O(peak_meter_min), 60, "peak meter min", NULL }, /* 0...100 */
-    {7, S_O(peak_meter_max), 0, "peak meter max", NULL }, /* 0...100 */
-#endif
-#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
-    {7, S_O(mdb_strength), 0, "mdb strength", NULL},
-    {7, S_O(mdb_harmonics), 0, "mdb harmonics", NULL},
-    {9, S_O(mdb_center), 0, "mdb center", NULL},
-    {9, S_O(mdb_shape), 0, "mdb shape", NULL},
-    {1, S_O(mdb_enable), 0, "mdb enable", off_on},
-#endif
-#if CONFIG_CODEC == MAS3507D
-    {1, S_O(line_in), false, "line in", off_on },
-#endif
-    /* voice */
-    {2, S_O(talk_dir), 0, "talk dir", off_number_spell_hover },
-    {2, S_O(talk_file), 0, "talk file", off_number_spell_hover },
-    {1, S_O(talk_menu), true, "talk menu", off_on },
-
-    {2, S_O(sort_file), 0, "sort files", "alpha,oldest,newest,type" },
-    {2, S_O(sort_dir), 0, "sort dirs", "alpha,oldest,newest" },
-    {1, S_O(id3_v1_first), 0, "id3 tag priority", "v2-v1,v1-v2"},
-
-#ifdef HAVE_RECORDING
-    /* recording */
-    {1, S_O(recscreen_on), false, "recscreen on", off_on },
-    {1, S_O(rec_startup), false, "rec screen on startup", off_on },
-    {4, S_O(rec_timesplit), 0, "rec timesplit", /* 0...15 */
-        "off,00:05,00:10,00:15,00:30,01:00,01:14,01:20,02:00,04:00,06:00,08:00,10:00,12:00,18:00,24:00" },
-    {4, S_O(rec_sizesplit), 0, "rec sizesplit", /* 0...15 */
-        "off,5MB,10MB,15MB,32MB,64MB,75MB,100MB,128MB,256MB,512MB,650MB,700MB,1GB,1.5GB,1.75GB" },
-    {1, S_O(rec_channels), 0, "rec channels", "stereo,mono" },
-    {1, S_O(rec_split_type), 0, "rec split type", "Split, Stop" },
-    {1, S_O(rec_split_method), 0, "rec split method", "Time,Filesize" },
-
-    {
-#if defined(HAVE_SPDIF_IN) || defined(HAVE_FMRADIO_IN)
-        2,
-#else
-        1,
-#endif
-        S_O(rec_source), 0 /* 0=mic */, "rec source",
-        "mic,line"
-#ifdef HAVE_SPDIF_IN
-        ",spdif"
-#endif
-#ifdef HAVE_FMRADIO_IN
-        ",fmradio"
-#endif
-    },
-    {5, S_O(rec_prerecord_time), 0, "prerecording time", NULL }, /* 0...30 */
-    {1, S_O(rec_directory), 0, /* rec_base_directory */
-        "rec directory", REC_BASE_DIR ",current" },
-#ifdef CONFIG_BACKLIGHT
-    {2, S_O(cliplight), 0, "cliplight", "off,main,both,remote" },
-#endif 
-#if CONFIG_CODEC == MAS3587F
-    {4, S_O(rec_mic_gain), 8, "rec mic gain", NULL },
-    {4, S_O(rec_left_gain), 2 /* 0dB */, "rec left gain", NULL }, /* 0...15 */
-    {4, S_O(rec_right_gain), 2 /* 0dB */, "rec right gain", NULL }, /* 0...15 */
-    {3, S_O(rec_frequency), 0, /* 0=44.1kHz */
-        "rec frequency", "44,48,32,22,24,16" },
-    {3, S_O(rec_quality), 5 /* 192 kBit/s max */, "rec quality", NULL },
-    {1, S_O(rec_editable), false, "editable recordings", off_on },
-#endif /* CONFIG_CODEC == MAS3587F */
-
-#if CONFIG_CODEC == SWCODEC
-#ifdef HAVE_UDA1380
-    {8|SIGNED, S_O(rec_mic_gain), 16 /* 8 dB */, "rec mic gain", NULL }, /* -128...+108 */
-#endif
-#ifdef HAVE_TLV320
-    /* TLV320 only has no mic boost or 20db mic boost */
-    {1, S_O(rec_mic_gain), 0 /* 0 dB */, "rec mic gain", NULL }, /* 0db or 20db */
-#endif
-    {8|SIGNED, S_O(rec_left_gain), 0, "rec left gain", NULL }, /* -128...+96 */
-    {8|SIGNED, S_O(rec_right_gain), 0, "rec right gain", NULL }, /* -128...+96 */
-    {REC_FREQ_CFG_NUM_BITS, S_O(rec_frequency), REC_FREQ_DEFAULT,
-        "rec frequency", REC_FREQ_CFG_VAL_LIST },
-    {REC_FORMAT_CFG_NUM_BITS ,S_O(rec_format), REC_FORMAT_DEFAULT,
-        "rec format", REC_FORMAT_CFG_VAL_LIST },
-    /** Encoder settings start - keep these together **/
-    /* mp3_enc */
-    {5,S_O(mp3_enc_config.bitrate), MP3_ENC_BITRATE_CFG_DEFAULT,
-        "mp3_enc bitrate", MP3_ENC_BITRATE_CFG_VALUE_LIST },
-    /* wav_enc */
-    /* (no settings yet) */
-    /* wavpack_enc */
-    /* (no settings yet) */
-    /** Encoder settings end **/
-#endif /* CONFIG_CODEC == SWCODEC */
-
-    /* values for the trigger */
-    {8 | SIGNED, S_O(rec_start_thres), -35, "trigger start threshold", NULL},
-    {8 | SIGNED, S_O(rec_stop_thres), -45, "trigger stop threshold", NULL},
-    {4, S_O(rec_start_duration), 0, "trigger start duration", trig_durations_conf},
-    {4, S_O(rec_stop_postrec), 2, "trigger stop postrec", trig_durations_conf},
-    {4, S_O(rec_stop_gap), 1, "trigger min gap", trig_durations_conf},
-    {4, S_O(rec_trigger_mode ), 0, "trigger mode", "off,once,repeat"},
-#endif /* HAVE_RECORDING */
-
-#ifdef HAVE_SPDIF_POWER
-    {1, S_O(spdif_enable), false, "spdif enable", off_on},
-#endif
-
-    {2, S_O(next_folder), false, "folder navigation", "off,on,random" },
-    {1, S_O(runtimedb), false, "gather runtime data", off_on },
-
-#if CONFIG_CODEC == SWCODEC
-    {1, S_O(replaygain), false, "replaygain", off_on },
-    {2, S_O(replaygain_type), REPLAYGAIN_ALBUM, "replaygain type",
-        "track,album,track shuffle" },
-    {1, S_O(replaygain_noclip), false, "replaygain noclip", off_on },
-    {8 | SIGNED, S_O(replaygain_preamp), 0, "replaygain preamp", NULL },
-    {2, S_O(beep), 0, "beep", "off,weak,moderate,strong" },
-    {2, S_O(crossfade), 0, "crossfade", "off,shuffle,track skip,always"},
-    {3, S_O(crossfade_fade_in_delay), 0, "crossfade fade in delay", NULL},
-    {3, S_O(crossfade_fade_out_delay), 0, "crossfade fade out delay", NULL},
-    {4, S_O(crossfade_fade_in_duration), 0, "crossfade fade in duration", NULL},
-    {4, S_O(crossfade_fade_out_duration), 0, "crossfade fade out duration", NULL},
-    {1, S_O(crossfade_fade_out_mixmode), 0, "crossfade fade out mode", "crossfade,mix"},
-    {1, S_O(crossfeed), false, "crossfeed", off_on },
-    {6, S_O(crossfeed_direct_gain), 15, "crossfeed direct gain", NULL },
-    {7, S_O(crossfeed_cross_gain), 60, "crossfeed cross gain", NULL },
-    {8, S_O(crossfeed_hf_attenuation), 160, "crossfeed hf attenuation", NULL },
-    {11, S_O(crossfeed_hf_cutoff), 700, "crossfeed hf cutoff", NULL },
-
-    /* equalizer */
-    {1, S_O(eq_enabled), false, "eq enabled", off_on },
-    {8, S_O(eq_precut), 0, "eq precut", NULL },
-    /* 0..32768 Hz */
-    {15, S_O(eq_band0_cutoff), 60, "eq band 0 cutoff", NULL },
-    {15, S_O(eq_band1_cutoff), 200, "eq band 1 cutoff", NULL },
-    {15, S_O(eq_band2_cutoff), 800, "eq band 2 cutoff", NULL },
-    {15, S_O(eq_band3_cutoff), 4000, "eq band 3 cutoff", NULL },
-    {15, S_O(eq_band4_cutoff), 12000, "eq band 4 cutoff", NULL },
-    /* 0..64 (or 0.0 to 6.4) */
-    {6, S_O(eq_band0_q), 7, "eq band 0 q", NULL },
-    {6, S_O(eq_band1_q), 10, "eq band 1 q", NULL },
-    {6, S_O(eq_band2_q), 10, "eq band 2 q", NULL },
-    {6, S_O(eq_band3_q), 10, "eq band 3 q", NULL },
-    {6, S_O(eq_band4_q), 7, "eq band 4 q", NULL },
-    /* -240..240 (or -24db to +24db) */
-    {9|SIGNED, S_O(eq_band0_gain), 0, "eq band 0 gain", NULL },
-    {9|SIGNED, S_O(eq_band1_gain), 0, "eq band 1 gain", NULL },
-    {9|SIGNED, S_O(eq_band2_gain), 0, "eq band 2 gain", NULL },
-    {9|SIGNED, S_O(eq_band3_gain), 0, "eq band 3 gain", NULL },
-    {9|SIGNED, S_O(eq_band4_gain), 0, "eq band 4 gain", NULL },
-
-    /* dithering */
-    {1, S_O(dithering_enabled), false, "dithering enabled", off_on },
-#endif
-
-#ifdef HAVE_DIRCACHE
-    {1, S_O(dircache), false, "dircache", off_on },
-    {22, S_O(dircache_size), 0, NULL, NULL },
-#endif
-
-#ifdef HAVE_TAGCACHE
-#ifdef HAVE_TC_RAMCACHE
-    {1, S_O(tagcache_ram), 0, "tagcache_ram", off_on },
-#endif
-    {1, S_O(tagcache_autoupdate), 0, "tagcache_autoupdate", off_on },
-#endif
-
-    {4, S_O(default_codepage), 0, "default codepage",
-        "iso8859-1,iso8859-7,iso8859-8,cp1251,iso8859-11,cp1256,iso8859-9,iso8859-2,sjis,gb2312,ksx1001,big5,utf-8,cp1256" },
-
-    {1, S_O(warnon_erase_dynplaylist), false,
-        "warn when erasing dynamic playlist", off_on },
-
-#ifdef CONFIG_BACKLIGHT
-#ifdef HAS_BUTTON_HOLD
-    {2, S_O(backlight_on_button_hold), 0, "backlight on button hold",
-        "normal,off,on" },
-#endif
-
-#ifdef HAVE_LCD_SLEEP
-    {4, S_O(lcd_sleep_after_backlight_off), 3,
-        "lcd sleep after backlight off",
-        "always,never,5,10,15,20,30,45,60,90" },
-#endif
-#endif /* CONFIG_BACKLIGHT */
-
-#ifdef HAVE_WM8758
-    {1, S_O(eq_hw_enabled), false, "eq hardware enabled", off_on },
-    
-    {2, S_O(eq_hw_band0_cutoff), 1, "eq hardware band 0 cutoff", "80Hz,105Hz,135Hz,175Hz" },
-    {5|SIGNED, S_O(eq_hw_band0_gain), 0, "eq hardware band 0 gain", NULL },
-
-    {2, S_O(eq_hw_band1_center), 1, "eq hardware band 1 center", "230Hz,300Hz,385Hz,500Hz" },
-    {1, S_O(eq_hw_band1_bandwidth), 0, "eq hardware band 1 bandwidth", "narrow,wide" },
-    {5|SIGNED, S_O(eq_hw_band1_gain), 0, "eq hardware band 1 gain", NULL },
-
-    {2, S_O(eq_hw_band2_center), 1, "eq hardware band 2 center", "650Hz,850Hz,1.1kHz,1.4kHz" },
-    {1, S_O(eq_hw_band2_bandwidth), 0, "eq hardware band 2 bandwidth", "narrow,wide" },
-    {5|SIGNED, S_O(eq_hw_band2_gain), 0, "eq hardware band 2 gain", NULL },
-
-    {2, S_O(eq_hw_band3_center), 1, "eq hardware band 3 center", "1.8kHz,2.4kHz,3.2kHz,4.1kHz" },
-    {1, S_O(eq_hw_band3_bandwidth), 0, "eq hardware band 3 bandwidth", "narrow,wide" },
-    {5|SIGNED, S_O(eq_hw_band3_gain), 0, "eq hardware band 3 gain", NULL },
-
-    {2, S_O(eq_hw_band4_cutoff), 1, "eq hardware band 4 cutoff", "5.3kHz,6.9kHz,9kHz,11.7kHz" },
-    {5|SIGNED, S_O(eq_hw_band4_gain), 0, "eq hardware band 4 gain", NULL },
-#endif
-    {1, S_O(hold_lr_for_scroll_in_list), true, "hold_lr_for_scroll_in_list", off_on },
-
-    {2, S_O(show_path_in_browser), 0, "show path in browser", "off,current directory,full path" },
-#ifdef HAVE_AGC
-    {4, S_O(rec_agc_preset_mic), 1, "agc mic preset", NULL}, /* 0...5 */
-    {4, S_O(rec_agc_preset_line), 1, "agc line preset", NULL}, /* 0...5 */
-    {8|SIGNED, S_O(rec_agc_maxgain_mic), 104, "agc maximum mic gain", NULL},
-    {8|SIGNED, S_O(rec_agc_maxgain_line), 96, "agc maximum line gain", NULL},
-    {3, S_O(rec_agc_cliptime), 1, "agc cliptime", "0.2s,0.4s,0.6s,0.8,1s"},
-#endif
-
-#ifdef HAVE_REMOTE_LCD
-#ifdef HAS_REMOTE_BUTTON_HOLD
-    {2, S_O(remote_backlight_on_button_hold), 0, "remote backlight on button hold",
-        "normal,off,on" },
-#endif
-#endif
-
-#ifdef HAVE_HEADPHONE_DETECTION
-    {2, S_O(unplug_mode), 0, "pause on headphone unplug", NULL},
-    {4, S_O(unplug_rw), 0, "rewind duration on pause", NULL},
-    {1, S_O(unplug_autoresume), 0, "disable autoresume if phones not present", off_on },
-#endif
-#ifdef CONFIG_TUNER
-    {2, S_O(fm_region), 0, "fm_region", "eu,us,jp,kr" },
-#endif
-
-    {1, S_O(audioscrobbler), false, "Last.fm Logging", off_on},
-
-    /* If values are just added to the end, no need to bump the version. */
-    /* new stuff to be added at the end */
-#ifdef HAVE_RECORDING
-    {2, S_O(rec_trigger_type), 0, "trigger type", "stop,pause,nf stp"},
-#endif
-
-    /* Sum of all bit sizes must not grow beyond 0xB8*8 = 1472 */
+struct persistant_vars {
+    void *setting;
+    char value[MAX_FILENAME];
 };
-
-/* helper function to extract n (<=32) bits from an arbitrary position
- * counting from LSB to MSB */
-static uint32_t get_bits(
-    const uint32_t *p, /* the start of the bitfield array */
-    unsigned int from, /* bit no. to start reading from */
-    unsigned int size) /* how many bits to read */
-{
-    unsigned int long_index = from / 32;
-    unsigned int bit_index = from % 32;
-    uint32_t result;
-
-    result = p[long_index] >> bit_index;
-
-    if (bit_index + size > 32)     /* crossing longword boundary */
-        result |= p[long_index+1] << (32 - bit_index);
-
-    result &= 0xFFFFFFFF >> (32 - size);
-
-    return result;
+#define MAX_PERSISTANT_VARS 16
+struct persistant_vars persistant_variables[MAX_PERSISTANT_VARS];
+int persistant_vars_count = 0;
+void add_to_persistant(const struct settings_list *item, char* value)
+{
+    if (persistant_vars_count<MAX_PERSISTANT_VARS)
+    {
+        strcpy(persistant_variables[persistant_vars_count].value,value);
+        persistant_variables[persistant_vars_count].setting = item->setting;
+        persistant_vars_count++;
+    }
 }
 
-/* helper function to set n (<=32) bits to an arbitrary position,
- * counting from LSB to MSB */
-static void set_bits(
-    uint32_t *p,       /* the start of the bitfield array */
-    unsigned int from, /* bit no. to start writing into */
-    unsigned int size, /* how many bits to change */
-    uint32_t value)    /* content (LSBs will be taken) */
-{
-    unsigned int long_index = from / 32;
-    unsigned int bit_index = from % 32;
-    uint32_t mask;
-
-    mask = 0xFFFFFFFF >> (32 - size);
-    value &= mask;
-    mask <<= bit_index;
-
-    if (bit_index + size > 32)
-        p[long_index+1] =
-            (p[long_index+1] & (0xFFFFFFFF << (bit_index + size - 32)))
-            | (value >> (32 - bit_index));
-
-    p[long_index] = (p[long_index] & ~mask) | (value << bit_index);
-}
 
 #ifdef HAVE_LCD_COLOR
 /*
@@ -772,388 +168,953 @@
 }
 #endif
 
-/*
- * Calculates the checksum for the config block and returns it
- */
-
-static unsigned short calculate_config_checksum(const unsigned char* buf)
+void write_settings_to_disk(void)
 {
-    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];
+#ifndef SIMULATOR
+    if (ata_disk_is_active())
+        settings_save_config(ROCKBOX_CONFIGFILE,false);
+    else 
+#endif
+        settings_save();
 }
 
-/*
- * initialize the config block buffer
- */
-static void init_config_buffer( void )
+bool settings_save_ata_cb( void )
 {
-    DEBUGF( "init_config_buffer()\n" );
-
-    /* reset to 0 - all unused */
-    memset(config_block, 0, CONFIG_BLOCK_SIZE);
-    /* insert header */
-    config_block[0] = 'R';
-    config_block[1] = 'o';
-    config_block[2] = 'c';
-    config_block[3] = CONFIG_BLOCK_VERSION;
+#ifndef SIMULATOR
+    queue_broadcast(SYS_DUMPSETTINGS,0); /*hopefully only the main thread 
+                                           will accept use this, so it 
+                                           shouldnt stkOv! */
+#else
+    write_settings_to_disk();
+#endif
+    return 0;
 }
 
-bool flush_config_block_callback(void)
-{
-    ata_write_sectors(IF_MV2(0,) config_sector, 1, config_block);
-    return true;
-}
-/*
- * save the config block buffer to disk or RTC RAM
- */
-static int save_config_buffer( void )
+int settings_save( void )
 {
-    unsigned short chksum;
-#ifdef HAVE_RTC_RAM
-    unsigned int i;
-#endif
-
-    /* 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_RAM
-    /* 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 (config_sector != 0)
-        register_ata_idle_func(flush_config_block_callback);
-    else
-        return -1;
-
+    register_ata_idle_func(settings_save_ata_cb);
     return 0;
 }
 
-/*
- * load the config block buffer from disk or RTC RAM
- */
-static int load_config_buffer(int which)
+void save_item_to_gs(const struct settings_list *item, char* new_val)
 {
-    unsigned short chksum;
-    bool correct = false;
-
-
-    DEBUGF( "load_config_buffer()\n" );
-
-    if (which & SETTINGS_HD)
+    switch (item->flags&F_T_MASK)
     {
-        if (config_sector != 0) {
-            ata_read_sectors(IF_MV2(0,) config_sector, 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])
+        case F_T_INT:
+#ifdef HAVE_LCD_COLOR
+            if (item->flags&F_STORERGB)
             {
-                DEBUGF( "load_config_buffer: header & checksum test ok\n" );
-                correct = true;
+                *(int*)item->setting = hex_to_rgb(new_val);
             }
-        }
+            else 
+#endif
+                 if (item->flags&F_STOREREALVALUE)
+                        *(int*)item->setting
+                        = atoi(new_val);
+            else if (item->flags&F_T_CHOICE)
+            {
+                int i;
+                if (item->flags&F_LANG_STRING)
+                {
+                    for (i=0;i<item->nb_values;i++)
+                    {
+                        if (!strcmp(new_val, item->strings[i]))
+                        {
+                            *(int*)item->setting = i;
+                            break;
+                        }
+                    }
+                }
+                else
+                {
+                    char *start, *end;
+                    int len = strlen(new_val);
+                    start = strchr(item->conf_file_info,',');
+                    if (!start)
+                        break;
+                    end = strchr(++start,',');
+                    i = 0;
+                    while (start)
+                    {
+                        if (!strncmp(start,new_val, MAX(((end?end:0)-start),len)))
+                        {
+                            *(int*)item->setting = i;
+                            break;
+                        }
+                        i++;
+                        start = end+1;
+                        if (end)
+                            end = strchr(++end,',');
+                    }
+                }
+            }
+            else *(int*)item->setting = atoi(new_val);
+            break;
+        case F_T_UINT:
+            *(unsigned int*)item->setting = 
+                    (unsigned int)atoi(new_val);
+            break;
+        case F_T_BOOL:
+            if (!strcmp(new_val,"on"))
+                *(bool*)item->setting = true;
+            else *(bool*)item->setting = false;
+            break;
+        case F_T_CHARPTR:
+        case F_T_UCHARPTR:
+            if (item->flags&F_FILENAMEONLY && 
+                strrchr(new_val,'/'))
+            {
+                set_file(new_val,
+                         (char*)item->setting,MAX_FILENAME);
+            }
+            else strcpy((char*)item->setting,new_val);
+            break;
     }
+}
+bool check_setting_name(char* from_file, char* in_settings)
+{
+    int len = strlen(from_file);
+    return !strncmp(from_file,in_settings,len) &&
+            ( ( in_settings[len] == ',') ||
+                    ( in_settings[len] == '\0'));
+}
 
-#ifdef HAVE_RTC_RAM
-    if(!correct)
-    {
-        /* If the disk sector was incorrect, reinit the buffer */
-        memset(config_block, 0, CONFIG_BLOCK_SIZE);
-    }
+bool settings_load_config(const char* file)
+{
+    int fd;
+    char line[256];
+    char* name;
+    char* value;
+    int pos; /* currently returned position */
+    const struct settings_list *item;
+    bool persistant = false;
+    
+    fd = open(file, O_RDONLY);
+    if (fd < 0)
+        return false;
 
-    if (which & SETTINGS_RTC)
+    while (read_line(fd, line, sizeof line) > 0)
     {
-        unsigned int i;
-        unsigned char rtc_block[RTC_BLOCK_SIZE];
+        if (!settings_parseline(line, &name, &value))
+            continue;
 
-        /* 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])
+        if (name[0] == '~') /* load the value, and dont save the new value to disk */
         {
-            memcpy(config_block, rtc_block, RTC_BLOCK_SIZE);
-            correct = true;
+            persistant = true;
+            name++;
         }
-    }
-#endif
+        else persistant = false;
 
-    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;
+        for (pos = 0; pos < nb_settings ; pos++)
+        {
+            item = &settings[pos];
+            
+            if (item->flags&(F_SYSTEMSETTING|F_T_CHARPTR|F_LANG_IS_STRING))
+            {
+                if (!strcmp(name,item->cfg_string))
+                {
+                    if (persistant)
+                        add_to_persistant(item,value);
+                    save_item_to_gs(item,value);
+                    break;
+                }
+            }
+            else if (check_setting_name(name,item->conf_file_info))
+            {
+                if (persistant)
+                    add_to_persistant(item,value);
+                save_item_to_gs(item,value);
+                break;
+            }
+        } /* for (...) */
     }
 
-    return 0;
+    close(fd);
+    settings_apply(false);
+    return true;
 }
-
-
-/* helper to save content of global_settings into a bitfield,
-   as described per table */
-static void save_bit_table(const struct bit_entry* p_table, int count, int bitstart)
+#ifdef HAVE_RTC_RAM
+bool load_from_rtc(int rtc_item, int *value)
 {
-    uint32_t *p_bitfield = (uint32_t *)config_block; /* 32 bit addr. */
-    uint32_t value; /* 32 bit content */
-    int i;
-    const struct bit_entry* p_run = p_table; /* start after the size info */
-    int curr_bit = bitstart + p_table->bit_size;
-    count--; /* first is excluded from loop */
-
-    for (i=0; i<count; i++)
+    if (!rtc_read_multiple(0x14+(rtc_item*4),(char*)value,4))
+        return true;
+    return false;
+}
+    
+bool save_to_rtc(int rtc_item, int value)
+{
+    union { int i; char c[4]; } storage;
+    int j = 0;
+    int ret=0, address = 0x14+(rtc_item*4);
+    storage.i = value;
+    for(j=0; j<4 && ret==0;j++)
     {
-        p_run++;
-        /* could do a memcpy, but that would be endian-dependent */
-        switch(p_run->byte_size)
-        {
-        case 1:
-            value = ((uint8_t *)&global_settings)[p_run->settings_offset];
-            break;
-        case 2:
-            value = ((uint16_t *)&global_settings)[p_run->settings_offset/2];
-            break;
-        case 4:
-            value = ((uint32_t *)&global_settings)[p_run->settings_offset/4];
-            break;
-        default:
-            DEBUGF( "save_bit_table: illegal size!\n" );
-            continue;
-        }
-        set_bits(p_bitfield, curr_bit, p_run->bit_size & 0x3F, value);
-        curr_bit += p_run->bit_size & 0x3F;
+        ret = rtc_write(address+j, storage.c[j]);
     }
-    set_bits(p_bitfield, bitstart, p_table->bit_size, /* write size */
-        curr_bit); /* = position after last element */
+    return (ret==0) ? true : false;
 }
-
+#endif
 /*
- * figure out the config sector from the partition table and the
- * mounted file system
+ * load settings from disk or RTC RAM
  */
-void settings_calc_config_sector(void)
+void settings_load(int which)
 {
-#ifdef SIMULATOR
-    config_sector = 61;
-#else
-    int i;
-    long partition_start;
-    long sector = 0;
-
-    if (fat_startsector(IF_MV(0)) != 0)    /* There is a partition table */
+    DEBUGF( "reload_all_settings()\n" );
+#ifdef HAVE_RTC_RAM
+    if (which&SETTINGS_RTC)
     {
-        sector = 61;
-        for (i = 0; i < 4; i++)
+        int i, value, rtc_item = 0;
+        bool config_ok = false;
+        if (load_from_rtc(rtc_item,&value) == true)
         {
-            partition_start = disk_partinfo(i)->start;
-            if (partition_start != 0 && (partition_start - 2) < sector)
-                sector = partition_start - 2;
+            if (value == RTC_RAM_CONFIG_VERSION)
+                config_ok = true;
         }
-        if (sector < 0)
-            sector = 0;
-    }
-
-    config_sector = sector;
-#endif
-}
-
+        rtc_item++;
+        for (i=0; i<nb_settings; i++)
+        {
+            if (settings[i].flags&F_SAVETORTC)
+            {
+                if (config_ok == true)
+                {
+                    if (load_from_rtc(rtc_item++,
+                        (int*)settings[i].setting) == false)
+                    {
+                        *(int*)settings[i].setting
+                                = settings[i].default_val.int_;
+                    }
+                }
+                else *(int*)settings[i].setting
+                            = settings[i].default_val.int_;
+            }
+        }
+    }
+#endif
+    if (which&SETTINGS_HD)
+    {
+        settings_load_config(ROCKBOX_CONFIGFILE);
+    }
+}
+
+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 != '.') && (ptr != fptr)) {
+        extlen++;
+        ptr--;
+    }
+    if(ptr == fptr) extlen = 0;
+
+    if (strncasecmp(ROCKBOX_DIR, filename ,strlen(ROCKBOX_DIR)) ||
+        (len-extlen > maxlen))
+        return;
+
+    strncpy(setting, fptr, len-extlen);
+    setting[len-extlen]=0;
+    settings_save();
+}
+
 /*
- * persist all runtime user settings to disk or RTC RAM
+ * reset all settings to their default value
  */
-int settings_save( void )
+void settings_reset(void) 
 {
-    int i;
+    int i; 
+    const struct settings_list *item;
+    DEBUGF( "settings_reset()\n" );
 
+    for (i = 0; i < nb_settings ; i++)
     {
-        int elapsed_secs;
+        item = &settings[i];         
+        if (item->flags&F_T_SOUND)
+        {
+            *(int*)item->setting
+                    = sound_default(item->values[0]);
+            continue;
+        }
+        switch (item->flags&F_T_MASK)
+        {
+            case F_T_INT:
+                *(int*)item->setting
+                        = item->default_val.int_;
+                break;
+            case F_T_UINT:
+                *(unsigned int*)item->setting
+                        = item->default_val.uint_;
+                break;
+            case F_T_BOOL:
+                *(bool*)item->setting
+                        = item->default_val.bool_;
+                break;
+            case F_T_CHARPTR:
+            case F_T_UCHARPTR:
+                strcpy((char*)item->setting,
+                        item->default_val.charptr);
+                break;
+        }
+    } /* for (...) */
+}
 
-        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;
-    }
-
-    /* serialize scalar values into RTC and HD sector, specified via table */
-    save_bit_table(rtc_bits, sizeof(rtc_bits)/sizeof(rtc_bits[0]), 4*8);
-    save_bit_table(hd_bits, sizeof(hd_bits)/sizeof(hd_bits[0]), RTC_BLOCK_SIZE*8);
-
-    i = 0xb8;
-    strncpy((char *)&config_block[i], (char *)global_settings.wps_file,
-            MAX_FILENAME);
-    i+= MAX_FILENAME;
-    strncpy((char *)&config_block[i], (char *)global_settings.lang_file,
-            MAX_FILENAME);
-    i+= MAX_FILENAME;
-    strncpy((char *)&config_block[i], (char *)global_settings.font_file,
-            MAX_FILENAME);
-    i+= MAX_FILENAME;
-#ifdef HAVE_REMOTE_LCD
-    strncpy((char *)&config_block[i], (char *)global_settings.rwps_file,
-            MAX_FILENAME);
-    i+= MAX_FILENAME;
+bool settings_save_config(const char* filename, bool theme)
+{
+    int fd;
+    int i, value = 0, type;
+    int j;
+    bool persistant = false;
+    char name[256], *char_value;
+    const struct settings_list *item;
+    
+#ifdef HAVE_RTC_RAM
+    j = 0;
+    save_to_rtc(j++, RTC_RAM_CONFIG_VERSION);
+    for (i=0; i<nb_settings; i++)
+    {
+        if (settings[i].flags&F_SAVETORTC)
+        {
+            value = *(int*)settings[i].setting;
+            save_to_rtc(j++, value);
+        }
+    }
 #endif
 
-#ifdef CONFIG_TUNER
-    strncpy((char *)&config_block[i], (char *)global_settings.fmr_file,
-            MAX_FILENAME);
-    i+= MAX_FILENAME;
-#endif
+    fd = creat(filename, O_WRONLY);
+    if (fd < 0)
+        return false;
+    
+    fdprintf(fd, "#\r\n# .cfg file created by rockbox %s - "
+            "http://www.rockbox.org\r\n#\r\n\r\n", appsversion);
+    
+    for (i=0; i < nb_settings; i++)
+    {
+        persistant = false;
+        item = &settings[i];
+        if (theme && ((item->flags&F_THEMESETTING) == 0))
+            continue;
+        type = item->flags&F_T_MASK;
+        if (item->flags&F_LANG_IS_STRING)
+            strcpy(name,item->cfg_string);
+        else 
+        {
+            char *p = strchr(item->conf_file_info,',');
+            if (p)
+            {
+                strncpy(name,item->conf_file_info,p-item->conf_file_info);
+                name[p-item->conf_file_info] = '\0';
+            }
+            else strcpy(name,item->conf_file_info);
+        }
+        
+        char_value = NULL;
 
-#if LCD_DEPTH > 1
-    strncpy((char *)&config_block[i], (char *)global_settings.backdrop_file,
-            MAX_FILENAME);
-    i+= MAX_FILENAME;
-#endif
-#ifdef HAVE_LCD_BITMAP
-    strncpy((char *)&config_block[i], (char *)global_settings.kbd_file,
-            MAX_FILENAME);
-    i+= MAX_FILENAME;
-#endif
+        for (j=0; j<persistant_vars_count; j++)
+        {
+            if (persistant_variables[j].setting == item->setting)
+            {
+                persistant = true;
+                char_value = persistant_variables[j].value;
+                break;
+            }
+        }
 
-    if(save_config_buffer())
-    {
-        lcd_clear_display();
-#ifdef HAVE_REMOTE_LCD
-        lcd_remote_clear_display();
-#endif
-#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();
-#ifdef HAVE_REMOTE_LCD
-        lcd_remote_puts(4, 2, str(LANG_SETTINGS_SAVE_RECORDER));
-        lcd_remote_puts(2, 4, str(LANG_SETTINGS_BATTERY_RECORDER));
-        lcd_remote_update();
-#endif
+        if (persistant == false)
+        {
+            switch (type)
+            {
+                case F_T_INT:
+                    value = *(int*)item->setting;
+                    if ((item->flags&(F_T_CHOICE|F_SYSTEMSETTING|
+                            F_STORERGB|F_T_SOUND|F_STOREREALVALUE)) == 0)
+                        fdprintf(fd,"# %s - min=%d, max=%d, step=%d\r\n",
+                            name,item->values[0],item->values[1],
+                            item->values[2]);
+                    break;
+                case F_T_UINT:
+                    value = *(unsigned int*)item->setting;
+                    if ((item->flags&(F_T_CHOICE|F_SYSTEMSETTING|
+                            F_STORERGB|F_T_SOUND|F_STOREREALVALUE)) == 0)
+                        fdprintf(fd,"# %s - min=%d, max=%d, step=%d\r\n",
+                            name,
+                                item->values[0],item->values[1],item->values[2]);
+                    break;
+                case F_T_BOOL:
+                    char_value = 
+                            (*(bool*)item->setting==true)?
+                                    "on":"off";
+                    fdprintf(fd,"# %s - on, off\r\n",name);
+                    break;
+                case F_T_CHARPTR:
+                case F_T_UCHARPTR:
+                    char_value = (char*)item->setting;
+                    break;
+            }
+            if ((item->flags&F_T_CHOICE) && ((item->flags&F_STOREREALVALUE) == 0))
+            {
+                fdprintf(fd,"# %s - ", name);
+                if (item->flags&F_LANG_STRING)
+                {
+                    for(j=0;j<item->nb_values;j++)
+                        fdprintf(fd,"%s,", item->strings[j]);
+                    fdprintf(fd,"\r\n");
+                    char_value = item->strings[value];
+                }
+                else 
+                {
+                    char *p;
+                    p = strchr(item->conf_file_info,',');
+                    if (p)
+                    {
+                        p++;
+                        fdprintf(fd,"%s\r\n", p);
+                        for(j=0;j<value && *p;j++)
+                        {
+                            while (*p != ',' && *p)
+                                p++;
+                            if (*p) p++; /* skip over the comma */
+                        }
+                        char_value = p;
+                    }
+                    else char_value = item->conf_file_info;
+                }
+            }
+        } /* if (!persistant) */
+        
+#ifdef HAVE_LCD_COLOR
+        if (item->flags&F_STORERGB && char_value==NULL)
+        {
+            fdprintf(fd, "# %s - RRGGBB (hex values)\r\n%s: %02x%02x%02x\r\n",
+                    name,name,
+                    (int)RGB_UNPACK_RED(value),
+                    (int)RGB_UNPACK_GREEN(value),
+                    (int)RGB_UNPACK_BLUE(value));
+        }
+        else 
 #endif
-        sleep(HZ*2);
-        return -1;
-    }
-    return 0;
+        if (char_value == NULL)
+        {
+            fdprintf(fd,"%c%s: %d\r\n",(persistant == true)?'~':'\0',
+                     name, value);
+        }
+        else
+        {
+            char *p = strchr(char_value,',');
+            char text[128];
+            if (p)
+            {
+                strncpy(text,char_value,p-char_value);
+                text[p-char_value] = '\0';
+            }
+            else strcpy(text,char_value);
+            fdprintf(fd,"%c%s: %s\r\n",(persistant == true)?'~':'\0',
+                    name, text);
+        }
+    } /* for(...) */
+    close(fd);
+    return true;
+}
+bool set_bool(const char* string, bool* variable )
+{
+    return set_bool_options(string, variable,
+                            (char *)STR(LANG_SET_BOOL_YES),
+                            (char *)STR(LANG_SET_BOOL_NO),
+                            NULL);
 }
 
-#ifdef HAVE_LCD_BITMAP
-/**
- * Applies the range infos stored in global_settings to
- * the peak meter.
- */
-void settings_apply_pm_range(void)
+/* wrapper to convert from int param to bool param in set_option */
+static void (*boolfunction)(bool);
+void bool_funcwrapper(int value)
 {
-    int pm_min, pm_max;
+    if (value)
+        boolfunction(true);
+    else
+        boolfunction(false);
+}
 
-    /* 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)
+bool set_bool_options(const char* string, bool* variable,
+                      const char* yes_str, int yes_voice,
+                      const char* no_str, int no_voice,
+                      void (*function)(bool))
+{
+    struct opt_items names[] = {
+        {(unsigned char *)no_str, no_voice},
+        {(unsigned char *)yes_str, yes_voice}
+    };
+    bool result;
+
+    boolfunction = function;
+    result = set_option(string, variable, BOOL, names, 2,
+                        function ? bool_funcwrapper : NULL);
+    return result;
+}
+
+void talk_unit(int unit, int value)
+{
+    if (global_settings.talk_menu)
     {
-        /* convert to dBfs * 100          */
-        pm_min = -(((int)global_settings.peak_meter_min) * 100);
-        pm_max = -(((int)global_settings.peak_meter_max) * 100);
+        if (unit < UNIT_LAST)
+        {   /* use the available unit definition */
+            talk_value(value, unit, false);
+        }
+        else
+        {   /* say the number, followed by an arbitrary voice ID */
+            talk_number(value, false);
+            talk_id(unit, true);
+        }
     }
+}
+ 
+int selected_setting; /* Used by the callback */
+void dec_sound_formatter(char *buffer, int buffer_size, int val, const char * unit)
+{
+    val = sound_val2phys(selected_setting, val);
+    char sign = ' ';
+    if(val < 0)
+    {
+        sign = '-';
+        val = (val<0) ? -val : val;
+    }
+    int integer = val / 10;
+    int dec = val % 10;
+    snprintf(buffer, buffer_size, "%c%d.%d %s", sign, integer, dec, unit);
+}
+
+bool set_sound(const unsigned char * string,
+               int* variable,
+               int setting)
+{
+    int talkunit = UNIT_INT;
+    const char* unit = sound_unit(setting);
+    int numdec = sound_numdecimals(setting);
+    int steps = sound_steps(setting);
+    int min = sound_min(setting);
+    int max = sound_max(setting);
+    sound_set_type* sound_callback = sound_get_fn(setting);
+    if (*unit == 'd') /* crude reconstruction */
+        talkunit = UNIT_DB;
+    else if (*unit == '%')
+        talkunit = UNIT_PERCENT;
+    else if (*unit == 'H')
+        talkunit = UNIT_HERTZ;
+    if(!numdec)
+#if CONFIG_CODEC == SWCODEC
+        /* We need to hijack this one and send it off to apps/dsp.c instead of
+                firmware/sound.c */
+                if (setting == SOUND_STEREO_WIDTH)
+                return set_int(string, unit, talkunit,  variable, &stereo_width_set,
+                               steps, min, max, NULL );
     else
-    {
-        /* percent is stored directly -> no conversion */
-        pm_min = global_settings.peak_meter_min;
-        pm_max = global_settings.peak_meter_max;
+#endif   
+                return set_int(string, unit, talkunit,  variable, sound_callback,
+                               steps, min, max, NULL );
+    else
+    {/* Decimal number */
+        selected_setting=setting;
+        return set_int(string, unit, talkunit,  variable, sound_callback,
+                       steps, min, max, &dec_sound_formatter );
     }
-
-    /* apply the range */
-    peak_meter_init_range(global_settings.peak_meter_dbfs, pm_min, pm_max);
 }
-#endif /* HAVE_LCD_BITMAP */
 
-void sound_settings_apply(void)
+ struct value_setting_data {
+     enum optiontype type;
+    int cur_setting; /* current setting as an index in settings list*/
+     /* used for "value" settings.. */
+     int max;
+     int step;
+     int voice_unit;
+     const char * unit;
+     void (*formatter)(char* dest, int dest_length,
+     int variable, const char* unit);
+     /* used for BOOL and "choice" settings */
+     struct opt_items* options;
+ };
+    
+char * value_setting_get_name_cb(int selected_item,void * data, char *buffer)
 {
-    sound_set(SOUND_BASS, global_settings.bass);
-    sound_set(SOUND_TREBLE, global_settings.treble);
-    sound_set(SOUND_BALANCE, global_settings.balance);
-    sound_set(SOUND_VOLUME, global_settings.volume);
-#if CONFIG_CODEC == SWCODEC
-    channels_set(global_settings.channel_config);
-    stereo_width_set(global_settings.stereo_width);
+    struct value_setting_data* cb_data = 
+            (struct value_setting_data*)data;
+    if (cb_data->type == INT && !cb_data->options)
+    {
+        int item = cb_data->max -(selected_item*cb_data->step);
+        if (cb_data->formatter)
+            cb_data->formatter(buffer, MAX_PATH,item,cb_data->unit);
+        else
+            snprintf(buffer, MAX_PATH,"%d %s",item,cb_data->unit);
+    }
+    else strcpy(buffer,P2STR(cb_data->options[selected_item].string));
+    return buffer;
+} 
+void value_setting_icon_cb(int selected_item, void * data, ICON * icon)
+{
+    struct value_setting_data* cb_data = 
+            (struct value_setting_data*)data;
+
+    if (selected_item == cb_data->cur_setting)
+#ifdef HAVE_LCD_BITMAP
+        *icon=bitmap_icons_6x8[Icon_Checkmark];
 #else
-    sound_set(SOUND_CHANNELS, global_settings.channel_config);
-    sound_set(SOUND_STEREO_WIDTH, global_settings.stereo_width);
+        *icon=Icon_Checkmark;
 #endif
-#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
-    sound_set(SOUND_LOUDNESS, global_settings.loudness);
-    sound_set(SOUND_AVC, global_settings.avc);
-    sound_set(SOUND_MDB_STRENGTH, global_settings.mdb_strength);
-    sound_set(SOUND_MDB_HARMONICS, global_settings.mdb_harmonics);
-    sound_set(SOUND_MDB_CENTER, global_settings.mdb_center);
-    sound_set(SOUND_MDB_SHAPE, global_settings.mdb_shape);
-    sound_set(SOUND_MDB_ENABLE, global_settings.mdb_enable);
-    sound_set(SOUND_SUPERBASS, global_settings.superbass);
+    else
+#ifdef HAVE_LCD_BITMAP
+        *icon=0;
+#else
+        *icon=-1;
 #endif
 }
-
-void settings_apply(void)
+void talk_setting(void *global_settings_variable)
 {
-    char buf[64];
-#if CONFIG_CODEC == SWCODEC
-    int i;
-#endif
-
-    sound_settings_apply();
-
-    audio_set_buffer_margin(global_settings.buffer_margin);
-
-#ifdef HAVE_LCD_CONTRAST
-    lcd_set_contrast(global_settings.contrast);
-#endif
-    lcd_scroll_speed(global_settings.scroll_speed);
-#ifdef HAVE_REMOTE_LCD
-    lcd_remote_set_contrast(global_settings.remote_contrast);
-    lcd_remote_set_invert_display(global_settings.remote_invert);
-    lcd_remote_set_flip(global_settings.remote_flip_display);
-    lcd_remote_scroll_speed(global_settings.remote_scroll_speed);
-    lcd_remote_scroll_step(global_settings.remote_scroll_step);
-    lcd_remote_scroll_delay(global_settings.remote_scroll_delay * (HZ/10));
-    lcd_remote_bidir_scroll(global_settings.remote_bidir_limit);
-#ifdef HAVE_REMOTE_LCD_TICKING
-    lcd_remote_emireduce(global_settings.remote_reduce_ticking);
-#endif
-    remote_backlight_set_timeout(global_settings.remote_backlight_timeout);
-#ifdef CONFIG_CHARGING
-    remote_backlight_set_timeout_plugged(global_settings.remote_backlight_timeout_plugged);
-#endif
+    const struct settings_list *setting;
+    int id = -1;
+    if (global_settings.talk_menu == 0)
+        return;
+    setting = find_setting(global_settings_variable);
+    if (setting == NULL)
+        return;
+    if ((setting->flags&F_LANG_IS_STRING) == 0)
+    {
+        id = setting->cfg_lang_id;
+    }
+    if (id != -1)
+        talk_id(id,false);
+}
+    
+ #define type_fromvoidptr(type, value) \
+     (type == INT)? \
+         (int)(*(int*)(value)) \
+     : \
+         (bool)(*(bool*)(value))
+ bool do_set_setting(const unsigned char* string, void *variable,
+                     int nb_items,
+                     struct value_setting_data *cb_data,
+                     void (*function)(int))
+ {
+    int action;
+    bool done = false;
+    struct gui_synclist lists;
+    int oldvalue;
+    bool allow_wrap = true;
+    
+    if (cb_data->type == INT)
+    {
+         oldvalue = *(int*)variable;
+         if (variable == &global_settings.volume)
+             allow_wrap = false;
+    }
+    else oldvalue = *(bool*)variable;
+    
+    gui_synclist_init(&lists,value_setting_get_name_cb,(void*)cb_data,false,1);
+    gui_synclist_set_title(&lists, (char*)string, NOICON);
+    gui_synclist_set_icon_callback(&lists,value_setting_icon_cb);
+    gui_synclist_set_nb_items(&lists,nb_items);
+    gui_synclist_limit_scroll(&lists,true);
+    gui_synclist_select_item(&lists, cb_data->cur_setting);
+    
+    if (global_settings.talk_menu)
+    {
+        if (cb_data->type == INT && !cb_data->options)
+            talk_unit(cb_data->voice_unit, *(int*)variable);
+        else talk_id(cb_data->options[cb_data->cur_setting].voice_id, false);
+    }
+    
+    gui_synclist_draw(&lists);
+    while (!done)
+    {
+        
+        action = get_action(CONTEXT_LIST,TIMEOUT_BLOCK); 
+        if (action == ACTION_NONE)
+            continue;
+        if (gui_synclist_do_button(&lists,action,
+                                   allow_wrap?LIST_WRAP_UNLESS_HELD:LIST_WRAP_OFF))
+        {
+            if (global_settings.talk_menu)
+            {
+                int value;
+                if (cb_data->type == INT && !cb_data->options)
+                {
+                    value = cb_data->max - 
+                            gui_synclist_get_sel_pos(&lists)*cb_data->step;
+                    talk_unit(cb_data->voice_unit, value);
+                }
+                else 
+                {
+                    value = gui_synclist_get_sel_pos(&lists);
+                    talk_id(cb_data->options[value].voice_id, false);
+                }
+            }
+            if (cb_data->type == INT && !cb_data->options)
+                *(int*)variable = cb_data->max - 
+                        gui_synclist_get_sel_pos(&lists)*cb_data->step;
+            else if (cb_data->type == BOOL)
+                *(bool*)variable = gui_synclist_get_sel_pos(&lists) ? true : false;
+            else *(int*)variable = gui_synclist_get_sel_pos(&lists);
+        }  
+        else if (action == ACTION_STD_CANCEL)
+        {
+            gui_syncsplash(HZ/2,true,str(LANG_MENU_SETTING_CANCEL));
+            if (cb_data->type == INT)
+                *(int*)variable = oldvalue;
+            else *(bool*)variable = (bool)oldvalue;
+            done = true;
+        }
+        else if (action == ACTION_STD_OK)
+        {
+            done = true;
+        }
+        else if(default_event_handler(action) == SYS_USB_CONNECTED)
+            return true;
+        gui_syncstatusbar_draw(&statusbars, false);
+        if ( function )
+            function(type_fromvoidptr(cb_data->type,variable));
+    }
+    return false;
+}
+bool set_int(const unsigned char* string,
+             const char* unit,
+             int voice_unit,
+             int* variable,
+             void (*function)(int),
+             int step,
+             int min,
+             int max,
+             void (*formatter)(char*, int, int, const char*) )
+{
+#if CONFIG_KEYPAD != PLAYER_PAD
+    struct value_setting_data data = {
+        INT,(max-*variable)/step,max, step, voice_unit,unit,formatter,NULL };
+    return do_set_setting(string,variable,(max-min)/step + 1,
+                          &data,function);
+#else
+    int count = (max-min)/step + 1;
+    struct value_setting_data data = {
+        INT,count - ((max-*variable)/step),min, -step, voice_unit,unit,formatter,NULL };
+    return do_set_setting(string,variable,count,
+                          &data,function);
+#endif
+}
+
+/* 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(const char* string, void* variable, enum optiontype type,
+                const struct opt_items* options, int numoptions, void (*function)(int))
+{
+    struct value_setting_data data = {
+        type,0,0, 0, 0,NULL,NULL,(struct opt_items*)options };
+    if (type == BOOL)
+        data.cur_setting = *(bool*)variable ? 1 : 0;
+    else data.cur_setting = *(int*)variable;
+    return do_set_setting(string,variable,numoptions,
+                          &data,function);
+}
+
+#define MAX_OPTIONS 64
+bool load_setting_screen(struct settings_list *setting)
+{
+    void* variable;
+    int   temp_var = 0;
+    bool ret = false;
+    if(!setting)
+        return false;
+    variable = setting->setting;
+        
+    switch (setting->flags&F_T_MASK)
+    {
+        case F_T_BOOL:
+            if (setting->flags&F_TEMPVARIABLE)
+            {
+                bool temp_v = *(bool*)setting->setting;
+                ret = set_bool(str(setting->cfg_lang_id),&temp_v);
+                if (temp_v != *(bool*)setting->setting)
+                    *(bool*)setting->setting = temp_v;
+            }
+            else ret = set_bool(str(setting->cfg_lang_id),(bool*)variable);
+            break;
+        case F_T_INT:
+        case F_T_UINT:
+            if (setting->flags&F_T_CHOICE)
+            {
+                static struct opt_items options[MAX_OPTIONS];
+                int i, count = setting->nb_values, j=0;
+                bool store_real = setting->flags&F_STOREREALVALUE;
+                for (i=0; i<count && i<MAX_OPTIONS; i++)
+                {
+                    if (setting->flags&F_LANG_STRING)
+                    {
+                        options[j].string = setting->strings[i];
+                        if (settings->talk_id != NULL)
+                            options[j].voice_id = settings->talk_id[i];
+                    }
+                    else 
+                    {
+                        options[j].string = ID2P(setting->values[i]);
+                        options[j].voice_id = setting->values[i];
+                    }
+                    if (store_real)
+                        i++; /* skip the real val for now */
+                    j++;
+                }
+                if (setting->flags&(F_TEMPVARIABLE|F_STOREREALVALUE))
+                {
+                    variable = (void*)&temp_var;
+                    temp_var = *(int*)setting->setting;
+                    if (store_real) /* find the fake value */
+                    {
+                        for (i=1; i<count; i+=2)
+                        {
+                            if (setting->values[i] == temp_var)
+                            {
+                                temp_var = (i/2);
+                                break;
+                            }
+                        }
+                    }
+                    
+                    ret = set_option(ID2P(setting->cfg_lang_id),variable,INT,
+                                     options, j, (void*)setting->function);
+                    if (store_real) /* convert it back to the real value*/
+                    {
+                        temp_var = setting->values[1+(temp_var*2)];
+                    }
+                    if (*(int*)variable != 
+                          *(int*)setting->setting)
+                        *(int*)setting->setting
+                                = *(int*)variable;
+                }
+                else ret = set_option(str(setting->cfg_lang_id),variable,INT,
+                                      options, i, (void*)setting->function);
+            }
+            else if (setting->flags&F_T_SOUND)
+            {
+                ret = set_sound(str(setting->cfg_lang_id),
+                          (int*)variable,setting->values[0]);
+            }
+            else
+            {
+                if (setting->flags&F_TEMPVARIABLE)
+                {
+                    variable = (void*)temp_var;
+                    *(int*)variable = *(int*)setting->setting;
+                }
+                ret = set_int(str(setting->cfg_lang_id),
+                              str(setting->talk_id[0]),setting->talk_id[0],
+                              (int*)variable,(void*)setting->function,
+                              setting->values[2],
+                              setting->values[0],setting->values[1],
+                              (void*)setting->values[3]);
+                if (setting->flags&F_TEMPVARIABLE)
+                {
+                    if (*(int*)variable != 
+                          *(int*)setting->setting)
+                        *(int*)setting->setting
+                                = *(int*)variable;
+                }
+            }
+            break;
+    }
+    
+    return ret;
+}
+
+#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 sound_settings_apply(void)
+{
+    sound_set(SOUND_BASS, global_settings.bass);
+    sound_set(SOUND_TREBLE, global_settings.treble);
+    sound_set(SOUND_BALANCE, global_settings.balance);
+    sound_set(SOUND_VOLUME, global_settings.volume);
+#if CONFIG_CODEC == SWCODEC
+    channels_set(global_settings.channel_config);
+    stereo_width_set(global_settings.stereo_width);
+#else
+    sound_set(SOUND_CHANNELS, global_settings.channel_config);
+    sound_set(SOUND_STEREO_WIDTH, global_settings.stereo_width);
+#endif
+#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
+    sound_set(SOUND_LOUDNESS, global_settings.loudness);
+    sound_set(SOUND_AVC, global_settings.avc);
+    sound_set(SOUND_MDB_STRENGTH, global_settings.mdb_strength);
+    sound_set(SOUND_MDB_HARMONICS, global_settings.mdb_harmonics);
+    sound_set(SOUND_MDB_CENTER, global_settings.mdb_center);
+    sound_set(SOUND_MDB_SHAPE, global_settings.mdb_shape);
+    sound_set(SOUND_MDB_ENABLE, global_settings.mdb_enable);
+    sound_set(SOUND_SUPERBASS, global_settings.superbass);
+#endif
+}
+
+void settings_apply(bool partial)
+{
+    (void)partial;
+    char buf[MAX_PATH];
+#if CONFIG_CODEC == SWCODEC
+    int i;
+#endif
+
+    sound_settings_apply();
+
+    audio_set_buffer_margin(global_settings.buffer_margin);
+
+#ifdef HAVE_LCD_CONTRAST
+    lcd_set_contrast(global_settings.contrast);
+#endif
+    lcd_scroll_speed(global_settings.scroll_speed);
+#ifdef HAVE_REMOTE_LCD
+    lcd_remote_set_contrast(global_settings.remote_contrast);
+    lcd_remote_set_invert_display(global_settings.remote_invert);
+    lcd_remote_set_flip(global_settings.remote_flip_display);
+    lcd_remote_scroll_speed(global_settings.remote_scroll_speed);
+    lcd_remote_scroll_step(global_settings.remote_scroll_step);
+    lcd_remote_scroll_delay(global_settings.remote_scroll_delay * (HZ/10));
+    lcd_remote_bidir_scroll(global_settings.remote_bidir_limit);
+#ifdef HAVE_REMOTE_LCD_TICKING
+    lcd_remote_emireduce(global_settings.remote_reduce_ticking);
+#endif
+    remote_backlight_set_timeout(global_settings.remote_backlight_timeout);
+#ifdef CONFIG_CHARGING
+    remote_backlight_set_timeout_plugged(global_settings.remote_backlight_timeout_plugged);
+#endif
 #ifdef HAS_REMOTE_BUTTON_HOLD
     remote_backlight_set_on_button_hold(global_settings.remote_backlight_on_button_hold);
 #endif
@@ -1325,890 +1286,3 @@
     enc_global_settings_apply();
 #endif
 }
-
-
-/* helper to load global_settings from a bitfield, as described per table */
-static void load_bit_table(const struct bit_entry* p_table, int count, int bitstart)
-{
-    uint32_t *p_bitfield = (uint32_t *)config_block; /* 32 bit addr. */
-    uint32_t value; /* 32 bit content */
-    int i;
-    int maxbit; /* how many bits are valid in the saved part */
-    const struct bit_entry* p_run = p_table; /* start after the size info */
-    count--; /* first is excluded from loop */
-    maxbit = get_bits(p_bitfield, bitstart, p_table->bit_size);
-    bitstart += p_table->bit_size;
-
-    for (i=0; i<count; i++)
-    {
-        int size;
-        p_run++;
-
-        size = p_run->bit_size & 0x3F; /* mask off abused bits */
-        if (bitstart + size > maxbit)
-            break; /* exit if this is not valid any more in bitfield */
-
-        value = get_bits(p_bitfield, bitstart, size);
-        bitstart += size;
-        if (p_run->bit_size & SIGNED)
-        {   // sign extend the read value
-            unsigned long mask = 0xFFFFFFFF << (size - 1);
-            if (value & mask) /* true if MSB of value is set */
-                value |= mask;
-        }
-
-        /* could do a memcpy, but that would be endian-dependent */
-        switch(p_run->byte_size)
-        {
-        case 1:
-            ((uint8_t *)&global_settings)[p_run->settings_offset] =
-                (unsigned char)value;
-            break;
-        case 2:
-            ((uint16_t *)&global_settings)[p_run->settings_offset/2] =
-                (unsigned short)value;
-            break;
-        case 4:
-            ((uint32_t *)&global_settings)[p_run->settings_offset/4] =
-                (unsigned int)value;
-            break;
-        default:
-            DEBUGF( "load_bit_table: illegal size!\n" );
-            continue;
-        }
-    }
-}
-
-
-/*
- * load settings from disk or RTC RAM
- */
-void settings_load(int which)
-{
-    int i;
-    DEBUGF( "reload_all_settings()\n" );
-
-    /* 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(which))
-    {
-        /* load scalar values from RTC and HD sector, specified via table */
-        if (which & SETTINGS_RTC)
-        {
-            load_bit_table(rtc_bits, sizeof(rtc_bits)/sizeof(rtc_bits[0]), 4*8);
-        }
-        if (which & SETTINGS_HD)
-        {
-            load_bit_table(hd_bits, sizeof(hd_bits)/sizeof(hd_bits[0]),
-                RTC_BLOCK_SIZE*8);
-        }
-
-#ifdef HAVE_RECORDING
-    global_settings.recscreen_on = false;
-#endif
-
-#ifdef HAVE_LCD_CONTRAST
-        if ( global_settings.contrast < MIN_CONTRAST_SETTING ||
-             global_settings.contrast > MAX_CONTRAST_SETTING )
-            global_settings.contrast = lcd_default_contrast();
-#endif
-
-#ifdef HAVE_LCD_REMOTE
-        if (global_settings.remote_contrast < MIN_REMOTE_CONTRAST_SETTING ||
-            global_settings.remote_contrast > MAX_REMOTE_CONTRAST_SETTING )
-            global_settings.remote_contrast = lcd_remote_default_contrast();
-#endif
-        i = 0xb8;
-        strncpy((char *)global_settings.wps_file, (char *)&config_block[i],
-                MAX_FILENAME);
-        i+= MAX_FILENAME;
-        strncpy((char *)global_settings.lang_file, (char *)&config_block[i],
-                MAX_FILENAME);
-        i+= MAX_FILENAME;
-        strncpy((char *)global_settings.font_file, (char *)&config_block[i],
-                MAX_FILENAME);
-        i+= MAX_FILENAME;
-#ifdef HAVE_REMOTE_LCD
-        strncpy((char *)global_settings.rwps_file, (char *)&config_block[i],
-                MAX_FILENAME);
-        i+= MAX_FILENAME;
-#endif
-
-#ifdef CONFIG_TUNER
-        strncpy((char *)global_settings.fmr_file, (char *)&config_block[i],
-                MAX_FILENAME);
-        i+= MAX_FILENAME;
-#endif
-
-#if LCD_DEPTH > 1
-        strncpy((char *)global_settings.backdrop_file, (char *)&config_block[i],
-                MAX_FILENAME);
-        i+= MAX_FILENAME;
-#endif
-#ifdef HAVE_LCD_BITMAP
-        strncpy((char *)global_settings.kbd_file, (char *)&config_block[i],
-                MAX_FILENAME);
-        i+= MAX_FILENAME;
-#endif
-    }
-}
-
-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 != '.') && (ptr != fptr)) {
-        extlen++;
-        ptr--;
-    }
-    if(ptr == fptr) extlen = 0;
-
-    if (strncasecmp(ROCKBOX_DIR, filename ,strlen(ROCKBOX_DIR)) ||
-        (len-extlen > maxlen))
-        return;
-
-    strncpy(setting, fptr, len-extlen);
-    setting[len-extlen]=0;
-
-    settings_save();
-}
-
-/* helper to sort a .cfg file entry into a global_settings member,
-   as described per table. Returns the position if found, else 0. */
-static int load_cfg_table(
-    const struct bit_entry* p_table, /* the table which describes the entries */
-    int count, /* number of entries in the table, including the first */
-    const char* name, /* the item to be searched */
-    const char* value, /* the value which got loaded for that item */
-    int hint) /* position to start looking */
-{
-    int i = hint;
-
-    do
-    {
-        if (p_table[i].cfg_name != NULL && !strcasecmp(name, p_table[i].cfg_name))
-        { /* found */
-            int val = 0;
-            if (p_table[i].cfg_val == NULL)
-            {   /* numerical value, just convert the string */
-                val = atoi(value);
-            }
-#if HAVE_LCD_COLOR
-            else if (!strncasecmp(p_table[i].cfg_val,"rgb",4))
-            {
-                val = hex_to_rgb(value);
-            }
-#endif
-            else
-            {   /* set of string values, find the index */
-                const char* item;
-                const char* run;
-                int len = strlen(value);
-
-                item = run = p_table[i].cfg_val;
-
-                while(1)
-                {
-                    /* count the length of the field */
-                    while (*run != ',' && *run != '\0')
-                        run++;
-
-                    if (!strncasecmp(value, item, MAX(run-item, len)))
-                        break; /* match, exit the search */
-
-                    if (*run == '\0') /* reached the end of the choices */
-                        return i; /* return the position, but don't update */
-
-                    val++; /* count the item up */
-                    run++; /* behind the ',' */
-                    item = run;
-                }
-            }
-
-            /* could do a memcpy, but that would be endian-dependent */
-            switch(p_table[i].byte_size)
-            {
-            case 1:
-                ((unsigned char*)&global_settings)[p_table[i].settings_offset] =
-                    (unsigned char)val;
-                break;
-            case 2:
-                ((unsigned short*)&global_settings)[p_table[i].settings_offset/2] =
-                    (unsigned short)val;
-                break;
-            case 4:
-                ((unsigned int*)&global_settings)[p_table[i].settings_offset/4] =
-                    (unsigned int)val;
-                break;
-            default:
-                DEBUGF( "illegal size!" );
-                continue;
-            }
-
-            return i; /* return the position */
-        }
-
-        i++;
-        if (i==count)
-            i=1; /* wraparound */
-    } while (i != hint); /* back where we started, all searched */
-
-    return 0; /* indicate not found */
-}
-
-
-bool settings_load_config(const 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;
-        const struct bit_entry* table[2] = { rtc_bits, hd_bits };
-        const int ta_size[2] = {
-            sizeof(rtc_bits)/sizeof(rtc_bits[0]),
-            sizeof(hd_bits)/sizeof(hd_bits[0])
-        };
-        int last_table = 0; /* which table was used last round */
-        int last_pos = 1; /* at which position did we succeed */
-        int pos; /* currently returned position */
-
-        if (!settings_parseline(line, &name, &value))
-            continue;
-
-        /* check for the string values */
-        if (!strcasecmp(name, "wps")) {
-#if LCD_DEPTH > 1
-            unload_wps_backdrop();
-#endif
-            int fd2;
-            if ((fd2 = open(value, O_RDONLY)) >= 0) {
-                close(fd2);
-                set_file(value, (char *)global_settings.wps_file, MAX_FILENAME);
-            }
-        }
-#if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1)
-        else if (!strcasecmp(name, "rwps")) {
-            int fd2;
-            if ((fd2 = open(value, O_RDONLY)) >= 0) {
-                close(fd2);
-                set_file(value, (char *)global_settings.rwps_file, MAX_FILENAME);
-            }
-        }
-#endif
-        else if (!strcasecmp(name, "lang")) {
-            if (!lang_load(value))
-            {
-                set_file(value, (char *)global_settings.lang_file, MAX_FILENAME);
-                talk_init(); /* use voice of same language */
-            }
-        }
-#ifdef CONFIG_TUNER
-        else if (!strcasecmp(name, "fmr")) {
-            set_file(value, global_settings.fmr_file, MAX_FILENAME);
-        }
-#endif
-#ifdef HAVE_LCD_BITMAP
-        else if (!strcasecmp(name, "font")) {
-            if (font_load(value))
-                set_file(value, (char *)global_settings.font_file, MAX_FILENAME);
-        }
-#endif
-#if LCD_DEPTH > 1
-        else if (!strcasecmp(name, "backdrop")) {
-            if (load_main_backdrop(value)) {
-                set_file(value, (char *)global_settings.backdrop_file, MAX_FILENAME);
-                show_main_backdrop();
-            }
-        }
-#endif
-#ifdef HAVE_LCD_BITMAP
-        else if (!strcasecmp(name, "keyboard")) {
-            if (!load_kbd(value))
-                set_file(value, (char *)global_settings.kbd_file, MAX_FILENAME);
-        }
-#endif
-
-
-        /* check for scalar values, using the two tables */
-        pos = load_cfg_table(table[last_table], ta_size[last_table],
-            name, value, last_pos);
-        if (pos) /* success */
-        {
-            last_pos = pos; /* remember as a position hint for next round */
-            continue;
-        }
-
-        last_table = 1-last_table; /* try other table */
-        last_pos = 1; /* search from start */
-        pos = load_cfg_table(table[last_table], ta_size[last_table],
-            name, value, last_pos);
-        if (pos) /* success */
-        {
-            last_pos = pos; /* remember as a position hint for next round */
-            continue;
-        }
-    }
-
-    close(fd);
-    settings_apply();
-    settings_save();
-    return true;
-}
-
-
-/* helper to save content of global_settings into a file,
-   as described per table */
-static void save_cfg_table(const struct bit_entry* p_table, int count, int fd)
-{
-    long value; /* 32 bit content */
-    int i;
-    const struct bit_entry* p_run = p_table; /* start after the size info */
-    count--; /* first is excluded from loop */
-
-    for (i=0; i<count; i++)
-    {
-        p_run++;
-
-        if (p_run->cfg_name == NULL)
-            continue; /* this value is not to be saved */
-
-        /* could do a memcpy, but that would be endian-dependent */
-        switch(p_run->byte_size)
-        {
-        case 1:
-            if (p_run->bit_size & SIGNED) /* signed? */
-                value = ((char*)&global_settings)[p_run->settings_offset];
-            else
-                value = ((unsigned char*)&global_settings)[p_run->settings_offset];
-            break;
-        case 2:
-            if (p_run->bit_size & SIGNED) /* signed? */
-                value = ((short*)&global_settings)[p_run->settings_offset/2];
-            else
-                value = ((unsigned short*)&global_settings)[p_run->settings_offset/2];
-            break;
-        case 4:
-            value = ((unsigned int*)&global_settings)[p_run->settings_offset/4];
-            break;
-        default:
-            DEBUGF( "illegal size!" );
-            continue;
-        }
-
-        if (p_run->cfg_val == NULL) /* write as number */
-        {
-            fdprintf(fd, "%s: %ld\r\n", p_run->cfg_name, value);
-        }
-#ifdef HAVE_LCD_COLOR
-        else if (!strcasecmp(p_run->cfg_val, "rgb"))
-        {
-            fdprintf(fd, "%s: %02x%02x%02x\r\n", p_run->cfg_name,
-                                                 (int)RGB_UNPACK_RED(value),
-                                                 (int)RGB_UNPACK_GREEN(value),
-                                                 (int)RGB_UNPACK_BLUE(value));
-        }
-#endif
-        else /* write as item */
-        {
-            const char* p = p_run->cfg_val;
-
-            fdprintf(fd, "%s: ", p_run->cfg_name);
-
-            while(value >= 0)
-            {
-                char c = *p++; /* currently processed char */
-                if (c == ',') /* separator */
-                    value--;
-                else if (c == '\0') /* end of string */
-                    break; /* not found */
-                else if (value == 0) /* the right place */
-                    write(fd, &c, 1); /* char by char, this is lame, OK */
-            }
-
-            fdprintf(fd, "\r\n");
-            if (p_run->cfg_val != off_on) /* explaination for non-bool */
-                fdprintf(fd, "# (possible values: %s)\r\n", p_run->cfg_val);
-        }
-    }
-}
-
-bool settings_save_config(void)
-{
-    int fd;
-    char filename[MAX_PATH];
-
-    create_numbered_filename(filename, ROCKBOX_DIR, "config", ".cfg", 2
-                             IF_CNFN_NUM_(, NULL));
-
-    /* allow user to modify filename */
-    while (true) {
-        if (!kbd_input(filename, sizeof filename)) {
-            fd = creat(filename, O_WRONLY);
-            if (fd < 0)
-                gui_syncsplash(HZ, true, str(LANG_FAILED));
-            else
-                break;
-        }
-        else {
-            gui_syncsplash(HZ, true, str(LANG_MENU_SETTING_CANCEL));
-            return false;
-        }
-    }
-
-    fdprintf(fd, "# .cfg file created by rockbox %s - "
-                 "http://www.rockbox.org\r\n#\r\n#\r\n# wps / rwps / language"
-                 " / font / fmpreset / backdrop \r\n#\r\n", appsversion);
-
-    if (global_settings.wps_file[0] != 0)
-        fdprintf(fd, "wps: %s/%s.wps\r\n", WPS_DIR,
-                 global_settings.wps_file);
-
-#ifdef HAVE_REMOTE_LCD
-    if (global_settings.rwps_file[0] != 0)
-        fdprintf(fd, "rwps: %s/%s.rwps\r\n", WPS_DIR,
-                 global_settings.rwps_file);
-#endif
-
-    if (global_settings.lang_file[0] != 0)
-        fdprintf(fd, "lang: %s/%s.lng\r\n", LANG_DIR,
-                 global_settings.lang_file);
-
-#ifdef HAVE_LCD_BITMAP
-    if (global_settings.font_file[0] != 0)
-        fdprintf(fd, "font: %s/%s.fnt\r\n", FONT_DIR,
-                 global_settings.font_file);
-#endif
-
-#if LCD_DEPTH > 1
-    if (global_settings.backdrop_file[0] != 0)
-        fdprintf(fd, "backdrop: %s/%s.bmp\r\n", BACKDROP_DIR,
-                 global_settings.backdrop_file);
-#endif
-
-#ifdef CONFIG_TUNER
-    if (global_settings.fmr_file[0] != 0)
-        fdprintf(fd, "fmr: %s/%s.fmr\r\n", FMPRESET_PATH,
-                 global_settings.fmr_file);
-#endif
-
-#ifdef HAVE_LCD_BITMAP
-    if (global_settings.kbd_file[0] != 0)
-        fdprintf(fd, "keyboard: %s/%s.kbd\r\n", ROCKBOX_DIR,
-                 global_settings.kbd_file);
-#endif
-
-    /* here's the action: write values to file, specified via table */
-    save_cfg_table(rtc_bits, sizeof(rtc_bits)/sizeof(rtc_bits[0]), fd);
-    save_cfg_table(hd_bits, sizeof(hd_bits)/sizeof(hd_bits[0]), fd);
-
-    close(fd);
-
-    gui_syncsplash(HZ, true, str(LANG_SETTINGS_SAVED));
-    return true;
-}
-
-
-/* helper to load defaults from table into global_settings members */
-static void default_table(const struct bit_entry* p_table, int count)
-{
-    int i;
-
-    for (i=1; i<count; i++) /* exclude the first, the size placeholder */
-    {
-        /* could do a memcpy, but that would be endian-dependent */
-        switch(p_table[i].byte_size)
-        {
-        case 1:
-            ((unsigned char*)&global_settings)[p_table[i].settings_offset] =
-                (unsigned char)p_table[i].default_val;
-            break;
-        case 2:
-            ((unsigned short*)&global_settings)[p_table[i].settings_offset/2] =
-                (unsigned short)p_table[i].default_val;
-            break;
-        case 4:
-            ((unsigned int*)&global_settings)[p_table[i].settings_offset/4] =
-                (unsigned int)p_table[i].default_val;
-            break;
-        default:
-            DEBUGF( "illegal size!" );
-            continue;
-        }
-    }
-}
-
-
-/*
- * reset all settings to their default value
- */
-void settings_reset(void) {
-
-    DEBUGF( "settings_reset()\n" );
-
-    /* read defaults from table(s) into global_settings */
-    default_table(rtc_bits, sizeof(rtc_bits)/sizeof(rtc_bits[0]));
-    default_table(hd_bits, sizeof(hd_bits)/sizeof(hd_bits[0]));
-
-    /* do some special cases not covered by table */
-    global_settings.volume      = sound_default(SOUND_VOLUME);
-    global_settings.balance     = sound_default(SOUND_BALANCE);
-    global_settings.bass        = sound_default(SOUND_BASS);
-    global_settings.treble      = sound_default(SOUND_TREBLE);
-    global_settings.channel_config = sound_default(SOUND_CHANNELS);
-    global_settings.stereo_width = sound_default(SOUND_STEREO_WIDTH);
-#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
-    global_settings.loudness    = sound_default(SOUND_LOUDNESS);
-    global_settings.avc         = sound_default(SOUND_AVC);
-    global_settings.mdb_strength = sound_default(SOUND_MDB_STRENGTH);
-    global_settings.mdb_harmonics = sound_default(SOUND_MDB_HARMONICS);
-    global_settings.mdb_center = sound_default(SOUND_MDB_CENTER);
-    global_settings.mdb_shape = sound_default(SOUND_MDB_SHAPE);
-    global_settings.mdb_enable = sound_default(SOUND_MDB_ENABLE);
-    global_settings.superbass = sound_default(SOUND_SUPERBASS);
-#endif
-#ifdef HAVE_LCD_CONTRAST 
-    global_settings.contrast = lcd_default_contrast();
-#endif
-#ifdef HAVE_LCD_REMOTE
-    global_settings.remote_contrast = lcd_remote_default_contrast();
-#endif
-
-#ifdef CONFIG_TUNER
-    global_settings.fmr_file[0] = '\0';
-#endif
-    global_settings.wps_file[0] = '\0';
-#ifdef HAVE_REMOTE_LCD
-    global_settings.rwps_file[0] = '\0';
-#endif
-    global_settings.font_file[0] = '\0';
-    global_settings.lang_file[0] = '\0';
-#if LCD_DEPTH > 1
-    global_settings.backdrop_file[0] = '\0';
-#endif
-#ifdef HAVE_LCD_COLOR
-    global_settings.fg_color = LCD_DEFAULT_FG;
-    global_settings.bg_color = LCD_DEFAULT_BG;
-#endif
-#ifdef HAVE_LCD_BITMAP
-    global_settings.kbd_file[0] = '\0';
-#endif
-    global_settings.hold_lr_for_scroll_in_list = true;
-
-#if defined (HAVE_RECORDING) && CONFIG_CODEC == SWCODEC
-    enc_global_settings_reset();
-#endif
-}
-
-bool set_bool(const char* string, bool* variable )
-{
-    return set_bool_options(string, variable,
-                            (char *)STR(LANG_SET_BOOL_YES),
-                            (char *)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(const char* string, bool* variable,
-                      const char* yes_str, int yes_voice,
-                      const char* no_str, int no_voice,
-                      void (*function)(bool))
-{
-    struct opt_items names[] = {
-        {(unsigned char *)no_str, no_voice},
-        {(unsigned char *)yes_str, yes_voice}
-    };
-    bool result;
-
-    boolfunction = function;
-    result = set_option(string, variable, BOOL, names, 2,
-                        function ? bool_funcwrapper : NULL);
-    return result;
-}
-
-void talk_unit(int unit, int value)
-{
-    if (global_settings.talk_menu)
-    {
-        if (unit < UNIT_LAST)
-        {   /* use the available unit definition */
-            talk_value(value, unit, false);
-        }
-        else
-        {   /* say the number, followed by an arbitrary voice ID */
-            talk_number(value, false);
-            talk_id(unit, true);
-        }
-    }
-}
-
-struct value_setting_data {
-    enum optiontype type;
-    /* used for "value" settings.. */
-    int max;
-    int step;
-    int voice_unit;
-    const char * unit;
-    void (*formatter)(char* dest, int dest_length,
-                          int variable, const char* unit);
-    /* used for BOOL and "choice" settings */
-    struct opt_items* options;    
-};
-    
-char * value_setting_get_name_cb(int selected_item,void * data, char *buffer)
-{
-    struct value_setting_data* cb_data = 
-            (struct value_setting_data*)data;
-    if (cb_data->type == INT && !cb_data->options)
-    {
-        int item = cb_data->max -(selected_item*cb_data->step);
-        if (cb_data->formatter)
-            cb_data->formatter(buffer, MAX_PATH,item,cb_data->unit);
-        else
-            snprintf(buffer, MAX_PATH,"%d %s",item,cb_data->unit);
-    }
-    else strcpy(buffer,P2STR(cb_data->options[selected_item].string));
-    return buffer;
-} 
-#define type_fromvoidptr(type, value) \
-    (type == INT)? \
-        (int)(*(int*)(value)) \
-    : \
-        (bool)(*(bool*)(value))
-bool do_set_setting(const unsigned char* string, void *variable,
-                    int nb_items,int selected, 
-                    struct value_setting_data *cb_data,
-                    void (*function)(int))
-{
-    int action;
-    bool done = false;
-    struct gui_synclist lists;
-    int oldvalue;
-    bool allow_wrap = true;
-    
-    if (cb_data->type == INT)
-    {
-         oldvalue = *(int*)variable;
-         if (variable == &global_settings.volume)
-             allow_wrap = false;
-    }
-    else oldvalue = *(bool*)variable;
-    
-    gui_synclist_init(&lists,value_setting_get_name_cb,(void*)cb_data,false,1);
-    gui_synclist_set_title(&lists, (char*)string, NOICON);
-    gui_synclist_set_icon_callback(&lists,NULL);
-    gui_synclist_set_nb_items(&lists,nb_items);
-    gui_synclist_limit_scroll(&lists,true);
-    gui_synclist_select_item(&lists, selected);
-    
-    if (global_settings.talk_menu)
-    {
-        if (cb_data->type == INT && !cb_data->options)
-            talk_unit(cb_data->voice_unit, *(int*)variable);
-        else talk_id(cb_data->options[selected].voice_id, false);
-    }
-    
-    gui_synclist_draw(&lists);
-    while (!done)
-    {
-        
-        action = get_action(CONTEXT_LIST,TIMEOUT_BLOCK); 
-        if (action == ACTION_NONE)
-            continue;
-        if (gui_synclist_do_button(&lists,action,
-                                   allow_wrap?LIST_WRAP_UNLESS_HELD:LIST_WRAP_OFF))
-        {
-            if (global_settings.talk_menu)
-            {
-                int value;
-                if (cb_data->type == INT && !cb_data->options)
-                {
-                    value = cb_data->max - 
-                            gui_synclist_get_sel_pos(&lists)*cb_data->step;
-                    talk_unit(cb_data->voice_unit, value);
-                }
-                else 
-                {
-                    value = gui_synclist_get_sel_pos(&lists);
-                    talk_id(cb_data->options[value].voice_id, false);
-                }
-            }
-            if (cb_data->type == INT && !cb_data->options)
-                *(int*)variable = cb_data->max - 
-                        gui_synclist_get_sel_pos(&lists)*cb_data->step;
-            else if (cb_data->type == BOOL)
-                *(bool*)variable = gui_synclist_get_sel_pos(&lists) ? true : false;
-            else *(int*)variable = gui_synclist_get_sel_pos(&lists);
-        }  
-        else if (action == ACTION_STD_CANCEL)
-        {
-            gui_syncsplash(HZ/2,true,str(LANG_MENU_SETTING_CANCEL));
-            if (cb_data->type == INT)
-                *(int*)variable = oldvalue;
-            else *(bool*)variable = (bool)oldvalue;
-            done = true;
-        }
-        else if (action == ACTION_STD_OK)
-        {
-            done = true;
-        }
-        else if(default_event_handler(action) == SYS_USB_CONNECTED)
-            return true;
-        gui_syncstatusbar_draw(&statusbars, false);
-        if ( function )
-            function(type_fromvoidptr(cb_data->type,variable));
-    }
-    return false;
-}
-bool set_int(const unsigned char* string,
-             const char* unit,
-             int voice_unit,
-             int* variable,
-             void (*function)(int),
-             int step,
-             int min,
-             int max,
-             void (*formatter)(char*, int, int, const char*) )
-{
-#if CONFIG_KEYPAD != PLAYER_PAD
-    struct value_setting_data data = {
-        INT,max, step, voice_unit,unit,formatter,NULL };
-    return do_set_setting(string,variable,(max-min)/step + 1,
-                          (max-*variable)/step, &data,function);
-#else
-    int count = (max-min)/step + 1;
-    struct value_setting_data data = {
-        INT,min, -step, voice_unit,unit,formatter,NULL };
-    return do_set_setting(string,variable,count,
-                          count - ((max-*variable)/step), &data,function);
-#endif
-}
-
-/* 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(const char* string, void* variable, enum optiontype type,
-                const struct opt_items* options, int numoptions, void (*function)(int))
-{
-    struct value_setting_data data = {
-        type,0, 0, 0,NULL,NULL,(struct opt_items*)options };
-    int selected;
-    if (type == BOOL)
-        selected = *(bool*)variable ? 1 : 0;
-    else selected = *(int*)variable;
-    return do_set_setting(string,variable,numoptions,
-                          selected, &data,function);
-}
-
-#ifdef HAVE_RECORDING
-/* This array holds the record timer interval lengths, in seconds */
-static const unsigned long rec_timer_seconds[] =
-{
-    0,        /* 0 means OFF */
-    5*60,     /* 00:05 */
-    10*60,    /* 00:10 */
-    15*60,    /* 00:15 */
-    30*60,    /* 00:30 */
-    60*60,    /* 01:00 */
-    74*60,    /* 74:00 */
-    80*60,    /* 80:00 */
-    2*60*60,  /* 02:00 */
-    4*60*60,  /* 04:00 */
-    6*60*60,  /* 06:00 */
-    8*60*60,  /* 08:00 */
-    10L*60*60, /* 10:00 */
-    12L*60*60, /* 12:00 */
-    18L*60*60, /* 18:00 */
-    24L*60*60  /* 24:00 */
-};
-
-unsigned int rec_timesplit_seconds(void)
-{
-    return rec_timer_seconds[global_settings.rec_timesplit];
-}
-
-/* This array holds the record size interval lengths, in bytes */
-static const unsigned long rec_size_bytes[] =
-{
-    0,               /* 0 means OFF */
-    5*1024*1024,     /* 5MB */
-    10*1024*1024,    /* 10MB */
-    15*1024*1024,    /* 15MB */
-    32*1024*1024,    /* 32MB */
-    64*1024*1024,    /* 64MB */
-    75*1024*1024,    /* 75MB */
-    100*1024*1024,   /* 100MB */
-    128*1024*1024,   /* 128MB */
-    256*1024*1024,   /* 256MB */
-    512*1024*1024,   /* 512MB */
-    650*1024*1024,   /* 650MB */
-    700*1024*1024,   /* 700MB */
-    1024*1024*1024,  /* 1GB */
-    1536*1024*1024,  /* 1.5GB */
-    1792*1024*1024,  /* 1.75GB  */
-};
-
-unsigned long rec_sizesplit_bytes(void)
-{
-    return rec_size_bytes[global_settings.rec_sizesplit];
-}
-/*
- * Time strings used for the trigger durations.
- * Keep synchronous to trigger_times in settings_apply_trigger
- */
-const char * const trig_durations[TRIG_DURATION_COUNT] =
-{
-    "0s", "1s", "2s", "5s",
-    "10s", "15s", "20s", "25s", "30s",
-    "1min", "2min", "5min", "10min"
-};
-
-void settings_apply_trigger(void)
-{
-    /* Keep synchronous to trig_durations and trig_durations_conf*/
-    static const long trigger_times[TRIG_DURATION_COUNT] = {
-        0, HZ, 2*HZ, 5*HZ,
-        10*HZ, 15*HZ, 20*HZ, 25*HZ, 30*HZ,
-        60*HZ, 2*60*HZ, 5*60*HZ, 10*60*HZ
-    };
-
-    peak_meter_define_trigger(
-        global_settings.rec_start_thres,
-        trigger_times[global_settings.rec_start_duration],
-        MIN(trigger_times[global_settings.rec_start_duration] / 2, 2*HZ),
-        global_settings.rec_stop_thres,
-        trigger_times[global_settings.rec_stop_postrec],
-        trigger_times[global_settings.rec_stop_gap]
-    );
-}
-#endif
Index: apps/settings.h
===================================================================
RCS file: /cvsroot/rockbox/apps/settings.h,v
retrieving revision 1.254
diff -u -r1.254 settings.h
--- apps/settings.h	13 Nov 2006 00:45:20 -0000	1.254
+++ apps/settings.h	15 Nov 2006 08:00:24 -0000
@@ -28,6 +28,7 @@
 #include "timefuncs.h"
 #include "tagcache.h"
 #include "button.h"
+#include "settings_list.h"
 
 #if CONFIG_CODEC == SWCODEC
 #include "audio.h"
@@ -54,9 +55,11 @@
 #define REC_BASE_DIR "/recordings"
 #define EQS_DIR     ROCKBOX_DIR "/eqs"
 #define CODECS_DIR  ROCKBOX_DIR"/codecs"
+#define ROCKBOX_CONFIGFILE ROCKBOX_DIR "/config.cfg"
 
 #define MAX_FILENAME 20
 
+
 /* data structures */
 
 #define BOOKMARK_NO  0
@@ -346,7 +349,7 @@
 
     bool   line_in;       /* false=off, true=active */
 
-    bool id3_v1_first;    /* true = ID3V1 has prio over ID3V2 tag */
+    int id3_v1_first;    /* 0 = ID3V1 has prio over ID3V2 tag */
 
     /* playlist viewer settings */
     bool playlist_viewer_icons; /* display icons on viewer */
@@ -549,12 +552,12 @@
 void settings_load(int which);
 void settings_reset(void);
 void sound_settings_apply(void);
-void settings_apply(void);
+void settings_apply(bool partial);
 void settings_apply_pm_range(void);
 void settings_display(void);
 
 bool settings_load_config(const char* file);
-bool settings_save_config(void);
+bool settings_save_config(const char* filename,bool theme);
 bool set_bool_options(const char* string, bool* variable,
                       const char* yes_str, int yes_voice,
                       const char* no_str, int no_voice,
@@ -571,9 +574,9 @@
 int read_line(int fd, char* buffer, int buffer_size);
 void set_file(char* filename, char* setting, int maxlen);
 
-unsigned int rec_timesplit_seconds(void);
-unsigned long rec_sizesplit_bytes(void);
-void settings_apply_trigger(void);
+bool load_setting_screen(struct settings_list *setting);
+const struct settings_list *find_setting(void* variable);
+void talk_setting(void *global_settings_variable);
 
 /* global settings */
 extern struct user_settings global_settings;
Index: apps/settings_list.c
===================================================================
RCS file: apps/settings_list.c
diff -N apps/settings_list.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ apps/settings_list.c	15 Nov 2006 08:00:25 -0000
@@ -0,0 +1,956 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id:  $
+ *
+ * Copyright (C) 2006 Jonathan Gordon
+ *
+ * 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 <stdbool.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include "config.h"
+#include "lang.h"
+#include "settings.h"
+#include "sound.h"
+#include "stdio.h"
+#include "lcd.h"
+#include "talk.h"
+#include "settings_list.h"
+#include "splash.h"
+#include "kernel.h"
+
+/* files needed for the variaous option callbacks*/
+#include "playback.h"
+#include "eq_menu.h"
+#include "statusbar.h"
+#include "settings.h"
+
+/* helpful macros for hopefully this file only! */
+#define GS(a) &global_settings.a
+#define _INT(...) {.values = (int[]){__VA_ARGS__}}
+#define _STR(...) {.strings = (char*[]){__VA_ARGS__}}
+#define _TALKID(...) (int[]){__VA_ARGS__}
+#define _REALVAL(s,v) (void*)s,(void*)v
+
+#define SOUND_ITEM(flags,var,name,setting, cfg)                       \
+    {flags|F_T_INT|F_T_SOUND, GS(var), {0}, {.cfg_lang_id = name}, 1, \
+    _INT(setting), NULL, NULL, cfg }
+    
+#define BOOL_ITEM(flags,var,name,default,cb, cfg)                     \
+    {flags|F_T_BOOL, GS(var), {.bool_ = default},                     \
+    {.cfg_lang_id = name}, 0,{NULL}, NULL, cb, cfg }
+    
+#define INT_ITEM(flags,var,name,default,min,max,step,unit,            \
+    cb,formatter, cfg) {flags|F_T_INT, GS(var), {.int_ = default},    \
+    {name}, 3,_INT(min,max,step,(int)formatter), _TALKID(unit),       \
+    cb, cfg }
+    
+#define SYSTEM_ITEM(type,var,default, cb)                             \
+    {type|F_SYSTEMSETTING|F_LANG_IS_STRING, GS(var), {default},       \
+    {.cfg_string = #var}, 0,{NULL}, NULL, cb ,NULL}
+    
+#define CHOICE_ITEM(flags,var,name, cfg,default, cb,count,...)        \
+    {flags|F_T_INT|F_T_CHOICE, GS(var), {.int_ = default}, {name},    \
+    count, _INT(__VA_ARGS__),NULL, cb, cfg }
+#define STRINGCHOICE_ITEM(flags,var,name,cfg,default,count,           \
+        Strings,talks, cb) {flags|F_T_INT|F_T_CHOICE|F_LANG_STRING,   \
+        GS(var), {.int_ = default}, {name},count, Strings, talks,     \
+        cb, cfg }
+#define STRING_ITEM(flags,var,name,default,cb)                        \
+    {flags|F_T_CHARPTR|F_LANG_IS_STRING, GS(var),                     \
+    {.charptr = default}, {.cfg_string = name},0, {NULL}, NULL,       \
+    cb, name}
+
+
+#if defined(CONFIG_BACKLIGHT)
+/* use me when realvalues are impleneted for backlight and such
+static const char *backlight_times_strings[] = {
+        _REALVAL("on",-1),_REALVAL("off",0),_REALVAL("1",1),_REALVAL("2",2),
+        _REALVAL("3",3),_REALVAL("4",4),_REALVAL("5",5),_REALVAL("6",6),
+        _REALVAL("7",7),_REALVAL("8",8),_REALVAL("9",9),_REALVAL("10",10),
+        _REALVAL("15",15),_REALVAL("20",20),_REALVAL("25",25),_REALVAL("30",30),
+        _REALVAL("45",45),_REALVAL("60",60),_REALVAL("90",90)};
+*/
+static const char *backlight_times_strings[] = {
+                      "off","on","1","2","3","4","5","6","7","8",
+                      "9","10","15","20","25","30","45","60","90"};
+static const int  backlight_times_talks[] =  {
+                LANG_OFF,LANG_ON,TALK_ID(1,UNIT_SEC),TALK_ID(2,UNIT_SEC),
+                TALK_ID(3,UNIT_SEC),TALK_ID(4,UNIT_SEC),TALK_ID(5,UNIT_SEC),
+                TALK_ID(6,UNIT_SEC),TALK_ID(7,UNIT_SEC),TALK_ID(8,UNIT_SEC),
+                TALK_ID(9,UNIT_SEC),TALK_ID(10,UNIT_SEC),TALK_ID(15,UNIT_SEC),
+                TALK_ID(20,UNIT_SEC),TALK_ID(25,UNIT_SEC),TALK_ID(30,UNIT_SEC),
+                TALK_ID(45,UNIT_SEC),TALK_ID(60,UNIT_SEC),TALK_ID(90,UNIT_SEC)};
+#endif
+#ifdef HAVE_RECORDING
+/* keep synchronous to trig_durations and
+   trigger_times in settings_apply_trigger */
+static const char *trig_durations_strings[] = 
+    {"0s","1s","2s","5s","10s","15s","20s",
+    "25s","30s","1min","2min","5min","10min"};
+static const int  trig_durations_talks[] =  {
+    TALK_ID(0,UNIT_SEC),TALK_ID(1,UNIT_SEC),
+    TALK_ID(2,UNIT_SEC),TALK_ID(5,UNIT_SEC),
+    TALK_ID(10,UNIT_SEC),TALK_ID(15,UNIT_SEC),
+    TALK_ID(20,UNIT_SEC),TALK_ID(25,UNIT_SEC),
+    TALK_ID(30,UNIT_SEC),TALK_ID(1,UNIT_MIN),
+    TALK_ID(2,UNIT_MIN),TALK_ID(5,UNIT_MIN),TALK_ID(10,UNIT_MIN)};
+#endif
+
+/* callback functions needed for the settings */
+#if CONFIG_CODEC == SWCODEC
+    /* scrossfeed */
+static void crossfeed_format(char* buffer, int buffer_size, int value,
+                                 const char* unit)
+{
+    snprintf(buffer, buffer_size, "%s%d.%d %s", value == 0 ? " " : "-",
+             value / 10, value % 10, unit);
+}
+#endif /* CONFIG_CODEC == SWCODEC */
+#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
+static void set_mdb_enable(bool value)
+{
+    sound_set_mdb_enable((int)value);
+}
+#endif
+#include "debug.h"
+#ifdef HAVE_DIRCACHE
+static void dircache_cb(bool value)
+{
+    DEBUGF("hi!\n");
+    (void)value;
+    if (!dircache_is_enabled() && global_settings.dircache)
+        gui_syncsplash(HZ, true, str(LANG_DIRCACHE_REBOOT));
+}
+#endif /* HAVE_DIRCACHE */
+
+
+
+
+const struct settings_list  settings[] = {
+    /* sound */
+    SOUND_ITEM(0,volume,LANG_VOLUME,SOUND_VOLUME,"volume"),
+    SOUND_ITEM(0,balance,LANG_BALANCE,SOUND_BALANCE,"balance"),
+    SOUND_ITEM(0,bass,LANG_BASS,SOUND_BASS,"bass"),
+    SOUND_ITEM(0,treble,LANG_TREBLE,SOUND_TREBLE,"treble"),
+#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
+    SOUND_ITEM(0,loudness,LANG_LOUDNESS,SOUND_LOUDNESS,"loudness"),
+    STRINGCHOICE_ITEM(0,avc,LANG_AUTOVOL,"auto volume",0,5,
+                      _STR("off","20ms","2","4","8"),
+                      _TALKID(LANG_OFF,TALK_ID(20, UNIT_MS),TALK_ID(2, UNIT_SEC),
+                              TALK_ID(4, UNIT_SEC),TALK_ID(8, UNIT_SEC)), NULL),
+    BOOL_ITEM(0,superbass,LANG_SUPERBASS,false, NULL,"superbass"),
+#endif
+    CHOICE_ITEM(0,channel_config,LANG_CHANNEL,
+                "channels,stereo,mono,custom,mono left,mono right,karaoke",
+                0, NULL,6,
+                LANG_CHANNEL_STEREO,LANG_CHANNEL_MONO,
+                LANG_CHANNEL_CUSTOM,LANG_CHANNEL_LEFT,
+                LANG_CHANNEL_RIGHT,LANG_CHANNEL_KARAOKE),
+    SOUND_ITEM(0,stereo_width,LANG_STEREO_WIDTH,SOUND_STEREO_WIDTH,"stereo width"),
+    
+    /* playback */
+    BOOL_ITEM(0,resume,LANG_RESUME,false, NULL, "resume"),
+    BOOL_ITEM(0,playlist_shuffle,LANG_SHUFFLE,false, NULL, "shuffle"),
+    SYSTEM_ITEM(F_T_INT,resume_index,-1, NULL),
+    SYSTEM_ITEM(F_T_INT,resume_first_index,0, NULL),
+    SYSTEM_ITEM(F_T_INT,resume_offset,-1, NULL),
+    SYSTEM_ITEM(F_T_INT,resume_seed,-1, NULL),
+    CHOICE_ITEM(0,repeat_mode,LANG_REPEAT, "repeat,off,all,one,shuffle,ab",
+                REPEAT_ALL, NULL,NUM_REPEAT_MODES,
+        LANG_OFF,LANG_REPEAT_ALL,LANG_REPEAT_ONE,LANG_SHUFFLE,LANG_REPEAT_AB),
+    
+    /* LCD */
+#ifdef HAVE_LCD_CONTRAST
+    INT_ITEM(0,contrast,LANG_CONTRAST,DEFAULT_CONTRAST_SETTING,
+             MIN_CONTRAST_SETTING,MAX_CONTRAST_SETTING,1,UNIT_INT,
+             NULL, NULL, "contrast"),
+#endif
+#ifdef CONFIG_BACKLIGHT
+    STRINGCHOICE_ITEM(0,backlight_timeout,LANG_BACKLIGHT,
+                      "backlight timeout",
+                      6,sizeof(backlight_times_strings)/
+                              sizeof(*backlight_times_strings),
+                      {.strings = (char **)backlight_times_strings},
+                      (int*)backlight_times_talks, NULL),
+#ifdef CONFIG_CHARGING
+    STRINGCHOICE_ITEM(0,backlight_timeout_plugged,
+                      LANG_BACKLIGHT_ON_WHEN_CHARGING,
+                      "backlight timeout plugged",11,
+                  sizeof(backlight_times_strings)/
+                          sizeof(*backlight_times_strings),
+                  {.strings = (char **)backlight_times_strings},
+                  (int*)backlight_times_talks, NULL),
+#endif
+#endif /* CONFIG_BACKLIGHT */
+    
+    /* display */
+#ifdef HAVE_LCD_BITMAP
+    CHOICE_ITEM(0,invert,LANG_INVERT, "invert,off,on",
+                0, NULL,2,LANG_INVERT_LCD_NORMAL,LANG_INVERT_LCD_INVERSE),
+    BOOL_ITEM(0,flip_display,LANG_FLIP_DISPLAY,false, NULL, "flip display"),
+    BOOL_ITEM(0,invert_cursor,LANG_INVERT_CURSOR,true, NULL, "invert cursor"),
+    BOOL_ITEM(F_TEMPVARIABLE|F_THEMESETTING,statusbar,LANG_STATUS_BAR,true, NULL, "statusbar"),
+    BOOL_ITEM(0,scrollbar,LANG_SCROLL_BAR,true, NULL, "scrollbar"),
+#if CONFIG_KEYPAD == RECORDER_PAD
+    BOOL_ITEM(0,buttonbar,LANG_BUTTON_BAR,true, NULL, "buttonbar"),
+#endif
+    CHOICE_ITEM(0,volume_type,LANG_VOLUME_DISPLAY, "volume display,graphic,numeric",
+                0, NULL,2,LANG_DISPLAY_GRAPHIC,LANG_DISPLAY_NUMERIC),
+    CHOICE_ITEM(0,battery_display,LANG_BATTERY_DISPLAY,
+                "battery display,graphic,numeric",
+                0, NULL,2,LANG_DISPLAY_GRAPHIC,LANG_DISPLAY_NUMERIC),
+    CHOICE_ITEM(0,timeformat,LANG_TIMEFORMAT, 
+                "time format,24hour,12hour", 0, NULL,2,
+                LANG_24_HOUR_CLOCK,LANG_12_HOUR_CLOCK),
+#endif /* HAVE_LCD_BITMAP */
+    BOOL_ITEM(0,show_icons,LANG_SHOW_ICONS,true, NULL, "show icons"),
+    
+    /* system */
+    STRINGCHOICE_ITEM(0,poweroff,LANG_POWEROFF_IDLE,"idle poweroff",
+                      10,15,
+                      _STR("off","1","2","3","4","5","6","7",
+                           "8","9","10","15","30","45","60"),
+                      _TALKID(LANG_OFF,TALK_ID(1, UNIT_MIN),
+                              TALK_ID(2, UNIT_MIN),TALK_ID(3, UNIT_MIN),
+                              TALK_ID(4, UNIT_MIN),TALK_ID(5, UNIT_MIN),
+                              TALK_ID(6, UNIT_MIN),TALK_ID(7, UNIT_MIN),
+                              TALK_ID(8, UNIT_MIN),TALK_ID(9, UNIT_MIN),
+                              TALK_ID(10, UNIT_MIN),TALK_ID(15, UNIT_MIN),
+                              TALK_ID(30, UNIT_MIN),TALK_ID(45, UNIT_MIN),
+                              TALK_ID(60, UNIT_MIN)), NULL),
+    SYSTEM_ITEM(F_T_INT,runtime,0, NULL),
+    SYSTEM_ITEM(F_T_INT,topruntime,0, NULL),
+    INT_ITEM(0,max_files_in_playlist,LANG_MAX_FILES_IN_PLAYLIST,
+#if MEM > 1
+             10000,1000,20000,1000
+#else
+             1000,1000,10000,100
+#endif
+            ,UNIT_INT, NULL, NULL,"max files in playlist"),
+    INT_ITEM(0,max_files_in_dir,LANG_MAX_FILES_IN_DIR,
+#if MEM > 1
+             400,50,10000,50
+#else
+             200,50,10000,50
+#endif
+            ,UNIT_INT, NULL, NULL,"max files in dir"),
+
+    /* battery */
+#ifndef SIMULATOR
+    INT_ITEM(0,battery_capacity,LANG_BATTERY_CAPACITY,BATTERY_CAPACITY_DEFAULT,
+             BATTERY_CAPACITY_MIN,BATTERY_CAPACITY_MAX,BATTERY_CAPACITY_INC,
+             UNIT_INT, NULL, NULL,"battery capacity"),
+#ifdef CONFIG_CHARGING
+    BOOL_ITEM(0,car_adapter_mode,LANG_CAR_ADAPTER_MODE,false,
+              NULL,"car adapter mode"),
+#endif
+#if BATTERY_TYPES_COUNT > 1
+    CHOICE_ITEM(0,battery_type,LANG_BATTERY_TYPE,"battery type,alkaline,nimh",
+                0, NULL,2,LANG_BATTERY_TYPE_ALKALINE,LANG_BATTERY_TYPE_NIMH),
+#endif
+#endif
+#ifdef CONFIG_TUNER
+    /* tuner */
+    BOOL_ITEM(0,fm_force_mono,LANG_FM_MONO_MODE,false, NULL,"force fm mono"),
+    SYSTEM_ITEM(F_T_INT,last_frequency,0, NULL),
+    STRINGCHOICE_ITEM(0,fm_region,LANG_FM_REGION,"fm_region",
+                      0,4,
+                      _STR("eu","us","jp","kr"),
+                      NULL, NULL),
+#endif
+
+#ifdef HAVE_REMOTE_LCD
+    /* remote lcd */
+    INT_ITEM(0,remote_contrast,LANG_CONTRAST,42,
+                   MIN_CONTRAST_SETTING,MAX_CONTRAST_SETTING,1,UNIT_INT,
+                   NULL, NULL,"remote contrast"),
+    CHOICE_ITEM(0,remote_invert,LANG_INVERT, "remote invert,off,on",
+                0, NULL,2,LANG_INVERT_LCD_NORMAL,LANG_INVERT_LCD_INVERSE),
+    BOOL_ITEM(0,remote_flip_display,LANG_FLIP_DISPLAY,false, NULL,
+              "remote flip display"),
+    STRINGCHOICE_ITEM(0,remote_backlight_timeout,LANG_BACKLIGHT,
+                            "remote backlight timeout",
+                            6,sizeof(backlight_times_strings)/
+                                    sizeof(*backlight_times_strings),
+                      {.strings = (char **)backlight_times_strings},
+                      (int*)backlight_times_talks, NULL),
+#ifdef CONFIG_CHARGING
+    STRINGCHOICE_ITEM(0,remote_backlight_timeout_plugged,
+                      LANG_BACKLIGHT_ON_WHEN_CHARGING,
+                            "remote backlight timeout plugged",11,
+                      sizeof(backlight_times_strings)/
+                              sizeof(*backlight_times_strings),
+                      {.strings = (char **)backlight_times_strings},
+                      (int*)backlight_times_talks, NULL),
+#endif
+#ifdef HAVE_REMOTE_LCD_TICKING
+    BOOL_ITEM(0,remote_reduce_ticking,LANG_REDUCE_TICKING,false,
+              NULL, "remote reduce ticking"),
+#endif
+    BOOL_ITEM(0,remote_bl_filter_first_keypress,
+              LANG_BACKLIGHT_FILTER_FIRST_KEYPRESS,false, NULL,
+                    "backlight filters first remote keypress"),
+#endif /* HAVE_REMOTE_LCD */
+#ifdef CONFIG_BACKLIGHT
+    BOOL_ITEM(0,bl_filter_first_keypress,
+              LANG_BACKLIGHT_FILTER_FIRST_KEYPRESS,false, NULL,
+              "backlight filters first keypress"),
+#endif
+
+    /***************   end of old rtc table    ******************/
+    
+    /* display */
+#ifdef CONFIG_BACKLIGHT
+    BOOL_ITEM(0,caption_backlight,LANG_CAPTION_BACKLIGHT,false,
+              NULL, "caption backlight"),
+#endif
+#ifdef HAVE_REMOTE_LCD
+    BOOL_ITEM(0,remote_caption_backlight,LANG_CAPTION_BACKLIGHT,false,
+              NULL,"remote caption backlight"),
+#endif
+#ifdef HAVE_BACKLIGHT_BRIGHTNESS
+    INT_ITEM(0,brightness,LANG_CAPTION_BACKLIGHT,DEFAULT_BRIGHTNESS_SETTING,
+             MIN_BRIGHTNESS_SETTING,MAX_BRIGHTNESS_SETTING,1,UNIT_INT, NULL,
+             NULL, "brightness"),
+#endif
+#ifdef HAVE_BACKLIGHT_PWM_FADING
+    /* backlight fading */
+    STRINGCHOICE_ITEM(0,backlight_fade_in,LANG_BACKLIGHT_FADE_IN,
+                      "backlight fade in",1,4,
+                      _STR("off","500ms","1s","2s"),
+                      _TALKID(LANG_OFF,TALK_ID(500, UNIT_MS),
+                              TALK_ID(1, UNIT_SEC),TALK_ID(2, UNIT_SEC)), NULL),
+    STRINGCHOICE_ITEM(0,backlight_fade_out,LANG_BACKLIGHT_FADE_OUT,
+                      "backlight fade out",4,8,
+                    _STR("off","500ms","1s","2s","3s","4s","5s","10s"),
+                    _TALKID(LANG_OFF,TALK_ID(500, UNIT_MS),TALK_ID(1, UNIT_SEC),
+                            TALK_ID(2, UNIT_SEC),TALK_ID(3, UNIT_SEC),
+                            TALK_ID(4, UNIT_SEC),TALK_ID(5, UNIT_SEC),
+                            TALK_ID(10, UNIT_SEC)), NULL),
+#endif
+    INT_ITEM(0,scroll_speed,LANG_SCROLL_SPEED,9,0,15,1,UNIT_INT,
+             NULL, NULL, "scroll speed"),
+    INT_ITEM(0,scroll_delay,LANG_SCROLL_DELAY,6,0,250,1,UNIT_INT,
+             NULL, NULL, "scroll delay"),
+    INT_ITEM(0,bidir_limit,LANG_BIDIR_SCROLL,50,0,200,1,UNIT_INT,
+             NULL, NULL, "bidir limit"),
+#ifdef HAVE_REMOTE_LCD
+    INT_ITEM(0,remote_scroll_speed,LANG_SCROLL_SPEED,6,0,15,1,
+             UNIT_INT, NULL, NULL, "remote scroll speed"),
+    INT_ITEM(0,remote_scroll_step,LANG_SCROLL_STEP,9,1,160,1,
+             UNIT_INT, NULL, NULL, "remote scroll step"),
+    INT_ITEM(0,remote_scroll_delay,LANG_SCROLL_DELAY,100,0,250,1,
+             UNIT_INT, NULL, NULL, "remote scroll delay"),
+    INT_ITEM(0,remote_bidir_limit,LANG_BIDIR_SCROLL,50,0,200,1,
+             UNIT_INT, NULL, NULL, "remote bidir limit"),
+#endif
+#ifdef HAVE_LCD_BITMAP
+    BOOL_ITEM(0,offset_out_of_view,LANG_SCREEN_SCROLL_VIEW,
+              false, NULL, "Screen Scrolls Out Of View"),
+    INT_ITEM(0,scroll_step,LANG_SCROLL_STEP,6,1,LCD_WIDTH,1,
+             LANG_PIXELS, NULL, NULL, "scroll step"),
+    INT_ITEM(0,screen_scroll_step,LANG_SCREEN_SCROLL_STEP,16,1,
+             LCD_WIDTH,1,LANG_PIXELS, NULL, NULL, "screen scroll step"),
+#endif /* HAVE_LCD_BITMAP */
+#ifdef HAVE_LCD_CHARCELLS
+    STRINGCHOICE_ITEM(0,jump_scroll,LANG_JUMP_SCROLL, "jump scroll",0,6,
+                      _STR(ID2P(LANG_OFF),ID2P(LANG_ON),"2","3","4",
+                           ID2P(LANG_ALWAYS)),
+                      _TALKID(LANG_OFF,LANG_ON,TALK_ID(2, UNIT_INT),
+                              TALK_ID(3, UNIT_INT),
+                              TALK_ID(4, UNIT_INT),LANG_ALWAYS), NULL),
+    INT_ITEM(0,jump_scroll_delay,LANG_JUMP_SCROLL_DELAY,500,0,2500,100,
+             UNIT_MS, NULL, NULL, "jump scroll delay"),
+#endif
+    BOOL_ITEM(0,scroll_paginated,LANG_SCROLL_PAGINATED,false,
+              NULL, "scroll paginated"),
+#ifdef HAVE_LCD_COLOR
+{F_T_INT|F_STORERGB|F_LANG_IS_STRING|F_THEMESETTING, GS(fg_color), {LCD_DEFAULT_FG}, 
+    {.cfg_string = "foreground color"}, 0,{NULL}, NULL, NULL ,"foreground color"},
+{F_T_INT|F_STORERGB|F_LANG_IS_STRING|F_THEMESETTING, GS(bg_color), {LCD_DEFAULT_BG}, 
+    {.cfg_string = "background color"}, 0,{NULL}, NULL, NULL ,"background color"},
+#endif
+
+    /* more playback */
+    BOOL_ITEM(0,play_selected,LANG_PLAY_SELECTED,true, NULL, "play selected"),
+    BOOL_ITEM(0,party_mode,LANG_PARTY_MODE,false, NULL,"party mode"),
+    BOOL_ITEM(0,fade_on_stop,LANG_FADE_ON_STOP,true, NULL, "volume fade"),
+    INT_ITEM(0,ff_rewind_min_step,LANG_FFRW_STEP,FF_REWIND_1000,0,60,1,
+             UNIT_INT, NULL, NULL,
+             "scan min step"),
+    INT_ITEM(0,ff_rewind_accel,LANG_FFRW_ACCEL,3,0,60,1,UNIT_SEC,
+             NULL, NULL, "scan accel"),
+    STRINGCHOICE_ITEM(0,ff_rewind_accel,LANG_FFRW_ACCEL,
+                      "scan accel",3,16,
+                      _STR("off","2x/1s","2x/2s","2x/3s","2x/4s",
+                           "2x/5s","2x/6s","2x/7s",
+                           "2x/8s","2x/9s","2x/10s","2x/11s","2x/12s",
+                           "2x/13s","2x/14s","2x/15s"),
+                      _TALKID(LANG_OFF,TALK_ID(1, UNIT_INT),TALK_ID(2, UNIT_INT),
+                              TALK_ID(3, UNIT_INT),TALK_ID(4, UNIT_INT),
+                              TALK_ID(5, UNIT_INT),TALK_ID(6, UNIT_INT),
+                              TALK_ID(7, UNIT_INT),TALK_ID(8, UNIT_INT),
+                              TALK_ID(9, UNIT_INT),TALK_ID(10, UNIT_INT),
+                              TALK_ID(11, UNIT_INT),TALK_ID(12, UNIT_INT),
+                              TALK_ID(13, UNIT_INT),TALK_ID(14, UNIT_INT),
+                              TALK_ID(15, UNIT_INT)), NULL),
+#if CONFIG_CODEC == SWCODEC
+    STRINGCHOICE_ITEM(0,buffer_margin,LANG_MP3BUFFER_MARGIN,
+                      "antiskip",0,8,
+                      _STR("5s","15s","30s","1min","2min","3min","5min","10min"),
+                      _TALKID(TALK_ID(5, UNIT_SEC),TALK_ID(15, UNIT_SEC),
+                              TALK_ID(30, UNIT_SEC),TALK_ID(1, UNIT_MIN),
+                              TALK_ID(2, UNIT_MIN),TALK_ID(3, UNIT_MIN),
+                              TALK_ID(5, UNIT_MIN),TALK_ID(10, UNIT_MIN)), NULL),
+#else
+    INT_ITEM(0,buffer_margin,LANG_MP3BUFFER_MARGIN,1,0,7,1,UNIT_SEC,
+             NULL, NULL, "antiskip"),
+#endif
+
+    /* disk */
+#ifndef HAVE_MMC
+#ifdef HAVE_ATA_POWER_OFF
+    BOOL_ITEM(0,disk_poweroff,LANG_POWEROFF_IDLE,false, NULL, "disk poweroff"),
+#endif
+    INT_ITEM(0,disk_spindown,LANG_SPINDOWN,
+             5,1,254,3,UNIT_SEC, NULL, NULL, "disk spindown"),
+#endif /* !HAVE_MMC */
+
+    /* browser */
+    CHOICE_ITEM(0,dirfilter,LANG_FILTER,
+                "show files,all,supported,music,playlists,id3 database",
+                SHOW_SUPPORTED, NULL,5,
+                LANG_FILTER_ALL,LANG_FILTER_SUPPORTED,LANG_FILTER_MUSIC,
+                LANG_FILTER_PLAYLIST,LANG_FILTER_ID3DB),
+    BOOL_ITEM(0,sort_case,LANG_SORT_CASE,false, NULL, "sort case"),
+    BOOL_ITEM(0,browse_current,LANG_FOLLOW,false, NULL, "follow playlist"),
+    
+    /* playlist */
+    BOOL_ITEM(0,playlist_viewer_icons,LANG_SHOW_ICONS,true,
+              NULL, "playlist viewer icons"),
+    BOOL_ITEM(0,playlist_viewer_indices,LANG_SHOW_INDICES,true,
+              NULL, "playlist viewer indices"),
+    CHOICE_ITEM(0,playlist_viewer_track_display,LANG_TRACK_DISPLAY,
+                "playlist viewer track display,track name,full path", 0, NULL,2,
+                LANG_DISPLAY_TRACK_NAME_ONLY,LANG_DISPLAY_FULL_PATH),
+    CHOICE_ITEM(0,recursive_dir_insert,LANG_RECURSE_DIRECTORY,
+                "recursive directory insert,off,on,ask",
+                RECURSE_OFF, NULL,3,
+                LANG_ON,LANG_OFF,LANG_RESUME_SETTING_ASK),
+    
+    /* bookmarks */
+    CHOICE_ITEM(0,autocreatebookmark,LANG_BOOKMARK_SETTINGS_AUTOCREATE, 
+                "autocreate bookmarks,off,on,ask,recent only - on,recent only - ask",
+                BOOKMARK_NO, NULL,5,
+                LANG_OFF,LANG_ON,LANG_RESUME_SETTING_ASK,
+                LANG_BOOKMARK_SETTINGS_RECENT_ONLY_YES,
+                LANG_BOOKMARK_SETTINGS_RECENT_ONLY_ASK),
+    CHOICE_ITEM(0,autoloadbookmark,LANG_BOOKMARK_SETTINGS_AUTOLOAD,
+                "autoload bookmarks,off,on,ask",BOOKMARK_NO, NULL,3,
+                LANG_ON,LANG_OFF,LANG_RESUME_SETTING_ASK),
+    CHOICE_ITEM(0,usemrb,LANG_BOOKMARK_SETTINGS_MAINTAIN_RECENT_BOOKMARKS,
+                "use most-recent-bookmarks,off,on,unique only",BOOKMARK_NO, NULL,3,
+                LANG_OFF,LANG_ON,LANG_BOOKMARK_SETTINGS_UNIQUE_ONLY),
+    
+    /* peak meter */
+#ifdef HAVE_LCD_BITMAP
+    STRINGCHOICE_ITEM(0,peak_meter_clip_hold,LANG_PM_CLIP_HOLD,
+                      "peak meter clip hold",
+                      16,24,
+                _STR("on","1s","2s","3s","4s","5s","6s","7s","8s","9s","10s",
+                    "15s","20s","30s","45s","60s","90s","2min","3min","5min","10min",
+                    "20min","45min","90min"),
+                _TALKID(LANG_OFF,TALK_ID(1, UNIT_SEC),TALK_ID(2, UNIT_SEC),
+                        TALK_ID(3, UNIT_SEC),TALK_ID(4, UNIT_SEC),
+                        TALK_ID(5, UNIT_SEC),TALK_ID(6, UNIT_SEC),
+                        TALK_ID(7, UNIT_SEC),TALK_ID(8, UNIT_SEC),
+                        TALK_ID(9, UNIT_SEC),TALK_ID(10, UNIT_SEC),
+                        TALK_ID(15, UNIT_SEC),TALK_ID(20, UNIT_SEC),
+                        TALK_ID(30, UNIT_SEC),TALK_ID(45, UNIT_SEC),
+                        TALK_ID(60, UNIT_SEC),TALK_ID(90, UNIT_SEC),
+                        TALK_ID(2, UNIT_MIN),TALK_ID(3, UNIT_MIN),
+                        TALK_ID(5, UNIT_MIN),TALK_ID(10, UNIT_MIN),
+                        TALK_ID(20, UNIT_MIN),TALK_ID(45, UNIT_MIN),
+                        TALK_ID(90, UNIT_MIN)), NULL),
+    STRINGCHOICE_ITEM(0,peak_meter_hold,LANG_PM_PEAK_HOLD,
+                      "peak meter hold",
+                      3,18,
+                _STR("off","200ms","300ms","500ms","1s","2s","3s","4s",
+                    "5s","6s","7s","8s","9s","10s","15s","20s","30s","60s"),
+                _TALKID(LANG_OFF,TALK_ID(200, UNIT_MS),TALK_ID(300, UNIT_MS),
+                        TALK_ID(500, UNIT_MS),TALK_ID(1, UNIT_SEC),
+                        TALK_ID(2, UNIT_SEC),TALK_ID(3, UNIT_SEC),
+                        TALK_ID(4, UNIT_SEC),TALK_ID(5, UNIT_SEC),
+                        TALK_ID(6, UNIT_SEC),TALK_ID(7, UNIT_SEC),
+                        TALK_ID(8, UNIT_SEC),TALK_ID(9, UNIT_SEC),
+                        TALK_ID(10, UNIT_SEC),TALK_ID(15, UNIT_SEC),
+                        TALK_ID(20, UNIT_SEC),TALK_ID(30, UNIT_SEC),
+                        TALK_ID(60, UNIT_SEC)), NULL),
+    INT_ITEM(0,peak_meter_release,LANG_PM_RELEASE,8,0,126,1,
+             LANG_PM_UNITS_PER_READ, NULL, NULL, "peak meter release"),
+    BOOL_ITEM(0,peak_meter_dbfs,LANG_PM_DBFS,true, NULL, "peak meter dbfs"),
+    INT_ITEM(0,peak_meter_min,LANG_PM_MIN,60,0,100,1,UNIT_INT, NULL,
+             NULL, "peak meter min"),
+    INT_ITEM(0,peak_meter_max,LANG_PM_MAX,0,0,100,1,UNIT_INT, NULL,
+             NULL, "peak meter max"),
+#endif /* HAVE_LCD_BITMAP */
+#if (CONFIG_CODEC == MAS3587F) || (CONFIG_CODEC == MAS3539F)
+    SOUND_ITEM(0,mdb_strength,LANG_MDB_STRENGTH,
+               SOUND_MDB_STRENGTH, "mdb strength"),
+    SOUND_ITEM(0,mdb_harmonics,LANG_MDB_HARMONICS,
+               SOUND_MDB_HARMONICS, "mdb harmonics"),
+    SOUND_ITEM(0,mdb_center,LANG_MDB_CENTER,SOUND_MDB_CENTER, "mdb center"),
+    SOUND_ITEM(0,mdb_shape,LANG_MDB_SHAPE,SOUND_MDB_SHAPE, "mdb shape"),
+    BOOL_ITEM(0,mdb_enable,LANG_MDB_ENABLE, false,set_mdb_enable, "mdb enable"),
+#endif
+#if CONFIG_CODEC == MAS3507D
+    BOOL_ITEM(0,line_in,LANG_LINE_IN, false,NULL, "line in"),
+#endif
+
+    /* voice */
+    CHOICE_ITEM(0,talk_dir,LANG_VOICE_DIR, 
+                "talk dir,off,number,spell,hover",0, NULL,4,
+                LANG_OFF,LANG_VOICE_NUMBER,LANG_VOICE_SPELL,LANG_VOICE_DIR_HOVER),
+    CHOICE_ITEM(0,talk_file,LANG_VOICE_FILE, 
+                "talk file,off,number,spell,hover",0, NULL,4,
+                LANG_OFF,LANG_VOICE_NUMBER,LANG_VOICE_SPELL,LANG_VOICE_DIR_HOVER),
+    BOOL_ITEM(F_TEMPVARIABLE,talk_menu,LANG_VOICE_MENU, false,NULL, "talk menu"),
+    
+    /* file sorting */
+    CHOICE_ITEM(0,sort_file,LANG_SORT_FILE,
+                "sort files,alpha,oldest,newest,type",0, NULL,4,
+                LANG_SORT_ALPHA,LANG_SORT_DATE,
+                LANG_SORT_DATE_REVERSE,LANG_SORT_TYPE),
+    CHOICE_ITEM(0,sort_dir,LANG_SORT_DIR, 
+                "sort dirs,alpha,oldest,newest",0, NULL,3,
+                LANG_SORT_ALPHA,LANG_SORT_DATE,LANG_SORT_DATE_REVERSE),
+/*    CHOICE_ITEM(0,id3_v1_first,LANG_ID3_ORDER, 
+                "id3 tag priority,v2-v1,v1-v2",0, mpeg_id3_options,2,
+                LANG_ID3_V1_FIRST,LANG_ID3_V2_FIRST),
+ */
+#ifdef HAVE_RECORDING
+    /* recording */
+    SYSTEM_ITEM(F_T_BOOL,recscreen_on,0, NULL),
+    BOOL_ITEM(0,rec_startup,LANG_RECORD_STARTUP, 
+              false,NULL, "rec screen on startup"),
+    STRINGCHOICE_ITEM(0,rec_timesplit,LANG_SPLIT_TIME,
+                      "rec timesplit", 0,16,
+                      _STR("off","00:05","00:10","00:15","00:30","01:00","01:14",
+                           "01:20","02:00","04:00","06:00","08:00",
+                           "10:00","12:00","18:00","24:00"),
+                      _TALKID(LANG_OFF,TALK_ID(5, UNIT_MIN),TALK_ID(10, UNIT_MIN),
+                              TALK_ID(15, UNIT_MIN),TALK_ID(30, UNIT_MIN),
+                              TALK_ID(60, UNIT_MIN),TALK_ID(72, UNIT_MIN),
+                              TALK_ID(80, UNIT_MIN),TALK_ID(2, UNIT_HOUR),
+                              TALK_ID(4, UNIT_HOUR),TALK_ID(6, UNIT_HOUR),
+                              TALK_ID(8, UNIT_HOUR),TALK_ID(10, UNIT_HOUR),
+                              TALK_ID(12, UNIT_HOUR),TALK_ID(18, UNIT_HOUR),
+                              TALK_ID(24, UNIT_HOUR)), NULL),
+    STRINGCHOICE_ITEM(0,rec_sizesplit,LANG_SPLIT_SIZE,
+                      "rec sizesplit",0,16,
+                    _STR("off","5MB","10MB","15MB","32MB","64MB","75MB",
+                            "100MB","128MB","256MB","512MB","650MB",
+                            "700MB","1GB","1.5GB","1.75GB"),
+                    _TALKID(LANG_OFF,TALK_ID(5, UNIT_MB),TALK_ID(10, UNIT_MB),
+                            TALK_ID(15, UNIT_MB),TALK_ID(32, UNIT_MB),
+                            TALK_ID(64, UNIT_MB),TALK_ID(75, UNIT_MB),
+                            TALK_ID(100, UNIT_MB),TALK_ID(128, UNIT_MB),
+                            TALK_ID(256, UNIT_MB),TALK_ID(512, UNIT_MB),
+                            TALK_ID(650, UNIT_MB),TALK_ID(700, UNIT_MB),
+                            TALK_ID(1024, UNIT_MB),TALK_ID(1536, UNIT_MB),
+                            TALK_ID(1792, UNIT_MB)),NULL),
+    CHOICE_ITEM(0,rec_channels,LANG_RECORDING_CHANNELS,"rec channels,stereo,mono",
+                0, NULL,2,LANG_CHANNEL_STEREO,LANG_CHANNEL_MONO),
+    CHOICE_ITEM(0,rec_split_type,LANG_SPLIT_TYPE, "rec split type,Split,Stop",
+                0, NULL,2,LANG_START_NEW_FILE,LANG_STOP_RECORDING),
+    CHOICE_ITEM(0,rec_split_method,LANG_SPLIT_MEASURE, "rec split method,Time,Filesize",
+                0, NULL,2,LANG_SPLIT_TIME,LANG_SPLIT_SIZE),
+    CHOICE_ITEM(0,rec_source,LANG_RECORDING_SOURCE, "rec source"
+#if defined(HAVE_SPDIF_IN) && defined(HAVE_FMRADIO_IN)
+                "mic,line,spdif,fmradio", 2,NULL, 4,
+#elif defined(HAVE_SPDIF_IN)
+                "mic,line,spdif", 2,NULL, 3,
+#elif defined(HAVE_FMRADIO_IN)
+                "mic,line,fmradio", 2,NULL, 3,
+#else
+                "mic,line",1,NULL, 2,
+#endif
+                LANG_RECORDING_SRC_MIC,LANG_RECORDING_SRC_LINE
+#if defined(HAVE_SPDIF_IN)
+                ,LANG_RECORDING_SRC_DIGITAL
+#endif
+#if defined(HAVE_FMRADIO_IN)
+                ,LANG_FM_RADIO
+#endif
+               ),
+    INT_ITEM(0,rec_prerecord_time,LANG_RECORD_PRERECORD_TIME,0,0,30,1,UNIT_SEC,
+             NULL, NULL, "prerecording time"),
+    STRINGCHOICE_ITEM(0,rec_directory,LANG_RECORD_DIRECTORY,
+                      "rec directory",0,2,
+                      _STR(REC_BASE_DIR,/*LANG_RECORD_CURRENT_DIR*/"Current Directory"),
+                      _TALKID(-1,LANG_RECORD_CURRENT_DIR),NULL),
+#ifdef CONFIG_BACKLIGHT
+    CHOICE_ITEM(0,cliplight,LANG_CLIP_LIGHT, "cliplight,off,main,both,remote",0,
+                NULL,4,LANG_OFF,LANG_MAIN_UNIT,LANG_REMOTE_MAIN,LANG_REMOTE_UNIT),
+#endif
+#if CONFIG_CODEC == MAS3587F
+    INT_ITEM(0,rec_mic_gain,LANG_RECORDING_GAIN,8,-128,128,1,UNIT_DB, NULL,
+             NULL, "rec mic gain"),
+    INT_ITEM(0,rec_left_gain,LANG_RECORDING_LEFT,8,0,15,1,UNIT_DB, NULL,
+             NULL, "rec left gain"),
+    INT_ITEM(0,rec_right_gain,LANG_RECORDING_RIGHT,8,0,15,1,UNIT_DB, NULL,
+             NULL, "rec right gain"),
+    STRINGCHOICE_ITEM(0,rec_frequency,LANG_RECORDING_FREQUENCY,"rec frequency",0,6,
+                      _STR("44.1kHz","48kHz","32kHz","22.05kHz","24kHz","16kHz"),
+                      _TALKID(TALK_ID(44, UNIT_KHZ),TALK_ID(48, UNIT_KHZ),
+                              TALK_ID(32, UNIT_KHZ),TALK_ID(22, UNIT_KHZ),
+                              TALK_ID(24, UNIT_KHZ),TALK_ID(16, UNIT_KHZ)),NULL),
+    INT_ITEM(0,rec_quality,LANG_RECORDING_QUALITY,5,0,7,1,UNIT_INT, NULL, 
+             NULL, "rec quality"),
+    BOOL_ITEM(0,rec_editable,LANG_RECORDING_EDITABLE, false,NULL, 
+              "editable recordings"),
+#endif /* CONFIG_CODEC == MAS3587F */
+#if CONFIG_CODEC == SWCODEC && defined(HAVE_RECORDING)
+#ifdef HAVE_UDA1380
+    INT_ITEM(0,rec_mic_gain,LANG_RECORDING_GAIN,16,-128,128,1,UNIT_DB, 
+             NULL, NULL, "rec mic gain"),
+#endif
+#ifdef HAVE_TLV320
+    /* TLV320 only has no mic boost or 20db mic boost */
+    INT_ITEM(0,rec_mic_gain,LANG_RECORDING_GAIN,0,0,20,20,UNIT_DB, 
+             NULL, NULL, "rec mic gain"),
+#endif
+    INT_ITEM(0,rec_left_gain,LANG_RECORDING_LEFT,0,-128,96,1,UNIT_DB,
+             NULL, NULL, "rec left gain"),
+    INT_ITEM(0,rec_right_gain,LANG_RECORDING_RIGHT,0,-128,96,1,UNIT_DB,
+             NULL, NULL, "rec right gain"),
+    
+#if 0 /* Till samplerates are added for SWCODEC */
+    STRINGCHOICE_ITEM(0,rec_frequency,LANG_RECORDING_FREQUENCY,"rec frequency",0,6,
+                    _STR("44.1kHz","48kHz","32kHz","22.05kHz","24kHz","16kHz"),
+                    _TALKID(TALK_ID(44, UNIT_KHZ),TALK_ID(48, UNIT_KHZ),
+                            TALK_ID(32, UNIT_KHZ),TALK_ID(22, UNIT_KHZ),
+                            TALK_ID(24, UNIT_KHZ),TALK_ID(16, UNIT_KHZ)),NULL),
+#else
+    STRINGCHOICE_ITEM(0,rec_frequency,LANG_RECORDING_FREQUENCY,
+                      "rec frequency",0,1,
+                    _STR("44.1kHz"), _TALKID(TALK_ID(44, UNIT_KHZ)),NULL),
+#endif
+
+#endif /* CONFIG_CODEC == SWCODEC && defined(HAVE_RECORDING) */
+    /* values for the trigger */
+    INT_ITEM(0,rec_start_thres,LANG_RECORD_START_THRESHOLD,-35,-87,100,1,
+             UNIT_INT, NULL, NULL, "trigger start threshold"),
+    INT_ITEM(0,rec_stop_thres,LANG_RECORD_STOP_THRESHOLD,-45,-87,100,1,
+             UNIT_INT, NULL, NULL, "trigger stop threshold"),
+    STRINGCHOICE_ITEM(0,rec_start_duration,LANG_RECORD_MIN_DURATION, 
+                      "trigger start duration",
+                      0,sizeof(trig_durations_strings)/
+                              sizeof(*trig_durations_strings),
+                      {.strings = (char **)trig_durations_strings},
+                      (int*)trig_durations_talks, NULL),
+    STRINGCHOICE_ITEM(0,rec_stop_postrec,LANG_RECORD_STOP_POSTREC,
+                      "trigger stop postrec",
+                      2,sizeof(trig_durations_strings)/
+                              sizeof(*trig_durations_strings),
+                      {.strings = (char **)trig_durations_strings},
+                      (int*)trig_durations_talks, NULL),
+    STRINGCHOICE_ITEM(0,rec_stop_gap,LANG_RECORD_STOP_GAP,
+                      "trigger min gap",
+                      1,sizeof(trig_durations_strings)/
+                              sizeof(*trig_durations_strings),
+                      {.strings = (char **)trig_durations_strings},
+                      (int*)trig_durations_talks, NULL),
+/*    CHOICE_ITEM(0,rec_trigger_mode,LANG_RECORD_TRIGGER_MODE,
+                "trigger mode,off,once,repeat", 0, NULL,3,
+                LANG_OFF,LANG_ONCE,LANG_REPEAT),*/
+#endif /* HAVE_RECORDING */
+#ifdef HAVE_SPDIF_POWER
+    BOOL_ITEM(0,spdif_enable,LANG_SPDIF_ENABLE, false,NULL, "spdif enable"),
+#endif
+    CHOICE_ITEM(0,next_folder,LANG_NEXT_FOLDER, "folder navigation,off,on,random",
+                0,NULL,3,LANG_OFF,LANG_ON,LANG_RANDOM),
+    BOOL_ITEM(0,runtimedb,LANG_RUNTIMEDB_ACTIVE, false,NULL, "gather runtime data"),
+
+#ifdef HAVE_DIRCACHE
+    /* dircache */
+    BOOL_ITEM(0,dircache,LANG_DIRCACHE_ENABLE, false,dircache_cb, "dircache"),
+    SYSTEM_ITEM(F_T_INT,dircache_size,0, NULL),
+#endif
+    
+    /* tagcache */
+#ifdef HAVE_TC_RAMCACHE
+    BOOL_ITEM(0,tagcache_ram,LANG_TAGCACHE_RAM, false,NULL, "tagcache_ram"),
+#endif
+    BOOL_ITEM(0,tagcache_autoupdate,LANG_TAGCACHE_AUTOUPDATE,
+              false,NULL, "tagcache_autoupdate"),
+    CHOICE_ITEM(0,default_codepage,LANG_DEFAULT_CODEPAGE,
+                "default codepage,iso8859-1,iso8859-7,iso8859-8,cp1251,"
+                "iso8859-11,cp1256,iso8859-9,iso8859-2,sjis,"
+                "gb2312,ksx1001,big5,utf-8,cp1256",
+                0, NULL,13,
+                LANG_CODEPAGE_LATIN1,LANG_CODEPAGE_GREEK,LANG_CODEPAGE_HEBREW,
+                LANG_CODEPAGE_CYRILLIC,LANG_CODEPAGE_THAI,LANG_CODEPAGE_ARABIC,
+                LANG_CODEPAGE_TURKISH,LANG_CODEPAGE_LATIN_EXTENDED,
+                LANG_CODEPAGE_JAPANESE,LANG_CODEPAGE_SIMPLIFIED,
+                LANG_CODEPAGE_KOREAN,LANG_CODEPAGE_TRADITIONAL,LANG_CODEPAGE_UTF8),
+    BOOL_ITEM(0,warnon_erase_dynplaylist,LANG_WARN_ERASEDYNPLAYLIST_MENU,
+              false,NULL,"warn when erasing dynamic playlist"),
+    
+#ifdef CONFIG_BACKLIGHT
+#ifdef HAS_BUTTON_HOLD
+    CHOICE_ITEM(0,backlight_on_button_hold,LANG_BACKLIGHT_ON_BUTTON_HOLD,
+                "backlight on button hold,normal,off,on",0,NULL,3,
+                LANG_BACKLIGHT_ON_BUTTON_HOLD_NORMAL, LANG_OFF,LANG_ON),
+#endif
+#ifdef HAVE_LCD_SLEEP
+    STRINGCHOICE_ITEM(0,lcd_sleep_after_backlight_off,
+                      LANG_LCD_SLEEP_AFTER_BACKLIGHT_OFF,
+                      "lcd sleep after backlight off",3,6,
+                      _STR("always","never","5","10","15","20","30","45","60","90"),
+                      _TALKID(LANG_ALWAYS,LANG_NEVER,TALK_ID(5, UNIT_SEC),
+                              TALK_ID(10, UNIT_SEC),TALK_ID(15, UNIT_SEC),
+                              TALK_ID(20, UNIT_SEC),TALK_ID(30, UNIT_SEC),
+                              TALK_ID(45, UNIT_SEC),TALK_ID(60, UNIT_SEC),
+                              TALK_ID(90, UNIT_SEC)),NULL),
+#endif
+#endif /* CONFIG_BACKLIGHT */
+
+#if CONFIG_CODEC == SWCODEC
+    /* replay gaim */
+    BOOL_ITEM(0,replaygain,LANG_REPLAYGAIN, false,NULL, "replaygain"),
+    CHOICE_ITEM(0,replaygain_type,LANG_REPLAYGAIN_MODE,
+                "replaygain type,track,album,track shuffle", 0,NULL,3,
+                LANG_TRACK_GAIN, LANG_ALBUM_GAIN,LANG_SHUFFLE_GAIN),
+    BOOL_ITEM(0,replaygain_noclip,LANG_REPLAYGAIN_NOCLIP, false,NULL,
+              "replaygain noclip"),
+    INT_ITEM(0,replaygain_preamp,LANG_REPLAYGAIN_PREAMP,0,-120,120,1,
+             UNIT_DB, NULL, NULL, "replaygain preamp"),
+    CHOICE_ITEM(0,beep,LANG_BEEP,"beep,off,weak,moderate,strong", 0,NULL,4,
+                LANG_OFF, LANG_WEAK,LANG_MODERATE,LANG_STRONG),
+    /* crossfade */
+    /* FIXME|FIXME all the cross* settings need checking FIXME|FIXME|FIXME*/
+    CHOICE_ITEM(0,crossfade,LANG_CROSSFADE_ENABLE,
+                "crossfade,off,shuffle,track skip,always", 0,NULL,4,
+                LANG_OFF, LANG_SHUFFLE,LANG_TRACKSKIP,LANG_ALWAYS),
+    INT_ITEM(0,crossfade_fade_in_delay,LANG_CROSSFADE_FADE_IN_DELAY,
+             0,0,7,1,UNIT_SEC, NULL, NULL, "crossfade fade in delay"),
+    INT_ITEM(0,crossfade_fade_out_delay,LANG_CROSSFADE_FADE_OUT_DELAY,
+             0,0,7,1,UNIT_SEC, NULL, NULL, "crossfade fade out delay"),
+    INT_ITEM(0,crossfade_fade_in_duration,LANG_CROSSFADE_FADE_IN_DURATION,
+             0,0,15,1,UNIT_SEC, NULL, NULL, "crossfade fade in duration"),
+    INT_ITEM(0,crossfade_fade_out_duration,LANG_CROSSFADE_FADE_OUT_DURATION,
+             0,0,15,1,UNIT_SEC, NULL, NULL, "crossfade fade out duration"),
+    CHOICE_ITEM(0,crossfade_fade_out_mixmode,LANG_CROSSFADE_FADE_OUT_MODE,
+                "crossfade fade out mode,crossfade,mix", 0,NULL,2,
+                LANG_CROSSFADE, LANG_MIX),
+    BOOL_ITEM(0,crossfeed,LANG_CROSSFEED, false,NULL, "crossfeed"),
+    INT_ITEM(0,crossfeed_direct_gain,LANG_CROSSFEED_DIRECT_GAIN,15,0,
+             60,5,UNIT_DB, NULL, crossfeed_format, "crossfeed direct gain"),
+    INT_ITEM(0,crossfeed_cross_gain,LANG_CROSSFEED_CROSS_GAIN,60,30,
+             120,5,UNIT_DB, NULL, crossfeed_format, "crossfeed cross gain"),
+    INT_ITEM(0,crossfeed_hf_attenuation,LANG_CROSSFEED_HF_ATTENUATION,
+             160,60,240,5,UNIT_DB, NULL, crossfeed_format, 
+             "crossfeed hf attenuation"),
+    INT_ITEM(0,crossfeed_hf_cutoff,LANG_CROSSFEED_HF_CUTOFF,700,500,
+             2000,100,UNIT_DB, NULL, NULL, "crossfeed hf cutoff"),
+#if 0
+    /* / FIXME|FIXME|FIXME|FIXME|FIXME|FIXME|FIXME|FIXME|FIXME|FIXME|FIXME| */
+    /* sw equalizer */
+    BOOL_ITEM(0,eq_enabled,LANG_EQUALIZER_ENABLED, false,NULL, "eq enabled"),
+    INT_ITEM(0,eq_precut,LANG_EQUALIZER_PRECUT,0,0,240,5,UNIT_DB,
+             NULL, NULL, "eq precut"),
+    /* 0..32768 Hz */
+    INT_ITEM(0,eq_band0_cutoff,LANG_EQUALIZER_BAND_CUTOFF,60,
+             EQ_CUTOFF_MIN,EQ_CUTOFF_MAX,EQ_CUTOFF_STEP,UNIT_DB, 
+             NULL, NULL,"eq band 0 cutoff"),
+    INT_ITEM(0,eq_band1_cutoff,LANG_EQUALIZER_BAND_CUTOFF,200,
+             EQ_CUTOFF_MIN,EQ_CUTOFF_MAX,EQ_CUTOFF_STEP,UNIT_DB, 
+             NULL, NULL,"eq band 1 cutoff"),
+    INT_ITEM(0,eq_band2_cutoff,LANG_EQUALIZER_BAND_CUTOFF,800,
+             EQ_CUTOFF_MIN,EQ_CUTOFF_MAX,EQ_CUTOFF_STEP,UNIT_DB, 
+             NULL, NULL,"eq band 2 cutoff"),
+    INT_ITEM(0,eq_band3_cutoff,LANG_EQUALIZER_BAND_CUTOFF,4000,
+             EQ_CUTOFF_MIN,EQ_CUTOFF_MAX,EQ_CUTOFF_STEP,UNIT_DB, 
+             NULL, NULL,"eq band 3 cutoff"),
+    INT_ITEM(0,eq_band4_cutoff,LANG_EQUALIZER_BAND_CUTOFF,12000,
+             EQ_CUTOFF_MIN,EQ_CUTOFF_MAX,EQ_CUTOFF_STEP,UNIT_DB, 
+             NULL, NULL,"eq band 4 cutoff"),
+    /* 0..64 (or 0.0 to 6.4) */
+    INT_ITEM(0,eq_band0_q,LANG_EQUALIZER_BAND_Q,7,
+             EQ_Q_MIN,EQ_Q_MAX,EQ_Q_STEP,UNIT_DB, NULL, NULL,"eq band 0 q"),
+    INT_ITEM(0,eq_band1_q,LANG_EQUALIZER_BAND_Q,10,
+             EQ_Q_MIN,EQ_Q_MAX,EQ_Q_STEP,UNIT_DB, NULL, NULL,"eq band 1 q"),
+    INT_ITEM(0,eq_band2_q,LANG_EQUALIZER_BAND_Q,10,
+             EQ_Q_MIN,EQ_Q_MAX,EQ_Q_STEP,UNIT_DB, NULL, NULL,"eq band 2 q"),
+    INT_ITEM(0,eq_band3_q,LANG_EQUALIZER_BAND_Q,10,
+             EQ_Q_MIN,EQ_Q_MAX,EQ_Q_STEP,UNIT_DB, NULL, NULL,"eq band 3 q"),
+    INT_ITEM(0,eq_band4_q,LANG_EQUALIZER_BAND_Q,7,
+             EQ_Q_MIN,EQ_Q_MAX,EQ_Q_STEP,UNIT_DB, NULL, NULL,"eq band 4 q"),
+    /* -240..240 (or -24db to +24db) */
+    INT_ITEM(0,eq_band0_gain,LANG_EQUALIZER_BAND_GAIN,0,
+             EQ_GAIN_MIN,EQ_GAIN_MAX,EQ_GAIN_STEP,UNIT_DB,
+             NULL, NULL,"eq band 0 gain"),
+    INT_ITEM(0,eq_band1_gain,LANG_EQUALIZER_BAND_GAIN,0,
+             EQ_GAIN_MIN,EQ_GAIN_MAX,EQ_GAIN_STEP,UNIT_DB, 
+             NULL, NULL,"eq band 1 gain"),
+    INT_ITEM(0,eq_band2_gain,LANG_EQUALIZER_BAND_GAIN,0,
+             EQ_GAIN_MIN,EQ_GAIN_MAX,EQ_GAIN_STEP,UNIT_DB, 
+             NULL, NULL,"eq band 2 gain"),
+    INT_ITEM(0,eq_band3_gain,LANG_EQUALIZER_BAND_GAIN,0,
+             EQ_GAIN_MIN,EQ_GAIN_MAX,EQ_GAIN_STEP,UNIT_DB, 
+             NULL, NULL,"eq band 3 gain"),
+    INT_ITEM(0,eq_band4_gain,LANG_EQUALIZER_BAND_GAIN,0,
+             EQ_GAIN_MIN,EQ_GAIN_MAX,EQ_GAIN_STEP,UNIT_DB,
+             NULL, NULL,"eq band 4 gain"),
+    BOOL_ITEM(0,dithering_enabled,LANG_DITHERING, false,NULL, "dithering enabled"),
+#endif
+#endif /* CONFIG_CODEC == SWCODEC */
+
+#ifdef HAVE_WM8758
+    /* hardware eq */
+    BOOL_ITEM(0,eq_hw_enabled,LANG_EQUALIZER_HARDWARE_ENABLED,
+              false,NULL, "eq hardware enabled"),
+    /* band 0 */
+    STRINGCHOICE_ITEM(0,eq_hw_band0_cutoff,LANG_EQUALIZER_BAND_CUTOFF,
+                      "eq hardware band 0 cutoff",1,4,
+                      _STR("80Hz","105Hz","135Hz","175Hz"),
+                      _TALKID(TALK_ID(80, UNIT_HERTZ),TALK_ID(105, UNIT_HERTZ),
+                              TALK_ID(135, UNIT_HERTZ),TALK_ID(175, UNIT_HERTZ)),
+                      NULL),
+    INT_ITEM(0,eq_band0_gain,LANG_EQUALIZER_BAND_GAIN,0,
+             EQ_HW_GAIN_MIN,EQ_HW_GAIN_MAX,EQ_HW_GAIN_STEP,
+             UNIT_DB, NULL, NULL,"eq hardware band 0 gain"),
+    /* band 1 */
+    STRINGCHOICE_ITEM(0,eq_hw_band1_center,LANG_EQUALIZER_BAND_CENTER,
+                      "eq hardware band 1 center",1,4,
+                      _STR("230Hz","300Hz","385Hz","500Hz"),
+                      _TALKID(TALK_ID(230, UNIT_HERTZ),TALK_ID(300, UNIT_HERTZ),
+                              TALK_ID(385, UNIT_HERTZ),TALK_ID(500, UNIT_HERTZ)),
+                      NULL),
+    CHOICE_ITEM(0,eq_hw_band1_bandwidth,LANG_EQUALIZER_BANDWIDTH,
+                "eq hardware band 1 bandwidth,narrow,wide", 0,NULL,2,
+                LANG_EQUALIZER_HARDWARE_BANDWIDTH_NARROW,
+                LANG_EQUALIZER_HARDWARE_BANDWIDTH_WIDE),
+    INT_ITEM(0,eq_hw_band1_gain,LANG_EQUALIZER_BAND_GAIN,0,
+             EQ_HW_GAIN_MIN,EQ_HW_GAIN_MAX,EQ_HW_GAIN_STEP,UNIT_DB,
+             NULL, NULL, "eq hardware band 1 gain"),
+    /* band 2 */
+    STRINGCHOICE_ITEM(0,eq_hw_band2_center,LANG_EQUALIZER_BAND_CENTER,
+                      "eq hardware band 2 center",1,4,
+                      _STR("650Hz","850Hz","1100Hz","1400Hz"),
+                      _TALKID(TALK_ID(650, UNIT_HERTZ),TALK_ID(850, UNIT_HERTZ),
+                              TALK_ID(1100, UNIT_HERTZ),
+                              TALK_ID(1400, UNIT_HERTZ)),NULL),
+    CHOICE_ITEM(0,eq_hw_band2_bandwidth,LANG_EQUALIZER_BANDWIDTH,
+                "eq hardware band 2 bandwidth,narrow,wide", 0,NULL,2,
+                LANG_EQUALIZER_HARDWARE_BANDWIDTH_NARROW,
+                LANG_EQUALIZER_HARDWARE_BANDWIDTH_WIDE),
+    INT_ITEM(F_LANG_HARDWARE,eq_hw_band2_gain,LANG_EQUALIZER_BAND_GAIN,0,
+             EQ_HW_GAIN_MIN,EQ_HW_GAIN_MAX,EQ_HW_GAIN_STEP,UNIT_DB,
+             NULL, NULL, "eq hardware band 2 gain"),
+    /* band 3 */
+    STRINGCHOICE_ITEM(0,eq_hw_band3_center,LANG_EQUALIZER_BAND_CENTER,
+                      "eq hardware band 3 center",1,4,
+                      _STR("1800Hz","2400Hz","3200Hz","4100Hz"),
+                      _TALKID(TALK_ID(1800, UNIT_HERTZ),TALK_ID(2400, UNIT_HERTZ),
+                              TALK_ID(3200, UNIT_HERTZ),
+                              TALK_ID(4100, UNIT_HERTZ)),NULL),
+    CHOICE_ITEM(0,eq_hw_band3_bandwidth,LANG_EQUALIZER_BANDWIDTH
+            "eq hardware band 3 bandwidth,narrow,wide", 0,NULL,2,
+                LANG_EQUALIZER_HARDWARE_BANDWIDTH_NARROW,
+                LANG_EQUALIZER_HARDWARE_BANDWIDTH_WIDE),
+    INT_ITEM(F_LANG_HARDWARE,eq_hw_band3_gain,LANG_EQUALIZER_BAND_GAIN,0,
+             EQ_HW_GAIN_MIN,EQ_HW_GAIN_MAX,EQ_HW_GAIN_STEP,
+             UNIT_DB, NULL, NULL,"eq hardware band 3 gain"),
+    /* band 4 */
+    STRINGCHOICE_ITEM(0,eq_hw_band4_cutoff,LANG_EQUALIZER_BAND_CUTOFF,
+                      "eq hardware band 4 cutoff",1,4,
+                      _STR("5300Hz","6900Hz","9000Hz","11700Hz"),
+                      _TALKID(TALK_ID(5300, UNIT_HERTZ),TALK_ID(6900, UNIT_HERTZ),
+                              TALK_ID(9000, UNIT_HERTZ),
+                              TALK_ID(11700, UNIT_HERTZ)),NULL),
+    INT_ITEM(0,eq_band4_gain,LANG_EQUALIZER_BAND_GAIN,0,
+             EQ_HW_GAIN_MIN,EQ_HW_GAIN_MAX,EQ_HW_GAIN_STEP,
+             UNIT_DB, NULL, NULL,"eq hardware band 4 gain"),
+#endif /* HAVE_WM8758 */
+
+/*    BOOL_ITEM(0,hold_lr_for_scroll_in_list,
+              LANG_HOLD_DIRECTION_FOR_SCROLL, true,NULL,
+              "hold_lr_for_scroll_in_list"),
+*/    CHOICE_ITEM(0,show_path_in_browser,LANG_SHOW_PATH,
+                "show path in browser,off,current directory,full path",0,NULL,3,
+                LANG_OFF,LANG_SHOW_PATH_CURRENT, LANG_SHOW_PATH_FULL),
+
+#ifdef HAVE_AGC
+    /* active gain control */
+    CHOICE_ITEM(0,rec_agc_preset_mic,LANG_RECORD_AGC_PRESET,
+                "agc mic preset", 1,NULL,6,
+                LANG_OFF,LANG_AGC_SAFETY, LANG_AGC_LIVE,
+                LANG_AGC_DJSET, LANG_AGC_MEDIUM, LANG_AGC_VOICE),
+    CHOICE_ITEM(0,rec_agc_preset_line,LANG_RECORD_AGC_PRESET,
+                "agc line preset", 1,NULL,6,
+                LANG_OFF,LANG_AGC_SAFETY, LANG_AGC_LIVE,
+                LANG_AGC_DJSET, LANG_AGC_MEDIUM, LANG_AGC_VOICE),
+    SYSTEM_ITEM(F_T_INT,rec_agc_maxgain_mic,104, NULL),
+    SYSTEM_ITEM(F_T_INT,rec_agc_maxgain_line,96, NULL),
+    STRINGCHOICE_ITEM(0,rec_agc_cliptime,LANG_RECORD_AGC_CLIPTIME,
+                      "agc cliptime",1,5,
+                      _STR("0.2s","0.4s","0.6s","0.8s","1s"),
+                      _TALKID(TALK_ID(200, UNIT_MS),TALK_ID(400, UNIT_MS),
+                              TALK_ID(600, UNIT_MS),TALK_ID(800, UNIT_MS),
+                              TALK_ID(1, UNIT_SEC)),NULL),
+#endif /* HAVE_AGC */
+
+#ifdef HAVE_REMOTE_LCD
+#ifdef HAS_REMOTE_BUTTON_HOLD
+    CHOICE_ITEM(0,remote_backlight_on_button_hold,LANG_BACKLIGHT_ON_BUTTON_HOLD,
+                      "remote backlight on button hold,normal,off,on",0,NULL,3,
+                  LANG_BACKLIGHT_ON_BUTTON_HOLD_NORMAL,LANG_OFF,LANG_ON),
+#endif
+#endif /* HAVE_REMOTE_LCD */
+
+    /* filename storage */
+#ifdef CONFIG_TUNER
+    STRING_ITEM(F_FILENAMEONLY|F_THEMESETTING,fmr_file,"fmr","",NULL),
+#endif
+    STRING_ITEM(F_FILENAMEONLY|F_THEMESETTING,font_file,"font","",NULL),
+    STRING_ITEM(F_FILENAMEONLY|F_THEMESETTING,wps_file,"wps","",NULL),
+#ifdef HAVE_REMOTE_LCD
+    STRING_ITEM(F_FILENAMEONLY|F_THEMESETTING,rwps_file,"rwps","",NULL),
+#endif
+    STRING_ITEM(F_FILENAMEONLY,lang_file,"lang","",NULL),
+#ifdef HAVE_LCD_COLOR
+    STRING_ITEM(F_FILENAMEONLY|F_THEMESETTING,backdrop_file,"backdrop","",NULL),
+#endif
+#ifdef HAVE_LCD_BITMAP
+    STRING_ITEM(F_FILENAMEONLY,kbd_file,"keyboard","",NULL),
+#endif
+#ifdef HAVE_HEADPHONE_DETECTION
+    CHOICE_ITEM(0,unplug_mode,LANG_UNPLUG,
+                "pause on headphone unplug,off,pause,resume", 0,NULL,3,
+                LANG_OFF,LANG_PAUSE, LANG_UNPLUG_RESUME),
+    INT_ITEM(0,unplug_rw,LANG_UNPLUG_RW,0,
+             0,15,1,UNIT_SEC, NULL, NULL,"rewind duration on pause"),
+    BOOL_ITEM(0,unplug_autoresume,
+              LANG_UNPLUG_DISABLE_AUTORESUME, false, NULL,
+              "disable autoresume if phones not present"),
+#endif
+    BOOL_ITEM(0,audioscrobbler,
+              LANG_AUDIOSCROBBLER, false, NULL,
+              "Last.fm Logging"),
+
+};
+const int nb_settings = sizeof(settings) / sizeof(*settings);
Index: apps/settings_list.h
===================================================================
RCS file: apps/settings_list.h
diff -N apps/settings_list.h
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ apps/settings_list.h	15 Nov 2006 08:00:25 -0000
@@ -0,0 +1,89 @@
+/***************************************************************************
+ *             __________               __   ___.
+ *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
+ *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
+ *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
+ *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
+ *                     \/            \/     \/    \/            \/
+ * $Id:  $
+ *
+ * Copyright (C) 2006 Jonathan Gordon
+ *
+ * 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.
+ *
+ ****************************************************************************/
+#ifndef __SETTINGSLIST_H
+#define __SETTINGSLIST_H
+#include "config.h"
+
+union storage_type {
+    int int_;
+    unsigned int uint_;
+    bool bool_;
+    char *charptr;
+    unsigned char *ucharptr;
+};
+/* the variable type for the setting */
+#define F_T_INT     1
+#define F_T_UINT    2
+#define F_T_BOOL    3
+#define F_T_CHARPTR 4
+#define F_T_UCHARPTR 5
+#define F_T_MASK    0x7     /* we can go up to 7 types, 3 bits should be enough */
+#define F_T_SOUND   0x8     /* this variable uses the set_sound stuff, | with one of the above types \
+                               values[0] = setting type */
+                            
+#define F_T_CHOICE  0x10    /* this variable is a "choice" type, \
+                               if this is not set then values[0] = min, values[1] = max, values[2] = step   \
+                               talk_id[0] = talk unit                                                       */
+#define F_LANG_STRING 0x20  /* this variable uses *strings in the union for the values, donot try to xlate  \
+                               unless talk_id is NULL it will try to talk the corresponding value there     \
+                               talk_id is only needed to be filled if this is set */
+                               
+#define F_LANG_REMOTE 0x40  /* prepends "Remote " to the setting name in the config file */
+#define F_LANG_HARDWARE 0x80  /* prepends "Hardware " to the setting name in the config file */
+/* F_LANG_REMOTE and F_LANG_HARDWARE are mutually exclusive... */
+
+#define F_LANG_IS_STRING 0x100 /* use this if the cfg_string vairable is used instead of cfg_lang_id */
+#define F_TEMPVARIABLE  0x200 /* set this to have only set the new value after it has been accepted, i.e for lcd mod */
+#define F_STORERGB      0x400 /* save it as rgb in the text file, but store as LCDPACK() */
+#define F_SYSTEMSETTING 0x800 /* if set it will be saved in data.dat not config.cfg */
+
+#define F_STOREREALVALUE 0x1000 /* use this to store a real value instead of the index into the values/strings array */
+#define F_SAVETORTC     0x2000 /* use this if the setting must be saved to non-volatile RAM if the target has */
+#define F_FILENAMEONLY  0x4000 /* use this for string settings which need to have the path removed */
+#define F_THEMESETTING  0x8000 /* only settings with this flag will be saved when saving a theme */
+
+struct settings_list {
+    int                 flags;     /* ____ ____ ____ ____ TFRV SRTS HRSC STTT */
+    void                *setting;  /* the variable in global_settings, use GS() macro for this */
+    union storage_type default_val;
+    union {
+        int             cfg_lang_id;  /* lang_id of this variable in the .cfg file */
+        char           *cfg_string;   /* for system settings which are not translated */
+    };
+    int                 nb_values; /* # of values, ignored unless F_T_CHOICE is set */
+    union {
+        int             *values;    /* If F_T_CHOICE is not set and (F_T_MASK!=F_T_BOOL)        */
+        char           **strings;   /*    then values[0] = min, [1]=max, [2]=step. [3]=formatter   */
+    };
+    int                *talk_id;
+    void        (*function)(bool);  /* callback to pass to set_option() */
+    char               *conf_file_info; /* comma seperated list,
+                                           the first item is the setting name, 
+                                    then all the valid options, BOOL and INT only need to setting name */
+    /* If F_T_SOUND is set then default_val, values and nb_values are ignored */ 
+};
+
+#ifndef PLUGIN
+/* not needed for plugins and just causes compile error, possibly fix proberly later */
+extern const int nb_settings;
+extern const struct settings_list  settings[];
+#endif
+    
+    
+#endif
Index: apps/sound_menu.h
===================================================================
RCS file: /cvsroot/rockbox/apps/sound_menu.h,v
retrieving revision 1.7
diff -u -r1.7 sound_menu.h
--- apps/sound_menu.h	26 Mar 2006 22:33:25 -0000	1.7
+++ apps/sound_menu.h	15 Nov 2006 08:00:25 -0000
@@ -7,7 +7,7 @@
  *                     \/            \/     \/    \/            \/
  * $Id: sound_menu.h,v 1.7 2006-03-26 22:33:25 linus Exp $
  *
- * Copyright (C) 2002 Björn Stenberg
+ * Copyright (C) 2002 Bjï¿½n Stenberg
  *
  * 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.
@@ -22,8 +22,6 @@
 #include "menu.h"
 
 bool sound_menu(void);
-bool recording_menu(bool no_source);
-bool rectrigger(void);
 bool set_sound(const unsigned char * string, int* variable, int setting);
 
 #endif
Index: apps/tagcache.c
===================================================================
RCS file: /cvsroot/rockbox/apps/tagcache.c,v
retrieving revision 1.77
diff -u -r1.77 tagcache.c
--- apps/tagcache.c	10 Nov 2006 09:52:46 -0000	1.77
+++ apps/tagcache.c	15 Nov 2006 08:00:28 -0000
@@ -3804,23 +3804,23 @@
     queue_post(&tagcache_queue, Q_START_SCAN, 0);
 }
 
-bool tagcache_update(void)
+int tagcache_update(void)
 {
     if (!tc_stat.ready)
-        return false;
+        return 0;
     
     queue_post(&tagcache_queue, Q_UPDATE, 0);
     gui_syncsplash(HZ*2, true, str(LANG_TAGCACHE_FORCE_UPDATE_SPLASH));
     
-    return false;
+    return 0;
 }
 
-bool tagcache_rebuild(void)
+int tagcache_rebuild(void)
 {
     queue_post(&tagcache_queue, Q_REBUILD, 0);
     gui_syncsplash(HZ*2, true, str(LANG_TAGCACHE_FORCE_UPDATE_SPLASH));
     
-    return false;
+    return 0;
 }
 
 void tagcache_stop_scan(void)
Index: apps/tagcache.h
===================================================================
RCS file: /cvsroot/rockbox/apps/tagcache.h,v
retrieving revision 1.30
diff -u -r1.30 tagcache.h
--- apps/tagcache.h	10 Nov 2006 08:03:22 -0000	1.30
+++ apps/tagcache.h	15 Nov 2006 08:00:29 -0000
@@ -182,8 +182,8 @@
 bool tagcache_is_initialized(void);
 void tagcache_start_scan(void);
 void tagcache_stop_scan(void);
-bool tagcache_update(void);
-bool tagcache_rebuild(void);
+int tagcache_update(void);
+int tagcache_rebuild(void);
 
 #endif
 #endif
Index: apps/tagtree.c
===================================================================
RCS file: /cvsroot/rockbox/apps/tagtree.c,v
retrieving revision 1.56
diff -u -r1.56 tagtree.c
--- apps/tagtree.c	11 Nov 2006 17:39:37 -0000	1.56
+++ apps/tagtree.c	15 Nov 2006 08:00:30 -0000
@@ -666,7 +666,7 @@
     tagcache_search_finish(&tcs);
 }
 
-bool tagtree_export(void)
+int tagtree_export(void)
 {
     gui_syncsplash(0, true, str(LANG_CREATING));
     if (!tagcache_create_changelog(&tcs))
@@ -674,10 +674,10 @@
         gui_syncsplash(HZ*2, true, str(LANG_FAILED));
     }
     
-    return false;
+    return 0;
 }
 
-bool tagtree_import(void)
+int tagtree_import(void)
 {
     gui_syncsplash(0, true, str(LANG_WAIT));
     if (!tagcache_import_changelog())
@@ -685,7 +685,7 @@
         gui_syncsplash(HZ*2, true, str(LANG_FAILED));
     }
     
-    return false;
+    return 0;
 }
 
 static bool parse_menu(const char *filename);
Index: apps/tagtree.h
===================================================================
RCS file: /cvsroot/rockbox/apps/tagtree.h,v
retrieving revision 1.14
diff -u -r1.14 tagtree.h
--- apps/tagtree.h	25 Oct 2006 10:17:56 -0000	1.14
+++ apps/tagtree.h	15 Nov 2006 08:00:30 -0000
@@ -36,8 +36,8 @@
     int extraseek;
 };
 
-bool tagtree_export(void);
-bool tagtree_import(void);
+int tagtree_export(void);
+int tagtree_import(void);
 void tagtree_init(void);
 int tagtree_enter(struct tree_context* c);
 void tagtree_exit(struct tree_context* c);
Index: apps/tree.c
===================================================================
RCS file: /cvsroot/rockbox/apps/tree.c,v
retrieving revision 1.455
diff -u -r1.455 tree.c
--- apps/tree.c	13 Nov 2006 00:45:20 -0000	1.455
+++ apps/tree.c	15 Nov 2006 08:00:32 -0000
@@ -31,7 +31,6 @@
 #include "kernel.h"
 #include "usb.h"
 #include "tree.h"
-#include "main_menu.h"
 #include "sprintf.h"
 #include "audio.h"
 #include "playlist.h"
@@ -640,7 +639,7 @@
             sleep(HZ);
 #endif
             recording_screen(false);
-            rec_menu();
+            recording_menu();
             main_menu();
         }
         else
Index: apps/gui/gwps.c
===================================================================
RCS file: /cvsroot/rockbox/apps/gui/gwps.c,v
retrieving revision 1.54
diff -u -r1.54 gwps.c
--- apps/gui/gwps.c	13 Nov 2006 00:45:21 -0000	1.54
+++ apps/gui/gwps.c	15 Nov 2006 08:00:33 -0000
@@ -37,7 +37,7 @@
 #include "audio.h"
 #include "usb.h"
 #include "status.h"
-#include "main_menu.h"
+#include "menu.h"
 #include "ata.h"
 #include "screens.h"
 #include "playlist.h"
Index: apps/gui/statusbar.c
===================================================================
RCS file: /cvsroot/rockbox/apps/gui/statusbar.c,v
retrieving revision 1.33
diff -u -r1.33 statusbar.c
--- apps/gui/statusbar.c	6 Nov 2006 18:07:26 -0000	1.33
+++ apps/gui/statusbar.c	15 Nov 2006 08:00:34 -0000
@@ -772,3 +772,4 @@
         gui_statusbar_draw( &(bars->statusbars[i]), force_redraw );
     }
 }
+
Index: apps/gui/statusbar.h
===================================================================
RCS file: /cvsroot/rockbox/apps/gui/statusbar.h,v
retrieving revision 1.17
diff -u -r1.17 statusbar.h
--- apps/gui/statusbar.h	2 Sep 2006 17:30:30 -0000	1.17
+++ apps/gui/statusbar.h	15 Nov 2006 08:00:34 -0000
@@ -121,5 +121,4 @@
 
 extern void gui_syncstatusbar_init(struct gui_syncstatusbar * bars);
 extern void gui_syncstatusbar_draw(struct gui_syncstatusbar * bars, bool force_redraw);
-
 #endif /*_GUI_STATUSBAR_H_*/
Index: apps/lang/english.lang
===================================================================
RCS file: /cvsroot/rockbox/apps/lang/english.lang,v
retrieving revision 1.297
diff -u -r1.297 english.lang
--- apps/lang/english.lang	11 Nov 2006 01:18:57 -0000	1.297
+++ apps/lang/english.lang	15 Nov 2006 08:00:40 -0000
@@ -10224,3 +10224,59 @@
     *: ""
   </voice>
 </phrase>
+<phrase>
+  id: LANG_HOLD_DIRECTION_FOR_SCROLL
+  desc: hold direction arrows to scroll filename
+  user:
+  <source>
+    *: "Hold left/right to scroll filename"
+  </source>
+  <dest>
+    *: "Hold left/right to scroll filename"
+  </dest>
+  <voice>
+    *: ""
+  </voice>
+</phrase>
+<phrase>
+  id: LANG_ONCE
+  desc: once
+  user:
+  <source>
+    *: "Once"
+  </source>
+  <dest>
+    *: "Once"
+  </dest>
+  <voice>
+    *: "Once"
+  </voice>
+</phrase>
+<phrase>
+  id: LANG_MAIN_MENU
+  desc: main menu text
+  user:
+  <source>
+    *: "Main Menu"
+  </source>
+  <dest>
+    *: "Main Menu"
+  </dest>
+  <voice>
+    *: "Main Menu"
+  </voice>
+</phrase>
+<phrase>
+  id: LANG_USER_MENU
+  desc: user menu text
+  user:
+  <source>
+    *: "User Menu"
+  </source>
+  <dest>
+    *: "User Menu"
+  </dest>
+  <voice>
+    *: "User Menu"
+  </voice>
+</phrase>
\ No newline at end of file
Index: apps/player/icons.h
===================================================================
RCS file: /cvsroot/rockbox/apps/player/icons.h,v
retrieving revision 1.9
diff -u -r1.9 icons.h
--- apps/player/icons.h	16 Nov 2005 02:12:25 -0000	1.9
+++ apps/player/icons.h	15 Nov 2006 08:00:40 -0000
@@ -31,7 +31,8 @@
     Icon_Queued = 'Q',
     Icon_Moving = 'M',
     Icon_Unknown = 0x90,
-    Icon_Bookmark = 0x16,
+    Icon_Checkmark = 0x15,
+    Icon_Bookmark,
     Icon_Plugin,
     Icon_Folder,
     Icon_Firmware,
@@ -40,7 +41,7 @@
     Icon_Wps,
     Icon_Playlist,
     Icon_Text,
-    Icon_Config,
+    Icon_Config
 };
 
 #endif
Index: apps/recorder/icons.c
===================================================================
RCS file: /cvsroot/rockbox/apps/recorder/icons.c,v
retrieving revision 1.87
diff -u -r1.87 icons.c
--- apps/recorder/icons.c	6 Nov 2006 18:07:27 -0000	1.87
+++ apps/recorder/icons.c	15 Nov 2006 08:00:41 -0000
@@ -62,6 +62,7 @@
     { 0x3e, 0x41, 0x3e, 0x1c, 0x1c, 0x08 }, /* Moving Item */
     { 0x7f, 0x7f, 0x1c, 0x3e, 0x77, 0x63 }, /* Keyboard file */
     { 0x00, 0x00, 0x00, 0x08, 0x1c, 0x3e }, /* Reverse Cursor / Marker */
+    { 0x38, 0x70, 0x38, 0x1c, 0x0e, 0x07 }, /* Checkmark */
 };
 
 const unsigned char bitmap_icons_7x8[][7] =
Index: apps/recorder/icons.h
===================================================================
RCS file: /cvsroot/rockbox/apps/recorder/icons.h,v
retrieving revision 1.67
diff -u -r1.67 icons.h
--- apps/recorder/icons.h	6 Nov 2006 18:07:27 -0000	1.67
+++ apps/recorder/icons.h	15 Nov 2006 08:00:42 -0000
@@ -64,6 +64,7 @@
     Icon_Moving,
     Icon_Keyboard,
     Icon_Reverse_Cursor,
+    Icon_Checkmark,
     Icon6x8Last,
 };
 
Index: apps/recorder/radio.c
===================================================================
RCS file: /cvsroot/rockbox/apps/recorder/radio.c,v
retrieving revision 1.114
diff -u -r1.114 radio.c
--- apps/recorder/radio.c	6 Nov 2006 18:07:27 -0000	1.114
+++ apps/recorder/radio.c	15 Nov 2006 08:00:43 -0000
@@ -43,7 +43,6 @@
 #include "peakmeter.h"
 #include "lang.h"
 #include "font.h"
-#include "sound_menu.h"
 #include "recording.h"
 #include "talk.h"
 #include "tuner.h"
@@ -1528,7 +1527,7 @@
 #define FM_RECORDING_SETTINGS
 static bool fm_recording_settings(void)
 {
-    bool ret = recording_menu(true);
+    bool ret = recording_menu();
 
 #if CONFIG_CODEC != SWCODEC
     if (!ret)
Index: apps/recorder/recording.c
===================================================================
RCS file: /cvsroot/rockbox/apps/recorder/recording.c,v
retrieving revision 1.146
diff -u -r1.146 recording.c
--- apps/recorder/recording.c	13 Nov 2006 23:21:52 -0000	1.146
+++ apps/recorder/recording.c	15 Nov 2006 08:00:46 -0000
@@ -58,7 +58,6 @@
 #include "peakmeter.h"
 #include "statusbar.h"
 #include "menu.h"
-#include "sound_menu.h"
 #include "timefuncs.h"
 #include "debug.h"
 #include "misc.h"
@@ -74,8 +73,14 @@
 #include "screen_access.h"
 #include "action.h"
 #include "radio.h"
+#include "widgets.h"
 #ifdef HAVE_RECORDING
 
+/* these are at the bottom of the file */
+unsigned int rec_timesplit_seconds(void);
+unsigned long rec_sizesplit_bytes(void);
+void settings_apply_trigger(void);
+
 #define PM_HEIGHT ((LCD_HEIGHT >= 72) ? 2 : 1)
 
 #if CONFIG_KEYPAD == RECORDER_PAD
@@ -891,6 +896,7 @@
 
     struct audio_recording_options rec_options;
 
+    (void)no_source;
     global_settings.recscreen_on = true;
     cursor = 0;
 #if (CONFIG_LED == LED_REAL) && !defined(SIMULATOR)
@@ -1280,7 +1286,7 @@
                     /* led is restored at begin of loop / end of function */
                     led(false);
 #endif
-                    if (recording_menu(no_source))
+                    if (recording_menu())
                     {
                         done = true;
                         been_in_usb_mode = true;
@@ -2056,7 +2062,7 @@
             case BUTTON_DOWN:
             case BUTTON_F3 | BUTTON_DOWN:
 #ifndef SIMULATOR
-                rectrigger();
+                //rectrigger(); FIXME
                 settings_apply_trigger();
 #endif
                 exit = true;
@@ -2200,5 +2206,466 @@
 #endif /* #ifdef SIMULATOR */
 #endif /* #ifdef CONFIG_CODEC == SWCODEC */
 
+int rec_menu_recording_screen(void)
+{
+    return recording_screen(false);
+}
 
+enum trigger_menu_option
+{
+    TRIGGER_MODE,
+    PRERECORD_TIME,
+    START_THRESHOLD,
+    START_DURATION,
+    STOP_THRESHOLD,
+    STOP_POSTREC,
+    STOP_GAP,
+    TRIG_OPTION_COUNT,
+};
+
+#if !defined(SIMULATOR) && CONFIG_CODEC == MAS3587F
+static char* create_thres_str(int threshold)
+{
+    static char retval[6];
+    if (threshold < 0) {
+        if (threshold < -88) {
+            snprintf (retval, sizeof retval, "%s", str(LANG_DB_INF));
+        } else {
+            snprintf (retval, sizeof retval, "%ddb", threshold + 1);
+        }
+    } else {
+        snprintf (retval, sizeof retval, "%d%%", threshold);
+    }
+    return retval;
+}
+
+#define INF_DB (-89)
+static void change_threshold(int *threshold, int change)
+{
+    if (global_settings.peak_meter_dbfs) {
+        if (*threshold >= 0) {
+            int db = (calc_db(*threshold * MAX_PEAK / 100) - 9000) / 100;
+            *threshold = db;
+        }
+        *threshold += change;
+        if (*threshold > -1) {
+            *threshold = INF_DB;
+        } else if (*threshold < INF_DB) {
+            *threshold = -1;
+        }
+    } else {
+        if (*threshold < 0) {
+            *threshold = peak_meter_db2sample(*threshold * 100) * 100 / MAX_PEAK;
+        }
+        *threshold += change;
+        if (*threshold > 100) {
+            *threshold = 0;
+        } else if (*threshold < 0) {
+            *threshold = 100;
+        }
+    }
+}
+
+/* Variable button definitions */
+#if CONFIG_KEYPAD == RECORDER_PAD
+#define TRIG_CANCEL BUTTON_OFF
+#define TRIG_ACCEPT BUTTON_PLAY
+#define TRIG_RESET_SIM BUTTON_F2
+
+#elif CONFIG_KEYPAD == ONDIO_PAD
+#define TRIG_CANCEL BUTTON_OFF
+#define TRIG_ACCEPT BUTTON_MENU
+#endif
+
+/**
+ * Displays a menu for editing the trigger settings.
+ */
+int rectrigger(void)
+{
+    int exit_request = false;
+    enum trigger_menu_option selected = TRIGGER_MODE;
+    bool retval = false;
+    int old_x_margin, old_y_margin;
+
+#define TRIGGER_MODE_COUNT 3
+    static const unsigned char *trigger_modes[] = {
+    ID2P(LANG_OFF),
+    ID2P(LANG_RECORD_TRIG_NOREARM),
+    ID2P(LANG_RECORD_TRIG_REARM)
+    };
+
+#define PRERECORD_TIMES_COUNT 31
+    static const unsigned char *prerecord_times[] = {
+    ID2P(LANG_OFF),"1s","2s", "3s", "4s", "5s", "6s", "7s", "8s", "9s",
+    "10s", "11s", "12s", "13s", "14s", "15s", "16s", "17s", "18s", "19s",
+    "20s", "21s", "22s", "23s", "24s", "25s", "26s", "27s", "28s", "29s",
+    "30s"
+    };
+
+    static const unsigned char *option_name[] = {
+        [TRIGGER_MODE] =    ID2P(LANG_RECORD_TRIGGER_MODE),
+        [PRERECORD_TIME] =  ID2P(LANG_RECORD_PRERECORD_TIME),
+        [START_THRESHOLD] = ID2P(LANG_RECORD_START_THRESHOLD),
+        [START_DURATION] =  ID2P(LANG_RECORD_MIN_DURATION),
+        [STOP_THRESHOLD] =  ID2P(LANG_RECORD_STOP_THRESHOLD),
+        [STOP_POSTREC] =    ID2P(LANG_RECORD_STOP_POSTREC),
+        [STOP_GAP] =        ID2P(LANG_RECORD_STOP_GAP)
+    };
+
+    int old_start_thres = global_settings.rec_start_thres;
+    int old_start_duration = global_settings.rec_start_duration;
+    int old_prerecord_time = global_settings.rec_prerecord_time;
+    int old_stop_thres = global_settings.rec_stop_thres;
+    int old_stop_postrec = global_settings.rec_stop_postrec;
+    int old_stop_gap = global_settings.rec_stop_gap;
+    int old_trigger_mode = global_settings.rec_trigger_mode;
+
+    int offset = 0;
+    int option_lines;
+    int w, h;
+    /* array for y ordinate of peak_meter_draw_get_button
+    function in peakmeter.c*/
+    int pm_y[NB_SCREENS];
+
+    /* restart trigger with new values */
+    settings_apply_trigger();
+    peak_meter_trigger (global_settings.rec_trigger_mode != TRIG_MODE_OFF);
+
+    lcd_clear_display();
+
+    old_x_margin = lcd_getxmargin();
+    old_y_margin = lcd_getymargin();
+    if(global_settings.statusbar)
+        lcd_setmargins(0, STATUSBAR_HEIGHT);
+    else
+        lcd_setmargins(0, 0);
+
+    lcd_getstringsize("M", &w, &h);
+
+    // two lines are reserved for peak meter and trigger status
+    option_lines = (LCD_HEIGHT/h) - (global_settings.statusbar ? 1:0) - 2;
+
+    while (!exit_request) {
+        int stat_height = global_settings.statusbar ? STATUSBAR_HEIGHT : 0;
+        int button, i;
+        const char *str;
+        char option_value[TRIG_OPTION_COUNT][7];
+
+        snprintf(
+                option_value[TRIGGER_MODE],
+        sizeof option_value[TRIGGER_MODE],
+        "%s",
+        P2STR(trigger_modes[global_settings.rec_trigger_mode]));
+
+        snprintf (
+                option_value[PRERECORD_TIME],
+        sizeof option_value[PRERECORD_TIME],
+        "%s",
+        P2STR(prerecord_times[global_settings.rec_prerecord_time]));
+
+        /* due to value range shift (peak_meter_define_trigger) -1 is 0db */
+        if (global_settings.rec_start_thres == -1) {
+            str = str(LANG_OFF);
+        } else {
+            str = create_thres_str(global_settings.rec_start_thres);
+        }
+        snprintf(
+                option_value[START_THRESHOLD],
+        sizeof option_value[START_THRESHOLD],
+        "%s",
+        str);
+
+        snprintf(
+                option_value[START_DURATION],
+        sizeof option_value[START_DURATION],
+        "%s",
+        trig_durations[global_settings.rec_start_duration]);
+
+
+        if (global_settings.rec_stop_thres <= INF_DB) {
+            str = str(LANG_OFF);
+        } else {
+            str = create_thres_str(global_settings.rec_stop_thres);
+        }
+        snprintf(
+                option_value[STOP_THRESHOLD],
+        sizeof option_value[STOP_THRESHOLD],
+        "%s",
+        str);
+
+        snprintf(
+                option_value[STOP_POSTREC],
+        sizeof option_value[STOP_POSTREC],
+        "%s",
+        trig_durations[global_settings.rec_stop_postrec]);
+
+        snprintf(
+                option_value[STOP_GAP],
+        sizeof option_value[STOP_GAP],
+        "%s",
+        trig_durations[global_settings.rec_stop_gap]);
+
+        lcd_set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID);
+        lcd_fillrect(0, stat_height, LCD_WIDTH, LCD_HEIGHT - stat_height);
+        lcd_set_drawmode(DRMODE_SOLID);
+        gui_syncstatusbar_draw(&statusbars, true);
+
+        /* reselect FONT_SYSFONT as status_draw has changed the font */
+        /*lcd_setfont(FONT_SYSFIXED);*/
+
+        for (i = 0; i < option_lines; i++) {
+            int x, y;
+
+            str = P2STR(option_name[i + offset]);
+            lcd_putsxy(5, stat_height + i * h, str);
+
+            str = option_value[i + offset];
+            lcd_getstringsize(str, &w, &h);
+            y = stat_height + i * h;
+            x = LCD_WIDTH - w;
+            lcd_putsxy(x, y, str);
+            if ((int)selected == (i + offset)) {
+                lcd_set_drawmode(DRMODE_COMPLEMENT);
+                lcd_fillrect(x, y, w, h);
+                lcd_set_drawmode(DRMODE_SOLID);
+            }
+        }
+
+        scrollbar(0, stat_height,
+                  4, LCD_HEIGHT - 16 - stat_height,
+                  TRIG_OPTION_COUNT, offset, offset + option_lines,
+                  VERTICAL);
+
+        peak_meter_draw_trig(0, LCD_HEIGHT - 8 - TRIG_HEIGHT);
+
+        FOR_NB_SCREENS(i)
+                pm_y[i] = screens[i].height - 8;
+        button = peak_meter_draw_get_btn(0, pm_y, 8, NB_SCREENS);
+
+        lcd_update();
+
+        switch (button) {
+            case TRIG_CANCEL:
+                gui_syncsplash(50, true, str(LANG_MENU_SETTING_CANCEL));
+                global_settings.rec_start_thres = old_start_thres;
+                global_settings.rec_start_duration = old_start_duration;
+                global_settings.rec_prerecord_time = old_prerecord_time;
+                global_settings.rec_stop_thres = old_stop_thres;
+                global_settings.rec_stop_postrec = old_stop_postrec;
+                global_settings.rec_stop_gap = old_stop_gap;
+                global_settings.rec_trigger_mode = old_trigger_mode;
+                exit_request = true;
+                break;
+
+            case TRIG_ACCEPT:
+                exit_request = true;
+                break;
+
+            case BUTTON_UP:
+                selected += TRIG_OPTION_COUNT - 1;
+                selected %= TRIG_OPTION_COUNT;
+                offset = MIN(offset, (int)selected);
+                offset = MAX(offset, (int)selected - option_lines + 1);
+                break;
+
+            case BUTTON_DOWN:
+                selected ++;
+                selected %= TRIG_OPTION_COUNT;
+                offset = MIN(offset, (int)selected);
+                offset = MAX(offset, (int)selected - option_lines + 1);
+                break;
+
+            case BUTTON_RIGHT:
+            case BUTTON_RIGHT | BUTTON_REPEAT:
+                switch (selected) {
+                    case TRIGGER_MODE:
+                        global_settings.rec_trigger_mode ++;
+                        global_settings.rec_trigger_mode %= TRIGGER_MODE_COUNT;
+                        break;
+
+                    case PRERECORD_TIME:
+                        global_settings.rec_prerecord_time ++;
+                        global_settings.rec_prerecord_time %= PRERECORD_TIMES_COUNT;
+                        break;
+
+                    case START_THRESHOLD:
+                        change_threshold(&global_settings.rec_start_thres, 1);
+                        break;
+
+                    case START_DURATION:
+                        global_settings.rec_start_duration ++;
+                        global_settings.rec_start_duration %= TRIG_DURATION_COUNT;
+                        break;
+
+                    case STOP_THRESHOLD:
+                        change_threshold(&global_settings.rec_stop_thres, 1);
+                        break;
+
+                    case STOP_POSTREC:
+                        global_settings.rec_stop_postrec ++;
+                        global_settings.rec_stop_postrec %= TRIG_DURATION_COUNT;
+                        break;
+
+                    case STOP_GAP:
+                        global_settings.rec_stop_gap ++;
+                        global_settings.rec_stop_gap %= TRIG_DURATION_COUNT;
+                        break;
+
+                    case TRIG_OPTION_COUNT:
+                        // avoid compiler warnings
+                        break;
+                }
+                peak_meter_trigger(global_settings.rec_trigger_mode!=TRIG_OFF);
+                settings_apply_trigger();
+                break;
+
+            case BUTTON_LEFT:
+            case BUTTON_LEFT | BUTTON_REPEAT:
+                switch (selected) {
+                    case TRIGGER_MODE:
+                        global_settings.rec_trigger_mode+=TRIGGER_MODE_COUNT-1;
+                        global_settings.rec_trigger_mode %= TRIGGER_MODE_COUNT;
+                        break;
+
+                    case PRERECORD_TIME:
+                        global_settings.rec_prerecord_time += PRERECORD_TIMES_COUNT - 1;
+                        global_settings.rec_prerecord_time %= PRERECORD_TIMES_COUNT;
+                        break;
+
+                    case START_THRESHOLD:
+                        change_threshold(&global_settings.rec_start_thres, -1);
+                        break;
+
+                    case START_DURATION:
+                        global_settings.rec_start_duration += TRIG_DURATION_COUNT-1;
+                        global_settings.rec_start_duration %= TRIG_DURATION_COUNT;
+                        break;
+
+                    case STOP_THRESHOLD:
+                        change_threshold(&global_settings.rec_stop_thres, -1);
+                        break;
+
+                    case STOP_POSTREC:
+                        global_settings.rec_stop_postrec +=
+                                TRIG_DURATION_COUNT - 1;
+                        global_settings.rec_stop_postrec %=
+                                TRIG_DURATION_COUNT;
+                        break;
+
+                    case STOP_GAP:
+                        global_settings.rec_stop_gap +=
+                                TRIG_DURATION_COUNT - 1;
+                        global_settings.rec_stop_gap %= TRIG_DURATION_COUNT;
+                        break;
+
+                    case TRIG_OPTION_COUNT:
+                        // avoid compiler warnings
+                        break;
+                }
+                peak_meter_trigger(global_settings.rec_trigger_mode!=TRIG_OFF);
+                settings_apply_trigger();
+                break;
+
+#ifdef TRIG_RESET_SIM
+            case TRIG_RESET_SIM:
+                peak_meter_trigger(true);
+                break;
+#endif
+
+            case SYS_USB_CONNECTED:
+                if(default_event_handler(button) == SYS_USB_CONNECTED) {
+                    retval = true;
+                    exit_request = true;
+                }
+                break;
+        }
+    }
+
+    peak_meter_trigger(false);
+    lcd_setfont(FONT_UI);
+    lcd_setmargins(old_x_margin, old_y_margin);
+    return (int)retval;
+}
+#endif  /* !defined(SIMULATOR) && CONFIG_CODEC == MAS3587F */
+
+/* This array holds the record timer interval lengths, in seconds */
+static const unsigned long rec_timer_seconds[] =
+{
+    0,        /* 0 means OFF */
+    5*60,     /* 00:05 */
+    10*60,    /* 00:10 */
+    15*60,    /* 00:15 */
+    30*60,    /* 00:30 */
+    60*60,    /* 01:00 */
+    74*60,    /* 74:00 */
+    80*60,    /* 80:00 */
+    2*60*60,  /* 02:00 */
+    4*60*60,  /* 04:00 */
+    6*60*60,  /* 06:00 */
+    8*60*60,  /* 08:00 */
+    10L*60*60, /* 10:00 */
+    12L*60*60, /* 12:00 */
+    18L*60*60, /* 18:00 */
+    24L*60*60  /* 24:00 */
+};
+
+unsigned int rec_timesplit_seconds(void)
+{
+    return rec_timer_seconds[global_settings.rec_timesplit];
+}
+
+/* This array holds the record size interval lengths, in bytes */
+static const unsigned long rec_size_bytes[] =
+{
+    0,               /* 0 means OFF */
+    5*1024*1024,     /* 5MB */
+    10*1024*1024,    /* 10MB */
+    15*1024*1024,    /* 15MB */
+    32*1024*1024,    /* 32MB */
+    64*1024*1024,    /* 64MB */
+    75*1024*1024,    /* 75MB */
+    100*1024*1024,   /* 100MB */
+    128*1024*1024,   /* 128MB */
+    256*1024*1024,   /* 256MB */
+    512*1024*1024,   /* 512MB */
+    650*1024*1024,   /* 650MB */
+    700*1024*1024,   /* 700MB */
+    1024*1024*1024,  /* 1GB */
+    1536*1024*1024,  /* 1.5GB */
+    1792*1024*1024,  /* 1.75GB  */
+};
+
+unsigned long rec_sizesplit_bytes(void)
+{
+    return rec_size_bytes[global_settings.rec_sizesplit];
+}
+/*
+ * Time strings used for the trigger durations.
+ * Keep synchronous to trigger_times in settings_apply_trigger
+ */
+const char * const trig_durations[TRIG_DURATION_COUNT] =
+{
+    "0s", "1s", "2s", "5s",
+    "10s", "15s", "20s", "25s", "30s",
+    "1min", "2min", "5min", "10min"
+};
+
+void settings_apply_trigger(void)
+{
+    /* Keep synchronous to trig_durations and trig_durations_conf*/
+    static const long trigger_times[TRIG_DURATION_COUNT] = {
+        0, HZ, 2*HZ, 5*HZ,
+        10*HZ, 15*HZ, 20*HZ, 25*HZ, 30*HZ,
+        60*HZ, 2*60*HZ, 5*60*HZ, 10*60*HZ
+    };
+
+    peak_meter_define_trigger(
+            global_settings.rec_start_thres,
+    trigger_times[global_settings.rec_start_duration],
+    MIN(trigger_times[global_settings.rec_start_duration] / 2, 2*HZ),
+    global_settings.rec_stop_thres,
+    trigger_times[global_settings.rec_stop_postrec],
+    trigger_times[global_settings.rec_stop_gap]
+                             );
+}
 #endif /* HAVE_RECORDING */
Index: apps/recorder/recording.h
===================================================================
RCS file: /cvsroot/rockbox/apps/recorder/recording.h,v
retrieving revision 1.6
diff -u -r1.6 recording.h
--- apps/recorder/recording.h	6 Nov 2006 18:07:27 -0000	1.6
+++ apps/recorder/recording.h	15 Nov 2006 08:00:46 -0000
@@ -49,4 +49,7 @@
 /* creates unique filename and starts recording */
 void rec_new_file(void);
 
+int rec_menu_recording_screen(void);
+int rectrigger(void);
+
 #endif
Index: firmware/drivers/lcd-player-charset.c
===================================================================
RCS file: /cvsroot/rockbox/firmware/drivers/lcd-player-charset.c,v
retrieving revision 1.9
diff -u -r1.9 lcd-player-charset.c
--- firmware/drivers/lcd-player-charset.c	23 May 2005 12:04:30 -0000	1.9
+++ firmware/drivers/lcd-player-charset.c	15 Nov 2006 08:00:47 -0000
@@ -49,7 +49,7 @@
    RESERVED_CHAR, /* reserved */
    RESERVED_CHAR, /* reserved */
    RESERVED_CHAR, /* reserved */
-   RESERVED_CHAR, /* reserved */
+   0x215, /* 0x15 .. "checkmark" icon */
    0x216, /* 0x16 .. "bookmark" icon */
    0x217, /* 0x17 .. "plugin" icon */
    0x218, /* 0x18 .. "folder" icon */
@@ -311,7 +311,7 @@
    RESERVED_CHAR, /* reserved */
    RESERVED_CHAR, /* reserved */
    RESERVED_CHAR, /* reserved */
-   RESERVED_CHAR, /* reserved */
+   0x215, /* 0x15 .. "checkmark" icon */
    0x216, /* 0x16 .. "bookmark" icon */
    0x217, /* 0x17 .. "plugin" icon */
    0x218, /* 0x18 .. "folder" icon */
@@ -671,7 +671,7 @@
   { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 12 */
   { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 13 */
   { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 14 */
-  { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, /* 15 */
+  { 0x00, 0x01, 0x03, 0x16, 0x1c, 0x08, 0x00, 0x00}, /* 15 Checkmark */
   { 0x00, 0x03, 0x07, 0x0e, 0x1c, 0x08, 0x00, 0x00}, /* 16 Bookmark icon */
   { 0x04, 0x1e, 0x07, 0x1f, 0x05, 0x01, 0x06, 0x00}, /* 17 Plugin file icon */
   { 0x0c, 0x13, 0x11, 0x11, 0x11, 0x11, 0x1f, 0x00}, /* 18 Folder icon */
Index: firmware/export/kernel.h
===================================================================
RCS file: /cvsroot/rockbox/firmware/export/kernel.h,v
retrieving revision 1.28
diff -u -r1.28 kernel.h
--- firmware/export/kernel.h	19 Oct 2006 11:43:13 -0000	1.28
+++ firmware/export/kernel.h	15 Nov 2006 08:00:48 -0000
@@ -7,7 +7,7 @@
  *                     \/            \/     \/    \/            \/
  * $Id: kernel.h,v 1.28 2006-10-19 11:43:13 linus Exp $
  *
- * Copyright (C) 2002 by Björn Stenberg
+ * Copyright (C) 2002 by Bjï¿½n Stenberg
  *
  * 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.
@@ -48,6 +48,7 @@
 #define SYS_CHARGER_DISCONNECTED  ((SYS_EVENT | ((long)11 << 27)))
 #define SYS_PHONE_PLUGGED         ((SYS_EVENT | ((long)12 << 27)))
 #define SYS_PHONE_UNPLUGGED       ((SYS_EVENT | ((long)13 << 27)))
+#define SYS_DUMPSETTINGS          ((SYS_EVENT | ((long)14 << 27)))
 
 struct event
 {
