-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Problem] Currently the application does nothing. [Solution] This updates the app to have a simple main menu, with the options that will be available in the final version of the app. It also sets up some directory structures, dividing the code up into pieces that are more easily digestible. Specifically, different scenes can be managed on their own, without being as dependent on a single file. [Testing] Built and confirmed working on device. Should probably investigate unit testing but that can come later.
- Loading branch information
Showing
10 changed files
with
423 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
#include <gui/modules/menu.h> | ||
#include <gui/modules/popup.h> | ||
|
||
#include "tone_gen.h" | ||
#include "app_context.h" | ||
|
||
/** custom event handler - passes the event to the scene manager */ | ||
bool viewDispatcherCustomCallback(void* context, uint32_t custom_event) { | ||
furi_assert(context); | ||
struct AppContext_t* appContext = context; | ||
return scene_manager_handle_custom_event(appContext->scene_manager, custom_event); | ||
} | ||
|
||
/** navigation event handler - passes the event to the scene manager */ | ||
bool viewDispatcherNavigationCallback(void* context) { | ||
furi_assert(context); | ||
struct AppContext_t* appContext = context; | ||
return scene_manager_handle_back_event(appContext->scene_manager); | ||
} | ||
|
||
AppContextStatus initializeAppContext( | ||
struct AppContext_t** context, | ||
const SceneManagerHandlers* sceneManagerHandlers) { | ||
FURI_LOG_I(TAG, "Allocating memory for app context"); | ||
|
||
*context = malloc(sizeof(struct AppContext_t)); | ||
if(*context == NULL) { | ||
FURI_LOG_E(TAG, "Failed to allocate memory for app context"); | ||
return APP_CONTEXT_CANT_ALLOCATE; | ||
} | ||
|
||
// Allocate our scene manager with the handlers provided | ||
FURI_LOG_I(TAG, "Setting up the scene manager"); | ||
(*context)->scene_manager = scene_manager_alloc(sceneManagerHandlers, *context); | ||
|
||
// Now setup our view dispatchers | ||
FURI_LOG_I(TAG, "Setting up the view dispatcher"); | ||
(*context)->view_dispatcher = view_dispatcher_alloc(); | ||
view_dispatcher_enable_queue((*context)->view_dispatcher); | ||
|
||
FURI_LOG_I(TAG, "Setting view dispatcher callbacks"); | ||
view_dispatcher_set_event_callback_context((*context)->view_dispatcher, (*context)); | ||
FURI_LOG_I(TAG, "Setting view dispatcher custom event callbacks"); | ||
view_dispatcher_set_custom_event_callback( | ||
(*context)->view_dispatcher, viewDispatcherCustomCallback); | ||
FURI_LOG_I(TAG, "Setting view dispatcher navigation event callbacks"); | ||
view_dispatcher_set_navigation_event_callback( | ||
(*context)->view_dispatcher, viewDispatcherNavigationCallback); | ||
FURI_LOG_I(TAG, "Setting view dispatcher callbacks done"); | ||
|
||
return APP_CONTEXT_OK; | ||
} | ||
|
||
AppContextStatus freeAppContextViews(struct AppContext_t** context) { | ||
FURI_LOG_I(TAG, "Freeing views"); | ||
struct ListNode_t* root = (*context)->activeViews; | ||
while(root) { | ||
struct View_t* view = root->data; | ||
view_dispatcher_remove_view((*context)->view_dispatcher, view->viewId); | ||
|
||
switch(view->type) { | ||
case MENU: | ||
menu_free(view->viewData); | ||
break; | ||
case POPUP: | ||
popup_free(view->viewData); | ||
break; | ||
} | ||
root = root->next; | ||
} | ||
FURI_LOG_I(TAG, "Removing all views from list"); | ||
LinkedListStatus result = removeAllNodes(&(*context)->activeViews); | ||
if(result != LIST_OK) { | ||
return APP_CONTEXT_UNKNOWN_ERROR; | ||
} | ||
return APP_CONTEXT_OK; | ||
} | ||
|
||
AppContextStatus freeAppContext(struct AppContext_t** context) { | ||
FURI_LOG_I(TAG, "Ensuring views are free'd"); | ||
AppContextStatus result = freeAppContextViews(context); | ||
if(result != APP_CONTEXT_OK) { | ||
return APP_CONTEXT_CANT_FREE_VIEWS; | ||
} | ||
FURI_LOG_I(TAG, "Freeing the scene"); | ||
scene_manager_free((*context)->scene_manager); | ||
FURI_LOG_I(TAG, "Freeing the view dispatcher"); | ||
view_dispatcher_free((*context)->view_dispatcher); | ||
FURI_LOG_I(TAG, "Freeing the app context"); | ||
free((*context)); | ||
return APP_CONTEXT_OK; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
#ifndef _APP_CONTEXT_H_ | ||
|
||
#define _APP_CONTEXT_H_ | ||
|
||
#include <gui/view_dispatcher.h> | ||
#include <gui/scene_manager.h> | ||
|
||
#include "utils/linked_list.h" | ||
|
||
typedef enum { | ||
MENU, | ||
POPUP, | ||
} ViewType; | ||
|
||
struct View_t { | ||
ViewType type; | ||
int viewId; | ||
void* viewData; | ||
}; | ||
|
||
typedef enum { | ||
APP_CONTEXT_OK = 0, | ||
APP_CONTEXT_CANT_ALLOCATE = -1, | ||
APP_CONTEXT_CANT_FREE_VIEWS = -2, | ||
APP_CONTEXT_UNKNOWN_ERROR = -3, | ||
} AppContextStatus; | ||
|
||
struct AppContext_t { | ||
SceneManager* scene_manager; | ||
ViewDispatcher* view_dispatcher; | ||
struct ListNode_t* activeViews; | ||
}; | ||
|
||
/// @brief Creates an app context with the desired scene handlers. | ||
/// @param context The app context to populate. Will be passed through to the supplied scene handlers. | ||
/// @param sceneManagerHandlers The scene handlers to use for each scene in your app. | ||
/// @return Returns APP_CONTEXT_OK on success, APP_CONTEXT_CANT_ALLOCATE if there is an error. | ||
AppContextStatus initializeAppContext( | ||
struct AppContext_t** context, | ||
const SceneManagerHandlers* sceneManagerHandlers); | ||
|
||
/// @brief Frees and removes all views attached to the app context. | ||
/// @param context The app context to remove all of the views from. | ||
/// @return Returns APP_CONTEXT_OK on success. Should not error. | ||
AppContextStatus freeAppContextViews(struct AppContext_t** context); | ||
|
||
/// @brief Frees the app context entirely, cleaning it up from usage. | ||
/// @param context The app context to clean up. | ||
/// @return Returns APP_CONTEXT_OK on success. Should not error. | ||
AppContextStatus freeAppContext(struct AppContext_t** context); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
#include <gui/modules/menu.h> | ||
#include <gui/modules/popup.h> | ||
|
||
#include "main_menu.h" | ||
#include "../app_context.h" | ||
#include "../tone_gen.h" | ||
#include "../utils/linked_list.h" | ||
|
||
/** indices for menu items */ | ||
typedef enum { | ||
ToneGenAppMenuSelection_Play, | ||
ToneGenAppMenuSelection_Adjust | ||
} ToneGenAppMenuSelection; | ||
|
||
/** main menu callback - sends a custom event to the scene manager based on the menu selection */ | ||
void menu_callback_main_menu(void* context, uint32_t index) { | ||
FURI_LOG_I(TAG, "menu_callback_main_menu"); | ||
UNUSED(context); | ||
// struct AppContext_t* app = context; | ||
switch(index) { | ||
case ToneGenAppMenuSelection_Play: | ||
FURI_LOG_I(TAG, "selection one"); | ||
// scene_manager_handle_custom_event(app->scene_manager, ToneGenAppEvent_StartPlayback); | ||
break; | ||
case ToneGenAppMenuSelection_Adjust: | ||
FURI_LOG_I(TAG, "selection two"); | ||
// scene_manager_handle_custom_event(app->scene_manager, ToneGenAppEvent_AdjustTone); | ||
break; | ||
} | ||
} | ||
|
||
/** resets the menu, gives it content, callbacks and selection enums */ | ||
void scene_on_enter_main_menu(void* context) { | ||
FURI_LOG_I(TAG, "scene_on_enter_main_menu"); | ||
struct AppContext_t* app = (struct AppContext_t*)context; | ||
// Setup our menu | ||
FURI_LOG_D(TAG, "Adding view menu"); | ||
struct View_t* menuView = malloc(sizeof(struct View_t)); | ||
menuView->viewData = menu_alloc(); | ||
menuView->viewId = ToneGenAppView_Menu; | ||
menuView->type = MENU; | ||
view_dispatcher_add_view( | ||
app->view_dispatcher, ToneGenAppView_Menu, menu_get_view(menuView->viewData)); | ||
|
||
// Set the currently active view | ||
addNode(&app->activeViews, menuView); | ||
menu_reset(menuView->viewData); | ||
|
||
// NB. icons are specified as NULL below, because: | ||
// * icons are _always_ animated by the menu | ||
// * the icons provided (&I_one, &I_two) are generated by the build process | ||
// * these icons do not have a framerate (resulting in a division by zero) | ||
menu_add_item( | ||
menuView->viewData, | ||
"Play Tone", | ||
NULL, | ||
ToneGenAppMenuSelection_Play, | ||
menu_callback_main_menu, | ||
app); | ||
menu_add_item( | ||
menuView->viewData, | ||
"Adjust Tone", | ||
NULL, | ||
ToneGenAppMenuSelection_Adjust, | ||
menu_callback_main_menu, | ||
app); | ||
view_dispatcher_switch_to_view(app->view_dispatcher, ToneGenAppView_Menu); | ||
} | ||
|
||
/** main menu event handler - switches scene based on the event */ | ||
bool scene_on_event_main_menu(void* context, SceneManagerEvent event) { | ||
FURI_LOG_I(TAG, "scene_on_event_main_menu"); | ||
UNUSED(context); | ||
// struct AppContext_t* app = context; | ||
bool consumed = false; | ||
switch(event.type) { | ||
case SceneManagerEventTypeCustom: | ||
// switch(event.event) { | ||
// case ToneGenAppEvent_StartPlayback: | ||
// scene_manager_next_scene(app->scene_manager, ToneGenAppScene_Playback); | ||
// consumed = true; | ||
// break; | ||
// case ToneGenAppEvent_AdjustTone: | ||
// scene_manager_next_scene(app->scene_manager, ToneGenAppScene_AdjustTone); | ||
// consumed = true; | ||
// break; | ||
// } | ||
break; | ||
default: // eg. SceneManagerEventTypeBack, SceneManagerEventTypeTick | ||
consumed = false; | ||
break; | ||
} | ||
return consumed; | ||
} | ||
|
||
void scene_on_exit_main_menu(void* context) { | ||
FURI_LOG_I(TAG, "scene_on_exit_main_menu"); | ||
struct AppContext_t* app = context; | ||
freeAppContextViews(&app); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#ifndef _MAIN_MENU_H_ | ||
|
||
#define _MAIN_MENU_H_ | ||
|
||
#include <gui/scene_manager.h> | ||
|
||
void scene_on_enter_main_menu(void* context); | ||
bool scene_on_event_main_menu(void* context, SceneManagerEvent event); | ||
void scene_on_exit_main_menu(void* context); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
#include <gui/modules/menu.h> | ||
|
||
/* generated by fbt from .png files in images folder */ | ||
#include <tone_gen_icons.h> | ||
|
||
#include "app_context.h" | ||
#include "tone_gen.h" | ||
|
||
#include "menus/main_menu.h" | ||
|
||
/** collection of all scene on_enter handlers - in the same order as their enum */ | ||
void (*const scene_on_enter_handlers[])(void*) = { | ||
scene_on_enter_main_menu, | ||
}; | ||
|
||
/** collection of all scene on event handlers - in the same order as their enum */ | ||
bool (*const scene_on_event_handlers[])(void*, SceneManagerEvent) = { | ||
scene_on_event_main_menu, | ||
}; | ||
|
||
/** collection of all scene on exit handlers - in the same order as their enum */ | ||
void (*const scene_on_exit_handlers[])(void*) = { | ||
scene_on_exit_main_menu, | ||
}; | ||
|
||
const SceneManagerHandlers scene_event_handlers = { | ||
.on_enter_handlers = scene_on_enter_handlers, | ||
.on_event_handlers = scene_on_event_handlers, | ||
.on_exit_handlers = scene_on_exit_handlers, | ||
.scene_num = ToneGenAppScene_count}; | ||
|
||
int32_t tone_gen_app(void* p) { | ||
UNUSED(p); | ||
|
||
FURI_LOG_I(TAG, "Tone gen app starting..."); | ||
|
||
struct AppContext_t* appContext; | ||
AppContextStatus result = initializeAppContext(&appContext, &scene_event_handlers); | ||
|
||
if(result == APP_CONTEXT_OK) { | ||
// set the scene and launch the main loop | ||
FURI_LOG_D(TAG, "Setting the scene"); | ||
Gui* gui = furi_record_open(RECORD_GUI); | ||
view_dispatcher_attach_to_gui( | ||
appContext->view_dispatcher, gui, ViewDispatcherTypeFullscreen); | ||
scene_manager_next_scene(appContext->scene_manager, ToneGenAppScene_MainMenu); | ||
FURI_LOG_D(TAG, "Starting the view dispatcher"); | ||
view_dispatcher_run(appContext->view_dispatcher); | ||
|
||
// free all memory | ||
FURI_LOG_D(TAG, "Ending the app"); | ||
furi_record_close(RECORD_GUI); | ||
freeAppContext(&appContext); | ||
return 0; | ||
} | ||
return -1; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#ifndef _TONE_GEN_H_ | ||
|
||
#define _TONE_GEN_H_ | ||
|
||
#define TAG "tone-gen" | ||
|
||
#include <furi.h> | ||
#include <music_worker/music_worker.h> | ||
|
||
// ids for all scenes used by the app | ||
typedef enum { ToneGenAppScene_MainMenu, ToneGenAppScene_count } ToneGenAppScene; | ||
|
||
// ids for the 2 types of view used by the app | ||
typedef enum { ToneGenAppView_Menu, ToneGenAppView_Popup } ToneGenAppView; | ||
|
||
#endif |
Oops, something went wrong.