diff --git a/apps/SOURCES b/apps/SOURCES index 2304ee7031..d47e2bdd29 100644 --- a/apps/SOURCES +++ b/apps/SOURCES @@ -11,6 +11,14 @@ language.c main.c main_menu.c menu.c +menus/display_menu.c +menus/main_menu.c +menus/playlist_menu.c +#ifdef HAVE_RECORDING +menus/recording_menu.c +#endif +menus/settings_menu.c +menus/sound_menu.c misc.c onplay.c playlist.c diff --git a/apps/action.h b/apps/action.h index 5a8168ea80..9519bd0fc7 100644 --- a/apps/action.h +++ b/apps/action.h @@ -154,6 +154,10 @@ enum { ACTION_REC_F3, /* main menu */ + ACTION_REQUEST_MENUITEM, + ACTION_EXIT_MENUITEM, + ACTION_ENTER_MENUITEM, + ACTION_MENU_WPS, /* id3db */ diff --git a/apps/main_menu.c b/apps/main_menu.c index 7e20656dc9..078e7669f2 100644 --- a/apps/main_menu.c +++ b/apps/main_menu.c @@ -281,16 +281,6 @@ static bool show_info(void) return false; } -static bool plugin_browse(void) -{ - return rockbox_browse(PLUGIN_DIR, SHOW_PLUGINS); -} - -static bool custom_theme_browse(void) -{ - return rockbox_browse(THEME_DIR, SHOW_CFG); -} - #ifdef HAVE_RECORDING static bool rec_menu_recording_screen(void) @@ -340,7 +330,7 @@ bool rec_menu(void) } #endif -static bool info_menu(void) +bool info_menu(void) { int m; bool result; @@ -368,6 +358,7 @@ static bool info_menu(void) return result; } +#if 0 #ifdef HAVE_LCD_CHARCELLS static bool do_shutdown(void) { @@ -375,7 +366,6 @@ static bool do_shutdown(void) return false; } #endif - bool main_menu(void) { int m; @@ -445,7 +435,7 @@ bool main_menu(void) return result; } - +#endif /* ----------------------------------------------------------------- * vim: et sw=4 ts=8 sts=4 tw=78 */ diff --git a/apps/menu.c b/apps/menu.c index 261286b8fa..9c5afbe94a 100644 --- a/apps/menu.c +++ b/apps/menu.c @@ -35,12 +35,14 @@ #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 "menus/exported_menus.h" #ifdef HAVE_LCD_BITMAP #include "icons.h" @@ -356,3 +358,337 @@ void put_cursorxy(int x, int y, bool on) #endif } } + +/******************************************************************/ +/* New menu stuff here!! + ******************************************************************/ + + +/* used to allow for dynamic menus */ +#define MAX_MENU_SUBITEMS 64 +static int current_subitems[MAX_MENU_SUBITEMS]; +static int current_subitems_count = 0; + +void get_menu_callback(const struct menu_item_ex *m, + menu_callback_type menu_callback) +{ + if (m->flags&MENU_HAS_DESC) + menu_callback= m->callback_and_desc->menu_callback; + else menu_callback = m->menu_callback; +} + +static int get_menu_selection(int selected_item, const struct menu_item_ex *menu) +{ + int type = (menu->flags&MENU_TYPE_MASK); + if (type == MT_MENU && (selected_itemflags&MENU_TYPE_MASK); + selected_item = get_menu_selection(selected_item, menu); + + (void)buffer; + /* only MT_MENU or MT_RETURN_ID is allowed in here */ + if (type == MT_RETURN_ID) + { + return (char*)menu->strings[selected_item]; + } + + menu = menu->submenus[selected_item]; + type = (menu->flags&MENU_TYPE_MASK); + if (type == MT_SETTING) + { + const struct settings_list *v + = find_setting(menu->variable); + if (v) + return str(v->lang_id); + else return "Not Done yet!"; + } + return P2STR(menu->callback_and_desc->desc); +} + +static void init_menu_lists(const struct menu_item_ex *menu, + struct gui_synclist *lists, int selected, bool callback) +{ + int i, count = (menu->flags&MENU_COUNT_MASK)>>MENU_COUNT_SHIFT; + menu_callback_type menu_callback = NULL; + current_subitems_count = 0; + for (i=0; isubmenus[i],menu_callback); + if (menu_callback) + { + if (menu_callback(ACTION_REQUEST_MENUITEM,menu->submenus[i]) + != ACTION_EXIT_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->callback_and_desc->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); + + get_menu_callback(menu,menu_callback); + if (callback && menu_callback) + menu_callback(ACTION_ENTER_MENUITEM,menu); +} + +static 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->flags&MENU_TYPE_MASK) == MT_MENU) + { + if ((menu->submenus[sel]->flags&MENU_TYPE_MASK) == MT_SETTING) + talk_setting(menu->submenus[sel]->variable); + else + { + id = P2ID(menu->submenus[sel]->callback_and_desc->desc); + if (id != -1) + talk_id(id,false); + } + } + } +} +#define MAX_OPTIONS 32 +int do_menu(const struct menu_item_ex *start_menu) +{ + int action; + int selected = 0; + struct gui_synclist lists; + const struct menu_item_ex *temp, *menu; + int ret = 0; + + const struct menu_item_ex *menu_stack[MAX_MENUS]; + int menu_stack_selected_item[MAX_MENUS]; + int stack_top = 0; + bool in_stringlist; + menu_callback_type menu_callback = NULL; + if (start_menu == NULL) + menu = &main_menu_; + else menu = start_menu; + + init_menu_lists(menu,&lists,selected,true); + in_stringlist = ((menu->flags&MENU_TYPE_MASK) == MT_RETURN_ID); + + talk_menu_item(menu, &lists); + + gui_synclist_draw(&lists); + gui_syncstatusbar_draw(&statusbars, true); + action_signalscreenchange(); + + while (ret == 0) + { + action = get_action(CONTEXT_MAINMENU,HZ); + /* HZ so the status bar redraws corectly */ + if (action == ACTION_NONE) + { + gui_syncstatusbar_draw(&statusbars, true); + continue; + } + + get_menu_callback(menu,menu_callback); + if (menu_callback) + { + action = menu_callback(action,menu); + } + + if (gui_synclist_do_button(&lists,action,LIST_WRAP_UNLESS_HELD)) + { + talk_menu_item(menu, &lists); + } + else if (action == ACTION_MENU_WPS) + { + ret = MENU_RETURN_TO_WPS; + } + else if ((action == ACTION_STD_CANCEL) || + (action == ACTION_STD_MENU)) + { + if (in_stringlist) + in_stringlist = false; + if (stack_top > 0) + { + get_menu_callback(menu,menu_callback); + if (menu_callback) + { + if (menu_callback(action,menu) == + ACTION_EXIT_MENUITEM) + break; + } + stack_top--; + menu = menu_stack[stack_top]; + init_menu_lists(menu, &lists, + menu_stack_selected_item[stack_top], false); + talk_menu_item(menu, &lists); + } + else + { + 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->flags&MENU_TYPE_MASK); + else type = (temp->flags&MENU_TYPE_MASK); + get_menu_callback(temp,menu_callback); + if (menu_callback) + { + action = menu_callback(ACTION_ENTER_MENUITEM,temp); + if (action == ACTION_EXIT_MENUITEM) + break; + } + switch (type) + { + case MT_MENU: + if (stack_top < MAX_MENUS) + { + 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, true); + menu = temp; + talk_menu_item(menu, &lists); + } + break; + case MT_FUNCTION_CALL: + action_signalscreenchange(); + temp->function(); + break; + case MT_FUNCTION_WITH_PARAM: + action_signalscreenchange(); + temp->func_with_param->function( + temp->func_with_param->param); + break; + case MT_SETTING: + { + const struct settings_list *setting = find_setting( + temp->variable); + if (setting) + { + if ((setting->flags&F_BOOL_SETTING) == F_BOOL_SETTING) + { + bool temp_var, *var; + if (setting->flags&F_TEMPVAR) + { + temp_var = *(bool*)setting->setting; + var = &temp_var; + } + else + { + var = (bool*)setting->setting; + } + set_bool_options(str(setting->lang_id),var, + STR(setting->bool_setting->lang_yes), + STR(setting->bool_setting->lang_no), + setting->bool_setting->option_callback); + if (setting->flags&F_TEMPVAR) + *(bool*)setting->setting = temp_var; + } + else if (setting->flags&F_T_SOUND) + { + set_sound(str(setting->lang_id), setting->setting, + setting->sound_setting->setting); + } + else /* other setting, must be an INT type */ + { + int temp_var, *var; + if (setting->flags&F_TEMPVAR) + { + temp_var = *(int*)setting->setting; + var = &temp_var; + } + else + { + var = (int*)setting->setting; + } + DEBUGF("%x\n",setting->flags); + if (setting->flags&F_INT_SETTING) + {DEBUGF("boo"); + set_int(str(setting->lang_id), + str(setting->int_setting->unit), + setting->int_setting->unit,var, + setting->int_setting->option_callback, + setting->int_setting->step, + setting->int_setting->min, + setting->int_setting->max, + setting->int_setting->formatter); + } + else if (setting->flags&F_CHOICE_SETTING) + { + static struct opt_items options[MAX_OPTIONS]; + int i,j, count = setting->choice_setting->count; + for (i=0, j=0; ichoice_setting->desc[i]); + options[j].voice_id = + P2ID(setting->choice_setting->desc[i]); + j++; + } + set_option(str(setting->lang_id), var, INT, + options,count, + setting->choice_setting->option_callback); + } + if (setting->flags&F_TEMPVAR) + *(int*)setting->setting = temp_var; + } + } + 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,false); + in_stringlist = true; + } + break; + } + get_menu_callback(temp,menu_callback); + if (type != MT_MENU && menu_callback) + menu_callback(ACTION_EXIT_MENUITEM,temp); + } + else if(default_event_handler(action) == SYS_USB_CONNECTED) + ret = MENU_ATTACHED_USB; + gui_syncstatusbar_draw(&statusbars, true); + gui_synclist_draw(&lists); + } + action_signalscreenchange(); + return ret; +} + +int main_menu(void) +{ + return do_menu(NULL); +} diff --git a/apps/menu.h b/apps/menu.h index f9a3d1ffd8..b0a1b4cb7f 100644 --- a/apps/menu.h +++ b/apps/menu.h @@ -22,101 +22,14 @@ #include -/* button definitions */ -#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ - (CONFIG_KEYPAD == IRIVER_H300_PAD) -#define MENU_EXIT BUTTON_LEFT -#define MENU_EXIT2 BUTTON_OFF -#define MENU_EXIT_MENU BUTTON_MODE -#define MENU_ENTER BUTTON_RIGHT -#define MENU_ENTER2 BUTTON_SELECT - -#define MENU_RC_EXIT BUTTON_RC_STOP -#define MENU_RC_EXIT_MENU BUTTON_RC_MODE -#define MENU_RC_ENTER BUTTON_RC_ON -#define MENU_RC_ENTER2 BUTTON_RC_MENU - - -#elif CONFIG_KEYPAD == RECORDER_PAD - -#define MENU_EXIT BUTTON_LEFT -#define MENU_EXIT2 BUTTON_OFF -#define MENU_EXIT_MENU BUTTON_F1 -#define MENU_ENTER BUTTON_RIGHT -#define MENU_ENTER2 BUTTON_PLAY - -#define MENU_RC_EXIT BUTTON_RC_STOP -#define MENU_RC_ENTER BUTTON_RC_PLAY - -#elif CONFIG_KEYPAD == PLAYER_PAD -#define MENU_EXIT BUTTON_STOP -#define MENU_EXIT_MENU BUTTON_MENU -#define MENU_ENTER BUTTON_PLAY - -#define MENU_RC_EXIT BUTTON_RC_STOP -#define MENU_RC_ENTER BUTTON_RC_PLAY - -#elif CONFIG_KEYPAD == ONDIO_PAD -#define MENU_EXIT BUTTON_LEFT -#define MENU_EXIT_MENU BUTTON_MENU -#define MENU_ENTER BUTTON_RIGHT - -#elif (CONFIG_KEYPAD == IPOD_3G_PAD) || (CONFIG_KEYPAD == IPOD_4G_PAD) - -/* TODO: Check menu button assignments */ - -#define MENU_NEXT BUTTON_DOWN -#define MENU_PREV BUTTON_UP -#define MENU_EXIT BUTTON_LEFT -#define MENU_EXIT_MENU BUTTON_MENU -#define MENU_ENTER BUTTON_RIGHT -#define MENU_ENTER2 BUTTON_SELECT - -#elif CONFIG_KEYPAD == IRIVER_IFP7XX_PAD - -#define MENU_NEXT BUTTON_DOWN -#define MENU_PREV BUTTON_UP -#define MENU_EXIT BUTTON_LEFT -#define MENU_EXIT_MENU BUTTON_PLAY -#define MENU_ENTER BUTTON_RIGHT - -#elif CONFIG_KEYPAD == IAUDIO_X5_PAD - -#define MENU_NEXT BUTTON_DOWN -#define MENU_PREV BUTTON_UP -#define MENU_EXIT BUTTON_LEFT -#define MENU_EXIT_MENU BUTTON_REC -#define MENU_ENTER BUTTON_RIGHT -#define MENU_ENTER2 BUTTON_SELECT - -#elif CONFIG_KEYPAD == GIGABEAT_PAD - -#define MENU_EXIT BUTTON_LEFT -#define MENU_EXIT2 BUTTON_A -#define MENU_EXIT_MENU BUTTON_MENU -#define MENU_ENTER BUTTON_RIGHT -#define MENU_ENTER2 BUTTON_SELECT -#define MENU_NEXT BUTTON_DOWN -#define MENU_PREV BUTTON_UP - -#elif CONFIG_KEYPAD == IRIVER_H10_PAD - -#define MENU_NEXT BUTTON_SCROLL_DOWN -#define MENU_PREV BUTTON_SCROLL_UP -#define MENU_EXIT BUTTON_LEFT -#define MENU_EXIT_MENU BUTTON_REW -#define MENU_ENTER BUTTON_RIGHT -#define MENU_ENTER2 BUTTON_FF - -#endif - struct menu_item { unsigned char *desc; /* string or ID */ bool (*function) (void); /* return true if USB was connected */ }; -int menu_init(const struct menu_item* mitems, int count, int (*callback)(int, int), - const char *button1, const char *button2, const char *button3); +int menu_init(const struct menu_item* mitems, int count, + int (*callback)(int, int), + const char *button1, const char *button2, const char *button3); void menu_exit(int menu); void put_cursorxy(int x, int y, bool on); @@ -125,6 +38,8 @@ void put_cursorxy(int x, int y, bool on); int menu_show(int m); #define MENU_ATTACHED_USB -1 #define MENU_SELECTED_EXIT -2 +#define MENU_EXIT_ALL -3 +#define MENU_RETURN_TO_WPS -4 bool menu_run(int menu); int menu_cursor(int menu); @@ -138,4 +53,87 @@ void menu_insert(int menu, int position, char *desc, bool (*function) (void)); void menu_set_cursor(int menu, int position); void menu_talk_selected(int m); + +enum menu_item_type { + MT_MENU = 0, + MT_SETTING, + MT_FUNCTION_CALL, /* used when the standard code wont work */ + MT_FUNCTION_WITH_PARAM, + MT_RETURN_ID, /* returns the position of the selected item (starting at 0)*/ +}; + +typedef int (*menu_function)(void); +struct menu_func_with_param { + int (*function)(void* param); + void *param; +}; + +#define MENU_TYPE_MASK 0xF /* MT_* type */ +#define MENU_HAS_DESC 0x10 +#define MENU_COUNT_MASK (~(MENU_TYPE_MASK|MENU_HAS_DESC)) /* unless we need more flags*/ +#define MENU_COUNT_SHIFT 5 + +struct menu_item_ex { + int flags; /* above defines */ + union { + const struct menu_item_ex **submenus; /* used with MT_MENU */ + void *variable; /* used with MT_SETTING, + must be in the settings_list.c list */ + int (*function)(void); /* used with MT_FUNCTION_CALL */ + const struct menu_func_with_param + *func_with_param; /* MT_FUNCTION_WITH_PARAM */ + const char **strings; /* used with MT_RETURN_ID */ + }; + union { + int (*menu_callback)(int action, const struct menu_item_ex *this_item); + const struct menu_callback_with_desc { + int (*menu_callback)(int action, + const struct menu_item_ex *this_item); + unsigned char *desc; /* string or ID */ + } *callback_and_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 MENU_ITEM_COUNT(c) (c< ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: $ + * + * Copyright (C) 2007 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 +#include +#include +#include "config.h" +#include "lang.h" +#include "action.h" +#include "settings.h" +#include "menu.h" +#include "settings_menu.h" + +bool display_settings_menu(void); /* from ../settings_menu.c */ +MENUITEM_FUNCTION(display_menu,ID2P(LANG_DISPLAY),(menu_function)display_settings_menu,NULL); diff --git a/apps/menus/exported_menus.h b/apps/menus/exported_menus.h new file mode 100644 index 0000000000..3d6a11a16e --- /dev/null +++ b/apps/menus/exported_menus.h @@ -0,0 +1,40 @@ +/*************************************************************************** + * __________ __ ___. + * 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 _EXPORTED_MENUS_H +#define _EXPORTED_MENUS_H + +#include "menu.h" +/* not needed for plugins */ +#ifndef PLUGIN + +extern const struct menu_item_ex + main_menu_, /* main_menu.c */ + display_menu, /* display_menu.c */ +// playback_settings, /* playback_menu.c */ +#ifdef HAVE_RECORDING + recording_settings_menu, /* recording_menu.c */ +#endif + sound_settings, /* sound_menu.c */ + settings_menu_item, /* settings_menu.c */ + playlist_menu_item; /* playlist_menu.c */ + + + +#endif /* ! PLUGIN */ +#endif /*_EXPORTED_MENUS_H */ diff --git a/apps/menus/main_menu.c b/apps/menus/main_menu.c new file mode 100644 index 0000000000..e830f4bbc7 --- /dev/null +++ b/apps/menus/main_menu.c @@ -0,0 +1,125 @@ + +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: $ + * + * Copyright (C) 2007 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 +#include +#include +#include "config.h" +#include "lang.h" +#include "action.h" +#include "settings.h" +#include "powermgmt.h" +#include "menu.h" +#include "settings_menu.h" +#include "exported_menus.h" +#include "tree.h" +#ifdef CONFIG_TUNER +#include "radio.h" +#endif +#ifdef HAVE_RECORDING +#include "recording.h" +#endif +#include "bookmark.h" + +/* lazy coders can use this function if the needed callback + is just to say if the item is shown or not */ +int dynamicitem_callback(int action,const struct menu_item_ex *this_item); + +/***********************************/ +/* MAIN MENU */ + +struct browse_folder_info { + const char* dir; + int show_options; +}; +static struct browse_folder_info theme = {THEME_DIR, SHOW_CFG}; +static struct browse_folder_info rocks = {PLUGIN_DIR, SHOW_PLUGINS}; +static int browse_folder(void *param) +{ + const struct browse_folder_info *info = + (const struct browse_folder_info*)param; + return rockbox_browse(info->dir, info->show_options); +} +MENUITEM_FUNCTION_WPARAM(browse_themes, ID2P(LANG_CUSTOM_THEME), + browse_folder, (void*)&theme, NULL); +MENUITEM_FUNCTION_WPARAM(browse_plugins, ID2P(LANG_PLUGINS), + browse_folder, (void*)&rocks, NULL); + +#ifdef CONFIG_TUNER +MENUITEM_FUNCTION(load_radio_screen, ID2P(LANG_FM_RADIO), + (menu_function)radio_screen, dynamicitem_callback); +#endif + +#include "settings_menu.h" +MENUITEM_FUNCTION(manage_settings_menu_item, ID2P(LANG_MANAGE_MENU), + (menu_function)manage_settings_menu, NULL); +bool info_menu(void); /* from apps/main_menu.c TEMP*/ +MENUITEM_FUNCTION(info_menu_item, ID2P(LANG_INFO), + (menu_function)info_menu, NULL); +MENUITEM_FUNCTION(mrb_bookmarks, ID2P(LANG_BOOKMARK_MENU_RECENT_BOOKMARKS), + (menu_function)bookmark_mrb_load, NULL); + +#ifdef HAVE_LCD_CHARCELLS +static int do_shutdown(void) +{ + sys_poweroff(); + return 0; +} +MENUITEM_FUNCTION(do_shutdown_item, ID2P(LANG_SHUTDOWN), do_shutdown, NULL); +#endif + +/* NOTE: This title will be translatable once we decide what to call this menu + when the root menu comes in... hopefully in the next few days */ +MAKE_MENU(main_menu_, "ROCKbox Main Menu", NULL, + &mrb_bookmarks, &sound_settings, + &settings_menu_item, &manage_settings_menu_item, &browse_themes, +#ifdef CONFIG_TUNER + &load_radio_screen, +#endif +#ifdef HAVE_RECORDING + &recording_settings_menu, +#endif + &playlist_menu_item, &browse_plugins, &info_menu_item +#ifdef HAVE_LCD_CHARCELLS + ,&do_shutdown_item +#endif + ); +/* MAIN MENU */ +/***********************************/ + +/* lazy coders can use this function if the needed + callback is just to say if the item is shown or not */ +int dynamicitem_callback(int action,const struct menu_item_ex *this_item) +{ + if (action != ACTION_ENTER_MENUITEM) + return action; + +#ifdef CONFIG_TUNER + if (this_item == &load_radio_screen) + { + if (radio_hardware_present() == 0) + return ACTION_EXIT_MENUITEM; + } +#else + (void)this_item; +#endif + + return action; +} diff --git a/apps/menus/playlist_menu.c b/apps/menus/playlist_menu.c new file mode 100644 index 0000000000..b38870e540 --- /dev/null +++ b/apps/menus/playlist_menu.c @@ -0,0 +1,32 @@ + +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: $ + * + * Copyright (C) 2007 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 +#include +#include +#include "config.h" +#include "lang.h" +#include "action.h" +#include "settings.h" +#include "menu.h" +#include "playlist_menu.h" + +MENUITEM_FUNCTION(playlist_menu_item, ID2P(LANG_PLAYLIST_MENU), (menu_function)playlist_menu, NULL); + diff --git a/apps/menus/recording_menu.c b/apps/menus/recording_menu.c new file mode 100644 index 0000000000..d1aed69dea --- /dev/null +++ b/apps/menus/recording_menu.c @@ -0,0 +1,41 @@ + +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: $ + * + * Copyright (C) 2007 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 +#include +#include +#include "config.h" +#include "lang.h" +#include "action.h" +#include "settings.h" +#include "menu.h" +#include "recording.h" + +#ifdef HAVE_RECORDING +MENUITEM_FUNCTION(rec_menu_recording_screen_item, ID2P(LANG_RECORDING_MENU), + (menu_function)recording_screen, NULL); +/* TEMP */ +bool recording_menu(bool no_source); /* from apps/sound_menu.h */ +MENUITEM_FUNCTION_WPARAM(recording_settings, ID2P(LANG_RECORDING_MENU), + (int (*)(void*))recording_menu,0, NULL); + +MAKE_MENU(recording_settings_menu,ID2P(LANG_RECORDING),0, + &rec_menu_recording_screen_item, &recording_settings); +#endif diff --git a/apps/menus/recording_settings_menu.c b/apps/menus/recording_settings_menu.c new file mode 100644 index 0000000000..1bc38ddbcd --- /dev/null +++ b/apps/menus/recording_settings_menu.c @@ -0,0 +1,33 @@ + +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: $ + * + * Copyright (C) 2007 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 +#include +#include +#include "config.h" +#include "lang.h" +#include "action.h" +#include "settings.h" +#include "menu.h" +#include "settings_menu.h" +#include "playback_menu.h" + +bool display_settings_menu(void); /* from ../settings_menu.c */ +MENUITEM_FUNCTION(display_menu,ID2P(LANG_DISPLAY),display_settings_menu,NULL); diff --git a/apps/menus/settings_menu.c b/apps/menus/settings_menu.c new file mode 100644 index 0000000000..3ea35320dd --- /dev/null +++ b/apps/menus/settings_menu.c @@ -0,0 +1,33 @@ + +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: $ + * + * Copyright (C) 2007 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 +#include +#include +#include "config.h" +#include "lang.h" +#include "action.h" +#include "settings.h" +#include "menu.h" +#include "sound_menu.h" + +#include "settings_menu.h" +MENUITEM_FUNCTION(settings_menu_item, ID2P(LANG_GENERAL_SETTINGS), + (menu_function)settings_menu, NULL); diff --git a/apps/menus/sound_menu.c b/apps/menus/sound_menu.c new file mode 100644 index 0000000000..6d656da14d --- /dev/null +++ b/apps/menus/sound_menu.c @@ -0,0 +1,32 @@ + +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: $ + * + * Copyright (C) 2007 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 +#include +#include +#include "config.h" +#include "lang.h" +#include "action.h" +#include "settings.h" +#include "menu.h" +#include "sound_menu.h" + +MENUITEM_FUNCTION(sound_settings, ID2P(LANG_SOUND_SETTINGS), (menu_function)sound_menu, NULL); + diff --git a/apps/recorder/recording.h b/apps/recorder/recording.h index a67337b9b6..e78af50671 100644 --- a/apps/recorder/recording.h +++ b/apps/recorder/recording.h @@ -18,6 +18,7 @@ ****************************************************************************/ #ifndef RECORDING_H #define RECORDING_H +#include "audio.h" bool recording_screen(bool no_source); char *rec_create_filename(char *buf); diff --git a/apps/settings.c b/apps/settings.c index 2cdab771db..4d4a96c639 100644 --- a/apps/settings.c +++ b/apps/settings.c @@ -19,6 +19,7 @@ ****************************************************************************/ #include #include +#include #include #include "inttypes.h" #include "config.h" @@ -922,6 +923,78 @@ void settings_reset(void) { } /** Changing setting values **/ +const struct settings_list* find_setting(void* variable) +{ + int i; + for(i=0;ilang_id) + talk_id(setting->lang_id,false); +} +static int selected_setting; /* Used by the callback */ +static 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 = abs(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 +#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 ); + } +} bool set_bool(const char* string, bool* variable ) { diff --git a/apps/settings.h b/apps/settings.h index 379084b885..8244163e2e 100644 --- a/apps/settings.h +++ b/apps/settings.h @@ -224,6 +224,10 @@ struct opt_items { unsigned const char* string; long voice_id; }; +const struct settings_list* find_setting(void* variable); +void talk_setting(void *global_settings_variable); +bool set_sound(const unsigned char * string, + int* variable, int setting); bool set_bool_options(const char* string, bool* variable, const char* yes_str, int yes_voice, const char* no_str, int no_voice, diff --git a/apps/settings_list.c b/apps/settings_list.c index 8641cd83b9..5f784d4998 100644 --- a/apps/settings_list.c +++ b/apps/settings_list.c @@ -21,10 +21,12 @@ #include #include "lang.h" +#include "talk.h" #include "lcd.h" #include "settings.h" #include "settings_list.h" #include "sound.h" +#include "dsp.h" /* some sets of values which are used more than once, to save memory */ static const char off_on[] = "off,on"; @@ -92,24 +94,39 @@ static const char backlight_times_conf [] = #define NODEFAULT INT(0) #define SOUND_SETTING(flags,var,lang_id,setting) \ - {flags|F_T_INT|F_T_SOUND, GS(var),lang_id, NODEFAULT,#var,NULL,\ - {.sound_setting=(struct sound_setting[]){{setting}}} } + {flags|F_T_INT|F_T_SOUND, GS(var),lang_id, NODEFAULT,#var,NULL,\ + {.sound_setting=(struct sound_setting[]){{setting}}} } #define BOOL_SETTING(flags,var,lang_id,default,name,cfgvals,yes,no,opt_cb) \ - {flags|F_T_BOOL, GS(var),lang_id, BOOL(default),name,cfgvals, \ - {.bool_setting=(struct bool_setting[]){{opt_cb,yes,no}}} } + {flags|F_BOOL_SETTING, GS(var),lang_id, BOOL(default),name,cfgvals,\ + {.bool_setting=(struct bool_setting[]){{opt_cb,yes,no}}} } #define OFFON_SETTING(flags,var,lang_id,default,name,cb) \ - {flags|F_T_BOOL, GS(var),lang_id, BOOL(default),name,off_on, \ - {.bool_setting=(struct bool_setting[]) \ - {{cb,LANG_SET_BOOL_YES,LANG_SET_BOOL_NO}}} } + {flags|F_BOOL_SETTING, GS(var),lang_id, BOOL(default),name,off_on, \ + {.bool_setting=(struct bool_setting[]) \ + {{cb,LANG_SET_BOOL_YES,LANG_SET_BOOL_NO}}} } #define SYSTEM_SETTING(flags,var,default) \ - {flags|F_T_INT, &global_status.var,-1, INT(default), NULL, NULL, UNUSED} + {flags|F_T_INT, &global_status.var,-1, INT(default), \ + NULL, NULL, UNUSED} #define FILENAME_SETTING(flags,var,name,default,prefix,suffix,len) \ - {flags|F_T_UCHARPTR, GS(var),-1, CHARPTR(default),name,NULL,\ - {.filename_setting=(struct filename_setting[]){{prefix,suffix,len}}} } + {flags|F_T_UCHARPTR, GS(var),-1, CHARPTR(default),name,NULL,\ + {.filename_setting= \ + (struct filename_setting[]){{prefix,suffix,len}}} } + +#define CHOICE_SETTING(flags,var,lang_id,default,name,cfg_vals,cb,count,...) \ + {flags|F_CHOICE_SETTING|F_T_INT, GS(var), lang_id, \ + INT(default), name, cfg_vals, \ + {.choice_setting = (struct choice_setting[]){ \ + {cb,count,(unsigned char*[]){__VA_ARGS__}}}}} + +#define INT_SETTING(flags, var, lang_id, default, name, cfg_vals, \ + unit, min, max, step, formatter, cb) \ + {flags|F_INT_SETTING|F_T_INT, GS(var), lang_id, INT(default), \ + name, cfg_vals, {.int_setting = (struct int_setting[]){ \ + {cb, unit, min, max, step, formatter}}}} + const struct settings_list settings[] = { /* sound settings */ SOUND_SETTING(0,volume, LANG_VOLUME, SOUND_VOLUME), @@ -122,10 +139,17 @@ const struct settings_list settings[] = { "off,20ms,2,4,8", UNUSED }, OFFON_SETTING(0,superbass,LANG_SUPERBASS,false,"superbass",NULL), #endif - { F_T_INT, GS(channel_config), LANG_CHANNEL, INT(0), "channels", - "stereo,mono,custom,mono left,mono right,karaoke", UNUSED }, - { F_T_INT, GS(stereo_width),LANG_STEREO_WIDTH, - INT(100), "stereo width", NULL, UNUSED }, + CHOICE_SETTING(0,channel_config,LANG_CHANNEL,0,"channels", + "stereo,mono,custom,mono left,mono right,karaoke", +#if CONFIG_CODEC == SWCODEC + channels_set, +#else + sound_set_channels, +#endif + 6, ID2P(LANG_CHANNEL_STEREO), ID2P(LANG_CHANNEL_MONO), + ID2P(LANG_CHANNEL_CUSTOM), ID2P(LANG_CHANNEL_LEFT), + ID2P(LANG_CHANNEL_RIGHT), ID2P(LANG_CHANNEL_KARAOKE)), + SOUND_SETTING(0,stereo_width, LANG_STEREO_WIDTH, SOUND_STEREO_WIDTH), /* playback */ OFFON_SETTING(0, resume, LANG_RESUME, false, "resume", NULL), OFFON_SETTING(0, playlist_shuffle, LANG_SHUFFLE, false, "shuffle", NULL), @@ -174,8 +198,8 @@ const struct settings_list settings[] = { SYSTEM_SETTING(NVRAM(4),runtime,0), SYSTEM_SETTING(NVRAM(4),topruntime,0), #if MEM > 1 - {F_T_INT,GS(max_files_in_playlist),LANG_MAX_FILES_IN_PLAYLIST, - INT(10000),"max files in playlist",NULL,UNUSED}, + INT_SETTING(0,max_files_in_playlist,LANG_MAX_FILES_IN_PLAYLIST,10000, + "max files in playlist", NULL, UNIT_INT,1000,20000,1000,NULL,NULL), {F_T_INT,GS(max_files_in_dir),LANG_MAX_FILES_IN_DIR, INT(400),"max files in dir",NULL,UNUSED}, #else diff --git a/apps/settings_list.h b/apps/settings_list.h index 195703bfe3..663d9db228 100644 --- a/apps/settings_list.h +++ b/apps/settings_list.h @@ -53,7 +53,7 @@ struct bool_setting { int lang_yes; int lang_no; }; -#define F_BOOL_SETTING F_T_BOOL|0x10 +#define F_BOOL_SETTING (F_T_BOOL|0x10) #define F_RGB 0x20 struct filename_setting { @@ -64,29 +64,42 @@ struct filename_setting { #define F_FILENAME 0x40 struct int_setting { - void (*option_callback)(int); - int min; - int max; - int step; + void (*option_callback)(int); + int unit; + int min; + int max; + int step; + void (*formatter)(char*, int, int, const char*); }; +#define F_INT_SETTING 0x80 + +struct choice_setting { + void (*option_callback)(int); + int count; + unsigned char **desc; +}; +#define F_CHOICE_SETTING 0x100 + /* these use the _isfunc_type type for the function */ /* typedef int (*_isfunc_type)(void); */ #define F_MIN_ISFUNC 0x100000 /* min(above) is function pointer to above type */ #define F_MAX_ISFUNC 0x200000 /* max(above) is function pointer to above type */ #define F_DEF_ISFUNC 0x400000 /* default_val is function pointer to above type */ -#define F_NVRAM_BYTES_MASK 0xE00 /*0-4 bytes can be stored */ -#define F_NVRAM_MASK_SHIFT 9 +#define F_THEMESETTING 0x800000 + +#define F_NVRAM_BYTES_MASK 0xE000 /*0-4 bytes can be stored */ +#define F_NVRAM_MASK_SHIFT 13 #define NVRAM_CONFIG_VERSION 2 /* Above define should be bumped if - a new NVRAM setting is added between 2 other NVRAM settings - number of bytes for a NVRAM setting is changed - a NVRAM setting is removed */ -#define F_THEMESETTING 0x800000 +#define F_TEMPVAR 0x200 /* used if the setting should be set using a temp var */ struct settings_list { - uint32_t flags; /* ____ ____ TFFF ____ ____ NNN_ IFRB STTT */ + uint32_t flags; /* ____ ____ TFFF ____ NNN_ __TC IFRB STTT */ void *setting; int lang_id; /* -1 for none */ union storage_type default_val; @@ -98,6 +111,8 @@ struct settings_list { struct sound_setting *sound_setting; /* use F_T_SOUND for this */ struct bool_setting *bool_setting; /* F_BOOL_SETTING */ struct filename_setting *filename_setting; /* use F_FILENAME */ + struct int_setting *int_setting; /* use F_INT_SETTING */ + struct choice_setting *choice_setting; /* F_CHOICE_SETTING */ }; }; diff --git a/apps/settings_menu.c b/apps/settings_menu.c index 8e6fbd02d7..054dd145a9 100644 --- a/apps/settings_menu.c +++ b/apps/settings_menu.c @@ -1767,7 +1767,7 @@ static bool unplug_menu(void) } #endif -static bool playback_settings_menu(void) +bool playback_settings_menu(void) { int m; bool result; @@ -2061,7 +2061,7 @@ static bool bars_settings_menu(void) #endif -static bool display_settings_menu(void) +bool display_settings_menu(void) { int m; bool result; diff --git a/apps/sound_menu.c b/apps/sound_menu.c index 19dc57b1a7..f7ddc430cc 100644 --- a/apps/sound_menu.c +++ b/apps/sound_menu.c @@ -61,57 +61,6 @@ #endif #include "action.h" -static int selected_setting; /* Used by the callback */ -static 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 = abs(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 -#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 ); - } -} - static bool volume(void) { return set_sound(str(LANG_VOLUME), &global_settings.volume, SOUND_VOLUME); diff --git a/apps/sound_menu.h b/apps/sound_menu.h index 4e85b9c03c..4d295b0a70 100644 --- a/apps/sound_menu.h +++ b/apps/sound_menu.h @@ -24,6 +24,5 @@ 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