diff --git a/applications/applications.c b/applications/applications.c index a33c540d9..22a4ea4a8 100755 --- a/applications/applications.c +++ b/applications/applications.c @@ -9,7 +9,6 @@ extern int32_t dolphin_srv(void* p); extern int32_t gui_srv(void* p); extern int32_t input_srv(void* p); extern int32_t loader_srv(void* p); -extern int32_t menu_srv(void* p); extern int32_t notification_srv(void* p); extern int32_t power_observer_srv(void* p); extern int32_t power_srv(void* p); @@ -87,8 +86,7 @@ const FlipperApplication FLIPPER_SERVICES[] = { {.app = input_srv, .name = "Input", .stack_size = 1024, .icon = NULL}, #endif -#ifdef SRV_MENU - {.app = menu_srv, .name = "Menu", .stack_size = 1024, .icon = NULL}, +#ifdef SRV_LOADER {.app = loader_srv, .name = "Loader", .stack_size = 1024, .icon = NULL}, #endif @@ -107,43 +105,6 @@ const FlipperApplication FLIPPER_SERVICES[] = { #ifdef SRV_STORAGE {.app = storage_srv, .name = "Storage", .stack_size = 4096, .icon = NULL}, #endif - -/* Fake services (autorun) */ -#ifdef SRV_BLINK - {.app = blink_test_app, .name = "Blink", .stack_size = 1024, .icon = &A_Plugins_14}, -#endif - -#ifdef SRV_LF_RFID - {.app = lfrfid_app, .name = "125 kHz RFID", .stack_size = 2048, .icon = &A_Plugins_14}, -#endif - -#ifdef SRV_IRDA - {.app = irda_app, .name = "Infrared", .stack_size = 1024 * 3, .icon = &A_Plugins_14}, -#endif - -#ifdef SRV_MUSIC_PLAYER - {.app = music_player_app, .name = "Music Player", .stack_size = 1024, .icon = &A_Plugins_14}, -#endif - -#ifdef SRV_IBUTTON - {.app = ibutton_app, .name = "iButton", .stack_size = 2048, .icon = &A_Plugins_14}, -#endif - -#ifdef SRV_GPIO_TEST - {.app = gpio_test_app, .name = "GPIO Test", .stack_size = 1024, .icon = &A_Plugins_14}, -#endif - -#ifdef SRV_KEYPAD_TEST - {.app = keypad_test_app, .name = "Keypad Test", .stack_size = 1024, .icon = &A_Plugins_14}, -#endif - -#ifdef SRV_ACCESSOR - {.app = accessor_app, .name = "Accessor", .stack_size = 4096, .icon = &A_Plugins_14}, -#endif - -#ifdef SRV_STORAGE_TEST - {.app = storage_test_app, .name = "Storage Test", .stack_size = 1024, .icon = &A_Plugins_14}, -#endif }; const size_t FLIPPER_SERVICES_COUNT = sizeof(FLIPPER_SERVICES) / sizeof(FlipperApplication); @@ -184,25 +145,35 @@ const FlipperOnStartHook FLIPPER_ON_SYSTEM_START[] = { #ifdef SRV_CLI crypto_cli_init, #endif + +#ifdef APP_IRDA irda_cli_init, +#endif + #ifdef APP_NFC nfc_cli_init, #endif + #ifdef APP_SUBGHZ subghz_cli_init, #endif + #ifdef APP_LF_RFID lfrfid_cli_init, #endif + #ifdef APP_IBUTTON ibutton_cli_init, #endif + #ifdef SRV_BT bt_cli_init, #endif + #ifdef SRV_POWER power_cli_init, #endif + #ifdef SRV_STORAGE storage_cli_init, #endif diff --git a/applications/applications.mk b/applications/applications.mk index 3b92a7232..77d35e213 100644 --- a/applications/applications.mk +++ b/applications/applications.mk @@ -1,278 +1,248 @@ APP_DIR = $(PROJECT_ROOT)/applications -LIB_DIR = $(PROJECT_ROOT)/lib +LIB_DIR = $(PROJECT_ROOT)/lib CFLAGS += -I$(APP_DIR) -C_SOURCES += $(shell find $(APP_DIR) -name *.c) -CPP_SOURCES += $(shell find $(APP_DIR) -name *.cpp) +C_SOURCES += $(shell find $(APP_DIR) -name *.c) +CPP_SOURCES += $(shell find $(APP_DIR) -name *.cpp) -# Use SRV_* for autostart app -# Use APP_* for add app to build - APP_RELEASE ?= 1 ifeq ($(APP_RELEASE), 1) # Services -SRV_BT = 1 -SRV_CLI = 1 -SRV_DIALOGS = 1 -SRV_DOLPHIN = 1 -SRV_GUI = 1 -SRV_INPUT = 1 -SRV_MENU = 1 +SRV_BT = 1 +SRV_CLI = 1 +SRV_DIALOGS = 1 +SRV_DOLPHIN = 1 +SRV_GUI = 1 +SRV_INPUT = 1 +SRV_LOADER = 1 SRV_NOTIFICATION = 1 -SRV_POWER = 1 +SRV_POWER = 1 SRV_POWER_OBSERVER = 1 -SRV_STORAGE = 1 +SRV_STORAGE = 1 # Apps -SRV_DESKTOP = 1 -APP_ARCHIVE = 1 +SRV_DESKTOP = 1 +APP_ARCHIVE = 1 APP_GPIO_TEST = 1 -APP_IBUTTON = 1 -APP_IRDA = 1 -APP_LF_RFID = 1 -APP_NFC = 1 -APP_SUBGHZ = 1 -APP_ABOUT = 1 +APP_IBUTTON = 1 +APP_IRDA = 1 +APP_LF_RFID = 1 +APP_NFC = 1 +APP_SUBGHZ = 1 +APP_ABOUT = 1 # Plugins APP_MUSIC_PLAYER = 1 # Debug APP_ACCESSOR = 1 -APP_BLINK = 1 +APP_BLINK = 1 APP_IRDA_MONITOR = 1 APP_KEYPAD_TEST = 1 -APP_SD_TEST = 1 +APP_SD_TEST = 1 APP_UNIT_TESTS = 0 APP_VIBRO_DEMO = 1 endif -SRV_BT ?= 0 -ifeq ($(SRV_BT), 1) -SRV_CLI = 1 -CFLAGS += -DSRV_BT -endif +# Applications +# that will be shown in menu +# Prefix with APP_* -SRV_DOLPHIN ?= 0 -ifeq ($(SRV_DOLPHIN), 1) -SRV_MENU = 1 -CFLAGS += -DSRV_DOLPHIN -endif - -SRV_POWER ?= 0 -ifeq ($(SRV_POWER), 1) -SRV_GUI = 1 -SRV_CLI = 1 -CFLAGS += -DSRV_POWER -endif - -SRV_POWER_OBSERVER ?= 0 -ifeq ($(SRV_POWER_OBSERVER), 1) -SRV_POWER = 1 -CFLAGS += -DSRV_POWER_OBSERVER -endif - -SRV_MENU ?= 0 -ifeq ($(SRV_MENU), 1) -CFLAGS += -DSRV_MENU -APP_MENU = 1 -endif -APP_MENU ?= 0 -ifeq ($(APP_MENU), 1) -SRV_INPUT = 1 -SRV_GUI = 1 -CFLAGS += -DAPP_MENU -endif APP_IRDA_MONITOR ?= 0 ifeq ($(APP_IRDA_MONITOR), 1) CFLAGS += -DAPP_IRDA_MONITOR +SRV_GUI = 1 endif + APP_UNIT_TESTS ?= 0 ifeq ($(APP_UNIT_TESTS), 1) CFLAGS += -DAPP_UNIT_TESTS endif -SRV_DESKTOP ?= 0 -ifeq ($(SRV_DESKTOP), 1) -CFLAGS += -DSRV_DESKTOP -SRV_DESKTOP = 1 -endif APP_ARCHIVE ?= 0 -ifeq ($(APP_NFC), 1) +ifeq ($(APP_ARCHIVE), 1) CFLAGS += -DAPP_ARCHIVE -APP_ARCHIVE = 1 +SRV_GUI = 1 endif -SRV_BLINK ?= 0 -ifeq ($(SRV_BLINK), 1) -CFLAGS += -DSRV_BLINK -APP_BLINK = 1 -endif + APP_BLINK ?= 0 ifeq ($(APP_BLINK), 1) CFLAGS += -DAPP_BLINK -SRV_INPUT = 1 +SRV_GUI = 1 endif -SRV_UART_WRITE ?= 0 -ifeq ($(SRV_UART_WRITE), 1) -CFLAGS += -DSRV_UART_WRITE -APP_UART_WRITE = 1 -endif -APP_UART_WRITE ?= 0 -ifeq ($(APP_UART_WRITE), 1) -CFLAGS += -DAPP_UART_WRITE -endif - -SRV_IPC ?= 0 -ifeq ($(SRV_IPC), 1) -CFLAGS += -DSRV_IPC -APP_IPC = 1 -endif -APP_IPC ?= 0 -ifeq ($(APP_IPC), 1) -CFLAGS += -DAPP_IPC -endif +APP_SUBGHZ ?= 0 ifeq ($(APP_SUBGHZ), 1) CFLAGS += -DAPP_SUBGHZ -SRV_INPUT = 1 -SRV_GUI = 1 -SRV_CLI = 1 +SRV_GUI = 1 +SRV_CLI = 1 endif + +APP_ABOUT ?= 0 ifeq ($(APP_ABOUT), 1) CFLAGS += -DAPP_ABOUT -SRV_INPUT = 1 -SRV_GUI = 1 +SRV_GUI = 1 endif -SRV_LF_RFID ?= 0 -ifeq ($(SRV_LF_RFID), 1) -CFLAGS += -DSRV_LF_RFID -APP_LF_RFID = 1 -endif + APP_LF_RFID ?= 0 ifeq ($(APP_LF_RFID), 1) CFLAGS += -DAPP_LF_RFID -SRV_INPUT = 1 -SRV_GUI = 1 +SRV_GUI = 1 endif + APP_NFC ?= 0 ifeq ($(APP_NFC), 1) CFLAGS += -DAPP_NFC -SRV_MENU = 1 -SRV_INPUT = 1 -SRV_GUI = 1 +SRV_GUI = 1 endif -SRV_IRDA ?= 0 -ifeq ($(SRV_IRDA), 1) -CFLAGS += -DSRV_IRDA -APP_IRDA = 1 -endif + APP_IRDA ?= 0 ifeq ($(APP_IRDA), 1) CFLAGS += -DAPP_IRDA -SRV_INPUT = 1 -SRV_GUI = 1 +SRV_GUI = 1 endif + APP_VIBRO_DEMO ?= 0 ifeq ($(APP_VIBRO_DEMO), 1) CFLAGS += -DAPP_VIBRO_DEMO -SRV_INPUT = 1 +SRV_GUI = 1 endif -SRV_KEYPAD_TEST ?= 0 -ifeq ($(SRV_KEYPAD_TEST), 1) -CFLAGS += -DSRV_KEYPAD_TEST -APP_KEYPAD_TEST = 1 -endif + APP_KEYPAD_TEST ?= 0 ifeq ($(APP_KEYPAD_TEST), 1) CFLAGS += -DAPP_KEYPAD_TEST -APP_KEYPAD_TEST = 1 +SRV_GUI = 1 endif -SRV_ACCESSOR ?= 0 -ifeq ($(SRV_ACCESSOR), 1) -CFLAGS += -DSRV_ACCESSOR -APP_ACCESSOR = 1 -endif + APP_ACCESSOR ?= 0 ifeq ($(APP_ACCESSOR), 1) CFLAGS += -DAPP_ACCESSOR -APP_ACCESSOR = 1 +SRV_GUI = 1 endif -SRV_GPIO_TEST ?= 0 -ifeq ($(SRV_GPIO_TEST), 1) -CFLAGS += -DSRV_GPIO_TEST -APP_GPIO_TEST = 1 -endif + APP_GPIO_TEST ?= 0 ifeq ($(APP_GPIO_TEST), 1) CFLAGS += -DAPP_GPIO_TEST +SRV_GUI = 1 endif -SRV_MUSIC_PLAYER ?= 0 -ifeq ($(SRV_MUSIC_PLAYER), 1) -CFLAGS += -DSRV_MUSIC_PLAYER -APP_MUSIC_PLAYER = 1 -endif + APP_MUSIC_PLAYER ?= 0 ifeq ($(APP_MUSIC_PLAYER), 1) CFLAGS += -DAPP_MUSIC_PLAYER +SRV_GUI = 1 endif -SRV_IBUTTON ?= 0 -ifeq ($(SRV_IBUTTON), 1) -CFLAGS += -DSRV_IBUTTON -APP_IBUTTON = 1 -endif + APP_IBUTTON ?= 0 ifeq ($(APP_IBUTTON), 1) CFLAGS += -DAPP_IBUTTON +SRV_GUI = 1 +endif + + +# Services +# that will start with OS +# Prefix with SRV_* + + +SRV_BT ?= 0 +ifeq ($(SRV_BT), 1) +CFLAGS += -DSRV_BT +SRV_CLI = 1 +endif + + +SRV_DESKTOP ?= 0 +ifeq ($(SRV_DESKTOP), 1) +CFLAGS += -DSRV_DESKTOP +SRV_LOADER = 1 +SRV_GUI = 1 +endif + + +SRV_DOLPHIN ?= 0 +ifeq ($(SRV_DOLPHIN), 1) +CFLAGS += -DSRV_DOLPHIN +endif + + +SRV_POWER_OBSERVER ?= 0 +ifeq ($(SRV_POWER_OBSERVER), 1) +CFLAGS += -DSRV_POWER_OBSERVER +SRV_POWER = 1 +endif + + +SRV_POWER ?= 0 +ifeq ($(SRV_POWER), 1) +CFLAGS += -DSRV_POWER +SRV_GUI = 1 +SRV_CLI = 1 +endif + + +SRV_LOADER ?= 0 +ifeq ($(SRV_LOADER), 1) +CFLAGS += -DSRV_LOADER +SRV_GUI = 1 +# Loader autostart hook +LOADER_AUTOSTART ?= "" +ifneq ($(strip $(LOADER_AUTOSTART)),) +CFLAGS += -DLOADER_AUTOSTART="\"$(LOADER_AUTOSTART)\"" +endif +# Loader autostart hook END +endif + + +SRV_DIALOGS ?= 0 +ifeq ($(SRV_DIALOGS), 1) +CFLAGS += -DSRV_DIALOGS +SRV_GUI = 1 endif -# -# Essential services -# SRV_GUI ?= 0 ifeq ($(SRV_GUI), 1) CFLAGS += -DSRV_GUI +SRV_INPUT = 1 endif + SRV_INPUT ?= 0 ifeq ($(SRV_INPUT), 1) CFLAGS += -DSRV_INPUT endif + SRV_CLI ?= 0 ifeq ($(SRV_CLI), 1) -SRV_GUI = 1 CFLAGS += -DSRV_CLI endif + SRV_NOTIFICATION ?= 0 ifeq ($(SRV_NOTIFICATION), 1) CFLAGS += -DSRV_NOTIFICATION endif + SRV_STORAGE ?= 0 ifeq ($(SRV_STORAGE), 1) CFLAGS += -DSRV_STORAGE endif - -SRV_DIALOGS ?= 0 -ifeq ($(SRV_DIALOGS), 1) -CFLAGS += -DSRV_DIALOGS -endif diff --git a/applications/desktop/desktop.c b/applications/desktop/desktop.c index a658bcaa4..aa1755e90 100644 --- a/applications/desktop/desktop.c +++ b/applications/desktop/desktop.c @@ -21,7 +21,6 @@ bool desktop_back_event_callback(void* context) { Desktop* desktop_alloc() { Desktop* desktop = furi_alloc(sizeof(Desktop)); - desktop->menu_vm = furi_record_open("menu"); desktop->gui = furi_record_open("gui"); desktop->scene_thread = furi_thread_alloc(); desktop->view_dispatcher = view_dispatcher_alloc(); @@ -101,7 +100,6 @@ void desktop_free(Desktop* desktop) { furi_thread_free(desktop->scene_thread); furi_record_close("menu"); - desktop->menu_vm = NULL; free(desktop); } diff --git a/applications/desktop/desktop_i.h b/applications/desktop/desktop_i.h index 05ba47933..d3a9d457c 100644 --- a/applications/desktop/desktop_i.h +++ b/applications/desktop/desktop_i.h @@ -2,7 +2,6 @@ #include #include -#include #include #include #include @@ -34,8 +33,6 @@ typedef enum { } DesktopViewEnum; struct Desktop { - // Menu - ValueMutex* menu_vm; // Scene FuriThread* scene_thread; // GUI diff --git a/applications/desktop/scenes/desktop_scene_main.c b/applications/desktop/scenes/desktop_scene_main.c index a9d7411fa..c71a0d81a 100644 --- a/applications/desktop/scenes/desktop_scene_main.c +++ b/applications/desktop/scenes/desktop_scene_main.c @@ -1,6 +1,7 @@ #include "../desktop_i.h" #include "../views/desktop_main.h" #include "applications.h" +#include #define MAIN_VIEW_DEFAULT (0UL) static void desktop_switch_to_app(Desktop* desktop, const FlipperApplication* flipper_app) { @@ -48,8 +49,7 @@ const bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { switch(event.event) { case DesktopMainEventOpenMenu: - with_value_mutex( - desktop->menu_vm, (Menu * menu) { menu_ok(menu); }); + loader_show_menu(); consumed = true; break; diff --git a/applications/gui/modules/menu.c b/applications/gui/modules/menu.c new file mode 100755 index 000000000..e09437d95 --- /dev/null +++ b/applications/gui/modules/menu.c @@ -0,0 +1,199 @@ +#include "menu.h" + +#include +#include +#include + +struct Menu { + View* view; +}; + +typedef struct { + const char* label; + IconAnimation* icon; + uint32_t index; + MenuItemCallback callback; + void* callback_context; +} MenuItem; + +ARRAY_DEF(MenuItemArray, MenuItem, M_POD_OPLIST); + +typedef struct { + MenuItemArray_t items; + uint8_t position; +} MenuModel; + +static void menu_process_up(Menu* menu); +static void menu_process_down(Menu* menu); +static void menu_process_ok(Menu* menu); + +static void menu_draw_callback(Canvas* canvas, void* _model) { + MenuModel* model = _model; + + canvas_clear(canvas); + + uint8_t position = model->position; + size_t items_count = MenuItemArray_size(model->items); + if(items_count) { + MenuItem* item; + size_t shift_position; + // First line + canvas_set_font(canvas, FontSecondary); + shift_position = (0 + position + items_count - 1) % items_count; + item = MenuItemArray_get(model->items, shift_position); + if(item->icon) { + canvas_draw_icon_animation(canvas, 4, 3, item->icon); + icon_animation_stop(item->icon); + } + canvas_draw_str(canvas, 22, 14, item->label); + // Second line main + canvas_set_font(canvas, FontPrimary); + shift_position = (1 + position + items_count - 1) % items_count; + item = MenuItemArray_get(model->items, shift_position); + if(item->icon) { + canvas_draw_icon_animation(canvas, 4, 25, item->icon); + icon_animation_start(item->icon); + } + canvas_draw_str(canvas, 22, 36, item->label); + // Third line + canvas_set_font(canvas, FontSecondary); + shift_position = (2 + position + items_count - 1) % items_count; + item = MenuItemArray_get(model->items, shift_position); + if(item->icon) { + canvas_draw_icon_animation(canvas, 4, 47, item->icon); + icon_animation_stop(item->icon); + } + canvas_draw_str(canvas, 22, 58, item->label); + // Frame and scrollbar + elements_frame(canvas, 0, 21, 128 - 5, 21); + elements_scrollbar(canvas, position, items_count); + } else { + canvas_draw_str(canvas, 2, 32, "Empty"); + elements_scrollbar(canvas, 0, 0); + } +} + +static bool menu_input_callback(InputEvent* event, void* context) { + Menu* menu = context; + bool consumed = false; + + if(event->type == InputTypeShort) { + if(event->key == InputKeyUp) { + consumed = true; + menu_process_up(menu); + } else if(event->key == InputKeyDown) { + consumed = true; + menu_process_down(menu); + } else if(event->key == InputKeyOk) { + consumed = true; + menu_process_ok(menu); + } + } + + return consumed; +} + +Menu* menu_alloc() { + Menu* menu = furi_alloc(sizeof(Menu)); + menu->view = view_alloc(menu->view); + view_set_context(menu->view, menu); + view_allocate_model(menu->view, ViewModelTypeLocking, sizeof(MenuModel)); + view_set_draw_callback(menu->view, menu_draw_callback); + view_set_input_callback(menu->view, menu_input_callback); + + with_view_model( + menu->view, (MenuModel * model) { + MenuItemArray_init(model->items); + model->position = 0; + return true; + }); + + return menu; +} + +void menu_free(Menu* menu) { + furi_assert(menu); + with_view_model( + menu->view, (MenuModel * model) { + MenuItemArray_clear(model->items); + return true; + }); + view_free(menu->view); + free(menu); +} + +View* menu_get_view(Menu* menu) { + furi_assert(menu); + return (menu->view); +} + +void menu_add_item( + Menu* menu, + const char* label, + IconAnimation* icon, + uint32_t index, + MenuItemCallback callback, + void* context) { + furi_assert(menu); + furi_assert(label); + + MenuItem* item = NULL; + with_view_model( + menu->view, (MenuModel * model) { + item = MenuItemArray_push_new(model->items); + item->label = label; + item->icon = icon; + item->index = index; + item->callback = callback; + item->callback_context = context; + return true; + }); +} + +void menu_clean(Menu* menu) { + furi_assert(menu); + with_view_model( + menu->view, (MenuModel * model) { + MenuItemArray_clean(model->items); + model->position = 0; + return true; + }); +} + +static void menu_process_up(Menu* menu) { + with_view_model( + menu->view, (MenuModel * model) { + if(model->position > 0) { + model->position--; + } else { + model->position = MenuItemArray_size(model->items) - 1; + } + return true; + }); +} + +static void menu_process_down(Menu* menu) { + with_view_model( + menu->view, (MenuModel * model) { + if(model->position < MenuItemArray_size(model->items) - 1) { + model->position++; + } else { + model->position = 0; + } + return true; + }); +} + +static void menu_process_ok(Menu* menu) { + MenuItem* item = NULL; + with_view_model( + menu->view, (MenuModel * model) { + if(model->position < MenuItemArray_size(model->items)) { + item = MenuItemArray_get(model->items, model->position); + } + return true; + }); + if(item && item->callback) { + item->callback(item->callback_context, item->index); + } +} diff --git a/applications/gui/modules/menu.h b/applications/gui/modules/menu.h new file mode 100755 index 000000000..2abc2fc8f --- /dev/null +++ b/applications/gui/modules/menu.h @@ -0,0 +1,52 @@ +#pragma once +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** Menu anonymous structure */ +typedef struct Menu Menu; +typedef void (*MenuItemCallback)(void* context, uint32_t index); + +/** Menu allocation and initialization + * @return Menu instance + */ +Menu* menu_alloc(); + +/** Free menu + * @param menu - Menu instance + */ +void menu_free(Menu* menu); + +/** Get Menu view + * @param menu - Menu instance + * @return View instance + */ +View* menu_get_view(Menu* menu); + +/** Add item to menu + * @param menu - Menu instance + * @param label - menu item string label + * @param icon - IconAnimation instance + * @param index - menu item index + * @param callback - MenuItemCallback instance + * @param context - pointer to context + */ +void menu_add_item( + Menu* menu, + const char* label, + IconAnimation* icon, + uint32_t index, + MenuItemCallback callback, + void* context); + +/** Clean menu + * Note: this function does not free menu instance + * @param menu - Menu instance + */ +void menu_clean(Menu* menu); + +#ifdef __cplusplus +} +#endif diff --git a/applications/gui/modules/submenu.c b/applications/gui/modules/submenu.c index 7c12eebc9..105ebd6a0 100644 --- a/applications/gui/modules/submenu.c +++ b/applications/gui/modules/submenu.c @@ -1,23 +1,22 @@ #include "submenu.h" -#include "gui/canvas.h" + #include -#include #include -#include - -struct SubmenuItem { - const char* label; - uint32_t index; - SubmenuItemCallback callback; - void* callback_context; -}; - -ARRAY_DEF(SubmenuItemArray, SubmenuItem, M_POD_OPLIST); +#include struct Submenu { View* view; }; +typedef struct { + const char* label; + uint32_t index; + SubmenuItemCallback callback; + void* callback_context; +} SubmenuItem; + +ARRAY_DEF(SubmenuItemArray, SubmenuItem, M_POD_OPLIST); + typedef struct { SubmenuItemArray_t items; const char* header; @@ -149,7 +148,7 @@ View* submenu_get_view(Submenu* submenu) { return submenu->view; } -SubmenuItem* submenu_add_item( +void submenu_add_item( Submenu* submenu, const char* label, uint32_t index, @@ -168,8 +167,6 @@ SubmenuItem* submenu_add_item( item->callback_context = callback_context; return true; }); - - return item; } void submenu_clean(Submenu* submenu) { diff --git a/applications/gui/modules/submenu.h b/applications/gui/modules/submenu.h index 64cb9b962..50a9211e1 100644 --- a/applications/gui/modules/submenu.h +++ b/applications/gui/modules/submenu.h @@ -7,7 +7,6 @@ extern "C" { /* Submenu anonymous structure */ typedef struct Submenu Submenu; -typedef struct SubmenuItem SubmenuItem; typedef void (*SubmenuItemCallback)(void* context, uint32_t index); /** @@ -36,9 +35,8 @@ View* submenu_get_view(Submenu* submenu); * @param index - menu item index, used for callback, may be the same with other items * @param callback - menu item callback * @param callback_context - menu item callback context - * @return SubmenuItem instance that can be used to modify or delete that item */ -SubmenuItem* submenu_add_item( +void submenu_add_item( Submenu* submenu, const char* label, uint32_t index, diff --git a/applications/loader/loader.c b/applications/loader/loader.c old mode 100644 new mode 100755 index 0ef11677e..90986aac2 --- a/applications/loader/loader.c +++ b/applications/loader/loader.c @@ -1,8 +1,11 @@ #include "loader_i.h" +#define LOADER_THREAD_FLAG_SHOW_MENU (1 << 0) +#define LOADER_THREAD_FLAG_ALL (LOADER_THREAD_FLAG_SHOW_MENU) + static Loader* loader_instance = NULL; -static void loader_menu_callback(void* _ctx) { +static void loader_menu_callback(void* _ctx, uint32_t index) { const FlipperApplication* flipper_app = _ctx; furi_assert(flipper_app->app); @@ -27,6 +30,11 @@ static void loader_menu_callback(void* _ctx) { furi_thread_start(loader_instance->thread); } +static void loader_submenu_callback(void* context, uint32_t index) { + uint32_t view_id = (uint32_t)context; + view_dispatcher_switch_to_view(loader_instance->view_dispatcher, view_id); +} + static void loader_cli_callback(Cli* cli, string_t args, void* _ctx) { furi_assert(_ctx); const FlipperApplication* flipper_app = (FlipperApplication*)_ctx; @@ -60,6 +68,15 @@ bool loader_start(Loader* instance, const char* name, const char* args) { } } + if(!flipper_app) { + for(size_t i = 0; i < FLIPPER_DEBUG_APPS_COUNT; i++) { + if(strcmp(FLIPPER_DEBUG_APPS[i].name, name) == 0) { + flipper_app = &FLIPPER_DEBUG_APPS[i]; + break; + } + } + } + if(!flipper_app) { FURI_LOG_E(LOADER_LOG_TAG, "Can't find application with name %s", name); return false; @@ -138,6 +155,14 @@ static void loader_thread_state_callback(FuriThreadState thread_state, void* con } } +static uint32_t loader_hide_menu(void* context) { + return VIEW_NONE; +} + +static uint32_t loader_back_to_primary_menu(void* context) { + return LoaderMenuViewPrimary; +} + static Loader* loader_alloc() { Loader* instance = furi_alloc(sizeof(Loader)); @@ -150,10 +175,45 @@ static Loader* loader_alloc() { instance->mutex = osMutexNew(NULL); - instance->menu_vm = furi_record_open("menu"); - instance->cli = furi_record_open("cli"); + instance->loader_thread = osThreadGetId(); + + // Gui + instance->gui = furi_record_open("gui"); + instance->view_dispatcher = view_dispatcher_alloc(); + view_dispatcher_attach_to_gui( + instance->view_dispatcher, instance->gui, ViewDispatcherTypeFullscreen); + // Primary menu + instance->primary_menu = menu_alloc(); + view_set_previous_callback(menu_get_view(instance->primary_menu), loader_hide_menu); + view_dispatcher_add_view( + instance->view_dispatcher, LoaderMenuViewPrimary, menu_get_view(instance->primary_menu)); + // Plugins menu + instance->plugins_menu = submenu_alloc(); + view_set_previous_callback( + submenu_get_view(instance->plugins_menu), loader_back_to_primary_menu); + view_dispatcher_add_view( + instance->view_dispatcher, + LoaderMenuViewPlugins, + submenu_get_view(instance->plugins_menu)); + // Debug menu + instance->debug_menu = submenu_alloc(); + view_set_previous_callback( + submenu_get_view(instance->debug_menu), loader_back_to_primary_menu); + view_dispatcher_add_view( + instance->view_dispatcher, LoaderMenuViewDebug, submenu_get_view(instance->debug_menu)); + // Settings menu + instance->settings_menu = submenu_alloc(); + view_set_previous_callback( + submenu_get_view(instance->settings_menu), loader_back_to_primary_menu); + view_dispatcher_add_view( + instance->view_dispatcher, + LoaderMenuViewSettings, + submenu_get_view(instance->settings_menu)); + + view_dispatcher_enable_queue(instance->view_dispatcher); + return instance; } @@ -162,133 +222,111 @@ static void loader_free(Loader* instance) { furi_record_close("cli"); - furi_record_close("menu"); - osMutexDelete(instance->mutex); string_clear(instance->args); furi_thread_free(instance->thread); + menu_free(loader_instance->primary_menu); + view_dispatcher_remove_view(loader_instance->view_dispatcher, LoaderMenuViewPrimary); + submenu_free(loader_instance->plugins_menu); + view_dispatcher_remove_view(loader_instance->view_dispatcher, LoaderMenuViewPlugins); + submenu_free(loader_instance->debug_menu); + view_dispatcher_remove_view(loader_instance->view_dispatcher, LoaderMenuViewDebug); + submenu_free(loader_instance->settings_menu); + view_dispatcher_remove_view(loader_instance->view_dispatcher, LoaderMenuViewSettings); + view_dispatcher_free(loader_instance->view_dispatcher); + + furi_record_close("gui"); + free(instance); + instance = NULL; +} + +static void loader_add_cli_command(FlipperApplication* app) { + string_t cli_name; + string_init_printf(cli_name, "app_%s", app->name); + cli_add_command( + loader_instance->cli, + string_get_cstr(cli_name), + CliCommandFlagDefault, + loader_cli_callback, + app); + string_clear(cli_name); } static void loader_build_menu() { FURI_LOG_I(LOADER_LOG_TAG, "Building main menu"); - with_value_mutex( - loader_instance->menu_vm, (Menu * menu) { - for(size_t i = 0; i < FLIPPER_APPS_COUNT; i++) { - // Add menu item - menu_item_add( - menu, - menu_item_alloc_function( - FLIPPER_APPS[i].name, - FLIPPER_APPS[i].icon ? icon_animation_alloc(FLIPPER_APPS[i].icon) : NULL, - loader_menu_callback, - (void*)&FLIPPER_APPS[i])); - - // Add cli command - string_t cli_name; - string_init_set_str(cli_name, "app_"); - string_cat_str(cli_name, FLIPPER_APPS[i].name); - cli_add_command( - loader_instance->cli, - string_get_cstr(cli_name), - CliCommandFlagDefault, - loader_cli_callback, - (void*)&FLIPPER_APPS[i]); - string_clear(cli_name); - } - }); + size_t i; + for(i = 0; i < FLIPPER_APPS_COUNT; i++) { + loader_add_cli_command((FlipperApplication*)&FLIPPER_APPS[i]); + menu_add_item( + loader_instance->primary_menu, + FLIPPER_APPS[i].name, + FLIPPER_APPS[i].icon ? icon_animation_alloc(FLIPPER_APPS[i].icon) : NULL, + i, + loader_menu_callback, + (void*)&FLIPPER_APPS[i]); + } + menu_add_item( + loader_instance->primary_menu, + "Plugins", + icon_animation_alloc(&A_Plugins_14), + i++, + loader_submenu_callback, + (void*)LoaderMenuViewPlugins); + menu_add_item( + loader_instance->primary_menu, + "Debug tools", + icon_animation_alloc(&A_Debug_14), + i++, + loader_submenu_callback, + (void*)LoaderMenuViewDebug); + menu_add_item( + loader_instance->primary_menu, + "Settings", + icon_animation_alloc(&A_Settings_14), + i++, + loader_submenu_callback, + (void*)LoaderMenuViewSettings); FURI_LOG_I(LOADER_LOG_TAG, "Building plugins menu"); - with_value_mutex( - loader_instance->menu_vm, (Menu * menu) { - MenuItem* menu_plugins = - menu_item_alloc_menu("Plugins", icon_animation_alloc(&A_Plugins_14)); - - for(size_t i = 0; i < FLIPPER_PLUGINS_COUNT; i++) { - // Add menu item - menu_item_subitem_add( - menu_plugins, - menu_item_alloc_function( - FLIPPER_PLUGINS[i].name, - FLIPPER_PLUGINS[i].icon ? icon_animation_alloc(FLIPPER_PLUGINS[i].icon) : - NULL, - loader_menu_callback, - (void*)&FLIPPER_PLUGINS[i])); - - // Add cli command - string_t cli_name; - string_init_set_str(cli_name, "app_"); - string_cat_str(cli_name, FLIPPER_PLUGINS[i].name); - cli_add_command( - loader_instance->cli, - string_get_cstr(cli_name), - CliCommandFlagDefault, - loader_cli_callback, - (void*)&FLIPPER_PLUGINS[i]); - string_clear(cli_name); - } - - menu_item_add(menu, menu_plugins); - }); + for(i = 0; i < FLIPPER_PLUGINS_COUNT; i++) { + loader_add_cli_command((FlipperApplication*)&FLIPPER_PLUGINS[i]); + submenu_add_item( + loader_instance->plugins_menu, + FLIPPER_PLUGINS[i].name, + i, + loader_menu_callback, + (void*)&FLIPPER_PLUGINS[i]); + } FURI_LOG_I(LOADER_LOG_TAG, "Building debug menu"); - with_value_mutex( - loader_instance->menu_vm, (Menu * menu) { - MenuItem* menu_debug = - menu_item_alloc_menu("Debug tools", icon_animation_alloc(&A_Debug_14)); - - for(size_t i = 0; i < FLIPPER_DEBUG_APPS_COUNT; i++) { - // Add menu item - menu_item_subitem_add( - menu_debug, - menu_item_alloc_function( - FLIPPER_DEBUG_APPS[i].name, - FLIPPER_DEBUG_APPS[i].icon ? - icon_animation_alloc(FLIPPER_DEBUG_APPS[i].icon) : - NULL, - loader_menu_callback, - (void*)&FLIPPER_DEBUG_APPS[i])); - - // Add cli command - string_t cli_name; - string_init_set_str(cli_name, "app_"); - string_cat_str(cli_name, FLIPPER_DEBUG_APPS[i].name); - cli_add_command( - loader_instance->cli, - string_get_cstr(cli_name), - CliCommandFlagDefault, - loader_cli_callback, - (void*)&FLIPPER_DEBUG_APPS[i]); - string_clear(cli_name); - } - - menu_item_add(menu, menu_debug); - }); + for(i = 0; i < FLIPPER_DEBUG_APPS_COUNT; i++) { + loader_add_cli_command((FlipperApplication*)&FLIPPER_DEBUG_APPS[i]); + submenu_add_item( + loader_instance->debug_menu, + FLIPPER_DEBUG_APPS[i].name, + i, + loader_menu_callback, + (void*)&FLIPPER_DEBUG_APPS[i]); + } FURI_LOG_I(LOADER_LOG_TAG, "Building settings menu"); - with_value_mutex( - loader_instance->menu_vm, (Menu * menu) { - MenuItem* menu_debug = - menu_item_alloc_menu("Settings", icon_animation_alloc(&A_Settings_14)); + for(i = 0; i < FLIPPER_SETTINGS_APPS_COUNT; i++) { + submenu_add_item( + loader_instance->settings_menu, + FLIPPER_SETTINGS_APPS[i].name, + i, + loader_menu_callback, + (void*)&FLIPPER_SETTINGS_APPS[i]); + } +} - for(size_t i = 0; i < FLIPPER_SETTINGS_APPS_COUNT; i++) { - // Add menu item - menu_item_subitem_add( - menu_debug, - menu_item_alloc_function( - FLIPPER_SETTINGS_APPS[i].name, - FLIPPER_SETTINGS_APPS[i].icon ? - icon_animation_alloc(FLIPPER_SETTINGS_APPS[i].icon) : - NULL, - loader_menu_callback, - (void*)&FLIPPER_SETTINGS_APPS[i])); - } - - menu_item_add(menu, menu_debug); - }); +void loader_show_menu() { + furi_assert(loader_instance); + osThreadFlagsSet(loader_instance->loader_thread, LOADER_THREAD_FLAG_SHOW_MENU); } int32_t loader_srv(void* p) { @@ -300,15 +338,24 @@ int32_t loader_srv(void* p) { // Call on start hooks for(size_t i = 0; i < FLIPPER_ON_SYSTEM_START_COUNT; i++) { - (*FLIPPER_ON_SYSTEM_START[i])(); + FLIPPER_ON_SYSTEM_START[i](); } FURI_LOG_I(LOADER_LOG_TAG, "Started"); furi_record_create("loader", loader_instance); +#ifdef LOADER_AUTOSTART + loader_start(loader_instance, LOADER_AUTOSTART, NULL); +#endif + while(1) { - osThreadSuspend(osThreadGetId()); + uint32_t flags = osThreadFlagsWait(LOADER_THREAD_FLAG_ALL, osFlagsWaitAny, osWaitForever); + if(flags & LOADER_THREAD_FLAG_SHOW_MENU) { + view_dispatcher_switch_to_view( + loader_instance->view_dispatcher, LoaderMenuViewPrimary); + view_dispatcher_run(loader_instance->view_dispatcher); + } } loader_free(loader_instance); diff --git a/applications/loader/loader.h b/applications/loader/loader.h index 5e81e9274..568cfaa3c 100644 --- a/applications/loader/loader.h +++ b/applications/loader/loader.h @@ -18,3 +18,6 @@ bool loader_lock(Loader* instance); /** Unlock application start */ void loader_unlock(Loader* instance); + +/** Show primary loader */ +void loader_show_menu(); diff --git a/applications/loader/loader_i.h b/applications/loader/loader_i.h index f5340434c..8d44911fb 100644 --- a/applications/loader/loader_i.h +++ b/applications/loader/loader_i.h @@ -3,20 +3,39 @@ #include #include #include -#include -#include + +#include + +#include +#include + #include #include #define LOADER_LOG_TAG "loader" struct Loader { + osThreadId_t loader_thread; FuriThread* thread; const FlipperApplication* current_app; string_t args; Cli* cli; - ValueMutex* menu_vm; + Gui* gui; + + ViewDispatcher* view_dispatcher; + Menu* primary_menu; + Submenu* plugins_menu; + Submenu* debug_menu; + Submenu* settings_menu; + size_t free_heap_size; osMutexId_t mutex; volatile uint8_t lock_semaphore; }; + +typedef enum { + LoaderMenuViewPrimary, + LoaderMenuViewPlugins, + LoaderMenuViewDebug, + LoaderMenuViewSettings, +} LoaderMenuView; diff --git a/applications/menu/menu.c b/applications/menu/menu.c deleted file mode 100644 index 544a88219..000000000 --- a/applications/menu/menu.c +++ /dev/null @@ -1,337 +0,0 @@ -#include "menu.h" -#include -#include - -#include -#include -#include - -#include "menu_event.h" -#include "menu_item.h" -#include - -struct Menu { - MenuEvent* event; - - // GUI - Gui* gui; - ViewPort* view_port; - IconAnimation* icon; - - // State - MenuItem* root; - MenuItem* settings; - MenuItem* current; -}; - -void menu_view_port_callback(Canvas* canvas, void* context); - -ValueMutex* menu_init() { - Menu* menu = furi_alloc(sizeof(Menu)); - - // Event dispatcher - menu->event = menu_event_alloc(); - - ValueMutex* menu_mutex = furi_alloc(sizeof(ValueMutex)); - if(menu_mutex == NULL || !init_mutex(menu_mutex, menu, sizeof(Menu))) { - printf("[menu_task] cannot create menu mutex\r\n"); - furi_crash(NULL); - } - - // OpenGui record - menu->gui = furi_record_open("gui"); - - // Allocate and configure view_port - menu->view_port = view_port_alloc(); - - // Open GUI and register fullscreen view_port - gui_add_view_port(menu->gui, menu->view_port, GuiLayerFullscreen); - - view_port_enabled_set(menu->view_port, false); - view_port_draw_callback_set(menu->view_port, menu_view_port_callback, menu_mutex); - view_port_input_callback_set(menu->view_port, menu_event_input_callback, menu->event); - - return menu_mutex; -} - -void menu_build_main(Menu* menu) { - furi_assert(menu); - // Root point - menu->root = menu_item_alloc_menu(NULL, NULL); -} - -void menu_item_add(Menu* menu, MenuItem* item) { - menu_item_subitem_add(menu->root, item); -} - -void menu_settings_item_add(Menu* menu, MenuItem* item) { - menu_item_subitem_add(menu->settings, item); -} - -void menu_draw_primary(Menu* menu, Canvas* canvas) { - size_t position = menu_item_get_position(menu->current); - MenuItemArray_t* items = menu_item_get_subitems(menu->current); - size_t items_count = MenuItemArray_size(*items); - if(items_count) { - MenuItem* item; - size_t shift_position; - // First line - canvas_set_font(canvas, FontSecondary); - shift_position = (0 + position + items_count - 1) % (MenuItemArray_size(*items)); - item = *MenuItemArray_get(*items, shift_position); - canvas_draw_icon_animation(canvas, 4, 3, menu_item_get_icon(item)); - canvas_draw_str(canvas, 22, 14, menu_item_get_label(item)); - // Second line main - canvas_set_font(canvas, FontPrimary); - shift_position = (1 + position + items_count - 1) % (MenuItemArray_size(*items)); - item = *MenuItemArray_get(*items, shift_position); - canvas_draw_icon_animation(canvas, 4, 25, menu_item_get_icon(item)); - canvas_draw_str(canvas, 22, 36, menu_item_get_label(item)); - // Third line - canvas_set_font(canvas, FontSecondary); - shift_position = (2 + position + items_count - 1) % (MenuItemArray_size(*items)); - item = *MenuItemArray_get(*items, shift_position); - canvas_draw_icon_animation(canvas, 4, 47, menu_item_get_icon(item)); - canvas_draw_str(canvas, 22, 58, menu_item_get_label(item)); - // Frame and scrollbar - // elements_frame(canvas, 0, 0, 128 - 5, 21); - elements_frame(canvas, 0, 21, 128 - 5, 21); - // elements_frame(canvas, 0, 42, 128 - 5, 21); - elements_scrollbar(canvas, position, items_count); - } else { - canvas_draw_str(canvas, 2, 32, "Empty"); - elements_scrollbar(canvas, 0, 0); - } -} - -void menu_draw_secondary(Menu* menu, Canvas* canvas) { - size_t position = 0; - size_t selected_position = menu_item_get_position(menu->current); - size_t window_position = menu_item_get_window_position(menu->current); - MenuItemArray_t* items = menu_item_get_subitems(menu->current); - const uint8_t items_on_screen = 4; - const uint8_t item_height = 16; - const uint8_t item_width = 123; - size_t items_count = MenuItemArray_size(*items); - MenuItemArray_it_t it; - - canvas_set_font(canvas, FontSecondary); - for(MenuItemArray_it(it, *items); !MenuItemArray_end_p(it); MenuItemArray_next(it)) { - size_t item_position = position - window_position; - - if(item_position < items_on_screen) { - if(position == selected_position) { - canvas_set_color(canvas, ColorBlack); - elements_slightly_rounded_box( - canvas, 0, (item_position * item_height) + 1, item_width, item_height - 2); - canvas_set_color(canvas, ColorWhite); - } else { - canvas_set_color(canvas, ColorBlack); - } - canvas_draw_str( - canvas, - 6, - (item_position * item_height) + item_height - 4, - menu_item_get_label(*MenuItemArray_ref(it))); - } - - position++; - } - - elements_scrollbar(canvas, selected_position, items_count); -} - -void menu_view_port_callback(Canvas* canvas, void* context) { - furi_assert(canvas); - furi_assert(context); - - Menu* menu = acquire_mutex((ValueMutex*)context, 100); // wait 10 ms to get mutex - if(menu == NULL) return; // redraw fail - - furi_assert(menu->current); - - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - - // if top level - if(menu_item_get_parent(menu->current) == NULL) { - menu_draw_primary(menu, canvas); - } else { - menu_draw_secondary(menu, canvas); - } - - release_mutex((ValueMutex*)context, menu); -} - -void menu_set_icon(Menu* menu, IconAnimation* icon) { - furi_assert(menu); - - if(menu->icon) { - icon_animation_stop(menu->icon); - } - - menu->icon = icon; - - if(menu->icon) { - icon_animation_start(menu->icon); - } -} - -void menu_update(Menu* menu) { - furi_assert(menu); - - if(menu->current) { - size_t position = menu_item_get_position(menu->current); - MenuItemArray_t* items = menu_item_get_subitems(menu->current); - size_t items_count = MenuItemArray_size(*items); - if(items_count) { - MenuItem* item = *MenuItemArray_get(*items, position); - menu_set_icon(menu, menu_item_get_icon(item)); - } - } - - menu_event_activity_notify(menu->event); - view_port_update(menu->view_port); -} - -void menu_up(Menu* menu) { - furi_assert(menu); - size_t position = menu_item_get_position(menu->current); - size_t window_position = menu_item_get_window_position(menu->current); - MenuItemArray_t* items = menu_item_get_subitems(menu->current); - - const uint8_t items_on_screen = 4; - - if(position > 0) { - position--; - if(((position - window_position) < 1) && window_position > 0) { - window_position--; - } - } else { - position = MenuItemArray_size(*items) - 1; - if(position > (items_on_screen - 1)) { - window_position = position - (items_on_screen - 1); - } - } - - menu_item_set_position(menu->current, position); - menu_item_set_window_position(menu->current, window_position); - menu_update(menu); -} - -void menu_down(Menu* menu) { - furi_assert(menu); - size_t position = menu_item_get_position(menu->current); - size_t window_position = menu_item_get_window_position(menu->current); - MenuItemArray_t* items = menu_item_get_subitems(menu->current); - - const uint8_t items_on_screen = 4; - if(position < (MenuItemArray_size(*items) - 1)) { - position++; - if((position - window_position) > (items_on_screen - 2) && - window_position < (MenuItemArray_size(*items) - items_on_screen)) { - window_position++; - } - } else { - position = 0; - window_position = 0; - } - - menu_item_set_position(menu->current, position); - menu_item_set_window_position(menu->current, window_position); - menu_update(menu); -} - -void menu_ok(Menu* menu) { - furi_assert(menu); - - if(!menu->current) { - view_port_enabled_set(menu->view_port, true); - menu->current = menu->root; - menu_item_set_position(menu->current, 0); - menu_item_set_window_position(menu->current, 0); - menu_update(menu); - return; - } - - MenuItemArray_t* items = menu_item_get_subitems(menu->current); - if(!items || MenuItemArray_size(*items) == 0) { - return; - } - - size_t position = menu_item_get_position(menu->current); - MenuItem* item = *MenuItemArray_get(*items, position); - MenuItemType type = menu_item_get_type(item); - - if(type == MenuItemTypeMenu) { - menu->current = item; - menu_item_set_position(menu->current, 0); - menu_item_set_window_position(menu->current, 0); - menu_update(menu); - } else if(type == MenuItemTypeFunction) { - menu_item_function_call(item); - gui_send_view_port_back(menu->gui, menu->view_port); - } -} - -void menu_back(Menu* menu) { - furi_assert(menu); - MenuItem* parent = menu_item_get_parent(menu->current); - if(parent) { - menu->current = parent; - menu_update(menu); - } else { - menu_exit(menu); - } -} - -void menu_exit(Menu* menu) { - furi_assert(menu); - view_port_enabled_set(menu->view_port, false); - menu->current = NULL; - menu_update(menu); -} - -int32_t menu_srv(void* p) { - ValueMutex* menu_mutex = menu_init(); - - MenuEvent* menu_event = NULL; - { - Menu* menu = acquire_mutex_block(menu_mutex); - furi_check(menu); - - menu_build_main(menu); - - // immutable thread-safe object - menu_event = menu->event; - - release_mutex(menu_mutex, menu); - } - - furi_record_create("menu", menu_mutex); - - while(1) { - MenuMessage m = menu_event_next(menu_event); - - Menu* menu = acquire_mutex_block(menu_mutex); - - if(!menu->current && m.type != MenuMessageTypeOk) { - } else if(m.type == MenuMessageTypeUp) { - menu_up(menu); - } else if(m.type == MenuMessageTypeDown) { - menu_down(menu); - } else if(m.type == MenuMessageTypeOk) { - menu_ok(menu); - } else if(m.type == MenuMessageTypeBack) { - menu_back(menu); - } else if(m.type == MenuMessageTypeIdle) { - menu_exit(menu); - } else { - // TODO: fail somehow? - } - - release_mutex(menu_mutex, menu); - } - - return 0; -} diff --git a/applications/menu/menu.h b/applications/menu/menu.h deleted file mode 100644 index f8607fda1..000000000 --- a/applications/menu/menu.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once - -#include "menu/menu_item.h" - -typedef struct Menu Menu; -typedef struct MenuItem MenuItem; - -// Add menu item to root menu -void menu_item_add(Menu* menu, MenuItem* item); - -// Add menu item to settings menu -void menu_settings_item_add(Menu* menu, MenuItem* item); - -// Menu controls -void menu_up(Menu* menu); -void menu_down(Menu* menu); -void menu_ok(Menu* menu); -void menu_back(Menu* menu); -void menu_exit(Menu* menu); diff --git a/applications/menu/menu_event.c b/applications/menu/menu_event.c deleted file mode 100644 index e39b83deb..000000000 --- a/applications/menu/menu_event.c +++ /dev/null @@ -1,65 +0,0 @@ -#include "menu_event.h" - -#include -#include - -#include - -#define MENU_MESSAGE_MQUEUE_SIZE 8 - -struct MenuEvent { - osMessageQueueId_t mqueue; -}; - -void MenuEventimeout_callback(void* arg) { - MenuEvent* menu_event = arg; - MenuMessage message; - message.type = MenuMessageTypeIdle; - osMessageQueuePut(menu_event->mqueue, &message, 0, osWaitForever); -} - -MenuEvent* menu_event_alloc() { - MenuEvent* menu_event = furi_alloc(sizeof(MenuEvent)); - menu_event->mqueue = osMessageQueueNew(MENU_MESSAGE_MQUEUE_SIZE, sizeof(MenuMessage), NULL); - furi_check(menu_event->mqueue); - return menu_event; -} - -void menu_event_free(MenuEvent* menu_event) { - furi_assert(menu_event); - furi_check(osMessageQueueDelete(menu_event->mqueue) == osOK); - free(menu_event); -} - -void menu_event_activity_notify(MenuEvent* menu_event) { - furi_assert(menu_event); -} - -MenuMessage menu_event_next(MenuEvent* menu_event) { - furi_assert(menu_event); - MenuMessage message; - while(osMessageQueueGet(menu_event->mqueue, &message, NULL, osWaitForever) != osOK) { - }; - return message; -} - -void menu_event_input_callback(InputEvent* input_event, void* context) { - MenuEvent* menu_event = context; - MenuMessage message; - - if(input_event->type != InputTypeShort) return; - - if(input_event->key == InputKeyUp) { - message.type = MenuMessageTypeUp; - } else if(input_event->key == InputKeyDown) { - message.type = MenuMessageTypeDown; - } else if(input_event->key == InputKeyOk) { - message.type = MenuMessageTypeOk; - } else if(input_event->key == InputKeyBack) { - message.type = MenuMessageTypeBack; - } else { - message.type = MenuMessageTypeUnknown; - } - - osMessageQueuePut(menu_event->mqueue, &message, 0, osWaitForever); -} \ No newline at end of file diff --git a/applications/menu/menu_event.h b/applications/menu/menu_event.h deleted file mode 100644 index 031b8f4e6..000000000 --- a/applications/menu/menu_event.h +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include -#include - -typedef enum { - MenuMessageTypeUp = 0x00, - MenuMessageTypeDown = 0x01, - MenuMessageTypeLeft = 0x02, - MenuMessageTypeRight = 0x03, - MenuMessageTypeOk = 0x04, - MenuMessageTypeBack = 0x05, - MenuMessageTypeIdle = 0x06, - MenuMessageTypeUnknown = 0xFF, -} MenuMessageType; - -typedef struct { - MenuMessageType type; - void* data; -} MenuMessage; - -typedef struct MenuEvent MenuEvent; - -MenuEvent* menu_event_alloc(); - -void menu_event_free(MenuEvent* menu_event); - -void menu_event_activity_notify(MenuEvent* menu_event); - -MenuMessage menu_event_next(MenuEvent* menu_event); - -void menu_event_input_callback(InputEvent* input_event, void* context); diff --git a/applications/menu/menu_item.c b/applications/menu/menu_item.c deleted file mode 100644 index b79cdabd8..000000000 --- a/applications/menu/menu_item.c +++ /dev/null @@ -1,135 +0,0 @@ -#include "menu_item.h" -#include -#include -#include - -struct MenuItem { - MenuItemType type; - - const char* label; - IconAnimation* icon; - - size_t position; - size_t window_position; - MenuItem* parent; - void* data; - - // callback related - MenuItemCallback callback; - void* callback_context; -}; - -MenuItem* menu_item_alloc() { - MenuItem* menu_item = furi_alloc(sizeof(MenuItem)); - return menu_item; -} - -MenuItem* menu_item_alloc_menu(const char* label, IconAnimation* icon) { - MenuItem* menu_item = menu_item_alloc(); - - menu_item->type = MenuItemTypeMenu; - menu_item->label = label; - menu_item->icon = icon; - - MenuItemArray_t* items = furi_alloc(sizeof(MenuItemArray_t)); - MenuItemArray_init(*items); - menu_item->data = items; - - return menu_item; -} - -MenuItem* menu_item_alloc_function( - const char* label, - IconAnimation* icon, - MenuItemCallback callback, - void* context) { - MenuItem* menu_item = menu_item_alloc(); - - menu_item->type = MenuItemTypeFunction; - menu_item->label = label; - menu_item->icon = icon; - menu_item->callback = callback; - menu_item->callback_context = context; - menu_item->parent = NULL; - - return menu_item; -} - -void menu_item_release(MenuItem* menu_item) { - furi_assert(menu_item); - if(menu_item->type == MenuItemTypeMenu) { - //TODO: iterate and release - free(menu_item->data); - } - free(menu_item); -} - -MenuItem* menu_item_get_parent(MenuItem* menu_item) { - furi_assert(menu_item); - return menu_item->parent; -} - -void menu_item_subitem_add(MenuItem* menu_item, MenuItem* sub_item) { - furi_assert(menu_item); - furi_check(menu_item->type == MenuItemTypeMenu); - MenuItemArray_t* items = menu_item->data; - sub_item->parent = menu_item; - MenuItemArray_push_back(*items, sub_item); -} - -MenuItemType menu_item_get_type(MenuItem* menu_item) { - furi_assert(menu_item); - return menu_item->type; -} - -void menu_item_set_position(MenuItem* menu_item, size_t position) { - furi_assert(menu_item); - menu_item->position = position; -} - -size_t menu_item_get_position(MenuItem* menu_item) { - furi_assert(menu_item); - return menu_item->position; -} - -void menu_item_set_window_position(MenuItem* menu_item, size_t window_position) { - furi_assert(menu_item); - menu_item->window_position = window_position; -} - -size_t menu_item_get_window_position(MenuItem* menu_item) { - furi_assert(menu_item); - return menu_item->window_position; -} - -void menu_item_set_label(MenuItem* menu_item, const char* label) { - furi_assert(menu_item); - menu_item->label = label; -} - -const char* menu_item_get_label(MenuItem* menu_item) { - furi_assert(menu_item); - return menu_item->label; -} - -void menu_item_set_icon(MenuItem* menu_item, IconAnimation* icon) { - furi_assert(menu_item); - menu_item->icon = icon; -} - -IconAnimation* menu_item_get_icon(MenuItem* menu_item) { - furi_assert(menu_item); - return menu_item->icon; -} - -MenuItemArray_t* menu_item_get_subitems(MenuItem* menu_item) { - furi_assert(menu_item); - furi_check(menu_item->type == MenuItemTypeMenu); - return menu_item->data; -} - -void menu_item_function_call(MenuItem* menu_item) { - furi_assert(menu_item); - furi_check(menu_item->type == MenuItemTypeFunction); - if(menu_item->callback) menu_item->callback(menu_item->callback_context); -} diff --git a/applications/menu/menu_item.h b/applications/menu/menu_item.h deleted file mode 100644 index 336f58a36..000000000 --- a/applications/menu/menu_item.h +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once - -#include -#include -#include - -typedef enum { - MenuItemTypeMenu = 0x00, - MenuItemTypeFunction = 0x01, -} MenuItemType; - -typedef struct MenuItem MenuItem; -typedef void (*MenuItemCallback)(void* context); - -ARRAY_DEF(MenuItemArray, MenuItem*, M_PTR_OPLIST); - -MenuItem* menu_item_alloc_menu(const char* label, IconAnimation* icon); - -MenuItem* menu_item_alloc_function( - const char* label, - IconAnimation* icon, - MenuItemCallback callback, - void* context); - -void menu_item_release(MenuItem* menu_item); - -MenuItem* menu_item_get_parent(MenuItem* menu_item); - -void menu_item_subitem_add(MenuItem* menu_item, MenuItem* sub_item); - -MenuItemType menu_item_get_type(MenuItem* menu_item); - -void menu_item_set_position(MenuItem* menu_item, size_t position); -size_t menu_item_get_position(MenuItem* menu_item); - -void menu_item_set_window_position(MenuItem* menu_item, size_t window_position); -size_t menu_item_get_window_position(MenuItem* menu_item); - -void menu_item_set_label(MenuItem* menu_item, const char* label); -const char* menu_item_get_label(MenuItem* menu_item); - -void menu_item_set_icon(MenuItem* menu_item, IconAnimation* icon); -IconAnimation* menu_item_get_icon(MenuItem* menu_item); - -MenuItemArray_t* menu_item_get_subitems(MenuItem* menu_item); - -void menu_item_function_call(MenuItem* menu_item); diff --git a/lib/app-scened-template/view-modules/submenu-vm.cpp b/lib/app-scened-template/view-modules/submenu-vm.cpp index 12c283f96..3bd5533ca 100644 --- a/lib/app-scened-template/view-modules/submenu-vm.cpp +++ b/lib/app-scened-template/view-modules/submenu-vm.cpp @@ -16,12 +16,12 @@ void SubmenuVM::clean() { submenu_clean(submenu); } -SubmenuItem* SubmenuVM::add_item( +void SubmenuVM::add_item( const char* label, uint32_t index, SubmenuItemCallback callback, void* callback_context) { - return submenu_add_item(submenu, label, index, callback, callback_context); + submenu_add_item(submenu, label, index, callback, callback_context); } void SubmenuVM::set_selected_item(uint32_t index) { diff --git a/lib/app-scened-template/view-modules/submenu-vm.h b/lib/app-scened-template/view-modules/submenu-vm.h index d508d75e9..b1bcd3abc 100644 --- a/lib/app-scened-template/view-modules/submenu-vm.h +++ b/lib/app-scened-template/view-modules/submenu-vm.h @@ -16,9 +16,8 @@ public: * @param index - menu item index, used for callback, may be the same with other items * @param callback - menu item callback * @param callback_context - menu item callback context - * @return SubmenuItem instance that can be used to modify or delete that item */ - SubmenuItem* add_item( + void add_item( const char* label, uint32_t index, SubmenuItemCallback callback,