Merge branch 'release-candidate' into release
This commit is contained in:
		
						commit
						3f164ef30d
					
				@ -13,7 +13,7 @@ bool archive_back_event_callback(void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ArchiveApp* archive_alloc() {
 | 
					ArchiveApp* archive_alloc() {
 | 
				
			||||||
    ArchiveApp* archive = furi_alloc(sizeof(ArchiveApp));
 | 
					    ArchiveApp* archive = malloc(sizeof(ArchiveApp));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    archive->gui = furi_record_open("gui");
 | 
					    archive->gui = furi_record_open("gui");
 | 
				
			||||||
    archive->text_input = text_input_alloc();
 | 
					    archive->text_input = text_input_alloc();
 | 
				
			||||||
 | 
				
			|||||||
@ -305,7 +305,7 @@ bool archive_view_input(InputEvent* event, void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ArchiveBrowserView* browser_alloc() {
 | 
					ArchiveBrowserView* browser_alloc() {
 | 
				
			||||||
    ArchiveBrowserView* browser = furi_alloc(sizeof(ArchiveBrowserView));
 | 
					    ArchiveBrowserView* browser = malloc(sizeof(ArchiveBrowserView));
 | 
				
			||||||
    browser->view = view_alloc();
 | 
					    browser->view = view_alloc();
 | 
				
			||||||
    view_allocate_model(browser->view, ViewModelTypeLocking, sizeof(ArchiveBrowserViewModel));
 | 
					    view_allocate_model(browser->view, ViewModelTypeLocking, sizeof(ArchiveBrowserViewModel));
 | 
				
			||||||
    view_set_context(browser->view, browser);
 | 
					    view_set_context(browser->view, browser);
 | 
				
			||||||
 | 
				
			|||||||
@ -41,7 +41,7 @@ static bool bad_usb_check_assets() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
BadUsbApp* bad_usb_app_alloc(char* arg) {
 | 
					BadUsbApp* bad_usb_app_alloc(char* arg) {
 | 
				
			||||||
    BadUsbApp* app = furi_alloc(sizeof(BadUsbApp));
 | 
					    BadUsbApp* app = malloc(sizeof(BadUsbApp));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(arg != NULL) {
 | 
					    if(arg != NULL) {
 | 
				
			||||||
        string_t filename;
 | 
					        string_t filename;
 | 
				
			||||||
 | 
				
			|||||||
@ -524,7 +524,7 @@ static int32_t bad_usb_worker(void* context) {
 | 
				
			|||||||
BadUsbScript* bad_usb_script_open(string_t file_path) {
 | 
					BadUsbScript* bad_usb_script_open(string_t file_path) {
 | 
				
			||||||
    furi_assert(file_path);
 | 
					    furi_assert(file_path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    BadUsbScript* bad_usb = furi_alloc(sizeof(BadUsbScript));
 | 
					    BadUsbScript* bad_usb = malloc(sizeof(BadUsbScript));
 | 
				
			||||||
    string_init(bad_usb->file_path);
 | 
					    string_init(bad_usb->file_path);
 | 
				
			||||||
    string_set(bad_usb->file_path, file_path);
 | 
					    string_set(bad_usb->file_path, file_path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -115,7 +115,7 @@ static bool bad_usb_input_callback(InputEvent* event, void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
BadUsb* bad_usb_alloc() {
 | 
					BadUsb* bad_usb_alloc() {
 | 
				
			||||||
    BadUsb* bad_usb = furi_alloc(sizeof(BadUsb));
 | 
					    BadUsb* bad_usb = malloc(sizeof(BadUsb));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bad_usb->view = view_alloc();
 | 
					    bad_usb->view = view_alloc();
 | 
				
			||||||
    view_allocate_model(bad_usb->view, ViewModelTypeLocking, sizeof(BadUsbModel));
 | 
					    view_allocate_model(bad_usb->view, ViewModelTypeLocking, sizeof(BadUsbModel));
 | 
				
			||||||
 | 
				
			|||||||
@ -27,7 +27,7 @@ uint32_t bt_debug_start_view(void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
BtDebugApp* bt_debug_app_alloc() {
 | 
					BtDebugApp* bt_debug_app_alloc() {
 | 
				
			||||||
    BtDebugApp* app = furi_alloc(sizeof(BtDebugApp));
 | 
					    BtDebugApp* app = malloc(sizeof(BtDebugApp));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Load settings
 | 
					    // Load settings
 | 
				
			||||||
    bt_settings_load(&app->settings);
 | 
					    bt_settings_load(&app->settings);
 | 
				
			||||||
 | 
				
			|||||||
@ -130,7 +130,7 @@ static void bt_test_carrier_timer_callback(void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
BtCarrierTest* bt_carrier_test_alloc() {
 | 
					BtCarrierTest* bt_carrier_test_alloc() {
 | 
				
			||||||
    BtCarrierTest* bt_carrier_test = furi_alloc(sizeof(BtCarrierTest));
 | 
					    BtCarrierTest* bt_carrier_test = malloc(sizeof(BtCarrierTest));
 | 
				
			||||||
    bt_carrier_test->bt_test = bt_test_alloc();
 | 
					    bt_carrier_test->bt_test = bt_test_alloc();
 | 
				
			||||||
    bt_test_set_context(bt_carrier_test->bt_test, bt_carrier_test);
 | 
					    bt_test_set_context(bt_carrier_test->bt_test, bt_carrier_test);
 | 
				
			||||||
    bt_test_set_change_state_callback(
 | 
					    bt_test_set_change_state_callback(
 | 
				
			||||||
 | 
				
			|||||||
@ -98,7 +98,7 @@ static void bt_test_packet_timer_callback(void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
BtPacketTest* bt_packet_test_alloc() {
 | 
					BtPacketTest* bt_packet_test_alloc() {
 | 
				
			||||||
    BtPacketTest* bt_packet_test = furi_alloc(sizeof(BtPacketTest));
 | 
					    BtPacketTest* bt_packet_test = malloc(sizeof(BtPacketTest));
 | 
				
			||||||
    bt_packet_test->bt_test = bt_test_alloc();
 | 
					    bt_packet_test->bt_test = bt_test_alloc();
 | 
				
			||||||
    bt_test_set_context(bt_packet_test->bt_test, bt_packet_test);
 | 
					    bt_test_set_context(bt_packet_test->bt_test, bt_packet_test);
 | 
				
			||||||
    bt_test_set_change_state_callback(
 | 
					    bt_test_set_change_state_callback(
 | 
				
			||||||
 | 
				
			|||||||
@ -291,7 +291,7 @@ void bt_test_process_back(BtTest* bt_test) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
BtTest* bt_test_alloc() {
 | 
					BtTest* bt_test_alloc() {
 | 
				
			||||||
    BtTest* bt_test = furi_alloc(sizeof(BtTest));
 | 
					    BtTest* bt_test = malloc(sizeof(BtTest));
 | 
				
			||||||
    bt_test->view = view_alloc();
 | 
					    bt_test->view = view_alloc();
 | 
				
			||||||
    view_set_context(bt_test->view, bt_test);
 | 
					    view_set_context(bt_test->view, bt_test);
 | 
				
			||||||
    view_allocate_model(bt_test->view, ViewModelTypeLocking, sizeof(BtTestModel));
 | 
					    view_allocate_model(bt_test->view, ViewModelTypeLocking, sizeof(BtTestModel));
 | 
				
			||||||
 | 
				
			|||||||
@ -54,7 +54,7 @@ void bt_hid_connection_status_changed_callback(BtStatus status, void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
BtHid* bt_hid_app_alloc() {
 | 
					BtHid* bt_hid_app_alloc() {
 | 
				
			||||||
    BtHid* app = furi_alloc(sizeof(BtHid));
 | 
					    BtHid* app = malloc(sizeof(BtHid));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Gui
 | 
					    // Gui
 | 
				
			||||||
    app->gui = furi_record_open("gui");
 | 
					    app->gui = furi_record_open("gui");
 | 
				
			||||||
 | 
				
			|||||||
@ -161,7 +161,7 @@ static bool bt_hid_keynote_input_callback(InputEvent* event, void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
BtHidKeynote* bt_hid_keynote_alloc() {
 | 
					BtHidKeynote* bt_hid_keynote_alloc() {
 | 
				
			||||||
    BtHidKeynote* bt_hid_keynote = furi_alloc(sizeof(BtHidKeynote));
 | 
					    BtHidKeynote* bt_hid_keynote = malloc(sizeof(BtHidKeynote));
 | 
				
			||||||
    bt_hid_keynote->view = view_alloc();
 | 
					    bt_hid_keynote->view = view_alloc();
 | 
				
			||||||
    view_set_context(bt_hid_keynote->view, bt_hid_keynote);
 | 
					    view_set_context(bt_hid_keynote->view, bt_hid_keynote);
 | 
				
			||||||
    view_allocate_model(bt_hid_keynote->view, ViewModelTypeLocking, sizeof(BtHidKeynoteModel));
 | 
					    view_allocate_model(bt_hid_keynote->view, ViewModelTypeLocking, sizeof(BtHidKeynoteModel));
 | 
				
			||||||
 | 
				
			|||||||
@ -162,7 +162,7 @@ static bool bt_hid_media_input_callback(InputEvent* event, void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
BtHidMedia* bt_hid_media_alloc() {
 | 
					BtHidMedia* bt_hid_media_alloc() {
 | 
				
			||||||
    BtHidMedia* bt_hid_media = furi_alloc(sizeof(BtHidMedia));
 | 
					    BtHidMedia* bt_hid_media = malloc(sizeof(BtHidMedia));
 | 
				
			||||||
    bt_hid_media->view = view_alloc();
 | 
					    bt_hid_media->view = view_alloc();
 | 
				
			||||||
    view_set_context(bt_hid_media->view, bt_hid_media);
 | 
					    view_set_context(bt_hid_media->view, bt_hid_media);
 | 
				
			||||||
    view_allocate_model(bt_hid_media->view, ViewModelTypeLocking, sizeof(BtHidMediaModel));
 | 
					    view_allocate_model(bt_hid_media->view, ViewModelTypeLocking, sizeof(BtHidMediaModel));
 | 
				
			||||||
 | 
				
			|||||||
@ -101,7 +101,7 @@ static void bt_battery_level_changed_callback(const void* _event, void* context)
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Bt* bt_alloc() {
 | 
					Bt* bt_alloc() {
 | 
				
			||||||
    Bt* bt = furi_alloc(sizeof(Bt));
 | 
					    Bt* bt = malloc(sizeof(Bt));
 | 
				
			||||||
    // Init default maximum packet size
 | 
					    // Init default maximum packet size
 | 
				
			||||||
    bt->max_packet_size = FURI_HAL_BT_SERIAL_PACKET_SIZE_MAX;
 | 
					    bt->max_packet_size = FURI_HAL_BT_SERIAL_PACKET_SIZE_MAX;
 | 
				
			||||||
    bt->profile = BtProfileSerial;
 | 
					    bt->profile = BtProfileSerial;
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,7 @@ static bool bt_settings_back_event_callback(void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
BtSettingsApp* bt_settings_app_alloc() {
 | 
					BtSettingsApp* bt_settings_app_alloc() {
 | 
				
			||||||
    BtSettingsApp* app = furi_alloc(sizeof(BtSettingsApp));
 | 
					    BtSettingsApp* app = malloc(sizeof(BtSettingsApp));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Load settings
 | 
					    // Load settings
 | 
				
			||||||
    bt_settings_load(&app->settings);
 | 
					    bt_settings_load(&app->settings);
 | 
				
			||||||
 | 
				
			|||||||
@ -5,7 +5,7 @@
 | 
				
			|||||||
#include <loader/loader.h>
 | 
					#include <loader/loader.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Cli* cli_alloc() {
 | 
					Cli* cli_alloc() {
 | 
				
			||||||
    Cli* cli = furi_alloc(sizeof(Cli));
 | 
					    Cli* cli = malloc(sizeof(Cli));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CliCommandTree_init(cli->commands);
 | 
					    CliCommandTree_init(cli->commands);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -67,7 +67,7 @@ void crypto_cli_encrypt(Cli* cli, string_t args) {
 | 
				
			|||||||
                size = size - remain + 16;
 | 
					                size = size - remain + 16;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            string_reserve(input, size);
 | 
					            string_reserve(input, size);
 | 
				
			||||||
            uint8_t* output = furi_alloc(size);
 | 
					            uint8_t* output = malloc(size);
 | 
				
			||||||
            if(!furi_hal_crypto_encrypt((const uint8_t*)string_get_cstr(input), output, size)) {
 | 
					            if(!furi_hal_crypto_encrypt((const uint8_t*)string_get_cstr(input), output, size)) {
 | 
				
			||||||
                printf("Failed to encrypt input");
 | 
					                printf("Failed to encrypt input");
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
@ -135,8 +135,8 @@ void crypto_cli_decrypt(Cli* cli, string_t args) {
 | 
				
			|||||||
        size_t hex_size = string_size(hex_input);
 | 
					        size_t hex_size = string_size(hex_input);
 | 
				
			||||||
        if(hex_size > 0 && hex_size % 2 == 0) {
 | 
					        if(hex_size > 0 && hex_size % 2 == 0) {
 | 
				
			||||||
            size_t size = hex_size / 2;
 | 
					            size_t size = hex_size / 2;
 | 
				
			||||||
            uint8_t* input = furi_alloc(size);
 | 
					            uint8_t* input = malloc(size);
 | 
				
			||||||
            uint8_t* output = furi_alloc(size);
 | 
					            uint8_t* output = malloc(size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(args_read_hex_bytes(hex_input, input, size)) {
 | 
					            if(args_read_hex_bytes(hex_input, input, size)) {
 | 
				
			||||||
                if(furi_hal_crypto_decrypt(input, output, size)) {
 | 
					                if(furi_hal_crypto_decrypt(input, output, size)) {
 | 
				
			||||||
 | 
				
			|||||||
@ -121,7 +121,7 @@ static void display_config_set_contrast(VariableItem* item) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DisplayTest* display_test_alloc() {
 | 
					DisplayTest* display_test_alloc() {
 | 
				
			||||||
    DisplayTest* instance = furi_alloc(sizeof(DisplayTest));
 | 
					    DisplayTest* instance = malloc(sizeof(DisplayTest));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    View* view = NULL;
 | 
					    View* view = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -155,7 +155,7 @@ static void view_display_test_timer_callback(void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ViewDisplayTest* view_display_test_alloc() {
 | 
					ViewDisplayTest* view_display_test_alloc() {
 | 
				
			||||||
    ViewDisplayTest* instance = furi_alloc(sizeof(ViewDisplayTest));
 | 
					    ViewDisplayTest* instance = malloc(sizeof(ViewDisplayTest));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    instance->view = view_alloc();
 | 
					    instance->view = view_alloc();
 | 
				
			||||||
    view_set_context(instance->view, instance);
 | 
					    view_set_context(instance->view, instance);
 | 
				
			||||||
 | 
				
			|||||||
@ -178,7 +178,7 @@ static int32_t uart_echo_worker(void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static UartEchoApp* uart_echo_app_alloc() {
 | 
					static UartEchoApp* uart_echo_app_alloc() {
 | 
				
			||||||
    UartEchoApp* app = furi_alloc(sizeof(UartEchoApp));
 | 
					    UartEchoApp* app = malloc(sizeof(UartEchoApp));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    app->rx_stream = xStreamBufferCreate(2048, 1);
 | 
					    app->rx_stream = xStreamBufferCreate(2048, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -201,7 +201,7 @@ static UartEchoApp* uart_echo_app_alloc() {
 | 
				
			|||||||
            for(size_t i = 0; i < LINES_ON_SCREEN; i++) {
 | 
					            for(size_t i = 0; i < LINES_ON_SCREEN; i++) {
 | 
				
			||||||
                model->line = 0;
 | 
					                model->line = 0;
 | 
				
			||||||
                model->escape = false;
 | 
					                model->escape = false;
 | 
				
			||||||
                model->list[i] = furi_alloc(sizeof(ListElement));
 | 
					                model->list[i] = malloc(sizeof(ListElement));
 | 
				
			||||||
                string_init(model->list[i]->text);
 | 
					                string_init(model->list[i]->text);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
 | 
				
			|||||||
@ -47,7 +47,7 @@ uint32_t usb_test_exit(void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
UsbTestApp* usb_test_app_alloc() {
 | 
					UsbTestApp* usb_test_app_alloc() {
 | 
				
			||||||
    UsbTestApp* app = furi_alloc(sizeof(UsbTestApp));
 | 
					    UsbTestApp* app = malloc(sizeof(UsbTestApp));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Gui
 | 
					    // Gui
 | 
				
			||||||
    app->gui = furi_record_open("gui");
 | 
					    app->gui = furi_record_open("gui");
 | 
				
			||||||
 | 
				
			|||||||
@ -258,7 +258,7 @@ static void animation_manager_replace_current_animation(
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
AnimationManager* animation_manager_alloc(void) {
 | 
					AnimationManager* animation_manager_alloc(void) {
 | 
				
			||||||
    AnimationManager* animation_manager = furi_alloc(sizeof(AnimationManager));
 | 
					    AnimationManager* animation_manager = malloc(sizeof(AnimationManager));
 | 
				
			||||||
    animation_manager->animation_view = bubble_animation_view_alloc();
 | 
					    animation_manager->animation_view = bubble_animation_view_alloc();
 | 
				
			||||||
    animation_manager->view_stack = view_stack_alloc();
 | 
					    animation_manager->view_stack = view_stack_alloc();
 | 
				
			||||||
    View* animation_view = bubble_animation_get_view(animation_manager->animation_view);
 | 
					    View* animation_view = bubble_animation_get_view(animation_manager->animation_view);
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
#include <flipper_file.h>
 | 
					#include <flipper_format/flipper_format.h>
 | 
				
			||||||
#include <furi.h>
 | 
					#include <furi.h>
 | 
				
			||||||
#include <furi/dangerous_defines.h>
 | 
					#include <furi/dangerous_defines.h>
 | 
				
			||||||
#include <storage/storage.h>
 | 
					#include <storage/storage.h>
 | 
				
			||||||
@ -30,41 +30,41 @@ static bool animation_storage_load_single_manifest_info(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    bool result = false;
 | 
					    bool result = false;
 | 
				
			||||||
    Storage* storage = furi_record_open("storage");
 | 
					    Storage* storage = furi_record_open("storage");
 | 
				
			||||||
    FlipperFile* file = flipper_file_alloc(storage);
 | 
					    FlipperFormat* file = flipper_format_file_alloc(storage);
 | 
				
			||||||
    flipper_file_set_strict_mode(file, true);
 | 
					    flipper_format_set_strict_mode(file, true);
 | 
				
			||||||
    string_t read_string;
 | 
					    string_t read_string;
 | 
				
			||||||
    string_init(read_string);
 | 
					    string_init(read_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        uint32_t u32value;
 | 
					        uint32_t u32value;
 | 
				
			||||||
        if(FSE_OK != storage_sd_status(storage)) break;
 | 
					        if(FSE_OK != storage_sd_status(storage)) break;
 | 
				
			||||||
        if(!flipper_file_open_existing(file, ANIMATION_MANIFEST_FILE)) break;
 | 
					        if(!flipper_format_file_open_existing(file, ANIMATION_MANIFEST_FILE)) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(!flipper_file_read_header(file, read_string, &u32value)) break;
 | 
					        if(!flipper_format_read_header(file, read_string, &u32value)) break;
 | 
				
			||||||
        if(string_cmp_str(read_string, "Flipper Animation Manifest")) break;
 | 
					        if(string_cmp_str(read_string, "Flipper Animation Manifest")) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        manifest_info->name = NULL;
 | 
					        manifest_info->name = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* skip other animation names */
 | 
					        /* skip other animation names */
 | 
				
			||||||
        flipper_file_set_strict_mode(file, false);
 | 
					        flipper_format_set_strict_mode(file, false);
 | 
				
			||||||
        while(flipper_file_read_string(file, "Name", read_string) &&
 | 
					        while(flipper_format_read_string(file, "Name", read_string) &&
 | 
				
			||||||
              string_cmp_str(read_string, name))
 | 
					              string_cmp_str(read_string, name))
 | 
				
			||||||
            ;
 | 
					            ;
 | 
				
			||||||
        if(string_cmp_str(read_string, name)) break;
 | 
					        if(string_cmp_str(read_string, name)) break;
 | 
				
			||||||
        flipper_file_set_strict_mode(file, true);
 | 
					        flipper_format_set_strict_mode(file, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        manifest_info->name = furi_alloc(string_size(read_string) + 1);
 | 
					        manifest_info->name = malloc(string_size(read_string) + 1);
 | 
				
			||||||
        strcpy((char*)manifest_info->name, string_get_cstr(read_string));
 | 
					        strcpy((char*)manifest_info->name, string_get_cstr(read_string));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(!flipper_file_read_uint32(file, "Min butthurt", &u32value, 1)) break;
 | 
					        if(!flipper_format_read_uint32(file, "Min butthurt", &u32value, 1)) break;
 | 
				
			||||||
        manifest_info->min_butthurt = u32value;
 | 
					        manifest_info->min_butthurt = u32value;
 | 
				
			||||||
        if(!flipper_file_read_uint32(file, "Max butthurt", &u32value, 1)) break;
 | 
					        if(!flipper_format_read_uint32(file, "Max butthurt", &u32value, 1)) break;
 | 
				
			||||||
        manifest_info->max_butthurt = u32value;
 | 
					        manifest_info->max_butthurt = u32value;
 | 
				
			||||||
        if(!flipper_file_read_uint32(file, "Min level", &u32value, 1)) break;
 | 
					        if(!flipper_format_read_uint32(file, "Min level", &u32value, 1)) break;
 | 
				
			||||||
        manifest_info->min_level = u32value;
 | 
					        manifest_info->min_level = u32value;
 | 
				
			||||||
        if(!flipper_file_read_uint32(file, "Max level", &u32value, 1)) break;
 | 
					        if(!flipper_format_read_uint32(file, "Max level", &u32value, 1)) break;
 | 
				
			||||||
        manifest_info->max_level = u32value;
 | 
					        manifest_info->max_level = u32value;
 | 
				
			||||||
        if(!flipper_file_read_uint32(file, "Weight", &u32value, 1)) break;
 | 
					        if(!flipper_format_read_uint32(file, "Weight", &u32value, 1)) break;
 | 
				
			||||||
        manifest_info->weight = u32value;
 | 
					        manifest_info->weight = u32value;
 | 
				
			||||||
        result = true;
 | 
					        result = true;
 | 
				
			||||||
    } while(0);
 | 
					    } while(0);
 | 
				
			||||||
@ -73,8 +73,7 @@ static bool animation_storage_load_single_manifest_info(
 | 
				
			|||||||
        free((void*)manifest_info->name);
 | 
					        free((void*)manifest_info->name);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    string_clear(read_string);
 | 
					    string_clear(read_string);
 | 
				
			||||||
    flipper_file_close(file);
 | 
					    flipper_format_free(file);
 | 
				
			||||||
    flipper_file_free(file);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    furi_record_close("storage");
 | 
					    furi_record_close("storage");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -86,9 +85,9 @@ void animation_storage_fill_animation_list(StorageAnimationList_t* animation_lis
 | 
				
			|||||||
    furi_assert(!StorageAnimationList_size(*animation_list));
 | 
					    furi_assert(!StorageAnimationList_size(*animation_list));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Storage* storage = furi_record_open("storage");
 | 
					    Storage* storage = furi_record_open("storage");
 | 
				
			||||||
    FlipperFile* file = flipper_file_alloc(storage);
 | 
					    FlipperFormat* file = flipper_format_file_alloc(storage);
 | 
				
			||||||
    /* Forbid skipping fields */
 | 
					    /* Forbid skipping fields */
 | 
				
			||||||
    flipper_file_set_strict_mode(file, true);
 | 
					    flipper_format_set_strict_mode(file, true);
 | 
				
			||||||
    string_t read_string;
 | 
					    string_t read_string;
 | 
				
			||||||
    string_init(read_string);
 | 
					    string_init(read_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -97,28 +96,28 @@ void animation_storage_fill_animation_list(StorageAnimationList_t* animation_lis
 | 
				
			|||||||
        StorageAnimation* storage_animation = NULL;
 | 
					        StorageAnimation* storage_animation = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(FSE_OK != storage_sd_status(storage)) break;
 | 
					        if(FSE_OK != storage_sd_status(storage)) break;
 | 
				
			||||||
        if(!flipper_file_open_existing(file, ANIMATION_MANIFEST_FILE)) break;
 | 
					        if(!flipper_format_file_open_existing(file, ANIMATION_MANIFEST_FILE)) break;
 | 
				
			||||||
        if(!flipper_file_read_header(file, read_string, &u32value)) break;
 | 
					        if(!flipper_format_read_header(file, read_string, &u32value)) break;
 | 
				
			||||||
        if(string_cmp_str(read_string, "Flipper Animation Manifest")) break;
 | 
					        if(string_cmp_str(read_string, "Flipper Animation Manifest")) break;
 | 
				
			||||||
        do {
 | 
					        do {
 | 
				
			||||||
            storage_animation = furi_alloc(sizeof(StorageAnimation));
 | 
					            storage_animation = malloc(sizeof(StorageAnimation));
 | 
				
			||||||
            storage_animation->external = true;
 | 
					            storage_animation->external = true;
 | 
				
			||||||
            storage_animation->animation = NULL;
 | 
					            storage_animation->animation = NULL;
 | 
				
			||||||
            storage_animation->manifest_info.name = NULL;
 | 
					            storage_animation->manifest_info.name = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(!flipper_file_read_string(file, "Name", read_string)) break;
 | 
					            if(!flipper_format_read_string(file, "Name", read_string)) break;
 | 
				
			||||||
            storage_animation->manifest_info.name = furi_alloc(string_size(read_string) + 1);
 | 
					            storage_animation->manifest_info.name = malloc(string_size(read_string) + 1);
 | 
				
			||||||
            strcpy((char*)storage_animation->manifest_info.name, string_get_cstr(read_string));
 | 
					            strcpy((char*)storage_animation->manifest_info.name, string_get_cstr(read_string));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(!flipper_file_read_uint32(file, "Min butthurt", &u32value, 1)) break;
 | 
					            if(!flipper_format_read_uint32(file, "Min butthurt", &u32value, 1)) break;
 | 
				
			||||||
            storage_animation->manifest_info.min_butthurt = u32value;
 | 
					            storage_animation->manifest_info.min_butthurt = u32value;
 | 
				
			||||||
            if(!flipper_file_read_uint32(file, "Max butthurt", &u32value, 1)) break;
 | 
					            if(!flipper_format_read_uint32(file, "Max butthurt", &u32value, 1)) break;
 | 
				
			||||||
            storage_animation->manifest_info.max_butthurt = u32value;
 | 
					            storage_animation->manifest_info.max_butthurt = u32value;
 | 
				
			||||||
            if(!flipper_file_read_uint32(file, "Min level", &u32value, 1)) break;
 | 
					            if(!flipper_format_read_uint32(file, "Min level", &u32value, 1)) break;
 | 
				
			||||||
            storage_animation->manifest_info.min_level = u32value;
 | 
					            storage_animation->manifest_info.min_level = u32value;
 | 
				
			||||||
            if(!flipper_file_read_uint32(file, "Max level", &u32value, 1)) break;
 | 
					            if(!flipper_format_read_uint32(file, "Max level", &u32value, 1)) break;
 | 
				
			||||||
            storage_animation->manifest_info.max_level = u32value;
 | 
					            storage_animation->manifest_info.max_level = u32value;
 | 
				
			||||||
            if(!flipper_file_read_uint32(file, "Weight", &u32value, 1)) break;
 | 
					            if(!flipper_format_read_uint32(file, "Weight", &u32value, 1)) break;
 | 
				
			||||||
            storage_animation->manifest_info.weight = u32value;
 | 
					            storage_animation->manifest_info.weight = u32value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            StorageAnimationList_push_back(*animation_list, storage_animation);
 | 
					            StorageAnimationList_push_back(*animation_list, storage_animation);
 | 
				
			||||||
@ -128,8 +127,7 @@ void animation_storage_fill_animation_list(StorageAnimationList_t* animation_lis
 | 
				
			|||||||
    } while(0);
 | 
					    } while(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    string_clear(read_string);
 | 
					    string_clear(read_string);
 | 
				
			||||||
    flipper_file_close(file);
 | 
					    flipper_format_free(file);
 | 
				
			||||||
    flipper_file_free(file);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // add hard-coded animations
 | 
					    // add hard-coded animations
 | 
				
			||||||
    for(int i = 0; i < dolphin_internal_size; ++i) {
 | 
					    for(int i = 0; i < dolphin_internal_size; ++i) {
 | 
				
			||||||
@ -162,7 +160,7 @@ StorageAnimation* animation_storage_find_animation(const char* name) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /* look through external animations */
 | 
					    /* look through external animations */
 | 
				
			||||||
    if(!storage_animation) {
 | 
					    if(!storage_animation) {
 | 
				
			||||||
        storage_animation = furi_alloc(sizeof(StorageAnimation));
 | 
					        storage_animation = malloc(sizeof(StorageAnimation));
 | 
				
			||||||
        storage_animation->external = true;
 | 
					        storage_animation->external = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        bool result = false;
 | 
					        bool result = false;
 | 
				
			||||||
@ -288,7 +286,7 @@ static bool animation_storage_load_frames(
 | 
				
			|||||||
    FURI_CONST_ASSIGN(icon->frame_rate, 0);
 | 
					    FURI_CONST_ASSIGN(icon->frame_rate, 0);
 | 
				
			||||||
    FURI_CONST_ASSIGN(icon->height, height);
 | 
					    FURI_CONST_ASSIGN(icon->height, height);
 | 
				
			||||||
    FURI_CONST_ASSIGN(icon->width, width);
 | 
					    FURI_CONST_ASSIGN(icon->width, width);
 | 
				
			||||||
    icon->frames = furi_alloc(sizeof(const uint8_t*) * icon->frame_count);
 | 
					    icon->frames = malloc(sizeof(const uint8_t*) * icon->frame_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool frames_ok = false;
 | 
					    bool frames_ok = false;
 | 
				
			||||||
    File* file = storage_file_alloc(storage);
 | 
					    File* file = storage_file_alloc(storage);
 | 
				
			||||||
@ -317,7 +315,7 @@ static bool animation_storage_load_frames(
 | 
				
			|||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        FURI_CONST_ASSIGN_PTR(icon->frames[i], furi_alloc(file_info.size));
 | 
					        FURI_CONST_ASSIGN_PTR(icon->frames[i], malloc(file_info.size));
 | 
				
			||||||
        if(storage_file_read(file, (void*)icon->frames[i], file_info.size) != file_info.size) {
 | 
					        if(storage_file_read(file, (void*)icon->frames[i], file_info.size) != file_info.size) {
 | 
				
			||||||
            FURI_LOG_E(TAG, "Read failed: \'%s\'", string_get_cstr(filename));
 | 
					            FURI_LOG_E(TAG, "Read failed: \'%s\'", string_get_cstr(filename));
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
@ -348,7 +346,7 @@ static bool animation_storage_load_frames(
 | 
				
			|||||||
    return frames_ok;
 | 
					    return frames_ok;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool animation_storage_load_bubbles(BubbleAnimation* animation, FlipperFile* ff) {
 | 
					static bool animation_storage_load_bubbles(BubbleAnimation* animation, FlipperFormat* ff) {
 | 
				
			||||||
    uint32_t u32value;
 | 
					    uint32_t u32value;
 | 
				
			||||||
    string_t str;
 | 
					    string_t str;
 | 
				
			||||||
    string_init(str);
 | 
					    string_init(str);
 | 
				
			||||||
@ -356,7 +354,7 @@ static bool animation_storage_load_bubbles(BubbleAnimation* animation, FlipperFi
 | 
				
			|||||||
    furi_assert(!animation->frame_bubble_sequences);
 | 
					    furi_assert(!animation->frame_bubble_sequences);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        if(!flipper_file_read_uint32(ff, "Bubble slots", &u32value, 1)) break;
 | 
					        if(!flipper_format_read_uint32(ff, "Bubble slots", &u32value, 1)) break;
 | 
				
			||||||
        if(u32value > 20) break;
 | 
					        if(u32value > 20) break;
 | 
				
			||||||
        animation->frame_bubble_sequences_count = u32value;
 | 
					        animation->frame_bubble_sequences_count = u32value;
 | 
				
			||||||
        if(animation->frame_bubble_sequences_count == 0) {
 | 
					        if(animation->frame_bubble_sequences_count == 0) {
 | 
				
			||||||
@ -365,22 +363,22 @@ static bool animation_storage_load_bubbles(BubbleAnimation* animation, FlipperFi
 | 
				
			|||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        animation->frame_bubble_sequences =
 | 
					        animation->frame_bubble_sequences =
 | 
				
			||||||
            furi_alloc(sizeof(FrameBubble*) * animation->frame_bubble_sequences_count);
 | 
					            malloc(sizeof(FrameBubble*) * animation->frame_bubble_sequences_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        uint32_t current_slot = 0;
 | 
					        uint32_t current_slot = 0;
 | 
				
			||||||
        for(int i = 0; i < animation->frame_bubble_sequences_count; ++i) {
 | 
					        for(int i = 0; i < animation->frame_bubble_sequences_count; ++i) {
 | 
				
			||||||
            FURI_CONST_ASSIGN_PTR(
 | 
					            FURI_CONST_ASSIGN_PTR(
 | 
				
			||||||
                animation->frame_bubble_sequences[i], furi_alloc(sizeof(FrameBubble)));
 | 
					                animation->frame_bubble_sequences[i], malloc(sizeof(FrameBubble)));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const FrameBubble* bubble = animation->frame_bubble_sequences[0];
 | 
					        const FrameBubble* bubble = animation->frame_bubble_sequences[0];
 | 
				
			||||||
        int8_t index = -1;
 | 
					        int8_t index = -1;
 | 
				
			||||||
        for(;;) {
 | 
					        for(;;) {
 | 
				
			||||||
            if(!flipper_file_read_uint32(ff, "Slot", ¤t_slot, 1)) break;
 | 
					            if(!flipper_format_read_uint32(ff, "Slot", ¤t_slot, 1)) break;
 | 
				
			||||||
            if((current_slot != 0) && (index == -1)) break;
 | 
					            if((current_slot != 0) && (index == -1)) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(current_slot == index) {
 | 
					            if(current_slot == index) {
 | 
				
			||||||
                FURI_CONST_ASSIGN_PTR(bubble->next_bubble, furi_alloc(sizeof(FrameBubble)));
 | 
					                FURI_CONST_ASSIGN_PTR(bubble->next_bubble, malloc(sizeof(FrameBubble)));
 | 
				
			||||||
                bubble = bubble->next_bubble;
 | 
					                bubble = bubble->next_bubble;
 | 
				
			||||||
            } else if(current_slot == index + 1) {
 | 
					            } else if(current_slot == index + 1) {
 | 
				
			||||||
                ++index;
 | 
					                ++index;
 | 
				
			||||||
@ -392,27 +390,27 @@ static bool animation_storage_load_bubbles(BubbleAnimation* animation, FlipperFi
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            if(index >= animation->frame_bubble_sequences_count) break;
 | 
					            if(index >= animation->frame_bubble_sequences_count) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(!flipper_file_read_uint32(ff, "X", &u32value, 1)) break;
 | 
					            if(!flipper_format_read_uint32(ff, "X", &u32value, 1)) break;
 | 
				
			||||||
            FURI_CONST_ASSIGN(bubble->bubble.x, u32value);
 | 
					            FURI_CONST_ASSIGN(bubble->bubble.x, u32value);
 | 
				
			||||||
            if(!flipper_file_read_uint32(ff, "Y", &u32value, 1)) break;
 | 
					            if(!flipper_format_read_uint32(ff, "Y", &u32value, 1)) break;
 | 
				
			||||||
            FURI_CONST_ASSIGN(bubble->bubble.y, u32value);
 | 
					            FURI_CONST_ASSIGN(bubble->bubble.y, u32value);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(!flipper_file_read_string(ff, "Text", str)) break;
 | 
					            if(!flipper_format_read_string(ff, "Text", str)) break;
 | 
				
			||||||
            if(string_size(str) > 100) break;
 | 
					            if(string_size(str) > 100) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            string_replace_all_str(str, "\\n", "\n");
 | 
					            string_replace_all_str(str, "\\n", "\n");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            FURI_CONST_ASSIGN_PTR(bubble->bubble.text, furi_alloc(string_size(str) + 1));
 | 
					            FURI_CONST_ASSIGN_PTR(bubble->bubble.text, malloc(string_size(str) + 1));
 | 
				
			||||||
            strcpy((char*)bubble->bubble.text, string_get_cstr(str));
 | 
					            strcpy((char*)bubble->bubble.text, string_get_cstr(str));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(!flipper_file_read_string(ff, "AlignH", str)) break;
 | 
					            if(!flipper_format_read_string(ff, "AlignH", str)) break;
 | 
				
			||||||
            if(!animation_storage_cast_align(str, (Align*)&bubble->bubble.align_h)) break;
 | 
					            if(!animation_storage_cast_align(str, (Align*)&bubble->bubble.align_h)) break;
 | 
				
			||||||
            if(!flipper_file_read_string(ff, "AlignV", str)) break;
 | 
					            if(!flipper_format_read_string(ff, "AlignV", str)) break;
 | 
				
			||||||
            if(!animation_storage_cast_align(str, (Align*)&bubble->bubble.align_v)) break;
 | 
					            if(!animation_storage_cast_align(str, (Align*)&bubble->bubble.align_v)) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(!flipper_file_read_uint32(ff, "StartFrame", &u32value, 1)) break;
 | 
					            if(!flipper_format_read_uint32(ff, "StartFrame", &u32value, 1)) break;
 | 
				
			||||||
            FURI_CONST_ASSIGN(bubble->start_frame, u32value);
 | 
					            FURI_CONST_ASSIGN(bubble->start_frame, u32value);
 | 
				
			||||||
            if(!flipper_file_read_uint32(ff, "EndFrame", &u32value, 1)) break;
 | 
					            if(!flipper_format_read_uint32(ff, "EndFrame", &u32value, 1)) break;
 | 
				
			||||||
            FURI_CONST_ASSIGN(bubble->end_frame, u32value);
 | 
					            FURI_CONST_ASSIGN(bubble->end_frame, u32value);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        success = (index + 1) == animation->frame_bubble_sequences_count;
 | 
					        success = (index + 1) == animation->frame_bubble_sequences_count;
 | 
				
			||||||
@ -431,15 +429,15 @@ static bool animation_storage_load_bubbles(BubbleAnimation* animation, FlipperFi
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static BubbleAnimation* animation_storage_load_animation(const char* name) {
 | 
					static BubbleAnimation* animation_storage_load_animation(const char* name) {
 | 
				
			||||||
    furi_assert(name);
 | 
					    furi_assert(name);
 | 
				
			||||||
    BubbleAnimation* animation = furi_alloc(sizeof(BubbleAnimation));
 | 
					    BubbleAnimation* animation = malloc(sizeof(BubbleAnimation));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint32_t height = 0;
 | 
					    uint32_t height = 0;
 | 
				
			||||||
    uint32_t width = 0;
 | 
					    uint32_t width = 0;
 | 
				
			||||||
    uint32_t* u32array = NULL;
 | 
					    uint32_t* u32array = NULL;
 | 
				
			||||||
    Storage* storage = furi_record_open("storage");
 | 
					    Storage* storage = furi_record_open("storage");
 | 
				
			||||||
    FlipperFile* ff = flipper_file_alloc(storage);
 | 
					    FlipperFormat* ff = flipper_format_file_alloc(storage);
 | 
				
			||||||
    /* Forbid skipping fields */
 | 
					    /* Forbid skipping fields */
 | 
				
			||||||
    flipper_file_set_strict_mode(ff, true);
 | 
					    flipper_format_set_strict_mode(ff, true);
 | 
				
			||||||
    string_t str;
 | 
					    string_t str;
 | 
				
			||||||
    string_init(str);
 | 
					    string_init(str);
 | 
				
			||||||
    animation->frame_bubble_sequences = NULL;
 | 
					    animation->frame_bubble_sequences = NULL;
 | 
				
			||||||
@ -451,28 +449,28 @@ static BubbleAnimation* animation_storage_load_animation(const char* name) {
 | 
				
			|||||||
        if(FSE_OK != storage_sd_status(storage)) break;
 | 
					        if(FSE_OK != storage_sd_status(storage)) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        string_printf(str, ANIMATION_DIR "/%s/" ANIMATION_META_FILE, name);
 | 
					        string_printf(str, ANIMATION_DIR "/%s/" ANIMATION_META_FILE, name);
 | 
				
			||||||
        if(!flipper_file_open_existing(ff, string_get_cstr(str))) break;
 | 
					        if(!flipper_format_file_open_existing(ff, string_get_cstr(str))) break;
 | 
				
			||||||
        if(!flipper_file_read_header(ff, str, &u32value)) break;
 | 
					        if(!flipper_format_read_header(ff, str, &u32value)) break;
 | 
				
			||||||
        if(string_cmp_str(str, "Flipper Animation")) break;
 | 
					        if(string_cmp_str(str, "Flipper Animation")) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(!flipper_file_read_uint32(ff, "Width", &width, 1)) break;
 | 
					        if(!flipper_format_read_uint32(ff, "Width", &width, 1)) break;
 | 
				
			||||||
        if(!flipper_file_read_uint32(ff, "Height", &height, 1)) break;
 | 
					        if(!flipper_format_read_uint32(ff, "Height", &height, 1)) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(!flipper_file_read_uint32(ff, "Passive frames", &u32value, 1)) break;
 | 
					        if(!flipper_format_read_uint32(ff, "Passive frames", &u32value, 1)) break;
 | 
				
			||||||
        animation->passive_frames = u32value;
 | 
					        animation->passive_frames = u32value;
 | 
				
			||||||
        if(!flipper_file_read_uint32(ff, "Active frames", &u32value, 1)) break;
 | 
					        if(!flipper_format_read_uint32(ff, "Active frames", &u32value, 1)) break;
 | 
				
			||||||
        animation->active_frames = u32value;
 | 
					        animation->active_frames = u32value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        uint8_t frames = animation->passive_frames + animation->active_frames;
 | 
					        uint8_t frames = animation->passive_frames + animation->active_frames;
 | 
				
			||||||
        uint32_t count = 0;
 | 
					        uint32_t count = 0;
 | 
				
			||||||
        if(!flipper_file_get_value_count(ff, "Frames order", &count)) break;
 | 
					        if(!flipper_format_get_value_count(ff, "Frames order", &count)) break;
 | 
				
			||||||
        if(count != frames) {
 | 
					        if(count != frames) {
 | 
				
			||||||
            FURI_LOG_E(TAG, "Error loading animation: frames order");
 | 
					            FURI_LOG_E(TAG, "Error loading animation: frames order");
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        u32array = furi_alloc(sizeof(uint32_t) * frames);
 | 
					        u32array = malloc(sizeof(uint32_t) * frames);
 | 
				
			||||||
        if(!flipper_file_read_uint32(ff, "Frames order", u32array, frames)) break;
 | 
					        if(!flipper_format_read_uint32(ff, "Frames order", u32array, frames)) break;
 | 
				
			||||||
        animation->frame_order = furi_alloc(sizeof(uint8_t) * frames);
 | 
					        animation->frame_order = malloc(sizeof(uint8_t) * frames);
 | 
				
			||||||
        for(int i = 0; i < frames; ++i) {
 | 
					        for(int i = 0; i < frames; ++i) {
 | 
				
			||||||
            FURI_CONST_ASSIGN(animation->frame_order[i], u32array[i]);
 | 
					            FURI_CONST_ASSIGN(animation->frame_order[i], u32array[i]);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -481,13 +479,13 @@ static BubbleAnimation* animation_storage_load_animation(const char* name) {
 | 
				
			|||||||
        if(!animation_storage_load_frames(storage, name, animation, u32array, width, height))
 | 
					        if(!animation_storage_load_frames(storage, name, animation, u32array, width, height))
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(!flipper_file_read_uint32(ff, "Active cycles", &u32value, 1)) break;
 | 
					        if(!flipper_format_read_uint32(ff, "Active cycles", &u32value, 1)) break;
 | 
				
			||||||
        animation->active_cycles = u32value;
 | 
					        animation->active_cycles = u32value;
 | 
				
			||||||
        if(!flipper_file_read_uint32(ff, "Frame rate", &u32value, 1)) break;
 | 
					        if(!flipper_format_read_uint32(ff, "Frame rate", &u32value, 1)) break;
 | 
				
			||||||
        FURI_CONST_ASSIGN(animation->icon_animation.frame_rate, u32value);
 | 
					        FURI_CONST_ASSIGN(animation->icon_animation.frame_rate, u32value);
 | 
				
			||||||
        if(!flipper_file_read_uint32(ff, "Duration", &u32value, 1)) break;
 | 
					        if(!flipper_format_read_uint32(ff, "Duration", &u32value, 1)) break;
 | 
				
			||||||
        animation->duration = u32value;
 | 
					        animation->duration = u32value;
 | 
				
			||||||
        if(!flipper_file_read_uint32(ff, "Active cooldown", &u32value, 1)) break;
 | 
					        if(!flipper_format_read_uint32(ff, "Active cooldown", &u32value, 1)) break;
 | 
				
			||||||
        animation->active_cooldown = u32value;
 | 
					        animation->active_cooldown = u32value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(!animation_storage_load_bubbles(animation, ff)) break;
 | 
					        if(!animation_storage_load_bubbles(animation, ff)) break;
 | 
				
			||||||
@ -495,8 +493,7 @@ static BubbleAnimation* animation_storage_load_animation(const char* name) {
 | 
				
			|||||||
    } while(0);
 | 
					    } while(0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    string_clear(str);
 | 
					    string_clear(str);
 | 
				
			||||||
    flipper_file_close(ff);
 | 
					    flipper_format_free(ff);
 | 
				
			||||||
    flipper_file_free(ff);
 | 
					 | 
				
			||||||
    if(u32array) {
 | 
					    if(u32array) {
 | 
				
			||||||
        free(u32array);
 | 
					        free(u32array);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -256,17 +256,17 @@ static Icon* bubble_animation_clone_first_frame(const Icon* icon_orig) {
 | 
				
			|||||||
    furi_assert(icon_orig->frames);
 | 
					    furi_assert(icon_orig->frames);
 | 
				
			||||||
    furi_assert(icon_orig->frames[0]);
 | 
					    furi_assert(icon_orig->frames[0]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Icon* icon_clone = furi_alloc(sizeof(Icon));
 | 
					    Icon* icon_clone = malloc(sizeof(Icon));
 | 
				
			||||||
    memcpy(icon_clone, icon_orig, sizeof(Icon));
 | 
					    memcpy(icon_clone, icon_orig, sizeof(Icon));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    icon_clone->frames = furi_alloc(sizeof(uint8_t*));
 | 
					    icon_clone->frames = malloc(sizeof(uint8_t*));
 | 
				
			||||||
    /* icon bitmap can be either compressed or not. It is compressed if
 | 
					    /* icon bitmap can be either compressed or not. It is compressed if
 | 
				
			||||||
     * compressed size is less than original, so max size for bitmap is
 | 
					     * compressed size is less than original, so max size for bitmap is
 | 
				
			||||||
     * uncompressed (width * height) + 1 byte (in uncompressed case)
 | 
					     * uncompressed (width * height) + 1 byte (in uncompressed case)
 | 
				
			||||||
     * for compressed header
 | 
					     * for compressed header
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    size_t max_bitmap_size = ROUND_UP_TO(icon_orig->width, 8) * icon_orig->height + 1;
 | 
					    size_t max_bitmap_size = ROUND_UP_TO(icon_orig->width, 8) * icon_orig->height + 1;
 | 
				
			||||||
    FURI_CONST_ASSIGN_PTR(icon_clone->frames[0], furi_alloc(max_bitmap_size));
 | 
					    FURI_CONST_ASSIGN_PTR(icon_clone->frames[0], malloc(max_bitmap_size));
 | 
				
			||||||
    memcpy((void*)icon_clone->frames[0], icon_orig->frames[0], max_bitmap_size);
 | 
					    memcpy((void*)icon_clone->frames[0], icon_orig->frames[0], max_bitmap_size);
 | 
				
			||||||
    FURI_CONST_ASSIGN(icon_clone->frame_count, 1);
 | 
					    FURI_CONST_ASSIGN(icon_clone->frame_count, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -304,7 +304,7 @@ static void bubble_animation_exit(void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
BubbleAnimationView* bubble_animation_view_alloc(void) {
 | 
					BubbleAnimationView* bubble_animation_view_alloc(void) {
 | 
				
			||||||
    BubbleAnimationView* view = furi_alloc(sizeof(BubbleAnimationView));
 | 
					    BubbleAnimationView* view = malloc(sizeof(BubbleAnimationView));
 | 
				
			||||||
    view->view = view_alloc();
 | 
					    view->view = view_alloc();
 | 
				
			||||||
    view->interact_callback = NULL;
 | 
					    view->interact_callback = NULL;
 | 
				
			||||||
    view->timer = osTimerNew(bubble_animation_timer_callback, osTimerPeriodic, view, NULL);
 | 
					    view->timer = osTimerNew(bubble_animation_timer_callback, osTimerPeriodic, view, NULL);
 | 
				
			||||||
 | 
				
			|||||||
@ -78,7 +78,7 @@ static bool one_shot_view_input(InputEvent* event, void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
OneShotView* one_shot_view_alloc(void) {
 | 
					OneShotView* one_shot_view_alloc(void) {
 | 
				
			||||||
    OneShotView* view = furi_alloc(sizeof(OneShotView));
 | 
					    OneShotView* view = malloc(sizeof(OneShotView));
 | 
				
			||||||
    view->view = view_alloc();
 | 
					    view->view = view_alloc();
 | 
				
			||||||
    view->update_timer =
 | 
					    view->update_timer =
 | 
				
			||||||
        xTimerCreate(NULL, 1000, pdTRUE, view, one_shot_view_update_timer_callback);
 | 
					        xTimerCreate(NULL, 1000, pdTRUE, view, one_shot_view_update_timer_callback);
 | 
				
			||||||
 | 
				
			|||||||
@ -39,7 +39,7 @@ static void desktop_tick_event_callback(void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Desktop* desktop_alloc() {
 | 
					Desktop* desktop_alloc() {
 | 
				
			||||||
    Desktop* desktop = furi_alloc(sizeof(Desktop));
 | 
					    Desktop* desktop = malloc(sizeof(Desktop));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    desktop->unload_animation_semaphore = osSemaphoreNew(1, 0, NULL);
 | 
					    desktop->unload_animation_semaphore = osSemaphoreNew(1, 0, NULL);
 | 
				
			||||||
    desktop->animation_manager = animation_manager_alloc();
 | 
					    desktop->animation_manager = animation_manager_alloc();
 | 
				
			||||||
 | 
				
			|||||||
@ -19,7 +19,7 @@ static bool desktop_settings_back_event_callback(void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DesktopSettingsApp* desktop_settings_app_alloc() {
 | 
					DesktopSettingsApp* desktop_settings_app_alloc() {
 | 
				
			||||||
    DesktopSettingsApp* app = furi_alloc(sizeof(DesktopSettingsApp));
 | 
					    DesktopSettingsApp* app = malloc(sizeof(DesktopSettingsApp));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    app->gui = furi_record_open("gui");
 | 
					    app->gui = furi_record_open("gui");
 | 
				
			||||||
    app->view_dispatcher = view_dispatcher_alloc();
 | 
					    app->view_dispatcher = view_dispatcher_alloc();
 | 
				
			||||||
 | 
				
			|||||||
@ -55,7 +55,7 @@ void desktop_settings_view_pin_setup_howto_set_callback(
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DesktopSettingsViewPinSetupHowto* desktop_settings_view_pin_setup_howto_alloc() {
 | 
					DesktopSettingsViewPinSetupHowto* desktop_settings_view_pin_setup_howto_alloc() {
 | 
				
			||||||
    DesktopSettingsViewPinSetupHowto* view = furi_alloc(sizeof(DesktopSettingsViewPinSetupHowto));
 | 
					    DesktopSettingsViewPinSetupHowto* view = malloc(sizeof(DesktopSettingsViewPinSetupHowto));
 | 
				
			||||||
    view->view = view_alloc();
 | 
					    view->view = view_alloc();
 | 
				
			||||||
    view_allocate_model(view->view, ViewModelTypeLockFree, 1);
 | 
					    view_allocate_model(view->view, ViewModelTypeLockFree, 1);
 | 
				
			||||||
    view_set_context(view->view, view);
 | 
					    view_set_context(view->view, view);
 | 
				
			||||||
 | 
				
			|||||||
@ -77,8 +77,7 @@ void desktop_settings_view_pin_setup_howto2_set_ok_callback(
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DesktopSettingsViewPinSetupHowto2* desktop_settings_view_pin_setup_howto2_alloc() {
 | 
					DesktopSettingsViewPinSetupHowto2* desktop_settings_view_pin_setup_howto2_alloc() {
 | 
				
			||||||
    DesktopSettingsViewPinSetupHowto2* view =
 | 
					    DesktopSettingsViewPinSetupHowto2* view = malloc(sizeof(DesktopSettingsViewPinSetupHowto2));
 | 
				
			||||||
        furi_alloc(sizeof(DesktopSettingsViewPinSetupHowto2));
 | 
					 | 
				
			||||||
    view->view = view_alloc();
 | 
					    view->view = view_alloc();
 | 
				
			||||||
    view_allocate_model(view->view, ViewModelTypeLockFree, 1);
 | 
					    view_allocate_model(view->view, ViewModelTypeLockFree, 1);
 | 
				
			||||||
    view_set_context(view->view, view);
 | 
					    view_set_context(view->view, view);
 | 
				
			||||||
 | 
				
			|||||||
@ -16,7 +16,7 @@ void desktop_scene_hw_mismatch_on_enter(void* context) {
 | 
				
			|||||||
    furi_assert(desktop);
 | 
					    furi_assert(desktop);
 | 
				
			||||||
    Popup* popup = desktop->hw_mismatch_popup;
 | 
					    Popup* popup = desktop->hw_mismatch_popup;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    char* text_buffer = furi_alloc(256);
 | 
					    char* text_buffer = malloc(256);
 | 
				
			||||||
    scene_manager_set_scene_state(
 | 
					    scene_manager_set_scene_state(
 | 
				
			||||||
        desktop->scene_manager, DesktopSceneHwMismatch, (uint32_t)text_buffer);
 | 
					        desktop->scene_manager, DesktopSceneHwMismatch, (uint32_t)text_buffer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -80,7 +80,7 @@ void desktop_scene_pin_input_on_enter(void* context) {
 | 
				
			|||||||
    desktop_view_pin_input_set_done_callback(
 | 
					    desktop_view_pin_input_set_done_callback(
 | 
				
			||||||
        desktop->pin_input_view, desktop_scene_pin_input_done_callback);
 | 
					        desktop->pin_input_view, desktop_scene_pin_input_done_callback);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DesktopScenePinInputState* state = furi_alloc(sizeof(DesktopScenePinInputState));
 | 
					    DesktopScenePinInputState* state = malloc(sizeof(DesktopScenePinInputState));
 | 
				
			||||||
    state->timer =
 | 
					    state->timer =
 | 
				
			||||||
        xTimerCreate(NULL, 10000, pdFALSE, desktop, desktop_scene_pin_input_timer_callback);
 | 
					        xTimerCreate(NULL, 10000, pdFALSE, desktop, desktop_scene_pin_input_timer_callback);
 | 
				
			||||||
    scene_manager_set_scene_state(desktop->scene_manager, DesktopScenePinInput, (uint32_t)state);
 | 
					    scene_manager_set_scene_state(desktop->scene_manager, DesktopScenePinInput, (uint32_t)state);
 | 
				
			||||||
 | 
				
			|||||||
@ -150,7 +150,7 @@ bool desktop_debug_input(InputEvent* event, void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DesktopDebugView* desktop_debug_alloc() {
 | 
					DesktopDebugView* desktop_debug_alloc() {
 | 
				
			||||||
    DesktopDebugView* debug_view = furi_alloc(sizeof(DesktopDebugView));
 | 
					    DesktopDebugView* debug_view = malloc(sizeof(DesktopDebugView));
 | 
				
			||||||
    debug_view->view = view_alloc();
 | 
					    debug_view->view = view_alloc();
 | 
				
			||||||
    view_allocate_model(debug_view->view, ViewModelTypeLocking, sizeof(DesktopDebugViewModel));
 | 
					    view_allocate_model(debug_view->view, ViewModelTypeLocking, sizeof(DesktopDebugViewModel));
 | 
				
			||||||
    view_set_context(debug_view->view, debug_view);
 | 
					    view_set_context(debug_view->view, debug_view);
 | 
				
			||||||
 | 
				
			|||||||
@ -131,7 +131,7 @@ static void desktop_first_start_exit(void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DesktopFirstStartView* desktop_first_start_alloc() {
 | 
					DesktopFirstStartView* desktop_first_start_alloc() {
 | 
				
			||||||
    DesktopFirstStartView* instance = furi_alloc(sizeof(DesktopFirstStartView));
 | 
					    DesktopFirstStartView* instance = malloc(sizeof(DesktopFirstStartView));
 | 
				
			||||||
    instance->view = view_alloc();
 | 
					    instance->view = view_alloc();
 | 
				
			||||||
    view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(DesktopFirstStartViewModel));
 | 
					    view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(DesktopFirstStartViewModel));
 | 
				
			||||||
    view_set_context(instance->view, instance);
 | 
					    view_set_context(instance->view, instance);
 | 
				
			||||||
 | 
				
			|||||||
@ -112,7 +112,7 @@ bool desktop_lock_menu_input(InputEvent* event, void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DesktopLockMenuView* desktop_lock_menu_alloc() {
 | 
					DesktopLockMenuView* desktop_lock_menu_alloc() {
 | 
				
			||||||
    DesktopLockMenuView* lock_menu = furi_alloc(sizeof(DesktopLockMenuView));
 | 
					    DesktopLockMenuView* lock_menu = malloc(sizeof(DesktopLockMenuView));
 | 
				
			||||||
    lock_menu->view = view_alloc();
 | 
					    lock_menu->view = view_alloc();
 | 
				
			||||||
    view_allocate_model(lock_menu->view, ViewModelTypeLocking, sizeof(DesktopLockMenuViewModel));
 | 
					    view_allocate_model(lock_menu->view, ViewModelTypeLocking, sizeof(DesktopLockMenuViewModel));
 | 
				
			||||||
    view_set_context(lock_menu->view, lock_menu);
 | 
					    view_set_context(lock_menu->view, lock_menu);
 | 
				
			||||||
 | 
				
			|||||||
@ -184,7 +184,7 @@ static bool desktop_view_locked_input(InputEvent* event, void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DesktopViewLocked* desktop_view_locked_alloc() {
 | 
					DesktopViewLocked* desktop_view_locked_alloc() {
 | 
				
			||||||
    DesktopViewLocked* locked_view = furi_alloc(sizeof(DesktopViewLocked));
 | 
					    DesktopViewLocked* locked_view = malloc(sizeof(DesktopViewLocked));
 | 
				
			||||||
    locked_view->view = view_alloc();
 | 
					    locked_view->view = view_alloc();
 | 
				
			||||||
    locked_view->timer =
 | 
					    locked_view->timer =
 | 
				
			||||||
        xTimerCreate(NULL, 1000 / 16, pdTRUE, locked_view, locked_view_timer_callback);
 | 
					        xTimerCreate(NULL, 1000 / 16, pdTRUE, locked_view, locked_view_timer_callback);
 | 
				
			||||||
 | 
				
			|||||||
@ -58,7 +58,7 @@ bool desktop_main_input(InputEvent* event, void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DesktopMainView* desktop_main_alloc() {
 | 
					DesktopMainView* desktop_main_alloc() {
 | 
				
			||||||
    DesktopMainView* main_view = furi_alloc(sizeof(DesktopMainView));
 | 
					    DesktopMainView* main_view = malloc(sizeof(DesktopMainView));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    main_view->view = view_alloc();
 | 
					    main_view->view = view_alloc();
 | 
				
			||||||
    view_allocate_model(main_view->view, ViewModelTypeLockFree, 1);
 | 
					    view_allocate_model(main_view->view, ViewModelTypeLockFree, 1);
 | 
				
			||||||
 | 
				
			|||||||
@ -185,7 +185,7 @@ static void desktop_view_pin_input_exit(void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DesktopViewPinInput* desktop_view_pin_input_alloc(void) {
 | 
					DesktopViewPinInput* desktop_view_pin_input_alloc(void) {
 | 
				
			||||||
    DesktopViewPinInput* pin_input = furi_alloc(sizeof(DesktopViewPinInput));
 | 
					    DesktopViewPinInput* pin_input = malloc(sizeof(DesktopViewPinInput));
 | 
				
			||||||
    pin_input->view = view_alloc();
 | 
					    pin_input->view = view_alloc();
 | 
				
			||||||
    view_allocate_model(pin_input->view, ViewModelTypeLocking, sizeof(DesktopViewPinInputModel));
 | 
					    view_allocate_model(pin_input->view, ViewModelTypeLocking, sizeof(DesktopViewPinInputModel));
 | 
				
			||||||
    view_set_context(pin_input->view, pin_input);
 | 
					    view_set_context(pin_input->view, pin_input);
 | 
				
			||||||
 | 
				
			|||||||
@ -57,7 +57,7 @@ void desktop_view_pin_done_set_callback(
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DesktopViewPinSetupDone* desktop_view_pin_done_alloc() {
 | 
					DesktopViewPinSetupDone* desktop_view_pin_done_alloc() {
 | 
				
			||||||
    DesktopViewPinSetupDone* view = furi_alloc(sizeof(DesktopViewPinSetupDone));
 | 
					    DesktopViewPinSetupDone* view = malloc(sizeof(DesktopViewPinSetupDone));
 | 
				
			||||||
    view->view = view_alloc();
 | 
					    view->view = view_alloc();
 | 
				
			||||||
    view_allocate_model(view->view, ViewModelTypeLockFree, 1);
 | 
					    view_allocate_model(view->view, ViewModelTypeLockFree, 1);
 | 
				
			||||||
    view_set_context(view->view, view);
 | 
					    view_set_context(view->view, view);
 | 
				
			||||||
 | 
				
			|||||||
@ -77,7 +77,7 @@ void desktop_view_pin_timeout_free(DesktopViewPinTimeout* instance) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DesktopViewPinTimeout* desktop_view_pin_timeout_alloc(void) {
 | 
					DesktopViewPinTimeout* desktop_view_pin_timeout_alloc(void) {
 | 
				
			||||||
    DesktopViewPinTimeout* instance = furi_alloc(sizeof(DesktopViewPinTimeout));
 | 
					    DesktopViewPinTimeout* instance = malloc(sizeof(DesktopViewPinTimeout));
 | 
				
			||||||
    instance->timer = xTimerCreate(
 | 
					    instance->timer = xTimerCreate(
 | 
				
			||||||
        NULL, pdMS_TO_TICKS(1000), pdTRUE, instance, desktop_view_pin_timeout_timer_callback);
 | 
					        NULL, pdMS_TO_TICKS(1000), pdTRUE, instance, desktop_view_pin_timeout_timer_callback);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -25,8 +25,7 @@ bool dialogs_app_process_module_file_select(const DialogsAppMessageDataFileSelec
 | 
				
			|||||||
    bool ret = false;
 | 
					    bool ret = false;
 | 
				
			||||||
    Gui* gui = furi_record_open("gui");
 | 
					    Gui* gui = furi_record_open("gui");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DialogsAppFileSelectContext* file_select_context =
 | 
					    DialogsAppFileSelectContext* file_select_context = malloc(sizeof(DialogsAppFileSelectContext));
 | 
				
			||||||
        furi_alloc(sizeof(DialogsAppFileSelectContext));
 | 
					 | 
				
			||||||
    file_select_context->lock = API_LOCK_INIT_LOCKED();
 | 
					    file_select_context->lock = API_LOCK_INIT_LOCKED();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ViewHolder* view_holder = view_holder_alloc();
 | 
					    ViewHolder* view_holder = view_holder_alloc();
 | 
				
			||||||
 | 
				
			|||||||
@ -46,6 +46,8 @@ static void dialogs_app_message_callback(DialogExResult result, void* context) {
 | 
				
			|||||||
    case DialogExResultCenter:
 | 
					    case DialogExResultCenter:
 | 
				
			||||||
        message_context->result = DialogMessageButtonCenter;
 | 
					        message_context->result = DialogMessageButtonCenter;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
					    default:
 | 
				
			||||||
 | 
					        break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    API_LOCK_UNLOCK(message_context->lock);
 | 
					    API_LOCK_UNLOCK(message_context->lock);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -54,7 +56,7 @@ DialogMessageButton dialogs_app_process_module_message(const DialogsAppMessageDa
 | 
				
			|||||||
    DialogMessageButton ret = DialogMessageButtonBack;
 | 
					    DialogMessageButton ret = DialogMessageButtonBack;
 | 
				
			||||||
    Gui* gui = furi_record_open("gui");
 | 
					    Gui* gui = furi_record_open("gui");
 | 
				
			||||||
    const DialogMessage* message = data->message;
 | 
					    const DialogMessage* message = data->message;
 | 
				
			||||||
    DialogsAppMessageContext* message_context = furi_alloc(sizeof(DialogsAppMessageContext));
 | 
					    DialogsAppMessageContext* message_context = malloc(sizeof(DialogsAppMessageContext));
 | 
				
			||||||
    message_context->lock = API_LOCK_INIT_LOCKED();
 | 
					    message_context->lock = API_LOCK_INIT_LOCKED();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ViewHolder* view_holder = view_holder_alloc();
 | 
					    ViewHolder* view_holder = view_holder_alloc();
 | 
				
			||||||
@ -100,7 +102,7 @@ DialogMessageButton dialogs_app_process_module_message(const DialogsAppMessageDa
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DialogMessage* dialog_message_alloc() {
 | 
					DialogMessage* dialog_message_alloc() {
 | 
				
			||||||
    DialogMessage* message = furi_alloc(sizeof(DialogMessage));
 | 
					    DialogMessage* message = malloc(sizeof(DialogMessage));
 | 
				
			||||||
    return message;
 | 
					    return message;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -21,7 +21,7 @@ static void view_holder_draw_callback(Canvas* canvas, void* context);
 | 
				
			|||||||
static void view_holder_input_callback(InputEvent* event, void* context);
 | 
					static void view_holder_input_callback(InputEvent* event, void* context);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ViewHolder* view_holder_alloc() {
 | 
					ViewHolder* view_holder_alloc() {
 | 
				
			||||||
    ViewHolder* view_holder = furi_alloc(sizeof(ViewHolder));
 | 
					    ViewHolder* view_holder = malloc(sizeof(ViewHolder));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    view_holder->view_port = view_port_alloc();
 | 
					    view_holder->view_port = view_port_alloc();
 | 
				
			||||||
    view_port_draw_callback_set(view_holder->view_port, view_holder_draw_callback, view_holder);
 | 
					    view_port_draw_callback_set(view_holder->view_port, view_holder_draw_callback, view_holder);
 | 
				
			||||||
 | 
				
			|||||||
@ -74,7 +74,7 @@ void dolphin_clear_limits_timer_callback(TimerHandle_t xTimer) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Dolphin* dolphin_alloc() {
 | 
					Dolphin* dolphin_alloc() {
 | 
				
			||||||
    Dolphin* dolphin = furi_alloc(sizeof(Dolphin));
 | 
					    Dolphin* dolphin = malloc(sizeof(Dolphin));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    dolphin->state = dolphin_state_alloc();
 | 
					    dolphin->state = dolphin_state_alloc();
 | 
				
			||||||
    dolphin->event_queue = osMessageQueueNew(8, sizeof(DolphinEvent), NULL);
 | 
					    dolphin->event_queue = osMessageQueueNew(8, sizeof(DolphinEvent), NULL);
 | 
				
			||||||
 | 
				
			|||||||
@ -17,7 +17,7 @@
 | 
				
			|||||||
#define BUTTHURT_MIN 0
 | 
					#define BUTTHURT_MIN 0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DolphinState* dolphin_state_alloc() {
 | 
					DolphinState* dolphin_state_alloc() {
 | 
				
			||||||
    return furi_alloc(sizeof(DolphinState));
 | 
					    return malloc(sizeof(DolphinState));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void dolphin_state_free(DolphinState* dolphin_state) {
 | 
					void dolphin_state_free(DolphinState* dolphin_state) {
 | 
				
			||||||
 | 
				
			|||||||
@ -22,7 +22,7 @@ static void gpio_app_tick_event_callback(void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GpioApp* gpio_app_alloc() {
 | 
					GpioApp* gpio_app_alloc() {
 | 
				
			||||||
    GpioApp* app = furi_alloc(sizeof(GpioApp));
 | 
					    GpioApp* app = malloc(sizeof(GpioApp));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    app->gui = furi_record_open("gui");
 | 
					    app->gui = furi_record_open("gui");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -18,7 +18,7 @@ void gpio_scene_usb_uart_on_enter(void* context) {
 | 
				
			|||||||
    GpioApp* app = context;
 | 
					    GpioApp* app = context;
 | 
				
			||||||
    uint32_t prev_state = scene_manager_get_scene_state(app->scene_manager, GpioAppViewUsbUart);
 | 
					    uint32_t prev_state = scene_manager_get_scene_state(app->scene_manager, GpioAppViewUsbUart);
 | 
				
			||||||
    if(prev_state == 0) {
 | 
					    if(prev_state == 0) {
 | 
				
			||||||
        scene_usb_uart = furi_alloc(sizeof(SceneUsbUartBridge));
 | 
					        scene_usb_uart = malloc(sizeof(SceneUsbUartBridge));
 | 
				
			||||||
        scene_usb_uart->cfg.vcp_ch = 0; // TODO: settings load
 | 
					        scene_usb_uart->cfg.vcp_ch = 0; // TODO: settings load
 | 
				
			||||||
        scene_usb_uart->cfg.uart_ch = 0;
 | 
					        scene_usb_uart->cfg.uart_ch = 0;
 | 
				
			||||||
        scene_usb_uart->cfg.flow_pins = 0;
 | 
					        scene_usb_uart->cfg.flow_pins = 0;
 | 
				
			||||||
@ -33,6 +33,7 @@ void gpio_scene_usb_uart_on_enter(void* context) {
 | 
				
			|||||||
    gpio_usb_uart_set_callback(app->gpio_usb_uart, gpio_scene_usb_uart_callback, app);
 | 
					    gpio_usb_uart_set_callback(app->gpio_usb_uart, gpio_scene_usb_uart_callback, app);
 | 
				
			||||||
    scene_manager_set_scene_state(app->scene_manager, GpioAppViewUsbUart, 0);
 | 
					    scene_manager_set_scene_state(app->scene_manager, GpioAppViewUsbUart, 0);
 | 
				
			||||||
    view_dispatcher_switch_to_view(app->view_dispatcher, GpioAppViewUsbUart);
 | 
					    view_dispatcher_switch_to_view(app->view_dispatcher, GpioAppViewUsbUart);
 | 
				
			||||||
 | 
					    notification_message(app->notifications, &sequence_display_lock);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool gpio_scene_usb_uart_on_event(void* context, SceneManagerEvent event) {
 | 
					bool gpio_scene_usb_uart_on_event(void* context, SceneManagerEvent event) {
 | 
				
			||||||
@ -62,4 +63,5 @@ void gpio_scene_usb_uart_on_exit(void* context) {
 | 
				
			|||||||
        usb_uart_disable(app->usb_uart_bridge);
 | 
					        usb_uart_disable(app->usb_uart_bridge);
 | 
				
			||||||
        free(scene_usb_uart);
 | 
					        free(scene_usb_uart);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    notification_message(app->notifications, &sequence_display_unlock);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -91,7 +91,7 @@ void gpio_scene_usb_uart_cfg_on_enter(void* context) {
 | 
				
			|||||||
    GpioApp* app = context;
 | 
					    GpioApp* app = context;
 | 
				
			||||||
    VariableItemList* var_item_list = app->var_item_list;
 | 
					    VariableItemList* var_item_list = app->var_item_list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cfg_set = furi_alloc(sizeof(UsbUartConfig));
 | 
					    cfg_set = malloc(sizeof(UsbUartConfig));
 | 
				
			||||||
    usb_uart_get_config(app->usb_uart_bridge, cfg_set);
 | 
					    usb_uart_get_config(app->usb_uart_bridge, cfg_set);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    VariableItem* item;
 | 
					    VariableItem* item;
 | 
				
			||||||
 | 
				
			|||||||
@ -312,7 +312,7 @@ static void vcp_on_line_config(void* context, struct usb_cdc_line_coding* config
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
UsbUartBridge* usb_uart_enable(UsbUartConfig* cfg) {
 | 
					UsbUartBridge* usb_uart_enable(UsbUartConfig* cfg) {
 | 
				
			||||||
    UsbUartBridge* usb_uart = furi_alloc(sizeof(UsbUartBridge));
 | 
					    UsbUartBridge* usb_uart = malloc(sizeof(UsbUartBridge));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    memcpy(&(usb_uart->cfg_new), cfg, sizeof(UsbUartConfig));
 | 
					    memcpy(&(usb_uart->cfg_new), cfg, sizeof(UsbUartConfig));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -96,7 +96,7 @@ static bool gpio_test_process_ok(GpioTest* gpio_test, InputEvent* event) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GpioTest* gpio_test_alloc() {
 | 
					GpioTest* gpio_test_alloc() {
 | 
				
			||||||
    GpioTest* gpio_test = furi_alloc(sizeof(GpioTest));
 | 
					    GpioTest* gpio_test = malloc(sizeof(GpioTest));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    gpio_test->view = view_alloc();
 | 
					    gpio_test->view = view_alloc();
 | 
				
			||||||
    view_allocate_model(gpio_test->view, ViewModelTypeLocking, sizeof(GpioTestModel));
 | 
					    view_allocate_model(gpio_test->view, ViewModelTypeLocking, sizeof(GpioTestModel));
 | 
				
			||||||
 | 
				
			|||||||
@ -102,7 +102,7 @@ static bool gpio_usb_uart_input_callback(InputEvent* event, void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
GpioUsbUart* gpio_usb_uart_alloc() {
 | 
					GpioUsbUart* gpio_usb_uart_alloc() {
 | 
				
			||||||
    GpioUsbUart* usb_uart = furi_alloc(sizeof(GpioUsbUart));
 | 
					    GpioUsbUart* usb_uart = malloc(sizeof(GpioUsbUart));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    usb_uart->view = view_alloc();
 | 
					    usb_uart->view = view_alloc();
 | 
				
			||||||
    view_allocate_model(usb_uart->view, ViewModelTypeLocking, sizeof(GpioUsbUartModel));
 | 
					    view_allocate_model(usb_uart->view, ViewModelTypeLocking, sizeof(GpioUsbUartModel));
 | 
				
			||||||
 | 
				
			|||||||
@ -15,7 +15,7 @@ const CanvasFontParameters canvas_font_params[FontTotalNumber] = {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Canvas* canvas_init() {
 | 
					Canvas* canvas_init() {
 | 
				
			||||||
    Canvas* canvas = furi_alloc(sizeof(Canvas));
 | 
					    Canvas* canvas = malloc(sizeof(Canvas));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    furi_hal_power_insomnia_enter();
 | 
					    furi_hal_power_insomnia_enter();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -27,18 +27,12 @@ typedef struct {
 | 
				
			|||||||
    const char* text;
 | 
					    const char* text;
 | 
				
			||||||
} ElementTextBoxLine;
 | 
					} ElementTextBoxLine;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void elements_progress_bar(
 | 
					void elements_progress_bar(Canvas* canvas, uint8_t x, uint8_t y, uint8_t width, float progress) {
 | 
				
			||||||
    Canvas* canvas,
 | 
					 | 
				
			||||||
    uint8_t x,
 | 
					 | 
				
			||||||
    uint8_t y,
 | 
					 | 
				
			||||||
    uint8_t width,
 | 
					 | 
				
			||||||
    uint8_t progress,
 | 
					 | 
				
			||||||
    uint8_t total) {
 | 
					 | 
				
			||||||
    furi_assert(canvas);
 | 
					    furi_assert(canvas);
 | 
				
			||||||
    furi_assert(total > 0);
 | 
					    furi_assert((progress >= 0) && (progress <= 1.0));
 | 
				
			||||||
    uint8_t height = 9;
 | 
					    uint8_t height = 9;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint8_t progress_length = roundf(((float)progress / total) * (width - 2));
 | 
					    uint8_t progress_length = roundf(progress * (width - 2));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    canvas_set_color(canvas, ColorWhite);
 | 
					    canvas_set_color(canvas, ColorWhite);
 | 
				
			||||||
    canvas_draw_box(canvas, x + 1, y + 1, width - 2, height - 2);
 | 
					    canvas_draw_box(canvas, x + 1, y + 1, width - 2, height - 2);
 | 
				
			||||||
 | 
				
			|||||||
@ -27,16 +27,9 @@ extern "C" {
 | 
				
			|||||||
 * @param   x           progress bar position on X axis
 | 
					 * @param   x           progress bar position on X axis
 | 
				
			||||||
 * @param   y           progress bar position on Y axis
 | 
					 * @param   y           progress bar position on Y axis
 | 
				
			||||||
 * @param   width       progress bar width
 | 
					 * @param   width       progress bar width
 | 
				
			||||||
 * @param   progress    progress in unnamed metric
 | 
					 * @param   progress    progress (0.0 - 1.0)
 | 
				
			||||||
 * @param   total       total amount in unnamed metric
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void elements_progress_bar(
 | 
					void elements_progress_bar(Canvas* canvas, uint8_t x, uint8_t y, uint8_t width, float progress);
 | 
				
			||||||
    Canvas* canvas,
 | 
					 | 
				
			||||||
    uint8_t x,
 | 
					 | 
				
			||||||
    uint8_t y,
 | 
					 | 
				
			||||||
    uint8_t width,
 | 
					 | 
				
			||||||
    uint8_t progress,
 | 
					 | 
				
			||||||
    uint8_t total);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Draw scrollbar on canvas at specific position.
 | 
					/** Draw scrollbar on canvas at specific position.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 | 
				
			|||||||
@ -417,7 +417,7 @@ void gui_set_lockdown(Gui* gui, bool lockdown) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Gui* gui_alloc() {
 | 
					Gui* gui_alloc() {
 | 
				
			||||||
    Gui* gui = furi_alloc(sizeof(Gui));
 | 
					    Gui* gui = malloc(sizeof(Gui));
 | 
				
			||||||
    // Thread ID
 | 
					    // Thread ID
 | 
				
			||||||
    gui->thread = osThreadGetId();
 | 
					    gui->thread = osThreadGetId();
 | 
				
			||||||
    // Allocate mutex
 | 
					    // Allocate mutex
 | 
				
			||||||
 | 
				
			|||||||
@ -5,7 +5,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
IconAnimation* icon_animation_alloc(const Icon* icon) {
 | 
					IconAnimation* icon_animation_alloc(const Icon* icon) {
 | 
				
			||||||
    furi_assert(icon);
 | 
					    furi_assert(icon);
 | 
				
			||||||
    IconAnimation* instance = furi_alloc(sizeof(IconAnimation));
 | 
					    IconAnimation* instance = malloc(sizeof(IconAnimation));
 | 
				
			||||||
    instance->icon = icon;
 | 
					    instance->icon = icon;
 | 
				
			||||||
    instance->timer = osTimerNew(icon_animation_timer_callback, osTimerPeriodic, instance, NULL);
 | 
					    instance->timer = osTimerNew(icon_animation_timer_callback, osTimerPeriodic, instance, NULL);
 | 
				
			||||||
    return instance;
 | 
					    return instance;
 | 
				
			||||||
 | 
				
			|||||||
@ -290,7 +290,7 @@ ButtonMenuItem* button_menu_add_item(
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ButtonMenu* button_menu_alloc(void) {
 | 
					ButtonMenu* button_menu_alloc(void) {
 | 
				
			||||||
    ButtonMenu* button_menu = furi_alloc(sizeof(ButtonMenu));
 | 
					    ButtonMenu* button_menu = malloc(sizeof(ButtonMenu));
 | 
				
			||||||
    button_menu->view = view_alloc();
 | 
					    button_menu->view = view_alloc();
 | 
				
			||||||
    view_set_orientation(button_menu->view, ViewOrientationVertical);
 | 
					    view_set_orientation(button_menu->view, ViewOrientationVertical);
 | 
				
			||||||
    view_set_context(button_menu->view, button_menu);
 | 
					    view_set_context(button_menu->view, button_menu);
 | 
				
			||||||
 | 
				
			|||||||
@ -40,8 +40,6 @@ ARRAY_DEF(ButtonMatrix, ButtonArray_t);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
struct ButtonPanel {
 | 
					struct ButtonPanel {
 | 
				
			||||||
    View* view;
 | 
					    View* view;
 | 
				
			||||||
    ButtonPanelInputCallback input_callback;
 | 
					 | 
				
			||||||
    void* input_context;
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
@ -51,8 +49,6 @@ typedef struct {
 | 
				
			|||||||
    uint16_t reserve_y;
 | 
					    uint16_t reserve_y;
 | 
				
			||||||
    uint16_t selected_item_x;
 | 
					    uint16_t selected_item_x;
 | 
				
			||||||
    uint16_t selected_item_y;
 | 
					    uint16_t selected_item_y;
 | 
				
			||||||
    ButtonPanelDrawCallback draw_callback;
 | 
					 | 
				
			||||||
    void* draw_context;
 | 
					 | 
				
			||||||
} ButtonPanelModel;
 | 
					} ButtonPanelModel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static ButtonItem** button_panel_get_item(ButtonPanelModel* model, size_t x, size_t y);
 | 
					static ButtonItem** button_panel_get_item(ButtonPanelModel* model, size_t x, size_t y);
 | 
				
			||||||
@ -65,14 +61,13 @@ static void button_panel_view_draw_callback(Canvas* canvas, void* _model);
 | 
				
			|||||||
static bool button_panel_view_input_callback(InputEvent* event, void* context);
 | 
					static bool button_panel_view_input_callback(InputEvent* event, void* context);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ButtonPanel* button_panel_alloc() {
 | 
					ButtonPanel* button_panel_alloc() {
 | 
				
			||||||
    ButtonPanel* button_panel = furi_alloc(sizeof(ButtonPanel));
 | 
					    ButtonPanel* button_panel = malloc(sizeof(ButtonPanel));
 | 
				
			||||||
    button_panel->view = view_alloc();
 | 
					    button_panel->view = view_alloc();
 | 
				
			||||||
    view_set_orientation(button_panel->view, ViewOrientationVertical);
 | 
					    view_set_orientation(button_panel->view, ViewOrientationVertical);
 | 
				
			||||||
    view_set_context(button_panel->view, button_panel);
 | 
					    view_set_context(button_panel->view, button_panel);
 | 
				
			||||||
    view_allocate_model(button_panel->view, ViewModelTypeLocking, sizeof(ButtonPanelModel));
 | 
					    view_allocate_model(button_panel->view, ViewModelTypeLocking, sizeof(ButtonPanelModel));
 | 
				
			||||||
    view_set_draw_callback(button_panel->view, button_panel_view_draw_callback);
 | 
					    view_set_draw_callback(button_panel->view, button_panel_view_draw_callback);
 | 
				
			||||||
    view_set_input_callback(button_panel->view, button_panel_view_input_callback);
 | 
					    view_set_input_callback(button_panel->view, button_panel_view_input_callback);
 | 
				
			||||||
    button_panel->input_callback = NULL;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with_view_model(
 | 
					    with_view_model(
 | 
				
			||||||
        button_panel->view, (ButtonPanelModel * model) {
 | 
					        button_panel->view, (ButtonPanelModel * model) {
 | 
				
			||||||
@ -80,7 +75,6 @@ ButtonPanel* button_panel_alloc() {
 | 
				
			|||||||
            model->reserve_y = 0;
 | 
					            model->reserve_y = 0;
 | 
				
			||||||
            model->selected_item_x = 0;
 | 
					            model->selected_item_x = 0;
 | 
				
			||||||
            model->selected_item_y = 0;
 | 
					            model->selected_item_y = 0;
 | 
				
			||||||
            model->draw_callback = NULL;
 | 
					 | 
				
			||||||
            ButtonMatrix_init(model->button_matrix);
 | 
					            ButtonMatrix_init(model->button_matrix);
 | 
				
			||||||
            LabelList_init(model->labels);
 | 
					            LabelList_init(model->labels);
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
@ -173,7 +167,7 @@ void button_panel_add_item(
 | 
				
			|||||||
            ButtonItem** button_item_ptr =
 | 
					            ButtonItem** button_item_ptr =
 | 
				
			||||||
                button_panel_get_item(model, matrix_place_x, matrix_place_y);
 | 
					                button_panel_get_item(model, matrix_place_x, matrix_place_y);
 | 
				
			||||||
            furi_check(*button_item_ptr == NULL);
 | 
					            furi_check(*button_item_ptr == NULL);
 | 
				
			||||||
            *button_item_ptr = furi_alloc(sizeof(ButtonItem));
 | 
					            *button_item_ptr = malloc(sizeof(ButtonItem));
 | 
				
			||||||
            ButtonItem* button_item = *button_item_ptr;
 | 
					            ButtonItem* button_item = *button_item_ptr;
 | 
				
			||||||
            button_item->callback = callback;
 | 
					            button_item->callback = callback;
 | 
				
			||||||
            button_item->callback_context = callback_context;
 | 
					            button_item->callback_context = callback_context;
 | 
				
			||||||
@ -216,8 +210,6 @@ static void button_panel_view_draw_callback(Canvas* canvas, void* _model) {
 | 
				
			|||||||
            canvas_set_font(canvas, label->font);
 | 
					            canvas_set_font(canvas, label->font);
 | 
				
			||||||
            canvas_draw_str(canvas, label->x, label->y, label->str);
 | 
					            canvas_draw_str(canvas, label->x, label->y, label->str);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    if(model->draw_callback) model->draw_callback(canvas, model->draw_context);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void button_panel_process_down(ButtonPanel* button_panel) {
 | 
					static void button_panel_process_down(ButtonPanel* button_panel) {
 | 
				
			||||||
@ -341,9 +333,7 @@ static bool button_panel_view_input_callback(InputEvent* event, void* context) {
 | 
				
			|||||||
    furi_assert(button_panel);
 | 
					    furi_assert(button_panel);
 | 
				
			||||||
    bool consumed = false;
 | 
					    bool consumed = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(button_panel->input_callback) {
 | 
					    if(event->type == InputTypeShort) {
 | 
				
			||||||
        consumed = button_panel->input_callback(event, button_panel->input_context);
 | 
					 | 
				
			||||||
    } else if(event->type == InputTypeShort) {
 | 
					 | 
				
			||||||
        switch(event->key) {
 | 
					        switch(event->key) {
 | 
				
			||||||
        case InputKeyUp:
 | 
					        case InputKeyUp:
 | 
				
			||||||
            consumed = true;
 | 
					            consumed = true;
 | 
				
			||||||
@ -391,23 +381,3 @@ void button_panel_add_label(
 | 
				
			|||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
void button_panel_set_popup_draw_callback(
 | 
					 | 
				
			||||||
    ButtonPanel* button_panel,
 | 
					 | 
				
			||||||
    ButtonPanelDrawCallback callback,
 | 
					 | 
				
			||||||
    void* context) {
 | 
					 | 
				
			||||||
    with_view_model(
 | 
					 | 
				
			||||||
        button_panel->view, (ButtonPanelModel * model) {
 | 
					 | 
				
			||||||
            model->draw_callback = callback;
 | 
					 | 
				
			||||||
            model->draw_context = context;
 | 
					 | 
				
			||||||
            return true;
 | 
					 | 
				
			||||||
        });
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void button_panel_set_popup_input_callback(
 | 
					 | 
				
			||||||
    ButtonPanel* button_panel,
 | 
					 | 
				
			||||||
    ButtonPanelInputCallback callback,
 | 
					 | 
				
			||||||
    void* context) {
 | 
					 | 
				
			||||||
    button_panel->input_context = context;
 | 
					 | 
				
			||||||
    button_panel->input_callback = callback;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
				
			|||||||
@ -17,12 +17,6 @@ typedef struct ButtonPanel ButtonPanel;
 | 
				
			|||||||
/** Callback type to call for handling selecting button_panel items */
 | 
					/** Callback type to call for handling selecting button_panel items */
 | 
				
			||||||
typedef void (*ButtonItemCallback)(void* context, uint32_t index);
 | 
					typedef void (*ButtonItemCallback)(void* context, uint32_t index);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Callback type for additional drawings above main button_panel screen */
 | 
					 | 
				
			||||||
typedef void (*ButtonPanelDrawCallback)(Canvas* canvas, void* _model);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** Callback type to intercept input events of button_panel */
 | 
					 | 
				
			||||||
typedef bool (*ButtonPanelInputCallback)(InputEvent* event, void* context);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** Allocate new button_panel module.
 | 
					/** Allocate new button_panel module.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @return     ButtonPanel instance
 | 
					 * @return     ButtonPanel instance
 | 
				
			||||||
@ -106,34 +100,6 @@ void button_panel_add_label(
 | 
				
			|||||||
    Font font,
 | 
					    Font font,
 | 
				
			||||||
    const char* label_str);
 | 
					    const char* label_str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO: [FL-1445] Have to replace callbacks above with additional popup-layer
 | 
					 | 
				
			||||||
/** Set popup draw callback for button_panel module.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Used to add popup drawings after main draw callback is done.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param      button_panel  ButtonPanel instance
 | 
					 | 
				
			||||||
 * @param      callback      callback function to set for draw event
 | 
					 | 
				
			||||||
 * @param      context       context to pass to callback
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
void button_panel_set_popup_draw_callback(
 | 
					 | 
				
			||||||
    ButtonPanel* button_panel,
 | 
					 | 
				
			||||||
    ButtonPanelDrawCallback callback,
 | 
					 | 
				
			||||||
    void* context);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** Set popup input callback for button_panel module.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Used to add popup input callback. It will intercept all input events for
 | 
					 | 
				
			||||||
 * current view.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @param      button_panel  ButtonPanel instance
 | 
					 | 
				
			||||||
 * @param      callback      function to overwrite main input callbacks
 | 
					 | 
				
			||||||
 * @param      context       context to pass to callback
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
void button_panel_set_popup_input_callback(
 | 
					 | 
				
			||||||
    ButtonPanel* button_panel,
 | 
					 | 
				
			||||||
    ButtonPanelInputCallback callback,
 | 
					 | 
				
			||||||
    void* context);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -695,7 +695,7 @@ static void byte_input_reset_model_input_data(ByteInputModel* model) {
 | 
				
			|||||||
 * @return ByteInput instance pointer
 | 
					 * @return ByteInput instance pointer
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
ByteInput* byte_input_alloc() {
 | 
					ByteInput* byte_input_alloc() {
 | 
				
			||||||
    ByteInput* byte_input = furi_alloc(sizeof(ByteInput));
 | 
					    ByteInput* byte_input = malloc(sizeof(ByteInput));
 | 
				
			||||||
    byte_input->view = view_alloc();
 | 
					    byte_input->view = view_alloc();
 | 
				
			||||||
    view_set_context(byte_input->view, byte_input);
 | 
					    view_set_context(byte_input->view, byte_input);
 | 
				
			||||||
    view_allocate_model(byte_input->view, ViewModelTypeLocking, sizeof(ByteInputModel));
 | 
					    view_allocate_model(byte_input->view, ViewModelTypeLocking, sizeof(ByteInputModel));
 | 
				
			||||||
 | 
				
			|||||||
@ -60,7 +60,7 @@ static bool dialog_view_input_callback(InputEvent* event, void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Dialog* dialog_alloc() {
 | 
					Dialog* dialog_alloc() {
 | 
				
			||||||
    Dialog* dialog = furi_alloc(sizeof(Dialog));
 | 
					    Dialog* dialog = malloc(sizeof(Dialog));
 | 
				
			||||||
    dialog->view = view_alloc();
 | 
					    dialog->view = view_alloc();
 | 
				
			||||||
    view_set_context(dialog->view, dialog);
 | 
					    view_set_context(dialog->view, dialog);
 | 
				
			||||||
    view_allocate_model(dialog->view, ViewModelTypeLockFree, sizeof(DialogModel));
 | 
					    view_allocate_model(dialog->view, ViewModelTypeLockFree, sizeof(DialogModel));
 | 
				
			||||||
 | 
				
			|||||||
@ -6,6 +6,7 @@ struct DialogEx {
 | 
				
			|||||||
    View* view;
 | 
					    View* view;
 | 
				
			||||||
    void* context;
 | 
					    void* context;
 | 
				
			||||||
    DialogExResultCallback callback;
 | 
					    DialogExResultCallback callback;
 | 
				
			||||||
 | 
					    bool enable_extended_events;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
@ -96,17 +97,44 @@ static bool dialog_ex_view_input_callback(InputEvent* event, void* context) {
 | 
				
			|||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Process key presses only
 | 
					    if(dialog_ex->callback) {
 | 
				
			||||||
    if(event->type == InputTypeShort && dialog_ex->callback) {
 | 
					        if(event->type == InputTypeShort) {
 | 
				
			||||||
        if(event->key == InputKeyLeft && left_text != NULL) {
 | 
					            if(event->key == InputKeyLeft && left_text != NULL) {
 | 
				
			||||||
            dialog_ex->callback(DialogExResultLeft, dialog_ex->context);
 | 
					                dialog_ex->callback(DialogExResultLeft, dialog_ex->context);
 | 
				
			||||||
            consumed = true;
 | 
					                consumed = true;
 | 
				
			||||||
        } else if(event->key == InputKeyOk && center_text != NULL) {
 | 
					            } else if(event->key == InputKeyOk && center_text != NULL) {
 | 
				
			||||||
            dialog_ex->callback(DialogExResultCenter, dialog_ex->context);
 | 
					                dialog_ex->callback(DialogExResultCenter, dialog_ex->context);
 | 
				
			||||||
            consumed = true;
 | 
					                consumed = true;
 | 
				
			||||||
        } else if(event->key == InputKeyRight && right_text != NULL) {
 | 
					            } else if(event->key == InputKeyRight && right_text != NULL) {
 | 
				
			||||||
            dialog_ex->callback(DialogExResultRight, dialog_ex->context);
 | 
					                dialog_ex->callback(DialogExResultRight, dialog_ex->context);
 | 
				
			||||||
            consumed = true;
 | 
					                consumed = true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(event->type == InputTypePress && dialog_ex->enable_extended_events) {
 | 
				
			||||||
 | 
					            if(event->key == InputKeyLeft && left_text != NULL) {
 | 
				
			||||||
 | 
					                dialog_ex->callback(DialogExPressLeft, dialog_ex->context);
 | 
				
			||||||
 | 
					                consumed = true;
 | 
				
			||||||
 | 
					            } else if(event->key == InputKeyOk && center_text != NULL) {
 | 
				
			||||||
 | 
					                dialog_ex->callback(DialogExPressCenter, dialog_ex->context);
 | 
				
			||||||
 | 
					                consumed = true;
 | 
				
			||||||
 | 
					            } else if(event->key == InputKeyRight && right_text != NULL) {
 | 
				
			||||||
 | 
					                dialog_ex->callback(DialogExPressRight, dialog_ex->context);
 | 
				
			||||||
 | 
					                consumed = true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if(event->type == InputTypeRelease && dialog_ex->enable_extended_events) {
 | 
				
			||||||
 | 
					            if(event->key == InputKeyLeft && left_text != NULL) {
 | 
				
			||||||
 | 
					                dialog_ex->callback(DialogExReleaseLeft, dialog_ex->context);
 | 
				
			||||||
 | 
					                consumed = true;
 | 
				
			||||||
 | 
					            } else if(event->key == InputKeyOk && center_text != NULL) {
 | 
				
			||||||
 | 
					                dialog_ex->callback(DialogExReleaseCenter, dialog_ex->context);
 | 
				
			||||||
 | 
					                consumed = true;
 | 
				
			||||||
 | 
					            } else if(event->key == InputKeyRight && right_text != NULL) {
 | 
				
			||||||
 | 
					                dialog_ex->callback(DialogExReleaseRight, dialog_ex->context);
 | 
				
			||||||
 | 
					                consumed = true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -114,7 +142,7 @@ static bool dialog_ex_view_input_callback(InputEvent* event, void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DialogEx* dialog_ex_alloc() {
 | 
					DialogEx* dialog_ex_alloc() {
 | 
				
			||||||
    DialogEx* dialog_ex = furi_alloc(sizeof(DialogEx));
 | 
					    DialogEx* dialog_ex = malloc(sizeof(DialogEx));
 | 
				
			||||||
    dialog_ex->view = view_alloc();
 | 
					    dialog_ex->view = view_alloc();
 | 
				
			||||||
    view_set_context(dialog_ex->view, dialog_ex);
 | 
					    view_set_context(dialog_ex->view, dialog_ex);
 | 
				
			||||||
    view_allocate_model(dialog_ex->view, ViewModelTypeLockFree, sizeof(DialogExModel));
 | 
					    view_allocate_model(dialog_ex->view, ViewModelTypeLockFree, sizeof(DialogExModel));
 | 
				
			||||||
@ -144,6 +172,7 @@ DialogEx* dialog_ex_alloc() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					    dialog_ex->enable_extended_events = false;
 | 
				
			||||||
    return dialog_ex;
 | 
					    return dialog_ex;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -262,3 +291,13 @@ void dialog_ex_reset(DialogEx* dialog_ex) {
 | 
				
			|||||||
    dialog_ex->context = NULL;
 | 
					    dialog_ex->context = NULL;
 | 
				
			||||||
    dialog_ex->callback = NULL;
 | 
					    dialog_ex->callback = NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void dialog_ex_enable_extended_events(DialogEx* dialog_ex) {
 | 
				
			||||||
 | 
					    furi_assert(dialog_ex);
 | 
				
			||||||
 | 
					    dialog_ex->enable_extended_events = true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void dialog_ex_disable_extended_events(DialogEx* dialog_ex) {
 | 
				
			||||||
 | 
					    furi_assert(dialog_ex);
 | 
				
			||||||
 | 
					    dialog_ex->enable_extended_events = false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -19,6 +19,12 @@ typedef enum {
 | 
				
			|||||||
    DialogExResultLeft,
 | 
					    DialogExResultLeft,
 | 
				
			||||||
    DialogExResultCenter,
 | 
					    DialogExResultCenter,
 | 
				
			||||||
    DialogExResultRight,
 | 
					    DialogExResultRight,
 | 
				
			||||||
 | 
					    DialogExPressLeft,
 | 
				
			||||||
 | 
					    DialogExPressCenter,
 | 
				
			||||||
 | 
					    DialogExPressRight,
 | 
				
			||||||
 | 
					    DialogExReleaseLeft,
 | 
				
			||||||
 | 
					    DialogExReleaseCenter,
 | 
				
			||||||
 | 
					    DialogExReleaseRight,
 | 
				
			||||||
} DialogExResult;
 | 
					} DialogExResult;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** DialogEx result callback type
 | 
					/** DialogEx result callback type
 | 
				
			||||||
@ -145,6 +151,18 @@ void dialog_ex_set_right_button_text(DialogEx* dialog_ex, const char* text);
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
void dialog_ex_reset(DialogEx* dialog_ex);
 | 
					void dialog_ex_reset(DialogEx* dialog_ex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Enable press/release events
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param      dialog_ex  DialogEx instance
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void dialog_ex_enable_extended_events(DialogEx* dialog_ex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Disable press/release events
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param      dialog_ex  DialogEx instance
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void dialog_ex_disable_extended_events(DialogEx* dialog_ex);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -14,7 +14,7 @@ static bool empty_screen_view_input_callback(InputEvent* event, void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
EmptyScreen* empty_screen_alloc() {
 | 
					EmptyScreen* empty_screen_alloc() {
 | 
				
			||||||
    EmptyScreen* empty_screen = furi_alloc(sizeof(EmptyScreen));
 | 
					    EmptyScreen* empty_screen = malloc(sizeof(EmptyScreen));
 | 
				
			||||||
    empty_screen->view = view_alloc();
 | 
					    empty_screen->view = view_alloc();
 | 
				
			||||||
    view_set_context(empty_screen->view, empty_screen);
 | 
					    view_set_context(empty_screen->view, empty_screen);
 | 
				
			||||||
    view_set_draw_callback(empty_screen->view, empty_screen_view_draw_callback);
 | 
					    view_set_draw_callback(empty_screen->view, empty_screen_view_draw_callback);
 | 
				
			||||||
 | 
				
			|||||||
@ -181,7 +181,7 @@ static bool file_select_init_inner(FileSelect* file_select) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
FileSelect* file_select_alloc() {
 | 
					FileSelect* file_select_alloc() {
 | 
				
			||||||
    FileSelect* file_select = furi_alloc(sizeof(FileSelect));
 | 
					    FileSelect* file_select = malloc(sizeof(FileSelect));
 | 
				
			||||||
    file_select->view = view_alloc();
 | 
					    file_select->view = view_alloc();
 | 
				
			||||||
    file_select->fs_api = furi_record_open("storage");
 | 
					    file_select->fs_api = furi_record_open("storage");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -278,7 +278,7 @@ bool file_select_fill_strings(FileSelect* file_select) {
 | 
				
			|||||||
    uint8_t string_counter = 0;
 | 
					    uint8_t string_counter = 0;
 | 
				
			||||||
    uint16_t file_counter = 0;
 | 
					    uint16_t file_counter = 0;
 | 
				
			||||||
    const uint8_t name_length = 100;
 | 
					    const uint8_t name_length = 100;
 | 
				
			||||||
    char* name = furi_alloc(name_length);
 | 
					    char* name = malloc(name_length);
 | 
				
			||||||
    uint16_t first_file_index = 0;
 | 
					    uint16_t first_file_index = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with_view_model(
 | 
					    with_view_model(
 | 
				
			||||||
@ -346,7 +346,7 @@ bool file_select_fill_count(FileSelect* file_select) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    uint16_t file_counter = 0;
 | 
					    uint16_t file_counter = 0;
 | 
				
			||||||
    const uint8_t name_length = 100;
 | 
					    const uint8_t name_length = 100;
 | 
				
			||||||
    char* name = furi_alloc(name_length);
 | 
					    char* name = malloc(name_length);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(!storage_dir_open(directory, file_select->path)) {
 | 
					    if(!storage_dir_open(directory, file_select->path)) {
 | 
				
			||||||
        storage_dir_close(directory);
 | 
					        storage_dir_close(directory);
 | 
				
			||||||
@ -397,7 +397,7 @@ void file_select_set_selected_file_internal(FileSelect* file_select, const char*
 | 
				
			|||||||
    File* directory = storage_file_alloc(file_select->fs_api);
 | 
					    File* directory = storage_file_alloc(file_select->fs_api);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const uint8_t name_length = 100;
 | 
					    const uint8_t name_length = 100;
 | 
				
			||||||
    char* name = furi_alloc(name_length);
 | 
					    char* name = malloc(name_length);
 | 
				
			||||||
    uint16_t file_position = 0;
 | 
					    uint16_t file_position = 0;
 | 
				
			||||||
    bool file_found = false;
 | 
					    bool file_found = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										94
									
								
								applications/gui/modules/loading.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								applications/gui/modules/loading.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,94 @@
 | 
				
			|||||||
 | 
					#include <stdint.h>
 | 
				
			||||||
 | 
					#include <furi.h>
 | 
				
			||||||
 | 
					#include <assets_icons.h>
 | 
				
			||||||
 | 
					#include <gui/icon_animation.h>
 | 
				
			||||||
 | 
					#include <gui/elements.h>
 | 
				
			||||||
 | 
					#include <gui/canvas.h>
 | 
				
			||||||
 | 
					#include <gui/view.h>
 | 
				
			||||||
 | 
					#include <input/input.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "loading.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct Loading {
 | 
				
			||||||
 | 
					    View* view;
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					    IconAnimation* icon;
 | 
				
			||||||
 | 
					} LoadingModel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void loading_draw_callback(Canvas* canvas, void* _model) {
 | 
				
			||||||
 | 
					    LoadingModel* model = (LoadingModel*)_model;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint8_t x = 7;
 | 
				
			||||||
 | 
					    uint8_t y = 40;
 | 
				
			||||||
 | 
					    uint8_t width = 49;
 | 
				
			||||||
 | 
					    uint8_t height = 47;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    elements_bold_rounded_frame(canvas, x, y, width, height);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    canvas_set_font(canvas, FontSecondary);
 | 
				
			||||||
 | 
					    elements_multiline_text(canvas, x + 7, y + 13, "Loading...");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    canvas_draw_icon_animation(canvas, x + 13, y + 19, model->icon);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static bool loading_input_callback(InputEvent* event, void* context) {
 | 
				
			||||||
 | 
					    furi_assert(context);
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void loading_enter_callback(void* context) {
 | 
				
			||||||
 | 
					    furi_assert(context);
 | 
				
			||||||
 | 
					    Loading* instance = context;
 | 
				
			||||||
 | 
					    LoadingModel* model = view_get_model(instance->view);
 | 
				
			||||||
 | 
					    /* using Loading View in conjunction with several
 | 
				
			||||||
 | 
					     * Stack View obligates to reassign
 | 
				
			||||||
 | 
					     * Update callback, as it can be rewritten
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    view_tie_icon_animation(instance->view, model->icon);
 | 
				
			||||||
 | 
					    icon_animation_start(model->icon);
 | 
				
			||||||
 | 
					    view_commit_model(instance->view, false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void loading_exit_callback(void* context) {
 | 
				
			||||||
 | 
					    furi_assert(context);
 | 
				
			||||||
 | 
					    Loading* instance = context;
 | 
				
			||||||
 | 
					    LoadingModel* model = view_get_model(instance->view);
 | 
				
			||||||
 | 
					    icon_animation_stop(model->icon);
 | 
				
			||||||
 | 
					    view_commit_model(instance->view, false);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Loading* loading_alloc(void) {
 | 
				
			||||||
 | 
					    Loading* instance = malloc(sizeof(Loading));
 | 
				
			||||||
 | 
					    instance->view = view_alloc();
 | 
				
			||||||
 | 
					    view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(LoadingModel));
 | 
				
			||||||
 | 
					    LoadingModel* model = view_get_model(instance->view);
 | 
				
			||||||
 | 
					    model->icon = icon_animation_alloc(&A_Loading_24);
 | 
				
			||||||
 | 
					    view_tie_icon_animation(instance->view, model->icon);
 | 
				
			||||||
 | 
					    view_commit_model(instance->view, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    view_set_context(instance->view, instance);
 | 
				
			||||||
 | 
					    view_set_draw_callback(instance->view, loading_draw_callback);
 | 
				
			||||||
 | 
					    view_set_input_callback(instance->view, loading_input_callback);
 | 
				
			||||||
 | 
					    view_set_enter_callback(instance->view, loading_enter_callback);
 | 
				
			||||||
 | 
					    view_set_exit_callback(instance->view, loading_exit_callback);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return instance;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void loading_free(Loading* instance) {
 | 
				
			||||||
 | 
					    LoadingModel* model = view_get_model(instance->view);
 | 
				
			||||||
 | 
					    icon_animation_free(model->icon);
 | 
				
			||||||
 | 
					    view_commit_model(instance->view, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    furi_assert(instance);
 | 
				
			||||||
 | 
					    view_free(instance->view);
 | 
				
			||||||
 | 
					    free(instance);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					View* loading_get_view(Loading* instance) {
 | 
				
			||||||
 | 
					    furi_assert(instance);
 | 
				
			||||||
 | 
					    furi_assert(instance->view);
 | 
				
			||||||
 | 
					    return instance->view;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										35
									
								
								applications/gui/modules/loading.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								applications/gui/modules/loading.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					#pragma once
 | 
				
			||||||
 | 
					#include <gui/view.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Loading anonymous structure */
 | 
				
			||||||
 | 
					typedef struct Loading Loading;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Allocate and initialize
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This View used to show system is doing some processing
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return     Loading View instance
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					Loading* loading_alloc();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Deinitialize and free Loading View
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param      instance  Loading instance
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void loading_free(Loading* instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Get Loading view
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param      instance  Loading instance
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return     View instance that can be used for embedding
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					View* loading_get_view(Loading* instance);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
@ -125,7 +125,7 @@ static void menu_exit(void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Menu* menu_alloc() {
 | 
					Menu* menu_alloc() {
 | 
				
			||||||
    Menu* menu = furi_alloc(sizeof(Menu));
 | 
					    Menu* menu = malloc(sizeof(Menu));
 | 
				
			||||||
    menu->view = view_alloc(menu->view);
 | 
					    menu->view = view_alloc(menu->view);
 | 
				
			||||||
    view_set_context(menu->view, menu);
 | 
					    view_set_context(menu->view, menu);
 | 
				
			||||||
    view_allocate_model(menu->view, ViewModelTypeLocking, sizeof(MenuModel));
 | 
					    view_allocate_model(menu->view, ViewModelTypeLocking, sizeof(MenuModel));
 | 
				
			||||||
 | 
				
			|||||||
@ -108,7 +108,7 @@ void popup_stop_timer(void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Popup* popup_alloc() {
 | 
					Popup* popup_alloc() {
 | 
				
			||||||
    Popup* popup = furi_alloc(sizeof(Popup));
 | 
					    Popup* popup = malloc(sizeof(Popup));
 | 
				
			||||||
    popup->view = view_alloc();
 | 
					    popup->view = view_alloc();
 | 
				
			||||||
    popup->timer = osTimerNew(popup_timer_callback, osTimerOnce, popup, NULL);
 | 
					    popup->timer = osTimerNew(popup_timer_callback, osTimerOnce, popup, NULL);
 | 
				
			||||||
    furi_assert(popup->timer);
 | 
					    furi_assert(popup->timer);
 | 
				
			||||||
 | 
				
			|||||||
@ -120,7 +120,7 @@ static bool submenu_view_input_callback(InputEvent* event, void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Submenu* submenu_alloc() {
 | 
					Submenu* submenu_alloc() {
 | 
				
			||||||
    Submenu* submenu = furi_alloc(sizeof(Submenu));
 | 
					    Submenu* submenu = malloc(sizeof(Submenu));
 | 
				
			||||||
    submenu->view = view_alloc();
 | 
					    submenu->view = view_alloc();
 | 
				
			||||||
    view_set_context(submenu->view, submenu);
 | 
					    view_set_context(submenu->view, submenu);
 | 
				
			||||||
    view_allocate_model(submenu->view, ViewModelTypeLocking, sizeof(SubmenuModel));
 | 
					    view_allocate_model(submenu->view, ViewModelTypeLocking, sizeof(SubmenuModel));
 | 
				
			||||||
 | 
				
			|||||||
@ -128,7 +128,7 @@ static bool text_box_view_input_callback(InputEvent* event, void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TextBox* text_box_alloc() {
 | 
					TextBox* text_box_alloc() {
 | 
				
			||||||
    TextBox* text_box = furi_alloc(sizeof(TextBox));
 | 
					    TextBox* text_box = malloc(sizeof(TextBox));
 | 
				
			||||||
    text_box->view = view_alloc();
 | 
					    text_box->view = view_alloc();
 | 
				
			||||||
    view_set_context(text_box->view, text_box);
 | 
					    view_set_context(text_box->view, text_box);
 | 
				
			||||||
    view_allocate_model(text_box->view, ViewModelTypeLocking, sizeof(TextBoxModel));
 | 
					    view_allocate_model(text_box->view, ViewModelTypeLocking, sizeof(TextBoxModel));
 | 
				
			||||||
 | 
				
			|||||||
@ -410,7 +410,7 @@ void text_input_timer_callback(void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
TextInput* text_input_alloc() {
 | 
					TextInput* text_input_alloc() {
 | 
				
			||||||
    TextInput* text_input = furi_alloc(sizeof(TextInput));
 | 
					    TextInput* text_input = malloc(sizeof(TextInput));
 | 
				
			||||||
    text_input->view = view_alloc();
 | 
					    text_input->view = view_alloc();
 | 
				
			||||||
    view_set_context(text_input->view, text_input);
 | 
					    view_set_context(text_input->view, text_input);
 | 
				
			||||||
    view_allocate_model(text_input->view, ViewModelTypeLocking, sizeof(TextInputModel));
 | 
					    view_allocate_model(text_input->view, ViewModelTypeLocking, sizeof(TextInputModel));
 | 
				
			||||||
 | 
				
			|||||||
@ -28,7 +28,7 @@ bool validator_is_file_callback(const char* text, string_t error, void* context)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
ValidatorIsFile*
 | 
					ValidatorIsFile*
 | 
				
			||||||
    validator_is_file_alloc_init(const char* app_path_folder, const char* app_extension) {
 | 
					    validator_is_file_alloc_init(const char* app_path_folder, const char* app_extension) {
 | 
				
			||||||
    ValidatorIsFile* instance = furi_alloc(sizeof(ValidatorIsFile));
 | 
					    ValidatorIsFile* instance = malloc(sizeof(ValidatorIsFile));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    instance->app_path_folder = app_path_folder;
 | 
					    instance->app_path_folder = app_path_folder;
 | 
				
			||||||
    instance->app_extension = app_extension;
 | 
					    instance->app_extension = app_extension;
 | 
				
			||||||
 | 
				
			|||||||
@ -276,7 +276,7 @@ void variable_item_list_process_ok(VariableItemList* variable_item_list) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
VariableItemList* variable_item_list_alloc() {
 | 
					VariableItemList* variable_item_list_alloc() {
 | 
				
			||||||
    VariableItemList* variable_item_list = furi_alloc(sizeof(VariableItemList));
 | 
					    VariableItemList* variable_item_list = malloc(sizeof(VariableItemList));
 | 
				
			||||||
    variable_item_list->view = view_alloc();
 | 
					    variable_item_list->view = view_alloc();
 | 
				
			||||||
    view_set_context(variable_item_list->view, variable_item_list);
 | 
					    view_set_context(variable_item_list->view, variable_item_list);
 | 
				
			||||||
    view_allocate_model(
 | 
					    view_allocate_model(
 | 
				
			||||||
 | 
				
			|||||||
@ -52,7 +52,7 @@ static bool gui_widget_view_input_callback(InputEvent* event, void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Widget* widget_alloc() {
 | 
					Widget* widget_alloc() {
 | 
				
			||||||
    Widget* widget = furi_alloc(sizeof(Widget));
 | 
					    Widget* widget = malloc(sizeof(Widget));
 | 
				
			||||||
    widget->view = view_alloc();
 | 
					    widget->view = view_alloc();
 | 
				
			||||||
    view_set_context(widget->view, widget);
 | 
					    view_set_context(widget->view, widget);
 | 
				
			||||||
    view_allocate_model(widget->view, ViewModelTypeLocking, sizeof(GuiWidgetModel));
 | 
					    view_allocate_model(widget->view, ViewModelTypeLocking, sizeof(GuiWidgetModel));
 | 
				
			||||||
 | 
				
			|||||||
@ -61,14 +61,14 @@ WidgetElement* widget_element_button_create(
 | 
				
			|||||||
    ButtonCallback callback,
 | 
					    ButtonCallback callback,
 | 
				
			||||||
    void* context) {
 | 
					    void* context) {
 | 
				
			||||||
    // Allocate and init model
 | 
					    // Allocate and init model
 | 
				
			||||||
    GuiButtonModel* model = furi_alloc(sizeof(GuiButtonModel));
 | 
					    GuiButtonModel* model = malloc(sizeof(GuiButtonModel));
 | 
				
			||||||
    model->button_type = button_type;
 | 
					    model->button_type = button_type;
 | 
				
			||||||
    model->callback = callback;
 | 
					    model->callback = callback;
 | 
				
			||||||
    model->context = context;
 | 
					    model->context = context;
 | 
				
			||||||
    string_init_set_str(model->text, text);
 | 
					    string_init_set_str(model->text, text);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Allocate and init Element
 | 
					    // Allocate and init Element
 | 
				
			||||||
    WidgetElement* gui_button = furi_alloc(sizeof(WidgetElement));
 | 
					    WidgetElement* gui_button = malloc(sizeof(WidgetElement));
 | 
				
			||||||
    gui_button->parent = NULL;
 | 
					    gui_button->parent = NULL;
 | 
				
			||||||
    gui_button->input = gui_button_input;
 | 
					    gui_button->input = gui_button_input;
 | 
				
			||||||
    gui_button->draw = gui_button_draw;
 | 
					    gui_button->draw = gui_button_draw;
 | 
				
			||||||
 | 
				
			|||||||
@ -29,7 +29,7 @@ WidgetElement* widget_element_frame_create(
 | 
				
			|||||||
    uint8_t height,
 | 
					    uint8_t height,
 | 
				
			||||||
    uint8_t radius) {
 | 
					    uint8_t radius) {
 | 
				
			||||||
    // Allocate and init model
 | 
					    // Allocate and init model
 | 
				
			||||||
    GuiFrameModel* model = furi_alloc(sizeof(GuiFrameModel));
 | 
					    GuiFrameModel* model = malloc(sizeof(GuiFrameModel));
 | 
				
			||||||
    model->x = x;
 | 
					    model->x = x;
 | 
				
			||||||
    model->y = y;
 | 
					    model->y = y;
 | 
				
			||||||
    model->width = width;
 | 
					    model->width = width;
 | 
				
			||||||
@ -37,7 +37,7 @@ WidgetElement* widget_element_frame_create(
 | 
				
			|||||||
    model->radius = radius;
 | 
					    model->radius = radius;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Allocate and init Element
 | 
					    // Allocate and init Element
 | 
				
			||||||
    WidgetElement* gui_frame = furi_alloc(sizeof(WidgetElement));
 | 
					    WidgetElement* gui_frame = malloc(sizeof(WidgetElement));
 | 
				
			||||||
    gui_frame->parent = NULL;
 | 
					    gui_frame->parent = NULL;
 | 
				
			||||||
    gui_frame->input = NULL;
 | 
					    gui_frame->input = NULL;
 | 
				
			||||||
    gui_frame->draw = gui_frame_draw;
 | 
					    gui_frame->draw = gui_frame_draw;
 | 
				
			||||||
 | 
				
			|||||||
@ -27,13 +27,13 @@ WidgetElement* widget_element_icon_create(uint8_t x, uint8_t y, const Icon* icon
 | 
				
			|||||||
    furi_assert(icon);
 | 
					    furi_assert(icon);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Allocate and init model
 | 
					    // Allocate and init model
 | 
				
			||||||
    GuiIconModel* model = furi_alloc(sizeof(GuiIconModel));
 | 
					    GuiIconModel* model = malloc(sizeof(GuiIconModel));
 | 
				
			||||||
    model->x = x;
 | 
					    model->x = x;
 | 
				
			||||||
    model->y = y;
 | 
					    model->y = y;
 | 
				
			||||||
    model->icon = icon;
 | 
					    model->icon = icon;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Allocate and init Element
 | 
					    // Allocate and init Element
 | 
				
			||||||
    WidgetElement* gui_icon = furi_alloc(sizeof(WidgetElement));
 | 
					    WidgetElement* gui_icon = malloc(sizeof(WidgetElement));
 | 
				
			||||||
    gui_icon->parent = NULL;
 | 
					    gui_icon->parent = NULL;
 | 
				
			||||||
    gui_icon->input = NULL;
 | 
					    gui_icon->input = NULL;
 | 
				
			||||||
    gui_icon->draw = gui_icon_draw;
 | 
					    gui_icon->draw = gui_icon_draw;
 | 
				
			||||||
 | 
				
			|||||||
@ -46,7 +46,7 @@ WidgetElement* widget_element_string_create(
 | 
				
			|||||||
    furi_assert(text);
 | 
					    furi_assert(text);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Allocate and init model
 | 
					    // Allocate and init model
 | 
				
			||||||
    GuiStringModel* model = furi_alloc(sizeof(GuiStringModel));
 | 
					    GuiStringModel* model = malloc(sizeof(GuiStringModel));
 | 
				
			||||||
    model->x = x;
 | 
					    model->x = x;
 | 
				
			||||||
    model->y = y;
 | 
					    model->y = y;
 | 
				
			||||||
    model->horizontal = horizontal;
 | 
					    model->horizontal = horizontal;
 | 
				
			||||||
@ -55,7 +55,7 @@ WidgetElement* widget_element_string_create(
 | 
				
			|||||||
    string_init_set_str(model->text, text);
 | 
					    string_init_set_str(model->text, text);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Allocate and init Element
 | 
					    // Allocate and init Element
 | 
				
			||||||
    WidgetElement* gui_string = furi_alloc(sizeof(WidgetElement));
 | 
					    WidgetElement* gui_string = malloc(sizeof(WidgetElement));
 | 
				
			||||||
    gui_string->parent = NULL;
 | 
					    gui_string->parent = NULL;
 | 
				
			||||||
    gui_string->input = NULL;
 | 
					    gui_string->input = NULL;
 | 
				
			||||||
    gui_string->draw = gui_string_draw;
 | 
					    gui_string->draw = gui_string_draw;
 | 
				
			||||||
 | 
				
			|||||||
@ -47,7 +47,7 @@ WidgetElement* widget_element_string_multiline_create(
 | 
				
			|||||||
    furi_assert(text);
 | 
					    furi_assert(text);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Allocate and init model
 | 
					    // Allocate and init model
 | 
				
			||||||
    GuiStringMultiLineModel* model = furi_alloc(sizeof(GuiStringMultiLineModel));
 | 
					    GuiStringMultiLineModel* model = malloc(sizeof(GuiStringMultiLineModel));
 | 
				
			||||||
    model->x = x;
 | 
					    model->x = x;
 | 
				
			||||||
    model->y = y;
 | 
					    model->y = y;
 | 
				
			||||||
    model->horizontal = horizontal;
 | 
					    model->horizontal = horizontal;
 | 
				
			||||||
@ -56,7 +56,7 @@ WidgetElement* widget_element_string_multiline_create(
 | 
				
			|||||||
    string_init_set_str(model->text, text);
 | 
					    string_init_set_str(model->text, text);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Allocate and init Element
 | 
					    // Allocate and init Element
 | 
				
			||||||
    WidgetElement* gui_string = furi_alloc(sizeof(WidgetElement));
 | 
					    WidgetElement* gui_string = malloc(sizeof(WidgetElement));
 | 
				
			||||||
    gui_string->parent = NULL;
 | 
					    gui_string->parent = NULL;
 | 
				
			||||||
    gui_string->input = NULL;
 | 
					    gui_string->input = NULL;
 | 
				
			||||||
    gui_string->draw = gui_string_multiline_draw;
 | 
					    gui_string->draw = gui_string_multiline_draw;
 | 
				
			||||||
 | 
				
			|||||||
@ -50,7 +50,7 @@ WidgetElement* widget_element_text_box_create(
 | 
				
			|||||||
    furi_assert(text);
 | 
					    furi_assert(text);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Allocate and init model
 | 
					    // Allocate and init model
 | 
				
			||||||
    GuiTextBoxModel* model = furi_alloc(sizeof(GuiTextBoxModel));
 | 
					    GuiTextBoxModel* model = malloc(sizeof(GuiTextBoxModel));
 | 
				
			||||||
    model->x = x;
 | 
					    model->x = x;
 | 
				
			||||||
    model->y = y;
 | 
					    model->y = y;
 | 
				
			||||||
    model->width = width;
 | 
					    model->width = width;
 | 
				
			||||||
@ -60,7 +60,7 @@ WidgetElement* widget_element_text_box_create(
 | 
				
			|||||||
    string_init_set_str(model->text, text);
 | 
					    string_init_set_str(model->text, text);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Allocate and init Element
 | 
					    // Allocate and init Element
 | 
				
			||||||
    WidgetElement* gui_string = furi_alloc(sizeof(WidgetElement));
 | 
					    WidgetElement* gui_string = malloc(sizeof(WidgetElement));
 | 
				
			||||||
    gui_string->parent = NULL;
 | 
					    gui_string->parent = NULL;
 | 
				
			||||||
    gui_string->input = NULL;
 | 
					    gui_string->input = NULL;
 | 
				
			||||||
    gui_string->draw = gui_text_box_draw;
 | 
					    gui_string->draw = gui_text_box_draw;
 | 
				
			||||||
 | 
				
			|||||||
@ -4,12 +4,12 @@
 | 
				
			|||||||
SceneManager* scene_manager_alloc(const SceneManagerHandlers* app_scene_handlers, void* context) {
 | 
					SceneManager* scene_manager_alloc(const SceneManagerHandlers* app_scene_handlers, void* context) {
 | 
				
			||||||
    furi_assert(context);
 | 
					    furi_assert(context);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    SceneManager* scene_manager = furi_alloc(sizeof(SceneManager));
 | 
					    SceneManager* scene_manager = malloc(sizeof(SceneManager));
 | 
				
			||||||
    // Set SceneManager context and scene handlers
 | 
					    // Set SceneManager context and scene handlers
 | 
				
			||||||
    scene_manager->context = context;
 | 
					    scene_manager->context = context;
 | 
				
			||||||
    scene_manager->scene_handlers = app_scene_handlers;
 | 
					    scene_manager->scene_handlers = app_scene_handlers;
 | 
				
			||||||
    // Allocate all scenes
 | 
					    // Allocate all scenes
 | 
				
			||||||
    scene_manager->scene = furi_alloc(sizeof(AppScene) * app_scene_handlers->scene_num);
 | 
					    scene_manager->scene = malloc(sizeof(AppScene) * app_scene_handlers->scene_num);
 | 
				
			||||||
    // Initialize ScaneManager array for navigation
 | 
					    // Initialize ScaneManager array for navigation
 | 
				
			||||||
    SceneManagerIdStack_init(scene_manager->scene_id_stack);
 | 
					    SceneManagerIdStack_init(scene_manager->scene_id_stack);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -48,9 +48,16 @@ bool scene_manager_handle_custom_event(SceneManager* scene_manager, uint32_t cus
 | 
				
			|||||||
        .type = SceneManagerEventTypeCustom,
 | 
					        .type = SceneManagerEventTypeCustom,
 | 
				
			||||||
        .event = custom_event,
 | 
					        .event = custom_event,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    uint32_t scene_id = *SceneManagerIdStack_back(scene_manager->scene_id_stack);
 | 
					
 | 
				
			||||||
    return scene_manager->scene_handlers->on_event_handlers[scene_id](
 | 
					    bool result = false;
 | 
				
			||||||
        scene_manager->context, event);
 | 
					    if(SceneManagerIdStack_size(scene_manager->scene_id_stack) > 0) {
 | 
				
			||||||
 | 
					        uint32_t* scene_id_p = SceneManagerIdStack_back(scene_manager->scene_id_stack);
 | 
				
			||||||
 | 
					        uint32_t scene_id = *scene_id_p;
 | 
				
			||||||
 | 
					        result = scene_manager->scene_handlers->on_event_handlers[scene_id](
 | 
				
			||||||
 | 
					            scene_manager->context, event);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool scene_manager_handle_back_event(SceneManager* scene_manager) {
 | 
					bool scene_manager_handle_back_event(SceneManager* scene_manager) {
 | 
				
			||||||
@ -59,9 +66,15 @@ bool scene_manager_handle_back_event(SceneManager* scene_manager) {
 | 
				
			|||||||
    SceneManagerEvent event = {
 | 
					    SceneManagerEvent event = {
 | 
				
			||||||
        .type = SceneManagerEventTypeBack,
 | 
					        .type = SceneManagerEventTypeBack,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    uint32_t scene_id = *SceneManagerIdStack_back(scene_manager->scene_id_stack);
 | 
					
 | 
				
			||||||
    bool consumed =
 | 
					    bool consumed = false;
 | 
				
			||||||
        scene_manager->scene_handlers->on_event_handlers[scene_id](scene_manager->context, event);
 | 
					    if(SceneManagerIdStack_size(scene_manager->scene_id_stack) > 0) {
 | 
				
			||||||
 | 
					        uint32_t* scene_id_p = SceneManagerIdStack_back(scene_manager->scene_id_stack);
 | 
				
			||||||
 | 
					        uint32_t scene_id = *scene_id_p;
 | 
				
			||||||
 | 
					        consumed = scene_manager->scene_handlers->on_event_handlers[scene_id](
 | 
				
			||||||
 | 
					            scene_manager->context, event);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(!consumed) {
 | 
					    if(!consumed) {
 | 
				
			||||||
        consumed = scene_manager_previous_scene(scene_manager);
 | 
					        consumed = scene_manager_previous_scene(scene_manager);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -74,8 +87,12 @@ void scene_manager_handle_tick_event(SceneManager* scene_manager) {
 | 
				
			|||||||
    SceneManagerEvent event = {
 | 
					    SceneManagerEvent event = {
 | 
				
			||||||
        .type = SceneManagerEventTypeTick,
 | 
					        .type = SceneManagerEventTypeTick,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    uint32_t scene_id = *SceneManagerIdStack_back(scene_manager->scene_id_stack);
 | 
					
 | 
				
			||||||
    scene_manager->scene_handlers->on_event_handlers[scene_id](scene_manager->context, event);
 | 
					    if(SceneManagerIdStack_size(scene_manager->scene_id_stack) > 0) {
 | 
				
			||||||
 | 
					        uint32_t* scene_id_p = SceneManagerIdStack_back(scene_manager->scene_id_stack);
 | 
				
			||||||
 | 
					        uint32_t scene_id = *scene_id_p;
 | 
				
			||||||
 | 
					        scene_manager->scene_handlers->on_event_handlers[scene_id](scene_manager->context, event);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void scene_manager_next_scene(SceneManager* scene_manager, uint32_t next_scene_id) {
 | 
					void scene_manager_next_scene(SceneManager* scene_manager, uint32_t next_scene_id) {
 | 
				
			||||||
@ -83,7 +100,7 @@ void scene_manager_next_scene(SceneManager* scene_manager, uint32_t next_scene_i
 | 
				
			|||||||
    furi_assert(next_scene_id < scene_manager->scene_handlers->scene_num);
 | 
					    furi_assert(next_scene_id < scene_manager->scene_handlers->scene_num);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Check if it is not the first scene
 | 
					    // Check if it is not the first scene
 | 
				
			||||||
    if(SceneManagerIdStack_size(scene_manager->scene_id_stack)) {
 | 
					    if(SceneManagerIdStack_size(scene_manager->scene_id_stack) > 0) {
 | 
				
			||||||
        uint32_t cur_scene_id = *SceneManagerIdStack_back(scene_manager->scene_id_stack);
 | 
					        uint32_t cur_scene_id = *SceneManagerIdStack_back(scene_manager->scene_id_stack);
 | 
				
			||||||
        scene_manager->scene_handlers->on_exit_handlers[cur_scene_id](scene_manager->context);
 | 
					        scene_manager->scene_handlers->on_exit_handlers[cur_scene_id](scene_manager->context);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -95,18 +112,22 @@ void scene_manager_next_scene(SceneManager* scene_manager, uint32_t next_scene_i
 | 
				
			|||||||
bool scene_manager_previous_scene(SceneManager* scene_manager) {
 | 
					bool scene_manager_previous_scene(SceneManager* scene_manager) {
 | 
				
			||||||
    furi_assert(scene_manager);
 | 
					    furi_assert(scene_manager);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint32_t cur_scene_id = 0;
 | 
					    if(SceneManagerIdStack_size(scene_manager->scene_id_stack) > 0) {
 | 
				
			||||||
    SceneManagerIdStack_pop_back(&cur_scene_id, scene_manager->scene_id_stack);
 | 
					        uint32_t cur_scene_id = 0;
 | 
				
			||||||
 | 
					        SceneManagerIdStack_pop_back(&cur_scene_id, scene_manager->scene_id_stack);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Handle exit from start scene separately
 | 
					        // Handle exit from start scene separately
 | 
				
			||||||
    if(SceneManagerIdStack_size(scene_manager->scene_id_stack) == 0) {
 | 
					        if(SceneManagerIdStack_size(scene_manager->scene_id_stack) == 0) {
 | 
				
			||||||
 | 
					            scene_manager->scene_handlers->on_exit_handlers[cur_scene_id](scene_manager->context);
 | 
				
			||||||
 | 
					            return false;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        uint32_t prev_scene_id = *SceneManagerIdStack_back(scene_manager->scene_id_stack);
 | 
				
			||||||
        scene_manager->scene_handlers->on_exit_handlers[cur_scene_id](scene_manager->context);
 | 
					        scene_manager->scene_handlers->on_exit_handlers[cur_scene_id](scene_manager->context);
 | 
				
			||||||
 | 
					        scene_manager->scene_handlers->on_enter_handlers[prev_scene_id](scene_manager->context);
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    uint32_t prev_scene_id = *SceneManagerIdStack_back(scene_manager->scene_id_stack);
 | 
					 | 
				
			||||||
    scene_manager->scene_handlers->on_exit_handlers[cur_scene_id](scene_manager->context);
 | 
					 | 
				
			||||||
    scene_manager->scene_handlers->on_enter_handlers[prev_scene_id](scene_manager->context);
 | 
					 | 
				
			||||||
    return true;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool scene_manager_search_and_switch_to_previous_scene(
 | 
					bool scene_manager_search_and_switch_to_previous_scene(
 | 
				
			||||||
@ -114,48 +135,55 @@ bool scene_manager_search_and_switch_to_previous_scene(
 | 
				
			|||||||
    uint32_t scene_id) {
 | 
					    uint32_t scene_id) {
 | 
				
			||||||
    furi_assert(scene_manager);
 | 
					    furi_assert(scene_manager);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint32_t prev_scene_id = 0;
 | 
					    if(SceneManagerIdStack_size(scene_manager->scene_id_stack) > 0) {
 | 
				
			||||||
    uint32_t cur_scene_id = *SceneManagerIdStack_back(scene_manager->scene_id_stack);
 | 
					        uint32_t prev_scene_id = 0;
 | 
				
			||||||
    SceneManagerIdStack_it_t scene_it;
 | 
					        uint32_t cur_scene_id = *SceneManagerIdStack_back(scene_manager->scene_id_stack);
 | 
				
			||||||
    SceneManagerIdStack_it_last(scene_it, scene_manager->scene_id_stack);
 | 
					        SceneManagerIdStack_it_t scene_it;
 | 
				
			||||||
    // Search scene with given id in navigation stack
 | 
					        SceneManagerIdStack_it_last(scene_it, scene_manager->scene_id_stack);
 | 
				
			||||||
    bool scene_found = false;
 | 
					        // Search scene with given id in navigation stack
 | 
				
			||||||
    while(!scene_found) {
 | 
					        bool scene_found = false;
 | 
				
			||||||
        SceneManagerIdStack_previous(scene_it);
 | 
					        while(!scene_found) {
 | 
				
			||||||
        if(SceneManagerIdStack_end_p(scene_it)) {
 | 
					            SceneManagerIdStack_previous(scene_it);
 | 
				
			||||||
            return false;
 | 
					            if(SceneManagerIdStack_end_p(scene_it)) {
 | 
				
			||||||
        }
 | 
					                return false;
 | 
				
			||||||
        prev_scene_id = *SceneManagerIdStack_ref(scene_it);
 | 
					            }
 | 
				
			||||||
        if(prev_scene_id == scene_id) {
 | 
					            prev_scene_id = *SceneManagerIdStack_ref(scene_it);
 | 
				
			||||||
            scene_found = true;
 | 
					            if(prev_scene_id == scene_id) {
 | 
				
			||||||
 | 
					                scene_found = true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        // Remove all scene id from navigation stack
 | 
				
			||||||
 | 
					        SceneManagerIdStack_next(scene_it);
 | 
				
			||||||
 | 
					        SceneManagerIdStack_pop_until(scene_manager->scene_id_stack, scene_it);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        scene_manager->scene_handlers->on_exit_handlers[cur_scene_id](scene_manager->context);
 | 
				
			||||||
 | 
					        scene_manager->scene_handlers->on_enter_handlers[prev_scene_id](scene_manager->context);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return true;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // Remove all scene id from navigation stack
 | 
					 | 
				
			||||||
    SceneManagerIdStack_next(scene_it);
 | 
					 | 
				
			||||||
    SceneManagerIdStack_pop_until(scene_manager->scene_id_stack, scene_it);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    scene_manager->scene_handlers->on_exit_handlers[cur_scene_id](scene_manager->context);
 | 
					 | 
				
			||||||
    scene_manager->scene_handlers->on_enter_handlers[prev_scene_id](scene_manager->context);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return true;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool scene_manager_has_previous_scene(SceneManager* scene_manager, uint32_t scene_id) {
 | 
					bool scene_manager_has_previous_scene(SceneManager* scene_manager, uint32_t scene_id) {
 | 
				
			||||||
    furi_assert(scene_manager);
 | 
					    furi_assert(scene_manager);
 | 
				
			||||||
    bool scene_found = false;
 | 
					    bool scene_found = false;
 | 
				
			||||||
    uint32_t prev_scene_id;
 | 
					 | 
				
			||||||
    SceneManagerIdStack_it_t scene_it;
 | 
					 | 
				
			||||||
    SceneManagerIdStack_it_last(scene_it, scene_manager->scene_id_stack);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Perform search in scene stack
 | 
					    if(SceneManagerIdStack_size(scene_manager->scene_id_stack) > 0) {
 | 
				
			||||||
    while(!scene_found) {
 | 
					        uint32_t prev_scene_id;
 | 
				
			||||||
        SceneManagerIdStack_previous(scene_it);
 | 
					        SceneManagerIdStack_it_t scene_it;
 | 
				
			||||||
        if(SceneManagerIdStack_end_p(scene_it)) {
 | 
					        SceneManagerIdStack_it_last(scene_it, scene_manager->scene_id_stack);
 | 
				
			||||||
            break;
 | 
					
 | 
				
			||||||
        }
 | 
					        // Perform search in scene stack
 | 
				
			||||||
        prev_scene_id = *SceneManagerIdStack_ref(scene_it);
 | 
					        while(!scene_found) {
 | 
				
			||||||
        if(prev_scene_id == scene_id) {
 | 
					            SceneManagerIdStack_previous(scene_it);
 | 
				
			||||||
            scene_found = true;
 | 
					            if(SceneManagerIdStack_end_p(scene_it)) {
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            prev_scene_id = *SceneManagerIdStack_ref(scene_it);
 | 
				
			||||||
 | 
					            if(prev_scene_id == scene_id) {
 | 
				
			||||||
 | 
					                scene_found = true;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return scene_found;
 | 
					    return scene_found;
 | 
				
			||||||
@ -167,25 +195,29 @@ bool scene_manager_search_and_switch_to_another_scene(
 | 
				
			|||||||
    furi_assert(scene_manager);
 | 
					    furi_assert(scene_manager);
 | 
				
			||||||
    furi_assert(scene_id < scene_manager->scene_handlers->scene_num);
 | 
					    furi_assert(scene_id < scene_manager->scene_handlers->scene_num);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint32_t cur_scene_id = *SceneManagerIdStack_back(scene_manager->scene_id_stack);
 | 
					    if(SceneManagerIdStack_size(scene_manager->scene_id_stack) > 0) {
 | 
				
			||||||
    SceneManagerIdStack_it_t scene_it;
 | 
					        uint32_t cur_scene_id = *SceneManagerIdStack_back(scene_manager->scene_id_stack);
 | 
				
			||||||
    SceneManagerIdStack_it(scene_it, scene_manager->scene_id_stack);
 | 
					        SceneManagerIdStack_it_t scene_it;
 | 
				
			||||||
    SceneManagerIdStack_next(scene_it);
 | 
					        SceneManagerIdStack_it(scene_it, scene_manager->scene_id_stack);
 | 
				
			||||||
    // Remove all scene id from navigation stack until first scene
 | 
					        SceneManagerIdStack_next(scene_it);
 | 
				
			||||||
    SceneManagerIdStack_pop_until(scene_manager->scene_id_stack, scene_it);
 | 
					        // Remove all scene id from navigation stack until first scene
 | 
				
			||||||
    // Add next scene
 | 
					        SceneManagerIdStack_pop_until(scene_manager->scene_id_stack, scene_it);
 | 
				
			||||||
    SceneManagerIdStack_push_back(scene_manager->scene_id_stack, scene_id);
 | 
					        // Add next scene
 | 
				
			||||||
 | 
					        SceneManagerIdStack_push_back(scene_manager->scene_id_stack, scene_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    scene_manager->scene_handlers->on_exit_handlers[cur_scene_id](scene_manager->context);
 | 
					        scene_manager->scene_handlers->on_exit_handlers[cur_scene_id](scene_manager->context);
 | 
				
			||||||
    scene_manager->scene_handlers->on_enter_handlers[scene_id](scene_manager->context);
 | 
					        scene_manager->scene_handlers->on_enter_handlers[scene_id](scene_manager->context);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return true;
 | 
					        return true;
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void scene_manager_stop(SceneManager* scene_manager) {
 | 
					void scene_manager_stop(SceneManager* scene_manager) {
 | 
				
			||||||
    furi_assert(scene_manager);
 | 
					    furi_assert(scene_manager);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(SceneManagerIdStack_size(scene_manager->scene_id_stack)) {
 | 
					    if(SceneManagerIdStack_size(scene_manager->scene_id_stack) > 0) {
 | 
				
			||||||
        uint32_t cur_scene_id = *SceneManagerIdStack_back(scene_manager->scene_id_stack);
 | 
					        uint32_t cur_scene_id = *SceneManagerIdStack_back(scene_manager->scene_id_stack);
 | 
				
			||||||
        scene_manager->scene_handlers->on_exit_handlers[cur_scene_id](scene_manager->context);
 | 
					        scene_manager->scene_handlers->on_exit_handlers[cur_scene_id](scene_manager->context);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -1,7 +1,7 @@
 | 
				
			|||||||
#include "view_i.h"
 | 
					#include "view_i.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
View* view_alloc() {
 | 
					View* view_alloc() {
 | 
				
			||||||
    View* view = furi_alloc(sizeof(View));
 | 
					    View* view = malloc(sizeof(View));
 | 
				
			||||||
    view->orientation = ViewOrientationHorizontal;
 | 
					    view->orientation = ViewOrientationHorizontal;
 | 
				
			||||||
    return view;
 | 
					    return view;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -78,12 +78,12 @@ void view_allocate_model(View* view, ViewModelType type, size_t size) {
 | 
				
			|||||||
    furi_assert(view->model == NULL);
 | 
					    furi_assert(view->model == NULL);
 | 
				
			||||||
    view->model_type = type;
 | 
					    view->model_type = type;
 | 
				
			||||||
    if(view->model_type == ViewModelTypeLockFree) {
 | 
					    if(view->model_type == ViewModelTypeLockFree) {
 | 
				
			||||||
        view->model = furi_alloc(size);
 | 
					        view->model = malloc(size);
 | 
				
			||||||
    } else if(view->model_type == ViewModelTypeLocking) {
 | 
					    } else if(view->model_type == ViewModelTypeLocking) {
 | 
				
			||||||
        ViewModelLocking* model = furi_alloc(sizeof(ViewModelLocking));
 | 
					        ViewModelLocking* model = malloc(sizeof(ViewModelLocking));
 | 
				
			||||||
        model->mutex = osMutexNew(NULL);
 | 
					        model->mutex = osMutexNew(NULL);
 | 
				
			||||||
        furi_check(model->mutex);
 | 
					        furi_check(model->mutex);
 | 
				
			||||||
        model->data = furi_alloc(size);
 | 
					        model->data = malloc(size);
 | 
				
			||||||
        view->model = model;
 | 
					        view->model = model;
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        furi_assert(false);
 | 
					        furi_assert(false);
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,7 @@
 | 
				
			|||||||
#define TAG "ViewDispatcher"
 | 
					#define TAG "ViewDispatcher"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ViewDispatcher* view_dispatcher_alloc() {
 | 
					ViewDispatcher* view_dispatcher_alloc() {
 | 
				
			||||||
    ViewDispatcher* view_dispatcher = furi_alloc(sizeof(ViewDispatcher));
 | 
					    ViewDispatcher* view_dispatcher = malloc(sizeof(ViewDispatcher));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    view_dispatcher->view_port = view_port_alloc();
 | 
					    view_dispatcher->view_port = view_port_alloc();
 | 
				
			||||||
    view_port_draw_callback_set(
 | 
					    view_port_draw_callback_set(
 | 
				
			||||||
 | 
				
			|||||||
@ -35,7 +35,7 @@ static void view_port_setup_canvas_orientation(const ViewPort* view_port, Canvas
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ViewPort* view_port_alloc() {
 | 
					ViewPort* view_port_alloc() {
 | 
				
			||||||
    ViewPort* view_port = furi_alloc(sizeof(ViewPort));
 | 
					    ViewPort* view_port = malloc(sizeof(ViewPort));
 | 
				
			||||||
    view_port->orientation = ViewPortOrientationHorizontal;
 | 
					    view_port->orientation = ViewPortOrientationHorizontal;
 | 
				
			||||||
    view_port->is_enabled = true;
 | 
					    view_port->is_enabled = true;
 | 
				
			||||||
    return view_port;
 | 
					    return view_port;
 | 
				
			||||||
 | 
				
			|||||||
@ -33,7 +33,7 @@ static void view_stack_enter(void* context) {
 | 
				
			|||||||
    ViewStack* view_stack = context;
 | 
					    ViewStack* view_stack = context;
 | 
				
			||||||
    ViewStackModel* model = view_get_model(view_stack->view);
 | 
					    ViewStackModel* model = view_get_model(view_stack->view);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* if more than 1 composite views hold same view they have to reassign update_callback_context */
 | 
					    /* if more than 1 Stack View hold same view they have to reassign update_callback_context */
 | 
				
			||||||
    for(int i = 0; i < MAX_VIEWS; ++i) {
 | 
					    for(int i = 0; i < MAX_VIEWS; ++i) {
 | 
				
			||||||
        if(model->views[i]) {
 | 
					        if(model->views[i]) {
 | 
				
			||||||
            view_set_update_callback_context(model->views[i], view_stack->view);
 | 
					            view_set_update_callback_context(model->views[i], view_stack->view);
 | 
				
			||||||
@ -62,7 +62,7 @@ static void view_stack_exit(void* context) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ViewStack* view_stack_alloc(void) {
 | 
					ViewStack* view_stack_alloc(void) {
 | 
				
			||||||
    ViewStack* view_stack = furi_alloc(sizeof(ViewStack));
 | 
					    ViewStack* view_stack = malloc(sizeof(ViewStack));
 | 
				
			||||||
    view_stack->view = view_alloc();
 | 
					    view_stack->view = view_alloc();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    view_allocate_model(view_stack->view, ViewModelTypeLocking, sizeof(ViewStackModel));
 | 
					    view_allocate_model(view_stack->view, ViewModelTypeLocking, sizeof(ViewStackModel));
 | 
				
			||||||
@ -131,6 +131,9 @@ void view_stack_add_view(ViewStack* view_stack, View* view) {
 | 
				
			|||||||
            model->views[i] = view;
 | 
					            model->views[i] = view;
 | 
				
			||||||
            view_set_update_callback(model->views[i], view_stack_update_callback);
 | 
					            view_set_update_callback(model->views[i], view_stack_update_callback);
 | 
				
			||||||
            view_set_update_callback_context(model->views[i], view_stack->view);
 | 
					            view_set_update_callback_context(model->views[i], view_stack->view);
 | 
				
			||||||
 | 
					            if(view->enter_callback) {
 | 
				
			||||||
 | 
					                view->enter_callback(view->context);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            result = true;
 | 
					            result = true;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -149,6 +152,9 @@ void view_stack_remove_view(ViewStack* view_stack, View* view) {
 | 
				
			|||||||
    ViewStackModel* model = view_get_model(view_stack->view);
 | 
					    ViewStackModel* model = view_get_model(view_stack->view);
 | 
				
			||||||
    for(int i = 0; i < MAX_VIEWS; ++i) {
 | 
					    for(int i = 0; i < MAX_VIEWS; ++i) {
 | 
				
			||||||
        if(model->views[i] == view) {
 | 
					        if(model->views[i] == view) {
 | 
				
			||||||
 | 
					            if(view->exit_callback) {
 | 
				
			||||||
 | 
					                view->exit_callback(view->context);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
            view_set_update_callback(model->views[i], NULL);
 | 
					            view_set_update_callback(model->views[i], NULL);
 | 
				
			||||||
            view_set_update_callback_context(model->views[i], NULL);
 | 
					            view_set_update_callback_context(model->views[i], NULL);
 | 
				
			||||||
            model->views[i] = NULL;
 | 
					            model->views[i] = NULL;
 | 
				
			||||||
 | 
				
			|||||||
@ -13,6 +13,10 @@
 | 
				
			|||||||
#include <stdbool.h>
 | 
					#include <stdbool.h>
 | 
				
			||||||
#include "view.h"
 | 
					#include "view.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					extern "C" {
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** ViewStack, anonymous type. */
 | 
					/** ViewStack, anonymous type. */
 | 
				
			||||||
typedef struct ViewStack ViewStack;
 | 
					typedef struct ViewStack ViewStack;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -51,3 +55,7 @@ void view_stack_add_view(ViewStack* view_stack, View* view);
 | 
				
			|||||||
 * @view        view        view to remove
 | 
					 * @view        view        view to remove
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void view_stack_remove_view(ViewStack* view_stack, View* view);
 | 
					void view_stack_remove_view(ViewStack* view_stack, View* view);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __cplusplus
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,7 @@
 | 
				
			|||||||
#include <callback-connector.h>
 | 
					#include <callback-connector.h>
 | 
				
			||||||
#include <m-string.h>
 | 
					#include <m-string.h>
 | 
				
			||||||
#include <toolbox/path.h>
 | 
					#include <toolbox/path.h>
 | 
				
			||||||
#include <flipper_file/flipper_file.h>
 | 
					#include <flipper_format/flipper_format.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const char* iButtonApp::app_folder = "/any/ibutton";
 | 
					const char* iButtonApp::app_folder = "/any/ibutton";
 | 
				
			||||||
const char* iButtonApp::app_extension = ".ibtn";
 | 
					const char* iButtonApp::app_extension = ".ibtn";
 | 
				
			||||||
@ -191,7 +191,7 @@ bool iButtonApp::save_key(const char* key_name) {
 | 
				
			|||||||
    // Create ibutton directory if necessary
 | 
					    // Create ibutton directory if necessary
 | 
				
			||||||
    make_app_folder();
 | 
					    make_app_folder();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    FlipperFile* file = flipper_file_alloc(storage);
 | 
					    FlipperFormat* file = flipper_format_file_alloc(storage);
 | 
				
			||||||
    string_t key_file_name;
 | 
					    string_t key_file_name;
 | 
				
			||||||
    bool result = false;
 | 
					    bool result = false;
 | 
				
			||||||
    string_init(key_file_name);
 | 
					    string_init(key_file_name);
 | 
				
			||||||
@ -207,29 +207,29 @@ bool iButtonApp::save_key(const char* key_name) {
 | 
				
			|||||||
        string_printf(key_file_name, "%s/%s%s", app_folder, key.get_name(), app_extension);
 | 
					        string_printf(key_file_name, "%s/%s%s", app_folder, key.get_name(), app_extension);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Open file for write
 | 
					        // Open file for write
 | 
				
			||||||
        if(!flipper_file_open_always(file, string_get_cstr(key_file_name))) break;
 | 
					        if(!flipper_format_file_open_always(file, string_get_cstr(key_file_name))) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Write header
 | 
					        // Write header
 | 
				
			||||||
        if(!flipper_file_write_header_cstr(file, iButtonApp::app_filetype, 1)) break;
 | 
					        if(!flipper_format_write_header_cstr(file, iButtonApp::app_filetype, 1)) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Write key type
 | 
					        // Write key type
 | 
				
			||||||
        if(!flipper_file_write_comment_cstr(file, "Key type can be Cyfral, Dallas or Metakom"))
 | 
					        if(!flipper_format_write_comment_cstr(file, "Key type can be Cyfral, Dallas or Metakom"))
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        const char* key_type = key.get_key_type_string_by_type(key.get_key_type());
 | 
					        const char* key_type = key.get_key_type_string_by_type(key.get_key_type());
 | 
				
			||||||
        if(!flipper_file_write_string_cstr(file, "Key type", key_type)) break;
 | 
					        if(!flipper_format_write_string_cstr(file, "Key type", key_type)) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Write data
 | 
					        // Write data
 | 
				
			||||||
        if(!flipper_file_write_comment_cstr(
 | 
					        if(!flipper_format_write_comment_cstr(
 | 
				
			||||||
               file, "Data size for Cyfral is 2, for Metakom is 4, for Dallas is 8"))
 | 
					               file, "Data size for Cyfral is 2, for Metakom is 4, for Dallas is 8"))
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(!flipper_file_write_hex(file, "Data", key.get_data(), key.get_type_data_size())) break;
 | 
					        if(!flipper_format_write_hex(file, "Data", key.get_data(), key.get_type_data_size()))
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
        result = true;
 | 
					        result = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    } while(false);
 | 
					    } while(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    flipper_file_close(file);
 | 
					    flipper_format_free(file);
 | 
				
			||||||
    flipper_file_free(file);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    string_clear(key_file_name);
 | 
					    string_clear(key_file_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -241,28 +241,28 @@ bool iButtonApp::save_key(const char* key_name) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool iButtonApp::load_key_data(string_t key_path) {
 | 
					bool iButtonApp::load_key_data(string_t key_path) {
 | 
				
			||||||
    FlipperFile* file = flipper_file_alloc(storage);
 | 
					    FlipperFormat* file = flipper_format_file_alloc(storage);
 | 
				
			||||||
    bool result = false;
 | 
					    bool result = false;
 | 
				
			||||||
    string_t data;
 | 
					    string_t data;
 | 
				
			||||||
    string_init(data);
 | 
					    string_init(data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        if(!flipper_file_open_existing(file, string_get_cstr(key_path))) break;
 | 
					        if(!flipper_format_file_open_existing(file, string_get_cstr(key_path))) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // header
 | 
					        // header
 | 
				
			||||||
        uint32_t version;
 | 
					        uint32_t version;
 | 
				
			||||||
        if(!flipper_file_read_header(file, data, &version)) break;
 | 
					        if(!flipper_format_read_header(file, data, &version)) break;
 | 
				
			||||||
        if(string_cmp_str(data, iButtonApp::app_filetype) != 0) break;
 | 
					        if(string_cmp_str(data, iButtonApp::app_filetype) != 0) break;
 | 
				
			||||||
        if(version != 1) break;
 | 
					        if(version != 1) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // key type
 | 
					        // key type
 | 
				
			||||||
        iButtonKeyType type;
 | 
					        iButtonKeyType type;
 | 
				
			||||||
        if(!flipper_file_read_string(file, "Key type", data)) break;
 | 
					        if(!flipper_format_read_string(file, "Key type", data)) break;
 | 
				
			||||||
        if(!key.get_key_type_by_type_string(string_get_cstr(data), &type)) break;
 | 
					        if(!key.get_key_type_by_type_string(string_get_cstr(data), &type)) break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // key data
 | 
					        // key data
 | 
				
			||||||
        uint8_t key_data[IBUTTON_KEY_DATA_SIZE] = {0};
 | 
					        uint8_t key_data[IBUTTON_KEY_DATA_SIZE] = {0};
 | 
				
			||||||
        if(!flipper_file_read_hex(file, "Data", key_data, key.get_type_data_size_by_type(type)))
 | 
					        if(!flipper_format_read_hex(file, "Data", key_data, key.get_type_data_size_by_type(type)))
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        key.set_type(type);
 | 
					        key.set_type(type);
 | 
				
			||||||
@ -271,8 +271,7 @@ bool iButtonApp::load_key_data(string_t key_path) {
 | 
				
			|||||||
        result = true;
 | 
					        result = true;
 | 
				
			||||||
    } while(false);
 | 
					    } while(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    flipper_file_close(file);
 | 
					    flipper_format_free(file);
 | 
				
			||||||
    flipper_file_free(file);
 | 
					 | 
				
			||||||
    string_clear(data);
 | 
					    string_clear(data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(!result) {
 | 
					    if(!result) {
 | 
				
			||||||
 | 
				
			|||||||
@ -66,7 +66,7 @@ const char* input_get_type_name(InputType type) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int32_t input_srv() {
 | 
					int32_t input_srv() {
 | 
				
			||||||
    input = furi_alloc(sizeof(Input));
 | 
					    input = malloc(sizeof(Input));
 | 
				
			||||||
    input->thread = osThreadGetId();
 | 
					    input->thread = osThreadGetId();
 | 
				
			||||||
    input->event_pubsub = furi_pubsub_alloc();
 | 
					    input->event_pubsub = furi_pubsub_alloc();
 | 
				
			||||||
    furi_record_create("input_events", input->event_pubsub);
 | 
					    furi_record_create("input_events", input->event_pubsub);
 | 
				
			||||||
@ -78,7 +78,7 @@ int32_t input_srv() {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    input->pin_states = furi_alloc(input_pins_count * sizeof(InputPinState));
 | 
					    input->pin_states = malloc(input_pins_count * sizeof(InputPinState));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for(size_t i = 0; i < input_pins_count; i++) {
 | 
					    for(size_t i = 0; i < input_pins_count; i++) {
 | 
				
			||||||
        GpioPin gpio = {(GPIO_TypeDef*)input_pins[i].port, (uint16_t)input_pins[i].pin};
 | 
					        GpioPin gpio = {(GPIO_TypeDef*)input_pins[i].port, (uint16_t)input_pins[i].pin};
 | 
				
			||||||
 | 
				
			|||||||
@ -145,7 +145,7 @@ static void irda_cli_start_ir_tx(Cli* cli, string_t args) {
 | 
				
			|||||||
    uint32_t frequency;
 | 
					    uint32_t frequency;
 | 
				
			||||||
    float duty_cycle;
 | 
					    float duty_cycle;
 | 
				
			||||||
    uint32_t timings_cnt = MAX_TIMINGS_AMOUNT;
 | 
					    uint32_t timings_cnt = MAX_TIMINGS_AMOUNT;
 | 
				
			||||||
    uint32_t* timings = (uint32_t*)furi_alloc(sizeof(uint32_t) * timings_cnt);
 | 
					    uint32_t* timings = (uint32_t*)malloc(sizeof(uint32_t) * timings_cnt);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(parse_message(str, &message)) {
 | 
					    if(parse_message(str, &message)) {
 | 
				
			||||||
        irda_send(&message, 1);
 | 
					        irda_send(&message, 1);
 | 
				
			||||||
 | 
				
			|||||||
@ -4,37 +4,42 @@
 | 
				
			|||||||
#include "irda/helpers/irda_parser.h"
 | 
					#include "irda/helpers/irda_parser.h"
 | 
				
			||||||
#include "irda_worker.h"
 | 
					#include "irda_worker.h"
 | 
				
			||||||
#include "m-string.h"
 | 
					#include "m-string.h"
 | 
				
			||||||
#include <flipper_file.h>
 | 
					#include <flipper_format/flipper_format.h>
 | 
				
			||||||
#include <memory>
 | 
					#include <memory>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
#include <furi_hal_irda.h>
 | 
					#include <furi_hal_irda.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define TAG "IrdaParser"
 | 
					#define TAG "IrdaParser"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool irda_parser_save_signal(FlipperFile* ff, const IrdaAppSignal& signal, const std::string& name) {
 | 
					bool irda_parser_save_signal(
 | 
				
			||||||
 | 
					    FlipperFormat* ff,
 | 
				
			||||||
 | 
					    const IrdaAppSignal& signal,
 | 
				
			||||||
 | 
					    const std::string& name) {
 | 
				
			||||||
    furi_assert(ff);
 | 
					    furi_assert(ff);
 | 
				
			||||||
    furi_assert(!name.empty());
 | 
					    furi_assert(!name.empty());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool result = false;
 | 
					    bool result = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        if(!flipper_file_write_comment_cstr(ff, "")) break;
 | 
					        if(!flipper_format_write_comment_cstr(ff, "")) break;
 | 
				
			||||||
        if(!flipper_file_write_string_cstr(ff, "name", name.c_str())) break;
 | 
					        if(!flipper_format_write_string_cstr(ff, "name", name.c_str())) break;
 | 
				
			||||||
        if(signal.is_raw()) {
 | 
					        if(signal.is_raw()) {
 | 
				
			||||||
            furi_assert(signal.get_raw_signal().timings_cnt <= MAX_TIMINGS_AMOUNT);
 | 
					            furi_assert(signal.get_raw_signal().timings_cnt <= MAX_TIMINGS_AMOUNT);
 | 
				
			||||||
            auto raw_signal = signal.get_raw_signal();
 | 
					            auto raw_signal = signal.get_raw_signal();
 | 
				
			||||||
            if(!flipper_file_write_string_cstr(ff, "type", "raw")) break;
 | 
					            if(!flipper_format_write_string_cstr(ff, "type", "raw")) break;
 | 
				
			||||||
            if(!flipper_file_write_uint32(ff, "frequency", &raw_signal.frequency, 1)) break;
 | 
					            if(!flipper_format_write_uint32(ff, "frequency", &raw_signal.frequency, 1)) break;
 | 
				
			||||||
            if(!flipper_file_write_float(ff, "duty_cycle", &raw_signal.duty_cycle, 1)) break;
 | 
					            if(!flipper_format_write_float(ff, "duty_cycle", &raw_signal.duty_cycle, 1)) break;
 | 
				
			||||||
            if(!flipper_file_write_uint32(ff, "data", raw_signal.timings, raw_signal.timings_cnt))
 | 
					            if(!flipper_format_write_uint32(ff, "data", raw_signal.timings, raw_signal.timings_cnt))
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            auto parsed_signal = signal.get_message();
 | 
					            auto parsed_signal = signal.get_message();
 | 
				
			||||||
            const char* protocol_name = irda_get_protocol_name(parsed_signal.protocol);
 | 
					            const char* protocol_name = irda_get_protocol_name(parsed_signal.protocol);
 | 
				
			||||||
            if(!flipper_file_write_string_cstr(ff, "type", "parsed")) break;
 | 
					            if(!flipper_format_write_string_cstr(ff, "type", "parsed")) break;
 | 
				
			||||||
            if(!flipper_file_write_string_cstr(ff, "protocol", protocol_name)) break;
 | 
					            if(!flipper_format_write_string_cstr(ff, "protocol", protocol_name)) break;
 | 
				
			||||||
            if(!flipper_file_write_hex(ff, "address", (uint8_t*)&parsed_signal.address, 4)) break;
 | 
					            if(!flipper_format_write_hex(ff, "address", (uint8_t*)&parsed_signal.address, 4))
 | 
				
			||||||
            if(!flipper_file_write_hex(ff, "command", (uint8_t*)&parsed_signal.command, 4)) break;
 | 
					                break;
 | 
				
			||||||
 | 
					            if(!flipper_format_write_hex(ff, "command", (uint8_t*)&parsed_signal.command, 4))
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        result = true;
 | 
					        result = true;
 | 
				
			||||||
    } while(0);
 | 
					    } while(0);
 | 
				
			||||||
@ -42,7 +47,7 @@ bool irda_parser_save_signal(FlipperFile* ff, const IrdaAppSignal& signal, const
 | 
				
			|||||||
    return result;
 | 
					    return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool irda_parser_read_signal(FlipperFile* ff, IrdaAppSignal& signal, std::string& name) {
 | 
					bool irda_parser_read_signal(FlipperFormat* ff, IrdaAppSignal& signal, std::string& name) {
 | 
				
			||||||
    furi_assert(ff);
 | 
					    furi_assert(ff);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool result = false;
 | 
					    bool result = false;
 | 
				
			||||||
@ -50,31 +55,31 @@ bool irda_parser_read_signal(FlipperFile* ff, IrdaAppSignal& signal, std::string
 | 
				
			|||||||
    string_init(read_string);
 | 
					    string_init(read_string);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        if(!flipper_file_read_string(ff, "name", read_string)) break;
 | 
					        if(!flipper_format_read_string(ff, "name", read_string)) break;
 | 
				
			||||||
        name = string_get_cstr(read_string);
 | 
					        name = string_get_cstr(read_string);
 | 
				
			||||||
        if(!flipper_file_read_string(ff, "type", read_string)) break;
 | 
					        if(!flipper_format_read_string(ff, "type", read_string)) break;
 | 
				
			||||||
        if(!string_cmp_str(read_string, "raw")) {
 | 
					        if(!string_cmp_str(read_string, "raw")) {
 | 
				
			||||||
            uint32_t* timings = nullptr;
 | 
					            uint32_t* timings = nullptr;
 | 
				
			||||||
            uint32_t timings_cnt = 0;
 | 
					            uint32_t timings_cnt = 0;
 | 
				
			||||||
            uint32_t frequency = 0;
 | 
					            uint32_t frequency = 0;
 | 
				
			||||||
            float duty_cycle = 0;
 | 
					            float duty_cycle = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if(!flipper_file_read_uint32(ff, "frequency", &frequency, 1)) break;
 | 
					            if(!flipper_format_read_uint32(ff, "frequency", &frequency, 1)) break;
 | 
				
			||||||
            if(!flipper_file_read_float(ff, "duty_cycle", &duty_cycle, 1)) break;
 | 
					            if(!flipper_format_read_float(ff, "duty_cycle", &duty_cycle, 1)) break;
 | 
				
			||||||
            if(!flipper_file_get_value_count(ff, "data", &timings_cnt)) break;
 | 
					            if(!flipper_format_get_value_count(ff, "data", &timings_cnt)) break;
 | 
				
			||||||
            if(timings_cnt > MAX_TIMINGS_AMOUNT) break;
 | 
					            if(timings_cnt > MAX_TIMINGS_AMOUNT) break;
 | 
				
			||||||
            timings = (uint32_t*)furi_alloc(sizeof(uint32_t) * timings_cnt);
 | 
					            timings = (uint32_t*)malloc(sizeof(uint32_t) * timings_cnt);
 | 
				
			||||||
            if(flipper_file_read_uint32(ff, "data", timings, timings_cnt)) {
 | 
					            if(flipper_format_read_uint32(ff, "data", timings, timings_cnt)) {
 | 
				
			||||||
                signal.set_raw_signal(timings, timings_cnt, frequency, duty_cycle);
 | 
					                signal.set_raw_signal(timings, timings_cnt, frequency, duty_cycle);
 | 
				
			||||||
                result = true;
 | 
					                result = true;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            free(timings);
 | 
					            free(timings);
 | 
				
			||||||
        } else if(!string_cmp_str(read_string, "parsed")) {
 | 
					        } else if(!string_cmp_str(read_string, "parsed")) {
 | 
				
			||||||
            IrdaMessage parsed_signal;
 | 
					            IrdaMessage parsed_signal;
 | 
				
			||||||
            if(!flipper_file_read_string(ff, "protocol", read_string)) break;
 | 
					            if(!flipper_format_read_string(ff, "protocol", read_string)) break;
 | 
				
			||||||
            parsed_signal.protocol = irda_get_protocol_by_name(string_get_cstr(read_string));
 | 
					            parsed_signal.protocol = irda_get_protocol_by_name(string_get_cstr(read_string));
 | 
				
			||||||
            if(!flipper_file_read_hex(ff, "address", (uint8_t*)&parsed_signal.address, 4)) break;
 | 
					            if(!flipper_format_read_hex(ff, "address", (uint8_t*)&parsed_signal.address, 4)) break;
 | 
				
			||||||
            if(!flipper_file_read_hex(ff, "command", (uint8_t*)&parsed_signal.command, 4)) break;
 | 
					            if(!flipper_format_read_hex(ff, "command", (uint8_t*)&parsed_signal.command, 4)) break;
 | 
				
			||||||
            if(!irda_parser_is_parsed_signal_valid(&parsed_signal)) break;
 | 
					            if(!irda_parser_is_parsed_signal_valid(&parsed_signal)) break;
 | 
				
			||||||
            signal.set_message(&parsed_signal);
 | 
					            signal.set_message(&parsed_signal);
 | 
				
			||||||
            result = true;
 | 
					            result = true;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,10 +1,13 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "../irda_app_signal.h"
 | 
					#include "../irda_app_signal.h"
 | 
				
			||||||
#include <flipper_file.h>
 | 
					#include <flipper_format/flipper_format.h>
 | 
				
			||||||
#include <string>
 | 
					#include <string>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool irda_parser_save_signal(FlipperFile* ff, const IrdaAppSignal& signal, const std::string& name);
 | 
					bool irda_parser_save_signal(
 | 
				
			||||||
bool irda_parser_read_signal(FlipperFile* ff, IrdaAppSignal& signal, std::string& name);
 | 
					    FlipperFormat* ff,
 | 
				
			||||||
 | 
					    const IrdaAppSignal& signal,
 | 
				
			||||||
 | 
					    const std::string& name);
 | 
				
			||||||
 | 
					bool irda_parser_read_signal(FlipperFormat* ff, IrdaAppSignal& signal, std::string& name);
 | 
				
			||||||
bool irda_parser_is_parsed_signal_valid(const IrdaMessage* signal);
 | 
					bool irda_parser_is_parsed_signal_valid(const IrdaMessage* signal);
 | 
				
			||||||
bool irda_parser_is_raw_signal_valid(uint32_t frequency, float duty_cycle, uint32_t timings_cnt);
 | 
					bool irda_parser_is_raw_signal_valid(uint32_t frequency, float duty_cycle, uint32_t timings_cnt);
 | 
				
			||||||
 | 
				
			|||||||
@ -279,3 +279,8 @@ const IrdaAppSignal& IrdaApp::get_received_signal() const {
 | 
				
			|||||||
void IrdaApp::set_received_signal(const IrdaAppSignal& signal) {
 | 
					void IrdaApp::set_received_signal(const IrdaAppSignal& signal) {
 | 
				
			||||||
    received_signal = signal;
 | 
					    received_signal = signal;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void IrdaApp::signal_sent_callback(void* context) {
 | 
				
			||||||
 | 
					    IrdaApp* app = static_cast<IrdaApp*>(context);
 | 
				
			||||||
 | 
					    app->notify_blink_green();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -3,7 +3,6 @@
 | 
				
			|||||||
#include <irda.h>
 | 
					#include <irda.h>
 | 
				
			||||||
#include <furi.h>
 | 
					#include <furi.h>
 | 
				
			||||||
#include "scene/irda_app_scene.h"
 | 
					#include "scene/irda_app_scene.h"
 | 
				
			||||||
#include "irda_app_event.h"
 | 
					 | 
				
			||||||
#include "scene/irda_app_scene.h"
 | 
					#include "scene/irda_app_scene.h"
 | 
				
			||||||
#include "irda_app_view_manager.h"
 | 
					#include "irda_app_view_manager.h"
 | 
				
			||||||
#include "irda_app_remote_manager.h"
 | 
					#include "irda_app_remote_manager.h"
 | 
				
			||||||
@ -11,6 +10,7 @@
 | 
				
			|||||||
#include <stdint.h>
 | 
					#include <stdint.h>
 | 
				
			||||||
#include <notification/notification_messages.h>
 | 
					#include <notification/notification_messages.h>
 | 
				
			||||||
#include <irda_worker.h>
 | 
					#include <irda_worker.h>
 | 
				
			||||||
 | 
					#include "irda_app_view_manager.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class IrdaApp {
 | 
					class IrdaApp {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
@ -87,6 +87,7 @@ public:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    static void text_input_callback(void* context);
 | 
					    static void text_input_callback(void* context);
 | 
				
			||||||
    static void popup_callback(void* context);
 | 
					    static void popup_callback(void* context);
 | 
				
			||||||
 | 
					    static void signal_sent_callback(void* context);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    IrdaApp();
 | 
					    IrdaApp();
 | 
				
			||||||
    ~IrdaApp();
 | 
					    ~IrdaApp();
 | 
				
			||||||
 | 
				
			|||||||
@ -16,15 +16,15 @@ bool IrdaAppBruteForce::calculate_messages() {
 | 
				
			|||||||
    bool result = false;
 | 
					    bool result = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Storage* storage = static_cast<Storage*>(furi_record_open("storage"));
 | 
					    Storage* storage = static_cast<Storage*>(furi_record_open("storage"));
 | 
				
			||||||
    FlipperFile* ff = flipper_file_alloc(storage);
 | 
					    FlipperFormat* ff = flipper_format_file_alloc(storage);
 | 
				
			||||||
    result = flipper_file_open_existing(ff, universal_db_filename);
 | 
					    result = flipper_format_file_open_existing(ff, universal_db_filename);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(result) {
 | 
					    if(result) {
 | 
				
			||||||
        IrdaAppSignal signal;
 | 
					        IrdaAppSignal signal;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        string_t signal_name;
 | 
					        string_t signal_name;
 | 
				
			||||||
        string_init(signal_name);
 | 
					        string_init(signal_name);
 | 
				
			||||||
        while(flipper_file_read_string(ff, "name", signal_name)) {
 | 
					        while(flipper_format_read_string(ff, "name", signal_name)) {
 | 
				
			||||||
            auto element = records.find(string_get_cstr(signal_name));
 | 
					            auto element = records.find(string_get_cstr(signal_name));
 | 
				
			||||||
            if(element != records.cend()) {
 | 
					            if(element != records.cend()) {
 | 
				
			||||||
                ++element->second.amount;
 | 
					                ++element->second.amount;
 | 
				
			||||||
@ -33,8 +33,7 @@ bool IrdaAppBruteForce::calculate_messages() {
 | 
				
			|||||||
        string_clear(signal_name);
 | 
					        string_clear(signal_name);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    flipper_file_close(ff);
 | 
					    flipper_format_free(ff);
 | 
				
			||||||
    flipper_file_free(ff);
 | 
					 | 
				
			||||||
    furi_record_close("storage");
 | 
					    furi_record_close("storage");
 | 
				
			||||||
    return result;
 | 
					    return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -45,8 +44,7 @@ void IrdaAppBruteForce::stop_bruteforce() {
 | 
				
			|||||||
    if(current_record.size()) {
 | 
					    if(current_record.size()) {
 | 
				
			||||||
        furi_assert(ff);
 | 
					        furi_assert(ff);
 | 
				
			||||||
        current_record.clear();
 | 
					        current_record.clear();
 | 
				
			||||||
        flipper_file_close(ff);
 | 
					        flipper_format_free(ff);
 | 
				
			||||||
        flipper_file_free(ff);
 | 
					 | 
				
			||||||
        furi_record_close("storage");
 | 
					        furi_record_close("storage");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -84,11 +82,10 @@ bool IrdaAppBruteForce::start_bruteforce(int index, int& record_amount) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if(record_amount) {
 | 
					    if(record_amount) {
 | 
				
			||||||
        Storage* storage = static_cast<Storage*>(furi_record_open("storage"));
 | 
					        Storage* storage = static_cast<Storage*>(furi_record_open("storage"));
 | 
				
			||||||
        ff = flipper_file_alloc(storage);
 | 
					        ff = flipper_format_file_alloc(storage);
 | 
				
			||||||
        result = flipper_file_open_existing(ff, universal_db_filename);
 | 
					        result = flipper_format_file_open_existing(ff, universal_db_filename);
 | 
				
			||||||
        if(!result) {
 | 
					        if(!result) {
 | 
				
			||||||
            flipper_file_close(ff);
 | 
					            flipper_format_free(ff);
 | 
				
			||||||
            flipper_file_free(ff);
 | 
					 | 
				
			||||||
            furi_record_close("storage");
 | 
					            furi_record_close("storage");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -2,12 +2,12 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include <unordered_map>
 | 
					#include <unordered_map>
 | 
				
			||||||
#include <memory>
 | 
					#include <memory>
 | 
				
			||||||
#include <flipper_file.h>
 | 
					#include <flipper_format/flipper_format.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class IrdaAppBruteForce {
 | 
					class IrdaAppBruteForce {
 | 
				
			||||||
    const char* universal_db_filename;
 | 
					    const char* universal_db_filename;
 | 
				
			||||||
    std::string current_record;
 | 
					    std::string current_record;
 | 
				
			||||||
    FlipperFile* ff;
 | 
					    FlipperFormat* ff;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    typedef struct {
 | 
					    typedef struct {
 | 
				
			||||||
        int index;
 | 
					        int index;
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,5 @@
 | 
				
			|||||||
#include <file_worker_cpp.h>
 | 
					#include <file_worker_cpp.h>
 | 
				
			||||||
#include <flipper_file.h>
 | 
					#include <flipper_format/flipper_format.h>
 | 
				
			||||||
#include "irda_app_remote_manager.h"
 | 
					#include "irda_app_remote_manager.h"
 | 
				
			||||||
#include "irda/helpers/irda_parser.h"
 | 
					#include "irda/helpers/irda_parser.h"
 | 
				
			||||||
#include "irda/irda_app_signal.h"
 | 
					#include "irda/irda_app_signal.h"
 | 
				
			||||||
@ -169,12 +169,12 @@ bool IrdaAppRemoteManager::store(void) {
 | 
				
			|||||||
    if(!file_worker.mkdir(IrdaApp::irda_directory)) return false;
 | 
					    if(!file_worker.mkdir(IrdaApp::irda_directory)) return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Storage* storage = static_cast<Storage*>(furi_record_open("storage"));
 | 
					    Storage* storage = static_cast<Storage*>(furi_record_open("storage"));
 | 
				
			||||||
    FlipperFile* ff = flipper_file_alloc(storage);
 | 
					    FlipperFormat* ff = flipper_format_file_alloc(storage);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    FURI_LOG_I("RemoteManager", "store file: \'%s\'", make_full_name(remote->name).c_str());
 | 
					    FURI_LOG_I("RemoteManager", "store file: \'%s\'", make_full_name(remote->name).c_str());
 | 
				
			||||||
    result = flipper_file_open_always(ff, make_full_name(remote->name).c_str());
 | 
					    result = flipper_format_file_open_always(ff, make_full_name(remote->name).c_str());
 | 
				
			||||||
    if(result) {
 | 
					    if(result) {
 | 
				
			||||||
        result = flipper_file_write_header_cstr(ff, "IR signals file", 1);
 | 
					        result = flipper_format_write_header_cstr(ff, "IR signals file", 1);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if(result) {
 | 
					    if(result) {
 | 
				
			||||||
        for(const auto& button : remote->buttons) {
 | 
					        for(const auto& button : remote->buttons) {
 | 
				
			||||||
@ -185,8 +185,7 @@ bool IrdaAppRemoteManager::store(void) {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    flipper_file_close(ff);
 | 
					    flipper_format_free(ff);
 | 
				
			||||||
    flipper_file_free(ff);
 | 
					 | 
				
			||||||
    furi_record_close("storage");
 | 
					    furi_record_close("storage");
 | 
				
			||||||
    return result;
 | 
					    return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -194,15 +193,15 @@ bool IrdaAppRemoteManager::store(void) {
 | 
				
			|||||||
bool IrdaAppRemoteManager::load(const std::string& remote_name) {
 | 
					bool IrdaAppRemoteManager::load(const std::string& remote_name) {
 | 
				
			||||||
    bool result = false;
 | 
					    bool result = false;
 | 
				
			||||||
    Storage* storage = static_cast<Storage*>(furi_record_open("storage"));
 | 
					    Storage* storage = static_cast<Storage*>(furi_record_open("storage"));
 | 
				
			||||||
    FlipperFile* ff = flipper_file_alloc(storage);
 | 
					    FlipperFormat* ff = flipper_format_file_alloc(storage);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    FURI_LOG_I("RemoteManager", "load file: \'%s\'", make_full_name(remote_name).c_str());
 | 
					    FURI_LOG_I("RemoteManager", "load file: \'%s\'", make_full_name(remote_name).c_str());
 | 
				
			||||||
    result = flipper_file_open_existing(ff, make_full_name(remote_name).c_str());
 | 
					    result = flipper_format_file_open_existing(ff, make_full_name(remote_name).c_str());
 | 
				
			||||||
    if(result) {
 | 
					    if(result) {
 | 
				
			||||||
        string_t header;
 | 
					        string_t header;
 | 
				
			||||||
        string_init(header);
 | 
					        string_init(header);
 | 
				
			||||||
        uint32_t version;
 | 
					        uint32_t version;
 | 
				
			||||||
        result = flipper_file_read_header(ff, header, &version);
 | 
					        result = flipper_format_read_header(ff, header, &version);
 | 
				
			||||||
        if(result) {
 | 
					        if(result) {
 | 
				
			||||||
            result = !string_cmp_str(header, "IR signals file") && (version == 1);
 | 
					            result = !string_cmp_str(header, "IR signals file") && (version == 1);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -217,8 +216,7 @@ bool IrdaAppRemoteManager::load(const std::string& remote_name) {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    flipper_file_close(ff);
 | 
					    flipper_format_free(ff);
 | 
				
			||||||
    flipper_file_free(ff);
 | 
					 | 
				
			||||||
    furi_record_close("storage");
 | 
					    furi_record_close("storage");
 | 
				
			||||||
    return result;
 | 
					    return result;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,8 +1,15 @@
 | 
				
			|||||||
#include "furi.h"
 | 
					#include <gui/modules/button_menu.h>
 | 
				
			||||||
#include "gui/modules/button_panel.h"
 | 
					#include <gui/view_stack.h>
 | 
				
			||||||
 | 
					#include <gui/modules/loading.h>
 | 
				
			||||||
 | 
					#include <gui/modules/button_panel.h>
 | 
				
			||||||
 | 
					#include <gui/modules/dialog_ex.h>
 | 
				
			||||||
 | 
					#include <furi.h>
 | 
				
			||||||
 | 
					#include <callback-connector.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "irda/irda_app_view_manager.h"
 | 
				
			||||||
 | 
					#include "irda/view/irda_progress_view.h"
 | 
				
			||||||
#include "irda_app.h"
 | 
					#include "irda_app.h"
 | 
				
			||||||
#include "irda/irda_app_event.h"
 | 
					#include "irda/irda_app_event.h"
 | 
				
			||||||
#include <callback-connector.h>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
IrdaAppViewManager::IrdaAppViewManager() {
 | 
					IrdaAppViewManager::IrdaAppViewManager() {
 | 
				
			||||||
    event_queue = osMessageQueueNew(10, sizeof(IrdaAppEvent), NULL);
 | 
					    event_queue = osMessageQueueNew(10, sizeof(IrdaAppEvent), NULL);
 | 
				
			||||||
@ -19,16 +26,20 @@ IrdaAppViewManager::IrdaAppViewManager() {
 | 
				
			|||||||
    dialog_ex = dialog_ex_alloc();
 | 
					    dialog_ex = dialog_ex_alloc();
 | 
				
			||||||
    text_input = text_input_alloc();
 | 
					    text_input = text_input_alloc();
 | 
				
			||||||
    button_panel = button_panel_alloc();
 | 
					    button_panel = button_panel_alloc();
 | 
				
			||||||
    popup_brut = popup_brut_alloc();
 | 
					    progress_view = irda_progress_view_alloc();
 | 
				
			||||||
 | 
					    loading_view = loading_alloc();
 | 
				
			||||||
 | 
					    universal_view_stack = view_stack_alloc();
 | 
				
			||||||
 | 
					    view_stack_add_view(universal_view_stack, button_panel_get_view(button_panel));
 | 
				
			||||||
 | 
					    view_set_orientation(view_stack_get_view(universal_view_stack), ViewOrientationVertical);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    add_view(ViewType::ButtonPanel, button_panel_get_view(button_panel));
 | 
					    add_view(ViewType::UniversalRemote, view_stack_get_view(universal_view_stack));
 | 
				
			||||||
    add_view(ViewType::ButtonMenu, button_menu_get_view(button_menu));
 | 
					    add_view(ViewType::ButtonMenu, button_menu_get_view(button_menu));
 | 
				
			||||||
    add_view(ViewType::Submenu, submenu_get_view(submenu));
 | 
					    add_view(ViewType::Submenu, submenu_get_view(submenu));
 | 
				
			||||||
    add_view(ViewType::Popup, popup_get_view(popup));
 | 
					    add_view(ViewType::Popup, popup_get_view(popup));
 | 
				
			||||||
    add_view(ViewType::DialogEx, dialog_ex_get_view(dialog_ex));
 | 
					    add_view(ViewType::DialogEx, dialog_ex_get_view(dialog_ex));
 | 
				
			||||||
    add_view(ViewType::TextInput, text_input_get_view(text_input));
 | 
					    add_view(ViewType::TextInput, text_input_get_view(text_input));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    view_set_previous_callback(button_panel_get_view(button_panel), callback);
 | 
					    view_set_previous_callback(view_stack_get_view(universal_view_stack), callback);
 | 
				
			||||||
    view_set_previous_callback(button_menu_get_view(button_menu), callback);
 | 
					    view_set_previous_callback(button_menu_get_view(button_menu), callback);
 | 
				
			||||||
    view_set_previous_callback(submenu_get_view(submenu), callback);
 | 
					    view_set_previous_callback(submenu_get_view(submenu), callback);
 | 
				
			||||||
    view_set_previous_callback(popup_get_view(popup), callback);
 | 
					    view_set_previous_callback(popup_get_view(popup), callback);
 | 
				
			||||||
@ -38,7 +49,7 @@ IrdaAppViewManager::IrdaAppViewManager() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
IrdaAppViewManager::~IrdaAppViewManager() {
 | 
					IrdaAppViewManager::~IrdaAppViewManager() {
 | 
				
			||||||
    view_dispatcher_remove_view(
 | 
					    view_dispatcher_remove_view(
 | 
				
			||||||
        view_dispatcher, static_cast<uint32_t>(IrdaAppViewManager::ViewType::ButtonPanel));
 | 
					        view_dispatcher, static_cast<uint32_t>(IrdaAppViewManager::ViewType::UniversalRemote));
 | 
				
			||||||
    view_dispatcher_remove_view(
 | 
					    view_dispatcher_remove_view(
 | 
				
			||||||
        view_dispatcher, static_cast<uint32_t>(IrdaAppViewManager::ViewType::ButtonMenu));
 | 
					        view_dispatcher, static_cast<uint32_t>(IrdaAppViewManager::ViewType::ButtonMenu));
 | 
				
			||||||
    view_dispatcher_remove_view(
 | 
					    view_dispatcher_remove_view(
 | 
				
			||||||
@ -50,13 +61,16 @@ IrdaAppViewManager::~IrdaAppViewManager() {
 | 
				
			|||||||
    view_dispatcher_remove_view(
 | 
					    view_dispatcher_remove_view(
 | 
				
			||||||
        view_dispatcher, static_cast<uint32_t>(IrdaAppViewManager::ViewType::Popup));
 | 
					        view_dispatcher, static_cast<uint32_t>(IrdaAppViewManager::ViewType::Popup));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    view_stack_remove_view(universal_view_stack, button_panel_get_view(button_panel));
 | 
				
			||||||
 | 
					    view_stack_free(universal_view_stack);
 | 
				
			||||||
 | 
					    button_panel_free(button_panel);
 | 
				
			||||||
    submenu_free(submenu);
 | 
					    submenu_free(submenu);
 | 
				
			||||||
    popup_free(popup);
 | 
					    popup_free(popup);
 | 
				
			||||||
    button_panel_free(button_panel);
 | 
					 | 
				
			||||||
    button_menu_free(button_menu);
 | 
					    button_menu_free(button_menu);
 | 
				
			||||||
    dialog_ex_free(dialog_ex);
 | 
					    dialog_ex_free(dialog_ex);
 | 
				
			||||||
    text_input_free(text_input);
 | 
					    text_input_free(text_input);
 | 
				
			||||||
    popup_brut_free(popup_brut);
 | 
					    irda_progress_view_free(progress_view);
 | 
				
			||||||
 | 
					    loading_free(loading_view);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    view_dispatcher_free(view_dispatcher);
 | 
					    view_dispatcher_free(view_dispatcher);
 | 
				
			||||||
    furi_record_close("gui");
 | 
					    furi_record_close("gui");
 | 
				
			||||||
@ -91,8 +105,16 @@ ButtonPanel* IrdaAppViewManager::get_button_panel() {
 | 
				
			|||||||
    return button_panel;
 | 
					    return button_panel;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
IrdaAppPopupBrut* IrdaAppViewManager::get_popup_brut() {
 | 
					IrdaProgressView* IrdaAppViewManager::get_progress() {
 | 
				
			||||||
    return popup_brut;
 | 
					    return progress_view;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Loading* IrdaAppViewManager::get_loading() {
 | 
				
			||||||
 | 
					    return loading_view;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					ViewStack* IrdaAppViewManager::get_universal_view_stack() {
 | 
				
			||||||
 | 
					    return universal_view_stack;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
osMessageQueueId_t IrdaAppViewManager::get_event_queue() {
 | 
					osMessageQueueId_t IrdaAppViewManager::get_event_queue() {
 | 
				
			||||||
@ -113,13 +135,17 @@ void IrdaAppViewManager::receive_event(IrdaAppEvent* event) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void IrdaAppViewManager::send_event(IrdaAppEvent* event) {
 | 
					void IrdaAppViewManager::send_event(IrdaAppEvent* event) {
 | 
				
			||||||
    uint32_t timeout = 0;
 | 
					    uint32_t timeout = 0;
 | 
				
			||||||
    /* Rapid button hammering on Remote Scene causes queue overflow - ignore it,
 | 
					    /* Rapid button hammering on signal send scenes causes queue overflow - ignore it,
 | 
				
			||||||
     * but try to keep button release event - it switches off IRDA DMA sending. */
 | 
					     * but try to keep button release event - it switches off IRDA DMA sending. */
 | 
				
			||||||
    if(event->type == IrdaAppEvent::Type::MenuSelectedRelease) {
 | 
					    if(event->type == IrdaAppEvent::Type::MenuSelectedRelease) {
 | 
				
			||||||
        timeout = 200;
 | 
					        timeout = 200;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    if((event->type == IrdaAppEvent::Type::DialogExSelected) &&
 | 
				
			||||||
 | 
					       (event->payload.dialog_ex_result == DialogExReleaseCenter)) {
 | 
				
			||||||
 | 
					        timeout = 200;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    osMessageQueuePut(event_queue, event, 0, timeout);
 | 
					    osMessageQueuePut(event_queue, event, 0, timeout);
 | 
				
			||||||
    /* furi_check(result == osOK); */
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uint32_t IrdaAppViewManager::previous_view_callback(void* context) {
 | 
					uint32_t IrdaAppViewManager::previous_view_callback(void* context) {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,14 +1,17 @@
 | 
				
			|||||||
#pragma once
 | 
					#pragma once
 | 
				
			||||||
#include "gui/modules/button_menu.h"
 | 
					#include <gui/modules/button_menu.h>
 | 
				
			||||||
#include "gui/modules/text_input.h"
 | 
					#include <gui/modules/text_input.h>
 | 
				
			||||||
 | 
					#include <gui/view_stack.h>
 | 
				
			||||||
 | 
					#include <gui/modules/button_panel.h>
 | 
				
			||||||
#include <furi.h>
 | 
					#include <furi.h>
 | 
				
			||||||
#include <gui/view_dispatcher.h>
 | 
					#include <gui/view_dispatcher.h>
 | 
				
			||||||
#include <gui/modules/dialog_ex.h>
 | 
					#include <gui/modules/dialog_ex.h>
 | 
				
			||||||
#include <gui/modules/submenu.h>
 | 
					#include <gui/modules/submenu.h>
 | 
				
			||||||
#include <gui/modules/popup.h>
 | 
					#include <gui/modules/popup.h>
 | 
				
			||||||
#include "irda_app.h"
 | 
					#include <gui/modules/loading.h>
 | 
				
			||||||
#include "view/irda_app_brut_view.h"
 | 
					
 | 
				
			||||||
#include "gui/modules/button_panel.h"
 | 
					#include "irda_app_event.h"
 | 
				
			||||||
 | 
					#include "view/irda_progress_view.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class IrdaAppViewManager {
 | 
					class IrdaAppViewManager {
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
@ -17,7 +20,7 @@ public:
 | 
				
			|||||||
        TextInput,
 | 
					        TextInput,
 | 
				
			||||||
        Submenu,
 | 
					        Submenu,
 | 
				
			||||||
        ButtonMenu,
 | 
					        ButtonMenu,
 | 
				
			||||||
        ButtonPanel,
 | 
					        UniversalRemote,
 | 
				
			||||||
        Popup,
 | 
					        Popup,
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -36,7 +39,9 @@ public:
 | 
				
			|||||||
    TextInput* get_text_input();
 | 
					    TextInput* get_text_input();
 | 
				
			||||||
    ButtonMenu* get_button_menu();
 | 
					    ButtonMenu* get_button_menu();
 | 
				
			||||||
    ButtonPanel* get_button_panel();
 | 
					    ButtonPanel* get_button_panel();
 | 
				
			||||||
    IrdaAppPopupBrut* get_popup_brut();
 | 
					    ViewStack* get_universal_view_stack();
 | 
				
			||||||
 | 
					    IrdaProgressView* get_progress();
 | 
				
			||||||
 | 
					    Loading* get_loading();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    osMessageQueueId_t get_event_queue();
 | 
					    osMessageQueueId_t get_event_queue();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -51,7 +56,9 @@ private:
 | 
				
			|||||||
    Popup* popup;
 | 
					    Popup* popup;
 | 
				
			||||||
    ButtonMenu* button_menu;
 | 
					    ButtonMenu* button_menu;
 | 
				
			||||||
    ButtonPanel* button_panel;
 | 
					    ButtonPanel* button_panel;
 | 
				
			||||||
    IrdaAppPopupBrut* popup_brut;
 | 
					    ViewStack* universal_view_stack;
 | 
				
			||||||
 | 
					    IrdaProgressView* progress_view;
 | 
				
			||||||
 | 
					    Loading* loading_view;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    osMessageQueueId_t event_queue;
 | 
					    osMessageQueueId_t event_queue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -50,6 +50,7 @@ public:
 | 
				
			|||||||
    void on_enter(IrdaApp* app) final;
 | 
					    void on_enter(IrdaApp* app) final;
 | 
				
			||||||
    bool on_event(IrdaApp* app, IrdaAppEvent* event) final;
 | 
					    bool on_event(IrdaApp* app, IrdaAppEvent* event) final;
 | 
				
			||||||
    void on_exit(IrdaApp* app) final;
 | 
					    void on_exit(IrdaApp* app) final;
 | 
				
			||||||
 | 
					    bool button_pressed = false;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class IrdaAppSceneLearnEnterName : public IrdaAppScene {
 | 
					class IrdaAppSceneLearnEnterName : public IrdaAppScene {
 | 
				
			||||||
 | 
				
			|||||||
@ -57,6 +57,8 @@ bool IrdaAppSceneAskBack::on_event(IrdaApp* app, IrdaAppEvent* event) {
 | 
				
			|||||||
            app->switch_to_previous_scene();
 | 
					            app->switch_to_previous_scene();
 | 
				
			||||||
            consumed = true;
 | 
					            consumed = true;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -70,7 +70,7 @@ bool IrdaAppSceneEditDelete::on_event(IrdaApp* app, IrdaAppEvent* event) {
 | 
				
			|||||||
        case DialogExResultCenter:
 | 
					        case DialogExResultCenter:
 | 
				
			||||||
            furi_assert(0);
 | 
					            furi_assert(0);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case DialogExResultRight:
 | 
					        case DialogExResultRight: {
 | 
				
			||||||
            auto remote_manager = app->get_remote_manager();
 | 
					            auto remote_manager = app->get_remote_manager();
 | 
				
			||||||
            bool result = false;
 | 
					            bool result = false;
 | 
				
			||||||
            if(app->get_edit_element() == IrdaApp::EditElement::Remote) {
 | 
					            if(app->get_edit_element() == IrdaApp::EditElement::Remote) {
 | 
				
			||||||
@ -88,6 +88,9 @@ bool IrdaAppSceneEditDelete::on_event(IrdaApp* app, IrdaAppEvent* event) {
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            break;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return consumed;
 | 
					    return consumed;
 | 
				
			||||||
 | 
				
			|||||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user