diff --git a/apps/filetree.c b/apps/filetree.c index efe5e80a0f..75a32a9e42 100644 --- a/apps/filetree.c +++ b/apps/filetree.c @@ -435,7 +435,7 @@ static void ft_load_font(char *file) int ft_enter(struct tree_context* c) { int rc = GO_TO_PREVIOUS; - static char buf[MAX_PATH]; + char buf[MAX_PATH]; struct entry* file = tree_get_entry_at(c, c->selected_item); if (!file) @@ -641,6 +641,8 @@ int ft_enter(struct tree_context* c) splash(HZ, ID2P(LANG_PARTY_MODE)); break; } + +#ifdef PLUGINS_RUN_IN_BROWSER /* Stay in the filetree to run a plugin */ switch (plugin_load(plugin, argument)) { case PLUGIN_GOTO_WPS: @@ -664,6 +666,10 @@ int ft_enter(struct tree_context* c) default: break; } +#else /* Exit the filetree to run a plugin */ + plugin_open(plugin, argument); + rc = GO_TO_PLUGIN; +#endif break; } @@ -687,6 +693,7 @@ int ft_enter(struct tree_context* c) plugin = filetype_get_plugin(file, plugin_path, sizeof(plugin_path)); if (plugin) { +#ifdef PLUGINS_RUN_IN_BROWSER /* Stay in the filetree to run a plugin */ switch (plugin_load(plugin, argument)) { case PLUGIN_USB_CONNECTED: @@ -705,6 +712,10 @@ int ft_enter(struct tree_context* c) default: break; } +#else /* Exit the filetree to run a plugin */ + plugin_open(plugin, argument); + rc = GO_TO_PLUGIN; +#endif } break; } diff --git a/apps/gui/list.c b/apps/gui/list.c index 13a850bd7b..640a57fbd3 100644 --- a/apps/gui/list.c +++ b/apps/gui/list.c @@ -754,7 +754,7 @@ bool gui_synclist_do_button(struct gui_synclist * lists, if (lists->offset_position[0] == 0) { pgleft_allow_cancel = true; - *actionptr = ACTION_STD_CANCEL; + *actionptr = ACTION_STD_MENU; return true; } *actionptr = ACTION_TREE_PGLEFT; diff --git a/apps/keymaps/keymap-fiiom3k.c b/apps/keymaps/keymap-fiiom3k.c index 4cd2691d33..f4c7c6dd44 100644 --- a/apps/keymaps/keymap-fiiom3k.c +++ b/apps/keymaps/keymap-fiiom3k.c @@ -40,39 +40,41 @@ static const struct button_mapping button_context_standard[] = { {ACTION_STD_OK, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT}, {ACTION_STD_CANCEL, BUTTON_BACK|BUTTON_REL, BUTTON_BACK}, {ACTION_STD_CONTEXT, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_SELECT}, - {ACTION_STD_CONTEXT, BUTTON_MENU|BUTTON_REL, BUTTON_MENU}, - {ACTION_STD_MENU, BUTTON_BACK|BUTTON_REPEAT, BUTTON_BACK}, - {ACTION_STD_QUICKSCREEN, BUTTON_MENU|BUTTON_REPEAT, BUTTON_MENU}, + {ACTION_STD_QUICKSCREEN, BUTTON_MENU|BUTTON_REL, BUTTON_MENU}, + {ACTION_STD_MENU, BUTTON_MENU|BUTTON_REPEAT, BUTTON_MENU}, {ACTION_STD_KEYLOCK, BUTTON_POWER|BUTTON_REL, BUTTON_POWER}, - {ACTION_STD_HOTKEY, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY}, LAST_ITEM_IN_LIST }; /* button_context_standard */ static const struct button_mapping button_context_wps[] = { {ACTION_WPS_PLAY, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY}, - {ACTION_WPS_PLAY, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT}, + {ACTION_WPS_VIEW_PLAYLIST, BUTTON_SELECT|BUTTON_REL, BUTTON_SELECT}, {ACTION_WPS_STOP, BUTTON_POWER|BUTTON_REPEAT, BUTTON_POWER}, {ACTION_WPS_VOLUP, BUTTON_VOL_UP, BUTTON_NONE}, {ACTION_WPS_VOLUP, BUTTON_VOL_UP|BUTTON_REPEAT, BUTTON_NONE}, {ACTION_WPS_VOLDOWN, BUTTON_VOL_DOWN, BUTTON_NONE}, {ACTION_WPS_VOLDOWN, BUTTON_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE}, + {ACTION_WPS_VOLUP, BUTTON_SCROLL_BACK, BUTTON_NONE}, + {ACTION_WPS_VOLUP, BUTTON_SCROLL_BACK|BUTTON_REPEAT, BUTTON_NONE}, + {ACTION_WPS_VOLDOWN, BUTTON_SCROLL_FWD, BUTTON_NONE}, + {ACTION_WPS_VOLDOWN, BUTTON_SCROLL_FWD|BUTTON_REPEAT, BUTTON_NONE}, + {ACTION_WPS_VOLUP, BUTTON_UP|BUTTON_REL, BUTTON_UP}, + {ACTION_WPS_VOLDOWN, BUTTON_DOWN|BUTTON_REL, BUTTON_DOWN}, {ACTION_WPS_SKIPNEXT, BUTTON_RIGHT|BUTTON_REL, BUTTON_RIGHT}, {ACTION_WPS_SKIPPREV, BUTTON_LEFT|BUTTON_REL, BUTTON_LEFT}, {ACTION_WPS_SEEKFWD, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE}, {ACTION_WPS_STOPSEEK, BUTTON_RIGHT|BUTTON_REL, BUTTON_RIGHT|BUTTON_REPEAT}, {ACTION_WPS_SEEKBACK, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE}, {ACTION_WPS_STOPSEEK, BUTTON_LEFT|BUTTON_REL, BUTTON_LEFT|BUTTON_REPEAT}, - {ACTION_WPS_BROWSE, BUTTON_BACK|BUTTON_REPEAT, BUTTON_BACK}, - {ACTION_WPS_MENU, BUTTON_BACK|BUTTON_REL, BUTTON_BACK}, - {ACTION_WPS_CONTEXT, BUTTON_MENU|BUTTON_REL, BUTTON_MENU}, - {ACTION_WPS_QUICKSCREEN, BUTTON_MENU|BUTTON_REPEAT, BUTTON_MENU}, + {ACTION_WPS_BROWSE, BUTTON_BACK|BUTTON_REL, BUTTON_BACK}, + {ACTION_WPS_QUICKSCREEN, BUTTON_MENU|BUTTON_REL, BUTTON_MENU}, + {ACTION_WPS_MENU, BUTTON_MENU|BUTTON_REPEAT, BUTTON_MENU}, {ACTION_STD_KEYLOCK, BUTTON_POWER|BUTTON_REL, BUTTON_POWER}, {ACTION_WPS_HOTKEY, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_PLAY}, - {ACTION_WPS_VIEW_PLAYLIST, BUTTON_SCROLL_FWD, BUTTON_NONE}, - {ACTION_WPS_VIEW_PLAYLIST, BUTTON_SCROLL_BACK, BUTTON_NONE}, + {ACTION_WPS_CONTEXT, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_SELECT}, {ACTION_WPS_ABSETA_PREVDIR, BUTTON_UP|BUTTON_REPEAT, BUTTON_UP}, {ACTION_WPS_ABSETB_NEXTDIR, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_DOWN}, - {ACTION_WPS_ABRESET, BUTTON_SELECT|BUTTON_REPEAT, BUTTON_SELECT}, + {ACTION_WPS_ABRESET, BUTTON_BACK|BUTTON_REPEAT, BUTTON_BACK}, LAST_ITEM_IN_LIST }; /* button_context_wps */ @@ -87,11 +89,20 @@ static const struct button_mapping button_context_wps_locked[] = { }; /* button_context_wps_locked */ static const struct button_mapping button_context_tree[] = { - {ACTION_TREE_STOP, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_PLAY}, - {ACTION_TREE_WPS, BUTTON_BACK|BUTTON_REPEAT, BUTTON_BACK}, + {ACTION_TREE_WPS, BUTTON_PLAY|BUTTON_REL, BUTTON_PLAY }, + {ACTION_TREE_HOTKEY, BUTTON_PLAY|BUTTON_REPEAT, BUTTON_PLAY}, + {ACTION_TREE_STOP, BUTTON_POWER|BUTTON_REPEAT, BUTTON_POWER}, LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_LIST) }; /* button_context_tree */ + +static const struct button_mapping button_context_tree_scroll_lr[] = { + { ACTION_TREE_ROOT_INIT, BUTTON_MENU|BUTTON_REPEAT, BUTTON_MENU }, + { ACTION_TREE_PGLEFT, BUTTON_MENU|BUTTON_REPEAT, BUTTON_NONE }, + { ACTION_TREE_PGRIGHT, BUTTON_BACK|BUTTON_REPEAT, BUTTON_NONE }, + LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_CUSTOM|CONTEXT_TREE), +}; /* button_context_tree_scroll_lr */ + static const struct button_mapping button_context_bmark[] = { {ACTION_BMS_DELETE, BUTTON_PLAY, BUTTON_NONE}, LAST_ITEM_IN_LIST__NEXTLIST(CONTEXT_TREE), @@ -140,14 +151,25 @@ static const struct button_mapping button_context_settings_eq[] = { static const struct button_mapping button_context_quickscreen[] = { {ACTION_QS_TOP, BUTTON_UP, BUTTON_NONE}, + {ACTION_QS_TOP, BUTTON_UP|BUTTON_REPEAT, BUTTON_NONE}, + {ACTION_QS_TOP, BUTTON_SCROLL_BACK, BUTTON_NONE}, + {ACTION_QS_TOP, BUTTON_SCROLL_BACK|BUTTON_REPEAT, BUTTON_NONE}, {ACTION_QS_DOWN, BUTTON_DOWN, BUTTON_NONE}, + {ACTION_QS_DOWN, BUTTON_DOWN|BUTTON_REPEAT, BUTTON_NONE}, + {ACTION_QS_DOWN, BUTTON_SCROLL_FWD, BUTTON_NONE}, + {ACTION_QS_DOWN, BUTTON_SCROLL_FWD|BUTTON_REPEAT, BUTTON_NONE}, {ACTION_QS_LEFT, BUTTON_LEFT, BUTTON_NONE}, + {ACTION_QS_LEFT, BUTTON_LEFT|BUTTON_REPEAT, BUTTON_NONE}, {ACTION_QS_RIGHT, BUTTON_RIGHT, BUTTON_NONE}, + {ACTION_QS_RIGHT, BUTTON_RIGHT|BUTTON_REPEAT, BUTTON_NONE}, {ACTION_QS_VOLUP, BUTTON_VOL_UP, BUTTON_NONE}, + {ACTION_QS_VOLUP, BUTTON_VOL_UP|BUTTON_REPEAT, BUTTON_NONE}, {ACTION_QS_VOLDOWN, BUTTON_VOL_DOWN, BUTTON_NONE}, + {ACTION_QS_VOLDOWN, BUTTON_VOL_DOWN|BUTTON_REPEAT, BUTTON_NONE}, {ACTION_STD_CANCEL, BUTTON_SELECT, BUTTON_NONE}, {ACTION_STD_CANCEL, BUTTON_POWER, BUTTON_NONE}, {ACTION_STD_CANCEL, BUTTON_BACK, BUTTON_NONE}, + {ACTION_STD_CANCEL, BUTTON_MENU, BUTTON_NONE}, LAST_ITEM_IN_LIST }; /* button_context_quickscreen */ @@ -279,6 +301,10 @@ const struct button_mapping* get_context_mapping(int context) return button_context_wps; case CONTEXT_TREE: case CONTEXT_MAINMENU: + if (global_settings.hold_lr_for_scroll_in_list) + return button_context_tree_scroll_lr; + /* else fall through to CUSTOM|CONTEXT_TREE */ + case CONTEXT_CUSTOM|CONTEXT_TREE: return button_context_tree; case CONTEXT_BOOKMARKSCREEN: return button_context_bmark; diff --git a/apps/menus/plugin_menu.c b/apps/menus/plugin_menu.c index 7f29e61af4..7edfc7acc6 100644 --- a/apps/menus/plugin_menu.c +++ b/apps/menus/plugin_menu.c @@ -29,7 +29,6 @@ #include "rbpaths.h" #include "root_menu.h" #include "tree.h" -static int reenter = 0; enum { GAMES, @@ -46,6 +45,12 @@ static const struct { { PLUGIN_DEMOS_DIR, LANG_PLUGIN_DEMOS }, }; +/* if handler is active we are waiting to reenter menu */ +static void pm_handler(unsigned short id, void *data) +{ + remove_event(id, data); +} + static int plugins_menu(void* param) { intptr_t item = (intptr_t)param; @@ -60,7 +65,8 @@ static int plugins_menu(void* param) if (ret == GO_TO_PREVIOUS) return 0; if (ret == GO_TO_PLUGIN) - reenter = 1; + add_event(SYS_EVENT_USB_INSERTED, pm_handler); + return ret; } @@ -74,8 +80,11 @@ static int menu_callback(int action, if (action == ACTION_ENTER_MENUITEM) { this_list->selected_item = selected; - if (reenter-- > 0) - action = ACTION_STD_OK; + if (!add_event(SYS_EVENT_USB_INSERTED, pm_handler)) + { + action = ACTION_STD_OK; /* event exists -- reenter menu */ + } + remove_event(SYS_EVENT_USB_INSERTED, pm_handler); } else if (action == ACTION_STD_OK) { diff --git a/apps/onplay.c b/apps/onplay.c index 83b24da78d..f8233da92c 100644 --- a/apps/onplay.c +++ b/apps/onplay.c @@ -778,6 +778,7 @@ static int treeplaylist_callback(int action, void onplay_show_playlist_menu(char* path) { + context = CONTEXT_STD; selected_file = path; if (dir_exists(path)) selected_file_attr = ATTR_DIRECTORY; @@ -825,6 +826,7 @@ MAKE_ONPLAYMENU(cat_playlist_menu, ID2P(LANG_CATALOG), void onplay_show_playlist_cat_menu(char* track_name) { + context = CONTEXT_STD; selected_file = track_name; selected_file_attr = FILE_ATTR_AUDIO; do_menu(&cat_playlist_menu, NULL, NULL, false); diff --git a/apps/root_menu.c b/apps/root_menu.c index ed6bdfdcca..f731531e16 100644 --- a/apps/root_menu.c +++ b/apps/root_menu.c @@ -709,47 +709,41 @@ static int load_context_screen(int selection) static int load_plugin_screen(char *key) { - int ret_val; + int ret_val = PLUGIN_ERROR; + int loops = 100; int old_previous = last_screen; int old_global = global_status.last_screen; last_screen = next_screen; global_status.last_screen = (char)next_screen; status_save(); - int opret = open_plugin_get_entry(key, &open_plugin_entry); - char *path = open_plugin_entry.path; - char *param = open_plugin_entry.param; - if (param[0] == '\0') - param = NULL; - - switch (plugin_load(path, param)) + while(loops-- > 0) /* just to keep things from getting out of hand */ { - case PLUGIN_USB_CONNECTED: - ret_val = GO_TO_ROOT; - break; - case PLUGIN_GOTO_WPS: - ret_val = GO_TO_WPS; - break; - case PLUGIN_GOTO_PLUGIN: - ret_val = GO_TO_PLUGIN; - break; - case PLUGIN_OK: - /* Prevents infinite loop with WPS & Plugins*/ - if (old_global == GO_TO_WPS && !audio_status()) - { + int opret = open_plugin_get_entry(key, &open_plugin_entry); + char *path = open_plugin_entry.path; + char *param = open_plugin_entry.param; + if (param[0] == '\0') + param = NULL; + + int ret = plugin_load(path, param); + + if (ret == PLUGIN_USB_CONNECTED) ret_val = GO_TO_ROOT; - break; + else if (ret == PLUGIN_GOTO_WPS) + ret_val = GO_TO_WPS; + else if (ret == PLUGIN_GOTO_PLUGIN) + continue; + else + { + /* Prevents infinite loop with WPS & Plugins*/ + if (ret == PLUGIN_OK && old_global == GO_TO_WPS && !audio_status()) + ret_val = GO_TO_ROOT; + ret_val = GO_TO_PREVIOUS; + last_screen = (old_previous == next_screen) ? GO_TO_ROOT : old_previous; } - /*fallthrough*/ - default: - ret_val = GO_TO_PREVIOUS; - last_screen = (old_previous == next_screen) ? GO_TO_ROOT : old_previous; - break; - } + /* ret_val != GO_TO_PLUGIN */ - if (ret_val != GO_TO_PLUGIN) - { if (opret != OPEN_PLUGIN_NEEDS_FLUSHED || last_screen != GO_TO_WPS) { /* Keep the entry in case of GO_TO_PREVIOUS */ @@ -757,7 +751,8 @@ static int load_plugin_screen(char *key) open_plugin_entry.lang_id = LANG_PREVIOUS_SCREEN; /*open_plugin_add_path(NULL, NULL, NULL);// clear entry */ } - } + break; + } /*while */ return ret_val; } diff --git a/apps/tree.c b/apps/tree.c index e35f769a14..63363422ba 100644 --- a/apps/tree.c +++ b/apps/tree.c @@ -1196,6 +1196,7 @@ static int ft_play_filename(char *dir, char *file, int attr) /* These two functions are called by the USB and shutdown handlers */ void tree_flush(void) { + tc.browse = NULL; /* clear browse to prevent reentry to a possibly missing file */ #ifdef HAVE_TAGCACHE tagcache_shutdown(); #endif diff --git a/firmware/export/events.h b/firmware/export/events.h index 4591058d4f..8bdf1b55e2 100644 --- a/firmware/export/events.h +++ b/firmware/export/events.h @@ -52,7 +52,7 @@ #define EVENT_CLASS_RECORDING 0x1000 #define EVENT_CLASS_LCD 0x2000 #define EVENT_CLASS_VOICE 0x4000 - +#define EVENT_CLASS_SYSTEM 0x8000 /*LAST ONE */ /** * Subscribe to an event with a simple callback. The callback will be called * synchronously everytime the event fires, passing the event id and data to @@ -99,4 +99,14 @@ void remove_event_ex(unsigned short id, void (*handler)(unsigned short id, void */ void send_event(unsigned short id, void *data); +/** System events **/ +enum { + /* USB_INSERTED + data = &usbmode */ + SYS_EVENT_USB_INSERTED = (EVENT_CLASS_SYSTEM|1), + /* USB_EXTRACTED + data = NULL */ + SYS_EVENT_USB_EXTRACTED, +}; + #endif diff --git a/firmware/target/hosted/xduoo/button-xduoo.c b/firmware/target/hosted/xduoo/button-xduoo.c index 568ad2614d..c06b60bd9f 100644 --- a/firmware/target/hosted/xduoo/button-xduoo.c +++ b/firmware/target/hosted/xduoo/button-xduoo.c @@ -58,13 +58,13 @@ int button_map(int keycode) #if defined(XDUOO_X3II) && defined(USE_REMOTE) /* Headphone remote */ case KEY_NEXTSONG: - return (BUTTON_NEXT | BUTTON_DELAY_RELEASE); + return headphones_inserted()? (BUTTON_NEXT | BUTTON_DELAY_RELEASE) : 0; case KEY_PLAYPAUSE: - return (BUTTON_PLAY | BUTTON_DELAY_RELEASE); + return headphones_inserted()? (BUTTON_PLAY | BUTTON_DELAY_RELEASE) : 0; case KEY_PREVIOUSSONG: - return (BUTTON_PREV | BUTTON_DELAY_RELEASE); + return headphones_inserted()? (BUTTON_PREV | BUTTON_DELAY_RELEASE) : 0; #endif default: diff --git a/firmware/usb.c b/firmware/usb.c index b919fe468d..4c122e8eea 100644 --- a/firmware/usb.c +++ b/firmware/usb.c @@ -476,7 +476,12 @@ static void NORETURN_ATTR usb_thread(void) usb_state = USB_POWERED; usb_stack_enable(true); - +#ifndef BOOTLOADER +#ifndef HAVE_USB_POWER + int usb_mode = -1; +#endif + send_event(SYS_EVENT_USB_INSERTED, &usb_mode); +#endif /* Power (charging-only) button */ #ifdef HAVE_USB_POWER new_usbmode = usb_mode; @@ -547,7 +552,9 @@ static void NORETURN_ATTR usb_thread(void) #ifdef HAVE_USB_POWER new_usbmode = usb_mode; #endif - +#ifndef BOOTLOADER + send_event(SYS_EVENT_USB_EXTRACTED, NULL); +#endif usb_set_host_present(false); break; /* USB_EXTRACTED: */ diff --git a/uisimulator/common/sim_tasks.c b/uisimulator/common/sim_tasks.c index c862d4d909..8c1f193080 100644 --- a/uisimulator/common/sim_tasks.c +++ b/uisimulator/common/sim_tasks.c @@ -145,10 +145,17 @@ void sim_trigger_screendump(void) static bool is_usb_inserted; void sim_trigger_usb(bool inserted) { + int usbmode = -1; if (inserted) + { + send_event(SYS_EVENT_USB_INSERTED, &usbmode); queue_post(&sim_queue, SIM_USB_INSERTED, 0); + } else + { + send_event(SYS_EVENT_USB_EXTRACTED, NULL); queue_post(&sim_queue, SIM_USB_EXTRACTED, 0); + } is_usb_inserted = inserted; }