diff --git a/apps/gui/wps.c b/apps/gui/wps.c
index a5e7ad3029..d905cdb69d 100644
--- a/apps/gui/wps.c
+++ b/apps/gui/wps.c
@@ -798,9 +798,10 @@ long gui_wps_show(void)
case ACTION_WPS_HOTKEY:
{
hotkey = true;
- if (!global_settings.hotkey_wps)
+ int act = HK_CTX_GET(0, global_settings.context_wps);
+ if (act == HOTKEY_OFF)
break;
- if (get_hotkey(global_settings.hotkey_wps)->flags & HOTKEY_FLAG_NOSBS)
+ if (get_hotkey(act)->flags & HOTKEY_FLAG_NOSBS)
{
/* leave WPS without re-enabling theme */
theme_enabled = false;
@@ -836,7 +837,7 @@ long gui_wps_show(void)
{
restore_theme();
theme_enabled = false;
- open_plugin_run(ID2P(LANG_OPEN_PLUGIN_SET_WPS_CONTEXT_PLUGIN));
+ open_plugin_run(ID2P(LANG_ONPLAY_MENU_TITLE));
}
restore = true;
diff --git a/apps/lang/english.lang b/apps/lang/english.lang
index 8e0523a42b..6ed795f602 100644
--- a/apps/lang/english.lang
+++ b/apps/lang/english.lang
@@ -15205,17 +15205,17 @@
- id: LANG_OPEN_PLUGIN_SET_WPS_CONTEXT_PLUGIN
- desc: open plugin module
+ id: LANG_SET_CONTEXT_ITEM
+ desc: WPS context item
user: core
- *: "Set WPS Context Plugin"
+ *: "Set Context Item"
- *: "Set WPS Context Plugin"
+ *: "Set Context Item"
- *: "Set WPS Context Plugin"
+ *: "Set Context Item"
diff --git a/apps/menus/settings_menu.c b/apps/menus/settings_menu.c
index 9ea1b4dbee..f3246f8e11 100644
--- a/apps/menus/settings_menu.c
+++ b/apps/menus/settings_menu.c
@@ -721,32 +721,110 @@ MAKE_MENU(voice_settings_menu, ID2P(LANG_VOICE), 0, Icon_Voice,
/* VOICE MENU */
/***********************************/
-/* WPS_CONTEXT_PLUGIN */
+/* WPS_CONTEXT_MENU */
/***********************************/
-static void wps_plugin_cb(void)
+
+
+static char *wps_context_menu_get_name(int selected_item, void * data,
+ char *buffer, size_t buffer_len)
{
- open_plugin_browse(ID2P(LANG_OPEN_PLUGIN_SET_WPS_CONTEXT_PLUGIN));
+ int item = (intptr_t)data;
+ int act = HK_CTX_GET(item, global_settings.context_wps);
+ const struct hotkey_assignment *cur = get_hotkey(act);
+#ifdef HAVE_HOTKEY
+ if (item == 0)
+ {
+ snprintf(buffer, buffer_len,"%s [%s]",
+ str(LANG_HOTKEY_WPS), str(cur->lang_id));
+ }
+ else
+#endif
+ {
+ snprintf(buffer, buffer_len,"%s %d [%s]",
+ str(LANG_SET_CONTEXT_ITEM), item, str(cur->lang_id));
+ }
+ return buffer;
+ (void)selected_item;
}
-MENUITEM_FUNCTION(wps_set_context_plugin, 0,
- ID2P(LANG_OPEN_PLUGIN_SET_WPS_CONTEXT_PLUGIN),
- wps_plugin_cb, NULL, Icon_Plugin);
-/* WPS_CONTEXT_PLUGIN */
-/***********************************/
+static int wps_context_menu_speak_item(int selected_item, void * data)
+{
+ int item = (intptr_t)data;
+ int act = HK_CTX_GET(item, global_settings.context_wps);
+ const struct hotkey_assignment *cur = get_hotkey(act);
+#ifdef HAVE_HOTKEY
+ if (item == 0)
+ {
+ talk_id(LANG_HOTKEY_WPS, false);
+ }
+ else
+#endif
+ {
+ talk_id(LANG_SET_CONTEXT_ITEM, false);
+ talk_number((intptr_t)data, true);
+ }
+ talk_id(cur->lang_id, true);
+ return 0;
+ (void)selected_item;
+}
+
+#ifdef HAVE_HOTKEY
+MENUITEM_FUNCTION_DYNTEXT_W_PARAM(hotkey_wps_item, 0,
+ wps_context_menu_do_setting, (void*)0,
+ wps_context_menu_get_name,
+ wps_context_menu_speak_item,
+ (void*)0, NULL, Icon_Menu_setting);
+#else
+MENUITEM_FUNCTION_DYNTEXT_W_PARAM(wps_set_context_item_0, 0,
+ wps_context_menu_do_setting, (void*)0,
+ wps_context_menu_get_name,
+ wps_context_menu_speak_item,
+ (void*)0, NULL, Icon_Menu_setting);
+#endif
+MENUITEM_FUNCTION_DYNTEXT_W_PARAM(wps_set_context_item_1, 0,
+ wps_context_menu_do_setting, (void*)1,
+ wps_context_menu_get_name,
+ wps_context_menu_speak_item,
+ (void*)1, NULL, Icon_Menu_setting);
+
+MENUITEM_FUNCTION_DYNTEXT_W_PARAM(wps_set_context_item_2, 0,
+ wps_context_menu_do_setting, (void*)2,
+ wps_context_menu_get_name,
+ wps_context_menu_speak_item,
+ (void*)2, NULL, Icon_Menu_setting);
+
+MENUITEM_FUNCTION_DYNTEXT_W_PARAM(wps_set_context_item_3, 0,
+ wps_context_menu_do_setting, (void*)3,
+ wps_context_menu_get_name,
+ wps_context_menu_speak_item,
+ (void*)3, NULL, Icon_Menu_setting);
+
+MENUITEM_FUNCTION_DYNTEXT_W_PARAM(wps_set_context_item_4, 0,
+ wps_context_menu_do_setting, (void*)4,
+ wps_context_menu_get_name,
+ wps_context_menu_speak_item,
+ (void*)4, NULL, Icon_Menu_setting);
+
+static void reset_wps_items(void)
+{
+ reset_setting(find_setting(&global_settings.context_wps), NULL);
+}
+MENUITEM_FUNCTION(reset_wps_item, 0, ID2P(LANG_RESET), reset_wps_items, NULL, Icon_Queued)
/***********************************/
/* WPS Settings MENU */
-
-#ifdef HAVE_HOTKEY
-MENUITEM_SETTING(hotkey_wps_item, &global_settings.hotkey_wps, NULL);
-#endif
-
MAKE_MENU(wps_settings, ID2P(LANG_WPS), 0, Icon_Playback_menu
#ifdef HAVE_HOTKEY
- ,&hotkey_wps_item
+ ,&hotkey_wps_item /* this is item 0 */
+#else
+ ,&wps_set_context_item_0
#endif
- ,&wps_set_context_plugin
+ ,&wps_set_context_item_1
+ ,&wps_set_context_item_2
+ ,&wps_set_context_item_3
+ ,&wps_set_context_item_4
+ ,&reset_wps_item
);
/* WPS Settings MENU */
diff --git a/apps/onplay.c b/apps/onplay.c
index 824b2f38cc..87ad633526 100644
--- a/apps/onplay.c
+++ b/apps/onplay.c
@@ -70,6 +70,7 @@
static int onplay_result = ONPLAY_OK;
static bool in_queue_submenu = false;
+static char ctx_plugin_namebuf[OPEN_PLUGIN_NAMESZ];
static bool (*ctx_current_playlist_insert)(int position, bool queue, bool create_new);
static int (*ctx_add_to_playlist)(const char* playlist, bool new_playlist);
@@ -664,8 +665,185 @@ MENUITEM_FUNCTION(rating_item, 0, ID2P(LANG_MENU_SET_RATING),
set_rating_inline,
ratingitem_callback, Icon_Questionmark);
#endif
-MENUITEM_RETURNVALUE(plugin_item, ID2P(LANG_OPEN_PLUGIN),
- GO_TO_PLUGIN, NULL, Icon_Plugin);
+
+static char *wps_context_get_item_name(int selected_item, void * data,
+ char *buffer, size_t buffer_len)
+{
+ (void)selected_item; (void)data; (void)buffer; (void)buffer_len;
+ int item = (intptr_t)data;
+ const struct hotkey_assignment *hkey =
+ get_hotkey(HK_CTX_GET(item, global_settings.context_wps));
+ if (hkey->action == HOTKEY_PLUGIN)
+ {
+ return ctx_plugin_namebuf;
+ }
+#ifdef HAVE_PITCHCONTROL
+ else if (hkey->action == HOTKEY_PITCHSCREEN)
+ {
+ int32_t ts = dsp_get_timestretch();
+ int32_t pitch = sound_get_pitch();
+ if (ts != PITCH_SPEED_100 || pitch != PITCH_SPEED_100)
+ {
+ int32_t speed = GET_SPEED(pitch, ts);
+ snprintf(buffer, buffer_len,"%s %ld.%ld%% / %ld.%ld%%", str(hkey->lang_id),
+ pitch / PITCH_SPEED_PRECISION,
+ (pitch % PITCH_SPEED_PRECISION) / (PITCH_SPEED_PRECISION / 10),
+ speed / PITCH_SPEED_PRECISION,
+ (speed % PITCH_SPEED_PRECISION) / (PITCH_SPEED_PRECISION / 10));
+ return buffer;
+ }
+ }
+#endif
+ return ID2P(hkey->lang_id);
+}
+
+static int wps_context_item_speak_item(int selected_item, void * data)
+{
+ if (!global_settings.talk_menu)
+ return 0;
+ int item = (intptr_t)data;
+ const struct hotkey_assignment *hkey =
+ get_hotkey(HK_CTX_GET(item, global_settings.context_wps));
+
+ if (hkey->action == HOTKEY_PLUGIN)
+ {
+ talk_spell(ctx_plugin_namebuf, false);
+ return 0;
+ }
+#ifdef HAVE_PITCHCONTROL
+ else if (hkey->action == HOTKEY_PITCHSCREEN)
+ {
+ int32_t ts = dsp_get_timestretch();
+ int32_t pitch = sound_get_pitch();
+ if (ts != PITCH_SPEED_100 || pitch != PITCH_SPEED_100)
+ {
+ if (global_settings.talk_menu)
+ {
+ talk_id(hkey->lang_id, false);
+
+ if (pitch != PITCH_SPEED_100)
+ talk_value_decimal(pitch, UNIT_PERCENT, 2, true);
+ if (ts != PITCH_SPEED_100)
+ {
+ int32_t speed = GET_SPEED(pitch, ts);
+ talk_id(LANG_SPEED, true);
+ talk_value_decimal(speed, UNIT_PERCENT, 2, true);
+ }
+ }
+ return 0;
+ }
+ }
+#endif
+ talk_id(hkey->lang_id, false);
+ return 0;
+ (void)selected_item;
+}
+
+static int execute_hotkey(int action);
+static int wps_context_item_cb(int,const struct menu_item_ex *,struct gui_synclist *);
+
+/* need special handling so we can change the icon */
+#define WPSCTX_RETURNVALUE_DYNTEXT(name, val, cb, text_callback, \
+ voice_callback, text_cb_data, icon) \
+ struct menu_get_name_and_icon name##_ \
+ = {cb,text_callback,voice_callback,text_cb_data,icon}; \
+ static const struct menu_item_ex name = \
+ { MT_RETURN_VALUE|MENU_DYNAMIC_DESC, { .value = val}, \
+ {.menu_get_name_and_icon = & name##_}};
+
+WPSCTX_RETURNVALUE_DYNTEXT(context_item_0, GO_TO_PREVIOUS, wps_context_item_cb,
+ wps_context_get_item_name, wps_context_item_speak_item, (void*)0, Icon_NOICON);
+
+WPSCTX_RETURNVALUE_DYNTEXT(context_item_1, GO_TO_PREVIOUS, wps_context_item_cb,
+ wps_context_get_item_name, wps_context_item_speak_item, (void*)1, Icon_NOICON);
+
+WPSCTX_RETURNVALUE_DYNTEXT(context_item_2, GO_TO_PREVIOUS, wps_context_item_cb,
+ wps_context_get_item_name, wps_context_item_speak_item, (void*)2, Icon_NOICON);
+
+WPSCTX_RETURNVALUE_DYNTEXT(context_item_3, GO_TO_PREVIOUS, wps_context_item_cb,
+ wps_context_get_item_name, wps_context_item_speak_item, (void*)3, Icon_NOICON);
+
+WPSCTX_RETURNVALUE_DYNTEXT(context_item_4, GO_TO_PREVIOUS, wps_context_item_cb,
+ wps_context_get_item_name, wps_context_item_speak_item, (void*)4, Icon_NOICON);
+
+/* map item number to menu_get_name_and_icon structs so we can change icons */
+static struct menu_get_name_and_icon * const ctx_item_map[HK_CTX_ITEMS]=
+ {&context_item_0_, &context_item_1_, &context_item_2_, &context_item_3_, &context_item_4_};
+
+#ifdef HAVE_PITCHCONTROL
+MENUITEM_FUNCTION(pitch_screen_item, 0, ID2P(LANG_PITCH),
+ gui_syncpitchscreen_run, NULL, Icon_Audio);
+MENUITEM_FUNCTION(pitch_reset_item, 0, ID2P(LANG_RESET_SETTING),
+ reset_pitch, NULL, Icon_Submenu_Entered);
+
+MAKE_ONPLAYMENU(pitch_menu, ID2P(LANG_PITCH),
+ NULL, Icon_Audio,
+ &pitch_screen_item,
+ &pitch_reset_item);
+#endif
+
+static int wps_context_item_cb(int action,
+ const struct menu_item_ex *this_item,
+ struct gui_synclist *this_list)
+{
+ if (action == ACTION_ENTER_MENUITEM || action == ACTION_REQUEST_MENUITEM)
+ {
+ int item = (intptr_t) this_item->menu_get_name_and_icon->list_get_name_data;
+ int act = HK_CTX_GET(item, global_settings.context_wps);
+ if (act == HOTKEY_OFF)
+ {
+ return ACTION_EXIT_MENUITEM;
+ }
+ ctx_item_map[item]->icon_id = get_hotkey(act)->icon;
+ if (act == HOTKEY_PLUGIN && action == ACTION_REQUEST_MENUITEM)
+ {
+ int res = open_plugin_load_entry(ID2P(LANG_ONPLAY_MENU_TITLE));
+ if (res >= 0 || res == OPEN_PLUGIN_NEEDS_FLUSHED)
+ {
+ struct open_plugin_entry_t *op = open_plugin_get_entry();
+ strmemccpy(ctx_plugin_namebuf, op->name, sizeof(ctx_plugin_namebuf));
+ }
+ else
+ {
+ strmemccpy(ctx_plugin_namebuf, str(LANG_OPEN_PLUGIN),
+ sizeof(ctx_plugin_namebuf));
+ }
+ }
+#ifdef HAVE_PITCHCONTROL
+ else if (act == HOTKEY_PITCHSCREEN)
+ {
+ int32_t ts = dsp_get_timestretch();
+ if (sound_get_pitch() != PITCH_SPEED_100 || ts != PITCH_SPEED_100)
+ {
+ ctx_item_map[item]->icon_id = Icon_Submenu; /* if setting changed show + */
+ }
+ }
+#endif
+
+ }
+ else if (action == ACTION_EXIT_MENUITEM) /* selected */
+ {
+ int item = (intptr_t) this_item->menu_get_name_and_icon->list_get_name_data;
+ int act = HK_CTX_GET(item, global_settings.context_wps);
+ if (act == HOTKEY_CONTEXT_MENU)
+ {
+ onplay_result = hotkey_run_menu(HOTKEY_FLAG_WPS, true, 0);
+ }
+#ifdef HAVE_PITCHCONTROL
+ else if (act == HOTKEY_PITCHSCREEN && ctx_item_map[item]->icon_id == Icon_Submenu)
+ {
+ do_menu(&pitch_menu, NULL, NULL, false);
+ }
+#endif
+ else
+ {
+ onplay_result = execute_hotkey(act);
+ }
+ return ACTION_EXIT_AFTER_THIS_MENUITEM;
+ }
+ return action;
+ (void)this_list;
+}
static bool view_cue(void)
{
@@ -710,60 +888,6 @@ static int browse_id3_wrapper(void)
MENUITEM_FUNCTION(browse_id3_item, MENU_FUNC_CHECK_RETVAL, ID2P(LANG_MENU_SHOW_ID3_INFO),
browse_id3_wrapper, NULL, Icon_NOICON);
-#ifdef HAVE_PITCHCONTROL
-MENUITEM_FUNCTION(pitch_screen_item, 0, ID2P(LANG_PITCH),
- gui_syncpitchscreen_run, NULL, Icon_Audio);
-MENUITEM_FUNCTION(pitch_reset_item, 0, ID2P(LANG_RESET_SETTING),
- reset_pitch, NULL, Icon_Submenu_Entered);
-
-static int pitch_callback(int action,
- const struct menu_item_ex *this_item,
- struct gui_synclist *this_list);
-
-/* need special handling so we can toggle the icon */
-#define MAKE_PITCHMENU( name, str, callback, icon, ... ) \
- static const struct menu_item_ex *name##_[] = {__VA_ARGS__}; \
- struct menu_callback_with_desc name##__ = {callback,str,icon}; \
- static const struct menu_item_ex name = \
- {MT_MENU|MENU_HAS_DESC|MENU_EXITAFTERTHISMENU| \
- MENU_ITEM_COUNT(sizeof( name##_)/sizeof(*name##_)), \
- { (void*)name##_},{.callback_and_desc = & name##__}};
-
-MAKE_PITCHMENU(pitch_menu, ID2P(LANG_PITCH),
- pitch_callback, Icon_Audio,
- &pitch_screen_item,
- &pitch_reset_item);
-
-static int pitch_callback(int action,
- const struct menu_item_ex *this_item,
- struct gui_synclist *this_list)
-{
- if (action == ACTION_ENTER_MENUITEM || action == ACTION_REQUEST_MENUITEM)
- {
- pitch_menu__.icon_id = Icon_Submenu; /* if setting changed show + */
- int32_t ts = dsp_get_timestretch();
- if (sound_get_pitch() == PITCH_SPEED_100 && ts == PITCH_SPEED_100)
- {
- pitch_menu__.icon_id = Icon_Audio;
- if (action == ACTION_ENTER_MENUITEM)
- { /* if default then run pitch screen directly */
- gui_syncpitchscreen_run();
- action = ACTION_EXIT_MENUITEM;
- }
- }
- }
- return action;
-
- (void)this_item;
- (void)this_list;
-}
-#endif /*def HAVE_PITCHCONTROL*/
-
-#ifdef HAVE_ALBUMART
-MENUITEM_FUNCTION(view_album_art_item, 0, ID2P(LANG_VIEW_ALBUMART),
- view_album_art, NULL, Icon_NOICON);
-#endif
-
static int clipboard_delete_selected_fileobject(void)
{
int rc = delete_fileobject(selected_file.path);
@@ -912,7 +1036,7 @@ static int reveal(void)
strmemccpy(global_status.browse_last_folder, selected_file.path,
sizeof global_status.browse_last_folder);
onplay_result = ONPLAY_REVEAL_FILE;
- return 0;
+ return GO_TO_FILEBROWSER;
}
MENUITEM_FUNCTION(reveal_item, 0, ID2P(LANG_SHOW_IN_FILES),
@@ -1146,15 +1270,14 @@ MAKE_ONPLAYMENU( wps_onplay_menu, ID2P(LANG_ONPLAY_MENU_TITLE),
&rating_item,
#endif
&bookmark_menu,
- &plugin_item,
- &browse_id3_item,
- &reveal_item, &view_cue_item,
-#ifdef HAVE_PITCHCONTROL
- &pitch_menu,
-#endif
-#ifdef HAVE_ALBUMART
- &view_album_art_item,
+ &view_cue_item,
+#ifndef HAVE_HOTKEY
+ &context_item_0,
#endif
+ &context_item_1,
+ &context_item_2,
+ &context_item_3,
+ &context_item_4,
);
int sort_playlists_callback(int action,
@@ -1194,11 +1317,13 @@ MAKE_ONPLAYMENU( tree_onplay_menu, ID2P(LANG_ONPLAY_MENU_TITLE),
#endif
&add_to_faves_item, &set_as_dir_menu, &file_menu, &sort_playlists,
);
+
static int onplaymenu_callback(int action,
const struct menu_item_ex *this_item,
struct gui_synclist *this_list)
{
(void)this_list;
+
switch (action)
{
case ACTION_TREE_STOP:
@@ -1226,7 +1351,6 @@ static int onplaymenu_callback(int action,
return action;
}
-#ifdef HAVE_HOTKEY
/* direct function calls, no need for menu callbacks */
static bool hotkey_delete_item(void)
{
@@ -1287,12 +1411,26 @@ static int hotkey_tree_run_plugin(void *param)
return ONPLAY_RELOAD_DIR;
}
-static int hotkey_run_menu(void); /* display hotkey items as a menu */
static int hotkey_wps_run_plugin(void)
{
- open_plugin_run(ID2P(LANG_HOTKEY_WPS));
+ if (get_current_activity() == ACTIVITY_CONTEXTMENU)
+ open_plugin_run(ID2P(LANG_ONPLAY_MENU_TITLE));
+#ifdef HAVE_HOTKEY
+ else
+ open_plugin_run(ID2P(LANG_HOTKEY_WPS));
+#endif
return ONPLAY_OK;
}
+
+static int hotkey_execute_menu(void)
+{
+ intptr_t flag = HOTKEY_FLAG_WPS;
+ if (selected_file.context != CONTEXT_WPS)
+ flag = HOTKEY_FLAG_TREE;
+
+ return hotkey_run_menu(flag, true, 0);
+}
+
#define HOTKEY_FUNC(func, param) {{(void *)func}, param}
/* Any desired hotkey functions go here, in the enum in onplay.h,
@@ -1304,82 +1442,103 @@ static const struct hotkey_assignment hotkey_items[] = {
.lang_id = LANG_OFF,
.func = HOTKEY_FUNC(NULL,NULL),
.return_code = ONPLAY_RELOAD_DIR,
- .flags = HOTKEY_FLAG_WPS | HOTKEY_FLAG_TREE },
- { .action = HOTKEY_VIEW_PLAYLIST,
+ .flags = HOTKEY_FLAG_WPS | HOTKEY_FLAG_TREE,
+ .icon=Icon_NOICON},
+ { .action = HOTKEY_VIEW_PLAYLIST,
.lang_id = LANG_VIEW_DYNAMIC_PLAYLIST,
.func = HOTKEY_FUNC(NULL, NULL),
.return_code = ONPLAY_PLAYLIST,
- .flags = HOTKEY_FLAG_WPS },
- { .action = HOTKEY_SHOW_TRACK_INFO,
+ .flags = HOTKEY_FLAG_WPS,
+ .icon = Icon_Playlist},
+ { .action = HOTKEY_SHOW_TRACK_INFO,
.lang_id = LANG_MENU_SHOW_ID3_INFO,
.func = HOTKEY_FUNC(browse_id3_wrapper, NULL),
.return_code = ONPLAY_RELOAD_DIR,
- .flags = HOTKEY_FLAG_WPS },
+ .flags = HOTKEY_FLAG_WPS,
+ .icon = Icon_Questionmark},
#ifdef HAVE_PITCHCONTROL
{ .action = HOTKEY_PITCHSCREEN,
.lang_id = LANG_PITCH,
.func = HOTKEY_FUNC(gui_syncpitchscreen_run, NULL),
.return_code = ONPLAY_RELOAD_DIR,
- .flags = HOTKEY_FLAG_WPS | HOTKEY_FLAG_NOSBS },
+ .flags = HOTKEY_FLAG_WPS | HOTKEY_FLAG_NOSBS,
+ .icon = Icon_Audio},
#endif
{ .action = HOTKEY_OPEN_WITH,
.lang_id = LANG_ONPLAY_OPEN_WITH,
.func = HOTKEY_FUNC(hotkey_open_with, NULL),
.return_code = ONPLAY_RELOAD_DIR,
- .flags = HOTKEY_FLAG_WPS | HOTKEY_FLAG_TREE },
- { .action = HOTKEY_DELETE,
+ .flags = HOTKEY_FLAG_WPS | HOTKEY_FLAG_TREE,
+ .icon = Icon_Plugin},
+ { .action = HOTKEY_DELETE,
.lang_id = LANG_DELETE,
.func = HOTKEY_FUNC(hotkey_delete_item, NULL),
.return_code = ONPLAY_RELOAD_DIR,
- .flags = HOTKEY_FLAG_WPS | HOTKEY_FLAG_TREE },
- { .action = HOTKEY_INSERT,
+ .flags = HOTKEY_FLAG_WPS | HOTKEY_FLAG_TREE,
+ .icon = Icon_NOICON},
+ { .action = HOTKEY_INSERT,
.lang_id = LANG_ADD,
.func = HOTKEY_FUNC(add_to_playlist, (intptr_t*)&addtopl_insert),
.return_code = ONPLAY_RELOAD_DIR,
- .flags = HOTKEY_FLAG_TREE },
- { .action = HOTKEY_INSERT_SHUFFLED,
+ .flags = HOTKEY_FLAG_TREE,
+ .icon = Icon_Queued},
+ { .action = HOTKEY_INSERT_SHUFFLED,
.lang_id = LANG_ADD_SHUFFLED,
.func = HOTKEY_FUNC(hotkey_tree_pl_insert_shuffled, NULL),
.return_code = ONPLAY_FUNC_RETURN,
- .flags = HOTKEY_FLAG_TREE },
- { .action = HOTKEY_PLUGIN,
+ .flags = HOTKEY_FLAG_TREE,
+ .icon = Icon_Queued},
+ { .action = HOTKEY_PLUGIN,
.lang_id = LANG_OPEN_PLUGIN,
.func = HOTKEY_FUNC(hotkey_wps_run_plugin, NULL),
.return_code = ONPLAY_FUNC_RETURN,
- .flags = HOTKEY_FLAG_WPS | HOTKEY_FLAG_NOSBS },
- { .action = HOTKEY_BOOKMARK,
+ .flags = HOTKEY_FLAG_WPS | HOTKEY_FLAG_NOSBS,
+ .icon = Icon_Plugin},
+ { .action = HOTKEY_BOOKMARK,
.lang_id = LANG_BOOKMARK_MENU_CREATE,
.func = HOTKEY_FUNC(bookmark_create_menu, NULL),
.return_code = ONPLAY_OK,
- .flags = HOTKEY_FLAG_WPS | HOTKEY_FLAG_NOSBS },
- { .action = HOTKEY_BOOKMARK_LIST,
+ .flags = HOTKEY_FLAG_WPS | HOTKEY_FLAG_NOSBS,
+ .icon = Icon_Bookmark},
+ { .action = HOTKEY_BOOKMARK_LIST,
.lang_id = LANG_BOOKMARK_MENU_LIST,
.func = HOTKEY_FUNC(bookmark_load_menu, NULL),
.return_code = ONPLAY_START_PLAY,
- .flags = HOTKEY_FLAG_WPS },
- { .action = HOTKEY_PROPERTIES,
+ .flags = HOTKEY_FLAG_WPS,
+ .icon = Icon_Bookmark},
+ { .action = HOTKEY_PROPERTIES,
.lang_id = LANG_PROPERTIES,
.func = HOTKEY_FUNC(hotkey_tree_run_plugin, (void *)"properties"),
.return_code = ONPLAY_FUNC_RETURN,
- .flags = HOTKEY_FLAG_TREE },
- { .action = HOTKEY_CONTEXT_MENU,
+ .flags = HOTKEY_FLAG_TREE,
+ .icon = Icon_NOICON},
+ { .action = HOTKEY_SHOW_IN_FILES,
+ .lang_id = LANG_SHOW_IN_FILES,
+ .func = HOTKEY_FUNC(reveal, NULL),
+ .return_code = ONPLAY_REVEAL_FILE,
+ .flags = HOTKEY_FLAG_WPS,
+ .icon = Icon_file_view_menu},
+ { .action = HOTKEY_CONTEXT_MENU,
.lang_id = LANG_ONPLAY_MENU_TITLE,
- .func = HOTKEY_FUNC(hotkey_run_menu, NULL),
+ .func = HOTKEY_FUNC(hotkey_execute_menu, NULL),
.return_code = ONPLAY_FUNC_RETURN,
- .flags = HOTKEY_FLAG_WPS | HOTKEY_FLAG_TREE },
+ .flags = HOTKEY_FLAG_WPS | HOTKEY_FLAG_TREE,
+ .icon = Icon_Submenu},
#ifdef HAVE_ALBUMART
{ .action = HOTKEY_ALBUMART,
.lang_id = LANG_VIEW_ALBUMART,
.func = HOTKEY_FUNC(view_album_art, NULL),
.return_code = ONPLAY_OK,
- .flags = HOTKEY_FLAG_WPS | HOTKEY_FLAG_NOSBS },
+ .flags = HOTKEY_FLAG_WPS | HOTKEY_FLAG_NOSBS,
+ .icon = Icon_Wps},
#endif
#ifdef HAVE_TAGCACHE
{ .action = HOTKEY_PICTUREFLOW,
.lang_id = LANG_ONPLAY_PICTUREFLOW,
.func = HOTKEY_FUNC(hotkey_tree_run_plugin, (void *)"pictureflow"),
.return_code = ONPLAY_FUNC_RETURN,
- .flags = HOTKEY_FLAG_TREE },
+ .flags = HOTKEY_FLAG_TREE,
+ .icon = Icon_Plugin},
#endif
};
@@ -1406,9 +1565,13 @@ static int execute_hotkey(int action)
if (func.function != NULL)
{
if (func.param != NULL)
+ {
func_return = (*func.function_w_param)(func.param);
+ }
else
+ {
func_return = (*func.function)();
+ }
}
const int return_code = this_item->return_code;
@@ -1417,60 +1580,83 @@ static int execute_hotkey(int action)
return return_code; /* or return the associated value */
}
+struct hk_menu_data
+{
+ const struct hotkey_assignment **hk_menu;
+ int hide_off;
+};
+
static const char* hotkey_get_name(int selected_item, void * data,
char * buffer, size_t buffer_len)
{
(void)buffer; (void)buffer_len;
- const struct hotkey_assignment **hk_menu = (const struct hotkey_assignment **)data;
- return ID2P(hk_menu[selected_item + 1]->lang_id); /* +1 to skip HOTKEY_OFF */
+ struct hk_menu_data *hk_data = (struct hk_menu_data*)data;
+ return ID2P(hk_data->hk_menu[selected_item + hk_data->hide_off]->lang_id);
}
static int hotkey_get_talk(int selected_item, void * data)
{
if (global_settings.talk_menu)
{
- const struct hotkey_assignment **hk_menu = (const struct hotkey_assignment **)data;
- talk_id(hk_menu[selected_item + 1]->lang_id, false); /* +1 to skip HOTKEY_OFF */
+ struct hk_menu_data *hk_data = (struct hk_menu_data*)data;
+ talk_id(hk_data->hk_menu[selected_item + hk_data->hide_off]->lang_id, false);
}
return 0;
}
-static int hotkey_run_menu(void)
+static enum themable_icons hotkey_get_icon(int selected_item, void * data)
{
- intptr_t flag = HOTKEY_FLAG_WPS;
- if (selected_file.context != CONTEXT_WPS)
- flag = HOTKEY_FLAG_TREE;
+ struct hk_menu_data *hk_data = (struct hk_menu_data*)data;
+ return hk_data->hk_menu[selected_item + hk_data->hide_off]->icon;
+}
+int hotkey_run_menu(intptr_t flag, bool execute, int current_action)
+{
const struct hotkey_assignment *hk_menu[ARRAYLEN(hotkey_items)];
+ struct hk_menu_data data = {hk_menu, execute ? 1 : 0};
+
struct simplelist_info info;
+ int selected = 0;
int count = 0;
for (size_t i = 0; i < ARRAYLEN(hotkey_items); i++)
{
hk_menu[i] = NULL; /*clear all the hk_menu entries prior to setting them */
if ((hotkey_items[i].flags & flag) == flag)
{
- if (hotkey_items[i].action != HOTKEY_CONTEXT_MENU)
+ if (!execute || hotkey_items[i].action != HOTKEY_CONTEXT_MENU)
{
+ if (hotkey_items[i].action == current_action)
+ selected = count;
hk_menu[count++] = &hotkey_items[i];
}
}
}
/* count -1 don't display HOTKEY_OFF item */
- simplelist_info_init(&info, str(LANG_ONPLAY_MENU_TITLE), count - 1, (void*)&hk_menu);
+ simplelist_info_init(&info, str(LANG_ONPLAY_MENU_TITLE), count - data.hide_off, (void*)&data);
info.get_name = hotkey_get_name;
- info.get_icon = NULL;
+ info.get_icon = hotkey_get_icon;
info.get_talk = hotkey_get_talk;
-
+ info.selection = selected - data.hide_off;
simplelist_show_list(&info);
- if (info.selection >= 0) /* run user selected hotkey item */
+ if (execute)
{
- return execute_hotkey(hk_menu[info.selection + 1]->action);
+ if (info.selection >= 0) /* run user selected hotkey item */
+ {
+ return execute_hotkey(hk_menu[info.selection + 1]->action);
+ }
+ return ONPLAY_RELOAD_DIR;
}
- return ONPLAY_RELOAD_DIR;
+ else
+ {
+ if (info.selection >= 0) /* return selected hotkey item */
+ {
+ return hk_menu[info.selection]->action;
+ }
+ }
+ return -1; /* canceled */
}
-#endif /* HOTKEY */
int onplay(char* file, int attr, int from_context, bool hotkey, int customaction)
{
@@ -1506,8 +1692,15 @@ int onplay(char* file, int attr, int from_context, bool hotkey, int customaction
#ifdef HAVE_HOTKEY
if (hotkey)
- return execute_hotkey((from_context == CONTEXT_WPS ?
- global_settings.hotkey_wps : global_settings.hotkey_tree));
+ {
+ if (from_context == CONTEXT_WPS)
+ {
+ wps_context_item_cb(ACTION_EXIT_MENUITEM, &context_item_0, NULL);
+ return onplay_result;
+ }
+ else
+ return execute_hotkey(global_settings.hotkey_tree);
+ }
#else
(void)hotkey;
#endif
@@ -1530,7 +1723,6 @@ int onplay(char* file, int attr, int from_context, bool hotkey, int customaction
if (get_current_activity() == ACTIVITY_CONTEXTMENU) /* Activity may have been */
pop_current_activity(); /* popped already by menu item */
-
if (menu_selection == GO_TO_WPS)
return ONPLAY_START_PLAY;
if (menu_selection == GO_TO_ROOT)
@@ -1549,3 +1741,101 @@ int get_onplay_context(void)
{
return selected_file.context;
}
+
+int wps_context_menu_do_setting(void *param)
+{
+ int context_wps = global_settings.context_wps;
+ int item = (intptr_t)param;
+
+ int temp = HK_CTX_GET(item, context_wps);
+ int sel = hotkey_run_menu(HOTKEY_FLAG_WPS, false, temp);
+ if (sel >=0)
+ {
+ if (sel == HOTKEY_PLUGIN)
+ {
+ if (get_current_activity() != ACTIVITY_QUICKSCREEN)
+ {
+#ifdef HAVE_HOTKEY
+ if (item == 0)
+ open_plugin_browse(ID2P(LANG_HOTKEY_WPS));
+ else
+#endif
+ open_plugin_browse(ID2P(LANG_ONPLAY_MENU_TITLE));
+ }
+ }
+
+ context_wps &= ~HK_CTX_SET(item, HK_CTX_MASK);/*clear*/
+ context_wps |= HK_CTX_SET(item, sel);
+
+ /* check for duplicates */
+#ifdef HAVE_HOTKEY
+ if (item > 0)
+ for (int i = 1; i < HK_CTX_ITEMS; i++)
+#else
+ for (int i = 0; i < HK_CTX_ITEMS; i++)
+#endif
+ {
+ if (i != item)
+ {
+ if (HK_CTX_GET(i, global_settings.context_wps) == sel)
+ {
+ context_wps &= ~HK_CTX_SET(i, HK_CTX_MASK);/*clear*/
+ }
+ }
+ }
+ global_settings.context_wps = context_wps;
+ }
+ return sel;
+}
+
+void wps_context_menu_load_from_cfg(void* setting, char *value)
+{
+ int item = 0;
+ int var = 0;
+ char *st = value;
+ char *end = value;
+ while (*end != '\0' && item < HK_CTX_ITEMS)
+ {
+ end++;
+ if (*end == ',' || *end == '\0')
+ {
+ st = skip_whitespace(st);
+
+ for (size_t i = ARRAYLEN(hotkey_items) - 1; i < ARRAYLEN(hotkey_items); i--)
+ {
+ if (strncasecmp(st, str(hotkey_items[i].lang_id), end-st) == 0)
+ {
+ var |= HK_CTX_SET(item, hotkey_items[i].action);
+ }
+ }
+ st = end + 1;
+ item++;
+ }
+ }
+ *(int*)setting = var;
+}
+
+char* wps_context_menu_write_to_cfg(void* setting, char*buf, int buf_len)
+{
+ int var = *(int*)setting;
+ unsigned i, written;
+ char *buffer = buf;
+ for (i = 0; i < HK_CTX_ITEMS && buf_len > 0; i++)
+ {
+ written = snprintf(buffer, buf_len, "%s, ",
+ str(get_hotkey(HK_CTX_GET(i, var))->lang_id));
+ buf_len -= written;
+ buffer += written;
+ }
+ return buf;
+}
+
+void wps_context_menu_set_default(void* setting, void* defaultval)
+{
+ *(int*)setting = *(int*)defaultval;
+}
+
+bool wps_context_menu_is_changed(void* setting, void* defaultval)
+{
+ return *(int*)setting != *(int*)defaultval;
+}
diff --git a/apps/onplay.h b/apps/onplay.h
index e811b9b983..2f1407b58f 100644
--- a/apps/onplay.h
+++ b/apps/onplay.h
@@ -21,20 +21,15 @@
#ifndef _ONPLAY_H_
#define _ONPLAY_H_
-#ifdef HAVE_HOTKEY
#include "menu.h"
-#endif
-enum {
+enum onplay_custom_action {
ONPLAY_NO_CUSTOMACTION,
ONPLAY_CUSTOMACTION_SHUFFLE_SONGS,
ONPLAY_CUSTOMACTION_FIRSTLETTER,
};
-int onplay(char* file, int attr, int from_context, bool hotkey, int customaction);
-int get_onplay_context(void);
-
-enum {
+enum onplay_return_code {
ONPLAY_MAINMENU = -1,
ONPLAY_OK = 0,
ONPLAY_RELOAD_DIR,
@@ -42,13 +37,9 @@ enum {
ONPLAY_START_PLAY,
ONPLAY_PLAYLIST,
ONPLAY_PLUGIN,
-#ifdef HAVE_HOTKEY
ONPLAY_FUNC_RETURN, /* for use in hotkey_assignment only */
-#endif
};
-#ifdef HAVE_HOTKEY
-
enum hotkey_action {
HOTKEY_OFF = 0,
HOTKEY_VIEW_PLAYLIST,
@@ -64,7 +55,9 @@ enum hotkey_action {
HOTKEY_INSERT_SHUFFLED,
HOTKEY_BOOKMARK_LIST,
HOTKEY_ALBUMART,
- HOTKEY_CONTEXT_MENU, /* shows / executes above actions in a menu */
+ HOTKEY_SHOW_IN_FILES,
+ HOTKEY_CONTEXT_MENU = 0x3E, /* Last item shows / executes above actions in a menu */
+ /* Note no more than 62 items */
};
enum hotkey_flags {
HOTKEY_FLAG_NONE = 0x0,
@@ -74,19 +67,37 @@ enum hotkey_flags {
};
struct hotkey_assignment {
- int action; /* hotkey_action */
int lang_id; /* Language ID */
struct menu_func_param func; /* Function to run if this entry is selected */
- int16_t return_code; /* What to return after the function is run. */
- uint16_t flags; /* Flags what context, display options */
-}; /* (Pick ONPLAY_FUNC_RETURN to use function's return value) */
+ int8_t return_code; /* What to return after the function is run. */
+ uint8_t flags; /* Flags what context, display options */
+ /* (Pick ONPLAY_FUNC_RETURN to use function's return value) */
+ uint8_t action; /* hotkey_action */
+ uint8_t icon; /* context menu icon */
+};
+
+/* hotkey & wps context menu */
+#define HK_CTX_ITEMS (5) /* 6 x 5 = 30 bits */
+#define HK_CTX_MASK (0x3F)
+#define HK_CTX_BITS (6) /* 6 bits, enough for 62 hotkey actions */
+#define HK_CTX_SET(item, hotkey) ((hotkey & HK_CTX_MASK) << (item * HK_CTX_BITS))
+#define HK_CTX_GET(item, hotkey) ((hotkey >> (item * HK_CTX_BITS)) & HK_CTX_MASK)
const struct hotkey_assignment *get_hotkey(int action);
-#endif
+int hotkey_run_menu(intptr_t flag, bool execute, int current_action);
+
+int onplay(char* file, int attr, int from_context, bool hotkey, int customaction);
+int get_onplay_context(void);
/* needed for the playlist viewer.. eventually clean this up */
void onplay_show_playlist_cat_menu(const char* track_name, int attr,
void (*add_to_pl_cb));
void onplay_show_playlist_menu(const char* path, int attr, void (*playlist_insert_cb));
+int wps_context_menu_do_setting(void *param);
+void wps_context_menu_set_default(void* setting, void* defaultval);
+char* wps_context_menu_write_to_cfg(void* setting, char*buf, int buf_len);
+void wps_context_menu_load_from_cfg(void* setting, char *value);
+bool wps_context_menu_is_changed(void* setting, void* defaultval);
+
#endif
diff --git a/apps/root_menu.c b/apps/root_menu.c
index 35cd63d5fb..f0553e24d4 100644
--- a/apps/root_menu.c
+++ b/apps/root_menu.c
@@ -1019,7 +1019,7 @@ void root_menu(void)
key = ID2P(LANG_START_SCREEN);
break;
case GO_TO_WPS:
- key = ID2P(LANG_OPEN_PLUGIN_SET_WPS_CONTEXT_PLUGIN);
+ key = ID2P(LANG_ONPLAY_MENU_TITLE);
break;
case GO_TO_SHORTCUTMENU:
key = ID2P(LANG_SHORTCUTS);
diff --git a/apps/settings.h b/apps/settings.h
index 618e91184a..0517c68ea9 100644
--- a/apps/settings.h
+++ b/apps/settings.h
@@ -844,10 +844,11 @@ struct user_settings
#ifdef HAVE_HOTKEY
/* hotkey assignments - acceptable values are in
hotkey_action enum in onplay.h */
- int hotkey_wps;
int hotkey_tree;
#endif
-
+ /* WPS context assignments - acceptable values are in
+ hotkey_action enum in onplay.h */
+ int context_wps;
/* When resuming playback (after a stop), rewind this number of seconds */
int resume_rewind;
diff --git a/apps/settings_list.c b/apps/settings_list.c
index 7601cf66ca..4e7999ca26 100644
--- a/apps/settings_list.c
+++ b/apps/settings_list.c
@@ -61,10 +61,10 @@
#include "touchscreen.h"
#include "ctype.h" /* For isspace() */
#endif
-#ifdef HAVE_HOTKEY
+
#include "onplay.h"
#include "misc.h" /* current activity */
-#endif
+
#include "playlist.h"
#include "tree.h"
#include "iap-usb.h"
@@ -690,6 +690,17 @@ struct eq_band_setting eq_defaults[EQ_NUM_BANDS] = {
{ 16000, 7, 0 },
};
+static const int wps_context_menu_default =
+ HK_CTX_SET(0, HOTKEY_VIEW_PLAYLIST) /* hotkey*/
+ | HK_CTX_SET(1, HOTKEY_SHOW_TRACK_INFO)
+ | HK_CTX_SET(2, HOTKEY_SHOW_IN_FILES)
+#ifdef HAVE_PITCHCONTROL
+ | HK_CTX_SET(3, HOTKEY_PITCHSCREEN)
+#else
+ | HK_CTX_SET(3, HOTKEY_DELETE)
+#endif
+ | HK_CTX_SET(4, HOTKEY_ALBUMART);
+
#ifndef __PCTOOL__
static void eq_load_from_cfg(void *setting, char *value)
{
@@ -885,14 +896,6 @@ static void tsc_set_default(void* setting, void* defaultval)
}
#endif
#ifdef HAVE_HOTKEY
-static void hotkey_callback(int var)
-{
- if (get_current_activity() != ACTIVITY_QUICKSCREEN)
- {
- if (get_hotkey(var)->action == HOTKEY_PLUGIN)
- open_plugin_browse(ID2P(LANG_HOTKEY_WPS));
- }
-}
static const char* hotkey_formatter(char* buffer, size_t buffer_size, int value,
const char* unit)
{
@@ -906,7 +909,7 @@ static int32_t hotkey_getlang(int value, int unit)
(void)unit;
return get_hotkey(value)->lang_id;
}
-#endif /* HAVE_HOTKEY */
+#endif
static void start_in_callback(int var)
{
@@ -2338,25 +2341,13 @@ const struct settings_list settings[] = {
#ifdef HAVE_MORSE_INPUT
OFFON_SETTING(0, morse_input, LANG_MORSE_INPUT, false, "morse input", NULL),
#endif
+ CUSTOM_SETTING(0, context_wps,
+ LANG_ONPLAY_MENU_TITLE, /* lang string here is never actually used */
+ &wps_context_menu_default, "context_wps",
+ wps_context_menu_load_from_cfg, wps_context_menu_write_to_cfg,
+ wps_context_menu_is_changed, wps_context_menu_set_default),
#ifdef HAVE_HOTKEY
-/* WPS HOTKEY */
- TABLE_SETTING(F_CB_ON_SELECT_ONLY, hotkey_wps,
- LANG_HOTKEY_WPS, HOTKEY_VIEW_PLAYLIST, "hotkey wps",
- "off,view playlist,show track info,pitchscreen,open with,delete,bookmark,plugin,bookmark list"
-#ifdef HAVE_ALBUMART
- ",show_album_art,context menu"
- ,UNIT_INT, hotkey_formatter, hotkey_getlang, hotkey_callback,11,
-#else
- ",context menu"
- ,UNIT_INT, hotkey_formatter, hotkey_getlang, hotkey_callback,10,
-#endif
- HOTKEY_OFF, HOTKEY_VIEW_PLAYLIST, HOTKEY_SHOW_TRACK_INFO, HOTKEY_PITCHSCREEN,
- HOTKEY_OPEN_WITH, HOTKEY_DELETE, HOTKEY_BOOKMARK, HOTKEY_PLUGIN, HOTKEY_BOOKMARK_LIST,
-#ifdef HAVE_ALBUMART
- HOTKEY_ALBUMART,
-#endif
- HOTKEY_CONTEXT_MENU),
/* TREE HOTKEY */
TABLE_SETTING(0, hotkey_tree,
LANG_HOTKEY_FILE_BROWSER, HOTKEY_OFF, "hotkey tree",
diff --git a/manual/configure_rockbox/wps.tex b/manual/configure_rockbox/wps.tex
index 4208806d08..c07325d31e 100644
--- a/manual/configure_rockbox/wps.tex
+++ b/manual/configure_rockbox/wps.tex
@@ -6,7 +6,15 @@
\item[WPS Hotkey.] Sets the hotkey function for
the WPS (see \reference{ref:Hotkeys}). The
default is \setting{View Playlist}.
+ \item[Set Context Item (1 - 4).]
}
- \item[Set WPS Context Plugin.]
- This option will allow you to run a Rockbox plugin from the WPS context menu.
- \end{description}
+ \nopt{hotkey}{\item[Set Context Item (0 - 4).]}
+
+ This option will allow you to set an entry in the WPS context menu.
+ \note{Setting an item to Off will hide the menu item;
+ Each item is only available once, duplicates will be set to Off;}
+
+ \item[Reset Settings.]
+ This option will allow you to return all items to default.
+ \opt{hotkey}{\note{including WPS Hotkey}}
+ \end{description}