David Lee 2 лет назад
Родитель
Сommit
c6f71ae262
47 измененных файлов с 1975 добавлено и 1985 удалено
  1. 2 0
      .vscode/compile_commands.json
  2. BIN
      dist/debug/xremote_d.elf
  3. BIN
      dist/xremote.fap
  4. 2 1
      helpers/xremote_custom_event.h
  5. 4 5
      helpers/xremote_haptic.c
  6. 0 1
      helpers/xremote_haptic.h
  7. 6 4
      helpers/xremote_led.c
  8. 0 1
      helpers/xremote_led.h
  9. 2 3
      helpers/xremote_speaker.c
  10. 115 119
      helpers/xremote_storage.c
  11. 15 15
      helpers/xremote_storage.h
  12. 261 264
      models/cross/xremote_remote.c
  13. 27 27
      models/cross/xremote_remote.h
  14. 240 241
      models/cross/xremote_remote_item.c
  15. 0 3
      models/cross/xremote_remote_item.h
  16. 3 2
      models/infrared/xremote_ir_remote.c
  17. 32 32
      models/infrared/xremote_ir_remote_button.c
  18. 12 12
      models/infrared/xremote_ir_remote_button.h
  19. 218 218
      models/infrared/xremote_ir_signal.c
  20. 38 38
      models/infrared/xremote_ir_signal.h
  21. 0 2
      models/subghz/subghz_i.h
  22. 8 9
      models/subghz/xremote_sg_remote.c
  23. 30 30
      scenes/xremote_scene.c
  24. 29 29
      scenes/xremote_scene.h
  25. 7 6
      scenes/xremote_scene_create.c
  26. 6 5
      scenes/xremote_scene_create_add.c
  27. 10 11
      scenes/xremote_scene_edit_item.c
  28. 25 24
      scenes/xremote_scene_infoscreen.c
  29. 2 3
      scenes/xremote_scene_ir_list.c
  30. 9 7
      scenes/xremote_scene_ir_remote.c
  31. 85 69
      scenes/xremote_scene_menu.c
  32. 25 25
      scenes/xremote_scene_pause_set.c
  33. 71 73
      scenes/xremote_scene_save_remote.c
  34. 44 44
      scenes/xremote_scene_save_remote_item.c
  35. 5 23
      scenes/xremote_scene_settings.c
  36. 2 3
      scenes/xremote_scene_sg_list.c
  37. 154 153
      scenes/xremote_scene_transmit.c
  38. 37 38
      scenes/xremote_scene_wip.c
  39. 46 43
      scenes/xremote_scene_xr_list.c
  40. 41 42
      scenes/xremote_scene_xr_list_edit.c
  41. 64 50
      scenes/xremote_scene_xr_list_edit_item.c
  42. 37 50
      views/xremote_infoscreen.c
  43. 53 60
      views/xremote_pause_set.c
  44. 139 150
      views/xremote_transmit.c
  45. 23 23
      views/xremote_transmit.h
  46. 45 26
      xremote.c
  47. 1 1
      xremote.h

Разница между файлами не показана из-за своего большого размера
+ 2 - 0
.vscode/compile_commands.json


BIN
dist/debug/xremote_d.elf


BIN
dist/xremote.fap


+ 2 - 1
helpers/xremote_custom_event.h

@@ -57,7 +57,8 @@ static inline uint32_t xremote_custom_menu_event_pack(uint16_t type, int16_t val
     return event.packed_value;
 }
 
