| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307 |
- #include <furi.h>
- #include <string.h>
- #include <storage/storage.h>
- #include <toolbox/stream/stream.h>
- #include <toolbox/stream/file_stream.h>
- #include <nfc_playlist_worker.h>
- #include <gui/gui.h>
- #include <gui/view_dispatcher.h>
- #include <gui/scene_manager.h>
- #include <gui/modules/menu.h>
- #include <gui/modules/submenu.h>
- #include <gui/modules/popup.h>
- // Define log tag
- #define TAG "NfcPlaylist"
- /** ids for all scenes used by the app */
- typedef enum {
- NfcPlaylistScene_MainMenu,
- NfcPlaylistScene_FirstPopup,
- NfcPlaylistScene_count
- } NfcPlaylistScene;
- /** ids for the 2 types of view used by the app */
- typedef enum { NfcPlaylistView_Menu, NfcPlaylistView_Popup } NfcPlaylistView;
- /** the app context struct */
- typedef struct {
- SceneManager* scene_manager;
- ViewDispatcher* view_dispatcher;
- Submenu* menu;
- Popup* popup;
- NfcPlaylistWorker* nfc_worker;
- int emulate_timeout;
- bool cancel_emulate;
- } NfcPlaylist;
- /** all custom events */
- typedef enum { NfcPlaylistEvent_ShowPopupOne } NfcPlaylistEvent;
- /* main menu scene */
- /** indices for menu items */
- typedef enum { NfcPlaylistMenuSelection_One } NfcPlaylistMenuSelection;
- /** main menu callback - sends a custom event to the scene manager based on the menu selection */
- void nfc_playlist_menu_callback_main_menu(void* context, uint32_t index) {
- FURI_LOG_T(TAG, "nfc_playlist_menu_callback_main_menu");
- NfcPlaylist* app = context;
- switch(index) {
- case NfcPlaylistMenuSelection_One:
- scene_manager_handle_custom_event(app->scene_manager, NfcPlaylistEvent_ShowPopupOne);
- break;
- }
- }
- /** resets the menu, gives it content, callbacks and selection enums */
- void nfc_playlist_scene_on_enter_main_menu(void* context) {
- FURI_LOG_T(TAG, "nfc_playlist_scene_on_enter_main_menu");
- NfcPlaylist* app = context;
- submenu_reset(app->menu);
- submenu_set_header(app->menu, "NFC Playlist");
- submenu_add_item(
- app->menu,
- "Start",
- NfcPlaylistMenuSelection_One,
- nfc_playlist_menu_callback_main_menu,
- app);
- view_dispatcher_switch_to_view(app->view_dispatcher, NfcPlaylistView_Menu);
- }
- /** main menu event handler - switches scene based on the event */
- bool nfc_playlist_scene_on_event_main_menu(void* context, SceneManagerEvent event) {
- FURI_LOG_T(TAG, "nfc_playlist_scene_on_event_main_menu");
- NfcPlaylist* app = context;
- bool consumed = false;
- switch(event.type) {
- case SceneManagerEventTypeCustom:
- switch(event.event) {
- case NfcPlaylistEvent_ShowPopupOne:
- scene_manager_next_scene(app->scene_manager, NfcPlaylistScene_FirstPopup);
- consumed = true;
- break;
- }
- break;
- default: // eg. SceneManagerEventTypeBack, SceneManagerEventTypeTick
- consumed = false;
- break;
- }
- return consumed;
- }
- void nfc_playlist_scene_on_exit_main_menu(void* context) {
- FURI_LOG_T(TAG, "nfc_playlist_scene_on_exit_main_menu");
- NfcPlaylist* app = context;
- submenu_reset(app->menu);
- }
- /* popup 1 scene */
- void nfc_playlist_scene_on_enter_popup_emulating(void* context) {
- FURI_LOG_T(TAG, "nfc_playlist_scene_on_enter_popup_emulating");
- NfcPlaylist* app = context;
- // open/alloc resources
- Storage* storage = furi_record_open(RECORD_STORAGE);
- Stream* stream = file_stream_alloc(storage);
- FuriString* line = furi_string_alloc();
- app->nfc_worker = nfc_playlist_worker_alloc();
- // Read file
- if(file_stream_open(stream, APP_DATA_PATH("playlist.txt"), FSAM_READ, FSOM_OPEN_EXISTING)) {
- popup_reset(app->popup);
- popup_set_context(app->popup, app);
- popup_set_header(app->popup, "Emulating", 64, 10, AlignCenter, AlignTop);
- view_dispatcher_switch_to_view(app->view_dispatcher, NfcPlaylistView_Popup);
- // read the file line by line and print the text
- while(stream_read_line(stream, line) && !app->cancel_emulate) {
- char* file_path = (char*)furi_string_get_cstr(line);
- char* file_name = strrchr(file_path, (int)"/");
- popup_set_text(app->popup, file_name, 64, 30, AlignCenter, AlignTop);
- nfc_playlist_worker_set_nfc_data(app->nfc_worker, file_path);
- nfc_playlist_worker_start(app->nfc_worker);
- int time_counter_ms = app->emulate_timeout;
- while(nfc_playlist_worker_is_emulating(app->nfc_worker)) {
- furi_delay_ms(50);
- time_counter_ms -= 50;
- if (time_counter_ms <= 0) {
- break;
- }
- }
- if (nfc_playlist_worker_is_emulating(app->nfc_worker)) {
- nfc_playlist_worker_stop(app->nfc_worker);
- }
- furi_string_reset(line);
- }
- } else {
- FURI_LOG_E(TAG, "Failed to open file");
- }
- // Free/close resources
- furi_string_free(line);
- file_stream_close(stream);
- stream_free(stream);
- nfc_playlist_worker_free(app->nfc_worker);
- app->nfc_worker = NULL;
- app->cancel_emulate = false;
- // Close storage
- furi_record_close(RECORD_STORAGE);
- popup_reset(app->popup);
- scene_manager_previous_scene(app->scene_manager);
- }
- bool nfc_playlist_scene_on_event_popup_emulating(void* context, SceneManagerEvent event) {
- FURI_LOG_T(TAG, "nfc_playlist_scene_on_event_popup_emulating");
- UNUSED(context);
- UNUSED(event);
- return false;
- }
- void nfc_playlist_scene_on_exit_popup_emulating(void* context) {
- FURI_LOG_T(TAG, "nfc_playlist_scene_on_exit_popup_emulating");
- NfcPlaylist* app = context;
- if (nfc_playlist_worker_is_emulating(app->nfc_worker)) {
- nfc_playlist_worker_stop(app->nfc_worker);
- app->cancel_emulate = true;
- }
- popup_reset(app->popup);
- }
- /** collection of all scene on_enter handlers - in the same order as their enum */
- void (*const nfc_playlist_scene_on_enter_handlers[])(void*) = {
- nfc_playlist_scene_on_enter_main_menu,
- nfc_playlist_scene_on_enter_popup_emulating};
- /** collection of all scene on event handlers - in the same order as their enum */
- bool (*const nfc_playlist_scene_on_event_handlers[])(void*, SceneManagerEvent) = {
- nfc_playlist_scene_on_event_main_menu,
- nfc_playlist_scene_on_event_popup_emulating};
- /** collection of all scene on exit handlers - in the same order as their enum */
- void (*const nfc_playlist_scene_on_exit_handlers[])(void*) = {
- nfc_playlist_scene_on_exit_main_menu,
- nfc_playlist_scene_on_exit_popup_emulating};
- /** collection of all on_enter, on_event, on_exit handlers */
- const SceneManagerHandlers nfc_playlist_scene_event_handlers = {
- .on_enter_handlers = nfc_playlist_scene_on_enter_handlers,
- .on_event_handlers = nfc_playlist_scene_on_event_handlers,
- .on_exit_handlers = nfc_playlist_scene_on_exit_handlers,
- .scene_num = NfcPlaylistScene_count};
- /** custom event handler - passes the event to the scene manager */
- bool nfc_playlist_scene_manager_custom_event_callback(void* context, uint32_t custom_event) {
- FURI_LOG_T(TAG, "nfc_playlist_scene_manager_custom_event_callback");
- furi_assert(context);
- NfcPlaylist* app = context;
- return scene_manager_handle_custom_event(app->scene_manager, custom_event);
- }
- /** navigation event handler - passes the event to the scene manager */
- bool nfc_playlist_scene_manager_navigation_event_callback(void* context) {
- FURI_LOG_T(TAG, "nfc_playlist_scene_manager_navigation_event_callback");
- furi_assert(context);
- NfcPlaylist* app = context;
- return scene_manager_handle_back_event(app->scene_manager);
- }
- /** initialise the scene manager with all handlers */
- void nfc_playlist_scene_manager_init(NfcPlaylist* app) {
- FURI_LOG_T(TAG, "nfc_playlist_scene_manager_init");
- app->scene_manager = scene_manager_alloc(&nfc_playlist_scene_event_handlers, app);
- }
- /** initialise the views, and initialise the view dispatcher with all views */
- void nfc_playlist_view_dispatcher_init(NfcPlaylist* app) {
- FURI_LOG_T(TAG, "nfc_playlist_view_dispatcher_init");
- app->view_dispatcher = view_dispatcher_alloc();
- view_dispatcher_enable_queue(app->view_dispatcher);
- // allocate each view
- FURI_LOG_D(TAG, "nfc_playlist_view_dispatcher_init allocating views");
- app->menu = submenu_alloc();
- app->popup = popup_alloc();
- app->emulate_timeout = 2000;
- app->cancel_emulate = false;
- // assign callback that pass events from views to the scene manager
- FURI_LOG_D(TAG, "nfc_playlist_view_dispatcher_init setting callbacks");
- view_dispatcher_set_event_callback_context(app->view_dispatcher, app);
- view_dispatcher_set_custom_event_callback(
- app->view_dispatcher, nfc_playlist_scene_manager_custom_event_callback);
- view_dispatcher_set_navigation_event_callback(
- app->view_dispatcher, nfc_playlist_scene_manager_navigation_event_callback);
- // add views to the dispatcher, indexed by their enum value
- FURI_LOG_D(TAG, "nfc_playlist_view_dispatcher_init adding view menu");
- view_dispatcher_add_view(app->view_dispatcher, NfcPlaylistView_Menu, submenu_get_view(app->menu));
- FURI_LOG_D(TAG, "nfc_playlist_view_dispatcher_init adding view popup");
- view_dispatcher_add_view(app->view_dispatcher, NfcPlaylistView_Popup, popup_get_view(app->popup));
- }
- /** initialise app data, scene manager, and view dispatcher */
- NfcPlaylist* nfc_playlist_init() {
- FURI_LOG_T(TAG, "nfc_playlist_init");
- NfcPlaylist* app = malloc(sizeof(NfcPlaylist));
- nfc_playlist_scene_manager_init(app);
- nfc_playlist_view_dispatcher_init(app);
- return app;
- }
- /** free all app data, scene manager, and view dispatcher */
- void nfc_playlist_free(NfcPlaylist* app) {
- FURI_LOG_T(TAG, "nfc_playlist_free");
- scene_manager_free(app->scene_manager);
- view_dispatcher_remove_view(app->view_dispatcher, NfcPlaylistView_Menu);
- view_dispatcher_remove_view(app->view_dispatcher, NfcPlaylistView_Popup);
- view_dispatcher_free(app->view_dispatcher);
- submenu_free(app->menu);
- popup_free(app->popup);
- free(app);
- }
- /** go to trace log level in the dev environment */
- void nfc_playlist_set_log_level() {
- #ifdef FURI_DEBUG
- furi_log_set_level(FuriLogLevelTrace);
- #else
- furi_log_set_level(FuriLogLevelInfo);
- #endif
- }
- // Application entry point
- int32_t nfc_playlist_main(void* p) {
- // Mark argument as unused
- UNUSED(p);
- nfc_playlist_set_log_level();
- // create the app context struct, scene manager, and view dispatcher
- FURI_LOG_I(TAG, "NFC PLaylist starting...");
- NfcPlaylist* app = nfc_playlist_init();
- // set the scene and launch the main loop
- Gui* gui = furi_record_open(RECORD_GUI);
- view_dispatcher_attach_to_gui(app->view_dispatcher, gui, ViewDispatcherTypeFullscreen);
- scene_manager_next_scene(app->scene_manager, NfcPlaylistScene_MainMenu);
- FURI_LOG_D(TAG, "Starting dispatcher...");
- view_dispatcher_run(app->view_dispatcher);
- // free all memory
- FURI_LOG_I(TAG, "NFC PLaylist finishing...");
- furi_record_close(RECORD_GUI);
- nfc_playlist_free(app);
- return 0;
- }
|