diff --git a/README.md b/README.md index 02bd4c4ef10..e72310f8802 100644 --- a/README.md +++ b/README.md @@ -20,6 +20,7 @@ As i know these firmwares are supported and working if you know any more please - Emulate time (How long the NFC card will be emulated for) - Delay time (How long the gap between the cards will be) - LED indicator (Whether or not the LED's will be on) +- Skip errors (Makes it so you can make the emulation screen hide errors and skip delays between errors and emulation) - Reset settings (Puts all the settings back to the defaults) ## Playlist editor: - Create PLaylist (Creates a new playlist with the given name) diff --git a/application.fam b/application.fam index f969f9dc50d..1d0a313387b 100644 --- a/application.fam +++ b/application.fam @@ -8,7 +8,7 @@ App( fap_category="NFC", fap_author="@acegoal07", fap_weburl="https://github.com/acegoal07/FlipperZero_NFC_Playlist/tree/main", - fap_version="1.7", + fap_version="1.8", fap_icon="assets/icon.png", fap_private_libs=[ Lib( diff --git a/nfc_playlist.c b/nfc_playlist.c index 33a1b020eab..6f34b1e176f 100644 --- a/nfc_playlist.c +++ b/nfc_playlist.c @@ -28,6 +28,7 @@ static NfcPlaylist* nfc_playlist_alloc() { nfc_playlist->settings.emulate_timeout = default_emulate_timeout; nfc_playlist->settings.emulate_delay = default_emulate_delay; nfc_playlist->settings.emulate_led_indicator = default_emulate_led_indicator; + nfc_playlist->settings.skip_error = default_skip_error; nfc_playlist->notification = furi_record_open(RECORD_NOTIFICATION); nfc_playlist->file_browser = file_browser_alloc(nfc_playlist->file_browser_output); diff --git a/nfc_playlist.h b/nfc_playlist.h index 23aa1033797..c4b35cd866c 100644 --- a/nfc_playlist.h +++ b/nfc_playlist.h @@ -35,7 +35,7 @@ typedef enum { NfcPlaylistView_VariableItemList, NfcPlaylistView_FileBrowser, NfcPlaylistView_TextInput -} NfcPlaylistView; +} NfcPlaylistViews; typedef struct { FuriString* file_path; @@ -43,6 +43,7 @@ typedef struct { uint8_t emulate_timeout; uint8_t emulate_delay; bool emulate_led_indicator; + bool skip_error; } NfcPlaylistSettings; typedef struct { @@ -58,6 +59,7 @@ typedef struct { char* text_input_output; NotificationApp* notification; FuriThread* thread; + FuriString* temp_furi_string; NfcPlaylistWorker* nfc_playlist_worker; NfcPlaylistSettings settings; } NfcPlaylist; @@ -67,6 +69,7 @@ static const int default_emulate_timeout = 4; static const int options_emulate_delay[] = {0, 1, 2, 3, 4, 5, 6}; static const int default_emulate_delay = 0; static const bool default_emulate_led_indicator = true; +static const bool default_skip_error = false; #define PLAYLIST_LOCATION "/ext/apps_data/nfc_playlist/" #define PLAYLIST_DIR "/ext/apps_data/nfc_playlist" diff --git a/scenes/nfc_playlist_scene_emulation.c b/scenes/nfc_playlist_scene_emulation.c index e7ba6c6821f..850473405bf 100644 --- a/scenes/nfc_playlist_scene_emulation.c +++ b/scenes/nfc_playlist_scene_emulation.c @@ -13,10 +13,11 @@ int32_t nfc_playlist_emulation_task(void* context) { Storage* storage = furi_record_open(RECORD_STORAGE); Stream* stream = file_stream_alloc(storage); + bool skip_delay = false; popup_reset(nfc_playlist->popup); popup_set_context(nfc_playlist->popup, nfc_playlist); - + view_dispatcher_switch_to_view(nfc_playlist->view_dispatcher, NfcPlaylistView_Popup); if (file_stream_open(stream, furi_string_get_cstr(nfc_playlist->settings.file_path), FSAM_READ, FSOM_OPEN_EXISTING)) { @@ -31,19 +32,20 @@ int32_t nfc_playlist_emulation_task(void* context) { char* file_path = (char*)furi_string_get_cstr(line); - if(strlen(file_path) <= 1) {continue;} + if (strlen(file_path) <= 1) {continue;} - if(nfc_playlist->settings.emulate_delay > 0 && file_position != 0) { + if (nfc_playlist->settings.emulate_delay > 0 && file_position != 0 && !skip_delay) { popup_set_header(nfc_playlist->popup, "Delaying", 64, 10, AlignCenter, AlignTop); start_blink(nfc_playlist, NfcPlaylistLedState_Error); int time_counter_delay_ms = (options_emulate_delay[nfc_playlist->settings.emulate_delay]*1000); - do { + while(time_counter_delay_ms > 0 && EmulationState == NfcPlaylistEmulationState_Emulating) { furi_string_printf(tmp_counter_str, "%ds", (time_counter_delay_ms/1000)); popup_set_text(nfc_playlist->popup, furi_string_get_cstr(tmp_counter_str), 64, 50, AlignCenter, AlignTop); furi_delay_ms(50); time_counter_delay_ms -= 50; - } while(time_counter_delay_ms > 0 && EmulationState == NfcPlaylistEmulationState_Emulating); + }; } else if (nfc_playlist->settings.emulate_delay > 0) { + skip_delay = false; file_position++; } @@ -53,38 +55,46 @@ int32_t nfc_playlist_emulation_task(void* context) { char const* file_ext = &strrchr(file_path, '.')[1]; int time_counter_ms = (options_emulate_timeout[nfc_playlist->settings.emulate_timeout]*1000); - if(storage_file_exists(storage, file_path) == false) { - furi_string_printf(tmp_header_str, "ERROR not found:\n%s", file_name); + if(!strcasestr(file_ext, "nfc")) { + if(nfc_playlist->settings.skip_error) { + skip_delay = true; + continue; + } + furi_string_printf(tmp_header_str, "ERROR invalid file:\n%s", file_name); popup_set_header(nfc_playlist->popup, furi_string_get_cstr(tmp_header_str), 64, 10, AlignCenter, AlignTop); start_blink(nfc_playlist, NfcPlaylistLedState_Error); - do { + while(time_counter_ms > 0 && EmulationState == NfcPlaylistEmulationState_Emulating) { furi_string_printf(tmp_counter_str, "%ds", (time_counter_ms/1000)); popup_set_text(nfc_playlist->popup, furi_string_get_cstr(tmp_counter_str), 64, 50, AlignCenter, AlignTop); furi_delay_ms(50); time_counter_ms -= 50; - } while(time_counter_ms > 0 && EmulationState == NfcPlaylistEmulationState_Emulating); - } else if (strcasestr(file_ext, "nfc") == NULL) { - furi_string_printf(tmp_header_str, "ERROR invalid file:\n%s", file_name); + }; + } else if(!storage_file_exists(storage, file_path)) { + if(nfc_playlist->settings.skip_error) { + skip_delay = true; + continue; + } + furi_string_printf(tmp_header_str, "ERROR not found:\n%s", file_name); popup_set_header(nfc_playlist->popup, furi_string_get_cstr(tmp_header_str), 64, 10, AlignCenter, AlignTop); start_blink(nfc_playlist, NfcPlaylistLedState_Error); - do { + while(time_counter_ms > 0 && EmulationState == NfcPlaylistEmulationState_Emulating) { furi_string_printf(tmp_counter_str, "%ds", (time_counter_ms/1000)); popup_set_text(nfc_playlist->popup, furi_string_get_cstr(tmp_counter_str), 64, 50, AlignCenter, AlignTop); furi_delay_ms(50); time_counter_ms -= 50; - } while(time_counter_ms > 0 && EmulationState == NfcPlaylistEmulationState_Emulating); + }; } else { furi_string_printf(tmp_header_str, "Emulating:\n%s", file_name); popup_set_header(nfc_playlist->popup, furi_string_get_cstr(tmp_header_str), 64, 10, AlignCenter, AlignTop); nfc_playlist_worker_set_nfc_data(nfc_playlist->nfc_playlist_worker, file_path); nfc_playlist_worker_start(nfc_playlist->nfc_playlist_worker); start_blink(nfc_playlist, NfcPlaylistLedState_Normal); - do { + while(nfc_playlist_worker_is_emulating(nfc_playlist->nfc_playlist_worker) && time_counter_ms > 0 && EmulationState == NfcPlaylistEmulationState_Emulating) { furi_string_printf(tmp_counter_str, "%ds", (time_counter_ms/1000)); popup_set_text(nfc_playlist->popup, furi_string_get_cstr(tmp_counter_str), 64, 50, AlignCenter, AlignTop); furi_delay_ms(50); time_counter_ms -= 50; - } while(nfc_playlist_worker_is_emulating(nfc_playlist->nfc_playlist_worker) && time_counter_ms > 0 && EmulationState == NfcPlaylistEmulationState_Emulating); + }; nfc_playlist_worker_stop(nfc_playlist->nfc_playlist_worker); nfc_playlist_worker_clear_nfc_data(nfc_playlist->nfc_playlist_worker); } @@ -98,7 +108,6 @@ int32_t nfc_playlist_emulation_task(void* context) { furi_string_free(line); furi_string_free(tmp_header_str); furi_string_free(tmp_counter_str); - } else { popup_set_header(nfc_playlist->popup, "Failed to open playlist", 64, 10, AlignCenter, AlignTop); popup_set_text(nfc_playlist->popup, "Press back", 64, 50, AlignCenter, AlignTop); diff --git a/scenes/nfc_playlist_scene_file_rename.c b/scenes/nfc_playlist_scene_file_rename.c index 399971c16b7..ddb5d21cee6 100644 --- a/scenes/nfc_playlist_scene_file_rename.c +++ b/scenes/nfc_playlist_scene_file_rename.c @@ -9,7 +9,7 @@ void nfc_playlist_file_rename_menu_callback(void* context) { FuriString* tmp_old_file_path = furi_string_alloc_set_str(old_file_path); furi_string_replace(tmp_old_file_path, old_file_name, ""); - + FuriString* tmp_new_file_path = furi_string_alloc(); furi_string_printf(tmp_new_file_path, "%s%s.txt", furi_string_get_cstr(tmp_old_file_path), nfc_playlist->text_input_output); @@ -37,7 +37,7 @@ void nfc_playlist_file_rename_scene_on_enter(void* context) { text_input_set_header_text(nfc_playlist->text_input, "Enter new file name"); text_input_set_minimum_length(nfc_playlist->text_input, 1); text_input_set_result_callback(nfc_playlist->text_input, nfc_playlist_file_rename_menu_callback, nfc_playlist, nfc_playlist->text_input_output, 50, false); - + view_dispatcher_switch_to_view(nfc_playlist->view_dispatcher, NfcPlaylistView_TextInput); } diff --git a/scenes/nfc_playlist_scene_main_menu.c b/scenes/nfc_playlist_scene_main_menu.c index 7c983a10655..9a18dba258a 100644 --- a/scenes/nfc_playlist_scene_main_menu.c +++ b/scenes/nfc_playlist_scene_main_menu.c @@ -61,7 +61,7 @@ void nfc_playlist_main_menu_scene_on_enter(void* context) { NfcPlaylistMenuSelection_Settings, nfc_playlist_main_menu_menu_callback, nfc_playlist); - + view_dispatcher_switch_to_view(nfc_playlist->view_dispatcher, NfcPlaylistView_Submenu); } diff --git a/scenes/nfc_playlist_scene_name_new_file.c b/scenes/nfc_playlist_scene_name_new_file.c index 9da0a68bb0e..52241d18efe 100644 --- a/scenes/nfc_playlist_scene_name_new_file.c +++ b/scenes/nfc_playlist_scene_name_new_file.c @@ -12,7 +12,7 @@ void nfc_playlist_name_new_file_menu_callback(void* context) { storage_file_close(file); furi_string_swap(nfc_playlist->settings.file_path, file_name); } - + storage_file_free(file); furi_string_free(file_name); furi_record_close(RECORD_STORAGE); @@ -25,7 +25,7 @@ void nfc_playlist_name_new_file_scene_on_enter(void* context) { text_input_set_header_text(nfc_playlist->text_input, "Enter file name"); text_input_set_minimum_length(nfc_playlist->text_input, 1); text_input_set_result_callback(nfc_playlist->text_input, nfc_playlist_name_new_file_menu_callback, nfc_playlist, nfc_playlist->text_input_output, 50, true); - + view_dispatcher_switch_to_view(nfc_playlist->view_dispatcher, NfcPlaylistView_TextInput); } diff --git a/scenes/nfc_playlist_scene_nfc_select.c b/scenes/nfc_playlist_scene_nfc_select.c index e6ade324d10..9a24f6e23f7 100644 --- a/scenes/nfc_playlist_scene_nfc_select.c +++ b/scenes/nfc_playlist_scene_nfc_select.c @@ -5,7 +5,7 @@ void nfc_playlist_nfc_select_menu_callback(void* context) { Storage* storage = furi_record_open(RECORD_STORAGE); File* file = storage_file_alloc(storage); - + if (storage_file_open(file, furi_string_get_cstr(nfc_playlist->settings.file_path), FSAM_READ_WRITE, FSOM_OPEN_EXISTING)) { uint8_t buffer[PLAYLIST_VIEW_MAX_SIZE]; uint16_t read_count = storage_file_read(file, buffer, PLAYLIST_VIEW_MAX_SIZE); @@ -30,7 +30,7 @@ void nfc_playlist_nfc_select_menu_callback(void* context) { storage_file_free(file); furi_record_close(RECORD_STORAGE); furi_string_reset(nfc_playlist->file_browser_output); - + scene_manager_previous_scene(nfc_playlist->scene_manager); } @@ -48,7 +48,7 @@ void nfc_playlist_nfc_select_scene_on_enter(void* context) { FuriString* tmp_str = furi_string_alloc_set_str("/ext/nfc/"); file_browser_start(nfc_playlist->file_browser, tmp_str); furi_string_free(tmp_str); - + view_dispatcher_switch_to_view(nfc_playlist->view_dispatcher, NfcPlaylistView_FileBrowser); } diff --git a/scenes/nfc_playlist_scene_playlist_select.c b/scenes/nfc_playlist_scene_playlist_select.c index 4e9eb59a26a..b09b8e856f6 100644 --- a/scenes/nfc_playlist_scene_playlist_select.c +++ b/scenes/nfc_playlist_scene_playlist_select.c @@ -21,7 +21,7 @@ void nfc_playlist_playlist_select_scene_on_enter(void* context) { FuriString* tmp_str = furi_string_alloc_set_str(PLAYLIST_LOCATION); file_browser_start(nfc_playlist->file_browser, tmp_str); furi_string_free(tmp_str); - + view_dispatcher_switch_to_view(nfc_playlist->view_dispatcher, NfcPlaylistView_FileBrowser); } diff --git a/scenes/nfc_playlist_scene_settings.c b/scenes/nfc_playlist_scene_settings.c index ad01d283fb8..533a2f2e5be 100644 --- a/scenes/nfc_playlist_scene_settings.c +++ b/scenes/nfc_playlist_scene_settings.c @@ -4,6 +4,7 @@ typedef enum { NfcPlaylistSettings_Timeout, NfcPlaylistSettings_Delay, NfcPlaylistSettings_LedIndicator, + NfcPlaylistSettings_SkipError, NfcPlaylistSettings_Reset } NfcPlaylistSettingsMenuSelection; @@ -33,6 +34,10 @@ void nfc_playlist_settings_options_change_callback(VariableItem* item) { nfc_playlist->settings.emulate_led_indicator = option_value_index; variable_item_set_current_value_text(item, nfc_playlist->settings.emulate_led_indicator ? "ON" : "OFF"); break; + case NfcPlaylistSettings_SkipError: + nfc_playlist->settings.skip_error = option_value_index; + variable_item_set_current_value_text(item, nfc_playlist->settings.skip_error ? "ON" : "OFF"); + break; default: break; } @@ -45,34 +50,43 @@ void nfc_playlist_settings_scene_on_enter(void* context) { variable_item_list_set_header(nfc_playlist->variable_item_list, "Settings"); - VariableItem* emulation_timeout_settings = variable_item_list_add( + VariableItem* emulation_timeout_setting = variable_item_list_add( nfc_playlist->variable_item_list, "Emulate time", (sizeof(options_emulate_timeout)/sizeof(options_emulate_timeout[0])), nfc_playlist_settings_options_change_callback, nfc_playlist); - variable_item_set_current_value_index(emulation_timeout_settings, nfc_playlist->settings.emulate_timeout); + variable_item_set_current_value_index(emulation_timeout_setting, nfc_playlist->settings.emulate_timeout); furi_string_printf(tmp_str, "%ds", options_emulate_timeout[nfc_playlist->settings.emulate_timeout]); - variable_item_set_current_value_text(emulation_timeout_settings, furi_string_get_cstr(tmp_str)); + variable_item_set_current_value_text(emulation_timeout_setting, furi_string_get_cstr(tmp_str)); - VariableItem* emulation_delay_settings = variable_item_list_add( + VariableItem* emulation_delay_setting = variable_item_list_add( nfc_playlist->variable_item_list, "Delay time", (sizeof(options_emulate_delay)/sizeof(options_emulate_delay[0])), nfc_playlist_settings_options_change_callback, nfc_playlist); - variable_item_set_current_value_index(emulation_delay_settings, nfc_playlist->settings.emulate_delay); + variable_item_set_current_value_index(emulation_delay_setting, nfc_playlist->settings.emulate_delay); furi_string_printf(tmp_str, "%ds", options_emulate_delay[nfc_playlist->settings.emulate_delay]); - variable_item_set_current_value_text(emulation_delay_settings, furi_string_get_cstr(tmp_str)); + variable_item_set_current_value_text(emulation_delay_setting, furi_string_get_cstr(tmp_str)); - VariableItem* emulation_led_indicator_settings = variable_item_list_add( + VariableItem* emulation_led_indicator_setting = variable_item_list_add( nfc_playlist->variable_item_list, "LED Indicator", 2, nfc_playlist_settings_options_change_callback, nfc_playlist); - variable_item_set_current_value_index(emulation_led_indicator_settings, nfc_playlist->settings.emulate_led_indicator); - variable_item_set_current_value_text(emulation_led_indicator_settings, nfc_playlist->settings.emulate_led_indicator ? "ON" : "OFF"); + variable_item_set_current_value_index(emulation_led_indicator_setting, nfc_playlist->settings.emulate_led_indicator); + variable_item_set_current_value_text(emulation_led_indicator_setting, nfc_playlist->settings.emulate_led_indicator ? "ON" : "OFF"); + + VariableItem* emulation_skip_error_setting = variable_item_list_add( + nfc_playlist->variable_item_list, + "Skip Error", + 2, + nfc_playlist_settings_options_change_callback, + nfc_playlist); + variable_item_set_current_value_index(emulation_skip_error_setting, nfc_playlist->settings.skip_error); + variable_item_set_current_value_text(emulation_skip_error_setting, nfc_playlist->settings.skip_error ? "ON" : "OFF"); variable_item_list_add(nfc_playlist->variable_item_list, "Reset settings", 0, NULL, NULL); @@ -81,7 +95,7 @@ void nfc_playlist_settings_scene_on_enter(void* context) { variable_item_list_set_enter_callback(nfc_playlist->variable_item_list, nfc_playlist_settings_menu_callback, nfc_playlist); furi_string_free(tmp_str); - + view_dispatcher_switch_to_view(nfc_playlist->view_dispatcher, NfcPlaylistView_VariableItemList); } @@ -94,21 +108,26 @@ bool nfc_playlist_settings_scene_on_event(void* context, SceneManagerEvent event FuriString* tmp_str = furi_string_alloc(); nfc_playlist->settings.emulate_timeout = default_emulate_timeout; - VariableItem* emulation_timeout_settings = variable_item_list_get(nfc_playlist->variable_item_list, NfcPlaylistSettings_Timeout); - variable_item_set_current_value_index(emulation_timeout_settings, nfc_playlist->settings.emulate_timeout); + VariableItem* emulation_timeout_setting = variable_item_list_get(nfc_playlist->variable_item_list, NfcPlaylistSettings_Timeout); + variable_item_set_current_value_index(emulation_timeout_setting, nfc_playlist->settings.emulate_timeout); furi_string_printf(tmp_str, "%ds", options_emulate_timeout[nfc_playlist->settings.emulate_timeout]); - variable_item_set_current_value_text(emulation_timeout_settings, furi_string_get_cstr(tmp_str)); + variable_item_set_current_value_text(emulation_timeout_setting, furi_string_get_cstr(tmp_str)); nfc_playlist->settings.emulate_delay = default_emulate_delay; - VariableItem* emulation_delay_settings = variable_item_list_get(nfc_playlist->variable_item_list, NfcPlaylistSettings_Delay); - variable_item_set_current_value_index(emulation_delay_settings, nfc_playlist->settings.emulate_delay); + VariableItem* emulation_delay_setting = variable_item_list_get(nfc_playlist->variable_item_list, NfcPlaylistSettings_Delay); + variable_item_set_current_value_index(emulation_delay_setting, nfc_playlist->settings.emulate_delay); furi_string_printf(tmp_str, "%ds", options_emulate_delay[nfc_playlist->settings.emulate_delay]); - variable_item_set_current_value_text(emulation_delay_settings, furi_string_get_cstr(tmp_str)); + variable_item_set_current_value_text(emulation_delay_setting, furi_string_get_cstr(tmp_str)); nfc_playlist->settings.emulate_led_indicator = default_emulate_led_indicator; - VariableItem* emulation_led_indicator_settings = variable_item_list_get(nfc_playlist->variable_item_list, NfcPlaylistSettings_LedIndicator); - variable_item_set_current_value_index(emulation_led_indicator_settings, nfc_playlist->settings.emulate_led_indicator); - variable_item_set_current_value_text(emulation_led_indicator_settings, nfc_playlist->settings.emulate_led_indicator ? "ON" : "OFF"); + VariableItem* emulation_led_indicator_setting = variable_item_list_get(nfc_playlist->variable_item_list, NfcPlaylistSettings_LedIndicator); + variable_item_set_current_value_index(emulation_led_indicator_setting, nfc_playlist->settings.emulate_led_indicator); + variable_item_set_current_value_text(emulation_led_indicator_setting, nfc_playlist->settings.emulate_led_indicator ? "ON" : "OFF"); + + nfc_playlist->settings.skip_error = default_skip_error; + VariableItem* emulation_skip_error_setting = variable_item_list_get(nfc_playlist->variable_item_list, NfcPlaylistSettings_SkipError); + variable_item_set_current_value_index(emulation_skip_error_setting, nfc_playlist->settings.skip_error); + variable_item_set_current_value_text(emulation_skip_error_setting, nfc_playlist->settings.skip_error ? "ON" : "OFF"); furi_string_free(tmp_str); consumed = true; diff --git a/scenes/nfc_playlist_scene_view_playlist_content.c b/scenes/nfc_playlist_scene_view_playlist_content.c index e7821073413..98509a4698a 100644 --- a/scenes/nfc_playlist_scene_view_playlist_content.c +++ b/scenes/nfc_playlist_scene_view_playlist_content.c @@ -5,7 +5,7 @@ void nfc_playlist_view_playlist_content_scene_on_enter(void* context) { Storage* storage = furi_record_open(RECORD_STORAGE); File* file = storage_file_alloc(storage); - + if (storage_file_open(file, furi_string_get_cstr(nfc_playlist->settings.file_path), FSAM_READ, FSOM_OPEN_EXISTING)) { uint8_t buffer[PLAYLIST_VIEW_MAX_SIZE]; uint16_t read_count = storage_file_read(file, buffer, PLAYLIST_VIEW_MAX_SIZE);