-static inline void xremote_custom_menu_event_unpack(uint32_t packed_value, uint16_t* type, int16_t* value) {
+static inline void
+    xremote_custom_menu_event_unpack(uint32_t packed_value, uint16_t* type, int16_t* value) {
     XRemoteCustomEventMenu event = {.packed_value = packed_value};
     if(type) *type = event.content.type;
     if(value) *value = event.content.value;

+ 4 - 5
helpers/xremote_haptic.c

@@ -1,10 +1,9 @@
 #include "xremote_haptic.h"
 #include "../xremote.h"
 
-
 void xremote_play_happy_bump(void* context) {
     XRemote* app = context;
-    if (app->haptic != 1) {
+    if(app->haptic != 1) {
         return;
     }
     notification_message(app->notification, &sequence_set_vibro_on);
@@ -14,7 +13,7 @@ void xremote_play_happy_bump(void* context) {
 
 void xremote_play_bad_bump(void* context) {
     XRemote* app = context;
-    if (app->haptic != 1) {
+    if(app->haptic != 1) {
         return;
     }
     notification_message(app->notification, &sequence_set_vibro_on);
@@ -24,10 +23,10 @@ void xremote_play_bad_bump(void* context) {
 
 void xremote_play_long_bump(void* context) {
     XRemote* app = context;
-    if (app->haptic != 1) {
+    if(app->haptic != 1) {
         return;
     }
-    for (int i = 0; i < 4; i++) {
+    for(int i = 0; i < 4; i++) {
         notification_message(app->notification, &sequence_set_vibro_on);
         furi_thread_flags_wait(0, FuriFlagWaitAny, 50);
         notification_message(app->notification, &sequence_reset_vibro);

+ 0 - 1
helpers/xremote_haptic.h

@@ -7,4 +7,3 @@ void xremote_play_happy_bump(void* context);
 void xremote_play_bad_bump(void* context);
 
 void xremote_play_long_bump(void* context);
-

+ 6 - 4
helpers/xremote_led.c

@@ -2,7 +2,7 @@
 
 void xremote_led_set_rgb(void* context, int red, int green, int blue) {
     XRemote* app = context;
-    if (app->led != 1) {
+    if(app->led != 1) {
         return;
     }
     NotificationMessage notification_led_message_1;
@@ -23,7 +23,8 @@ void xremote_led_set_rgb(void* context, int red, int green, int blue) {
         NULL,
     };
     notification_message(app->notification, &notification_sequence);
-    furi_thread_flags_wait(0, FuriFlagWaitAny, 10); //Delay, prevent removal from RAM before LED value set    
+    furi_thread_flags_wait(
+        0, FuriFlagWaitAny, 10); //Delay, prevent removal from RAM before LED value set
 }
 
 void xremote_led_reset(void* context) {
@@ -31,6 +32,7 @@ void xremote_led_reset(void* context) {
     notification_message(app->notification, &sequence_reset_red);
     notification_message(app->notification, &sequence_reset_green);
     notification_message(app->notification, &sequence_reset_blue);
-    
-    furi_thread_flags_wait(0, FuriFlagWaitAny, 300); //Delay, prevent removal from RAM before LED value set    
+
+    furi_thread_flags_wait(
+        0, FuriFlagWaitAny, 300); //Delay, prevent removal from RAM before LED value set
 }

+ 0 - 1
helpers/xremote_led.h

@@ -5,4 +5,3 @@
 void xremote_led_set_rgb(void* context, int red, int green, int blue);
 
 void xremote_led_reset(void* context);
-

+ 2 - 3
helpers/xremote_speaker.c

@@ -4,19 +4,18 @@
 
 void xremote_play_input_sound(void* context) {
     XRemote* app = context;
-    if (app->speaker != 1) {
+    if(app->speaker != 1) {
         return;
     }
     float volume = 1.0f;
     if(furi_hal_speaker_is_mine() || furi_hal_speaker_acquire(30)) {
         furi_hal_speaker_start(NOTE_INPUT, volume);
     }
-    
 }
 
 void xremote_stop_all_sound(void* context) {
     XRemote* app = context;
-    if (app->speaker != 1) {
+    if(app->speaker != 1) {
         return;
     }
     if(furi_hal_speaker_is_mine()) {

+ 115 - 119
helpers/xremote_storage.c

@@ -1,120 +1,116 @@
-#include "xremote_storage.h"
-
-
-static Storage* xremote_open_storage() {
-    return furi_record_open(RECORD_STORAGE);
-}
-
-static void xremote_close_storage() {
-    furi_record_close(RECORD_STORAGE);
-}
-
-static void xremote_close_config_file(FlipperFormat* file) {
-    if (file == NULL) return;
-    flipper_format_file_close(file);
-    flipper_format_free(file);
-}
-
-void xremote_save_settings(void* context) {
-    XRemote* app = context;
-    if (app->save_settings == 0) {
-        return;
-    }
-
-    FURI_LOG_D(TAG, "Saving Settings");
-    Storage* storage = xremote_open_storage();
-    FlipperFormat* fff_file = flipper_format_file_alloc(storage);
-    
-    // Overwrite wont work, so delete first
-    if(storage_file_exists(storage, XREMOTE_SETTINGS_SAVE_PATH)) {
-        storage_simply_remove(storage, XREMOTE_SETTINGS_SAVE_PATH);
-    }
-
-    // Open File, create if not exists
-    if(!storage_common_stat(storage, XREMOTE_SETTINGS_SAVE_PATH, NULL) == FSE_OK) {
-        FURI_LOG_D(TAG, "Config file %s is not found. Will create new.", XREMOTE_SETTINGS_SAVE_PATH);
-        if(storage_common_stat(storage, CONFIG_FILE_DIRECTORY_PATH, NULL) == FSE_NOT_EXIST) {
-            FURI_LOG_D(
-                TAG,
-                "Directory %s doesn't exist. Will create new.",
-                CONFIG_FILE_DIRECTORY_PATH);
-            if(!storage_simply_mkdir(storage, CONFIG_FILE_DIRECTORY_PATH)) {
-                FURI_LOG_E(TAG, "Error creating directory %s", CONFIG_FILE_DIRECTORY_PATH);
-            }
-        }
-    }
-
-    if(!flipper_format_file_open_new(fff_file, XREMOTE_SETTINGS_SAVE_PATH)) {
-        //totp_close_config_file(fff_file);
-        FURI_LOG_E(TAG, "Error creating new file %s", XREMOTE_SETTINGS_SAVE_PATH);
-        xremote_close_storage();
-        return;
-    }
-    
-    // Store Settings
-    flipper_format_write_header_cstr(
-        fff_file, XREMOTE_SETTINGS_HEADER, XREMOTE_SETTINGS_FILE_VERSION);
-    flipper_format_write_uint32(
-        fff_file, XREMOTE_SETTINGS_KEY_HAPTIC, &app->haptic, 1);
-    flipper_format_write_uint32(
-        fff_file, XREMOTE_SETTINGS_KEY_SPEAKER, &app->speaker, 1);
-    flipper_format_write_uint32(
-        fff_file, XREMOTE_SETTINGS_KEY_LED, &app->led, 1);
-    flipper_format_write_uint32(
-        fff_file, XREMOTE_SETTINGS_KEY_SAVE_SETTINGS, &app->save_settings, 1);
-    
-    if(!flipper_format_rewind(fff_file)) {
-        xremote_close_config_file(fff_file);
-        FURI_LOG_E(TAG, "Rewind error");
-        xremote_close_storage();
-        return;
-    }
-
-    xremote_close_config_file(fff_file);
-    xremote_close_storage();
-}
-
-void xremote_read_settings(void* context) {
-    XRemote* app = context;
-    Storage* storage = xremote_open_storage();
-    FlipperFormat* fff_file = flipper_format_file_alloc(storage);
-
-    if(storage_common_stat(storage, XREMOTE_SETTINGS_SAVE_PATH, NULL) != FSE_OK) {
-        xremote_close_config_file(fff_file);
-        xremote_close_storage();
-        return;
-    }
-    uint32_t file_version;
-    FuriString* temp_str = furi_string_alloc();
-
-    if (!flipper_format_file_open_existing(fff_file, XREMOTE_SETTINGS_SAVE_PATH)) {
-        FURI_LOG_E(TAG, "Cannot open file %s", XREMOTE_SETTINGS_SAVE_PATH);
-        xremote_close_config_file(fff_file);
-        xremote_close_storage();
-        return;
-    }
-
-    if(!flipper_format_read_header(fff_file, temp_str, &file_version)) {
-        FURI_LOG_E(TAG, "Missing Header Data");
-        xremote_close_config_file(fff_file);
-        xremote_close_storage();
-        return;
-    }
-
-    if(file_version < XREMOTE_SETTINGS_FILE_VERSION) {
-        FURI_LOG_I(TAG, "old config version, will be removed.");
-        xremote_close_config_file(fff_file);
-        xremote_close_storage();
-        return;
-    }
-
-    flipper_format_read_uint32(fff_file, XREMOTE_SETTINGS_KEY_HAPTIC, &app->haptic, 1);
-    flipper_format_read_uint32(fff_file, XREMOTE_SETTINGS_KEY_SPEAKER, &app->speaker, 1);
-    flipper_format_read_uint32(fff_file, XREMOTE_SETTINGS_KEY_LED, &app->led, 1);
-    flipper_format_read_uint32(fff_file, XREMOTE_SETTINGS_KEY_SAVE_SETTINGS, &app->save_settings, 1);
-
-    flipper_format_rewind(fff_file);
-
-    xremote_close_config_file(fff_file);
-    xremote_close_storage();
+#include "xremote_storage.h"
+
+static Storage* xremote_open_storage() {
+    return furi_record_open(RECORD_STORAGE);
+}
+
+static void xremote_close_storage() {
+    furi_record_close(RECORD_STORAGE);
+}
+
+static void xremote_close_config_file(FlipperFormat* file) {
+    if(file == NULL) return;
+    flipper_format_file_close(file);
+    flipper_format_free(file);
+}
+
+void xremote_save_settings(void* context) {
+    XRemote* app = context;
+    if(app->save_settings == 0) {
+        return;
+    }
+
+    FURI_LOG_D(TAG, "Saving Settings");
+    Storage* storage = xremote_open_storage();
+    FlipperFormat* fff_file = flipper_format_file_alloc(storage);
+
+    // Overwrite wont work, so delete first
+    if(storage_file_exists(storage, XREMOTE_SETTINGS_SAVE_PATH)) {
+        storage_simply_remove(storage, XREMOTE_SETTINGS_SAVE_PATH);
+    }
+
+    // Open File, create if not exists
+    if(!storage_common_stat(storage, XREMOTE_SETTINGS_SAVE_PATH, NULL) == FSE_OK) {
+        FURI_LOG_D(
+            TAG, "Config file %s is not found. Will create new.", XREMOTE_SETTINGS_SAVE_PATH);
+        if(storage_common_stat(storage, CONFIG_FILE_DIRECTORY_PATH, NULL) == FSE_NOT_EXIST) {
+            FURI_LOG_D(
+                TAG, "Directory %s doesn't exist. Will create new.", CONFIG_FILE_DIRECTORY_PATH);
+            if(!storage_simply_mkdir(storage, CONFIG_FILE_DIRECTORY_PATH)) {
+                FURI_LOG_E(TAG, "Error creating directory %s", CONFIG_FILE_DIRECTORY_PATH);
+            }
+        }
+    }
+
+    if(!flipper_format_file_open_new(fff_file, XREMOTE_SETTINGS_SAVE_PATH)) {
+        //totp_close_config_file(fff_file);
+        FURI_LOG_E(TAG, "Error creating new file %s", XREMOTE_SETTINGS_SAVE_PATH);
+        xremote_close_storage();
+        return;
+    }
+
+    // Store Settings
+    flipper_format_write_header_cstr(
+        fff_file, XREMOTE_SETTINGS_HEADER, XREMOTE_SETTINGS_FILE_VERSION);
+    flipper_format_write_uint32(fff_file, XREMOTE_SETTINGS_KEY_HAPTIC, &app->haptic, 1);
+    flipper_format_write_uint32(fff_file, XREMOTE_SETTINGS_KEY_SPEAKER, &app->speaker, 1);
+    flipper_format_write_uint32(fff_file, XREMOTE_SETTINGS_KEY_LED, &app->led, 1);
+    flipper_format_write_uint32(
+        fff_file, XREMOTE_SETTINGS_KEY_SAVE_SETTINGS, &app->save_settings, 1);
+
+    if(!flipper_format_rewind(fff_file)) {
+        xremote_close_config_file(fff_file);
+        FURI_LOG_E(TAG, "Rewind error");
+        xremote_close_storage();
+        return;
+    }
+
+    xremote_close_config_file(fff_file);
+    xremote_close_storage();
+}
+
+void xremote_read_settings(void* context) {
+    XRemote* app = context;
+    Storage* storage = xremote_open_storage();
+    FlipperFormat* fff_file = flipper_format_file_alloc(storage);
+
+    if(storage_common_stat(storage, XREMOTE_SETTINGS_SAVE_PATH, NULL) != FSE_OK) {
+        xremote_close_config_file(fff_file);
+        xremote_close_storage();
+        return;
+    }
+    uint32_t file_version;
+    FuriString* temp_str = furi_string_alloc();
+
+    if(!flipper_format_file_open_existing(fff_file, XREMOTE_SETTINGS_SAVE_PATH)) {
+        FURI_LOG_E(TAG, "Cannot open file %s", XREMOTE_SETTINGS_SAVE_PATH);
+        xremote_close_config_file(fff_file);
+        xremote_close_storage();
+        return;
+    }
+
+    if(!flipper_format_read_header(fff_file, temp_str, &file_version)) {
+        FURI_LOG_E(TAG, "Missing Header Data");
+        xremote_close_config_file(fff_file);
+        xremote_close_storage();
+        return;
+    }
+
+    if(file_version < XREMOTE_SETTINGS_FILE_VERSION) {
+        FURI_LOG_I(TAG, "old config version, will be removed.");
+        xremote_close_config_file(fff_file);
+        xremote_close_storage();
+        return;
+    }
+
+    flipper_format_read_uint32(fff_file, XREMOTE_SETTINGS_KEY_HAPTIC, &app->haptic, 1);
+    flipper_format_read_uint32(fff_file, XREMOTE_SETTINGS_KEY_SPEAKER, &app->speaker, 1);
+    flipper_format_read_uint32(fff_file, XREMOTE_SETTINGS_KEY_LED, &app->led, 1);
+    flipper_format_read_uint32(
+        fff_file, XREMOTE_SETTINGS_KEY_SAVE_SETTINGS, &app->save_settings, 1);
+
+    flipper_format_rewind(fff_file);
+
+    xremote_close_config_file(fff_file);
+    xremote_close_storage();
 }

+ 15 - 15
helpers/xremote_storage.h

@@ -1,16 +1,16 @@
-#pragma once
-
-#include "../xremote.h"
-
-#define XREMOTE_SETTINGS_FILE_VERSION 1
-#define CONFIG_FILE_DIRECTORY_PATH EXT_PATH("apps_data/xremote")
-#define XREMOTE_SETTINGS_SAVE_PATH CONFIG_FILE_DIRECTORY_PATH "/xremote.conf"
-#define XREMOTE_SETTINGS_SAVE_PATH_TMP XREMOTE_SETTINGS_SAVE_PATH ".tmp"
-#define XREMOTE_SETTINGS_HEADER "Xremote Config File"
-#define XREMOTE_SETTINGS_KEY_HAPTIC "Haptic"
-#define XREMOTE_SETTINGS_KEY_LED "Led"
-#define XREMOTE_SETTINGS_KEY_SPEAKER "Speaker"
-#define XREMOTE_SETTINGS_KEY_SAVE_SETTINGS "SaveSettings"
-
-void xremote_save_settings(void* context);
+#pragma once
+
+#include "../xremote.h"
+
+#define XREMOTE_SETTINGS_FILE_VERSION 1
+#define CONFIG_FILE_DIRECTORY_PATH EXT_PATH("apps_data/xremote")
+#define XREMOTE_SETTINGS_SAVE_PATH CONFIG_FILE_DIRECTORY_PATH "/xremote.conf"
+#define XREMOTE_SETTINGS_SAVE_PATH_TMP XREMOTE_SETTINGS_SAVE_PATH ".tmp"
+#define XREMOTE_SETTINGS_HEADER "Xremote Config File"
+#define XREMOTE_SETTINGS_KEY_HAPTIC "Haptic"
+#define XREMOTE_SETTINGS_KEY_LED "Led"
+#define XREMOTE_SETTINGS_KEY_SPEAKER "Speaker"
+#define XREMOTE_SETTINGS_KEY_SAVE_SETTINGS "SaveSettings"
+
+void xremote_save_settings(void* context);
 void xremote_read_settings(void* context);

+ 261 - 264
models/cross/xremote_remote.c

@@ -1,265 +1,262 @@
-#include "xremote_remote.h"
-
-ARRAY_DEF(CrossRemoteItemArray, CrossRemoteItem*, M_PTR_OPLIST);
-
-struct CrossRemote {
-    FuriString* name;
-    FuriString* path;
-    CrossRemoteItemArray_t items;
-    int transmitting;
-};
-
-static void cross_remote_clear_items(CrossRemote* remote) {
-    CrossRemoteItemArray_it_t it;
-    for(CrossRemoteItemArray_it(it, remote->items); !CrossRemoteItemArray_end_p(it);
-        CrossRemoteItemArray_next(it)) {
-        xremote_remote_item_free(*CrossRemoteItemArray_cref(it));
-    }
-    CrossRemoteItemArray_reset(remote->items);
-}
-
-static void cross_remote_find_vacant_remote_name(FuriString* name, const char* path) {
-    Storage* storage = furi_record_open(RECORD_STORAGE);
-
-    FuriString* base_path;
-    base_path = furi_string_alloc_set(path);
-
-    if(furi_string_end_with(base_path, XREMOTE_APP_EXTENSION)) {
-        size_t filename_start = furi_string_search_rchar(base_path, '/');
-        furi_string_left(base_path, filename_start);
-    }
-
-    furi_string_printf(
-        base_path, "%s/%s%s", path, furi_string_get_cstr(name), XREMOTE_APP_EXTENSION);
-
-    FS_Error status = storage_common_stat(storage, furi_string_get_cstr(base_path), NULL);
-
-    if(status == FSE_OK) {
-        // If name is taken, try another name2, name3 etc
-        size_t dot = furi_string_search_rchar(base_path, '.');
-        furi_string_left(base_path, dot);
-
-        FuriString* path_temp;
-        path_temp = furi_string_alloc();
-
-        uint32_t i = 1;
-        do {
-            furi_string_printf(
-                path_temp, "%s%lu%s", furi_string_get_cstr(base_path), ++i, XREMOTE_APP_EXTENSION);
-            status = storage_common_stat(storage, furi_string_get_cstr(path_temp), NULL);
-        } while(status == FSE_OK);
-
-        furi_string_free(path_temp);
-
-        if(status == FSE_NOT_EXIST) {
-            furi_string_cat_printf(name, "%lu", i);
-        }
-    }
-
-    furi_string_free(base_path);
-    furi_record_close(RECORD_STORAGE);
-}
-
-CrossRemote* cross_remote_alloc() {
-    CrossRemote* remote = malloc(sizeof(CrossRemote));
-    CrossRemoteItemArray_init(remote->items);
-    remote->name = furi_string_alloc();
-    remote->path = furi_string_alloc();
-    remote->transmitting = 0;
-    return remote;
-}
-
-void cross_remote_set_transmitting(CrossRemote* remote, int status) {
-    remote->transmitting = status;
-}
-
-int cross_remote_get_transmitting(CrossRemote* remote) {
-    return remote->transmitting;
-}
-
-void cross_remote_free(CrossRemote* remote) {
-    furi_string_free(remote->name);
-    furi_string_free(remote->path);
-    cross_remote_clear_items(remote);
-    CrossRemoteItemArray_clear(remote->items);
-    free(remote);
-}
-
-const char* cross_remote_get_name(CrossRemote* remote) {
-    return furi_string_get_cstr(remote->name);
-}
-
-bool cross_remote_add_ir_item(CrossRemote* remote, const char* name, InfraredSignal* signal) {
-    CrossRemoteItem* item = xremote_remote_item_alloc();
-    xremote_remote_item_set_type(item, XRemoteRemoteItemTypeInfrared);
-    xremote_remote_item_set_name(item, name);
-    xremote_remote_item_set_ir_signal(item, signal);
-    CrossRemoteItemArray_push_back(remote->items, item);
-    return true;
-}
-
-bool cross_remote_add_pause(CrossRemote* remote, int time) {
-    CrossRemoteItem* item = xremote_remote_item_alloc();
-    xremote_remote_item_set_type(item, XRemoteRemoteItemTypePause);
-    char name[9];
-    snprintf(name, 9, CROSS_REMOTE_PAUSE_NAME, time);
-    xremote_remote_item_set_name(item, name);
-    xremote_remote_item_set_time(item, time);
-    CrossRemoteItemArray_push_back(remote->items, item);
-    return true;
-}
-
-bool cross_remote_add_subghz(CrossRemote* remote, SubGhzRemote* subghz) {
-    UNUSED(subghz);
-    CrossRemoteItem* item = xremote_remote_item_alloc();
-    xremote_remote_item_set_type(item, XRemoteRemoteItemTypeSubGhz);
-    xremote_remote_item_set_name(item, xremote_sg_remote_get_name(subghz));
-    xremote_remote_item_set_sg_signal(item, subghz);
-
-    CrossRemoteItemArray_push_back(remote->items, item);
-    return true;
-}
-
-size_t cross_remote_get_item_count(CrossRemote* remote) {
-    return CrossRemoteItemArray_size(remote->items);
-}
-
-CrossRemoteItem* cross_remote_get_item(CrossRemote* remote, size_t index) {
-    furi_assert(index < CrossRemoteItemArray_size(remote->items));
-    return *CrossRemoteItemArray_get(remote->items, index);
-}
-
-void cross_remote_remove_item(CrossRemote* remote, size_t index) {
-    CrossRemoteItemArray_erase(remote->items, index);
-}
-
-void cross_remote_rename_item(CrossRemote* remote, size_t index, const char* name) {
-    CrossRemoteItem* item = cross_remote_get_item(remote, index);
-    xremote_remote_item_set_name(item, name);
-}
-
-
-bool cross_remote_load(CrossRemote* remote, FuriString* path) {
-    Storage* storage = furi_record_open(RECORD_STORAGE);
-    FlipperFormat* ff = flipper_format_buffered_file_alloc(storage);
-    FuriString* buf;
-    buf = furi_string_alloc();
-
-    FURI_LOG_I(TAG, "loading file: \'%s\'", furi_string_get_cstr(path));
-    bool success = false;
-    do {
-        // File not found
-        if(!flipper_format_buffered_file_open_existing(ff, furi_string_get_cstr(path))) break;
-        uint32_t version;
-        // Read Version & Type
-        if(!flipper_format_read_header(ff, buf, &version)) break;
-        if(!furi_string_equal(buf, XREMOTE_FILE_TYPE) || (version != XREMOTE_FILE_VERSION)) break;
-
-        // Init Remote
-        path_extract_filename(path, buf, true);
-        cross_remote_clear_items(remote);
-        cross_remote_set_name(remote, furi_string_get_cstr(buf));
-        cross_remote_set_path(remote, furi_string_get_cstr(path));
-        // Load Items
-        for(bool can_read = true; can_read;) {
-            CrossRemoteItem* item = xremote_remote_item_alloc();
-            can_read = xremote_remote_item_read(item, ff);
-            if(can_read) {
-                CrossRemoteItemArray_push_back(remote->items, item);
-            } else {
-                xremote_remote_item_free(item);
-            }
-        }
-        success = true;
-    } while(false);
-
-    furi_string_free(buf);
-    flipper_format_free(ff);
-    furi_record_close(RECORD_STORAGE);
-    return success;
-}
-
-void cross_remote_set_name(CrossRemote* remote, const char* name) {
-    furi_string_set(remote->name, name);
-}
-
-void cross_remote_set_path(CrossRemote* remote, const char* path) {
-    furi_string_set(remote->path, path);
-}
-
-bool cross_remote_save_new(CrossRemote* remote, const char* name) {
-    FuriString *new_name, *new_path;
-    new_name = furi_string_alloc_set(name);
-    new_path = furi_string_alloc_set(XREMOTE_APP_FOLDER);
-    
-    cross_remote_find_vacant_remote_name(new_name, furi_string_get_cstr(new_path));
-    furi_string_cat_printf(
-        new_path, "/%s%s", furi_string_get_cstr(new_name), XREMOTE_APP_EXTENSION);
-
-    cross_remote_set_name(remote, furi_string_get_cstr(new_name));
-    cross_remote_set_path(remote, furi_string_get_cstr(new_path));
-
-    furi_string_free(new_name);
-    furi_string_free(new_path);
-    return cross_remote_store(remote);
-}
-
-void cross_remote_reset(CrossRemote* remote) {
-    furi_string_reset(remote->name);
-    furi_string_reset(remote->path);
-    CrossRemoteItemArray_clear(remote->items);
-    remote->transmitting = 0;
-}
-
-bool cross_remote_delete(CrossRemote* remote) {
-    Storage* storage = furi_record_open(RECORD_STORAGE);
-    FS_Error status = storage_common_remove(storage, furi_string_get_cstr(remote->path));
-
-    cross_remote_reset(remote);
-
-    furi_record_close(RECORD_STORAGE);
-    return (status == FSE_OK || status == FSE_NOT_EXIST);
-}
-
-bool cross_remote_store(CrossRemote* remote) {
-    Storage* storage = furi_record_open(RECORD_STORAGE);
-    FlipperFormat* ff = flipper_format_file_alloc(storage);
-    const char* path = furi_string_get_cstr(remote->path);
-
-    FURI_LOG_I(TAG, "Storing file: \'%s\'", path);
-
-    bool success = flipper_format_file_open_always(ff, path) &&
-                   flipper_format_write_header_cstr(ff, XREMOTE_FILE_TYPE, XREMOTE_FILE_VERSION);
-
-    // save Items
-    if(success) {
-        CrossRemoteItemArray_it_t it;
-        for(CrossRemoteItemArray_it(it, remote->items); !CrossRemoteItemArray_end_p(it);
-            CrossRemoteItemArray_next(it)) {
-            CrossRemoteItem* item = *CrossRemoteItemArray_cref(it);
-            success = false;
-            if (item->type == XRemoteRemoteItemTypeInfrared) {
-                success = xremote_ir_signal_save(
-                    xremote_remote_item_get_ir_signal(item),
-                    ff,
-                    xremote_remote_item_get_name(item));
-            } else if(item->type == XRemoteRemoteItemTypePause) {
-                success = xremote_pause_save(ff, 
-                    item->time,
-                    xremote_remote_item_get_name(item));
-            } else if(item->type == XRemoteRemoteItemTypeSubGhz) {
-                success = xremote_sg_signal_save(
-                    xremote_remote_item_get_sg_signal(item),
-                    ff,
-                    xremote_remote_item_get_name(item));
-            }
-            if(!success) {
-                break;
-            }
-        }
-    }
-
-    flipper_format_free(ff);
-    furi_record_close(RECORD_STORAGE);
-    return success;
+#include "xremote_remote.h"
+
+ARRAY_DEF(CrossRemoteItemArray, CrossRemoteItem*, M_PTR_OPLIST);
+
+struct CrossRemote {
+    FuriString* name;
+    FuriString* path;
+    CrossRemoteItemArray_t items;
+    int transmitting;
+};
+
+static void cross_remote_clear_items(CrossRemote* remote) {
+    CrossRemoteItemArray_it_t it;
+    for(CrossRemoteItemArray_it(it, remote->items); !CrossRemoteItemArray_end_p(it);
+        CrossRemoteItemArray_next(it)) {
+        xremote_remote_item_free(*CrossRemoteItemArray_cref(it));
+    }
+    CrossRemoteItemArray_reset(remote->items);
+}
+
+static void cross_remote_find_vacant_remote_name(FuriString* name, const char* path) {
+    Storage* storage = furi_record_open(RECORD_STORAGE);
+
+    FuriString* base_path;
+    base_path = furi_string_alloc_set(path);
+
+    if(furi_string_end_with(base_path, XREMOTE_APP_EXTENSION)) {
+        size_t filename_start = furi_string_search_rchar(base_path, '/');
+        furi_string_left(base_path, filename_start);
+    }
+
+    furi_string_printf(
+        base_path, "%s/%s%s", path, furi_string_get_cstr(name), XREMOTE_APP_EXTENSION);
+
+    FS_Error status = storage_common_stat(storage, furi_string_get_cstr(base_path), NULL);
+
+    if(status == FSE_OK) {
+        // If name is taken, try another name2, name3 etc
+        size_t dot = furi_string_search_rchar(base_path, '.');
+        furi_string_left(base_path, dot);
+
+        FuriString* path_temp;
+        path_temp = furi_string_alloc();
+
+        uint32_t i = 1;
+        do {
+            furi_string_printf(
+                path_temp, "%s%lu%s", furi_string_get_cstr(base_path), ++i, XREMOTE_APP_EXTENSION);
+            status = storage_common_stat(storage, furi_string_get_cstr(path_temp), NULL);
+        } while(status == FSE_OK);
+
+        furi_string_free(path_temp);
+
+        if(status == FSE_NOT_EXIST) {
+            furi_string_cat_printf(name, "%lu", i);
+        }
+    }
+
+    furi_string_free(base_path);
+    furi_record_close(RECORD_STORAGE);
+}
+
+CrossRemote* cross_remote_alloc() {
+    CrossRemote* remote = malloc(sizeof(CrossRemote));
+    CrossRemoteItemArray_init(remote->items);
+    remote->name = furi_string_alloc();
+    remote->path = furi_string_alloc();
+    remote->transmitting = 0;
+    return remote;
+}
+
+void cross_remote_set_transmitting(CrossRemote* remote, int status) {
+    remote->transmitting = status;
+}
+
+int cross_remote_get_transmitting(CrossRemote* remote) {
+    return remote->transmitting;
+}
+
+void cross_remote_free(CrossRemote* remote) {
+    furi_string_free(remote->name);
+    furi_string_free(remote->path);
+    cross_remote_clear_items(remote);
+    CrossRemoteItemArray_clear(remote->items);
+    free(remote);
+}
+
+const char* cross_remote_get_name(CrossRemote* remote) {
+    return furi_string_get_cstr(remote->name);
+}
+
+bool cross_remote_add_ir_item(CrossRemote* remote, const char* name, InfraredSignal* signal) {
+    CrossRemoteItem* item = xremote_remote_item_alloc();
+    xremote_remote_item_set_type(item, XRemoteRemoteItemTypeInfrared);
+    xremote_remote_item_set_name(item, name);
+    xremote_remote_item_set_ir_signal(item, signal);
+    CrossRemoteItemArray_push_back(remote->items, item);
+    return true;
+}
+
+bool cross_remote_add_pause(CrossRemote* remote, int time) {
+    CrossRemoteItem* item = xremote_remote_item_alloc();
+    xremote_remote_item_set_type(item, XRemoteRemoteItemTypePause);
+    char name[9];
+    snprintf(name, 9, CROSS_REMOTE_PAUSE_NAME, time);
+    xremote_remote_item_set_name(item, name);
+    xremote_remote_item_set_time(item, time);
+    CrossRemoteItemArray_push_back(remote->items, item);
+    return true;
+}
+
+bool cross_remote_add_subghz(CrossRemote* remote, SubGhzRemote* subghz) {
+    UNUSED(subghz);
+    CrossRemoteItem* item = xremote_remote_item_alloc();
+    xremote_remote_item_set_type(item, XRemoteRemoteItemTypeSubGhz);
+    xremote_remote_item_set_name(item, xremote_sg_remote_get_name(subghz));
+    xremote_remote_item_set_sg_signal(item, subghz);
+
+    CrossRemoteItemArray_push_back(remote->items, item);
+    return true;
+}
+
+size_t cross_remote_get_item_count(CrossRemote* remote) {
+    return CrossRemoteItemArray_size(remote->items);
+}
+
+CrossRemoteItem* cross_remote_get_item(CrossRemote* remote, size_t index) {
+    furi_assert(index < CrossRemoteItemArray_size(remote->items));
+    return *CrossRemoteItemArray_get(remote->items, index);
+}
+
+void cross_remote_remove_item(CrossRemote* remote, size_t index) {
+    CrossRemoteItemArray_erase(remote->items, index);
+}
+
+void cross_remote_rename_item(CrossRemote* remote, size_t index, const char* name) {
+    CrossRemoteItem* item = cross_remote_get_item(remote, index);
+    xremote_remote_item_set_name(item, name);
+}
+
+bool cross_remote_load(CrossRemote* remote, FuriString* path) {
+    Storage* storage = furi_record_open(RECORD_STORAGE);
+    FlipperFormat* ff = flipper_format_buffered_file_alloc(storage);
+    FuriString* buf;
+    buf = furi_string_alloc();
+
+    FURI_LOG_I(TAG, "loading file: \'%s\'", furi_string_get_cstr(path));
+    bool success = false;
+    do {
+        // File not found
+        if(!flipper_format_buffered_file_open_existing(ff, furi_string_get_cstr(path))) break;
+        uint32_t version;
+        // Read Version & Type
+        if(!flipper_format_read_header(ff, buf, &version)) break;
+        if(!furi_string_equal(buf, XREMOTE_FILE_TYPE) || (version != XREMOTE_FILE_VERSION)) break;
+
+        // Init Remote
+        path_extract_filename(path, buf, true);
+        cross_remote_clear_items(remote);
+        cross_remote_set_name(remote, furi_string_get_cstr(buf));
+        cross_remote_set_path(remote, furi_string_get_cstr(path));
+        // Load Items
+        for(bool can_read = true; can_read;) {
+            CrossRemoteItem* item = xremote_remote_item_alloc();
+            can_read = xremote_remote_item_read(item, ff);
+            if(can_read) {
+                CrossRemoteItemArray_push_back(remote->items, item);
+            } else {
+                xremote_remote_item_free(item);
+            }
+        }
+        success = true;
+    } while(false);
+
+    furi_string_free(buf);
+    flipper_format_free(ff);
+    furi_record_close(RECORD_STORAGE);
+    return success;
+}
+
+void cross_remote_set_name(CrossRemote* remote, const char* name) {
+    furi_string_set(remote->name, name);
+}
+
+void cross_remote_set_path(CrossRemote* remote, const char* path) {
+    furi_string_set(remote->path, path);
+}
+
+bool cross_remote_save_new(CrossRemote* remote, const char* name) {
+    FuriString *new_name, *new_path;
+    new_name = furi_string_alloc_set(name);
+    new_path = furi_string_alloc_set(XREMOTE_APP_FOLDER);
+
+    cross_remote_find_vacant_remote_name(new_name, furi_string_get_cstr(new_path));
+    furi_string_cat_printf(
+        new_path, "/%s%s", furi_string_get_cstr(new_name), XREMOTE_APP_EXTENSION);
+
+    cross_remote_set_name(remote, furi_string_get_cstr(new_name));
+    cross_remote_set_path(remote, furi_string_get_cstr(new_path));
+
+    furi_string_free(new_name);
+    furi_string_free(new_path);
+    return cross_remote_store(remote);
+}
+
+void cross_remote_reset(CrossRemote* remote) {
+    furi_string_reset(remote->name);
+    furi_string_reset(remote->path);
+    CrossRemoteItemArray_clear(remote->items);
+    remote->transmitting = 0;
+}
+
+bool cross_remote_delete(CrossRemote* remote) {
+    Storage* storage = furi_record_open(RECORD_STORAGE);
+    FS_Error status = storage_common_remove(storage, furi_string_get_cstr(remote->path));
+
+    cross_remote_reset(remote);
+
+    furi_record_close(RECORD_STORAGE);
+    return (status == FSE_OK || status == FSE_NOT_EXIST);
+}
+
+bool cross_remote_store(CrossRemote* remote) {
+    Storage* storage = furi_record_open(RECORD_STORAGE);
+    FlipperFormat* ff = flipper_format_file_alloc(storage);
+    const char* path = furi_string_get_cstr(remote->path);
+
+    FURI_LOG_I(TAG, "Storing file: \'%s\'", path);
+
+    bool success = flipper_format_file_open_always(ff, path) &&
+                   flipper_format_write_header_cstr(ff, XREMOTE_FILE_TYPE, XREMOTE_FILE_VERSION);
+
+    // save Items
+    if(success) {
+        CrossRemoteItemArray_it_t it;
+        for(CrossRemoteItemArray_it(it, remote->items); !CrossRemoteItemArray_end_p(it);
+            CrossRemoteItemArray_next(it)) {
+            CrossRemoteItem* item = *CrossRemoteItemArray_cref(it);
+            success = false;
+            if(item->type == XRemoteRemoteItemTypeInfrared) {
+                success = xremote_ir_signal_save(
+                    xremote_remote_item_get_ir_signal(item),
+                    ff,
+                    xremote_remote_item_get_name(item));
+            } else if(item->type == XRemoteRemoteItemTypePause) {
+                success = xremote_pause_save(ff, item->time, xremote_remote_item_get_name(item));
+            } else if(item->type == XRemoteRemoteItemTypeSubGhz) {
+                success = xremote_sg_signal_save(
+                    xremote_remote_item_get_sg_signal(item),
+                    ff,
+                    xremote_remote_item_get_name(item));
+            }
+            if(!success) {
+                break;
+            }
+        }
+    }
+
+    flipper_format_free(ff);
+    furi_record_close(RECORD_STORAGE);
+    return success;
 }

+ 27 - 27
models/cross/xremote_remote.h

@@ -1,28 +1,28 @@
-#pragma once
-
-#include "xremote_remote_item.h"
-#include "../../xremote_i.h"
-
-#define CROSS_REMOTE_PAUSE_NAME "Pause %ds"
-
-CrossRemote* cross_remote_alloc();
-
-void cross_remote_free(CrossRemote* cross_remote);
-bool cross_remote_load(CrossRemote* cross_remote, FuriString* path);
-const char* cross_remote_get_name(CrossRemote* remote);
-void cross_remote_set_transmitting(CrossRemote* remote, int status);
-int cross_remote_get_transmitting(CrossRemote* remote);
-bool cross_remote_add_pause(CrossRemote* remote, int time);
-bool cross_remote_add_ir_item(CrossRemote* remote, const char* name, InfraredSignal* signal);
-bool cross_remote_add_subghz(CrossRemote* remote, SubGhzRemote* subghz);
-void cross_remote_remove_item(CrossRemote* remote, size_t index);
-void cross_remote_rename_item(CrossRemote* remote, size_t index, const char* name);
-size_t cross_remote_get_item_count(CrossRemote* remote);
-CrossRemoteItem* cross_remote_get_item(CrossRemote* remote, size_t index);
-
-void cross_remote_set_name(CrossRemote* remote, const char* name);
-void cross_remote_set_path(CrossRemote* remote, const char* path);
-bool cross_remote_save_new(CrossRemote* remote, const char* name);
-bool cross_remote_store(CrossRemote* remote);
-void cross_remote_reset(CrossRemote* remote);
+#pragma once
+
+#include "xremote_remote_item.h"
+#include "../../xremote_i.h"
+
+#define CROSS_REMOTE_PAUSE_NAME "Pause %ds"
+
+CrossRemote* cross_remote_alloc();
+
+void cross_remote_free(CrossRemote* cross_remote);
+bool cross_remote_load(CrossRemote* cross_remote, FuriString* path);
+const char* cross_remote_get_name(CrossRemote* remote);
+void cross_remote_set_transmitting(CrossRemote* remote, int status);
+int cross_remote_get_transmitting(CrossRemote* remote);
+bool cross_remote_add_pause(CrossRemote* remote, int time);
+bool cross_remote_add_ir_item(CrossRemote* remote, const char* name, InfraredSignal* signal);
+bool cross_remote_add_subghz(CrossRemote* remote, SubGhzRemote* subghz);
+void cross_remote_remove_item(CrossRemote* remote, size_t index);
+void cross_remote_rename_item(CrossRemote* remote, size_t index, const char* name);
+size_t cross_remote_get_item_count(CrossRemote* remote);
+CrossRemoteItem* cross_remote_get_item(CrossRemote* remote, size_t index);
+
+void cross_remote_set_name(CrossRemote* remote, const char* name);
+void cross_remote_set_path(CrossRemote* remote, const char* path);
+bool cross_remote_save_new(CrossRemote* remote, const char* name);
+bool cross_remote_store(CrossRemote* remote);
+void cross_remote_reset(CrossRemote* remote);
 bool cross_remote_delete(CrossRemote* remote);

+ 240 - 241
models/cross/xremote_remote_item.c

@@ -1,241 +1,240 @@
-#include "xremote_remote_item.h"
-
-
-CrossRemoteItem* xremote_remote_item_alloc() {
-    CrossRemoteItem* item = malloc(sizeof(CrossRemoteItem));
-    item->name = furi_string_alloc();
-    item->time = 0;
-    item->type = 0;
-    item->ir_signal = xremote_ir_signal_alloc();
-    item->sg_signal = xremote_sg_remote_alloc();
-    
-    return item;
-}
-
-static inline bool xremote_ir_signal_save_message(InfraredMessage* message, FlipperFormat* ff) {
-    const char* protocol_name = infrared_get_protocol_name(message->protocol);
-    return flipper_format_write_string_cstr(ff, "type", "parsed") &&
-           flipper_format_write_string_cstr(ff, "protocol", protocol_name) &&
-           flipper_format_write_hex(ff, "address", (uint8_t*)&message->address, 4) &&
-           flipper_format_write_hex(ff, "command", (uint8_t*)&message->command, 4);
-}
-
-static inline bool xremote_ir_signal_save_raw(InfraredRawSignal* raw, FlipperFormat* ff) {
-    furi_assert(raw->timings_size <= MAX_TIMINGS_AMOUNT);
-    return flipper_format_write_string_cstr(ff, "type", "raw") &&
-           flipper_format_write_uint32(ff, "frequency", &raw->frequency, 1) &&
-           flipper_format_write_float(ff, "duty_cycle", &raw->duty_cycle, 1) &&
-           flipper_format_write_uint32(ff, "data", raw->timings, raw->timings_size);
-}
-
-static inline bool xremote_sg_signal_save_data(SubGhzRemote* remote, FlipperFormat* ff) {
-    UNUSED(remote);
-    UNUSED(ff);
-    return true;
-    /*return flipper_format_write_uint32(ff, "frequency", xremote_sg_remote_get_frequency(remote)) &&
-           flipper_format_write_string_cstr(ff, "preset", xremote_sg_remote_get_preset(remote));*/
-}
-
-static bool xremote_ir_signal_is_message_valid(InfraredMessage* message) {
-    if(!infrared_is_protocol_valid(message->protocol)) {
-        FURI_LOG_E(TAG, "Unknown protocol");
-        return false;
-    }
-
-    uint32_t address_length = infrared_get_protocol_address_length(message->protocol);
-    uint32_t address_mask = (1UL << address_length) - 1;
-
-    if(message->address != (message->address & address_mask)) {
-        FURI_LOG_E(
-            TAG,
-            "Address is out of range (mask 0x%08lX): 0x%lX\r\n",
-            address_mask,
-            message->address);
-        return false;
-    }
-
-    uint32_t command_length = infrared_get_protocol_command_length(message->protocol);
-    uint32_t command_mask = (1UL << command_length) - 1;
-
-    if(message->command != (message->command & command_mask)) {
-        FURI_LOG_E(
-            TAG,
-            "Command is out of range (mask 0x%08lX): 0x%lX\r\n",
-            command_mask,
-            message->command);
-        return false;
-    }
-
-    return true;
-}
-
-bool xremote_remote_item_read(CrossRemoteItem* item, FlipperFormat* ff) {
-    FuriString* type = furi_string_alloc();
-    bool success = false;
-    do {
-        if(!flipper_format_read_string(ff, "remote_type", type)) break;
-        if(furi_string_equal(type, "IR")) {
-            success = xremote_remote_item_read_ir(item, ff);
-        } else if(furi_string_equal(type, "PAUSE")) {
-            success = xremote_remote_item_read_pause(item, ff);
-        } else {
-            break;
-        }
-        success = true;
-    } while(false);
-    return success;
-}
-
-bool xremote_remote_item_read_ir(CrossRemoteItem* item, FlipperFormat* ff) {
-    FuriString* buf;
-    bool success = false;
-    buf = furi_string_alloc();
-    item->type = XRemoteRemoteItemTypeInfrared;
-    item->time = 0;
-    
-    do {
-        if(!flipper_format_read_string(ff, "name", item->name)) break;
-        if(!flipper_format_read_string(ff, "type", buf)) break;
-        if(furi_string_equal(buf, "raw")) {
-            if(!xremote_remote_item_read_ir_signal_raw(item, ff)) break;
-        } else if(furi_string_equal(buf, "parsed")) {
-            if(!xremote_remote_item_read_message(item, ff)) break;
-        } else {
-            break;
-        }
-        success = true;
-    } while(false);
-    furi_string_free(buf);
-
-    return success;
-}
-
-bool xremote_remote_item_read_pause(CrossRemoteItem* item, FlipperFormat* ff) {
-    bool success = false;
-    item->type = XRemoteRemoteItemTypePause;
-
-    do {
-        if(!flipper_format_read_string(ff, "name", item->name)) break;
-        if(!flipper_format_read_int32(ff, "time", &item->time, 1)) break;
-        success = true;
-    } while(false);
-
-    return success;
-}
-
-bool xremote_remote_item_read_ir_signal_raw(CrossRemoteItem* item, FlipperFormat* ff) {
-    uint32_t timings_size, frequency;
-    float duty_cycle;
-
-    bool success = flipper_format_read_uint32(ff, "frequency", &frequency, 1) &&
-                   flipper_format_read_float(ff, "duty_cycle", &duty_cycle, 1) &&
-                   flipper_format_get_value_count(ff, "data", &timings_size);
-
-    if(!success || timings_size > MAX_TIMINGS_AMOUNT) {
-        return false;
-    }
-
-    uint32_t* timings = malloc(sizeof(uint32_t) * timings_size);
-    success = flipper_format_read_uint32(ff, "data", timings, timings_size);
-
-    if(success) {
-        xremote_ir_signal_set_raw_signal(item->ir_signal, timings, timings_size, frequency, duty_cycle);
-    }
-
-    free(timings);
-
-    return success;
-}
-
-bool xremote_remote_item_read_message(CrossRemoteItem* item, FlipperFormat* ff) {
-    FuriString* buf = furi_string_alloc();
-    bool success = false;
-
-    do {
-        if(!flipper_format_read_string(ff, "protocol", buf)) break;
-        InfraredMessage message;
-        message.protocol = infrared_get_protocol_by_name(furi_string_get_cstr(buf));
-        success = flipper_format_read_hex(ff, "address", (uint8_t*)&message.address, 4) &&
-                  flipper_format_read_hex(ff, "command", (uint8_t*)&message.command, 4) &&
-                  xremote_ir_signal_is_message_valid(&message);
-
-        if(!success) break;
-
-        xremote_ir_signal_set_message(item->ir_signal, &message);
-    } while(false);
-
-    furi_string_free(buf);
-    return success;
-}
-
-
-void xremote_remote_item_free(CrossRemoteItem* item) {
-    furi_string_free(item->name);
-    //Determine type before free
-    //xremote_ir_signal_free(item->ir_signal);
-    //xremote_sg_remote_free(item->sg_signal);
-    free(item);
-}
-
-void xremote_remote_item_set_type(CrossRemoteItem* item, int type) {
-    item->type = type;
-}
-
-void xremote_remote_item_set_name(CrossRemoteItem* item, const char* name) {
-    furi_string_set(item->name, name);
-}
-
-void xremote_remote_item_set_time(CrossRemoteItem* item, int32_t time) {
-    item->time = time;
-}
-
-void xremote_remote_item_set_ir_signal(CrossRemoteItem* item, InfraredSignal* signal) {
-    xremote_ir_signal_set_signal(item->ir_signal, signal);
-}
-
-void xremote_remote_item_set_sg_signal(CrossRemoteItem* item, SubGhzRemote* subghz) {
-    item->sg_signal = subghz;
-}
-
-const char* xremote_remote_item_get_name(CrossRemoteItem* item) {
-    return furi_string_get_cstr(item->name);
-}
-
-InfraredSignal* xremote_remote_item_get_ir_signal(CrossRemoteItem* item) {
-    return item->ir_signal;
-}
-
-SubGhzRemote* xremote_remote_item_get_sg_signal(CrossRemoteItem* item) {
-    return item->sg_signal;
-}
-
-bool xremote_ir_signal_save(InfraredSignal* signal, FlipperFormat* ff, const char* name) {
-    if(!flipper_format_write_comment_cstr(ff, "") || 
-       !flipper_format_write_string_cstr(ff, "remote_type", "IR") || 
-       !flipper_format_write_string_cstr(ff, "name", name)) {
-        return false;
-    } else if(signal->is_raw) {
-        return xremote_ir_signal_save_raw(&signal->payload.raw, ff);
-    } else {
-        return xremote_ir_signal_save_message(&signal->payload.message, ff);
-    }
-}
-
-bool xremote_pause_save(FlipperFormat* ff, int32_t time, const char* name) {
-    if(!flipper_format_write_comment_cstr(ff, "") ||
-       !flipper_format_write_string_cstr(ff, "remote_type", "PAUSE") ||
-       !flipper_format_write_string_cstr(ff, "name", name) || 
-       !flipper_format_write_int32(ff, "time", &time, 1)) {
-       return false;
-    }
-    return true;
-}
-
-bool xremote_sg_signal_save(SubGhzRemote* remote, FlipperFormat* ff, const char* name) {
-    if(!flipper_format_write_comment_cstr(ff, "") || 
-       !flipper_format_write_string_cstr(ff, "remote_type", "SG") || 
-       !flipper_format_write_string_cstr(ff, "name", name)) {
-        return false;
-    }
-    return xremote_sg_signal_save_data(remote, ff);
-}
+#include "xremote_remote_item.h"
+
+CrossRemoteItem* xremote_remote_item_alloc() {
+    CrossRemoteItem* item = malloc(sizeof(CrossRemoteItem));
+    item->name = furi_string_alloc();
+    item->time = 0;
+    item->type = 0;
+    item->ir_signal = xremote_ir_signal_alloc();
+    item->sg_signal = xremote_sg_remote_alloc();
+
+    return item;
+}
+
+static inline bool xremote_ir_signal_save_message(InfraredMessage* message, FlipperFormat* ff) {
+    const char* protocol_name = infrared_get_protocol_name(message->protocol);
+    return flipper_format_write_string_cstr(ff, "type", "parsed") &&
+           flipper_format_write_string_cstr(ff, "protocol", protocol_name) &&
+           flipper_format_write_hex(ff, "address", (uint8_t*)&message->address, 4) &&
+           flipper_format_write_hex(ff, "command", (uint8_t*)&message->command, 4);
+}
+
+static inline bool xremote_ir_signal_save_raw(InfraredRawSignal* raw, FlipperFormat* ff) {
+    furi_assert(raw->timings_size <= MAX_TIMINGS_AMOUNT);
+    return flipper_format_write_string_cstr(ff, "type", "raw") &&
+           flipper_format_write_uint32(ff, "frequency", &raw->frequency, 1) &&
+           flipper_format_write_float(ff, "duty_cycle", &raw->duty_cycle, 1) &&
+           flipper_format_write_uint32(ff, "data", raw->timings, raw->timings_size);
+}
+
+static inline bool xremote_sg_signal_save_data(SubGhzRemote* remote, FlipperFormat* ff) {
+    UNUSED(remote);
+    UNUSED(ff);
+    return true;
+    /*return flipper_format_write_uint32(ff, "frequency", xremote_sg_remote_get_frequency(remote)) &&
+           flipper_format_write_string_cstr(ff, "preset", xremote_sg_remote_get_preset(remote));*/
+}
+
+static bool xremote_ir_signal_is_message_valid(InfraredMessage* message) {
+    if(!infrared_is_protocol_valid(message->protocol)) {
+        FURI_LOG_E(TAG, "Unknown protocol");
+        return false;
+    }
+
+    uint32_t address_length = infrared_get_protocol_address_length(message->protocol);
+    uint32_t address_mask = (1UL << address_length) - 1;
+
+    if(message->address != (message->address & address_mask)) {
+        FURI_LOG_E(
+            TAG,
+            "Address is out of range (mask 0x%08lX): 0x%lX\r\n",
+            address_mask,
+            message->address);
+        return false;
+    }
+
+    uint32_t command_length = infrared_get_protocol_command_length(message->protocol);
+    uint32_t command_mask = (1UL << command_length) - 1;
+
+    if(message->command != (message->command & command_mask)) {
+        FURI_LOG_E(
+            TAG,
+            "Command is out of range (mask 0x%08lX): 0x%lX\r\n",
+            command_mask,
+            message->command);
+        return false;
+    }
+
+    return true;
+}
+
+bool xremote_remote_item_read(CrossRemoteItem* item, FlipperFormat* ff) {
+    FuriString* type = furi_string_alloc();
+    bool success = false;
+    do {
+        if(!flipper_format_read_string(ff, "remote_type", type)) break;
+        if(furi_string_equal(type, "IR")) {
+            success = xremote_remote_item_read_ir(item, ff);
+        } else if(furi_string_equal(type, "PAUSE")) {
+            success = xremote_remote_item_read_pause(item, ff);
+        } else {
+            break;
+        }
+        success = true;
+    } while(false);
+    return success;
+}
+
+bool xremote_remote_item_read_ir(CrossRemoteItem* item, FlipperFormat* ff) {
+    FuriString* buf;
+    bool success = false;
+    buf = furi_string_alloc();
+    item->type = XRemoteRemoteItemTypeInfrared;
+    item->time = 0;
+
+    do {
+        if(!flipper_format_read_string(ff, "name", item->name)) break;
+        if(!flipper_format_read_string(ff, "type", buf)) break;
+        if(furi_string_equal(buf, "raw")) {
+            if(!xremote_remote_item_read_ir_signal_raw(item, ff)) break;
+        } else if(furi_string_equal(buf, "parsed")) {
+            if(!xremote_remote_item_read_message(item, ff)) break;
+        } else {
+            break;
+        }
+        success = true;
+    } while(false);
+    furi_string_free(buf);
+
+    return success;
+}
+
+bool xremote_remote_item_read_pause(CrossRemoteItem* item, FlipperFormat* ff) {
+    bool success = false;
+    item->type = XRemoteRemoteItemTypePause;
+
+    do {
+        if(!flipper_format_read_string(ff, "name", item->name)) break;
+        if(!flipper_format_read_int32(ff, "time", &item->time, 1)) break;
+        success = true;
+    } while(false);
+
+    return success;
+}
+
+bool xremote_remote_item_read_ir_signal_raw(CrossRemoteItem* item, FlipperFormat* ff) {
+    uint32_t timings_size, frequency;
+    float duty_cycle;
+
+    bool success = flipper_format_read_uint32(ff, "frequency", &frequency, 1) &&
+                   flipper_format_read_float(ff, "duty_cycle", &duty_cycle, 1) &&
+                   flipper_format_get_value_count(ff, "data", &timings_size);
+
+    if(!success || timings_size > MAX_TIMINGS_AMOUNT) {
+        return false;
+    }
+
+    uint32_t* timings = malloc(sizeof(uint32_t) * timings_size);
+    success = flipper_format_read_uint32(ff, "data", timings, timings_size);
+
+    if(success) {
+        xremote_ir_signal_set_raw_signal(
+            item->ir_signal, timings, timings_size, frequency, duty_cycle);
+    }
+
+    free(timings);
+
+    return success;
+}
+
+bool xremote_remote_item_read_message(CrossRemoteItem* item, FlipperFormat* ff) {
+    FuriString* buf = furi_string_alloc();
+    bool success = false;
+
+    do {
+        if(!flipper_format_read_string(ff, "protocol", buf)) break;
+        InfraredMessage message;
+        message.protocol = infrared_get_protocol_by_name(furi_string_get_cstr(buf));
+        success = flipper_format_read_hex(ff, "address", (uint8_t*)&message.address, 4) &&
+                  flipper_format_read_hex(ff, "command", (uint8_t*)&message.command, 4) &&
+                  xremote_ir_signal_is_message_valid(&message);
+
+        if(!success) break;
+
+        xremote_ir_signal_set_message(item->ir_signal, &message);
+    } while(false);
+
+    furi_string_free(buf);
+    return success;
+}
+
+void xremote_remote_item_free(CrossRemoteItem* item) {
+    furi_string_free(item->name);
+    //Determine type before free
+    //xremote_ir_signal_free(item->ir_signal);
+    //xremote_sg_remote_free(item->sg_signal);
+    free(item);
+}
+
+void xremote_remote_item_set_type(CrossRemoteItem* item, int type) {
+    item->type = type;
+}
+
+void xremote_remote_item_set_name(CrossRemoteItem* item, const char* name) {
+    furi_string_set(item->name, name);
+}
+
+void xremote_remote_item_set_time(CrossRemoteItem* item, int32_t time) {
+    item->time = time;
+}
+
+void xremote_remote_item_set_ir_signal(CrossRemoteItem* item, InfraredSignal* signal) {
+    xremote_ir_signal_set_signal(item->ir_signal, signal);
+}
+
+void xremote_remote_item_set_sg_signal(CrossRemoteItem* item, SubGhzRemote* subghz) {
+    item->sg_signal = subghz;
+}
+
+const char* xremote_remote_item_get_name(CrossRemoteItem* item) {
+    return furi_string_get_cstr(item->name);
+}
+
+InfraredSignal* xremote_remote_item_get_ir_signal(CrossRemoteItem* item) {
+    return item->ir_signal;
+}
+
+SubGhzRemote* xremote_remote_item_get_sg_signal(CrossRemoteItem* item) {
+    return item->sg_signal;
+}
+
+bool xremote_ir_signal_save(InfraredSignal* signal, FlipperFormat* ff, const char* name) {
+    if(!flipper_format_write_comment_cstr(ff, "") ||
+       !flipper_format_write_string_cstr(ff, "remote_type", "IR") ||
+       !flipper_format_write_string_cstr(ff, "name", name)) {
+        return false;
+    } else if(signal->is_raw) {
+        return xremote_ir_signal_save_raw(&signal->payload.raw, ff);
+    } else {
+        return xremote_ir_signal_save_message(&signal->payload.message, ff);
+    }
+}
+
+bool xremote_pause_save(FlipperFormat* ff, int32_t time, const char* name) {
+    if(!flipper_format_write_comment_cstr(ff, "") ||
+       !flipper_format_write_string_cstr(ff, "remote_type", "PAUSE") ||
+       !flipper_format_write_string_cstr(ff, "name", name) ||
+       !flipper_format_write_int32(ff, "time", &time, 1)) {
+        return false;
+    }
+    return true;
+}
+
+bool xremote_sg_signal_save(SubGhzRemote* remote, FlipperFormat* ff, const char* name) {
+    if(!flipper_format_write_comment_cstr(ff, "") ||
+       !flipper_format_write_string_cstr(ff, "remote_type", "SG") ||
+       !flipper_format_write_string_cstr(ff, "name", name)) {
+        return false;
+    }
+    return xremote_sg_signal_save_data(remote, ff);
+}

+ 0 - 3
models/cross/xremote_remote_item.h

@@ -5,7 +5,6 @@
 #include "../subghz/subghz_i.h"
 #include "../../xremote_i.h"
 
-
 bool xremote_remote_item_read(CrossRemoteItem* item, FlipperFormat* ff);
 bool xremote_remote_item_read_ir(CrossRemoteItem* item, FlipperFormat* ff);
 bool xremote_remote_item_read_ir_signal_raw(CrossRemoteItem* item, FlipperFormat* ff);
@@ -30,5 +29,3 @@ void xremote_remote_item_set_sg_signal(CrossRemoteItem* item, SubGhzRemote* subg
 bool xremote_pause_save(FlipperFormat* ff, int32_t time, const char* name);
 bool xremote_ir_signal_save(InfraredSignal* signal, FlipperFormat* ff, const char* name);
 bool xremote_sg_signal_save(SubGhzRemote* remote, FlipperFormat* ff, const char* name);
-
-

+ 3 - 2
models/infrared/xremote_ir_remote.c

@@ -63,8 +63,9 @@ bool xremote_ir_remote_load(InfraredRemote* remote, FuriString* path) {
 
         for(bool can_read = true; can_read;) {
             InfraredRemoteButton* button = xremote_ir_remote_button_alloc();
-            can_read = xremote_ir_signal_read(xremote_ir_remote_button_get_signal(button), ff, buf);
-            if (can_read) {
+            can_read =
+                xremote_ir_signal_read(xremote_ir_remote_button_get_signal(button), ff, buf);
+            if(can_read) {
                 xremote_ir_remote_button_set_name(button, furi_string_get_cstr(buf));
                 InfraredButtonArray_push_back(remote->buttons, button);
             } else {

+ 32 - 32
models/infrared/xremote_ir_remote_button.c

@@ -1,33 +1,33 @@
-#include "xremote_ir_remote_button.h"
-
-#include <stdlib.h>
-
-struct InfraredRemoteButton {
-    FuriString* name;
-    InfraredSignal* signal;
-};
-
-InfraredRemoteButton* xremote_ir_remote_button_alloc() {
-    InfraredRemoteButton* button = malloc(sizeof(InfraredRemoteButton));
-    button->name = furi_string_alloc();
-    button->signal = xremote_ir_signal_alloc();
-    return button;
-}
-
-void xremote_ir_remote_button_free(InfraredRemoteButton* button) {
-    furi_string_free(button->name);
-    xremote_ir_signal_free(button->signal);
-    free(button);
-}
-
-void xremote_ir_remote_button_set_name(InfraredRemoteButton* button, const char* name) {
-    furi_string_set(button->name, name);
-}
-
-const char* xremote_ir_remote_button_get_name(InfraredRemoteButton* button) {
-    return furi_string_get_cstr(button->name);
-}
-
-InfraredSignal* xremote_ir_remote_button_get_signal(InfraredRemoteButton* button) {
-    return button->signal;
+#include "xremote_ir_remote_button.h"
+
+#include <stdlib.h>
+
+struct InfraredRemoteButton {
+    FuriString* name;
+    InfraredSignal* signal;
+};
+
+InfraredRemoteButton* xremote_ir_remote_button_alloc() {
+    InfraredRemoteButton* button = malloc(sizeof(InfraredRemoteButton));
+    button->name = furi_string_alloc();
+    button->signal = xremote_ir_signal_alloc();
+    return button;
+}
+
+void xremote_ir_remote_button_free(InfraredRemoteButton* button) {
+    furi_string_free(button->name);
+    xremote_ir_signal_free(button->signal);
+    free(button);
+}
+
+void xremote_ir_remote_button_set_name(InfraredRemoteButton* button, const char* name) {
+    furi_string_set(button->name, name);
+}
+
+const char* xremote_ir_remote_button_get_name(InfraredRemoteButton* button) {
+    return furi_string_get_cstr(button->name);
+}
+
+InfraredSignal* xremote_ir_remote_button_get_signal(InfraredRemoteButton* button) {
+    return button->signal;
 }

+ 12 - 12
models/infrared/xremote_ir_remote_button.h

@@ -1,13 +1,13 @@
-#pragma once
-
-//#include "../../xremote_i.h"
-#include "xremote_ir_signal.h"
-//#include "../xremote.h"
-
-typedef struct InfraredRemoteButton InfraredRemoteButton;
-
-InfraredRemoteButton* xremote_ir_remote_button_alloc();
-void xremote_ir_remote_button_free(InfraredRemoteButton* button);
-void xremote_ir_remote_button_set_name(InfraredRemoteButton* button, const char* name);
-const char* xremote_ir_remote_button_get_name(InfraredRemoteButton* button);
+#pragma once
+
+//#include "../../xremote_i.h"
+#include "xremote_ir_signal.h"
+//#include "../xremote.h"
+
+typedef struct InfraredRemoteButton InfraredRemoteButton;
+
+InfraredRemoteButton* xremote_ir_remote_button_alloc();
+void xremote_ir_remote_button_free(InfraredRemoteButton* button);
+void xremote_ir_remote_button_set_name(InfraredRemoteButton* button, const char* name);
+const char* xremote_ir_remote_button_get_name(InfraredRemoteButton* button);
 InfraredSignal* xremote_ir_remote_button_get_signal(InfraredRemoteButton* button);

+ 218 - 218
models/infrared/xremote_ir_signal.c

@@ -1,218 +1,218 @@
-#include "xremote_ir_signal.h"
-#include "../../xremote_i.h"
-
-static void xremote_ir_signal_clear_timings(InfraredSignal* signal) {
-    if(signal->is_raw) {
-        free(signal->payload.raw.timings);
-        signal->payload.raw.timings_size = 0;
-        signal->payload.raw.timings = NULL;
-    }
-}
-
-static bool xremote_ir_signal_is_message_valid(InfraredMessage* message) {
-    if(!infrared_is_protocol_valid(message->protocol)) {
-        FURI_LOG_E(TAG, "Unknown protocol");
-        return false;
-    }
-
-    uint32_t address_length = infrared_get_protocol_address_length(message->protocol);
-    uint32_t address_mask = (1UL << address_length) - 1;
-
-    if(message->address != (message->address & address_mask)) {
-        FURI_LOG_E(
-            TAG,
-            "Address is out of range (mask 0x%08lX): 0x%lX\r\n",
-            address_mask,
-            message->address);
-        return false;
-    }
-
-    uint32_t command_length = infrared_get_protocol_command_length(message->protocol);
-    uint32_t command_mask = (1UL << command_length) - 1;
-
-    if(message->command != (message->command & command_mask)) {
-        FURI_LOG_E(
-            TAG,
-            "Command is out of range (mask 0x%08lX): 0x%lX\r\n",
-            command_mask,
-            message->command);
-        return false;
-    }
-
-    return true;
-}
-
-static bool xremote_ir_signal_is_raw_valid(InfraredRawSignal* raw) {
-    if((raw->frequency > INFRARED_MAX_FREQUENCY) || (raw->frequency < INFRARED_MIN_FREQUENCY)) {
-        FURI_LOG_E(
-            TAG,
-            "Frequency is out of range (%X - %X): %lX",
-            INFRARED_MIN_FREQUENCY,
-            INFRARED_MAX_FREQUENCY,
-            raw->frequency);
-        return false;
-
-    } else if((raw->duty_cycle <= 0) || (raw->duty_cycle > 1)) {
-        FURI_LOG_E(TAG, "Duty cycle is out of range (0 - 1): %f", (double)raw->duty_cycle);
-        return false;
-
-    } else if((raw->timings_size <= 0) || (raw->timings_size > MAX_TIMINGS_AMOUNT)) {
-        FURI_LOG_E(
-            TAG,
-            "Timings amount is out of range (0 - %X): %zX",
-            MAX_TIMINGS_AMOUNT,
-            raw->timings_size);
-        return false;
-    }
-
-    return true;
-}
-
-static inline bool xremote_ir_signal_read_message(InfraredSignal* signal, FlipperFormat* ff) {
-    FuriString* buf;
-    buf = furi_string_alloc();
-    bool success = false;
-
-    do {
-        if(!flipper_format_read_string(ff, "protocol", buf)) break;
-
-        InfraredMessage message;
-        message.protocol = infrared_get_protocol_by_name(furi_string_get_cstr(buf));
-        success = flipper_format_read_hex(ff, "address", (uint8_t*)&message.address, 4) &&
-                  flipper_format_read_hex(ff, "command", (uint8_t*)&message.command, 4) &&
-                  xremote_ir_signal_is_message_valid(&message);
-
-        if(!success) break;
-
-        xremote_ir_signal_set_message(signal, &message);
-    } while(0);
-
-    return success;
-}
-
-static inline bool xremote_ir_signal_read_raw(InfraredSignal* signal, FlipperFormat* ff) {
-    uint32_t timings_size, frequency;
-    float duty_cycle;
-
-    bool success = flipper_format_read_uint32(ff, "frequency", &frequency, 1) &&
-                   flipper_format_read_float(ff, "duty_cycle", &duty_cycle, 1) &&
-                   flipper_format_get_value_count(ff, "data", &timings_size);
-
-    if(!success || timings_size > MAX_TIMINGS_AMOUNT) {
-        return false;
-    }
-
-    uint32_t* timings = malloc(sizeof(uint32_t) * timings_size);
-    success = flipper_format_read_uint32(ff, "data", timings, timings_size);
-
-    if(success) {
-        xremote_ir_signal_set_raw_signal(signal, timings, timings_size, frequency, duty_cycle);
-    }
-
-    free(timings);
-    return success;
-}
-
-InfraredSignal* xremote_ir_signal_alloc() {
-    InfraredSignal* signal = malloc(sizeof(InfraredSignal));
-
-    signal->is_raw = false;
-    signal->payload.message.protocol = InfraredProtocolUnknown;
-
-    return signal;
-}
-
-void xremote_ir_signal_free(InfraredSignal* signal) {
-    xremote_ir_signal_clear_timings(signal);
-    free(signal);
-}
-
-bool xremote_ir_signal_is_raw(InfraredSignal* signal) {
-    return signal->is_raw;
-}
-
-bool xremote_ir_signal_is_valid(InfraredSignal* signal) {
-    return signal->is_raw ? xremote_ir_signal_is_raw_valid(&signal->payload.raw) :
-                            xremote_ir_signal_is_message_valid(&signal->payload.message);
-}
-
-void xremote_ir_signal_set_signal(InfraredSignal* signal, const InfraredSignal* other) {
-    if(other->is_raw) {
-        const InfraredRawSignal* raw = &other->payload.raw;
-        xremote_ir_signal_set_raw_signal(
-            signal, raw->timings, raw->timings_size, raw->frequency, raw->duty_cycle);
-    } else {
-        const InfraredMessage* message = &other->payload.message;
-        xremote_ir_signal_set_message(signal, message);
-    }
-}
-
-void xremote_ir_signal_set_raw_signal(
-    InfraredSignal* signal,
-    const uint32_t* timings,
-    size_t timings_size,
-    uint32_t frequency,
-    float duty_cycle) {
-    xremote_ir_signal_clear_timings(signal);
-
-    signal->is_raw = true;
-
-    signal->payload.raw.timings_size = timings_size;
-    signal->payload.raw.frequency = frequency;
-    signal->payload.raw.duty_cycle = duty_cycle;
-
-    signal->payload.raw.timings = malloc(timings_size * sizeof(uint32_t));
-    memcpy(signal->payload.raw.timings, timings, timings_size * sizeof(uint32_t));
-}
-InfraredRawSignal* xremote_ir_signal_get_raw_signal(InfraredSignal* signal) {
-    furi_assert(signal->is_raw);
-    return &signal->payload.raw;
-}
-
-static bool xremote_ir_signal_read_body(InfraredSignal* signal, FlipperFormat* ff) {
-    FuriString* tmp = furi_string_alloc();
-
-    bool success = false;
-
-    do {
-        if(!flipper_format_read_string(ff, "type", tmp)) break;
-        if(furi_string_equal(tmp, "raw")) {
-            success = xremote_ir_signal_read_raw(signal, ff);
-        } else if(furi_string_equal(tmp, "parsed")) {
-            success = xremote_ir_signal_read_message(signal, ff);
-        } else {
-            FURI_LOG_E(TAG, "Unknown signal type");
-        }
-    } while(false);
-
-    furi_string_free(tmp);
-    return success;
-}
-
-bool xremote_ir_signal_read(InfraredSignal* signal, FlipperFormat* ff, FuriString* name) {
-    FuriString* tmp = furi_string_alloc();
-
-    bool success = false;
-
-    do {
-        if(!flipper_format_read_string(ff, "name", tmp)) break;
-        furi_string_set(name, tmp);
-        if(!xremote_ir_signal_read_body(signal, ff)) break;
-        success = true;
-    } while(0);
-
-    furi_string_free(tmp);
-    return success;
-}
-
-void xremote_ir_signal_set_message(InfraredSignal* signal, const InfraredMessage* message) {
-    xremote_ir_signal_clear_timings(signal);
-
-    signal->is_raw = false;
-    signal->payload.message = *message;
-}
-
-InfraredMessage* xremote_ir_signal_get_message(InfraredSignal* signal) {
-    furi_assert(!signal->is_raw);
-    return &signal->payload.message;
-}
+#include "xremote_ir_signal.h"
+#include "../../xremote_i.h"
+
+static void xremote_ir_signal_clear_timings(InfraredSignal* signal) {
+    if(signal->is_raw) {
+        free(signal->payload.raw.timings);
+        signal->payload.raw.timings_size = 0;
+        signal->payload.raw.timings = NULL;
+    }
+}
+
+static bool xremote_ir_signal_is_message_valid(InfraredMessage* message) {
+    if(!infrared_is_protocol_valid(message->protocol)) {
+        FURI_LOG_E(TAG, "Unknown protocol");
+        return false;
+    }
+
+    uint32_t address_length = infrared_get_protocol_address_length(message->protocol);
+    uint32_t address_mask = (1UL << address_length) - 1;
+
+    if(message->address != (message->address & address_mask)) {
+        FURI_LOG_E(
+            TAG,
+            "Address is out of range (mask 0x%08lX): 0x%lX\r\n",
+            address_mask,
+            message->address);
+        return false;
+    }
+
+    uint32_t command_length = infrared_get_protocol_command_length(message->protocol);
+    uint32_t command_mask = (1UL << command_length) - 1;
+
+    if(message->command != (message->command & command_mask)) {
+        FURI_LOG_E(
+            TAG,
+            "Command is out of range (mask 0x%08lX): 0x%lX\r\n",
+            command_mask,
+            message->command);
+        return false;
+    }
+
+    return true;
+}
+
+static bool xremote_ir_signal_is_raw_valid(InfraredRawSignal* raw) {
+    if((raw->frequency > INFRARED_MAX_FREQUENCY) || (raw->frequency < INFRARED_MIN_FREQUENCY)) {
+        FURI_LOG_E(
+            TAG,
+            "Frequency is out of range (%X - %X): %lX",
+            INFRARED_MIN_FREQUENCY,
+            INFRARED_MAX_FREQUENCY,
+            raw->frequency);
+        return false;
+
+    } else if((raw->duty_cycle <= 0) || (raw->duty_cycle > 1)) {
+        FURI_LOG_E(TAG, "Duty cycle is out of range (0 - 1): %f", (double)raw->duty_cycle);
+        return false;
+
+    } else if((raw->timings_size <= 0) || (raw->timings_size > MAX_TIMINGS_AMOUNT)) {
+        FURI_LOG_E(
+            TAG,
+            "Timings amount is out of range (0 - %X): %zX",
+            MAX_TIMINGS_AMOUNT,
+            raw->timings_size);
+        return false;
+    }
+
+    return true;
+}
+
+static inline bool xremote_ir_signal_read_message(InfraredSignal* signal, FlipperFormat* ff) {
+    FuriString* buf;
+    buf = furi_string_alloc();
+    bool success = false;
+
+    do {
+        if(!flipper_format_read_string(ff, "protocol", buf)) break;
+
+        InfraredMessage message;
+        message.protocol = infrared_get_protocol_by_name(furi_string_get_cstr(buf));
+        success = flipper_format_read_hex(ff, "address", (uint8_t*)&message.address, 4) &&
+                  flipper_format_read_hex(ff, "command", (uint8_t*)&message.command, 4) &&
+                  xremote_ir_signal_is_message_valid(&message);
+
+        if(!success) break;
+
+        xremote_ir_signal_set_message(signal, &message);
+    } while(0);
+
+    return success;
+}
+
+static inline bool xremote_ir_signal_read_raw(InfraredSignal* signal, FlipperFormat* ff) {
+    uint32_t timings_size, frequency;
+    float duty_cycle;
+
+    bool success = flipper_format_read_uint32(ff, "frequency", &frequency, 1) &&
+                   flipper_format_read_float(ff, "duty_cycle", &duty_cycle, 1) &&
+                   flipper_format_get_value_count(ff, "data", &timings_size);
+
+    if(!success || timings_size > MAX_TIMINGS_AMOUNT) {
+        return false;
+    }
+
+    uint32_t* timings = malloc(sizeof(uint32_t) * timings_size);
+    success = flipper_format_read_uint32(ff, "data", timings, timings_size);
+
+    if(success) {
+        xremote_ir_signal_set_raw_signal(signal, timings, timings_size, frequency, duty_cycle);
+    }
+
+    free(timings);
+    return success;
+}
+
+InfraredSignal* xremote_ir_signal_alloc() {
+    InfraredSignal* signal = malloc(sizeof(InfraredSignal));
+
+    signal->is_raw = false;
+    signal->payload.message.protocol = InfraredProtocolUnknown;
+
+    return signal;
+}
+
+void xremote_ir_signal_free(InfraredSignal* signal) {
+    xremote_ir_signal_clear_timings(signal);
+    free(signal);
+}
+
+bool xremote_ir_signal_is_raw(InfraredSignal* signal) {
+    return signal->is_raw;
+}
+
+bool xremote_ir_signal_is_valid(InfraredSignal* signal) {
+    return signal->is_raw ? xremote_ir_signal_is_raw_valid(&signal->payload.raw) :
+                            xremote_ir_signal_is_message_valid(&signal->payload.message);
+}
+
+void xremote_ir_signal_set_signal(InfraredSignal* signal, const InfraredSignal* other) {
+    if(other->is_raw) {
+        const InfraredRawSignal* raw = &other->payload.raw;
+        xremote_ir_signal_set_raw_signal(
+            signal, raw->timings, raw->timings_size, raw->frequency, raw->duty_cycle);
+    } else {
+        const InfraredMessage* message = &other->payload.message;
+        xremote_ir_signal_set_message(signal, message);
+    }
+}
+
+void xremote_ir_signal_set_raw_signal(
+    InfraredSignal* signal,
+    const uint32_t* timings,
+    size_t timings_size,
+    uint32_t frequency,
+    float duty_cycle) {
+    xremote_ir_signal_clear_timings(signal);
+
+    signal->is_raw = true;
+
+    signal->payload.raw.timings_size = timings_size;
+    signal->payload.raw.frequency = frequency;
+    signal->payload.raw.duty_cycle = duty_cycle;
+
+    signal->payload.raw.timings = malloc(timings_size * sizeof(uint32_t));
+    memcpy(signal->payload.raw.timings, timings, timings_size * sizeof(uint32_t));
+}
+InfraredRawSignal* xremote_ir_signal_get_raw_signal(InfraredSignal* signal) {
+    furi_assert(signal->is_raw);
+    return &signal->payload.raw;
+}
+
+static bool xremote_ir_signal_read_body(InfraredSignal* signal, FlipperFormat* ff) {
+    FuriString* tmp = furi_string_alloc();
+
+    bool success = false;
+
+    do {
+        if(!flipper_format_read_string(ff, "type", tmp)) break;
+        if(furi_string_equal(tmp, "raw")) {
+            success = xremote_ir_signal_read_raw(signal, ff);
+        } else if(furi_string_equal(tmp, "parsed")) {
+            success = xremote_ir_signal_read_message(signal, ff);
+        } else {
+            FURI_LOG_E(TAG, "Unknown signal type");
+        }
+    } while(false);
+
+    furi_string_free(tmp);
+    return success;
+}
+
+bool xremote_ir_signal_read(InfraredSignal* signal, FlipperFormat* ff, FuriString* name) {
+    FuriString* tmp = furi_string_alloc();
+
+    bool success = false;
+
+    do {
+        if(!flipper_format_read_string(ff, "name", tmp)) break;
+        furi_string_set(name, tmp);
+        if(!xremote_ir_signal_read_body(signal, ff)) break;
+        success = true;
+    } while(0);
+
+    furi_string_free(tmp);
+    return success;
+}
+
+void xremote_ir_signal_set_message(InfraredSignal* signal, const InfraredMessage* message) {
+    xremote_ir_signal_clear_timings(signal);
+
+    signal->is_raw = false;
+    signal->payload.message = *message;
+}
+
+InfraredMessage* xremote_ir_signal_get_message(InfraredSignal* signal) {
+    furi_assert(!signal->is_raw);
+    return &signal->payload.message;
+}

+ 38 - 38
models/infrared/xremote_ir_signal.h

@@ -1,38 +1,38 @@
-#pragma once
-
-#include <stddef.h>
-#include <stdint.h>
-#include <stdbool.h>
-
-#include <infrared.h>
-#include <flipper_format/flipper_format.h>
-
-typedef struct InfraredSignal InfraredSignal;
-
-typedef struct {
-    size_t timings_size;
-    uint32_t* timings;
-    uint32_t frequency;
-    float duty_cycle;
-} InfraredRawSignal;
-
-InfraredSignal* xremote_ir_signal_alloc();
-void xremote_ir_signal_free(InfraredSignal* signal);
-
-bool xremote_ir_signal_is_raw(InfraredSignal* signal);
-bool xremote_ir_signal_is_valid(InfraredSignal* signal);
-
-void xremote_ir_signal_set_signal(InfraredSignal* signal, const InfraredSignal* other);
-
-void xremote_ir_signal_set_raw_signal(
-    InfraredSignal* signal, 
-    const uint32_t* timings, 
-    size_t timings_size, 
-    uint32_t frequency, 
-    float duty_cycle);
-InfraredRawSignal* xremote_ir_signal_get_raw_signal(InfraredSignal* signal);
-
-void xremote_ir_signal_set_message(InfraredSignal* signal, const InfraredMessage* message);
-InfraredMessage* xremote_ir_signal_get_message(InfraredSignal* signal);
-
-bool xremote_ir_signal_read(InfraredSignal* signal, FlipperFormat* ff, FuriString* name);
+#pragma once
+
+#include <stddef.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#include <infrared.h>
+#include <flipper_format/flipper_format.h>
+
+typedef struct InfraredSignal InfraredSignal;
+
+typedef struct {
+    size_t timings_size;
+    uint32_t* timings;
+    uint32_t frequency;
+    float duty_cycle;
+} InfraredRawSignal;
+
+InfraredSignal* xremote_ir_signal_alloc();
+void xremote_ir_signal_free(InfraredSignal* signal);
+
+bool xremote_ir_signal_is_raw(InfraredSignal* signal);
+bool xremote_ir_signal_is_valid(InfraredSignal* signal);
+
+void xremote_ir_signal_set_signal(InfraredSignal* signal, const InfraredSignal* other);
+
+void xremote_ir_signal_set_raw_signal(
+    InfraredSignal* signal,
+    const uint32_t* timings,
+    size_t timings_size,
+    uint32_t frequency,
+    float duty_cycle);
+InfraredRawSignal* xremote_ir_signal_get_raw_signal(InfraredSignal* signal);
+
+void xremote_ir_signal_set_message(InfraredSignal* signal, const InfraredMessage* message);
+InfraredMessage* xremote_ir_signal_get_message(InfraredSignal* signal);
+
+bool xremote_ir_signal_read(InfraredSignal* signal, FlipperFormat* ff, FuriString* name);

+ 0 - 2
models/subghz/subghz_i.h

@@ -53,5 +53,3 @@ struct SubGhzTxRx {
 };
 
 typedef struct SubGhzTxRx SubGhzTxRx;
-
-

+ 8 - 9
models/subghz/xremote_sg_remote.c

@@ -22,8 +22,6 @@
 
 #define TAG "Xremote"
 
-
-
 struct SubGhzRemote {
     FuriString* name;
     FuriString* path;
@@ -59,7 +57,7 @@ SubGhzRemote* xremote_sg_remote_alloc() {
     SubGhzRemote* remote = malloc(sizeof(SubGhzRemote));
     remote->name = furi_string_alloc();
     remote->path = furi_string_alloc();
-    
+
     // SubGhz Settings
     remote->setting = subghz_setting_alloc();
     subghz_setting_load(remote->setting, EXT_PATH("subghz/assets/setting_user"));
@@ -142,8 +140,8 @@ bool xremote_sg_remote_load(SubGhzRemote* remote, FuriString* path) {
         const char* fullPath = furi_string_get_cstr(path);
         char* fileName = strrchr(fullPath, '/') + 1;
         char* dotPosition = strrchr(fileName, '.');
-        if (dotPosition != NULL) {  // check if there is a dot in the file name
-            *dotPosition = '\0';     // set the dot position to NULL character to truncate the string
+        if(dotPosition != NULL) { // check if there is a dot in the file name
+            *dotPosition = '\0'; // set the dot position to NULL character to truncate the string
         }
         //remote->name = fileName;
         furi_string_set_str(remote->name, fileName);
@@ -172,9 +170,7 @@ bool xremote_sg_remote_load(SubGhzRemote* remote, FuriString* path) {
                 remote->setting, furi_string_get_cstr(remote->txrx->preset->name));
             //load custom preset from file
             if(!subghz_setting_load_custom_preset(
-                   remote->setting,
-                   furi_string_get_cstr(remote->txrx->preset->name),
-                   ff)) {
+                   remote->setting, furi_string_get_cstr(remote->txrx->preset->name), ff)) {
                 FURI_LOG_E(TAG, "Missing Custom preset");
                 break;
             }
@@ -186,7 +182,10 @@ bool xremote_sg_remote_load(SubGhzRemote* remote, FuriString* path) {
         }
 
         if(!strcmp(furi_string_get_cstr(buf), "RAW")) {
-            subghz_protocol_raw_gen_fff_data(remote->txrx->fff_data, furi_string_get_cstr(path), subghz_txrx_radio_device_get_name(remote->txrx));
+            subghz_protocol_raw_gen_fff_data(
+                remote->txrx->fff_data,
+                furi_string_get_cstr(path),
+                subghz_txrx_radio_device_get_name(remote->txrx));
         } else {
             stream_copy_full(
                 flipper_format_get_raw_stream(ff),

+ 30 - 30
scenes/xremote_scene.c

@@ -1,30 +1,30 @@
-#include "xremote_scene.h"
-
-// Generate scene on_enter handlers array
-#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter,
-void (*const xremote_on_enter_handlers[])(void*) = {
-#include "xremote_scene_config.h"
-};
-#undef ADD_SCENE
-
-// Generate scene on_event handlers array
-#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event,
-bool (*const xremote_on_event_handlers[])(void* context, SceneManagerEvent event) = {
-#include "xremote_scene_config.h"
-};
-#undef ADD_SCENE
-
-// Generate scene on_exit handlers array
-#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit,
-void (*const xremote_on_exit_handlers[])(void* context) = {
-#include "xremote_scene_config.h"
-};
-#undef ADD_SCENE
-
-// Initialize scene handlers configuration structure
-const SceneManagerHandlers xremote_scene_handlers = {
-    .on_enter_handlers = xremote_on_enter_handlers,
-    .on_event_handlers = xremote_on_event_handlers,
-    .on_exit_handlers = xremote_on_exit_handlers,
-    .scene_num = XRemoteSceneNum,
-};
+#include "xremote_scene.h"
+
+// Generate scene on_enter handlers array
+#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter,
+void (*const xremote_on_enter_handlers[])(void*) = {
+#include "xremote_scene_config.h"
+};
+#undef ADD_SCENE
+
+// Generate scene on_event handlers array
+#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event,
+bool (*const xremote_on_event_handlers[])(void* context, SceneManagerEvent event) = {
+#include "xremote_scene_config.h"
+};
+#undef ADD_SCENE
+
+// Generate scene on_exit handlers array
+#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit,
+void (*const xremote_on_exit_handlers[])(void* context) = {
+#include "xremote_scene_config.h"
+};
+#undef ADD_SCENE
+
+// Initialize scene handlers configuration structure
+const SceneManagerHandlers xremote_scene_handlers = {
+    .on_enter_handlers = xremote_on_enter_handlers,
+    .on_event_handlers = xremote_on_event_handlers,
+    .on_exit_handlers = xremote_on_exit_handlers,
+    .scene_num = XRemoteSceneNum,
+};

+ 29 - 29
scenes/xremote_scene.h

@@ -1,29 +1,29 @@
-#pragma once
-
-#include <gui/scene_manager.h>
-
-// Generate scene id and total number
-#define ADD_SCENE(prefix, name, id) XRemoteScene##id,
-typedef enum {
-#include "xremote_scene_config.h"
-    XRemoteSceneNum,
-} XRemoteScene;
-#undef ADD_SCENE
-
-extern const SceneManagerHandlers xremote_scene_handlers;
-
-// Generate scene on_enter handlers declaration
-#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*);
-#include "xremote_scene_config.h"
-#undef ADD_SCENE
-
-// Generate scene on_event handlers declaration
-#define ADD_SCENE(prefix, name, id) \
-    bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event);
-#include "xremote_scene_config.h"
-#undef ADD_SCENE
-
-// Generate scene on_exit handlers declaration
-#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context);
-#include "xremote_scene_config.h"
-#undef ADD_SCENE
+#pragma once
+
+#include <gui/scene_manager.h>
+
+// Generate scene id and total number
+#define ADD_SCENE(prefix, name, id) XRemoteScene##id,
+typedef enum {
+#include "xremote_scene_config.h"
+    XRemoteSceneNum,
+} XRemoteScene;
+#undef ADD_SCENE
+
+extern const SceneManagerHandlers xremote_scene_handlers;
+
+// Generate scene on_enter handlers declaration
+#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*);
+#include "xremote_scene_config.h"
+#undef ADD_SCENE
+
+// Generate scene on_event handlers declaration
+#define ADD_SCENE(prefix, name, id) \
+    bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event);
+#include "xremote_scene_config.h"
+#undef ADD_SCENE
+
+// Generate scene on_exit handlers declaration
+#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context);
+#include "xremote_scene_config.h"
+#undef ADD_SCENE

+ 7 - 6
scenes/xremote_scene_create.c

@@ -9,7 +9,7 @@ typedef enum {
 
 static void xremote_create_callback(void* context, int32_t index, InputType type) {
     XRemote* app = context;
-    
+
     uint16_t custom_type;
     if(type == InputTypePress) {
         custom_type = XRemoteCustomEventMenuSelected;
@@ -22,7 +22,8 @@ static void xremote_create_callback(void* context, int32_t index, InputType type
         furi_crash("Unexpected Input Type");
     }
 
-    view_dispatcher_send_custom_event(app->view_dispatcher, xremote_custom_menu_event_pack(custom_type, index));
+    view_dispatcher_send_custom_event(
+        app->view_dispatcher, xremote_custom_menu_event_pack(custom_type, index));
 }
 
 void xremote_scene_create_on_enter(void* context) {
@@ -71,7 +72,7 @@ void xremote_scene_create_on_enter(void* context) {
 bool xremote_scene_create_on_event(void* context, SceneManagerEvent event) {
     XRemote* app = context;
     bool consumed = false;
-    
+
     if(event.type == SceneManagerEventTypeBack) {
         scene_manager_next_scene(app->scene_manager, XRemoteSceneMenu);
         consumed = true;
@@ -86,8 +87,8 @@ bool xremote_scene_create_on_event(void* context, SceneManagerEvent event) {
         const uint16_t custom_type = xremote_custom_menu_event_get_type(event.event);
         const int16_t button_index = xremote_custom_menu_event_get_value(event.event);
         scene_manager_set_scene_state(
-                app->scene_manager, XRemoteSceneCreate, (unsigned)button_index);
-        if (custom_type == XRemoteCustomEventMenuSelected && button_index < 0) {
+            app->scene_manager, XRemoteSceneCreate, (unsigned)button_index);
+        if(custom_type == XRemoteCustomEventMenuSelected && button_index < 0) {
             //scene_manager_set_scene_state(
             //    app->scene_manager, XRemoteSceneCreate, (unsigned)button_index);
             if(button_index == ButtonIndexPlus) {
@@ -120,7 +121,7 @@ bool xremote_scene_create_on_event(void* context, SceneManagerEvent event) {
                 break;
         }*/
     }
-    
+
     return consumed;
 }
 

+ 6 - 5
scenes/xremote_scene_create_add.c

@@ -10,7 +10,7 @@ typedef enum {
 
 static void xremote_create_add_callback(void* context, int32_t index, InputType type) {
     XRemote* app = context;
-    
+
     uint16_t custom_type;
     if(type == InputTypePress) {
         custom_type = XRemoteCustomEventMenuVoid;
@@ -22,7 +22,8 @@ static void xremote_create_add_callback(void* context, int32_t index, InputType
         furi_crash("Unexpected Input Type");
     }
 
-    view_dispatcher_send_custom_event(app->view_dispatcher, xremote_custom_menu_event_pack(custom_type, index));
+    view_dispatcher_send_custom_event(
+        app->view_dispatcher, xremote_custom_menu_event_pack(custom_type, index));
 }
 
 void xremote_scene_create_add_on_enter(void* context) {
@@ -66,11 +67,11 @@ void xremote_scene_create_add_on_enter(void* context) {
 bool xremote_scene_create_add_on_event(void* context, SceneManagerEvent event) {
     XRemote* app = context;
     bool consumed = false;
-    
+
     if(event.type == SceneManagerEventTypeCustom) {
         const uint16_t custom_type = xremote_custom_menu_event_get_type(event.event);
         const int16_t button_index = xremote_custom_menu_event_get_value(event.event);
-        if (custom_type == XRemoteCustomEventMenuAddSelected) {
+        if(custom_type == XRemoteCustomEventMenuAddSelected) {
             furi_assert(button_index < 0);
             scene_manager_set_scene_state(
                 app->scene_manager, XRemoteSceneCreate, (unsigned)button_index);
@@ -87,7 +88,7 @@ bool xremote_scene_create_add_on_event(void* context, SceneManagerEvent event) {
             consumed = true;
         }
     }
-    
+
     return consumed;
 }
 

+ 10 - 11
scenes/xremote_scene_edit_item.c

@@ -11,26 +11,27 @@ void xremote_scene_edit_item_submenu_callback(void* context, uint32_t index) {
     view_dispatcher_send_custom_event(app->view_dispatcher, index);
 }
 
-void xremote_scene_edit_item_on_enter(void* context)
-{
+void xremote_scene_edit_item_on_enter(void* context) {
     XRemote* app = context;
-    submenu_add_item(app->editmenu, "Rename", SubmenuIndexRename, xremote_scene_edit_item_submenu_callback, app);
-    submenu_add_item(app->editmenu, "Delete", SubmenuIndexDelete, xremote_scene_edit_item_submenu_callback, app);
+    submenu_add_item(
+        app->editmenu, "Rename", SubmenuIndexRename, xremote_scene_edit_item_submenu_callback, app);
+    submenu_add_item(
+        app->editmenu, "Delete", SubmenuIndexDelete, xremote_scene_edit_item_submenu_callback, app);
 
-    submenu_set_selected_item(app->editmenu, scene_manager_get_scene_state(app->scene_manager, XRemoteSceneMenu));
+    submenu_set_selected_item(
+        app->editmenu, scene_manager_get_scene_state(app->scene_manager, XRemoteSceneMenu));
 
     view_dispatcher_switch_to_view(app->view_dispatcher, XRemoteViewIdEditItem);
 }
 
-bool xremote_scene_edit_item_on_event(void* context, SceneManagerEvent event)
-{
+bool xremote_scene_edit_item_on_event(void* context, SceneManagerEvent event) {
     XRemote* app = context;
     if(event.type == SceneManagerEventTypeBack) {
         //exit app
         scene_manager_previous_scene(app->scene_manager);
         return true;
     } else if(event.type == SceneManagerEventTypeCustom) {
-        if(event.event == SubmenuIndexDelete) { 
+        if(event.event == SubmenuIndexDelete) {
             cross_remote_remove_item(app->cross_remote, app->edit_item);
         } else if(event.event == SubmenuIndexRename) {
             scene_manager_next_scene(app->scene_manager, XRemoteSceneSaveRemoteItem);
@@ -42,9 +43,7 @@ bool xremote_scene_edit_item_on_event(void* context, SceneManagerEvent event)
     return 0;
 }
 
-
-void xremote_scene_edit_item_on_exit(void* context)
-{
+void xremote_scene_edit_item_on_exit(void* context) {
     XRemote* app = context;
     submenu_reset(app->editmenu);
 }

+ 25 - 24
scenes/xremote_scene_infoscreen.c

@@ -11,40 +11,41 @@ void xremote_scene_infoscreen_callback(XRemoteCustomEvent event, void* context)
 void xremote_scene_infoscreen_on_enter(void* context) {
     furi_assert(context);
     XRemote* app = context;
-    xremote_infoscreen_set_callback(app->xremote_infoscreen, xremote_scene_infoscreen_callback, app);
+    xremote_infoscreen_set_callback(
+        app->xremote_infoscreen, xremote_scene_infoscreen_callback, app);
     view_dispatcher_switch_to_view(app->view_dispatcher, XRemoteViewIdInfoscreen);
 }
 
 bool xremote_scene_infoscreen_on_event(void* context, SceneManagerEvent event) {
     XRemote* app = context;
     bool consumed = false;
-    
+
     if(event.type == SceneManagerEventTypeCustom) {
         switch(event.event) {
-            case XRemoteCustomEventInfoscreenLeft:
-            case XRemoteCustomEventInfoscreenRight:
-                break;
-            case XRemoteCustomEventInfoscreenUp:
-            case XRemoteCustomEventInfoscreenDown:
-                break;
-            case XRemoteCustomEventInfoscreenOk:
-                scene_manager_next_scene(app->scene_manager, XRemoteSceneMenu);
-                consumed = true;
-                break;
-            case XRemoteCustomEventInfoscreenBack:
-                notification_message(app->notification, &sequence_reset_red);
-                notification_message(app->notification, &sequence_reset_green);
-                notification_message(app->notification, &sequence_reset_blue);
-                if(!scene_manager_search_and_switch_to_previous_scene(
-                    app->scene_manager, XRemoteSceneInfoscreen)) {
-                        scene_manager_stop(app->scene_manager);
-                        view_dispatcher_stop(app->view_dispatcher);
-                    }
-                consumed = true;
-                break;
+        case XRemoteCustomEventInfoscreenLeft:
+        case XRemoteCustomEventInfoscreenRight:
+            break;
+        case XRemoteCustomEventInfoscreenUp:
+        case XRemoteCustomEventInfoscreenDown:
+            break;
+        case XRemoteCustomEventInfoscreenOk:
+            scene_manager_next_scene(app->scene_manager, XRemoteSceneMenu);
+            consumed = true;
+            break;
+        case XRemoteCustomEventInfoscreenBack:
+            notification_message(app->notification, &sequence_reset_red);
+            notification_message(app->notification, &sequence_reset_green);
+            notification_message(app->notification, &sequence_reset_blue);
+            if(!scene_manager_search_and_switch_to_previous_scene(
+                   app->scene_manager, XRemoteSceneInfoscreen)) {
+                scene_manager_stop(app->scene_manager);
+                view_dispatcher_stop(app->view_dispatcher);
+            }
+            consumed = true;
+            break;
         }
     }
-    
+
     return consumed;
 }
 

+ 2 - 3
scenes/xremote_scene_ir_list.c

@@ -2,7 +2,7 @@
 
 void xremote_scene_ir_list_on_enter(void* context) {
     XRemote* app = context;
-    
+
     DialogsFileBrowserOptions browser_options;
     dialog_file_browser_set_basic_options(&browser_options, INFRARED_APP_EXTENSION, &I_ir_10px);
     browser_options.base_path = INFRARED_APP_FOLDER;
@@ -10,8 +10,7 @@ void xremote_scene_ir_list_on_enter(void* context) {
     FuriString* path;
     path = furi_string_alloc();
     furi_string_set(path, INFRARED_APP_FOLDER);
-    bool success = dialog_file_browser_show(
-        app->dialogs, app->file_path, path, &browser_options);
+    bool success = dialog_file_browser_show(app->dialogs, app->file_path, path, &browser_options);
     furi_string_free(path);
 
     if(success) {

+ 9 - 7
scenes/xremote_scene_ir_remote.c

@@ -6,7 +6,8 @@ typedef enum {
     ButtonIndexNA = 0,
 } ButtonIndex;
 
-static void xremote_scene_ir_remote_button_menu_callback(void* context, int32_t index, InputType type) {
+static void
+    xremote_scene_ir_remote_button_menu_callback(void* context, int32_t index, InputType type) {
     XRemote* app = context;
 
     uint16_t custom_type;
@@ -41,7 +42,7 @@ void xremote_scene_ir_remote_on_enter(void* context) {
     }
 
     button_menu_set_header(button_menu, "Select Cmd");
-    const int16_t button_index = 
+    const int16_t button_index =
         (signed)scene_manager_get_scene_state(app->scene_manager, XRemoteViewIdIrRemote);
     button_menu_set_selected_item(button_menu, button_index);
 
@@ -51,15 +52,16 @@ void xremote_scene_ir_remote_on_enter(void* context) {
 bool xremote_scene_ir_remote_on_event(void* context, SceneManagerEvent event) {
     XRemote* app = context;
     bool consumed = false;
-    
+
     if(event.type == SceneManagerEventTypeCustom) {
         const uint16_t custom_type = xremote_custom_menu_event_get_type(event.event);
         const int16_t button_index = xremote_custom_menu_event_get_value(event.event);
-        if (custom_type == XRemoteCustomEventMenuAddIrSelected) {
+        if(custom_type == XRemoteCustomEventMenuAddIrSelected) {
             scene_manager_set_scene_state(
                 app->scene_manager, XRemoteSceneIrRemote, (unsigned)button_index);
-            
-            InfraredRemoteButton* ir_button = xremote_ir_remote_get_button(app->ir_remote_buffer, button_index);
+
+            InfraredRemoteButton* ir_button =
+                xremote_ir_remote_get_button(app->ir_remote_buffer, button_index);
             const char* button_name = xremote_ir_remote_button_get_name(ir_button);
             InfraredSignal* signal = xremote_ir_remote_button_get_signal(ir_button);
 
@@ -68,7 +70,7 @@ bool xremote_scene_ir_remote_on_event(void* context, SceneManagerEvent event) {
             consumed = true;
         }
     }
-    
+
     return consumed;
 }
 

+ 85 - 69
scenes/xremote_scene_menu.c

@@ -1,70 +1,86 @@
-#include "../xremote.h"
-
-enum SubmenuIndex {
-    SubmenuIndexCreate = 10,
-    SubmenuIndexLoad,
-    SubmenuIndexEdit,
-    SubmenuIndexSettings,
-    SubmenuIndexInfoscreen,
-};
-
-void xremote_scene_menu_submenu_callback(void* context, uint32_t index) {
-    XRemote* app = context;
-    view_dispatcher_send_custom_event(app->view_dispatcher, index);
-}
-
-void xremote_scene_menu_on_enter(void* context) {
-    XRemote* app = context;
-
-    submenu_add_item(app->submenu, "New Command Chain", SubmenuIndexCreate, xremote_scene_menu_submenu_callback, app);
-    submenu_add_item(app->submenu, "Run Saved Command", SubmenuIndexLoad, xremote_scene_menu_submenu_callback, app);
-    submenu_add_item(app->submenu, "Edit / Delete Command", SubmenuIndexEdit, xremote_scene_menu_submenu_callback, app);
-    submenu_add_item(app->submenu, "Settings", SubmenuIndexSettings, xremote_scene_menu_submenu_callback, app);
-    submenu_add_item(app->submenu, "App Info", SubmenuIndexInfoscreen, xremote_scene_menu_submenu_callback, app);
-
-    submenu_set_selected_item(app->submenu, scene_manager_get_scene_state(app->scene_manager, XRemoteSceneMenu));
-
-    view_dispatcher_switch_to_view(app->view_dispatcher, XRemoteViewIdMenu);
-}
-
-bool xremote_scene_menu_on_event(void* context, SceneManagerEvent event) {
-    XRemote* app = context;
-    if(event.type == SceneManagerEventTypeBack) {
-        //exit app
-        scene_manager_stop(app->scene_manager);
-        view_dispatcher_stop(app->view_dispatcher);
-        return true;
-    } else if(event.type == SceneManagerEventTypeCustom) {
-        if(event.event == SubmenuIndexCreate) {
-            scene_manager_set_scene_state(
-                app->scene_manager, XRemoteSceneMenu, SubmenuIndexCreate);
-            scene_manager_next_scene(app->scene_manager, XRemoteSceneCreate);
-            return true;
-        } else if (event.event == SubmenuIndexLoad) {
-            scene_manager_set_scene_state(
-                app->scene_manager, XRemoteSceneMenu, SubmenuIndexLoad);
-            scene_manager_next_scene(app->scene_manager, XRemoteSceneXrList);
-            return true;
-        } else if (event.event == SubmenuIndexSettings) {
-            scene_manager_set_scene_state(
-                app->scene_manager, XRemoteSceneMenu, SubmenuIndexSettings);
-            scene_manager_next_scene(app->scene_manager, XRemoteSceneSettings);
-            return true;
-        } else if (event.event == SubmenuIndexInfoscreen) {
-            scene_manager_set_scene_state(
-                app->scene_manager, XRemoteSceneMenu, SubmenuIndexInfoscreen);
-            scene_manager_next_scene(app->scene_manager, XRemoteSceneInfoscreen);
-            return true;
-        } else if (event.event == SubmenuIndexEdit) {
-            scene_manager_set_scene_state(
-                app->scene_manager, XRemoteSceneMenu, SubmenuIndexEdit);
-            scene_manager_next_scene(app->scene_manager, XRemoteSceneXrListEdit);
-        }
-    }
-    return false;
-}
-
-void xremote_scene_menu_on_exit(void* context) {
-    XRemote* app = context;
-    submenu_reset(app->submenu);
+#include "../xremote.h"
+
+enum SubmenuIndex {
+    SubmenuIndexCreate = 10,
+    SubmenuIndexLoad,
+    SubmenuIndexEdit,
+    SubmenuIndexSettings,
+    SubmenuIndexInfoscreen,
+};
+
+void xremote_scene_menu_submenu_callback(void* context, uint32_t index) {
+    XRemote* app = context;
+    view_dispatcher_send_custom_event(app->view_dispatcher, index);
+}
+
+void xremote_scene_menu_on_enter(void* context) {
+    XRemote* app = context;
+
+    submenu_add_item(
+        app->submenu,
+        "New Command Chain",
+        SubmenuIndexCreate,
+        xremote_scene_menu_submenu_callback,
+        app);
+    submenu_add_item(
+        app->submenu,
+        "Run Saved Command",
+        SubmenuIndexLoad,
+        xremote_scene_menu_submenu_callback,
+        app);
+    submenu_add_item(
+        app->submenu,
+        "Edit / Delete Command",
+        SubmenuIndexEdit,
+        xremote_scene_menu_submenu_callback,
+        app);
+    submenu_add_item(
+        app->submenu, "Settings", SubmenuIndexSettings, xremote_scene_menu_submenu_callback, app);
+    submenu_add_item(
+        app->submenu, "App Info", SubmenuIndexInfoscreen, xremote_scene_menu_submenu_callback, app);
+
+    submenu_set_selected_item(
+        app->submenu, scene_manager_get_scene_state(app->scene_manager, XRemoteSceneMenu));
+
+    view_dispatcher_switch_to_view(app->view_dispatcher, XRemoteViewIdMenu);
+}
+
+bool xremote_scene_menu_on_event(void* context, SceneManagerEvent event) {
+    XRemote* app = context;
+    if(event.type == SceneManagerEventTypeBack) {
+        //exit app
+        scene_manager_stop(app->scene_manager);
+        view_dispatcher_stop(app->view_dispatcher);
+        return true;
+    } else if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == SubmenuIndexCreate) {
+            scene_manager_set_scene_state(
+                app->scene_manager, XRemoteSceneMenu, SubmenuIndexCreate);
+            scene_manager_next_scene(app->scene_manager, XRemoteSceneCreate);
+            return true;
+        } else if(event.event == SubmenuIndexLoad) {
+            scene_manager_set_scene_state(app->scene_manager, XRemoteSceneMenu, SubmenuIndexLoad);
+            scene_manager_next_scene(app->scene_manager, XRemoteSceneXrList);
+            return true;
+        } else if(event.event == SubmenuIndexSettings) {
+            scene_manager_set_scene_state(
+                app->scene_manager, XRemoteSceneMenu, SubmenuIndexSettings);
+            scene_manager_next_scene(app->scene_manager, XRemoteSceneSettings);
+            return true;
+        } else if(event.event == SubmenuIndexInfoscreen) {
+            scene_manager_set_scene_state(
+                app->scene_manager, XRemoteSceneMenu, SubmenuIndexInfoscreen);
+            scene_manager_next_scene(app->scene_manager, XRemoteSceneInfoscreen);
+            return true;
+        } else if(event.event == SubmenuIndexEdit) {
+            scene_manager_set_scene_state(app->scene_manager, XRemoteSceneMenu, SubmenuIndexEdit);
+            scene_manager_next_scene(app->scene_manager, XRemoteSceneXrListEdit);
+        }
+    }
+    return false;
+}
+
+void xremote_scene_menu_on_exit(void* context) {
+    XRemote* app = context;
+    submenu_reset(app->submenu);
 }

+ 25 - 25
scenes/xremote_scene_pause_set.c

@@ -17,38 +17,38 @@ void xremote_scene_pause_set_on_enter(void* context) {
 bool xremote_scene_pause_set_on_event(void* context, SceneManagerEvent event) {
     XRemote* app = context;
     bool consumed = false;
-    
+
     if(event.type == SceneManagerEventTypeCustom) {
         switch(event.event) {
-            case XRemoteCustomEventInfoscreenLeft:
-            case XRemoteCustomEventInfoscreenRight:
-                break;
-            case XRemoteCustomEventInfoscreenUp:
-            case XRemoteCustomEventInfoscreenDown:
-                break;
-            case XRemoteCustomEventInfoscreenOk:
-                scene_manager_next_scene(app->scene_manager, XRemoteSceneMenu);
-                consumed = true;
-                break;
-            case XRemoteCustomEventPauseSetBack:
-                if(!scene_manager_search_and_switch_to_previous_scene(
-                    app->scene_manager, XRemoteSceneCreateAdd)) {
-                        scene_manager_stop(app->scene_manager);
-                        view_dispatcher_stop(app->view_dispatcher);
-                    }
-                consumed = true;
-                break;
-            case XRemoteCustomEventPauseSetOk:
-                //cross_remote_add_pause(app->cross_remote, time);
-                scene_manager_search_and_switch_to_previous_scene(app->scene_manager, XRemoteSceneCreate);
-                consumed = true;
-                break;
+        case XRemoteCustomEventInfoscreenLeft:
+        case XRemoteCustomEventInfoscreenRight:
+            break;
+        case XRemoteCustomEventInfoscreenUp:
+        case XRemoteCustomEventInfoscreenDown:
+            break;
+        case XRemoteCustomEventInfoscreenOk:
+            scene_manager_next_scene(app->scene_manager, XRemoteSceneMenu);
+            consumed = true;
+            break;
+        case XRemoteCustomEventPauseSetBack:
+            if(!scene_manager_search_and_switch_to_previous_scene(
+                   app->scene_manager, XRemoteSceneCreateAdd)) {
+                scene_manager_stop(app->scene_manager);
+                view_dispatcher_stop(app->view_dispatcher);
+            }
+            consumed = true;
+            break;
+        case XRemoteCustomEventPauseSetOk:
+            //cross_remote_add_pause(app->cross_remote, time);
+            scene_manager_search_and_switch_to_previous_scene(
+                app->scene_manager, XRemoteSceneCreate);
+            consumed = true;
+            break;
         }
     }
     return consumed;
 }
 
-
 void xremote_scene_pause_set_on_exit(void* context) {
     UNUSED(context);
 }

+ 71 - 73
scenes/xremote_scene_save_remote.c

@@ -1,74 +1,72 @@
-#include "../xremote.h"
-
-#include <string.h>
-#include <toolbox/path.h>
-
-void xremote_scene_save_remote_on_enter(void* context) {
-    XRemote* app = context;
-    CrossRemote* remote = app->cross_remote;
-    TextInput* text_input = app->text_input;
-    size_t enter_name_length = 0;
-
-    text_input_set_header_text(text_input, "Name the remote");
-    enter_name_length = XREMOTE_MAX_REMOTE_NAME_LENGTH;
-
-    FuriString* folder_path;
-    folder_path = furi_string_alloc();
-
-    //if(furi_string_end_with(app->))
-
-    //A lot missing here
-
-    ValidatorIsFile* validator_is_file = validator_is_file_alloc_init(
-        furi_string_get_cstr(folder_path),
-        XREMOTE_APP_EXTENSION,
-        cross_remote_get_name(remote));
-    text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
-
-    furi_string_free(folder_path);
-
-    text_input_set_result_callback(
-        text_input,
-        xremote_text_input_callback,
-        context,
-        app->text_store[0],
-        enter_name_length,
-        false);
-
-    view_dispatcher_switch_to_view(app->view_dispatcher, XRemoteViewIdTextInput);
-}
-
-bool xremote_scene_save_remote_on_event(void* context, SceneManagerEvent event) {
-    XRemote* app = context;
-    CrossRemote* remote = app->cross_remote;
-    SceneManager* scene_manager = app->scene_manager;
-    bool consumed = false;
-    
-    if(event.type == SceneManagerEventTypeCustom) {
-        bool success = false;
-
-        success = cross_remote_save_new(remote, app->text_store[0]);
-
-        if(success) {
-            scene_manager_next_scene(scene_manager, XRemoteSceneMenu);
-        } else {
-            scene_manager_search_and_switch_to_previous_scene(scene_manager, XRemoteSceneCreate);
-        }
-        consumed = true;
-    }
-    return consumed;
-}
-
-void xremote_scene_save_remote_on_exit(void* context) {
-    XRemote* app = context;
-    TextInput* text_input = app->text_input;
-
-    void* validator_context = text_input_get_validator_callback_context(text_input);
-    text_input_set_validator(text_input, NULL, NULL);
-
-    size_t enter_name_length = XREMOTE_MAX_REMOTE_NAME_LENGTH;
-    strncpy(app->text_store[0], "", enter_name_length);
-    if(validator_context) {
-        validator_is_file_free((ValidatorIsFile*)validator_context);
-    }
+#include "../xremote.h"
+
+#include <string.h>
+#include <toolbox/path.h>
+
+void xremote_scene_save_remote_on_enter(void* context) {
+    XRemote* app = context;
+    CrossRemote* remote = app->cross_remote;
+    TextInput* text_input = app->text_input;
+    size_t enter_name_length = 0;
+
+    text_input_set_header_text(text_input, "Name the remote");
+    enter_name_length = XREMOTE_MAX_REMOTE_NAME_LENGTH;
+
+    FuriString* folder_path;
+    folder_path = furi_string_alloc();
+
+    //if(furi_string_end_with(app->))
+
+    //A lot missing here
+
+    ValidatorIsFile* validator_is_file = validator_is_file_alloc_init(
+        furi_string_get_cstr(folder_path), XREMOTE_APP_EXTENSION, cross_remote_get_name(remote));
+    text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
+
+    furi_string_free(folder_path);
+
+    text_input_set_result_callback(
+        text_input,
+        xremote_text_input_callback,
+        context,
+        app->text_store[0],
+        enter_name_length,
+        false);
+
+    view_dispatcher_switch_to_view(app->view_dispatcher, XRemoteViewIdTextInput);
+}
+
+bool xremote_scene_save_remote_on_event(void* context, SceneManagerEvent event) {
+    XRemote* app = context;
+    CrossRemote* remote = app->cross_remote;
+    SceneManager* scene_manager = app->scene_manager;
+    bool consumed = false;
+
+    if(event.type == SceneManagerEventTypeCustom) {
+        bool success = false;
+
+        success = cross_remote_save_new(remote, app->text_store[0]);
+
+        if(success) {
+            scene_manager_next_scene(scene_manager, XRemoteSceneMenu);
+        } else {
+            scene_manager_search_and_switch_to_previous_scene(scene_manager, XRemoteSceneCreate);
+        }
+        consumed = true;
+    }
+    return consumed;
+}
+
+void xremote_scene_save_remote_on_exit(void* context) {
+    XRemote* app = context;
+    TextInput* text_input = app->text_input;
+
+    void* validator_context = text_input_get_validator_callback_context(text_input);
+    text_input_set_validator(text_input, NULL, NULL);
+
+    size_t enter_name_length = XREMOTE_MAX_REMOTE_NAME_LENGTH;
+    strncpy(app->text_store[0], "", enter_name_length);
+    if(validator_context) {
+        validator_is_file_free((ValidatorIsFile*)validator_context);
+    }
 }

+ 44 - 44
scenes/xremote_scene_save_remote_item.c

@@ -1,45 +1,45 @@
-#include "../xremote.h"
-#include "../models/cross/xremote_remote.h"
-
-#include <string.h>
-#include <toolbox/path.h>
-
-void xremote_scene_save_remote_item_on_enter(void* context) {
-    XRemote* app = context;
-    TextInput* text_input = app->text_input;
-
-    text_input_set_header_text(text_input, "Name the Sequence");
-    
-    size_t enter_name_length = XREMOTE_MAX_REMOTE_NAME_LENGTH;
-    CrossRemoteItem* item = cross_remote_get_item(app->cross_remote, app->edit_item);
-    strncpy(app->text_store[0], furi_string_get_cstr(item->name), enter_name_length);
-    text_input_set_result_callback(
-        text_input,
-        xremote_text_input_callback,
-        context,
-        app->text_store[0],
-        enter_name_length,
-        false);
-    
-    view_dispatcher_switch_to_view(app->view_dispatcher, XRemoteViewIdTextInput);
-}
-
-bool xremote_scene_save_remote_item_on_event(void* context, SceneManagerEvent event) {
-    XRemote* app = context;
-    CrossRemote* remote = app->cross_remote;
-    SceneManager* scene_manager = app->scene_manager;
-    bool consumed = false;
-    
-    if(event.type == SceneManagerEventTypeCustom) {
-        cross_remote_rename_item(remote, app->edit_item, app->text_store[0]);
-        scene_manager_next_scene(scene_manager, XRemoteSceneCreate);
-        consumed = true;
-    }
-    return consumed;
-}
-
-void xremote_scene_save_remote_item_on_exit(void* context) {
-    XRemote* app = context;
-    size_t enter_name_length = XREMOTE_MAX_REMOTE_NAME_LENGTH;
-    strncpy(app->text_store[0], "", enter_name_length);
+#include "../xremote.h"
+#include "../models/cross/xremote_remote.h"
+
+#include <string.h>
+#include <toolbox/path.h>
+
+void xremote_scene_save_remote_item_on_enter(void* context) {
+    XRemote* app = context;
+    TextInput* text_input = app->text_input;
+
+    text_input_set_header_text(text_input, "Name the Sequence");
+
+    size_t enter_name_length = XREMOTE_MAX_REMOTE_NAME_LENGTH;
+    CrossRemoteItem* item = cross_remote_get_item(app->cross_remote, app->edit_item);
+    strncpy(app->text_store[0], furi_string_get_cstr(item->name), enter_name_length);
+    text_input_set_result_callback(
+        text_input,
+        xremote_text_input_callback,
+        context,
+        app->text_store[0],
+        enter_name_length,
+        false);
+
+    view_dispatcher_switch_to_view(app->view_dispatcher, XRemoteViewIdTextInput);
+}
+
+bool xremote_scene_save_remote_item_on_event(void* context, SceneManagerEvent event) {
+    XRemote* app = context;
+    CrossRemote* remote = app->cross_remote;
+    SceneManager* scene_manager = app->scene_manager;
+    bool consumed = false;
+
+    if(event.type == SceneManagerEventTypeCustom) {
+        cross_remote_rename_item(remote, app->edit_item, app->text_store[0]);
+        scene_manager_next_scene(scene_manager, XRemoteSceneCreate);
+        consumed = true;
+    }
+    return consumed;
+}
+
+void xremote_scene_save_remote_item_on_exit(void* context) {
+    XRemote* app = context;
+    size_t enter_name_length = XREMOTE_MAX_REMOTE_NAME_LENGTH;
+    strncpy(app->text_store[0], "", enter_name_length);
 }

+ 5 - 23
scenes/xremote_scene_settings.c

@@ -43,7 +43,6 @@ const uint32_t settings_value[2] = {
     XRemoteSettingsOn,
 };
 
-
 static void xremote_scene_settings_set_haptic(VariableItem* item) {
     XRemote* app = variable_item_get_context(item);
     uint8_t index = variable_item_get_current_value_index(item);
@@ -85,48 +84,32 @@ void xremote_scene_settings_on_enter(void* context) {
 
     // Vibro on/off
     item = variable_item_list_add(
-        app->variable_item_list,
-        "Vibro/Haptic:",
-        2,
-        xremote_scene_settings_set_haptic,
-        app);
+        app->variable_item_list, "Vibro/Haptic:", 2, xremote_scene_settings_set_haptic, app);
     value_index = value_index_uint32(app->haptic, haptic_value, 2);
     variable_item_set_current_value_index(item, value_index);
     variable_item_set_current_value_text(item, haptic_text[value_index]);
 
     // Sound on/off
     item = variable_item_list_add(
-        app->variable_item_list,
-        "Sound:",
-        2,
-        xremote_scene_settings_set_speaker,
-        app);
+        app->variable_item_list, "Sound:", 2, xremote_scene_settings_set_speaker, app);
     value_index = value_index_uint32(app->speaker, speaker_value, 2);
     variable_item_set_current_value_index(item, value_index);
     variable_item_set_current_value_text(item, speaker_text[value_index]);
 
     // LED Effects on/off
     item = variable_item_list_add(
-        app->variable_item_list,
-        "LED FX:",
-        2,
-        xremote_scene_settings_set_led,
-        app);
+        app->variable_item_list, "LED FX:", 2, xremote_scene_settings_set_led, app);
     value_index = value_index_uint32(app->led, led_value, 2);
     variable_item_set_current_value_index(item, value_index);
     variable_item_set_current_value_text(item, led_text[value_index]);
 
     // Save Settings to File
     item = variable_item_list_add(
-        app->variable_item_list,
-        "Save Settings",
-        2,
-        xremote_scene_settings_set_save_settings,
-        app);
+        app->variable_item_list, "Save Settings", 2, xremote_scene_settings_set_save_settings, app);
     value_index = value_index_uint32(app->save_settings, settings_value, 2);
     variable_item_set_current_value_index(item, value_index);
     variable_item_set_current_value_text(item, settings_text[value_index]);
-    
+
     view_dispatcher_switch_to_view(app->view_dispatcher, XRemoteViewIdSettings);
 }
 
@@ -135,7 +118,6 @@ bool xremote_scene_settings_on_event(void* context, SceneManagerEvent event) {
     UNUSED(app);
     bool consumed = false;
     if(event.type == SceneManagerEventTypeCustom) {
-        
     }
     return consumed;
 }

+ 2 - 3
scenes/xremote_scene_sg_list.c

@@ -2,7 +2,7 @@
 
 void xremote_scene_sg_list_on_enter(void* context) {
     XRemote* app = context;
-    
+
     DialogsFileBrowserOptions browser_options;
     dialog_file_browser_set_basic_options(&browser_options, SUBGHZ_APP_EXTENSION, &I_sg_10px);
     browser_options.base_path = SUBGHZ_APP_FOLDER;
@@ -10,8 +10,7 @@ void xremote_scene_sg_list_on_enter(void* context) {
     FuriString* path;
     path = furi_string_alloc();
     furi_string_set(path, SUBGHZ_APP_FOLDER);
-    bool success = dialog_file_browser_show(
-        app->dialogs, app->file_path, path, &browser_options);
+    bool success = dialog_file_browser_show(app->dialogs, app->file_path, path, &browser_options);
     furi_string_free(path);
 
     if(success) {

+ 154 - 153
scenes/xremote_scene_transmit.c

@@ -1,154 +1,155 @@
-#include "../xremote.h"
-#include "../views/xremote_transmit.h"
-#include "../models/infrared/xremote_ir_signal.h"
-
-static const NotificationSequence* xremote_notification_sequences[] = {
-    &sequence_success,
-    &sequence_set_only_green_255,
-    &sequence_reset_green,
-    &sequence_solid_yellow,
-    &sequence_reset_rgb,
-    &sequence_blink_start_cyan,
-    &sequence_blink_start_magenta,
-    &sequence_blink_stop,
-    &sequence_blink_start_yellow,
-    &sequence_blink_stop,
-    &sequence_blink_start_blue,
-    &sequence_blink_stop,
-};
-
-void xremote_transmit_callback(XRemoteCustomEvent event, void* context) {
-    furi_assert(context);
-    XRemote* app = context;
-    view_dispatcher_send_custom_event(app->view_dispatcher, event);
-}
-
-void xremote_scene_ir_notification_message(XRemote* app, uint32_t message) {
-    if (app->led == 1) {
-        notification_message(app->notification, xremote_notification_sequences[message]);
-    }
-}
-
-bool xremote_scene_ir_signal_is_raw(InfraredSignal* signal) {
-    if (signal->is_raw) {
-        return true;
-    }
-    return false;
-}
-
-void xremote_scene_transmit_stop_ir_signal(XRemote* app) {
-    if(!app->transmitting) {
-        return;
-    }
-    app->transmitting = false;
-    infrared_worker_tx_stop(app->ir_worker);
-    infrared_worker_tx_set_get_signal_callback(app->ir_worker, NULL, NULL);
-    xremote_scene_ir_notification_message(app, InfraredNotificationMessageBlinkStop);
-}
-
-void xremote_scene_transmit_send_ir_signal(XRemote* app, CrossRemoteItem* item) {
-    InfraredSignal* signal = xremote_remote_item_get_ir_signal(item);
-    dolphin_deed(DolphinDeedIrSend);
-    xremote_scene_ir_notification_message(app, InfraredNotificationMessageBlinkStartSend);
-    if (xremote_scene_ir_signal_is_raw(signal)) {
-        InfraredRawSignal* raw = xremote_ir_signal_get_raw_signal(signal);
-        infrared_worker_set_raw_signal(app->ir_worker, raw->timings, raw->timings_size, raw->frequency, raw->duty_cycle);
-    } else {
-        InfraredMessage* message = xremote_ir_signal_get_message(signal);
-        infrared_worker_set_decoded_signal(app->ir_worker, message);
-    }
-    infrared_worker_tx_set_get_signal_callback(
-        app->ir_worker, infrared_worker_tx_get_signal_steady_callback, app);
-    infrared_worker_tx_start(app->ir_worker);
-    app->transmitting = true;    
-    furi_thread_flags_wait(0, FuriFlagWaitAny, 1000);
-    xremote_scene_transmit_stop_ir_signal(app);
-}
-
-void xremote_scene_transmit_send_pause(XRemote* app, CrossRemoteItem* item) {
-    app->transmitting = true;
-    xremote_scene_ir_notification_message(app, PauseNotificationMessageBlinkStartSend);
-    furi_thread_flags_wait(0, FuriFlagWaitAny, item->time * 1000);
-    app->transmitting = false;
-    xremote_scene_ir_notification_message(app, PauseNotificationMessageBlinkStop);
-}
-
-void xremote_scene_transmit_send_subghz(XRemote* app, CrossRemoteItem* item) {
-    UNUSED(item);
-    app->transmitting = true;
-    xremote_scene_ir_notification_message(app, SubGhzNotificationMessageBlinkStartSend);
-    // ADD SEND METHOD HERE 
-    furi_thread_flags_wait(0, FuriFlagWaitAny, 2000); //Remove later
-    app->transmitting = false;
-    xremote_scene_ir_notification_message(app, SubGhzNotificationMessageBlinkStop);
-}
-
-void xremote_scene_transmit_send_signal(void* context, CrossRemoteItem* item) {
-    furi_assert(context);
-    XRemote* app = context;
-    CrossRemote* remote = app->cross_remote;
-
-    if(app->transmitting) {
-        return;
-    }
-    
-    xremote_transmit_model_set_name(app->xremote_transmit, xremote_remote_item_get_name(item));
-    xremote_transmit_model_set_type(app->xremote_transmit, item->type);
-    if(item->type == XRemoteRemoteItemTypeInfrared) {
-        xremote_scene_transmit_send_ir_signal(app, item);
-    } else if(item->type == XRemoteRemoteItemTypePause) { 
-        xremote_scene_transmit_send_pause(app, item);
-    } else if(item->type == XRemoteRemoteItemTypeSubGhz) {
-        xremote_scene_transmit_send_subghz(app, item);
-    }
-
-    cross_remote_set_transmitting(remote, XRemoteTransmittingStop);
-}
-
-void xremote_scene_transmit_run_remote(void* context) {
-    furi_assert(context);
-    XRemote* app = context;
-    CrossRemote* remote = app->cross_remote;
-
-    size_t item_count = cross_remote_get_item_count(remote);
-    for(size_t i = 0; i < item_count;) {
-        if (cross_remote_get_transmitting(remote) == XRemoteTransmittingIdle) {
-            cross_remote_set_transmitting(remote, XRemoteTransmittingStart);
-            CrossRemoteItem* item = cross_remote_get_item(remote, i);
-            xremote_scene_transmit_send_signal(app, item);
-            //furi_thread_flags_wait(0, FuriFlagWaitAny, 2000);
-            xremote_scene_ir_notification_message(app, InfraredNotificationMessageBlinkStartSend);
-        } else if(cross_remote_get_transmitting(remote) == XRemoteTransmittingStop) {
-            i++;
-            cross_remote_set_transmitting(remote, XRemoteTransmittingIdle);
-        } 
-    }
-    xremote_scene_ir_notification_message(app, InfraredNotificationMessageBlinkStop);
-
-    //scene_manager_next_scene(app->scene_manager, XRemoteSceneXrList);
-    scene_manager_previous_scene(app->scene_manager);
-    //xremote_transmit_model_set_name(app->xremote_transmit, cross_remote_get_name(remote));
-}
-
-void xremote_scene_transmit_on_enter(void* context) {
-    furi_assert(context);
-    XRemote* app = context;
-    xremote_transmit_set_callback(app->xremote_transmit, xremote_transmit_callback, app);
-    
-    view_dispatcher_switch_to_view(app->view_dispatcher, XRemoteViewIdTransmit);
-    xremote_scene_transmit_run_remote(app);
-}
-
-bool xremote_scene_transmit_on_event(void* context, SceneManagerEvent event) {
-    XRemote* app = context;
-
-    UNUSED(app);
-    UNUSED(event);
-    bool consumed = false;
-    return consumed;
-}
-
-void xremote_scene_transmit_on_exit(void* context) {
-    XRemote* app = context;
-    UNUSED(app);
+#include "../xremote.h"
+#include "../views/xremote_transmit.h"
+#include "../models/infrared/xremote_ir_signal.h"
+
+static const NotificationSequence* xremote_notification_sequences[] = {
+    &sequence_success,
+    &sequence_set_only_green_255,
+    &sequence_reset_green,
+    &sequence_solid_yellow,
+    &sequence_reset_rgb,
+    &sequence_blink_start_cyan,
+    &sequence_blink_start_magenta,
+    &sequence_blink_stop,
+    &sequence_blink_start_yellow,
+    &sequence_blink_stop,
+    &sequence_blink_start_blue,
+    &sequence_blink_stop,
+};
+
+void xremote_transmit_callback(XRemoteCustomEvent event, void* context) {
+    furi_assert(context);
+    XRemote* app = context;
+    view_dispatcher_send_custom_event(app->view_dispatcher, event);
+}
+
+void xremote_scene_ir_notification_message(XRemote* app, uint32_t message) {
+    if(app->led == 1) {
+        notification_message(app->notification, xremote_notification_sequences[message]);
+    }
+}
+
+bool xremote_scene_ir_signal_is_raw(InfraredSignal* signal) {
+    if(signal->is_raw) {
+        return true;
+    }
+    return false;
+}
+
+void xremote_scene_transmit_stop_ir_signal(XRemote* app) {
+    if(!app->transmitting) {
+        return;
+    }
+    app->transmitting = false;
+    infrared_worker_tx_stop(app->ir_worker);
+    infrared_worker_tx_set_get_signal_callback(app->ir_worker, NULL, NULL);
+    xremote_scene_ir_notification_message(app, InfraredNotificationMessageBlinkStop);
+}
+
+void xremote_scene_transmit_send_ir_signal(XRemote* app, CrossRemoteItem* item) {
+    InfraredSignal* signal = xremote_remote_item_get_ir_signal(item);
+    dolphin_deed(DolphinDeedIrSend);
+    xremote_scene_ir_notification_message(app, InfraredNotificationMessageBlinkStartSend);
+    if(xremote_scene_ir_signal_is_raw(signal)) {
+        InfraredRawSignal* raw = xremote_ir_signal_get_raw_signal(signal);
+        infrared_worker_set_raw_signal(
+            app->ir_worker, raw->timings, raw->timings_size, raw->frequency, raw->duty_cycle);
+    } else {
+        InfraredMessage* message = xremote_ir_signal_get_message(signal);
+        infrared_worker_set_decoded_signal(app->ir_worker, message);
+    }
+    infrared_worker_tx_set_get_signal_callback(
+        app->ir_worker, infrared_worker_tx_get_signal_steady_callback, app);
+    infrared_worker_tx_start(app->ir_worker);
+    app->transmitting = true;
+    furi_thread_flags_wait(0, FuriFlagWaitAny, 1000);
+    xremote_scene_transmit_stop_ir_signal(app);
+}
+
+void xremote_scene_transmit_send_pause(XRemote* app, CrossRemoteItem* item) {
+    app->transmitting = true;
+    xremote_scene_ir_notification_message(app, PauseNotificationMessageBlinkStartSend);
+    furi_thread_flags_wait(0, FuriFlagWaitAny, item->time * 1000);
+    app->transmitting = false;
+    xremote_scene_ir_notification_message(app, PauseNotificationMessageBlinkStop);
+}
+
+void xremote_scene_transmit_send_subghz(XRemote* app, CrossRemoteItem* item) {
+    UNUSED(item);
+    app->transmitting = true;
+    xremote_scene_ir_notification_message(app, SubGhzNotificationMessageBlinkStartSend);
+    // ADD SEND METHOD HERE
+    furi_thread_flags_wait(0, FuriFlagWaitAny, 2000); //Remove later
+    app->transmitting = false;
+    xremote_scene_ir_notification_message(app, SubGhzNotificationMessageBlinkStop);
+}
+
+void xremote_scene_transmit_send_signal(void* context, CrossRemoteItem* item) {
+    furi_assert(context);
+    XRemote* app = context;
+    CrossRemote* remote = app->cross_remote;
+
+    if(app->transmitting) {
+        return;
+    }
+
+    xremote_transmit_model_set_name(app->xremote_transmit, xremote_remote_item_get_name(item));
+    xremote_transmit_model_set_type(app->xremote_transmit, item->type);
+    if(item->type == XRemoteRemoteItemTypeInfrared) {
+        xremote_scene_transmit_send_ir_signal(app, item);
+    } else if(item->type == XRemoteRemoteItemTypePause) {
+        xremote_scene_transmit_send_pause(app, item);
+    } else if(item->type == XRemoteRemoteItemTypeSubGhz) {
+        xremote_scene_transmit_send_subghz(app, item);
+    }
+
+    cross_remote_set_transmitting(remote, XRemoteTransmittingStop);
+}
+
+void xremote_scene_transmit_run_remote(void* context) {
+    furi_assert(context);
+    XRemote* app = context;
+    CrossRemote* remote = app->cross_remote;
+
+    size_t item_count = cross_remote_get_item_count(remote);
+    for(size_t i = 0; i < item_count;) {
+        if(cross_remote_get_transmitting(remote) == XRemoteTransmittingIdle) {
+            cross_remote_set_transmitting(remote, XRemoteTransmittingStart);
+            CrossRemoteItem* item = cross_remote_get_item(remote, i);
+            xremote_scene_transmit_send_signal(app, item);
+            //furi_thread_flags_wait(0, FuriFlagWaitAny, 2000);
+            xremote_scene_ir_notification_message(app, InfraredNotificationMessageBlinkStartSend);
+        } else if(cross_remote_get_transmitting(remote) == XRemoteTransmittingStop) {
+            i++;
+            cross_remote_set_transmitting(remote, XRemoteTransmittingIdle);
+        }
+    }
+    xremote_scene_ir_notification_message(app, InfraredNotificationMessageBlinkStop);
+
+    //scene_manager_next_scene(app->scene_manager, XRemoteSceneXrList);
+    scene_manager_previous_scene(app->scene_manager);
+    //xremote_transmit_model_set_name(app->xremote_transmit, cross_remote_get_name(remote));
+}
+
+void xremote_scene_transmit_on_enter(void* context) {
+    furi_assert(context);
+    XRemote* app = context;
+    xremote_transmit_set_callback(app->xremote_transmit, xremote_transmit_callback, app);
+
+    view_dispatcher_switch_to_view(app->view_dispatcher, XRemoteViewIdTransmit);
+    xremote_scene_transmit_run_remote(app);
+}
+
+bool xremote_scene_transmit_on_event(void* context, SceneManagerEvent event) {
+    XRemote* app = context;
+
+    UNUSED(app);
+    UNUSED(event);
+    bool consumed = false;
+    return consumed;
+}
+
+void xremote_scene_transmit_on_exit(void* context) {
+    XRemote* app = context;
+    UNUSED(app);
 }

+ 37 - 38
scenes/xremote_scene_wip.c

@@ -1,39 +1,38 @@
-#include "../xremote.h"
-
-void xremote_scene_wip_on_enter(void* context) {
-    furi_assert(context);
-    XRemote* app = context;
-    Popup* popup = app->popup;
-    
-    //popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62);
-    popup_set_header(popup, "SubGhz coming soon", 10, 19, AlignLeft, AlignBottom);
-    popup_set_text(popup, "Check back later", 10, 29, AlignLeft, AlignBottom);
-    popup_set_text(popup, "Press back long", 10, 39, AlignLeft, AlignBottom);
-
-    popup_set_callback(popup, xremote_popup_closed_callback);
-    popup_set_context(popup, context);
-    popup_set_timeout(popup, 100);
-    popup_enable_timeout(popup);
-
-    view_dispatcher_switch_to_view(app->view_dispatcher, XRemoteViewIdWip);
-}
-
-bool xremote_scene_wip_on_event(void* context, SceneManagerEvent event) {
-    XRemote* app = context;
-    UNUSED(app);
-    bool consumed = false;
-    
-    if(event.type == SceneManagerEventTypeCustom) {
-        if (event.event == XRemoteCustomEventTypePopupClosed) {
-
-        }
-        consumed = true;
-    }
-    
-    return consumed;
-}
-
-void xremote_scene_wip_on_exit(void* context) {
-    XRemote* app = context;
-    UNUSED(app);
+#include "../xremote.h"
+
+void xremote_scene_wip_on_enter(void* context) {
+    furi_assert(context);
+    XRemote* app = context;
+    Popup* popup = app->popup;
+
+    //popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62);
+    popup_set_header(popup, "SubGhz coming soon", 10, 19, AlignLeft, AlignBottom);
+    popup_set_text(popup, "Check back later", 10, 29, AlignLeft, AlignBottom);
+    popup_set_text(popup, "Press back long", 10, 39, AlignLeft, AlignBottom);
+
+    popup_set_callback(popup, xremote_popup_closed_callback);
+    popup_set_context(popup, context);
+    popup_set_timeout(popup, 100);
+    popup_enable_timeout(popup);
+
+    view_dispatcher_switch_to_view(app->view_dispatcher, XRemoteViewIdWip);
+}
+
+bool xremote_scene_wip_on_event(void* context, SceneManagerEvent event) {
+    XRemote* app = context;
+    UNUSED(app);
+    bool consumed = false;
+
+    if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == XRemoteCustomEventTypePopupClosed) {
+        }
+        consumed = true;
+    }
+
+    return consumed;
+}
+
+void xremote_scene_wip_on_exit(void* context) {
+    XRemote* app = context;
+    UNUSED(app);
 }

+ 46 - 43
scenes/xremote_scene_xr_list.c

@@ -1,44 +1,47 @@
-#include "../xremote.h"
-
-void xremote_scene_xr_list_on_enter(void* context) {
-    XRemote* app = context;
-    
-    DialogsFileBrowserOptions browser_options;
-    dialog_file_browser_set_basic_options(&browser_options, XREMOTE_APP_EXTENSION, &I_xr_10px);
-    browser_options.base_path = XREMOTE_APP_FOLDER;
-
-    FuriString* path;
-    path = furi_string_alloc();
-    furi_string_set(path, XREMOTE_APP_FOLDER);
-
-    bool success = dialog_file_browser_show(
-        //app->dialogs, app->file_path, app->file_path, &browser_options);
-        app->dialogs, app->file_path, path, &browser_options);
-    furi_string_free(path);
-
-    if(success) {
-        //Load Remote into buffer
-        success = cross_remote_load(app->cross_remote, app->file_path);
-    }
-
-    if(success) {
-        //Load Remote Button View
-        //scene_manager_next_scene(app->scene_manager, XRemoteSceneWip);
-        scene_manager_next_scene(app->scene_manager, XRemoteSceneTransmit);
-    } else {
-        //scene_manager_next_scene(app->scene_manager, XRemoteSceneWip);
-        scene_manager_previous_scene(app->scene_manager);
-    }
-}
-
-bool xremote_scene_xr_list_on_event(void* context, SceneManagerEvent event) {
-    UNUSED(context);
-    UNUSED(event);
-    bool consumed = true;
-
-    return consumed;
-}
-
-void xremote_scene_xr_list_on_exit(void* context) {
-    UNUSED(context);
+#include "../xremote.h"
+
+void xremote_scene_xr_list_on_enter(void* context) {
+    XRemote* app = context;
+
+    DialogsFileBrowserOptions browser_options;
+    dialog_file_browser_set_basic_options(&browser_options, XREMOTE_APP_EXTENSION, &I_xr_10px);
+    browser_options.base_path = XREMOTE_APP_FOLDER;
+
+    FuriString* path;
+    path = furi_string_alloc();
+    furi_string_set(path, XREMOTE_APP_FOLDER);
+
+    bool success = dialog_file_browser_show(
+        //app->dialogs, app->file_path, app->file_path, &browser_options);
+        app->dialogs,
+        app->file_path,
+        path,
+        &browser_options);
+    furi_string_free(path);
+
+    if(success) {
+        //Load Remote into buffer
+        success = cross_remote_load(app->cross_remote, app->file_path);
+    }
+
+    if(success) {
+        //Load Remote Button View
+        //scene_manager_next_scene(app->scene_manager, XRemoteSceneWip);
+        scene_manager_next_scene(app->scene_manager, XRemoteSceneTransmit);
+    } else {
+        //scene_manager_next_scene(app->scene_manager, XRemoteSceneWip);
+        scene_manager_previous_scene(app->scene_manager);
+    }
+}
+
+bool xremote_scene_xr_list_on_event(void* context, SceneManagerEvent event) {
+    UNUSED(context);
+    UNUSED(event);
+    bool consumed = true;
+
+    return consumed;
+}
+
+void xremote_scene_xr_list_on_exit(void* context) {
+    UNUSED(context);
 }

+ 41 - 42
scenes/xremote_scene_xr_list_edit.c

@@ -1,43 +1,42 @@
-#include "../xremote.h"
-
-void xremote_scene_xr_list_edit_on_enter(void* context) {
-    XRemote* app = context;
-    
-    DialogsFileBrowserOptions browser_options;
-    dialog_file_browser_set_basic_options(&browser_options, XREMOTE_APP_EXTENSION, &I_xr_10px);
-    browser_options.base_path = XREMOTE_APP_FOLDER;
-
-    FuriString* path;
-    path = furi_string_alloc();
-    furi_string_set(path, XREMOTE_APP_FOLDER);
-
-    bool success = dialog_file_browser_show(
-        app->dialogs, app->file_path, path, &browser_options);
-    furi_string_free(path);
-
-    if(success) {
-        //Load Remote into buffer
-        success = cross_remote_load(app->cross_remote, app->file_path);
-    }
-
-    if(success) {
-        //Load Remote Button View
-        //scene_manager_next_scene(app->scene_manager, XRemoteSceneWip);
-        scene_manager_next_scene(app->scene_manager, XRemoteSceneXrListEditItem);
-    } else {
-        //scene_manager_next_scene(app->scene_manager, XRemoteSceneWip);
-        scene_manager_previous_scene(app->scene_manager);
-    }
-}
-
-bool xremote_scene_xr_list_edit_on_event(void* context, SceneManagerEvent event) {
-    UNUSED(context);
-    UNUSED(event);
-    bool consumed = true;
-
-    return consumed;
-}
-
-void xremote_scene_xr_list_edit_on_exit(void* context) {
-    UNUSED(context);
+#include "../xremote.h"
+
+void xremote_scene_xr_list_edit_on_enter(void* context) {
+    XRemote* app = context;
+
+    DialogsFileBrowserOptions browser_options;
+    dialog_file_browser_set_basic_options(&browser_options, XREMOTE_APP_EXTENSION, &I_xr_10px);
+    browser_options.base_path = XREMOTE_APP_FOLDER;
+
+    FuriString* path;
+    path = furi_string_alloc();
+    furi_string_set(path, XREMOTE_APP_FOLDER);
+
+    bool success = dialog_file_browser_show(app->dialogs, app->file_path, path, &browser_options);
+    furi_string_free(path);
+
+    if(success) {
+        //Load Remote into buffer
+        success = cross_remote_load(app->cross_remote, app->file_path);
+    }
+
+    if(success) {
+        //Load Remote Button View
+        //scene_manager_next_scene(app->scene_manager, XRemoteSceneWip);
+        scene_manager_next_scene(app->scene_manager, XRemoteSceneXrListEditItem);
+    } else {
+        //scene_manager_next_scene(app->scene_manager, XRemoteSceneWip);
+        scene_manager_previous_scene(app->scene_manager);
+    }
+}
+
+bool xremote_scene_xr_list_edit_on_event(void* context, SceneManagerEvent event) {
+    UNUSED(context);
+    UNUSED(event);
+    bool consumed = true;
+
+    return consumed;
+}
+
+void xremote_scene_xr_list_edit_on_exit(void* context) {
+    UNUSED(context);
 }

+ 64 - 50
scenes/xremote_scene_xr_list_edit_item.c

@@ -1,51 +1,65 @@
-#include "../xremote.h"
-
-enum SubmenuIndexEdit {
-    SubmenuIndexRename = 10,
-    SubmenuIndexEdit,
-    SubmenuIndexDelete,
-};
-
-void xremote_scene_xr_list_edit_item_submenu_callback(void* context, uint32_t index) {
-    XRemote* app = context;
-    view_dispatcher_send_custom_event(app->view_dispatcher, index);
-}
-
-void xremote_scene_xr_list_edit_item_on_enter(void* context) {
-    XRemote* app = context;
-    //submenu_add_item(app->editmenu, "Rename", SubmenuIndexRename, xremote_scene_xr_list_edit_item_submenu_callback, app);
-    submenu_add_item(app->editmenu, "Edit", SubmenuIndexEdit, xremote_scene_xr_list_edit_item_submenu_callback, app);
-    submenu_add_item(app->editmenu, "Delete", SubmenuIndexDelete, xremote_scene_xr_list_edit_item_submenu_callback, app);
-
-    submenu_set_selected_item(app->editmenu, scene_manager_get_scene_state(app->scene_manager, XRemoteSceneMenu));
-
-    view_dispatcher_switch_to_view(app->view_dispatcher, XRemoteViewIdEditItem);
-}
-
-bool xremote_scene_xr_list_edit_item_on_event(void* context, SceneManagerEvent event) {
-    XRemote* app = context;
-    if(event.type == SceneManagerEventTypeBack) {
-        //exit app
-        scene_manager_previous_scene(app->scene_manager);
-        return true;
-    } else if(event.type == SceneManagerEventTypeCustom) {
-        if(event.event == SubmenuIndexDelete) { 
-            cross_remote_delete(app->cross_remote);
-        } else if(event.event == SubmenuIndexEdit) {
-            strncpy(app->text_store[0], cross_remote_get_name(app->cross_remote), XREMOTE_MAX_REMOTE_NAME_LENGTH);
-            scene_manager_next_scene(app->scene_manager, XRemoteSceneCreate);
-            return 0;
-        } else if(event.event == SubmenuIndexRename) {
-            //scene_manager_next_scene(app->scene_manager, XRemoteSceneSaveRemoteItem);
-            //scene_manager_next_scene(app->scene_manager, XRemoteSceneWip);
-            return 0;
-        }
-        scene_manager_previous_scene(app->scene_manager);
-    }
-    return 0;
-}
-
-void xremote_scene_xr_list_edit_item_on_exit(void* context) {
-    XRemote* app = context;
-    submenu_reset(app->editmenu);
+#include "../xremote.h"
+
+enum SubmenuIndexEdit {
+    SubmenuIndexRename = 10,
+    SubmenuIndexEdit,
+    SubmenuIndexDelete,
+};
+
+void xremote_scene_xr_list_edit_item_submenu_callback(void* context, uint32_t index) {
+    XRemote* app = context;
+    view_dispatcher_send_custom_event(app->view_dispatcher, index);
+}
+
+void xremote_scene_xr_list_edit_item_on_enter(void* context) {
+    XRemote* app = context;
+    //submenu_add_item(app->editmenu, "Rename", SubmenuIndexRename, xremote_scene_xr_list_edit_item_submenu_callback, app);
+    submenu_add_item(
+        app->editmenu,
+        "Edit",
+        SubmenuIndexEdit,
+        xremote_scene_xr_list_edit_item_submenu_callback,
+        app);
+    submenu_add_item(
+        app->editmenu,
+        "Delete",
+        SubmenuIndexDelete,
+        xremote_scene_xr_list_edit_item_submenu_callback,
+        app);
+
+    submenu_set_selected_item(
+        app->editmenu, scene_manager_get_scene_state(app->scene_manager, XRemoteSceneMenu));
+
+    view_dispatcher_switch_to_view(app->view_dispatcher, XRemoteViewIdEditItem);
+}
+
+bool xremote_scene_xr_list_edit_item_on_event(void* context, SceneManagerEvent event) {
+    XRemote* app = context;
+    if(event.type == SceneManagerEventTypeBack) {
+        //exit app
+        scene_manager_previous_scene(app->scene_manager);
+        return true;
+    } else if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == SubmenuIndexDelete) {
+            cross_remote_delete(app->cross_remote);
+        } else if(event.event == SubmenuIndexEdit) {
+            strncpy(
+                app->text_store[0],
+                cross_remote_get_name(app->cross_remote),
+                XREMOTE_MAX_REMOTE_NAME_LENGTH);
+            scene_manager_next_scene(app->scene_manager, XRemoteSceneCreate);
+            return 0;
+        } else if(event.event == SubmenuIndexRename) {
+            //scene_manager_next_scene(app->scene_manager, XRemoteSceneSaveRemoteItem);
+            //scene_manager_next_scene(app->scene_manager, XRemoteSceneWip);
+            return 0;
+        }
+        scene_manager_previous_scene(app->scene_manager);
+    }
+    return 0;
+}
+
+void xremote_scene_xr_list_edit_item_on_exit(void* context) {
+    XRemote* app = context;
+    submenu_reset(app->editmenu);
 }

+ 37 - 50
views/xremote_infoscreen.c

@@ -7,7 +7,6 @@ struct XRemoteInfoscreen {
     void* context;
 };
 
-
 typedef struct {
     int some_value;
 } XRemoteInfoscreenModel;
@@ -27,11 +26,11 @@ void xremote_infoscreen_draw(Canvas* canvas, XRemoteInfoscreenModel* model) {
     canvas_clear(canvas);
     canvas_set_color(canvas, ColorBlack);
     canvas_set_font(canvas, FontPrimary);
-    canvas_draw_str_aligned(canvas, 64, 10, AlignCenter, AlignTop, "Cross Remote"); 
+    canvas_draw_str_aligned(canvas, 64, 10, AlignCenter, AlignTop, "Cross Remote");
     canvas_set_font(canvas, FontSecondary);
-    canvas_draw_str_aligned(canvas, 64, 22, AlignCenter, AlignTop, "Chain IR and SubGhz"); 
+    canvas_draw_str_aligned(canvas, 64, 22, AlignCenter, AlignTop, "Chain IR and SubGhz");
     canvas_draw_str_aligned(canvas, 64, 32, AlignCenter, AlignTop, "Commands");
-    elements_button_center(canvas, "Back"); 
+    elements_button_center(canvas, "Back");
 }
 
 static void xremote_infoscreen_model_init(XRemoteInfoscreenModel* const model) {
@@ -39,36 +38,36 @@ static void xremote_infoscreen_model_init(XRemoteInfoscreenModel* const model) {
 }
 
 bool xremote_infoscreen_input(InputEvent* event, void* context) {
-    furi_assert(context); 
+    furi_assert(context);
     XRemoteInfoscreen* instance = context;
-    if (event->type == InputTypeRelease) {
+    if(event->type == InputTypeRelease) {
         switch(event->key) {
-            case InputKeyBack:
-                with_view_model(
-                    instance->view,
-                    XRemoteInfoscreenModel * model,
-                    {
-                        UNUSED(model);
-                        instance->callback(XRemoteCustomEventInfoscreenBack, instance->context);
-                    },
-                    true);
-                break;
-            case InputKeyLeft:
-            case InputKeyRight:
-            case InputKeyUp:
-            case InputKeyDown:
-            case InputKeyOk:
-                with_view_model(
-                    instance->view,
-                    XRemoteInfoscreenModel* model,
-                    {
-                        UNUSED(model);
-                        instance->callback(XRemoteCustomEventInfoscreenOk, instance->context);
-                    },
-                    true);
-                break;
-            case InputKeyMAX:
-                break;
+        case InputKeyBack:
+            with_view_model(
+                instance->view,
+                XRemoteInfoscreenModel * model,
+                {
+                    UNUSED(model);
+                    instance->callback(XRemoteCustomEventInfoscreenBack, instance->context);
+                },
+                true);
+            break;
+        case InputKeyLeft:
+        case InputKeyRight:
+        case InputKeyUp:
+        case InputKeyDown:
+        case InputKeyOk:
+            with_view_model(
+                instance->view,
+                XRemoteInfoscreenModel * model,
+                {
+                    UNUSED(model);
+                    instance->callback(XRemoteCustomEventInfoscreenOk, instance->context);
+                },
+                true);
+            break;
+        case InputKeyMAX:
+            break;
         }
     }
     return true;
@@ -84,11 +83,8 @@ void xremote_infoscreen_enter(void* context) {
     with_view_model(
         instance->view,
         XRemoteInfoscreenModel * model,
-        {
-            xremote_infoscreen_model_init(model);
-        },
-        true
-    );
+        { xremote_infoscreen_model_init(model); },
+        true);
 }
 
 XRemoteInfoscreen* xremote_infoscreen_alloc() {
@@ -104,12 +100,9 @@ XRemoteInfoscreen* xremote_infoscreen_alloc() {
     with_view_model(
         instance->view,
         XRemoteInfoscreenModel * model,
-        {
-            xremote_infoscreen_model_init(model);
-        },
-        true
-    );
-    
+        { xremote_infoscreen_model_init(model); },
+        true);
+
     return instance;
 }
 
@@ -117,12 +110,7 @@ void xremote_infoscreen_free(XRemoteInfoscreen* instance) {
     furi_assert(instance);
 
     with_view_model(
-        instance->view,
-        XRemoteInfoscreenModel * model,
-        {
-            UNUSED(model);
-        },
-        true);
+        instance->view, XRemoteInfoscreenModel * model, { UNUSED(model); }, true);
     view_free(instance->view);
     free(instance);
 }
@@ -131,4 +119,3 @@ View* xremote_infoscreen_get_view(XRemoteInfoscreen* instance) {
     furi_assert(instance);
     return instance->view;
 }
-

+ 53 - 60
views/xremote_pause_set.c

@@ -33,64 +33,63 @@ void xremote_pause_set_draw(Canvas* canvas, XRemotePauseSetModel* model) {
     canvas_clear(canvas);
     canvas_set_color(canvas, ColorBlack);
     canvas_set_font(canvas, FontPrimary);
-    canvas_draw_str_aligned(canvas, 64, 10, AlignCenter, AlignTop, "Pause duration"); 
+    canvas_draw_str_aligned(canvas, 64, 10, AlignCenter, AlignTop, "Pause duration");
     canvas_set_font(canvas, FontSecondary);
     canvas_draw_icon(canvas, 59, 22, &I_ButtonUp_10x5);
     canvas_draw_icon(canvas, 59, 42, &I_ButtonDown_10x5);
-    canvas_draw_str_aligned(canvas, 64, 31, AlignCenter, AlignTop, seconds); 
-    elements_button_center(canvas, "Add"); 
+    canvas_draw_str_aligned(canvas, 64, 31, AlignCenter, AlignTop, seconds);
+    elements_button_center(canvas, "Add");
 }
 
 bool xremote_pause_set_input(InputEvent* event, void* context) {
     furi_assert(context);
     XRemotePauseSet* instance = context;
-    if (event->type == InputTypeRelease) {
+    if(event->type == InputTypeRelease) {
         switch(event->key) {
-            case InputKeyBack:
-                instance->callback(XRemoteCustomEventPauseSetBack, instance->context);
-                break;
-            case InputKeyLeft:
-            case InputKeyRight:
-                break;
-            case InputKeyUp:
-                with_view_model(
-                    instance->view,
-                    XRemotePauseSetModel* model,
-                    {
-                        model->time++;
-                        if (model->time > 9) {
-                            model->time = 0;
-                        }
-                    },
-                    true);
-                break;
-            case InputKeyDown:
-                with_view_model(
-                    instance->view,
-                    XRemotePauseSetModel* model,
-                    {
-                        model->time--;
-                        if (model->time < 0) {
-                            model->time = 9;
-                        }
-                    },
-                    true);
-                break;
-            case InputKeyOk:
-                with_view_model(
-                    instance->view,
-                    XRemotePauseSetModel * model,
-                    {
-                        XRemote* app = instance->context;
-                        cross_remote_add_pause(app->cross_remote, model->time);
-                    },
-                    true
-                );
+        case InputKeyBack:
+            instance->callback(XRemoteCustomEventPauseSetBack, instance->context);
+            break;
+        case InputKeyLeft:
+        case InputKeyRight:
+            break;
+        case InputKeyUp:
+            with_view_model(
+                instance->view,
+                XRemotePauseSetModel * model,
+                {
+                    model->time++;
+                    if(model->time > 9) {
+                        model->time = 0;
+                    }
+                },
+                true);
+            break;
+        case InputKeyDown:
+            with_view_model(
+                instance->view,
+                XRemotePauseSetModel * model,
+                {
+                    model->time--;
+                    if(model->time < 0) {
+                        model->time = 9;
+                    }
+                },
+                true);
+            break;
+        case InputKeyOk:
+            with_view_model(
+                instance->view,
+                XRemotePauseSetModel * model,
+                {
+                    XRemote* app = instance->context;
+                    cross_remote_add_pause(app->cross_remote, model->time);
+                },
+                true);
 
-                instance->callback(XRemoteCustomEventPauseSetOk, instance->context);
-                break;
-            case InputKeyMAX:
-                break;
+            instance->callback(XRemoteCustomEventPauseSetOk, instance->context);
+            break;
+        case InputKeyMAX:
+            break;
         }
     }
     return true;
@@ -104,30 +103,24 @@ XRemotePauseSet* xremote_pause_set_alloc() {
     view_set_draw_callback(instance->view, (ViewDrawCallback)xremote_pause_set_draw);
     view_set_enter_callback(instance->view, xremote_pause_set_enter);
     view_set_input_callback(instance->view, xremote_pause_set_input);
-    
+
     with_view_model(
         instance->view,
         XRemotePauseSetModel * model,
-        {
-            xremote_pause_set_model_init(model);
-        },
-        true
-    );
+        { xremote_pause_set_model_init(model); },
+        true);
 
     return instance;
 }
 
 void xremote_pause_set_enter(void* context) {
     furi_assert(context);
-    XRemotePauseSet* instance = (XRemotePauseSet*) context;
+    XRemotePauseSet* instance = (XRemotePauseSet*)context;
     with_view_model(
         instance->view,
         XRemotePauseSetModel * model,
-        {
-            xremote_pause_set_model_init(model);
-        },
-        true
-    );
+        { xremote_pause_set_model_init(model); },
+        true);
 }
 
 View* xremote_pause_set_get_view(XRemotePauseSet* instance) {

+ 139 - 150
views/xremote_transmit.c

@@ -1,151 +1,140 @@
-#include "xremote_transmit.h"
-
-struct XRemoteTransmit {
-    View* view;
-    XRemoteTransmitCallback callback;
-    void* context;
-};
-
-typedef struct {
-    int type;
-    const char* name;
-    int time;
-} XRemoteTransmitModel;
-
-static void xremote_transmit_model_init(XRemoteTransmitModel* const model) {
-    model->type = XRemoteRemoteItemTypeInfrared;
-    model->time = 1;
-}
-
-void xremote_transmit_model_set_name(XRemoteTransmit* instance, const char* name) {
-    furi_assert(instance);
-    XRemoteTransmitModel* model = view_get_model(instance->view);
-    model->name = name;
-    view_commit_model(instance->view, false);
-}
-
-void xremote_transmit_model_set_type(XRemoteTransmit* instance, int type) {
-    furi_assert(instance);
-    XRemoteTransmitModel* model = view_get_model(instance->view);
-    model->time = 1;
-    model->type = type;
-    view_commit_model(instance->view, false);
-}
-
-void xremote_transmit_set_callback(
-    XRemoteTransmit* instance,
-    XRemoteTransmitCallback callback,
-    void* context) {
-    furi_assert(instance);
-    furi_assert(callback);
-    instance->callback = callback;
-    instance->context = context;
-}
-
-void xremote_transmit_draw_ir(Canvas* canvas, XRemoteTransmitModel* model) {
-    model->time++;
-    canvas_clear(canvas);
-    canvas_set_color(canvas, ColorBlack);
-    canvas_draw_icon(canvas, 0, 0, &I_ir_transmit_128x64);
-    canvas_set_font(canvas, FontPrimary);
-    canvas_draw_str_aligned(canvas, 74, 5, AlignLeft, AlignTop, "Sending"); 
-    canvas_set_font(canvas, FontSecondary);
-    canvas_draw_str_aligned(canvas, 74, 20, AlignLeft, AlignTop, "Infrared"); 
-    canvas_draw_str_aligned(canvas, 74, 30, AlignLeft, AlignTop, model->name);
-    
-    char temp_str[18];
-    snprintf(temp_str, 18, "%u", model->time);
-    canvas_draw_str_aligned(canvas, 74, 40, AlignLeft, AlignTop, temp_str);
-}
-
-void xremote_transmit_draw_pause(Canvas* canvas, XRemoteTransmitModel* model) {
-    model->time++;
-    canvas_clear(canvas);
-    canvas_set_color(canvas, ColorBlack);
-    canvas_draw_icon(canvas, 0, 0, &I_pause_128x64);
-    canvas_set_font(canvas, FontPrimary);
-    canvas_draw_str_aligned(canvas, 74, 5, AlignLeft, AlignTop, "Waiting"); 
-    canvas_set_font(canvas, FontSecondary);
-    canvas_draw_str_aligned(canvas, 74, 20, AlignLeft, AlignTop, "Sequence"); 
-    canvas_draw_str_aligned(canvas, 74, 30, AlignLeft, AlignTop, model->name);
-    
-    char temp_str[18];
-    snprintf(temp_str, 18, "%u", model->time);
-    canvas_draw_str_aligned(canvas, 74, 40, AlignLeft, AlignTop, temp_str);
-}
-
-void xremote_transmit_draw_subghz(Canvas* canvas, XRemoteTransmitModel* model) {
-    model->time++;
-    canvas_clear(canvas);
-    canvas_set_color(canvas, ColorBlack);
-    canvas_draw_icon(canvas, 0, 0, &I_sg_transmit_128x64);
-    canvas_set_font(canvas, FontPrimary);
-    canvas_draw_str_aligned(canvas, 74, 5, AlignLeft, AlignTop, "Sending"); 
-    canvas_set_font(canvas, FontSecondary);
-    canvas_draw_str_aligned(canvas, 74, 20, AlignLeft, AlignTop, "SubGhz"); 
-    canvas_draw_str_aligned(canvas, 74, 30, AlignLeft, AlignTop, model->name);
-    
-    char temp_str[18];
-    snprintf(temp_str, 18, "%u", model->time);
-    canvas_draw_str_aligned(canvas, 74, 40, AlignLeft, AlignTop, temp_str);
-}
-
-void xremote_transmit_draw(Canvas* canvas, XRemoteTransmitModel* model) {
-    if(model->type == XRemoteRemoteItemTypeInfrared) {
-        xremote_transmit_draw_ir(canvas, model);
-    } else if(model->type == XRemoteRemoteItemTypePause) {
-        xremote_transmit_draw_pause(canvas, model);
-    }
-}
-
-XRemoteTransmit* xremote_transmit_alloc() {
-    XRemoteTransmit* instance = malloc(sizeof(XRemoteTransmit));
-    instance->view = view_alloc();
-    view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(XRemoteTransmitModel));
-    view_set_context(instance->view, instance);
-    view_set_draw_callback(instance->view, (ViewDrawCallback)xremote_transmit_draw);
-    view_set_enter_callback(instance->view, xremote_transmit_enter);
-
-    with_view_model(
-        instance->view,
-        XRemoteTransmitModel * model,
-        {
-            xremote_transmit_model_init(model);
-        },
-        true
-    );
-
-    return instance;
-}
-
-void xremote_transmit_enter(void* context) {
-    furi_assert(context);
-    XRemoteTransmit* instance = (XRemoteTransmit*) context;
-    with_view_model(
-        instance->view,
-        XRemoteTransmitModel * model,
-        {
-            xremote_transmit_model_init(model);
-        },
-        true
-    );
-}
-
-void xremote_transmit_free(XRemoteTransmit* instance) {
-    furi_assert(instance);
-
-    with_view_model(
-        instance->view,
-        XRemoteTransmitModel * model,
-        {
-            UNUSED(model);
-        },
-        true);
-    view_free(instance->view);
-    free(instance);
-}
-
-View* xremote_transmit_get_view(XRemoteTransmit* instance) {
-    furi_assert(instance);
-    return instance->view;
+#include "xremote_transmit.h"
+
+struct XRemoteTransmit {
+    View* view;
+    XRemoteTransmitCallback callback;
+    void* context;
+};
+
+typedef struct {
+    int type;
+    const char* name;
+    int time;
+} XRemoteTransmitModel;
+
+static void xremote_transmit_model_init(XRemoteTransmitModel* const model) {
+    model->type = XRemoteRemoteItemTypeInfrared;
+    model->time = 1;
+}
+
+void xremote_transmit_model_set_name(XRemoteTransmit* instance, const char* name) {
+    furi_assert(instance);
+    XRemoteTransmitModel* model = view_get_model(instance->view);
+    model->name = name;
+    view_commit_model(instance->view, false);
+}
+
+void xremote_transmit_model_set_type(XRemoteTransmit* instance, int type) {
+    furi_assert(instance);
+    XRemoteTransmitModel* model = view_get_model(instance->view);
+    model->time = 1;
+    model->type = type;
+    view_commit_model(instance->view, false);
+}
+
+void xremote_transmit_set_callback(
+    XRemoteTransmit* instance,
+    XRemoteTransmitCallback callback,
+    void* context) {
+    furi_assert(instance);
+    furi_assert(callback);
+    instance->callback = callback;
+    instance->context = context;
+}
+
+void xremote_transmit_draw_ir(Canvas* canvas, XRemoteTransmitModel* model) {
+    model->time++;
+    canvas_clear(canvas);
+    canvas_set_color(canvas, ColorBlack);
+    canvas_draw_icon(canvas, 0, 0, &I_ir_transmit_128x64);
+    canvas_set_font(canvas, FontPrimary);
+    canvas_draw_str_aligned(canvas, 74, 5, AlignLeft, AlignTop, "Sending");
+    canvas_set_font(canvas, FontSecondary);
+    canvas_draw_str_aligned(canvas, 74, 20, AlignLeft, AlignTop, "Infrared");
+    canvas_draw_str_aligned(canvas, 74, 30, AlignLeft, AlignTop, model->name);
+
+    char temp_str[18];
+    snprintf(temp_str, 18, "%u", model->time);
+    canvas_draw_str_aligned(canvas, 74, 40, AlignLeft, AlignTop, temp_str);
+}
+
+void xremote_transmit_draw_pause(Canvas* canvas, XRemoteTransmitModel* model) {
+    model->time++;
+    canvas_clear(canvas);
+    canvas_set_color(canvas, ColorBlack);
+    canvas_draw_icon(canvas, 0, 0, &I_pause_128x64);
+    canvas_set_font(canvas, FontPrimary);
+    canvas_draw_str_aligned(canvas, 74, 5, AlignLeft, AlignTop, "Waiting");
+    canvas_set_font(canvas, FontSecondary);
+    canvas_draw_str_aligned(canvas, 74, 20, AlignLeft, AlignTop, "Sequence");
+    canvas_draw_str_aligned(canvas, 74, 30, AlignLeft, AlignTop, model->name);
+
+    char temp_str[18];
+    snprintf(temp_str, 18, "%u", model->time);
+    canvas_draw_str_aligned(canvas, 74, 40, AlignLeft, AlignTop, temp_str);
+}
+
+void xremote_transmit_draw_subghz(Canvas* canvas, XRemoteTransmitModel* model) {
+    model->time++;
+    canvas_clear(canvas);
+    canvas_set_color(canvas, ColorBlack);
+    canvas_draw_icon(canvas, 0, 0, &I_sg_transmit_128x64);
+    canvas_set_font(canvas, FontPrimary);
+    canvas_draw_str_aligned(canvas, 74, 5, AlignLeft, AlignTop, "Sending");
+    canvas_set_font(canvas, FontSecondary);
+    canvas_draw_str_aligned(canvas, 74, 20, AlignLeft, AlignTop, "SubGhz");
+    canvas_draw_str_aligned(canvas, 74, 30, AlignLeft, AlignTop, model->name);
+
+    char temp_str[18];
+    snprintf(temp_str, 18, "%u", model->time);
+    canvas_draw_str_aligned(canvas, 74, 40, AlignLeft, AlignTop, temp_str);
+}
+
+void xremote_transmit_draw(Canvas* canvas, XRemoteTransmitModel* model) {
+    if(model->type == XRemoteRemoteItemTypeInfrared) {
+        xremote_transmit_draw_ir(canvas, model);
+    } else if(model->type == XRemoteRemoteItemTypePause) {
+        xremote_transmit_draw_pause(canvas, model);
+    }
+}
+
+XRemoteTransmit* xremote_transmit_alloc() {
+    XRemoteTransmit* instance = malloc(sizeof(XRemoteTransmit));
+    instance->view = view_alloc();
+    view_allocate_model(instance->view, ViewModelTypeLocking, sizeof(XRemoteTransmitModel));
+    view_set_context(instance->view, instance);
+    view_set_draw_callback(instance->view, (ViewDrawCallback)xremote_transmit_draw);
+    view_set_enter_callback(instance->view, xremote_transmit_enter);
+
+    with_view_model(
+        instance->view,
+        XRemoteTransmitModel * model,
+        { xremote_transmit_model_init(model); },
+        true);
+
+    return instance;
+}
+
+void xremote_transmit_enter(void* context) {
+    furi_assert(context);
+    XRemoteTransmit* instance = (XRemoteTransmit*)context;
+    with_view_model(
+        instance->view,
+        XRemoteTransmitModel * model,
+        { xremote_transmit_model_init(model); },
+        true);
+}
+
+void xremote_transmit_free(XRemoteTransmit* instance) {
+    furi_assert(instance);
+
+    with_view_model(
+        instance->view, XRemoteTransmitModel * model, { UNUSED(model); }, true);
+    view_free(instance->view);
+    free(instance);
+}
+
+View* xremote_transmit_get_view(XRemoteTransmit* instance) {
+    furi_assert(instance);
+    return instance->view;
 }

+ 23 - 23
views/xremote_transmit.h

@@ -1,24 +1,24 @@
-#pragma once
-
-#include "../xremote.h"
-#include "../helpers/xremote_custom_event.h"
-
-typedef struct XRemoteTransmit XRemoteTransmit;
-
-typedef void (*XRemoteTransmitCallback)(XRemoteCustomEvent event, void* context);
-
-void xremote_transmit_model_set_name(XRemoteTransmit* instance, const char* name);
-void xremote_transmit_model_set_type(XRemoteTransmit* instance, int type);
-
-void xremote_transmit_set_callback(
-    XRemoteTransmit* instance,
-    XRemoteTransmitCallback callback,
-    void* context);
-
-XRemoteTransmit* xremote_transmit_alloc();
-
-void xremote_transmit_free(XRemoteTransmit* instance);
-
-View* xremote_transmit_get_view(XRemoteTransmit* instance);
-
+#pragma once
+
+#include "../xremote.h"
+#include "../helpers/xremote_custom_event.h"
+
+typedef struct XRemoteTransmit XRemoteTransmit;
+
+typedef void (*XRemoteTransmitCallback)(XRemoteCustomEvent event, void* context);
+
+void xremote_transmit_model_set_name(XRemoteTransmit* instance, const char* name);
+void xremote_transmit_model_set_type(XRemoteTransmit* instance, int type);
+
+void xremote_transmit_set_callback(
+    XRemoteTransmit* instance,
+    XRemoteTransmitCallback callback,
+    void* context);
+
+XRemoteTransmit* xremote_transmit_alloc();
+
+void xremote_transmit_free(XRemoteTransmit* instance);
+
+View* xremote_transmit_get_view(XRemoteTransmit* instance);
+
 void xremote_transmit_enter(void* context);

+ 45 - 26
xremote.c

@@ -23,7 +23,7 @@ XRemote* xremote_app_alloc() {
     XRemote* app = malloc(sizeof(XRemote));
     app->gui = furi_record_open(RECORD_GUI);
     app->notification = furi_record_open(RECORD_NOTIFICATION);
-    
+
     //Turn backlight on, believe me this makes testing your app easier
     notification_message(app->notification, &sequence_display_backlight_on);
 
@@ -33,8 +33,10 @@ XRemote* xremote_app_alloc() {
 
     app->scene_manager = scene_manager_alloc(&xremote_scene_handlers, app);
     view_dispatcher_set_event_callback_context(app->view_dispatcher, app);
-    view_dispatcher_set_navigation_event_callback(app->view_dispatcher, xremote_navigation_event_callback);
-    view_dispatcher_set_tick_event_callback(app->view_dispatcher, xremote_tick_event_callback, 100);
+    view_dispatcher_set_navigation_event_callback(
+        app->view_dispatcher, xremote_navigation_event_callback);
+    view_dispatcher_set_tick_event_callback(
+        app->view_dispatcher, xremote_tick_event_callback, 100);
     view_dispatcher_set_custom_event_callback(app->view_dispatcher, xremote_custom_event_callback);
     app->submenu = submenu_alloc();
     app->editmenu = submenu_alloc();
@@ -57,29 +59,49 @@ XRemote* xremote_app_alloc() {
     app->cross_remote = cross_remote_alloc();
 
     app->sg_remote_buffer = xremote_sg_remote_alloc();
-    
+
     app->loading = loading_alloc();
 
     app->text_input = text_input_alloc();
-    view_dispatcher_add_view(app->view_dispatcher, XRemoteViewIdTextInput, text_input_get_view(app->text_input));
+    view_dispatcher_add_view(
+        app->view_dispatcher, XRemoteViewIdTextInput, text_input_get_view(app->text_input));
 
-    view_dispatcher_add_view(app->view_dispatcher, XRemoteViewIdMenu, submenu_get_view(app->submenu));
-    view_dispatcher_add_view(app->view_dispatcher, XRemoteViewIdEditItem, submenu_get_view(app->editmenu));
+    view_dispatcher_add_view(
+        app->view_dispatcher, XRemoteViewIdMenu, submenu_get_view(app->submenu));
+    view_dispatcher_add_view(
+        app->view_dispatcher, XRemoteViewIdEditItem, submenu_get_view(app->editmenu));
     app->xremote_infoscreen = xremote_infoscreen_alloc();
-    view_dispatcher_add_view(app->view_dispatcher, XRemoteViewIdInfoscreen, xremote_infoscreen_get_view(app->xremote_infoscreen));
+    view_dispatcher_add_view(
+        app->view_dispatcher,
+        XRemoteViewIdInfoscreen,
+        xremote_infoscreen_get_view(app->xremote_infoscreen));
     app->xremote_transmit = xremote_transmit_alloc();
-    view_dispatcher_add_view(app->view_dispatcher, XRemoteViewIdTransmit, xremote_transmit_get_view(app->xremote_transmit));
+    view_dispatcher_add_view(
+        app->view_dispatcher,
+        XRemoteViewIdTransmit,
+        xremote_transmit_get_view(app->xremote_transmit));
     app->xremote_pause_set = xremote_pause_set_alloc();
-    view_dispatcher_add_view(app->view_dispatcher, XRemoteViewIdPauseSet, xremote_pause_set_get_view(app->xremote_pause_set));
+    view_dispatcher_add_view(
+        app->view_dispatcher,
+        XRemoteViewIdPauseSet,
+        xremote_pause_set_get_view(app->xremote_pause_set));
     app->button_menu_create = button_menu_alloc();
-    view_dispatcher_add_view(app->view_dispatcher, XRemoteViewIdCreate, button_menu_get_view(app->button_menu_create));
+    view_dispatcher_add_view(
+        app->view_dispatcher, XRemoteViewIdCreate, button_menu_get_view(app->button_menu_create));
     app->button_menu_create_add = button_menu_alloc();
-    view_dispatcher_add_view(app->view_dispatcher, XRemoteViewIdCreateAdd, button_menu_get_view(app->button_menu_create_add));
+    view_dispatcher_add_view(
+        app->view_dispatcher,
+        XRemoteViewIdCreateAdd,
+        button_menu_get_view(app->button_menu_create_add));
     app->button_menu_ir = button_menu_alloc();
-    view_dispatcher_add_view(app->view_dispatcher, XRemoteViewIdIrRemote, button_menu_get_view(app->button_menu_ir));
+    view_dispatcher_add_view(
+        app->view_dispatcher, XRemoteViewIdIrRemote, button_menu_get_view(app->button_menu_ir));
     app->variable_item_list = variable_item_list_alloc();
-    view_dispatcher_add_view(app->view_dispatcher, XRemoteViewIdSettings, variable_item_list_get_view(app->variable_item_list));
-    
+    view_dispatcher_add_view(
+        app->view_dispatcher,
+        XRemoteViewIdSettings,
+        variable_item_list_get_view(app->variable_item_list));
+
     app->popup = popup_alloc();
     view_dispatcher_add_view(app->view_dispatcher, XRemoteViewIdWip, popup_get_view(app->popup));
     app->view_stack = view_stack_alloc();
@@ -93,7 +115,7 @@ XRemote* xremote_app_alloc() {
 
 void xremote_app_free(XRemote* app) {
     furi_assert(app);
-    
+
     // Scene manager
     scene_manager_free(app->scene_manager);
 
@@ -124,7 +146,7 @@ void xremote_app_free(XRemote* app) {
     furi_string_free(app->file_path);
 
     loading_free(app->loading);
-    
+
     app->gui = NULL;
     app->notification = NULL;
 
@@ -135,8 +157,7 @@ void xremote_app_free(XRemote* app) {
 void xremote_popup_closed_callback(void* context) {
     furi_assert(context);
     XRemote* app = context;
-    view_dispatcher_send_custom_event(
-        app->view_dispatcher, XRemoteCustomEventTypePopupClosed);
+    view_dispatcher_send_custom_event(app->view_dispatcher, XRemoteCustomEventTypePopupClosed);
 }
 
 void xremote_text_input_callback(void* context) {
@@ -148,23 +169,21 @@ void xremote_text_input_callback(void* context) {
 int32_t xremote_app(void* p) {
     UNUSED(p);
     XRemote* app = xremote_app_alloc();
-    
+
     view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
-    
+
     //scene_manager_next_scene(app->scene_manager, XRemoteSceneInfoscreen); //Start with start screen
-    scene_manager_next_scene(app->scene_manager, XRemoteSceneMenu); //if you want to directly start with Menu
+    scene_manager_next_scene(
+        app->scene_manager, XRemoteSceneMenu); //if you want to directly start with Menu
 
     furi_hal_power_suppress_charge_enter();
 
     view_dispatcher_run(app->view_dispatcher);
 
     xremote_save_settings(app);
-    
+
     furi_hal_power_suppress_charge_exit();
     xremote_app_free(app);
 
     return 0;
 }
-
-
-

+ 1 - 1
xremote.h

@@ -33,7 +33,7 @@ typedef struct {
     InfraredWorker* ir_worker;
     SubGhzRemote* sg_remote_buffer;
     CrossRemote* cross_remote;
-    uint32_t haptic; 
+    uint32_t haptic;
     uint32_t speaker;
     uint32_t led;
     uint32_t save_settings;

Некоторые файлы не были показаны из-за большого количества измененных файлов