Index: apps/action.h =================================================================== --- apps/action.h (revision 25376) +++ apps/action.h (working copy) @@ -126,7 +126,9 @@ ACTION_WPS_CONTEXT, ACTION_WPS_QUICKSCREEN,/* optional */ ACTION_WPS_MENU, /*this should be the same as ACTION_STD_MENU */ +#ifndef HOTKEY ACTION_WPS_VIEW_PLAYLIST, +#endif ACTION_WPS_REC, #if 0 ACTION_WPSAB_SINGLE, /* This needs to be #defined in @@ -195,8 +197,13 @@ ACTION_SETTINGS_DECBIGSTEP, ACTION_SETTINGS_RESET, + /* hotkey */ +#ifdef HOTKEY + ACTION_HOTKEY, +#else /* bookmark screen */ ACTION_BMS_DELETE, +#endif /* quickscreen */ ACTION_QS_LEFT, Index: apps/tree.c =================================================================== --- apps/tree.c (revision 25376) +++ apps/tree.c (working copy) @@ -757,12 +757,22 @@ #endif case ACTION_STD_CONTEXT: +#ifdef HOTKEY + case ACTION_HOTKEY: { + bool hotkey = button == ACTION_HOTKEY; +#else + { +#endif int onplay_result; int attr = 0; if(!numentries) - onplay_result = onplay(NULL, 0, curr_context); + onplay_result = onplay(NULL, 0, curr_context +#ifdef HOTKEY + , hotkey +#endif + ); else { #ifdef HAVE_TAGCACHE if (id3db) @@ -788,7 +798,11 @@ snprintf(buf, sizeof buf, "/%s", dircache[tc.selected_item].name); } - onplay_result = onplay(buf, attr, curr_context); + onplay_result = onplay(buf, attr, curr_context +#ifdef HOTKEY + , hotkey +#endif + ); } switch (onplay_result) { Index: apps/lang/english.lang =================================================================== --- apps/lang/english.lang (revision 25376) +++ apps/lang/english.lang (working copy) @@ -13394,3 +13394,71 @@ lineout_poweroff: "Line Out" + + id: LANG_SET_HOTKEY + desc: hotkey splash + user: core + + *: none + hotkey: "Set Hotkey: %s" + + + *: none + hotkey: "Set Hotkey: %s" + + + *: none + hotkey: "Set Hotkey: %s" + + + + id: LANG_HOTKEY_NOT_SET + desc: hotkey splash + user: core + + *: none + hotkey: "Hotkey Not Set" + + + *: none + hotkey: "Hotkey Not Set" + + + *: none + hotkey: "Hotkey Not Set" + + + + id: LANG_HOTKEY + desc: hotkey menu + user: core + + *: none + hotkey: "Hotkey" + + + *: none + hotkey: "Hotkey" + + + *: none + hotkey: "Hotkey" + + + + id: LANG_VIEW_HOTKEY + desc: hotkey menu + user: core + + *: none + hotkey: "View Hotkey Settings" + + + *: none + hotkey: "View Hotkey Settings" + + + *: none + hotkey: "View Hotkey Settings" + + Index: apps/onplay.c =================================================================== --- apps/onplay.c (revision 25376) +++ apps/onplay.c (working copy) @@ -64,6 +64,7 @@ #include "statusbar-skinned.h" #include "pitchscreen.h" #include "viewport.h" +#include "hotkey.h" static int context; static char* selected_file = NULL; @@ -262,7 +263,6 @@ return action; else return ACTION_EXIT_MENUITEM; - break; } return action; } @@ -378,7 +378,6 @@ } } return ACTION_EXIT_MENUITEM; - break; } return action; } @@ -442,7 +441,6 @@ } else return ACTION_EXIT_MENUITEM; - break; } return action; } @@ -528,7 +526,7 @@ /* share code for file and directory deletion, saves space */ -static bool delete_handler(bool is_dir) +static bool delete_item(void) { char file_to_delete[MAX_PATH]; strcpy(file_to_delete, selected_file); @@ -551,7 +549,7 @@ splash(0, str(LANG_DELETING)); int res; - if (is_dir) + if (selected_file_attr & ATTR_DIRECTORY) /* true if directory */ { char pathname[MAX_PATH]; /* space to go deep */ cpu_boost(true); @@ -568,16 +566,6 @@ return (res == 0); } -static bool delete_file(void) -{ - return delete_handler(false); -} - -static bool delete_dir(void) -{ - return delete_handler(true); -} - static bool rename_file(void) { char newname[MAX_PATH]; @@ -988,9 +976,9 @@ MENUITEM_FUNCTION(clipboard_paste_item, 0, ID2P(LANG_PASTE), clipboard_paste, NULL, clipboard_callback, Icon_NOICON); MENUITEM_FUNCTION(delete_file_item, 0, ID2P(LANG_DELETE), - delete_file, NULL, clipboard_callback, Icon_NOICON); + delete_item, NULL, clipboard_callback, Icon_NOICON); MENUITEM_FUNCTION(delete_dir_item, 0, ID2P(LANG_DELETE_DIR), - delete_dir, NULL, clipboard_callback, Icon_NOICON); + delete_item, NULL, clipboard_callback, Icon_NOICON); MENUITEM_FUNCTION(create_dir_item, 0, ID2P(LANG_CREATE_DIR), create_dir, NULL, clipboard_callback, Icon_NOICON); @@ -1128,7 +1116,6 @@ #endif } return ACTION_EXIT_MENUITEM; - break; } return action; } @@ -1176,23 +1163,163 @@ break; case ACTION_EXIT_MENUITEM: return ACTION_EXIT_AFTER_THIS_MENUITEM; - break; } return action; } + +#ifdef HOTKEY +extern const struct menu_item_ex *selected_menu_item; +extern bool hotkey_settable_menu; + +#define HOT_MASK 0x0FF +#define HOT_WPS 0x100 +#define HOT_TREE 0x200 + +struct hotkey_assignment { + int item; + struct menu_func func; + int return_code; + const struct menu_item_ex *menu_addr; +}; + +#define HOTKEY_FUNC(func, param) {{(void *)func}, param} + +/* Any desired hotkey functions go in this struct. + Also update the enum table in hotkey.h */ +static struct hotkey_assignment hotkey_items[] = { + { HOTKEY_VIEW_PLAYLIST | HOT_WPS , HOTKEY_FUNC(NULL, NULL), + ONPLAY_PLAYLIST, &view_cur_playlist }, +#ifdef HAVE_PITCHSCREEN + { HOTKEY_PITCHSCREEN | HOT_WPS , HOTKEY_FUNC(gui_syncpitchscreen_run, NULL), + ONPLAY_RELOAD_DIR, &pitch_screen_item }, +#endif + { HOTKEY_DELETE | HOT_WPS | HOT_TREE , HOTKEY_FUNC(delete_item, NULL), + ONPLAY_RELOAD_DIR, &delete_file_item }, + { HOTKEY_DELETE | HOT_TREE , HOTKEY_FUNC(delete_item, NULL), + ONPLAY_RELOAD_DIR, &delete_dir_item }, + { HOTKEY_INSERT | HOT_TREE , HOTKEY_FUNC(playlist_insert_func, (intptr_t*)PLAYLIST_INSERT), + ONPLAY_START_PLAY, &i_pl_item }, +}; + +static const int num_hotkey_items = sizeof(hotkey_items) / sizeof(hotkey_items[0]); + +/* Execute the hotkey function, if listed for this screen */ +static int execute_hotkey(bool is_wps) +{ + int i; + struct hotkey_assignment *this_item; + const int context = is_wps ? HOT_WPS : HOT_TREE; + const int this_hotkey = (is_wps ? global_settings.hotkey_wps : + global_settings.hotkey_tree); + + /* search assignment struct for a match for the hotkey setting */ + for (i = 0; i < num_hotkey_items; i++) + { + this_item = &hotkey_items[i]; + if ((this_item->item & context) && + ((this_item->item & HOT_MASK) == this_hotkey)) + { + /* run the associated function (with optional param), if any */ + const struct menu_func func = this_item->func; + if (func.function != NULL) + { + if (func.param != NULL) + (*(func.function_w_param))(func.param); + else + (*(func.function))(); + } + /* return with the associated code */ + return this_item->return_code; + } + } + + /* no valid hotkey set */ + splash(HZ, ID2P(LANG_HOTKEY_NOT_SET)); + return ONPLAY_RELOAD_DIR; +} + +/* Set the hotkey to the current context menu function, if listed */ +static void set_hotkey(bool is_wps) +{ + int i; + struct hotkey_assignment *this_item; + const int context = is_wps ? HOT_WPS : HOT_TREE; + int *hk_func = is_wps ? &global_settings.hotkey_wps : + &global_settings.hotkey_tree, + *hk_desc = is_wps ? &global_settings.hotkey_wps_desc_id : + &global_settings.hotkey_tree_desc_id; + int this_hk, + this_id; + bool match_found = false; + + /* search assignment struct for a function that matches the current menu item */ + for (i = 0; i < num_hotkey_items; i++) + { + this_item = &hotkey_items[i]; + if ((this_item->item & context) && + (this_item->menu_addr == selected_menu_item)) + { + this_hk = this_item->item & HOT_MASK; + this_id = P2ID((selected_menu_item->callback_and_desc)->desc); + match_found = true; + break; + } + } + + /* ignore the hotkey if no match found or no change to setting */ + if (!match_found || (this_hk == *hk_func)) return; + + char line1_buf[100]; + char line2_buf[101]; + char *line1 = line1_buf; + char *line2 = line2_buf; + char **line1_ptr = &line1; + char **line2_ptr = &line2; + const struct text_message message={(const char **)line2_ptr, 1}; + const struct text_message yes_message={(const char **)line1_ptr, 1}; + + snprintf(line1, 100, str(LANG_SET_HOTKEY), str(this_id)); + strcat(strcpy(line2, line1), "?"); + + /* confirm the hotkey setting change */ + if(gui_syncyesno_run(&message, &yes_message, NULL)==YESNO_YES) + { + /* store the hotkey settings */ + *hk_func = this_hk; + *hk_desc = this_id; + + settings_save(); + splash(HZ*2, line1); + } +} + +int onplay(char* file, int attr, int from, bool hotkey) +#else int onplay(char* file, int attr, int from) +#endif /* HOTKEY */ { const struct menu_item_ex *menu; onplay_result = ONPLAY_OK; context = from; selected_file = file; selected_file_attr = attr; +#ifdef HOTKEY + if (hotkey) + return execute_hotkey(context == CONTEXT_WPS); + hotkey_settable_menu = true; +#endif if (context == CONTEXT_WPS) menu = &wps_onplay_menu; else menu = &tree_onplay_menu; switch (do_menu(menu, NULL, NULL, false)) { +#ifdef HOTKEY + hotkey_settable_menu = false; + case MENU_SELECTED_HOTKEY: + set_hotkey(context == CONTEXT_WPS); + return ONPLAY_RELOAD_DIR; +#endif case GO_TO_WPS: return ONPLAY_START_PLAY; case GO_TO_ROOT: Index: apps/gui/wps.c =================================================================== --- apps/gui/wps.c (revision 25376) +++ apps/gui/wps.c (working copy) @@ -888,10 +888,20 @@ switch(button) { case ACTION_WPS_CONTEXT: +#ifdef HOTKEY + case ACTION_HOTKEY: { + bool hotkey = button == ACTION_HOTKEY; +#else + { +#endif gwps_leave_wps(); int retval = onplay(wps_state.id3->path, - FILE_ATTR_AUDIO, CONTEXT_WPS); + FILE_ATTR_AUDIO, CONTEXT_WPS +#ifdef HOTKEY + , hotkey +#endif + ); /* if music is stopped in the context menu we want to exit the wps */ if (retval == ONPLAY_MAINMENU || !audio_status()) @@ -1182,10 +1192,12 @@ case SYS_POWEROFF: default_event_handler(SYS_POWEROFF); break; +#ifndef HOTKEY case ACTION_WPS_VIEW_PLAYLIST: gwps_leave_wps(); return GO_TO_PLAYLIST_VIEWER; break; +#endif default: if(default_event_handler(button) == SYS_USB_CONNECTED) { Index: apps/menu.c =================================================================== --- apps/menu.c (revision 25376) +++ apps/menu.c (working copy) @@ -61,6 +61,12 @@ #include "list.h" #include "buttonbar.h" +/* hotkey settings */ +#ifdef HOTKEY +const struct menu_item_ex *selected_menu_item; +bool hotkey_settable_menu = false; +#endif + #define MAX_MENUS 8 /* used to allow for dynamic menus */ #define MAX_MENU_SUBITEMS 64 @@ -426,6 +432,15 @@ done = true; } #endif +#ifdef HOTKEY + else if ((action == ACTION_HOTKEY) && hotkey_settable_menu) + { + ret = MENU_SELECTED_HOTKEY; + done = true; + selected = get_menu_selection(gui_synclist_get_sel_pos(&lists),menu); + selected_menu_item = menu->submenus[selected]; + } +#endif else if (action == ACTION_TREE_WPS) { ret = GO_TO_PREVIOUS_MUSIC; Index: apps/settings.h =================================================================== --- apps/settings.h (revision 25376) +++ apps/settings.h (working copy) @@ -816,6 +816,13 @@ bool morse_input; /* text input method setting */ #endif +#ifdef HOTKEY + int hotkey_wps; + int hotkey_wps_desc_id; + int hotkey_tree; + int hotkey_tree_desc_id; +#endif + }; /** global variables **/ Index: apps/menus/settings_menu.c =================================================================== --- apps/menus/settings_menu.c (revision 25376) +++ apps/menus/settings_menu.c (working copy) @@ -47,6 +47,10 @@ #ifdef HAVE_DIRCACHE #include "dircache.h" #endif +#ifdef HOTKEY +#include "list.h" +#include "settings_list.h" +#endif /***********************************/ /* TAGCACHE MENU */ @@ -400,6 +404,58 @@ /***********************************/ +/* HOTKEY MENU */ +#ifdef HOTKEY +static void view_hotkey_info(void) +{ + struct simplelist_info info; + simplelist_info_init(&info, str(LANG_VIEW_HOTKEY), 0, NULL); + info.hide_selection = true; + simplelist_set_line_count(2); + simplelist_addline(0, "WPS: %s", + str(global_settings.hotkey_wps_desc_id)); + simplelist_addline(1, "Tree: %s", + str(global_settings.hotkey_tree_desc_id)); + simplelist_show_list(&info); +} + +/* reset hotkey settings to their defaults */ +static void reset_hotkey_settings(void) +{ + void *vars[] = { + &global_settings.hotkey_tree, + &global_settings.hotkey_tree_desc_id, + &global_settings.hotkey_wps, + &global_settings.hotkey_wps_desc_id, + }; + const int num_settings = sizeof(vars) / sizeof(vars[0]); + int i; + + for (i = 0; i < num_settings; i++) + { + const struct settings_list *setting = + find_setting(vars[i], NULL); + reset_setting(setting, setting->setting); + } + + settings_save(); + splash(HZ, str(LANG_RESET_DONE_CLEAR)); +} + +MENUITEM_FUNCTION(hotkey_view, 0, ID2P(LANG_VIEW_HOTKEY), + (int(*)(void))view_hotkey_info, NULL, + NULL, Icon_NOICON); +MENUITEM_FUNCTION(hotkey_reset, 0, ID2P(LANG_RESET), + (int(*)(void))reset_hotkey_settings, NULL, + NULL, Icon_NOICON); +MAKE_MENU(hotkey_menu, ID2P(LANG_HOTKEY), 0, Icon_NOICON, + &hotkey_view, &hotkey_reset); +#endif /*hotkey */ +/* HOTKEY MENU */ +/***********************************/ + + +/***********************************/ /* SETTINGS MENU */ static int language_browse(void) { @@ -415,7 +471,10 @@ &tagcache_menu, #endif &display_menu, &system_menu, - &bookmark_settings_menu, &browse_langs, &voice_settings_menu + &bookmark_settings_menu, &browse_langs, &voice_settings_menu, +#ifdef HOTKEY + &hotkey_menu, +#endif ); /* SETTINGS MENU */ /***********************************/ Index: apps/onplay.h =================================================================== --- apps/onplay.h (revision 25376) +++ apps/onplay.h (working copy) @@ -21,7 +21,11 @@ #ifndef _ONPLAY_H_ #define _ONPLAY_H_ -int onplay(char* file, int attr, int from_screen); +int onplay(char* file, int attr, int from_screen +#ifdef HOTKEY + , bool hotkey +#endif + ); enum { ONPLAY_MAINMENU = -1, Index: apps/settings_list.c =================================================================== --- apps/settings_list.c (revision 25376) +++ apps/settings_list.c (working copy) @@ -56,6 +56,7 @@ #include "touchscreen.h" #include "ctype.h" /* For isspace() */ #endif +#include "hotkey.h" #define NVRAM(bytes) (bytes< ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id: hotkey.h 24791 2010-02-20 19:06:39Z kugel $ + * + * Copyright (C) 2002 Björn Stenberg + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ +#ifndef _HOTKEY_H_ +#define _HOTKEY_H_ + +#ifdef HOTKEY +enum hotkey_settings { + HOTKEY_OFF, + HOTKEY_VIEW_PLAYLIST, +#ifdef HAVE_PITCHSCREEN + HOTKEY_PITCHSCREEN, +#endif + HOTKEY_DELETE, + HOTKEY_INSERT, +}; + +#define HOTKEY_WPS_DEFAULT HOTKEY_VIEW_PLAYLIST +#define HOTKEY_WPS_ID_DEFAULT LANG_VIEW_DYNAMIC_PLAYLIST +#define HOTKEY_TREE_DEFAULT HOTKEY_OFF +#define HOTKEY_TREE_ID_DEFAULT LANG_OFF + +#endif + +#endif Property changes on: apps/hotkey.h ___________________________________________________________________ Added: svn:executable + * Index: apps/features.txt =================================================================== --- apps/features.txt (revision 25376) +++ apps/features.txt (working copy) @@ -70,6 +70,10 @@ remote_button_hold #endif +#if defined(HOTKEY) +hotkey +#endif + #if defined(HAVE_LCD_BITMAP) lcd_bitmap #endif Index: apps/bookmark.c =================================================================== --- apps/bookmark.c (revision 25376) +++ apps/bookmark.c (working copy) @@ -728,7 +728,12 @@ ID2P(LANG_BOOKMARK_CONTEXT_DELETE)); static const int menu_actions[] = { - ACTION_STD_OK, ACTION_BMS_DELETE + ACTION_STD_OK, +#ifdef HOTKEY + ACTION_HOTKEY +#else + ACTION_BMS_DELETE +#endif }; int selection = do_menu(&menu_items, NULL, NULL, false); @@ -757,7 +762,11 @@ exit = true; break; +#ifdef HOTKEY + case ACTION_HOTKEY: +#else case ACTION_BMS_DELETE: +#endif if (item >= 0) { const char *lines[]={ Index: apps/root_menu.h =================================================================== --- apps/root_menu.h (revision 25376) +++ apps/root_menu.h (working copy) @@ -53,6 +53,9 @@ GO_TO_BROWSEPLUGINS, GO_TO_TIMESCREEN, GO_TO_PLAYLIST_VIEWER, +#ifdef HOTKEY + MENU_SELECTED_HOTKEY, +#endif }; extern const struct menu_item_ex root_menu_; Index: apps/keymaps/keymap-e200.c =================================================================== --- apps/keymaps/keymap-e200.c (revision 25376) +++ apps/keymaps/keymap-e200.c (working copy) @@ -80,11 +80,16 @@ { ACTION_WPS_QUICKSCREEN, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_DOWN }, { ACTION_WPS_MENU, BUTTON_DOWN|BUTTON_REL, BUTTON_DOWN }, +#ifndef HOTKEY { ACTION_WPS_VIEW_PLAYLIST, BUTTON_REC|BUTTON_REL, BUTTON_REC }, +#endif { ACTION_WPS_REC, BUTTON_REC|BUTTON_REPEAT, BUTTON_NONE }, { ACTION_WPS_PITCHSCREEN, BUTTON_SELECT|BUTTON_UP, BUTTON_SELECT }, { ACTION_WPS_ID3SCREEN, BUTTON_SELECT|BUTTON_DOWN, BUTTON_SELECT }, +#ifdef HOTKEY + { ACTION_HOTKEY, BUTTON_REC|BUTTON_REL, BUTTON_REC }, +#endif LAST_ITEM_IN_LIST }; /* button_context_wps */ @@ -108,6 +113,9 @@ static const struct button_mapping button_context_list[] = { { ACTION_LISTTREE_PGUP, BUTTON_REC|BUTTON_SCROLL_BACK, BUTTON_REC }, { ACTION_LISTTREE_PGDOWN, BUTTON_REC|BUTTON_SCROLL_FWD, BUTTON_REC }, +#ifdef HOTKEY + { ACTION_HOTKEY, BUTTON_REC|BUTTON_REL, BUTTON_REC }, +#endif LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_STD) }; /* button_context_list */ @@ -272,11 +280,13 @@ LAST_ITEM_IN_LIST }; /* button_context_keyboard */ +#ifndef HOTKEY static const struct button_mapping button_context_bmark[] = { { ACTION_BMS_DELETE, BUTTON_REC, BUTTON_NONE }, LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_LIST), }; /* button_context_bmark */ +#endif #ifdef USB_ENABLE_HID static const struct button_mapping button_context_usb_hid[] = { @@ -418,7 +428,11 @@ case CONTEXT_FM: return button_context_radio; case CONTEXT_BOOKMARKSCREEN: +#ifdef HOTKEY + return button_context_list; +#else return button_context_bmark; +#endif case CONTEXT_QUICKSCREEN: return button_context_quickscreen; case CONTEXT_PITCHSCREEN: Index: apps/playlist_catalog.c =================================================================== --- apps/playlist_catalog.c (revision 25376) +++ apps/playlist_catalog.c (working copy) @@ -280,8 +280,11 @@ snprintf(playlist, MAX_PATH, "%s/%s", playlist_dir, sel_file); - if (onplay(playlist, FILE_ATTR_M3U, - CONTEXT_TREE) != ONPLAY_OK) + if (onplay(playlist, FILE_ATTR_M3U, CONTEXT_TREE +#ifdef HOTKEY + , false +#endif + ) != ONPLAY_OK) { result = 0; exit = true; Index: firmware/export/config/sansae200.h =================================================================== --- firmware/export/config/sansae200.h (revision 25376) +++ firmware/export/config/sansae200.h (working copy) @@ -214,3 +214,5 @@ #define IRAMORIG 0x40004000 #endif +/* Define this if a programmable hotkey is mapped */ +#define HOTKEY