diff --git a/applications/applications.c b/applications/applications.c index c932f86ce..dccab589f 100644 --- a/applications/applications.c +++ b/applications/applications.c @@ -21,7 +21,6 @@ extern int32_t accessor_app(void* p); extern int32_t archive_app(void* p); extern int32_t bad_usb_app(void* p); extern int32_t u2f_app(void* p); -extern int32_t wav_player_app(void* p); extern int32_t uart_echo_app(void* p); extern int32_t blink_test_app(void* p); extern int32_t bt_debug_app(void* p); @@ -50,8 +49,6 @@ extern int32_t file_browser_app(void* p); // Plugins extern int32_t music_player_app(void* p); extern int32_t snake_game_app(void* p); -extern int32_t tetris_game_app(void *p); -extern int32_t clock_app(void *p); // On system start hooks declaration extern void bt_on_system_start(); @@ -209,14 +206,6 @@ const size_t FLIPPER_SYSTEM_APPS_COUNT = COUNT_OF(FLIPPER_SYSTEM_APPS); // Main menu APP const FlipperApplication FLIPPER_APPS[] = { -#ifdef APP_CLOCK - {.app = clock_app, - .name = "Clock", - .stack_size = 2048, - .icon = &A_Clock_14, - .flags = FlipperApplicationFlagDefault}, -#endif - #ifdef APP_SUBGHZ {.app = subghz_app, .name = "Sub-GHz", @@ -280,6 +269,7 @@ const FlipperApplication FLIPPER_APPS[] = { .icon = &A_U2F_14, .flags = FlipperApplicationFlagDefault}, #endif + }; const size_t FLIPPER_APPS_COUNT = COUNT_OF(FLIPPER_APPS); @@ -349,7 +339,7 @@ const FlipperApplication FLIPPER_PLUGINS[] = { {.app = music_player_app, .name = "Music Player", .stack_size = 2048, - .icon = &A_MusicPlayer_14, + .icon = &A_Plugins_14, .flags = FlipperApplicationFlagDefault}, #endif @@ -360,16 +350,6 @@ const FlipperApplication FLIPPER_PLUGINS[] = { .icon = &A_Plugins_14, .flags = FlipperApplicationFlagDefault}, #endif - -#ifdef APP_TETRIS_GAME - {.app = tetris_game_app, .name = "Tetris Game", .stack_size = 1024, .icon = NULL}, -#endif - - {.app = wav_player_app, - .name = "Wav Player", - .stack_size = 4096, - .icon = &A_MusicPlayer_14, - .flags = FlipperApplicationFlagDefault}, }; const size_t FLIPPER_PLUGINS_COUNT = COUNT_OF(FLIPPER_PLUGINS); @@ -440,14 +420,6 @@ const FlipperApplication FLIPPER_DEBUG_APPS[] = { .flags = FlipperApplicationFlagDefault}, #endif -#ifdef APP_SCENED - {.app = scened_app, - .name = "Templated Scene", - .stack_size = 1024, - .icon = NULL, - .flags = FlipperApplicationFlagDefault}, -#endif - #ifdef APP_LF_RFID {.app = lfrfid_debug_app, .name = "LF-RFID Debug", diff --git a/applications/applications.mk b/applications/applications.mk index 30dffbcaf..e7a9ebfc0 100644 --- a/applications/applications.mk +++ b/applications/applications.mk @@ -47,8 +47,6 @@ APP_UPDATER = 1 # Plugins APP_MUSIC_PLAYER = 1 APP_SNAKE_GAME = 1 -APP_TETRIS_GAME = 1 -APP_CLOCK = 1 # Debug APP_ACCESSOR = 1 @@ -236,27 +234,12 @@ CFLAGS += -DAPP_MUSIC_PLAYER SRV_GUI = 1 endif - APP_SNAKE_GAME ?= 0 ifeq ($(APP_SNAKE_GAME), 1) CFLAGS += -DAPP_SNAKE_GAME SRV_GUI = 1 endif - -APP_TETRIS_GAME ?= 0 -ifeq ($(APP_TETRIS_GAME), 1) -CFLAGS += -DAPP_TETRIS_GAME -SRV_GUI = 1 -endif - - -APP_CLOCK ?= 0 -ifeq ($(APP_CLOCK), 1) -CFLAGS += -DAPP_CLOCK -SRV_GUI = 1 -endif - APP_IBUTTON ?= 0 ifeq ($(APP_IBUTTON), 1) CFLAGS += -DAPP_IBUTTON diff --git a/applications/bad_usb/bad_usb_app.c b/applications/bad_usb/bad_usb_app.c index eb647e004..65ccc575b 100644 --- a/applications/bad_usb/bad_usb_app.c +++ b/applications/bad_usb/bad_usb_app.c @@ -1,4 +1,5 @@ #include "bad_usb_app_i.h" +#include "m-string.h" #include #include #include @@ -22,33 +23,13 @@ static void bad_usb_app_tick_event_callback(void* context) { scene_manager_handle_tick_event(app->scene_manager); } -static bool bad_usb_check_assets() { - Storage* fs_api = furi_record_open("storage"); - - File* dir = storage_file_alloc(fs_api); - bool ret = false; - - if(storage_dir_open(dir, BAD_USB_APP_PATH_FOLDER)) { - ret = true; - } - - storage_dir_close(dir); - storage_file_free(dir); - - furi_record_close("storage"); - - return ret; -} - BadUsbApp* bad_usb_app_alloc(char* arg) { BadUsbApp* app = malloc(sizeof(BadUsbApp)); + string_init(app->file_path); + if(arg != NULL) { - string_t filename; - string_init(filename); - path_extract_filename_no_ext(arg, filename); - strncpy(app->file_name, string_get_cstr(filename), BAD_USB_FILE_NAME_LEN); - string_clear(filename); + string_set_str(app->file_path, arg); } app->gui = furi_record_open("gui"); @@ -83,13 +64,11 @@ BadUsbApp* bad_usb_app_alloc(char* arg) { app->error = BadUsbAppErrorCloseRpc; scene_manager_next_scene(app->scene_manager, BadUsbSceneError); } else { - if(*app->file_name != '\0') { + if(!string_empty_p(app->file_path)) { scene_manager_next_scene(app->scene_manager, BadUsbSceneWork); - } else if(bad_usb_check_assets()) { - scene_manager_next_scene(app->scene_manager, BadUsbSceneFileSelect); } else { - app->error = BadUsbAppErrorNoFiles; - scene_manager_next_scene(app->scene_manager, BadUsbSceneError); + string_set_str(app->file_path, BAD_USB_APP_PATH_FOLDER); + scene_manager_next_scene(app->scene_manager, BadUsbSceneFileSelect); } } @@ -117,6 +96,8 @@ void bad_usb_app_free(BadUsbApp* app) { furi_record_close("notification"); furi_record_close("dialogs"); + string_clear(app->file_path); + free(app); } diff --git a/applications/bad_usb/bad_usb_app_i.h b/applications/bad_usb/bad_usb_app_i.h index 67f5816b8..c82419e0f 100644 --- a/applications/bad_usb/bad_usb_app_i.h +++ b/applications/bad_usb/bad_usb_app_i.h @@ -16,7 +16,6 @@ #define BAD_USB_APP_PATH_FOLDER "/any/badusb" #define BAD_USB_APP_EXTENSION ".txt" -#define BAD_USB_FILE_NAME_LEN 40 typedef enum { BadUsbAppErrorNoFiles, @@ -32,7 +31,7 @@ struct BadUsbApp { Widget* widget; BadUsbAppError error; - char file_name[BAD_USB_FILE_NAME_LEN + 1]; + string_t file_path; BadUsb* bad_usb_view; BadUsbScript* bad_usb_script; }; diff --git a/applications/bad_usb/scenes/bad_usb_scene_file_select.c b/applications/bad_usb/scenes/bad_usb_scene_file_select.c index 82f03bab0..1e6ba895a 100644 --- a/applications/bad_usb/scenes/bad_usb_scene_file_select.c +++ b/applications/bad_usb/scenes/bad_usb_scene_file_select.c @@ -5,14 +5,16 @@ static bool bad_usb_file_select(BadUsbApp* bad_usb) { furi_assert(bad_usb); - // Input events and views are managed by file_select - bool res = dialog_file_select_show( + // Input events and views are managed by file_browser + bool res = dialog_file_browser_show( bad_usb->dialogs, - BAD_USB_APP_PATH_FOLDER, + bad_usb->file_path, + bad_usb->file_path, BAD_USB_APP_EXTENSION, - bad_usb->file_name, - sizeof(bad_usb->file_name), - NULL); + true, + &I_badusb_10px, + true); + return res; } diff --git a/applications/bad_usb/scenes/bad_usb_scene_work.c b/applications/bad_usb/scenes/bad_usb_scene_work.c index a3a46803a..516cbde3a 100644 --- a/applications/bad_usb/scenes/bad_usb_scene_work.c +++ b/applications/bad_usb/scenes/bad_usb_scene_work.c @@ -2,6 +2,8 @@ #include "../bad_usb_app_i.h" #include "../views/bad_usb_view.h" #include "furi_hal.h" +#include "m-string.h" +#include "toolbox/path.h" void bad_usb_scene_work_ok_callback(InputType type, void* context) { furi_assert(context); @@ -28,10 +30,9 @@ void bad_usb_scene_work_on_enter(void* context) { string_t file_name; string_init(file_name); - bad_usb_set_file_name(app->bad_usb_view, app->file_name); - string_printf( - file_name, "%s/%s%s", BAD_USB_APP_PATH_FOLDER, app->file_name, BAD_USB_APP_EXTENSION); - app->bad_usb_script = bad_usb_script_open(file_name); + path_extract_filename(app->file_path, file_name, true); + bad_usb_set_file_name(app->bad_usb_view, string_get_cstr(file_name)); + app->bad_usb_script = bad_usb_script_open(app->file_path); string_clear(file_name); diff --git a/applications/bad_usb/views/bad_usb_view.c b/applications/bad_usb/views/bad_usb_view.c index 5b6fe6e89..430885df3 100644 --- a/applications/bad_usb/views/bad_usb_view.c +++ b/applications/bad_usb/views/bad_usb_view.c @@ -2,6 +2,8 @@ #include "../bad_usb_script.h" #include +#define MAX_NAME_LEN 64 + struct BadUsb { View* view; BadUsbOkCallback callback; @@ -9,7 +11,7 @@ struct BadUsb { }; typedef struct { - char* file_name; + char file_name[MAX_NAME_LEN]; BadUsbState state; uint8_t anim_frame; } BadUsbModel; @@ -149,11 +151,11 @@ void bad_usb_set_ok_callback(BadUsb* bad_usb, BadUsbOkCallback callback, void* c }); } -void bad_usb_set_file_name(BadUsb* bad_usb, char* name) { +void bad_usb_set_file_name(BadUsb* bad_usb, const char* name) { furi_assert(name); with_view_model( bad_usb->view, (BadUsbModel * model) { - model->file_name = name; + strncpy(model->file_name, name, MAX_NAME_LEN); return true; }); } diff --git a/applications/bad_usb/views/bad_usb_view.h b/applications/bad_usb/views/bad_usb_view.h index f5a8a0fab..80a47e2ca 100755 --- a/applications/bad_usb/views/bad_usb_view.h +++ b/applications/bad_usb/views/bad_usb_view.h @@ -14,6 +14,6 @@ View* bad_usb_get_view(BadUsb* bad_usb); void bad_usb_set_ok_callback(BadUsb* bad_usb, BadUsbOkCallback callback, void* context); -void bad_usb_set_file_name(BadUsb* bad_usb, char* name); +void bad_usb_set_file_name(BadUsb* bad_usb, const char* name); void bad_usb_set_state(BadUsb* bad_usb, BadUsbState* st); diff --git a/applications/clock_app/clock_app.c b/applications/clock_app/clock_app.c deleted file mode 100644 index 60f442589..000000000 --- a/applications/clock_app/clock_app.c +++ /dev/null @@ -1,282 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#define TAG "Clock" - -bool timerStarted=false; -int timerSecs=0; -int songSelect=0; - -typedef enum { - EventTypeTick, - EventTypeKey, -} EventType; - -typedef struct { - EventType type; - InputEvent input; -} PluginEvent; - -typedef struct { - FuriHalRtcDateTime datetime; -} ClockState; - -static void clock_input_callback(InputEvent* input_event, osMessageQueueId_t event_queue) { - furi_assert(event_queue); - PluginEvent event = {.type = EventTypeKey, .input = *input_event}; - osMessageQueuePut(event_queue, &event, 0, osWaitForever); -} - -static void clock_render_callback(Canvas* const canvas, void* ctx) { - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - ClockState* state = (ClockState*)acquire_mutex((ValueMutex*)ctx, 25); - char strings[3][20]; - int curMin = (timerSecs/60); - int curSec = timerSecs-(curMin *60); - sprintf(strings[0], "%.4d-%.2d-%.2d", state->datetime.year, state->datetime.month, state->datetime.day); - sprintf(strings[1], "%.2d:%.2d:%.2d", state->datetime.hour, state->datetime.minute, state->datetime.second); - sprintf(strings[2], "%.2d:%.2d", curMin , curSec); - release_mutex((ValueMutex*)ctx, state); - canvas_set_font(canvas, FontBigNumbers); - canvas_draw_str_aligned(canvas, 64, 8, AlignCenter, AlignCenter, strings[1]); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned(canvas, 64, 20, AlignCenter, AlignTop, strings[0]); - // elements_button_left(canvas, "Alarms"); - // elements_button_right(canvas, "Settings"); - // elements_button_center(canvas, "Reset"); - canvas_set_font(canvas, FontBigNumbers); - canvas_draw_str_aligned(canvas, 64, 32, AlignCenter, AlignTop, strings[2]); - canvas_set_font(canvas, FontSecondary); - if(timerStarted) { - elements_button_center(canvas, "Stop"); - } else { - elements_button_center(canvas, "Start"); - } - if(songSelect==0) { - elements_button_right(canvas, "S:OFF"); - } else if(songSelect==1) { - elements_button_right(canvas, "S:PoRa"); - } else if(songSelect==2) { - elements_button_right(canvas, "S:Mario"); - } else if(songSelect==3) { - elements_button_right(canvas, "S:ByMin"); - } -} - -static void clock_state_init(ClockState* const state) { - furi_hal_rtc_get_datetime(&state->datetime); -} - -const NotificationSequence clock_alert_silent = { - &message_force_vibro_setting_on, &message_vibro_on, &message_red_255, &message_green_255, &message_blue_255, &message_display_backlight_on, - &message_vibro_off, &message_display_backlight_off, &message_delay_50, &message_display_backlight_on, NULL, -}; -const NotificationSequence clock_alert_pr1 = { - &message_force_speaker_volume_setting_1f, - &message_force_vibro_setting_on, &message_vibro_on, &message_red_255, &message_green_255, &message_blue_255, &message_display_backlight_on, - &message_note_g5, &message_delay_100, &message_delay_100, &message_delay_50, &message_sound_off, - &message_vibro_off, &message_display_backlight_off, &message_delay_50, &message_display_backlight_on, - &message_note_g5, &message_delay_100, &message_delay_100, &message_delay_50, &message_sound_off, NULL, -}; -const NotificationSequence clock_alert_pr2 = { - &message_force_speaker_volume_setting_1f, - &message_force_vibro_setting_on, &message_vibro_on, - &message_note_fs5, &message_delay_100, &message_delay_100, &message_sound_off, - &message_display_backlight_off, &message_vibro_off, &message_delay_50, - &message_note_g5, &message_delay_100, &message_delay_100, &message_sound_off, - &message_display_backlight_on, &message_delay_50, - &message_note_a5, &message_delay_100, &message_delay_100, &message_sound_off, NULL, -}; -const NotificationSequence clock_alert_pr3 = { - &message_force_speaker_volume_setting_1f, - &message_display_backlight_off, - &message_note_g5, &message_delay_100, &message_delay_100, &message_sound_off, - &message_delay_50, &message_red_255, &message_green_255, &message_blue_255, &message_display_backlight_on, &message_delay_100, NULL, -}; -const NotificationSequence clock_alert_mario1 = { - &message_force_speaker_volume_setting_1f, - &message_force_vibro_setting_on, &message_vibro_on, &message_red_255, &message_green_255, &message_blue_255, &message_display_backlight_on, - &message_note_e5, &message_delay_100, &message_delay_100, &message_delay_50, &message_sound_off, - &message_note_e5, &message_delay_100, &message_delay_100, &message_delay_50, &message_sound_off, - &message_vibro_off, &message_display_backlight_off, &message_delay_100, &message_display_backlight_on, &message_delay_100, - &message_note_e5, &message_delay_100, &message_delay_100, &message_delay_50, &message_sound_off, NULL, -}; -const NotificationSequence clock_alert_mario2 = { - &message_force_speaker_volume_setting_1f, - &message_force_vibro_setting_on, &message_vibro_on, &message_display_backlight_off, &message_delay_100, &message_display_backlight_on, &message_delay_100, - &message_note_c5, &message_delay_100, &message_delay_100, &message_sound_off, - &message_display_backlight_off, &message_vibro_off, &message_delay_50, - &message_note_e5, &message_delay_100, &message_delay_100, &message_sound_off, - &message_display_backlight_on, NULL, -}; -const NotificationSequence clock_alert_mario3 = { - &message_force_speaker_volume_setting_1f, - &message_display_backlight_off, - &message_note_g5, &message_delay_100, &message_delay_100, &message_delay_100, &message_delay_100, &message_sound_off, - &message_delay_50, &message_red_255, &message_green_255, &message_blue_255, &message_display_backlight_on, &message_delay_100, - &message_note_g4, &message_delay_100, &message_delay_100, &message_delay_100, &message_delay_100, &message_sound_off, - NULL, -}; -const NotificationSequence clock_alert_perMin = { - &message_force_speaker_volume_setting_1f, - &message_note_g5, &message_delay_100, &message_delay_50, &message_sound_off, - &message_delay_10, - &message_note_g4, &message_delay_50, &message_delay_10, &message_delay_10, &message_sound_off, - NULL, -}; -const NotificationSequence clock_alert_startStop = { - &message_force_speaker_volume_setting_1f, - &message_note_d6, &message_delay_100, &message_delay_10, &message_delay_10, &message_sound_off, NULL, -}; - -// Runs every 1000ms by default -static void clock_tick(void* ctx) { - furi_assert(ctx); - osMessageQueueId_t event_queue = ctx; - PluginEvent event = {.type = EventTypeTick}; - if(timerStarted) { - timerSecs=timerSecs+1; - if(timerSecs%60==0 && songSelect!=0) { - NotificationApp* notification = furi_record_open("notification"); - notification_message(notification, &clock_alert_perMin); - furi_record_close("notification"); - } - if(songSelect==1 ) { - if(timerSecs==80) { - NotificationApp* notification = furi_record_open("notification"); - notification_message(notification, &clock_alert_pr1); - furi_record_close("notification"); - } - if(timerSecs==81) { - NotificationApp* notification = furi_record_open("notification"); - notification_message(notification, &clock_alert_pr2); - furi_record_close("notification"); - } - if(timerSecs==82) { - NotificationApp* notification = furi_record_open("notification"); - notification_message(notification, &clock_alert_pr3); - furi_record_close("notification"); - } - } else if(songSelect==2 ) { - if(timerSecs==80) { - NotificationApp* notification = furi_record_open("notification"); - notification_message(notification, &clock_alert_mario1); - furi_record_close("notification"); - } - if(timerSecs==81) { - NotificationApp* notification = furi_record_open("notification"); - notification_message(notification, &clock_alert_mario2); - furi_record_close("notification"); - } - if(timerSecs==82) { - NotificationApp* notification = furi_record_open("notification"); - notification_message(notification, &clock_alert_mario3); - furi_record_close("notification"); - } - } else { - if(timerSecs==80) { - NotificationApp* notification = furi_record_open("notification"); - notification_message(notification, &clock_alert_silent); - furi_record_close("notification"); - } - } - } - // It's OK to loose this event if system overloaded - osMessageQueuePut(event_queue, &event, 0, 0); -} - -int32_t clock_app(void* p) { - UNUSED(p); - timerStarted=false; - timerSecs=0; - songSelect=0; - osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(PluginEvent), NULL); - ClockState* plugin_state = malloc(sizeof(ClockState)); - clock_state_init(plugin_state); - ValueMutex state_mutex; - if (!init_mutex(&state_mutex, plugin_state, sizeof(ClockState))) { - FURI_LOG_E(TAG, "cannot create mutex\r\n"); - free(plugin_state); - return 255; - } - // Set system callbacks - ViewPort* view_port = view_port_alloc(); - view_port_draw_callback_set(view_port, clock_render_callback, &state_mutex); - view_port_input_callback_set(view_port, clock_input_callback, event_queue); - osTimerId_t timer = osTimerNew(clock_tick, osTimerPeriodic, event_queue, NULL); - osTimerStart(timer, osKernelGetTickFreq()); - // Open GUI and register view_port - Gui* gui = furi_record_open("gui"); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - // Main loop - PluginEvent event; - for (bool processing = true; processing;) { - osStatus_t event_status = osMessageQueueGet(event_queue, &event, NULL, 100); - ClockState* plugin_state = (ClockState*)acquire_mutex_block(&state_mutex); - if (event_status == osOK) { - // press events - if (event.type == EventTypeKey) { - if (event.input.type == InputTypeShort || event.input.type == InputTypeRepeat) { - switch(event.input.key) { - case InputKeyUp: - if(timerStarted) timerSecs=timerSecs+5; - break; - case InputKeyDown: - if(timerStarted) timerSecs=timerSecs-5; - break; - case InputKeyRight: - if(songSelect==0) { - songSelect=1; - } else if(songSelect==1) { - songSelect=2; - } else if(songSelect==2) { - songSelect=3; - } else { - songSelect=0; - } - break; - case InputKeyLeft: - break; - case InputKeyOk: - if(songSelect==1 || songSelect==2 || songSelect==3) { - NotificationApp* notification = furi_record_open("notification"); - notification_message(notification, &clock_alert_startStop); - furi_record_close("notification"); - } - if(timerStarted) { - timerStarted=false; - timerSecs=0; - } else { - timerStarted=true; - } - break; - case InputKeyBack: - // Exit the plugin - processing = false; - break; - } - } - } else if(event.type == EventTypeTick) { - furi_hal_rtc_get_datetime(&plugin_state->datetime); - } - } else { - FURI_LOG_D(TAG, "osMessageQueue: event timeout"); - // event timeout - } - view_port_update(view_port); - release_mutex(&state_mutex, plugin_state); - } - osTimerDelete(timer); - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - furi_record_close("gui"); - view_port_free(view_port); - osMessageQueueDelete(event_queue); - return 0; -} diff --git a/applications/debug_tools/file_browser_test/file_browser_app.c b/applications/debug_tools/file_browser_test/file_browser_app.c index a408f5cde..c9b63ecb0 100644 --- a/applications/debug_tools/file_browser_test/file_browser_app.c +++ b/applications/debug_tools/file_browser_test/file_browser_app.c @@ -48,7 +48,7 @@ FileBrowserApp* file_browser_app_alloc(char* arg) { app->widget = widget_alloc(); string_init(app->file_path); - app->file_browser = file_browser_alloc(&(app->file_path)); + app->file_browser = file_browser_alloc(app->file_path); file_browser_configure(app->file_browser, "*", true, &I_badusb_10px, true); view_dispatcher_add_view( diff --git a/applications/debug_tools/file_browser_test/scenes/file_browser_scene_browser.c b/applications/debug_tools/file_browser_test/scenes/file_browser_scene_browser.c index 9c570cec0..ca16ad0d1 100644 --- a/applications/debug_tools/file_browser_test/scenes/file_browser_scene_browser.c +++ b/applications/debug_tools/file_browser_test/scenes/file_browser_scene_browser.c @@ -20,12 +20,10 @@ bool file_browser_scene_browser_on_event(void* context, SceneManagerEvent event) return consumed; } -static void file_browser_callback(void* context, bool state) { +static void file_browser_callback(void* context) { FileBrowserApp* app = context; furi_assert(app); view_dispatcher_send_custom_event(app->view_dispatcher, SceneManagerEventTypeCustom); - - UNUSED(state); } void file_browser_scene_browser_on_enter(void* context) { diff --git a/applications/desktop/desktop.c b/applications/desktop/desktop.c index 514166375..34c169e07 100644 --- a/applications/desktop/desktop.c +++ b/applications/desktop/desktop.c @@ -56,12 +56,7 @@ static bool desktop_custom_event_callback(void* context, uint32_t event) { return true; case DesktopGlobalAutoLock: if(!loader_is_locked(desktop->loader)) { - if(desktop->settings.pin_code.length > 0) { - desktop_pin_lock(&desktop->settings); - desktop_lock(desktop); - } else { - desktop_lock(desktop); - } + desktop_lock(desktop); } return true; } diff --git a/applications/dialogs/dialogs.c b/applications/dialogs/dialogs.c index cf4a2ad68..8929dc116 100644 --- a/applications/dialogs/dialogs.c +++ b/applications/dialogs/dialogs.c @@ -1,6 +1,7 @@ +#include "dialogs/dialogs_message.h" #include "dialogs_i.h" #include "dialogs_api_lock.h" -#include "dialogs_module_file_select.h" +#include "dialogs_module_file_browser.h" #include "dialogs_module_message.h" static DialogsApp* dialogs_app_alloc() { @@ -13,9 +14,9 @@ static DialogsApp* dialogs_app_alloc() { static void dialogs_app_process_message(DialogsApp* app, DialogsAppMessage* message) { UNUSED(app); switch(message->command) { - case DialogsAppCommandFileOpen: + case DialogsAppCommandFileBrowser: message->return_data->bool_value = - dialogs_app_process_module_file_select(&message->data->file_select); + dialogs_app_process_module_file_browser(&message->data->file_browser); break; case DialogsAppCommandDialog: message->return_data->dialog_value = diff --git a/applications/dialogs/dialogs.h b/applications/dialogs/dialogs.h index 9c71c0989..536060565 100644 --- a/applications/dialogs/dialogs.h +++ b/applications/dialogs/dialogs.h @@ -1,6 +1,7 @@ #pragma once #include #include +#include "m-string.h" #ifdef __cplusplus extern "C" { @@ -10,25 +11,27 @@ extern "C" { typedef struct DialogsApp DialogsApp; -/****************** FILE SELECT ******************/ +/****************** FILE BROWSER ******************/ /** - * Shows and processes the file selection dialog + * Shows and processes the file browser dialog * @param context api pointer - * @param path path to directory + * @param result_path selected file path string pointer + * @param path preselected file path string pointer * @param extension file extension to be offered for selection - * @param selected_filename buffer where the selected filename will be saved - * @param selected_filename_size and the size of this buffer - * @param preselected_filename filename to be preselected + * @param skip_assets true - do not show assets folders + * @param icon file icon pointer, NULL for default icon + * @param hide_ext true - hide extensions for files * @return bool whether a file was selected */ -bool dialog_file_select_show( +bool dialog_file_browser_show( DialogsApp* context, - const char* path, + string_ptr result_path, + string_ptr path, const char* extension, - char* result, - uint8_t result_size, - const char* preselected_filename); + bool skip_assets, + const Icon* icon, + bool hide_ext); /****************** MESSAGE ******************/ diff --git a/applications/dialogs/dialogs_api.c b/applications/dialogs/dialogs_api.c index c4efb287d..fab3a5eae 100644 --- a/applications/dialogs/dialogs_api.c +++ b/applications/dialogs/dialogs_api.c @@ -1,31 +1,36 @@ +#include "dialogs/dialogs_message.h" #include "dialogs_i.h" #include "dialogs_api_lock.h" +#include "m-string.h" -/****************** File select ******************/ +/****************** File browser ******************/ -bool dialog_file_select_show( +bool dialog_file_browser_show( DialogsApp* context, - const char* path, + string_ptr result_path, + string_ptr path, const char* extension, - char* result, - uint8_t result_size, - const char* preselected_filename) { + bool skip_assets, + const Icon* icon, + bool hide_ext) { FuriApiLock lock = API_LOCK_INIT_LOCKED(); furi_check(lock != NULL); DialogsAppData data = { - .file_select = { - .path = path, + .file_browser = { .extension = extension, - .result = result, - .result_size = result_size, - .preselected_filename = preselected_filename, + .result_path = result_path, + .file_icon = icon, + .hide_ext = hide_ext, + .skip_assets = skip_assets, + .preselected_filename = path, + }}; DialogsAppReturn return_data; DialogsAppMessage message = { .lock = lock, - .command = DialogsAppCommandFileOpen, + .command = DialogsAppCommandFileBrowser, .data = &data, .return_data = &return_data, }; diff --git a/applications/dialogs/dialogs_message.h b/applications/dialogs/dialogs_message.h index d7b5fabf4..ccfbdece5 100644 --- a/applications/dialogs/dialogs_message.h +++ b/applications/dialogs/dialogs_message.h @@ -2,25 +2,27 @@ #include #include "dialogs_i.h" #include "dialogs_api_lock.h" +#include "m-string.h" #ifdef __cplusplus extern "C" { #endif typedef struct { - const char* path; const char* extension; - char* result; - uint8_t result_size; - const char* preselected_filename; -} DialogsAppMessageDataFileSelect; + bool skip_assets; + bool hide_ext; + const Icon* file_icon; + string_ptr result_path; + string_ptr preselected_filename; +} DialogsAppMessageDataFileBrowser; typedef struct { const DialogMessage* message; } DialogsAppMessageDataDialog; typedef union { - DialogsAppMessageDataFileSelect file_select; + DialogsAppMessageDataFileBrowser file_browser; DialogsAppMessageDataDialog dialog; } DialogsAppData; @@ -30,7 +32,7 @@ typedef union { } DialogsAppReturn; typedef enum { - DialogsAppCommandFileOpen, + DialogsAppCommandFileBrowser, DialogsAppCommandDialog, } DialogsAppCommand; diff --git a/applications/dialogs/dialogs_module_file_browser.c b/applications/dialogs/dialogs_module_file_browser.c new file mode 100644 index 000000000..ecd0ca79b --- /dev/null +++ b/applications/dialogs/dialogs_module_file_browser.c @@ -0,0 +1,59 @@ +#include "dialogs_i.h" +#include "dialogs_api_lock.h" +#include "gui/modules/file_browser.h" + +typedef struct { + FuriApiLock lock; + bool result; +} DialogsAppFileBrowserContext; + +static void dialogs_app_file_browser_back_callback(void* context) { + furi_assert(context); + DialogsAppFileBrowserContext* file_browser_context = context; + file_browser_context->result = false; + API_LOCK_UNLOCK(file_browser_context->lock); +} + +static void dialogs_app_file_browser_callback(void* context) { + furi_assert(context); + DialogsAppFileBrowserContext* file_browser_context = context; + file_browser_context->result = true; + API_LOCK_UNLOCK(file_browser_context->lock); +} + +bool dialogs_app_process_module_file_browser(const DialogsAppMessageDataFileBrowser* data) { + bool ret = false; + Gui* gui = furi_record_open("gui"); + + DialogsAppFileBrowserContext* file_browser_context = + malloc(sizeof(DialogsAppFileBrowserContext)); + file_browser_context->lock = API_LOCK_INIT_LOCKED(); + + ViewHolder* view_holder = view_holder_alloc(); + view_holder_attach_to_gui(view_holder, gui); + view_holder_set_back_callback( + view_holder, dialogs_app_file_browser_back_callback, file_browser_context); + + FileBrowser* file_browser = file_browser_alloc(data->result_path); + file_browser_set_callback( + file_browser, dialogs_app_file_browser_callback, file_browser_context); + file_browser_configure( + file_browser, data->extension, data->skip_assets, data->file_icon, data->hide_ext); + file_browser_start(file_browser, data->preselected_filename); + + view_holder_set_view(view_holder, file_browser_get_view(file_browser)); + view_holder_start(view_holder); + API_LOCK_WAIT_UNTIL_UNLOCK(file_browser_context->lock); + + ret = file_browser_context->result; + + view_holder_stop(view_holder); + view_holder_free(view_holder); + file_browser_stop(file_browser); + file_browser_free(file_browser); + API_LOCK_FREE(file_browser_context->lock); + free(file_browser_context); + furi_record_close("gui"); + + return ret; +} diff --git a/applications/dialogs/dialogs_module_file_select.h b/applications/dialogs/dialogs_module_file_browser.h similarity index 54% rename from applications/dialogs/dialogs_module_file_select.h rename to applications/dialogs/dialogs_module_file_browser.h index 749fe9c1d..b6cbdf6a5 100644 --- a/applications/dialogs/dialogs_module_file_select.h +++ b/applications/dialogs/dialogs_module_file_browser.h @@ -5,7 +5,7 @@ extern "C" { #endif -bool dialogs_app_process_module_file_select(const DialogsAppMessageDataFileSelect* data); +bool dialogs_app_process_module_file_browser(const DialogsAppMessageDataFileBrowser* data); #ifdef __cplusplus } diff --git a/applications/dialogs/dialogs_module_file_select.c b/applications/dialogs/dialogs_module_file_select.c deleted file mode 100644 index f133c00a0..000000000 --- a/applications/dialogs/dialogs_module_file_select.c +++ /dev/null @@ -1,59 +0,0 @@ -#include "dialogs_i.h" -#include "dialogs_api_lock.h" -#include - -typedef struct { - FuriApiLock lock; - bool result; -} DialogsAppFileSelectContext; - -static void dialogs_app_file_select_back_callback(void* context) { - furi_assert(context); - DialogsAppFileSelectContext* file_select_context = context; - file_select_context->result = false; - API_LOCK_UNLOCK(file_select_context->lock); -} - -static void dialogs_app_file_select_callback(bool result, void* context) { - furi_assert(context); - DialogsAppFileSelectContext* file_select_context = context; - file_select_context->result = result; - API_LOCK_UNLOCK(file_select_context->lock); -} - -bool dialogs_app_process_module_file_select(const DialogsAppMessageDataFileSelect* data) { - bool ret = false; - Gui* gui = furi_record_open("gui"); - - DialogsAppFileSelectContext* file_select_context = malloc(sizeof(DialogsAppFileSelectContext)); - file_select_context->lock = API_LOCK_INIT_LOCKED(); - - ViewHolder* view_holder = view_holder_alloc(); - view_holder_attach_to_gui(view_holder, gui); - view_holder_set_back_callback( - view_holder, dialogs_app_file_select_back_callback, file_select_context); - - FileSelect* file_select = file_select_alloc(); - file_select_set_callback(file_select, dialogs_app_file_select_callback, file_select_context); - file_select_set_filter(file_select, data->path, data->extension); - file_select_set_result_buffer(file_select, data->result, data->result_size); - file_select_init(file_select); - if(data->preselected_filename != NULL) { - file_select_set_selected_file(file_select, data->preselected_filename); - } - - view_holder_set_view(view_holder, file_select_get_view(file_select)); - view_holder_start(view_holder); - API_LOCK_WAIT_UNTIL_UNLOCK(file_select_context->lock); - - ret = file_select_context->result; - - view_holder_stop(view_holder); - view_holder_free(view_holder); - file_select_free(file_select); - API_LOCK_FREE(file_select_context->lock); - free(file_select_context); - furi_record_close("gui"); - - return ret; -} diff --git a/applications/gui/modules/file_browser.c b/applications/gui/modules/file_browser.c index 919750962..1cef1d079 100644 --- a/applications/gui/modules/file_browser.c +++ b/applications/gui/modules/file_browser.c @@ -10,6 +10,7 @@ #include #include #include +#include "toolbox/path.h" #define LIST_ITEMS 5u #define MAX_LEN_PX 110 @@ -60,13 +61,13 @@ ARRAY_DEF( struct FileBrowser { View* view; BrowserWorker* worker; - char* ext_filter; + const char* ext_filter; bool skip_assets; FileBrowserCallback callback; void* context; - string_t* result_path; + string_ptr result_path; }; typedef struct { @@ -100,7 +101,7 @@ static void browser_list_load_cb(void* context, uint32_t list_load_offset); static void browser_list_item_cb(void* context, string_t item_path, bool is_folder, bool is_last); static void browser_long_load_cb(void* context); -FileBrowser* file_browser_alloc(string_t* result_path) { +FileBrowser* file_browser_alloc(string_ptr result_path) { furi_assert(result_path); FileBrowser* browser = malloc(sizeof(FileBrowser)); browser->view = view_alloc(); @@ -140,7 +141,7 @@ View* file_browser_get_view(FileBrowser* browser) { void file_browser_configure( FileBrowser* browser, - char* extension, + const char* extension, bool skip_assets, const Icon* file_icon, bool hide_ext) { @@ -250,6 +251,7 @@ static void with_view_model( browser->view, (FileBrowserModel * model) { + items_array_reset(model->items); if(is_root) { model->item_cnt = item_cnt; model->item_idx = (file_idx > 0) ? file_idx : 0; @@ -383,7 +385,7 @@ static void browser_draw_list(Canvas* canvas, FileBrowserModel* model) { BrowserItem_t* item = items_array_get( model->items, CLAMP(idx - model->array_offset, (int32_t)(array_size - 1), 0)); item_type = item->type; - file_browser_worker_get_filename( + path_extract_filename( item->path, filename, (model->hide_ext) && (item_type == BrowserItemTypeFile)); } else { string_set_str(filename, "---"); @@ -505,9 +507,9 @@ static bool file_browser_view_input_callback(InputEvent* event, void* context) { file_browser_worker_folder_enter( browser->worker, selected_item->path, select_index); } else if(selected_item->type == BrowserItemTypeFile) { - string_set(*(browser->result_path), selected_item->path); + string_set(browser->result_path, selected_item->path); if(browser->callback) { - browser->callback(browser->context, true); + browser->callback(browser->context); } } } diff --git a/applications/gui/modules/file_browser.h b/applications/gui/modules/file_browser.h index b77c6e65c..ebc64509a 100644 --- a/applications/gui/modules/file_browser.h +++ b/applications/gui/modules/file_browser.h @@ -13,9 +13,9 @@ extern "C" { #endif typedef struct FileBrowser FileBrowser; -typedef void (*FileBrowserCallback)(void* context, bool state); +typedef void (*FileBrowserCallback)(void* context); -FileBrowser* file_browser_alloc(string_t* result_path); +FileBrowser* file_browser_alloc(string_ptr result_path); void file_browser_free(FileBrowser* browser); @@ -23,7 +23,7 @@ View* file_browser_get_view(FileBrowser* browser); void file_browser_configure( FileBrowser* browser, - char* extension, + const char* extension, bool skip_assets, const Icon* file_icon, bool hide_ext); diff --git a/applications/gui/modules/file_browser_worker.c b/applications/gui/modules/file_browser_worker.c index 13fc97111..93baba008 100644 --- a/applications/gui/modules/file_browser_worker.c +++ b/applications/gui/modules/file_browser_worker.c @@ -8,6 +8,7 @@ #include #include #include +#include "toolbox/path.h" #define TAG "BrowserWorker" @@ -149,6 +150,7 @@ static bool browser_folder_init( (*item_cnt)++; } if(total_files_cnt == LONG_LOAD_THRESHOLD) { + // There are too many files in folder and counting them will take some time - send callback to app if(browser->long_load_cb) { browser->long_load_cb(browser->cb_ctx); } @@ -255,7 +257,7 @@ static int32_t browser_worker(void* context) { string_t filename; string_init(filename); if(browser_path_is_file(browser->path_next)) { - file_browser_worker_get_filename(browser->path_next, filename, false); + path_extract_filename(browser->path_next, filename, false); } osThreadFlagsSet(furi_thread_get_thread_id(browser->thread), WorkerEvtFolderEnter); @@ -319,21 +321,7 @@ static int32_t browser_worker(void* context) { return 0; } -void file_browser_worker_get_filename(string_t path, string_t name, bool trim_ext) { - size_t filename_start = string_search_rchar(path, '/'); - if(filename_start > 0) { - filename_start++; - string_set_n(name, path, filename_start, string_size(path) - filename_start); - } - if(trim_ext) { - size_t dot = string_search_rchar(name, '.'); - if(dot > 0) { - string_left(name, dot); - } - } -} - -BrowserWorker* file_browser_worker_alloc(string_t path, char* filter_ext, bool skip_assets) { +BrowserWorker* file_browser_worker_alloc(string_t path, const char* filter_ext, bool skip_assets) { BrowserWorker* browser = malloc(sizeof(BrowserWorker)); idx_last_array_init(browser->idx_last); diff --git a/applications/gui/modules/file_browser_worker.h b/applications/gui/modules/file_browser_worker.h index 821d5103f..b0d360a38 100644 --- a/applications/gui/modules/file_browser_worker.h +++ b/applications/gui/modules/file_browser_worker.h @@ -22,9 +22,7 @@ typedef void (*BrowserWorkerListItemCallback)( bool is_last); typedef void (*BrowserWorkerLongLoadCallback)(void* context); -void file_browser_worker_get_filename(string_t path, string_t name, bool trim_ext); - -BrowserWorker* file_browser_worker_alloc(string_t path, char* filter_ext, bool skip_assets); +BrowserWorker* file_browser_worker_alloc(string_t path, const char* filter_ext, bool skip_assets); void file_browser_worker_free(BrowserWorker* browser); diff --git a/applications/gui/modules/file_select.c b/applications/gui/modules/file_select.c deleted file mode 100644 index 14541196b..000000000 --- a/applications/gui/modules/file_select.c +++ /dev/null @@ -1,475 +0,0 @@ -#include "file_select.h" -#include -#include -#include - -#define FILENAME_COUNT 4 - -struct FileSelect { - // public - View* view; - Storage* fs_api; - const char* path; - const char* extension; - - bool init_completed; - - FileSelectCallback callback; - void* context; - - char* buffer; - uint8_t buffer_size; -}; - -typedef struct { - string_t filename[FILENAME_COUNT]; - uint8_t position; - - uint16_t first_file_index; - uint16_t file_count; - -} FileSelectModel; - -bool file_select_fill_strings(FileSelect* file_select); -bool file_select_fill_count(FileSelect* file_select); -static bool file_select_init_inner(FileSelect* file_select); - -static void file_select_draw_callback(Canvas* canvas, void* _model) { - FileSelectModel* model = _model; - - string_t string_buff; - const uint8_t item_height = 16; - const uint8_t item_width = 123; - const uint8_t text_max_width = 115; - - canvas_clear(canvas); - canvas_set_font(canvas, FontSecondary); - - if(model->file_count) { - for(uint8_t i = 0; i < MIN(FILENAME_COUNT, model->file_count); i++) { - if(i == model->position) { - canvas_set_color(canvas, ColorBlack); - canvas_draw_box(canvas, 0, (i * item_height) + 1, item_width, item_height - 2); - - canvas_set_color(canvas, ColorWhite); - canvas_draw_dot(canvas, 0, (i * item_height) + 1); - canvas_draw_dot(canvas, 0, (i * item_height) + item_height - 2); - canvas_draw_dot(canvas, item_width - 1, (i * item_height) + 1); - canvas_draw_dot(canvas, item_width - 1, (i * item_height) + item_height - 2); - } else { - canvas_set_color(canvas, ColorBlack); - } - - string_init_set(string_buff, model->filename[i]); - elements_string_fit_width(canvas, string_buff, text_max_width); - canvas_draw_str( - canvas, 6, (i * item_height) + item_height - 4, string_get_cstr(string_buff)); - - string_clear(string_buff); - } - } else { - canvas_draw_str(canvas, 6, item_height, "Empty folder"); - } - elements_scrollbar(canvas, model->first_file_index + model->position, model->file_count); -} - -static bool file_select_input_callback(InputEvent* event, void* context) { - FileSelect* file_select = (FileSelect*)context; - bool consumed = false; - - if((event->type == InputTypeShort) | (event->type == InputTypeRepeat)) { - if(!file_select->init_completed) { - if(!file_select_init_inner(file_select)) { - file_select->callback(false, file_select->context); - } - } else if(event->key == InputKeyUp) { - with_view_model( - file_select->view, (FileSelectModel * model) { - if(model->position == 0) { - if(model->first_file_index == 0) { - // wrap - int16_t max_first_file_index = model->file_count - FILENAME_COUNT; - model->position = MIN(FILENAME_COUNT - 1, model->file_count - 1); - model->first_file_index = - max_first_file_index < 0 ? 0 : max_first_file_index; - } else { - model->first_file_index--; - } - } else if(model->position == 1) { - if(model->first_file_index == 0) { - model->position--; - } else { - model->first_file_index--; - } - } else { - model->position--; - } - return true; - }); - consumed = true; - if(!file_select_fill_strings(file_select)) { - file_select->callback(false, file_select->context); - } - } else if(event->key == InputKeyDown) { - with_view_model( - file_select->view, (FileSelectModel * model) { - uint16_t max_first_file_index = model->file_count > FILENAME_COUNT ? - model->file_count - FILENAME_COUNT : - 0; - - if(model->position >= MIN(FILENAME_COUNT - 1, model->file_count - 1)) { - if(model->first_file_index >= max_first_file_index) { - // wrap - model->position = 0; - model->first_file_index = 0; - } else { - model->first_file_index++; - } - } else if(model->position >= (FILENAME_COUNT - 2)) { - if(model->first_file_index >= max_first_file_index) { - model->position++; - } else { - model->first_file_index++; - } - } else { - model->position++; - } - return true; - }); - consumed = true; - if(!file_select_fill_strings(file_select)) { - file_select->callback(false, file_select->context); - } - } else if(event->key == InputKeyOk) { - if(file_select->callback != NULL) { - size_t files = 0; - if(file_select->buffer) { - with_view_model( - file_select->view, (FileSelectModel * model) { - files = model->file_count; - strlcpy( - file_select->buffer, - string_get_cstr(model->filename[model->position]), - file_select->buffer_size); - - return false; - }); - }; - if(files > 0) { - file_select->callback(true, file_select->context); - } - } - consumed = true; - } - } - - return consumed; -} - -static bool file_select_init_inner(FileSelect* file_select) { - bool result = false; - if(file_select->path && file_select->extension && file_select->fs_api) { - if(file_select_fill_count(file_select)) { - if(file_select_fill_strings(file_select)) { - file_select->init_completed = true; - result = true; - } - } - } - - return result; -} - -FileSelect* file_select_alloc() { - FileSelect* file_select = malloc(sizeof(FileSelect)); - file_select->view = view_alloc(); - file_select->fs_api = furi_record_open("storage"); - - view_set_context(file_select->view, file_select); - view_allocate_model(file_select->view, ViewModelTypeLockFree, sizeof(FileSelectModel)); - view_set_draw_callback(file_select->view, file_select_draw_callback); - view_set_input_callback(file_select->view, file_select_input_callback); - - with_view_model( - file_select->view, (FileSelectModel * model) { - for(uint8_t i = 0; i < FILENAME_COUNT; i++) { - string_init(model->filename[i]); - } - - model->first_file_index = 0; - model->file_count = 0; - return false; - }); - - return file_select; -} - -void file_select_free(FileSelect* file_select) { - furi_assert(file_select); - with_view_model( - file_select->view, (FileSelectModel * model) { - for(uint8_t i = 0; i < FILENAME_COUNT; i++) { - string_clear(model->filename[i]); - } - return false; - }); - view_free(file_select->view); - free(file_select); - furi_record_close("storage"); -} - -View* file_select_get_view(FileSelect* file_select) { - furi_assert(file_select); - return file_select->view; -} - -void file_select_set_callback(FileSelect* file_select, FileSelectCallback callback, void* context) { - file_select->context = context; - file_select->callback = callback; -} - -void file_select_set_filter(FileSelect* file_select, const char* path, const char* extension) { - furi_assert(file_select); - file_select->path = path; - file_select->extension = extension; -} - -void file_select_set_result_buffer(FileSelect* file_select, char* buffer, uint8_t buffer_size) { - file_select->buffer = buffer; - file_select->buffer_size = buffer_size; - - if(file_select->buffer) { - strlcpy(file_select->buffer, "", file_select->buffer_size); - } -} - -bool file_select_init(FileSelect* file_select) { - if(!file_select_init_inner(file_select)) { - file_select->callback(false, file_select->context); - return false; - } else { - return true; - } -} - -static bool filter_file(FileSelect* file_select, FileInfo* file_info, char* name) { - bool result = false; - - if(!(file_info->flags & FSF_DIRECTORY)) { - if(strcmp(file_select->extension, "*") == 0) { - result = true; - } else if(strstr(name, file_select->extension) != NULL) { - result = true; - } - } - - return result; -} - -bool file_select_fill_strings(FileSelect* file_select) { - furi_assert(file_select); - furi_assert(file_select->fs_api); - furi_assert(file_select->path); - furi_assert(file_select->extension); - - FileInfo file_info; - File* directory = storage_file_alloc(file_select->fs_api); - - uint8_t string_counter = 0; - uint16_t file_counter = 0; - const uint8_t name_length = 100; - char* name = malloc(name_length); - uint16_t first_file_index = 0; - - with_view_model( - file_select->view, (FileSelectModel * model) { - first_file_index = model->first_file_index; - return false; - }); - - if(!storage_dir_open(directory, file_select->path)) { - storage_dir_close(directory); - storage_file_free(directory); - free(name); - return true; - } - - while(1) { - if(!storage_dir_read(directory, &file_info, name, name_length)) { - break; - } - - if(storage_file_get_error(directory) == FSE_OK) { - if(filter_file(file_select, &file_info, name)) { - if(file_counter >= first_file_index) { - with_view_model( - file_select->view, (FileSelectModel * model) { - string_set_str(model->filename[string_counter], name); - - if(strcmp(file_select->extension, "*") != 0) { - string_replace_all_str( - model->filename[string_counter], file_select->extension, ""); - } - - return true; - }); - string_counter++; - - if(string_counter >= FILENAME_COUNT) { - break; - } - } - file_counter++; - } - } else { - storage_dir_close(directory); - storage_file_free(directory); - free(name); - return false; - } - } - - storage_dir_close(directory); - storage_file_free(directory); - free(name); - return true; -} - -bool file_select_fill_count(FileSelect* file_select) { - furi_assert(file_select); - furi_assert(file_select->fs_api); - furi_assert(file_select->path); - furi_assert(file_select->extension); - - FileInfo file_info; - File* directory = storage_file_alloc(file_select->fs_api); - - uint16_t file_counter = 0; - const uint8_t name_length = 100; - char* name = malloc(name_length); - - if(!storage_dir_open(directory, file_select->path)) { - storage_dir_close(directory); - storage_file_free(directory); - free(name); - return true; - } - - while(1) { - if(!storage_dir_read(directory, &file_info, name, name_length)) { - break; - } - - if(storage_file_get_error(directory) == FSE_OK) { - if(filter_file(file_select, &file_info, name)) { - file_counter++; - } - } else { - storage_dir_close(directory); - storage_file_free(directory); - free(name); - return false; - } - } - - with_view_model( - file_select->view, (FileSelectModel * model) { - model->file_count = file_counter; - return false; - }); - - storage_dir_close(directory); - storage_file_free(directory); - free(name); - return true; -} - -void file_select_set_selected_file_internal(FileSelect* file_select, const char* filename) { - furi_assert(file_select); - furi_assert(filename); - furi_assert(file_select->fs_api); - furi_assert(file_select->path); - furi_assert(file_select->extension); - - if(strlen(filename) == 0) return; - - FileInfo file_info; - File* directory = storage_file_alloc(file_select->fs_api); - - const uint8_t name_length = 100; - char* name = malloc(name_length); - uint16_t file_position = 0; - bool file_found = false; - - string_t filename_str; - string_init_set_str(filename_str, filename); - if(strcmp(file_select->extension, "*") != 0) { - string_cat_str(filename_str, file_select->extension); - } - - if(!storage_dir_open(directory, file_select->path)) { - string_clear(filename_str); - storage_dir_close(directory); - storage_file_free(directory); - free(name); - return; - } - - while(1) { - if(!storage_dir_read(directory, &file_info, name, name_length)) { - break; - } - - if(storage_file_get_error(directory) == FSE_OK) { - if(filter_file(file_select, &file_info, name)) { - if(strcmp(string_get_cstr(filename_str), name) == 0) { - file_found = true; - break; - } - - file_position++; - } - } else { - string_clear(filename_str); - storage_dir_close(directory); - storage_file_free(directory); - free(name); - return; - } - } - - if(file_found) { - with_view_model( - file_select->view, (FileSelectModel * model) { - uint16_t max_first_file_index = - model->file_count > FILENAME_COUNT ? model->file_count - FILENAME_COUNT : 0; - - model->first_file_index = file_position; - - if(model->first_file_index > 0) { - model->first_file_index -= 1; - } - - if(model->first_file_index >= max_first_file_index) { - model->first_file_index = max_first_file_index; - } - - model->position = file_position - model->first_file_index; - - return true; - }); - } - - string_clear(filename_str); - storage_dir_close(directory); - storage_file_free(directory); - free(name); -} - -void file_select_set_selected_file(FileSelect* file_select, const char* filename) { - file_select_set_selected_file_internal(file_select, filename); - - if(!file_select_fill_strings(file_select)) { - file_select->callback(false, file_select->context); - } -} diff --git a/applications/gui/modules/file_select.h b/applications/gui/modules/file_select.h deleted file mode 100644 index ed3d5b60c..000000000 --- a/applications/gui/modules/file_select.h +++ /dev/null @@ -1,31 +0,0 @@ -/** - * @file file_select.h - * GUI: FileSelect view module API - */ - -#pragma once - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct FileSelect FileSelect; - -typedef void (*FileSelectCallback)(bool result, void* context); - -FileSelect* file_select_alloc(); - -void file_select_free(FileSelect* file_select); -View* file_select_get_view(FileSelect* file_select); - -void file_select_set_callback(FileSelect* file_select, FileSelectCallback callback, void* context); -void file_select_set_filter(FileSelect* file_select, const char* path, const char* extension); -void file_select_set_result_buffer(FileSelect* file_select, char* buffer, uint8_t buffer_size); -bool file_select_init(FileSelect* file_select); -void file_select_set_selected_file(FileSelect* file_select, const char* filename); - -#ifdef __cplusplus -} -#endif diff --git a/applications/gui/modules/validators.c b/applications/gui/modules/validators.c index 242dbe682..546423d02 100644 --- a/applications/gui/modules/validators.c +++ b/applications/gui/modules/validators.c @@ -3,7 +3,7 @@ #include "applications/storage/storage.h" struct ValidatorIsFile { - const char* app_path_folder; + char* app_path_folder; const char* app_extension; char* current_name; }; @@ -40,7 +40,7 @@ ValidatorIsFile* validator_is_file_alloc_init( const char* current_name) { ValidatorIsFile* instance = malloc(sizeof(ValidatorIsFile)); - instance->app_path_folder = app_path_folder; + instance->app_path_folder = strdup(app_path_folder); instance->app_extension = app_extension; instance->current_name = strdup(current_name); @@ -49,6 +49,7 @@ ValidatorIsFile* validator_is_file_alloc_init( void validator_is_file_free(ValidatorIsFile* instance) { furi_assert(instance); + free(instance->app_path_folder); free(instance->current_name); free(instance); } diff --git a/applications/ibutton/ibutton.c b/applications/ibutton/ibutton.c index a38f077f3..b1b5bf62f 100644 --- a/applications/ibutton/ibutton.c +++ b/applications/ibutton/ibutton.c @@ -1,7 +1,8 @@ #include "ibutton.h" +#include "assets_icons.h" #include "ibutton_i.h" #include "ibutton/scenes/ibutton_scene.h" - +#include "m-string.h" #include #include @@ -85,6 +86,8 @@ void ibutton_tick_event_callback(void* context) { iButton* ibutton_alloc() { iButton* ibutton = malloc(sizeof(iButton)); + string_init(ibutton->file_path); + ibutton->scene_manager = scene_manager_alloc(&ibutton_scene_handlers, ibutton); ibutton->view_dispatcher = view_dispatcher_alloc(); @@ -176,49 +179,28 @@ void ibutton_free(iButton* ibutton) { ibutton_worker_free(ibutton->key_worker); ibutton_key_free(ibutton->key); + string_clear(ibutton->file_path); + free(ibutton); } bool ibutton_file_select(iButton* ibutton) { - bool success = dialog_file_select_show( + bool success = dialog_file_browser_show( ibutton->dialogs, - IBUTTON_APP_FOLDER, + ibutton->file_path, + ibutton->file_path, IBUTTON_APP_EXTENSION, - ibutton->file_name, - IBUTTON_FILE_NAME_SIZE, - ibutton_key_get_name_p(ibutton->key)); + true, + &I_ibutt_10px, + true); if(success) { - string_t key_str; - string_init_printf( - key_str, "%s/%s%s", IBUTTON_APP_FOLDER, ibutton->file_name, IBUTTON_APP_EXTENSION); - success = ibutton_load_key_data(ibutton, key_str); - - if(success) { - ibutton_key_set_name(ibutton->key, ibutton->file_name); - } - - string_clear(key_str); + success = ibutton_load_key_data(ibutton, ibutton->file_path); } return success; } -bool ibutton_load_key(iButton* ibutton, const char* key_name) { - string_t key_path; - string_init_set_str(key_path, key_name); - - const bool success = ibutton_load_key_data(ibutton, key_path); - - if(success) { - path_extract_filename_no_ext(key_name, key_path); - ibutton_key_set_name(ibutton->key, string_get_cstr(key_path)); - } - - string_clear(key_path); - return success; -} - bool ibutton_save_key(iButton* ibutton, const char* key_name) { // Create ibutton directory if necessary ibutton_make_app_folder(ibutton); @@ -226,27 +208,22 @@ bool ibutton_save_key(iButton* ibutton, const char* key_name) { FlipperFormat* file = flipper_format_file_alloc(ibutton->storage); iButtonKey* key = ibutton->key; - string_t key_file_name; bool result = false; - string_init(key_file_name); do { // First remove key if it was saved (we rename the key) - if(!ibutton_delete_key(ibutton)) break; - - // Save the key - ibutton_key_set_name(key, key_name); + ibutton_delete_key(ibutton); // Set full file name, for new key - string_printf( - key_file_name, - "%s/%s%s", - IBUTTON_APP_FOLDER, - ibutton_key_get_name_p(key), - IBUTTON_APP_EXTENSION); + if(string_end_with_str_p(ibutton->file_path, IBUTTON_APP_EXTENSION)) { + size_t filename_start = string_search_rchar(ibutton->file_path, '/'); + string_left(ibutton->file_path, filename_start); + } + + string_cat_printf(ibutton->file_path, "/%s%s", key_name, IBUTTON_APP_EXTENSION); // Open file for write - if(!flipper_format_file_open_always(file, string_get_cstr(key_file_name))) break; + if(!flipper_format_file_open_always(file, string_get_cstr(ibutton->file_path))) break; // Write header if(!flipper_format_write_header_cstr(file, IBUTTON_APP_FILE_TYPE, 1)) break; @@ -271,8 +248,6 @@ bool ibutton_save_key(iButton* ibutton, const char* key_name) { flipper_format_free(file); - string_clear(key_file_name); - if(!result) { dialog_message_show_storage_error(ibutton->dialogs, "Cannot save\nkey file"); } @@ -281,17 +256,8 @@ bool ibutton_save_key(iButton* ibutton, const char* key_name) { } bool ibutton_delete_key(iButton* ibutton) { - string_t file_name; bool result = false; - - string_init_printf( - file_name, - "%s/%s%s", - IBUTTON_APP_FOLDER, - ibutton_key_get_name_p(ibutton->key), - IBUTTON_APP_EXTENSION); - result = storage_simply_remove(ibutton->storage, string_get_cstr(file_name)); - string_clear(file_name); + result = storage_simply_remove(ibutton->storage, string_get_cstr(ibutton->file_path)); return result; } @@ -335,8 +301,17 @@ int32_t ibutton_app(void* p) { ibutton_make_app_folder(ibutton); - if(p && ibutton_load_key(ibutton, (const char*)p)) { - // TODO: Display an error if the key from p could not be loaded + bool key_loaded = false; + + if(p) { + string_set_str(ibutton->file_path, (const char*)p); + if(ibutton_load_key_data(ibutton, ibutton->file_path)) { + key_loaded = true; + // TODO: Display an error if the key from p could not be loaded + } + } + + if(key_loaded) { scene_manager_next_scene(ibutton->scene_manager, iButtonSceneEmulate); } else { scene_manager_next_scene(ibutton->scene_manager, iButtonSceneStart); diff --git a/applications/ibutton/ibutton_i.h b/applications/ibutton/ibutton_i.h index 36857fd64..e66712bee 100644 --- a/applications/ibutton/ibutton_i.h +++ b/applications/ibutton/ibutton_i.h @@ -41,7 +41,7 @@ struct iButton { iButtonWorker* key_worker; iButtonKey* key; - char file_name[IBUTTON_FILE_NAME_SIZE]; + string_t file_path; char text_store[IBUTTON_TEXT_STORE_SIZE + 1]; Submenu* submenu; @@ -74,7 +74,6 @@ typedef enum { } iButtonNotificationMessage; bool ibutton_file_select(iButton* ibutton); -bool ibutton_load_key(iButton* ibutton, const char* key_name); bool ibutton_save_key(iButton* ibutton, const char* key_name); bool ibutton_delete_key(iButton* ibutton); void ibutton_text_store_set(iButton* ibutton, const char* text, ...); diff --git a/applications/ibutton/scenes/ibutton_scene_add_type.c b/applications/ibutton/scenes/ibutton_scene_add_type.c index db129295a..273330e71 100644 --- a/applications/ibutton/scenes/ibutton_scene_add_type.c +++ b/applications/ibutton/scenes/ibutton_scene_add_type.c @@ -1,4 +1,5 @@ #include "../ibutton_i.h" +#include "m-string.h" enum SubmenuIndex { SubmenuIndexCyfral, @@ -44,7 +45,7 @@ bool ibutton_scene_add_type_on_event(void* context, SceneManagerEvent event) { furi_crash("Unknown key type"); } - ibutton_key_set_name(key, ""); + string_set_str(ibutton->file_path, IBUTTON_APP_FOLDER); ibutton_key_clear_data(key); scene_manager_next_scene(ibutton->scene_manager, iButtonSceneAddValue); } diff --git a/applications/ibutton/scenes/ibutton_scene_delete_confirm.c b/applications/ibutton/scenes/ibutton_scene_delete_confirm.c index 73ea97cc6..51f1f2794 100644 --- a/applications/ibutton/scenes/ibutton_scene_delete_confirm.c +++ b/applications/ibutton/scenes/ibutton_scene_delete_confirm.c @@ -1,4 +1,5 @@ #include "../ibutton_i.h" +#include static void ibutton_scene_delete_confirm_widget_callback( GuiButtonType result, @@ -16,7 +17,11 @@ void ibutton_scene_delete_confirm_on_enter(void* context) { iButtonKey* key = ibutton->key; const uint8_t* key_data = ibutton_key_get_data_p(key); - ibutton_text_store_set(ibutton, "\e#Delete %s?\e#", ibutton_key_get_name_p(key)); + string_t key_name; + string_init(key_name); + path_extract_filename(ibutton->file_path, key_name, true); + + ibutton_text_store_set(ibutton, "\e#Delete %s?\e#", string_get_cstr(key_name)); widget_add_text_box_element( widget, 0, 0, 128, 27, AlignCenter, AlignCenter, ibutton->text_store, false); widget_add_button_element( @@ -62,6 +67,8 @@ void ibutton_scene_delete_confirm_on_enter(void* context) { widget, 64, 33, AlignCenter, AlignBottom, FontSecondary, ibutton->text_store); view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget); + + string_clear(key_name); } bool ibutton_scene_delete_confirm_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/ibutton/scenes/ibutton_scene_emulate.c b/applications/ibutton/scenes/ibutton_scene_emulate.c index 8ffe73b66..590223979 100644 --- a/applications/ibutton/scenes/ibutton_scene_emulate.c +++ b/applications/ibutton/scenes/ibutton_scene_emulate.c @@ -1,5 +1,6 @@ #include "../ibutton_i.h" #include +#include static void ibutton_scene_emulate_callback(void* context, bool emulated) { iButton* ibutton = context; @@ -15,14 +16,19 @@ void ibutton_scene_emulate_on_enter(void* context) { iButtonKey* key = ibutton->key; const uint8_t* key_data = ibutton_key_get_data_p(key); - const char* key_name = ibutton_key_get_name_p(key); + + string_t key_name; + string_init(key_name); + if(string_end_with_str_p(ibutton->file_path, IBUTTON_APP_EXTENSION)) { + path_extract_filename(ibutton->file_path, key_name, true); + } uint8_t line_count = 2; DOLPHIN_DEED(DolphinDeedIbuttonEmulate); // check that stored key has name - if(strcmp(key_name, "") != 0) { - ibutton_text_store_set(ibutton, "emulating\n%s", key_name); + if(!string_empty_p(key_name)) { + ibutton_text_store_set(ibutton, "emulating\n%s", string_get_cstr(key_name)); line_count = 2; } else { // if not, show key data @@ -77,6 +83,8 @@ void ibutton_scene_emulate_on_enter(void* context) { ibutton_worker_emulate_set_callback( ibutton->key_worker, ibutton_scene_emulate_callback, ibutton); ibutton_worker_emulate_start(ibutton->key_worker, key); + + string_clear(key_name); } bool ibutton_scene_emulate_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/ibutton/scenes/ibutton_scene_info.c b/applications/ibutton/scenes/ibutton_scene_info.c index 5b0af1d8f..bd364ada8 100644 --- a/applications/ibutton/scenes/ibutton_scene_info.c +++ b/applications/ibutton/scenes/ibutton_scene_info.c @@ -1,4 +1,5 @@ #include "../ibutton_i.h" +#include void ibutton_scene_info_on_enter(void* context) { iButton* ibutton = context; @@ -7,7 +8,11 @@ void ibutton_scene_info_on_enter(void* context) { const uint8_t* key_data = ibutton_key_get_data_p(key); - ibutton_text_store_set(ibutton, "%s", ibutton_key_get_name_p(key)); + string_t key_name; + string_init(key_name); + path_extract_filename(ibutton->file_path, key_name, true); + + ibutton_text_store_set(ibutton, "%s", string_get_cstr(key_name)); widget_add_text_box_element( widget, 0, 0, 128, 28, AlignCenter, AlignCenter, ibutton->text_store, false); @@ -46,6 +51,8 @@ void ibutton_scene_info_on_enter(void* context) { widget, 64, 35, AlignCenter, AlignBottom, FontPrimary, ibutton->text_store); view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget); + + string_clear(key_name); } bool ibutton_scene_info_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/ibutton/scenes/ibutton_scene_read.c b/applications/ibutton/scenes/ibutton_scene_read.c index a25f27e60..0cc0a8dff 100644 --- a/applications/ibutton/scenes/ibutton_scene_read.c +++ b/applications/ibutton/scenes/ibutton_scene_read.c @@ -18,7 +18,7 @@ void ibutton_scene_read_on_enter(void* context) { popup_set_icon(popup, 0, 5, &I_DolphinWait_61x59); view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewPopup); - ibutton_key_set_name(key, ""); + string_set_str(ibutton->file_path, IBUTTON_APP_FOLDER); ibutton_worker_read_set_callback(worker, ibutton_scene_read_callback, ibutton); ibutton_worker_read_start(worker, key); diff --git a/applications/ibutton/scenes/ibutton_scene_save_name.c b/applications/ibutton/scenes/ibutton_scene_save_name.c index b1baf6afc..6caf5d2d5 100644 --- a/applications/ibutton/scenes/ibutton_scene_save_name.c +++ b/applications/ibutton/scenes/ibutton_scene_save_name.c @@ -1,5 +1,7 @@ #include "../ibutton_i.h" +#include "m-string.h" #include +#include static void ibutton_scene_save_name_text_input_callback(void* context) { iButton* ibutton = context; @@ -10,13 +12,17 @@ void ibutton_scene_save_name_on_enter(void* context) { iButton* ibutton = context; TextInput* text_input = ibutton->text_input; - const char* key_name = ibutton_key_get_name_p(ibutton->key); - const bool key_name_is_empty = !strcmp(key_name, ""); + string_t key_name; + string_init(key_name); + if(string_end_with_str_p(ibutton->file_path, IBUTTON_APP_EXTENSION)) { + path_extract_filename(ibutton->file_path, key_name, true); + } + const bool key_name_is_empty = string_empty_p(key_name); if(key_name_is_empty) { set_random_name(ibutton->text_store, IBUTTON_TEXT_STORE_SIZE); } else { - ibutton_text_store_set(ibutton, "%s", key_name); + ibutton_text_store_set(ibutton, "%s", string_get_cstr(key_name)); } text_input_set_header_text(text_input, "Name the key"); @@ -28,11 +34,19 @@ void ibutton_scene_save_name_on_enter(void* context) { IBUTTON_KEY_NAME_SIZE, key_name_is_empty); - ValidatorIsFile* validator_is_file = - validator_is_file_alloc_init(IBUTTON_APP_FOLDER, IBUTTON_APP_EXTENSION, key_name); + string_t folder_path; + string_init(folder_path); + + path_extract_dirname(string_get_cstr(ibutton->file_path), folder_path); + + ValidatorIsFile* validator_is_file = validator_is_file_alloc_init( + string_get_cstr(folder_path), IBUTTON_APP_EXTENSION, string_get_cstr(key_name)); text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewTextInput); + + string_clear(key_name); + string_clear(folder_path); } bool ibutton_scene_save_name_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/ibutton/scenes/ibutton_scene_start.c b/applications/ibutton/scenes/ibutton_scene_start.c index a3141f5ad..cc8af9839 100644 --- a/applications/ibutton/scenes/ibutton_scene_start.c +++ b/applications/ibutton/scenes/ibutton_scene_start.c @@ -36,6 +36,7 @@ bool ibutton_scene_start_on_event(void* context, SceneManagerEvent event) { if(event.event == SubmenuIndexRead) { scene_manager_next_scene(ibutton->scene_manager, iButtonSceneRead); } else if(event.event == SubmenuIndexSaved) { + string_set_str(ibutton->file_path, IBUTTON_APP_FOLDER); scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSelectKey); } else if(event.event == SubmenuIndexAdd) { scene_manager_next_scene(ibutton->scene_manager, iButtonSceneAddType); diff --git a/applications/ibutton/scenes/ibutton_scene_write.c b/applications/ibutton/scenes/ibutton_scene_write.c index 35e45d83b..4ce19408a 100644 --- a/applications/ibutton/scenes/ibutton_scene_write.c +++ b/applications/ibutton/scenes/ibutton_scene_write.c @@ -1,4 +1,6 @@ #include "../ibutton_i.h" +#include "m-string.h" +#include "toolbox/path.h" typedef enum { iButtonSceneWriteStateDefault, @@ -17,13 +19,18 @@ void ibutton_scene_write_on_enter(void* context) { iButtonWorker* worker = ibutton->key_worker; const uint8_t* key_data = ibutton_key_get_data_p(key); - const char* key_name = ibutton_key_get_name_p(key); + + string_t key_name; + string_init(key_name); + if(string_end_with_str_p(ibutton->file_path, IBUTTON_APP_EXTENSION)) { + path_extract_filename(ibutton->file_path, key_name, true); + } uint8_t line_count = 2; // check that stored key has name - if(strcmp(key_name, "") != 0) { - ibutton_text_store_set(ibutton, "writing\n%s", key_name); + if(!string_empty_p(key_name)) { + ibutton_text_store_set(ibutton, "writing\n%s", string_get_cstr(key_name)); line_count = 2; } else { // if not, show key data @@ -79,6 +86,8 @@ void ibutton_scene_write_on_enter(void* context) { ibutton_worker_write_set_callback(worker, ibutton_scene_write_callback, ibutton); ibutton_worker_write_start(worker, key); + + string_clear(key_name); } bool ibutton_scene_write_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/infrared/infrared_app.cpp b/applications/infrared/infrared_app.cpp index 5dc3b311d..1ac859d10 100644 --- a/applications/infrared/infrared_app.cpp +++ b/applications/infrared/infrared_app.cpp @@ -1,4 +1,5 @@ #include "infrared_app.h" +#include "m-string.h" #include #include #include @@ -12,20 +13,18 @@ int32_t InfraredApp::run(void* args) { bool exit = false; if(args) { - std::string path = static_cast(args); - std::string remote_name(path, path.find_last_of('/') + 1, path.size()); - auto last_dot = remote_name.find_last_of('.'); - if(last_dot != std::string::npos) { - remote_name.erase(last_dot); - path.erase(path.find_last_of('/')); - bool result = remote_manager.load(path, remote_name); + string_t path; + string_init_set_str(path, (char*)args); + if(string_end_with_str_p(path, InfraredApp::infrared_extension)) { + bool result = remote_manager.load(path); if(result) { current_scene = InfraredApp::Scene::Remote; } else { - printf("Failed to load remote \'%s\'\r\n", remote_name.c_str()); + printf("Failed to load remote \'%s\'\r\n", string_get_cstr(path)); return -1; } } + string_clear(path); } scenes[current_scene]->on_enter(this); @@ -51,6 +50,7 @@ int32_t InfraredApp::run(void* args) { InfraredApp::InfraredApp() { furi_check(InfraredAppRemoteManager::max_button_name_length < get_text_store_size()); + string_init_set_str(file_path, InfraredApp::infrared_directory); notification = static_cast(furi_record_open("notification")); dialogs = static_cast(furi_record_open("dialogs")); infrared_worker = infrared_worker_alloc(); @@ -60,6 +60,7 @@ InfraredApp::~InfraredApp() { infrared_worker_free(infrared_worker); furi_record_close("notification"); furi_record_close("dialogs"); + string_clear(file_path); for(auto& [key, scene] : scenes) delete scene; } diff --git a/applications/infrared/infrared_app.h b/applications/infrared/infrared_app.h index e0db7c51b..1cb8b6617 100644 --- a/applications/infrared/infrared_app.h +++ b/applications/infrared/infrared_app.h @@ -251,6 +251,8 @@ public: /** Main class destructor, deinitializes all critical objects */ ~InfraredApp(); + string_t file_path; + /** Path to Infrared directory */ static constexpr const char* infrared_directory = "/any/infrared"; /** Infrared files extension (remote files and universal databases) */ diff --git a/applications/infrared/infrared_app_remote_manager.cpp b/applications/infrared/infrared_app_remote_manager.cpp index 4fd645532..faeccb39e 100644 --- a/applications/infrared/infrared_app_remote_manager.cpp +++ b/applications/infrared/infrared_app_remote_manager.cpp @@ -1,3 +1,5 @@ +#include "m-string.h" +#include "storage/filesystem_api_defines.h" #include #include "infrared_app_remote_manager.h" #include "infrared/helpers/infrared_parser.h" @@ -11,44 +13,58 @@ #include #include #include "infrared_app.h" +#include static const char* default_remote_name = "remote"; -std::string InfraredAppRemoteManager::make_full_name( - const std::string& path, - const std::string& remote_name) const { - return std::string("") + path + "/" + remote_name + InfraredApp::infrared_extension; -} - -std::string InfraredAppRemoteManager::find_vacant_remote_name(const std::string& name) { - std::string result_name; +void InfraredAppRemoteManager::find_vacant_remote_name(string_t name, string_t path) { Storage* storage = static_cast(furi_record_open("storage")); - FS_Error error = storage_common_stat( - storage, make_full_name(InfraredApp::infrared_directory, name).c_str(), NULL); + string_t base_path; + string_init_set(base_path, path); - if(error == FSE_NOT_EXIST) { - result_name = name; - } else if(error != FSE_OK) { - result_name = std::string(); - } else { + if(string_end_with_str_p(base_path, InfraredApp::infrared_extension)) { + size_t filename_start = string_search_rchar(base_path, '/'); + string_left(base_path, filename_start); + } + + string_printf( + base_path, + "%s/%s%s", + string_get_cstr(path), + string_get_cstr(name), + InfraredApp::infrared_extension); + + FS_Error error = storage_common_stat(storage, string_get_cstr(base_path), NULL); + + if(error == FSE_OK) { /* if suggested name is occupied, try another one (name2, name3, etc) */ + size_t dot = string_search_rchar(base_path, '.'); + string_left(base_path, dot); + + string_t path_temp; + string_init(path_temp); + uint32_t i = 1; - std::string new_name; do { - new_name = make_full_name(InfraredApp::infrared_directory, name + std::to_string(++i)); - error = storage_common_stat(storage, new_name.c_str(), NULL); + string_printf( + path_temp, + "%s%u%s", + string_get_cstr(base_path), + ++i, + InfraredApp::infrared_extension); + error = storage_common_stat(storage, string_get_cstr(path_temp), NULL); } while(error == FSE_OK); + string_clear(path_temp); + if(error == FSE_NOT_EXIST) { - result_name = name + std::to_string(i); - } else { - result_name = std::string(); + string_cat_printf(name, "%u", i); } } + string_clear(base_path); furi_record_close("storage"); - return result_name; } bool InfraredAppRemoteManager::add_button(const char* button_name, const InfraredAppSignal& signal) { @@ -61,12 +77,23 @@ bool InfraredAppRemoteManager::add_remote_with_button( const InfraredAppSignal& signal) { furi_check(button_name != nullptr); - auto new_name = find_vacant_remote_name(default_remote_name); - if(new_name.empty()) { - return false; - } + string_t new_name; + string_init_set_str(new_name, default_remote_name); + + string_t new_path; + string_init_set_str(new_path, InfraredApp::infrared_directory); + + find_vacant_remote_name(new_name, new_path); + + string_cat_printf( + new_path, "/%s%s", string_get_cstr(new_name), InfraredApp::infrared_extension); + + remote = std::make_unique(new_path); + remote->name = std::string(string_get_cstr(new_name)); + + string_clear(new_path); + string_clear(new_name); - remote = std::make_unique(InfraredApp::infrared_directory, new_name); return add_button(button_name, signal); } @@ -93,8 +120,7 @@ const InfraredAppSignal& InfraredAppRemoteManager::get_button_data(size_t index) bool InfraredAppRemoteManager::delete_remote() { Storage* storage = static_cast(furi_record_open("storage")); - FS_Error error = - storage_common_remove(storage, make_full_name(remote->path, remote->name).c_str()); + FS_Error error = storage_common_remove(storage, string_get_cstr(remote->path)); reset_remote(); furi_record_close("storage"); @@ -128,22 +154,33 @@ std::string InfraredAppRemoteManager::get_remote_name() { bool InfraredAppRemoteManager::rename_remote(const char* str) { furi_check(str != nullptr); furi_check(remote.get() != nullptr); + furi_check(!string_empty_p(remote->path)); if(!remote->name.compare(str)) { return true; } - auto new_name = find_vacant_remote_name(str); - if(new_name.empty()) { - return false; + string_t new_name; + string_init_set_str(new_name, str); + find_vacant_remote_name(new_name, remote->path); + + string_t new_path; + string_init_set(new_path, remote->path); + if(string_end_with_str_p(new_path, InfraredApp::infrared_extension)) { + size_t filename_start = string_search_rchar(new_path, '/'); + string_left(new_path, filename_start); } + string_cat_printf( + new_path, "/%s%s", string_get_cstr(new_name), InfraredApp::infrared_extension); Storage* storage = static_cast(furi_record_open("storage")); - std::string old_filename = make_full_name(remote->path, remote->name); - std::string new_filename = make_full_name(remote->path, new_name); - FS_Error error = storage_common_rename(storage, old_filename.c_str(), new_filename.c_str()); - remote->name = new_name; + FS_Error error = + storage_common_rename(storage, string_get_cstr(remote->path), string_get_cstr(new_path)); + remote->name = std::string(string_get_cstr(new_name)); + + string_clear(new_name); + string_clear(new_path); furi_record_close("storage"); return (error == FSE_OK || error == FSE_EXIST); @@ -171,10 +208,8 @@ bool InfraredAppRemoteManager::store(void) { FlipperFormat* ff = flipper_format_file_alloc(storage); - FURI_LOG_I( - "RemoteManager", "store file: \'%s\'", make_full_name(remote->path, remote->name).c_str()); - result = - flipper_format_file_open_always(ff, make_full_name(remote->path, remote->name).c_str()); + FURI_LOG_I("RemoteManager", "store file: \'%s\'", string_get_cstr(remote->path)); + result = flipper_format_file_open_always(ff, string_get_cstr(remote->path)); if(result) { result = flipper_format_write_header_cstr(ff, "IR signals file", 1); } @@ -192,13 +227,13 @@ bool InfraredAppRemoteManager::store(void) { return result; } -bool InfraredAppRemoteManager::load(const std::string& path, const std::string& remote_name) { +bool InfraredAppRemoteManager::load(string_t path) { bool result = false; Storage* storage = static_cast(furi_record_open("storage")); FlipperFormat* ff = flipper_format_file_alloc(storage); - FURI_LOG_I("RemoteManager", "load file: \'%s\'", make_full_name(path, remote_name).c_str()); - result = flipper_format_file_open_existing(ff, make_full_name(path, remote_name).c_str()); + FURI_LOG_I("RemoteManager", "load file: \'%s\'", string_get_cstr(path)); + result = flipper_format_file_open_existing(ff, string_get_cstr(path)); if(result) { string_t header; string_init(header); @@ -210,7 +245,14 @@ bool InfraredAppRemoteManager::load(const std::string& path, const std::string& string_clear(header); } if(result) { - remote = std::make_unique(path, remote_name); + string_t new_name; + string_init(new_name); + + remote = std::make_unique(path); + path_extract_filename(path, new_name, true); + remote->name = std::string(string_get_cstr(new_name)); + + string_clear(new_name); InfraredAppSignal signal; std::string signal_name; while(infrared_parser_read_signal(ff, signal, signal_name)) { diff --git a/applications/infrared/infrared_app_remote_manager.h b/applications/infrared/infrared_app_remote_manager.h index 31557d54b..b6f0b170f 100644 --- a/applications/infrared/infrared_app_remote_manager.h +++ b/applications/infrared/infrared_app_remote_manager.h @@ -8,6 +8,7 @@ #include "infrared_app_signal.h" +#include "m-string.h" #include #include @@ -60,17 +61,19 @@ class InfraredAppRemote { /** Name of remote */ std::string name; /** Path to remote file */ - std::string path; + string_t path; public: /** Initialize new remote * * @param path - remote file path - * @param name - new remote name */ - InfraredAppRemote(const std::string& path, const std::string& name) - : name(name) - , path(path) { + InfraredAppRemote(string_t file_path) { + string_init_set(path, file_path); + } + + ~InfraredAppRemote() { + string_clear(path); } }; @@ -78,12 +81,6 @@ public: class InfraredAppRemoteManager { /** Remote instance. There can be 1 remote loaded at a time. */ std::unique_ptr remote; - /** Make full name from remote name - * - * @param remote_name name of remote - * @retval full name of remote on disk - */ - std::string make_full_name(const std::string& path, const std::string& remote_name) const; public: /** Restriction to button name length. Buttons larger are ignored. */ @@ -125,9 +122,9 @@ public: * incremented digit(2,3,4,etc) added to name and check repeated. * * @param name - suggested remote name - * @retval garanteed free remote name, prefixed with suggested + * @param path - remote file path */ - std::string find_vacant_remote_name(const std::string& name); + void find_vacant_remote_name(string_t name, string_t path); /** Get button list * @@ -185,8 +182,8 @@ public: /** Load data from disk into current remote * - * @param name - name of remote to load + * @param path - path to remote file * @retval true if success, false otherwise */ - bool load(const std::string& path, const std::string& name); + bool load(string_t path); }; diff --git a/applications/infrared/scene/infrared_app_scene_edit_rename.cpp b/applications/infrared/scene/infrared_app_scene_edit_rename.cpp index dc63c64b1..761da49f3 100644 --- a/applications/infrared/scene/infrared_app_scene_edit_rename.cpp +++ b/applications/infrared/scene/infrared_app_scene_edit_rename.cpp @@ -1,4 +1,6 @@ #include "../infrared_app.h" +#include "m-string.h" +#include "toolbox/path.h" void InfraredAppSceneEditRename::on_enter(InfraredApp* app) { InfraredAppViewManager* view_manager = app->get_view_manager(); @@ -21,9 +23,18 @@ void InfraredAppSceneEditRename::on_enter(InfraredApp* app) { enter_name_length = InfraredAppRemoteManager::max_remote_name_length; text_input_set_header_text(text_input, "Name the remote"); + string_t folder_path; + string_init(folder_path); + + if(string_end_with_str_p(app->file_path, InfraredApp::infrared_extension)) { + path_extract_dirname(string_get_cstr(app->file_path), folder_path); + } + ValidatorIsFile* validator_is_file = validator_is_file_alloc_init( - app->infrared_directory, app->infrared_extension, remote_name.c_str()); + string_get_cstr(folder_path), app->infrared_extension, remote_name.c_str()); text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); + + string_clear(folder_path); } text_input_set_result_callback( diff --git a/applications/infrared/scene/infrared_app_scene_remote_list.cpp b/applications/infrared/scene/infrared_app_scene_remote_list.cpp index f59ff3e91..c72acb6e8 100644 --- a/applications/infrared/scene/infrared_app_scene_remote_list.cpp +++ b/applications/infrared/scene/infrared_app_scene_remote_list.cpp @@ -1,4 +1,5 @@ #include "../infrared_app.h" +#include "assets_icons.h" #include "infrared/infrared_app_event.h" #include @@ -8,11 +9,6 @@ void InfraredAppSceneRemoteList::on_enter(InfraredApp* app) { bool result = false; bool file_select_result; auto remote_manager = app->get_remote_manager(); - auto last_selected_remote = remote_manager->get_remote_name(); - const char* last_selected_remote_name = - last_selected_remote.size() ? last_selected_remote.c_str() : nullptr; - auto filename_ts = - std::make_unique(InfraredAppRemoteManager::max_remote_name_length); DialogsApp* dialogs = app->get_dialogs(); InfraredAppViewManager* view_manager = app->get_view_manager(); @@ -20,16 +16,17 @@ void InfraredAppSceneRemoteList::on_enter(InfraredApp* app) { button_menu_reset(button_menu); view_manager->switch_to(InfraredAppViewManager::ViewId::ButtonMenu); - file_select_result = dialog_file_select_show( + file_select_result = dialog_file_browser_show( dialogs, - InfraredApp::infrared_directory, + app->file_path, + app->file_path, InfraredApp::infrared_extension, - filename_ts->text, - filename_ts->text_size, - last_selected_remote_name); + true, + &I_ir_10px, + true); if(file_select_result) { - if(remote_manager->load(InfraredApp::infrared_directory, std::string(filename_ts->text))) { + if(remote_manager->load(app->file_path)) { app->switch_to_next_scene(InfraredApp::Scene::Remote); result = true; } diff --git a/applications/infrared/scene/infrared_app_scene_start.cpp b/applications/infrared/scene/infrared_app_scene_start.cpp index c42ab9fed..5efdce7a0 100644 --- a/applications/infrared/scene/infrared_app_scene_start.cpp +++ b/applications/infrared/scene/infrared_app_scene_start.cpp @@ -26,6 +26,8 @@ void InfraredAppSceneStart::on_enter(InfraredApp* app) { submenu, "Learn New Remote", SubmenuIndexLearnNewRemote, submenu_callback, app); submenu_add_item(submenu, "Saved Remotes", SubmenuIndexSavedRemotes, submenu_callback, app); submenu_set_selected_item(submenu, submenu_item_selected); + + string_set_str(app->file_path, InfraredApp::infrared_directory); submenu_item_selected = 0; view_manager->switch_to(InfraredAppViewManager::ViewId::Submenu); diff --git a/applications/lfrfid/lfrfid_app.cpp b/applications/lfrfid/lfrfid_app.cpp index c2274234b..4027a07ea 100644 --- a/applications/lfrfid/lfrfid_app.cpp +++ b/applications/lfrfid/lfrfid_app.cpp @@ -1,4 +1,7 @@ #include "lfrfid_app.h" +#include "assets_icons.h" +#include "furi/common_defines.h" +#include "m-string.h" #include "scene/lfrfid_app_scene_start.h" #include "scene/lfrfid_app_scene_read.h" #include "scene/lfrfid_app_scene_read_success.h" @@ -31,9 +34,11 @@ LfRfidApp::LfRfidApp() , storage{"storage"} , dialogs{"dialogs"} , text_store(40) { + string_init_set_str(file_path, app_folder); } LfRfidApp::~LfRfidApp() { + string_clear(file_path); } void LfRfidApp::run(void* _args) { @@ -42,7 +47,8 @@ void LfRfidApp::run(void* _args) { make_app_folder(); if(strlen(args)) { - load_key_data(args, &worker.key); + string_set_str(file_path, args); + load_key_data(file_path, &worker.key); scene_controller.add_scene(SceneType::Emulate, new LfRfidAppSceneEmulate()); scene_controller.process(100, SceneType::Emulate); } else { @@ -69,65 +75,49 @@ void LfRfidApp::run(void* _args) { } bool LfRfidApp::save_key(RfidKey* key) { - string_t file_name; bool result = false; make_app_folder(); - string_init_printf(file_name, "%s/%s%s", app_folder, key->get_name(), app_extension); - result = save_key_data(string_get_cstr(file_name), key); - string_clear(file_name); + if(string_end_with_str_p(file_path, app_extension)) { + size_t filename_start = string_search_rchar(file_path, '/'); + string_left(file_path, filename_start); + } + string_cat_printf(file_path, "/%s%s", key->get_name(), app_extension); + + result = save_key_data(file_path, key); return result; } bool LfRfidApp::load_key_from_file_select(bool need_restore) { - TextStore* filename_ts = new TextStore(64); - bool result = false; - - if(need_restore) { - result = dialog_file_select_show( - dialogs, - app_folder, - app_extension, - filename_ts->text, - filename_ts->text_size, - worker.key.get_name()); - } else { - result = dialog_file_select_show( - dialogs, app_folder, app_extension, filename_ts->text, filename_ts->text_size, NULL); + if(!need_restore) { + string_set_str(file_path, app_folder); } + bool result = dialog_file_browser_show( + dialogs, file_path, file_path, app_extension, true, &I_125_10px, true); + if(result) { - string_t key_str; - string_init_printf(key_str, "%s/%s%s", app_folder, filename_ts->text, app_extension); - result = load_key_data(string_get_cstr(key_str), &worker.key); - string_clear(key_str); + result = load_key_data(file_path, &worker.key); } - delete filename_ts; return result; } bool LfRfidApp::delete_key(RfidKey* key) { - string_t file_name; - bool result = false; - - string_init_printf(file_name, "%s/%s%s", app_folder, key->get_name(), app_extension); - result = storage_simply_remove(storage, string_get_cstr(file_name)); - string_clear(file_name); - - return result; + UNUSED(key); + return storage_simply_remove(storage, string_get_cstr(file_path)); } -bool LfRfidApp::load_key_data(const char* path, RfidKey* key) { +bool LfRfidApp::load_key_data(string_t path, RfidKey* key) { FlipperFormat* file = flipper_format_file_alloc(storage); bool result = false; string_t str_result; string_init(str_result); do { - if(!flipper_format_file_open_existing(file, path)) break; + if(!flipper_format_file_open_existing(file, string_get_cstr(path))) break; // header uint32_t version; @@ -149,7 +139,7 @@ bool LfRfidApp::load_key_data(const char* path, RfidKey* key) { break; loaded_key.set_data(key_data, loaded_key.get_type_data_count()); - path_extract_filename_no_ext(path, str_result); + path_extract_filename(path, str_result, true); loaded_key.set_name(string_get_cstr(str_result)); *key = loaded_key; @@ -166,12 +156,12 @@ bool LfRfidApp::load_key_data(const char* path, RfidKey* key) { return result; } -bool LfRfidApp::save_key_data(const char* path, RfidKey* key) { +bool LfRfidApp::save_key_data(string_t path, RfidKey* key) { FlipperFormat* file = flipper_format_file_alloc(storage); bool result = false; do { - if(!flipper_format_file_open_always(file, path)) break; + if(!flipper_format_file_open_always(file, string_get_cstr(path))) break; if(!flipper_format_write_header_cstr(file, app_filetype, 1)) break; if(!flipper_format_write_comment_cstr(file, "Key type can be EM4100, H10301 or I40134")) break; diff --git a/applications/lfrfid/lfrfid_app.h b/applications/lfrfid/lfrfid_app.h index dddfb753a..3f8209a1d 100644 --- a/applications/lfrfid/lfrfid_app.h +++ b/applications/lfrfid/lfrfid_app.h @@ -1,4 +1,5 @@ #pragma once +#include "m-string.h" #include #include @@ -76,6 +77,8 @@ public: TextStore text_store; + string_t file_path; + void run(void* args); static const char* app_folder; @@ -86,8 +89,8 @@ public: bool load_key_from_file_select(bool need_restore); bool delete_key(RfidKey* key); - bool load_key_data(const char* path, RfidKey* key); - bool save_key_data(const char* path, RfidKey* key); + bool load_key_data(string_t path, RfidKey* key); + bool save_key_data(string_t path, RfidKey* key); void make_app_folder(); }; diff --git a/applications/lfrfid/scene/lfrfid_app_scene_save_name.cpp b/applications/lfrfid/scene/lfrfid_app_scene_save_name.cpp index d460724e2..d7ba2c9ed 100644 --- a/applications/lfrfid/scene/lfrfid_app_scene_save_name.cpp +++ b/applications/lfrfid/scene/lfrfid_app_scene_save_name.cpp @@ -1,11 +1,14 @@ #include "lfrfid_app_scene_save_name.h" +#include "m-string.h" #include +#include void LfRfidAppSceneSaveName::on_enter(LfRfidApp* app, bool /* need_restore */) { const char* key_name = app->worker.key.get_name(); bool key_name_empty = !strcmp(key_name, ""); if(key_name_empty) { + string_set_str(app->file_path, app->app_folder); set_random_name(app->text_store.text, app->text_store.text_size); } else { app->text_store.set("%s", key_name); @@ -21,10 +24,17 @@ void LfRfidAppSceneSaveName::on_enter(LfRfidApp* app, bool /* need_restore */) { app->worker.key.get_name_length(), key_name_empty); + string_t folder_path; + string_init(folder_path); + + path_extract_dirname(string_get_cstr(app->file_path), folder_path); + ValidatorIsFile* validator_is_file = - validator_is_file_alloc_init(app->app_folder, app->app_extension, key_name); + validator_is_file_alloc_init(string_get_cstr(folder_path), app->app_extension, key_name); text_input->set_validator(validator_is_file_callback, validator_is_file); + string_clear(folder_path); + app->view_controller.switch_to(); } diff --git a/applications/music_player/music_player.c b/applications/music_player/music_player.c index 6dfef4920..9b5dda0fa 100644 --- a/applications/music_player/music_player.c +++ b/applications/music_player/music_player.c @@ -1,3 +1,5 @@ +#include "assets_icons.h" +#include "m-string.h" #include #include @@ -298,23 +300,23 @@ int32_t music_player_app(void* p) { if(p) { string_cat_str(file_path, p); } else { - char file_name[256] = {0}; + string_set_str(file_path, MUSIC_PLAYER_APP_PATH_FOLDER); + DialogsApp* dialogs = furi_record_open("dialogs"); - bool res = dialog_file_select_show( + bool res = dialog_file_browser_show( dialogs, - MUSIC_PLAYER_APP_PATH_FOLDER, + file_path, + file_path, MUSIC_PLAYER_APP_EXTENSION, - file_name, - 255, - NULL); + true, + &I_music_10px, + false); + furi_record_close("dialogs"); if(!res) { FURI_LOG_E(TAG, "No file selected"); break; } - string_cat_str(file_path, MUSIC_PLAYER_APP_PATH_FOLDER); - string_cat_str(file_path, "/"); - string_cat_str(file_path, file_name); } if(!music_player_worker_load(music_player->worker, string_get_cstr(file_path))) { diff --git a/applications/nfc/nfc_device.c b/applications/nfc/nfc_device.c index 63f0c3ccb..51e14a6c1 100644 --- a/applications/nfc/nfc_device.c +++ b/applications/nfc/nfc_device.c @@ -1,4 +1,6 @@ #include "nfc_device.h" +#include "assets_icons.h" +#include "m-string.h" #include "nfc_types.h" #include @@ -14,6 +16,7 @@ NfcDevice* nfc_device_alloc() { NfcDevice* nfc_dev = malloc(sizeof(NfcDevice)); nfc_dev->storage = furi_record_open("storage"); nfc_dev->dialogs = furi_record_open("dialogs"); + string_init(nfc_dev->load_path); return nfc_dev; } @@ -22,6 +25,7 @@ void nfc_device_free(NfcDevice* nfc_dev) { nfc_device_clear(nfc_dev); furi_record_close("storage"); furi_record_close("dialogs"); + string_clear(nfc_dev->load_path); free(nfc_dev); } @@ -730,11 +734,24 @@ void nfc_device_set_name(NfcDevice* dev, const char* name) { strlcpy(dev->dev_name, name, NFC_DEV_NAME_MAX_LEN); } +static void nfc_device_get_path_without_ext(string_t orig_path, string_t shadow_path) { + // TODO: this won't work if there is ".nfc" anywhere in the path other than + // at the end + size_t ext_start = string_search_str(orig_path, NFC_APP_EXTENSION); + string_set_n(shadow_path, orig_path, 0, ext_start); +} + +static void nfc_device_get_shadow_path(string_t orig_path, string_t shadow_path) { + nfc_device_get_path_without_ext(orig_path, shadow_path); + string_cat_printf(shadow_path, "%s", NFC_APP_SHADOW_EXTENSION); +} + static bool nfc_device_save_file( NfcDevice* dev, const char* dev_name, const char* folder, - const char* extension) { + const char* extension, + bool use_load_path) { furi_assert(dev); bool saved = false; @@ -744,10 +761,19 @@ static bool nfc_device_save_file( string_init(temp_str); do { - // Create nfc directory if necessary - if(!storage_simply_mkdir(dev->storage, NFC_APP_FOLDER)) break; - // First remove nfc device file if it was saved - string_printf(temp_str, "%s/%s%s", folder, dev_name, extension); + if(use_load_path && !string_empty_p(dev->load_path)) { + // Get directory name + path_extract_dirname(string_get_cstr(dev->load_path), temp_str); + // Create nfc directory if necessary + if(!storage_simply_mkdir(dev->storage, string_get_cstr(temp_str))) break; + // Make path to file to save + string_cat_printf(temp_str, "/%s%s", dev_name, extension); + } else { + // Create nfc directory if necessary + if(!storage_simply_mkdir(dev->storage, NFC_APP_FOLDER)) break; + // First remove nfc device file if it was saved + string_printf(temp_str, "%s/%s%s", folder, dev_name, extension); + } // Open file if(!flipper_format_file_open_always(file, string_get_cstr(temp_str))) break; // Write header @@ -786,12 +812,12 @@ static bool nfc_device_save_file( } bool nfc_device_save(NfcDevice* dev, const char* dev_name) { - return nfc_device_save_file(dev, dev_name, NFC_APP_FOLDER, NFC_APP_EXTENSION); + return nfc_device_save_file(dev, dev_name, NFC_APP_FOLDER, NFC_APP_EXTENSION, true); } bool nfc_device_save_shadow(NfcDevice* dev, const char* dev_name) { dev->shadow_file_exist = true; - return nfc_device_save_file(dev, dev_name, NFC_APP_FOLDER, NFC_APP_SHADOW_EXTENSION); + return nfc_device_save_file(dev, dev_name, NFC_APP_FOLDER, NFC_APP_SHADOW_EXTENSION, true); } static bool nfc_device_load_data(NfcDevice* dev, string_t path) { @@ -805,9 +831,7 @@ static bool nfc_device_load_data(NfcDevice* dev, string_t path) { do { // Check existance of shadow file - size_t ext_start = string_search_str(path, NFC_APP_EXTENSION); - string_set_n(temp_str, path, 0, ext_start); - string_cat_printf(temp_str, "%s", NFC_APP_SHADOW_EXTENSION); + nfc_device_get_shadow_path(path, temp_str); dev->shadow_file_exist = storage_common_stat(dev->storage, string_get_cstr(temp_str), NULL) == FSE_OK; // Open shadow file if it exists. If not - open original @@ -864,15 +888,16 @@ bool nfc_device_load(NfcDevice* dev, const char* file_path) { furi_assert(file_path); // Load device data - string_t path; - string_init_set_str(path, file_path); - bool dev_load = nfc_device_load_data(dev, path); + string_set_str(dev->load_path, file_path); + bool dev_load = nfc_device_load_data(dev, dev->load_path); if(dev_load) { // Set device name - path_extract_filename_no_ext(file_path, path); - nfc_device_set_name(dev, string_get_cstr(path)); + string_t filename; + string_init(filename); + path_extract_filename_no_ext(file_path, filename); + nfc_device_set_name(dev, string_get_cstr(filename)); + string_clear(filename); } - string_clear(path); return dev_load; } @@ -880,23 +905,22 @@ bool nfc_device_load(NfcDevice* dev, const char* file_path) { bool nfc_file_select(NfcDevice* dev) { furi_assert(dev); - // Input events and views are managed by file_select - bool res = dialog_file_select_show( - dev->dialogs, - NFC_APP_FOLDER, - NFC_APP_EXTENSION, - dev->file_name, - sizeof(dev->file_name), - dev->dev_name); + // Input events and views are managed by file_browser + string_t nfc_app_folder; + string_init_set_str(nfc_app_folder, NFC_APP_FOLDER); + bool res = dialog_file_browser_show( + dev->dialogs, dev->load_path, nfc_app_folder, NFC_APP_EXTENSION, true, &I_Nfc_10px, true); + string_clear(nfc_app_folder); if(res) { - string_t dev_str; - // Get key file path - string_init_printf(dev_str, "%s/%s%s", NFC_APP_FOLDER, dev->file_name, NFC_APP_EXTENSION); - res = nfc_device_load_data(dev, dev_str); + string_t filename; + string_init(filename); + path_extract_filename(dev->load_path, filename, true); + strncpy(dev->dev_name, string_get_cstr(filename), NFC_DEV_NAME_MAX_LEN); + res = nfc_device_load_data(dev, dev->load_path); if(res) { - nfc_device_set_name(dev, dev->file_name); + nfc_device_set_name(dev, dev->dev_name); } - string_clear(dev_str); + string_clear(filename); } return res; @@ -914,9 +938,10 @@ void nfc_device_clear(NfcDevice* dev) { nfc_device_data_clear(&dev->dev_data); memset(&dev->dev_data, 0, sizeof(dev->dev_data)); dev->format = NfcDeviceSaveFormatUid; + string_reset(dev->load_path); } -bool nfc_device_delete(NfcDevice* dev) { +bool nfc_device_delete(NfcDevice* dev, bool use_load_path) { furi_assert(dev); bool deleted = false; @@ -925,12 +950,20 @@ bool nfc_device_delete(NfcDevice* dev) { do { // Delete original file - string_init_printf(file_path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_EXTENSION); + if(use_load_path && !string_empty_p(dev->load_path)) { + string_set(file_path, dev->load_path); + } else { + string_printf(file_path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_EXTENSION); + } if(!storage_simply_remove(dev->storage, string_get_cstr(file_path))) break; // Delete shadow file if it exists if(dev->shadow_file_exist) { - string_printf( - file_path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_SHADOW_EXTENSION); + if(use_load_path && !string_empty_p(dev->load_path)) { + nfc_device_get_shadow_path(dev->load_path, file_path); + } else { + string_printf( + file_path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_SHADOW_EXTENSION); + } if(!storage_simply_remove(dev->storage, string_get_cstr(file_path))) break; } deleted = true; @@ -944,19 +977,29 @@ bool nfc_device_delete(NfcDevice* dev) { return deleted; } -bool nfc_device_restore(NfcDevice* dev) { +bool nfc_device_restore(NfcDevice* dev, bool use_load_path) { furi_assert(dev); furi_assert(dev->shadow_file_exist); bool restored = false; string_t path; + string_init(path); + do { - string_init_printf( - path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_SHADOW_EXTENSION); + if(use_load_path && !string_empty_p(dev->load_path)) { + nfc_device_get_shadow_path(dev->load_path, path); + } else { + string_printf( + path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_SHADOW_EXTENSION); + } if(!storage_simply_remove(dev->storage, string_get_cstr(path))) break; dev->shadow_file_exist = false; - string_printf(path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_EXTENSION); + if(use_load_path && !string_empty_p(dev->load_path)) { + string_set(path, dev->load_path); + } else { + string_printf(path, "%s/%s%s", NFC_APP_FOLDER, dev->dev_name, NFC_APP_EXTENSION); + } if(!nfc_device_load_data(dev, path)) break; restored = true; } while(0); diff --git a/applications/nfc/nfc_device.h b/applications/nfc/nfc_device.h index 215f637fa..400f6c363 100644 --- a/applications/nfc/nfc_device.h +++ b/applications/nfc/nfc_device.h @@ -12,7 +12,6 @@ #include #define NFC_DEV_NAME_MAX_LEN 22 -#define NFC_FILE_NAME_MAX_LEN 120 #define NFC_READER_DATA_MAX_SIZE 64 #define NFC_APP_FOLDER "/any/nfc" @@ -57,7 +56,7 @@ typedef struct { DialogsApp* dialogs; NfcDeviceData dev_data; char dev_name[NFC_DEV_NAME_MAX_LEN + 1]; - char file_name[NFC_FILE_NAME_MAX_LEN]; + string_t load_path; NfcDeviceSaveFormat format; bool shadow_file_exist; } NfcDevice; @@ -80,6 +79,6 @@ void nfc_device_data_clear(NfcDeviceData* dev); void nfc_device_clear(NfcDevice* dev); -bool nfc_device_delete(NfcDevice* dev); +bool nfc_device_delete(NfcDevice* dev, bool use_load_path); -bool nfc_device_restore(NfcDevice* dev); +bool nfc_device_restore(NfcDevice* dev, bool use_load_path); diff --git a/applications/nfc/scenes/nfc_scene_delete.c b/applications/nfc/scenes/nfc_scene_delete.c index e8ba3e440..1946b9290 100755 --- a/applications/nfc/scenes/nfc_scene_delete.c +++ b/applications/nfc/scenes/nfc_scene_delete.c @@ -73,7 +73,7 @@ bool nfc_scene_delete_on_event(void* context, SceneManagerEvent event) { if(event.event == GuiButtonTypeLeft) { return scene_manager_previous_scene(nfc->scene_manager); } else if(event.event == GuiButtonTypeRight) { - if(nfc_device_delete(nfc->dev)) { + if(nfc_device_delete(nfc->dev, true)) { scene_manager_next_scene(nfc->scene_manager, NfcSceneDeleteSuccess); } else { scene_manager_search_and_switch_to_previous_scene( diff --git a/applications/nfc/scenes/nfc_scene_save_name.c b/applications/nfc/scenes/nfc_scene_save_name.c old mode 100755 new mode 100644 index e95c97eb4..d5e05472a --- a/applications/nfc/scenes/nfc_scene_save_name.c +++ b/applications/nfc/scenes/nfc_scene_save_name.c @@ -1,6 +1,8 @@ #include "../nfc_i.h" +#include "m-string.h" #include #include +#include void nfc_scene_save_name_text_input_callback(void* context) { Nfc* nfc = context; @@ -29,11 +31,22 @@ void nfc_scene_save_name_on_enter(void* context) { NFC_DEV_NAME_MAX_LEN, dev_name_empty); - ValidatorIsFile* validator_is_file = - validator_is_file_alloc_init(NFC_APP_FOLDER, NFC_APP_EXTENSION, nfc->dev->dev_name); + string_t folder_path; + string_init(folder_path); + + if(string_end_with_str_p(nfc->dev->load_path, NFC_APP_EXTENSION)) { + path_extract_dirname(string_get_cstr(nfc->dev->load_path), folder_path); + } else { + string_set_str(folder_path, NFC_APP_FOLDER); + } + + ValidatorIsFile* validator_is_file = validator_is_file_alloc_init( + string_get_cstr(folder_path), NFC_APP_EXTENSION, nfc->dev->dev_name); text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextInput); + + string_clear(folder_path); } bool nfc_scene_save_name_on_event(void* context, SceneManagerEvent event) { @@ -43,7 +56,7 @@ bool nfc_scene_save_name_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == NfcCustomEventTextInputDone) { if(strcmp(nfc->dev->dev_name, "")) { - nfc_device_delete(nfc->dev); + nfc_device_delete(nfc->dev, true); } if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSetUid)) { nfc->dev->dev_data.nfc_data = nfc->dev_edit_data; diff --git a/applications/nfc/scenes/nfc_scene_save_success.c b/applications/nfc/scenes/nfc_scene_save_success.c index 985897a6d..5c15a509a 100644 --- a/applications/nfc/scenes/nfc_scene_save_success.c +++ b/applications/nfc/scenes/nfc_scene_save_success.c @@ -30,9 +30,6 @@ bool nfc_scene_save_success_on_event(void* context, SceneManagerEvent event) { if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneCardMenu)) { consumed = scene_manager_search_and_switch_to_previous_scene( nfc->scene_manager, NfcSceneCardMenu); - } else if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSetType)) { - consumed = scene_manager_search_and_switch_to_another_scene( - nfc->scene_manager, NfcSceneFileSelect); } else if(scene_manager_has_previous_scene( nfc->scene_manager, NfcSceneMifareDesfireMenu)) { consumed = scene_manager_search_and_switch_to_previous_scene( diff --git a/applications/nfc/scenes/nfc_scene_saved_menu.c b/applications/nfc/scenes/nfc_scene_saved_menu.c index 1b435ccd1..f2b2dea37 100644 --- a/applications/nfc/scenes/nfc_scene_saved_menu.c +++ b/applications/nfc/scenes/nfc_scene_saved_menu.c @@ -78,7 +78,7 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(nfc->scene_manager, NfcSceneDeviceInfo); consumed = true; } else if(event.event == SubmenuIndexRestoreOriginal) { - if(!nfc_device_restore(nfc->dev)) { + if(!nfc_device_restore(nfc->dev, true)) { scene_manager_search_and_switch_to_previous_scene( nfc->scene_manager, NfcSceneStart); } else { diff --git a/applications/nfc/scenes/nfc_scene_set_type.c b/applications/nfc/scenes/nfc_scene_set_type.c index 0dbb4f7ea..0fe63424f 100755 --- a/applications/nfc/scenes/nfc_scene_set_type.c +++ b/applications/nfc/scenes/nfc_scene_set_type.c @@ -1,4 +1,5 @@ #include "../nfc_i.h" +#include "m-string.h" enum SubmenuIndex { SubmenuIndexNFCA4, @@ -16,6 +17,7 @@ void nfc_scene_set_type_on_enter(void* context) { Submenu* submenu = nfc->submenu; // Clear device name nfc_device_set_name(nfc->dev, ""); + string_set_str(nfc->dev->load_path, ""); submenu_add_item( submenu, "NFC-A 7-bytes UID", SubmenuIndexNFCA7, nfc_scene_set_type_submenu_callback, nfc); submenu_add_item( diff --git a/applications/power/power_service/views/power_off.c b/applications/power/power_service/views/power_off.c old mode 100755 new mode 100644 diff --git a/applications/scened_app_example/scene/scened_app_scene_byte_input.cpp b/applications/scened_app_example/scene/scened_app_scene_byte_input.cpp deleted file mode 100644 index 200252ad6..000000000 --- a/applications/scened_app_example/scene/scened_app_scene_byte_input.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#include "scened_app_scene_byte_input.h" - -void ScenedAppSceneByteInput::on_enter(ScenedApp* app, bool /* need_restore */) { - ByteInputVM* byte_input = app->view_controller; - auto callback = cbc::obtain_connector(this, &ScenedAppSceneByteInput::result_callback); - - byte_input->set_result_callback(callback, NULL, app, data, 4); - byte_input->set_header_text("Enter the key"); - - app->view_controller.switch_to(); -} - -bool ScenedAppSceneByteInput::on_event(ScenedApp* app, ScenedApp::Event* event) { - bool consumed = false; - - if(event->type == ScenedApp::EventType::ByteEditResult) { - app->scene_controller.switch_to_previous_scene(); - consumed = true; - } - - return consumed; -} - -void ScenedAppSceneByteInput::on_exit(ScenedApp* app) { - app->view_controller.get()->clean(); -} - -void ScenedAppSceneByteInput::result_callback(void* context) { - ScenedApp* app = static_cast(context); - ScenedApp::Event event; - - event.type = ScenedApp::EventType::ByteEditResult; - - app->view_controller.send_event(&event); -} diff --git a/applications/scened_app_example/scene/scened_app_scene_byte_input.h b/applications/scened_app_example/scene/scened_app_scene_byte_input.h deleted file mode 100644 index 0f0b02acb..000000000 --- a/applications/scened_app_example/scene/scened_app_scene_byte_input.h +++ /dev/null @@ -1,19 +0,0 @@ -#pragma once -#include "../scened_app.h" - -class ScenedAppSceneByteInput : public GenericScene { -public: - void on_enter(ScenedApp* app, bool need_restore) final; - bool on_event(ScenedApp* app, ScenedApp::Event* event) final; - void on_exit(ScenedApp* app) final; - -private: - void result_callback(void* context); - - uint8_t data[4] = { - 0x01, - 0xA2, - 0xF4, - 0xD3, - }; -}; diff --git a/applications/scened_app_example/scene/scened_app_scene_start.cpp b/applications/scened_app_example/scene/scened_app_scene_start.cpp deleted file mode 100644 index 5538962ba..000000000 --- a/applications/scened_app_example/scene/scened_app_scene_start.cpp +++ /dev/null @@ -1,47 +0,0 @@ -#include "scened_app_scene_start.h" - -typedef enum { - SubmenuByteInput, -} SubmenuIndex; - -void ScenedAppSceneStart::on_enter(ScenedApp* app, bool need_restore) { - auto submenu = app->view_controller.get(); - auto callback = cbc::obtain_connector(this, &ScenedAppSceneStart::submenu_callback); - - submenu->add_item("Byte Input", SubmenuByteInput, callback, app); - - if(need_restore) { - submenu->set_selected_item(submenu_item_selected); - } - app->view_controller.switch_to(); -} - -bool ScenedAppSceneStart::on_event(ScenedApp* app, ScenedApp::Event* event) { - bool consumed = false; - - if(event->type == ScenedApp::EventType::MenuSelected) { - submenu_item_selected = event->payload.menu_index; - switch(event->payload.menu_index) { - case SubmenuByteInput: - app->scene_controller.switch_to_next_scene(ScenedApp::SceneType::ByteInputScene); - break; - } - consumed = true; - } - - return consumed; -} - -void ScenedAppSceneStart::on_exit(ScenedApp* app) { - app->view_controller.get()->clean(); -} - -void ScenedAppSceneStart::submenu_callback(void* context, uint32_t index) { - ScenedApp* app = static_cast(context); - ScenedApp::Event event; - - event.type = ScenedApp::EventType::MenuSelected; - event.payload.menu_index = index; - - app->view_controller.send_event(&event); -} diff --git a/applications/scened_app_example/scene/scened_app_scene_start.h b/applications/scened_app_example/scene/scened_app_scene_start.h deleted file mode 100644 index 8324a20fd..000000000 --- a/applications/scened_app_example/scene/scened_app_scene_start.h +++ /dev/null @@ -1,13 +0,0 @@ -#pragma once -#include "../scened_app.h" - -class ScenedAppSceneStart : public GenericScene { -public: - void on_enter(ScenedApp* app, bool need_restore) final; - bool on_event(ScenedApp* app, ScenedApp::Event* event) final; - void on_exit(ScenedApp* app) final; - -private: - void submenu_callback(void* context, uint32_t index); - uint32_t submenu_item_selected = 0; -}; diff --git a/applications/scened_app_example/scened_app.cpp b/applications/scened_app_example/scened_app.cpp deleted file mode 100644 index 64040b22d..000000000 --- a/applications/scened_app_example/scened_app.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "scened_app.h" -#include "scene/scened_app_scene_start.h" -#include "scene/scened_app_scene_byte_input.h" - -ScenedApp::ScenedApp() - : scene_controller{this} - , text_store{128} - , notification{"notification"} { -} - -ScenedApp::~ScenedApp() { -} - -void ScenedApp::run() { - scene_controller.add_scene(SceneType::Start, new ScenedAppSceneStart()); - scene_controller.add_scene(SceneType::ByteInputScene, new ScenedAppSceneByteInput()); - - notification_message(notification, &sequence_blink_green_10); - scene_controller.process(100); -} diff --git a/applications/scened_app_example/scened_app.h b/applications/scened_app_example/scened_app.h deleted file mode 100644 index c6cecb477..000000000 --- a/applications/scened_app_example/scened_app.h +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include - -class ScenedApp { -public: - enum class EventType : uint8_t { - GENERIC_EVENT_ENUM_VALUES, - MenuSelected, - ByteEditResult, - }; - - enum class SceneType : uint8_t { - GENERIC_SCENE_ENUM_VALUES, - ByteInputScene, - }; - - class Event { - public: - union { - int32_t menu_index; - } payload; - - EventType type; - }; - - SceneController, ScenedApp> scene_controller; - TextStore text_store; - ViewController view_controller; - RecordController notification; - - ~ScenedApp(); - ScenedApp(); - - void run(); -}; diff --git a/applications/scened_app_example/scened_app_launcher.cpp b/applications/scened_app_example/scened_app_launcher.cpp deleted file mode 100644 index 3d0bdfcaf..000000000 --- a/applications/scened_app_example/scened_app_launcher.cpp +++ /dev/null @@ -1,11 +0,0 @@ -#include "scened_app.h" - -// app enter function -extern "C" int32_t scened_app(void* p) { - UNUSED(p); - ScenedApp* app = new ScenedApp(); - app->run(); - delete app; - - return 0; -} diff --git a/applications/storage/storage_cli.c b/applications/storage/storage_cli.c index b35e37a89..4ce91770a 100644 --- a/applications/storage/storage_cli.c +++ b/applications/storage/storage_cli.c @@ -593,7 +593,7 @@ static void storage_cli_factory_reset(Cli* cli, string_t args, void* context) { void storage_on_system_start() { #ifdef SRV_CLI Cli* cli = furi_record_open("cli"); - cli_add_command(cli, "storage", CliCommandFlagDefault, storage_cli, NULL); + cli_add_command(cli, "storage", CliCommandFlagParallelSafe, storage_cli, NULL); cli_add_command( cli, "factory_reset", CliCommandFlagParallelSafe, storage_cli_factory_reset, NULL); furi_record_close("cli"); diff --git a/applications/storage_settings/scenes/storage_settings_scene_unmounted.c b/applications/storage_settings/scenes/storage_settings_scene_unmounted.c old mode 100644 new mode 100755 diff --git a/applications/subghz/helpers/subghz_custom_event.h b/applications/subghz/helpers/subghz_custom_event.h index eac2eb1c0..f31b69d6a 100644 --- a/applications/subghz/helpers/subghz_custom_event.h +++ b/applications/subghz/helpers/subghz_custom_event.h @@ -44,6 +44,6 @@ typedef enum { SubGhzCustomEventViewTransmitterSendStart, SubGhzCustomEventViewTransmitterSendStop, SubGhzCustomEventViewTransmitterError, - + SubGhzCustomEventByteInputDone, } SubGhzCustomEvent; diff --git a/applications/subghz/helpers/subghz_frequency_analyzer_worker.c b/applications/subghz/helpers/subghz_frequency_analyzer_worker.c index 93a3ed86f..69e597595 100644 --- a/applications/subghz/helpers/subghz_frequency_analyzer_worker.c +++ b/applications/subghz/helpers/subghz_frequency_analyzer_worker.c @@ -3,8 +3,6 @@ #include -#include "../subghz_i.h" - #define TAG "SubghzFrequencyAnalyzerWorker" #define SUBGHZ_FREQUENCY_ANALYZER_THRESHOLD -95.0f @@ -182,6 +180,9 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) { osDelay(3); rssi = furi_hal_subghz_get_rssi(); + + FURI_LOG_T(TAG, "#:%u:%f", frequency, (double)rssi); + if(frequency_rssi.rssi < rssi) { frequency_rssi.rssi = rssi; frequency_rssi.frequency = frequency; @@ -222,7 +223,8 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) { return 0; } -SubGhzFrequencyAnalyzerWorker* subghz_frequency_analyzer_worker_alloc() { +SubGhzFrequencyAnalyzerWorker* subghz_frequency_analyzer_worker_alloc(void* context) { + furi_assert(context); SubGhzFrequencyAnalyzerWorker* instance = malloc(sizeof(SubGhzFrequencyAnalyzerWorker)); instance->thread = furi_thread_alloc(); @@ -231,8 +233,8 @@ SubGhzFrequencyAnalyzerWorker* subghz_frequency_analyzer_worker_alloc() { furi_thread_set_context(instance->thread, instance); furi_thread_set_callback(instance->thread, subghz_frequency_analyzer_worker_thread); - instance->setting = subghz_setting_alloc(); - subghz_setting_load(instance->setting, "/ext/subghz/assets/setting_frequency_analyzer_user"); + SubGhz* subghz = context; + instance->setting = subghz->setting; return instance; } @@ -240,7 +242,6 @@ void subghz_frequency_analyzer_worker_free(SubGhzFrequencyAnalyzerWorker* instan furi_assert(instance); furi_thread_free(instance->thread); - subghz_setting_free(instance->setting); free(instance); } diff --git a/applications/subghz/helpers/subghz_frequency_analyzer_worker.h b/applications/subghz/helpers/subghz_frequency_analyzer_worker.h index 93f7caf01..424270a03 100644 --- a/applications/subghz/helpers/subghz_frequency_analyzer_worker.h +++ b/applications/subghz/helpers/subghz_frequency_analyzer_worker.h @@ -1,6 +1,7 @@ #pragma once #include +#include "../subghz_i.h" typedef struct SubGhzFrequencyAnalyzerWorker SubGhzFrequencyAnalyzerWorker; @@ -14,9 +15,10 @@ typedef struct { /** Allocate SubGhzFrequencyAnalyzerWorker * + * @param context SubGhz* context * @return SubGhzFrequencyAnalyzerWorker* */ -SubGhzFrequencyAnalyzerWorker* subghz_frequency_analyzer_worker_alloc(); +SubGhzFrequencyAnalyzerWorker* subghz_frequency_analyzer_worker_alloc(void* context); /** Free SubGhzFrequencyAnalyzerWorker * diff --git a/applications/subghz/scenes/subghz_scene_delete.c b/applications/subghz/scenes/subghz_scene_delete.c index 83d6d4751..43151de20 100644 --- a/applications/subghz/scenes/subghz_scene_delete.c +++ b/applications/subghz/scenes/subghz_scene_delete.c @@ -49,7 +49,7 @@ bool subghz_scene_delete_on_event(void* context, SceneManagerEvent event) { SubGhz* subghz = context; if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubGhzCustomEventSceneDelete) { - strncpy(subghz->file_path_tmp, subghz->file_path, SUBGHZ_MAX_LEN_NAME); + string_set(subghz->file_path_tmp, subghz->file_path); if(subghz_delete_file(subghz)) { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneDeleteSuccess); } else { diff --git a/applications/subghz/scenes/subghz_scene_delete_raw.c b/applications/subghz/scenes/subghz_scene_delete_raw.c index 03f0eb81b..a20968d5b 100644 --- a/applications/subghz/scenes/subghz_scene_delete_raw.c +++ b/applications/subghz/scenes/subghz_scene_delete_raw.c @@ -24,7 +24,7 @@ void subghz_scene_delete_raw_on_enter(void* context) { char delete_str[SUBGHZ_MAX_LEN_NAME + 16]; string_t file_name; string_init(file_name); - path_extract_filename_no_ext(subghz->file_path, file_name); + path_extract_filename(subghz->file_path, file_name, true); snprintf(delete_str, sizeof(delete_str), "\e#Delete %s?\e#", string_get_cstr(file_name)); string_clear(file_name); @@ -61,7 +61,7 @@ bool subghz_scene_delete_raw_on_event(void* context, SceneManagerEvent event) { SubGhz* subghz = context; if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubGhzCustomEventSceneDeleteRAW) { - strncpy(subghz->file_path_tmp, subghz->file_path, SUBGHZ_MAX_LEN_NAME); + string_set(subghz->file_path_tmp, subghz->file_path); if(subghz_delete_file(subghz)) { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneDeleteSuccess); } else { diff --git a/applications/subghz/scenes/subghz_scene_more_raw.c b/applications/subghz/scenes/subghz_scene_more_raw.c index 54bd08158..a5bade927 100644 --- a/applications/subghz/scenes/subghz_scene_more_raw.c +++ b/applications/subghz/scenes/subghz_scene_more_raw.c @@ -45,7 +45,7 @@ bool subghz_scene_more_raw_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneDeleteRAW); return true; } else if(event.event == SubmenuIndexEdit) { - memset(subghz->file_path_tmp, 0, sizeof(subghz->file_path_tmp)); + string_reset(subghz->file_path_tmp); scene_manager_set_scene_state( subghz->scene_manager, SubGhzSceneMoreRAW, SubmenuIndexEdit); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName); diff --git a/applications/subghz/scenes/subghz_scene_read_raw.c b/applications/subghz/scenes/subghz_scene_read_raw.c index 5323bfe58..4e60f1b60 100644 --- a/applications/subghz/scenes/subghz_scene_read_raw.c +++ b/applications/subghz/scenes/subghz_scene_read_raw.c @@ -25,7 +25,7 @@ bool subghz_scene_read_raw_update_filename(SubGhz* subghz) { break; } - strncpy(subghz->file_path, string_get_cstr(temp_str), SUBGHZ_MAX_LEN_NAME); + string_set(subghz->file_path, temp_str); ret = true; } while(false); @@ -75,13 +75,13 @@ void subghz_scene_read_raw_on_enter(void* context) { subghz_read_raw_set_status(subghz->subghz_read_raw, SubGhzReadRAWStatusIDLE, ""); break; case SubGhzRxKeyStateRAWLoad: - path_extract_filename_no_ext(subghz->file_path, file_name); + path_extract_filename(subghz->file_path, file_name, true); subghz_read_raw_set_status( subghz->subghz_read_raw, SubGhzReadRAWStatusLoadKeyTX, string_get_cstr(file_name)); subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE; break; case SubGhzRxKeyStateRAWSave: - path_extract_filename_no_ext(subghz->file_path, file_name); + path_extract_filename(subghz->file_path, file_name, true); subghz_read_raw_set_status( subghz->subghz_read_raw, SubGhzReadRAWStatusSaveKey, string_get_cstr(file_name)); subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE; @@ -171,7 +171,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { case SubGhzCustomEventViewReadRAWErase: subghz->txrx->rx_key_state = SubGhzRxKeyStateIDLE; if(subghz_scene_read_raw_update_filename(subghz)) { - strncpy(subghz->file_path_tmp, subghz->file_path, SUBGHZ_MAX_LEN_NAME); + string_set(subghz->file_path_tmp, subghz->file_path); subghz_delete_file(subghz); } notification_message(subghz->notifications, &sequence_reset_rgb); @@ -281,7 +281,6 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { , datetime.year, datetime.month, datetime.day , datetime.hour, datetime.minute ); - if(subghz_protocol_raw_save_to_file_init( (SubGhzProtocolDecoderRAW*)subghz->txrx->decoder_result, strings[0], @@ -296,7 +295,7 @@ bool subghz_scene_read_raw_on_event(void* context, SceneManagerEvent event) { subghz->state_notifications = SubGhzNotificationStateRx; subghz->txrx->rx_key_state = SubGhzRxKeyStateAddKey; } else { - string_set(subghz->error_str, "Function requires\nan SD card."); + string_set_str(subghz->error_str, "Function requires\nan SD card."); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); } } diff --git a/applications/subghz/scenes/subghz_scene_receiver_info.c b/applications/subghz/scenes/subghz_scene_receiver_info.c index 8a2637b21..950ea0d24 100644 --- a/applications/subghz/scenes/subghz_scene_receiver_info.c +++ b/applications/subghz/scenes/subghz_scene_receiver_info.c @@ -84,6 +84,7 @@ void subghz_scene_receiver_info_on_enter(void* context) { subghz_scene_receiver_info_callback, subghz); } + // Removed static check if(((subghz->txrx->decoder_result->protocol->flag & SubGhzProtocolFlag_Send) == SubGhzProtocolFlag_Send) && subghz->txrx->decoder_result->protocol->encoder->deserialize) { @@ -157,6 +158,7 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event) if(!subghz_scene_receiver_info_update_parser(subghz)) { return false; } + if((subghz->txrx->decoder_result->protocol->flag & SubGhzProtocolFlag_Save) == SubGhzProtocolFlag_Save) { subghz_file_name_clear(subghz); diff --git a/applications/subghz/scenes/subghz_scene_save_name.c b/applications/subghz/scenes/subghz_scene_save_name.c index 617709cc7..95fc19388 100644 --- a/applications/subghz/scenes/subghz_scene_save_name.c +++ b/applications/subghz/scenes/subghz_scene_save_name.c @@ -1,4 +1,6 @@ #include "../subghz_i.h" +#include "m-string.h" +#include "subghz/types.h" #include #include "../helpers/subghz_custom_event.h" #include @@ -20,45 +22,49 @@ void subghz_scene_save_name_on_enter(void* context) { bool dev_name_empty = false; string_t file_name; + string_t dir_name; string_init(file_name); + string_init(dir_name); - if(!strcmp(subghz->file_path, "")) { + if(!subghz_path_is_file(subghz->file_path)) { char file_name_buf[SUBGHZ_MAX_LEN_NAME] = {0}; set_random_name(file_name_buf, SUBGHZ_MAX_LEN_NAME); - string_set(file_name, file_name_buf); - strncpy(subghz->file_dir, SUBGHZ_APP_FOLDER, SUBGHZ_MAX_LEN_NAME); + string_set_str(file_name, file_name_buf); + string_set_str(subghz->file_path, SUBGHZ_APP_FOLDER); //highlighting the entire filename by default dev_name_empty = true; } else { - strncpy(subghz->file_path_tmp, subghz->file_path, SUBGHZ_MAX_LEN_NAME); - path_extract_dirname(subghz->file_path, file_name); - strncpy(subghz->file_dir, string_get_cstr(file_name), SUBGHZ_MAX_LEN_NAME); - path_extract_filename_no_ext(subghz->file_path, file_name); + string_set(subghz->file_path_tmp, subghz->file_path); + path_extract_dirname(string_get_cstr(subghz->file_path), dir_name); + path_extract_filename(subghz->file_path, file_name, true); if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) != SubGhzCustomEventManagerNoSet) { subghz_get_next_name_file(subghz, SUBGHZ_MAX_LEN_NAME); - path_extract_filename_no_ext(subghz->file_path, file_name); + path_extract_filename(subghz->file_path, file_name, true); if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) == SubGhzCustomEventManagerSetRAW) { dev_name_empty = true; } } + string_set(subghz->file_path, dir_name); } - strncpy(subghz->file_path, string_get_cstr(file_name), SUBGHZ_MAX_LEN_NAME); + + strncpy(subghz->file_name_tmp, string_get_cstr(file_name), SUBGHZ_MAX_LEN_NAME); text_input_set_header_text(text_input, "Name signal"); text_input_set_result_callback( text_input, subghz_scene_save_name_text_input_callback, subghz, - subghz->file_path, + subghz->file_name_tmp, MAX_TEXT_INPUT_LEN, // buffer size dev_name_empty); - ValidatorIsFile* validator_is_file = - validator_is_file_alloc_init(subghz->file_dir, SUBGHZ_APP_EXTENSION, NULL); + ValidatorIsFile* validator_is_file = validator_is_file_alloc_init( + string_get_cstr(subghz->file_path), SUBGHZ_APP_EXTENSION, NULL); text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); string_clear(file_name); + string_clear(dir_name); view_dispatcher_switch_to_view(subghz->view_dispatcher, SubGhzViewIdTextInput); } @@ -66,18 +72,15 @@ void subghz_scene_save_name_on_enter(void* context) { bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent event) { SubGhz* subghz = context; if(event.type == SceneManagerEventTypeBack) { - strncpy(subghz->file_path, subghz->file_path_tmp, SUBGHZ_MAX_LEN_NAME); + string_set(subghz->file_path, subghz->file_path_tmp); scene_manager_previous_scene(subghz->scene_manager); return true; } else if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubGhzCustomEventSceneSaveName) { - if(strcmp(subghz->file_path, "")) { - string_t temp_str; - string_init_printf( - temp_str, "%s/%s%s", subghz->file_dir, subghz->file_path, SUBGHZ_APP_EXTENSION); - strncpy(subghz->file_path, string_get_cstr(temp_str), SUBGHZ_MAX_LEN_NAME); - string_clear(temp_str); - if(strcmp(subghz->file_path_tmp, "")) { + if(strcmp(subghz->file_name_tmp, "")) { + string_cat_printf( + subghz->file_path, "/%s%s", subghz->file_name_tmp, SUBGHZ_APP_EXTENSION); + if(subghz_path_is_file(subghz->file_path_tmp)) { if(!subghz_rename_file(subghz)) { return false; } @@ -85,7 +88,7 @@ bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent event) { if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneSetType) != SubGhzCustomEventManagerNoSet) { subghz_save_protocol_to_file( - subghz, subghz->txrx->fff_data, subghz->file_path); + subghz, subghz->txrx->fff_data, string_get_cstr(subghz->file_path)); scene_manager_set_scene_state( subghz->scene_manager, SubGhzSceneSetType, @@ -95,13 +98,14 @@ bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent event) { subghz, subghz_history_get_raw_data( subghz->txrx->history, subghz->txrx->idx_menu_chosen), - subghz->file_path); + string_get_cstr(subghz->file_path)); } } if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) != SubGhzCustomEventManagerNoSet) { - subghz_protocol_raw_gen_fff_data(subghz->txrx->fff_data, subghz->file_path); + subghz_protocol_raw_gen_fff_data( + subghz->txrx->fff_data, string_get_cstr(subghz->file_path)); scene_manager_set_scene_state( subghz->scene_manager, SubGhzSceneReadRAW, SubGhzCustomEventManagerNoSet); } else { @@ -111,7 +115,7 @@ bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveSuccess); return true; } else { - string_set(subghz->error_str, "No name file"); + string_set_str(subghz->error_str, "No name file"); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowErrorSub); return true; } diff --git a/applications/subghz/scenes/subghz_scene_set_type.c b/applications/subghz/scenes/subghz_scene_set_type.c index 206863f4d..add461c93 100644 --- a/applications/subghz/scenes/subghz_scene_set_type.c +++ b/applications/subghz/scenes/subghz_scene_set_type.c @@ -49,7 +49,7 @@ bool subghz_scene_set_type_submenu_gen_data_protocol( subghz_receiver_search_decoder_base_by_name(subghz->txrx->receiver, protocol_name); if(subghz->txrx->decoder_result == NULL) { - string_set(subghz->error_str, "Protocol not found"); + string_set_str(subghz->error_str, "Protocol not found"); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowErrorSub); return false; } @@ -340,7 +340,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { } subghz_transmitter_free(subghz->txrx->transmitter); if(!generated_protocol) { - string_set( + string_set_str( subghz->error_str, "Function requires\nan SD card with\nfresh databases."); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); } @@ -364,12 +364,12 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { } subghz_transmitter_free(subghz->txrx->transmitter); if(!generated_protocol) { - string_set( + string_set_str( subghz->error_str, "Function requires\nan SD card with\nfresh databases."); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); } break; - case SubmenuIndexLiftMaster_315_00: + case SubmenuIndexLiftMaster_315_00: while(!subghz_protocol_secplus_v1_check_fixed(key)) { key = subghz_random_serial(); } diff --git a/applications/subghz/scenes/subghz_scene_transmitter.c b/applications/subghz/scenes/subghz_scene_transmitter.c index 38ab84994..b8b22749c 100644 --- a/applications/subghz/scenes/subghz_scene_transmitter.c +++ b/applications/subghz/scenes/subghz_scene_transmitter.c @@ -94,7 +94,7 @@ bool subghz_scene_transmitter_on_event(void* context, SceneManagerEvent event) { subghz->scene_manager, SubGhzSceneStart); return true; } else if(event.event == SubGhzCustomEventViewTransmitterError) { - string_set(subghz->error_str, "Protocol not found"); + string_set_str(subghz->error_str, "Protocol not found"); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowErrorSub); } } else if(event.type == SceneManagerEventTypeTick) { diff --git a/applications/subghz/subghz.c b/applications/subghz/subghz.c index 99c9db452..d8f620c2a 100644 --- a/applications/subghz/subghz.c +++ b/applications/subghz/subghz.c @@ -1,5 +1,7 @@ /* Abandon hope, all ye who enter here. */ +#include "m-string.h" +#include "subghz/types.h" #include "subghz_i.h" #include @@ -24,6 +26,9 @@ void subghz_tick_event_callback(void* context) { SubGhz* subghz_alloc() { SubGhz* subghz = malloc(sizeof(SubGhz)); + string_init(subghz->file_path); + string_init(subghz->file_path_tmp); + // GUI subghz->gui = furi_record_open("gui"); @@ -144,6 +149,7 @@ SubGhz* subghz_alloc() { subghz->txrx->worker = subghz_worker_alloc(); subghz->txrx->fff_data = flipper_format_string_alloc(); subghz->txrx->secure_data = malloc(sizeof(SecureData)); + subghz->txrx->environment = subghz_environment_alloc(); subghz_environment_set_came_atomo_rainbow_table_file_name( subghz->txrx->environment, "/ext/subghz/assets/came_atomo"); @@ -251,9 +257,9 @@ void subghz_free(SubGhz* subghz) { furi_record_close("notification"); subghz->notifications = NULL; - // About birds - furi_assert(subghz->file_path[SUBGHZ_MAX_LEN_NAME] == 0); - furi_assert(subghz->file_path_tmp[SUBGHZ_MAX_LEN_NAME] == 0); + // Path strings + string_clear(subghz->file_path); + string_clear(subghz->file_path_tmp); // The rest free(subghz); @@ -270,7 +276,7 @@ int32_t subghz_app(void* p) { // Check argument and run corresponding scene if(p) { if(subghz_key_load(subghz, p)) { - strncpy(subghz->file_path, p, SUBGHZ_MAX_LEN_NAME); + string_set_str(subghz->file_path, p); if((!strcmp(subghz->txrx->decoder_result->protocol->name, "RAW"))) { //Load Raw TX @@ -286,12 +292,13 @@ int32_t subghz_app(void* p) { view_dispatcher_stop(subghz->view_dispatcher); } } else { + string_set_str(subghz->file_path, SUBGHZ_APP_FOLDER); if(load_database) { scene_manager_next_scene(subghz->scene_manager, SubGhzSceneStart); } else { scene_manager_set_scene_state( subghz->scene_manager, SubGhzSceneShowError, SubGhzCustomEventManagerSet); - string_set( + string_set_str( subghz->error_str, "No SD card or\ndatabase found.\nSome app function\nmay be reduced."); scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError); diff --git a/applications/subghz/subghz_cli.c b/applications/subghz/subghz_cli.c index f919e1cf2..6c92a5d6b 100644 --- a/applications/subghz/subghz_cli.c +++ b/applications/subghz/subghz_cli.c @@ -303,7 +303,7 @@ void subghz_cli_command_decode_raw(Cli* cli, string_t args, void* context) { UNUSED(context); string_t file_name; string_init(file_name); - string_set(file_name, "/any/subghz/test.sub"); + string_set_str(file_name, "/any/subghz/test.sub"); Storage* storage = furi_record_open("storage"); FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); diff --git a/applications/subghz/subghz_history.c b/applications/subghz/subghz_history.c index cb30726ba..a8f86eecb 100644 --- a/applications/subghz/subghz_history.c +++ b/applications/subghz/subghz_history.c @@ -169,14 +169,14 @@ bool subghz_history_add_to_history( break; } if(!strcmp(string_get_cstr(instance->tmp_string), "KeeLoq")) { - string_set(instance->tmp_string, "KL "); + string_set_str(instance->tmp_string, "KL "); if(!flipper_format_read_string(item->flipper_string, "Manufacture", text)) { FURI_LOG_E(TAG, "Missing Protocol"); break; } string_cat(instance->tmp_string, text); } else if(!strcmp(string_get_cstr(instance->tmp_string), "Star Line")) { - string_set(instance->tmp_string, "SL "); + string_set_str(instance->tmp_string, "SL "); if(!flipper_format_read_string(item->flipper_string, "Manufacture", text)) { FURI_LOG_E(TAG, "Missing Protocol"); break; diff --git a/applications/subghz/subghz_i.c b/applications/subghz/subghz_i.c index 690e85f74..5439fd2a9 100644 --- a/applications/subghz/subghz_i.c +++ b/applications/subghz/subghz_i.c @@ -1,5 +1,8 @@ #include "subghz_i.h" +#include "assets_icons.h" +#include "m-string.h" +#include "subghz/types.h" #include #include #include @@ -45,11 +48,11 @@ void subghz_get_frequency_modulation(SubGhz* subghz, string_t frequency, string_ if(modulation != NULL) { if(subghz->txrx->preset == FuriHalSubGhzPresetOok650Async || subghz->txrx->preset == FuriHalSubGhzPresetOok270Async) { - string_set(modulation, "AM"); + string_set_str(modulation, "AM"); } else if( subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev238Async || subghz->txrx->preset == FuriHalSubGhzPreset2FSKDev476Async) { - string_set(modulation, "FM"); + string_set_str(modulation, "FM"); } else { furi_crash("SugGhz: Modulation is incorrect."); } @@ -191,8 +194,9 @@ void subghz_tx_stop(SubGhz* subghz) { //if protocol dynamic then we save the last upload if((subghz->txrx->decoder_result->protocol->type == SubGhzProtocolTypeDynamic) && - (strcmp(subghz->file_path, ""))) { - subghz_save_protocol_to_file(subghz, subghz->txrx->fff_data, subghz->file_path); + (subghz_path_is_file(subghz->file_path))) { + subghz_save_protocol_to_file( + subghz, subghz->txrx->fff_data, string_get_cstr(subghz->file_path)); } subghz_idle(subghz); notification_message(subghz->notifications, &sequence_reset_red); @@ -334,10 +338,10 @@ bool subghz_get_next_name_file(SubGhz* subghz, uint8_t max_len) { bool res = false; - if(strcmp(subghz->file_path, "")) { + if(subghz_path_is_file(subghz->file_path)) { //get the name of the next free file - path_extract_filename_no_ext(subghz->file_path, file_name); - path_extract_dirname(subghz->file_path, file_path); + path_extract_filename(subghz->file_path, file_name, true); + path_extract_dirname(string_get_cstr(subghz->file_path), file_path); storage_get_next_filename( storage, @@ -353,7 +357,7 @@ bool subghz_get_next_name_file(SubGhz* subghz, uint8_t max_len) { string_get_cstr(file_path), string_get_cstr(file_name), SUBGHZ_APP_EXTENSION); - strncpy(subghz->file_path, string_get_cstr(temp_str), SUBGHZ_MAX_LEN_NAME); + string_set(subghz->file_path, temp_str); res = true; } @@ -413,19 +417,17 @@ bool subghz_load_protocol_from_file(SubGhz* subghz) { string_init(file_path); // Input events and views are managed by file_select - bool res = dialog_file_select_show( + bool res = dialog_file_browser_show( subghz->dialogs, - SUBGHZ_APP_FOLDER, - SUBGHZ_APP_EXTENSION, subghz->file_path, - sizeof(subghz->file_path), - NULL); + subghz->file_path, + SUBGHZ_APP_EXTENSION, + true, + &I_sub1_10px, + true); if(res) { - string_printf( - file_path, "%s/%s%s", SUBGHZ_APP_FOLDER, subghz->file_path, SUBGHZ_APP_EXTENSION); - strncpy(subghz->file_path, string_get_cstr(file_path), SUBGHZ_MAX_LEN_NAME); - res = subghz_key_load(subghz, subghz->file_path); + res = subghz_key_load(subghz, string_get_cstr(subghz->file_path)); } string_clear(file_path); @@ -439,9 +441,9 @@ bool subghz_rename_file(SubGhz* subghz) { Storage* storage = furi_record_open("storage"); - if(strcmp(subghz->file_path_tmp, subghz->file_path)) { - FS_Error fs_result = - storage_common_rename(storage, subghz->file_path_tmp, subghz->file_path); + if(string_cmp(subghz->file_path_tmp, subghz->file_path)) { + FS_Error fs_result = storage_common_rename( + storage, string_get_cstr(subghz->file_path_tmp), string_get_cstr(subghz->file_path)); if(fs_result != FSE_OK) { dialog_message_show_storage_error(subghz->dialogs, "Cannot rename\n file/directory"); @@ -457,7 +459,7 @@ bool subghz_delete_file(SubGhz* subghz) { furi_assert(subghz); Storage* storage = furi_record_open("storage"); - bool result = storage_simply_remove(storage, subghz->file_path_tmp); + bool result = storage_simply_remove(storage, string_get_cstr(subghz->file_path_tmp)); furi_record_close("storage"); subghz_file_name_clear(subghz); @@ -467,8 +469,12 @@ bool subghz_delete_file(SubGhz* subghz) { void subghz_file_name_clear(SubGhz* subghz) { furi_assert(subghz); - memset(subghz->file_path, 0, sizeof(subghz->file_path)); - memset(subghz->file_path_tmp, 0, sizeof(subghz->file_path_tmp)); + string_set_str(subghz->file_path, SUBGHZ_APP_FOLDER); + string_reset(subghz->file_path_tmp); +} + +bool subghz_path_is_file(string_t path) { + return string_end_with_str_p(path, SUBGHZ_APP_EXTENSION); } uint32_t subghz_random_serial(void) { diff --git a/applications/subghz/subghz_i.h b/applications/subghz/subghz_i.h index b1a932836..accb79c00 100644 --- a/applications/subghz/subghz_i.h +++ b/applications/subghz/subghz_i.h @@ -36,7 +36,7 @@ #include #include -#define SUBGHZ_MAX_LEN_NAME 250 +#define SUBGHZ_MAX_LEN_NAME 64 /** SubGhzNotification state */ typedef enum { @@ -128,10 +128,9 @@ struct SubGhz { ByteInput* byte_input; Widget* widget; DialogsApp* dialogs; - char file_path[SUBGHZ_MAX_LEN_NAME + 1]; - char file_path_tmp[SUBGHZ_MAX_LEN_NAME + 1]; - //ToDo you can get rid of it, you need to refactor text input to return the path to the folder - char file_dir[SUBGHZ_MAX_LEN_NAME + 1]; + string_t file_path; + string_t file_path_tmp; + char file_name_tmp[SUBGHZ_MAX_LEN_NAME]; SubGhzNotificationState state_notifications; SubGhzViewReceiver* subghz_receiver; @@ -183,5 +182,6 @@ bool subghz_load_protocol_from_file(SubGhz* subghz); bool subghz_rename_file(SubGhz* subghz); bool subghz_delete_file(SubGhz* subghz); void subghz_file_name_clear(SubGhz* subghz); +bool subghz_path_is_file(string_t path); uint32_t subghz_random_serial(void); void subghz_hopper_update(SubGhz* subghz); diff --git a/applications/subghz/subghz_setting.c b/applications/subghz/subghz_setting.c index f5d3da5d4..6a589c03e 100644 --- a/applications/subghz/subghz_setting.c +++ b/applications/subghz/subghz_setting.c @@ -7,16 +7,14 @@ #define TAG "SubGhzSetting" -#define SUBGHZ_SETTING_FILE_VERSION 1 #define SUBGHZ_SETTING_FILE_TYPE "Flipper SubGhz Setting File" +#define SUBGHZ_SETTING_FILE_VERSION 1 -typedef enum { - SubGhzSettingStateNoLoad = 0, - SubGhzSettingStateLoadFrequencyDefault, - SubGhzSettingStateOkLoad, -} SubGhzSettingState; +#define FREQUENCY_FLAG_DEFAULT (1 << 31) +#define FREQUENCY_MASK (0xFFFFFFFF ^ FREQUENCY_FLAG_DEFAULT) -static const uint32_t subghz_frequencies[] = { +/* Default */ +static const uint32_t subghz_frequency_list[] = { /* 300 - 348 */ 300000000, 302757000, /* FCC ID N6U303NTX */ @@ -36,8 +34,7 @@ static const uint32_t subghz_frequencies[] = { 433220000, /* 2016-2020 Honda */ 433420000, 433889000, /* ROGUE? */ - - 433920000, /* LPD433 mid */ + 433920000 | FREQUENCY_FLAG_DEFAULT, /* LPD433 mid */ 434420000, 434775000, /* LPD433 last channels */ 438900000, @@ -51,7 +48,9 @@ static const uint32_t subghz_frequencies[] = { 928000000, 0, }; -static const uint32_t subghz_hopper_frequencies[] = { + +static const uint32_t subghz_hopper_frequency_list[] = { + 310000000, 315000000, 318000000, 390000000, @@ -59,13 +58,14 @@ static const uint32_t subghz_hopper_frequencies[] = { 868350000, 0, }; -static const uint32_t subghz_frequency_default_index = 9; -static const uint32_t subghz_frequencies_region_eu_ru[] = { +/* Europe and Russia */ +static const uint32_t subghz_frequency_list_region_eu_ru[] = { /* 300 - 348 */ 300000000, 303875000, 304250000, + 310000000, 315000000, 318000000, @@ -74,7 +74,7 @@ static const uint32_t subghz_frequencies_region_eu_ru[] = { 418000000, 433075000, /* LPD433 first */ 433420000, - 433920000, /* LPD433 mid */ + 433920000 | FREQUENCY_FLAG_DEFAULT, /* LPD433 mid */ 434420000, 434775000, /* LPD433 last channels */ 438900000, @@ -85,7 +85,8 @@ static const uint32_t subghz_frequencies_region_eu_ru[] = { 925000000, 0, }; -static const uint32_t subghz_hopper_frequencies_region_eu_ru[] = { +static const uint32_t subghz_hopper_frequency_list_region_eu_ru[] = { + 310000000, 315000000, 318000000, 390000000, @@ -93,13 +94,14 @@ static const uint32_t subghz_hopper_frequencies_region_eu_ru[] = { 868350000, 0, }; -static const uint32_t subghz_frequency_default_index_region_eu_ru = 9; -static const uint32_t subghz_frequencies_region_us_ca_au[] = { +/* Region 0 */ +static const uint32_t subghz_frequency_list_region_us_ca_au[] = { /* 300 - 348 */ 300000000, 303875000, 304250000, + 310000000, 315000000, 318000000, @@ -108,7 +110,7 @@ static const uint32_t subghz_frequencies_region_us_ca_au[] = { 418000000, 433075000, /* LPD433 first */ 433420000, - 433920000, /* LPD433 mid */ + 433920000 | FREQUENCY_FLAG_DEFAULT, /* LPD433 mid */ 434420000, 434775000, /* LPD433 last channels */ 438900000, @@ -119,7 +121,8 @@ static const uint32_t subghz_frequencies_region_us_ca_au[] = { 925000000, 0, }; -static const uint32_t subghz_hopper_frequencies_region_us_ca_au[] = { +static const uint32_t subghz_hopper_frequency_list_region_us_ca_au[] = { + 310000000, 315000000, 318000000, 390000000, @@ -127,13 +130,13 @@ static const uint32_t subghz_hopper_frequencies_region_us_ca_au[] = { 868350000, 0, }; -static const uint32_t subghz_frequency_default_index_region_us_ca_au = 9; -static const uint32_t subghz_frequencies_region_jp[] = { +static const uint32_t subghz_frequency_list_region_jp[] = { /* 300 - 348 */ 300000000, 303875000, 304250000, + 310000000, 315000000, 318000000, @@ -142,7 +145,7 @@ static const uint32_t subghz_frequencies_region_jp[] = { 418000000, 433075000, /* LPD433 first */ 433420000, - 433920000, /* LPD433 mid */ + 433920000 | FREQUENCY_FLAG_DEFAULT, /* LPD433 mid */ 434420000, 434775000, /* LPD433 last channels */ 438900000, @@ -153,7 +156,8 @@ static const uint32_t subghz_frequencies_region_jp[] = { 925000000, 0, }; -static const uint32_t subghz_hopper_frequencies_region_jp[] = { +static const uint32_t subghz_hopper_frequency_list_region_jp[] = { + 310000000, 315000000, 318000000, 390000000, @@ -161,72 +165,68 @@ static const uint32_t subghz_hopper_frequencies_region_jp[] = { 868350000, 0, }; -static const uint32_t subghz_frequency_default_index_region_jp = 9; -LIST_DEF(FrequenciesList, uint32_t) +LIST_DEF(FrequencyList, uint32_t) + +#define M_OPL_FrequencyList_t() LIST_OPLIST(FrequencyList) struct SubGhzSetting { - FrequenciesList_t frequencies; - FrequenciesList_t hopper_frequencies; - size_t frequencies_count; - size_t hopper_frequencies_count; - uint32_t frequency_default_index; + FrequencyList_t frequencies; + FrequencyList_t hopper_frequencies; }; SubGhzSetting* subghz_setting_alloc(void) { SubGhzSetting* instance = malloc(sizeof(SubGhzSetting)); - FrequenciesList_init(instance->frequencies); - FrequenciesList_init(instance->hopper_frequencies); + FrequencyList_init(instance->frequencies); + FrequencyList_init(instance->hopper_frequencies); return instance; } void subghz_setting_free(SubGhzSetting* instance) { furi_assert(instance); - FrequenciesList_clear(instance->frequencies); - FrequenciesList_clear(instance->hopper_frequencies); + FrequencyList_clear(instance->frequencies); + FrequencyList_clear(instance->hopper_frequencies); free(instance); } -void subghz_setting_load_default( +static void subghz_setting_load_default_region( SubGhzSetting* instance, const uint32_t frequencies[], - const uint32_t hopper_frequencies[], - const uint32_t frequency_default_index) { + const uint32_t hopper_frequencies[]) { furi_assert(instance); - size_t i = 0; - FrequenciesList_clear(instance->frequencies); - FrequenciesList_clear(instance->hopper_frequencies); - i = 0; - while(frequencies[i]) { - FrequenciesList_push_back(instance->frequencies, frequencies[i]); - i++; - } - instance->frequencies_count = i; - i = 0; - while(hopper_frequencies[i]) { - FrequenciesList_push_back(instance->hopper_frequencies, hopper_frequencies[i]); - i++; - } - instance->hopper_frequencies_count = i; + FrequencyList_reset(instance->frequencies); + FrequencyList_reset(instance->hopper_frequencies); - instance->frequency_default_index = frequency_default_index; + while(*frequencies) { + FrequencyList_push_back(instance->frequencies, *frequencies); + frequencies++; + } + + while(*hopper_frequencies) { + FrequencyList_push_back(instance->hopper_frequencies, *hopper_frequencies); + hopper_frequencies++; + } +} + +// Region check removed +void subghz_setting_load_default(SubGhzSetting* instance) { + subghz_setting_load_default_region( + instance, subghz_frequency_list, subghz_hopper_frequency_list); } void subghz_setting_load(SubGhzSetting* instance, const char* file_path) { furi_assert(instance); - FrequenciesList_clear(instance->frequencies); - FrequenciesList_clear(instance->hopper_frequencies); - Storage* storage = furi_record_open("storage"); FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); string_t temp_str; string_init(temp_str); uint32_t temp_data32; - SubGhzSettingState loading = SubGhzSettingStateNoLoad; - uint16_t i = 0; + bool temp_bool; + + subghz_setting_load_default(instance); if(file_path) { do { @@ -247,63 +247,60 @@ void subghz_setting_load(SubGhzSetting* instance, const char* file_path) { break; } + // Standard frequencies (optional) + temp_bool = true; + flipper_format_read_bool(fff_data_file, "add_standard_frequencies", &temp_bool, 1); + if(!temp_bool) { + FURI_LOG_I(TAG, "Removing standard frequencies"); + FrequencyList_reset(instance->frequencies); + FrequencyList_reset(instance->hopper_frequencies); + } else { + FURI_LOG_I(TAG, "Keeping standard frequencies"); + } + + // Load frequencies if(!flipper_format_rewind(fff_data_file)) { FURI_LOG_E(TAG, "Rewind error"); break; } - i = 0; while(flipper_format_read_uint32( - fff_data_file, "Frequency", (uint32_t*)&temp_data32, 1)) { + fff_data_file, "frequency", (uint32_t*)&temp_data32, 1)) { if(furi_hal_subghz_is_frequency_valid(temp_data32)) { FURI_LOG_I(TAG, "Frequency loaded %lu", temp_data32); - FrequenciesList_push_back(instance->frequencies, temp_data32); - i++; + FrequencyList_push_back(instance->frequencies, temp_data32); } else { FURI_LOG_E(TAG, "Frequency not supported %lu", temp_data32); } } - instance->frequencies_count = i; + // Load hopper frequencies if(!flipper_format_rewind(fff_data_file)) { FURI_LOG_E(TAG, "Rewind error"); break; } - i = 0; while(flipper_format_read_uint32( - fff_data_file, "Hopper_frequency", (uint32_t*)&temp_data32, 1)) { + fff_data_file, "hopper_frequency", (uint32_t*)&temp_data32, 1)) { if(furi_hal_subghz_is_frequency_valid(temp_data32)) { FURI_LOG_I(TAG, "Hopper frequency loaded %lu", temp_data32); - FrequenciesList_push_back(instance->hopper_frequencies, temp_data32); - i++; + FrequencyList_push_back(instance->hopper_frequencies, temp_data32); } else { FURI_LOG_E(TAG, "Hopper frequency not supported %lu", temp_data32); } } - instance->hopper_frequencies_count = i; + // Default frequency (optional) if(!flipper_format_rewind(fff_data_file)) { FURI_LOG_E(TAG, "Rewind error"); break; } - if(!flipper_format_read_uint32( - fff_data_file, "Frequency_default", (uint32_t*)&temp_data32, 1)) { - FURI_LOG_E(TAG, "Frequency default missing"); - break; - } - - for(i = 0; i < instance->frequencies_count; i++) { - if(subghz_setting_get_frequency(instance, i) == temp_data32) { - instance->frequency_default_index = i; - FURI_LOG_I(TAG, "Frequency default index %lu", i); - loading = SubGhzSettingStateLoadFrequencyDefault; - break; - } - } - - if(loading == SubGhzSettingStateLoadFrequencyDefault) { - loading = SubGhzSettingStateOkLoad; - } else { - FURI_LOG_E(TAG, "Frequency default index missing"); + if(flipper_format_read_uint32(fff_data_file, "default_frequency", &temp_data32, 1)) { + for + M_EACH(frequency, instance->frequencies, FrequencyList_t) { + *frequency &= FREQUENCY_MASK; + if(*frequency == temp_data32) { + *frequency |= FREQUENCY_FLAG_DEFAULT; + } + } } } while(false); } @@ -312,67 +309,56 @@ void subghz_setting_load(SubGhzSetting* instance, const char* file_path) { flipper_format_free(fff_data_file); furi_record_close("storage"); - if(loading != SubGhzSettingStateOkLoad) { - switch(furi_hal_version_get_hw_region()) { - case FuriHalVersionRegionEuRu: - subghz_setting_load_default( - instance, - subghz_frequencies_region_eu_ru, - subghz_hopper_frequencies_region_eu_ru, - subghz_frequency_default_index_region_eu_ru); - break; - case FuriHalVersionRegionUsCaAu: - subghz_setting_load_default( - instance, - subghz_frequencies_region_us_ca_au, - subghz_hopper_frequencies_region_us_ca_au, - subghz_frequency_default_index_region_us_ca_au); - break; - case FuriHalVersionRegionJp: - subghz_setting_load_default( - instance, - subghz_frequencies_region_jp, - subghz_hopper_frequencies_region_jp, - subghz_frequency_default_index_region_jp); - break; - - default: - subghz_setting_load_default( - instance, - subghz_frequencies, - subghz_hopper_frequencies, - subghz_frequency_default_index); - break; - } + if(!FrequencyList_size(instance->frequencies) || + !FrequencyList_size(instance->hopper_frequencies)) { + FURI_LOG_E(TAG, "Error loading user settings, loading default settings"); + subghz_setting_load_default(instance); } } size_t subghz_setting_get_frequency_count(SubGhzSetting* instance) { furi_assert(instance); - return instance->frequencies_count; + return FrequencyList_size(instance->frequencies); } size_t subghz_setting_get_hopper_frequency_count(SubGhzSetting* instance) { furi_assert(instance); - return instance->hopper_frequencies_count; + return FrequencyList_size(instance->hopper_frequencies); } uint32_t subghz_setting_get_frequency(SubGhzSetting* instance, size_t idx) { furi_assert(instance); - return *FrequenciesList_get(instance->frequencies, idx); + uint32_t* ret = FrequencyList_get(instance->frequencies, idx); + if(ret) { + return (*ret) & FREQUENCY_MASK; + } else { + return 0; + } } uint32_t subghz_setting_get_hopper_frequency(SubGhzSetting* instance, size_t idx) { furi_assert(instance); - return *FrequenciesList_get(instance->hopper_frequencies, idx); + uint32_t* ret = FrequencyList_get(instance->hopper_frequencies, idx); + if(ret) { + return *ret; + } else { + return 0; + } } uint32_t subghz_setting_get_frequency_default_index(SubGhzSetting* instance) { furi_assert(instance); - return instance->frequency_default_index; + for(size_t i = 0; i < FrequencyList_size(instance->frequencies); i++) { + uint32_t frequency = *FrequencyList_get(instance->frequencies, i); + if(frequency & FREQUENCY_FLAG_DEFAULT) { + return i; + } + } + return 0; } uint32_t subghz_setting_get_default_frequency(SubGhzSetting* instance) { furi_assert(instance); - return *FrequenciesList_get(instance->frequencies, instance->frequency_default_index); + return subghz_setting_get_frequency( + instance, subghz_setting_get_frequency_default_index(instance)); } diff --git a/applications/subghz/views/receiver.c b/applications/subghz/views/receiver.c index 7b19cbcf2..866d82726 100644 --- a/applications/subghz/views/receiver.c +++ b/applications/subghz/views/receiver.c @@ -111,9 +111,9 @@ void subghz_view_receiver_add_data_statusbar( furi_assert(subghz_receiver); with_view_model( subghz_receiver->view, (SubGhzViewReceiverModel * model) { - string_set(model->frequency_str, frequency_str); - string_set(model->preset_str, preset_str); - string_set(model->history_stat_str, history_stat_str); + string_set_str(model->frequency_str, frequency_str); + string_set_str(model->preset_str, preset_str); + string_set_str(model->history_stat_str, history_stat_str); return true; }); } diff --git a/applications/subghz/views/subghz_frequency_analyzer.c b/applications/subghz/views/subghz_frequency_analyzer.c index ec3c5ee9a..d3f773159 100644 --- a/applications/subghz/views/subghz_frequency_analyzer.c +++ b/applications/subghz/views/subghz_frequency_analyzer.c @@ -111,7 +111,7 @@ void subghz_frequency_analyzer_enter(void* context) { SubGhzFrequencyAnalyzer* instance = context; //Start worker - instance->worker = subghz_frequency_analyzer_worker_alloc(); + instance->worker = subghz_frequency_analyzer_worker_alloc(instance->context); subghz_frequency_analyzer_worker_set_pair_callback( instance->worker, diff --git a/applications/subghz/views/subghz_read_raw.c b/applications/subghz/views/subghz_read_raw.c index ff3ba45a3..a4807d775 100644 --- a/applications/subghz/views/subghz_read_raw.c +++ b/applications/subghz/views/subghz_read_raw.c @@ -46,8 +46,8 @@ void subghz_read_raw_add_data_statusbar( furi_assert(instance); with_view_model( instance->view, (SubGhzReadRAWModel * model) { - string_set(model->frequency_str, frequency_str); - string_set(model->preset_str, preset_str); + string_set_str(model->frequency_str, frequency_str); + string_set_str(model->preset_str, preset_str); return true; }); } @@ -372,7 +372,7 @@ bool subghz_read_raw_input(InputEvent* event, void* context) { model->satus = SubGhzReadRAWStatusStart; model->rssi_history_end = false; model->ind_write = 0; - string_set(model->sample_write, "0 spl."); + string_set_str(model->sample_write, "0 spl."); string_reset(model->file_name); instance->callback(SubGhzCustomEventViewReadRAWErase, instance->context); } @@ -424,7 +424,7 @@ void subghz_read_raw_set_status( model->rssi_history_end = false; model->ind_write = 0; string_reset(model->file_name); - string_set(model->sample_write, "0 spl."); + string_set_str(model->sample_write, "0 spl."); return true; }); break; @@ -441,8 +441,8 @@ void subghz_read_raw_set_status( model->satus = SubGhzReadRAWStatusLoadKeyIDLE; model->rssi_history_end = false; model->ind_write = 0; - string_set(model->file_name, file_name); - string_set(model->sample_write, "RAW"); + string_set_str(model->file_name, file_name); + string_set_str(model->sample_write, "RAW"); return true; }); break; @@ -451,8 +451,8 @@ void subghz_read_raw_set_status( instance->view, (SubGhzReadRAWModel * model) { model->satus = SubGhzReadRAWStatusLoadKeyIDLE; if(!model->ind_write) { - string_set(model->file_name, file_name); - string_set(model->sample_write, "RAW"); + string_set_str(model->file_name, file_name); + string_set_str(model->sample_write, "RAW"); } else { string_reset(model->file_name); } diff --git a/applications/subghz/views/transmitter.c b/applications/subghz/views/transmitter.c index 3113e31f6..3cbcf098a 100644 --- a/applications/subghz/views/transmitter.c +++ b/applications/subghz/views/transmitter.c @@ -36,9 +36,9 @@ void subghz_view_transmitter_add_data_to_show( furi_assert(subghz_transmitter); with_view_model( subghz_transmitter->view, (SubGhzViewTransmitterModel * model) { - string_set(model->key_str, key_str); - string_set(model->frequency_str, frequency_str); - string_set(model->preset_str, preset_str); + string_set_str(model->key_str, key_str); + string_set_str(model->frequency_str, frequency_str); + string_set_str(model->preset_str, preset_str); model->show_button = show_button; return true; }); diff --git a/applications/tetris_game/tetris_game.c b/applications/tetris_game/tetris_game.c deleted file mode 100644 index 18c221b89..000000000 --- a/applications/tetris_game/tetris_game.c +++ /dev/null @@ -1,479 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#define BORDER_OFFSET 1 -#define MARGIN_OFFSET 3 -#define BLOCK_HEIGHT 6 -#define BLOCK_WIDTH 6 - -#define FIELD_WIDTH 11 -#define FIELD_HEIGHT 24 - -typedef struct Point { - // Also used for offset data, which is sometimes negative - int8_t x, y; -} Point; - -// Rotation logic taken from -// https://www.youtube.com/watch?v=yIpk5TJ_uaI -typedef enum { - OffsetTypeCommon, - OffsetTypeI, - OffsetTypeO -} OffsetType; - -// Since we only support rotating clockwise, these are actual translation values, -// not values to be subtracted to get translation values - -static const Point rotOffsetTranslation[3][4][5] = { - { - { {0,0}, {-1,0}, {-1,-1}, {0,2}, {-1,2} }, - { {0,0}, {1,0}, {1,1}, {0,-2}, {1,-2} }, - { {0,0}, {1,0}, {1,-1}, {0,2}, {1,2} }, - { {0,0}, {-1,0}, {-1,1}, {0,-2}, {-1,-2} } - }, - { - { {1,0}, {-1,0}, {2,0}, {-1,1}, {2,-2} }, - { {0,1}, {-1,1}, {2,1}, {-1,-1}, {2,2} }, - { {-1,0}, {1,0}, {-2,0}, {1,-1}, {-2,2} }, - { {0,-1}, {1,-1}, {-2,-1}, {1,1}, {-2,-2} } - }, - { - { {0,-1}, {0,0}, {0,0}, {0,0}, {0,0} }, - { {1,0}, {0,0}, {0,0}, {0,0}, {0,0} }, - { {0,1}, {0,0}, {0,0}, {0,0}, {0,0} }, - { {-1,0}, {0,0}, {0,0}, {0,0}, {0,0} } - } -}; - -typedef struct { - Point p[4]; - uint8_t rotIdx; - OffsetType offsetType; -} Piece; - -// Shapes @ spawn locations, rotation point first -static Piece shapes[] = { - { .p = {{5, 1}, {4, 0}, {5, 0}, {6, 1}}, .rotIdx = 0, .offsetType = OffsetTypeCommon }, // Z - { .p = {{5, 1}, {4, 1}, {5, 0}, {6, 0}}, .rotIdx = 0, .offsetType = OffsetTypeCommon }, // S - { .p = {{5, 1}, {4, 1}, {6, 1}, {6, 0}}, .rotIdx = 0, .offsetType = OffsetTypeCommon }, // L - { .p = {{5, 1}, {4, 0}, {4, 1}, {6, 1}}, .rotIdx = 0, .offsetType = OffsetTypeCommon }, // J - { .p = {{5, 1}, {4, 1}, {5, 0}, {6, 1}}, .rotIdx = 0, .offsetType = OffsetTypeCommon }, // T - { .p = {{5, 1}, {4, 1}, {6, 1}, {7, 1}}, .rotIdx = 0, .offsetType = OffsetTypeI }, // I - { .p = {{5, 1}, {5, 0}, {6, 0}, {6, 1}}, .rotIdx = 0, .offsetType = OffsetTypeO } // O -}; - -typedef enum { - GameStatePlaying, - GameStateGameOver -} GameState; - -typedef struct { - bool playField[FIELD_HEIGHT][FIELD_WIDTH]; - Piece currPiece; - uint16_t numLines; - uint16_t fallSpeed; - GameState gameState; - osTimerId_t timer; -} TetrisState; - -typedef enum { - EventTypeTick, - EventTypeKey, -} EventType; - -typedef struct { - EventType type; - InputEvent input; -} TetrisEvent; - -static void tetris_game_draw_border(Canvas* const canvas) { - canvas_draw_line(canvas, 0, 0, 0, 127); - canvas_draw_line(canvas, 0, 127, 63, 127); - canvas_draw_line(canvas, 63, 127, 63, 0); - - canvas_draw_line(canvas, 2, 0, 2, 125); - canvas_draw_line(canvas, 2, 125, 61, 125); - canvas_draw_line(canvas, 61, 125, 61, 0); -} - -static void tetris_game_draw_playfield(Canvas* const canvas, const TetrisState* tetris_state) { - // Playfield: 11 x 24 - - for (int y = 0; y < FIELD_HEIGHT; y++) { - for (int x = 0; x < FIELD_WIDTH; x++) { - if (tetris_state->playField[y][x]) { - uint16_t xOffset = x * 5; - uint16_t yOffset = y * 5; - - canvas_draw_rframe( - canvas, - BORDER_OFFSET + MARGIN_OFFSET + xOffset, - BORDER_OFFSET + MARGIN_OFFSET + yOffset - 1, - BLOCK_WIDTH, - BLOCK_HEIGHT, - 1 - ); - canvas_draw_dot( - canvas, - BORDER_OFFSET + MARGIN_OFFSET + xOffset + 2, - BORDER_OFFSET + MARGIN_OFFSET + yOffset + 1 - ); - canvas_draw_dot( - canvas, - BORDER_OFFSET + MARGIN_OFFSET + xOffset + 3, - BORDER_OFFSET + MARGIN_OFFSET + yOffset + 1 - ); - canvas_draw_dot( - canvas, - BORDER_OFFSET + MARGIN_OFFSET + xOffset + 2, - BORDER_OFFSET + MARGIN_OFFSET + yOffset + 2 - ); - } - } - } -} - -static void tetris_game_render_callback(Canvas* const canvas, void* ctx) { - const TetrisState* tetris_state = acquire_mutex((ValueMutex*)ctx, 25); - if(tetris_state == NULL) { - FURI_LOG_E("TetrisGame", "it null"); - return; - } - - tetris_game_draw_border(canvas); - tetris_game_draw_playfield(canvas, tetris_state); - - if(tetris_state->gameState == GameStateGameOver) { - // 128 x 64 - canvas_set_color(canvas, ColorWhite); - canvas_draw_box(canvas, 1, 52, 62, 24); - - canvas_set_color(canvas, ColorBlack); - canvas_draw_frame(canvas, 1, 52, 62, 24); - - canvas_set_font(canvas, FontPrimary); - canvas_draw_str(canvas, 4, 63, "Game Over"); - - char buffer[13]; - snprintf(buffer, sizeof(buffer), "Lines: %u", tetris_state->numLines); - canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned(canvas, 32, 73, AlignCenter, AlignBottom, buffer); - } - release_mutex((ValueMutex *)ctx, tetris_state); - } - -static void tetris_game_input_callback(InputEvent* input_event, osMessageQueueId_t event_queue) { - furi_assert(event_queue); - - TetrisEvent event = {.type = EventTypeKey, .input = *input_event}; - osMessageQueuePut(event_queue, &event, 0, osWaitForever); -} - -static void tetris_game_init_state(TetrisState* tetris_state) { - tetris_state->gameState = GameStatePlaying; - tetris_state->numLines = 0; - tetris_state->fallSpeed = 500; - memset(tetris_state->playField, 0, sizeof(tetris_state->playField)); - - memcpy(&tetris_state->currPiece, &shapes[rand() % 7], sizeof(tetris_state->currPiece)); - - osTimerStart(tetris_state->timer, tetris_state->fallSpeed); -} - -static void tetris_game_remove_curr_piece(TetrisState* tetris_state) { - for (int i = 0; i < 4; i++) { - uint8_t x = tetris_state->currPiece.p[i].x; - uint8_t y = tetris_state->currPiece.p[i].y; - - tetris_state->playField[y][x] = false; - } -} - -static void tetris_game_render_curr_piece(TetrisState* tetris_state) { - for (int i = 0; i < 4; i++) { - uint8_t x = tetris_state->currPiece.p[i].x; - uint8_t y = tetris_state->currPiece.p[i].y; - - tetris_state->playField[y][x] = true; - } -} - -static void tetris_game_rotate_shape(Point currShape[], Point newShape[]) { - // Copy shape data - for(int i = 0; i < 4; i++) { - newShape[i] = currShape[i]; - } - - for (int i = 1; i < 4; i++) { - int8_t relX = currShape[i].x - currShape[0].x; - int8_t relY = currShape[i].y - currShape[0].y; - - // Matrix rotation thing - int8_t newRelX = (relX * 0) + (relY * -1); - int8_t newRelY = (relX * 1) + (relY * 0); - - newShape[i].x = currShape[0].x + newRelX; - newShape[i].y = currShape[0].y + newRelY; - } -} - -static void tetris_game_apply_kick(Point points[], Point kick) { - for(int i = 0; i < 4; i++) { - points[i].x += kick.x; - points[i].y += kick.y; - } -} - -static bool tetris_game_is_valid_pos(TetrisState* tetris_state, Point* shape) { - for (int i = 0; i < 4; i++) { - if(shape[i].x < 0 || shape[i].x > (FIELD_WIDTH - 1) || tetris_state->playField[shape[i].y][shape[i].x] == true) { - return false; - } - } - return true; -} - -static void tetris_game_try_rotation(TetrisState* tetris_state, Piece *newPiece) { - uint8_t currRotIdx = tetris_state->currPiece.rotIdx; - - Point *rotatedShape = malloc(sizeof(Point) * 4); - Point *kickedShape = malloc(sizeof(Point) * 4); - - memcpy(rotatedShape, &tetris_state->currPiece.p, sizeof(tetris_state->currPiece.p)); - - tetris_game_rotate_shape(tetris_state->currPiece.p, rotatedShape); - - for(int i = 0; i < 5; i++) { - memcpy(kickedShape, rotatedShape, (sizeof(Point) * 4)); - tetris_game_apply_kick(kickedShape, rotOffsetTranslation[newPiece->offsetType][currRotIdx][i]); - - if(tetris_game_is_valid_pos(tetris_state, kickedShape)) { - memcpy(&newPiece->p, kickedShape, sizeof(newPiece->p)); - newPiece->rotIdx = (newPiece->rotIdx + 1) % 4; - break; - } - } - free(rotatedShape); - free(kickedShape); -} - -static bool tetris_game_row_is_line(bool row[]) { - for(int i = 0; i < FIELD_WIDTH; i++) { - if(row[i] == false) - return false; - } - return true; -} - -static void tetris_game_check_for_lines(TetrisState* tetris_state, uint8_t* lines, uint8_t* numLines) { - for(int i = 0; i < FIELD_HEIGHT; i++) { - if(tetris_game_row_is_line(tetris_state->playField[i])) { - *(lines++) = i; - *numLines += 1; - } - } -} - -static bool tetris_game_piece_at_bottom(TetrisState* tetris_state, Piece* newPiece) { - for (int i = 0; i < 4; i++) { - Point *pos = (Point *)&newPiece->p; - if (pos[i].y >= FIELD_HEIGHT || tetris_state->playField[pos[i].y][pos[i].x] == true) { - return true; - } - } - return false; -} - -static void tetris_game_update_timer_callback(osMessageQueueId_t event_queue) { - furi_assert(event_queue); - - TetrisEvent event = {.type = EventTypeTick}; - osMessageQueuePut(event_queue, &event, 0, osWaitForever); -} - -static void tetris_game_process_step(TetrisState* tetris_state, Piece* newPiece, bool wasDownMove) { - if(tetris_state->gameState == GameStateGameOver) - return; - - tetris_game_remove_curr_piece(tetris_state); - - if(wasDownMove) { - if(tetris_game_piece_at_bottom(tetris_state, newPiece)) { - osTimerStop(tetris_state->timer); - - tetris_game_render_curr_piece(tetris_state); - uint8_t numLines = 0; - uint8_t lines[] = { 0,0,0,0 }; - - tetris_game_check_for_lines(tetris_state, lines, &numLines); - if(numLines > 0) { - for(int i = 0; i < numLines; i++) { - - // zero out row - for(int j = 0; j < FIELD_WIDTH; j++) { - tetris_state->playField[lines[i]][j] = false; - } - // move all above rows down - for(int k = lines[i]; k >= 0 ; k--) { - for(int m = 0; m < FIELD_WIDTH; m++) { - tetris_state->playField[k][m] = (k == 0) ? false : tetris_state->playField[k-1][m]; - } - } - } - - uint16_t oldNumLines = tetris_state->numLines; - tetris_state->numLines += numLines; - if((oldNumLines / 10) % 10 != (tetris_state->numLines / 10) % 10) { - tetris_state->fallSpeed -= 50; - } - } - - // Check for game over - Piece* spawnedPiece = &shapes[rand() % 7]; - if(!tetris_game_is_valid_pos(tetris_state, spawnedPiece->p)) { - tetris_state->gameState = GameStateGameOver; - } else { - memcpy(&tetris_state->currPiece, spawnedPiece, sizeof(tetris_state->currPiece)); - osTimerStart(tetris_state->timer, tetris_state->fallSpeed); - } - } - } - - if(tetris_game_is_valid_pos(tetris_state, newPiece->p)) { - memcpy(&tetris_state->currPiece, newPiece, sizeof(tetris_state->currPiece)); - } - - tetris_game_render_curr_piece(tetris_state); -} - - -int32_t tetris_game_app() { - srand(DWT->CYCCNT); - - osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(TetrisEvent), NULL); - - TetrisState* tetris_state = malloc(sizeof(TetrisState)); - - ValueMutex state_mutex; - if(!init_mutex(&state_mutex, tetris_state, sizeof(TetrisState))) { - FURI_LOG_E("TetrisGame", "cannot create mutex\r\n"); - free(tetris_state); - return 255; - } - - // Not doing this eventually causes issues with TimerSvc due to not sleeping/yielding enough in this task - TaskHandle_t timer_task = xTaskGetHandle(configTIMER_SERVICE_TASK_NAME); - TaskHandle_t curr_task = xTaskGetHandle("Tetris Game"); - - uint32_t origTimerPrio = uxTaskPriorityGet(timer_task); - uint32_t myPrio = uxTaskPriorityGet(curr_task); - vTaskPrioritySet(timer_task, myPrio + 1); - - ViewPort* view_port = view_port_alloc(); - view_port_set_orientation(view_port, ViewPortOrientationVertical); - view_port_draw_callback_set(view_port, tetris_game_render_callback, &state_mutex); - view_port_input_callback_set(view_port, tetris_game_input_callback, event_queue); - - // Open GUI and register view_port - Gui* gui = furi_record_open("gui"); - gui_add_view_port(gui, view_port, GuiLayerFullscreen); - - tetris_state->timer = osTimerNew(tetris_game_update_timer_callback, osTimerPeriodic, event_queue, NULL); - tetris_game_init_state(tetris_state); - - TetrisEvent event; - - Piece *newPiece = malloc(sizeof(Piece)); - uint8_t downRepeatCounter = 0; - - for(bool processing = true; processing;) { - // This 10U implicitly sets the game loop speed. downRepeatCounter relies on this value - osStatus_t event_status = osMessageQueueGet(event_queue, &event, NULL, 10U); - - TetrisState* tetris_state = (TetrisState*)acquire_mutex_block(&state_mutex); - - memcpy(newPiece, &tetris_state->currPiece, sizeof(tetris_state->currPiece)); - bool wasDownMove = false; - - if(!furi_hal_gpio_read(&gpio_button_right)) { - if(downRepeatCounter > 3) { - for (int i = 0; i < 4; i++) { - newPiece->p[i].y += 1; - } - downRepeatCounter = 0; - wasDownMove = true; - } else { - downRepeatCounter++; - } - } - - if(event_status == osOK) { - if(event.type == EventTypeKey) { - if(event.input.type == InputTypePress || event.input.type == InputTypeLong || event.input.type == InputTypeRepeat) { - switch(event.input.key) { - case InputKeyUp: - break; - case InputKeyDown: - break; - case InputKeyRight: - for (int i = 0; i < 4; i++) { - newPiece->p[i].x += 1; - } - break; - case InputKeyLeft: - for (int i = 0; i < 4; i++) { - newPiece->p[i].x -= 1; - } - break; - case InputKeyOk: - if(tetris_state->gameState == GameStatePlaying) { - tetris_game_remove_curr_piece(tetris_state); - tetris_game_try_rotation(tetris_state, newPiece); - tetris_game_render_curr_piece(tetris_state); - } else { - tetris_game_init_state(tetris_state); - } - break; - case InputKeyBack: - processing = false; - break; - } - } - } else if(event.type == EventTypeTick) { - // TODO: This is inverted. it returns true when the button is not pressed. - // see macro in input.c and do that - if(furi_hal_gpio_read(&gpio_button_right)) { - for (int i = 0; i < 4; i++) { - newPiece->p[i].y += 1; - } - wasDownMove = true; - } - } - } - - tetris_game_process_step(tetris_state, newPiece, wasDownMove); - - view_port_update(view_port); - release_mutex(&state_mutex, tetris_state); - } - - osTimerDelete(tetris_state->timer); - view_port_enabled_set(view_port, false); - gui_remove_view_port(gui, view_port); - furi_record_close("gui"); - view_port_free(view_port); - osMessageQueueDelete(event_queue); - delete_mutex(&state_mutex); - vTaskPrioritySet(timer_task, origTimerPrio); - free(newPiece); - free(tetris_state); - - return 0; -} diff --git a/applications/wav_player/wav_parser.c b/applications/wav_player/wav_parser.c deleted file mode 100644 index c2897706c..000000000 --- a/applications/wav_player/wav_parser.c +++ /dev/null @@ -1,84 +0,0 @@ -#include "wav_parser.h" - -#define TAG "WavParser" - -const char* format_text(FormatTag tag) { - switch(tag) { - case FormatTagPCM: - return "PCM"; - case FormatTagIEEE_FLOAT: - return "IEEE FLOAT"; - default: - return "Unknown"; - } -}; - -struct WavParser { - WavHeaderChunk header; - WavFormatChunk format; - WavDataChunk data; - size_t wav_data_start; - size_t wav_data_end; -}; - -WavParser* wav_parser_alloc() { - return malloc(sizeof(WavParser)); -} - -void wav_parser_free(WavParser* parser) { - free(parser); -} - -bool wav_parser_parse(WavParser* parser, Stream* stream) { - stream_read(stream, (uint8_t*)&parser->header, sizeof(WavHeaderChunk)); - stream_read(stream, (uint8_t*)&parser->format, sizeof(WavFormatChunk)); - stream_read(stream, (uint8_t*)&parser->data, sizeof(WavDataChunk)); - - if(memcmp(parser->header.riff, "RIFF", 4) != 0 || - memcmp(parser->header.wave, "WAVE", 4) != 0) { - FURI_LOG_E(TAG, "WAV: wrong header"); - return false; - } - - if(memcmp(parser->format.fmt, "fmt ", 4) != 0) { - FURI_LOG_E(TAG, "WAV: wrong format"); - return false; - } - - if(parser->format.tag != FormatTagPCM || memcmp(parser->data.data, "data", 4) != 0) { - FURI_LOG_E( - TAG, - "WAV: non-PCM format %u, next '%lu'", - parser->format.tag, - (uint32_t)parser->data.data); - return false; - } - - FURI_LOG_I( - TAG, - "Format tag: %s, ch: %u, smplrate: %lu, bps: %lu, bits: %u", - format_text(parser->format.tag), - parser->format.channels, - parser->format.sample_rate, - parser->format.byte_per_sec, - parser->format.bits_per_sample); - - parser->wav_data_start = stream_tell(stream); - parser->wav_data_end = parser->wav_data_start + parser->data.size; - - FURI_LOG_I(TAG, "data: %u - %u", parser->wav_data_start, parser->wav_data_end); - - return true; -} - -size_t wav_parser_get_data_start(WavParser* parser) { - return parser->wav_data_start; -} - -size_t wav_parser_get_data_end(WavParser* parser) { - return parser->wav_data_end; -} - -size_t wav_parser_get_data_len(WavParser* parser) { - return parser->wav_data_end - parser->wav_data_start; -} diff --git a/applications/wav_player/wav_parser.h b/applications/wav_player/wav_parser.h deleted file mode 100644 index f50c48b3f..000000000 --- a/applications/wav_player/wav_parser.h +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - FormatTagPCM = 0x0001, - FormatTagIEEE_FLOAT = 0x0003, -} FormatTag; - -typedef struct { - uint8_t riff[4]; - uint32_t size; - uint8_t wave[4]; -} WavHeaderChunk; - -typedef struct { - uint8_t fmt[4]; - uint32_t size; - uint16_t tag; - uint16_t channels; - uint32_t sample_rate; - uint32_t byte_per_sec; - uint16_t block_align; - uint16_t bits_per_sample; -} WavFormatChunk; - -typedef struct { - uint8_t data[4]; - uint32_t size; -} WavDataChunk; - -typedef struct WavParser WavParser; - -WavParser* wav_parser_alloc(); - -void wav_parser_free(WavParser* parser); - -bool wav_parser_parse(WavParser* parser, Stream* stream); - -size_t wav_parser_get_data_start(WavParser* parser); - -size_t wav_parser_get_data_end(WavParser* parser); - -size_t wav_parser_get_data_len(WavParser* parser); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/applications/wav_player/wav_player.c b/applications/wav_player/wav_player.c deleted file mode 100644 index e86acf5b2..000000000 --- a/applications/wav_player/wav_player.c +++ /dev/null @@ -1,303 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "wav_player_hal.h" -#include "wav_parser.h" -#include "wav_player_view.h" - -#define TAG "WavPlayer" - -static bool open_wav_stream(Storage* storage, Stream* stream) { - DialogsApp* dialogs = furi_record_open("dialogs"); - bool result = false; - size_t name_size = 255; - char* name_buffer = malloc(name_size); - string_t path; - string_init(path); - - bool ret = - dialog_file_select_show(dialogs, "/ext/wav_player", ".wav", name_buffer, name_size, NULL); - furi_record_close("dialogs"); - - if(ret) { - string_printf(path, "%s/%s.%s", "/ext/wav_player", name_buffer, "wav"); - if(!file_stream_open(stream, string_get_cstr(path), FSAM_READ, FSOM_OPEN_EXISTING)) { - FURI_LOG_E(TAG, "Cannot open file \"%s\"", string_get_cstr(path)); - } else { - result = true; - } - } - - string_clear(path); - free(name_buffer); - return result; -} - -typedef enum { - WavPlayerEventHalfTransfer, - WavPlayerEventFullTransfer, - WavPlayerEventCtrlVolUp, - WavPlayerEventCtrlVolDn, - WavPlayerEventCtrlMoveL, - WavPlayerEventCtrlMoveR, - WavPlayerEventCtrlOk, - WavPlayerEventCtrlBack, -} WavPlayerEventType; - -typedef struct { - WavPlayerEventType type; -} WavPlayerEvent; - -static void wav_player_dma_isr(void* ctx) { - osMessageQueueId_t event_queue = ctx; - - // half of transfer - if(LL_DMA_IsActiveFlag_HT1(DMA1)) { - LL_DMA_ClearFlag_HT1(DMA1); - // fill first half of buffer - WavPlayerEvent event = {.type = WavPlayerEventHalfTransfer}; - osMessageQueuePut(event_queue, &event, 0, 0); - } - - // transfer complete - if(LL_DMA_IsActiveFlag_TC1(DMA1)) { - LL_DMA_ClearFlag_TC1(DMA1); - // fill second half of buffer - WavPlayerEvent event = {.type = WavPlayerEventFullTransfer}; - osMessageQueuePut(event_queue, &event, 0, 0); - } -} - -typedef struct { - Storage* storage; - Stream* stream; - WavParser* parser; - uint16_t* sample_buffer; - uint8_t* tmp_buffer; - - size_t samples_count_half; - size_t samples_count; - - osMessageQueueId_t queue; - - float volume; - bool play; - - WavPlayerView* view; - ViewDispatcher* view_dispatcher; - Gui* gui; - NotificationApp* notification; -} WavPlayerApp; - -static WavPlayerApp* app_alloc() { - WavPlayerApp* app = malloc(sizeof(WavPlayerApp)); - app->samples_count_half = 1024 * 4; - app->samples_count = app->samples_count_half * 2; - app->storage = furi_record_open("storage"); - app->stream = file_stream_alloc(app->storage); - app->parser = wav_parser_alloc(); - app->sample_buffer = malloc(sizeof(uint16_t) * app->samples_count); - app->tmp_buffer = malloc(sizeof(uint8_t) * app->samples_count); - app->queue = osMessageQueueNew(10, sizeof(WavPlayerEvent), NULL); - - app->volume = 10.0f; - app->play = true; - - app->gui = furi_record_open("gui"); - app->view_dispatcher = view_dispatcher_alloc(); - app->view = wav_player_view_alloc(); - - view_dispatcher_add_view(app->view_dispatcher, 0, wav_player_view_get_view(app->view)); - view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); - view_dispatcher_switch_to_view(app->view_dispatcher, 0); - - app->notification = furi_record_open("notification"); - notification_message(app->notification, &sequence_display_backlight_enforce_on); - - return app; -} - -static void app_free(WavPlayerApp* app) { - view_dispatcher_remove_view(app->view_dispatcher, 0); - view_dispatcher_free(app->view_dispatcher); - wav_player_view_free(app->view); - furi_record_close("gui"); - - osMessageQueueDelete(app->queue); - free(app->tmp_buffer); - free(app->sample_buffer); - wav_parser_free(app->parser); - stream_free(app->stream); - furi_record_close("storage"); - - notification_message(app->notification, &sequence_display_backlight_enforce_auto); - furi_record_close("notification"); - free(app); -} - -// TODO: that works only with 8-bit 2ch audio -static bool fill_data(WavPlayerApp* app, size_t index) { - uint16_t* sample_buffer_start = &app->sample_buffer[index]; - size_t count = stream_read(app->stream, app->tmp_buffer, app->samples_count); - - for(size_t i = count; i < app->samples_count; i++) { - app->tmp_buffer[i] = 0; - } - - for(size_t i = 0; i < app->samples_count; i += 2) { - float data = app->tmp_buffer[i]; - data -= UINT8_MAX / 2; // to signed - data /= UINT8_MAX / 2; // scale -1..1 - - data *= app->volume; // volume - data = tanhf(data); // hyperbolic tangent limiter - - data *= UINT8_MAX / 2; // scale -128..127 - data += UINT8_MAX / 2; // to unsigned - - if(data < 0) { - data = 0; - } - - if(data > 255) { - data = 255; - } - - sample_buffer_start[i / 2] = data; - } - - wav_player_view_set_data(app->view, sample_buffer_start, app->samples_count_half); - - return count != app->samples_count; -} - -static void ctrl_callback(WavPlayerCtrl ctrl, void* ctx) { - osMessageQueueId_t event_queue = ctx; - WavPlayerEvent event; - - switch(ctrl) { - case WavPlayerCtrlVolUp: - event.type = WavPlayerEventCtrlVolUp; - osMessageQueuePut(event_queue, &event, 0, 0); - break; - case WavPlayerCtrlVolDn: - event.type = WavPlayerEventCtrlVolDn; - osMessageQueuePut(event_queue, &event, 0, 0); - break; - case WavPlayerCtrlMoveL: - event.type = WavPlayerEventCtrlMoveL; - osMessageQueuePut(event_queue, &event, 0, 0); - break; - case WavPlayerCtrlMoveR: - event.type = WavPlayerEventCtrlMoveR; - osMessageQueuePut(event_queue, &event, 0, 0); - break; - case WavPlayerCtrlOk: - event.type = WavPlayerEventCtrlOk; - osMessageQueuePut(event_queue, &event, 0, 0); - break; - case WavPlayerCtrlBack: - event.type = WavPlayerEventCtrlBack; - osMessageQueuePut(event_queue, &event, 0, 0); - break; - default: - break; - } -} - -static void app_run(WavPlayerApp* app) { - if(!open_wav_stream(app->storage, app->stream)) return; - if(!wav_parser_parse(app->parser, app->stream)) return; - - wav_player_view_set_volume(app->view, app->volume); - wav_player_view_set_start(app->view, wav_parser_get_data_start(app->parser)); - wav_player_view_set_current(app->view, stream_tell(app->stream)); - wav_player_view_set_end(app->view, wav_parser_get_data_end(app->parser)); - wav_player_view_set_play(app->view, app->play); - - wav_player_view_set_context(app->view, app->queue); - wav_player_view_set_ctrl_callback(app->view, ctrl_callback); - - bool eof = fill_data(app, 0); - eof = fill_data(app, app->samples_count_half); - - wav_player_speaker_init(); - wav_player_dma_init((uint32_t)app->sample_buffer, app->samples_count); - - furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, wav_player_dma_isr, app->queue); - - wav_player_dma_start(); - wav_player_speaker_start(); - - WavPlayerEvent event; - - while(1) { - if(osMessageQueueGet(app->queue, &event, NULL, osWaitForever) == osOK) { - if(event.type == WavPlayerEventHalfTransfer) { - eof = fill_data(app, 0); - wav_player_view_set_current(app->view, stream_tell(app->stream)); - if(eof) { - stream_seek( - app->stream, - wav_parser_get_data_start(app->parser), - StreamOffsetFromStart); - } - - } else if(event.type == WavPlayerEventFullTransfer) { - eof = fill_data(app, app->samples_count_half); - wav_player_view_set_current(app->view, stream_tell(app->stream)); - if(eof) { - stream_seek( - app->stream, - wav_parser_get_data_start(app->parser), - StreamOffsetFromStart); - } - } else if(event.type == WavPlayerEventCtrlVolUp) { - if(app->volume < 9.9) app->volume += 0.2; - wav_player_view_set_volume(app->view, app->volume); - } else if(event.type == WavPlayerEventCtrlVolDn) { - if(app->volume > 0.01) app->volume -= 0.2; - wav_player_view_set_volume(app->view, app->volume); - } else if(event.type == WavPlayerEventCtrlMoveL) { - int32_t seek = stream_tell(app->stream) - wav_parser_get_data_start(app->parser); - seek = MIN(seek, wav_parser_get_data_len(app->parser) / 100); - stream_seek(app->stream, -seek, StreamOffsetFromCurrent); - wav_player_view_set_current(app->view, stream_tell(app->stream)); - } else if(event.type == WavPlayerEventCtrlMoveR) { - int32_t seek = wav_parser_get_data_end(app->parser) - stream_tell(app->stream); - seek = MIN(seek, wav_parser_get_data_len(app->parser) / 100); - stream_seek(app->stream, seek, StreamOffsetFromCurrent); - wav_player_view_set_current(app->view, stream_tell(app->stream)); - } else if(event.type == WavPlayerEventCtrlOk) { - app->play = !app->play; - wav_player_view_set_play(app->view, app->play); - - if(!app->play) { - wav_player_speaker_stop(); - } else { - wav_player_speaker_start(); - } - } else if(event.type == WavPlayerEventCtrlBack) { - break; - } - } - } - - wav_player_speaker_stop(); - wav_player_dma_stop(); - - furi_hal_interrupt_set_isr(FuriHalInterruptIdDma1Ch1, NULL, NULL); -} - -int32_t wav_player_app(void* p) { - WavPlayerApp* app = app_alloc(); - app_run(app); - app_free(app); - return 0; -} \ No newline at end of file diff --git a/applications/wav_player/wav_player_hal.c b/applications/wav_player/wav_player_hal.c deleted file mode 100644 index ad0c019be..000000000 --- a/applications/wav_player/wav_player_hal.c +++ /dev/null @@ -1,58 +0,0 @@ -#include "wav_player_hal.h" -#include -#include - -#define FURI_HAL_SPEAKER_TIMER TIM16 -#define FURI_HAL_SPEAKER_CHANNEL LL_TIM_CHANNEL_CH1 -#define DMA_INSTANCE DMA1, LL_DMA_CHANNEL_1 - -void wav_player_speaker_init() { - LL_TIM_InitTypeDef TIM_InitStruct = {0}; - TIM_InitStruct.Prescaler = 4; - TIM_InitStruct.Autoreload = 255; - LL_TIM_Init(FURI_HAL_SPEAKER_TIMER, &TIM_InitStruct); - - LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0}; - TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1; - TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE; - TIM_OC_InitStruct.CompareValue = 127; - LL_TIM_OC_Init(FURI_HAL_SPEAKER_TIMER, FURI_HAL_SPEAKER_CHANNEL, &TIM_OC_InitStruct); -} - -void wav_player_speaker_start() { - LL_TIM_EnableAllOutputs(FURI_HAL_SPEAKER_TIMER); - LL_TIM_EnableCounter(FURI_HAL_SPEAKER_TIMER); -} - -void wav_player_speaker_stop() { - LL_TIM_DisableAllOutputs(FURI_HAL_SPEAKER_TIMER); - LL_TIM_DisableCounter(FURI_HAL_SPEAKER_TIMER); -} - -void wav_player_dma_init(uint32_t address, size_t size) { - uint32_t dma_dst = (uint32_t) & (FURI_HAL_SPEAKER_TIMER->CCR1); - - LL_DMA_ConfigAddresses(DMA_INSTANCE, address, dma_dst, LL_DMA_DIRECTION_MEMORY_TO_PERIPH); - LL_DMA_SetDataLength(DMA_INSTANCE, size); - - LL_DMA_SetPeriphRequest(DMA_INSTANCE, LL_DMAMUX_REQ_TIM16_UP); - LL_DMA_SetDataTransferDirection(DMA_INSTANCE, LL_DMA_DIRECTION_MEMORY_TO_PERIPH); - LL_DMA_SetChannelPriorityLevel(DMA_INSTANCE, LL_DMA_PRIORITY_VERYHIGH); - LL_DMA_SetMode(DMA_INSTANCE, LL_DMA_MODE_CIRCULAR); - LL_DMA_SetPeriphIncMode(DMA_INSTANCE, LL_DMA_PERIPH_NOINCREMENT); - LL_DMA_SetMemoryIncMode(DMA_INSTANCE, LL_DMA_MEMORY_INCREMENT); - LL_DMA_SetPeriphSize(DMA_INSTANCE, LL_DMA_PDATAALIGN_HALFWORD); - LL_DMA_SetMemorySize(DMA_INSTANCE, LL_DMA_MDATAALIGN_HALFWORD); - - LL_DMA_EnableIT_TC(DMA_INSTANCE); - LL_DMA_EnableIT_HT(DMA_INSTANCE); -} - -void wav_player_dma_start() { - LL_DMA_EnableChannel(DMA_INSTANCE); - LL_TIM_EnableDMAReq_UPDATE(FURI_HAL_SPEAKER_TIMER); -} - -void wav_player_dma_stop() { - LL_DMA_DisableChannel(DMA_INSTANCE); -} \ No newline at end of file diff --git a/applications/wav_player/wav_player_hal.h b/applications/wav_player/wav_player_hal.h deleted file mode 100644 index 124f51406..000000000 --- a/applications/wav_player/wav_player_hal.h +++ /dev/null @@ -1,23 +0,0 @@ -#pragma once -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -void wav_player_speaker_init(); - -void wav_player_speaker_start(); - -void wav_player_speaker_stop(); - -void wav_player_dma_init(uint32_t address, size_t size); - -void wav_player_dma_start(); - -void wav_player_dma_stop(); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/applications/wav_player/wav_player_view.c b/applications/wav_player/wav_player_view.c deleted file mode 100644 index 8068bf351..000000000 --- a/applications/wav_player/wav_player_view.c +++ /dev/null @@ -1,214 +0,0 @@ -#include "wav_player_view.h" - -#define DATA_COUNT 116 - -struct WavPlayerView { - View* view; - WavPlayerCtrlCallback callback; - void* context; -}; - -typedef struct { - bool play; - float volume; - size_t start; - size_t end; - size_t current; - uint8_t data[DATA_COUNT]; -} WavPlayerViewModel; - -float map(float x, float in_min, float in_max, float out_min, float out_max) { - return (x - in_min) * (out_max - out_min + 1) / (in_max - in_min + 1) + out_min; -} - -static void wav_player_view_draw_callback(Canvas* canvas, void* _model) { - WavPlayerViewModel* model = _model; - - canvas_clear(canvas); - canvas_set_color(canvas, ColorBlack); - uint8_t x_pos = 0; - uint8_t y_pos = 0; - - // volume - x_pos = 124; - y_pos = 0; - const float volume = (64 / 10.0f) * model->volume; - canvas_draw_frame(canvas, x_pos, y_pos, 4, 64); - canvas_draw_box(canvas, x_pos, y_pos + (64 - volume), 4, volume); - - // play / pause - x_pos = 58; - y_pos = 55; - if(model->play) { - canvas_draw_line(canvas, x_pos, y_pos, x_pos + 8, y_pos + 4); - canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos + 8, y_pos + 4); - canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos, y_pos); - } else { - canvas_draw_box(canvas, x_pos, y_pos, 3, 9); - canvas_draw_box(canvas, x_pos + 4, y_pos, 3, 9); - } - - x_pos = 78; - y_pos = 55; - canvas_draw_line(canvas, x_pos, y_pos, x_pos + 4, y_pos + 4); - canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos + 4, y_pos + 4); - canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos, y_pos); - - x_pos = 82; - y_pos = 55; - canvas_draw_line(canvas, x_pos, y_pos, x_pos + 4, y_pos + 4); - canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos + 4, y_pos + 4); - canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos, y_pos); - - x_pos = 40; - y_pos = 55; - canvas_draw_line(canvas, x_pos, y_pos, x_pos - 4, y_pos + 4); - canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos - 4, y_pos + 4); - canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos, y_pos); - - x_pos = 44; - y_pos = 55; - canvas_draw_line(canvas, x_pos, y_pos, x_pos - 4, y_pos + 4); - canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos - 4, y_pos + 4); - canvas_draw_line(canvas, x_pos, y_pos + 8, x_pos, y_pos); - - // len - x_pos = 4; - y_pos = 47; - const uint8_t play_len = 116; - uint8_t play_pos = map(model->current, model->start, model->end, 0, play_len - 4); - - canvas_draw_frame(canvas, x_pos, y_pos, play_len, 4); - canvas_draw_box(canvas, x_pos + play_pos, y_pos - 2, 4, 8); - canvas_draw_box(canvas, x_pos, y_pos, play_pos, 4); - - // osc - x_pos = 4; - y_pos = 0; - for(size_t i = 1; i < DATA_COUNT; i++) { - canvas_draw_line(canvas, x_pos + i - 1, model->data[i - 1], x_pos + i, model->data[i]); - } -} - -static bool wav_player_view_input_callback(InputEvent* event, void* context) { - WavPlayerView* wav_player_view = context; - bool consumed = false; - - if(wav_player_view->callback) { - if(event->type == InputTypeShort || event->type == InputTypeRepeat) { - if(event->key == InputKeyUp) { - wav_player_view->callback(WavPlayerCtrlVolUp, wav_player_view->context); - consumed = true; - } else if(event->key == InputKeyDown) { - wav_player_view->callback(WavPlayerCtrlVolDn, wav_player_view->context); - consumed = true; - } else if(event->key == InputKeyLeft) { - wav_player_view->callback(WavPlayerCtrlMoveL, wav_player_view->context); - consumed = true; - } else if(event->key == InputKeyRight) { - wav_player_view->callback(WavPlayerCtrlMoveR, wav_player_view->context); - consumed = true; - } else if(event->key == InputKeyOk) { - wav_player_view->callback(WavPlayerCtrlOk, wav_player_view->context); - consumed = true; - } else if(event->key == InputKeyBack) { - wav_player_view->callback(WavPlayerCtrlBack, wav_player_view->context); - consumed = true; - } - } - } - - return consumed; -} - -WavPlayerView* wav_player_view_alloc() { - WavPlayerView* wav_view = malloc(sizeof(WavPlayerView)); - wav_view->view = view_alloc(); - view_set_context(wav_view->view, wav_view); - view_allocate_model(wav_view->view, ViewModelTypeLocking, sizeof(WavPlayerViewModel)); - view_set_draw_callback(wav_view->view, wav_player_view_draw_callback); - view_set_input_callback(wav_view->view, wav_player_view_input_callback); - - return wav_view; -} - -void wav_player_view_free(WavPlayerView* wav_view) { - furi_assert(wav_view); - view_free(wav_view->view); - free(wav_view); -} - -View* wav_player_view_get_view(WavPlayerView* wav_view) { - furi_assert(wav_view); - return wav_view->view; -} - -void wav_player_view_set_volume(WavPlayerView* wav_view, float volume) { - furi_assert(wav_view); - with_view_model( - wav_view->view, (WavPlayerViewModel * model) { - model->volume = volume; - return true; - }); -} - -void wav_player_view_set_start(WavPlayerView* wav_view, size_t start) { - furi_assert(wav_view); - with_view_model( - wav_view->view, (WavPlayerViewModel * model) { - model->start = start; - return true; - }); -} - -void wav_player_view_set_end(WavPlayerView* wav_view, size_t end) { - furi_assert(wav_view); - with_view_model( - wav_view->view, (WavPlayerViewModel * model) { - model->end = end; - return true; - }); -} - -void wav_player_view_set_current(WavPlayerView* wav_view, size_t current) { - furi_assert(wav_view); - with_view_model( - wav_view->view, (WavPlayerViewModel * model) { - model->current = current; - return true; - }); -} - -void wav_player_view_set_play(WavPlayerView* wav_view, bool play) { - furi_assert(wav_view); - with_view_model( - wav_view->view, (WavPlayerViewModel * model) { - model->play = play; - return true; - }); -} - -void wav_player_view_set_data(WavPlayerView* wav_view, uint16_t* data, size_t data_count) { - furi_assert(wav_view); - with_view_model( - wav_view->view, (WavPlayerViewModel * model) { - size_t inc = (data_count / DATA_COUNT) - 1; - - for(size_t i = 0; i < DATA_COUNT; i++) { - model->data[i] = *data / 6; - if(model->data[i] > 42) model->data[i] = 42; - data += inc; - } - return true; - }); -} - -void wav_player_view_set_ctrl_callback(WavPlayerView* wav_view, WavPlayerCtrlCallback callback) { - furi_assert(wav_view); - wav_view->callback = callback; -} - -void wav_player_view_set_context(WavPlayerView* wav_view, void* context) { - furi_assert(wav_view); - wav_view->context = context; -} \ No newline at end of file diff --git a/applications/wav_player/wav_player_view.h b/applications/wav_player/wav_player_view.h deleted file mode 100644 index 246aeaf3e..000000000 --- a/applications/wav_player/wav_player_view.h +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct WavPlayerView WavPlayerView; - -typedef enum { - WavPlayerCtrlVolUp, - WavPlayerCtrlVolDn, - WavPlayerCtrlMoveL, - WavPlayerCtrlMoveR, - WavPlayerCtrlOk, - WavPlayerCtrlBack, -} WavPlayerCtrl; - -typedef void (*WavPlayerCtrlCallback)(WavPlayerCtrl ctrl, void* context); - -WavPlayerView* wav_player_view_alloc(); - -void wav_player_view_free(WavPlayerView* wav_view); - -View* wav_player_view_get_view(WavPlayerView* wav_view); - -void wav_player_view_set_volume(WavPlayerView* wav_view, float volume); - -void wav_player_view_set_start(WavPlayerView* wav_view, size_t start); - -void wav_player_view_set_end(WavPlayerView* wav_view, size_t end); - -void wav_player_view_set_current(WavPlayerView* wav_view, size_t current); - -void wav_player_view_set_play(WavPlayerView* wav_view, bool play); - -void wav_player_view_set_data(WavPlayerView* wav_view, uint16_t* data, size_t data_count); - -void wav_player_view_set_ctrl_callback(WavPlayerView* wav_view, WavPlayerCtrlCallback callback); - -void wav_player_view_set_context(WavPlayerView* wav_view, void* context); - -#ifdef __cplusplus -} -#endif \ No newline at end of file diff --git a/assets/compiled/assets_icons.c b/assets/compiled/assets_icons.c index e2ac18adc..fb125095a 100644 --- a/assets/compiled/assets_icons.c +++ b/assets/compiled/assets_icons.c @@ -325,16 +325,6 @@ const uint8_t _A_Bluetooth_14_4[] = {0x00,0x10,0x00,0x30,0x00,0x51,0x00,0x92,0x0 const uint8_t _A_Bluetooth_14_5[] = {0x00,0x10,0x00,0x30,0x00,0x51,0x00,0x92,0x00,0x94,0x04,0x58,0x08,0x30,0x09,0x30,0x09,0x58,0x08,0x94,0x04,0x92,0x00,0x51,0x00,0x30,0x00,0x10,0x00,}; const uint8_t* const _A_Bluetooth_14[] = {_A_Bluetooth_14_0,_A_Bluetooth_14_1,_A_Bluetooth_14_2,_A_Bluetooth_14_3,_A_Bluetooth_14_4,_A_Bluetooth_14_5}; -const uint8_t _A_Clock_14_0[] = {0x00,0xF0,0x01,0x0E,0x0E,0x47,0x1C,0x03,0x18,0x49,0x12,0x41,0x10,0x41,0x10,0x01,0x10,0x09,0x12,0x02,0x08,0x46,0x0C,0x0E,0x0E,0xF6,0x0D,0x02,0x08,}; -const uint8_t _A_Clock_14_1[] = {0x00,0xF0,0x01,0x0E,0x0E,0x47,0x1C,0x03,0x18,0x09,0x13,0x81,0x10,0x41,0x10,0x01,0x10,0x09,0x12,0x02,0x08,0x46,0x0C,0x0E,0x0E,0xF6,0x0D,0x02,0x08,}; -const uint8_t _A_Clock_14_2[] = {0x00,0xF0,0x01,0x0E,0x0E,0x47,0x1C,0x03,0x18,0x09,0x12,0x01,0x10,0xC1,0x11,0x01,0x10,0x09,0x12,0x02,0x08,0x46,0x0C,0x0E,0x0E,0xF6,0x0D,0x02,0x08,}; -const uint8_t _A_Clock_14_3[] = {0x00,0xF0,0x01,0x0E,0x0E,0x47,0x1C,0x03,0x18,0x09,0x12,0x01,0x10,0x41,0x10,0x81,0x10,0x09,0x13,0x02,0x08,0x46,0x0C,0x0E,0x0E,0xF6,0x0D,0x02,0x08,}; -const uint8_t _A_Clock_14_4[] = {0x00,0xF0,0x01,0x0E,0x0E,0x47,0x1C,0x03,0x18,0x09,0x12,0x01,0x10,0x41,0x10,0x41,0x10,0x49,0x12,0x02,0x08,0x46,0x0C,0x0E,0x0E,0xF6,0x0D,0x02,0x08,}; -const uint8_t _A_Clock_14_5[] = {0x00,0xF0,0x01,0x0E,0x0E,0x47,0x1C,0x03,0x18,0x09,0x12,0x01,0x10,0x41,0x10,0x21,0x10,0x19,0x12,0x02,0x08,0x46,0x0C,0x0E,0x0E,0xF6,0x0D,0x02,0x08,}; -const uint8_t _A_Clock_14_6[] = {0x00,0xF0,0x01,0x0E,0x0E,0x47,0x1C,0x03,0x18,0x09,0x12,0x01,0x10,0x71,0x10,0x01,0x10,0x09,0x12,0x02,0x08,0x46,0x0C,0x0E,0x0E,0xF6,0x0D,0x02,0x08,}; -const uint8_t _A_Clock_14_7[] = {0x00,0xF0,0x01,0x0E,0x0E,0x47,0x1C,0x03,0x18,0x19,0x12,0x21,0x10,0x41,0x10,0x01,0x10,0x09,0x12,0x02,0x08,0x46,0x0C,0x0E,0x0E,0xF6,0x0D,0x02,0x08,}; -const uint8_t* const _A_Clock_14[] = {_A_Clock_14_0,_A_Clock_14_1,_A_Clock_14_2,_A_Clock_14_3,_A_Clock_14_4,_A_Clock_14_5,_A_Clock_14_6,_A_Clock_14_7}; - const uint8_t _A_Debug_14_0[] = {0x00,0x20,0x01,0xC1,0x20,0x22,0x11,0x24,0x09,0xD9,0x26,0x16,0x1A,0xD8,0x06,0xD8,0x06,0xD6,0x1A,0x19,0x26,0xE4,0x09,0xC2,0x10,0x01,0x20,0x00,0x00,}; const uint8_t _A_Debug_14_1[] = {0x00,0x20,0x01,0xC0,0x00,0x22,0x11,0x25,0x29,0xD8,0x06,0x16,0x1A,0xD9,0x26,0xD8,0x06,0xD4,0x0A,0x12,0x12,0xEA,0x15,0xC5,0x28,0x02,0x10,0x02,0x10,}; const uint8_t _A_Debug_14_2[] = {0x00,0x20,0x01,0xC0,0x00,0x20,0x01,0x24,0x09,0xDA,0x16,0x11,0x22,0xDC,0x0E,0xDA,0x16,0xD9,0x26,0x14,0x0A,0xF2,0x13,0xD1,0x22,0x08,0x04,0x06,0x18,}; @@ -382,13 +372,6 @@ const uint8_t _A_Infrared_14_4[] = {0x01,0x00,0x0e,0x00,0x00,0x5f,0x82,0x02,0x05 const uint8_t _A_Infrared_14_5[] = {0x01,0x00,0x15,0x00,0x00,0x2f,0xc2,0x07,0x08,0x82,0x01,0x47,0xc1,0x01,0x05,0x98,0x14,0x41,0xa3,0xf8,0x83,0x80,0x47,0xff,0x3f,}; const uint8_t* const _A_Infrared_14[] = {_A_Infrared_14_0,_A_Infrared_14_1,_A_Infrared_14_2,_A_Infrared_14_3,_A_Infrared_14_4,_A_Infrared_14_5}; -const uint8_t _A_MusicPlayer_14_0[] = {0x01,0x00,0x17,0x00,0x00,0x1e,0x02,0x01,0xc0,0x80,0xf0,0x20,0x74,0x08,0x15,0x02,0x00,0x01,0x3b,0x84,0x02,0xf0,0x01,0x29,0x80,0x5c,0x80,}; -const uint8_t _A_MusicPlayer_14_1[] = {0x01,0x00,0x16,0x00,0x80,0x41,0x20,0x10,0xe8,0x04,0x7a,0x01,0x12,0x80,0x40,0x80,0x27,0x80,0x81,0xf0,0x00,0x25,0x80,0x80,0x86,0x94,}; -const uint8_t _A_MusicPlayer_14_2[] = {0x01,0x00,0x13,0x00,0x00,0x34,0x82,0x03,0x30,0x81,0xcc,0x20,0x51,0x08,0x00,0x05,0x63,0x90,0x08,0xf0,0x04,0xa1,0x80,}; -const uint8_t _A_MusicPlayer_14_3[] = {0x01,0x00,0x16,0x00,0x82,0x40,0x21,0xd0,0x08,0xf4,0x02,0x25,0x00,0x81,0x00,0x52,0x07,0x20,0x81,0xcc,0x00,0x23,0x01,0x90,0x06,0xd4,}; -const uint8_t _A_MusicPlayer_14_4[] = {0x01,0x00,0x15,0x00,0x00,0x2c,0x82,0x01,0x70,0x80,0x7c,0x20,0x19,0x08,0x04,0x40,0x02,0x91,0xc8,0x04,0x78,0x02,0x50,0xc8,0x00,}; -const uint8_t* const _A_MusicPlayer_14[] = {_A_MusicPlayer_14_0,_A_MusicPlayer_14_1,_A_MusicPlayer_14_2,_A_MusicPlayer_14_3,_A_MusicPlayer_14_4}; - const uint8_t _A_NFC_14_0[] = {0x00,0x00,0x08,0x00,0x10,0x00,0x12,0x00,0x22,0x42,0x24,0x87,0x24,0x8D,0x24,0x99,0x24,0xF1,0x24,0x62,0x24,0x00,0x22,0x00,0x12,0x00,0x10,0x00,0x08,}; const uint8_t _A_NFC_14_1[] = {0x01,0x00,0x1a,0x00,0x80,0x42,0x20,0x11,0x00,0x09,0x48,0x28,0x52,0x0c,0x3c,0x83,0x1b,0x20,0xcc,0xc8,0x3e,0x32,0x0b,0x14,0x80,0x1a,0x21,0x34,0x84,0x00,}; const uint8_t _A_NFC_14_2[] = {0x01,0x00,0x10,0x00,0x00,0x3d,0x0a,0x01,0x87,0x80,0x63,0x60,0x19,0x98,0x07,0xc6,0x01,0x62,0x09,0xc0,}; @@ -449,38 +432,6 @@ const uint8_t _A_Tamagotchi_14_4[] = {0x00,0xF0,0x03,0x08,0x06,0x04,0x0C,0x04,0x const uint8_t _A_Tamagotchi_14_5[] = {0x00,0xF0,0x03,0x08,0x06,0x04,0x0C,0x04,0x0C,0xF2,0x19,0x5A,0x1A,0xA9,0x32,0x49,0x33,0xF1,0x31,0x01,0x30,0x52,0x39,0x02,0x18,0x0C,0x0E,0xF0,0x07,}; const uint8_t* const _A_Tamagotchi_14[] = {_A_Tamagotchi_14_0,_A_Tamagotchi_14_1,_A_Tamagotchi_14_2,_A_Tamagotchi_14_3,_A_Tamagotchi_14_4,_A_Tamagotchi_14_5}; -const uint8_t _A_TouchTunes_14_0[] = {0x00,0x60,0x01,0xF8,0x07,0xF8,0x07,0x08,0x04,0x18,0x02,0x08,0x04,0x04,0x08,0x0C,0x0C,0x18,0x04,0x10,0x02,0x98,0x06,0xF8,0x07,0xF8,0x07,0x80,0x01,}; -const uint8_t _A_TouchTunes_14_1[] = {0x00,0x60,0x01,0xF8,0x07,0xF8,0x07,0x08,0x04,0x18,0x02,0x08,0x04,0x04,0x08,0x0C,0x0C,0x18,0x04,0x10,0x02,0x98,0x06,0xF8,0x07,0xF8,0x07,0x80,0x01,}; -const uint8_t _A_TouchTunes_14_2[] = {0x00,0x60,0x01,0xF8,0x07,0xF8,0x07,0x08,0x04,0x18,0x02,0x08,0x04,0x04,0x08,0x0C,0x0C,0x18,0x04,0x10,0x02,0x98,0x06,0xF8,0x07,0xF8,0x07,0x80,0x01,}; -const uint8_t _A_TouchTunes_14_3[] = {0x01,0x00,0x1a,0x00,0xd0,0x40,0x7f,0x10,0x70,0x08,0xc2,0x20,0x91,0x08,0x10,0x0c,0x60,0x90,0x88,0x64,0x32,0x30,0x09,0x2c,0xc4,0x18,0x26,0x78,0x08,0x08,}; -const uint8_t _A_TouchTunes_14_4[] = {0x00,0x40,0x01,0xF8,0x07,0xF8,0x07,0x18,0x04,0x10,0x06,0x08,0x04,0x0C,0x0C,0x08,0x04,0x18,0x02,0x10,0x06,0xD8,0x06,0xF8,0x07,0xF8,0x07,0x00,0x00,}; -const uint8_t _A_TouchTunes_14_5[] = {0x00,0x00,0x00,0xF0,0x07,0xF8,0x07,0x18,0x04,0x18,0x06,0x10,0x02,0x08,0x04,0x08,0x04,0x10,0x02,0x18,0x06,0xD8,0x06,0xF8,0x07,0xF0,0x03,0x00,0x00,}; -const uint8_t _A_TouchTunes_14_6[] = {0x00,0x00,0x01,0xF0,0x03,0xF8,0x07,0x18,0x04,0x10,0x02,0x18,0x04,0x0C,0x0C,0x08,0x04,0x18,0x02,0x10,0x02,0xF8,0x06,0xF8,0x07,0xF0,0x07,0x00,0x00,}; -const uint8_t _A_TouchTunes_14_7[] = {0x00,0x00,0x00,0xF8,0x07,0xF8,0x07,0x00,0x04,0x10,0x04,0x08,0x04,0x0C,0x0C,0x0C,0x0C,0x18,0x04,0x00,0x04,0xD8,0x06,0xF8,0x07,0xF0,0x03,0x00,0x00,}; -const uint8_t _A_TouchTunes_14_8[] = {0x00,0x00,0x00,0xF0,0x07,0xF8,0x07,0x18,0x04,0x08,0x04,0x0C,0x0C,0x0A,0x1C,0x0E,0x18,0x08,0x0C,0x48,0x00,0xD8,0x06,0xF8,0x07,0xF0,0x03,0x40,0x00,}; -const uint8_t _A_TouchTunes_14_9[] = {0x00,0x20,0x02,0xF8,0x07,0xF8,0x07,0x08,0x04,0x00,0x04,0x0C,0x0C,0x0B,0x34,0x0E,0x1C,0x0C,0x0C,0xE0,0x01,0xD8,0x06,0xF8,0x07,0xF8,0x07,0x00,0x00,}; -const uint8_t _A_TouchTunes_14_10[] = {0x00,0xA0,0x02,0xF8,0x07,0xF8,0x07,0x00,0x04,0x08,0x00,0x0C,0x0C,0x0B,0x34,0x0A,0x14,0x0C,0x0C,0xF0,0x01,0x98,0x05,0xF8,0x07,0xF8,0x07,0x40,0x00,}; -const uint8_t _A_TouchTunes_14_11[] = {0x00,0xA0,0x01,0xF8,0x07,0xF8,0x07,0x00,0x00,0x00,0x00,0x0E,0x0C,0x0A,0x34,0x0B,0x14,0x0C,0x0C,0xE0,0x01,0x98,0x05,0xF8,0x07,0xD8,0x07,0x60,0x00,}; -const uint8_t _A_TouchTunes_14_12[] = {0x00,0xA0,0x02,0xF8,0x07,0xF8,0x07,0x00,0x04,0x04,0x00,0x0C,0x0C,0x0A,0x14,0x0A,0x1C,0x0C,0x0C,0xE0,0x01,0x98,0x05,0xF8,0x07,0xD8,0x07,0x60,0x00,}; -const uint8_t _A_TouchTunes_14_13[] = {0x00,0x60,0x02,0xF8,0x07,0xF8,0x07,0x00,0x04,0x04,0x08,0x0C,0x0C,0x0A,0x34,0x0A,0x14,0x0C,0x0C,0xE8,0x05,0x98,0x05,0xF8,0x07,0xF8,0x07,0x80,0x00,}; -const uint8_t _A_TouchTunes_14_14[] = {0x00,0x60,0x02,0xF8,0x07,0xF8,0x07,0x00,0x04,0x04,0x08,0x0C,0x0C,0x0A,0x34,0x0A,0x14,0x0C,0x0C,0xE8,0x05,0x98,0x05,0xF8,0x07,0xF8,0x07,0x80,0x00,}; -const uint8_t _A_TouchTunes_14_15[] = {0x00,0x60,0x02,0xF8,0x07,0xF8,0x07,0x00,0x04,0x04,0x08,0x0C,0x0C,0x0A,0x34,0x0A,0x14,0x0C,0x0C,0xE8,0x05,0x98,0x05,0xF8,0x07,0xF8,0x07,0x80,0x00,}; -const uint8_t _A_TouchTunes_14_16[] = {0x00,0x60,0x02,0xF8,0x07,0xF8,0x07,0x00,0x04,0x04,0x08,0x0C,0x0C,0x0A,0x34,0x0A,0x14,0x0C,0x0C,0xE8,0x05,0x98,0x05,0xF8,0x07,0xF8,0x07,0x80,0x00,}; -const uint8_t _A_TouchTunes_14_17[] = {0x00,0xA0,0x01,0xF8,0x07,0xF8,0x07,0x00,0x00,0x04,0x08,0x0C,0x0C,0x0A,0x14,0x0A,0x1C,0x0C,0x0C,0xE0,0x01,0x98,0x06,0xF8,0x07,0xD8,0x07,0x60,0x00,}; -const uint8_t _A_TouchTunes_14_18[] = {0x00,0x20,0x02,0xF8,0x07,0xF8,0x07,0x08,0x04,0x08,0x04,0x0E,0x0C,0x0A,0x34,0x0B,0x14,0x0C,0x0C,0xE4,0x03,0xD8,0x06,0xF8,0x07,0xF8,0x07,0x00,0x00,}; -const uint8_t _A_TouchTunes_14_19[] = {0x00,0x00,0x00,0xF0,0x07,0xF8,0x07,0x18,0x04,0x04,0x08,0x0E,0x1C,0x0B,0x34,0x0A,0x14,0x0C,0x0C,0xE0,0x03,0xF8,0x06,0xF8,0x07,0xF0,0x07,0x00,0x00,}; -const uint8_t _A_TouchTunes_14_20[] = {0x00,0x00,0x01,0xF0,0x03,0xF8,0x07,0x18,0x04,0x04,0x00,0x0C,0x0C,0x0B,0x34,0x0B,0x34,0x0C,0x0C,0xE0,0x05,0xF8,0x06,0xF8,0x07,0xF0,0x03,0x00,0x00,}; -const uint8_t _A_TouchTunes_14_21[] = {0x00,0x00,0x00,0xF8,0x07,0xF8,0x07,0x10,0x00,0x08,0x04,0x0C,0x0C,0x0C,0x0C,0x0E,0x0C,0x08,0x04,0x88,0x04,0xF0,0x02,0xF8,0x07,0xF0,0x03,0x00,0x00,}; -const uint8_t _A_TouchTunes_14_22[] = {0x00,0x00,0x00,0xF8,0x07,0xF8,0x07,0x00,0x00,0x18,0x04,0x08,0x04,0x0C,0x0C,0x08,0x04,0x08,0x04,0x00,0x04,0xD8,0x02,0xF8,0x07,0xF0,0x03,0x00,0x00,}; -const uint8_t _A_TouchTunes_14_23[] = {0x01,0x00,0x14,0x00,0xa0,0x40,0x7f,0x10,0x70,0x08,0x81,0xc6,0x21,0x02,0x84,0x41,0x00,0x2a,0x09,0x1e,0xc4,0x18,0x26,0xa0,}; -const uint8_t _A_TouchTunes_14_24[] = {0x01,0x00,0x17,0x00,0x90,0x40,0xbf,0x10,0x70,0x08,0xc2,0x20,0x91,0x08,0x14,0x62,0x0c,0x05,0x10,0x3a,0xe6,0x20,0xa1,0x33,0xa0,0x40,0x00,}; -const uint8_t _A_TouchTunes_14_25[] = {0x01,0x00,0x1a,0x00,0xb0,0x40,0x7f,0x10,0x70,0x08,0xc2,0x20,0x91,0x88,0x34,0x62,0x04,0x05,0x10,0x39,0x40,0xa2,0x10,0x6c,0xc4,0x14,0x26,0x78,0x08,0x00,}; -const uint8_t _A_TouchTunes_14_26[] = {0x00,0x60,0x01,0xF8,0x07,0xF8,0x07,0x08,0x04,0x10,0x06,0x08,0x04,0x0C,0x0C,0x08,0x04,0x18,0x02,0x10,0x06,0x98,0x04,0xF8,0x07,0xF8,0x07,0x80,0x02,}; -const uint8_t _A_TouchTunes_14_27[] = {0x00,0x60,0x01,0xF8,0x07,0xF8,0x07,0x08,0x04,0x18,0x02,0x08,0x04,0x04,0x08,0x0C,0x0C,0x18,0x04,0x10,0x02,0x98,0x06,0xF8,0x07,0xF8,0x07,0x80,0x01,}; -const uint8_t _A_TouchTunes_14_28[] = {0x00,0x60,0x01,0xF8,0x07,0xF8,0x07,0x08,0x04,0x18,0x02,0x08,0x04,0x04,0x08,0x0C,0x0C,0x18,0x04,0x10,0x02,0x98,0x06,0xF8,0x07,0xF8,0x07,0x80,0x01,}; -const uint8_t _A_TouchTunes_14_29[] = {0x00,0x60,0x01,0xF8,0x07,0xF8,0x07,0x08,0x04,0x18,0x02,0x08,0x04,0x04,0x08,0x0C,0x0C,0x18,0x04,0x10,0x02,0x98,0x06,0xF8,0x07,0xF8,0x07,0x80,0x01,}; -const uint8_t* const _A_TouchTunes_14[] = {_A_TouchTunes_14_0,_A_TouchTunes_14_1,_A_TouchTunes_14_2,_A_TouchTunes_14_3,_A_TouchTunes_14_4,_A_TouchTunes_14_5,_A_TouchTunes_14_6,_A_TouchTunes_14_7,_A_TouchTunes_14_8,_A_TouchTunes_14_9,_A_TouchTunes_14_10,_A_TouchTunes_14_11,_A_TouchTunes_14_12,_A_TouchTunes_14_13,_A_TouchTunes_14_14,_A_TouchTunes_14_15,_A_TouchTunes_14_16,_A_TouchTunes_14_17,_A_TouchTunes_14_18,_A_TouchTunes_14_19,_A_TouchTunes_14_20,_A_TouchTunes_14_21,_A_TouchTunes_14_22,_A_TouchTunes_14_23,_A_TouchTunes_14_24,_A_TouchTunes_14_25,_A_TouchTunes_14_26,_A_TouchTunes_14_27,_A_TouchTunes_14_28,_A_TouchTunes_14_29}; - const uint8_t _A_U2F_14_0[] = {0x00,0x00,0x00,0x00,0x00,0xE0,0x01,0x10,0x02,0x08,0x04,0xFE,0x1F,0x01,0x20,0xD5,0x2D,0x55,0x25,0x15,0x2D,0x95,0x24,0xDD,0x25,0x01,0x20,0xFE,0x1F,}; const uint8_t _A_U2F_14_1[] = {0x00,0x00,0x00,0xE0,0x01,0x10,0x02,0x08,0x04,0x08,0x04,0xFE,0x1F,0x01,0x20,0xD5,0x2D,0x55,0x25,0x15,0x2D,0x95,0x24,0xDD,0x25,0x01,0x20,0xFE,0x1F,}; const uint8_t _A_U2F_14_2[] = {0x00,0xE0,0x01,0x10,0x02,0x08,0x04,0x08,0x04,0x08,0x00,0xFE,0x1F,0x01,0x20,0xD5,0x2D,0x55,0x25,0x15,0x2D,0x95,0x24,0xDD,0x25,0x01,0x20,0xFE,0x1F,}; @@ -793,13 +744,11 @@ const Icon I_KeySave_24x11 = {.width=24,.height=11,.frame_count=1,.frame_rate=0, const Icon A_125khz_14 = {.width=14,.height=14,.frame_count=4,.frame_rate=3,.frames=_A_125khz_14}; const Icon A_BadUsb_14 = {.width=14,.height=14,.frame_count=11,.frame_rate=3,.frames=_A_BadUsb_14}; const Icon A_Bluetooth_14 = {.width=14,.height=14,.frame_count=6,.frame_rate=3,.frames=_A_Bluetooth_14}; -const Icon A_Clock_14 = {.width=14,.height=14,.frame_count=8,.frame_rate=3,.frames=_A_Clock_14}; const Icon A_Debug_14 = {.width=14,.height=14,.frame_count=4,.frame_rate=3,.frames=_A_Debug_14}; const Icon A_FileManager_14 = {.width=14,.height=14,.frame_count=10,.frame_rate=3,.frames=_A_FileManager_14}; const Icon A_GPIO_14 = {.width=14,.height=14,.frame_count=8,.frame_rate=3,.frames=_A_GPIO_14}; const Icon A_Games_14 = {.width=14,.height=14,.frame_count=9,.frame_rate=3,.frames=_A_Games_14}; const Icon A_Infrared_14 = {.width=14,.height=14,.frame_count=6,.frame_rate=3,.frames=_A_Infrared_14}; -const Icon A_MusicPlayer_14 = {.width=14,.height=14,.frame_count=5,.frame_rate=3,.frames=_A_MusicPlayer_14}; const Icon A_NFC_14 = {.width=14,.height=14,.frame_count=4,.frame_rate=3,.frames=_A_NFC_14}; const Icon A_Passport_14 = {.width=14,.height=14,.frame_count=10,.frame_rate=3,.frames=_A_Passport_14}; const Icon A_Plugins_14 = {.width=14,.height=14,.frame_count=9,.frame_rate=3,.frames=_A_Plugins_14}; @@ -807,7 +756,6 @@ const Icon A_Power_14 = {.width=14,.height=14,.frame_count=1,.frame_rate=3,.fram const Icon A_Settings_14 = {.width=14,.height=14,.frame_count=10,.frame_rate=3,.frames=_A_Settings_14}; const Icon A_Sub1ghz_14 = {.width=14,.height=14,.frame_count=6,.frame_rate=3,.frames=_A_Sub1ghz_14}; const Icon A_Tamagotchi_14 = {.width=14,.height=14,.frame_count=6,.frame_rate=3,.frames=_A_Tamagotchi_14}; -const Icon A_TouchTunes_14 = {.width=14,.height=14,.frame_count=30,.frame_rate=3,.frames=_A_TouchTunes_14}; const Icon A_U2F_14 = {.width=14,.height=14,.frame_count=4,.frame_rate=3,.frames=_A_U2F_14}; const Icon A_iButton_14 = {.width=14,.height=14,.frame_count=7,.frame_rate=3,.frames=_A_iButton_14}; const Icon I_Detailed_chip_17x13 = {.width=17,.height=13,.frame_count=1,.frame_rate=0,.frames=_I_Detailed_chip_17x13}; diff --git a/assets/compiled/assets_icons.h b/assets/compiled/assets_icons.h index 27e6eaed1..459478802 100644 --- a/assets/compiled/assets_icons.h +++ b/assets/compiled/assets_icons.h @@ -94,13 +94,11 @@ extern const Icon I_KeySave_24x11; extern const Icon A_125khz_14; extern const Icon A_BadUsb_14; extern const Icon A_Bluetooth_14; -extern const Icon A_Clock_14; extern const Icon A_Debug_14; extern const Icon A_FileManager_14; extern const Icon A_GPIO_14; extern const Icon A_Games_14; extern const Icon A_Infrared_14; -extern const Icon A_MusicPlayer_14; extern const Icon A_NFC_14; extern const Icon A_Passport_14; extern const Icon A_Plugins_14; @@ -108,7 +106,6 @@ extern const Icon A_Power_14; extern const Icon A_Settings_14; extern const Icon A_Sub1ghz_14; extern const Icon A_Tamagotchi_14; -extern const Icon A_TouchTunes_14; extern const Icon A_U2F_14; extern const Icon A_iButton_14; extern const Icon I_Detailed_chip_17x13; diff --git a/assets/icons/Dolphin/Flipper_young_80x60.png b/assets/icons/Dolphin/Flipper_young_80x60.png deleted file mode 100644 index 4725aab90..000000000 Binary files a/assets/icons/Dolphin/Flipper_young_80x60.png and /dev/null differ diff --git a/assets/icons/Infrared/Back_15x10.png b/assets/icons/Infrared/Back_15x10.png deleted file mode 100644 index fe9ac5aad..000000000 Binary files a/assets/icons/Infrared/Back_15x10.png and /dev/null differ diff --git a/assets/icons/Infrared/Fill-marker_7x7.png b/assets/icons/Infrared/Fill-marker_7x7.png deleted file mode 100644 index afae1d047..000000000 Binary files a/assets/icons/Infrared/Fill-marker_7x7.png and /dev/null differ diff --git a/assets/icons/Interface/Back3_45x8.png b/assets/icons/Interface/Back3_45x8.png deleted file mode 100644 index 6cb945f62..000000000 Binary files a/assets/icons/Interface/Back3_45x8.png and /dev/null differ diff --git a/assets/icons/MainMenu/Clock_14/frame_01.png b/assets/icons/MainMenu/Clock_14/frame_01.png deleted file mode 100644 index 80193281a..000000000 Binary files a/assets/icons/MainMenu/Clock_14/frame_01.png and /dev/null differ diff --git a/assets/icons/MainMenu/Clock_14/frame_02.png b/assets/icons/MainMenu/Clock_14/frame_02.png deleted file mode 100644 index 7eb0f8bef..000000000 Binary files a/assets/icons/MainMenu/Clock_14/frame_02.png and /dev/null differ diff --git a/assets/icons/MainMenu/Clock_14/frame_03.png b/assets/icons/MainMenu/Clock_14/frame_03.png deleted file mode 100644 index 5d4e6243b..000000000 Binary files a/assets/icons/MainMenu/Clock_14/frame_03.png and /dev/null differ diff --git a/assets/icons/MainMenu/Clock_14/frame_04.png b/assets/icons/MainMenu/Clock_14/frame_04.png deleted file mode 100644 index 8578a5a73..000000000 Binary files a/assets/icons/MainMenu/Clock_14/frame_04.png and /dev/null differ diff --git a/assets/icons/MainMenu/Clock_14/frame_05.png b/assets/icons/MainMenu/Clock_14/frame_05.png deleted file mode 100644 index 9c50fe469..000000000 Binary files a/assets/icons/MainMenu/Clock_14/frame_05.png and /dev/null differ diff --git a/assets/icons/MainMenu/Clock_14/frame_06.png b/assets/icons/MainMenu/Clock_14/frame_06.png deleted file mode 100644 index 4fe0f2c63..000000000 Binary files a/assets/icons/MainMenu/Clock_14/frame_06.png and /dev/null differ diff --git a/assets/icons/MainMenu/Clock_14/frame_07.png b/assets/icons/MainMenu/Clock_14/frame_07.png deleted file mode 100644 index 8ff61ba2e..000000000 Binary files a/assets/icons/MainMenu/Clock_14/frame_07.png and /dev/null differ diff --git a/assets/icons/MainMenu/Clock_14/frame_08.png b/assets/icons/MainMenu/Clock_14/frame_08.png deleted file mode 100644 index baffdaa70..000000000 Binary files a/assets/icons/MainMenu/Clock_14/frame_08.png and /dev/null differ diff --git a/assets/icons/MainMenu/Clock_14/frame_rate b/assets/icons/MainMenu/Clock_14/frame_rate deleted file mode 100644 index 00750edc0..000000000 --- a/assets/icons/MainMenu/Clock_14/frame_rate +++ /dev/null @@ -1 +0,0 @@ -3 diff --git a/assets/icons/MainMenu/MusicPlayer_14/frame_0.png b/assets/icons/MainMenu/MusicPlayer_14/frame_0.png deleted file mode 100644 index 9b20ba849..000000000 Binary files a/assets/icons/MainMenu/MusicPlayer_14/frame_0.png and /dev/null differ diff --git a/assets/icons/MainMenu/MusicPlayer_14/frame_1.png b/assets/icons/MainMenu/MusicPlayer_14/frame_1.png deleted file mode 100644 index 781d353be..000000000 Binary files a/assets/icons/MainMenu/MusicPlayer_14/frame_1.png and /dev/null differ diff --git a/assets/icons/MainMenu/MusicPlayer_14/frame_2.png b/assets/icons/MainMenu/MusicPlayer_14/frame_2.png deleted file mode 100644 index 9a3099dbd..000000000 Binary files a/assets/icons/MainMenu/MusicPlayer_14/frame_2.png and /dev/null differ diff --git a/assets/icons/MainMenu/MusicPlayer_14/frame_3.png b/assets/icons/MainMenu/MusicPlayer_14/frame_3.png deleted file mode 100644 index 13ddc3eee..000000000 Binary files a/assets/icons/MainMenu/MusicPlayer_14/frame_3.png and /dev/null differ diff --git a/assets/icons/MainMenu/MusicPlayer_14/frame_4.png b/assets/icons/MainMenu/MusicPlayer_14/frame_4.png deleted file mode 100644 index 5ae831e64..000000000 Binary files a/assets/icons/MainMenu/MusicPlayer_14/frame_4.png and /dev/null differ diff --git a/assets/icons/MainMenu/MusicPlayer_14/frame_rate b/assets/icons/MainMenu/MusicPlayer_14/frame_rate deleted file mode 100644 index e440e5c84..000000000 --- a/assets/icons/MainMenu/MusicPlayer_14/frame_rate +++ /dev/null @@ -1 +0,0 @@ -3 \ No newline at end of file diff --git a/assets/icons/SDCard/SDError_43x35.png b/assets/icons/SDCard/SDError_43x35.png deleted file mode 100644 index d22e98539..000000000 Binary files a/assets/icons/SDCard/SDError_43x35.png and /dev/null differ diff --git a/assets/icons/StatusBar/USBConnected_15x8.png b/assets/icons/StatusBar/USBConnected_15x8.png deleted file mode 100644 index 4a282391e..000000000 Binary files a/assets/icons/StatusBar/USBConnected_15x8.png and /dev/null differ diff --git a/assets/icons/iButton/DolphinExcited_64x63.png b/assets/icons/iButton/DolphinExcited_64x63.png deleted file mode 100644 index e695c85f0..000000000 Binary files a/assets/icons/iButton/DolphinExcited_64x63.png and /dev/null differ diff --git a/assets/icons/iButton/iButtonDolphinSuccess_109x60.png b/assets/icons/iButton/iButtonDolphinSuccess_109x60.png deleted file mode 100644 index f234aba90..000000000 Binary files a/assets/icons/iButton/iButtonDolphinSuccess_109x60.png and /dev/null differ diff --git a/assets/resources/Manifest b/assets/resources/Manifest index a2e2ab317..9d854b13c 100644 --- a/assets/resources/Manifest +++ b/assets/resources/Manifest @@ -1,5 +1,5 @@ V:0 -T:1653685642 +T:1654009290 D:badusb D:dolphin D:infrared @@ -229,16 +229,13 @@ D:nfc/assets F:81dc04c7b181f94b644079a71476dff4:4742:nfc/assets/aid.nfc F:86efbebdf41bb6bf15cc51ef88f069d5:2565:nfc/assets/country_code.nfc F:41b4f08774249014cb8d3dffa5f5c07d:1757:nfc/assets/currency_code.nfc -F:18d6ceceaa8d86931a631103152f121d:50397:nfc/assets/mf_classic_dict.nfc +F:c60e862919731b0bd538a1001bbc1098:17453:nfc/assets/mf_classic_dict.nfc D:subghz/assets F:dda1ef895b8a25fde57c874feaaef997:650:subghz/assets/came_atomo F:610a0ffa2479a874f2060eb2348104c5:2712:subghz/assets/keeloq_mfcodes F:9214f9c10463b746a27e82ce0b96e040:465:subghz/assets/keeloq_mfcodes_user F:653bd8d349055a41e1152e557d4a52d3:202:subghz/assets/nice_flor_s -F:35851dab442aa3e18722fcaaf2ce070e:666:subghz/assets/setting_frequency_analyzer_user -F:2b9d171f9bbaa09f609eeba909a40b6a:861:subghz/assets/setting_user -F:e7199dcdbc7910508b1ef3fddf3fe219:255:subghz/assets/touchtunes_map -F:b27818b54bc04922f1a722334edbee0e:269:subghz/assets/universal_rf_map +F:c6ec4374275cd20f482ecd46de9f53e3:528:subghz/assets/setting_user D:u2f/assets F:7e11e688e39034bbb9d88410044795e1:365:u2f/assets/cert.der F:f60b88c20ed479ed9684e249f7134618:264:u2f/assets/cert_key.u2f diff --git a/assets/resources/subghz/assets/setting_frequency_analyzer_user b/assets/resources/subghz/assets/setting_frequency_analyzer_user deleted file mode 100644 index ee75a2c83..000000000 --- a/assets/resources/subghz/assets/setting_frequency_analyzer_user +++ /dev/null @@ -1,31 +0,0 @@ -Filetype: Flipper SubGhz Setting File -Version: 1 -Frequency_default: 433920000 -Frequency: 300000000 -Frequency: 302757000 -Frequency: 303875000 -Frequency: 304250000 -Frequency: 310000000 -Frequency: 312000000 -Frequency: 313850000 -Frequency: 314000000 -Frequency: 315000000 -Frequency: 318000000 -Frequency: 348000000 -Frequency: 387000000 -Frequency: 390000000 -Frequency: 418000000 -Frequency: 433075000 -Frequency: 433220000 -Frequency: 433420000 -Frequency: 433889000 -Frequency: 433920000 -Frequency: 434420000 -Frequency: 434775000 -Frequency: 438900000 -Frequency: 464000000 -Frequency: 779000000 -Frequency: 868350000 -Frequency: 915000000 -Frequency: 925000000 -Frequency: 928000000 diff --git a/assets/resources/subghz/assets/setting_user b/assets/resources/subghz/assets/setting_user index e3039e560..413dbf31f 100644 --- a/assets/resources/subghz/assets/setting_user +++ b/assets/resources/subghz/assets/setting_user @@ -1,38 +1,18 @@ Filetype: Flipper SubGhz Setting File Version: 1 -Frequency_default: 433920000 -Frequency: 300000000 -Frequency: 302757000 -Frequency: 303875000 -Frequency: 304250000 -Frequency: 310000000 -Frequency: 312000000 -Frequency: 313850000 -Frequency: 314000000 -Frequency: 315000000 -Frequency: 318000000 -Frequency: 348000000 -Frequency: 387000000 -Frequency: 390000000 -Frequency: 418000000 -Frequency: 433075000 -Frequency: 433220000 -Frequency: 433420000 -Frequency: 433889000 -Frequency: 433920000 -Frequency: 434420000 -Frequency: 434775000 -Frequency: 438900000 -Frequency: 464000000 -Frequency: 779000000 -Frequency: 868350000 -Frequency: 915000000 -Frequency: 925000000 -Frequency: 928000000 -Hopper_frequency: 312000000 -Hopper_frequency: 314000000 -Hopper_frequency: 315000000 -Hopper_frequency: 318000000 -Hopper_frequency: 390000000 -Hopper_frequency: 433920000 -Hopper_frequency: 868350000 \ No newline at end of file + +# Add Standard frequencies for your region +#add_standard_frequencies: true + +# Default Frequency: used as default for "Read" and "Read Raw" +#default_frequency: 433920000 + +# Frequencies used for "Read", "Read Raw" and "Frequency Analyzer" +#frequency: 300000000 +#frequency: 310000000 +#frequency: 320000000 + +# Frequencies used for hopping mode (keep this list small or flipper will miss signal) +#hopper_frequency: 300000000 +#hopper_frequency: 310000000 +#hopper_frequency: 310000000 diff --git a/assets/resources/subghz/assets/touchtunes_map b/assets/resources/subghz/assets/touchtunes_map deleted file mode 100644 index 2e2c6ff81..000000000 --- a/assets/resources/subghz/assets/touchtunes_map +++ /dev/null @@ -1,7 +0,0 @@ -Filetype: Flipper SubGhz RAW File -Version: 1 -UP: /any/subghz/touchtunes/brute/P2.sub -DOWN: /any/subghz/touchtunes/brute/Pause.sub -LEFT: /any/subghz/touchtunes/brute/Pwr.sub -RIGHT: /any/subghz/touchtunes/brute/P1.sub -OK: /any/subghz/touchtunes/brute/OK.sub \ No newline at end of file diff --git a/assets/resources/subghz/assets/universal_rf_map b/assets/resources/subghz/assets/universal_rf_map deleted file mode 100644 index 986ff9c35..000000000 --- a/assets/resources/subghz/assets/universal_rf_map +++ /dev/null @@ -1,7 +0,0 @@ -Filetype: Flipper SubGhz RAW File -Version: 1 -UP: /any/subghz/Vehicles/Tesla/Tesla_charge_door_AM270.sub -DOWN: /any/subghz/DoorbellFM.sub -LEFT: /any/subghz/Vehicles/Tesla/Tesla_charge_door_AM650.sub -RIGHT: /any/subghz/Doorbell1.sub -OK: /any/subghz/handicap_push_door.sub \ No newline at end of file diff --git a/firmware/targets/f7/furi_hal/furi_hal_subghz.c b/firmware/targets/f7/furi_hal/furi_hal_subghz.c index 2c182978f..1167b8650 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_subghz.c +++ b/firmware/targets/f7/furi_hal/furi_hal_subghz.c @@ -287,7 +287,7 @@ static const uint8_t furi_hal_subghz_preset_ook_async_patable[8] = { 0x00}; static const uint8_t furi_hal_subghz_preset_ook_async_patable_au[8] = { 0x00, - 0xC0, // 12dBm 0xC0, 10dBm 0xC5, 7dBm 0xCD, 5dBm 0x86, 0dBm 0x50, -6dBm 0x37, -10dBm 0x26, -15dBm 0x1D, -20dBm 0x17, -30dBm 0x03 + 0x37, // 12dBm 0xC0, 10dBm 0xC5, 7dBm 0xCD, 5dBm 0x86, 0dBm 0x50, -6dBm 0x37, -10dBm 0x26, -15dBm 0x1D, -20dBm 0x17, -30dBm 0x03 0x00, 0x00, 0x00, @@ -570,49 +570,9 @@ uint32_t furi_hal_subghz_set_frequency_and_path(uint32_t value) { } bool furi_hal_subghz_is_tx_allowed(uint32_t value) { - //checking regional settings - bool is_allowed = false; - switch(furi_hal_version_get_hw_region()) { - case FuriHalVersionRegionEuRu: - //433,05..434,79; 868,15..868,55 - if(!(value >= 299999755 && value <= 348000335) && - !(value >= 386999938 && value <= 464000000) && - !(value >= 778999847 && value <= 928000000)) { - } else { - is_allowed = true; - } - break; - case FuriHalVersionRegionUsCaAu: - //304,10..321,95; 433,05..434,79; 915,00..928,00 - if(!(value >= 299999755 && value <= 348000335) && - !(value >= 386999938 && value <= 464000000) && - !(value >= 778999847 && value <= 928000000)) { - } else { - if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { - if((value >= 304100000 && value <= 321950000) && - ((furi_hal_subghz_preset == FuriHalSubGhzPresetOok270Async) || - (furi_hal_subghz_preset == FuriHalSubGhzPresetOok650Async))) { - furi_hal_subghz_load_patable(furi_hal_subghz_preset_ook_async_patable_au); - } - } - is_allowed = true; - } - break; - case FuriHalVersionRegionJp: - //312,00..315,25; 920,50..923,50 - if(!(value >= 299999755 && value <= 348000335) && - !(value >= 386999938 && value <= 464000000) && - !(value >= 778999847 && value <= 928000000)) { - } else { - is_allowed = true; - } - break; - - default: - is_allowed = true; - break; - } - return is_allowed; + // Removed region check + + return true; } uint32_t furi_hal_subghz_set_frequency(uint32_t value) { diff --git a/firmware/targets/f7/target.mk b/firmware/targets/f7/target.mk index 4b019cae8..8e58a71c9 100644 --- a/firmware/targets/f7/target.mk +++ b/firmware/targets/f7/target.mk @@ -19,8 +19,9 @@ endif MCU_FLAGS = -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard # Warnings configuration -CFLAGS += $(MCU_FLAGS) -DSTM32WB55xx -Wall -fdata-sections -ffunction-sections +CFLAGS += -Wall -Wextra -Wredundant-decls -Wdouble-promotion +CFLAGS += $(MCU_FLAGS) -DSTM32WB55xx -fdata-sections -ffunction-sections -fsingle-precision-constant LDFLAGS += $(MCU_FLAGS) -specs=nosys.specs -specs=nano.specs CPPFLAGS += -fno-rtti -fno-use-cxa-atexit -fno-exceptions diff --git a/lib/one_wire/ibutton/ibutton_key.c b/lib/one_wire/ibutton/ibutton_key.c index c6d4466f0..2c0f7fa26 100644 --- a/lib/one_wire/ibutton/ibutton_key.c +++ b/lib/one_wire/ibutton/ibutton_key.c @@ -4,7 +4,6 @@ struct iButtonKey { uint8_t data[IBUTTON_KEY_DATA_SIZE]; - char name[IBUTTON_KEY_NAME_SIZE]; iButtonKeyType type; }; @@ -42,14 +41,6 @@ uint8_t ibutton_key_get_data_size(iButtonKey* key) { return ibutton_key_get_size_by_type(key->type); } -void ibutton_key_set_name(iButtonKey* key, const char* name) { - strlcpy(key->name, name, IBUTTON_KEY_NAME_SIZE); -} - -const char* ibutton_key_get_name_p(iButtonKey* key) { - return key->name; -} - void ibutton_key_set_type(iButtonKey* key, iButtonKeyType key_type) { key->type = key_type; } diff --git a/lib/one_wire/ibutton/ibutton_key.h b/lib/one_wire/ibutton/ibutton_key.h index 8d6732bcb..f66537d7e 100644 --- a/lib/one_wire/ibutton/ibutton_key.h +++ b/lib/one_wire/ibutton/ibutton_key.h @@ -68,20 +68,6 @@ const uint8_t* ibutton_key_get_data_p(iButtonKey* key); */ uint8_t ibutton_key_get_data_size(iButtonKey* key); -/** - * Set key name - * @param key - * @param name - */ -void ibutton_key_set_name(iButtonKey* key, const char* name); - -/** - * Get pointer to key name - * @param key - * @return const char* - */ -const char* ibutton_key_get_name_p(iButtonKey* key); - /** * Set key type * @param key diff --git a/lib/subghz/protocols/secplus_v1.c b/lib/subghz/protocols/secplus_v1.c index 0dacbda76..6767c3897 100644 --- a/lib/subghz/protocols/secplus_v1.c +++ b/lib/subghz/protocols/secplus_v1.c @@ -152,8 +152,8 @@ static bool level_duration_make(true, (uint32_t)subghz_protocol_secplus_v1_const.te_short * 2); break; case SECPLUS_V1_BIT_2: - instance->encoder.upload[index++] = level_duration_make( - false, (uint32_t)subghz_protocol_secplus_v1_const.te_short); + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_secplus_v1_const.te_short); instance->encoder.upload[index++] = level_duration_make(true, (uint32_t)subghz_protocol_secplus_v1_const.te_short * 3); break; @@ -188,8 +188,8 @@ static bool level_duration_make(true, (uint32_t)subghz_protocol_secplus_v1_const.te_short * 2); break; case SECPLUS_V1_BIT_2: - instance->encoder.upload[index++] = level_duration_make( - false, (uint32_t)subghz_protocol_secplus_v1_const.te_short); + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_secplus_v1_const.te_short); instance->encoder.upload[index++] = level_duration_make(true, (uint32_t)subghz_protocol_secplus_v1_const.te_short * 3); break; @@ -278,10 +278,10 @@ bool subghz_protocol_encoder_secplus_v1_deserialize(void* context, FlipperFormat flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - if(!subghz_protocol_secplus_v1_encode(instance)){ + if(!subghz_protocol_secplus_v1_encode(instance)) { break; } - if(!subghz_protocol_encoder_secplus_v1_get_upload(instance)){ + if(!subghz_protocol_encoder_secplus_v1_get_upload(instance)) { break; } @@ -528,12 +528,12 @@ bool subghz_protocol_decoder_secplus_v1_deserialize(void* context, FlipperFormat return subghz_block_generic_deserialize(&instance->generic, flipper_format); } -bool subghz_protocol_secplus_v1_check_fixed (uint32_t fixed) { +bool subghz_protocol_secplus_v1_check_fixed(uint32_t fixed) { //uint8_t id0 = (fixed / 3) % 3; uint8_t id1 = (fixed / 9) % 3; uint8_t btn = fixed % 3; - do{ + do { if(id1 == 0) return false; if(!(btn == 0 || btn == 1 || btn == 2)) return false; } while(false); diff --git a/lib/subghz/subghz_keystore.c b/lib/subghz/subghz_keystore.c index d64e1fda2..d3903bc51 100644 --- a/lib/subghz/subghz_keystore.c +++ b/lib/subghz/subghz_keystore.c @@ -334,7 +334,6 @@ bool subghz_keystore_save(SubGhzKeystore* instance, const char* file_name, uint8 SubGhzKeyArray_t* subghz_keystore_get_data(SubGhzKeystore* instance) { furi_assert(instance); return &instance->data; - FURI_LOG_I(TAG, "array: \n", &instance->data); } bool subghz_keystore_raw_encrypted_save( diff --git a/lib/toolbox/path.c b/lib/toolbox/path.c index 4fd042e41..a99e57d1f 100644 --- a/lib/toolbox/path.c +++ b/lib/toolbox/path.c @@ -19,6 +19,20 @@ void path_extract_filename_no_ext(const char* path, string_t filename) { string_mid(filename, start_position, end_position - start_position); } +void path_extract_filename(string_t path, string_t name, bool trim_ext) { + size_t filename_start = string_search_rchar(path, '/'); + if(filename_start > 0) { + filename_start++; + string_set_n(name, path, filename_start, string_size(path) - filename_start); + } + if(trim_ext) { + size_t dot = string_search_rchar(name, '.'); + if(dot > 0) { + string_left(name, dot); + } + } +} + static inline void path_cleanup(string_t path) { string_strim(path); while(string_end_with_str_p(path, "/")) { diff --git a/lib/toolbox/path.h b/lib/toolbox/path.h index 0de63bb2b..76e501cc1 100644 --- a/lib/toolbox/path.h +++ b/lib/toolbox/path.h @@ -14,6 +14,15 @@ extern "C" { */ void path_extract_filename_no_ext(const char* path, string_t filename); +/** + * @brief Extract filename string from path. + * + * @param path path string + * @param filename output filename string. Must be initialized before. + * @param trim_ext true - get filename without extension + */ +void path_extract_filename(string_t path, string_t filename, bool trim_ext); + /** * @brief Extract last path component * diff --git a/lib/toolbox/random_name.c b/lib/toolbox/random_name.c index cf2f8d7fb..60cbaf826 100644 --- a/lib/toolbox/random_name.c +++ b/lib/toolbox/random_name.c @@ -14,6 +14,4 @@ void set_random_name(char* name, uint8_t max_name_size) { , datetime.hour, datetime.minute ); sniprintf(name, max_name_size, "%s", strings[0]); - // Set first symbol to upper case - name[0] = name[0] - 0x20; } diff --git a/make/git.mk b/make/git.mk index 5ff53a1b8..8c0cd73ad 100644 --- a/make/git.mk +++ b/make/git.mk @@ -4,7 +4,7 @@ GIT_BRANCH_NUM := $(shell git rev-list --count HEAD || echo 'nan') BUILD_DATE := $(shell date '+%d-%m-%Y' || echo 'unknown') BUILD_TIME := $(shell date '+%H:%M:%S' || echo 'unknown') VERSION := $(shell git describe --tags --abbrev=0 --exact-match 2>/dev/null || echo 'unknown') -GIT_DIRTY_BUILD := $(shell echo 0) +GIT_DIRTY_BUILD := 0 # TODO: Return git diff check back GIT_DIRTY_SUFFIX := ifeq ($(GIT_DIRTY_BUILD), 1)